UPNP/DLNA for IPS: new version

… also, da ich mich frage, ob ihr das richtig bedient, habe ich ein kurzes how to auf einem taufrisch jungfräulichen IPS und der Installation der heutigen Datei nachgestellt. Das aber als PDF über ein Word-Dokument, da cut and paste screenshots notwendig waren.

Basis how to 2014-08-06.pdf (393 KB)

Übrigens Guido: versuch erstmal z.B. aus den Intel UPNP Developer Tools den Media Renderer oder ein Device, was ich getestet habe. Ich würde mal vermuten, dass bei dem Panasonic Gerät ein steuern über Netzwerk erst freigegeben werden muss (ist bei meinen Fernsehern so gewesen - nach Mediarenderer suchen o.ä.)

Einen kleinen Schönheitsfehler hatte die heutige Datei nach den heutigen Änderungen: ein C muß in einem Script getauscht werden sonst funktioniert Volume nicht (im PDF beschrieben - völlig easy und simpel).

Gruß André

Hallo André,

ganz tolle Beschreibung! Danke dafür. In der Tat scheint jetzt der Pana das Problem zu sein.

Ich werde mich mal in diese Intel Tools einlesen… :slight_smile:

VG
Guido

Hi Andre,

grad ausprobiert und funzt bisher super. Kurzer Hinweis noch. Die Anpassung (kleines „c“ durch großes „C“) muss auch für das Mute Skript UPNP_Mute durchgeführt werden:

SetMute($RenderingControlURL, $DeviceIP, $DevicePort, $DesiredMute);

Dann klappt auch das Mute wieder :wink:

EDIT: Leider ist meine Radio Playlist leer, muss dort noch irgendetwas angepasst werden?

Vielen Dank,

Gruß
Benjamin

Hallo André,

also der Intel Renderer funktioniert einwandfrei.

Meinen Panasonic kann ich über andere UPNP-Software auch super fernsteuern, nur mit IPS will es noch nicht so recht. Geräte sind alle freigegeben. Fällt dir noch was dazu ein?

Gruß
Guido

Hi Andre,

leider habe ich doch noch einige Probleme mit der DLNA Lösung:

Über den Firefox kann ich ganz normal in den Ordnern browsen aber auf allen meinen iOS devices funktioniert das browsen in den Server Ordnern nicht. Die Root Verzeichnisse werden angezeigt, aber wenn ich dann eine Ebene tiefer gehen will, markiert er mir den Ordner (blau hinterlegt) und sonst passiert nichts.

Hast du eine Idee? Habe auch mal den Atomic Browser getestet, leider gleiches verhalten.

Zu den DLNA Devices, funktionieren bei mir folgende:

-Samsung TV

  • Windows 8 MediaPlayer

Leider werden folgende Devices nicht gefunden:

  • PS3
  • Enigma2 Sat Box (vu+)
  • Squeezebox
  • DLNA Client iphone

Wäre hier eine Umsetzung für möglich?

Gruß
Benjamin

Hallo Gemeinde,

erstmal prima, dass es Fortschritte gibt und es rudimentär bei Euch in Gang gekommen ist. Ist doch ein Anreiz - oder ?

@GuidoS

Das mit dem Panasonic kann man sicher hinbekommen. Dazu musst Du aber ein bisschen mit den Intel Tools for UPNP herumspielen. Wichtig dazu ist der Device Spy. Erkläre ich mal, wenn ich wieder mehr Zeit habe.

@bennybunny

IE und Firefox funktionieren. Für andere Browser muss sicher etwas im verwendeten HTML bzw. Javascript angepasst werden. Stieß ich aber auch erst vor kurzem drauf.

Zu den Devices:
Diese Devices habe ich nicht - also auch nicht getestet. Hier solltest Du eventuell mal mit den Einsteellungen von
der function msearch (zu finden in UPNP_Discovery_Functions) herumspielen:

function mSearch($ST)
	{
	//Variablen------------------------------------------------------------------
	$USER_AGENT = 'WINDOWS, UPnP/1.0, Intel MicroStack/1.0.1497';
	$MULTICASTIP = '239.255.255.250';
	$MX = 3;
	$MAN = 'ssdp:discover';
	$sockTimout = '10';

	//Message--------------------------------------------------------------------
	$msg  = 'M-SEARCH * HTTP/1.1' . "
";
	$msg .= 'HOST: '.$MULTICASTIP.':1900' . "
";
	$msg .= 'MAN: "'. $MAN .'"' . "
";
	$msg .= 'MX: '. $MX ."
";
	$msg .= 'ST: ' . $ST ."
";
	//$msg .= 'USER-AGENT: '. $USER_AGENT . "
";
	$msg .= '' ."
";

	//MULTICAST MESSAGE absetzen-------------------------------------------------
	$sock = socket_create( AF_INET, SOCK_DGRAM, getprotobyname('udp') );
	$opt_ret = socket_set_option( $sock, SOL_SOCKET, SO_REUSEADDR, 1 );
	$send_ret = socket_sendto( $sock, $msg, strlen( $msg ), 0, $MULTICASTIP, 1900);

	//TIMEOUT setzen-------------------------------------------------------------
	socket_set_option( $sock, SOL_SOCKET, SO_RCVTIMEO, array( 'sec'=>$sockTimout, 'usec'=>'0' ) );

	//RESPONSE empfangen und bearbeiten (parseMSearchResponse())-----------------
	$response = array();
	do
	{
		unset( $buf );
		@socket_recv( $sock, $buf, 1024, MSG_WAITALL );
		if( !is_null($buf) ) $response[] = parseMSearchResponse( $buf );
	}

	while( !is_null($buf) );

	//SOCKET schliessen----------------------------------------------------------
	socket_close( $sock );

	return $response;
	print_r ($response);
}

Dabei insbesondere $MX und dem Timeout. Wenn das alles nichts hilft schaue ich mal bei Gelegenheit bezüglich des 2. Weges über einen Multicast-Socket den ich mal im Einsatz hatte, der aber etwas kompliziert zu installieren ist.

Würde mich freuen, wenn jemand etwas beisteuern kann !

Die Playlisterstellung (das ist auch für Radio notwendig) erkläre ich bei Gelegenheit mit einem how to - hier muss ich noch etwas anpassen.

Viele Grüße

André

Hi, auch von mir ein ganz kurzes Feedback

Mit der neuen Version ging es jetzt mit einigen Geräten. Mein Tablet mit BubbleUpnp funktioniert zum Abspielen, auch Mute geht, wenn man das C korrigiert, aber die Lautstärke funktioniert auch mit dem C nicht :slight_smile:

Es werden aber 2 von 5 Devices und 2 von 6 Servern angezeigt, dafür der Twonky doppelt…

Ich hab aber gerade nicht genug Zeit um ausführlich zu testen, das wäre dem Projekt jetzt nicht angemessen, deswegen berichte ich nochmal wenn ich etwas mehr Zeit habe.

Es wäre aber echt super wenn wir das noch Chrome-Kompatibel hinbekommen.

Ok. Ich würde mal sagen Feintuning ist angesagt…

Gesendet von meinem C6833 mit Tapatalk

Hi Andre,

was macht bzw wofür steht genau $MX? Was soll ich da anpassen um ggf die anderen DLNA Clients zu finden?

Gruß
Benjamin

Mal mit 5, 10 oder sogar 30 probieren. Es gibt die Reaktionszeit an. Vgl. Google. Ich bin bei den Sockets nicht so firm. Vielleicht kann man da noch was verbessern (z.B. Dauer des Empfangs)
Viele Grüße André

Gesendet von meinem C6833 mit Tapatalk

@Hagbard235

Ich denke es wird an den HTML Headern liegen in Upnp_Browse_Functions komme aber erst Sonntag ans Laptop um zu schauen. Hat Chrome einen Debugmodus?

Gruß André

@Hagbard235

soweit ich das Problem mit Chrome verifizieren konnte, liegt es an den Aktualisierungsaufrufen der iFrames.

Zu finden ist in UPNP_Browse_Server in verschiedenen Buttonerstellungen onklick-Aufrufe um eine Aktualisierung auszulösen wie:

parent.frames['iframe_XXX'].location.reload();

Diesen Ausdruck mögen manche Browser offenbar nicht. Hat jemand eine Idee?

Oder vielleicht anders: werden HTML-Boxen bei Veränderung des Inhaltes automatisch neu geladen ?

Für mich ist es nicht relevant, da ich IE oder Firefox benutze. Aber für Euch vielleicht.

Viele Grüße

André

Hi,

habe herausgefunden, dass es am Input-Type „hidden“ der Buttons liegt :confused:

Der Aufbau der Browse Buttons ist z.B.:

<div class="form-button">
 <input
  type="hidden"
  name=""
  value="Bilder"
  id="1"
  onclick="
  sndReq('link/UPNP_Browse_Web.php?ObjectID=4:cont1:90:0:0:');
  sndReq('link/UPNP_Browse_Verlauf_Web.php?Browse=2/4:cont1:90:0:0:/Bilder');
  ">
 </input>
 <img src="image/Folder.png" width="40" height="40">
 <label for="1"><font color="#6A6D64"><b>Folder</b></font><br/><font color="#FFFFFF">Bilder</font></label>
</div>

Diese etwas spezielle Zusammenstellung eines Buttons, auf hidden gesetzt, mit Bild und Beschriftung versteht Chrome nicht. IE und Firefox interpretieren es richtig.
Kann mir Jemand eine bessere Zusammensetzung beschreiben ?

Gruß André

Moin DigiHouse,

dies könnte funktionieren, habe es aber nicht getestet.

MFG MNB


<div class="form-button">
<div style="display: none">
<input
  type="text"
  name=""
  value="Bilder"
  id="1"
  onclick="
  sndReq('link/UPNP_Browse_Web.php?ObjectID=4:cont1:90:0:0:');
  sndReq('link/UPNP_Browse_Verlauf_Web.php?Browse=2/4:cont1:90:0:0:/Bilder');
  ">
 </input>
</div>
 <img src="image/Folder.png" width="40" height="40">
 <label for="1"><font color="#6A6D64"><b>Folder</b></font><br/><font color="#FFFFFF">Bilder</font></label>
</div>

Hallo mnb,

Es hilft nichts. Ich habe gestern angefangen, die Buttons umzubauen.

Bist Du mit dem Array weitergekommen?

Gruß André

Moin DigiHouse,

schade das es damit nicht geklappt hat.
Mit dem Array bin ich weiter gekommen,
nächste Woche kann ich dir das Script geben.
Bin zur Zeit unterwegs :-).

PS: Hattest du den Stand den ich dir vor ~1 1/2 Wochen geschickt hatte angeschaut,
ob die Informationen richtig ausgegeben werden?

MFG MNB

Hallo mnb,

bin mit der Anpassung der Buttons (Problem der besonderen Button-Zusammensetzung) fast fertig.

Würde gern das Browsen verbessern und suche eine Funktion, die schon die Message des Gerätes einfach auseinandernimmt. D.h. die 4 grundlegenden Variablen $Result, $NumberReturned, $TotalMatches, $UpdateID sollten in einem Array zurückgegeben werden.
Mit XPath kann man, wenn die Ebene im XML bekannt ist (die ändert sich nicht !) ja eigentlich direkt auf Result etc. zugreifen. Im unten gezeigten Ansatz bekomme ich aber nur die SimpleXMLElement Object´s jeweils als Array bzw. $NumberReturned, $TotalMatches, $UpdateID bleiben ganz leer. Es war eben ganz simpel gedacht - wäre ja auch zu schön gewesen.

<?

$message = '<?xml version="1.0"?>
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
 <s:Body>
  <u:BrowseResponse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1">
   <Result><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:pxn="urn:schemas-panasonic-com:pxn" xmlns:dvb="urn:schemas-dvb-org:metadata-1-0/" xmlns:vli="urn:schemas-panasonic-com:vli"><item id="AV-0-268435456-0-0-268436152-310261500" parentID="AV_ALL" restricted="0"><dc:title>FIFA WM 2014: Deutschland - Portugal</dc:title><upnp:writeStatus>NOT_WRITABLE</upnp:writeStatus><upnp:recordable>0</upnp:recordable><upnp:channelID type="DIGITAL">1.0</upnp:channelID><upnp:class name="videoItem">object.item.videoItem</upnp:class><res protocolInfo="http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01100000000000000000000000000000" duration="1:54:54" size="9730977792" pxn:NaviList="http://192.168.178.91:60002/AV/ROOTDB_RPL?CID=AV-0-268435456-0-0-268436152-310261500" pxn:StreamPort="60001" pxn:ChapterList="http://192.168.178.91:60002/AV/CHP_LIST?CID=AV-0-268435456-0-0-268436152-310261500" pxn:ResumePoint="0:00:00" pxn:VgaContentVideoBitrate="2626" pxn:VgaContentUri="http://192.168.178.91:60001/AV-0-268435456-0-0-268436152-310261500_BDY?CI=1&fmt=AVC_TS_MP_HD_AAC_LTP_T&bitrate=3000&resolution=360" pxn:VgaContentProtocolInfo="http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_LTP_T;DLNA.ORG_OP=10;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=81100000000000000000000000000000" vli:playitemNum="1">http://192.168.178.91:60001/AV-0-268435456-0-0-268436152-310261500_BDY</res><upnp:genre>Sports</upnp:genre><upnp:channelName>Das Erste HD</upnp:channelName><dc:date>2014-06-16T18:08:11</dc:date><upnp:channelNr>1</upnp:channelNr><dvb:objectType>DVB_TB</dvb:objectType><upnp:playbackCount>0</upnp:playbackCount><pxn:groupTopFlag>1</pxn:groupTopFlag><pxn:groupID>AV-0-268435456-0-1-150</pxn:groupID><pxn:groupMemberNum>1</pxn:groupMemberNum><pxn:groupPlaybackCount>0</pxn:groupPlaybackCount><pxn:bbr_content_id>0x100002B8</pxn:bbr_content_id><upnp:storageMedium>HDD</upnp:storageMedium></item><item id="AV-0-268435456-0-0-268436154-272840400" parentID="AV_ALL" restricted="0"><dc:title>FIFA WM 2014: Deutschland - Ghana</dc:title><upnp:writeStatus>NOT_WRITABLE</upnp:writeStatus><upnp:recordable>0</upnp:recordable><upnp:channelID type="DIGITAL">1.0</upnp:channelID><upnp:class name="videoItem">object.item.videoItem</upnp:class><res protocolInfo="http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01100000000000000000000000000000" duration="1:41:03" size="9897480192" pxn:NaviList="http://192.168.178.91:60002/AV/ROOTDB_RPL?CID=AV-0-268435456-0-0-268436154-272840400" pxn:StreamPort="60001" pxn:ChapterList="http://192.168.178.91:60002/AV/CHP_LIST?CID=AV-0-268435456-0-0-268436154-272840400" pxn:ResumePoint="0:00:00" pxn:VgaContentVideoBitrate="2626" pxn:VgaContentUri="http://192.168.178.91:60001/AV-0-268435456-0-0-268436154-272840400_BDY?CI=1&fmt=AVC_TS_MP_HD_AAC_LTP_T&bitrate=3000&resolution=360" pxn:VgaContentProtocolInfo="http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_LTP_T;DLNA.ORG_OP=10;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=81100000000000000000000000000000" vli:playitemNum="1">http://192.168.178.91:60001/AV-0-268435456-0-0-268436154-272840400_BDY</res><upnp:genre>Sports</upnp:genre><upnp:channelName>Das Erste HD</upnp:channelName><dc:date>2014-06-21T20:12:02</dc:date><upnp:channelNr>1</upnp:channelNr><dvb:objectType>DVB_TB</dvb:objectType><upnp:playbackCount>0</upnp:playbackCount><pxn:groupTopFlag>1</pxn:groupTopFlag><pxn:groupID>AV-0-268435456-0-1-152</pxn:groupID><pxn:groupMemberNum>1</pxn:groupMemberNum><pxn:groupPlaybackCount>0</pxn:groupPlaybackCount><pxn:bbr_content_id>0x100002BA</pxn:bbr_content_id><upnp:storageMedium>HDD</upnp:storageMedium></item><item id="AV-0-268435456-0-0-268436165-259394400" parentID="AV_ALL" restricted="0"><dc:title>Krauses Kur</dc:title><upnp:writeStatus>NOT_WRITABLE</upnp:writeStatus><upnp:recordable>0</upnp:recordable><upnp:channelID type="DIGITAL">15.0</upnp:channelID><upnp:class name="videoItem">object.item.videoItem</upnp:class><res protocolInfo="http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01100000000000000000000000000000" duration="1:36:04" size="6046175232" pxn:NaviList="http://192.168.178.91:60002/AV/ROOTDB_RPL?CID=AV-0-268435456-0-0-268436165-259394400" pxn:StreamPort="60001" pxn:ChapterList="http://192.168.178.91:60002/AV/CHP_LIST?CID=AV-0-268435456-0-0-268436165-259394400" pxn:ResumePoint="1:33:29" pxn:VgaContentVideoBitrate="2626" pxn:VgaContentUri="http://192.168.178.91:60001/AV-0-268435456-0-0-268436165-259394400_BDY?CI=1&fmt=AVC_TS_MP_HD_AAC_LTP_T&bitrate=3000&resolution=360" pxn:VgaContentProtocolInfo="http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_LTP_T;DLNA.ORG_OP=10;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=81100000000000000000000000000000" vli:playitemNum="1">http://192.168.178.91:60001/AV-0-268435456-0-0-268436165-259394400_BDY</res><upnp:genre>Movie/Drama</upnp:genre><upnp:channelName>MDR Sachsen</upnp:channelName><dc:date>2014-06-27T23:57:01</dc:date><upnp:channelNr>15</upnp:channelNr><dvb:objectType>DVB_TB</dvb:objectType><upnp:playbackCount>-1</upnp:playbackCount><pxn:groupTopFlag>1</pxn:groupTopFlag><pxn:groupID>AV-0-268435456-0-1-177</pxn:groupID><pxn:groupMemberNum>1</pxn:groupMemberNum><pxn:groupPlaybackCount>-1</pxn:groupPlaybackCount><pxn:bbr_content_id>0x100002C5</pxn:bbr_content_id><upnp:storageMedium>HDD</upnp:storageMedium></item><item id="AV-0-268435456-0-0-268436166-453454200" parentID="AV_ALL" restricted="0"><dc:title>Bad Boys II</dc:title><upnp:writeStatus>NOT_WRITABLE</upnp:writeStatus><upnp:recordable>0</upnp:recordable><upnp:channelID type="DIGITAL">6.0</upnp:channelID><upnp:class name="videoItem">object.item.videoItem</upnp:class><res protocolInfo="http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01100000000000000000000000000000" duration="2:47:56" size="7080996864" pxn:NaviList="http://192.168.178.91:60002/AV/ROOTDB_RPL?CID=AV-0-268435456-0-0-268436166-453454200" pxn:StreamPort="60001" pxn:ChapterList="http://192.168.178.91:60002/AV/CHP_LIST?CID=AV-0-268435456-0-0-268436166-453454200" pxn:ResumePoint="0:00:00" pxn:VgaContentVideoBitrate="2626" pxn:VgaContentUri="http://192.168.178.91:60001/AV-0-268435456-0-0-268436166-453454200_BDY?CI=1&fmt=AVC_TS_MP_HD_AAC_LTP_T&bitrate=3000&resolution=360" pxn:VgaContentProtocolInfo="http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_LTP_T;DLNA.ORG_OP=10;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=81100000000000000000000000000000" vli:playitemNum="1">http://192.168.178.91:60001/AV-0-268435456-0-0-268436166-453454200_BDY</res><upnp:genre>Unclassified</upnp:genre><upnp:channelName>ProSieben</upnp:channelName><dc:date>2014-07-13T03:06:57</dc:date><upnp:channelNr>6</upnp:channelNr><dvb:objectType>DVB_TB</dvb:objectType><upnp:playbackCount>0</upnp:playbackCount><pxn:groupTopFlag>1</pxn:groupTopFlag><pxn:groupID>AV-0-268435456-0-1-18</pxn:groupID><pxn:groupMemberNum>1</pxn:groupMemberNum><pxn:groupPlaybackCount>0</pxn:groupPlaybackCount><pxn:bbr_content_id>0x100002C6</pxn:bbr_content_id><upnp:storageMedium>HDD</upnp:storageMedium></item><item id="AV-0-268435456-0-0-268436167-290304000" parentID="AV_ALL" restricted="0"><dc:title>The Specialist</dc:title><upnp:writeStatus>NOT_WRITABLE</upnp:writeStatus><upnp:recordable>0</upnp:recordable><upnp:channelID type="DIGITAL">4.0</upnp:channelID><upnp:class name="videoItem">object.item.videoItem</upnp:class><res protocolInfo="http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01100000000000000000000000000000" duration="1:47:31" size="3602325504" pxn:NaviList="http://192.168.178.91:60002/AV/ROOTDB_RPL?CID=AV-0-268435456-0-0-268436167-290304000" pxn:StreamPort="60001" pxn:ChapterList="http://192.168.178.91:60002/AV/CHP_LIST?CID=AV-0-268435456-0-0-268436167-290304000" pxn:ResumePoint="0:00:00" pxn:VgaContentVideoBitrate="2626" pxn:VgaContentUri="http://192.168.178.91:60001/AV-0-268435456-0-0-268436167-290304000_BDY?CI=1&fmt=AVC_TS_MP_HD_AAC_LTP_T&bitrate=3000&resolution=360" pxn:VgaContentProtocolInfo="http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_LTP_T;DLNA.ORG_OP=10;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=81100000000000000000000000000000" vli:playitemNum="1">http://192.168.178.91:60001/AV-0-268435456-0-0-268436167-290304000_BDY</res><upnp:genre>Unclassified</upnp:genre><upnp:channelName>SAT.1</upnp:channelName><dc:date>2014-07-13T04:05:07</dc:date><upnp:channelNr>4</upnp:channelNr><dvb:objectType>DVB_TB</dvb:objectType><upnp:playbackCount>0</upnp:playbackCount><pxn:groupTopFlag>1</pxn:groupTopFlag><pxn:groupID>AV-0-268435456-0-1-33</pxn:groupID><pxn:groupMemberNum>1</pxn:groupMemberNum><pxn:groupPlaybackCount>0</pxn:groupPlaybackCount><pxn:bbr_content_id>0x100002C7</pxn:bbr_content_id><upnp:storageMedium>HDD</upnp:storageMedium></item><item id="AV-0-268435456-0-0-268436169-442368000" parentID="AV_ALL" restricted="0"><dc:title>Transformers - Die Rache</dc:title><upnp:writeStatus>NOT_WRITABLE</upnp:writeStatus><upnp:recordable>0</upnp:recordable><upnp:channelID type="DIGITAL">6.0</upnp:channelID><upnp:class name="videoItem">object.item.videoItem</upnp:class><res protocolInfo="http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01100000000000000000000000000000" duration="2:43:50" size="6572752896" pxn:NaviList="http://192.168.178.91:60002/AV/ROOTDB_RPL?CID=AV-0-268435456-0-0-268436169-442368000" pxn:StreamPort="60001" pxn:ChapterList="http://192.168.178.91:60002/AV/CHP_LIST?CID=AV-0-268435456-0-0-268436169-442368000" pxn:ResumePoint="0:00:00" pxn:VgaContentVideoBitrate="2626" pxn:VgaContentUri="http://192.168.178.91:60001/AV-0-268435456-0-0-268436169-442368000_BDY?CI=1&fmt=AVC_TS_MP_HD_AAC_LTP_T&bitrate=3000&resolution=360" pxn:VgaContentProtocolInfo="http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_LTP_T;DLNA.ORG_OP=10;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=81100000000000000000000000000000" vli:playitemNum="1">http://192.168.178.91:60001/AV-0-268435456-0-0-268436169-442368000_BDY</res><upnp:genre>Unclassified</upnp:genre><upnp:channelName>ProSieben</upnp:channelName><dc:date>2014-07-13T15:17:14</dc:date><upnp:channelNr>6</upnp:channelNr><dvb:objectType>DVB_TB</dvb:objectType><upnp:playbackCount>-1</upnp:playbackCount><pxn:groupTopFlag>1</pxn:groupTopFlag><pxn:groupID>AV-0-268435456-0-1-42</pxn:groupID><pxn:groupMemberNum>1</pxn:groupMemberNum><pxn:groupPlaybackCount>-1</pxn:groupPlaybackCount><pxn:bbr_content_id>0x100002C9</pxn:bbr_content_id><upnp:storageMedium>HDD</upnp:storageMedium></item><item id="AV-0-268435456-0-0-268436184-429429600" parentID="AV_ALL" restricted="0"><dc:title>Sphere - Die Macht aus dem All</dc:title><upnp:writeStatus>NOT_WRITABLE</upnp:writeStatus><upnp:recordable>0</upnp:recordable><upnp:channelID type="DIGITAL">7.0</upnp:channelID><upnp:class name="videoItem">object.item.videoItem</upnp:class><res protocolInfo="http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01100000000000000000000000000000" duration="2:39:02" size="4951179264" pxn:NaviList="http://192.168.178.91:60002/AV/ROOTDB_RPL?CID=AV-0-268435456-0-0-268436184-429429600" pxn:StreamPort="60001" pxn:ChapterList="http://192.168.178.91:60002/AV/CHP_LIST?CID=AV-0-268435456-0-0-268436184-429429600" pxn:ResumePoint="0:00:00" pxn:VgaContentVideoBitrate="2626" pxn:VgaContentUri="http://192.168.178.91:60001/AV-0-268435456-0-0-268436184-429429600_BDY?CI=1&fmt=AVC_TS_MP_HD_AAC_LTP_T&bitrate=3000&resolution=360" pxn:VgaContentProtocolInfo="http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_LTP_T;DLNA.ORG_OP=10;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=81100000000000000000000000000000" vli:playitemNum="1">http://192.168.178.91:60001/AV-0-268435456-0-0-268436184-429429600_BDY</res><upnp:genre>Movie/Drama</upnp:genre><upnp:channelName>RTL2</upnp:channelName><dc:date>2014-07-13T22:36:01</dc:date><upnp:channelNr>7</upnp:channelNr><dvb:objectType>DVB_TB</dvb:objectType><upnp:playbackCount>0</upnp:playbackCount><pxn:groupTopFlag>1</pxn:groupTopFlag><pxn:groupID>AV-0-268435456-0-1-165</pxn:groupID><pxn:groupMemberNum>1</pxn:groupMemberNum><pxn:groupPlaybackCount>0</pxn:groupPlaybackCount><pxn:bbr_content_id>0x100002D8</pxn:bbr_content_id><upnp:storageMedium>HDD</upnp:storageMedium></item><item id="AV-0-268435456-0-0-268436187-324151200" parentID="AV_ALL" restricted="0"><dc:title>Noch Tausend Worte</dc:title><upnp:writeStatus>NOT_WRITABLE</upnp:writeStatus><upnp:recordable>0</upnp:recordable><upnp:channelID type="DIGITAL">4.0</upnp:channelID><upnp:class name="videoItem">object.item.videoItem</upnp:class><res protocolInfo="http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01100000000000000000000000000000" duration="2:00:03" size="4085981184" pxn:NaviList="http://192.168.178.91:60002/AV/ROOTDB_RPL?CID=AV-0-268435456-0-0-268436187-324151200" pxn:StreamPort="60001" pxn:ChapterList="http://192.168.178.91:60002/AV/CHP_LIST?CID=AV-0-268435456-0-0-268436187-324151200" pxn:ResumePoint="0:00:00" pxn:VgaContentVideoBitrate="2626" pxn:VgaContentUri="http://192.168.178.91:60001/AV-0-268435456-0-0-268436187-324151200_BDY?CI=1&fmt=AVC_TS_MP_HD_AAC_LTP_T&bitrate=3000&resolution=360" pxn:VgaContentProtocolInfo="http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_LTP_T;DLNA.ORG_OP=10;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=81100000000000000000000000000000" vli:playitemNum="1">http://192.168.178.91:60001/AV-0-268435456-0-0-268436187-324151200_BDY</res><upnp:genre>Unclassified</upnp:genre><upnp:channelName>SAT.1</upnp:channelName><dc:date>2014-07-20T16:14:05</dc:date><upnp:channelNr>4</upnp:channelNr><dvb:objectType>DVB_TB</dvb:objectType><upnp:playbackCount>0</upnp:playbackCount><pxn:groupTopFlag>1</pxn:groupTopFlag><pxn:groupID>AV-0-268435456-0-1-64</pxn:groupID><pxn:groupMemberNum>1</pxn:groupMemberNum><pxn:groupPlaybackCount>0</pxn:groupPlaybackCount><pxn:bbr_content_id>0x100002DB</pxn:bbr_content_id><upnp:storageMedium>HDD</upnp:storageMedium></item><item id="AV-0-268435456-0-0-268436199-280951200" parentID="AV_ALL" restricted="0"><dc:title>Crank</dc:title><upnp:writeStatus>NOT_WRITABLE</upnp:writeStatus><upnp:recordable>0</upnp:recordable><upnp:channelID type="DIGITAL">7.0</upnp:channelID><upnp:class name="videoItem">object.item.videoItem</upnp:class><res protocolInfo="http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01100000000000000000000000000000" duration="1:44:03" size="3766001664" pxn:NaviList="http://192.168.178.91:60002/AV/ROOTDB_RPL?CID=AV-0-268435456-0-0-268436199-280951200" pxn:StreamPort="60001" pxn:ChapterList="http://192.168.178.91:60002/AV/CHP_LIST?CID=AV-0-268435456-0-0-268436199-280951200" pxn:ResumePoint="0:00:00" pxn:VgaContentVideoBitrate="2626" pxn:VgaContentUri="http://192.168.178.91:60001/AV-0-268435456-0-0-268436199-280951200_BDY?CI=1&fmt=AVC_TS_MP_HD_AAC_LTP_T&bitrate=3000&resolution=360" pxn:VgaContentProtocolInfo="http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_LTP_T;DLNA.ORG_OP=10;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=81100000000000000000000000000000" vli:playitemNum="1">http://192.168.178.91:60001/AV-0-268435456-0-0-268436199-280951200_BDY</res><upnp:genre>Movie/Drama</upnp:genre><upnp:channelName>RTL2</upnp:channelName><dc:date>2014-08-01T22:23:01</dc:date><upnp:channelNr>7</upnp:channelNr><dvb:objectType>DVB_TB</dvb:objectType><upnp:playbackCount>0</upnp:playbackCount><pxn:groupTopFlag>1</pxn:groupTopFlag><pxn:groupID>AV-0-268435456-0-1-154</pxn:groupID><pxn:groupMemberNum>1</pxn:groupMemberNum><pxn:groupPlaybackCount>0</pxn:groupPlaybackCount><pxn:bbr_content_id>0x100002E7</pxn:bbr_content_id><upnp:storageMedium>HDD</upnp:storageMedium></item></DIDL-Lite></Result>
   <NumberReturned>9</NumberReturned>
   <TotalMatches>129</TotalMatches>
   <UpdateID>324</UpdateID>
  </u:BrowseResponse>
 </s:Body>
</s:Envelope>';

print_r($message);

$xml = simplexml_load_string($message);

$Result = $xml->xpath("////Result");
print_r($Result);
$NumberReturned = $xml->xpath("////NumberReturned");
print_r($NumberReturned);
$TotalMatches = $xml->xpath("////TotalMatches");
print_r($TotalMatches);
$UpdateID = $xml->xpath("////UpdateID");
print_r($UpdateID);

?>

Kann man das jeweils als String, also alles was im Tag <Result>, <NumberReturned> etc. steht ausgeben bzw. in ein Array packen ?

Gruß André

Hallo mnb,

Mit Deinen Functions habe ich mich heute nochmal in diversen Testläufen beschäftigt - funzt schon sehr gut :smiley:
Es geht auch ein mischen von Foldern und Items. $MetaData habe ich dann gleich durch das Einfügen der gesamten DIDL-Lite mit implementiert.

Hier mein aktuelles Test-Skript:

<?
$xml = '<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:BrowseResponse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1"><Result><DIDL-Lite xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" xmlns:dlna="urn:schemas-dlna-org:metadata-1-0/">
<container id="A0$128$146$524565$22413589$22479125$192676117$192741653" parentID="A0$128$146$524565$22413589$22479125$192676117" restricted="1" childCount="31"><dc:title>ATB Sunset Beach DJ Session</dc:title><upnp:class>object.container.storageFolder</upnp:class></container><container id="A0$128$146$524565$22413589$22479125$192676117$192807189" parentID="A0$128$146$524565$22413589$22479125$192676117" restricted="1" childCount="26"><dc:title>Future Memories</dc:title><upnp:class>object.container.storageFolder</upnp:class></container><item id="A0$128$146$524565$22413589$22479125$192676117$571146500" parentID="A0$128$146$524565$22413589$22479125$192676117" restricted="1"><dc:title>Right Back (Original Mix)</dc:title><upnp:class>object.item.audioItem.musicTrack</upnp:class><dc:description>Amazon.com Song ID: 217023763</dc:description><dc:creator>Yuri Kane</dc:creator><dc:date>2014-07-20T16:21:15</dc:date><upnp:artist>Yuri Kane</upnp:artist><upnp:album>ATB Sunset Beach DJ Session</upnp:album><upnp:genre>Dance &amp; DJ</upnp:genre><upnp:originalTrackNumber>2</upnp:originalTrackNumber><res xmlns:dlna="urn:schemas-dlna-org:metadata-1-0/" size="11797385" duration="00:05:56.00" bitrate="259000" sampleFrequency="44100" nrAudioChannels="2" protocolInfo="http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000">http://192.168.178.10:8200/MediaItems/A0$128$146$524565$22413589$22479125$192676117$571146500.mp3?type=1,client=25,mime=audio/mpeg,pn=MP3</res></item><item id="A0$128$146$524565$22413589$22479125$192676117$571080964" parentID="A0$128$146$524565$22413589$22479125$192676117" restricted="1"><dc:title>L.A. Nights</dc:title><upnp:class>object.item.audioItem.musicTrack</upnp:class><dc:description>Amazon.com Song ID: 213174179</dc:description><dc:creator>ATB</dc:creator><dc:date>2014-07-20T16:21:13</dc:date><upnp:artist>ATB</upnp:artist><upnp:album>Future Memories</upnp:album><upnp:genre>Dance &amp; DJ</upnp:genre><upnp:originalTrackNumber>1</upnp:originalTrackNumber><res xmlns:dlna="urn:schemas-dlna-org:metadata-1-0/" size="9074176" duration="00:04:32.00" bitrate="264000" sampleFrequency="44100" nrAudioChannels="2" protocolInfo="http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000">http://192.168.178.10:8200/MediaItems/A0$128$146$524565$22413589$22479125$192676117$571080964.mp3?type=1,client=25,mime=audio/mpeg,pn=MP3</res><upnp:albumArtURI dlna:profileID="JPEG_TN" xmlns:dlna="urn:schemas-dlna-org:metadata-1-0/">http://192.168.178.10:8200/Thumbnails/A01/share/CACHEDEV1_DATA/.system/music/atb%2ffuture+memories.jpg</upnp:albumArtURI></item><item id="A0$128$146$524565$22413589$22479125$192676117$571015428" parentID="A0$128$146$524565$22413589$22479125$192676117" restricted="1"><dc:title>Could You Believe (Airplay Mix)</dc:title><upnp:class>object.item.audioItem.musicTrack</upnp:class><dc:description>Amazon.com Song ID: 217023762</dc:description><dc:creator>ATB</dc:creator><dc:date>2014-07-20T16:21:11</dc:date><upnp:artist>ATB</upnp:artist><upnp:album>ATB Sunset Beach DJ Session</upnp:album><upnp:genre>Dance &amp; DJ</upnp:genre><upnp:originalTrackNumber>1</upnp:originalTrackNumber><res xmlns:dlna="urn:schemas-dlna-org:metadata-1-0/" size="7360435" duration="00:03:29.00" bitrate="272000" sampleFrequency="44100" nrAudioChannels="2" protocolInfo="http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000">http://192.168.178.10:8200/MediaItems/A0$128$146$524565$22413589$22479125$192676117$571015428.mp3?type=1,client=25,mime=audio/mpeg,pn=MP3</res><upnp:albumArtURI dlna:profileID="JPEG_TN" xmlns:dlna="urn:schemas-dlna-org:metadata-1-0/">http://192.168.178.10:8200/Thumbnails/A01/share/CACHEDEV1_DATA/.system/music/atb%2fatb+sunset+beach+dj+session.jpg</upnp:albumArtURI></item><item id="A0$128$146$524565$22413589$22479125$192676117$571212036" parentID="A0$128$146$524565$22413589$22479125$192676117" restricted="1"><dc:title>What About Us</dc:title><upnp:class>object.item.audioItem.musicTrack</upnp:class><dc:description>Amazon.com Song ID: 213174180</dc:description><dc:creator>ATB</dc:creator><dc:date>2014-07-20T16:21:16</dc:date><upnp:artist>ATB</upnp:artist><upnp:album>Future Memories</upnp:album><upnp:genre>Dance &amp; DJ</upnp:genre><upnp:originalTrackNumber>2</upnp:originalTrackNumber><res xmlns:dlna="urn:schemas-dlna-org:metadata-1-0/" size="11756320" duration="00:05:35.00" bitrate="279000" sampleFrequency="44100" nrAudioChannels="2" protocolInfo="http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000">http://192.168.178.10:8200/MediaItems/A0$128$146$524565$22413589$22479125$192676117$571212036.mp3?type=1,client=25,mime=audio/mpeg,pn=MP3</res><upnp:albumArtURI dlna:profileID="JPEG_TN" xmlns:dlna="urn:schemas-dlna-org:metadata-1-0/">http://192.168.178.10:8200/Thumbnails/A01/share/CACHEDEV1_DATA/.system/music/atb%2ffuture+memories.jpg</upnp:albumArtURI></item></DIDL-Lite></Result>
<NumberReturned>6</NumberReturned>
<TotalMatches>6</TotalMatches>
<UpdateID>0</UpdateID></u:BrowseResponse></s:Body></s:Envelope>

';

$MetaData = simplexml_load_string($xml);
$MetaData = $MetaData->xpath("//Result");
$MetaData = (string) $MetaData[0];

//DIDL umwandeln
$DIDL = (xml2array($xml));
//print_r($DIDL);

//Array $Liste erstellen
$liste = BrowseList($DIDL, $MetaData);
print_r($liste);


//Functions---------------------------------------------------------------------

function xml2array($contents, $get_attributes=1, $priority = 'tag') {
    if(!$contents) return array();

    if(!function_exists('xml_parser_create')) {
        //print "'xml_parser_create()' function not found!";
        return array();
    }

    $contents = str_replace(array("<", ">", """, "&", "%3a", "%2f", "%25"), array("<", ">", "\"", "&", ":", "/", "%"), $contents);
    //Get the XML parser of PHP - PHP must have this module for the parser to work
    $parser = xml_parser_create('');
    xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8");
    xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
    xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
    xml_parse_into_struct($parser, trim($contents), $xml_values);
    xml_parser_free($parser);

    if(!$xml_values) return;//Hmm...

    //Initializations
    $xml_array = array();
    $parents = array();
    $opened_tags = array();
    $arr = array();

    $current = &$xml_array; //Refference

    //Go through the tags.
    $repeated_tag_index = array();//Multiple tags with same name will be turned into an array
    foreach($xml_values as $data) {
        unset($attributes,$value);//Remove existing values, or there will be trouble

        //This command will extract these variables into the foreach scope
        // tag(string), type(string), level(int), attributes(array).
        extract($data);//We could use the array by itself, but this cooler.

        $result = array();
        $attributes_data = array();

        if(isset($value)) {
            if($priority == 'tag') $result = $value;
            else $result['value'] = $value; //Put the value in a assoc array if we are in the 'Attribute' mode
        }

        //Set the attributes too.
        if(isset($attributes) and $get_attributes) {
            foreach($attributes as $attr => $val) {
                if($priority == 'tag') $attributes_data[$attr] = $val;
                else $result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr'
            }
        }

        //See tag status and do the needed.
        if($type == "open") {//The starting of the tag '<tag>'
            $parent[$level-1] = &$current;
            if(!is_array($current) or (!in_array($tag, array_keys($current)))) { //Insert New tag
                $current[$tag] = $result;
                if($attributes_data) $current[$tag. '_attr'] = $attributes_data;
                $repeated_tag_index[$tag.'_'.$level] = 1;

                $current = &$current[$tag];

            } else { //There was another element with the same tag name

                if(isset($current[$tag][0])) {//If there is a 0th element it is already an array
                    $current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result;
                } else {//This section will make the value an array if multiple tags with the same name appear together
                    $current[$tag] = array($current[$tag],$result);//This will combine the existing item and the new item together to make an array

                    if(isset($current[$tag.'_attr'])) { //The attribute of the last(0th) tag must be moved as well
                        $current[$tag]['0_attr'] = $current[$tag.'_attr'];
                        unset($current[$tag.'_attr']);
                    }
                }
                if($attributes_data) $current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data;
                $repeated_tag_index[$tag.'_'.$level]++;
                $last_item_index = $repeated_tag_index[$tag.'_'.$level]-1;
                $current = &$current[$tag][$last_item_index];
            }

        } elseif($type == "complete") { //Tags that ends in 1 line '<tag/>'

            // turn empty array to empty string
            if (is_array($result) && empty($result)) {
                $result = '';
            }

            //See if the key is already taken.
            if(!isset($current[$tag])) { //New Key
                $current[$tag] = $result;
                $repeated_tag_index[$tag.'_'.$level] = 1;
                if($priority == 'tag' and $attributes_data) $current[$tag. '_attr'] = $attributes_data;

            } else { //If taken, put all things inside a list(array)

                if(isset($current[$tag][0]) and is_array($current[$tag])) {//If it is already an array...

                    // ...push the new element into that array.
                    $current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result;

                    if($priority == 'tag' and $get_attributes and $attributes_data) {
                        $current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data;
                    }
                    $repeated_tag_index[$tag.'_'.$level]++;

                } else { //If it is not an array...
                    $current[$tag] = array($current[$tag],$result); //...Make it an array using using the existing value and the new value
                    $repeated_tag_index[$tag.'_'.$level] = 1;
                    if($priority == 'tag' and $get_attributes) {
                        if(isset($current[$tag.'_attr'])) { //The attribute of the last(0th) tag must be moved as well

                            $current[$tag]['0_attr'] = $current[$tag.'_attr'];
                            unset($current[$tag.'_attr']);
                        }

                        if($attributes_data) {
                            $current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data;
                        }
                    }
                    $repeated_tag_index[$tag.'_'.$level]++; //0 and 1 index is already taken
                }
            }

        } elseif($type == 'close') { //End of tag '</tag>'
            $current = &$parent[$level-1];
        }
    }

    return($xml_array);
}


function array_search_key($array,$search, $first_key_only = 1 )
{
        $key = preg_grep('/'.$search.'/', array_keys($array));
        reset($key);
        $first_key = key($key);
        if (isset($first_key)){
            if($first_key_only == 1)
            return($key[$first_key]);

            return($key);
        }

    return false;

}

function array_check($array,$key)
{
    if (is_array ($array))
    {
      return (isset($array[$key]) || array_key_exists($key,$array));
    }
    return (false);
}


function BrowseList($array, $MetaData)
{
    if(!$array) return array();

    //zum testen
    //$MetaData="blablabla";


    //Suche der Result im Array
    //sollte noch verbessert werden
    $key = array_search_key($array, "Envelope$");
    $key2 = array_search_key($array[$key], "Body$");
    $key3 = array_search_key($array[$key][$key2], "BrowseResponse$");
    $key4 = array_search_key($array[$key][$key2][$key3], "Result$");
    $DIDL = $array[$key][$key2][$key3][$key4]["DIDL-Lite"];
    $liste = array();
    $i = 0;

        if(array_check($DIDL,'container'))
        {

        $keys = array_search_key($DIDL['container'],"[0-9]$",0);
            $count = count($keys);
            if ($count==1){
                $i=0;
                $liste[$i]['typ']                       = 'container';
                $liste[$i]['metadata']                  = $MetaData;

                if(isset($DIDL['container_attr']['id']))
                $liste[$i]['id']                        = $DIDL['container_attr']['id'];
                if(isset($DIDL['container_attr']['refID']))
                $liste[$i]['refid']                     = $DIDL['container_attr']['refID'];
                if(isset($DIDL['container_attr']['parentID']))
                $liste[$i]['parentid']                  = $DIDL['container_attr']['parentID'];
                if(isset($DIDL['container_attr']['restricted']))
                $liste[$i]['restricted']                = $DIDL['container_attr']['restricted'];

                $key = array_search_key($DIDL['container'],"artist$");
                if($key)
                $liste[$i]['artist']                    = $DIDL['container'][$key];
                $key = array_search_key($DIDL['container'],"album$");
                if($key)
                $liste[$i]['album']                     = $DIDL['container'][$key];
                $key = array_search_key($DIDL['container'],"title$");
                if($key)
                $liste[$i]['title']                     = $DIDL['container'][$key];
            }
            else
            {
                for ($i=0; $i < $count; $i++)
                {
                    $liste[$i]['typ']                       = 'container';
                    $liste[$i]['metadata']                  = $MetaData;

                    if(isset($DIDL['container'][$i."_attr"]['id']))
                    $liste[$i]['id']                        = $DIDL['container'][$i."_attr"]['id'];
                    if(isset($DIDL['container'][$i."_attr"]['refID']))
                    $liste[$i]['refid']                     = $DIDL['container'][$i."_attr"]['refID'];
                    if(isset($DIDL['container'][$i."_attr"]['parentID']))
                    $liste[$i]['parentid']                  = $DIDL['container'][$i."_attr"]['parentID'];
                    if(isset($DIDL['container'][$i."_attr"]['restricted']))
                    $liste[$i]['restricted']                = $DIDL['container'][$i."_attr"]['restricted'];

                    $key = array_search_key($DIDL['container'][$i],"artist$");
                    if($key)
                    $liste[$i]['artist']                    = $DIDL['container'][$i][$key];
                    $key = array_search_key($DIDL['container'][$i],"album$");
                    if($key)
                    $liste[$i]['album']                     = $DIDL['container'][$i][$key];
                    $key = array_search_key($DIDL['container'][$i],"title$");
                    if($key)
                    $liste[$i]['title']                     = $DIDL['container'][$i][$key];
                }
            }
        }

        if(array_check($DIDL,'item'))
        {
            $keys = array_search_key($DIDL['item'],"[0-9]$",0);
            $count = (count($keys));
            $n = $i;

            if ($count==1){
                $i=0;
                $liste[$n+$i]['typ']                       = 'item';
                $liste[$n+$i]['metadata']                  = $MetaData;

                if(isset($DIDL['item_attr']['id']))
                $liste[$n+$i]['id']                        = $DIDL['item_attr']['id'];
                if(isset($DIDL['item_attr']['refID']))
                $liste[$n+$i]['refid']                     = $DIDL['item_attr']['refID'];
                if(isset($DIDL['item_attr']['parentID']))
                $liste[$n+$i]['parentid']                  = $DIDL['item_attr']['parentID'];
                if(isset($DIDL['item_attr']['restricted']))
                $liste[$n+$i]['restricted']                = $DIDL['item_attr']['restricted'];

                $key = array_search_key($DIDL['item'],"artist$");
                if($key){
                    if(array_check($DIDL['item'][$key],'0'))
                    $liste[$n+$i]['artist']                    = $DIDL['item'][$key]['0'];
                    else
                    $liste[$n+$i]['artist']                    = $DIDL['item'][$key];
                }

                $key = array_search_key($DIDL['item'],"album$");
                if($key)
                $liste[$n+$i]['album']                     = $DIDL['item'][$key];
                $key = array_search_key($DIDL['item'],"title$");
                if($key)
                $liste[$n+$i]['title']                     = $DIDL['item'][$key];


                 if(array_check($DIDL['item']['res'],'0')){
                    //kann noch verbessert werden, da mehrere Recourcen zur Verfügung stehen
                     $liste[$n+$i]['resource']                  = $DIDL['item']['res']['0'];
                    if(isset($DIDL['item']['res']['0_attr']['duration']))
                    $liste[$n+$i]['duration']                  = $DIDL['item']['res']['0_attr']['duration'];
                    if(isset($DIDL['item']['res']['0_attr']['size']))
                    $liste[$n+$i]['size']                      = $DIDL['item']['res']['0_attr']['size'];
                    if(isset($DIDL['item']['res']['0_attr']['bitrate']))
                    $liste[$n+$i]['bitrate']                   = $DIDL['item']['res']['0_attr']['bitrate'];
                 }
                 else {
                         if(array_check($DIDL['item'],'res')){
                           $liste[$n+$i]['resource']                  = $DIDL['item']['res'];
                             if(isset($DIDL['item']['res_attr']['duration']))
                             $liste[$n+$i]['duration']                  = $DIDL['item']['res_attr']['duration'];
                             if(isset($DIDL['item']['res_attr']['size']))
                             $liste[$n+$i]['size']                      = $DIDL['item']['res_attr']['size'];
                             if(isset($DIDL['item']['res_attr']['bitrate']))
                             $liste[$n+$i]['bitrate']                   = $DIDL['item']['res_attr']['bitrate'];
                          }
                 }


                $key = array_search_key($DIDL['item'],"albumArtURI$");
                if($key)
                $liste[$n+$i]['albumArtURI']               = $DIDL['item'][$key];

                $key = array_search_key($DIDL['item'],"genre$");
                if($key)
                $liste[$n+$i]['genre']                     = $DIDL['item'][$key];

                $key = array_search_key($DIDL['item'],"date$");
                if($key)
                $liste[$n+$i]['date']                      = $DIDL['item'][$key];

                $key = array_search_key($DIDL['item'],"originalTrackNumber$");
                if($key)
                $liste[$n+$i]['originalTrackNumber']       = $DIDL['item'][$key];

                $key = array_search_key($DIDL['item'],"class$");
                if($key)
                $liste[$n+$i]['class']                     = $DIDL['item'][$key];

            }
            else
            {
                for ($i=0; $i < $count; $i++)
                {
                    $liste[$n+$i]['typ']                       = 'item';
                    $liste[$n+$i]['metadata']                  = $MetaData;

                    if(isset($DIDL['item'][$i.'_attr']['id']))
                    $liste[$n+$i]['id']                        = $DIDL['item'][$i.'_attr']['id'];
                    if(isset($DIDL['item'][$i.'_attr']['refID']))
                    $liste[$n+$i]['refid']                     = $DIDL['item'][$i.'_attr']['refID'];
                    if(isset($DIDL['item'][$i.'_attr']['parentID']))
                    $liste[$n+$i]['parentid']                  = $DIDL['item'][$i.'_attr']['parentID'];
                    if(isset($DIDL['item'][$i.'_attr']['restricted']))
                    $liste[$n+$i]['restricted']                = $DIDL['item'][$i.'_attr']['restricted'];

                    $key = array_search_key($DIDL['item'][$i],"artist$");
                        if($key){
                        if(array_check($DIDL['item'][$i][$key],'0'))
                        $liste[$n+$i]['artist']                    = $DIDL['item'][$i][$key]['0'];
                        else
                        $liste[$n+$i]['artist']                    = $DIDL['item'][$i][$key];
                    }
                    $key = array_search_key($DIDL['item'][$i],"album$");
                    if($key)
                    $liste[$n+$i]['album']                     = $DIDL['item'][$i][$key];
                    $key = array_search_key($DIDL['item'][$i],"title$");
                    if($key)
                    $liste[$n+$i]['title']                     = $DIDL['item'][$i][$key];

                     if(array_check($DIDL['item'][$i]['res'],'0')){
                        //kann noch verbessert werden, da mehrere Recourcen zur Verfügung stehen
                         $liste[$n+$i]['resource']                  = $DIDL['item'][$i]['res']['0'];
                        if(isset($DIDL['item'][$i]['res']['0_attr']['duration']))
                        $liste[$n+$i]['duration']                  = $DIDL['item'][$i]['res']['0_attr']['duration'];
                        if(isset($DIDL['item'][$i]['res']['0_attr']['size']))
                        $liste[$n+$i]['size']                      = $DIDL['item'][$i]['res']['0_attr']['size'];
                        if(isset($DIDL['item'][$i]['res']['0_attr']['bitrate']))
                        $liste[$n+$i]['bitrate']                   = $DIDL['item'][$i]['res']['0_attr']['bitrate'];
                     }
                     else {
                             if(array_check($DIDL['item'][$i],'res')){
                               $liste[$n+$i]['resource']                  = $DIDL['item'][$i]['res'];
                                 if(isset($DIDL['item'][$i]['res_attr']['duration']))
                                 $liste[$n+$i]['duration']                  = $DIDL['item'][$i]['res_attr']['duration'];
                                 if(isset($DIDL['item'][$i]['res_attr']['size']))
                                 $liste[$n+$i]['size']                      = $DIDL['item'][$i]['res_attr']['size'];
                                 if(isset($DIDL['item'][$i]['res_attr']['bitrate']))
                                 $liste[$n+$i]['bitrate']                   = $DIDL['item'][$i]['res_attr']['bitrate'];
                              }
                     }

                    $key = array_search_key($DIDL['item'][$i],"albumArtURI$");
                    if($key)
                    $liste[$n+$i]['albumArtURI']               = $DIDL['item'][$i][$key];

                    $key = array_search_key($DIDL['item'][$i],"genre$");
                    if($key)
                    $liste[$n+$i]['genre']                     = $DIDL['item'][$i][$key];

                    $key = array_search_key($DIDL['item'][$i],"date$");
                    if($key)
                    $liste[$n+$i]['date']                      = $DIDL['item'][$i][$key];

                    $key = array_search_key($DIDL['item'][$i],"originalTrackNumber$");
                    if($key)
                    $liste[$n+$i]['originalTrackNumber']       = $DIDL['item'][$i][$key];

                    $key = array_search_key($DIDL['item'][$i],"class$");
                    if($key)
                    $liste[$n+$i]['class']                     = $DIDL['item'][$i][$key];
                }

            }
        }
         return ($liste);
}

?>

Was wir dazu noch brauchen:

das Array sollte immer die gleiche Struktur (Anzahl der Keys) haben, da der Zugriff später teils so als Entscheidungsbaum geschieht:

if (($liste[$i]['artist']) == "leer")

Wenn also eine Information nicht vorhanden ist sollte hier z.B. [Artist] → „leer“ im Array stehen.

Ich habe endlich auch die Lösung für das xpath-Problem :smiley:

$MetaData = simplexml_load_string($xml);
$MetaData = $MetaData->xpath("//Result");
$MetaData = (string) $MetaData[0];

Kennt aber jemand einen Ersatz für http_chunked_decode($string), da ja die php_http - Extension offenbar nicht mehr erhältlich ist ab PHP 5.4 ?

Nötig wäre das für Server, welche ihre Daten chunked übertragen wie die Fritzbox (siehe auch Post #7 von fschut2001, als ich über die Zeichenketten dazwischen ins Grübeln kam). Soweit ich rechrchieren konnte, gibt es Server, die die Antwort als einen String übertragen, aber auch andere, die aufgrund einer problematischen Größe die Antwort gleich zerteilt (zu erkennen an: Transfer-Encoding: chunked senden. Die Länge der einzelnen Strings wird dann Zeile für Zeile mitgegeben. Gedacht hatte ich schon an ein „Herausschneiden“ anhand der Zeilenumbrüche.
An diesen Strings beißt sich dann SimpleXML natürlich die Zähne aus. Deshalb habe ich auch zunächst den Explode-Weg gewählt um dieses Problem zu umgehen. Gut wäre aber ein Funktion die das ebenfalls macht, wie laut Recherche http_chunked_decode. Ich habe mir aber die Zähne ausgebissen diese php_http Extension zum Laufen zu bringen.

Gruß

André

Moin Digihouse,

gut das es schon mal mit dem Script soweit funktioniert.
Das mit den leeren Variablen werde ich noch ändern.

Die Funktion http_chunked_decode() funktioniert auch unter php 5.4,
aber sie ist kein Bestandteil von php selbst sondern von PECL und die DLL muss man selbst kompelieren.
Habe [b]hier [/b]ein paar Infos gefunden.

MFG MNB

Hallo mnb,

das Thema chunked_decode hat sich wahrscheinlich erledigt, da ich durch Zufall gelesen habe, dass statt HTTP/1.1 in der Browserabfrage ein HTTP/1.0 das erwünschte Ergebnis ohne Chunkes liefert !!! Tricky !!! Bis jetzt reibungslos auch für Fritzbox.

Falls sich doch Probleme ergeben nehmen wir alternativ die function decode_chunked aus Deinem Link.

Schau Dir auch mal Folgendes an:

function ContentDirectory_Browse ($Kernel, $ServerContentDirectory, $ServerIP, $ServerPort, $ObjectID, $BrowseFlag, $Filter, $StartingIndex, $RequestedCount, $SortCriteria)
{
//Preloader---------------------------------------------------------------------
$Preloader = "
<body>

<div>
	<img src=\"../image/Smiley_normal_100x100.gif\"/>
	<p><span style=\"color:white; font-size:100%; position:absolute; top:50px; left:150px; text-decoration:blink; font-family:Arial,sans-serif;\"><b>Ich suche ...</b></span></p>
</div>

</body>
";

//partielle Website erstellen---------------------------------------------------
$handle = fopen($Kernel."webfront/user/Multimedia/Browse/Browse.html", "w");
fwrite($handle, $Preloader);
fclose($handle);

//iFrame auffrischen------------------------------------------------------------
SetValue(UPNP_Browse_Webfront_iframe_Browse, '<iframe src="../user/Multimedia/Browse/Browse.html" frameborder="no" scrolling="no"</iframe>');

//iFrame auffrischen------------------------------------------------------------
SetValue(UPNP_Browse_Webfront_iframe_Browse_und_Verlauf, '<iframe src="../user/Multimedia/Browse/Browse_und_Verlauf.html" width="800" height="350" frameborder="no" scrolling="yes"></iframe>');

/*//////////////////////////////////////////////////////////////////////////////
17.08.2014 HTTP/1.0 implementiert um die Rückgabe von chunked Responses zu vermeiden !
/*//////////////////////////////////////////////////////////////////////////////

$header='POST '.$ServerContentDirectory.' HTTP/1.0
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);

	if (!$fp)
		{
    	echo "$errstr ($errno)<br />
";
		die;
		}
	else
		{
		fputs ($fp, $content_ContentDirectory_Browse);

				stream_set_timeout($fp, 60);

				$buffer = stream_get_contents($fp, -1);
				
				$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);
		}
	SetValue(33314 /*[Multimedia\Browse\Return\Message]*/, $message);
	
/*XML per XPATH auslesen und <Result>, <NumberReturned>, <TotalMatches> und 
<UpdateID> zum Weiterverarbeiten extrahieren*/

$xml = simplexml_load_string($message);

$Result = $xml->xpath("////Result");
$Result = (string) $Result[0];
//echo("
Result:$Result");

$NumberReturned = $xml->xpath("////NumberReturned");
$NumberReturned = (string) $NumberReturned[0];
//echo("
NumberReturned:$NumberReturned");

$TotalMatches = $xml->xpath("////TotalMatches");
$TotalMatches = (string) $TotalMatches[0];
//echo("
TotalMatches:$TotalMatches");

$UpdateID = $xml->xpath("////UpdateID");
$UpdateID = (string) $UpdateID[0];
//echo("
UpdateID:$UpdateID");

return array($message, $Result, $NumberReturned, $TotalMatches, $UpdateID);
}

Dabei insbesondere letzterer Teil, der mir per XPath nun brav die Variablen in einem Array liefert. Die werden sogar schon ohne Sonderzeichen übergeben, so dass man es direkt weiterverarbeiten kann.
Da waren die Kollegen von PHP.de beteiligt, da ich bisher dachte, dass ich per XPath nur über bekannte Nodes springen kann …

Ich habe die Function_BrowseList momentan so angepasst:

function BrowseList($Result)
{

$xml = simplexml_load_string($Result);

//print_r ($xml);

$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";
		print_r ($liste[$i]['typ']);
		}
	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']=utf8_decode((string)$interpret[0]);
		}
	else
		{
		$liste[$i]['artist']="leer";
		}

if($aktrow->xpath("upnp:album"))
		{
		$album = $aktrow->xpath("upnp:album");
		$liste[$i]['album']=utf8_decode((string)$album[0]);
		}
	else
		{
		$liste[$i]['album']="leer";
		}

if($aktrow->xpath("dc:title"))//eigentlich immer vorhanden
		{
		$titel = $aktrow->xpath("dc:title");
		$liste[$i]['title']=utf8_decode((string)$titel[0]);
		}
	else
		{
		$liste[$i]['title']="leer";
		}

if($aktrow->xpath("upnp:res") && is_array($aktrow->xpath("upnp:res")))
	{
	//echo ("Array !");
	//print_r($aktrow->xpath("upnp:res"));
	$res = $aktrow->xpath("upnp:res");
	$liste[$i]['resource'] = (string)$res[0];
	$resattr = $res[0];
	}
elseif($aktrow->xpath("upnp:res") && is_string($aktrow->xpath("upnp:res")))
	{
	//echo ("String !");
	//print_r($aktrow->xpath("upnp:res"));
	$res = $aktrow->xpath("upnp:res");
	$liste[$i]['resource'] = (string)$aktrow->xpath("upnp:res");
	$resattr = $res;
	}
else
	{
	$liste[$i]['resource'] = "leer";
	}

	//Attribute auslesen------------------------------------------------------------

	if(isset($resattr['duration']))
		{
		$liste[$i]['duration']=(string)$resattr['duration'];
		}
		else
			{
			$liste[$i]['duration']="leer";
			}

	if(isset($resattr['size']))
		{
		$liste[$i]['size']=(string)$resattr['size'];
		}
		else
			{
			$liste[$i]['size']="leer";
			}

	if(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']=utf8_decode((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";
		}
 }

return ($liste);
}

Ansonsten habe ich die Buttons größtenteils Chrome-tauglich gemacht (statt Hintergrundimages auf denen die Albumarts lagen CSS-gestylte Buttons) und meinem WF einen Darkskin verpasst :slight_smile:

Gruß

André