From d0b8d55c59d2f0358afb68e606148c5547e01f35 Mon Sep 17 00:00:00 2001
From: Wzut <>
Date: Wed, 18 Jan 2017 20:29:28 +0000
Subject: [PATCH] 73_MPD.pm: add two new set commands : channelUp and
channelDown, add new attr : unknown_artist_image, add new reading :
playlist_num
git-svn-id: https://svn.fhem.de/fhem/trunk@13144 2b470e98-0d58-463d-a4d8-8e2adae1ed80
---
fhem/FHEM/73_MPD.pm | 157 +++++++++++++++++++++++++++++++-------------
1 file changed, 110 insertions(+), 47 deletions(-)
diff --git a/fhem/FHEM/73_MPD.pm b/fhem/FHEM/73_MPD.pm
index dbf5398d8..f3d0884db 100644
--- a/fhem/FHEM/73_MPD.pm
+++ b/fhem/FHEM/73_MPD.pm
@@ -21,6 +21,7 @@
# GNU General Public License for more details.
################################################################
+# Version 1.43 - 18.01.17 add channelUp and channelDown
# Version 1.42 - 15.01.17 add Cover and playlist_json
# Version 1.41 - 12.01.17 add rawTitle
# Version 1.4 - 11.01.17 add mute, ctp, seekcur, Fix LWP:: , album cover
@@ -87,6 +88,8 @@ my %sets = (
"clear_readings:noArg" => "",
"mute:on,off,toggle" => "",
"seekcur" => "",
+ "channelUp:noArg" => "",
+ "channelDown:noArg" => "",
);
use constant clb => "command_list_begin\n";
@@ -109,7 +112,7 @@ sub MPD_Initialize($)
$hash->{UndefFn} = "MPD_Undef";
$hash->{ShutdownFn} = "MPD_Undef";
$hash->{AttrFn} = "MPD_Attr";
- $hash->{AttrList} = "disable:0,1 password loadMusic:0,1 loadPlaylists:0,1 volumeStep:1,2,5,10 titleSplit:1,0 timeout waits stateMusic:0,1 statePlaylists:0,1 lastfm_api_key image_size:-1,0,1,2,3 cache artist_summary:0,1 artist_content:0,1 player:mpd,mopidy,forked-daapd ".$readingFnAttributes;
+ $hash->{AttrList} = "disable:0,1 password loadMusic:0,1 loadPlaylists:0,1 volumeStep:1,2,5,10 titleSplit:1,0 timeout waits stateMusic:0,1 statePlaylists:0,1 lastfm_api_key image_size:-1,0,1,2,3 cache artist_summary:0,1 artist_content:0,1 player:mpd,mopidy,forked-daapd unknown_artist_image ".$readingFnAttributes;
$hash->{FW_summaryFn} = "MPD_summaryFn";
}
@@ -140,6 +143,8 @@ sub MPD_updateConfig($)
$hash->{".artist"} = "";
$hash->{".album"} = "";
$hash->{".playlist_crc"} = 0;
+ $hash->{helper}{playlistcollection}{val} = -1;
+
$hash->{".password"} = AttrVal($name, "password", "");
$hash->{TIMEOUT} = AttrVal($name, "timeout", 2);
$hash->{".sMusicL"} = AttrVal($name, "stateMusic", 1);
@@ -171,9 +176,16 @@ sub MPD_updateConfig($)
}
MPD_ClearReadings($hash); # beim Starten etwas aufräumen
+ readingsBeginUpdate($hash);
+ readingsBulkUpdate($hash,"playlist_json","");
+ readingsBulkUpdate($hash,"playlist_num","-1");
+ readingsBulkUpdate($hash,"playlistname","");
+ readingsBulkUpdate($hash,"playlistinfo","");
+ readingsBulkUpdate($hash,"playlistcollection","");
+ readingsEndUpdate($hash,0);
+
MPD_Outputs_Status($hash);
mpd_cmd($hash, clb.cle);
- #MPD_NewPlaylist($hash,mpd_cmd($hash,"i|playlistinfo|x"));
if ($hash->{".volume"} eq "0")
{ # ist Mute aktiv oder soll sie mit Absicht 0 sein ?
@@ -239,17 +251,19 @@ sub MPD_Define($$)
Log3 $name,3,"$name, Device defined.";
readingsSingleUpdate($hash,"state","defined",1);
- readingsSingleUpdate($hash,"playlist_json","",0);
+
$attr{$name}{devStateIcon} = 'play:rc_PLAY:stop stop:rc_STOP:play pause:rc_PAUSE:pause error:icoBlitz' unless (exists($attr{$name}{devStateIcon}));
$attr{$name}{icon} = 'it_radio' unless (exists($attr{$name}{icon}));
$attr{$name}{titleSplit} = '1' unless (exists($attr{$name}{titleSplit}));
$attr{$name}{player} = 'mpd' unless (exists($attr{$name}{player}));
- $attr{$name}{loadPlaylists} = '1' unless (exists($attr{$name}{loadPlaylists}));
- #$attr{$name}{cache} = 'lfm' unless (exists($attr{$name}{cache}));
- #$attr{$name}{loadMusic} = '1' unless (exists($attr{$name}{loadMusic})) && ($attr{$name}{player} ne 'mopidy');
+ $attr{$name}{loadPlaylists}= '1' unless (exists($attr{$name}{loadPlaylists}));
+ $attr{$name}{unknown_artist_image} = '/fhem/icons/1px-spacer' unless (exists($attr{$name}{unknown_artist_image}));
+ #$attr{$name}{cache} = 'lfm' unless (exists($attr{$name}{cache}));
+ #$attr{$name}{loadMusic} = '1' unless (exists($attr{$name}{loadMusic})) && ($attr{$name}{player} ne 'mopidy');
+
+ #DevIo_CloseDev($hash); das wird irgendwann auch mal kommen ... :)
- DevIo_CloseDev($hash);
$hash->{DeviceName} = $hash->{HOST}.":".$hash->{PORT};
RemoveInternalTimer($hash);
@@ -420,9 +434,9 @@ sub MPD_Set($@)
if ($cmd eq "stop")
{
readingsBeginUpdate($hash);
- readingsBulkUpdate($hash,"artist_image","/fhem/icons/1px-spacer");
+ readingsBulkUpdate($hash,"artist_image",AttrVal($name,"unknown_artist_image","/fhem/icons/1px-spacer"));
readingsBulkUpdate($hash,"artist_image_html","");
- readingsBulkUpdate($hash,"album_image","/fhem/icons/1px-spacer");
+ readingsBulkUpdate($hash,"album_image",AttrVal($name,"unknown_artist_image","/fhem/icons/1px-spacer"));
readingsBulkUpdate($hash,"album_image_html","");
readingsBulkUpdate($hash,"audio","");
readingsBulkUpdate($hash,"bitrate","");
@@ -443,11 +457,11 @@ sub MPD_Set($@)
if ($hash->{STATE} eq "play")
{
readingsBeginUpdate($hash);
- readingsBulkUpdate($hash,"artist_image","/fhem/icons/1px-spacer",1);
- readingsBulkUpdate($hash,"artist_image_html","",1);
- readingsBulkUpdate($hash,"album_image","/fhem/icons/1px-spacer",1);
- readingsBulkUpdate($hash,"album_image_html","",1);
- readingsBulkUpdate($hash,"Cover","",1);
+ readingsBulkUpdate($hash,"artist_image",AttrVal($name,"unknown_artist_image","/fhem/icons/1px-spacer"));
+ readingsBulkUpdate($hash,"artist_image_html","");
+ readingsBulkUpdate($hash,"album_image",AttrVal($name,"unknown_artist_image","/fhem/icons/1px-spacer"));
+ readingsBulkUpdate($hash,"album_image_html","");
+ readingsBulkUpdate($hash,"Cover","");
readingsEndUpdate($hash, 1);
$ret = mpd_cmd($hash, clb."stop\n".cle);
}
@@ -455,24 +469,26 @@ sub MPD_Set($@)
if ($cmd eq "previous")
{
- if (defined($hash->{READINGS}{"song"}{VAL}) > 0)
+ if (ReadingsNum($name,"song",0) > 0)
{
MPD_ClearReadings($hash);
- $ret = mpd_cmd($hash, clb."previous\n".cle);
+ return mpd_cmd($hash, clb."previous\n".cle);
}
else { return undef; }
}
if ($cmd eq "next")
{
- if ($hash->{READINGS}{"nextsong"}{VAL} != $hash->{READINGS}{"song"}{VAL})
+ if (ReadingsNum($name,"nextsong",0) != ReadingsNum($name,"song",0))
+ #if ($hash->{READINGS}{"nextsong"}{VAL} != $hash->{READINGS}{"song"}{VAL})
{
MPD_ClearReadings($hash);
- $ret = mpd_cmd($hash, clb."next\n".cle);
+ return mpd_cmd($hash, clb."next\n".cle);
}
else { return undef; }
}
+
if ($cmd eq "random")
{
my $rand = ($hash->{READINGS}{random}{VAL}) ? "0" : "1";
@@ -541,6 +557,7 @@ sub MPD_Set($@)
if ($cmd eq "seekcur")
{
+ $subcmd--; $subcmd++; # sicherstellen das subcmd numerisch ist
$ret = mpd_cmd($hash,clb."seekcur $subcmd\n".cle); # ungetestet !
}
@@ -564,23 +581,47 @@ sub MPD_Set($@)
# den Rest als ein String
$subcmd = join(" ",@a);
+ if ($cmd eq "channelUp")
+ {
+ my $i = ReadingsNum($name,"playlist_num",-1);
+ $i++;
+ if ($i <= $hash->{helper}{playlistcollection}{val})
+ {
+ $cmd = "playlist";
+ $subcmd = $hash->{helper}{playlistcollection}{$i};
+ }
+ }
+
+ if ($cmd eq "channelDown")
+ {
+ my $i = ReadingsNum($name,"playlist_num",0);
+ $i--;
+ if ($i > -1)
+ {
+ $cmd = "playlist";
+ $subcmd = $hash->{helper}{playlistcollection}{$i};
+ }
+ }
+
if ($cmd eq "playlist")
{
return "$name : no name !" if (!$subcmd);
my $error;
+ my $nr = -1;
MPD_ClearReadings($hash);
$hash->{".music"} = "";
- #my $old_list = $hash->{".playlist"};
+
$hash->{".playlist"} = $subcmd; # interne Playlisten Verwaltung
readingsSingleUpdate($hash,"playlistname",$subcmd,1);
$ret = mpd_cmd($hash, clb."stop\nclear\nload \"$subcmd\"\nplay\n".cle);
- #if ($old_list ne $hash->{".playlist"})
- #{
- # brauchen wir das hier wirklich noch ?
- #MPD_NewPlaylist($hash,mpd_cmd($hash, "i|playlistinfo|x|"));
- #}
- #
+ # welche Listen Nr ?
+ for (my $i=0; $i <= $hash->{helper}{playlistcollection}{val}; $i++)
+ {
+ $nr = $i if ($hash->{helper}{playlistcollection}{$i} eq $subcmd);
+ }
+ readingsSingleUpdate($hash,"playlist_num",$nr,1) if ($nr > -1);
+
my $json = ReadingsVal($name,"playlist_json","");
if ($json ne "")
@@ -645,7 +686,7 @@ sub MPD_Set($@)
mpd_cmd($hash, clb.cle) if ($subcmd ne "playlist");
shift @arr;
- MPD_NewPlaylist($hash,join ("\n", @arr)) if (ReadingsVal($name,"playlist_json","") eq "");
+ MPD_NewPlaylist($hash,join ("\n", @arr));# if ((ReadingsVal($name,"currentTrackProvider","Radio") eq "Radio") || (ReadingsVal($name,"playlist_json","") eq ""));
return undef;
}
@@ -763,8 +804,8 @@ sub mpd_cmd($$)
my $title = "";
my $exot = "";
my $rawTitle;
- my $name = $hash->{NAME};
- my $playlists = $hash->{".playlists"};
+ my $name = $hash->{NAME};
+ my $old_plists = $hash->{".playlists"};
$hash->{VERSION} = undef;
@@ -881,16 +922,16 @@ sub mpd_cmd($$)
readingsEndUpdate($hash, 1 );
- if ((AttrVal($name, "image_size", -1) > -1) && (ReadingsVal($name,"playlist_json","") ne ""))
+ if (AttrVal($name, "image_size", -1) > -1)
{
MPD_get_artist_info($hash, urlEncode($artist)) if ($artist);
MPD_get_album_info($hash, urlEncode($album)) if ($album);
}
- elsif (ReadingsVal($name,"playlist_json","") ne "")
+ if (ReadingsVal($name,"playlist_json","") ne "")
{
my $pos = ReadingsNum($name,"Pos",-1);
- readingsSingleUpdate($hash,"Cover",$Cover[$pos],1) if($pos > -1);
+ readingsSingleUpdate($hash,"Cover",$Cover[$pos],1) if($pos > -1) && defined($Cover[$pos]);
}
} # Ende der Ausgabe Readings und Internals, ab jetzt folgt nur noch Bildschirmausgabe
else
@@ -924,13 +965,21 @@ sub mpd_cmd($$)
print $sock "close\n";
close($sock);
- if ($hash->{".playlists"} ne $playlists) # haben sich sich die Listen geändert ?
+ if ($hash->{".playlists"} ne $old_plists) # haben sich sich die Listen geändert ?
{
$hash->{".playlists"} =~ s/\n+\z//;
- my $plists = $hash->{".playlists"};
- $plists =~ tr/\n/\:/; # Tablet UI will diese Art der Liste
- readingsSingleUpdate($hash,"playlistcollection", $plists,1);
- Log3 $name ,5 ,"$name, ".$hash->{READINGS}{"playlistcollection"}{VAL};
+ $old_plists = $hash->{".playlists"};
+ my @arr = split("\n",$old_plists);
+ my $i = 0 ;;
+ foreach (@arr)
+ {
+ $hash->{helper}{playlistcollection}{$i} = $_;
+ $i++;
+ }
+ $hash->{helper}{playlistcollection}{val} = $i-1;
+ $old_plists =~ tr/\n/\:/; # TabletUI will diese Art der Liste
+ readingsSingleUpdate($hash,"playlistcollection", $old_plists,1);
+ Log3 $name ,5 ,"$name, new playlistcollection -> $old_plists";
}
return $output; # falls es einen gibt , wenn nicht - auch gut ;)
@@ -1141,7 +1190,9 @@ sub MPD_try_idle($)
}
else
{
- Log3 $name, 4 , $name.", Idle Start failed, waiting $waits seconds for next try";
+ my $error = "Idle Start failed, waiting $waits seconds for next try";
+ Log3 $name, 4 , "$name, $error";
+ readingsSingleUpdate($hash,"last_error",$error,1);
RemoveInternalTimer($hash);
InternalTimer(gettimeofday()+$waits, "MPD_try_idle", $hash, 0);
return 0;
@@ -1174,7 +1225,10 @@ sub MPD_watch_idle($)
else
{
Log3 $name, 5 , $name.", idle PID ".$hash->{IPID}." found";
- if (($hash->{READINGS}{"presence"}{VAL} eq "present") && ($hash->{STATE} eq "play"))
+ if ((ReadingsVal($name,"presence","") eq "present") &&
+ ($hash->{STATE} eq "play") &&
+ (ReadingsVal($name,"currentTrackProvider","") ne "Radio")
+ )
{
# Wichtig um das Readings elapsed aktuell zu halten (TabletUI)
mpd_cmd($hash, "status");
@@ -1192,9 +1246,7 @@ sub MPD_get_artist_info ($$)
my ($hash, $artist) = @_;
my $name = $hash->{NAME};
return undef if (($hash->{'.artist'} eq $artist) || ($artist eq ""));
- #my $playlistinfo = ReadingsVal($hash,"playlistinfo","");
- #Log3 $name,3,"$name play :".ReadingsVal($hash,"playlistinfo","");
- #MPD_NewPlaylist($hash,mpd_cmd($hash,"i|playlistinfo|x")) if (!$playlistinfo || ($playlistinfo eq "[]"));
+
$hash->{'.artist'} = $artist;
my $data;
my $cache = AttrVal($name,"cache",""); # default
@@ -1273,6 +1325,7 @@ sub MPD_get_album_info ($$)
}
else # xml von lastfm holen
{
+ $fname = $artist."_".$album.".xml";
Log3 $name ,4,"$name, new album $fname , getting file from lastfm";
HttpUtils_NonblockingGet($param);
}
@@ -1667,7 +1720,7 @@ sub MPD_NewPlaylist($$)
for my $i (0 .. $#artist)
{
- $lastcover = "nan"; # default
+ $lastcover = AttrVal($name,"unknown_artist_image","/fhem/icons/1px-spacer"); # default
if (defined($albumUri[$i]))
{
@@ -2010,6 +2063,8 @@ If you are using Mopidy with Spotify support you may also need LWP::UserAgent ->
mpdCMD (cmd) => send a command to MPD Server ( MPD Command Ref )
mute => on,off,toggle
seekcur (time)
+ channelUp =>
+ channelDown =>
@@ -2055,6 +2110,7 @@ If you are using Mopidy with Spotify support you may also need LWP::UserAgent ->
attr rg_artist room MPD