diff options
-rw-r--r-- | bin/backend.php | 12 | ||||
-rw-r--r-- | bin/firephp.php | 1529 | ||||
-rw-r--r-- | bin/svdrp.php | 534 | ||||
-rwxr-xr-x | bin/vdr.php | 471 | ||||
-rwxr-xr-x | config.php | 38 | ||||
-rwxr-xr-x | config_default.php | 36 |
6 files changed, 2618 insertions, 2 deletions
diff --git a/bin/backend.php b/bin/backend.php index b2c41b3..4fd9ba2 100644 --- a/bin/backend.php +++ b/bin/backend.php @@ -1,15 +1,23 @@ <?php + header('Content-type: text/html'); + +if (file_exists('../config.php')) + include ('../config.php'); +else + include ('../config_default.php'); +include ('./vdr.php'); + $action=$_REQUEST['action']; switch ($action) { case ("getGlobals"): - $tree = file_get_contents("textfiles/getGlobals.txt"); + $tree = getGlobals(); print $tree; break; case ("getTvCat"): - $tree = file_get_contents("textfiles/getTvCat.txt"); + $tree = getTvCat(); print $tree; break; diff --git a/bin/firephp.php b/bin/firephp.php new file mode 100644 index 0000000..0533028 --- /dev/null +++ b/bin/firephp.php @@ -0,0 +1,1529 @@ +<?php +/** + * *** BEGIN LICENSE BLOCK ***** + * + * This file is part of FirePHP (http://www.firephp.org/). + * + * Software License Agreement (New BSD License) + * + * Copyright (c) 2006-2009, Christoph Dorn + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of Christoph Dorn nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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. + * + * ***** END LICENSE BLOCK ***** + * + * @copyright Copyright (C) 2007-2009 Christoph Dorn + * @author Christoph Dorn <christoph@christophdorn.com> + * @license http://www.opensource.org/licenses/bsd-license.php + * @package FirePHP + */ + + +/** + * Sends the given data to the FirePHP Firefox Extension. + * The data can be displayed in the Firebug Console or in the + * "Server" request tab. + * + * For more information see: http://www.firephp.org/ + * + * @copyright Copyright (C) 2007-2009 Christoph Dorn + * @author Christoph Dorn <christoph@christophdorn.com> + * @license http://www.opensource.org/licenses/bsd-license.php + * @package FirePHP + */ +class FirePHP { + + /** + * FirePHP version + * + * @var string + */ + const VERSION = '0.3'; + + /** + * Firebug LOG level + * + * Logs a message to firebug console. + * + * @var string + */ + const LOG = 'LOG'; + + /** + * Firebug INFO level + * + * Logs a message to firebug console and displays an info icon before the message. + * + * @var string + */ + const INFO = 'INFO'; + + /** + * Firebug WARN level + * + * Logs a message to firebug console, displays an warning icon before the message and colors the line turquoise. + * + * @var string + */ + const WARN = 'WARN'; + + /** + * Firebug ERROR level + * + * Logs a message to firebug console, displays an error icon before the message and colors the line yellow. Also increments the firebug error count. + * + * @var string + */ + const ERROR = 'ERROR'; + + /** + * Dumps a variable to firebug's server panel + * + * @var string + */ + const DUMP = 'DUMP'; + + /** + * Displays a stack trace in firebug console + * + * @var string + */ + const TRACE = 'TRACE'; + + /** + * Displays an exception in firebug console + * + * Increments the firebug error count. + * + * @var string + */ + const EXCEPTION = 'EXCEPTION'; + + /** + * Displays an table in firebug console + * + * @var string + */ + const TABLE = 'TABLE'; + + /** + * Starts a group in firebug console + * + * @var string + */ + const GROUP_START = 'GROUP_START'; + + /** + * Ends a group in firebug console + * + * @var string + */ + const GROUP_END = 'GROUP_END'; + + /** + * Singleton instance of FirePHP + * + * @var FirePHP + */ + protected static $instance = null; + + /** + * Flag whether we are logging from within the exception handler + * + * @var boolean + */ + protected $inExceptionHandler = false; + + /** + * Flag whether to throw PHP errors that have been converted to ErrorExceptions + * + * @var boolean + */ + protected $throwErrorExceptions = true; + + /** + * Flag whether to convert PHP assertion errors to Exceptions + * + * @var boolean + */ + protected $convertAssertionErrorsToExceptions = true; + + /** + * Flag whether to throw PHP assertion errors that have been converted to Exceptions + * + * @var boolean + */ + protected $throwAssertionExceptions = false; + + /** + * Wildfire protocol message index + * + * @var int + */ + protected $messageIndex = 1; + + /** + * Options for the library + * + * @var array + */ + protected $options = array('maxObjectDepth' => 10, + 'maxArrayDepth' => 20, + 'useNativeJsonEncode' => true, + 'includeLineNumbers' => true); + + /** + * Filters used to exclude object members when encoding + * + * @var array + */ + protected $objectFilters = array(); + + /** + * A stack of objects used to detect recursion during object encoding + * + * @var object + */ + protected $objectStack = array(); + + /** + * Flag to enable/disable logging + * + * @var boolean + */ + protected $enabled = true; + + /** + * The object constructor + */ + function __construct() { + } + + /** + * When the object gets serialized only include specific object members. + * + * @return array + */ + public function __sleep() { + return array('options','objectFilters','enabled'); + } + + /** + * Gets singleton instance of FirePHP + * + * @param boolean $AutoCreate + * @return FirePHP + */ + public static function getInstance($AutoCreate=false) { + if($AutoCreate===true && !self::$instance) { + self::init(); + } + return self::$instance; + } + + /** + * Creates FirePHP object and stores it for singleton access + * + * @return FirePHP + */ + public static function init() { + return self::$instance = new self(); + } + + /** + * Enable and disable logging to Firebug + * + * @param boolean $Enabled TRUE to enable, FALSE to disable + * @return void + */ + public function setEnabled($Enabled) { + $this->enabled = $Enabled; + } + + /** + * Check if logging is enabled + * + * @return boolean TRUE if enabled + */ + public function getEnabled() { + return $this->enabled; + } + + /** + * Specify a filter to be used when encoding an object + * + * Filters are used to exclude object members. + * + * @param string $Class The class name of the object + * @param array $Filter An array of members to exclude + * @return void + */ + public function setObjectFilter($Class, $Filter) { + $this->objectFilters[strtolower($Class)] = $Filter; + } + + /** + * Set some options for the library + * + * Options: + * - maxObjectDepth: The maximum depth to traverse objects (default: 10) + * - maxArrayDepth: The maximum depth to traverse arrays (default: 20) + * - useNativeJsonEncode: If true will use json_encode() (default: true) + * - includeLineNumbers: If true will include line numbers and filenames (default: true) + * + * @param array $Options The options to be set + * @return void + */ + public function setOptions($Options) { + $this->options = array_merge($this->options,$Options); + } + + /** + * Get options from the library + * + * @return array The currently set options + */ + public function getOptions() { + return $this->options; + } + + /** + * Register FirePHP as your error handler + * + * Will throw exceptions for each php error. + * + * @return mixed Returns a string containing the previously defined error handler (if any) + */ + public function registerErrorHandler($throwErrorExceptions=true) + { + //NOTE: The following errors will not be caught by this error handler: + // E_ERROR, E_PARSE, E_CORE_ERROR, + // E_CORE_WARNING, E_COMPILE_ERROR, + // E_COMPILE_WARNING, E_STRICT + + $this->throwErrorExceptions = $throwErrorExceptions; + + return set_error_handler(array($this,'errorHandler')); + } + + /** + * FirePHP's error handler + * + * Throws exception for each php error that will occur. + * + * @param int $errno + * @param string $errstr + * @param string $errfile + * @param int $errline + * @param array $errcontext + */ + public function errorHandler($errno, $errstr, $errfile, $errline, $errcontext) + { + // Don't throw exception if error reporting is switched off + if (error_reporting() == 0) { + return; + } + // Only throw exceptions for errors we are asking for + if (error_reporting() & $errno) { + + $exception = new ErrorException($errstr, 0, $errno, $errfile, $errline); + if($this->throwErrorExceptions) { + throw $exception; + } else { + $this->fb($exception); + } + } + } + + /** + * Register FirePHP as your exception handler + * + * @return mixed Returns the name of the previously defined exception handler, + * or NULL on error. + * If no previous handler was defined, NULL is also returned. + */ + public function registerExceptionHandler() + { + return set_exception_handler(array($this,'exceptionHandler')); + } + + /** + * FirePHP's exception handler + * + * Logs all exceptions to your firebug console and then stops the script. + * + * @param Exception $Exception + * @throws Exception + */ + function exceptionHandler($Exception) { + + $this->inExceptionHandler = true; + + header('HTTP/1.1 500 Internal Server Error'); + + $this->fb($Exception); + + $this->inExceptionHandler = false; + } + + /** + * Register FirePHP driver as your assert callback + * + * @param boolean $convertAssertionErrorsToExceptions + * @param boolean $throwAssertionExceptions + * @return mixed Returns the original setting or FALSE on errors + */ + public function registerAssertionHandler($convertAssertionErrorsToExceptions=true, $throwAssertionExceptions=false) + { + $this->convertAssertionErrorsToExceptions = $convertAssertionErrorsToExceptions; + $this->throwAssertionExceptions = $throwAssertionExceptions; + + if($throwAssertionExceptions && !$convertAssertionErrorsToExceptions) { + throw $this->newException('Cannot throw assertion exceptions as assertion errors are not being converted to exceptions!'); + } + + return assert_options(ASSERT_CALLBACK, array($this, 'assertionHandler')); + } + + /** + * FirePHP's assertion handler + * + * Logs all assertions to your firebug console and then stops the script. + * + * @param string $file File source of assertion + * @param int $line Line source of assertion + * @param mixed $code Assertion code + */ + public function assertionHandler($file, $line, $code) + { + + if($this->convertAssertionErrorsToExceptions) { + + $exception = new ErrorException('Assertion Failed - Code[ '.$code.' ]', 0, null, $file, $line); + + if($this->throwAssertionExceptions) { + throw $exception; + } else { + $this->fb($exception); + } + + } else { + + $this->fb($code, 'Assertion Failed', FirePHP::ERROR, array('File'=>$file,'Line'=>$line)); + + } + } + + /** + * Set custom processor url for FirePHP + * + * @param string $URL + */ + public function setProcessorUrl($URL) + { + $this->setHeader('X-FirePHP-ProcessorURL', $URL); + } + + /** + * Set custom renderer url for FirePHP + * + * @param string $URL + */ + public function setRendererUrl($URL) + { + $this->setHeader('X-FirePHP-RendererURL', $URL); + } + + /** + * Start a group for following messages. + * + * Options: + * Collapsed: [true|false] + * Color: [#RRGGBB|ColorName] + * + * @param string $Name + * @param array $Options OPTIONAL Instructions on how to log the group + * @return true + * @throws Exception + */ + public function group($Name, $Options=null) { + + if(!$Name) { + throw $this->newException('You must specify a label for the group!'); + } + + if($Options) { + if(!is_array($Options)) { + throw $this->newException('Options must be defined as an array!'); + } + if(array_key_exists('Collapsed', $Options)) { + $Options['Collapsed'] = ($Options['Collapsed'])?'true':'false'; + } + } + + return $this->fb(null, $Name, FirePHP::GROUP_START, $Options); + } + + /** + * Ends a group you have started before + * + * @return true + * @throws Exception + */ + public function groupEnd() { + return $this->fb(null, null, FirePHP::GROUP_END); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::LOG + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public function log($Object, $Label=null) { + return $this->fb($Object, $Label, FirePHP::LOG); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::INFO + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public function info($Object, $Label=null) { + return $this->fb($Object, $Label, FirePHP::INFO); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::WARN + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public function warn($Object, $Label=null) { + return $this->fb($Object, $Label, FirePHP::WARN); + } + + /** + * Log object with label to firebug console + * + * @see FirePHP::ERROR + * @param mixes $Object + * @param string $Label + * @return true + * @throws Exception + */ + public function error($Object, $Label=null) { + return $this->fb($Object, $Label, FirePHP::ERROR); + } + + /** + * Dumps key and variable to firebug server panel + * + * @see FirePHP::DUMP + * @param string $Key + * @param mixed $Variable + * @return true + * @throws Exception + */ + public function dump($Key, $Variable) { + return $this->fb($Variable, $Key, FirePHP::DUMP); + } + + /** + * Log a trace in the firebug console + * + * @see FirePHP::TRACE + * @param string $Label + * @return true + * @throws Exception + */ + public function trace($Label) { + return $this->fb($Label, FirePHP::TRACE); + } + + /** + * Log a table in the firebug console + * + * @see FirePHP::TABLE + * @param string $Label + * @param string $Table + * @return true + * @throws Exception + */ + public function table($Label, $Table) { + return $this->fb($Table, $Label, FirePHP::TABLE); + } + + /** + * Check if FirePHP is installed on client + * + * @return boolean + */ + public function detectClientExtension() { + /* Check if FirePHP is installed on client */ + if(!@preg_match_all('/\sFirePHP\/([\.|\d]*)\s?/si',$this->getUserAgent(),$m) || + !version_compare($m[1][0],'0.0.6','>=')) { + return false; + } + return true; + } + + /** + * Log varible to Firebug + * + * @see http://www.firephp.org/Wiki/Reference/Fb + * @param mixed $Object The variable to be logged + * @return true Return TRUE if message was added to headers, FALSE otherwise + * @throws Exception + */ + public function fb($Object) { + + if(!$this->enabled) { + return false; + } + + if (headers_sent($filename, $linenum)) { + // If we are logging from within the exception handler we cannot throw another exception + if($this->inExceptionHandler) { + // Simply echo the error out to the page + echo '<div style="border: 2px solid red; font-family: Arial; font-size: 12px; background-color: lightgray; padding: 5px;"><span style="color: red; font-weight: bold;">FirePHP ERROR:</span> Headers already sent in <b>'.$filename.'</b> on line <b>'.$linenum.'</b>. Cannot send log data to FirePHP. You must have Output Buffering enabled via ob_start() or output_buffering ini directive.</div>'; + } else { + throw $this->newException('Headers already sent in '.$filename.' on line '.$linenum.'. Cannot send log data to FirePHP. You must have Output Buffering enabled via ob_start() or output_buffering ini directive.'); + } + } + + $Type = null; + $Label = null; + $Options = array(); + + if(func_num_args()==1) { + } else + if(func_num_args()==2) { + switch(func_get_arg(1)) { + case self::LOG: + case self::INFO: + case self::WARN: + case self::ERROR: + case self::DUMP: + case self::TRACE: + case self::EXCEPTION: + case self::TABLE: + case self::GROUP_START: + case self::GROUP_END: + $Type = func_get_arg(1); + break; + default: + $Label = func_get_arg(1); + break; + } + } else + if(func_num_args()==3) { + $Type = func_get_arg(2); + $Label = func_get_arg(1); + } else + if(func_num_args()==4) { + $Type = func_get_arg(2); + $Label = func_get_arg(1); + $Options = func_get_arg(3); + } else { + throw $this->newException('Wrong number of arguments to fb() function!'); + } + + + if(!$this->detectClientExtension()) { + return false; + } + + $meta = array(); + $skipFinalObjectEncode = false; + + if($Object instanceof Exception) { + + $meta['file'] = $this->_escapeTraceFile($Object->getFile()); + $meta['line'] = $Object->getLine(); + + $trace = $Object->getTrace(); + if($Object instanceof ErrorException + && isset($trace[0]['function']) + && $trace[0]['function']=='errorHandler' + && isset($trace[0]['class']) + && $trace[0]['class']=='FirePHP') { + + $severity = false; + switch($Object->getSeverity()) { + case E_WARNING: $severity = 'E_WARNING'; break; + case E_NOTICE: $severity = 'E_NOTICE'; break; + case E_USER_ERROR: $severity = 'E_USER_ERROR'; break; + case E_USER_WARNING: $severity = 'E_USER_WARNING'; break; + case E_USER_NOTICE: $severity = 'E_USER_NOTICE'; break; + case E_STRICT: $severity = 'E_STRICT'; break; + case E_RECOVERABLE_ERROR: $severity = 'E_RECOVERABLE_ERROR'; break; + case E_DEPRECATED: $severity = 'E_DEPRECATED'; break; + case E_USER_DEPRECATED: $severity = 'E_USER_DEPRECATED'; break; + } + + $Object = array('Class'=>get_class($Object), + 'Message'=>$severity.': '.$Object->getMessage(), + 'File'=>$this->_escapeTraceFile($Object->getFile()), + 'Line'=>$Object->getLine(), + 'Type'=>'trigger', + 'Trace'=>$this->_escapeTrace(array_splice($trace,2))); + $skipFinalObjectEncode = true; + } else { + $Object = array('Class'=>get_class($Object), + 'Message'=>$Object->getMessage(), + 'File'=>$this->_escapeTraceFile($Object->getFile()), + 'Line'=>$Object->getLine(), + 'Type'=>'throw', + 'Trace'=>$this->_escapeTrace($trace)); + $skipFinalObjectEncode = true; + } + $Type = self::EXCEPTION; + + } else + if($Type==self::TRACE) { + + $trace = debug_backtrace(); + if(!$trace) return false; + for( $i=0 ; $i<sizeof($trace) ; $i++ ) { + + if(isset($trace[$i]['class']) + && isset($trace[$i]['file']) + && ($trace[$i]['class']=='FirePHP' + || $trace[$i]['class']=='FB') + && (substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php' + || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.php')) { + /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */ + } else + if(isset($trace[$i]['class']) + && isset($trace[$i+1]['file']) + && $trace[$i]['class']=='FirePHP' + && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') { + /* Skip fb() */ + } else + if($trace[$i]['function']=='fb' + || $trace[$i]['function']=='trace' + || $trace[$i]['function']=='send') { + $Object = array('Class'=>isset($trace[$i]['class'])?$trace[$i]['class']:'', + 'Type'=>isset($trace[$i]['type'])?$trace[$i]['type']:'', + 'Function'=>isset($trace[$i]['function'])?$trace[$i]['function']:'', + 'Message'=>$trace[$i]['args'][0], + 'File'=>isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):'', + 'Line'=>isset($trace[$i]['line'])?$trace[$i]['line']:'', + 'Args'=>isset($trace[$i]['args'])?$this->encodeObject($trace[$i]['args']):'', + 'Trace'=>$this->_escapeTrace(array_splice($trace,$i+1))); + + $skipFinalObjectEncode = true; + $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):''; + $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:''; + break; + } + } + + } else + if($Type==self::TABLE) { + + if(isset($Object[0]) && is_string($Object[0])) { + $Object[1] = $this->encodeTable($Object[1]); + } else { + $Object = $this->encodeTable($Object); + } + + $skipFinalObjectEncode = true; + + } else + if($Type==self::GROUP_START) { + + if(!$Label) { + throw $this->newException('You must specify a label for the group!'); + } + + } else { + if($Type===null) { + $Type = self::LOG; + } + } + + if($this->options['includeLineNumbers']) { + if(!isset($meta['file']) || !isset($meta['line'])) { + + $trace = debug_backtrace(); + for( $i=0 ; $trace && $i<sizeof($trace) ; $i++ ) { + + if(isset($trace[$i]['class']) + && isset($trace[$i]['file']) + && ($trace[$i]['class']=='FirePHP' + || $trace[$i]['class']=='FB') + && (substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php' + || substr($this->_standardizePath($trace[$i]['file']),-29,29)=='FirePHPCore/FirePHP.php')) { + /* Skip - FB::trace(), FB::send(), $firephp->trace(), $firephp->fb() */ + } else + if(isset($trace[$i]['class']) + && isset($trace[$i+1]['file']) + && $trace[$i]['class']=='FirePHP' + && substr($this->_standardizePath($trace[$i+1]['file']),-18,18)=='FirePHPCore/fb.php') { + /* Skip fb() */ + } else + if(isset($trace[$i]['file']) + && substr($this->_standardizePath($trace[$i]['file']),-18,18)=='FirePHPCore/fb.php') { + /* Skip FB::fb() */ + } else { + $meta['file'] = isset($trace[$i]['file'])?$this->_escapeTraceFile($trace[$i]['file']):''; + $meta['line'] = isset($trace[$i]['line'])?$trace[$i]['line']:''; + break; + } + } + + } + } else { + unset($meta['file']); + unset($meta['line']); + } + + $this->setHeader('X-Wf-Protocol-1','http://meta.wildfirehq.org/Protocol/JsonStream/0.2'); + $this->setHeader('X-Wf-1-Plugin-1','http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/'.self::VERSION); + + $structure_index = 1; + if($Type==self::DUMP) { + $structure_index = 2; + $this->setHeader('X-Wf-1-Structure-2','http://meta.firephp.org/Wildfire/Structure/FirePHP/Dump/0.1'); + } else { + $this->setHeader('X-Wf-1-Structure-1','http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1'); + } + + if($Type==self::DUMP) { + $msg = '{"'.$Label.'":'.$this->jsonEncode($Object, $skipFinalObjectEncode).'}'; + } else { + $msg_meta = $Options; + $msg_meta['Type'] = $Type; + if($Label!==null) { + $msg_meta['Label'] = $Label; + } + if(isset($meta['file']) && !isset($msg_meta['File'])) { + $msg_meta['File'] = $meta['file']; + } + if(isset($meta['line']) && !isset($msg_meta['Line'])) { + $msg_meta['Line'] = $meta['line']; + } + $msg = '['.$this->jsonEncode($msg_meta).','.$this->jsonEncode($Object, $skipFinalObjectEncode).']'; + } + + $parts = explode("\n",chunk_split($msg, 5000, "\n")); + + for( $i=0 ; $i<count($parts) ; $i++) { + + $part = $parts[$i]; + if ($part) { + + if(count($parts)>2) { + // Message needs to be split into multiple parts + $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex, + (($i==0)?strlen($msg):'') + . '|' . $part . '|' + . (($i<count($parts)-2)?'\\':'')); + } else { + $this->setHeader('X-Wf-1-'.$structure_index.'-'.'1-'.$this->messageIndex, + strlen($part) . '|' . $part . '|'); + } + + $this->messageIndex++; + + if ($this->messageIndex > 99999) { + throw $this->newException('Maximum number (99,999) of messages reached!'); + } + } + } + + $this->setHeader('X-Wf-1-Index',$this->messageIndex-1); + + return true; + } + + /** + * Standardizes path for windows systems. + * + * @param string $Path + * @return string + */ + protected function _standardizePath($Path) { + return preg_replace('/\\\\+/','/',$Path); + } + + /** + * Escape trace path for windows systems + * + * @param array $Trace + * @return array + */ + protected function _escapeTrace($Trace) { + if(!$Trace) return $Trace; + for( $i=0 ; $i<sizeof($Trace) ; $i++ ) { + if(isset($Trace[$i]['file'])) { + $Trace[$i]['file'] = $this->_escapeTraceFile($Trace[$i]['file']); + } + if(isset($Trace[$i]['args'])) { + $Trace[$i]['args'] = $this->encodeObject($Trace[$i]['args']); + } + } + return $Trace; + } + + /** + * Escape file information of trace for windows systems + * + * @param string $File + * @return string + */ + protected function _escapeTraceFile($File) { + /* Check if we have a windows filepath */ + if(strpos($File,'\\')) { + /* First strip down to single \ */ + + $file = preg_replace('/\\\\+/','\\',$File); + + return $file; + } + return $File; + } + + /** + * Send header + * + * @param string $Name + * @param string_type $Value + */ + protected function setHeader($Name, $Value) { + return header($Name.': '.$Value); + } + + /** + * Get user agent + * + * @return string|false + */ + protected function getUserAgent() { + if(!isset($_SERVER['HTTP_USER_AGENT'])) return false; + return $_SERVER['HTTP_USER_AGENT']; + } + + /** + * Returns a new exception + * + * @param string $Message + * @return Exception + */ + protected function newException($Message) { + return new Exception($Message); + } + + /** + * Encode an object into a JSON string + * + * Uses PHP's jeson_encode() if available + * + * @param object $Object The object to be encoded + * @return string The JSON string + */ + public function jsonEncode($Object, $skipObjectEncode=false) + { + if(!$skipObjectEncode) { + $Object = $this->encodeObject($Object); + } + + if(function_exists('json_encode') + && $this->options['useNativeJsonEncode']!=false) { + + return json_encode($Object); + } else { + return $this->json_encode($Object); + } + } + + /** + * Encodes a table by encoding each row and column with encodeObject() + * + * @param array $Table The table to be encoded + * @return array + */ + protected function encodeTable($Table) { + + if(!$Table) return $Table; + + $new_table = array(); + foreach($Table as $row) { + + if(is_array($row)) { + $new_row = array(); + + foreach($row as $item) { + $new_row[] = $this->encodeObject($item); + } + + $new_table[] = $new_row; + } + } + + return $new_table; + } + + /** + * Encodes an object including members with + * protected and private visibility + * + * @param Object $Object The object to be encoded + * @param int $Depth The current traversal depth + * @return array All members of the object + */ + protected function encodeObject($Object, $ObjectDepth = 1, $ArrayDepth = 1) + { + $return = array(); + + if (is_resource($Object)) { + + return '** '.(string)$Object.' **'; + + } else + if (is_object($Object)) { + + if ($ObjectDepth > $this->options['maxObjectDepth']) { + return '** Max Object Depth ('.$this->options['maxObjectDepth'].') **'; + } + + foreach ($this->objectStack as $refVal) { + if ($refVal === $Object) { + return '** Recursion ('.get_class($Object).') **'; + } + } + array_push($this->objectStack, $Object); + + $return['__className'] = $class = get_class($Object); + $class_lower = strtolower($class); + + $reflectionClass = new ReflectionClass($class); + $properties = array(); + foreach( $reflectionClass->getProperties() as $property) { + $properties[$property->getName()] = $property; + } + + $members = (array)$Object; + + foreach( $properties as $raw_name => $property ) { + + $name = $raw_name; + if($property->isStatic()) { + $name = 'static:'.$name; + } + if($property->isPublic()) { + $name = 'public:'.$name; + } else + if($property->isPrivate()) { + $name = 'private:'.$name; + $raw_name = "\0".$class."\0".$raw_name; + } else + if($property->isProtected()) { + $name = 'protected:'.$name; + $raw_name = "\0".'*'."\0".$raw_name; + } + + if(!(isset($this->objectFilters[$class_lower]) + && is_array($this->objectFilters[$class_lower]) + && in_array($raw_name,$this->objectFilters[$class_lower]))) { + + if(array_key_exists($raw_name,$members) + && !$property->isStatic()) { + + $return[$name] = $this->encodeObject($members[$raw_name], $ObjectDepth + 1, 1); + + } else { + if(method_exists($property,'setAccessible')) { + $property->setAccessible(true); + $return[$name] = $this->encodeObject($property->getValue($Object), $ObjectDepth + 1, 1); + } else + if($property->isPublic()) { + $return[$name] = $this->encodeObject($property->getValue($Object), $ObjectDepth + 1, 1); + } else { + $return[$name] = '** Need PHP 5.3 to get value **'; + } + } + } else { + $return[$name] = '** Excluded by Filter **'; + } + } + + // Include all members that are not defined in the class + // but exist in the object + foreach( $members as $raw_name => $value ) { + + $name = $raw_name; + + if ($name{0} == "\0") { + $parts = explode("\0", $name); + $name = $parts[2]; + } + + if(!isset($properties[$name])) { + $name = 'undeclared:'.$name; + + if(!(isset($this->objectFilters[$class_lower]) + && is_array($this->objectFilters[$class_lower]) + && in_array($raw_name,$this->objectFilters[$class_lower]))) { + + $return[$name] = $this->encodeObject($value, $ObjectDepth + 1, 1); + } else { + $return[$name] = '** Excluded by Filter **'; + } + } + } + + array_pop($this->objectStack); + + } elseif (is_array($Object)) { + + if ($ArrayDepth > $this->options['maxArrayDepth']) { + return '** Max Array Depth ('.$this->options['maxArrayDepth'].') **'; + } + + foreach ($Object as $key => $val) { + + // Encoding the $GLOBALS PHP array causes an infinite loop + // if the recursion is not reset here as it contains + // a reference to itself. This is the only way I have come up + // with to stop infinite recursion in this case. + if($key=='GLOBALS' + && is_array($val) + && array_key_exists('GLOBALS',$val)) { + $val['GLOBALS'] = '** Recursion (GLOBALS) **'; + } + + $return[$key] = $this->encodeObject($val, 1, $ArrayDepth + 1); + } + } else { + if(self::is_utf8($Object)) { + return $Object; + } else { + return utf8_encode($Object); + } + } + return $return; + } + + /** + * Returns true if $string is valid UTF-8 and false otherwise. + * + * @param mixed $str String to be tested + * @return boolean + */ + protected static function is_utf8($str) { + $c=0; $b=0; + $bits=0; + $len=strlen($str); + for($i=0; $i<$len; $i++){ + $c=ord($str[$i]); + if($c > 128){ + if(($c >= 254)) return false; + elseif($c >= 252) $bits=6; + elseif($c >= 248) $bits=5; + elseif($c >= 240) $bits=4; + elseif($c >= 224) $bits=3; + elseif($c >= 192) $bits=2; + else return false; + if(($i+$bits) > $len) return false; + while($bits > 1){ + $i++; + $b=ord($str[$i]); + if($b < 128 || $b > 191) return false; + $bits--; + } + } + } + return true; + } + + /** + * Converts to and from JSON format. + * + * JSON (JavaScript Object Notation) is a lightweight data-interchange + * format. It is easy for humans to read and write. It is easy for machines + * to parse and generate. It is based on a subset of the JavaScript + * Programming Language, Standard ECMA-262 3rd Edition - December 1999. + * This feature can also be found in Python. JSON is a text format that is + * completely language independent but uses conventions that are familiar + * to programmers of the C-family of languages, including C, C++, C#, Java, + * JavaScript, Perl, TCL, and many others. These properties make JSON an + * ideal data-interchange language. + * + * This package provides a simple encoder and decoder for JSON notation. It + * is intended for use with client-side Javascript applications that make + * use of HTTPRequest to perform server communication functions - data can + * be encoded into JSON notation for use in a client-side javascript, or + * decoded from incoming Javascript requests. JSON format is native to + * Javascript, and can be directly eval()'ed with no further parsing + * overhead + * + * All strings should be in ASCII or UTF-8 format! + * + * LICENSE: Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: Redistributions of source code must retain the + * above copyright notice, this list of conditions and the following + * disclaimer. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED ``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 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. + * + * @category + * @package Services_JSON + * @author Michal Migurski <mike-json@teczno.com> + * @author Matt Knapp <mdknapp[at]gmail[dot]com> + * @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com> + * @author Christoph Dorn <christoph@christophdorn.com> + * @copyright 2005 Michal Migurski + * @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $ + * @license http://www.opensource.org/licenses/bsd-license.php + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198 + */ + + + /** + * Keep a list of objects as we descend into the array so we can detect recursion. + */ + private $json_objectStack = array(); + + + /** + * convert a string from one UTF-8 char to one UTF-16 char + * + * Normally should be handled by mb_convert_encoding, but + * provides a slower PHP-only method for installations + * that lack the multibye string extension. + * + * @param string $utf8 UTF-8 character + * @return string UTF-16 character + * @access private + */ + private function json_utf82utf16($utf8) + { + // oh please oh please oh please oh please oh please + if(function_exists('mb_convert_encoding')) { + return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8'); + } + + switch(strlen($utf8)) { + case 1: + // this case should never be reached, because we are in ASCII range + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return $utf8; + + case 2: + // return a UTF-16 character from a 2-byte UTF-8 char + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0x07 & (ord($utf8{0}) >> 2)) + . chr((0xC0 & (ord($utf8{0}) << 6)) + | (0x3F & ord($utf8{1}))); + + case 3: + // return a UTF-16 character from a 3-byte UTF-8 char + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr((0xF0 & (ord($utf8{0}) << 4)) + | (0x0F & (ord($utf8{1}) >> 2))) + . chr((0xC0 & (ord($utf8{1}) << 6)) + | (0x7F & ord($utf8{2}))); + } + + // ignoring UTF-32 for now, sorry + return ''; + } + + /** + * encodes an arbitrary variable into JSON format + * + * @param mixed $var any number, boolean, string, array, or object to be encoded. + * see argument 1 to Services_JSON() above for array-parsing behavior. + * if var is a strng, note that encode() always expects it + * to be in ASCII or UTF-8 format! + * + * @return mixed JSON string representation of input var or an error if a problem occurs + * @access public + */ + private function json_encode($var) + { + + if(is_object($var)) { + if(in_array($var,$this->json_objectStack)) { + return '"** Recursion **"'; + } + } + + switch (gettype($var)) { + case 'boolean': + return $var ? 'true' : 'false'; + + case 'NULL': + return 'null'; + + case 'integer': + return (int) $var; + + case 'double': + case 'float': + return (float) $var; + + case 'string': + // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT + $ascii = ''; + $strlen_var = strlen($var); + + /* + * Iterate over every character in the string, + * escaping with a slash or encoding to UTF-8 where necessary + */ + for ($c = 0; $c < $strlen_var; ++$c) { + + $ord_var_c = ord($var{$c}); + + switch (true) { + case $ord_var_c == 0x08: + $ascii .= '\b'; + break; + case $ord_var_c == 0x09: + $ascii .= '\t'; + break; + case $ord_var_c == 0x0A: + $ascii .= '\n'; + break; + case $ord_var_c == 0x0C: + $ascii .= '\f'; + break; + case $ord_var_c == 0x0D: + $ascii .= '\r'; + break; + + case $ord_var_c == 0x22: + case $ord_var_c == 0x2F: + case $ord_var_c == 0x5C: + // double quote, slash, slosh + $ascii .= '\\'.$var{$c}; + break; + + case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): + // characters U-00000000 - U-0000007F (same as ASCII) + $ascii .= $var{$c}; + break; + + case (($ord_var_c & 0xE0) == 0xC0): + // characters U-00000080 - U-000007FF, mask 110XXXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, ord($var{$c + 1})); + $c += 1; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xF0) == 0xE0): + // characters U-00000800 - U-0000FFFF, mask 1110XXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2})); + $c += 2; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xF8) == 0xF0): + // characters U-00010000 - U-001FFFFF, mask 11110XXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3})); + $c += 3; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xFC) == 0xF8): + // characters U-00200000 - U-03FFFFFF, mask 111110XX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3}), + ord($var{$c + 4})); + $c += 4; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xFE) == 0xFC): + // characters U-04000000 - U-7FFFFFFF, mask 1111110X + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3}), + ord($var{$c + 4}), + ord($var{$c + 5})); + $c += 5; + $utf16 = $this->json_utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + } + } + + return '"'.$ascii.'"'; + + case 'array': + /* + * As per JSON spec if any array key is not an integer + * we must treat the the whole array as an object. We + * also try to catch a sparsely populated associative + * array with numeric keys here because some JS engines + * will create an array with empty indexes up to + * max_index which can cause memory issues and because + * the keys, which may be relevant, will be remapped + * otherwise. + * + * As per the ECMA and JSON specification an object may + * have any string as a property. Unfortunately due to + * a hole in the ECMA specification if the key is a + * ECMA reserved word or starts with a digit the + * parameter is only accessible using ECMAScript's + * bracket notation. + */ + + // treat as a JSON object + if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) { + + $this->json_objectStack[] = $var; + + $properties = array_map(array($this, 'json_name_value'), + array_keys($var), + array_values($var)); + + array_pop($this->json_objectStack); + + foreach($properties as $property) { + if($property instanceof Exception) { + return $property; + } + } + + return '{' . join(',', $properties) . '}'; + } + + $this->json_objectStack[] = $var; + + // treat it like a regular array + $elements = array_map(array($this, 'json_encode'), $var); + + array_pop($this->json_objectStack); + + foreach($elements as $element) { + if($element instanceof Exception) { + return $element; + } + } + + return '[' . join(',', $elements) . ']'; + + case 'object': + $vars = self::encodeObject($var); + + $this->json_objectStack[] = $var; + + $properties = array_map(array($this, 'json_name_value'), + array_keys($vars), + array_values($vars)); + + array_pop($this->json_objectStack); + + foreach($properties as $property) { + if($property instanceof Exception) { + return $property; + } + } + + return '{' . join(',', $properties) . '}'; + + default: + return null; + } + } + + /** + * array-walking function for use in generating JSON-formatted name-value pairs + * + * @param string $name name of key to use + * @param mixed $value reference to an array element to be encoded + * + * @return string JSON-formatted name-value pair, like '"name":value' + * @access private + */ + private function json_name_value($name, $value) + { + // Encoding the $GLOBALS PHP array causes an infinite loop + // if the recursion is not reset here as it contains + // a reference to itself. This is the only way I have come up + // with to stop infinite recursion in this case. + if($name=='GLOBALS' + && is_array($value) + && array_key_exists('GLOBALS',$value)) { + $value['GLOBALS'] = '** Recursion **'; + } + + $encoded_value = $this->json_encode($value); + + if($encoded_value instanceof Exception) { + return $encoded_value; + } + + return $this->json_encode(strval($name)) . ':' . $encoded_value; + } +} diff --git a/bin/svdrp.php b/bin/svdrp.php new file mode 100644 index 0000000..401d6d5 --- /dev/null +++ b/bin/svdrp.php @@ -0,0 +1,534 @@ +<?php +/** + * This file contain everything needed to communicate with a VDR instance + * This is merely a rewrite of the original class which was written in + * PHP4 and published some years ago. + * I wasn't able to find the original author name in order to give him + * credits. + * + * PHP version 5.1+ + * + * @author Philippe Gaultier <pgaultier[at]gmail.com> + * @license BSD License http://fr.wikipedia.org/wiki/Licence_BSD + * @link http://www.linuxtv.org/vdrwiki/index.php/Svdrp + */ +require_once ('firephp.php'); +$a = new SVDRP ( null, null, null, false ); +$a->connect (); +$a->listChannels (); +/** + * SVDRP class + * + * This class provide access to VDR SVDRP service + * + * @package utilities + * @author Philippe Gaultier <pgaultier[at]gmail.com> + * @since 1.0 + */ +class SVDRP { + private $_server = "localhost"; + private $_port = 2001; + private $_timeOut = 30; + + private $_handle = false; + private $_debug = false; + + private $_firePhp = null; + + /** + * Class constructor + * + * @param string $server the server to connect to (IP or name) + * @param integer $port the port number + * @param integer $timeOut timeout before closing the connection + * @param boolean $debug de/activate debug functions + * + * @return SVDRP + */ + public function __construct($server = null, $port = null, $timeOut = null, $debug = null) { + if ($server !== null) { + $this->_server = $server; + } + if ($port !== null) { + $this->_port = $port; + } + if ($timeOut !== null) { + $this->_timeOut = $timeOut; + } + if ($debug !== null) { + $this->_debug = $debug; + } + if (class_exists ( 'FirePHP' )) { + $this->_firePhp = FirePHP::getInstance ( true ); + $this->_firePhp->setEnabled ( $this->_debug ); + $this->group ( 'new ' . __CLASS__ . '($server, $port, $timeOut, $debug)' ); + $this->info ( $this->_server, '$server' ); + $this->info ( $this->_port, '$port' ); + $this->info ( $this->_timeOut, '$timeOut' ); + $this->info ( $this->_debug, '$debug' ); + $this->trace ( 'Object created' ); + $this->groupEnd (); + } else { + $this->_debug = false; + } + } + private function group($title) { + if ($this->_debug === true) { + $this->_firePhp->group ( $title ); + } + } + private function groupEnd() { + if ($this->_debug === true) { + $this->_firePhp->groupEnd (); + } + } + private function trace($message) { + if ($this->_debug === true) { + $this->_firePhp->trace ( 'Class ' . __CLASS__ . ' Trace : ' . $message ); + } + } + private function dump($name, $var) { + if ($this->_debug === true) { + $this->_firePhp->dump ( $name, $var ); + } + } + private function log($message, $label = null) { + if ($this->_debug === true) { + $this->_firePhp->log ( $message, $label ); + } + } + private function info($message, $label = null) { + if ($this->_debug === true) { + $this->_firePhp->info ( $message, $label ); + } + } + private function warn($message, $label = null) { + if ($this->_debug === true) { + $this->_firePhp->warn ( $message, $label ); + } + } + private function error($message, $label = null) { + if ($this->_debug === true) { + $this->_firePhp->error ( $message, $label ); + } + } + public function debugMessage($msg) { + if ($this->_debug === true) { + //TODO: do a better debug (use firePHP or something else) + // echo ($msg); + } + } + + public function connect() { + $result = false; + if ($this->_handle !== false) { + $this->disconnect (); + } + $errno = 0; + $errstr = ""; + // we use @ in order to avoid warning if server does not answer / allow the connection + $this->_handle = @fsockopen ( $this->_server, $this->_port, &$errno, &$errstr, $this->_timeOut ); + $this->group ( __METHOD__ . '()' ); + if ($this->_handle !== false) { + $this->info ( 'Handle created', 'SVDRP' ); + $input = fgets ( $this->_handle, 128 ); + + if ((preg_match ( "/^220 /", $input ) === true) && ($input != "")) { + $this->info ( 'Answer OK : ' . $input, 'SVDRP' ); + $result = true; + } else { + $this->warn ( 'Answer KO : ' . $input, 'SVDRP' ); + $this->disconnect (); + } + } else { + $this->error ( 'fsockopen error ' . $errno . ' (' . $errstr . ')', 'SVDRP' ); + } + $this->groupEnd (); + return $result; + } + + public function sendCommand($cmd) { + $result = false; + if ($this->_handle !== false) { + $result = array (); + $this->group ( __METHOD__ . '($cmd)' ); + $this->info ( $cmd, '$cmd' ); + fputs ( $this->_handle, $cmd . "\n" ); + $answer = ""; + $nbLines = 0; + while ( $answer .= fgets ( $this->_handle, 2048 ) ) { + $nbLines ++; + $this->info ( $answer ); + $data = null; + if (preg_match ( "/^(\\d{3})([ -])(.*)$/", $answer, $data ) === false) { + continue; + } + $number = $data [1]; + $result [] = trim ( $data [3] ); + /** + if(($data[2] !== "-") && ($nbLines === 1)) { + $result = trim($data[3]) ; + } + **/ + if ($data [2] != "-") { + break; + } + $answer = ""; + } + $this->trace ( 'Command sent, answer received' ); + $this->groupEnd (); + } + return $result; + } + + public function listChannels($channelNumberOrName = "") { + $lines = $this->sendCommand ( 'LSTC ' . $channelNumberOrName ); + if ($lines !== false) { + $channels = array (); + foreach ( $lines as $l ) { + list ( $fullName, $frequency, $parameters, $source, $symbolRate, $videoPid, $audioPid, $teletextPid, $conditionalAccess, $serviceId, $networkId, $transportId, $radioId ) = split ( ":", $l ); + list ( $shortName, $provider ) = split ( ";", $fullName ); + $channels [] = array ('shortName' => $shortName, 'provider' => $provider, 'frequency' => $frequency, 'parameters' => $parameters, 'source' => $source, 'symbolRate' => $symbolRate, 'videoPid' => $videoPid, 'audioPid' => $audioPid, 'teletextPid' => $teletextPid, 'conditionalAccess' => $conditionalAccess, 'serviceId' => $serviceId, 'networkId' => $networkId, 'transportId' => $transportId, 'radioId' => $radioId, 'group' => $provider, //XXX: Compatibility +'name' => $shortName );//XXX: Compatibility + + } + $lines = $channels; + } + return $lines; + } + + public function help() { + return $this->sendCommand ( 'HELP' ); + } + public function disconnect() { + if ($this->_handle !== false) { + $this->sendCommand ( 'QUIT' ); + fclose ( $this->_handle ); + $this->_handle = false; + $this->debugMessage ( "disconnected" ); + } + } + public function clearEpg() { + $result = $this->sendCommand ( 'CLRE' ); + if ($result !== false) { + $result = true; + } + return $result; + } + public function switchUp() { + return $this->switchChannel ( '+' ); + } + public function switchDown() { + return $this->switchChannel ( '-' ); + } + public function switchChannel($channel) { + $result = $this->sendCommand ( 'CHAN ' . $channel ); + if ($result !== false) { + $result = true; + } + return $result; + } + public function deleteChannel($channelId) { + $result = $this->sendCommand ( 'DELC ' . $channelId ); + if ($result !== false) { + $result = true; + } + return $result; + } + public function deleteRecord($recordId) { + $result = $this->sendCommand ( 'DELR ' . $recordId ); + if ($result !== false) { + $result = true; + } + return $result; + } + + public function grabImage($fileName, $type = 'jpeg', $quality = '', $width = '', $height) { + $result = $this->sendCommand ( 'GRAB ' . $fileName . ' ' . $type . ' ' . $quality . ' ' . $width . ' ' . $height ); + if ($result !== false) { + $result = true; + } + return $result; + } + public function hitKey($key) { + $result = $this->sendCommand ( 'HITK ' . $key ); + if ($result !== false) { + $result = true; + } + return $result; + } + public function powerOff() { + return $this->hitKey ( 'HITK Power' ); + } + public function getKeys() { + $lines = $this->sendCommand ( 'HITK' ); + if ($lines !== false) { + $keys = array (); + foreach ( $lines as $l ) { + if (preg_match ( "/^ {4}(.*)$/", $l, $m ) === false) { + continue; + } + $keys [] = $m [1]; + } + $lines = $keys; + } + return $lines; + } + public function listEPG($pStrChannel = "", $pStrTime = "") { + $lines = $this->sendCommand ( "LSTE" ); + if ($lines !== false) { + $epg = array (); + $channel = array (); + $event = array (); + $channelname = ""; + foreach ( $lines as $line ) { + if (preg_match ( "/^(.)\\s*(.*)$/", $line, $matches ) === true) { + $type = $matches [1]; + $text = $matches [2]; + switch ($type) { + case 'C' : // Channel + list ( $channeldata, $channelname ) = explode ( ' ', $text, 2 ); + break; + case 'E' : // new Event + sscanf ( $text, "%u %ld %d %X", $event ["EventID"], $event ["StartTime"], $event ["Duration"], $event ["TableID"] ); + break; + case 'T' : // Title + $event ["Title"] = $text; + break; + case 'S' : // Short text + $event ["Shottext"] = $text; + break; + case 'D' : // Description + $event ["Desc"] = $text; + break; + case 'V' : // VPS + $event ["VPS"] = $text; + break; + case 'e' : // Event end + if ((trim ( $pStrTime ) != '') && (($event ['StartTime'] > $pStrTime) || ($event ['StartTime'] + $event ["Duration"] < $pStrTime))) { + continue; + } + $channel [] = $event; + $event = array (); + break; + case 'c' : // Channel end + if ((trim ( $pStrChannel ) != '') && ($channelname != $pStrChannel)) { + continue; + } + $epg [$channelname] = $channel; + $channel = array (); + break; + } + } + } + if ((trim ( $pStrTime ) == '') || (($event ['StartTime'] < $pStrTime) && ($event ['StartTime'] + $event ["Duration"] > $pStrTime))) { + $channel [] = $event; + } + if ((trim ( $pStrChannel ) != '') || ($channelname == $pStrChannel)) { + $epg [$channelname] = $channel; + } + $lines = $epg; + } + return $lines; + } + + public function sendMessage($message) { + $result = $this->sendCommand ( 'MESG ' . $message ); + if ($result !== false) { + $result = true; + } + return $result; + } + /** + * Toggle volume + * + * @return boolean + */ + public function toggleMute() { + return $this->setVolume ( 'mute' ); + } + /** + * Raise sound volume + * + * @return boolean + */ + public function setVolumeUp() { + return $this->setVolume ( '+' ); + } + /** + * lower sound volume + * + * @return boolean + */ + public function setVolumeDown() { + return $this->setVolume ( '-' ); + } + /** + * Set volume to a specific value + * + * @param integer $volume new sound volume value + * + * @return boolean + */ + public function setVolume($volume) { + $result = $this->sendCommand ( 'VOLU ' . $volume ); + if ($result !== false) { + $result = true; + } + return $result; + } + /** + * Get current volume value + * + * @return boolean|integer + */ + public function getVolume() { + $result = $this->sendCommand ( 'VOLU' ); + if ($result !== false) { + $volumeData = array_shift ( $result ); + if ($volumeData == "Audio is mute") { + $result = 0; + } elseif (preg_match ( "/Audio volume is (.*)/", $volumeData, $matches ) === true) { + $result = $matches [1]; + } else { + $result = false; + } + } + return $result; + } + /** + * Get current disk information + * + * @return boolean|array + */ + public function getDiskInfo() { + $res = $this->sendCommand ( 'STAT DISK' ); + $result = $this->sendCommand ( 'STAT DISK' ); + if ($result !== false) { + $result = array_shift ( $result ); + sscanf ( $result, "%dMB %dMB %d%%", $data ['overall'], $data ['free'], $data ['percent'] ); + $data ['used'] = $data ['overall'] - $data ['free']; + $result = $data; + } + return $result; + } + /** + * Force a new scan + * + * @return boolean + */ + public function startScan() { + $result = $this->sendCommand ( 'SCAN' ); + if ($result !== false) { + $result = true; + } + return $result; + } + public function moveChannel($channelNumber, $target) { + $result = $this->sendCommand ( 'MOVC ' . $channelNumber . ' ' . $target ); + if ($result !== false) { + $result = true; + } + return $result; + } + + public function deleteTimer($timerId) { + $result = $this->sendCommand ( 'DELT ' . $timerId ); + if ($result !== false) { + $result = true; + } + return $result; + } + + public function moveTimer($timerNumber, $target) { + $result = $this->sendCommand ( 'MOVT ' . $timerNumber . ' ' . $target ); + if ($result !== false) { + $result = true; + } + return $result; + } + /** + * Change the status of a specific timer + * + * @param string $timerId timer id + * @param boolean $state status to set (true : on / false : off) + * + * @return boolean + */ + public function toggleTimer($timerId, $state = true) { + switch ($state) { + case false : + case 'off' : + case 0 : + $state = 'off'; + break; + default : + $state = 'on'; + break; + } + $result = $this->sendCommand ( 'MODT ' . $timerId . ' ' . $state ); + if ($result !== false) { + $result = true; + } + return $result; + } + + /** + * List all timers + * + * @return void + */ + public function listTimers() { + //TODO: implement timer listing + } + + /** + * List all recordings with specific data + * + * @return array + */ + public function listRecords() { + $lines = $this->sendCommand ( 'LSTR' ); + if ($lines !== false) { + $records = array (); + foreach ( $lines as $line ) { + if (preg_match ( '/^(\\d)\s(\\d*)\\.(\\d*)\\.(\\d*) (\\d*)\\:(\\d*).\s(.*)$/', $line, $matches ) == false) { + continue; + } + $records [$matches [1]] = array ('id' => $matches [1], 'day' => $matches [2], 'month' => $matches [3], 'year' => $matches [4], 'hour' => $matches [5], 'minute' => $matches [6], 'desc' => $matches [7] ); + } + $lines = $records; + } + return $lines; + } + + /** + * List recording by Id + * + * @param string $recordId + * + * @return string + */ + public function listRecord($recordId) { + //TODO: perhaps better implementation and check if we do not need array_shift + $lines = $this->sendCommand ( 'LSTR ' . $recordId ); + if ($lines !== false) { + $lines = array_shift ( $lines ); + $lines = $lines [0]; + } + return $lines; + } + +//TODO: Implement following commands: +/** + LSTT + MODT + NEWT + UPDT + MODC + NEWC + NEXT + PUTE + **/ +} + diff --git a/bin/vdr.php b/bin/vdr.php new file mode 100755 index 0000000..beda66c --- /dev/null +++ b/bin/vdr.php @@ -0,0 +1,471 @@ +<?php +include ('./svdrp.php'); + +function getGlobals() +{ + global $vdrstreamdev, $vdrrecpath, $mediasource; + + $ret = array(); + $ret['streamdev_server'] = $vdrstreamdev; + $ret['rec_path'] = $vdrrecpath; + $ret['video_path'] = "/mnt/media/Video/"; + $ret['audio_path'] = "/mnt/media/Music/"; + + return json_encode($ret); +} + +function getTvCat() +{ + global $vdrchannels; + + $catlist = array(); + + if (!file_exists($vdrchannels)) + { + print "Error: channels file not found"; + $ret['categories'] = $catlist; + return json_encode($ret); + } + + $fp = fopen ($vdrchannels,"r"); + if (!fp) + { + print "Unable to open channels file"; + $ret['categories'] = $catlist; + return json_encode($ret); + } + + $curcat = ""; + $curcatchancount = 0; + + while ($line = fgets($fp, 1024)) + { + // Check if it is a categorie + if ($line[0] == ":") + { + // Close current cat + if ($curcat != "") + { + $tmpcat = array(); + $tmpcat['name'] = $curcat; + $tmpcat['channels'] = $curcatchancount; + $catlist[] = $tmpcat; + + $curcatchancount = 0; + } + + // Remove : and @ + $curcat = substr($line, 1, -1); + if($curcat[0] == '@') + { + $catarray = explode(' ', $curcat); + $curcat = substr($curcat, strlen($catarray[0])+1); + } + } + else if ($line[0] != "") + $curcatchancount++; + } + + // Close last cat + if ($curcat != "") + { + $tmpcat = array(); + $tmpcat['name'] = $curcat; + $tmpcat['channels'] = $curcatchancount; + $catlist[] = $tmpcat; + } + + fclose($fp); + + $ret['categories'] = $catlist; + return json_encode($ret); +} + + + +function vdrsendcommand($cmd) +{ + global $svdrpip, $svdrpport; + + $svdrp = new SVDRP($svdrpip, $svdrpport); + $svdrp->Connect(); + $ret = $svdrp->Command($cmd); + $svdrp->Disconnect(); + + return $ret; +} + +function vdrgetinfostream($stream = "NULL", $ischan = 1) +{ + global $allepg, $allepgfilled; + $stream=stripslashes($stream); + if ($ischan) + { + // Fill epg if not yet done + if ($allepgfilled == 0) + { + $allepg = vdrsendcommand("LSTE NOW"); + $allepgfilled = 1; + } + + $channame = $stream; + } + else + { + $infofile = $stream ."/info"; + if (file_exists($infofile)) + $info= file_get_contents($infofile); + else + { + $infofile = $stream ."/info.vdr"; + if (file_exists($infofile)) + $info= file_get_contents($infofile); + else + $info=""; + } + + $allepg = explode("\n", $info); + } + + if ($ischan) + $chanfound = 0; + else + $chanfound = 1; + $epgtitlefound = 0; + + $epgtitle=""; + $epgdesc=""; + + // For all epg + $count = count($allepg); + for ($i = 0; $i < $count; $i++) + { + // Find the right chan (take the first one) + if ($chanfound == 0) + { + $streamArray = explode(";",$stream); + if (strstr($allepg[$i], $streamArray[0]) == $streamArray[0]) + $chanfound = 1; + } + else + { + // Now find T or C + if(ereg("^C", $allepg[$i])) + { + // Check if it is our chan too, else search again + if ($ischan) + { + if(!ereg("$stream$", $allepg[$i])) + { + $chanfound = 0; + continue; + } + } + else + { + $channame = substr($allepg[$i], 2); + $channames = explode(" ", $channame); + $channame = substr($channame, strlen($channames[0])+1); + } + } + else if(ereg("^T", $allepg[$i])) + $epgtitle=substr($allepg[$i], 2); + else if(ereg("^D", $allepg[$i])) + $epgdesc=substr($allepg[$i], 2); + } + } + + // Convert if needed + if (!is_utf8($epgtitle)) + $epgtitle = utf8_encode($epgtitle); + if (!is_utf8($epgdesc)) + $epgdesc = utf8_encode($epgdesc); + + + return array($epgtitle, $epgdesc, $channame); +} + +function vdrgettimerinfo($timernum=-1) +{ + if ($timernum != -1) + { + $timer = vdrsendcommand("LSTT " .$timernum); + + $timerarray = explode(":", $timer); + + $typearray = explode(" ", $timerarray[0]); + $type = $typearray[1]; + $channel = $timerarray[1]; + $date = $timerarray[2]; + $stime = $timerarray[3]; + $etime = $timerarray[4]; + $desc = $timerarray[7]; + } + else + { + $type = 1; + $channel = 1; + $date = date('Y-m-d'); + $stime = date('Hi'); + $etime = date('Hi'); + $desc = "New timer"; + } + + $channame = vdrgetchanname($channel); + + return array($type, $channame, $date, $stime, $etime, $desc); +} + +function vdrgetchannum($chan = "NULL") +{ + $channels = vdrsendcommand("LSTC"); + + // Get channel number + $channels = preg_grep(quotemeta('"'.$chan.';|'.$chan.':"'), $channels); + reset($channels); + + $channels = explode(" ", $channels[key($channels)]); + $channum = $channels[0]; + + return $channum; +} + +function vdrgetchanname($channum = 0) +{ + $channel = vdrsendcommand("LSTC " .$channum); + + // Get channel name + $chanarray = explode(":", $channel); + $chanarray = explode(";", $chanarray[0]); + $channame = $chanarray[0]; + $channame = substr($channame, strlen($channum)+1); + + return $channame; +} + + +function vdrlistcategories() +{ + global $vdrchannels; + + // All chans + print "<li class=\"menu\"><a class=\"noeffect\" href=\"javascript:sendForm('All');\"><span class=\"name\">All channels</span><span class=\"arrow\"></span></a></li>\r\n"; + print "<form name=\"All channels\" id=\"All\" method=\"post\" action=\"index.php\"><input name=\"action\" type=\"hidden\" id=\"action\" value=\"listchannels\"/><input name=\"cat\" type=\"hidden\" id=\"cat\" value=\"All\" /></form>\r\n"; + + if (!file_exists($vdrchannels)) + { + print "Error: channels file not found"; + return; + } + + $fp = fopen ($vdrchannels,"r"); + if (!fp) + { + print "Unable to open channels file"; + return; + } + while ($line = fgets($fp, 1024)) + { + // Check if it is a categorie + if ($line[0] == ":") + { + // Remove : and @ + $cat = substr($line, 1, -1); + if($cat[0] == '@') + { + $cat_array = explode(' ', $cat); + $cat = substr($cat, strlen($cat_array[0])+1); + } + + $cat2 = addslashes($cat); + + print "<li class=\"menu\"><a class=\"noeffect\" href=\"javascript:sendForm('$cat2');\"><span class=\"name\">$cat</span><span class=\"arrow\"></span></a></li>\r\n"; + print "<form name=\"$cat\" id=\"$cat\" method=\"post\" action=\"index.php\"><input name=\"action\" type=\"hidden\" id=\"action\" value=\"listchannels\"/><input name=\"cat\" type=\"hidden\" id=\"cat\" value=\"$cat\" /></form>\r\n"; + } + } + fclose($fp); +} + +function vdrlistchannels($category = "NULL") +{ + global $epgtitle; + global $vdrchannels; + + if ($category == "All") + $cat_found=1; + else + $cat_found=0; + + if (!file_exists($vdrchannels)) + { + print "Error: channels file not found"; + return; + } + + $fp = fopen ($vdrchannels,"r"); + if (!fp) + { + print "Unable to open channels file"; + return; + } + while ($line = fgets($fp, 1024)) + { + if ($cat_found) + { + if ($line[0] == ":") + { + if ($category == "All") + continue; + else + break; + } + + $channels = explode(":", $line); + $channels = explode(";", $channels[0]); + $chan = $channels[0]; + + // Get EPG title + $epgtitle = NULL; + list($epgtitle, $epgdesc, $channame) = vdrgetinfostream($chan, 1); + print "<li class=\"withimage\">"; + $chan2=addslashes($chan); + print " <a class=\"noeffect\" href=\"javascript:sendForm('$chan2');\">\r\n"; + $channoslash = preg_replace("$/$", " ", $chan); + if (!file_exists('logos/'.$channoslash.'.png')) + print " <img src=\"logos/nologoTV.png\" />\r\n"; + else + print " <img src=\"logos/{$channoslash}.png\" />\r\n"; + print " <span class=\"name\">$chan</span>\r\n"; + print " <span class=\"comment\">$epgtitle</span><span class=\"arrow\"></span></a>\r\n</li>\r\n"; + print " <form name=\"$chan\" id=\"$chan\" method=\"post\" action=\"index.php\">"; + print " <input name=\"action\" type=\"hidden\" id=\"action\" value=\"stream\" />"; + print " <input name=\"type\" type=\"hidden\" id=\"type\" value=1 />"; + print " <input name=\"name\" type=\"hidden\" id=\"name\" value=\"$chan\" />"; + print " </form>\r\n"; + } + else + { + if ($line[0] == ":") + { + // Remove : and @ + $cat = substr($line, 1, -1); + if($cat[0] == '@') + { + $cat_array = explode(' ', $cat); + $cat = substr($cat, strlen($cat_array[0])+1); + } + + // Check category + if ("$cat" == "$category") + $cat_found = 1; + } + } + } + fclose($fp); +} + +function vdrlistchannelsdrop($chansel = "") +{ + global $vdrchannels; + + $chanselected = 0; + + if (!file_exists($vdrchannels)) + { + print "Error: channels file not found"; + return; + } + + $fp = fopen ($vdrchannels,"r"); + if (!fp) + { + print "Unable to open channels file"; + return; + } + while ($line = fgets($fp, 1024)) + { + if ($line[0] == ":") + continue; + + $channels = explode(":", $line); + $channels = explode(";", $channels[0]); + $chan = $channels[0]; + if (($chan == $chansel) && !$chanselected) + { + print "<option selected value=\"{$chan}\">{$chan}</option>"; + $chanselected = 1; + } + else + print "<option value=\"{$chan}\">{$chan}</option>"; + } +} + +function vdrlisttimers() +{ + $timers = vdrsendcommand("LSTT"); + + if (gettype($timers) == "string") + { + if (!is_numeric(substr($timers,0,1))) + { + print "<li class=\"textbox\"><p>none</p></li>\r\n"; + return; + } + else + $timersarray[] = $timers; + } + else + $timersarray = $timers; + + foreach($timersarray as $timer) + { + // Extract timer # + $timerarray = explode(" ", $timer); + $timernum = $timerarray[0]; + + list($type, $channame, $date, $starthour, $endhour, $desc) = vdrgettimerinfo($timernum); + + print "<li class=\"menu\">"; + print " <a href=\"javascript:sendForm('timer {$timernum}')\">\r\n"; + + if ($type & 0x8) + print " <img alt=\"list\" src=\"images/pictos/timerrec.png\" />\r\n"; + else if ($type & 0x1) + print " <img alt=\"list\" src=\"images/pictos/timeron.png\" />\r\n"; + else + print " <img alt=\"list\" src=\"images/pictos/timeroff.png\" />\r\n"; + + print " <span class=\"name\">{$date}: {$desc}</span><span class=\"arrow\"></span>\r\n"; + + print " </a>\r\n"; + print "</li>\r\n"; + + print "<form name=\"timer {$timernum}\" id=\"timer {$timernum}\" method=\"post\" action=\"index.php\">\r\n"; + print " <input name=\"action\" type=\"hidden\" id=\"action\" value=\"edittimer\"/>\r\n"; + print " <input name=\"timer\" type=\"hidden\" id=\"timer\" value=\"{$timernum}\" />\r\n"; + print "</form>\r\n"; + } +} + +function vdrdeltimer($timer=0) +{ + return vdrsendcommand("DELT " .$timer); +} + +function vdrsettimer($prevtimer, $channame, $date, $stime, $etime, $desc, $active) +{ + $channum = vdrgetchannum($channame); + if ($active) + $type = "1"; + else + $type = "0"; + + if ($prevtimer == -1) + $command = "NEWT " .$type .":" .$channum .":" .$date .":" .$stime .":" .$etime .":99:99:" .$desc; + else + $command = "MODT " .$prevtimer ." " .$type .":" .$channum .":" .$date .":" .$stime .":" .$etime .":99:99:" .$desc; + + return vdrsendcommand($command); +} + +?> diff --git a/config.php b/config.php new file mode 100755 index 0000000..8efcd75 --- /dev/null +++ b/config.php @@ -0,0 +1,38 @@ +<?php + // Http configuration + $user = 'noos'; // Login + $pass = 'noos'; // Password + $httppath = '/'; // Path to the index.php file + + // VDR configuration + $vdrenabled=1; + $vdrchannels='/home/BoB/vdr/conf/channels.conf'; // VDR channel list + $svdrpport=2001; // SVDRP port + $svdrpip='127.0.0.1'; // SVDRP ip + $vdrstreamdev='http://127.0.0.1:3000/TS/'; // VDR streamdev URL + $vdrrecpath='/home/BoB/vdr/video/'; + + // Media configuration + $videotypes='mkv ts mov mp4 wmv avi '; // Supported video extensions + // 1:vid 2:aud Source name Source path + $mediasource=array(); + $mediasources[]=array ( 1, 'Foot', '/home/storage/Foot'); + $mediasources[]=array ( 1, 'Series', '/home/storage-2/Series'); + $mediasources[]=array ( 2, 'Storage-MP3', '/home/storage/Download/MP3'); + $mediasources[]=array ( 2, 'Site-MP3', '/home/www/mp3/'); + + // Encoding + // Name Video Audio Audio channels Resolution + $quality = array( 'Edge' => '128k 64k 1 240x160', + '3g' => '350k 64k 1 408x272', + 'Wifi' => '496k 96k 2 480x320' + ); + $maxencodingprocesses=10; // Max simultaneous encoding processes + + // Misc + $ffmpegpath = '/usr/local/bin/ffmpeg'; + $segmenterpath = '/usr/local/bin/segmenter'; //path to segmenter binary + + // Version + $isdversion = "0.3.6-alpha"; +?> diff --git a/config_default.php b/config_default.php new file mode 100755 index 0000000..1cce79f --- /dev/null +++ b/config_default.php @@ -0,0 +1,36 @@ +<?php + // Http configuration + $user = 'istreamdev'; // Login + $pass = 'iguest'; // Password + $httppath = '/istreamdev/'; // Absolute path to the index.php file. //Don't put http://yourdomain !! + + // VDR configuration + + $vdrenabled=1; // enable/disable VDR features + $vdrchannels='/etc/vdr/channels.conf'; // VDR channel list + $svdrpport=2001; // SVDRP port + $svdrpip='127.0.0.1'; // SVDRP ip + $vdrstreamdev='http://127.0.0.1:3000/TS/'; // VDR streamdev URL + $vdrrecpath='/video/'; //VDR recording directory + + // Media configuration + $videotypes='avi mkv ts mov mp4 wmv flv mpg mpeg mpeg2 mpv '; // Supported video extensions (must finish with a space) + // 1:vid 2:aud Source name Source path + $mediasource=array(); + $mediasources[]=array ( 1, 'Video', '/mnt/media/movies'); + $mediasources[]=array ( 2, 'Audio', '/mnt/media/music'); + + // Encoding + // Name Video Audio Audio channels Resolution + $quality=array ( 'Edge' => '128k 64k 1 240x160', + '3g' => '350k 64k 1 408x272', + 'Wifi' => '512k 128k 2 480x320'); + $maxencodingprocesses=10; // Max simultaneous encoding processes + + // Misc + $ffmpegpath = '/usr/bin/ffmpeg'; //path to ffmpeg binary + $segmenterpath = '/usr/bin/segmenter'; //path to segmenter binary + + // Version + $isdversion = "0.3.7"; +?> |