MPD Player Steuerung im FTUI

Begonnen von setstate, 27 Mai 2016, 00:02:46

Vorheriges Thema - Nächstes Thema

TWART016

Ich benutzer den Fully Browser mit Medialist. Nach unten scrollen funktioniert, nach oben nicht, weil die Seite dann neu lädt. Kann man da am Widget was optimieren, oder ist das ein Problem vom Browser?

Ist es möglich eine Suche einzubauen, welche nach Titel oder Künstler sucht?

TWART016

Zitat von: TWART016 am 27 Dezember 2016, 00:47:26
Ich benutzer den Fully Browser mit Medialist. Nach unten scrollen funktioniert, nach oben nicht, weil die Seite dann neu lädt. Kann man da am Widget was optimieren, oder ist das ein Problem vom Browser?
EDIT: eine Scrollleiste an der Seite ist bei Fully nicht vorhanden.

Ist es möglich eine Suche einzubauen, welche nach Titel oder Künstler sucht?

setstate

#32
Eine Suchfunktion brauche ich auch noch und werde das auch demnächst angehen. Aber das MPD Protokoll kennt keine generische Suchfunktion. Ich werde dafür die Spotify-Web API nutzen: https://developer.spotify.com/web-api/search-item/

UPDATE
Soweit mein Zwischenstand für die Albumsuche. Suche per Input-Widget und ich zeige das Ergebnis in einer Medialist an. Das Anklicken eines Albums zum Abspielen geht noch nicht. Dazu muss ich noch eine Änderung im Medialist-Widget machen. Vorerst muss man noch "set MPD1 playfile spotify:album:xyz123yxz123" eingeben.

sub call_mpd1_searchSpotify() {
    Log 1, "call_mpd1_searchSpotify";
    my $query = ReadingsVal("MPD1","searchquery","");
    BlockingCall("mpd_searchSpotify",$query,"done_mpd1_searchSpotify",120);
}

sub done_mpd1_searchSpotify($) {
    my $result = shift;
    Log 1, "done_mpd1_searchSpotify";
    fhem ("setreading MPD1 searchresult ".$result);
}

sub mpd_searchSpotify($) {
  my $query = shift;
  my $url;
  my $ret = '[';
  my $ua = LWP::UserAgent->new( ssl_opts => { verify_hostname => 1 } );

  my $response = $ua->get("https://api.spotify.com/v1/search?q=artist:".$query."&type=album");
  my $data = '';
  if ( $response->is_success ) {
      $data = $response->decoded_content();
      my $result = decode_json( $data );
      my @items = @{$result->{albums}->{items}};
      my $count = 0;

     foreach my $album (@items )
     {
     if ( $album->{album_type} eq "album" ) {
       $ret=$ret.'{"Artist":"'.$album->{artists}[0]->{name}.'",';
       $ret=$ret.'"Title":"'.$album->{name}.'",';
       $ret=$ret.'"Album":"'.$album->{name}.'",';
       $ret=$ret.'"Time":"0",';
       $ret=$ret.'"File":"'.$album->{uri}.'",';
       $ret=$ret.'"Track":"'.$count.'",';
       $ret=$ret.'"Cover":"'.$album->{images}[2]->{url}.'"},';
       $count++;
     }
   }
   if ( $count > 0 ) {
      $ret = substr($ret, 0, -1);   
   }
}
 
  $ret =~ s/;//g;
  $ret =~ s/\\n//g;
  $ret =~ s/[\x80-\x{FFFF}]/\x5F/g;
  $ret = $ret.']';
  return $ret;
}



define OnMpdSearchChanged notify MPD1:searchquery:.* {call_mpd1_searchSpotify()}

FTUI

            <div data-type="input" data-device="MPD1" data-get="searchquery" data-set="searchquery" data-cmd="setreading" data-value="" class=""></div>
             <div data-type="medialist" data-device="MPD1" data-get="searchresult" class=""></div>

ThorstenHeidelberger

Hallo setstate, das ist wirklich ein cooles Modul. Vielen Dank dafür.
Ich habe nur das Problem, dass in kürzester Zeit mein FHEM-Log vollgeschrieben wird.
Alles paar Sekunden kommen Einträge in der Art:

2016.12.30 00:05:35 0: done_mpd1_getcover
2016.12.30 00:05:42 0: done_mpd1_playlistinfo
2016.12.30 00:05:44 0: call_mpd1_playlistinfo
2016.12.30 00:05:44 3: OnMpdPlaylistChanged return value: HASH(0x3a82fd0)
2016.12.30 00:05:44 3: get MPD1 mpdCMD playlistinfo : MPD1 playlistinfo:
file: spotify:track:69l8nFPu0LWmnoJX7YSVYc
Time: 269
Artist: James Taylor
Album: Mud Slide Slim And The Blue Horizon
Title: You've Got A Friend
Date: 1971
Track: 2
Pos: 0
Id: 69
AlbumArtist: James Taylor
X-AlbumUri: spotify:album:0h8hazllDADHsrSpcQCltk
file: spotify:track:2DnJjbjNTV9Nd5NOa1KGba


Kann ich das Logging für die Playlist-Info irgendwie deaktivieren?

Viele Grüße,
Thorsten

Wzut

#34
Da Tobias mich heute im MPD Fred auf das Thema hier aufmerksam gemacht hat :

Zitat von: setstate am 27 Mai 2016, 00:02:46
Damit das Ganze fluffig läuft, musste ich das MPD Modul etwas optimieren.
--snip --
das mit dem originalen MPD Modul nicht 100% optimal klappte, habe ich die definierten Reading angepasst, die currentsong Abfrage bei Songwechsel verbessert und die Liste der Playlists in ein Reading gepackt, damit FTUI auch darauf zugreifen kann.

Was wird denn genau für FTUI gebraucht ?
Verstanden habe ich bis jetzt nur ein Reading mit dem Namen playlistcollection , d.h. eine Liste der vorhanden Playlisten mit Doppelpunkt getrennt ( ist ab morgen im Update verfügbar, aber war da nicht erst vor kurzem hier eine Diskussion das bestimmte Zeichen u.a. auch der Doppelpunkt nichts mehr in Reading Werten zu suchen haben ? .... muss ich jetzt direkt nochmal auf die Suche gehen)
Welche weiteren Readings werden noch benötigt ?
Was ist bei der current Songabfrage nicht OK ?
Reading cover : was wollt ihr hier haben - eine URL zum Bild des Interpreten ? Wenn ja ist im Reading  artist_image_html vorhanden, wenn es unbedingt cover sein muss kann ich es ändern bzw. man biegt es sich mit userreading selbst hin.
Maintainer der Module: MAX, MPD, UbiquitiMP, UbiquitiOut, SIP, BEOK, readingsWatcher

Tobias

So, jetzt nochmal zusammengefasst nachdem ich 2 Tage das aktuelle MPD-Modul versuche in TabletUI zu integrieren

- es muss in einem zu definierenden Intervall kontinuierlich das Reading "elapsed" aktualisiert werden. Angabe in Sekunden
- Reading "songtime" sollte ebenfalls die Anzahl in Sekunden der aktuellen Songlänge beinhalten
- "seekcur" aus dem MPD sollte noch ins Modul, damit man x-sekunden  vor- und zurückspulen kann
- Ein Reading "currentTrackProvider" sollte verfügbar sein. Dieser sollte folgende Ausprägungen haben
    - Radio: Ein Radiostream wird abgespielt
    - Bibliothek: Eine lokale MP3 wird abgespielt
- In ein Reading zb.: "playlist_json" wird von extern eine playlistdefinition, passend zur gleich abgespielten Playlist, eingesteuert. Darin befindet sich auch pro Track das passende Cover. Falls dieses Reading befüllt ist, sollte unter "artist_image" das daraus extrahierte Cover zum aktuell laufenden Track liegen
- der MPD stellt selbst kein "mute" zur Vefügung. Das könnte aber im MPD-fhem-Modul simuliert werden. Bei Mute: Volume merken und setvol=0, beim unmute entsprechend anders herum
Maintainer: Text2Speech, TrashCal, MediaList

Meine Projekte: https://github.com/tobiasfaust
* PumpControl v2: allround Bewässerungssteuerung mit ESP und FHEM
* Ein Modbus RS485 zu MQTT Gateway für SolarWechselrichter

Wzut

Zitat von: Tobias am 04 Januar 2017, 16:54:50
- es muss in einem zu definierenden Intervall kontinuierlich das Reading "elapsed" aktualisiert werden. Angabe in Sekunden
Ist in der aktuellen Version enthalten, wird parametriert über das attr waits und wirkt wenn der Status Play ist.

Zitat von: Tobias am 04 Januar 2017, 16:54:50
- Reading "songtime" sollte ebenfalls die Anzahl in Sekunden der aktuellen Songlänge beinhalten
songtime war eine Notlösung für das doppelte Time/time Reading. Nachdem das MPD Modul die Reading Namen 1:1 vom MPD verwendet gibt es dafür keinen Grund mehr. setstate ist in seinem Beispiel im ersten Post auch diesen Weg gegangen.

Zitat von: Tobias am 04 Januar 2017, 16:54:50
- "seekcur" aus dem MPD sollte noch ins Modul, damit man x-sekunden  vor- und zurückspulen kann
Auf der ToDo Liste

Zitat von: Tobias am 04 Januar 2017, 16:54:50
Ein Reading "currentTrackProvider" sollte verfügbar sein. Dieser sollte folgende Ausprägungen haben
    - Radio: Ein Radiostream wird abgespielt
    - Bibliothek: Eine lokale MP3 wird abgespielt
Die Unterscheidung ist heute schon möglich mit dem Reading "Name", wer das Kind unbedingt "currentTrackProvider" nennen will kann dies IMHO mitttels userReadings tun.

Zitat von: Tobias am 04 Januar 2017, 16:54:50
- In ein Reading zb.: "playlist_json" wird von extern eine playlistdefinition, passend zur gleich abgespielten Playlist, eingesteuert. Darin befindet sich auch pro Track das passende Cover. Falls dieses Reading befüllt ist, sollte unter "artist_image" das daraus extrahierte Cover zum aktuell laufenden Track liegen
Habe ich nun verstanden, die Umsetzung im Modul ist mir z.Z. aber noch unklar.
a. sehe ich da ein Timing Problem im Ablauf, da diese externe Info mit Sicherheit erst eintrifft wenn die Readings nach einem Song Wechsel bereits längst aktualisiert sind.
Ich werde das testen, allerdings muss der User dann auf den bequemen Weg verzichten die Bilder von Last.fm zu holen bzw. zu benutzen.
b. Unklar ist mir wie dein Modul 98_Medialist die exakte Zuordung Bild zu Song hinbekommt. Oder ist das pure Fleiß und Handarbeit ?
c. Sollte man darüber nachdenken das es sowohl Interpreten Bilder gibt = "artist_image" als auch Cover Bilder des Mediums LP/CD = "album_image".
Das MPD Modul kann beides dem User via Last.fm zur Verfügung stellen. Das medialist Widget kennt da heute leider nur ein Bild pro Song.

Zitat von: Tobias am 04 Januar 2017, 16:54:50
- der MPD stellt selbst kein "mute" zur Vefügung. Das könnte aber im MPD-fhem-Modul simuliert werden. Bei Mute: Volume merken und setvol=0, beim unmute entsprechend anders herum
da halte ich mich an :
Zitat von: Markus Bloch am 04 Januar 2017, 16:34:56
Schau mal hier: https://wiki.fhem.de/wiki/DevelopmentGuidelinesAV#Kommandos
Wäre cool, wenn du diese Syntax ebenfalls verwenden könntest für den Mute-Befehl. (on/off/toggle).
Maintainer der Module: MAX, MPD, UbiquitiMP, UbiquitiOut, SIP, BEOK, readingsWatcher

Tobias

#37
Zitat von: Wzut am 04 Januar 2017, 17:47:25
songtime war eine Notlösung für das doppelte Time/time Reading. Nachdem das MPD Modul die Reading Namen 1:1 vom MPD verwendet gibt es dafür keinen Grund mehr. setstate ist in seinem Beispiel im ersten Post auch diesen Weg gegangen.
das aktuelle time enthält bei mir: "<elapsed>:<songtime>
Edit: Gefunden: ist "Time". das "time" enthält beides.

Zitat von: Wzut am 04 Januar 2017, 17:47:25
Die Unterscheidung ist heute schon möglich mit dem Reading "Name", wer das Kind unbedingt "currentTrackProvider" nennen will kann dies IMHO mitttels userReadings tun.

In TabletUI ist es schwer zu prüfen ob ein REading leer oder mit eigendetwas gefüllt ist. ODer ich stell mich zu dumm an. Wenn du es also nicht als wichtig erachtest muss man ein Userreading anlegen ;)

Nachtrag: Problem ist, das das Reading "Name" bei einem Wechsel von Radio zu lokaler mp3 keinen EventTrigger bekommt. Damit wird dann das Userreading nicht angeschubst. Kannst du gut im Eventmonitor prüfen das da nix ankommt... Das Userreading müsste heißen: currentTrackProvider:Name.* {if(ReadingsVal("$name", "Name", "") eq "") {"Bibliothek"} else {"Radio"}}

Nachtrag2: Man kann das Reading "mpd_event" nutzen, im Falle lvon lokalen Dateien ist die Ausprägung "player", bei Radio ist es "playlist". Damit gehts nun

Zitat von: Wzut am 04 Januar 2017, 17:47:25
Habe ich nun verstanden, die Umsetzung im Modul ist mir z.Z. aber noch unklar.
a. sehe ich da ein Timing Problem im Ablauf, da diese externe Info mit Sicherheit erst eintrifft wenn die Readings nach einem Song Wechsel bereits längst aktualisiert sind.
Ich werde das testen, allerdings muss der User dann auf den bequemen Weg verzichten die Bilder von Last.fm zu holen bzw. zu benutzen.
b. Unklar ist mir wie dein Modul 98_Medialist die exakte Zuordung Bild zu Song hinbekommt. Oder ist das pure Fleiß und Handarbeit ?
c. Sollte man darüber nachdenken das es sowohl Interpreten Bilder gibt = "artist_image" als auch Cover Bilder des Mediums LP/CD = "album_image".
Das MPD Modul kann beides dem User via Last.fm zur Verfügung stellen. Das medialist Widget kennt da heute leider nur ein Bild pro Song.
Zuerst wird die playlist_json übergeben, dann ein "set <MPD> playlist <playlistname>" aufgerufen. Die Reihenfolge in der <playlistname> stimmt exakt mit dem playlist_json überein.
Somit steht der json string schon bereit wenn ein "set playlist" erfolgt
Bzgl der Cover: Es wird artist und album eines jeden songs ermittelt und dann zurZeit in 3 verschiendenen Quellen /Coverdatenbanken nach vorhandenen Covern gesucht. Wenn im selben lokalen Folder wie die MP3s aus der Playlist aber auch ein Cover liegt, wird dieses genutzt. Das will und kann ich aber noch verfeinern. Das hinzufügen von weiteren http Quellen ist ziemlich einfach.
Am besten das Cover liegt neben deinen in einem extra Reading. Dann kann man schön das Rotor Widget nutzen um in TabletUI automatisch zwischen den Covern zu wechseln und beide anzuzeigen.
Maintainer: Text2Speech, TrashCal, MediaList

Meine Projekte: https://github.com/tobiasfaust
* PumpControl v2: allround Bewässerungssteuerung mit ESP und FHEM
* Ein Modbus RS485 zu MQTT Gateway für SolarWechselrichter

Wzut

Update :
currentTrackProvider ist ab morgen verfügbar
playlistinfo hat nun auch bei Radiostreams einen Inhalt
album_image , wenn Album einen Inhalt hat (i.d.R. nicht bei Radiostreams)
ToDo:
playlist_json auswerten
Maintainer der Module: MAX, MPD, UbiquitiMP, UbiquitiOut, SIP, BEOK, readingsWatcher

Tobias

Vielen Dank,
CurrentTrackProvider funktioniert :)

Für dich als INfo oder Anregung fürs ToDo:
ich habe folgendes Userreading drin um die aktuelle Position in der aktuell abzuspielenden Playlist zu haben:
PlaylistPositionSec:elapsed.* {Utils_MPD_PlaylistPosition($NAME)}
# ####################################################################
# berechnet die aktuelle Position in der Playlist
# ####################################################################

sub Utils_MPD_PlaylistPosition($) {
  my ($device) = @_;
  return if(ReadingsVal($device, "mpd_event", "playlist") eq "playlist"); #Radiostream
 
  my $trackPosS = ReadingsVal($device, "elapsed", "0");
  my $plPosS = 0; #PlaylistPositionSeconds
  my $Track     = ReadingsVal($device, "Pos", "0");
  my $playlist  = ReadingsVal($device, "playlist_json", undef);
 
  my @data      = @{JSON::XS->new->decode($playlist)} if($playlist);
 
  #calculate elapsed time of whole playlist
  if($playlist) {
    for(my $j=0; $j<=$#data; $j++) {
      last if($j>=$Track);
      $plPosS += $data[$j]->{Time};
    }
  }
  $plPosS += $trackPosS;
 
  return $plPosS;
}


Somit habe ich nicht nur eine laufende Fortschrittsanzeige in TabletUI über den aktuellen TRack, sondern auch über eine laufende Fortschrittsanzeige über die gesamtSpielzeit
Maintainer: Text2Speech, TrashCal, MediaList

Meine Projekte: https://github.com/tobiasfaust
* PumpControl v2: allround Bewässerungssteuerung mit ESP und FHEM
* Ein Modbus RS485 zu MQTT Gateway für SolarWechselrichter

Wzut

Zitat von: Tobias am 05 Januar 2017, 08:55:49
Nachtrag2: Man kann das Reading "mpd_event" nutzen, im Falle lvon lokalen Dateien ist die Ausprägung "player", bei Radio ist es "playlist".
und
return if(ReadingsVal($device, "mpd_event", "playlist") eq "playlist"); #Radiostream
Ich denke hier liegst du nur zum Teil richtig , der event playlist wird laut MPD Doku erzeugt , wenn :
Zitatplaylist: the current playlist has been modified
Sicher das trift bei Radoistreams immer dann zu wenn sie den Titel Tag ändern, sei es weil ein neues Lied beginnt oder die Station andere Nachrichten verschickt.
Aber auch beim abspielen deiner eigenen Musik gibt es diesen Event, mit Sicherheit z.B. beim wechseln der Playliste.
Maintainer der Module: MAX, MPD, UbiquitiMP, UbiquitiOut, SIP, BEOK, readingsWatcher

Tobias

Ja, hab ich auch schon gemerkt, wen ich zb. volume ändere, ist das mpd_event = mixer.
Zum Glück hast du es ja jetzt korrekt eingebaut :)
Maintainer: Text2Speech, TrashCal, MediaList

Meine Projekte: https://github.com/tobiasfaust
* PumpControl v2: allround Bewässerungssteuerung mit ESP und FHEM
* Ein Modbus RS485 zu MQTT Gateway für SolarWechselrichter

fremitus

Hallo zusammen,

leider gelingt es mir nicht, das Medialist Modul zu laden. Wer kann helfen:

reload: Error:Modul 98_MediaList deactivated:
Can't locate MP3/Tag.pm in @INC (you may need to install the MP3::Tag module) (@INC contains: . /etc/perl /usr/local/lib/arm-linux-gnueabihf/perl/5.20.2 /usr/local/share/perl/5.20.2 /usr/lib/arm-linux-gnueabihf/perl5/5.20 /usr/share/perl5 /usr/lib/arm-linux-gnueabihf/perl/5.20 /usr/share/perl/5.20 /usr/local/lib/site_perl ./FHEM) at ./FHEM/98_MediaList.pm line 35, <$fh> line 69.
BEGIN failed--compilation aborted at ./FHEM/98_MediaList.pm line 35, <$fh> line 69.


gruss Peer

Tobias

#43
@fremitus,
ich habe das Modul noch nicht freigegeben da die Commandref-Doku noch fehlt. Funktionalität ist aber da, wird bei mir täglich getestet ;)
Ich häng dir mal die aktuelle Version hier an

Wikieintrag gibt schon, auch die benötigten Module: https://wiki.fhem.de/wiki/MediaList
Maintainer: Text2Speech, TrashCal, MediaList

Meine Projekte: https://github.com/tobiasfaust
* PumpControl v2: allround Bewässerungssteuerung mit ESP und FHEM
* Ein Modbus RS485 zu MQTT Gateway für SolarWechselrichter

fremitus

Danke, hat geholfen. Allerdings sieht es auf meinem 3.5 Display doch etwas schräg aus...das muss ich mir noch etwas anderes einfallen lassen.
Und Asche auf mein Haupt, ich habe ca. 4h im Internet recherchiert und bin auch über deine Anleitung gestolpert...nur die Installationsanweisung habe ich irgendwie übersehen....

gruss Peer