Sign up here and you can log into the forum!

upnp-cmd and upnp-meta updates

This is the place to ask for how to use software that is (or isn't) included in the various wdlxtv flavours. Questions about software such as rtorrent, NZBGet, sshfs, curlftpfs, ssh, telnet, etc.

upnp-cmd and upnp-meta updates   

Postby KAD » Fri May 30, 2014 6:40 pm

hey I don't have write access to /usr/bin on svn

upnp-cmd - change adds additional functionality

$hlp .= 'SetNextAVTransportURI <URI> <URIMetaData> (allowed URI: "http://server/file", "file:///folder/file"' . "\n";

Code: Select all
#!/usr/bin/php
<?php

# UPnP Command Line Tool for WDTV Live
# Version: 0.1.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 .= 'SetNextAVTransportURI <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 _actionSetNextAVTransportURI($prmURI = '', $prmMetaData = '') {
    $action = 'SetNextAVTransportURI';
    $args   = '<InstanceID>0</InstanceID>' . "\r\n";
    $args  .= '<NextURI>' . $prmURI . '</NextURI>' . "\r\n";
   $args  .= '<NrTracks>2</NrTracks>' . "\r\n";
    #$args  .= '<NextURIMetaData />'. "\r\n";
    $args  .= '<NextURIMetaData>' . htmlentities($prmMetaData) . '</NextURIMetaData>' . "\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("ifconfig  | grep 'inet addr:'| grep -v '127.0.0.1' | cut -d: -f2 | awk '{ print $1}' | tail -n 1");
    if ( $result != "" ) {
        return $result;
    } else {
        return null;
    }
} # end function

?>




upnp-meta - force all codecs to be properly recognized
not really needed for old devices, but new devices require it for proper playback via upnp-cmd
codec list was taken from SMP official docs

Code: Select all
#!/bin/sh

## $1 is URI
##
## split into:
## - URI
## - parentDir
## - fileName
## - fileSize

[ -z "$1" ] && echo "  usage: $0 <mediafile>" && exit 1
codec="*"
parentDir="`dirname "$1"`"
fileName="`basename "$1"`"
fileSize="`stat -c%s "$1"`"
if [ `echo "$fileName" | grep -q -i '\.3g2$\|\.3pg$\|\.mov$\|\.mp4$\|\.asf$\|\.wmv$\|\.divx$\|\.dat$\|\.dvr-ms$\|\.flv$\|\.iso$\|\.mts$\|\.m2t$\|\.m2ts$\|\.m4t$\|\.m4t$\|\.tp$\|\.trp$\|\.ts$\|\.tts$\|\.m1s$\|\.m2p$\|\.mpg$\|\.mpeg$\|\.mpeg2$\|\.mod$\|\.vbs$\|\.vob$\|\.mkv$\|\.avi$'; echo $?` -eq 0 ]; then
   if [ `echo "$fileName" | grep -q -i '\.3g2$'; echo $?` -eq 0 ]; then codec="video/3g2"; fi
   if [ `echo "$fileName" | grep -q -i '\.3pg$'; echo $?` -eq 0 ]; then codec="video/3pg"; fi
   if [ `echo "$fileName" | grep -q -i '\.mov$'; echo $?` -eq 0 ]; then codec="video/mov"; fi
   if [ `echo "$fileName" | grep -q -i '\.mp4$'; echo $?` -eq 0 ]; then codec="video/mp4"; fi
   if [ `echo "$fileName" | grep -q -i '\.asf$'; echo $?` -eq 0 ]; then codec="video/asf"; fi
   if [ `echo "$fileName" | grep -q -i '\.wmv$'; echo $?` -eq 0 ]; then codec="video/wmv"; fi
   if [ `echo "$fileName" | grep -q -i '\.divx$'; echo $?` -eq 0 ]; then codec="video/divx"; fi
   if [ `echo "$fileName" | grep -q -i '\.dat$'; echo $?` -eq 0 ]; then codec="video/dat"; fi
   if [ `echo "$fileName" | grep -q -i '\.dvr-ms$'; echo $?` -eq 0 ]; then codec="video/dvr-ms"; fi
   if [ `echo "$fileName" | grep -q -i '\.flv$'; echo $?` -eq 0 ]; then codec="video/flv"; fi
   if [ `echo "$fileName" | grep -q -i '\.iso$'; echo $?` -eq 0 ]; then codec="video/iso"; fi
   if [ `echo "$fileName" | grep -q -i '\.mts$'; echo $?` -eq 0 ]; then codec="video/mts"; fi
   if [ `echo "$fileName" | grep -q -i '\.m2t$'; echo $?` -eq 0 ]; then codec="video/m2t"; fi
   if [ `echo "$fileName" | grep -q -i '\.m2ts$'; echo $?` -eq 0 ]; then codec="video/m2ts"; fi
   if [ `echo "$fileName" | grep -q -i '\.m4t$'; echo $?` -eq 0 ]; then codec="video/m4t"; fi
   if [ `echo "$fileName" | grep -q -i '\.tp$'; echo $?` -eq 0 ]; then codec="video/tp"; fi
   if [ `echo "$fileName" | grep -q -i '\.trp$'; echo $?` -eq 0 ]; then codec="video/trp"; fi
   if [ `echo "$fileName" | grep -q -i '\.ts$'; echo $?` -eq 0 ]; then codec="video/ts"; fi
   if [ `echo "$fileName" | grep -q -i '\.tts$'; echo $?` -eq 0 ]; then codec="video/tts"; fi
   if [ `echo "$fileName" | grep -q -i '\.m1s$'; echo $?` -eq 0 ]; then codec="video/m1s"; fi
   if [ `echo "$fileName" | grep -q -i '\.m2p$'; echo $?` -eq 0 ]; then codec="video/m2p"; fi
   if [ `echo "$fileName" | grep -q -i '\.mpg$'; echo $?` -eq 0 ]; then codec="video/mpg"; fi
   if [ `echo "$fileName" | grep -q -i '\.mpeg$'; echo $?` -eq 0 ]; then codec="video/mpeg"; fi
   if [ `echo "$fileName" | grep -q -i '\.mpeg2$'; echo $?` -eq 0 ]; then codec="video/mpeg2"; fi
   if [ `echo "$fileName" | grep -q -i '\.mod$'; echo $?` -eq 0 ]; then codec="video/mod"; fi
   if [ `echo "$fileName" | grep -q -i '\.vbs$'; echo $?` -eq 0 ]; then codec="video/vbs"; fi
   if [ `echo "$fileName" | grep -q -i '\.vob$'; echo $?` -eq 0 ]; then codec="video/vob"; fi
   if [ `echo "$fileName" | grep -q -i '\.mkv$'; echo $?` -eq 0 ]; then codec="video/mkv"; fi
   if [ `echo "$fileName" | grep -q -i '\.avi$'; echo $?` -eq 0 ]; then codec="video/avi"; fi
elif [ `echo "$fileName" | grep -q -i '\.mp3$\|\.mp1$\|\.mp2$\|\.ac3$\|\.ec3$\|\.ape$\|\.wma$\|\.mpa$\|\.m4a$\|\.mp4a$\|\.ogg$\|\.wav$\|\.aac$\|\.flac$\|\.aif$\|\.aiff$\|\.mka$'; echo $?` -eq 0 ]; then
   if [ `echo "$fileName" | grep -q -i '\.mp3$'; echo $?` -eq 0 ]; then codec="audio/mp3"; fi
   if [ `echo "$fileName" | grep -q -i '\.mp1$'; echo $?` -eq 0 ]; then codec="audio/mp1"; fi
   if [ `echo "$fileName" | grep -q -i '\.mp2$'; echo $?` -eq 0 ]; then codec="audio/mp2"; fi
   if [ `echo "$fileName" | grep -q -i '\.ac3$'; echo $?` -eq 0 ]; then codec="audio/ac3"; fi
   if [ `echo "$fileName" | grep -q -i '\.ec3$'; echo $?` -eq 0 ]; then codec="audio/ec3"; fi
   if [ `echo "$fileName" | grep -q -i '\.ape$'; echo $?` -eq 0 ]; then codec="audio/ape"; fi
   if [ `echo "$fileName" | grep -q -i '\.wma$'; echo $?` -eq 0 ]; then codec="audio/wma"; fi
   if [ `echo "$fileName" | grep -q -i '\.mpa$'; echo $?` -eq 0 ]; then codec="audio/mpa"; fi
   if [ `echo "$fileName" | grep -q -i '\.m4a$'; echo $?` -eq 0 ]; then codec="audio/m4a"; fi
   if [ `echo "$fileName" | grep -q -i '\.mp4a$'; echo $?` -eq 0 ]; then codec="audio/mp4a"; fi
   if [ `echo "$fileName" | grep -q -i '\.ogg$'; echo $?` -eq 0 ]; then codec="audio/ogg"; fi
   if [ `echo "$fileName" | grep -q -i '\.wav$'; echo $?` -eq 0 ]; then codec="audio/wav"; fi
   if [ `echo "$fileName" | grep -q -i '\.aac$'; echo $?` -eq 0 ]; then codec="audio/aac"; fi
   if [ `echo "$fileName" | grep -q -i '\.flac$'; echo $?` -eq 0 ]; then codec="audio/flac"; fi
   if [ `echo "$fileName" | grep -q -i '\.aif$'; echo $?` -eq 0 ]; then codec="audio/aiff"; fi
   if [ `echo "$fileName" | grep -q -i '\.aiff$'; echo $?` -eq 0 ]; then codec="audio/aiff"; fi
   if [ `echo "$fileName" | grep -q -i '\.mka$'; echo $?` -eq 0 ]; then codec="audio/mka"; fi
elif [ `echo "$fileName" | grep -q -i '\.jpe*$\|\.png$\|\.tiff+$\|\.bmp$\|\.gif$\|\.jpg$'; echo $?` -eq 0 ]; then
   if [ `echo "$fileName" | grep -q -i '\.jpe*g$'; echo $?` -eq 0 ]; then codec="image/jpeg"; fi
   if [ `echo "$fileName" | grep -q -i '\.png$'; echo $?` -eq 0 ]; then codec="image/png"; fi
   if [ `echo "$fileName" | grep -q -i '\.tif+$'; echo $?` -eq 0 ]; then codec="image/tiff"; fi
   if [ `echo "$fileName" | grep -q -i '\.bmp$'; echo $?` -eq 0 ]; then codec="image/bmp"; fi
   if [ `echo "$fileName" | grep -q -i '\.gif$'; echo $?` -eq 0 ]; then codec="image/gif"; fi
else
   echo "No Codec Found. WTF !!!"
   exit
fi
echo "<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=\"3$1\" parentID=\"3$parentDir\/\" 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:*:$codec::DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=00000000001000000000000000000000\" protection=\"\" tokenType=\"0\" bitrate=\"0\" duration=\"\" size=\"$fileSize\" colorDepth=\"0\" ifoFileURI=\"\" resolution=\"\">file://$1</res></item></DIDL-Lite>"



if anybody would like to review and commit :D

I'll be using the new upnp-cmd function in next SMP release for a very robust version of videoscreensaver that does not require WDTVext for extended functionality
If you like my work please consider a Donation. Donate
Please read the appropriate documentation before posting questions! READ ME FAQ WIKI
PM's are for private matters. Post support questions to the appropriate forum, or they will be ignored.
User avatar
KAD
Global Moderator
 
Posts: 5103
Joined: Mon Apr 12, 2010 4:59 pm
Location: Seattle, WA USA

Re: upnp-cmd and upnp-meta updates   

Postby recliq » Sat May 31, 2014 2:23 am

Hey KAD,

nice work!
Can you provide a patch file? Either the diff from svn
Code: Select all
cd /
svn diff bin/upnp-cmd > /tmp/upnp-cmd.diff

or with diff like this
Code: Select all
diff -u /tmp/upnp-cmd.old /bin/upnp-cmd /tmp/upnp-cmd.patch
­WDLXTV Project Maintainer
-:] If you like my contributions feel free to donate for a beer or a new flash drive. ...and always remember: RTFM! (README, FAQ, WIKI) [:-
User avatar
recliq
WDLXTV Team
 
Posts: 5513
Joined: Thu Apr 15, 2010 8:09 am
Location: Kiel, Germany

Re: upnp-cmd and upnp-meta updates   

Postby KAD » Sat May 31, 2014 10:09 am

If you like my work please consider a Donation. Donate
Please read the appropriate documentation before posting questions! READ ME FAQ WIKI
PM's are for private matters. Post support questions to the appropriate forum, or they will be ignored.
User avatar
KAD
Global Moderator
 
Posts: 5103
Joined: Mon Apr 12, 2010 4:59 pm
Location: Seattle, WA USA


Return to Application Questions

Who is online

Users browsing this forum: No registered users and 1 guest