… so Radio funktioniert jetzt.
Bereitgestellt von Asset-UPNP ! Das ist einfach der Beste UPNP AUDIO SERVER, den ich kenne. Viel zu konfigurieren und vor allem eine Anbindung an TuneIn - Radio.
Das WF ist nur Testweise zugegeben etwas unaufgeräumt 
Der neue iFrame (senkrecht) soll mal die Playlist werden.
Dazu musste ich die UPNP_Browse_Functions.ips.php und UPNP_Browse_WF.php nochmal überarbeiten.
Hier die Neue UPNP_Browse_Functions_V1.6 (in user/Browse/link/UPNP_Browse_Functions.ips.php kopieren). Darin steckt die Abfrage an den Server als function ContentDirectory_Browse mit der Aufsplittung der zurückgegebenen XML welche zunächst das Array $Result ergibt. Daraus wird nach Auswertung der einzelnen Tags ein Array $liste mit allen verfügbaren Parametern (ID´s, Metadaten, Quelle, Quelle des AlbumArt, etc.)
<?
//------------------------------------------------------------------------------
//UPNP_Browse_Functions.ips.php-------------------------------------------------
//UPNP_Browse_Functions_V1.6----------------------------------------------------
//21.08.2013--------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//function ContentDirectory_Browse----------------------------------------------
//------------------------------------------------------------------------------
//IN: $ServerContentDirectory
//IN: $ServerIP
//IN: $ServerPort
//------------------------------------------------------------------------------
//IN: $ObjectID
//IN: $BrowseFlag
//IN: $Filter
//IN: $StartingIndex
//IN: $RequestedCount
//IN: $SortCriteria
//------------------------------------------------------------------------------
//OUT: $Result
//OUT: $NumberReturned
//OUT: $TotalMatches
//OUT: $TotalMatches
//------------------------------------------------------------------------------
function ContentDirectory_Browse ($ServerContentDirectory, $ServerIP, $ServerPort, $ObjectID, $BrowseFlag, $Filter, $StartingIndex, $RequestedCount, $SortCriteria)
{
$header='POST '.$ServerContentDirectory.' HTTP/1.1
HOST: '.$ServerIP.':'.$ServerPort.'
SOAPACTION: "urn:schemas-upnp-org:service:ContentDirectory:1#Browse"
CONTENT-TYPE: text/xml; charset="utf-8"
connection: close';
$xml='<?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:Browse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1">
<ObjectID>'.$ObjectID.'</ObjectID>
<BrowseFlag>'.$BrowseFlag.'</BrowseFlag>
<Filter>'.$Filter.'</Filter>
<StartingIndex>'.$StartingIndex.'</StartingIndex>
<RequestedCount>'.$RequestedCount.'</RequestedCount>
<SortCriteria>'.$SortCriteria.'</SortCriteria>
</u:Browse>
</s:Body>
</s:Envelope>';
$content_ContentDirectory_Browse = $header . '
Content-Length: '. strlen($xml) .'
'. $xml;
$fp = fsockopen ($ServerIP, $ServerPort, $errno, $errstr, 10);
fputs ($fp, $content_ContentDirectory_Browse);
$buffer = stream_get_contents($fp, -1);
echo $buffer;
$vars = explode("
", $buffer); //Header abtrennen
$header = $vars[0]; //Header
$message = $vars[1]; //Message
$handle = fopen('ContentDirectory_Browse.xml', "w"); //XML schreiben
fwrite($handle, $message);
fclose($handle);
fclose($fp);
//XML cutten und Variablen schreiben--------------------------------------------
$vars1 = explode("<Result>", $message);
$cutted1 = $vars1[0];
$cutted2 = $vars1[1];
$vars2 = explode("</Result>", $cutted2);
$cutted3 = $vars2[1];
$Result = $vars2[0];
echo $Result;
SetValue(42199 /*[Audio\Browse\Return\Result]*/, $Result);
$vars1 = explode("<NumberReturned>", $message);
$cutted1 = $vars1[0];
$cutted2 = $vars1[1];
$vars2 = explode("</NumberReturned>", $cutted2);
$cutted3 = $vars2[1];
$NumberReturned = $vars2[0];
echo $NumberReturned;
SetValue(26946 /*[Audio\Browse\Return\NumberReturned]*/, $NumberReturned);
$vars1 = explode("<TotalMatches>", $message);
$cutted1 = $vars1[0];
$cutted2 = $vars1[1];
$vars2 = explode("</TotalMatches>", $cutted2);
$cutted3 = $vars2[1];
$TotalMatches = $vars2[0];
echo $TotalMatches;
SetValue(52875 /*[Audio\Browse\Return\TotalMatches]*/, $TotalMatches);
$vars1 = explode("<UpdateID>", $message);
$cutted1 = $vars1[0];
$cutted2 = $vars1[1];
$vars2 = explode("</UpdateID>", $cutted2);
$cutted3 = $vars2[1];
$UpdateID = $vars2[0];
echo $UpdateID;
SetValue(53319 /*[Audio\Browse\Return\UpdateID]*/, $UpdateID);
Return ($Result);
}
//------------------------------------------------------------------------------
//function BrowseList($Result) --> $Results in Arrays ausgeben------------------
//------------------------------------------------------------------------------
//Sortierung:-------------------------------------------------------------------
//------------------------------------------------------------------------------
//01: container/item
//02: id
//03: refID
//04: parentid
//05: restricted
//06: artist
//07: album
//08: title
//09: resource
//10: duration
//11: size
//12: bitrate
//13: albumArtURI
//14: genre
//15: date
//16: originalTrackNumber
//17: class
//18: extension
//------------------------------------------------------------------------------
function BrowseList($Result)
{
$xmlParser = xml_parser_create();
$Result = substr($Result, stripos($Result, '<'));
$Result = substr($Result, 0, strrpos($Result, '>') + 4);
$Result = str_replace(array("<", ">", """, "&", "%3a", "%2f", "%25"), array("<", ">", "\"", "&", ":", "/", "%"), $Result);
$xml = new SimpleXMLElement($Result);
$liste = array();
for($i=0,$size=count($xml);$i<$size;$i++)
//Ereignisbaum Verzeichnis(container)/Musik(item)----------------------------
//Wenn Container vorhanden, dann ist es ein Browse Element-------------------
//Wenn Item vorhanden, dann ist es ein Song----------------------------------
{
if(isset($xml->container[$i]))
{
//Container vorhanden also Verzeichnis------------------------------------
$aktrow = $xml->container[$i];
$attr = $xml->container[$i]->attributes();
$liste[$i]['typ'] = "container";
}
else if(isset($xml->item[$i]))
{
//Item vorhanden also nur noch Musik--------------------------------------
$aktrow = $xml->item[$i];
$attr = $xml->item[$i]->attributes();
$liste[$i]['typ'] = "item";
//MetaData für jeden Titel zusammenstellen--------------------------------
$metadata_header = '<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/" xmlns:dlna="urn:schemas-dlna-org:metadata-1-0/">';
$raw_metadata_string = $xml->item[$i]->asxml();
$metadata_string = str_replace(array("<", ">"), array("<", ">"), $raw_metadata_string);
$metadata_close = '</DIDL-Lite>';
$metadata = ("$metadata_header"."$metadata_string"."$metadata_close");
$liste[$i]['metadata'] = $metadata;
}
else
{
//Fehler aufgetreten
return;
}
//Inhalte auswerten-------------------------------------------------------------
if(isset($attr['id']) && !empty($attr['id']))
{
$id = $attr['id'];
$liste[$i]['id']=(string)$id;
}
else
{
$liste[$i]['id']="leer";
}
if(isset($attr['refID']) && !empty($attr['refID']))
{
$refid = $attr['refID'];
$liste[$i]['refid']=(string)$refID;
}
else
{
$liste[$i]['refid']="leer";
}
if(isset($attr['parentID']) && !empty($attr['parentID']))
{
$parentID = $attr['parentID'];
$liste[$i]['parentid']=(string)$parentID;
}
else
{
$liste[$i]['parentid']="leer";
}
if(isset($attr['restricted']) && !empty($attr['restricted']))
{
$restricted = $attr['restricted'];
$liste[$i]['restricted']=(string)$restricted;
}
else
{
$liste[$i]['restricted']="leer";
}
if($aktrow->xpath("dc:creator"))
{
$interpret = $aktrow->xpath("dc:creator");
$liste[$i]['artist']=(string)$interpret[0];
}
else
{
$liste[$i]['artist']="leer";
}
if($aktrow->xpath("upnp:album"))
{
$album = $aktrow->xpath("upnp:album");
$liste[$i]['album']=(string)$album[0];
}
else
{
$liste[$i]['album']="leer";
}
if($aktrow->xpath("dc:title"))//eigentlich immer vorhanden
{
$titel = $aktrow->xpath("dc:title");
$liste[$i]['title']=(string)$titel[0];
}
else
{
$liste[$i]['title']="leer";
}
if(isset($aktrow->res))
{
$res = (string)$aktrow->res;
$liste[$i]['resource'] = $res;
}
else
{
$liste[$i]['resource'] = "leer";
}
//Attribute auslesen------------------------------------------------------------
if(isset($aktrow->res->attributes))
{
$resattr = $aktrow->res->attributes();
//wenn name ‘res’ und attribute ‘duration’ vorhanden
if(isset($aktrow->res) and isset($resattr['duration']))
{
$liste[$i]['duration']=(string)$resattr['duration'];
}
else
{
$liste[$i]['duration']="leer";
}
//wenn name ‘res’ und attribute ‘size’ vorhanden
if(isset($aktrow->res) and isset($resattr['size']))
{
$liste[$i]['size']=(string)$resattr['size'];
}
else
{
$liste[$i]['size']="leer";
}
//wenn name ‘res’ und attribute ‘bitrate’ vorhanden
if(isset($aktrow->res) and isset($resattr['bitrate']))
{
$liste[$i]['bitrate']=(string)$resattr['bitrate'];
}
else
{
$liste[$i]['bitrate']="leer";
}
}
if($aktrow->xpath("upnp:albumArtURI"))
{
$albumart = $aktrow->xpath("upnp:albumArtURI");
$liste[$i]['albumArtURI']=(string)$albumart[0];
}
else
{
$liste[$i]['albumArtURI'] ="leer";
}
if($aktrow->xpath("upnp:genre"))
{
$genre = $aktrow->xpath("upnp:genre");
$liste[$i]['genre']=(string)$genre[0];
}
else
{
$liste[$i]['genre']="leer";
}
if($aktrow->xpath("dc:date"))
{
$date = $aktrow->xpath("dc:date");
$liste[$i]['date']=(string)$date[0];
}
else
{
$liste[$i]['date']="leer";
}
if($aktrow->xpath("upnp:originalTrackNumber"))
{
$originalTrackNumber = $aktrow->xpath("upnp:originalTrackNumber");
$liste[$i]['originalTrackNumber']=(string) $originalTrackNumber[0];
}
else
{
$liste[$i]['originalTrackNumber']="leer";
}
if($aktrow->xpath("upnp:class"))
{
$class = $aktrow->xpath("upnp:class");
$liste[$i]['class']=(string)$class[0];
}
else
{
$liste[$i]['class']="leer";
}
if($aktrow->xpath("extension"))
{
$extension = $aktrow->xpath("extension");
$liste[$i]['extension']=(string)$extension[0];
}
else
{
$liste[$i]['extension']="leer";
}
}
return ($liste);
}
?>
Hier die neue UPNP_Browse_WF_V1.5 (in user/Browse/link/UPNP_Browse_WF.php kopieren). Sie ist die eigentliche Steuerung des browsens mit Buttonerstellung und Aktionsauslösung je nach Typ der Auswahl (Container → Verzeichnisse bzw. item → Titel). Die Buttons enthalten dann die spezifische Aktion (weiterbrowsen über die ID oder Play eines selektierten Titel)
<?
//------------------------------------------------------------------------------
//UPNP_Browse_WF.php------------------------------------------------------------
//V1.5
//22.08.2013--------------------------------------------------------------------
//------------------------------------------------------------------------------
$ObjectID = ($_GET["ObjectID"]);
SetValue(42159 /*[Audio\Browse\SelectID]*/, $ObjectID);
//include Functions-------------------------------------------------------------
include ("UPNP_Functions_V2.3.ips.php");
include ("UPNP_Browse_Functions.ips.php");
//IPAdresse und Port des Servers------------------------------------------------
$ServerContentDirectory = GetValue(21972 /*[Audio\Browse\Server:ContentDirectory]*/);
$ServerIP= GetValue(16642 /*[Audio\Browse\Server:IP]*/);
$ServerPort= GetValue(10238 /*[Audio\Browse\Server:Port]*/);
//max_execution_time auf 10 Minuten erhöhen-------------------------------------
ini_set('max_execution_time', 600);
//Suchvariablen-----------------------------------------------------------------
$BrowseFlag = "BrowseDirectChildren"; //GetValue();
$Filter = "*"; //GetValue();
$StartingIndex = "0"; //GetValue();
$RequestedCount = "0"; //GetValue();
$SortCriteria = ""; //GetValue();
//letzte ParentID merken-------------------------------------------------------------------------
$parentid = getvalue(41353 /*[Audio\Browse\DIDL-lite\ParentID [parentID]]*/);
$last_parentid = getvalue(41353 /*[Audio\Browse\DIDL-lite\ParentID [parentID]]*/);
// ContentDirectory_Browse aufrufen ? $Result / Message in Datei
$Result = ContentDirectory_Browse ($ServerContentDirectory, $ServerIP, $ServerPort, $ObjectID, $BrowseFlag, $Filter, $StartingIndex, $RequestedCount, $SortCriteria);
$liste = BrowseList($Result); //Daten aus $Result in Array ($liste) übertragen
print_r ($liste);
echo "
";
$size = count ($liste); //Zahl der Einträge im Array = NumberReturned
echo ($size);
//------------------------------------------------------------------------------
//Buttons erstellen-------------------------------------------------------------
//------------------------------------------------------------------------------
//Head und Buttons erstellen und in HTML-Box schreiben--------------------------
$head="<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>
<html xmlns='http://www.w3.org/1999/xhtml'>
<head>
<!--Variablenuebergabe per XMLHttpRequest / Auslesen per GET in php-->
<script type=\"text/JavaScript\">
function sndReq(url)
{
var action;
action = new XMLHttpRequest;
action.open('get', url);
action.send(null);
<!-- alert(url); -->
}
</script>
<style type=\"text/css\">
body { font-family:Arial,sans-serif; }
input { color:#D8D8D8; width:200px; height:30px; background-color:#0000FF; font-color:#FFBF00; font-weight:bold; font-size:12px; border:3px blue;}
input { background-image:url(image/Button.png); background-repeat:no-repeat; }
input:link { color:#FFBF00; text-decoration:none; font-weight:bold; }
input:visited { color:#FFBF00; text-decoration:none; font-weight:bold; }
input:focus { color:#FFBF00; background-color:#FFFF77; font-weight:bold; }
input:hover { color:#FFBF00; text-decoration:none; background-color:#0000FF; font-weight:bold; }
input:active { color:#FFBF00; background-color:#FFBF00; font-weight:bold; }
</style>
</head>
<body bgcolor=\"#0B243B\" text=\"#0000FF\" style=\"width:650px; height:1000px;\">
";
$buttons ="";
for($i=0,$size=count($liste);$i<$size;$i++)
{
$title = ($liste[$i]["title"]);
$id = ($liste[$i]['id']);
$artist = ($liste[$i]['artist']);
$res = ($liste[$i]['resource']);
$parentid = ($liste[$i]['parentid']);
//prüfen, ob Musik-Track --> wenn ja: Play-Aktion hinzufügen vorbereiten
if (($liste[$i]['typ']) == "item")
{
$play = (" sndReq('link/UPNP_Play_WF.php?Number=" . $i . "'); ");
}
else
{
$play = "";
}
$buttons .=("
<input type=\"button\"
name=\"" .$artist. " - " .$title. "\"
value=\"" .$title. "\"
id=\"" . $id . "\"
alt=\"".$title."\"
onclick=\"sndReq('link/UPNP_Browse_WF.php?ObjectID=" . $id . "');" . $play . "sndReq('link/UPNP_Browse_Verlauf_WF.php?Browse=2/" .$id. "/" .$title. "');\">
</input>
");
}
echo $buttons;
//zusammensetzen und in HTML-Box schreiben-------------------------------------
$auswahl = "$head". "$buttons". "
</body>
</html>
";
echo $auswahl;
SetValueString(11348 /*[Audio\Browse\Auswahl]*/, $auswahl);
if (isset($liste[0]['typ']) == "container")
{
setvaluestring(45881 /*[Audio\Browse\Eigenschaft]*/, "Verzeichnis");
//partielle Website in D:/IP-Symcon/webfront/user/Browse/Browse.html erstellen--
$handle = fopen("D:/IP-Symcon/webfront/user/Browse/Browse.html", "w"); //Browse schreiben
fwrite($handle, $auswahl);
fclose($handle);
//iFrame auffrischen
SetValue(40745 /*[Audio\Browse\Webfront\left\Browse_WF]*/, '<iframe src="../user/Browse/Browse.html" width="100%" height="500" frameborder="0" scrolling="yes"> </iframe>');
SetValue(16067 /*[Audio\Browse\Array]*/, $Result);
$TitelList="0";
$id = ($liste[$TitelList]['id']);
SetValue(38469 /*[Audio\Browse\DIDL-lite\ID [id]]*/, (string)$id);
//letzte ParentID speichern--------------------------------------------------
$parentid = $last_parentid;
setvalue(32592 /*[Audio\Browse\Last_ParentID]*/, (string)$last_parentid);
$parentid = $liste[$TitelList]['parentid']; // gibt parentid des X. Array aus
setvalue(41353 /*[Audio\Browse\DIDL-lite\ParentID [parentID]]*/, (string)$parentid);
}
if (isset($liste[0]['typ']) == "item")
{
setvaluestring(45881 /*[Audio\Browse\Eigenschaft]*/, "Musik");
}
?>
Meine Devices (auch der LG) nehmen es klaglos an. Nur das Senderbild wird auf dem LG noch nicht angezeigt. WMP ist nach wie vor „hartleibig“.
Viele Grüße
André
PS: fast 400 Klicks in 1 Woche sagen mir zumindest, dass das zumindest nicht ganz uninteressant für Euch ist. Wenn Ihr also Fragen habt oder mitentwickeln könnt habe ich immer ein offenes Ohr ! Ich erforsche so etwas gern, tue mich aber mit Programmierungen als „Quereinsteiger“ eher schwer 