Difference between revisions of "UMSP plugin development"

From WikiDLXTV
Jump to: navigation, search
(Added details about proxy plugins)
(Added reference to debug script umsp-test.php)
Line 142: Line 142:
  
 
==Troubleshooting==
 
==Troubleshooting==
 +
* You can test out and troubleshoot UMSP plugins (including proxies) by using the built-in '''umsp-test.php''' script. Point your browser to http://wdtvlive-IP/umsp/umsp-test.php
 
* User PaulF submitted a test script for UMSP plugins that can show output and errors. Save the file as '''/tmp/www-tmp/umsp2html.php''':  
 
* User PaulF submitted a test script for UMSP plugins that can show output and errors. Save the file as '''/tmp/www-tmp/umsp2html.php''':  
 
http://forum.wdlxtv.com/viewtopic.php?f=3&t=2756#p21358. On your PC browse to: http://wdtvlive-IP/tmp/umsp2html.php?path=0
 
http://forum.wdlxtv.com/viewtopic.php?f=3&t=2756#p21358. On your PC browse to: http://wdtvlive-IP/tmp/umsp2html.php?path=0

Revision as of 09:15, 3 January 2011

This page is under development and may not be very useful --Mad ady 12:51, 16 December 2010 (UTC)

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

A proxy is by definition an entity that behaves like the real target server, but it's not. Proxies are useful for when you need to do some extra steps in order to get the data you want, but you want to do this transparently for other processes.

Basically a proxy gets called like any other media file. The MediaPlayer process will query the proxy like it's the end server and will request details about the media that is to be played (e.g. Content-length), and it will also request the media file (or bits and pieces of it).

Umsp-proxy-msc.png

In the MSC ([[1]]) above a few interactions are shown between the player, the proxy and the server.

The player first makes a request to the "server" (which is the proxy plugin) in order to find more about the media it's supposed to play. The parameters of every query between the MediaPlayer and the Proxy are sent as HTTP header entries and can be accessed in the PHP variable $_SERVER. The first query usually asks for the server's header in order to get the media's Content-length and to see if streaming is supported by the server.

Here's a sample view of the $_SERVER variable in a serialized way for the first query:

a:28:{
 s:9:"UNIQUE_ID";s:24:"TSBV538AAAEAAA6qC-sAAAAB";
 s:10:"SCRIPT_URL";s:67:"/umsp/plugins/youtube-subscriptions/youtube-subscriptions-proxy.php";
 s:10:"SCRIPT_URI";s:83:"http://127.0.0.1/umsp/plugins/youtube-subscriptions/youtube-subscriptions-proxy.php";
 s:9:"HTTP_HOST";s:12:"127.0.0.1:80";
 s:32:"HTTP_GETCONTENTFEATURES_DLNA_ORG";s:1:"1";
 s:26:"HTTP_TRANSFERMODE_DLNA_ORG";s:9:"Streaming";
 s:15:"HTTP_USER_AGENT";s:49:"INTEL_NMPR/2.1 DLNADOC/1.50 dma/3.0 alphanetworks";
 s:4:"PATH";s:103:"/apps/vim/bin:/apps/mc/bin:/apps/iftop/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
 s:16:"SERVER_SIGNATURE";s:115:"<address>Apache/2.2.15 (Debian) PHP/5.3.2-1 with Suhosin-Patch mod_scgi/1.13 Server at 127.0.0.1 Port 80</address>";
 s:15:"SERVER_SOFTWARE";s:67:"Apache/2.2.15 (Debian) PHP/5.3.2-1 with Suhosin-Patch mod_scgi/1.13";
 s:11:"SERVER_NAME";s:9:"127.0.0.1";
 s:11:"SERVER_ADDR";s:9:"127.0.0.1";
 s:11:"SERVER_PORT";s:2:"80";
 s:11:"REMOTE_ADDR";s:9:"127.0.0.1";
 s:13:"DOCUMENT_ROOT";s:8:"/var/www";
 s:12:"SERVER_ADMIN";s:19:"webmaster@localhost";
 s:15:"SCRIPT_FILENAME";s:75:"/var/www/umsp/plugins/youtube-subscriptions/youtube-subscriptions-proxy.php";
 s:11:"REMOTE_PORT";s:5:"40702";
 s:17:"GATEWAY_INTERFACE";s:7:"CGI/1.1";
 s:15:"SERVER_PROTOCOL";s:8:"HTTP/1.0";
 s:14:"REQUEST_METHOD";s:4:"HEAD";
 s:12:"QUERY_STRING";s:20:"video_id=FPfiY33nqgo";
 s:11:"REQUEST_URI";s:88:"/umsp/plugins/youtube-subscriptions/youtube-subscriptions-proxy.php?video_id=FPfiY33nqgo";
 s:11:"SCRIPT_NAME";s:67:"/umsp/plugins/youtube-subscriptions/youtube-subscriptions-proxy.php";
 s:8:"PHP_SELF";s:67:"/umsp/plugins/youtube-subscriptions/youtube-subscriptions-proxy.php";
 s:12:"REQUEST_TIME";i:1293964775;
 s:4:"argv";a:1:{i:0;s:20:"video_id=FPfiY33nqgo";}s:4:"argc";i:1;}

Most notable in this query is the use of REQUEST_METHOD=HEAD (to avoid asking for the whole file). The proxy script should ask for the video file (also with a HEAD query) and should return back the server's HTTP headers. The proxy should add an extra header as Content-Disposition: attachment; filename="video.flv" if none is provided (change the filename name and extension appropriately).

Based on the first query, the MediaPlayer could make several more requests in order to get more information. One such query might be "play from the start":

a:28:{
 s:9:"UNIQUE_ID";s:24:"TSBV6H8AAAEAAAjPBNEAAAAA";
 s:10:"SCRIPT_URL";s:67:"/umsp/plugins/youtube-subscriptions/youtube-subscriptions-proxy.php";
 s:10:"SCRIPT_URI";s:83:"http://127.0.0.1/umsp/plugins/youtube-subscriptions/youtube-subscriptions-proxy.php";
 s:9:"HTTP_HOST";s:12:"127.0.0.1:80";
 s:14:"CONTENT_LENGTH";s:1:"0";
 s:26:"HTTP_TRANSFERMODE_DLNA_ORG";s:9:"Streaming";
 s:15:"HTTP_USER_AGENT";s:49:"INTEL_NMPR/2.1 DLNADOC/1.50 dma/3.0 alphanetworks";
 s:4:"PATH";s:103:"/apps/vim/bin:/apps/mc/bin:/apps/iftop/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
 s:16:"SERVER_SIGNATURE";s:115:"<address>Apache/2.2.15 (Debian) PHP/5.3.2-1 with Suhosin-Patch mod_scgi/1.13 Server at 127.0.0.1 Port 80</address>";
 s:15:"SERVER_SOFTWARE";s:67:"Apache/2.2.15 (Debian) PHP/5.3.2-1 with Suhosin-Patch mod_scgi/1.13";
 s:11:"SERVER_NAME";s:9:"127.0.0.1";
 s:11:"SERVER_ADDR";s:9:"127.0.0.1";
 s:11:"SERVER_PORT";s:2:"80";
 s:11:"REMOTE_ADDR";s:9:"127.0.0.1";
 s:13:"DOCUMENT_ROOT";s:8:"/var/www";
 s:12:"SERVER_ADMIN";s:19:"webmaster@localhost";
 s:15:"SCRIPT_FILENAME";s:75:"/var/www/umsp/plugins/youtube-subscriptions/youtube-subscriptions-proxy.php";
 s:11:"REMOTE_PORT";s:5:"40705";
 s:17:"GATEWAY_INTERFACE";s:7:"CGI/1.1";
 s:15:"SERVER_PROTOCOL";s:8:"HTTP/1.0";
 s:14:"REQUEST_METHOD";s:3:"GET";
 s:12:"QUERY_STRING";s:20:"video_id=FPfiY33nqgo";
 s:11:"REQUEST_URI";s:88:"/umsp/plugins/youtube-subscriptions/youtube-subscriptions-proxy.php?video_id=FPfiY33nqgo";
 s:11:"SCRIPT_NAME";s:67:"/umsp/plugins/youtube-subscriptions/youtube-subscriptions-proxy.php";
 s:8:"PHP_SELF";s:67:"/umsp/plugins/youtube-subscriptions/youtube-subscriptions-proxy.php";
 s:12:"REQUEST_TIME";i:1293964776;
 s:4:"argv";a:1:{i:0;s:20:"video_id=FPfiY33nqgo";}s:4:"argc";i:1;}

Here you can see that the Content-Length is set to zero (we're not sending anything), the Request-method is GET. The proxy should reply to the MediaPlayer with the header received from the server, adding Content-Disposition (as above) and passing the output from the proxy to the server (e.g. using fpassthru($fp))


If the user decides to navigate inside the video, the MediaPlayer process will receive DLNA commands (like MediaPlay(64 1)) telling it to jump to a specific point in time (e.g. 64 seconds into the video). Fortunately, the MediaPlayer process will convert the time it receives to a specific byte offset in the media stream and will make a request to the proxy to fetch data starting from that offset (using HTTP Ranges requests - see http://labs.apache.org/webarch/http/draft-fielding-http/p5-range.html). If the server supports ranges, it will return data from that offset, and it's the MediaPlayer's job to render it. The proxy just has to forward the request to the server.

Here is a request for such a jump, starting from offset 238192480 (238MB into the video):

a:28:{
 s:9:"UNIQUE_ID";s:24:"TSBYSX8AAAEAAAjPBNIAAAAA";
 s:10:"SCRIPT_URL";s:67:"/umsp/plugins/youtube-subscriptions/youtube-subscriptions-proxy.php";
 s:10:"SCRIPT_URI";s:83:"http://127.0.0.1/umsp/plugins/youtube-subscriptions/youtube-subscriptions-proxy.php";
 s:9:"HTTP_HOST";s:12:"127.0.0.1:80";
 s:10:"HTTP_RANGE";s:16:"bytes=238192480-";
 s:26:"HTTP_TRANSFERMODE_DLNA_ORG";s:9:"Streaming";
 s:15:"HTTP_USER_AGENT";s:49:"INTEL_NMPR/2.1 DLNADOC/1.50 dma/3.0 alphanetworks";
 s:4:"PATH";s:103:"/apps/vim/bin:/apps/mc/bin:/apps/iftop/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
 s:16:"SERVER_SIGNATURE";s:115:"<address>Apache/2.2.15 (Debian) PHP/5.3.2-1 with Suhosin-Patch mod_scgi/1.13 Server at 127.0.0.1 Port 80</address>";
 s:15:"SERVER_SOFTWARE";s:67:"Apache/2.2.15 (Debian) PHP/5.3.2-1 with Suhosin-Patch mod_scgi/1.13";
 s:11:"SERVER_NAME";s:9:"127.0.0.1";
 s:11:"SERVER_ADDR";s:9:"127.0.0.1";
 s:11:"SERVER_PORT";s:2:"80";
 s:11:"REMOTE_ADDR";s:9:"127.0.0.1";
 s:13:"DOCUMENT_ROOT";s:8:"/var/www";
 s:12:"SERVER_ADMIN";s:19:"webmaster@localhost";
 s:15:"SCRIPT_FILENAME";s:75:"/var/www/umsp/plugins/youtube-subscriptions/youtube-subscriptions-proxy.php";
 s:11:"REMOTE_PORT";s:5:"45030";
 s:17:"GATEWAY_INTERFACE";s:7:"CGI/1.1";
 s:15:"SERVER_PROTOCOL";s:8:"HTTP/1.0";
 s:14:"REQUEST_METHOD";s:3:"GET";
 s:12:"QUERY_STRING";s:20:"video_id=FPfiY33nqgo";
 s:11:"REQUEST_URI";s:88:"/umsp/plugins/youtube-subscriptions/youtube-subscriptions-proxy.php?video_id=FPfiY33nqgo";
 s:11:"SCRIPT_NAME";s:67:"/umsp/plugins/youtube-subscriptions/youtube-subscriptions-proxy.php";
 s:8:"PHP_SELF";s:67:"/umsp/plugins/youtube-subscriptions/youtube-subscriptions-proxy.php";
 s:12:"REQUEST_TIME";i:1293965385;
 s:4:"argv";a:1:{i:0;s:20:"video_id=FPfiY33nqgo";}s:4:"argc";i:1;}

The difference between this request and the request above (the one for playback) is that now "Content-length=0" is no longer set and there's a new parameter called "HTTP_RANGE" that tells the server exactly where to go. The proxy should forward these parameters to the server and should return the content to the player just like above.

Note: You can enable debugging in the youtube-subscriptions-proxy.php (switch on $want_debug) and you will get more detailed debug output in /var/log/php5/error_log. The output will also show the headers that are sent and received from communicating with the server, and it will show what gets sent back to the MediaPlayer client.

Note2: Some relevant links about this subject: [2], [3], [4]

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

  • You can test out and troubleshoot UMSP plugins (including proxies) by using the built-in umsp-test.php script. Point your browser to http://wdtvlive-IP/umsp/umsp-test.php
  • User PaulF submitted a test script for UMSP plugins that can show output and errors. Save the file as /tmp/www-tmp/umsp2html.php:

http://forum.wdlxtv.com/viewtopic.php?f=3&t=2756#p21358. On your PC browse to: http://wdtvlive-IP/tmp/umsp2html.php?path=0

  • You can start the MediaPlayer process (which handles playback) in debug mode to observe what's going on. Details here: http://forum.wdlxtv.com/viewtopic.php?f=53&t=517#p3287. You will be getting a lot of debug output including the DLNA commands for skipping, pausing, etc:
killall MediaLogic
MediaLogic AV MSGL_DBG