UPNP/DLNA for IPS: new version

Hallo Gemeinde,

… sooooooooooooo. Nach langem Bugs suchen, nochmal suchen und finden sowie einigen Umstellungen habe ich jetzt eine Version meines Control Points die ich auch auf einem Zweit- und Drittrechner ohne große Zicken installieren konnte :smiley:

Dies gelang nur mit Hilfe von Raketenschnecke, mit welchem ich die letzten Tage viel kommunizierte, da er den Project-Exporter schrieb, den ich zum Export verwende (Danke für die Hilfe ! und: Super-Tool !)

Hier ist es und das in nur einem Installationsfile (how to siehe unten)
Es legt sowohl den ganzen Objektbaum unter Multimedia an, als auch das Webfront-Verzeichnis Multimedia.

Multimedia 2013-10-23.zip (319 KB)

Vorab: es ist ein Entwicklungsschritt und keinesfalls fertig ! Einige Grundlagen habe ich bereits in http://www.ip-symcon.de/forum/threads/22187-UPNP-DLNA-for-IPS-basics-and-first-how-to beschrieben. Seit dem hat sich Einiges getan. Unter anderem habe ich viele Details geändert und auch die Hauptroutinen auf den Server verlagert. Video und Radio funktionieren jetzt auch sowie eine rudimentäre Playlisterstellung.

Kerngedanke ist nach wie vor:

… einen UPNP/DLNA Control Point auf einem Server zu haben, der ehedem 24/7 läuft und mir ein Web-basiertes Frontend zur Verfügung stellt, auf das ich mit meinen Tablets oder Smartphone sozusagen als Fernsteuerung zugreifen kann.

Was ich zur Verfügung stelle sind genau genommen 2 Versionen (die unterscheiden sich nur in der Vorselektion der Anzeige im WFC – siehe Punkt 5). Die erste Version als Basis (nur die iframes), die zweite Version mit einem Accordeon-Menu (auf IE getestet bei anderen Browsern kann die senkrechte Schrift fehlen)

Vorraussetzung ist natürlich ein UPNP-Server. Lauffähig und getestet sind:

[ul]
[li]Twonky (Audio, Video, Foto)
[/li][li]WMP (Audio, Video, Foto)
[/li][li]Asset-UPNP (Audio)
[/li][/ul]

Da UPNP ein universeller Ansatz ist schickt mir der Control Point sowohl Audio als auch Video und Foto quer durch`s Haus ! Optimiert ist das Ganze eigentlich für Touchscreen.

Vieles ist zugegebenermaßen noch etwas hakelig, aber dieses Projekt soll Euch zeigen, dass UPNP/DLNA auf IPS lauffähig ist. Änderungen und Entwicklungen und natürlich (konstruktive) Kritik sind ausdrücklich erwünscht. Ich bitte Euch nur bei Änderungen/Verbesserungen in der Kopfzeile eine neue Versionsnummer und Datum zu vergeben, damit wir differenzieren können. z.B.

//------------------------------------------------------------------------------
//UPNP_Browse_Functions.ips.php------------------------2013 von André Liebmann--
//UPNP_Browse_Functions_V2.1----------------------------------------------------
//16.10.2013--------------------------------------------------------------------
//------------------------------------------------------------------------------

Erfolgreich getestet habe ich bisher:

Das Portieren per Installationsscript auf 3 weitere Rechner

Server:

[ul]
[li]Twonky
[/li][li]Asset UPNP
[/li][li]Sony Media Library
[/li][li]Cyberlink
[/li][/ul]

Renderer:

[ul]
[li]alle meine Sony Devices (STR-DN2010,STR-DA5800ES, SA-NS400, SA-NS410, SA-NS300, SA-NS310)
[/li][li]LG TV (LM660S)
[/li][li]PowerDVD (weiteres Notebook)
[/li][li]Sony Bravia V5800
[/li][/ul]

Ich habe wieder versucht, die umfangreichen Scripte und Variablen per Raketenschneckes ProjectExporter für Euch zusammenzustellen. Ein per Hand erstellen scheidet aus, da das zu umfangreich wäre.

Kurzes how to:

  1. Ein Installationsscript im Root des Objektbaumes anlegen und Inhalt der Multimedia.php (als zip beiliegend - siehe oben) hineinkopieren und die WFC_TargetID entsprechend Eures WFC anpassen

  1. Ausführen – der Objektbaum sollte dann so aussehen:

  1. IP/Port des IPS-Servers in die UPNP_Constants.ips.php eintragen

04 IP in Constants.jpg

  1. Fehlermeldung der Installation betreffen inaktive Ereignisse:

  1. Also diese Ereignisse aktivieren (ggf. andere Zeiten wählen)

  1. UPNP_Initialize ausführen (versteckt in Config) und ggf. Devices/Server nochmal im WF aktualisieren. Die Devices und Server sollten automatisch erkannt werden!!! Das war ursprünglich ein casus knacktus, da ich alles händisch konfigurieren musste

  1. Es kann sein, dass man im WFC zwischen den beiden Konfigurationen einmal hin und her schalten müsst (unter item 1716 jeweils die andere Position 0 aktivieren) – bei meinen Installationen war das fast immer so, den Hintergrund habe ich noch nicht herausgefunden.

Noch die Bedienung (Version ohne Accordeon):

Lasst Euch nicht vom Umfang des Projektes abschrecken! Das war eine Mammutaufgabe von den ersten Schritten einen Ton aus meinen Netwerklautsprechern zu bekommen, über die Funktionsweisen (WireShark und die INTEL UPNP Developer Tools lassen grüßen) bis zur heutigen Script-Sammlung. Der sprichwörtliche Motor ist die UPNP_Functions (aktuell V2.5). Alles andere ist nur Beiwerk.

Ich schicke damit nicht nur Musik sondern auch Videos durch das Haus :smiley: Ich bin unheimlich gespannt, ob es auch bei Euch funzt …
Rückmeldungen, Fragen, Bug-Reports und vorallem Weiterentwicklungen sind ausdrücklich erwünscht !

Wenn ich Rückmeldungen bekomme kann ich in einem how to auf die einzelnen Scripte und Funktionsweisen eingehen. Vielleicht kann auch jemand Scripts verbessern (ich bin Laie aber lernfähig :slight_smile: ), aber das habe ich ja schon mehrfach gefragt.

Testen kann man die UPNP_Functions z.B. mit

<?

//------------------------------------------------------------------------------
//UPNP_Test
//------------------------------------------------------------------------------

include ("UPNP_Functions_V2.5.ips.php");

//IPAdresse und Port des Device

$DeviceIP = ""; //Device:IP z.B. 192.168.1.100
$DevicePort = ""; //Device:Port z.B. 8080
$controlURL = ""; //z.B. Sony: "/AVTransport/ctrl" oder LG: "/upnp/control/AVTransport1"

//Variablen definieren----------------------------------------------------------


$file = ""; //gültiges vom Netz erreichbares File (z.B. von LINN Kinsky auslesen) z.B. 'http://192.168.178.64:9000/disk/DLNA-PNMP3-OP01-FLAGS01700000/O0$1$8I204301.mp3'
$MetaData = ""; //ggf. DIDL, wenn eruierbar

SetAVTransportURI($controlURL, $DeviceIP, $DevicePort, $file, $MetaData);

Play_AV($controlURL, $DeviceIP, $DevicePort);

?>

Viele Grüße

André

… nur Ergänzung zu Install Punkt 7

Das hier ist gemeint:

Zwischen den Konfigurationen 0 (item 5257 und item 6438) wechseln.

Viele Grüße

André

Servus Andre

du Armer, da machst du dir so eine Mühe mit dem reisen haufen Script, und dann gibts kein Feedback.

Ich persönlich verwende zwar Twonky & BubbleUpnP habe aber dein Ding grad mal ausprobiert.

  1. Installation lief astrein, kein Problem oder Fehlermeldung

  2. Configuration nach deiner Anleitung auch -> vieleicht solltets aber erwähnen wo man die UPNP_Constants.ips.php findet. Hab mir einen Wolf gesucht.

  3. Meine Clients und Servers wurden alle gefunden. zzgl. zu den von dir getesteten sind das BubbleUpnp (Android), ein Samsung TV und der Windows Mediaplayer und XBMC. In der Doku solltest noch erwähnen das die Suche lange dauert, dachte erst alles abgestürzt.

  4. Was sehr nervt: Diese komische Accordeonauswahl springt immer auf die erste Seite, man kann quasi gar nicht durch den Mediaordner browsen.

  5. unter IE lief es zumindest mal rudimentär, unter Chrome geht aber mehr oder weniger gar nix. Hängt total und andauernd die Sanduhr.

  6. Übers Benutzerinterace kann man streiten. Ehrlich gesagt mein Geschmack ist das nicht.
    Viel zu große Buttons und totale Platzverschwendung. Da könntest schon noch etwas nachlegen.

Aller Voraussicht nach werde ich bei meiner Lösung bleiben. Möchte dir aber trotzdem zu diesem Kraftakt trotzdem gratulieren. Da müssen ja hunderte Stunden Aufwand drinstecken.

schöne Grüße
bb

… tja trotzdem danke fürs feedback :smiley:

Für mich läuft es schon annàhernd so wie ich wollte. Dachte nur dass es für viele zu undurchsichtig ist. Also nix mit Armer.
Wäre nur schön, wenn man noch zusammen daran feilen kann. Entsprechend der Klicks besteht ja Interesse.

Zum Frontend: nimm die 2. Variante ! (Im WFC den Haken an die 2. Konfiguration) Ist flüssiger …
Optik oder anpassen standen nicht im Vordergrund. Es kann ja auch jeder mal selbst anpacken!

UPNP auf IPS geht :slight_smile: - das ist die Grundaussage !

Wie gesagt kein fertiges Programm sondern Basics will ich vermitteln.

Viele Grüße

André

Ok verstehe.
Da du ein Webfront mitlieferst dachte ich es soll etwas endgültiges sein.

Ich selbst versuche in IPS wenn möglich nur Code zu verwenden den ich selbst geschrieben habe oder zumindest weitestgehend verstehe.
Dein UpNp ist mir von daher auch etwas zu heavy und komplex. Hab darum übrigens auch keine Library oder so (bis auf den Logger) im Einsatz.

Was mich aber sehr interessieren würde wäre Script gesteuertes Start/Stop von Renderern.

Ist deine Scriptsammlung dazu tauglich ? Gibt es sowas ähnliches wie starteplayer(„Wohnzimmer“); oder stopPlayer(„Wohnzimmer“);

Edit: Schon gefunden. Der Teil gefällt mir. Seht vom WrapperScript her vielversprechend aus.
Da werd ich morgen mal damit rumspielen.

gruß
bb

OK. Der Motor ist die UPNP_Functions_V2.5.ips.php alles andere ist nur Chassis. Frag, wenn Du nicht weiterkommst.

Wichtig ist aus der Device-Description unter Services die richtige ControlURL herauszufinden.
Hier ein Sony-Netzwerklautsprecher (z.B. http://192.168.178.154:8080/description.xml): da ist unter anderem zu finden


<service>
 <serviceType>urn:schemas-upnp-org:service:AVTransport:1</serviceType>
 <serviceId>urn:upnp-org:serviceId:AVTransport</serviceId>
 <SCPDURL>/AVTransport/desc.xml</SCPDURL>
 <controlURL>/AVTransport/ctrl</controlURL>
 <eventSubURL>/AVTransport/evt</eventSubURL>
</service>

also: „/AVTransport/ctrl“

In der UPNP_Functions enthalten:

//------------------------------------------------------------------------------
//UPNP_Functions_V2.5.ips.php--------------------------2013 von André Liebmann--
//------------------------------------------------------------------------------
//PHP Function-Skript aller HTTP-Post´s zur Steuerung von UPNP-Geräten:---------
//HTTP-Posts nach "urn:schemas-upnp-org:service:AVTransport:1"------------------
//HTTP-Posts nach "urn:schemas-upnp-org:service:RenderingControl:1"-------------
//HTTP-Posts nach "urn:schemas-sony-com:service:Party:1"------------------------
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
//imlementierte functions:------------------------------------------------------
//------------------------------------------------------------------------------
//function SetAVTransportURI($controlURL, $DeviceIP, $DevicePort, $file, $MetaData)
//-----------------IN:  $file (CurrentURI)
//-----------------IN:  $MetaData (CurrentURIMetaData)
//function SetNextAVTransportURI($controlURL, $DeviceIP, $DevicePort, $file_next, $MetaData_next)
//-----------------IN:  $file_next (NextURI)
//-----------------IN:  $MetaData_next (NextURIMetaData)
//------------------------------------------------------------------------------
//function Play_AV($controlURL, $DeviceIP, $DevicePort)
//function Stop_AV($controlURL, $DeviceIP, $DevicePort)
//function Pause_AV($controlURL, $DeviceIP, $DevicePort)
//function Next_AV($controlURL, $DeviceIP, $DevicePort) 			--> Funktion Next() in PHP vorhanden !!!
//function Previous_AV($controlURL, $DeviceIP, $DevicePort)
//function Seek_AV($controlURL, $DeviceIP, $DevicePort, $position)
//function Rewind_AV($controlURL, $DeviceIP, $DevicePort)			--> Funktion Rewind() in PHP vorhanden !!!
//function Playmode_Normal($controlURL, $DeviceIP, $DevicePort)
//function Playmode_Random($controlURL, $DeviceIP, $DevicePort)
//function Playmode_Repeat_One($controlURL, $DeviceIP, $DevicePort)
//function Playmode_Repeat_All($controlURL, $DeviceIP, $DevicePort)
//------------------------------------------------------------------------------
//function SetVolume($renderingcontrolURL, $DeviceIP, $DevicePort, $DesiredVolume)
//-----------------IN:  $DesiredVolume
//function GetVolume($renderingcontrolURL, $DeviceIP, $DevicePort)
//-----------------OUT: $CurrentVolume
//function SetMute($renderingcontrolURL, $DeviceIP, $DevicePort, $DesiredMute)
//-----------------IN:  $DesiredMute
//function GetMute($renderingcontrolURL, $DeviceIP, $DevicePort)
//-----------------OUT: $CurrentMute
//function GetDeviceCapabilities($controlURL, $DeviceIP, $DevicePort)
//-----------------OUT: $PlayMedia
//-----------------OUT: $RecMedia
//-----------------OUT: $RecQualityModes
//function GetMediaInfo($controlURL, $DeviceIP, $DevicePort)
//-----------------OUT: $NrTracks
//-----------------OUT: $MediaDuration
//-----------------OUT: $CurrentURI
//-----------------OUT: $CurrentURIMetaData
//-----------------OUT: $NextURI
//-----------------OUT: $NextURIMetaData
//-----------------OUT: $PlayMedium
//-----------------OUT: $RecordMedium
//-----------------OUT: $WriteStatus
//function GetTransportInfo($controlURL, $DeviceIP, $DevicePort)
//-----------------OUT: $CurrentTransportState
//-----------------OUT: $CurrentTransportStatus
//-----------------OUT: $CurrentSpeed
//function GetTransportSettings($controlURL, $DeviceIP, $DevicePort)
//-----------------OUT: $PlayMode
//-----------------OUT: $RecQualityMode
//function GetCurrentTransportActions($controlURL, $DeviceIP, $DevicePort)
//-----------------OUT: $Actions
//function GetPositionInfo($controlURL, $DeviceIP, $DevicePort)
//-----------------OUT: $Track
//-----------------OUT: $TrackDuration
//-----------------OUT: $TrackMetaData
//-----------------OUT: $TrackURI
//-----------------OUT: $RelTime
//-----------------OUT: $AbsTime
//-----------------OUT: $RelCount
//-----------------OUT: $AbsCount
//------------------------------------------------------------------------------
//function Party_X_GetState($DeviceIP, $DevicePort)
//-----------------OUT: $PartyState
//-----------------OUT: $PartyMode
//-----------------OUT: $PartySong
//-----------------OUT: $SessionID
//-----------------OUT: $NumberOfListeners
//-----------------OUT: $ListenerList
//-----------------OUT: $SingerUUID
//-----------------OUT: $SingerSessionID
//function Party_X_Start($DeviceIP, $DevicePort, $PartyMode, $ListenerList)
//-----------------IN:  $PartyMode
//-----------------IN:  $ListenerList     --> Auswahl der Geräte: UUID´s der Listener
//-----------------OUT: $SingerSessionID  --> essentiell für X_Entry / X_Abort
//function Party_X_Entry($DeviceIP, $DevicePort, $SingerSessionID, $ListenerList)
//-----------------IN:  $SingerSessionID  --> aus X-Start: SingerSessionID
//-----------------IN:  $ListenerList     --> aus X-Start: UUID´s der Listener
//function Party_X_Abort($DeviceIP, $DevicePort, $SingerSessionID)
//-----------------IN:  $SingerSessionID  --> aus X-Start: SingerSessionID
//function Party_X_Leave($DeviceIP, $DevicePort, $SingerSessionID, $ListenerList)
//-----------------IN:  $SingerSessionID  --> aus X-Start: UUID´s der Listener
//-----------------IN:  $ListenerList
//------------------------------------------------------------------------------
//function send($controlURL, $DeviceIP, $DevicePort, $content)
//-----------------OUT: $return (aus stream_get_contents)
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
//Variablen:...............X --> erforderlich
//.........................O --> anzulegen, wenn benötigt
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//zu übergebende Variablen------------------------------------------------------
//------------------------------------------------------------------------------
//$address.................X --> IP des Gerätes ("XXX.XXX.XXX.XXX")
//$port....................X --> Port des UPNP-Service (i.d.R. "8080")
//$file....................X --> Pfad zum MP3 etc.
//$MetaData................O --> MetaData des Files (kann leer bleiben)
//$file_next...............O --> Pfad zum nächsten MP3 etc.
//$MetaData_next...........O --> MetaData des nächsten Files (kann leer bleiben)
//$DesiredVolume...........X --> gewünschte Lautstärke an function SetVolume() übergeben
//$DesiredMute.............X --> gewünschtes Mute an function SetMute() übergeben
//$Target..................O --> für Rewind_AV()
//$Position................O --> für Seek_AV()
//------------------------------------------------------------------------------
//Statusvariablen---------------------------------------------------------------
//------------------------------------------------------------------------------
//$CurrentVolume...........X --> SetValue(49348 /*[Multimedia\Variablen\CurrentVolume]*/, $CurrentVolume);
//$CurrentMute.............X --> SetValue(35681 /*[Multimedia\Variablen\CurrentMute]*/, $CurrentMute);
//GetDeviceCapabilities---------------------------------------------------------
//$PlayMedia...............O --> SetValue(41033 /*[Multimedia\Variablen\GetDeviceCapabilities\PlayMedia]*/, $PlayMedia);
//$RecMedia................O --> SetValue(20844 /*[Multimedia\Variablen\GetDeviceCapabilities\RecMedia]*/, $RecMedia);
//$RecQualityModes.........O --> SetValue(37254 /*[Multimedia\Variablen\GetDeviceCapabilities\RecQualityModes]*/, $RecQualityModes);
//GetMediaInfo------------------------------------------------------------------
//$NrTracks................O --> SetValue(25573 /*[Multimedia\Variablen\GetMediaInfo\NrTracks]*/, $CurrentTransportState);
//$MediaDuration...........O --> SetValue(15324 /*[Multimedia\Variablen\GetMediaInfo\MediaDuration]*/, $CurrentTransportState);
//$CurrentURI..............O --> SetValue(49130 /*[Multimedia\Variablen\GetMediaInfo\CurrentURI]*/, $CurrentTransportState);
//$CurrentURIMetaData......O --> SetValue(28566 /*[Multimedia\Variablen\GetMediaInfo\CurrentURIMetaData]*/, $CurrentTransportState);
//$NextURI.................O --> SetValue(28865 /*[Multimedia\Variablen\GetMediaInfo\NextURI]*/, $CurrentTransportState);
//$NextURIMetaData.........O --> SetValue(39683 /*[Multimedia\Variablen\GetMediaInfo\NextURIMetaData]*/, $CurrentTransportState);
//$PlayMedium..............O --> SetValue(43433 /*[Multimedia\Variablen\GetMediaInfo\PlayMedium]*/, $CurrentTransportState);
//$RecordMedium............O --> SetValue(44923 /*[Multimedia\Variablen\GetMediaInfo\RecordMedium]*/, $CurrentTransportState);
//$WriteStatus.............O --> SetValue(14394 /*[Multimedia\Variablen\GetMediaInfo\WriteStatus]*/, $CurrentTransportState);
//GetTransportInfo--------------------------------------------------------------
//$CurrentTransportState...O --> SetValue(28600 /*[Multimedia\Variablen\GetTransportInfo\CurrentTransportState]*/, $CurrentTransportState);
//$CurrentTransportStatus..O --> SetValue(38643 /*[Multimedia\Variablen\GetTransportInfo\CurrentTransportStatus]*/, $CurrentTransportStatus);
//$CurrentSpeed............O --> SetValue(28539 /*[Multimedia\Variablen\GetTransportInfo\CurrentSpeed]*/, $CurrentSpeed);
//GetTransportSettings----------------------------------------------------------
//$PlayMode................O --> SetValue(11327 /*[Multimedia\Variablen\GetTransportSettings\PlayMode]*/, $PlayMode);
//$RecQualityMode..........O --> SetValue(22324 /*[Multimedia\Variablen\GetTransportSettings\RecQualityMode]*/, $RecQualityMode);
//GetCurrentTransportActions----------------------------------------------------
//$Actions.................O --> SetValue(34397 /*[Multimedia\Variablen\GetCurrentTransportActions\Actions]*/, $Actions);
//GetPositionInfo---------------------------------------------------------------
//$Track...................O --> Setvalue(37167 /*[Multimedia\Variablen\GetPositionInfo\Track]*/, $Track);
//$TrackDuration...........O --> SetValue(19680 /*[Multimedia\Variablen\GetPositionInfo\TrackDuration]*/, $TrackDuration);
//$TrackMetaData...........O --> SetValue(41870 /*[Multimedia\Variablen\GetPositionInfo\TrackMetaData]*/, $TrackMetaData);
//$TrackURI................O --> SetValue(52714 /*[Multimedia\Variablen\GetPositionInfo\TrackURI]*/, $TrackURI);
//$RelTime.................O --> SetValue(13956 /*[Multimedia\Variablen\GetPositionInfo\RelTime]*/, $RelTime);
//$AbsTime.................O --> SetValue(35614 /*[Multimedia\Variablen\GetPositionInfo\AbsTime]*/, $AbsTime);
//$RelCount................O --> SetValue(57388 /*[Multimedia\Variablen\GetPositionInfo\RelCount]*/, $RelCount);
//$AbsCount................O --> SetValue(26780 /*[Multimedia\Variablen\GetPositionInfo\AbsCount]*/, $AbsCount);
//Party_Mode Sony---------------------------------------------------------------
//$PartyState..............O --> Setvalue(15268 /*[Multimedia\Variablen\Party_Mode\PartyState]*/, $PartyState);
//$PartyMode...............O --> SetValue(53869 /*[Multimedia\Variablen\Party_Mode\PartyMode]*/, $PartyMode);
//$PartySong...............O --> Setvalue(23773 /*[Multimedia\Variablen\Party_Mode\PartySong]*/, $PartySong);
//$SessionID...............O --> Setvalue(56331 /*[Multimedia\Variablen\Party_Mode\SessionID]*/, $SessionID);
//$NumberOfListeners.......O --> Setvalue(36305 /*[Multimedia\Variablen\Party_Mode\NumberOfListeners]*/, $NumberOfListeners);
//$ListenerList............O --> SetValue(49311 /*[Multimedia\Variablen\Party_Mode\ListenerList]*/, $ListenerList);
//$SingerUUID..............O --> Setvalue(24532 /*[Multimedia\Variablen\Party_Mode\SingerUUID]*/, $SingerUUID);
//$SingerSessionID.........O --> Setvalue(23791 /*[Multimedia\Variablen\Party_Mode\SingerSessionID]*/, $SingerSessionID);
//------------------------------------------------------------------------------

Viele Grüße

André

Hallo,

erst mal recht vielen Dank an DigiHouse für die viele Arbeit.
Die Instalation hat bei mir auch reibungslos geklappt. Jetzt habert aber das Script UPNP_Initialize.

Hier mal die Fehlermeldung:

http://192.168.2.1:49000/TMediaCenterDevDesc.xml

modelName:FRITZ!BoxServerDescription:

http://192.168.2.1:49000/TMediaCenterDevDesc.xml

modelName:FRITZ!BoxHTTP/1.1 200 OK
DATE: Sun, 27 Oct 2013 18:31:31 GMT
SERVER: FRITZ!Box Fon WLAN 7390 UPnP/1.0 AVM FRITZ!Box Fon WLAN 7390 84.05.60
CONNECTION: close
CONTENT-TYPE: text/xml; charset=„utf-8“
EXT:
Transfer-Encoding: chunked

97f

<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/“><container id=„c744103936016590“ parentID=„0“ restricted=„0“ searchable=„1“ childCount=„10“ ><dc:title>Dokumente</dc:title> <upnp:class>object.container.storageFolder</upnp:class> <upnp:storageUsed>-1</upnp:storageUsed> </container><container id=„c1059865822969439“ parentID=„0“ restricted=„0“ searchable=„1“ childCount=„10“ ><dc:title>Fotos</dc:title> <upnp:class>object.container.storageFolder</upnp:class> <upnp:storageUsed>-1</upnp:storageUsed> </container><container id=„c4585349426805“ parentID=„0“ restricted=„0“ searchable=„1“ childCount=„10“ ><dc:title>Musik</dc:title> <upnp:class>object.container.storageFolder</upnp:class> <upnp:storageUsed>-1</upnp:storageUsed> </container><container id=„c726740199431104“ parentID=„0“ restricted=„0“ searchable=„1“ childCount=„10“ ><dc:title>Reposito</dc:title> <upnp:class>object.container.storageFolder</upnp:class> <upnp:storageUsed>-1</upnp:storageUsed> </container><container id=„c149232720943875“ parentID=„0“ restricted=„0“ searchable=„1“ childCount=„10“ ><dc:title>Software</dc:title> <upnp:class>object.container.storageFolder</upnp:class> <upnp:storageUsed>-1</upnp:storageUsed> </container><container id=„c797605706779884“ parentID=„0“ restricted=„0“ searchable=„1“ childCount=„10“ ><dc:title>Videos</dc:title> <upnp:class>object.container.storageFolder</upnp:class> <upnp:storageUsed>-1</upnp:storageUsed> </container></DIDL-Lite>
23

6
1f

6
17

0
2c

0

Message:

97f

<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/“><container id=„c744103936016590“ parentID=„0“ restricted=„0“ searchable=„1“ childCount=„10“ ><dc:title>Dokumente</dc:title> <upnp:class>object.container.storageFolder</upnp:class> <upnp:storageUsed>-1</upnp:storageUsed> </container><container id=„c1059865822969439“ parentID=„0“ restricted=„0“ searchable=„1“ childCount=„10“ ><dc:title>Fotos</dc:title> <upnp:class>object.container.storageFolder</upnp:class> <upnp:storageUsed>-1</upnp:storageUsed> </container><container id=„c4585349426805“ parentID=„0“ restricted=„0“ searchable=„1“ childCount=„10“ ><dc:title>Musik</dc:title> <upnp:class>object.container.storageFolder</upnp:class> <upnp:storageUsed>-1</upnp:storageUsed> </container><container id=„c726740199431104“ parentID=„0“ restricted=„0“ searchable=„1“ childCount=„10“ ><dc:title>Reposito</dc:title> <upnp:class>object.container.storageFolder</upnp:class> <upnp:storageUsed>-1</upnp:storageUsed> </container><container id=„c149232720943875“ parentID=„0“ restricted=„0“ searchable=„1“ childCount=„10“ ><dc:title>Software</dc:title> <upnp:class>object.container.storageFolder</upnp:class> <upnp:storageUsed>-1</upnp:storageUsed> </container><container id=„c797605706779884“ parentID=„0“ restricted=„0“ searchable=„1“ childCount=„10“ ><dc:title>Videos</dc:title> <upnp:class>object.container.storageFolder</upnp:class> <upnp:storageUsed>-1</upnp:storageUsed> </container></DIDL-Lite>
23

6
1f

6
17

0
2c

0
Warning: simplexml_load_string(): Entity: line 1: parser error : Start tag expected, ‚<‘ not found in D:\IP-Symcon\scripts\UPNP_Browse_Functions.ips.php on line 81

Warning: simplexml_load_string(): 97f in D:\IP-Symcon\scripts\UPNP_Browse_Functions.ips.php on line 81

Warning: simplexml_load_string(): ^ in D:\IP-Symcon\scripts\UPNP_Browse_Functions.ips.php on line 81

Fatal error: Call to a member function registerXPathNamespace() on a non-object in D:\IP-Symcon\scripts\UPNP_Browse_Functions.ips.php on line 82

Das Webfront funktioniert, ist alles eingerichtet und läßt sich auch etwas bedienen. Leider komme ich nicht auf eine Songauswahl und Töne konnte ich dem System auch noch nicht entlocken.
Aber bis hier hin eine super Arbeit.

Viele Grüße aus Thüringen

Frank

Hallo Frank

… OK. Danke für die Blumen :slight_smile: Die sind aber nur gerechtfertigt, wenn es auch bei Euch funktioniert

Auf jeden Fall prima Rückmeldung, da sich die Probleme so einkreisen lassen :smiley:

Zu dem Problem:

Sieht aus wie ein Mediamanager auf einer Fritzbox ? Habe ich nicht testen können. Ich habe so etwas im Einsatz:

http://www.dbpoweramp.com/asset-upnp-dlna.htm
(habe mir die Vollversionen zugelegt)
oder einfach den WMP

Der größte Teil der Message ist die visualisierte Rückgabe - also Zugriff besteht (schon mal sehr gut !) und DIDL ist auch enthalten. Dem Ausdruck nach stört mich das 97F und die anderen einzeln stehenden Zahlenkombinationen. Die Meldung wird über SimpleXML nicht geladen, da offenbar der Aufbau etwas anders ist. Zeig mir mal bitte die Message ohne HTML-Filterung oder sieh mal bitte in der ContentDirectory_Browse.xml (in IP-Symcon/scripts) nach wie diese aufgebaut ist. Wahrscheinlich wird bei Dir noch etwas vorangestellt, was herauszufiltern ist. Bei mir sieht die exemplarisch so aus:

<?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:dlna="urn:schemas-dlna-org:metadata-1-0/" xmlns:arib="urn:schemas-arib-or-jp:elements-1-0/" xmlns:dtcp="urn:schemas-dtcp-com:metadata-1-0/" xmlns:pv="http://www.pv.com/pvns/" xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"><item id="0$1$13$80$1534$1535R60429" refID="0$1$8I60429" parentID="0$1$13$80$1534$1535" restricted="1"><dc:title>Andromeda</dc:title><dc:date>2000-01-01</dc:date><upnp:genre>Pop</upnp:genre><upnp:album>Behind The Sun</upnp:album><upnp:originalTrackNumber>10</ ...

Die relevante Stelle in der UPNP_Browse_Functions.ips.php ist:

$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);

echo "

Message:

";
echo $message;

//$message (XML) auslesen ------------------------------------------------------
$sxml = simplexml_load_string($message);
$sxml->registerXPathNamespace('s', 'http://schemas.xmlsoap.org/soap/envelope/' );
$sxml->registerxPathNamespace('u', 'urn:schemas-upnp-org:service:ContentDirectory:1');

$ResponseArray = $sxml->xpath('//s:Envelope/s:Body/u:BrowseResponse');

//Testanzeige-------------------------------------------------------------------
echo "

ResponseArray:

";
print_r ($ResponseArray);

Bei mir musste ich nur den Header abtrennen und konnte die Message weiter verarbeiten.

Viele Grüße

André

PS: nochmal als Hinweis - Das Accordeon-Menu ist nur Spielerei als Mögliche Visualisierung ! Ich wollte das so und habe das auch so im Einsatz. Günstiger sind vielleicht für Euch die puren iframes (siehe oben --> im WFC auf die andere Konfiguration umschalten.

Hallo DigiHouse,

recht vielen Dank für die schnelle Antwort.
Den Fritz-Mediaserver habe ich erstmal ausgeschaltet, um überhaupt etwas vorwärts zu kommen.
Das Script UPNP_Initialize läuft jetzt fehlerfrei durch. Es wird hier wohl am Aufbau der xml liegen.

Leider bekomme ich trotzdem kein Ton raus.

Die angezeigten Server und Devices wechseln ständig. Es werden aber nie alle verfügbaren angezeigt (2 verschiedene WinPlayer und BubbleUpnP)

Nach Auswahl kann ich leider nicht in den Medien suchen, da mir immer nur das root-Verzeichnis angezeigt wird.

Durch Zufall bin ich beim Ausführen der UPNP_Browse_Server.ips.php auf folgenden Fehler gestoßen. Ich weiß aber nicht, ob das was zu sagen hat. Hier die Meldung:

Notice: Use of undefined constant UPNP_DIDL_Lite_ID - assumed ‚UPNP_DIDL_Lite_ID‘ in D:\IP-Symcon\scripts\UPNP_Browse_Server.ips.php on line 17

Warning: Wrong parameter type for GetValue() in D:\IP-Symcon\scripts\UPNP_Browse_Server.ips.php on line 17

Notice: Use of undefined constant UPNP_Server_ContentDirectory - assumed ‚UPNP_Server_ContentDirectory‘ in D:\IP-Symcon\scripts\UPNP_Browse_Server.ips.php on line 24

Warning: Wrong parameter type for GetValue() in D:\IP-Symcon\scripts\UPNP_Browse_Server.ips.php on line 24

Notice: Use of undefined constant UPNP_Server_IP - assumed ‚UPNP_Server_IP‘ in D:\IP-Symcon\scripts\UPNP_Browse_Server.ips.php on line 25

Warning: Wrong parameter type for GetValue() in D:\IP-Symcon\scripts\UPNP_Browse_Server.ips.php on line 25

Notice: Use of undefined constant UPNP_Server_Port - assumed ‚UPNP_Server_Port‘ in D:\IP-Symcon\scripts\UPNP_Browse_Server.ips.php on line 26

Warning: Wrong parameter type for GetValue() in D:\IP-Symcon\scripts\UPNP_Browse_Server.ips.php on line 26

Notice: Use of undefined constant UPNP_DIDL_Lite_ParentID - assumed ‚UPNP_DIDL_Lite_ParentID‘ in D:\IP-Symcon\scripts\UPNP_Browse_Server.ips.php on line 38

Warning: Wrong parameter type for GetValue() in D:\IP-Symcon\scripts\UPNP_Browse_Server.ips.php on line 38

Notice: Use of undefined constant UPNP_DIDL_Lite_Last_ParentID - assumed ‚UPNP_DIDL_Lite_Last_ParentID‘ in D:\IP-Symcon\scripts\UPNP_Browse_Server.ips.php on line 39

Warning: Wrong parameter type for GetValue() in D:\IP-Symcon\scripts\UPNP_Browse_Server.ips.php on line 39

Warning: fsockopen(): unable to connect to :0 (Failed to parse address „“) in D:\IP-Symcon\scripts\UPNP_Browse_Functions.ips.php on line 59

Warning: fputs() expects parameter 1 to be resource, boolean given in D:\IP-Symcon\scripts\UPNP_Browse_Functions.ips.php on line 61

Warning: stream_get_contents() expects parameter 1 to be resource, boolean given in D:\IP-Symcon\scripts\UPNP_Browse_Functions.ips.php on line 63

Achtung

Achtung vars

Array
(
[0] =>
)

Notice: Undefined offset: 1 in D:\IP-Symcon\scripts\UPNP_Browse_Functions.ips.php on line 73

Warning: fclose() expects parameter 1 to be resource, boolean given in D:\IP-Symcon\scripts\UPNP_Browse_Functions.ips.php on line 79

Message:

Fatal error: Call to a member function registerXPathNamespace() on a non-object in D:\IP-Symcon\scripts\UPNP_Browse_Functions.ips.php on line 86

Viele Grüße

Frank

Hallo Frank,

die Fehlermeldungen treten nur beim direkten ausführen der UPNP_Browse_Server.ips.php auf, da die UPNP_Constants.ips.php eingebunden sein muss. Das geschieht schon bei der Variablenübergabe in der UPNP_Browse_Web.php vom Webfrontverzeichnis aus. Anbei eine Skizze der Logik:

Das neue Suchen von Servern aller 2 Minuten ist sicherlich nicht sonderlich sinnvoll. Deshalb in einigen Posts vorher:

Und hat jemand eventuell einen Hinweis zu dem Problem auf 239.255.255.250:1900 den Traffic zu verfolgen? Pakete absetzen kann ich (z.B. Discovery mit SSDP) über UDP-Socket und angehängten Cutter und erhalte auch die Antworten der Geräte. Dies aber nur auf diese Anfrage. Meldungen dazwischen bekomme ich darüber nicht mit.
Oder verstehe ich da etwas generell falsch ? Die Geräte müssten doch ihre Präsenz in bestimmten Intervallen im Netzwerk nochmal bekanntgeben. Oder läuft das etwa nur über ein Event-Subscribe ? Hat jemand im Sonos-Bereich mal damit experimentiert ?

Ich habe jedoch derzeit keine andere Lösung neue Devices zu erkennen. Sinnvoll wäre hier wahrscheinlich ein Event-Subscribing, aber da bin ich nicht weitergekommen. Vielleicht hat jemand eine Idee. Es gibt auch noch eine 2. Variante über einen UDP-Socket, die ich probiert hatte (ist jedoch ein wenig komplizierter).

Vorschlag: Schalte die Events für UPNP_GetPositionInfo, UPNP_Select_Device und UPNP_Select_Server vorerst ab (Install Punkt 5). Aktualisiere dann manuell über das Webfront (siehe Picture Bedienung rechts Mitte - Refresh …)

Wenn das nichts bringt bediene mal aus dem Objektbaum heraus mit einer geringen Modifikation (für Testzwecke UPNP_Constants.ips.php und eine Objekt-ID übergeben) und berichte was passiert. Die Objekt-ID´s aus der Skriptrückgabe ggf. testweise oben einsetzen. So habe ich eine Menge Zeit mit dem Herausfinden von Baumstrukturen experimentiert.

in UPNP_Browse_Server.ips.php zum manuellen testen oben ersetzen:

<?

//------------------------------------------------------------------------------
//UPNP_Browse_Server.ips.php---------------------------2013 von André Liebmann--
//UPNP_Browse_Server V2.1 Menu--------------------------------------------------
//21.10.2013--------------------------------------------------------------------
//------------------------------------------------------------------------------

//für Testzwecke----------------------------------------------------------------
$ObjectID = "0";
include ("UPNP_Constants.ips.php");
//------------------------------------------------------------------------------

//ObjectID = GetValue(UPNP_DIDL_Lite_ID);

(Ich denke auch, dass eventuell nur lokale Server mit 127.0.0.1 und nicht über Netzwerk (192. …) zu sehen sind. Das kannst Du Gegenprüfen mit einem direkten starten der UPNP_Select_Server.ips.php --> die Server sollten in der Skriptausgabe angezeigt werden.)

Vielleicht kannst Du auch Asset oder den Twonky als Probeversion wie im vorherigen Post zum Testen benutzen. Der Windows Media Player sollte als Streamingserver auch erkannt werden, wenn dieser zumindest nicht explizit zu einem Heimnetzwerk zugehörig deklariert wurde.

Ich freue mich auf jeden fall über die Kommunikation. Die Skripts sind keineswegs perfekt, bei mir jedoch wie gesagt auf 3 Rechnern und o.g. Servern / Devices validiert und ich brauche auch Ideen bzw. Ratschläge, da ich kein Programmierer bin. Also melde Dich wo es hakt, wir versuchen es anzupassen und vorallem ist jeder Rat willkommen :smiley:

Gruß

André

PS Frank: aktiviere auch in den Verknüpfungen (in Webfront) die IP für gewählten Server und Device , so weisst Du welcher/s gerade angesprochen werden soll. So hast Du auch gleich rückkopplung.

Gruß André

Hallo André,

erst mal herlichen Dank für Deine Arbeit, genau das habe ich schon länger gesucht! Ich habe Dein Installationsscript ausgeführt und alles hat sich wunderbar eingefunden. Bei Punkt 4. gab es keine Einträge, bei Punkt 5. habe ich die ID’s neu zugeordnet und den Timer aktiviert, Punkt 6. lief auch, aber bei Punkt 7. bekomme ich einen Fehler:

http://192.168.63.25:2869/upnphost/udhisapi.dll?content=uuid:a718ca67-7190-4443-af1e-2c6311d0aaed

modelName:Windows Media Player Sharinghttp://192.168.63.3:9000/plugins/UPnP/MediaServer.xml

modelName:Logitech Media Server 7.7.31375965195http://192.168.63.25:2869/upnphost/udhisapi.dll?content=uuid:ee594aa0-b14d-4f7a-9f56-4979c92ebe1f

modelName:Windows Media Player Sharinghttp://192.168.63.25:2869/upnphost/udhisapi.dll?content=uuid:4a8954e0-28ce-4cbb-bad9-9a640943ea69

modelName:Windows Media Player Sharing

modelName:Windows Media Player SharingHTTP/1.1 500 Internal Server Error
Content-Length: 499
Content-Type: text/xml; charset="utf-8"
Server: Microsoft-Windows-NT/5.1 UPnP/1.0 UPnP-Device-Host/1.0 Microsoft-HTTPAPI/2.0
Date: Sat, 02 Nov 2013 21:26:30 GMT
Connection: close


SOAP-ENV:ClientUPnPError801Access denied


Message:


SOAP-ENV:ClientUPnPError801Access denied


ResponseArray:

Array
(
)

Notice:  Undefined offset: 0 in C:\IP-Symcon\scripts\UPNP_Browse_Functions.ips.php on line 92

Notice:  Trying to get property of non-object in C:\IP-Symcon\scripts\UPNP_Browse_Functions.ips.php on line 92


Result:



Result_WF:


Fatal error:  Uncaught exception 'Exception' with message 'String could not be parsed as XML' in C:\IP-Symcon\scripts\UPNP_Browse_Functions.ips.php:148
Stack trace:
#0 C:\IP-Symcon\scripts\UPNP_Browse_Functions.ips.php(148): SimpleXMLElement->__construct('')
#1 C:\IP-Symcon\scripts\UPNP_Browse_Server.ips.php(54): BrowseList(NULL)
#2 C:\IP-Symcon\scripts\26000.ips.php(176): include('C:\IP-Symcon\sc...')
#3 {main}
  thrown in C:\IP-Symcon\scripts\UPNP_Browse_Functions.ips.php on line 148
Abort Processing during Fatal-Error: Uncaught exception 'Exception' with message 'String could not be parsed as XML' in C:\IP-Symcon\scripts\UPNP_Browse_Functions.ips.php:148
Stack trace:
#0 C:\IP-Symcon\scripts\UPNP_Browse_Functions.ips.php(148): SimpleXMLElement->__construct('')
#1 C:\IP-Symcon\scripts\UPNP_Browse_Server.ips.php(54): BrowseList(NULL)
#2 C:\IP-Symcon\scripts\26000.ips.php(176): include('C:\IP-Symcon\sc...')
#3 {main}
  thrown
   Error in Script C:\IP-Symcon\scripts\UPNP_Browse_Functions.ips.php on Line 148

Ich habe schon selber etwas versucht über den Fehler herauszufinden, bin aber leider gescheitert. Offensichtlich stammt das Problem von meinem Windows 7 Rechner, der mehrere UPNP-Server anbietet (pro User). Dieses Phänomen tritt auch bei meiner Android-App auf und scheint mir eher „works as designed“ zu sein. Der PC bietet 3 Quellen an im Format COMPUTERNAME:USERNAME. Es scheint mir ein Login-Problem zu geben, oder?

Gruß,

Marcus

Hallo Marcus,

„Access denied“ deutet ja auf einen PW-Schutz hin. Der WMP funktioniert bei mir auch nur, wenn er explizit nicht in ein Heimnetzwerk eingebunden ist. Ich selbst verwende wie in Post vom 27.10.13 entweder Twonky oder Asset-UPNP.

Versuch mal mit Kinsky (http://www.linn.co.uk/software) zu testen, ob Du Zugriff hast.

Wenn ja, solltest Du die URI in das o.g. kurze Testscript für die UPNP_Functions einsetzen.

Dazu gehst du auf den Titel --> Rechstklick Details --> 2. Zeile von unten. Dazu IP und Port des Device. Bekommst Du das MP3 zu hören ist das Device so ansteuerbar.

Das war mein eigentliches Grundanliegen - die UPNP_Functions mit all den SOAP-Befehlen Euch näher zu bringen. Alles andere ist nur zur Vereinfachung für mich in meinem täglichen Gebrauch als Drumherum konstruiert :slight_smile:

Sollte tatsächlich ein Login erforderlich sein, könnte theoretisch ein Ergänzen des Login in der UPNP_Select_Server nach $ServerIp und -Port hilfreich sein (eigentlich glaube ich aber nicht, dass UPNP so funktioniert).

	//Rootverzeichnis/IP/Port----------------------------------------------------

	$vars1 = explode("//", $ServerDescription);
	$cutted1 	= $vars1[0];
	$cutted2 	= $vars1[1];
	$vars2 = explode("/", $cutted2);
	$cutted3 	= $vars2[0];
	$cutted4 	= $vars2[1];
	$vars3 = explode(":", $cutted3);
	$ServerIP 	= $vars3[0];           //hier !
	$ServerPort = $vars3[1];            //hier !

	$root = "http://"."$cutted3"."/";
			//echo "ROOT:$root

";
			//echo "IP:$ServerIP

";
			//echo "Port:$ServerPort

";

Hier der Button Aufbau:

<button
   type=\"button\"
	name=\"" .$modelName. "\"
	value=\"" .$friendlyName. "\"
	id=\"" .$UDN. "\"
	alt=\"\"
	onclick=\"
	sndReq('../Discovery/link/UPNP_Discovery_Server_Web.php?Server=$ServerContentDirectory@$ServerIP:$ServerPort');
	sndReq('../Browse/link/UPNP_Browse_Web.php?ObjectID=0');
	sndReq('../Browse/link/UPNP_Browse_Verlauf_Web.php?Browse=4');
	sleep(1000);
	reload_all();
	\">
                <p>
	 <img src=\"" .$iconurl. "\" width=\"80\" height=\"80\" border=\"0\">
	 <br>
                 <b>$friendlyName</b>
	</p>
  </button>

Ich kenne nur die genau Syntax nicht (a.e. … $ServerPort."@Username:Kennwort" oder so ähnlich). So könnte aber der Button eben das mit übergeben.
Ein anderer Weg wäre über die UPNP_Discovery_Server_Web (dort nach ServerIP anfügen).

	$Server = str_replace(" ", "+", $Server_get);

	$vars1 = explode("@", $Server);
	$ServerContentDirectory = $vars1[0];
	$cutted1 = $vars1[1];

	$vars2 = explode(":", $cutted1);
	$ServerIP 	= $vars2[0];
	$ServerPort = $vars2[1];              //hier dahinter!

	SetValue(UPNP_Server_IP, $ServerIP);

	SetValue(UPNP_Server_Port, $ServerPort);

	SetValueString(UPNP_Server_ContentDirectory, $ServerContentDirectory);

Gruß André

Hallo Gemeinde,

ich habe mir vor 1 Woche einen Panasonic DMR-BST730EG Blu-ray Recorder mit Twin HD Receiver genehmigt und bin absolut begeistert. Eine echte „eierlegende Wollmilchsau“. Das volle DLNA-Programm ist dabei nebst streamen der Aufnahmen ins Netzwerk und sogar streamen des Live-TV auf einen Zweit-TV oder Tablet ! Wow dachte ich. Muss ich gleich mal einbinden.

Aber: hier zeigt sich wiedermal die Offenheit des UPNP-Standards. Der Panasonic verwendet vollständige URL´s in seinen Descriptions statt der bei meinen anderen Geräten nur „Verzeichnissen“ (also ohne http://IP:Port).
Ebenfalls ist hier das Schema „urn:schemas-upnp-org:service:ContentDirectory:2“ statt „urn:schemas-upnp-org:service:ContentDirectory:1“ vorhanden.

Damit hatte ich nicht gerechnet und baue nun alles um.

Ich muss deshalb nochmal alle Interessierte ansprechen: Wäre schön Bug-Reports zu bekommen, die genau solche Probleme beinhalten. Das kann auch einfach die Description.xml des Device sein. Gerne auch als PN.

Aber noch das Positive: Am Mittwoch war (zumindest in Sachsen :slight_smile: ) Bus- und Bettag Da habe ich noch den Seek-Mode (Vor- und Zurückspulen), Previous und Next sowie eine funktionierende Playlisterstellung implementiert :slight_smile:

Viele Grüße

André

Hallo Gemeinde,

mal ein kurzer Zwischenbericht und Lebenszeichen von mir :smiley:

Ich habe das Auslesen der ControlURL auf ein Filtern eventuell komplett übergeben URL´s angepasst. Wie in der vorigen Meldung beschrieben habe ich das erst bei meinem Panasonic DMR-BST730EG Blu-ray Recorder entdeckt, dass es auch Devices gibt, die eine komplette URL (d.h. mit http//ip : port/) übergeben. Mein sonstiges Rudel an UPNP-Geräten hat das nicht getan.
Tja – UPNP ist eben nur ein Pseudo-Standard.

Vielleicht hilft das aber Denjenigen, die bisher keinen Ton übertragen konnten.

Mit dabei abgefallen ist ein Seek-Mode (zumindest für Geräte, die das unterstützen – bei mir ist es die Hälfte), Previous und Next. Eine Playlist-Erstellung sollte jetzt auch weitestgehend funktionieren.

Die neue Datei (getestet auf meinem Entwicklungs-Vaio und einem zweiten Rechner):

Multimedia 2013-11-29.zip (247 KB)

Installation wie in Post 1 beschrieben, aber mit folgenden Modifikationen:

  1. Im Objektbaum „Multimedia“ löschen -> bei mir werden dann auch alle zugehörigen Scripts in IP-Symcon/scripts/deleted verschoben. Wenn das bei Euch nicht so ist solltet ihr alle Scripts, die mit UPNP_ beginnen unter IP-Symcon /scripts löschen. Das war auch der Grund, dass alle zugehörigen Scripts diese eindeutigen Benennungen haben.

  2. Im Webfront-Configurator alle zugehörigen Einträge löschen (ID beginnt mit „Cpyitem …“)

  3. Punkt 1 bis 4 wie in Post 1 durchführen. Der Objektbaum sieht von den Scripts her jetzt nur ein wenig anders aus, da ich auch die SSDP-Abfrage geändert habe

  4. Punkt 6 ausführen -> das braucht ein wenig, da das Netzwerk abgefragt wird und antworten muss

Das WF sieht nach einigen Aktionen damit die iframes gefüllt werden jetzt so aus:

Das Accordeon-Menu habe ich jetzt erstmal rausgenommen bis ich ein Reload spezifischer iframes (also nicht „reload all()“ wie bisher) hinbekomme. Vielleicht kennt ja jemand auch einen Rat:

Unter webfront/user/Multimedia liegt Menu.html welches die iframes enthält. Wie kann ich nun nach einer Aktion im iframe die in Menu.html eingebetteten iframes spezifisch neu laden.

Bisherige Versuche:

top.getElementById('iframe_Browse').location.reload(); 
bzw.
top.frames["iframe_Browse"].location.reload();

Anmerkungen:

Die WFC_TargetID übertragen (hier 46136):

Initialize findet ihr hier:

Das ist kein Fehler, da hier usec ‚10000‘ interpretiert wird:

Beim manuellen Auslösen der Server und Device - Suche im WF bekommt ihr ein Array mit allen gefundenen Devices angezeigt. Das ist also keine Fehlermeldung:

Als Nächstes ist die Überarbeitung der UPNP_Functions mit dem Erweitern auf andere Versionsnummern von AVTransport und ContentDirectory (aktuell nur urn:schemas-upnp-org:service:ContentDirectory:1 etc.), eine periodische Abfrage per Ping und alles was sonst noch auffällt dran.

Nochmal: das ist wiedermal ein Zwischenstand und kein fertiges Konstrukt !!! Es ist ein Chassis für den eigentlichen Motor (UPNP_Functions). Für Kritik und noch mehr für Ideen bin ich jederzeit offen :rolleyes:

Viele Grüße

André

Hallo Andre,

ich finde es finde super das einer das UPnP Thema öffentlich angeht. Ich selber habe mehreren von den Sony NS Lautsprechern hier stehen, wir haben sogar den selben Fernseher, Medienserver ist Plesk. Vor 6 Monaten hatte ich eigene Versuche mit IP-Symcon und UPnP gestartet und war soweit das ich statische URLs an die Renderer schicken konnte, mangels Zeit und Umzug musste ich es aber erstmal auf Eis legen.

Zu Neujahr hin sieht es bei mir zeitlich wieder besser aus, vielleicht kann ich mich einbringen. Unter welcher Lizenz stellst du deinen Quelltext zu Verfügung?

Grüße,

Marco

Hallo Marco,

erstmal Danke für´s Interesse.

Zu Neujahr hin sieht es bei mir zeitlich wieder besser aus, vielleicht kann ich mich einbringen.

Ich suche Mitstreiter, die ein wenig mit entwickeln. Es steckt viel „Forschung“ drin, ich bin aber kein Programmierer.

Unter welcher Lizenz stellst du deinen Quelltext zu Verfügung?

Definitiv open source. es ist ja letztlich eine Spielerei.

Viele Grüße

André

Hallo Gemeinde,

ich brauche mal einen Tipp.

Um Playlists zu erstellen und unter spezifischen Namen abspeichern habe ich eine Idee. Aber wie könnte ich eine spezifische Datei, die unter /webfront/user/Multimedia/Playlists abgelegt ist aus dem Webfront heraus löschen ?

Viele Grüße

André

@fschult2001

Hallo Frank,

nachdem ich gestern eine FritzBox 7490 in Betrieb genommen habe, fiel mir dein Post mit dem Fehler der zwischengestreuten Hexadezimalzahlen in der Response ein. Ich habe genau das Selbe erlebt.

Ich habe somit die UPNP_Browse_Functions.ips.php etwas umgestellt (ein explode-Weg statt Auslesen über SimpleXML) und so funktioniert es jetzt bei mir auch mit der FritzBox :smiley:

Anbei mal die UPNP_Browse_Functions.ips.php (zum Austauschen). Da ich in letzter Zeit einiges verändert habe (Playlists erstellen, laden und speichern integriert; Device-Suche geändert; Seek etc.) kann es sein, dass das Austauschen der Datei allein nicht genügt. Gib ggf. Bescheid, dann packe ich nochmal einen aktuellen Entwicklungsstand zusammen.

<?

//------------------------------------------------------------------------------
//UPNP_Browse_Functions.ips.php-------------------------2014 by André Liebmann--
//UPNP_Browse_Functions_V2.3----------------------------------------------------
//03.01.2014--------------------------------------------------------------------
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
//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);
	$Result = $vars2[0];
	$cutted3 = $vars2[1];

	return $Result;

	SetValue(UPNP_Result, $Result);

	//NumberReturned ermitteln---------------------------------------------------

	$vars1 = explode("<NumberReturned>", $message);
   $cutted1 = $vars1[0];
	$cutted2 = $vars1[1];
	$vars2 = explode("</NumberReturned>", $cutted2);
	$cutted3 = $vars2[1];
	$NumberReturned = $vars2[0];

	return $NumberReturned;
		
	SetValue(UPNP_NumberReturned, $NumberReturned);

	//TotalMatches ermitteln-----------------------------------------------------

	$vars1 = explode("<TotalMatches>", $message);
	$cutted1 = $vars1[0];
	$cutted2 = $vars1[1];
	$vars2 = explode("</TotalMatches>", $cutted2);
	$cutted3 = $vars2[1];
	$TotalMatches = $vars2[0];

	return $TotalMatches;
		
	SetValue(UPNP_TotalMatches, $TotalMatches);
	
	//UpdateID ermitteln---------------------------------------------------------

	$vars1 = explode("<UpdateID>", $message);
   $cutted1 = $vars1[0];
	$cutted2 = $vars1[1];
	$vars2 = explode("</UpdateID>", $cutted2);
   $cutted3 = $vars2[1];
	$UpdateID = $vars2[0];

	return $UpdateID;
	
	SetValue(UPNP_UpdateID, $UpdateID);
}


//------------------------------------------------------------------------------
//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------------------------------------------------------------

$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);

}

//------------------------------------------------------------------------------
//Function rekey----------------------------------------------------------------
//umbenennen der im Array enthaltenen numerischen Keys zu Tracks----------------
//------------------------------------------------------------------------------

function rekey_array( $input , $prefix )
{
  $out = array();
  foreach( $input as $i => $v )
  {
    if ( is_numeric( $i ) )
    {
       $out[$prefix . $i] = $v;
       continue;
    }
    $out[$i] = $v;
  }
  return $out;
}

//------------------------------------------------------------------------------
//HTML-Grundstrukturen----------------------------------------------------------
//------------------------------------------------------------------------------

$HTML_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>

	<meta http-Equiv=\"Cache-Control\" Content=\"no-cache\">
	<meta http-Equiv=\"Pragma\" Content=\"no-cache\">
	<meta http-Equiv=\"Expires\" Content=\"0\">

	<script type=\"text/JavaScript\">

		<!--Variablenuebergabe per XMLHttpRequest / Auslesen per GET in php-->

		function sndReq(url)
		{
		var action;
		action = new XMLHttpRequest;
		action.open('get', url);
		action.send(null);
		<!--Test: alert(url);-->
		}

		<!--Funktion sleep in Millisekunden-->

		function sleep(ms)
		{
		var zeit=(new Date()).getTime();
		var stoppZeit=zeit+ms;
		while((new Date()).getTime()<stoppZeit){};
		}

		function reload_all()
		{
		for (var i = 0; i < parent.frames.length ; ++i)
			{
			top.frames[i].location.reload ();
			}
		}
		
	</script>
	
	<style type=\"text/css\">
	
		div.form-verlauf input { color:#FFFFFF; background-image:url(image/Button.png); background-repeat:no-repeat; float:left; font-size:10px; height:25px; width:100px; margin-top:5px; margin-right:5px; border:3px blue;}
		div.form-verlauf input:link { color:#FFBF00; text-decoration:none; font-weight:bold; }
		div.form-verlauf input:visited { color:#FFBF00; text-decoration:none; font-weight:bold; }
		div.form-verlauf input:focus { color:#FFBF00; background-color:#FFFF77; font-weight:bold; }
		div.form-verlauf input:hover { color:#FFBF00; text-decoration:none; background-color:#0000FF; }
		div.form-verlauf input:active { color:#FFBF00; background-color:#FFBF00; font-weight:bold; }

		div.form-checkbox { background-image:url(image/Button.png); background-repeat:no-repeat; float:left; font-size:12px; height:50px; width:200px; margin-top:5px; margin-right:5px;}
		div.form-checkbox img   {display:block; float:left; margin-top:5px; margin-left:5px; margin-right:5px;}
		div.form-checkbox label {display:block; float:middle;line-height: 25px; margin-left:5px;}
		div.form-checkbox input {display:block; float:right; margin-top:5px; height:30px}

		div.form-checkbox:link { color:#FFBF00; text-decoration:none; }
		div.form-checkbox:visited { color:#FFBF00; text-decoration:none; }
		div.form-checkbox:focus { color:#FFBF00; background-color:#FFFF77; }
		div.form-checkbox:hover { color:#FFBF00; text-decoration:none; background-color:#0000FF; }
		div.form-checkbox:active { color:#FFBF00; background-color:#FFBF00; }

		div.form-button { background-image:url(image/Button.png); background-repeat:no-repeat; float:left; font-size:12px; height:50px; width:200px; margin-top:5px; margin-right:5px;}
		div.form-button img   {display:block; float:left; margin-top:5px; margin-left:5px; margin-right:5px;}
		div.form-button label {display:block; float:middle; line-height: 25px; margin-left:5px;}

		div.form-button:link { color:#FFBF00; text-decoration:none; }
		div.form-button:visited { color:#FFBF00; text-decoration:none; }
		div.form-button:focus { color:#FFBF00; background-color:#FFFF77; }
		div.form-button:hover { color:#FFBF00; text-decoration:none; background-color:#0000FF; }
		div.form-button:active { color:#FFBF00; background-color:#FFBF00; }

		div.form-playlist { color:#FFFFFF; background-image:url(image/Playlist.png); float:left; font-size:12px; height:50px; width:400px; margin-top:5px; margin-right:5px;}
		div.form-playlist img   {display:block; float:left; margin-top:5px; margin-left:5px; margin-right:5px;}
		div.form-playlist label {display:block; float:middle; line-height: 20px; margin-left:5px;}

		div.form-playlist:link { color:#FFBF00; text-decoration:none; }
		div.form-playlist:visited { color:#FFBF00; text-decoration:none; }
		div.form-playlist:focus { color:#FFBF00; background-color:#FFFF77; }
		div.form-playlist:hover { color:#FFBF00; text-decoration:none; background-color:#0000FF; }
		div.form-playlist:active { color:#FFBF00; background-color:#FFBF00; }
		
		div.form-playlistlist input { color:#FFFFFF; background-image:url(image/Button.png); background-repeat:no-repeat; float:left; font-size:12px; font-weight:bold; height:25px; width:200px; margin-top:5px; margin-right:5px; border:3px blue;}
		div.form-playlistlist input:link { color:#FFBF00; text-decoration:none; font-weight:bold; }
		div.form-playlistlist input:visited { color:#FFBF00; text-decoration:none; font-weight:bold; }
		div.form-playlistlist input:focus { color:#FFBF00; background-color:#FFFF77; font-weight:bold; }
		div.form-playlistlist input:hover { color:#FFBF00; text-decoration:none; background-color:#0000FF; }
		div.form-playlistlist input:active { color:#FFBF00; background-color:#FFBF00; font-weight:bold; }
		
		div.form-submit input { color:#FFFFFF; background-color:#000000; font-size:15px; font-weight:bold; height:50px; width:50px; position:fixed; top:10px; right:10px; border:3px blue;}
		div.form-submit input:link { color:#FFBF00; text-decoration:none; }
		div.form-submit input:visited { color:#FFBF00; text-decoration:none; }
		div.form-submit input:focus { color:#FFBF00; background-color:#FFFF77; }
		div.form-submit input:hover { color:#FFBF00; text-decoration:none; background-color:#0000FF; }
		div.form-submit input:active { color:#FFBF00; background-color:#FFBF00; }
		
	</style>
	
  </head>
";

$HTML_Style_BrowseHistory = "
  <body bgcolor=\"#0B243B\" text=\"#6A6D64\" style=\"width:480px; height:200px; font-family:Arial,sans-serif;\">
";

$HTML_Style_Browse = "
  <body bgcolor=\"#0B243B\" text=\"#6A6D64\" style=\"width:480px; height:200px; font-family:Arial,sans-serif;\">
";

$HTML_Style_Playlist = "
  <body bgcolor=\"#0B243B\" text=\"#6A6D64\" style=\"width:100px; height:800px; font-family:Arial,sans-serif;\">
";

$HTML_Style_PlaylistList = "
  <body bgcolor=\"#0B243B\" text=\"#6A6D64\" style=\"width:220px; height:800px; font-family:Arial,sans-serif;\">
";

?>

Screenshot:

Viele Grüße aus Sachsen

André

Hallo Andre,

sorry, das ich mich jetzt erst melde. Hab eigentlich nur durch Zufall gesehen, dass sich etwas getan hat.

Hab sofort die Datei ausgetauscht und siehe da, es funktioniert ein bisschen mehr.

In der Verzeichnisstruktur der Server kann ich keine Verzeichnisse ändern, bzw. einsehen/auswählen. Und somit keine Musik auswählen!

Schöne Grüße

Frank