<?php

/**
 *
 * Copyright (c) 2013, EvoStream Inc.  All rights reserved.
 *
 * This software is provided free of charge to be used solely in conjunction
 * with the EvoStream Media Server.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the source code retain the above 
 * copyright notice, this list of conditions and the following disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * 
 * @package evostream
 * @subpackage api
 * @version 0.708
 */

/**
 * EMS API
 */
class EvoCoreAPI {
	/*
	 * evostream server url
	 * @var string
	 * @access private
	 */

	private $ServerUrl = "http://localhost:7777/";

	/*
	 * json data
	 * @var string
	 * @access private
	 */
	private $data = "";

	function __construct($svrURL) {

		if ($svrURL != "")
			$this->ServerUrl = $svrURL;
	}

	/*
	 * process ems api function with curl
	 *
	 * @param    string      $fn         api function
	 * @param    string      $params     function parameters
	 * @return   string                  json data
	 */

	private function _procFunc($fn, $params = '') {
		$url = $this->ServerUrl . $fn;

		if ($params != '') {
			$url .= '?params=' . base64_encode($params);
		}

		$curl = curl_init();

		// Set the URL including the parameters
		curl_setopt($curl, CURLOPT_URL, $url);

		// We don't need any HTTP header, so set as empty
		curl_setopt($curl, CURLOPT_HTTPHEADER, array());

		// Return the data instead of printing it out
		curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

		// Set the time out to 10sec, should be long enough in case no response from server
		curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10);

		// Actual curl exec
		$this->data = curl_exec($curl);

		curl_close($curl);

		// Return as string, this however is in JSON format
		return $this->data;
	}

	/*
	 * prints this help
	 */

	public function help() {
		return $this->_procFunc("help");
	}

	/*
	 * Will enable/disable RTMP authentication
	 */

	public function setAuthentication($enabled) {
		if (!isset($enabled) || $enabled === '') {
			Throw new Exception('parameter enabled required');
		}
		if (!preg_match('/^[0,1]{1}$/', $enabled)) {
			Throw new Exception('parameter enabled invalid');
		}
		$params = 'enabled=' . $enabled;
		return $this->_procFunc("setAuthentication", $params);
	}

	/*
	 * Returns the versions for framework and this application
	 */

	public function Version() {
		return $this->_procFunc("Version");
	}

	/*
	 * pull in a stream from an external source
	 */

	public function pullStream($uri, $keepAlive, $localStreamName, $width, $height, $forceTcp, $ttl, $tos, $internalArguments = NULL) {
		if (!isset($uri) || empty($uri)) {
			Throw new Exception('parameter uri required');
		}
		if (!isset($keepAlive) || $keepAlive === '') {
			$keepAlive = 1;
		}
		if (!preg_match('/^[0,1]{1}$/', $keepAlive)) {
			Throw new Exception('parameter keepAlive invalid');
		}
		if (!isset($localStreamName) || empty($localStreamName)) {
			$localStreamName = '';
		}
		if (!isset($width) || empty($width)) {
			$width = 0;
		} else if (!preg_match('/^\d+$/', $width)) {
			Throw new Exception('parameter width invalid');
		}
		if (!isset($height) || empty($height)) {
			$height = 0;
		} else if (!preg_match('/^\d+$/', $height)) {
			Throw new Exception('parameter height invalid');
		}
		if (!isset($forceTcp) || $forceTcp === '') {
			$forceTcp = 1;
		}
		if (!preg_match('/^[0,1]{1}$/', $forceTcp)) {
			Throw new Exception('parameter forceTcp invalid');
		}
		if (!isset($ttl) || empty($ttl)) {
			$ttl = 0;
		}
		if (!isset($tos) || empty($tos)) {
			$tos = 0;
		}
		$params = 'uri=' . str_replace(' ', '', $uri) . ' keepAlive=' . $keepAlive . ' localStreamName=' . str_replace(' ', '', $localStreamName) . ' width=' . $width . ' height=' . $height . ' forceTcp=' . $forceTcp . ' ttl=' . $ttl . ' tos=' . $tos . ' ' . $internalArguments;
		return $this->_procFunc("pullStream", $params);
	}

	/*
	 * push a local stream to an external destination
	 */

	public function pushStream($uri, $localStreamName, $keepAlive, $targetStreamName, $targetStreamType, $emulateUserAgent, $swfUrl, $pageUrl, $ttl, $tos, $internalArguments = NULL) {
		if (!isset($uri) || empty($uri)) {
			Throw new Exception('parameter uri required');
		}
		if (!isset($localStreamName) || empty($localStreamName)) {
			Throw new Exception('parameter localStreamName required');
		}
		if (!isset($keepAlive) || $keepAlive === '') {
			$keepAlive = 1;
		}
		if (!preg_match('/^[0,1]{1}$/', $keepAlive)) {
			Throw new Exception('parameter keepAlive invalid');
		}
		if (!isset($targetStreamName) || empty($targetStreamName)) {
			$targetStreamName = $localStreamName;
		}
		if (!isset($targetStreamType) || empty($targetStreamType)) {
			$targetStreamType = 'live';
		}
		if (!preg_match('/^live|record|append$/i', $targetStreamType)) {
			Throw new Exception('parameter targetStreamType invalid');
		}
		if (!isset($emulateUserAgent) || empty($emulateUserAgent)) {
			$emulateUserAgent = '';
		}
		if (!isset($swfUrl) || empty($swfUrl)) {
			$swfUrl = '';
		}
		if (!isset($pageUrl) || empty($pageUrl)) {
			$pageUrl = '';
		}
		if (!isset($ttl) || empty($ttl)) {
			$ttl = 0;
		}
		if (!isset($tos) || empty($tos)) {
			$tos = 0;
		}
		$params = 'uri=' . str_replace(' ', '', $uri) . ' localStreamName=' . str_replace(' ', '', $localStreamName) . ' keepAlive=' . $keepAlive . ' targetStreamName=' . str_replace(' ', '', $targetStreamName) . ' targetStreamType=' . $targetStreamType . ' emulateUserAgent=' . str_replace(' ', '', $emulateUserAgent) . ' swfUrl=' . $swfUrl . ' pageUrl=' . $pageUrl . ' ttl=' . $ttl . ' tos=' . $tos . ' ' . $internalArguments;
		return $this->_procFunc("pushStream", $params);
	}

	/*
	 * Get a list of IDs from every active stream
	 */

	public function listStreamsIds() {
		return $this->_procFunc("listStreamsIds");
	}

	/*
	 * Returns the number of active streams
	 */

	public function getStreamsCount() {
		return $this->_procFunc("getStreamsCount");
	}

	/*
	 * Returns a detailed set of information about a stream
	 */

	public function getStreamInfo($id) {
		if (!isset($id) || empty($id)) {
			Throw new Exception('parameter id required');
		} else if (!preg_match('/^\d+$/', $id)) {
			Throw new Exception('parameter id invalid');
		}
		$params = 'id=' . $id;
		return $this->_procFunc("getStreamInfo", $params);
	}

	/*
	 * Provides a detailed description of every active stream
	 */

	public function listStreams() {
		return $this->_procFunc("listStreams");
	}

	/*
	 * Terminate a specific stream
	 */

	public function shutdownStream($id, $localStreamName, $permanently) {
		if (!isset($id) || empty($id)) {
			Throw new Exception('parameter id required');
		} else if (!preg_match('/^\d+$/', $id)) {
			Throw new Exception('parameter id invalid');
		}
		if (!empty($localStreamName)) {
			$localStreamName = ' localStreamName=' . str_replace(' ', '', $localStreamName);
		}
		if (!isset($permanently) || $permanently === '') {
			$permanently = 1;
		}
		if (!preg_match('/^[0,1]{1}$/', $permanently)) {
			Throw new Exception('parameter permanently invalid');
		}

		$params = 'id=' . $id . $localStreamName . ' permanently=' . str_replace(' ', '', $permanently);
//		$params = 'id=' . $id. ' permanently=' . str_replace(' ', '', $permanently);
		return $this->_procFunc("shutdownStream", $params);
	}

	/*
	 * Returns a list with all push/pull configurations
	 */

	public function listConfig() {
		return $this->_procFunc("listConfig");
	}

	/*
	 * Removes a pull/push configuration. It does NOT stop the corresponding stream
	 */

	public function removeConfig($id, $HlsHdsGroup, $removeHLSFiles) {
		if (!isset($id) || empty($id)) {
			Throw new Exception('parameter id required');
		} else if (!preg_match('/^\d+$/', $id)) {
			Throw new Exception('parameter id invalid');
		}
		if (!isset($HlsHdsGroup) || empty($HlsHdsGroup)) {
			$HlsHdsGroup = '';
		}
		if (!isset($removeHLSFiles) || $removeHLSFiles === '') {
			$removeHLSFiles = 0;
		}
		if (!preg_match('/^[0,1]{1}$/', $removeHLSFiles)) {
			Throw new Exception('parameter removeHLSFiles invalid');
		}
		$params = 'id=' . $id . ' HlsHdsGroup=' . str_replace(' ', '', $HlsHdsGroup) . ' removeHLSFiles=' . $removeHLSFiles;
		return $this->_procFunc("removeConfig", $params);
	}

	/*
	 * Returns the list of available service
	 */

	public function listServices() {
		return $this->_procFunc("listServices");
	}

	/*
	 * Enable or disable a service
	 */

	public function enableService($id, $enable) {
		if (!isset($id) || empty($id)) {
			Throw new Exception('parameter id required');
		} else if (!preg_match('/^\d+$/', $id)) {
			Throw new Exception('parameter id invalid');
		}
		if (!isset($enable) || $enable === '') {
			Throw new Exception('parameter enable required');
		}
		if (!preg_match('/^[0,1]{1}$/', $enable)) {
			Throw new Exception('parameter enable invalid');
		}
		$params = 'id=' . $id . ' enable=' . $enable;
		return $this->_procFunc("enableService", $params);
	}

	/*
	 * Terminates a service
	 */

	public function shutdownService($id) {
		if (!isset($id) || empty($id)) {
			Throw new Exception('parameter id required');
		} else if (!preg_match('/^\d+$/', $id)) {
			Throw new Exception('parameter id invalid');
		}
		$params = 'id=' . $id;
		return $this->_procFunc("shutdownService", $params);
	}

	/*
	 * Creates a new service
	 */

	public function createService($ip, $port, $protocol, $sslCert, $sslKey) {
		if (!isset($ip) || empty($ip)) {
			Throw new Exception('parameter ip required');
		} else if (!preg_match('/^[0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}$/i', $ip)) {
			Throw new Exception('parameter ip invalid');
		}
		if (!isset($port) || empty($port)) {
			Throw new Exception('parameter port required');
		} else if (!preg_match('/^\d+$/', $port)) {
			Throw new Exception('parameter port invalid');
		}
		if (!isset($protocol) || empty($protocol)) {
			Throw new Exception('parameter protocol required');
		}
		if (!isset($sslCert) || empty($sslCert)) {
			$sslCert = '';
		}
		if (!isset($sslKey) || empty($sslKey)) {
			$sslKey = '';
		}
		$params = 'ip=' . $ip . ' port=' . $port . ' protocol=' . $protocol . ' sslCert=' . $sslCert . ' sslKey=' . $sslKey;
		return $this->_procFunc("createService", $params);
	}

	/*
	 * Returns a list containing the IDs of every active connection
	 */

	public function listConnectionsIds() {
		return $this->_procFunc("listConnectionsIds");
	}

	/*
	 * Returns a detailed description of the network descriptors counters
	 */

	public function getExtendedConnectionCounters() {
		return $this->_procFunc("getExtendedConnectionCounters");
	}

	/*
	 * Returns the number of active connections
	 */

	public function getConnectionsCount() {
		return $this->_procFunc("getConnectionsCount");
	}

	/*
	 * Returns a detailed set of information about a connection
	 */

	public function getConnectionInfo($id) {
		if (!isset($id) || empty($id)) {
			Throw new Exception('parameter id required');
		} else if (!preg_match('/^\d+$/', $id)) {
			Throw new Exception('parameter id invalid');
		}
		$params = 'id=' . $id;
		return $this->_procFunc("getConnectionInfo", $params);
	}

	/*
	 * Returns the list of active connections
	 */

	public function listConnections() {
		return $this->_procFunc("listConnections");
	}

	/*
	 * create HTTP live stream out of an existing H.264/AAC stream
	 */

	public function createHLSStream($localStreamNames, $targetFolder, $bandwidths, $keepAlive, $overwriteDestination, $staleRetentionCount, $createMasterPlaylist, $groupName, $playlistType, $playlistLength, $playlistName, $chunkLength, $chunkBaseName, $chunkOnIDR, $cleanupDestination) {
		if (!isset($localStreamNames) || empty($localStreamNames)) {
			Throw new Exception('parameter localStreamNames required');
		}
		if (!isset($targetFolder) || empty($targetFolder)) {
			Throw new Exception('parameter targetFolder required');
		}
		if (!isset($bandwidths) || empty($bandwidths)) {
			$bandwidths = null;
		}
		if (!isset($keepAlive) || $keepAlive === '') {
			$keepAlive = 1;
		}
		if (!preg_match('/^[0,1]{1}$/', $keepAlive)) {
			Throw new Exception('parameter keepAlive invalid');
		}
		if (!isset($overwriteDestination) || empty($overwriteDestination)) {
			$overwriteDestination = 1;
		}
		if (!preg_match('/^[0,1]{1}$/', $overwriteDestination)) {
			Throw new Exception('parameter overwriteDestination invalid');
		}
		if (!isset($playlistLength) || $playlistLength === '') {
			$playlistLength = 10;
		} else if (!preg_match('/^\d+$/', $playlistLength)) {
			Throw new Exception('parameter playlistLength invalid');
		}
		if (!isset($staleRetentionCount) || empty($staleRetentionCount)) {
			$staleRetentionCount = $playlistLength;
		} else if (!preg_match('/^\d+$/', $staleRetentionCount)) {
			Throw new Exception('parameter staleRetentionCount invalid');
		}
		if (!isset($createMasterPlaylist) || $createMasterPlaylist === '') {
			$createMasterPlaylist = 1;
		}
		if (!preg_match('/^[0,1]{1}$/', $createMasterPlaylist)) {
			Throw new Exception('parameter createMasterPlaylist invalid');
		}
		if (!isset($groupName) || empty($groupName)) {
			$groupName = '';
		}
		if (!isset($playlistType) || empty($playlistType)) {
			$playlistType = 'appending';
		}
		if (!preg_match('/^appending|rolling$/i', $playlistType)) {
			Throw new Exception('parameter playlistType invalid');
		}
		if (!isset($playlistName) || empty($playlistName)) {
			$playlistName = 'playlist.m3u8';
		}
		if (!isset($chunkLength) || empty($chunkLength)) {
			$chunkLength = 10;
		} else if (!preg_match('/^\d+$/', $chunkLength)) {
			Throw new Exception('parameter chunkLength invalid');
		}
		if (!isset($chunkBaseName) || empty($chunkBaseName)) {
			$chunkBaseName = 'segment';
		}
		if (!isset($chunkOnIDR) || $chunkOnIDR === '') {
			$chunkOnIDR = 1;
		}
		if (!preg_match('/^[0,1]{1}$/', $chunkOnIDR)) {
			Throw new Exception('parameter chunkOnIDR invalid');
		}
		if (!isset($cleanupDestination) || $cleanupDestination === '') {
			$cleanupDestination = 0;
		}
		if (!preg_match('/^[0,1]{1}$/', $cleanupDestination)) {
			Throw new Exception('parameter cleanupDestination invalid');
		}
		$params = 'localStreamNames=' . str_replace(' ', '', $localStreamNames) . ' targetFolder=' . str_replace(' ', '', $targetFolder) . ' keepAlive=' . $keepAlive . ' overwriteDestination=' . $overwriteDestination . ' staleRetentionCount=' . $staleRetentionCount . ' createMasterPlaylist=' . $createMasterPlaylist . ' groupName=' . str_replace(' ', '', $groupName) . ' playlistType=' . $playlistType . ' playlistLength=' . $playlistLength . ' playlistName=' . str_replace(' ', '', $playlistName) . ' chunkLength=' . $chunkLength . ' chunkBaseName=' . str_replace(' ', '', $chunkBaseName) . ' chunkOnIDR=' . $chunkOnIDR . ' cleanupDestination=' . $cleanupDestination;

		// Add bandwidths if available
		if (null != $bandwidths) {
			$params = $params . ' bandwidths=' . str_replace(' ', '', $bandwidths);
		}

		return $this->_procFunc("createHLSStream", $params);
	}

	/*
	 * Create an HTTP Dynamic Stream (HDS) out of an existing H.264/AAC stream.
	 */

	public function createHDSStream($localStreamNames, $targetFolder, $bandwidths, $groupName, $playlistType, $playlistLength, $manifestName, $chunkLength, $chunkBaseName, $chunkOnIDR, $keepAlive, $overwriteDestination, $cleanupDestination) {
		if (!isset($localStreamNames) || empty($localStreamNames)) {
			Throw new Exception('parameter localStreamNames required');
		}
		if (!isset($targetFolder) || empty($targetFolder)) {
			Throw new Exception('parameter targetFolder required');
		}
		if (!isset($bandwidths) || empty($bandwidths)) {
			$bandwidths = null;
		}
		if (!isset($keepAlive) || $keepAlive === '') {
			$keepAlive = 1;
		}
		if (!preg_match('/^[0,1]{1}$/', $keepAlive)) {
			Throw new Exception('parameter keepAlive invalid');
		}
		if (!isset($overwriteDestination) || empty($overwriteDestination)) {
			$overwriteDestination = 1;
		}
		if (!preg_match('/^[0,1]{1}$/', $overwriteDestination)) {
			Throw new Exception('parameter overwriteDestination invalid');
		}
		if (!isset($playlistLength) || empty($playlistLength)) {
			$playlistLength = 10;
		} else if (!preg_match('/^\d+$/', $playlistLength)) {
			Throw new Exception('parameter playlistLength invalid');
		}
		if (!isset($manifestName) || $manifestName === '') {
			$manifestName = 'manifest.f4m';
		}
		if (!isset($groupName) || empty($groupName)) {
			$groupName = '';
		}
		if (!isset($playlistType) || empty($playlistType)) {
			$playlistType = 'appending';
		}
		if (!preg_match('/^appending|rolling$/i', $playlistType)) {
			Throw new Exception('parameter playlistType invalid');
		}
		if (!isset($chunkLength) || empty($chunkLength)) {
			$chunkLength = 10;
		} else if (!preg_match('/^\d+$/', $chunkLength)) {
			Throw new Exception('parameter chunkLength invalid');
		}
		if (!isset($chunkBaseName) || empty($chunkBaseName)) {
			$chunkBaseName = 'f4v';
		}
		if (!isset($chunkOnIDR) || $chunkOnIDR === '') {
			$chunkOnIDR = 1;
		}
		if (!preg_match('/^[0,1]{1}$/', $chunkOnIDR)) {
			Throw new Exception('parameter chunkOnIDR invalid');
		}
		if (!isset($cleanupDestination) || $cleanupDestination === '') {
			$cleanupDestination = 0;
		}
		if (!preg_match('/^[0,1]{1}$/', $cleanupDestination)) {
			Throw new Exception('parameter cleanupDestination invalid');
		}
		$params = 'localStreamNames=' . str_replace(' ', '', $localStreamNames) . ' targetFolder=' . str_replace(' ', '', $targetFolder) . ' keepAlive=' . $keepAlive . ' overwriteDestination=' . $overwriteDestination . ' groupName=' . str_replace(' ', '', $groupName) . ' manifestName=' . str_replace(' ', '', $manifestName) . ' manifestName=' . str_replace(' ', '', $manifestName) . ' playlistType=' . $playlistType . ' playlistLength=' . $playlistLength . ' chunkLength=' . $chunkLength . ' chunkBaseName=' . str_replace(' ', '', $chunkBaseName) . ' chunkOnIDR=' . $chunkOnIDR . ' cleanupDestination=' . $cleanupDestination;

		// Add bandwidths if available
		if (null != $bandwidths) {
			$params = $params . ' bandwidths=' . str_replace(' ', '', $bandwidths);
		}

		return $this->_procFunc("createHDSStream", $params);
	}

	/*
	 * Returns the limit of concurrent connections. This is the maximum number of connections this EMS instance will allow at one time
	 */

	public function getConnectionsCountLimit() {
		return $this->_procFunc("getConnectionsCountLimit");
	}

	/*
	 * This interface sets a limit on the number of concurrent connections the EMS will allow
	 */

	public function setConnectionsCountLimit($count) {
		if (!isset($count) || empty($count)) {
			Throw new Exception('parameter count required');
		} else if (!preg_match('/^\d+$/', $count)) {
			Throw new Exception('parameter count invalid');
		}
		$params = 'count=' . $count;
		return $this->_procFunc("setConnectionsCountLimit", $params);
	}

	/*
	 * This interface enforces a limit on the input and output bandwidth.
	 */

	public function setBandwidthLimit($in, $out) {
		if (!isset($in) || empty($in)) {
			Throw new Exception('parameter in required');
		} else if (!preg_match('/^\d+$/', $in)) {
			Throw new Exception('parameter in invalid');
		}
		if (!isset($out) || empty($out)) {
			Throw new Exception('parameter out required');
		} else if (!preg_match('/^\d+$/', $out)) {
			Throw new Exception('parameter out invalid');
		}
		$params = 'in=' . $in . ' out=' . $out;
		return $this->_procFunc("setBandwidthLimit", $params);
	}

	/*
	 * Returns bandwidth information: limits and current values.
	 */

	public function getBandwidth() {
		return $this->_procFunc("getBandwidth");
	}

	/*
	 * Change the log level for all log appenders
	 */

	public function setLogLevel($level) {
		if (!isset($level) || $level === '') {
			Throw new Exception('parameter level required');
		}
		if (!preg_match('/^[0-7]{1}$/', $level)) {
			Throw new Exception('parameter level invalid');
		}
		$params = 'level=' . $level;
		return $this->_procFunc("setLogLevel", $params);
	}

	/*
	 * Reset the maximum, or high-water-mark, from the Connection Counters
	 */

	public function resetMaxFdCounters() {
		return $this->_procFunc("resetMaxFdCounters");
	}

	/*
	 * Reset the cumulative totals from the Connection Counters
	 */

	public function resetTotalFdCounters() {
		return $this->_procFunc("resetTotalFdCounters");
	}

	/*
	 * allow users to record a stream that does or does not yet exist
	 */

	public function record($localStreamName, $fileLocation, $keepAlive, $type, $overwrite, $internalArguments = NULL) {
		if (!isset($localStreamName) || empty($localStreamName)) {
			Throw new Exception('parameter localStreamName required');
		}
		if (realpath($fileLocation) == FALSE) {
			Throw new Exception('parameter file location is invalid');
		}
		if (!isset($keepAlive) || $keepAlive === '') {
			$keepAlive = 1;
		}
		if (!preg_match('/^[0,1]{1}$/', $keepAlive)) {
			Throw new Exception('parameter keepAlive invalid');
		}
		if (!isset($type) || empty($type)) {
			$type = 'mp4';
		}
		if (!isset($overwrite) || empty($overwrite)) {
			$overwrite = 0;
		}

		//Add filename to file location
		$pathToFile = $fileLocation . $localStreamName . "." . $type;

		$params = 'localStreamName=' . str_replace(' ', '', $localStreamName) . ' pathtofile=' . $pathToFile . ' keepAlive=' . $keepAlive . ' type=' . $type . ' overwrite=' . $overwrite . ' ' . $internalArguments;
		return $this->_procFunc("record", $params);
	}

	/*
	 * Allows you to create secondary name(s) for internal streams
	 */

	public function addStreamAlias($localStreamName, $aliasName) {
		if (!isset($localStreamName) || empty($localStreamName)) {
			Throw new Exception('parameter localStreamName required');
		}
		if (!isset($aliasName) || empty($aliasName)) {
			Throw new Exception('parameter aliasName required');
		}
		$params = 'localStreamName=' . str_replace(' ', '', $localStreamName) . ' aliasName=' . str_replace(' ', '', $aliasName);
		return $this->_procFunc("addStreamAlias", $params);
	}

	/*
	 * Removes an alias of a stream
	 */

	public function removeStreamAlias($aliasName) {
		if (!isset($aliasName) || empty($aliasName)) {
			Throw new Exception('parameter aliasName required');
		}
		$params = 'aliasName=' . str_replace(' ', '', $aliasName);
		return $this->_procFunc("removeStreamAlias", $params);
	}

	/*
	 * Returns a complete list of aliases
	 */

	public function listStreamAliases() {
		return $this->_procFunc("listStreamAliases");
	}

	/*
	 * Invalidates all streams aliases
	 */

	public function flushStreamAliases() {
		return $this->_procFunc("flushStreamAliases");
	}

	/*
	 * Shuts down the server
	 */

	public function shutdownServer() {
		$shutdownServerList = json_decode($this->_procFunc("shutdownServer"));
		$key = $shutdownServerList->data->key;

		if (!isset($key) || empty($key)) {
			Throw new Exception('parameter key required');
		}

		$params = 'key=' . str_replace(' ', '', $key);
		return $this->_procFunc("shutdownServer", $params);
	}

	/*
	 * launch an external process
	 * @TODO Skipped
	 */

	public function launchProcess($fullBinaryPath, $keepAlive, $arguments, $environmentVariables) {
		$argumentsParams = null;
		$environmentVariablesParams = null;

		if (!file_exists($fullBinaryPath)) {
			Throw new Exception('parameter fullBinaryPath required');
		}
		if (!is_executable($fullBinaryPath)) {
			Throw new Exception('parameter fullBinaryPath is an invalid executable');
		}
		if (!isset($keepAlive) || $keepAlive === '') {
			$keepAlive = 1;
		}
		if ($arguments != '') {
			if (!preg_match("/([^\s]+)([\\][ ])/", $arguments)) {
				Throw new Exception('parameter arguments invalid. it should be delimited by ESCAPED SPACES (“\ “).');
			}
			$argumentsParams = ' arguments=' . $arguments;
		}
		if ($environmentVariables !== '') {
			if (!preg_match('/([$][^\s]+)=([^\s]+)/', $environmentVariables)) {
				Throw new Exception('parameter environment Variables invalid');
			}
			$environmentVariablesParams = ' environmentVariables=' . $environmentVariables;
		}
		$params = 'fullBinaryPath=' . $fullBinaryPath . ' keepAlive=' . $keepAlive . $argumentsParams . $environmentVariablesParams;
		return $this->_procFunc("launchProcess", $params);
	}

	/*
	 * Lists currently available media storage locations
	 */

	public function listStorage() {
		return $this->_procFunc("listStorage");
	}

	/*
	 * Adds a new storage location
	 */

	public function addStorage($mediaFolder) {
		if (realpath($mediaFolder) == FALSE) {
			Throw new Exception('parameter mediaFolder is invalid');
		}
		$params = 'mediaFolder=' . $mediaFolder;
		return $this->_procFunc("addStorage", $params);
	}

	/*
	 * Removes a storage location
	 */

	public function removeStorage($mediaFolder) {
		if (realpath($mediaFolder) == FALSE) {
			Throw new Exception('parameter file location is invalid');
		}
		$params = 'mediaFolder=' . $mediaFolder;
		return $this->_procFunc("removeStorage", $params);
	}

	/*
	 * Adds a timer. When triggered, it will send an event to the event logger
	 */

	public function setTimer($timePeriod, $internalArguments = NULL) {
		if (!isset($timePeriod) || empty($timePeriod)) {
			Throw new Exception('parameter timePeriod required');
		}
		if (!is_int($timePeriod)) {
			Throw new Exception('parameter time period value invalid');
		}

		$params = 'value=' . str_replace(' ', '', $timePeriod) . ' ' . $internalArguments;

		return $this->_procFunc("setTimer", $params);
	}

	/*
	 * Returns a list of currently active timers
	 */

	public function listTimers() {
		return $this->_procFunc("listTimers");
	}

	/*
	 * Removes a previously armed timer
	 */

	public function removeTimer($id) {
		if (!isset($id) || empty($id)) {
			Throw new Exception('parameter id required');
		}
		$params = 'id=' . str_replace(' ', '', $id);
		return $this->_procFunc("removeTimer", $params);
	}

	/*
	 * transcode a stream, add an overlay, or crop a stream
	 */

	public function transcode($source, $destinations, $targetStreamNames, $groupName, $videoBitrates, $videoSizes, $videoAdvancedParamsProfiles, $audioBitrates, $audioChannelsCount, $audioFrequencies, $audioAdvancedParamsProfiles, $overlays, $croppings, $keepAlive, $internalArguments = NULL) {
		// initialize params
		$params = '';

		if (!isset($source) || empty($source)) {
			Throw new Exception('parameter source required');
		} else {
			$params .= 'source=' . $source;
		}

		if (!isset($destinations) || empty($destinations)) {
			Throw new Exception('parameter destinations required');
		} else {
			$params .= ' destinations=' . $destinations;
		}

		if (isset($targetStreamNames) && $targetStreamNames !== '') {
			$params .= ' targetStreamNames=' . $targetStreamNames;
		}

		if (isset($groupName) && $groupName !== '') {
			$params .= ' groupName=' . $groupName;
		}

		if (isset($videoBitrates) && $videoBitrates !== '') {
			$params .= ' videoBitrates=' . $videoBitrates;
		}

		if (isset($videoSizes) && $videoSizes !== '') {
			$params .= ' videoSizes=' . $videoSizes;
		}

		if (isset($videoAdvancedParamsProfiles) && $videoAdvancedParamsProfiles !== '') {
			$params .= ' videoAdvancedParamsProfiles=' . $videoAdvancedParamsProfiles;
		}

		if (isset($audioBitrates) && $audioBitrates !== '') {
			$params .= ' audioBitrates=' . $audioBitrates;
		}

		if (isset($audioChannelsCount) && $audioChannelsCount !== '') {
			$params .= ' audioChannelsCount=' . $audioChannelsCount;
		}

		if (isset($audioFrequencies) && $audioFrequencies !== '') {
			$params .= ' audioFrequencies=' . $audioFrequencies;
		}

		if (isset($audioAdvancedParamsProfiles) && $audioAdvancedParamsProfiles !== '') {
			$params .= ' audioAdvancedParamsProfiles=' . $audioAdvancedParamsProfiles;
		}

		if (isset($overlays) && $overlays !== '') {
			$params .= ' overlays=' . $overlays;
		}

		if (isset($croppings) && $croppings !== '') {
			$params .= ' croppings=' . $croppings;
		}

		if (isset($keepAlive) && $keepAlive !== '') {
			$params .= ' keepAlive=' . $keepAlive;
		}

		$params .= ' ' . $internalArguments;

		return $this->_procFunc("transcode", $params);
	}

}
