Difference between revisions of "UMSP plugin development"

From WikiDLXTV
Jump to: navigation, search
(Initial page created)
(No difference)

Revision as of 03:47, 16 December 2010

How UMSP works

  • TODO - High-level explanation

Plugin architecture

  • TODO - explain how the plugins are structured and how they intercommunicate

Plugin API

Here is a list of functions that can be used by your plugins, provided by the UMSP server:

  • TODO

Sample plugin

  • TODO - when I learn a bit more about the process :)

Plugins with proxies

  • TODO What should proxies do; how to support navigation, etc.

Logs

You can log your errors/warnings/etc to /var/www/php5/error_log by using

error_log("whatever you're trying to log");

As a best practice rule you can add a script name and a sevrity to help with filtering later on:

error_log("yt-subscriptions-proxy: INFO: whatever you're trying to log");

It is recommended (for your own troubleshooting ease) to enable logs only when you need them and disable them (except for errors) before commiting to SVN.

The same log file will hold syntax errors and other PHP errors. More information: http://forum.wdlxtv.com/viewtopic.php?f=3&t=2756&start=0

Troubleshooting

User PaulF submitted a test script for UMSP plugins that can show output and errors. Save the file as /tmp/www-tmp/umsp2html.php:

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 <title>Thumbnail Image Gallery</title>
 <style type="text/css">
 body {
     background-color: #fff;
     color: #000;
     font-family: Trebuchet MS, Arial, Helvetica, sans-serif;
     margin: 16px;
     padding: 0;
 }
 .thumbwrap {
     border: 1px solid #999;
     padding: 15px 8px 0 8px;
     background-color: #f4f4f4;
     margin: 0;
 }
 .thumbwrap li {
     display: -moz-inline-box;
     display: inline-block;
     margin: 0 7px 15px 7px;
     border: 1px solid #999;
     padding: 0;
 }
 /*  Moz: NO border qui altrimenti difficolta' con width, table altrimenti problemi a text resize (risolubili con refresh) */
 .thumbwrap li>div {
     width: 134px;
     border: 1px solid #999;
 }
 .thumbwrap a {
     display: block;
     text-decoration: none;
     color: #000;
     background-color: #ffe;
     cursor: pointer;
 }
 /*\*/
 .thumbwrap>li .wrimg {
     display: table-cell;
     vertical-align: middle;
     width: 134px;
     height: 200px;
 }
 /**/
 .thumbwrap img {
     border: solid 1px #66f;
     display: block;
     vertical-align: middle;
     margin-left: auto;
     margin-right: auto;
 }
 .thumbwrap a:hover {
     background-color: #dfd;
 }
 .thumbwrap .caption {
     display: block;
     padding: .3 5px;
     font-size: .9;
     line-height: 1.1;
     border-top: 1px solid #ccc;
     width: 134px;  /* Moz, IE6 */
 }
 /* top ib e hover Op < 9.5 */
 @media all and (min-width: 0px) {
     html:first-child .thumbwrap a {
         display: inline-block;
         vertical-align: top;
     }
     html:first-child .thumbwrap {
         border-collapse: collapse;
         display: inline-block; /* non deve avere margin */
     }
 }
 </style>
 </head>
 <body>
    <?php chdir('/usr/share/umsp/'); include('media-items.php'); include('funcs-misc.php'); $upnpRequest = array ( 'objectid' => $_GET['path'], 'startingindex' => 0, 'requestedcount' => 64, ); switch ($upnpRequest['objectid']) { case '0': # Root items: $items = $myMediaItems; break; default: # The parse_url function returns an array in this format: # Array ( # [scheme] => http # [host] => hostname # [user] => username # [pass] => password # [path] => /path # [query] => arg=value # [fragment] => anchor # ) $reqObjectURL = parse_url($upnpRequest['objectid']); switch ($reqObjectURL['scheme']) { case 'umsp': switch ($reqObjectURL['host']) { case 'plugins': # handle plugins # call with parameters query and path $items = _callPlugin($reqObjectURL['path'], $reqObjectURL['query']); break; case 'local': # handle local content # call with parameters query and path $items = _localMain($reqObjectURL['path'], $reqObjectURL['query']); break; } # end switch break; # URL is not umsp:// try to load URL as DIDL-XML ?? } # end switch } # end switch foreach ($items as $item) { $href = ; if($item['res'] != ){ $resObjectURL = parse_url($item['res']); if($resObjectURL['host'] == '127.0.0.1'){ $item['res'] = str_replace('127.0.0.1', $_SERVER['SERVER_ADDR'], $item['res']); } if($resObjectURL['scheme'] == 'http'){ $href = $item['res']; } } if($href == ){ $href = 'http://' . $_SERVER['SERVER_ADDR'] . $_SERVER['SCRIPT_NAME'] . '?path='. $item['id']; } if($item['upnp:album_art'] != ){ $item['upnp:album_art'] = str_replace('127.0.0.1', $_SERVER['SERVER_ADDR'], $item['upnp:album_art']); printf("
  • <a href=\"%s\">", $href);
                     printf("<img src=\"%s\" width=\"110\"/>",  $item['upnp:album_art']);
    
    printf("
    %s</a>
  • \n", $item['dc:title']);
                 } else {
    
    printf("

    <a href=\"%s\">%s</a>

    \n", $href, $item['dc:title']);
                 }
             }
             exit;
     function _callPlugin($prmPath, $prmQuery = null) {
             # TODO: make plugins config Ini based
             # prmPath is expected as '/pluginName'
             $tmpArr = explode('/', $prmPath, 3);
             if ($tmpArr[1] != ) {
                     $pluginName = $tmpArr[1];
                     $tmpUserPluginPath =    './user-plugins/'. $pluginName . '.php';
                     $tmpPluginPath =        './plugins/'. $pluginName . '.php';
             $tmpDirPluginPath =     './plugins/'. $pluginName . '/' . $tmpArr[2] . '.php';
             $tmpDir2PluginPath =    './plugins/'. $pluginName . '/' . $pluginName . '.php';
                     if (is_file($tmpUserPluginPath)) {
                             $pluginFile = $tmpUserPluginPath;
                     } elseif (is_file($tmpPluginPath)) {
                             $pluginFile = $tmpPluginPath;
                     } elseif (is_file($tmpDirPluginPath)) {
                             $pluginFile = $tmpDirPluginPath;
                     } elseif (is_file($tmpDir2PluginPath)) {
                             $pluginFile = $tmpDir2PluginPath;
                     } else {
                             return null;
                     }
             }
             # Save the plugin path to tmp to know our location in case of a search query
             _writeTmpVar('lastUsedPlugin', $pluginFile);
    
             # Load plugin file and call its _pluginMain function with query string as parameter
             # The plugin is expected to return an array of media items
             require $pluginFile;
             $pluginItems = _pluginMain($prmQuery);
             return $pluginItems;
     } # end function
     
     function _callPluginSearch($prmQuery) {
         #
         $lastPlugin = _readTmpVar('lastUsedPlugin', $pluginFile);
         if (!is_readable($lastPlugin)){
             return null;
         } else {
             require $lastPlugin;
             if (function_exists('_pluginSearch')) {
                 $searchItems = _pluginSearch($prmQuery);
                 return $searchItems;
             } else {
                 return null;
             }
         }
     }       
     
     function _createMessageItems($prmText) {
             # $prmText can be a single string or an array of multiple strings (lines)
             if (is_string($prmText)) { $prmText = array($prmText); }
             foreach ($prmText as $line) {
                     if (trim($line) != ) {
                     $retItems[] = array('id'                => 'msg_' . count($retItems),
                                                             'dc:title'      => $line,
                                                             'upnp:class'=> 'object.container',
                                                     );
                     } # end if
             } # end foreach
             return $retItems;
     } # end function
     
     function _readCache($prmId) {
             $filename = '/tmp/umsp-cache';
             if ($prmId == '0') {
                     # don't cache root and delete old cache
                     if (is_file($filename)) { unlink($filename); }
                     return null;
             } # end if
             if (!is_readable($filename)) { return null; }
             $handle = fopen($filename, 'r');
             $rawContent = fread($handle, trim(exec ('stat -c%s ' . escapeshellarg($filename))));
             fclose($handle);
             $cacheData = unserialize($rawContent);
             if ((is_array($cacheData['data'])) && ($cacheData['id'] == $prmId)) {
                     return $cacheData['data'];
             } else {
                     return null;
             } # end if
     } # end function
     
     function _writeCache($prmId, $prmDataArray) {
             if (!is_array($prmDataArray)) { return false; }
             if ($prmId == '0') { return false; } # don't cache root
             $filename = '/tmp/umsp-cache';
             $handle = fopen($filename, 'w');
             $rawContent = serialize(array('id' => $prmId, 'data' => $prmDataArray));
             $success = fwrite($handle, $rawContent);
             fclose ($handle);
             return $success;
     } # end function
     
     function _readTmpVar($prmVarName) {
             $filename = '/tmp/umsp-tmpvars';
             if (!is_readable($filename)) { return null; }
             $handle = fopen($filename, 'r');
             $rawContent = fread($handle, filesize($filename));
             fclose($handle);
             $varData = unserialize($rawContent);
             if (is_array($varData) && isset($varData[$prmVarName])) {
                     return $varData[$prmVarName];
             } else {
                     return null;
             } # end if
     } # end function
     
     function _writeTmpVar($prmVarName, $prmVarValue) {
         $filename = '/tmp/umsp-tmpvars';
         if (is_readable($filename)) {
             $handle = fopen($filename, 'r');
             $rawContent = fread($handle, filesize($filename));
             fclose($handle);
             $prevData = unserialize($rawContent);
             if ($prevData === false || !is_array($prevData)) {
                 $newData = array();
             } else {
                 $newData = $prevData;
             }
         } else {
             $newData = array();
         }
         $newData[$prmVarName] = $prmVarValue;
         $handle = fopen($filename, 'w');
         $rawContent = serialize($newData);
         $success = fwrite($handle, $rawContent);
         fclose ($handle);
         return $success;
     } # end function
     
             ?>
    
 </body>
 </html>