summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaromil <jaromil@dyne.org>2011-04-15 13:52:27 (GMT)
committer Jaromil <jaromil@dyne.org>2011-04-15 13:52:27 (GMT)
commit000c318e749aee9af2a6809d5a1e02701ea2660e (patch)
tree365da5a8df7c15ee7a0bb30459de6540e9ecb39d
parente9769fc16aee9d075c4cfa7bb749f4768f70b7b0 (diff)
some older implementations from wdlxtv and my own shell experiments
-rw-r--r--contrib/upnp-cmd.php296
-rw-r--r--contrib/upnp.sh100
2 files changed, 396 insertions, 0 deletions
diff --git a/contrib/upnp-cmd.php b/contrib/upnp-cmd.php
new file mode 100644
index 0000000..80dce5e
--- /dev/null
+++ b/contrib/upnp-cmd.php
@@ -0,0 +1,296 @@
+#!/usr/bin/php-cgi -q
+<?php
+
+# UPnP Command Line Tool for WDTV Live
+# Version: 0.1
+# Author: Zoster
+
+
+#### Command Line Functions ####
+
+if ( $argc < 2 ) {
+ die (_stringHelp());
+}
+
+$actionName = $argv[1];
+
+if ( function_exists('_action' . $actionName)) {
+ switch ($argc) {
+ case 2:
+ call_user_func('_action' . $actionName);
+ break;
+ case 3:
+ call_user_func('_action' . $actionName, $argv[2]);
+ break;
+ case 4:
+ call_user_func('_action' . $actionName, $argv[2], $argv[3]);
+ break;
+ default:
+ call_user_func('_action' . $actionName);
+ break;
+ }
+} else {
+ die (_stringHelp());
+}
+
+function _stringHelp() {
+ $hlp = 'UPnP command line tool for WDTV Live v0.1' . "\n";
+ $hlp .= 'Usage: upnp-cmd action argument' . "\n";
+ $hlp .= '' . "\n";
+ $hlp .= 'Available AVTransport actions:' . "\n";
+ $hlp .= '' . "\n";
+ $hlp .= 'GetCurrentTransportActions' . "\n";
+ $hlp .= 'GetDeviceCapabilities' . "\n";
+ $hlp .= 'GetMediaInfo' . "\n";
+ $hlp .= 'GetPositionInfo' . "\n";
+ $hlp .= 'GetTransportInfo' . "\n";
+ $hlp .= 'GetTransportSettings' . "\n";
+ $hlp .= 'Next' . "\n";
+ $hlp .= 'Pause' . "\n";
+ $hlp .= 'Play' . "\n";
+ $hlp .= 'Previous' . "\n";
+ $hlp .= 'Seek <SeekMode> <SeekTarget> (allowed SeekMode: "X_DLNA_REL_BYTE", "REL_TIME", "TRACK_NR")' . "\n";
+ $hlp .= 'SetAVTransportURI <URI> <URIMetaData> (allowed URI: "http://server/file", "file:///folder/file"' . "\n";
+ $hlp .= 'SetPlayMode <NewPlayMode> (allowed NewPlayMode = "NORMAL", "REPEAT_ONE", "REPEAT_ALL", "RANDOM")' . "\n";
+ $hlp .= 'Stop' . "\n";
+ $hlp .= 'X_DLNA_GetBytePositionInfo' . "\n";
+ $hlp .= '' . "\n";
+ $hlp .= 'Available RenderingControl actions:' . "\n";
+ $hlp .= '' . "\n";
+ $hlp .= 'GetMute' . "\n";
+ $hlp .= 'GetVolume' . "\n";
+ $hlp .= 'SetMute <DesiredMute> (allowed DesiredMute = 0 or 1)' . "\n";
+ $hlp .= 'SetVolume <DesiredVolume> (allowed DesiredVolume = 1 to 100)' . "\n";
+ return $hlp;
+}
+
+
+#### General UPnP Functions ####
+
+#### AVTransport Actions ####
+
+function _actionGetCurrentTransportActions() {
+ $action = 'GetCurrentTransportActions';
+ $args = '<InstanceID>0</InstanceID>' . "\r\n";
+ $result = _sendUPnPCommand($action, $args, 'AVTransport');
+}
+
+function _actionGetDeviceCapabilities() {
+ $action = 'GetDeviceCapabilities';
+ $args = '<InstanceID>0</InstanceID>' . "\r\n";
+ $result = _sendUPnPCommand($action, $args, 'AVTransport');
+}
+
+function _actionGetMediaInfo() {
+ $action = 'GetMediaInfo';
+ $args = '<InstanceID>0</InstanceID>' . "\r\n";
+ $result = _sendUPnPCommand($action, $args, 'AVTransport');
+}
+
+function _actionGetPositionInfo() {
+ $action = 'GetPositionInfo';
+ $args = '<InstanceID>0</InstanceID>' . "\r\n";
+ $result = _sendUPnPCommand($action, $args, 'AVTransport');
+}
+
+function _actionGetTransportInfo() {
+ $action = 'GetTransportInfo';
+ $args = '<InstanceID>0</InstanceID>' . "\r\n";
+ $result = _sendUPnPCommand($action, $args, 'AVTransport');
+}
+
+function _actionGetTransportSettings() {
+ $action = 'GetTransportSettings';
+ $args = '<InstanceID>0</InstanceID>' . "\r\n";
+ $result = _sendUPnPCommand($action, $args, 'AVTransport');
+}
+
+function _actionNext() {
+ $action = 'Next';
+ $args = '<InstanceID>0</InstanceID>' . "\r\n";
+ $result = _sendUPnPCommand($action, $args, 'AVTransport');
+}
+
+function _actionPause() {
+ $action = 'Pause';
+ $args = '<InstanceID>0</InstanceID>' . "\r\n";
+ $result = _sendUPnPCommand($action, $args, 'AVTransport');
+}
+
+function _actionPlay($prmSpeed = 1) {
+ $action = 'Play';
+ $args = '<InstanceID>0</InstanceID>' . "\r\n";
+ $args .= '<Speed>' . $prmSpeed . '</Speed>' . "\r\n";
+ $result = _sendUPnPCommand($action, $args, 'AVTransport');
+}
+
+function _actionPrevious() {
+ $action = 'Previous';
+ $args = '<InstanceID>0</InstanceID>' . "\r\n";
+ $result = _sendUPnPCommand($action, $args, 'AVTransport');
+}
+
+function _actionSeek($prmSeekMode, $prmSeekTarget) {
+ # SeekModes: "X_DLNA_REL_BYTE" = Bytes Integer, "REL_TIME" = hh:mm:ss, "TRACK_NR" = Track Integer
+ $action = 'Seek';
+ $args = '<InstanceID>0</InstanceID>' . "\r\n";
+ $args = '<SeekMode>' . $prmSeekMode . '</SeekMode>' . "\r\n";
+ $args = '<SeekTarget>' . $prmSeekTarget . '</SeekTarget>' . "\r\n";
+ $result = _sendUPnPCommand($action, $args, 'AVTransport');
+}
+
+function _actionSetAVTransportURI($prmURI = '', $prmMetaData = '') {
+ $action = 'SetAVTransportURI';
+ $args = '<InstanceID>0</InstanceID>' . "\r\n";
+ $args .= '<CurrentURI>' . $prmURI . '</CurrentURI>' . "\r\n";
+ #$args .= '<CurrentURIMetaData />'. "\r\n";
+ $args .= '<CurrentURIMetaData>' . htmlentities($prmMetaData) . '</CurrentURIMetaData>' . "\r\n";
+ $result = _sendUPnPCommand($action, $args, 'AVTransport');
+}
+
+function _actionSetPlayMode($prmNewPlayMode) {
+ #allowed NewPlayMode = "NORMAL", "REPEAT_ONE", "REPEAT_ALL", "RANDOM"
+ $action = 'SetPlayMode';
+ $args = '<InstanceID>0</InstanceID>' . "\r\n";
+ $args .= '<NewPlayMode>' . $prmNewPlayMode . '</NewPlayMode>' . "\r\n";
+ $result = _sendUPnPCommand($action, $args, 'AVTransport');
+}
+
+function _actionStop() {
+ $action = 'Stop';
+ $args = '<InstanceID>0</InstanceID>' . "\r\n";
+ $result = _sendUPnPCommand($action, $args, 'AVTransport');
+}
+
+function _actionX_DLNA_GetBytePositionInfo($prmTrackSize) {
+ $action = 'X_DLNA_GetBytePositionInfo';
+ $args = '<InstanceID>0</InstanceID>' . "\r\n";
+ $args = '<TrackSize>' . $prmTrackSize . '</TrackSize>' . "\r\n";
+ $result = _sendUPnPCommand($action, $args, 'AVTransport');
+}
+
+#### END AVTransport Actions ####
+
+
+#### RenderingControl Actions ####
+
+function _actionGetMute($prmChannel = 'Master') {
+ # allowed Channel = "Master", "LF", "RF"
+ $action = 'GetMute';
+ $args = '<InstanceID>0</InstanceID>' . "\r\n";
+ $args .= '<Channel>' . $prmChannel . '</Channel>' . "\r\n";
+ $result = _sendUPnPCommand($action, $args, 'RenderingControl');
+}
+
+function _actionGetVolume($prmChannel = 'Master') {
+ $action = 'GetVolume';
+ $args = '<InstanceID>0</InstanceID>' . "\r\n";
+ $args .= '<Channel>' . $prmChannel . '</Channel>' . "\r\n";
+ $result = _sendUPnPCommand($action, $args, 'RenderingControl');
+}
+
+function _actionSetMute($prmDesiredMute = 1, $prmChannel = 'Master' ) {
+ # allowed DesiredMute = 0 or 1
+ $action = 'SetMute';
+ $args = '<InstanceID>0</InstanceID>' . "\r\n";
+ $args .= '<Channel>' . $prmChannel . '</Channel>' . "\r\n";
+ $args .= '<DesiredMute>' . $prmDesiredMute . '</DesiredMute>' . "\r\n";
+ $result = _sendUPnPCommand($action, $args, 'RenderingControl');
+}
+
+function _actionSetVolume($prmDesiredVolume = 1, $prmChannel = 'Master' ) {
+ # allowed DesiredVolume = 1 to 100
+ $action = 'SetVolume';
+ $args = '<InstanceID>0</InstanceID>' . "\r\n";
+ $args .= '<Channel>' . $prmChannel . '</Channel>' . "\r\n";
+ $args .= '<DesiredVolume>' . $prmDesiredVolume . '</DesiredVolume>' . "\r\n";
+ $result = _sendUPnPCommand($action, $args, 'RenderingControl');
+}
+
+#### END RenderingControl Actions ####
+
+
+function _sendUPnPCommand($prmAction, $prmArguments, $prmService) {
+
+ $wdtvPort = _getPort();
+ $wdtvIP = _getIP();
+
+ $soap ='<?xml version="1.0" encoding="utf-8"?>' . "\r\n";
+ $soap .='<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">' . "\r\n";
+ $soap .=' <s:Body>' . "\r\n";
+ $soap .=' <u:' . $prmAction . ' xmlns:u="urn:schemas-upnp-org:service:' . $prmService . ':1">' . "\r\n";
+ $soap .= $prmArguments;
+ $soap .=' </u:' . $prmAction . '>' . "\r\n";
+ $soap .=' </s:Body>' . "\r\n";
+ $soap .='</s:Envelope>' . "\r\n";
+
+ $hdr ='POST /MediaRenderer_' . $prmService . '/control HTTP/1.0' . "\r\n";
+ $hdr .='SOAPACTION: "urn:schemas-upnp-org:service:' . $prmService . ':1#' . $prmAction . '"' . "\r\n";
+ $hdr .='CONTENT-TYPE: text/xml ; charset="utf-8"' . "\r\n";
+ $hdr .='HOST: 127.0.0.1:' . $wdtvPort . "\r\n";
+ $hdr .='Connection: close' . "\r\n";
+ $hdr .='Content-Length: ' . strlen($soap) . "\r\n";
+ $hdr .='' . "\r\n";
+
+ $msg = $hdr . $soap;
+
+ $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
+ socket_bind($sock, $wdtvIP);
+ socket_connect($sock, '127.0.0.1', $wdtvPort);
+ socket_write($sock, $msg);
+ $reply = "";
+ do {
+ $recv = "";
+ $recv = socket_read($sock, '1400');
+ if($recv != "") {
+ $reply .= $recv;
+ }
+ } while($recv != "");
+ socket_close($sock);
+ $tmpArr = explode("\r\n\r\n", $reply, 2);
+ $result = _parseUPnPResponse($tmpArr[1]);
+ #print_r($result);
+ _printArray($result);
+}
+
+function _parseUPnPResponse($prmResponseXML) {
+ $doc = new DOMDocument();
+ $doc->preserveWhiteSpace = false;
+ $doc->formatOutput = true;
+ $doc->loadXML($prmResponseXML);
+ $respItems = $doc->getElementsByTagName('Body')->item(0)->childNodes->item(0)->childNodes;
+ $arrResponse = array();
+ foreach ($respItems as $item) {
+ $arrResponse[$item->nodeName] = $item->nodeValue;
+ }
+ return $arrResponse;
+}
+
+function _printArray($prmArray) {
+ foreach($prmArray as $key => $value) {
+ echo '[' . $key . '] => ' . $value . "\n";
+ }
+}
+
+function _getPort() {
+ # get the listening port of DMARender
+ $result = exec('lsof -a -i4 -sTCP:LISTEN -c DMARender -F n');
+ if ( preg_match('/n\*:(\d*)$/', $result, $matches) ) {
+ return (int)$matches[1];
+ } else {
+ return null;
+ }
+} # end function
+
+function _getIP() {
+ # get our LAN IP
+ $result = exec('ipaddr show dev eth0 | grep inet');
+ if ( preg_match('/inet ([^\/]*)\//', $result, $matches) ) {
+ return $matches[1];
+ } else {
+ return null;
+ }
+} # end function
+
+?>
+
diff --git a/contrib/upnp.sh b/contrib/upnp.sh
new file mode 100644
index 0000000..9c635b5
--- /dev/null
+++ b/contrib/upnp.sh
@@ -0,0 +1,100 @@
+#!/bin/sh
+
+# small upnp player in shell script, for WDLXTV
+# this is supposed to work faster than the upnp-cmd
+# needed to lower latency of operation in hdsync.app.bin
+
+# (C) 2011 by Jaromil - GNU GPL v3
+
+if [ -z $1 ]; then
+ echo "usage: $0 [command]"
+ echo "commands: load filename, play, stop, pause"
+ exit 0
+fi
+
+HOST=127.0.0.1
+
+# detect UPNP port
+UPNPPORT="`lsof -a -i4 -sTCP:LISTEN -c DMARender -F n | awk -v FS=':' '/^n/ {print $2}'`"
+if ! [ $UPNPPORT ]; then
+ echo "error: no UPNP daemon found."
+ exit 1
+else
+ echo "UPNP daemon found listening on port $UPNPPORT"
+fi
+PORT=$UPNPPORT
+
+
+send_message() {
+ if [ -z $1 ]; then
+ echo "error: send_message"
+ return
+ fi
+ action="$1"
+ message="$2"
+ smsg="<?xml version=\"1.0\" encoding=\"utf-8\"?><s:Envelope s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body><u:$action xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID>$message</u:$action></s:Body></s:Envelope>"
+ wget -O - -q --post-data="$smsg" \
+ $HOST:$PORT/MediaRenderer_AVTransport/control \
+ --header="SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#$action\"" \
+ --bind-address=127.0.0.1
+ echo
+}
+
+# make cmd case insensitive
+cmd="`echo $1 | tr '[:upper:]' '[:lower:]'`"
+
+case $cmd in
+
+ load)
+ file="$2"
+ # if ! [ -r "$file" ]; then
+ # echo "file not found: $file"
+ # echo "operation aborted."; exit 1
+ # fi
+ uri="file://$file"
+ dirName="`dirname "$file"`"
+ fileName="`basename "$file"`"
+ fileSize="`stat -c%s "$file"`"
+
+ meta="<DIDL-Lite xmlns=\"urn:schemas-upnp-org:metadata-1-0/DIDL-Lite\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:upnp=\"urn:schemas-upnp-org:metadata-1-0/upnp/\"><item id=\"2$file\" parentID=\"2$dirName\" restricted=\"0\"><dc:title>$fileName</dc:title><dc:date></dc:date><upnp:class>object.item.imageItem</upnp:class><dc:creator></dc:creator><upnp:genre></upnp:genre><upnp:artist></upnp:artist><upnp:album></upnp:album><res protocolInfo=\"file-get:*:*:*:DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=00000000001000000000000000000000\" protection=\"\" tokenType=\"0\" bitrate=\"0\" duration=\"\" size=\"$fileSize\" colorDepth=\"0\" ifoFileURI=\"\" resolution=\"\">$uri</res></item></DIDL-Lite>"
+
+ msg="<CurrentURI>$uri</CurrentURI><CurrentURIMetaData>$meta</CurrentURIMetaData>"
+
+# send_message SetAVTransportURI "$msg"
+
+ upnp-cmd SetAVTransportURI "$uri" "$meta"
+ # allowed NewPlayMode = "NORMAL", "REPEAT_ONE", "REPEAT_ALL", "RANDOM"
+ upnp-cmd SetPlayMode REPEAT_ONE
+ ;;
+
+ mode)
+ mode="$2"
+ msg="<NewPlayMode>$mode</NewPlayMode>"
+ send_message SetPlayMode "$msg"
+ ;;
+
+ play)
+# msg="<Speed>1</Speed>"
+# send_message Play "$msg"
+
+ upnp-cmd Play
+ ;;
+
+ stop)
+ upnp-cmd Stop
+ ;;
+
+ pause)
+# send_message Pause ""
+ upnp-cmd Pause
+ ;;
+
+ *)
+ echo "unrecognized command: $cmd"
+ exit 1
+ ;;
+
+esac
+
+#echo "command $cmd executed succesfully"
+