2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-05-04 20:17:45 +00:00

contrib/98_SB_PLAYER: fixed alarm playlist url and Spotify coverart

git-svn-id: https://svn.fhem.de/fhem/trunk@8397 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
chrisd70 2015-04-07 19:48:18 +00:00
parent 9bbafdb386
commit 9816c98716

View File

@ -9,6 +9,12 @@
# #
# ############################################################################## # ##############################################################################
# #
# Written by bugster_de
#
# Contributions from: Siggi85, Oliv06, ChrisD, Markus M., Matthew, KernSani
#
# ##############################################################################
#
# This is absolutley open source. Please feel free to use just as you # This is absolutley open source. Please feel free to use just as you
# like. Please note, that no warranty is given and no liability # like. Please note, that no warranty is given and no liability
# granted # granted
@ -38,8 +44,7 @@
# DISPLAYTYPE what sort of display is there, if any # DISPLAYTYPE what sort of display is there, if any
# #
# ############################################################################## # ##############################################################################
# based on 98_SB_PLAYER.pm beta 20141120 bugster_de, Update 0031 CD/MM/Matthew
# ##############################################################################
package main; package main;
use strict; use strict;
@ -68,6 +73,8 @@ use constant { true => 1, false => 0 };
# used for $hash->{helper}{ttsstate} # used for $hash->{helper}{ttsstate}
use constant TTS_IDLE => 0; use constant TTS_IDLE => 0;
use constant TTS_TEXT2SPEECH_BUSY => 4;
use constant TTS_TEXT2SPEECH_ACTIVE => 6;
use constant TTS_POWERON => 10; use constant TTS_POWERON => 10;
use constant TTS_SAVE => 20; use constant TTS_SAVE => 20;
use constant TTS_UNSYNC => 30; use constant TTS_UNSYNC => 30;
@ -80,8 +87,12 @@ use constant TTS_STOP => 80;
use constant TTS_RESTORE => 90; use constant TTS_RESTORE => 90;
use constant TTS_SYNC => 100; use constant TTS_SYNC => 100;
use constant TTS_SYNCGROUPACTIVE => 1000; use constant TTS_SYNCGROUPACTIVE => 1000;
use constant TTS_EXT_TEXT2SPEECH_BUSY => 2004;
use constant TTS_EXT_TEXT2SPEECH_ACTIVE => 2006;
my %ttsstates = ( 0 =>'idle', my %ttsstates = ( 0 =>'idle',
4 =>'Text2Speech busy, waiting',
6 =>'Text2Speech active',
10 =>'power on', 10 =>'power on',
20 =>'save state', 20 =>'save state',
30 =>'unsync player', 30 =>'unsync player',
@ -93,7 +104,9 @@ my %ttsstates = ( 0 =>'idle',
80 =>'stopped', 80 =>'stopped',
90 =>'restore state', 90 =>'restore state',
100 =>'sync', 100 =>'sync',
1000=>'active'); 1000=>'active',
2004=>'Text2Speech busy, waiting',
2006=>'Text2Speech active');
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# Initialisation routine called upon start-up of FHEM # Initialisation routine called upon start-up of FHEM
@ -116,6 +129,9 @@ sub SB_PLAYER_Initialize( $ ) {
# CD 0007 # CD 0007
$hash->{AttrFn} = "SB_PLAYER_Attr"; $hash->{AttrFn} = "SB_PLAYER_Attr";
# CD 0032
$hash->{NotifyFn} = "SB_PLAYER_Notify";
# the attributes we have. Space separated list of attribute values in # the attributes we have. Space separated list of attribute values in
# the form name:default1,default2 # the form name:default1,default2
@ -134,6 +150,10 @@ sub SB_PLAYER_Initialize( $ ) {
$hash->{AttrList} .= "ttsOptions "; $hash->{AttrList} .= "ttsOptions ";
# CD 0030 # CD 0030
$hash->{AttrList} .= "ttsDelay "; $hash->{AttrList} .= "ttsDelay ";
# CD 0032
$hash->{AttrList} .= "ttsPrefix "; # DJAlex 665
# CD 0033
$hash->{AttrList} .= "ttsMP3FileDir ";
# CD 0007 # CD 0007
$hash->{AttrList} .= "syncVolume "; $hash->{AttrList} .= "syncVolume ";
$hash->{AttrList} .= "amplifierDelayOff "; # CD 0012 $hash->{AttrList} .= "amplifierDelayOff "; # CD 0012
@ -578,11 +598,18 @@ sub SB_PLAYER_tcb_TTSRestore( $ ) {
my(undef,$name) = split(':',$in); my(undef,$name) = split(':',$in);
my $hash = $defs{$name}; my $hash = $defs{$name};
if(!defined($hash->{helper}{ttsOptions}{nosaverestore})) { # CD 0033 start
SB_PLAYER_SetTTSState($hash,TTS_RESTORE,0,0); if(defined($hash->{helper}{ttsqueue})) {
SB_PLAYER_Recall( $hash ); SB_PLAYER_SetTTSState($hash,TTS_LOADPLAYLIST,0,0);
SB_PLAYER_LoadTalk($hash);
} else { } else {
SB_PLAYER_SetTTSState($hash,TTS_IDLE,0,1); # CD 0033 end
if(!defined($hash->{helper}{ttsOptions}{nosaverestore})) {
SB_PLAYER_SetTTSState($hash,TTS_RESTORE,0,0);
SB_PLAYER_Recall( $hash );
} else {
SB_PLAYER_SetTTSState($hash,TTS_IDLE,0,1);
}
} }
} }
# CD 0028 end # CD 0028 end
@ -829,6 +856,10 @@ sub SB_PLAYER_Parse( $$ ) {
# } # }
} elsif( $args[ 0 ] eq "cant_open" ) { } elsif( $args[ 0 ] eq "cant_open" ) {
#TODO: needs to be handled #TODO: needs to be handled
# CD 0033 TTS abbrechen bei Fehler
if($hash->{helper}{ttsstate}==TTS_WAITFORPLAY) {
SB_PLAYER_TTSStopped($hash);
}
} elsif( $args[ 0 ] eq "open" ) { } elsif( $args[ 0 ] eq "open" ) {
readingsBulkUpdate( $hash, "currentMedia", "$args[1]" ); readingsBulkUpdate( $hash, "currentMedia", "$args[1]" );
SB_PLAYER_Amplifier( $hash ); SB_PLAYER_Amplifier( $hash );
@ -1296,7 +1327,12 @@ sub SB_PLAYER_Parse( $$ ) {
elsif ($args[0] eq "ttsstopped") { elsif ($args[0] eq "ttsstopped") {
Log3( $hash, defined($hash->{helper}{ttsOptions}{debug})?0:6, "SB_PLAYER_Parse: $name: fhemrelay ttsstopped" ); Log3( $hash, defined($hash->{helper}{ttsOptions}{debug})?0:6, "SB_PLAYER_Parse: $name: fhemrelay ttsstopped" );
if($hash->{helper}{ttsstate}==TTS_PLAYING) { if($hash->{helper}{ttsstate}==TTS_PLAYING) {
SB_PLAYER_TTSStopped($hash); # CD 0034 delay ttsstopped
RemoveInternalTimer( "TTSStopped:$name");
InternalTimer( gettimeofday() + 0.01,
"SB_PLAYER_tcb_TTSStopped",
"TTSRestore:$name",
0 );
} }
} }
elsif ($args[0] eq "ttsplaying") { elsif ($args[0] eq "ttsplaying") {
@ -1373,20 +1409,38 @@ sub SB_PLAYER_tcb_TTSDelay( $ ) {
} }
# CD 0030 # CD 0030
# CD 0034
# ----------------------------------------------------------------------------
# delay ttsstopped
# ----------------------------------------------------------------------------
sub SB_PLAYER_tcb_TTSStopped( $ ) {
my($in ) = shift;
my(undef,$name) = split(':',$in);
my $hash = $defs{$name};
readingsBeginUpdate( $hash );
SB_PLAYER_TTSStopped($hash);
if( AttrVal( $name, "donotnotify", "false" ) eq "true" ) {
readingsEndUpdate( $hash, 0 );
} else {
readingsEndUpdate( $hash, 1 );
}
}
# CD 0034 end
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# called when talk is stopped, check if there are queued elements # called when talk is stopped, check if there are queued elements
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
sub SB_PLAYER_TTSStopped($) { sub SB_PLAYER_TTSStopped($) {
# readingsBulkUpdate muss aktiv sein
my ($hash) = @_; my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
if(defined($hash->{helper}{ttsqueue})) { if(defined($hash->{helper}{ttsqueue})) {
IOWrite( $hash, "$hash->{PLAYERMAC} playlist clear\n" );
for (@{$hash->{helper}{ttsqueue}}) {
IOWrite( $hash, "$hash->{PLAYERMAC} playlist add " . $_ . "\n" );
}
SB_PLAYER_SetTTSState($hash,TTS_LOADPLAYLIST,1,0); SB_PLAYER_SetTTSState($hash,TTS_LOADPLAYLIST,1,0);
delete($hash->{helper}{ttsqueue}); SB_PLAYER_LoadTalk($hash); # CD 0033
} else { } else {
SB_PLAYER_SetTTSState($hash,TTS_STOP,1,0); SB_PLAYER_SetTTSState($hash,TTS_STOP,1,0);
RemoveInternalTimer( "TTSRestore:$name"); RemoveInternalTimer( "TTSRestore:$name");
@ -1493,6 +1547,73 @@ sub SB_PLAYER_GetTTSDelay( $ ) {
} }
# CD 0030 end # CD 0030 end
# CD 0033 start
# ----------------------------------------------------------------------------
# called after Text2Speech has finished, start talk
# ----------------------------------------------------------------------------
sub SB_PLAYER_tcb_StartT2STalk( $ ) {
my($in ) = shift;
my(undef,$name) = split(':',$in);
my $hash = $defs{$name};
if($hash->{helper}{ttsstate}==TTS_TEXT2SPEECH_ACTIVE) {
# talk ist nicht aktiv
SB_PLAYER_PrepareTalk($hash);
}
SB_PLAYER_LoadTalk($hash);
}
# CD 0033 end
# ----------------------------------------------------------------------------
# the Notify function
# ----------------------------------------------------------------------------
sub SB_PLAYER_Notify( $$ ) {
my ( $hash, $dev_hash ) = @_;
my $name = $hash->{NAME}; # own name / hash
my $devName = $dev_hash->{NAME}; # Device that created the events
if ($dev_hash->{NAME} eq "global" && grep (m/^INITIALIZED$|^REREADCFG$/,@{$dev_hash->{CHANGED}})){
}
# CD 0033 start
if(defined($hash->{helper}{text2speech}{name}) && ($hash->{helper}{text2speech}{name} eq $devName)) {
$hash->{helper}{ttsExtstate}=TTS_IDLE if(!defined($hash->{helper}{ttsExtstate}));
if(($hash->{helper}{ttsstate}==TTS_TEXT2SPEECH_ACTIVE)||($hash->{helper}{ttsExtstate}==TTS_EXT_TEXT2SPEECH_ACTIVE)) {
foreach my $line (@{$dev_hash->{CHANGED}}) {
my @args=split(' ',$line);
if ($args[0] eq $name) {
if($args[1] eq "ttsadd") {
push(@{$hash->{helper}{ttsqueue}},$hash->{helper}{text2speech}{pathPrefix}.$args[2]);
}
elsif($args[1] eq 'ttsdone') {
RemoveInternalTimer( "StartTalk:$name");
InternalTimer( gettimeofday() + 0.01,
"SB_PLAYER_tcb_StartT2STalk",
"StartTalk:$name",
0 );
}
}
}
} elsif (($hash->{helper}{ttsstate}==TTS_TEXT2SPEECH_BUSY)||($hash->{helper}{ttsExtstate}==TTS_EXT_TEXT2SPEECH_BUSY)) {
# versuchen Text2Speech zu belegen
if(defined($dev_hash->{helper}{SB_PLAYER}) || (defined($dev_hash->{helper}{Text2Speech}) && @{$dev_hash->{helper}{Text2Speech}} > 0)) {
# zu spät, weiter warten
} else {
$dev_hash->{helper}{SB_PLAYER}=$name;
if($hash->{helper}{ttsstate}==TTS_TEXT2SPEECH_BUSY) {
SB_PLAYER_SetTTSState($hash,TTS_TEXT2SPEECH_ACTIVE,0,0);
} else {
$hash->{helper}{ttsExtstate}=TTS_EXT_TEXT2SPEECH_ACTIVE;
}
fhem("set $devName tts ".($hash->{helper}{text2speech}{text}));
delete($hash->{helper}{text2speech}{text});
}
}
}
# CD 0033 end
}
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# Set of a module # Set of a module
# called upon set <name> cmd, arg1, arg2, .... # called upon set <name> cmd, arg1, arg2, ....
@ -1728,99 +1849,138 @@ sub SB_PLAYER_Set( $@ ) {
( $cmd eq "TALK" ) || ( $cmd eq "TALK" ) ||
( $cmd eq "talk" ) || ( $cmd eq "talk" ) ||
( lc($cmd) eq "saytext" ) ) { # CD 0014 hinzugefügt ( lc($cmd) eq "saytext" ) ) { # CD 0014 hinzugefügt
$hash->{helper}{ttsstate}=TTS_IDLE if(!defined($hash->{helper}{ttsstate}));
$hash->{helper}{ttsExtstate}=TTS_IDLE if(!defined($hash->{helper}{ttsExtstate}));
# CD 0032 - Text2Speech verwenden ?
# CD 0033 - überarbeitet
my $useText2Speech=0;
my $errMsg;
if(AttrVal( $name, "ttslink", "none" )=~m/^Text2Speech/) {
my @extTTS=split(":",AttrVal( $name, "ttslink", "none" ));
# Device überhaupt verwendbar ?
if(defined($extTTS[1]) && defined($defs{$extTTS[1]})) {
my $ttshash=$defs{$extTTS[1]};
if(defined($ttshash->{TYPE}) && ($ttshash->{TYPE} eq 'Text2SpeechSB')) {
if(defined($ttshash->{ALSADEVICE}) && ($ttshash->{ALSADEVICE} eq 'SB_PLAYER')) {
if (AttrVal($hash->{NAME}, "TTS_Ressource", "Google") eq "Google") {
$useText2Speech=1;
$hash->{helper}{text2speech}{name}=$extTTS[1];
$hash->{helper}{text2speech}{pathPrefix}=join(':',@extTTS[2..$#extTTS]) if defined($extTTS[2]);
# Zustand Text2Speech ?
if(defined($ttshash->{helper}{SB_PLAYER}) || (defined($ttshash->{helper}{Text2Speech}) && @{$ttshash->{helper}{Text2Speech}} > 0)) {
# Text2Speech besetzt, warten
if($hash->{helper}{ttsstate}==TTS_IDLE) {
SB_PLAYER_SetTTSState($hash,TTS_TEXT2SPEECH_BUSY,0,0);
} else {
$hash->{helper}{ttsExtstate}=TTS_EXT_TEXT2SPEECH_BUSY if($hash->{helper}{ttsExtstate}==TTS_IDLE);
}
if(defined($hash->{helper}{text2speech}{text})) {
$hash->{helper}{text2speech}{text}.=" " . join( " ", @arg );
} else {
$hash->{helper}{text2speech}{text}=join( " ", @arg );
}
return;
} else {
# Text2Speech belegen
$ttshash->{helper}{SB_PLAYER}=$name;
if($hash->{helper}{ttsstate}==TTS_IDLE) {
SB_PLAYER_SetTTSState($hash,TTS_TEXT2SPEECH_ACTIVE,0,0);
} else {
$hash->{helper}{ttsExtstate}=TTS_EXT_TEXT2SPEECH_ACTIVE;
}
fhem("set $extTTS[1] tts ".join( " ", @arg ));
return;
}
} else {
$errMsg = "SB_PLAYER_Set: ".$extTTS[1].": attribute TTS_Ressource must be set to Google";
}
} else {
$errMsg = "SB_PLAYER_Set: ".$extTTS[1].": Text2Speech uses unsupported ALSADEVICE";
}
} else {
$errMsg = "SB_PLAYER_Set: ".$extTTS[1].": unsupported Text2Speech device";
}
} else {
$errMsg = "SB_PLAYER_Set: invalid Text2Speech device";
}
}
if(defined($errMsg)) {
Log3( $hash, 1, $errMsg );
return( $errMsg );
}
# CD 0028 start - komplett überarbeitet # CD 0028 start - komplett überarbeitet
# prepare text # prepare text
my $ttstext=join( " ", @arg ); my $ttstext=join( " ", @arg );
$ttstext =~ s/[\\|*~<>^\n\(\)\[\]\{\}[:cntrl:]]/ /g; $ttstext = AttrVal( $name, "ttsPrefix", "" )." ".$ttstext; # CD 0032
$ttstext =~ s/\s+/ /g;
$ttstext =~ s/^\s|\s$//g;
my %Sonderzeichen = ("ä" => "ae", "Ä" => "Ae", "ü" => "ue", "Ü" => "Ue", "ö" => "oe", "Ö" => "Oe", "ß" => "ss", my %Sonderzeichen = ("ä" => "ae", "Ä" => "Ae", "ü" => "ue", "Ü" => "Ue", "ö" => "oe", "Ö" => "Oe", "ß" => "ss",
"é" => "e", "è" => "e", "ë" => "e", "à" => "a", "ç" => "c" ); "é" => "e", "è" => "e", "ë" => "e", "à" => "a", "ç" => "c" );
my $Sonderzeichenkeys = join ("|", keys(%Sonderzeichen)); my $Sonderzeichenkeys = join ("|", keys(%Sonderzeichen));
$ttstext =~ s/($Sonderzeichenkeys)/$Sonderzeichen{$1}/g;
if (length($ttstext)==0) { if (length($ttstext)==0) {
my $msg = "SB_PLAYER_Set: no text passed for synthesis."; my $msg = "SB_PLAYER_Set: no text passed for synthesis.";
Log3( $hash, 3, $msg ); Log3( $hash, 3, $msg );
return( $msg ); return( $msg );
} }
$ttstext .= "." unless ($ttstext =~ m/^.+[.,?!:;]$/); $ttstext .= "." unless ($ttstext =~ m/^.+[.,?!:;]$/);
my @textlines; my @textlines;
my $tl=''; my $tl='';
# CD 0033 Unterstützung für Dateien und URLs hinzugefügt, teilweise aus 00_SONOS übernommen
my $targetSpeakMP3FileDir = AttrVal( $name, "ttsMP3FileDir", "" ); # CD 0033
if (length($ttstext)>0) { if (length($ttstext)>0) {
my @words=split(' ',$ttstext); my @words=split(' ',$ttstext);
for my $w (@words) { for my $w (@words) {
if((length($tl)+length($w)+1)<100) { # CD 0033 Datei ?, teilweise aus 00_SONOS übernommen
$tl.=' ' if(length($tl)>0); if ($w =~ m/\|(.*)\|/) {
$tl.=$w; push(@textlines,$tl) if($tl ne '');
$tl='';
my $filename = $1;
$filename = $targetSpeakMP3FileDir.'/'.$filename if ($filename !~ m/^(\/|[a-z]:)/i);
$filename = $filename.'.mp3' if ($filename !~ m/\.mp3$/i);
push(@textlines, '|'.$filename.'|');
} else { } else {
push(@textlines,$tl); $w =~ s/[\\|*~<>^\n\(\)\[\]\{\}[:cntrl:]]/ /g;
$tl=$w; $w =~ s/\s+/ /g;
$w =~ s/^\s|\s$//g;
$w =~ s/($Sonderzeichenkeys)/$Sonderzeichen{$1}/g;
# CD 0032 end
if((length($tl)+length($w)+1)<100) {
$tl.=' ' if(length($tl)>0);
$tl.=$w;
} else {
push(@textlines,$tl);
$tl=$w;
}
} }
} }
} }
push(@textlines,$tl) if($tl ne ''); push(@textlines,$tl) if($tl ne '');
$hash->{helper}{ttsstate}=TTS_IDLE if(!defined($hash->{helper}{ttsstate}));
if($hash->{helper}{ttsstate}==TTS_IDLE) { if($hash->{helper}{ttsstate}==TTS_IDLE) {
# talk ist nicht aktiv # talk ist nicht aktiv
if(!defined($hash->{helper}{ttsOptions}{nosaverestore})) { SB_PLAYER_PrepareTalk($hash);
SB_PLAYER_SetTTSState($hash,TTS_SAVE,0,0);
SB_PLAYER_Save( $hash ) if(!defined($hash->{helper}{saveLocked}));
}
$hash->{helper}{saveLocked}=1;
IOWrite( $hash, "$hash->{PLAYERMAC} playlist repeat 0\n" );
IOWrite( $hash, "$hash->{PLAYERMAC} playlist clear\n" );
if(defined($hash->{helper}{ttsVolume})) {
SB_PLAYER_SetTTSState($hash,TTS_SETVOLUME,0,0);
my $vol=$hash->{helper}{ttsVolume};
$vol=AttrVal( $name, "volumeLimit", 100 ) if(( $hash->{helper}{ttsVolume} > AttrVal( $name, "volumeLimit", 100 ) )&&!defined($hash->{helper}{ttsOptions}{ignorevolumelimit})); # CD 0031
IOWrite( $hash, "$hash->{PLAYERMAC} mixer volume ".$vol."\n" );
SB_PLAYER_SetSyncedVolume($hash,$hash->{helper}{ttsVolume});
}
SB_PLAYER_SetTTSState($hash,TTS_LOADPLAYLIST,0,0);
} else { } else {
} }
for (@textlines) { for my $outstr (@textlines) {
my $outstr = $_; if ($outstr =~ m/\|(.*)\|/) { # CD 0033
$outstr =~ s/\s/+/g; push(@{$hash->{helper}{ttsqueue}},$1); # CD 0033
$outstr = uri_escape( $outstr );
$outstr = AttrVal( $name, "ttslink", "none" )
. "&tl=" . AttrVal( $name, "ttslanguage", "de" )
. "&q=". $outstr;
if($hash->{helper}{ttsstate}==TTS_LOADPLAYLIST) {
# ich bin Master und talk ist nicht aktiv
IOWrite( $hash, "$hash->{PLAYERMAC} playlist add " . $outstr . "\n" );
} else { } else {
if($hash->{helper}{ttsstate}==TTS_SYNCGROUPACTIVE) { $outstr =~ s/\s/+/g;
# talk ist aktiv und ein anderer Player ist Master $outstr = uri_escape( $outstr );
IOWrite( $hash, $hash->{helper}{ttsMaster}." fhemrelay ttsadd ".$outstr."\n" ); $outstr = AttrVal( $name, "ttslink", "none" )
} else { . "&tl=" . AttrVal( $name, "ttslanguage", "de" )
# talk ist aktiv und ich bin Master . "&q=". $outstr;
push(@{$hash->{helper}{ttsqueue}},$outstr); push(@{$hash->{helper}{ttsqueue}},$outstr);
}
} }
} }
if($hash->{helper}{ttsstate}!=TTS_SYNCGROUPACTIVE) {
# andere Player in Gruppe informieren SB_PLAYER_LoadTalk($hash); # CD 0033
if (defined($hash->{SYNCGROUP}) && ($hash->{SYNCGROUP} ne '?') && ($hash->{SYNCMASTER} ne 'none')) {
my @pl=split(",",$hash->{SYNCGROUP}.",".$hash->{SYNCMASTER});
foreach (@pl) {
if ($hash->{PLAYERMAC} ne $_) {
IOWrite( $hash, "$_ fhemrelay ttsactive ".$hash->{PLAYERMAC}."\n" );
IOWrite( $hash, "$_ fhemrelay ttsforcegroupon\n" ) if(defined($hash->{helper}{ttsOptions}{forcegroupon})); # CD 0030
}
}
}
#if(($hash->{helper}{ttsstate}==TTS_STOP)||(ReadingsVal( "$name", "playStatus", "x" ) ne "playing")) {
# IOWrite( $hash, "$hash->{PLAYERMAC} play\n" );
# SB_PLAYER_SetTTSState($hash,TTS_WAITFORPLAY,0,0);
#}
}
# CD 0028 end # CD 0028 end
} elsif( ( $cmd eq "playlist" ) || } elsif( ( $cmd eq "playlist" ) ||
( $cmd eq "PLAYLIST" ) || ( $cmd eq "PLAYLIST" ) ||
@ -2034,6 +2194,77 @@ sub SB_PLAYER_Set( $@ ) {
} }
# CD 0033 hinzugefügt
# ----------------------------------------------------------------------------
# add talk segments to playlist
# ----------------------------------------------------------------------------
sub SB_PLAYER_LoadTalk($) {
# gespeicherte Elemente in Playlist einfügen
my ( $hash ) = @_;
my $name = $hash->{NAME};
if(defined($hash->{helper}{ttsqueue})) {
if(($hash->{helper}{ttsstate}==TTS_LOADPLAYLIST)||($hash->{helper}{ttsstate}==TTS_SYNCGROUPACTIVE)) {
IOWrite( $hash, "$hash->{PLAYERMAC} playlist clear\n" ) if($hash->{helper}{ttsstate}==TTS_LOADPLAYLIST);
for (@{$hash->{helper}{ttsqueue}}) {
if($hash->{helper}{ttsstate}==TTS_LOADPLAYLIST) {
# ich bin Master und talk ist nicht aktiv
IOWrite( $hash, "$hash->{PLAYERMAC} playlist add " . $_ . "\n" );
} else {
# talk ist aktiv und ein anderer Player ist Master
IOWrite( $hash, $hash->{helper}{ttsMaster}." fhemrelay ttsadd ".$_."\n" );
}
}
delete($hash->{helper}{ttsqueue});
if($hash->{helper}{ttsstate}!=TTS_SYNCGROUPACTIVE) {
# andere Player in Gruppe informieren
if (defined($hash->{SYNCGROUP}) && ($hash->{SYNCGROUP} ne '?') && ($hash->{SYNCMASTER} ne 'none')) {
my @pl=split(",",$hash->{SYNCGROUP}.",".$hash->{SYNCMASTER});
foreach (@pl) {
if ($hash->{PLAYERMAC} ne $_) {
IOWrite( $hash, "$_ fhemrelay ttsactive ".$hash->{PLAYERMAC}."\n" );
IOWrite( $hash, "$_ fhemrelay ttsforcegroupon\n" ) if(defined($hash->{helper}{ttsOptions}{forcegroupon})); # CD 0030
}
}
}
}
} else {
# talk ist aktiv und ich bin Master
# warten bis stop
}
}
}
# CD 0033 hinzugefügt
# ----------------------------------------------------------------------------
# prepare player for talk
# ----------------------------------------------------------------------------
sub SB_PLAYER_PrepareTalk($) {
# kein readingsBulkUpdate
# aktuellen Stand abspeichern, playlist löschen, Lautstärke setzen
my ( $hash ) = @_;
my $name = $hash->{NAME};
# talk ist nicht aktiv
if(!defined($hash->{helper}{ttsOptions}{nosaverestore})) {
SB_PLAYER_SetTTSState($hash,TTS_SAVE,0,0);
SB_PLAYER_Save( $hash ) if(!defined($hash->{helper}{saveLocked}));
}
$hash->{helper}{saveLocked}=1;
IOWrite( $hash, "$hash->{PLAYERMAC} playlist repeat 0\n" );
IOWrite( $hash, "$hash->{PLAYERMAC} playlist clear\n" );
if(defined($hash->{helper}{ttsVolume})) {
SB_PLAYER_SetTTSState($hash,TTS_SETVOLUME,0,0);
my $vol=$hash->{helper}{ttsVolume};
$vol=AttrVal( $name, "volumeLimit", 100 ) if(( $hash->{helper}{ttsVolume} > AttrVal( $name, "volumeLimit", 100 ) )&&!defined($hash->{helper}{ttsOptions}{ignorevolumelimit})); # CD 0031
IOWrite( $hash, "$hash->{PLAYERMAC} mixer volume ".$vol."\n" );
SB_PLAYER_SetSyncedVolume($hash,$hash->{helper}{ttsVolume});
}
SB_PLAYER_SetTTSState($hash,TTS_LOADPLAYLIST,0,0);
}
# CD 0014 start # CD 0014 start
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# recall player state # recall player state
@ -2209,7 +2440,7 @@ sub SB_PLAYER_Save($) {
if(($hash->{helper}{ttsstate}!=TTS_IDLE) && defined($hash->{helper}{ttsOptions}{debugsaverestore})) { if(($hash->{helper}{ttsstate}!=TTS_IDLE) && defined($hash->{helper}{ttsOptions}{debugsaverestore})) {
# CD 0029 start # CD 0029 start
if(defined($hash->{helper}{ttsOptions}{internalsave})) { if(defined($hash->{helper}{ttsOptions}{internalsave})) {
Log3( $hash, 0, "SB_PLAYER_Save: $name: forcing {helper}{playlistIds}: ".$hash->{helper}{playlistIds}); Log3( $hash, 0, "SB_PLAYER_Save: $name: forcing {helper}{playlistIds}: ".$hash->{helper}{playlistIds}) if(defined($hash->{helper}{playlistIds})); # CD 0033 if added
#Log3( $hash, 0, "SB_PLAYER_Save: $name: warning - negative playlist ids cannot be restored") if ($hash->{helper}{playlistIds}=~ /-/); #Log3( $hash, 0, "SB_PLAYER_Save: $name: warning - negative playlist ids cannot be restored") if ($hash->{helper}{playlistIds}=~ /-/);
} else { } else {
Log3( $hash, 0, "SB_PLAYER_Save: $name: multiple tracks in playlist, shuffle active, using {helper}{playlistIds} (".$hash->{helper}{playlistIds}.")"); Log3( $hash, 0, "SB_PLAYER_Save: $name: multiple tracks in playlist, shuffle active, using {helper}{playlistIds} (".$hash->{helper}{playlistIds}.")");
@ -2292,7 +2523,14 @@ sub SB_PLAYER_Alarm( $$@ ) {
} }
} }
# CD 0015 end # CD 0015 end
$cmdstr .= " playlist:" . uri_escape(decode('utf-8',$url)); # CD 0015 uri_escape und join hinzugefügt # CD 0020 decode hinzugefügt # CD 0034 überprüfen ob gültige url, wenn nicht, versuchen file:// anzuhängen
if($url !~ /:\/\//) {
$url='/' . $url if ($url =~ /^[a-zA-Z]:\\/); # für Windows
$url=~ s/\\/\//g;
$url='file://' . $url;
}
# CD 0034 end
$cmdstr .= " url:" . uri_escape(decode('utf-8',$url)); # CD 0015 uri_escape und join hinzugefügt # CD 0020 decode hinzugefügt # CD 0034 playlist: in url: geändert
} }
$cmdstr .= " time:$secs\n"; $cmdstr .= " time:$secs\n";
@ -2338,8 +2576,15 @@ sub SB_PLAYER_Alarm( $$@ ) {
} }
} }
} }
$cmdstr .= " playlist:" . uri_escape(decode('utf-8',$url)); # CD 0017 decode hinzugefügt # CD 0034 überprüfen ob gültige url, wenn nicht, versuchen file:// anzuhängen
IOWrite( $hash, $cmdstr ); # CD 0017 reaktiviert if($url !~ /:\/\//) {
$url='/' . $url if ($url =~ /^[a-zA-Z]:\\/); # für Windows
$url=~ s/\\/\//g;
$url='file://' . $url;
}
# CD 0034 end
$cmdstr .= "url:" . uri_escape(decode('utf-8',$url)); # CD 0017 decode hinzugefügt # CD 0034 playlist: in url: geändert
IOWrite( $hash, $cmdstr . "\n" ); # CD 0017 reaktiviert # CD 0034 \n hinzugefügt
} else { } else {
my $msg = "SB_PLAYER_Set: alarm, no value for sound."; my $msg = "SB_PLAYER_Set: alarm, no value for sound.";
Log3( $hash, 3, $msg ); Log3( $hash, 3, $msg );
@ -2843,7 +3088,11 @@ sub SB_PLAYER_IsValidMAC( $ ) {
my $dd = "$d$d"; my $dd = "$d$d";
if( $instr =~ /($dd([:-])$dd(\2$dd){4})/og ) { if( $instr =~ /($dd([:-])$dd(\2$dd){4})/og ) {
if( $instr =~ /^(00[:-]){5}(00)$/) { # CD 0032 00:00:00:00:00:00 is not a valid MAC
return( 0 );
} else {
return( 1 ); return( 1 );
}
} else { } else {
return( 0 ); return( 0 );
} }
@ -2988,10 +3237,19 @@ sub SB_PLAYER_CoverArt( $ ) {
} elsif( $hash->{ISREMOTESTREAM} eq "1" ) { # CD 0017 Abfrage || ( $hash->{ISREMOTESTREAM} == 1 ) entfernt } elsif( $hash->{ISREMOTESTREAM} eq "1" ) { # CD 0017 Abfrage || ( $hash->{ISREMOTESTREAM} == 1 ) entfernt
# CD 0011 überprüfen ob überhaupt eine URL vorhanden ist # CD 0011 überprüfen ob überhaupt eine URL vorhanden ist
if($hash->{ARTWORKURL} ne "?") { if($hash->{ARTWORKURL} ne "?") {
$hash->{COVERARTURL} = "http://www.mysqueezebox.com/public/" . # CD 0034 Abfrage für Spotify und LMS < 7.8, ungetest, #674, KernSani
"imageproxy?u=" . $hash->{ARTWORKURL} . # CD 0035 Code von KernSani übernommen, #676
"&h=" . AttrVal( $name, "coverartheight", 50 ) . if ($hash->{ARTWORKURL} =~ /spotifyimage%2Fspotify/) {
"&w=". AttrVal( $name, "coverartwidth", 50 ); my $cover = "cover.jpg";
my $coverArtWithSize = "cover_".AttrVal( $name, "coverartheight", 50 )."x".AttrVal( $name, "coverartwidth", 50 )."_o.jpg";
$hash->{ARTWORKURL} =~ s/$cover/$coverArtWithSize/g;
$hash->{COVERARTURL} = "http://" . $hash->{SBSERVER} . "/" . uri_unescape($hash->{ARTWORKURL});
} else {
$hash->{COVERARTURL} = "http://www.mysqueezebox.com/public/" .
"imageproxy?u=" . $hash->{ARTWORKURL} .
"&h=" . AttrVal( $name, "coverartheight", 50 ) .
"&w=". AttrVal( $name, "coverartwidth", 50 );
}
} else { } else {
$hash->{COVERARTURL} = "http://" . $hash->{SBSERVER} . "/music/" . $hash->{COVERARTURL} = "http://" . $hash->{SBSERVER} . "/music/" .
$hash->{COVERID} . "/cover_" . AttrVal( $name, "coverartheight", 50 ) . $hash->{COVERID} . "/cover_" . AttrVal( $name, "coverartheight", 50 ) .
@ -3354,7 +3612,7 @@ sub SB_PLAYER_EstimateElapsedTime( $ ) {
my $d=ReadingsVal($name,"duration",0); my $d=ReadingsVal($name,"duration",0);
# nur wenn duration>0 # nur wenn duration>0
if($d>0) { if(($d ne '?')&&($d>0)) { # CD 0033 check for '?'
# wenn {helper}{elapsedTime} bekannt ist als Basis verwenden # wenn {helper}{elapsedTime} bekannt ist als Basis verwenden
if((defined($hash->{helper}{elapsedTime}))&&($hash->{helper}{elapsedTime}{VAL}>0)) { if((defined($hash->{helper}{elapsedTime}))&&($hash->{helper}{elapsedTime}{VAL}>0)) {
$hash->{helper}{elapsedTime}{VAL}=$hash->{helper}{elapsedTime}{VAL}+(gettimeofday()-$hash->{helper}{elapsedTime}{TS}); $hash->{helper}{elapsedTime}{VAL}=$hash->{helper}{elapsedTime}{VAL}+(gettimeofday()-$hash->{helper}{elapsedTime}{TS});