UMSP plugin development
From WikiDLXTV
Contents
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>