2016-10-01 16:46:46 +00:00
# ##############################################################################
2015-03-19 20:37:01 +00:00
# $Id$
2014-02-20 23:34:51 +00:00
#
2015-03-19 20:37:01 +00:00
# FHEM Module for Squeezebox Players
2014-02-20 23:34:51 +00:00
#
2015-03-19 20:37:01 +00:00
# ##############################################################################
2014-02-20 23:34:51 +00:00
#
# used to interact with Squeezebox Player
#
2015-03-19 20:37:01 +00:00
# ##############################################################################
2014-02-20 23:34:51 +00:00
#
2015-04-07 19:48:18 +00:00
# Written by bugster_de
#
2016-10-01 16:46:46 +00:00
# Contributions from: Siggi85, Oliv06, ChrisD, Markus M., Matthew, KernSani,
2017-05-28 19:14:57 +00:00
# Heppel, Eberhard, Elektrolurch
2015-04-07 19:48:18 +00:00
#
# ##############################################################################
#
2014-02-20 23:34:51 +00:00
# This is absolutley open source. Please feel free to use just as you
2017-05-28 19:14:57 +00:00
# like. Please note, that no warranty is given and no liability
2014-03-22 23:32:21 +00:00
# granted
2014-02-20 23:34:51 +00:00
#
2015-03-19 20:37:01 +00:00
# ##############################################################################
2014-02-20 23:34:51 +00:00
#
# we have the following readings
2015-03-19 20:37:01 +00:00
# state on or off
2014-02-20 23:34:51 +00:00
#
2015-03-19 20:37:01 +00:00
# ##############################################################################
2014-02-20 23:34:51 +00:00
#
# we have the following attributes
# timer the time frequency how often we check
# volumeStep the volume delta when sending the up or down command
# timeout the timeout in seconds for the TCP connection
#
2015-03-19 20:37:01 +00:00
# ##############################################################################
2014-02-20 23:34:51 +00:00
# we have the following internals (all UPPERCASE)
# PLAYERIP the IP adress of the player in the network
# PLAYERID the unique identifier of the player. Mostly the MAC
# SERVER based on the IP and the port as given
# IP the IP of the server
# PLAYERNAME the name of the Player
# CONNECTION the connection status to the server
# CANPOWEROFF is the player supporting power off commands
# MODEL the model of the player
# DISPLAYTYPE what sort of display is there, if any
#
2015-03-19 20:37:01 +00:00
# ##############################################################################
2016-10-01 16:46:46 +00:00
2014-02-20 23:34:51 +00:00
package main ;
use strict ;
use warnings ;
use IO::Socket ;
use URI::Escape ;
2014-07-06 22:14:26 +00:00
use Encode qw( decode encode ) ;
2014-02-20 23:34:51 +00:00
# include this for the self-calling timer we use later on
use Time::HiRes qw( gettimeofday ) ;
2016-10-01 16:46:46 +00:00
no if $] >= 5.017011 , warnings = > 'experimental::smartmatch' ;
2014-07-23 06:22:52 +00:00
use constant { true = > 1 , false = > 0 } ;
2017-05-28 19:14:57 +00:00
sub SB_PLAYER_SonginfoHandleQueue ($) ; # CD 0075
2017-06-04 09:59:54 +00:00
sub SB_PLAYER_RemoveInternalTimers ($) ; # CD 0078
2017-07-26 19:25:07 +00:00
sub SB_PLAYER_ftuiMedialist ($) ; # CD 0082
2017-05-28 19:14:57 +00:00
2014-02-20 23:34:51 +00:00
# the list of favorites
2015-03-19 20:37:01 +00:00
# CD 0010 moved to $hash->{helper}{SB_PLAYER_Favs}, fixes problem on module reload
#my %SB_PLAYER_Favs;
2014-02-20 23:34:51 +00:00
2014-07-06 22:14:26 +00:00
# the list of sync masters
2015-03-19 20:37:01 +00:00
# CD 0010 moved to $hash->{helper}{SB_PLAYER_SyncMasters}, fixes problem on module reload
#my %SB_PLAYER_SyncMasters;
2014-07-06 22:14:26 +00:00
# the list of Server side playlists
2015-03-19 20:37:01 +00:00
# CD 0010 moved to $hash->{helper}{SB_PLAYER_Playlists}, fixes problem on module reload
#my %SB_PLAYER_Playlists;
# used for $hash->{helper}{ttsstate}
use constant TTS_IDLE = > 0 ;
2015-04-07 19:48:18 +00:00
use constant TTS_TEXT2SPEECH_BUSY = > 4 ;
use constant TTS_TEXT2SPEECH_ACTIVE = > 6 ;
2015-06-18 20:23:54 +00:00
use constant TTS_WAITFORPOWERON = > 10 ;
2015-03-19 20:37:01 +00:00
use constant TTS_SAVE = > 20 ;
use constant TTS_UNSYNC = > 30 ;
use constant TTS_SETVOLUME = > 40 ;
use constant TTS_LOADPLAYLIST = > 50 ;
use constant TTS_DELAY = > 55 ;
use constant TTS_WAITFORPLAY = > 60 ;
use constant TTS_PLAYING = > 70 ;
use constant TTS_STOP = > 80 ;
use constant TTS_RESTORE = > 90 ;
use constant TTS_SYNC = > 100 ;
use constant TTS_SYNCGROUPACTIVE = > 1000 ;
2015-04-07 19:48:18 +00:00
use constant TTS_EXT_TEXT2SPEECH_BUSY = > 2004 ;
use constant TTS_EXT_TEXT2SPEECH_ACTIVE = > 2006 ;
2015-03-19 20:37:01 +00:00
my % ttsstates = ( 0 = > 'idle' ,
2015-04-07 19:48:18 +00:00
4 = > 'Text2Speech busy, waiting' ,
6 = > 'Text2Speech active' ,
2015-06-18 20:23:54 +00:00
10 = > 'wait for power on' ,
2015-03-19 20:37:01 +00:00
20 = > 'save state' ,
30 = > 'unsync player' ,
40 = > 'set volume' ,
50 = > 'load playlist' ,
55 = > 'delay' ,
60 = > 'wait for play' ,
70 = > 'playing' ,
80 = > 'stopped' ,
90 = > 'restore state' ,
100 = > 'sync' ,
2015-04-07 19:48:18 +00:00
1000 = > 'active' ,
2004 = > 'Text2Speech busy, waiting' ,
2006 = > 'Text2Speech active' ) ;
2017-05-28 19:14:57 +00:00
2015-06-18 20:23:54 +00:00
my $ SB_PLAYER_hasDataDumper = 1 ; # CD 0036
2017-05-28 19:14:57 +00:00
2014-02-20 23:34:51 +00:00
# ----------------------------------------------------------------------------
# Initialisation routine called upon start-up of FHEM
# ----------------------------------------------------------------------------
sub SB_PLAYER_Initialize ( $ ) {
my ( $ hash ) = @ _ ;
# the commands we provide to FHEM
2017-05-28 19:14:57 +00:00
# installs the respecitive call-backs for FHEM. The call back in quotes
2014-02-20 23:34:51 +00:00
# must be realised as a sub later on in the file
$ hash - > { DefFn } = "SB_PLAYER_Define" ;
$ hash - > { UndefFn } = "SB_PLAYER_Undef" ;
$ hash - > { ShutdownFn } = "SB_PLAYER_Shutdown" ;
$ hash - > { SetFn } = "SB_PLAYER_Set" ;
$ hash - > { GetFn } = "SB_PLAYER_Get" ;
# for the two step approach
$ hash - > { Match } = "^SB_PLAYER:" ;
$ hash - > { ParseFn } = "SB_PLAYER_Parse" ;
2015-03-19 20:37:01 +00:00
# CD 0007
$ hash - > { AttrFn } = "SB_PLAYER_Attr" ;
2015-04-07 19:48:18 +00:00
# CD 0032
$ hash - > { NotifyFn } = "SB_PLAYER_Notify" ;
2017-05-28 19:14:57 +00:00
# the attributes we have. Space separated list of attribute values in
2014-02-20 23:34:51 +00:00
# the form name:default1,default2
2017-05-28 19:14:57 +00:00
$ hash - > { AttrList } = "IODev do_not_notify:1,0 " ; # CD 0077 ignore:1,0 entfernt, nicht verwendet
$ hash - > { AttrList } . = "volumeStep volumeLimit " ;
$ hash - > { AttrList } . = "ttslanguage:de,en,fr ttslink:multiple,Google,VoiceRSS " ;
2014-02-20 23:34:51 +00:00
$ hash - > { AttrList } . = "donotnotify:true,false " ;
2017-05-28 19:14:57 +00:00
$ hash - > { AttrList } . = "idismac " ; # CD 0077 nicht verwendet, entfernen
$ hash - > { AttrList } . = "serverautoon " ; # CD 0077 nicht verwendet, entfernen
2014-02-20 23:34:51 +00:00
$ hash - > { AttrList } . = "fadeinsecs " ;
2014-07-09 22:29:45 +00:00
$ hash - > { AttrList } . = "amplifier:on,play " ;
2017-07-26 19:25:07 +00:00
$ hash - > { AttrList } . = "coverartheight:50,100,200,400,800,1600 " ;
$ hash - > { AttrList } . = "coverartwidth:50,100,200,400,800,1600 " ;
2015-03-19 20:37:01 +00:00
# CD 0028
$ hash - > { AttrList } . = "ttsVolume " ;
2017-05-28 19:14:57 +00:00
$ hash - > { AttrList } . = "ttsOptions:multiple-strict,debug,debugsaverestore,unsync,nosaverestore,forcegroupon,ignorevolumelimit,eventondone " ; # CD 0062 Auswahl vorgeben
$ hash - > { AttrList } . = "trackPositionQueryInterval " ; # CD 0064
$ hash - > { AttrList } . = "sortFavorites:1,0 sortPlaylists:1,0 " ; # CD 0064
$ hash - > { AttrList } . = "volumeOffset " ; # CD 0065
2015-03-19 20:37:01 +00:00
# CD 0030
$ hash - > { AttrList } . = "ttsDelay " ;
2015-04-07 19:48:18 +00:00
# CD 0032
$ hash - > { AttrList } . = "ttsPrefix " ; # DJAlex 665
# CD 0033
$ hash - > { AttrList } . = "ttsMP3FileDir " ;
2015-11-02 08:26:30 +00:00
$ hash - > { AttrList } . = "ttsAPIKey " ; # CD 0045
2015-03-19 20:37:01 +00:00
# CD 0007
$ hash - > { AttrList } . = "syncVolume " ;
$ hash - > { AttrList } . = "amplifierDelayOff " ; # CD 0012
$ hash - > { AttrList } . = "updateReadingsOnSet:true,false " ; # CD 0017
2015-06-18 20:23:54 +00:00
$ hash - > { AttrList } . = "statusRequestInterval " ; # CD 0037
2016-10-01 16:46:46 +00:00
$ hash - > { AttrList } . = "syncedNamesSource:LMS,FHEM " ; # CD 0055
2017-08-26 19:46:07 +00:00
$ hash - > { AttrList } . = "ftuiSupport:multiple-strict,1,0,medialist,favorites,playlists " ; # CD 0065 neu # CD 0086 Auswahl hinzugef<65> gt
2014-02-20 23:34:51 +00:00
$ hash - > { AttrList } . = $ readingFnAttributes ;
2017-05-28 19:14:57 +00:00
2015-06-18 20:23:54 +00:00
# CD 0036 aus 37_sonosBookmarker
eval "use Data::Dumper" ;
2017-05-28 19:14:57 +00:00
$ SB_PLAYER_hasDataDumper = 0 if ( $@ ) ;
2014-02-20 23:34:51 +00:00
}
2015-03-19 20:37:01 +00:00
# CD 0007 start
# ----------------------------------------------------------------------------
2017-05-28 19:14:57 +00:00
# Attr functions
2015-03-19 20:37:01 +00:00
# ----------------------------------------------------------------------------
sub SB_PLAYER_Attr ( @ ) {
my $ cmd = shift ( @ _ ) ;
my $ name = shift ( @ _ ) ;
my @ args = @ _ ;
my $ hash = $ defs { $ name } ;
2017-05-28 19:14:57 +00:00
2015-03-19 20:37:01 +00:00
Log ( 4 , "SB_PLAYER_Attr($name): called with @args" ) ;
if ( $ args [ 0 ] eq "syncVolume" ) {
if ( $ cmd eq "set" ) {
if ( defined ( $ args [ 1 ] ) ) {
if ( $ args [ 1 ] eq "1" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playerpref syncVolume 1\n" ) ;
} else {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playerpref syncVolume 0\n" ) ;
}
} else {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playerpref syncVolume ?\n" ) ;
}
} else {
2017-05-28 19:14:57 +00:00
2015-03-19 20:37:01 +00:00
}
}
2016-10-01 16:46:46 +00:00
# CD 0012 start - bei <20> nderung des Attributes Zustand <20> berpr<70> fen
2015-03-19 20:37:01 +00:00
elsif ( $ args [ 0 ] eq "amplifier" ) {
RemoveInternalTimer ( "DelayAmplifier:$name" ) ;
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + 0.01 ,
2016-10-01 16:46:46 +00:00
"SB_PLAYER_tcb_DelayAmplifier" , # CD 0014 Name ge<67> ndert
2017-05-28 19:14:57 +00:00
"DelayAmplifier:$name" ,
2015-03-19 20:37:01 +00:00
0 ) ;
}
2015-11-02 08:26:30 +00:00
# CD 0043 start
elsif ( $ args [ 0 ] eq "amplifierDelayOff" ) {
$ hash - > { helper } { amplifierDelayOffStop } = 0 ;
$ hash - > { helper } { amplifierDelayOffPower } = 0 ;
$ hash - > { helper } { amplifierDelayOffPause } = 0 ;
if ( $ cmd eq "set" ) {
if ( defined ( $ args [ 1 ] ) ) {
my @ delays = split ( ',' , $ args [ 1 ] ) ;
$ hash - > { helper } { amplifierDelayOffStop } = $ delays [ 0 ] + 0 if defined ( $ delays [ 0 ] ) ;
$ hash - > { helper } { amplifierDelayOffPower } = $ delays [ 0 ] + 0 if defined ( $ delays [ 0 ] ) ;
$ hash - > { helper } { amplifierDelayOffPause } = $ delays [ 1 ] + 0 if defined ( $ delays [ 1 ] ) ;
} else {
return "missing value for amplifierDelayOff" ;
}
} else {
2017-05-28 19:14:57 +00:00
2015-11-02 08:26:30 +00:00
}
}
# CD 0043 end
2015-03-19 20:37:01 +00:00
# CD 0028
elsif ( $ args [ 0 ] eq "ttsVolume" ) {
if ( $ cmd eq "set" ) {
if ( defined ( $ args [ 1 ] ) ) {
return "invalid value for ttsVolume" if ( ( $ args [ 1 ] < 0 ) || ( $ args [ 1 ] > 100 ) ) ;
$ hash - > { helper } { ttsVolume } = $ args [ 1 ] ;
} else {
return "invalid value for ttsVolume" ;
}
} else {
delete ( $ hash - > { helper } { ttsVolume } ) if ( defined ( $ hash - > { helper } { ttsVolume } ) ) ;
}
}
elsif ( $ args [ 0 ] eq "ttsOptions" ) {
if ( $ cmd eq "set" ) {
if ( defined ( $ args [ 1 ] ) ) {
my @ options = split ( ',' , $ args [ 1 ] ) ;
delete ( $ hash - > { helper } { ttsOptions } ) if ( defined ( $ hash - > { helper } { ttsOptions } ) ) ;
for my $ opt ( @ options ) {
$ hash - > { helper } { ttsOptions } { debug } = 1 if ( $ opt =~ m/debug/ ) ;
$ hash - > { helper } { ttsOptions } { debugsaverestore } = 1 if ( $ opt =~ m/debugsaverestore/ ) ; # CD 0029
$ hash - > { helper } { ttsOptions } { unsync } = 1 if ( $ opt =~ m/unsync/ ) ;
$ hash - > { helper } { ttsOptions } { nosaverestore } = 1 if ( $ opt =~ m/nosaverestore/ ) ;
$ hash - > { helper } { ttsOptions } { forcegroupon } = 1 if ( $ opt =~ m/forcegroupon/ ) ;
$ hash - > { helper } { ttsOptions } { internalsave } = 1 if ( $ opt =~ m/internalsave/ ) ; # CD 0029
$ hash - > { helper } { ttsOptions } { ignorevolumelimit } = 1 if ( $ opt =~ m/ignorevolumelimit/ ) ; # CD 0031
2016-10-01 16:46:46 +00:00
$ hash - > { helper } { ttsOptions } { doubleescape } = 1 if ( $ opt =~ m/doubleescape/ ) ; # CD 0059
2017-05-28 19:14:57 +00:00
$ hash - > { helper } { ttsOptions } { eventondone } = 1 if ( $ opt =~ m/eventondone/ ) ; # CD 0061
2015-03-19 20:37:01 +00:00
}
} else {
return "invalid value for ttsOptions" ;
}
} else {
delete ( $ hash - > { helper } { ttsOptions } ) if ( defined ( $ hash - > { helper } { ttsOptions } ) ) ;
}
}
# CD 0030
2017-05-28 19:14:57 +00:00
elsif ( $ args [ 0 ] eq "ttsDelay" ) {
2015-03-19 20:37:01 +00:00
if ( $ cmd eq "set" ) {
if ( defined ( $ args [ 1 ] ) ) {
my @ options = split ( ',' , $ args [ 1 ] ) ;
$ hash - > { helper } { ttsDelay } { PowerIsOn } = $ options [ 0 ] ;
if ( defined ( $ options [ 1 ] ) ) {
$ hash - > { helper } { ttsDelay } { PowerIsOff } = $ options [ 1 ] ;
} else {
$ hash - > { helper } { ttsDelay } { PowerIsOff } = $ options [ 0 ] ;
}
} else {
return "invalid value for ttsDelay" ;
}
} else {
delete ( $ hash - > { helper } { ttsDelay } ) if ( defined ( $ hash - > { helper } { ttsDelay } ) ) ;
}
2015-06-18 20:23:54 +00:00
}
# CD 0037
elsif ( $ args [ 0 ] eq "statusRequestInterval" ) {
RemoveInternalTimer ( $ hash ) ;
if ( $ cmd eq "set" ) {
if ( defined ( $ args [ 1 ] ) ) {
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + $ args [ 1 ] ,
"SB_PLAYER_GetStatus" ,
$ hash ,
2015-06-18 20:23:54 +00:00
0 ) if $ args [ 1 ] > 0 ;
} else {
return "missing value for statusRequestInterval" ;
}
} else {
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + 5 ,
"SB_PLAYER_GetStatus" ,
$ hash ,
2015-06-18 20:23:54 +00:00
0 ) ;
}
}
2016-10-01 16:46:46 +00:00
# CD 0055 start
elsif ( $ args [ 0 ] eq "syncedNamesSource" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} status 0 500 tags:Kcu\n" ) if ( $ init_done > 0 ) ;
}
# CD 0055 end
2017-05-28 19:14:57 +00:00
# CD 0064 start
elsif ( $ args [ 0 ] eq "trackPositionQueryInterval" ) {
if ( $ cmd eq "set" ) {
RemoveInternalTimer ( "QueryElapsedTime:$name" ) ;
if ( ( ReadingsVal ( $ name , "playStatus" , "x" ) eq "playing" ) && ( $ args [ 1 ] > 0 ) ) {
InternalTimer ( gettimeofday ( ) + $ args [ 1 ] ,
"SB_PLAYER_tcb_QueryElapsedTime" ,
"QueryElapsedTime:$name" ,
0 ) ;
}
}
}
elsif ( $ args [ 0 ] eq "sortPlaylists" ) {
if ( $ cmd eq "set" ) {
if ( $ args [ 1 ] eq "1" ) {
my @ radios = split ( ',' , $ hash - > { SERVERPLAYLISTS } ) ;
$ hash - > { SERVERPLAYLISTS } = join ( ',' , sort { "\L$a" cmp "\L$b" } @ radios ) ;
}
}
}
elsif ( $ args [ 0 ] eq "sortFavorites" ) {
if ( $ cmd eq "set" ) {
if ( $ args [ 1 ] eq "1" ) {
my @ radios = split ( ',' , $ hash - > { FAVSTR } ) ;
$ hash - > { FAVSTR } = join ( ',' , sort { "\L$a" cmp "\L$b" } @ radios ) ;
}
}
}
# CD 0064 end
# CD 0065 start
elsif ( $ args [ 0 ] eq "ftuiSupport" ) {
my $ dodelete = 0 ;
if ( $ cmd eq "set" ) {
2017-08-26 19:46:07 +00:00
# CD 0086 Readings einzeln aktivierbar
my @ options = split ( ',' , $ args [ 1 ] ) ;
delete ( $ hash - > { helper } { ftuiSupport } ) if ( defined ( $ hash - > { helper } { ftuiSupport } ) ) ;
$ hash - > { helper } { ftuiSupport } { enable } = ( $ args [ 1 ] eq '0' ) ? 0 : 1 ;
for my $ opt ( @ options ) {
$ hash - > { helper } { ftuiSupport } { favorites } = 1 if ( $ opt =~ m/favorites/ ) || ( $ opt eq '1' ) ;
$ hash - > { helper } { ftuiSupport } { playlists } = 1 if ( $ opt =~ m/playlists/ ) || ( $ opt eq '1' ) ;
$ hash - > { helper } { ftuiSupport } { medialist } = 1 if ( $ opt =~ m/medialist/ ) || ( $ opt eq '1' ) ;
}
if ( defined ( $ hash - > { helper } { ftuiSupport } ) ) {
2017-07-26 19:25:07 +00:00
# CD 0082 Readings setzen (kein manueller statusRequest mehr n<> tig)
readingsBeginUpdate ( $ hash ) ;
2017-08-26 19:46:07 +00:00
if ( defined ( $ hash - > { helper } { ftuiSupport } { favorites } ) ) {
my $ t = $ hash - > { FAVSTR } ;
$ t =~ s/,/:/g ;
readingsBulkUpdate ( $ hash , "ftuiFavoritesItems" , $ t ) ;
$ t =~ s/_/ /g ;
readingsBulkUpdate ( $ hash , "ftuiFavoritesAlias" , $ t ) ;
}
if ( defined ( $ hash - > { helper } { ftuiSupport } { playlists } ) ) {
my $ t = $ hash - > { SERVERPLAYLISTS } ;
$ t =~ s/,/:/g ;
readingsBulkUpdate ( $ hash , "ftuiPlaylistsItems" , $ t ) ;
$ t =~ s/_/ /g ;
readingsBulkUpdate ( $ hash , "ftuiPlaylistsAlias" , $ t ) ;
}
2017-07-26 19:25:07 +00:00
if ( AttrVal ( $ name , "donotnotify" , "false" ) eq "true" ) {
readingsEndUpdate ( $ hash , 0 ) ;
} else {
readingsEndUpdate ( $ hash , 1 ) ;
}
# CD 0082 end
2017-05-28 19:14:57 +00:00
delete ( $ hash - > { SONGINFOQUEUE } ) if ( defined ( $ hash - > { SONGINFOQUEUE } ) ) ; # CD 0072
2017-08-26 19:46:07 +00:00
$ hash - > { helper } { songinfoquery } = '' ; # CD 0084
$ hash - > { helper } { songinfocounter } = 0 ; # CD 0084
$ hash - > { helper } { songinfopending } = 0 ; # CD 0084
if ( defined ( $ hash - > { helper } { ftuiSupport } { medialist } ) ) {
if ( defined ( $ hash - > { helper } { playlistIds } ) ) {
$ hash - > { helper } { playlistInfoRetries } = 5 ; # CD 0076
my @ ids = split ( ',' , $ hash - > { helper } { playlistIds } ) ;
foreach ( @ ids ) {
# CD 0084 verz<72> gert abfragen, ansonsten Probleme bei schwacher Hardware
SB_PLAYER_SonginfoAddQueue ( $ hash , $ _ , 0 ) unless ( ( defined ( $ hash - > { helper } { playlistInfo } { $ _ } ) && ! defined ( $ hash - > { helper } { playlistInfo } { $ _ } { remote } ) ) || ( $ _ == 0 ) ) ;
}
SB_PLAYER_SonginfoAddQueue ( $ hash , 0 , 0 ) ;
2017-05-28 19:14:57 +00:00
}
}
}
} else {
2017-08-26 19:46:07 +00:00
delete ( $ hash - > { helper } { ftuiSupport } ) if ( defined ( $ hash - > { helper } { ftuiSupport } ) ) ;
$ hash - > { helper } { ftuiSupport } { enable } = 0 ;
2017-05-28 19:14:57 +00:00
$ dodelete = 1 ;
}
# CD 0068 start
2017-08-26 19:46:07 +00:00
if ( ( $ dodelete == 1 ) || ! defined ( $ hash - > { helper } { ftuiSupport } { medialist } ) ) {
2017-05-28 19:14:57 +00:00
delete ( $ hash - > { READINGS } { ftuiMedialist } ) if defined ( $ hash - > { READINGS } { ftuiMedialist } ) ;
2017-08-26 19:46:07 +00:00
}
if ( ( $ dodelete == 1 ) || ! defined ( $ hash - > { helper } { ftuiSupport } { playlists } ) ) {
2017-05-28 19:14:57 +00:00
delete ( $ hash - > { READINGS } { ftuiPlaylistsItems } ) if defined ( $ hash - > { READINGS } { ftuiPlaylistsItems } ) ;
delete ( $ hash - > { READINGS } { ftuiPlaylistsAlias } ) if defined ( $ hash - > { READINGS } { ftuiPlaylistsAlias } ) ;
2017-08-26 19:46:07 +00:00
}
if ( ( $ dodelete == 1 ) || ! defined ( $ hash - > { helper } { ftuiSupport } { favorites } ) ) {
2017-05-28 19:14:57 +00:00
delete ( $ hash - > { READINGS } { ftuiFavoritesItems } ) if defined ( $ hash - > { READINGS } { ftuiFavoritesItems } ) ;
delete ( $ hash - > { READINGS } { ftuiFavoritesAlias } ) if defined ( $ hash - > { READINGS } { ftuiFavoritesAlias } ) ;
}
# CD 0068 end
}
# CD 0065 end
2015-03-19 20:37:01 +00:00
return ;
# CD 0012
}
# CD 0007 end
2014-02-20 23:34:51 +00:00
# ----------------------------------------------------------------------------
# Definition of a module instance
# called when defining an element via fhem.cfg
# ----------------------------------------------------------------------------
sub SB_PLAYER_Define ( $$ ) {
my ( $ hash , $ def ) = @ _ ;
2017-05-28 19:14:57 +00:00
2014-02-20 23:34:51 +00:00
my $ name = $ hash - > { NAME } ;
2017-05-28 19:14:57 +00:00
2014-02-20 23:34:51 +00:00
my @ a = split ( "[ \t][ \t]*" , $ def ) ;
2017-05-28 19:14:57 +00:00
2014-02-20 23:34:51 +00:00
# do we have the right number of arguments?
2014-07-09 22:29:45 +00:00
if ( ( @ a < 3 ) || ( @ a > 5 ) ) {
2015-03-19 20:37:01 +00:00
Log3 ( $ hash , 1 , "SB_PLAYER_Define: falsche Anzahl an Argumenten" ) ;
return ( "wrong syntax: define <name> SB_PLAYER <playerid> " .
"<ampl:FHEM_NAME> <coverart:FHEMNAME>" ) ;
2014-02-20 23:34:51 +00:00
}
2017-05-28 19:14:57 +00:00
2014-07-09 22:29:45 +00:00
# remove the name and our type
2014-07-23 06:22:52 +00:00
# my $name = shift( @a );
shift ( @ a ) ; # name
shift ( @ a ) ; # type
2014-07-09 22:29:45 +00:00
2014-02-20 23:34:51 +00:00
# needed for manual creation of the Player; autocreate checks in ParseFn
2014-07-09 22:29:45 +00:00
if ( SB_PLAYER_IsValidMAC ( $ a [ 0 ] ) == 1 ) {
2015-03-19 20:37:01 +00:00
# the MAC adress is valid
$ hash - > { PLAYERMAC } = lc ( $ a [ 0 ] ) ; # CD 0026 lc added
2014-02-20 23:34:51 +00:00
} else {
2017-05-28 19:14:57 +00:00
my $ msg = "SB_PLAYER_Define: playerid ist keine MAC Adresse " .
2015-03-19 20:37:01 +00:00
"im Format xx:xx:xx:xx:xx:xx oder xx-xx-xx-xx-xx-xx" ;
Log3 ( $ hash , 1 , $ msg ) ;
return ( $ msg ) ;
2014-02-20 23:34:51 +00:00
}
2014-07-09 22:29:45 +00:00
# shift the MAC away
shift ( @ a ) ;
$ hash - > { AMPLIFIER } = "none" ;
$ hash - > { COVERARTLINK } = "none" ;
foreach ( @ a ) {
2015-03-19 20:37:01 +00:00
if ( $ _ =~ /^(ampl:)(.*)/ ) {
$ hash - > { AMPLIFIER } = $ 2 ;
next ;
} elsif ( $ _ =~ /^(coverart:)(.*)/ ) {
$ hash - > { COVERARTLINK } = $ 2 ;
next ;
} else {
next ;
}
2014-07-09 22:29:45 +00:00
}
2014-02-20 23:34:51 +00:00
Log3 ( $ hash , 5 , "SB_PLAYER_Define successfully called" ) ;
# remove the : from the ID
my @ idbuf = split ( ":" , $ hash - > { PLAYERMAC } ) ;
my $ uniqueid = join ( "" , @ idbuf ) ;
# our unique id
$ hash - > { FHEMUID } = $ uniqueid ;
# do the alarms fade in
2015-03-19 20:37:01 +00:00
#$hash->{ALARMSFADEIN} = "?"; # CD 0016 deaktiviert, -> Reading
2014-02-20 23:34:51 +00:00
# the number of alarms of the player
2015-03-19 20:37:01 +00:00
$ hash - > { helper } { ALARMSCOUNT } = 0 ; # CD 0016 ALARMSCOUNT nach {helper} verschoben
2014-02-20 23:34:51 +00:00
# for the two step approach
$ modules { SB_PLAYER } { defptr } { $ uniqueid } = $ hash ;
AssignIoPort ( $ hash ) ;
2015-11-02 08:26:30 +00:00
if ( ! defined ( $ hash - > { OLDDEF } ) ) { # CD 0044
# preset the internals
# can the player power off
$ hash - > { CANPOWEROFF } = "?" ;
# graphical or textual display
$ hash - > { DISPLAYTYPE } = "?" ;
# which model do we see?
$ hash - > { MODEL } = "?" ;
# what's the ip adress of the player
$ hash - > { PLAYERIP } = "?" ;
# the name of the player as assigned by the server
$ hash - > { PLAYERNAME } = "?" ;
# the last alarm we did set
$ hash - > { LASTALARM } = 1 ;
# the reference to the favorites list
$ hash - > { FAVREF } = " " ;
# the command for selecting a favorite
$ hash - > { FAVSET } = "favorites" ;
# the entry in the global hash table
$ hash - > { FAVSTR } = "not,yet,defined " ;
# the selected favorites
$ hash - > { FAVSELECT } = "not" ;
# last received answer from the server
$ hash - > { LASTANSWER } = "none" ;
# for sync group (multi-room)
$ hash - > { SYNCMASTER } = "?" ;
$ hash - > { SYNCGROUP } = "?" ;
$ hash - > { SYNCED } = "?" ;
# seconds until sleeping
$ hash - > { WILLSLEEPIN } = "?" ;
# the list of potential sync masters
$ hash - > { SYNCMASTERS } = "not,yet,defined" ;
# is currently playing a remote stream
$ hash - > { ISREMOTESTREAM } = "?" ;
# the server side playlists
$ hash - > { SERVERPLAYLISTS } = "not,yet,defined" ;
# the URL to the artwork
$ hash - > { ARTWORKURL } = "?" ;
$ hash - > { COVERARTURL } = "?" ;
$ hash - > { COVERID } = "?" ;
# the IP and Port of the Server
$ hash - > { SBSERVER } = "?" ;
}
2017-05-28 19:14:57 +00:00
2014-02-20 23:34:51 +00:00
# preset the attributes
2014-07-09 22:29:45 +00:00
# volume delta settings
2014-02-20 23:34:51 +00:00
if ( ! defined ( $ attr { $ name } { volumeStep } ) ) {
2015-03-19 20:37:01 +00:00
$ attr { $ name } { volumeStep } = 10 ;
2014-02-20 23:34:51 +00:00
}
2014-07-23 06:22:52 +00:00
# Upper limit for volume setting
if ( ! defined ( $ attr { $ name } { volumeLimit } ) ) {
2015-03-19 20:37:01 +00:00
$ attr { $ name } { volumeLimit } = 100 ;
2014-07-23 06:22:52 +00:00
}
2014-07-09 22:29:45 +00:00
# how many secs for fade in when going from stop to play
2014-02-20 23:34:51 +00:00
if ( ! defined ( $ attr { $ name } { fadeinsecs } ) ) {
2016-10-01 16:46:46 +00:00
$ attr { $ name } { fadeinsecs } = "10" ;
2014-02-20 23:34:51 +00:00
}
2014-07-09 22:29:45 +00:00
# do not create FHEM notifies (true=no notifies)
2014-02-20 23:34:51 +00:00
if ( ! defined ( $ attr { $ name } { donotnotify } ) ) {
2015-03-19 20:37:01 +00:00
$ attr { $ name } { donotnotify } = "true" ;
2014-02-20 23:34:51 +00:00
}
2017-05-28 19:14:57 +00:00
# is the ID the MAC adress # CD 0077 nicht verwendet, deaktiviert
#if( !defined( $attr{$name}{idismac} ) ) {
# $attr{$name}{idismac} = "true";
#}
2014-02-20 23:34:51 +00:00
2014-07-09 22:29:45 +00:00
# the language for text2speech
if ( ! defined ( $ attr { $ name } { ttslanguage } ) ) {
2015-03-19 20:37:01 +00:00
$ attr { $ name } { ttslanguage } = "de" ;
2014-07-09 22:29:45 +00:00
}
# link to the text2speech engine
2014-02-20 23:34:51 +00:00
if ( ! defined ( $ attr { $ name } { ttslink } ) ) {
2017-05-28 19:14:57 +00:00
$ attr { $ name } { ttslink } = "http://translate.google.com" .
2016-10-01 16:46:46 +00:00
"/translate_tts?ie=UTF-8&tl=<LANG>&q=<TEXT>&client=tw-ob" ; # CD 0045 Format ge<67> ndert, &client=t&prev=input hinzugef<65> gt, CD 0048 client=tw-ob verwenden
2014-02-20 23:34:51 +00:00
}
2017-05-28 19:14:57 +00:00
# turn on the server when player is used # CD 0077 nicht verwendet, deaktiviert
#if( !defined( $attr{$name}{serverautoon} ) ) {
# $attr{$name}{serverautoon} = "true";
#}
2014-02-20 23:34:51 +00:00
2014-07-09 22:29:45 +00:00
# amplifier on/off when play/pause or on/off
if ( ! defined ( $ attr { $ name } { amplifier } ) ) {
2015-03-19 20:37:01 +00:00
$ attr { $ name } { amplifier } = "play" ;
2014-07-09 22:29:45 +00:00
}
# height and width of the cover art for the URL
2014-07-09 22:47:58 +00:00
if ( ! defined ( $ attr { $ name } { coverartwidth } ) ) {
2015-03-19 20:37:01 +00:00
$ attr { $ name } { coverartwidth } = 50 ;
2014-07-09 22:47:58 +00:00
}
if ( ! defined ( $ attr { $ name } { coverartheight } ) ) {
2015-03-19 20:37:01 +00:00
$ attr { $ name } { coverartheight } = 50 ;
2014-07-09 22:29:45 +00:00
}
2014-02-20 23:34:51 +00:00
# Preset our readings if undefined
my $ tn = TimeNow ( ) ;
# according to development guidelines of FHEM AV Module
if ( ! defined ( $ hash - > { READINGS } { presence } { VAL } ) ) {
2015-03-19 20:37:01 +00:00
$ hash - > { READINGS } { presence } { VAL } = "?" ;
2017-05-28 19:14:57 +00:00
$ hash - > { READINGS } { presence } { TIME } = $ tn ;
2014-02-20 23:34:51 +00:00
}
# according to development guidelines of FHEM AV Module
if ( ! defined ( $ hash - > { READINGS } { power } { VAL } ) ) {
2015-03-19 20:37:01 +00:00
$ hash - > { READINGS } { power } { VAL } = "?" ;
2017-05-28 19:14:57 +00:00
$ hash - > { READINGS } { power } { TIME } = $ tn ;
2014-02-20 23:34:51 +00:00
}
# the last unkown command
2016-10-01 16:46:46 +00:00
if ( ! defined ( $ hash - > { READINGS } { lastunknowncmd } { VAL } ) ) {
$ hash - > { READINGS } { lastunknowncmd } { VAL } = "none" ;
2017-05-28 19:14:57 +00:00
$ hash - > { READINGS } { lastunknowncmd } { TIME } = $ tn ;
2014-02-20 23:34:51 +00:00
}
# the last unkown IR command
if ( ! defined ( $ hash - > { READINGS } { lastir } { VAL } ) ) {
2015-03-19 20:37:01 +00:00
$ hash - > { READINGS } { lastir } { VAL } = "?" ;
2017-05-28 19:14:57 +00:00
$ hash - > { READINGS } { lastir } { TIME } = $ tn ;
2014-02-20 23:34:51 +00:00
}
2015-03-19 20:37:01 +00:00
# the id of the alarm we create # CD 0015 deaktiviert
# if( !defined( $hash->{READINGS}{alarmid1}{VAL} ) ) {
# $hash->{READINGS}{alarmid1}{VAL} = "none";
2017-05-28 19:14:57 +00:00
# $hash->{READINGS}{alarmid1}{TIME} = $tn;
2015-03-19 20:37:01 +00:00
# }
2014-02-20 23:34:51 +00:00
2015-03-19 20:37:01 +00:00
# if( !defined( $hash->{READINGS}{alarmid2}{VAL} ) ) {
# $hash->{READINGS}{alarmid2}{VAL} = "none";
2017-05-28 19:14:57 +00:00
# $hash->{READINGS}{alarmid2}{TIME} = $tn;
2015-03-19 20:37:01 +00:00
# }
2014-02-20 23:34:51 +00:00
# values according to standard
if ( ! defined ( $ hash - > { READINGS } { playStatus } { VAL } ) ) {
2015-03-19 20:37:01 +00:00
$ hash - > { READINGS } { playStatus } { VAL } = "?" ;
2017-05-28 19:14:57 +00:00
$ hash - > { READINGS } { playStatus } { TIME } = $ tn ;
2014-02-20 23:34:51 +00:00
}
if ( ! defined ( $ hash - > { READINGS } { currentArtist } { VAL } ) ) {
2015-03-19 20:37:01 +00:00
$ hash - > { READINGS } { currentArtist } { VAL } = "?" ;
2017-05-28 19:14:57 +00:00
$ hash - > { READINGS } { currentArtist } { TIME } = $ tn ;
2014-02-20 23:34:51 +00:00
}
if ( ! defined ( $ hash - > { READINGS } { currentAlbum } { VAL } ) ) {
2015-03-19 20:37:01 +00:00
$ hash - > { READINGS } { currentAlbum } { VAL } = "?" ;
2017-05-28 19:14:57 +00:00
$ hash - > { READINGS } { currentAlbum } { TIME } = $ tn ;
2014-02-20 23:34:51 +00:00
}
if ( ! defined ( $ hash - > { READINGS } { currentTitle } { VAL } ) ) {
2015-03-19 20:37:01 +00:00
$ hash - > { READINGS } { currentTitle } { VAL } = "?" ;
2017-05-28 19:14:57 +00:00
$ hash - > { READINGS } { currentTitle } { TIME } = $ tn ;
2014-02-20 23:34:51 +00:00
}
2014-07-23 11:22:23 +00:00
if ( ! defined ( $ hash - > { READINGS } { favorites } { VAL } ) ) {
2015-03-19 20:37:01 +00:00
$ hash - > { READINGS } { favorites } { VAL } = "not" ;
2017-05-28 19:14:57 +00:00
$ hash - > { READINGS } { favorites } { TIME } = $ tn ;
2014-07-23 11:22:23 +00:00
}
2014-07-23 11:29:30 +00:00
if ( ! defined ( $ hash - > { READINGS } { playlists } { VAL } ) ) {
2015-03-19 20:37:01 +00:00
$ hash - > { READINGS } { playlists } { VAL } = "not" ;
2017-05-28 19:14:57 +00:00
$ hash - > { READINGS } { playlists } { TIME } = $ tn ;
2014-07-23 11:29:30 +00:00
}
2014-02-20 23:34:51 +00:00
# for the FHEM AV Development Guidelinses
# we use this to store the currently playing ID to later on return to
if ( ! defined ( $ hash - > { READINGS } { currentMedia } { VAL } ) ) {
2015-03-19 20:37:01 +00:00
$ hash - > { READINGS } { currentMedia } { VAL } = "?" ;
2017-05-28 19:14:57 +00:00
$ hash - > { READINGS } { currentMedia } { TIME } = $ tn ;
2014-02-20 23:34:51 +00:00
}
if ( ! defined ( $ hash - > { READINGS } { currentPlaylistName } { VAL } ) ) {
2015-03-19 20:37:01 +00:00
$ hash - > { READINGS } { currentPlaylistName } { VAL } = "?" ;
2017-05-28 19:14:57 +00:00
$ hash - > { READINGS } { currentPlaylistName } { TIME } = $ tn ;
2014-02-20 23:34:51 +00:00
}
2014-03-22 23:32:21 +00:00
if ( ! defined ( $ hash - > { READINGS } { currentPlaylistUrl } { VAL } ) ) {
2015-03-19 20:37:01 +00:00
$ hash - > { READINGS } { currentPlaylistUrl } { VAL } = "?" ;
2017-05-28 19:14:57 +00:00
$ hash - > { READINGS } { currentPlaylistUrl } { TIME } = $ tn ;
2014-02-20 23:34:51 +00:00
}
if ( ! defined ( $ hash - > { READINGS } { volume } { VAL } ) ) {
2015-03-19 20:37:01 +00:00
$ hash - > { READINGS } { volume } { VAL } = 0 ;
2017-05-28 19:14:57 +00:00
$ hash - > { READINGS } { volume } { TIME } = $ tn ;
2014-02-20 23:34:51 +00:00
}
if ( ! defined ( $ hash - > { READINGS } { volumeStraight } { VAL } ) ) {
2015-03-19 20:37:01 +00:00
$ hash - > { READINGS } { volumeStraight } { VAL } = "?" ;
2017-05-28 19:14:57 +00:00
$ hash - > { READINGS } { volumeStraight } { TIME } = $ tn ;
2014-02-20 23:34:51 +00:00
}
if ( ! defined ( $ hash - > { READINGS } { connected } { VAL } ) ) {
2017-05-28 19:14:57 +00:00
$ hash - > { READINGS } { connected } { VAL } = "?" ;
$ hash - > { READINGS } { connected } { TIME } = $ tn ;
2014-02-20 23:34:51 +00:00
}
if ( ! defined ( $ hash - > { READINGS } { signalstrength } { VAL } ) ) {
2015-03-19 20:37:01 +00:00
$ hash - > { READINGS } { signalstrength } { VAL } = "?" ;
2017-05-28 19:14:57 +00:00
$ hash - > { READINGS } { currentTitle } { TIME } = $ tn ;
2014-02-20 23:34:51 +00:00
}
if ( ! defined ( $ hash - > { READINGS } { shuffle } { VAL } ) ) {
2015-03-19 20:37:01 +00:00
$ hash - > { READINGS } { shuffle } { VAL } = "?" ;
2017-05-28 19:14:57 +00:00
$ hash - > { READINGS } { currentTitle } { TIME } = $ tn ;
2014-02-20 23:34:51 +00:00
}
if ( ! defined ( $ hash - > { READINGS } { repeat } { VAL } ) ) {
2015-03-19 20:37:01 +00:00
$ hash - > { READINGS } { repeat } { VAL } = "?" ;
2017-05-28 19:14:57 +00:00
$ hash - > { READINGS } { currentTitle } { TIME } = $ tn ;
2014-02-20 23:34:51 +00:00
}
if ( ! defined ( $ hash - > { READINGS } { state } { VAL } ) ) {
2017-05-28 19:14:57 +00:00
$ hash - > { READINGS } { state } { VAL } = "?" ;
$ hash - > { READINGS } { state } { TIME } = $ tn ;
2014-02-20 23:34:51 +00:00
}
2015-11-02 08:26:30 +00:00
# mrbreil 0047 start
if ( ! defined ( $ hash - > { READINGS } { currentTrackPosition } { VAL } ) ) {
$ hash - > { READINGS } { currentTrackPosition } { VAL } = 0 ;
$ hash - > { READINGS } { currentTrackPosition } { TIME } = $ tn ;
}
# mrbreil 0047 end
2015-03-19 20:37:01 +00:00
$ hash - > { helper } { ttsstate } = TTS_IDLE ; # CD 0028
2015-11-02 08:26:30 +00:00
2017-05-28 19:14:57 +00:00
$ hash - > { helper } { noStopEventUntil } = 0 ; # CD 0063
2015-11-02 08:26:30 +00:00
if ( ! defined ( $ hash - > { OLDDEF } ) ) { # CD 0044
SB_PLAYER_LoadPlayerStates ( $ hash ) if ( $ SB_PLAYER_hasDataDumper == 1 ) ; # CD 0036
2017-05-28 19:14:57 +00:00
2015-11-02 08:26:30 +00:00
$ hash - > { helper } { playerStatusOK } = 0 ; # CD 0042
$ hash - > { helper } { playerStatusOKCounter } = 0 ; # CD 0042
$ hash - > { helper } { amplifierDelayOffStop } = 0 ; # CD 0043
$ hash - > { helper } { amplifierDelayOffPower } = 0 ; # CD 0043
$ hash - > { helper } { amplifierDelayOffPause } = 0 ; # CD 0043
2017-05-28 19:14:57 +00:00
$ hash - > { helper } { lmsvolume } = 0 ; # CD 0065
2015-11-02 08:26:30 +00:00
}
2017-08-26 19:46:07 +00:00
$ hash - > { helper } { songinfoquery } = '' ; # CD 0084
$ hash - > { helper } { songinfocounter } = 0 ; # CD 0084
$ hash - > { helper } { songinfopending } = 0 ; # CD 0084
2015-03-19 20:37:01 +00:00
# do and update of the status
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + 10 ,
"SB_PLAYER_GetStatus" ,
$ hash ,
2015-03-19 20:37:01 +00:00
0 ) ;
2014-07-06 22:14:26 +00:00
2017-06-27 18:38:12 +00:00
notifyRegexpChanged ( $ hash , "global" ) ; # CD 0080
2015-03-19 20:37:01 +00:00
return ( undef ) ;
}
2014-07-06 22:14:26 +00:00
2015-03-19 20:37:01 +00:00
# CD 0002 start
2016-10-01 16:46:46 +00:00
sub SB_PLAYER_tcb_QueryCoverArt ($) { # CD 0014 Name ge<67> ndert
2015-03-19 20:37:01 +00:00
my ( $ in ) = shift ;
my ( undef , $ name ) = split ( ':' , $ in ) ;
my $ hash = $ defs { $ name } ;
#Log 0,"delayed cover art query";
IOWrite ( $ hash , "$hash->{PLAYERMAC} status - 1 tags:Kcu\n" ) ; # CD 0030 u added to tags
# CD 0005 query cover art for synced players
if ( $ hash - > { PLAYERMAC } eq $ hash - > { SYNCMASTER } ) {
2016-10-01 16:46:46 +00:00
if ( defined ( $ hash - > { SYNCGROUP } ) && ( $ hash - > { SYNCGROUP } ne '?' ) && ( $ hash - > { SYNCMASTER } ne 'none' ) ) { # CD 0018 none hinzugef<65> gt
2015-03-19 20:37:01 +00:00
my @ pl = split ( "," , $ hash - > { SYNCGROUP } ) ;
foreach ( @ pl ) {
2016-10-01 16:46:46 +00:00
IOWrite ( $ hash , "$_ status - 1 tags:Kcu\n" ) ; # CD 0039 u hinzugef<65> gt
2015-03-19 20:37:01 +00:00
}
}
2014-03-22 23:32:21 +00:00
}
2015-03-19 20:37:01 +00:00
}
# CD 0002 end
2014-03-22 23:32:21 +00:00
2015-03-19 20:37:01 +00:00
# CD 0014 start
sub SB_PLAYER_tcb_DeleteRecallPause ($) {
my ( $ in ) = shift ;
my ( undef , $ name ) = split ( ':' , $ in ) ;
my $ hash = $ defs { $ name } ;
2014-02-20 23:34:51 +00:00
2015-03-19 20:37:01 +00:00
delete ( $ hash - > { helper } { recallPause } ) ;
}
sub SB_PLAYER_QueryElapsedTime ($) {
my ( $ hash ) = @ _ ;
2017-05-28 19:14:57 +00:00
my $ qi = AttrVal ( $ hash - > { NAME } , "trackPositionQueryInterval" , 5 ) ; # CD 0064
if ( ! defined ( $ hash - > { helper } { lastTimeQuery } ) || ( $ hash - > { helper } { lastTimeQuery } < gettimeofday ( ) - $ qi ) ) {
2015-03-19 20:37:01 +00:00
#Log 0,"Querying time, last: $hash->{helper}{lastTimeQuery}, now: ".gettimeofday();
$ hash - > { helper } { lastTimeQuery } = gettimeofday ( ) ;
IOWrite ( $ hash , "$hash->{PLAYERMAC} time ?\n" ) ;
}
2014-02-20 23:34:51 +00:00
}
2015-03-19 20:37:01 +00:00
# CD 0014 end
2014-02-20 23:34:51 +00:00
2015-11-02 08:26:30 +00:00
# CD 0047 start
sub SB_PLAYER_tcb_QueryElapsedTime ( $ ) {
my ( $ in ) = shift ;
my ( undef , $ name ) = split ( ':' , $ in ) ;
my $ hash = $ defs { $ name } ;
2017-05-28 19:14:57 +00:00
my $ qi = AttrVal ( $ hash - > { NAME } , "trackPositionQueryInterval" , 5 ) ; # CD 0064
2015-11-02 08:26:30 +00:00
SB_PLAYER_QueryElapsedTime ( $ hash ) ;
RemoveInternalTimer ( "QueryElapsedTime:$name" ) ;
2017-05-28 19:14:57 +00:00
if ( ( ReadingsVal ( $ name , "playStatus" , "x" ) eq "playing" ) && ( $ qi > 0 ) ) {
InternalTimer ( gettimeofday ( ) + $ qi ,
"SB_PLAYER_tcb_QueryElapsedTime" ,
"QueryElapsedTime:$name" ,
2015-11-02 08:26:30 +00:00
0 ) ;
}
}
# CD 0047 end
2017-05-28 19:14:57 +00:00
2015-03-19 20:37:01 +00:00
# CD 0028 start
sub SB_PLAYER_tcb_TTSRestore ( $ ) {
my ( $ in ) = shift ;
my ( undef , $ name ) = split ( ':' , $ in ) ;
my $ hash = $ defs { $ name } ;
2015-04-07 19:48:18 +00:00
# CD 0033 start
if ( defined ( $ hash - > { helper } { ttsqueue } ) ) {
SB_PLAYER_SetTTSState ( $ hash , TTS_LOADPLAYLIST , 0 , 0 ) ;
SB_PLAYER_LoadTalk ( $ hash ) ;
2015-03-19 20:37:01 +00:00
} else {
2015-04-07 19:48:18 +00:00
# CD 0033 end
2017-05-28 19:14:57 +00:00
if ( ! defined ( $ hash - > { helper } { ttsOptions } { nosaverestore } ) && ! defined ( $ hash - > { helper } { sgTalkActive } ) ) { # CD 0063 sgTalkActive hinzugef<65> gt
2015-04-07 19:48:18 +00:00
SB_PLAYER_SetTTSState ( $ hash , TTS_RESTORE , 0 , 0 ) ;
2015-06-18 20:23:54 +00:00
SB_PLAYER_Recall ( $ hash , "xxTTSxx del" ) ;
2015-04-07 19:48:18 +00:00
} else {
SB_PLAYER_SetTTSState ( $ hash , TTS_IDLE , 0 , 1 ) ;
2017-05-28 19:14:57 +00:00
delete $ hash - > { helper } { sgTalkActive } if defined ( $ hash - > { helper } { sgTalkActive } ) ; # CD 0063
2015-04-07 19:48:18 +00:00
}
2015-03-19 20:37:01 +00:00
}
}
# CD 0028 end
2014-02-20 23:34:51 +00:00
# ----------------------------------------------------------------------------
# called from the global dispatch if new data is available
# ----------------------------------------------------------------------------
sub SB_PLAYER_Parse ( $$ ) {
my ( $ iohash , $ msg ) = @ _ ;
# we expect the data to be in the following format
# xxxxxxxxxxxx cmd1 cmd2 cmd3 ...
# where xxxxxxxxxxxx is derived from xx:xx:xx:xx:xx:xx
# that needs to be done by the server
2017-05-28 19:14:57 +00:00
Log3 ( $ iohash , 5 , "SB_PLAYER_Parse: called with $msg" ) ;
# storing the last in an array is necessary, for tagged responses
2014-02-20 23:34:51 +00:00
my ( $ modtype , $ id , @ data ) = split ( ":" , $ msg , 3 ) ;
2017-05-28 19:14:57 +00:00
Log3 ( $ iohash , 5 , "SB_PLAYER_Parse: type:$modtype, ID:$id CMD:@data" ) ;
2014-02-20 23:34:51 +00:00
if ( $ modtype ne "SB_PLAYER" ) {
2015-03-19 20:37:01 +00:00
# funny stuff happens at the disptach function
Log3 ( $ iohash , 5 , "SB_PLAYER_Parse: wrong type given." ) ;
2014-02-20 23:34:51 +00:00
}
# let's see what we got. Split the data at the space
2017-05-28 19:14:57 +00:00
# necessary, for tagged responses
2014-02-20 23:34:51 +00:00
my @ args = split ( " " , join ( " " , @ data ) ) ;
my $ cmd = shift ( @ args ) ;
my $ hash = $ modules { SB_PLAYER } { defptr } { $ id } ;
if ( ! $ hash ) {
2017-05-28 19:14:57 +00:00
Log3 ( undef , 3 , "SB_PLAYER Unknown device with ID $id, " .
2015-03-19 20:37:01 +00:00
"please define it" ) ;
# do the autocreate; derive the unique id (MAC adress)
my @ playermac = ( $ id =~ m/.{2}/g ) ;
my $ idbuf = join ( ":" , @ playermac ) ;
Log3 ( undef , 3 , "SB_PLAYER Dervived the following MAC $idbuf " ) ;
if ( SB_PLAYER_IsValidMAC ( $ idbuf ) == 1 ) {
# the MAC Adress is valid
2017-05-28 19:14:57 +00:00
Log3 ( undef , 3 , "SB_PLAYER_Parse: the unknown ID $id is a valid " .
2015-03-19 20:37:01 +00:00
"MAC Adress" ) ;
# this line supports autocreate
return ( "UNDEFINED SB_PLAYER_$id SB_PLAYER $idbuf" ) ;
} else {
# the MAC adress is not valid
2017-05-28 19:14:57 +00:00
Log3 ( undef , 3 , "SB_PLAYER_Parse: the unknown ID $id is NOT " .
2015-03-19 20:37:01 +00:00
"a valid MAC Adress" ) ;
return ( undef ) ;
}
2014-02-20 23:34:51 +00:00
}
2017-05-28 19:14:57 +00:00
2014-02-20 23:34:51 +00:00
# so the data is for us
my $ name = $ hash - > { NAME } ;
2015-03-19 20:37:01 +00:00
#return "" if(IsIgnored($name));
2014-02-20 23:34:51 +00:00
2017-05-28 19:14:57 +00:00
Log3 ( $ hash , 5 , "SB_PLAYER_Parse: $name CMD:$cmd ARGS:@args..." ) ;
2014-02-20 23:34:51 +00:00
# what ever we have received, signal it
$ hash - > { LASTANSWER } = "$cmd @args" ;
2015-03-19 20:37:01 +00:00
$ hash - > { helper } { ttsstate } = TTS_IDLE if ( ! defined ( $ hash - > { helper } { ttsstate } ) ) ; # CD 0028
2014-02-20 23:34:51 +00:00
# signal the update to FHEM
readingsBeginUpdate ( $ hash ) ;
if ( $ cmd eq "mixer" ) {
2015-03-19 20:37:01 +00:00
if ( $ args [ 0 ] eq "volume" ) {
2017-05-28 19:14:57 +00:00
# update the volume
2015-03-19 20:37:01 +00:00
if ( $ args [ 1 ] eq "?" ) {
# it is a request
} else {
2015-06-18 20:23:54 +00:00
# CD 0040 start
if ( ( index ( $ args [ 1 ] , "+" ) != - 1 ) || ( index ( $ args [ 1 ] , "-" ) != - 1 ) ) {
# that was a relative value. We do nothing and fire an update
IOWrite ( $ hash , "$hash->{PLAYERMAC} mixer volume ?\n" ) ;
} else {
# CD 0040 end
SB_PLAYER_UpdateVolumeReadings ( $ hash , $ args [ 1 ] , true ) ;
# CD 0007 start
if ( ( defined ( $ hash - > { helper } { setSyncVolume } ) && ( $ hash - > { helper } { setSyncVolume } != $ args [ 1 ] ) ) || ( ! defined ( $ hash - > { helper } { setSyncVolume } ) ) ) {
2017-05-28 19:14:57 +00:00
SB_PLAYER_SetSyncedVolume ( $ hash , $ args [ 1 ] , 0 ) ;
2015-06-18 20:23:54 +00:00
}
delete $ hash - > { helper } { setSyncVolume } ;
# CD 0007 end
2015-03-19 20:37:01 +00:00
}
}
}
2014-02-20 23:34:51 +00:00
2014-07-06 22:14:26 +00:00
} elsif ( $ cmd eq "remote" ) {
2015-03-19 20:37:01 +00:00
if ( defined ( $ args [ 0 ] ) ) {
$ hash - > { ISREMOTESTREAM } = "$args[ 0 ]" ;
2017-05-28 19:14:57 +00:00
} else {
2015-03-19 20:37:01 +00:00
$ hash - > { ISREMOTESTREAM } = "0" ;
}
2014-11-09 18:01:21 +00:00
2014-07-06 22:14:26 +00:00
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "play" ) {
2015-03-19 20:37:01 +00:00
if ( ! defined ( $ hash - > { helper } { recallPause } ) ) { # CD 0014
readingsBulkUpdate ( $ hash , "playStatus" , "playing" ) ;
SB_PLAYER_Amplifier ( $ hash ) ;
} # CD 0014
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "stop" ) {
2015-03-19 20:37:01 +00:00
readingsBulkUpdate ( $ hash , "playStatus" , "stopped" ) ;
SB_PLAYER_Amplifier ( $ hash ) ;
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "pause" ) {
2015-03-19 20:37:01 +00:00
if ( ( defined ( $ args [ 0 ] ) ) && ( $ args [ 0 ] eq "0" ) ) { # CD 0028 check if $args[0] exists
readingsBulkUpdate ( $ hash , "playStatus" , "playing" ) ;
SB_PLAYER_Amplifier ( $ hash ) ;
} else {
readingsBulkUpdate ( $ hash , "playStatus" , "paused" ) ;
SB_PLAYER_Amplifier ( $ hash ) ;
2017-05-28 19:14:57 +00:00
}
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "mode" ) {
2015-06-18 20:23:54 +00:00
my $ updateSyncedPlayers = 0 ; # CD 0039
2015-11-02 08:26:30 +00:00
# a little more complex to fulfill FHEM Development guidelines
2017-05-28 19:14:57 +00:00
Log3 ( $ hash , 5 , "SB_PLAYER_Parse($name): mode:$cmd args:$args[0]" ) ;
2015-03-19 20:37:01 +00:00
if ( $ args [ 0 ] eq "play" ) {
# CD 0014 start
if ( defined ( $ hash - > { helper } { recallPause } ) ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} pause 1\n" ) ;
} else {
# CD 0014 end
readingsBulkUpdate ( $ hash , "playStatus" , "playing" ) ;
SB_PLAYER_Amplifier ( $ hash ) ;
SB_PLAYER_QueryElapsedTime ( $ hash ) ; # CD 0014
2015-11-02 08:26:30 +00:00
# CD 0047 start
RemoveInternalTimer ( "QueryElapsedTime:$name" ) ;
2017-05-28 19:14:57 +00:00
my $ qi = AttrVal ( $ hash - > { NAME } , "trackPositionQueryInterval" , 5 ) ; # CD 0064
if ( $ qi > 0 ) { # CD 0064
InternalTimer ( gettimeofday ( ) + $ qi ,
"SB_PLAYER_tcb_QueryElapsedTime" ,
"QueryElapsedTime:$name" ,
0 ) ;
# CD 0047 end
}
2015-03-19 20:37:01 +00:00
} # CD 0014
# CD 0029 start
if ( defined ( $ hash - > { helper } { ttsOptions } { logplay } ) ) {
Log3 ( $ hash , 0 , "SB_PLAYER_Parse: $name: mode play" ) ;
delete ( $ hash - > { helper } { ttsOptions } { logplay } ) ;
}
# CD 0029
# CD 0028 start
if ( $ hash - > { helper } { ttsstate } == TTS_WAITFORPLAY ) {
SB_PLAYER_SetTTSState ( $ hash , TTS_PLAYING , 1 , 0 ) ;
}
if ( ( $ hash - > { helper } { ttsstate } == TTS_SYNCGROUPACTIVE ) && ( $ hash - > { SYNCMASTER } eq $ hash - > { PLAYERMAC } ) ) {
IOWrite ( $ hash , $ hash - > { helper } { ttsMaster } . " fhemrelay ttsplaying\n" ) ;
}
# CD 0028 end
2015-06-18 20:23:54 +00:00
$ updateSyncedPlayers = 1 ; # CD 0039 gesyncte Player aktualisieren
2015-03-19 20:37:01 +00:00
} elsif ( $ args [ 0 ] eq "stop" ) {
# CD 0028 start
if ( $ hash - > { helper } { ttsstate } == TTS_PLAYING ) {
SB_PLAYER_TTSStopped ( $ hash ) ;
}
2016-10-01 16:46:46 +00:00
# wenn tts auf Slave aktiv ist schickt der LMS den Stop nur an den Master
if ( ReadingsVal ( $ name , "presence" , "x" ) eq "present" ) { # CD 0056 Meldung nicht weiterschicken wenn der Master nicht 'present' ist
if ( ( $ hash - > { helper } { ttsstate } == TTS_SYNCGROUPACTIVE ) && ( $ hash - > { SYNCMASTER } eq $ hash - > { PLAYERMAC } ) ) {
if ( defined ( $ hash - > { SYNCGROUP } ) && ( $ hash - > { SYNCGROUP } ne '?' ) && ( $ hash - > { SYNCMASTER } ne 'none' ) ) {
my @ pl = split ( "," , $ hash - > { SYNCGROUP } ) ;
foreach ( @ pl ) {
if ( $ hash - > { PLAYERMAC } ne $ _ ) {
IOWrite ( $ hash , "$_ fhemrelay ttsstopped\n" ) ;
}
2015-03-19 20:37:01 +00:00
}
}
}
}
# CD 0028 end
readingsBulkUpdate ( $ hash , "playStatus" , "stopped" ) ;
SB_PLAYER_Amplifier ( $ hash ) ;
2015-11-02 08:26:30 +00:00
RemoveInternalTimer ( "QueryElapsedTime:$name" ) ; # CD 0047
readingsBulkUpdate ( $ hash , "currentTrackPosition" , 0 ) ; # CD 0047
2015-06-18 20:23:54 +00:00
$ updateSyncedPlayers = 1 ; # CD 0039 gesyncte Player aktualisieren
2015-03-19 20:37:01 +00:00
} elsif ( $ args [ 0 ] eq "pause" ) {
readingsBulkUpdate ( $ hash , "playStatus" , "paused" ) ;
SB_PLAYER_Amplifier ( $ hash ) ;
2015-06-18 20:23:54 +00:00
$ updateSyncedPlayers = 1 ; # CD 0039 gesyncte Player aktualisieren
2015-03-19 20:37:01 +00:00
} else {
readingsBulkUpdate ( $ hash , "playStatus" , $ args [ 0 ] ) ;
}
2017-05-28 19:14:57 +00:00
2015-06-18 20:23:54 +00:00
# CD 0039 gesyncte Player aktualisieren
if ( $ updateSyncedPlayers == 1 ) {
if ( $ hash - > { PLAYERMAC } eq $ hash - > { SYNCMASTER } ) {
if ( defined ( $ hash - > { SYNCGROUP } ) && ( $ hash - > { SYNCGROUP } ne '?' ) && ( $ hash - > { SYNCMASTER } ne 'none' ) ) {
my @ pl = split ( "," , $ hash - > { SYNCGROUP } ) ;
foreach ( @ pl ) {
if ( $ hash - > { PLAYERMAC } ne $ _ ) {
IOWrite ( $ hash , "$_ mode ?\n" ) ;
}
}
}
}
}
# CD 0039 end
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "newmetadata" ) {
2015-03-19 20:37:01 +00:00
# the song has changed, but we are easy and just ask the player
# sending the requests causes endless loop
#IOWrite( $hash, "$hash->{PLAYERMAC} artist ?\n" );
#IOWrite( $hash, "$hash->{PLAYERMAC} album ?\n" );
#IOWrite( $hash, "$hash->{PLAYERMAC} title ?\n" );
IOWrite ( $ hash , "$hash->{PLAYERMAC} remote ?\n" ) ;
#IOWrite( $hash, "$hash->{PLAYERMAC} status 0 500 tags:Kc\n" );
#SB_PLAYER_CoverArt( $hash ); # CD 0026 deaktiviert
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "playlist" ) {
2015-03-19 20:37:01 +00:00
my $ queryMode = 1 ; # CD 0014
2017-05-28 19:14:57 +00:00
2015-03-19 20:37:01 +00:00
if ( $ args [ 0 ] eq "newsong" ) {
# the song has changed, but we are easy and just ask the player
IOWrite ( $ hash , "$hash->{PLAYERMAC} artist ?\n" ) ;
IOWrite ( $ hash , "$hash->{PLAYERMAC} album ?\n" ) ;
IOWrite ( $ hash , "$hash->{PLAYERMAC} title ?\n" ) ;
# CD 0007 get playlist name
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist name ?\n" ) ;
# CD 0014 get duration and index
IOWrite ( $ hash , "$hash->{PLAYERMAC} duration ?\n" ) ;
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist index ?\n" ) ;
IOWrite ( $ hash , "$hash->{PLAYERMAC} time ?\n" ) ;
# CD 0002 Coverart anfordern, todo: Zeit variabel
$ hash - > { helper } { CoverOk } = 0 ; # CD 0026 added # CD 0027 changed
# CD 0025 bei lokalen Playlisten schneller abfragen
if ( $ hash - > { ISREMOTESTREAM } eq "0" ) {
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + 3 ,
2015-03-19 20:37:01 +00:00
"SB_PLAYER_tcb_QueryCoverArt" ,
"QueryCoverArt:$name" ,
0 ) ;
} else {
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + 10 ,
2016-10-01 16:46:46 +00:00
"SB_PLAYER_tcb_QueryCoverArt" , # CD 0014 Name ge<67> ndert
"QueryCoverArt:$name" , # CD 0014 Name ge<67> ndert
2015-03-19 20:37:01 +00:00
0 ) ;
}
2016-10-01 16:46:46 +00:00
# CD 0002 zu fr<66> h, CoverArt ist noch nicht verf<72> gbar
2015-03-19 20:37:01 +00:00
# SB_PLAYER_CoverArt( $hash );
# CD 0000 start - sync players in same group
if ( $ hash - > { PLAYERMAC } eq $ hash - > { SYNCMASTER } ) {
2016-10-01 16:46:46 +00:00
if ( defined ( $ hash - > { SYNCGROUP } ) && ( $ hash - > { SYNCGROUP } ne '?' ) && ( $ hash - > { SYNCMASTER } ne 'none' ) ) { # CD 0018 none hinzugef<65> gt
2015-03-19 20:37:01 +00:00
my @ pl = split ( "," , $ hash - > { SYNCGROUP } ) ;
foreach ( @ pl ) {
#Log 0,"SB_Player to sync: $_";
IOWrite ( $ hash , "$_ artist ?\n" ) ;
IOWrite ( $ hash , "$_ album ?\n" ) ;
IOWrite ( $ hash , "$_ title ?\n" ) ;
# CD 0010
IOWrite ( $ hash , "$_ playlist name ?\n" ) ;
# CD 0014
IOWrite ( $ hash , "$_ duration ?\n" ) ;
IOWrite ( $ hash , "$_ playlist index ?\n" ) ;
}
}
}
# CD 0000 end
# CD 0014 start
if ( defined ( $ hash - > { helper } { recallPause } ) ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} pause 1\n" ) ;
RemoveInternalTimer ( "recallPause:$name" ) ;
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + 0.5 ,
"SB_PLAYER_tcb_DeleteRecallPause" ,
"recallPause:$name" ,
2015-03-19 20:37:01 +00:00
0 ) ;
}
# CD 0014 end
# the id is in the last return. ID not reported for radio stations
2017-05-28 19:14:57 +00:00
# so this will go wrong for e.g. Bayern 3
2015-03-19 20:37:01 +00:00
# if( $args[ $#args ] =~ /(^[0-9]{1,3})/g ) {
# readingsBulkUpdate( $hash, "currentMedia", $1 );
# }
} elsif ( $ args [ 0 ] eq "cant_open" ) {
#TODO: needs to be handled
2015-04-07 19:48:18 +00:00
# CD 0033 TTS abbrechen bei Fehler
if ( $ hash - > { helper } { ttsstate } == TTS_WAITFORPLAY ) {
SB_PLAYER_TTSStopped ( $ hash ) ;
}
2015-03-19 20:37:01 +00:00
} elsif ( $ args [ 0 ] eq "open" ) {
readingsBulkUpdate ( $ hash , "currentMedia" , "$args[1]" ) ;
SB_PLAYER_Amplifier ( $ hash ) ;
SB_PLAYER_GetStatus ( $ hash ) ; # CD 0014
# $args[ 2 ] =~ /^(file:)(.*)/g;
# if( defined( $2 ) ) {
#readingsBulkUpdate( $hash, "currentMedia", $2 );
# }
} elsif ( $ args [ 0 ] eq "repeat" ) {
if ( $ args [ 1 ] eq "0" ) {
readingsBulkUpdate ( $ hash , "repeat" , "off" ) ;
} elsif ( $ args [ 1 ] eq "1" ) {
readingsBulkUpdate ( $ hash , "repeat" , "one" ) ;
} elsif ( $ args [ 1 ] eq "2" ) {
readingsBulkUpdate ( $ hash , "repeat" , "all" ) ;
} else {
readingsBulkUpdate ( $ hash , "repeat" , "?" ) ;
}
2016-10-01 16:46:46 +00:00
# CD 0039 <20> nderung am Master, gesyncte Player aktualisieren
2015-06-18 20:23:54 +00:00
if ( $ hash - > { PLAYERMAC } eq $ hash - > { SYNCMASTER } ) {
if ( defined ( $ hash - > { SYNCGROUP } ) && ( $ hash - > { SYNCGROUP } ne '?' ) && ( $ hash - > { SYNCMASTER } ne 'none' ) ) {
my @ pl = split ( "," , $ hash - > { SYNCGROUP } ) ;
foreach ( @ pl ) {
IOWrite ( $ hash , "$_ playlist repeat ?\n" ) ;
}
}
}
# CD 0039 end
2015-03-19 20:37:01 +00:00
} elsif ( $ args [ 0 ] eq "shuffle" ) {
2017-08-26 19:46:07 +00:00
if ( defined ( $ args [ 1 ] ) ) { # CD 0086
if ( $ args [ 1 ] eq "0" ) {
readingsBulkUpdate ( $ hash , "shuffle" , "off" ) ;
} elsif ( $ args [ 1 ] eq "1" ) {
readingsBulkUpdate ( $ hash , "shuffle" , "song" ) ;
} elsif ( $ args [ 1 ] eq "2" ) {
readingsBulkUpdate ( $ hash , "shuffle" , "album" ) ;
} else {
readingsBulkUpdate ( $ hash , "shuffle" , "?" ) ;
}
# CD 0039 <20> nderung am Master, gesyncte Player aktualisieren
if ( $ hash - > { PLAYERMAC } eq $ hash - > { SYNCMASTER } ) {
if ( defined ( $ hash - > { SYNCGROUP } ) && ( $ hash - > { SYNCGROUP } ne '?' ) && ( $ hash - > { SYNCMASTER } ne 'none' ) ) {
my @ pl = split ( "," , $ hash - > { SYNCGROUP } ) ;
foreach ( @ pl ) {
IOWrite ( $ hash , "$_ playlist shuffle ?\n" ) ;
}
2015-06-18 20:23:54 +00:00
}
}
2017-08-26 19:46:07 +00:00
# CD 0039 end
SB_PLAYER_GetStatus ( $ hash ) ; # CD 0014
2015-06-18 20:23:54 +00:00
}
2015-03-19 20:37:01 +00:00
} elsif ( $ args [ 0 ] eq "name" ) {
# CD 0014 start
$ queryMode = 0 ;
if ( ! defined ( $ args [ 1 ] ) ) {
readingsBulkUpdate ( $ hash , "currentPlaylistName" , "-" ) ;
readingsBulkUpdate ( $ hash , "playlists" , "-" ) ;
#$hash->{FAVSELECT} = '-'; # CD 0021 deaktiviert
#readingsBulkUpdate( $hash, "$hash->{FAVSET}", '-' ); # CD 0021 deaktiviert
}
# CD 0014 end
if ( defined ( $ args [ 1 ] ) && ( $ args [ 1 ] ne '?' ) ) { # CD 0009 check empty name - 0011 ignore '?'
shift ( @ args ) ;
2017-05-28 19:14:57 +00:00
readingsBulkUpdate ( $ hash , "currentPlaylistName" ,
2015-03-19 20:37:01 +00:00
join ( " " , @ args ) ) ;
2016-10-01 16:46:46 +00:00
my $ pn = SB_SERVER_FavoritesName2UID ( join ( " " , @ args ) ) ; # CD 0021 verschoben, decode hinzugef<65> gt # CD 0023 decode entfernt
2015-03-19 20:37:01 +00:00
# CD 0008 update playlists reading
readingsBulkUpdate ( $ hash , "playlists" , $ pn ) ; # CD 0021 $pn verwenden wegen Dropdown
# join( "_", @args ) ); # CD 0021 deaktiviert
# CD 0007 start - check if playlist == fav, 0014 removed debug info
if ( defined ( $ hash - > { helper } { SB_PLAYER_Favs } { $ pn } ) && defined ( $ hash - > { helper } { SB_PLAYER_Favs } { $ pn } { ID } ) ) { # CD 0011 check if defined($hash->{helper}{SB_PLAYER_Favs}{$pn})
$ hash - > { FAVSELECT } = $ pn ;
readingsBulkUpdate ( $ hash , "$hash->{FAVSET}" , "$pn" ) ;
} else {
$ hash - > { FAVSELECT } = '-' ; # CD 0014
readingsBulkUpdate ( $ hash , "$hash->{FAVSET}" , '-' ) ; # CD 0014
}
# CD 0007 end
}
# CD 0009 start
# CD 0021 start, update favorites if url matches
} elsif ( $ args [ 0 ] eq "play" ) {
if ( defined ( $ args [ 1 ] ) ) {
$ args [ 1 ] =~ s/\\/\//g ;
$ hash - > { FAVSELECT } = "-" ;
foreach my $ e ( keys % { $ hash - > { helper } { SB_PLAYER_Favs } } ) {
if ( $ args [ 1 ] eq $ hash - > { helper } { SB_PLAYER_Favs } { $ e } { URL } ) {
$ hash - > { FAVSELECT } = $ e ;
last ;
}
}
readingsBulkUpdate ( $ hash , "$hash->{FAVSET}" , "$hash->{FAVSELECT}" ) ;
# CD 0022 send to synced players # CD 0023 fixed
if ( $ hash - > { SYNCED } eq "yes" ) {
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 favorites $hash->{FAVSELECT}\n" ) ;
}
}
}
}
}
2017-05-28 19:14:57 +00:00
$ hash - > { helper } { noStopEventUntil } = time ( ) + 2.0 ; # CD 0063
2015-03-19 20:37:01 +00:00
# CD 0021 end
} elsif ( $ args [ 0 ] eq "clear" ) {
readingsBulkUpdate ( $ hash , "currentPlaylistName" , "none" ) ;
readingsBulkUpdate ( $ hash , "playlists" , "none" ) ;
2017-08-26 19:46:07 +00:00
readingsBulkUpdate ( $ hash , "playlistTracks" , 0 ) ; # CD 0084
readingsBulkUpdate ( $ hash , "duration" , 0 ) ; # CD 0084
$ hash - > { helper } { playlistIds } = '0' ; # CD 0084
readingsBulkUpdate ( $ hash , "ftuiMedialist" , '[{"Artist":"-","Title":"-","Album":"-","Time":"0","File":"-","Track":"0","Cover":"-"}]' ) if ( defined ( $ hash - > { helper } { ftuiSupport } { medialist } ) ) ; # CD 0084
2015-03-19 20:37:01 +00:00
# CD 0009 end
SB_PLAYER_GetStatus ( $ hash ) ; # CD 0014
} elsif ( $ args [ 0 ] eq "url" ) {
shift ( @ args ) ;
2017-05-28 19:14:57 +00:00
readingsBulkUpdate ( $ hash , "currentPlaylistUrl" ,
2015-03-19 20:37:01 +00:00
join ( " " , @ args ) ) ;
} elsif ( $ args [ 0 ] eq "stop" ) {
readingsBulkUpdate ( $ hash , "playStatus" , "stopped" ) ; # CD 0012 'power off' durch 'playStatus stopped' ersetzt
SB_PLAYER_Amplifier ( $ hash ) ;
2017-05-28 19:14:57 +00:00
# CD 0063 start
RemoveInternalTimer ( "TriggerPlaylistStop:$name" ) ;
InternalTimer ( gettimeofday ( ) + 1.0 ,
"SB_PLAYER_tcb_TriggerPlaylistStop" ,
"TriggerPlaylistStop:$name" ,
0 ) ;
# CD 0063 stop
2015-03-19 20:37:01 +00:00
# CD 0014 start
} elsif ( $ args [ 0 ] eq "index" ) {
2016-10-01 16:46:46 +00:00
readingsBulkUpdate ( $ hash , "playlistCurrentTrack" , $ args [ 1 ] eq '?' ? 0 : $ args [ 1 ] + 1 ) ; # Heppel 0056
2015-03-19 20:37:01 +00:00
$ queryMode = 0 ;
} elsif ( $ args [ 0 ] eq "addtracks" ) {
$ queryMode = 0 ;
SB_PLAYER_GetStatus ( $ hash ) ;
2017-05-28 19:14:57 +00:00
# CD 0068 start
} elsif ( $ args [ 0 ] eq "add" ) {
$ queryMode = 0 ;
SB_PLAYER_GetStatus ( $ hash ) ;
# CD 0068 end
2015-03-19 20:37:01 +00:00
} elsif ( $ args [ 0 ] eq "delete" ) {
$ queryMode = 0 ;
#IOWrite( $hash, "$hash->{PLAYERMAC} alarm playlists 0 200\n" ); # CD 0016 get available elements for alarms # CD 0026 deaktiviert
SB_PLAYER_GetStatus ( $ hash ) ;
} elsif ( $ args [ 0 ] eq "load_done" ) {
if ( $ hash - > { helper } { ttsstate } == TTS_PLAYING ) {
2017-05-28 19:14:57 +00:00
#IOWrite( $hash, "$hash->{PLAYERMAC} playlist index +0\n");
2015-03-19 20:37:01 +00:00
#IOWrite( $hash, "$hash->{PLAYERMAC} play\n" );
}
if ( $ hash - > { helper } { ttsstate } == TTS_LOADPLAYLIST ) {
# CD 0030 start
if ( SB_PLAYER_GetTTSDelay ( $ hash ) > 0 ) {
RemoveInternalTimer ( "TTSDelay:$name" ) ;
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + SB_PLAYER_GetTTSDelay ( $ hash ) ,
2015-03-19 20:37:01 +00:00
"SB_PLAYER_tcb_TTSDelay" ,
2017-05-28 19:14:57 +00:00
"TTSDelay:$name" ,
0 ) ;
2015-03-19 20:37:01 +00:00
SB_PLAYER_SetTTSState ( $ hash , TTS_DELAY , 1 , 0 ) ;
} else {
# CD 0030 end
SB_PLAYER_SetTTSState ( $ hash , TTS_WAITFORPLAY , 1 , 0 ) ;
IOWrite ( $ hash , "$hash->{PLAYERMAC} play\n" ) ;
2016-10-01 16:46:46 +00:00
# CD 0038 Timeout hinzugef<65> gt
2015-06-18 20:23:54 +00:00
RemoveInternalTimer ( "TimeoutTTSWaitForPlay:$name" ) ;
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + 10.00 ,
2015-06-18 20:23:54 +00:00
"SB_PLAYER_tcb_TimeoutTTSWaitForPlay" ,
2017-05-28 19:14:57 +00:00
"TimeoutTTSWaitForPlay:$name" ,
2015-06-18 20:23:54 +00:00
0 ) ;
# CD 0038 end
2015-03-19 20:37:01 +00:00
}
}
# CD 0029 start
if ( defined ( $ hash - > { helper } { ttsOptions } { logloaddone } ) ) {
Log3 ( $ hash , 0 , "SB_PLAYER_Parse: $name: load_done" ) ;
delete ( $ hash - > { helper } { ttsOptions } { logloaddone } ) ;
}
# CD 0029 end
if ( defined ( $ hash - > { helper } { recallPending } ) ) {
delete ( $ hash - > { helper } { recallPending } ) ;
SB_PLAYER_SetTTSState ( $ hash , TTS_IDLE , 1 , 1 ) ;
IOWrite ( $ hash , "$hash->{PLAYERMAC} play 300\n" ) ;
2015-11-02 08:26:30 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} time $hash->{helper}{recallPendingElapsedTime}\n" ) ; # CD 0047, Position setzen korrigiert
delete ( $ hash - > { helper } { recallPendingElapsedTime } ) ; # CD 0047
2015-03-19 20:37:01 +00:00
}
} elsif ( $ args [ 0 ] eq "loadtracks" ) {
if ( defined ( $ hash - > { helper } { recallPending } ) ) {
delete ( $ hash - > { helper } { recallPending } ) ;
SB_PLAYER_SetTTSState ( $ hash , TTS_IDLE , 1 , 1 ) ;
IOWrite ( $ hash , "$hash->{PLAYERMAC} play 300\n" ) ;
2015-11-02 08:26:30 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} time $hash->{helper}{recallPendingElapsedTime}\n" ) ; # CD 0047, Position setzen korrigiert
delete ( $ hash - > { helper } { recallPendingElapsedTime } ) ; # CD 0047
2015-03-19 20:37:01 +00:00
}
# CD 0014 end
2015-11-02 08:26:30 +00:00
# CD 0048 start
} elsif ( $ args [ 0 ] eq "path" ) {
delete $ hash - > { helper } { path } if defined ( $ hash - > { helper } { path } ) ;
if ( defined ( $ args [ 1 ] ) && ( $ args [ 1 ] eq "0" ) ) {
$ hash - > { helper } { path } = $ args [ 2 ] if defined ( $ args [ 2 ] ) ;
}
# CD 0048 end
2015-03-19 20:37:01 +00:00
} else {
}
# check if this caused going to play, as not send automatically
2016-10-01 16:46:46 +00:00
if ( ! defined ( $ hash - > { helper } { lastModeQuery } ) || ( $ hash - > { helper } { lastModeQuery } < gettimeofday ( ) - 0.05 ) ) { # CD 0014 <20> berfl<66> ssige Abfragen begrenzen
IOWrite ( $ hash , "$hash->{PLAYERMAC} mode ?\n" ) if ( ! ( defined ( $ hash - > { helper } { recallPending } ) || defined ( $ hash - > { helper } { recallPause } ) || ( $ queryMode == 0 ) ) ) ; # CD 0014 if(... hinzugef<65> gt
2015-03-19 20:37:01 +00:00
$ hash - > { helper } { lastModeQuery } = gettimeofday ( ) ; # CD 0014
} # CD 0014
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "playlistcontrol" ) {
2015-03-19 20:37:01 +00:00
#playlistcontrol cmd:load artist_id:22 count:4
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "connected" ) {
2015-03-19 20:37:01 +00:00
readingsBulkUpdate ( $ hash , "connected" , $ args [ 0 ] ) ;
readingsBulkUpdate ( $ hash , "presence" , "present" ) ;
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "name" ) {
2015-03-19 20:37:01 +00:00
$ hash - > { PLAYERNAME } = join ( " " , @ args ) ;
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "title" ) {
2015-03-19 20:37:01 +00:00
readingsBulkUpdate ( $ hash , "currentTitle" , join ( " " , @ args ) ) ;
2017-08-26 19:46:07 +00:00
RemoveInternalTimer ( "ftuiMedialist:$name" ) ; # CD 0085
InternalTimer ( gettimeofday ( ) + 0.01 , # CD 0085
"SB_PLAYER_tcb_ftuiMedialist" ,
"ftuiMedialist:$name" ,
0 ) if ( defined ( $ hash - > { helper } { ftuiSupport } { medialist } ) ) ; # CD 0082
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "artist" ) {
2015-03-19 20:37:01 +00:00
readingsBulkUpdate ( $ hash , "currentArtist" , join ( " " , @ args ) ) ;
2017-08-26 19:46:07 +00:00
RemoveInternalTimer ( "ftuiMedialist:$name" ) ;
InternalTimer ( gettimeofday ( ) + 0.01 ,
"SB_PLAYER_tcb_ftuiMedialist" ,
"ftuiMedialist:$name" ,
0 ) if ( defined ( $ hash - > { helper } { ftuiSupport } { medialist } ) ) ; # CD 0082
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "album" ) {
2015-03-19 20:37:01 +00:00
readingsBulkUpdate ( $ hash , "currentAlbum" , join ( " " , @ args ) ) ;
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "player" ) {
2015-03-19 20:37:01 +00:00
if ( $ args [ 0 ] eq "model" ) {
$ hash - > { MODEL } = $ args [ 1 ] ;
} elsif ( $ args [ 0 ] eq "canpoweroff" ) {
$ hash - > { CANPOWEROFF } = $ args [ 1 ] ;
} elsif ( $ args [ 0 ] eq "ip" ) {
$ hash - > { PLAYERIP } = "$args[ 1 ]" ;
if ( defined ( $ args [ 2 ] ) ) {
$ hash - > { PLAYERIP } . = ":$args[ 2 ]" ;
}
2017-05-28 19:14:57 +00:00
2015-03-19 20:37:01 +00:00
} else {
}
2017-05-28 19:14:57 +00:00
# CD 0063 start
} elsif ( $ cmd eq "playerdata" ) {
$ hash - > { MODEL } = $ args [ 0 ] unless $ args [ 0 ] eq 'unknown' ;
$ hash - > { CANPOWEROFF } = $ args [ 1 ] unless $ args [ 1 ] eq 'unknown' ;
$ hash - > { DISPLAYTYPE } = $ args [ 2 ] unless $ args [ 2 ] eq 'unknown' ;
if ( $ args [ 3 ] ne 'unknown' ) {
readingsBulkUpdate ( $ hash , "connected" , $ args [ 3 ] ) ;
readingsBulkUpdate ( $ hash , "presence" , "present" ) ;
}
2014-02-20 23:34:51 +00:00
2017-05-28 19:14:57 +00:00
$ hash - > { PLAYERIP } = "$args[ 4 ]" unless $ args [ 4 ] eq 'unknown' ;
if ( defined ( $ args [ 5 ] ) ) {
$ hash - > { PLAYERIP } . = ":$args[ 5 ]" ;
}
# CD 0063 end
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "power" ) {
2015-03-19 20:37:01 +00:00
if ( ! ( @ args ) ) {
# no arguments were send with the Power command
2017-05-28 19:14:57 +00:00
# potentially this is a power toggle : should only happen
2015-03-19 20:37:01 +00:00
# when called with SB CLI
} elsif ( $ args [ 0 ] eq "1" ) {
readingsBulkUpdate ( $ hash , "state" , "on" ) ;
readingsBulkUpdate ( $ hash , "power" , "on" ) ;
2017-05-28 19:14:57 +00:00
2015-03-19 20:37:01 +00:00
SB_PLAYER_Amplifier ( $ hash ) ;
} elsif ( $ args [ 0 ] eq "0" ) {
2016-10-01 16:46:46 +00:00
#readingsBulkUpdate( $hash, "presence", "absent" ); # CD 0013 deaktiviert, power sagt nichts <20> ber presence
2015-03-19 20:37:01 +00:00
readingsBulkUpdate ( $ hash , "state" , "off" ) ;
readingsBulkUpdate ( $ hash , "power" , "off" ) ;
SB_PLAYER_Amplifier ( $ hash ) ;
} else {
# should be "?" normally
}
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "displaytype" ) {
2015-03-19 20:37:01 +00:00
$ hash - > { DISPLAYTYPE } = $ args [ 0 ] ;
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "signalstrength" ) {
2015-03-19 20:37:01 +00:00
if ( $ args [ 0 ] eq "0" ) {
readingsBulkUpdate ( $ hash , "signalstrength" , "wired" ) ;
} else {
readingsBulkUpdate ( $ hash , "signalstrength" , "$args[ 0 ]" ) ;
}
2017-05-28 19:14:57 +00:00
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "alarm" ) {
2015-03-19 20:37:01 +00:00
if ( $ args [ 0 ] eq "sound" ) {
# fired when an alarm goes off
2016-10-01 16:46:46 +00:00
DoTrigger ( $ name , "alarmSound " . SB_PLAYER_FindAlarmId ( $ hash , $ args [ 1 ] ) ) if ( SB_PLAYER_check_eocr ( $ hash , 'alarmSound' ) ) ; # CD 0046 # CD 0054 SB_PLAYER_check_eocr hinzugef<65> gt
2015-03-19 20:37:01 +00:00
} elsif ( $ args [ 0 ] eq "end" ) {
# fired when an alarm ends
2016-10-01 16:46:46 +00:00
DoTrigger ( $ name , "alarmEnd " . SB_PLAYER_FindAlarmId ( $ hash , $ args [ 1 ] ) ) if ( SB_PLAYER_check_eocr ( $ hash , 'alarmEnd' ) ) ; # CD 0046 # CD 0054 SB_PLAYER_check_eocr hinzugef<65> gt
2015-03-19 20:37:01 +00:00
} elsif ( $ args [ 0 ] eq "snooze" ) {
# fired when an alarm is snoozed by the user
2016-10-01 16:46:46 +00:00
DoTrigger ( $ name , "alarmSnooze " . SB_PLAYER_FindAlarmId ( $ hash , $ args [ 1 ] ) ) if ( SB_PLAYER_check_eocr ( $ hash , 'alarmSnooze' ) ) ; # CD 0046 # CD 0054 SB_PLAYER_check_eocr hinzugef<65> gt
2015-03-19 20:37:01 +00:00
} elsif ( $ args [ 0 ] eq "snooze_end" ) {
# fired when an alarm comes back from snooze
2016-10-01 16:46:46 +00:00
DoTrigger ( $ name , "alarmSnoozeEnd " . SB_PLAYER_FindAlarmId ( $ hash , $ args [ 1 ] ) ) if ( SB_PLAYER_check_eocr ( $ hash , 'alarmSnoozeEnd' ) ) ; # CD 0046 # CD 0054 SB_PLAYER_check_eocr hinzugef<65> gt
2015-03-19 20:37:01 +00:00
} elsif ( $ args [ 0 ] eq "add" ) {
2017-05-28 19:14:57 +00:00
# fired when an alarm has been added.
2015-03-19 20:37:01 +00:00
# this setup goes wrong, when an alarm is defined manually
# the last entry in the array shall contain th id
my $ idstr = $ args [ $# args ] ;
if ( $ idstr =~ /^(id:)([0-9a-zA-Z\.]+)/g ) {
#readingsBulkUpdate( $hash, "alarmid$hash->{LASTALARM}", $2 ); # CD 0015 deaktiviert
} else {
}
2016-10-01 16:46:46 +00:00
#IOWrite( $hash, "$hash->{PLAYERMAC} alarm playlists 0 200\n" ) if (!defined($hash->{helper}{alarmPlaylists})); # CD 0015 get available elements for alarms CD 0016 nur wenn nicht vorhanden abfragen # CD 0026 wird <20> ber Server verteilt
2015-03-19 20:37:01 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} alarms 0 200 tags:all filter:all\n" ) ; # CD 0015 update alarm list
} elsif ( $ args [ 0 ] eq "_cmd" ) {
2016-10-01 16:46:46 +00:00
#IOWrite( $hash, "$hash->{PLAYERMAC} alarm playlists 0 200\n" ); # CD 0015 get available elements for alarms CD 0016 deaktiviert, nicht n<> tig
2015-03-19 20:37:01 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} alarms 0 200 tags:all filter:all\n" ) ; # CD 0015 filter added
} elsif ( $ args [ 0 ] eq "update" ) {
2016-10-01 16:46:46 +00:00
#IOWrite( $hash, "$hash->{PLAYERMAC} alarm playlists 0 200\n" ) if (!defined($hash->{helper}{alarmPlaylists})); # CD 0015 get available elements for alarms CD 0016 nur wenn nicht vorhanden abfragen # CD 0026 wird <20> ber Server verteilt
2015-03-19 20:37:01 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} alarms 0 200 tags:all filter:all\n" ) ; # CD 0015 filter added
} elsif ( $ args [ 0 ] eq "delete" ) {
if ( ! defined ( $ hash - > { helper } { deleteAllAlarms } ) ) { # CD 0015 do not query while deleting all alarms
IOWrite ( $ hash , "$hash->{PLAYERMAC} alarms 0 200 tags:all filter:all\n" ) ; # CD 0015 filter added
}
# CD 0015 start
2016-10-01 16:46:46 +00:00
# verf<72> gbare Elemente f<> r Alarme, zwischenspeichern f<> r Anzeige
# CD 0026 deaktiviert, kommt <20> ber Broadcast vom Server
2015-03-19 20:37:01 +00:00
#} elsif( $args[ 0 ] eq "playlists" ) {
# delete($hash->{helper}{alarmPlaylists}) if (defined($hash->{helper}{alarmPlaylists}));
# my @r=split("category:",join(" ",@args));
# foreach my $a (@r){
# my $i1=index($a," title:");
# my $i2=index($a," url:");
# my $i3=index($a," singleton:");
# if (($i1!=-1)&&($i2!=-1)&&($i3!=-1)) {
# my $url=substr($a,$i2+5,$i3-$i2-5);
# $url=substr($a,$i1+7,$i2-$i1-7) if ($url eq "");
2016-10-01 16:46:46 +00:00
# my $pn=SB_SERVER_FavoritesName2UID(decode('utf-8',$url)); # CD 0021 decode hinzugef<65> gt
2015-03-19 20:37:01 +00:00
# $hash->{helper}{alarmPlaylists}{$pn}{category}=substr($a,0,$i1);
# $hash->{helper}{alarmPlaylists}{$pn}{title}=substr($a,$i1+7,$i2-$i1-7);
# $hash->{helper}{alarmPlaylists}{$pn}{url}=$url;
# }
# }
# CD 0015
} else {
}
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "alarms" ) {
2015-03-19 20:37:01 +00:00
delete ( $ hash - > { helper } { deleteAllAlarms } ) if ( defined ( $ hash - > { helper } { deleteAllAlarms } ) ) ; # CD 0015
SB_PLAYER_ParseAlarms ( $ hash , @ args ) ;
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "showbriefly" ) {
2015-03-19 20:37:01 +00:00
# to be ignored, we get two hashes
2014-02-20 23:34:51 +00:00
2014-03-22 23:32:21 +00:00
} elsif ( ( $ cmd eq "unknownir" ) || ( $ cmd eq "ir" ) ) {
2015-03-19 20:37:01 +00:00
readingsBulkUpdate ( $ hash , "lastir" , $ args [ 0 ] ) ;
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "status" ) {
2015-03-19 20:37:01 +00:00
SB_PLAYER_ParsePlayerStatus ( $ hash , \ @ args ) ;
2014-07-06 22:14:26 +00:00
} elsif ( $ cmd eq "client" ) {
2015-03-19 20:37:01 +00:00
if ( $ args [ 0 ] eq "new" ) {
# not to be handled here, should lead to a new FHEM Player
} elsif ( $ args [ 0 ] eq "disconnect" ) {
readingsBulkUpdate ( $ hash , "presence" , "absent" ) ;
readingsBulkUpdate ( $ hash , "state" , "off" ) ;
readingsBulkUpdate ( $ hash , "power" , "off" ) ;
2017-05-28 19:14:57 +00:00
# CD 0074 bei disconnect playStatus und Timer zur<75> cksetzen
readingsBulkUpdate ( $ hash , "playStatus" , "stopped" ) ;
RemoveInternalTimer ( $ hash ) ;
RemoveInternalTimer ( "QueryElapsedTime:$name" ) ;
# CD 0074 end
2015-03-19 20:37:01 +00:00
SB_PLAYER_Amplifier ( $ hash ) ;
2016-10-01 16:46:46 +00:00
# CD 0031 wenn Player w<> hrend TTS verschwindet Zustand zur<75> cksetzen
2015-03-19 20:37:01 +00:00
if ( ( $ hash - > { helper } { ttsstate } > TTS_IDLE ) && ( $ hash - > { helper } { ttsstate } < TTS_RESTORE ) ) {
$ hash - > { helper } { savedPlayerState } { power } = "off" if ( defined ( $ hash - > { helper } { savedPlayerState } ) ) ;
SB_PLAYER_SetTTSState ( $ hash , TTS_STOP , 1 , 0 ) ;
RemoveInternalTimer ( "TTSRestore:$name" ) ;
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + 0.01 ,
2015-03-19 20:37:01 +00:00
"SB_PLAYER_tcb_TTSRestore" ,
2017-05-28 19:14:57 +00:00
"TTSRestore:$name" ,
0 ) ;
2015-03-19 20:37:01 +00:00
}
# CD 0031 end
} elsif ( $ args [ 0 ] eq "reconnect" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} status 0 500 tags:Kcu\n" ) ; # CD 0030 u added to tags
2017-06-22 20:47:42 +00:00
# CD 0079 nach reconnect Status abfragen
delete ( $ hash - > { helper } { disableGetStatus } ) if defined ( $ hash - > { helper } { disableGetStatus } ) ;
InternalTimer ( gettimeofday ( ) + 5 ,
"SB_PLAYER_GetStatus" ,
$ hash ,
0 ) ;
2015-03-19 20:37:01 +00:00
} else {
}
2014-07-06 22:14:26 +00:00
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "prefset" ) {
2015-03-19 20:37:01 +00:00
if ( $ args [ 0 ] eq "server" ) {
if ( $ args [ 1 ] eq "currentSong" ) {
# readingsBulkUpdate( $hash, "currentMedia", $args[ 2 ] ); # CD 0014 deaktiviert
} elsif ( $ args [ 1 ] eq "volume" ) {
SB_PLAYER_UpdateVolumeReadings ( $ hash , $ args [ 2 ] , true ) ;
# CD 0000 start - handle 'prefset power' message for synced players
} elsif ( $ args [ 1 ] eq "power" ) {
if ( $ args [ 2 ] eq "1" ) {
#Log 0,"$name power on";
readingsBulkUpdate ( $ hash , "state" , "on" ) ;
readingsBulkUpdate ( $ hash , "power" , "on" ) ;
SB_PLAYER_Amplifier ( $ hash ) ;
2015-06-18 20:23:54 +00:00
# CD 0038 start
if ( $ hash - > { helper } { ttsstate } == TTS_WAITFORPOWERON ) {
# CD 0042 readingsBulkUpdate abwarten
RemoveInternalTimer ( "TTSStartAfterPowerOn:$name" ) ;
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + 0.01 ,
2015-06-18 20:23:54 +00:00
"SB_PLAYER_tcb_TTSStartAfterPowerOn" ,
2017-05-28 19:14:57 +00:00
"TTSStartAfterPowerOn:$name" ,
2015-06-18 20:23:54 +00:00
0 ) ;
}
# CD 0038 end
2015-03-19 20:37:01 +00:00
# CD 0030 send play only after power is on
if ( defined ( $ hash - > { helper } { playAfterPowerOn } ) ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} play " . $ hash - > { helper } { playAfterPowerOn } . "\n" ) ;
delete ( $ hash - > { helper } { playAfterPowerOn } ) ;
}
# CD 0030 end
} elsif ( $ args [ 2 ] eq "0" ) {
#Log 0,"$name power off";
2016-10-01 16:46:46 +00:00
#readingsBulkUpdate( $hash, "presence", "absent" ); # CD 0013 deaktiviert, power sagt nichts <20> ber presence
2015-03-19 20:37:01 +00:00
readingsBulkUpdate ( $ hash , "state" , "off" ) ;
readingsBulkUpdate ( $ hash , "power" , "off" ) ;
SB_PLAYER_Amplifier ( $ hash ) ;
delete ( $ hash - > { helper } { playAfterPowerOn } ) if ( defined ( $ hash - > { helper } { playAfterPowerOn } ) ) ; # CD 0030
2016-10-01 16:46:46 +00:00
# CD 0031 wenn Player w<> hrend TTS ausgeschaltet wird nicht wieder einschalten
2015-03-19 20:37:01 +00:00
if ( ( $ hash - > { helper } { ttsstate } > TTS_IDLE ) && ( $ hash - > { helper } { ttsstate } < TTS_RESTORE ) ) {
$ hash - > { helper } { savedPlayerState } { power } = "off" if ( defined ( $ hash - > { helper } { savedPlayerState } ) ) ;
SB_PLAYER_SetTTSState ( $ hash , TTS_STOP , 1 , 0 ) ;
RemoveInternalTimer ( "TTSRestore:$name" ) ;
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + 0.01 ,
2015-03-19 20:37:01 +00:00
"SB_PLAYER_tcb_TTSRestore" ,
2017-05-28 19:14:57 +00:00
"TTSRestore:$name" ,
0 ) ;
2015-03-19 20:37:01 +00:00
}
# CD 0031 end
}
# CD 0000 end
# CD 0010 start prefset server mute
} elsif ( $ args [ 1 ] eq "mute" ) {
2017-05-28 19:14:57 +00:00
SB_PLAYER_SetSyncedVolume ( $ hash , - 1 , 0 ) if ( $ args [ 2 ] == 1 ) ;
2015-03-19 20:37:01 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} mixer volume ?\n" ) if ( $ args [ 2 ] == 0 ) ;
# CD 0010 end
# CD 0016 start
} elsif ( $ args [ 1 ] eq "alarmTimeoutSeconds" ) {
readingsBulkUpdate ( $ hash , "alarmsTimeout" , $ args [ 2 ] / 60 ) ;
} elsif ( $ args [ 1 ] eq "alarmSnoozeSeconds" ) {
readingsBulkUpdate ( $ hash , "alarmsSnooze" , $ args [ 2 ] / 60 ) ;
} elsif ( $ args [ 1 ] eq "alarmDefaultVolume" ) {
2016-10-01 16:46:46 +00:00
readingsBulkUpdate ( $ hash , "alarmsDefaultVolume" , $ args [ 2 ] ) ; # CD 0052 fixed
2015-03-19 20:37:01 +00:00
} elsif ( $ args [ 1 ] eq "alarmfadeseconds" ) {
2017-07-26 19:25:07 +00:00
if ( $ args [ 2 ] ne "0" ) {
2015-03-19 20:37:01 +00:00
readingsBulkUpdate ( $ hash , "alarmsFadeIn" , "on" ) ;
2017-07-26 19:25:07 +00:00
readingsBulkUpdate ( $ hash , "alarmsFadeSeconds" , $ args [ 2 ] ) ; # CD 0082
2015-03-19 20:37:01 +00:00
} else {
readingsBulkUpdate ( $ hash , "alarmsFadeIn" , "off" ) ;
}
# CD 0016 end
# CD 0018 start
} elsif ( $ args [ 1 ] eq "syncgroupid" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} status 0 500 tags:Kcu\n" ) ; # CD 0030 u added to tags
# CD 0018 end
2016-10-01 16:46:46 +00:00
# CD 0039 f<> r gesyncte Player bei <20> nderung am Slave erh<72> lt der Master eine prefset Meldung, an alle Slaves weitergeben
2015-06-18 20:23:54 +00:00
} elsif ( $ args [ 1 ] eq "repeat" ) {
if ( $ args [ 2 ] eq "0" ) {
readingsBulkUpdate ( $ hash , "repeat" , "off" ) ;
} elsif ( $ args [ 2 ] eq "1" ) {
readingsBulkUpdate ( $ hash , "repeat" , "one" ) ;
} elsif ( $ args [ 2 ] eq "2" ) {
readingsBulkUpdate ( $ hash , "repeat" , "all" ) ;
} else {
readingsBulkUpdate ( $ hash , "repeat" , "?" ) ;
}
if ( $ hash - > { PLAYERMAC } eq $ hash - > { SYNCMASTER } ) {
if ( defined ( $ hash - > { SYNCGROUP } ) && ( $ hash - > { SYNCGROUP } ne '?' ) && ( $ hash - > { SYNCMASTER } ne 'none' ) ) {
my @ pl = split ( "," , $ hash - > { SYNCGROUP } ) ;
if ( @ pl > 1 ) {
foreach ( @ pl ) {
IOWrite ( $ hash , "$_ playlist repeat ?\n" ) ;
}
}
}
}
} elsif ( $ args [ 1 ] eq "shuffle" ) {
if ( $ args [ 2 ] eq "0" ) {
readingsBulkUpdate ( $ hash , "shuffle" , "off" ) ;
} elsif ( $ args [ 2 ] eq "1" ) {
readingsBulkUpdate ( $ hash , "shuffle" , "song" ) ;
} elsif ( $ args [ 2 ] eq "2" ) {
readingsBulkUpdate ( $ hash , "shuffle" , "album" ) ;
} else {
readingsBulkUpdate ( $ hash , "shuffle" , "?" ) ;
}
if ( $ hash - > { PLAYERMAC } eq $ hash - > { SYNCMASTER } ) {
if ( defined ( $ hash - > { SYNCGROUP } ) && ( $ hash - > { SYNCGROUP } ne '?' ) && ( $ hash - > { SYNCMASTER } ne 'none' ) ) {
my @ pl = split ( "," , $ hash - > { SYNCGROUP } ) ;
if ( @ pl > 1 ) {
foreach ( @ pl ) {
IOWrite ( $ hash , "$_ playlist shuffle ?\n" ) ;
}
}
}
}
SB_PLAYER_GetStatus ( $ hash ) ;
# CD 0039 end
2015-03-19 20:37:01 +00:00
}
} else {
2017-05-28 19:14:57 +00:00
readingsBulkUpdate ( $ hash , "lastunknowncmd" ,
2015-03-19 20:37:01 +00:00
$ cmd . " " . join ( " " , @ args ) ) ;
}
# CD 0007 start
} elsif ( $ cmd eq "playerpref" ) {
if ( $ args [ 0 ] eq "syncVolume" ) {
if ( defined ( $ args [ 1 ] ) ) {
$ hash - > { SYNCVOLUME } = $ args [ 1 ] ;
my $ sva = AttrVal ( $ hash - > { NAME } , "syncVolume" , undef ) ;
# force attribute
if ( defined ( $ sva ) ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playerpref syncVolume 0\n" ) if ( ( $ sva ne "1" ) && ( $ args [ 1 ] ne "0" ) ) ;
IOWrite ( $ hash , "$hash->{PLAYERMAC} playerpref syncVolume 1\n" ) if ( ( $ sva eq "1" ) && ( $ args [ 1 ] ne "1" ) ) ;
}
}
}
# CD 0007 end
2016-10-01 16:46:46 +00:00
# CD 0016 start, von MM <20> bernommen, Namen Readings ge<67> ndert
2015-03-19 20:37:01 +00:00
elsif ( $ args [ 0 ] eq "alarmsEnabled" ) {
if ( defined ( $ args [ 1 ] ) ) {
if ( $ args [ 1 ] eq "1" ) {
readingsBulkUpdate ( $ hash , "alarmsEnabled" , "on" ) ; # CD 0016 Internal durch Reading ersetzt # CD 0017 'yes' durch 'on' ersetzt
} else {
readingsBulkUpdate ( $ hash , "alarmsEnabled" , "off" ) ; # CD 0016 Internal durch Reading ersetzt # CD 0017 'no' durch 'off' ersetzt
}
}
}
elsif ( $ args [ 0 ] eq "alarmDefaultVolume" ) {
2016-10-01 16:46:46 +00:00
if ( defined ( $ args [ 1 ] ) && ( $ args [ 1 ] ne "?" ) ) { # CD 0016 R<> ckmeldung auf Anfrage ignorieren
#$hash->{ALARMSVOLUME} = $args[1]; # CD 0016 nicht ben<65> tigt
2015-03-19 20:37:01 +00:00
readingsBulkUpdate ( $ hash , "alarmsDefaultVolume" , $ args [ 1 ] ) ;
}
}
elsif ( $ args [ 0 ] eq "alarmTimeoutSeconds" ) {
2016-10-01 16:46:46 +00:00
if ( defined ( $ args [ 1 ] ) && ( $ args [ 1 ] ne "?" ) ) { # CD 0016 R<> ckmeldung auf Anfrage ignorieren
#$hash->{ALARMSTIMEOUT} = $args[1]/60 . " min"; # CD 0016 nicht ben<65> tigt
2015-03-19 20:37:01 +00:00
readingsBulkUpdate ( $ hash , "alarmsTimeout" , $ args [ 1 ] / 60 ) ;
}
}
elsif ( $ args [ 0 ] eq "alarmSnoozeSeconds" ) {
2016-10-01 16:46:46 +00:00
if ( defined ( $ args [ 1 ] ) && ( $ args [ 1 ] ne "?" ) ) { # CD 0016 R<> ckmeldung auf Anfrage ignorieren
#$hash->{ALARMSSNOOZE} = $args[1]/60 . " min"; # CD 0016 nicht ben<65> tigt
2015-03-19 20:37:01 +00:00
readingsBulkUpdate ( $ hash , "alarmsSnooze" , $ args [ 1 ] / 60 ) ;
}
}
# CD 0016 end
# CD 0014 start
} elsif ( $ cmd eq "duration" ) {
readingsBulkUpdate ( $ hash , "duration" , $ args [ 0 ] ) ;
} elsif ( $ cmd eq "time" ) {
2016-10-01 16:46:46 +00:00
$ args [ 0 ] = 0 unless defined ( $ args [ 0 ] ) ; # CD 0059
$ args [ 0 ] = 0 if ( $ args [ 0 ] eq '?' ) ; # CD 0050
2015-03-19 20:37:01 +00:00
$ hash - > { helper } { elapsedTime } { VAL } = $ args [ 0 ] ;
$ hash - > { helper } { elapsedTime } { TS } = gettimeofday ( ) ;
2017-05-28 19:14:57 +00:00
readingsBulkUpdate ( $ hash , "currentTrackPosition" , int ( $ args [ 0 ] + 0.5 ) ) ; # CD 0047
2015-03-19 20:37:01 +00:00
delete ( $ hash - > { helper } { saveLocked } ) if ( ( $ hash - > { helper } { ttsstate } == TTS_IDLE ) && defined ( $ hash - > { helper } { saveLocked } ) ) ;
} elsif ( $ cmd eq "playlist_tracks" ) {
readingsBulkUpdate ( $ hash , "playlistTracks" , $ args [ 0 ] ) ;
# CD 0014 end
# CD 0018 sync Meldungen auswerten, alle anderen Player abfragen
} elsif ( $ cmd eq "sync" ) {
foreach my $ e ( keys % { $ hash - > { helper } { SB_PLAYER_SyncMasters } } ) {
2016-10-01 16:46:46 +00:00
IOWrite ( $ hash , $ hash - > { helper } { SB_PLAYER_SyncMasters } { $ e } { MAC } . " status 0 500 tags:Kcu\n" ) if defined ( $ hash - > { helper } { SB_PLAYER_SyncMasters } { $ e } { MAC } ) ; # CD 0039 u hinzugef<65> gt # CD 0056 if defined hinzugef<65> gt
2015-03-19 20:37:01 +00:00
}
2016-10-01 16:46:46 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} status 0 500 tags:Kcu\n" ) ; # CD 0056 auch betroffenen Player abfragen
2015-03-19 20:37:01 +00:00
# CD 0018
2016-10-01 16:46:46 +00:00
# CD 0052 jivealarm Meldungen ignorieren
} elsif ( $ cmd eq "jivealarm" ) {
# CD 0018
# CD 0022 fhemrelay ist keine Meldung des LMS sondern eine Info die von einem anderen Player <20> ber 98_SB_PLAYER kommt
2015-03-19 20:37:01 +00:00
} elsif ( $ cmd eq "fhemrelay" ) {
if ( defined ( $ args [ 0 ] ) ) {
2016-10-01 16:46:46 +00:00
# CD 0022 Favoriten vom Sync-Master <20> bernehmen
2015-03-19 20:37:01 +00:00
if ( $ args [ 0 ] eq "favorites" ) {
if ( defined ( $ args [ 1 ] ) ) {
$ hash - > { FAVSELECT } = $ args [ 1 ] ;
readingsBulkUpdate ( $ hash , "$hash->{FAVSET}" , "$hash->{FAVSELECT}" ) ;
}
}
# CD 0028 tts aktiv
elsif ( $ args [ 0 ] eq "ttsactive" ) {
$ hash - > { helper } { ttsMaster } = $ args [ 1 ] ;
Log3 ( $ hash , defined ( $ hash - > { helper } { ttsOptions } { debug } ) ? 0 : 6 , "SB_PLAYER_Parse: $name: fhemrelay ttsactive " . $ hash - > { helper } { ttsMaster } ) ;
SB_PLAYER_SetTTSState ( $ hash , TTS_SYNCGROUPACTIVE , 1 , 0 ) ;
2016-10-01 16:46:46 +00:00
# CD 0031 Lautst<73> rke setzen
2015-03-19 20:37:01 +00:00
if ( ! defined ( $ hash - > { SYNCVOLUME } ) || ( $ hash - > { SYNCVOLUME } == 0 ) ) {
if ( defined ( $ hash - > { helper } { ttsVolume } ) ) {
$ hash - > { helper } { ttsRestoreVolumeAfterStop } = ReadingsVal ( $ name , "volumeStraight" , "?" ) ;
my $ vol = $ hash - > { helper } { ttsVolume } ;
$ vol = AttrVal ( $ name , "volumeLimit" , 100 ) if ( ( $ hash - > { helper } { ttsVolume } > AttrVal ( $ name , "volumeLimit" , 100 ) ) && ! defined ( $ hash - > { helper } { ttsOptions } { ignorevolumelimit } ) ) ;
2017-05-28 19:14:57 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} mixer volume " . SB_PLAYER_FHEM2LMSVolume ( $ hash , $ vol ) . "\n" ) ; # CD 0065 SB_PLAYER_FHEM2LMSVolume
2015-03-19 20:37:01 +00:00
}
}
# CD 0031 end
}
elsif ( $ args [ 0 ] eq "ttsstopped" ) {
2016-10-01 16:46:46 +00:00
# CD 0056 Meldung ignorieren wenn Player Syncmaster ist
if ( $ hash - > { PLAYERMAC } eq $ hash - > { SYNCMASTER } ) {
Log3 ( $ hash , defined ( $ hash - > { helper } { ttsOptions } { debug } ) ? 0 : 6 , "SB_PLAYER_Parse: $name: fhemrelay ttsstopped, ignoring" ) ;
} else {
# CD 0056 end
Log3 ( $ hash , defined ( $ hash - > { helper } { ttsOptions } { debug } ) ? 0 : 6 , "SB_PLAYER_Parse: $name: fhemrelay ttsstopped" ) ;
if ( $ hash - > { helper } { ttsstate } == TTS_PLAYING ) {
2017-05-28 19:14:57 +00:00
# CD 0034 delay ttsstopped
2016-10-01 16:46:46 +00:00
RemoveInternalTimer ( "TTSStopped:$name" ) ;
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + 0.01 ,
2016-10-01 16:46:46 +00:00
"SB_PLAYER_tcb_TTSStopped" ,
2017-05-28 19:14:57 +00:00
"TTSRestore:$name" ,
2016-10-01 16:46:46 +00:00
0 ) ;
}
2015-03-19 20:37:01 +00:00
}
}
elsif ( $ args [ 0 ] eq "ttsplaying" ) {
Log3 ( $ hash , defined ( $ hash - > { helper } { ttsOptions } { debug } ) ? 0 : 6 , "SB_PLAYER_Parse: $name: fhemrelay ttsplaying" ) ;
if ( $ hash - > { helper } { ttsstate } == TTS_WAITFORPLAY ) {
SB_PLAYER_SetTTSState ( $ hash , TTS_PLAYING , 1 , 0 ) ;
}
}
elsif ( $ args [ 0 ] eq "ttsidle" ) {
Log3 ( $ hash , defined ( $ hash - > { helper } { ttsOptions } { debug } ) ? 0 : 6 , "SB_PLAYER_Parse: $name: fhemrelay ttsidle" ) ;
SB_PLAYER_SetTTSState ( $ hash , TTS_IDLE , 1 , 0 ) ;
# CD 0030 start
if ( defined ( $ hash - > { helper } { ttspoweroffafterstop } ) ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} power 0\n" ) ;
delete ( $ hash - > { helper } { ttspoweroffafterstop } ) ;
}
# CD 0030 end
2016-10-01 16:46:46 +00:00
# CD 0031 Lautst<73> rke zur<75> cksetzen
2015-03-19 20:37:01 +00:00
if ( defined ( $ hash - > { helper } { ttsRestoreVolumeAfterStop } ) ) {
2017-05-28 19:14:57 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} mixer volume " . SB_PLAYER_FHEM2LMSVolume ( $ hash , $ hash - > { helper } { ttsRestoreVolumeAfterStop } ) . "\n" ) ; # CD 0065 SB_PLAYER_FHEM2LMSVolume
2015-03-19 20:37:01 +00:00
delete ( $ hash - > { helper } { ttsRestoreVolumeAfterStop } ) ;
}
# CD 0031 end
}
elsif ( $ args [ 0 ] eq "ttsadd" ) {
Log3 ( $ hash , defined ( $ hash - > { helper } { ttsOptions } { debug } ) ? 0 : 6 , "SB_PLAYER_Parse: $name: fhemrelay ttsadd $args[1]" ) ;
push ( @ { $ hash - > { helper } { ttsqueue } } , $ args [ 1 ] ) ;
}
# CD 0030 start
elsif ( $ args [ 0 ] eq "ttsforcegroupon" ) {
Log3 ( $ hash , defined ( $ hash - > { helper } { ttsOptions } { debug } ) ? 0 : 6 , "SB_PLAYER_Parse: $name: fhemrelay ttsforcegroupon" ) ;
if ( $ hash - > { CANPOWEROFF } ne "0" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} power 1\n" ) ;
$ hash - > { helper } { ttspoweroffafterstop } = 1 ;
}
}
# CD 0030 end
}
# CD 0022 end
2017-05-28 19:14:57 +00:00
# CD 0065 start
} elsif ( $ cmd eq "songinfo" ) {
my $ trackid = 0 ;
my $ title = "" ;
my $ artist = "" ;
my $ album = "" ;
my $ flush = 0 ;
#Log3( $hash, 3, "SB_PLAYER_Parse: $name: parsing songinfo: $msg" ); # CD 0072
2017-08-26 19:46:07 +00:00
$ hash - > { helper } { songinfopending } - - ; # CD 0084
2017-05-28 19:14:57 +00:00
foreach ( @ args ) {
$ flush = 0 ;
if ( $ _ =~ /^(id:)(-?[0-9]*)/ ) {
$ trackid = $ 2 ;
# bereits bekannt -> abbrechen
if ( defined ( $ hash - > { helper } { playlistInfo } { $ 2 } ) && ( $ trackid > 0 ) ) {
last ;
}
2017-07-26 19:25:07 +00:00
if ( $ trackid < 0 ) {
$ hash - > { helper } { playlistInfo } { $ trackid } { artist } = ReadingsVal ( $ name , 'currentArtist' , '-' ) ;
$ hash - > { helper } { playlistInfo } { $ trackid } { title } = ReadingsVal ( $ name , 'currentTitle' , '-' ) ;
} else {
$ hash - > { helper } { playlistInfo } { $ trackid } { artist } = '-' ;
$ hash - > { helper } { playlistInfo } { $ trackid } { title } = 'no data' ;
}
2017-05-28 19:14:57 +00:00
$ hash - > { helper } { playlistInfo } { $ trackid } { album } = '-' ;
$ hash - > { helper } { playlistInfo } { $ trackid } { coverid } = 0 ;
$ hash - > { helper } { playlistInfo } { $ trackid } { duration } = 0 ;
$ hash - > { helper } { playlistInfo } { $ trackid } { tracknum } = 0 ;
$ hash - > { helper } { playlistInfo } { $ trackid } { url } = '-' ;
$ hash - > { helper } { playlistInfo } { $ trackid } { artwork_url } = "-" unless ( defined ( $ hash - > { helper } { playlistInfo } { $ trackid } { artwork_url } ) ) ; # CD 0068
next ;
} elsif ( $ _ =~ /^(title:)(.*)/ ) {
$ title = $ 2 ;
$ flush = 6 ;
} elsif ( $ _ =~ /^(artist:)(.*)/ ) {
$ artist = $ 2 ;
$ flush = 5 ;
} elsif ( $ _ =~ /^(coverid:)(.*)/ ) {
$ hash - > { helper } { playlistInfo } { $ trackid } { coverid } = $ 2 ;
$ flush = 7 ;
} elsif ( $ _ =~ /^(remote:)(.*)/ ) {
$ hash - > { helper } { playlistInfo } { $ trackid } { remote } = 1 ;
$ flush = 7 ;
} elsif ( $ _ =~ /^(duration:)(.*)/ ) {
$ hash - > { helper } { playlistInfo } { $ trackid } { duration } = $ 2 ;
$ flush = 7 ;
} elsif ( $ _ =~ /^(tracknum:)(.*)/ ) {
$ hash - > { helper } { playlistInfo } { $ trackid } { tracknum } = $ 2 ;
$ flush = 7 ;
} elsif ( $ _ =~ /^(album:)(.*)/ ) {
$ album = $ 2 ;
$ flush = 3 ;
} elsif ( $ _ =~ /^(url:)(.*)/ ) {
$ hash - > { helper } { playlistInfo } { $ trackid } { url } = $ 2 ;
$ flush = 7 ;
} elsif ( $ _ =~ /^(artwork_url:)(http.*)/ ) {
$ hash - > { helper } { playlistInfo } { $ trackid } { artwork_url } = $ 2 ;
$ flush = 7 ;
} elsif ( $ _ =~ /^(.*:)(.*)/ ) {
$ flush = 7 ;
} else {
$ title . = " " . $ _ if ( $ title ne "" ) ;
$ album . = " " . $ _ if ( $ album ne "" ) ;
$ artist . = " " . $ _ if ( $ artist ne "" ) ;
next ;
}
if ( ( $ flush & 1 ) && ( $ title ne "" ) ) {
$ hash - > { helper } { playlistInfo } { $ trackid } { title } = $ title ;
$ title = "" ;
}
if ( ( $ flush & 2 ) && ( $ artist ne "" ) ) {
$ hash - > { helper } { playlistInfo } { $ trackid } { artist } = $ artist ;
$ artist = "" ;
}
if ( ( $ flush & 4 ) && ( $ album ne "" ) ) {
$ hash - > { helper } { playlistInfo } { $ trackid } { album } = $ album ;
$ album = "" ;
}
}
$ hash - > { helper } { playlistInfo } { $ trackid } { title } = $ title if ( $ title ne "" ) ;
$ hash - > { helper } { playlistInfo } { $ trackid } { artist } = $ artist if ( $ artist ne "" ) ;
$ hash - > { helper } { playlistInfo } { $ trackid } { album } = $ album if ( $ album ne "" ) ;
# TEST
# if (rand() > 0.4) {delete $hash->{helper}{playlistInfo}{$trackid}};
# TEST
} elsif ( $ cmd eq "FHEMupdatePlaylistInfoDone" ) {
2017-08-26 19:46:07 +00:00
$ hash - > { helper } { songinfopending } = 0 ; # CD 0084
RemoveInternalTimer ( "ftuiMedialist:$name" ) ; # CD 0085
InternalTimer ( gettimeofday ( ) + 0.01 , # CD 0085
"SB_PLAYER_tcb_ftuiMedialist" ,
"ftuiMedialist:$name" ,
0 ) ;
2017-05-28 19:14:57 +00:00
# CD 0065 end
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "NONE" ) {
2017-05-28 19:14:57 +00:00
# we shall never end up here, as cmd=NONE is used by the server for
2015-03-19 20:37:01 +00:00
# autocreate
2014-02-20 23:34:51 +00:00
} else {
2016-10-01 16:46:46 +00:00
# unknown command, we push it to the last command thingy
2017-05-28 19:14:57 +00:00
readingsBulkUpdate ( $ hash , "lastunknowncmd" ,
2015-03-19 20:37:01 +00:00
$ cmd . " " . join ( " " , @ args ) ) ;
2014-02-20 23:34:51 +00:00
}
2017-05-28 19:14:57 +00:00
2014-02-20 23:34:51 +00:00
# and signal the end of the readings update
2017-05-28 19:14:57 +00:00
2014-02-20 23:34:51 +00:00
if ( AttrVal ( $ name , "donotnotify" , "false" ) eq "true" ) {
2015-03-19 20:37:01 +00:00
readingsEndUpdate ( $ hash , 0 ) ;
2014-02-20 23:34:51 +00:00
} else {
2015-03-19 20:37:01 +00:00
readingsEndUpdate ( $ hash , 1 ) ;
2014-02-20 23:34:51 +00:00
}
2017-05-28 19:14:57 +00:00
2014-02-20 23:34:51 +00:00
Log3 ( $ hash , 5 , "SB_PLAYER_Parse: $name: leaving" ) ;
return ( $ name ) ;
}
2017-08-26 19:46:07 +00:00
# CD 0085
# ----------------------------------------------------------------------------
# delay building ftuiMedialist reading
# ----------------------------------------------------------------------------
sub SB_PLAYER_tcb_ftuiMedialist ( $ ) {
my ( $ in ) = shift ;
my ( undef , $ name ) = split ( ':' , $ in ) ;
my $ hash = $ defs { $ name } ;
if ( defined ( $ hash - > { helper } { ftuiSupport } { medialist } ) ) {
my $ t31 = time ;
readingsBeginUpdate ( $ hash ) ;
if ( ( time - $ t31 ) > 0.5 ) {
Log3 ( $ hash , 3 , "SB_PLAYER_tcb_ftuiMedialist($name), time:" . int ( ( time - $ t31 ) * 1000 ) . "ms cmd: prepare FHEM event handling" ) ;
}
$ t31 = time ;
SB_PLAYER_ftuiMedialist ( $ hash ) ;
if ( ( time - $ t31 ) > 0.5 ) {
Log3 ( $ hash , 3 , "SB_PLAYER_tcb_ftuiMedialist($name), time:" . int ( ( time - $ t31 ) * 1000 ) . "ms cmd: SB_PLAYER_ftuiMedialist" ) ;
}
$ t31 = time ;
if ( AttrVal ( $ name , "donotnotify" , "false" ) eq "true" ) {
readingsEndUpdate ( $ hash , 0 ) ;
} else {
readingsEndUpdate ( $ hash , 1 ) ;
}
if ( ( time - $ t31 ) > 0.5 ) {
Log3 ( $ hash , 3 , "SB_PLAYER_tcb_ftuiMedialist($name), time:" . int ( ( time - $ t31 ) * 1000 ) . "ms cmd: execute FHEM event handling" ) ;
}
}
}
2017-07-26 19:25:07 +00:00
# CD 0082
# ----------------------------------------------------------------------------
# build ftuiMedialist reading
# ----------------------------------------------------------------------------
sub SB_PLAYER_ftuiMedialist ($) {
my ( $ hash ) = @ _ ;
my $ name = $ hash - > { NAME } ;
my $ wait = 1 ;
my $ trackcounter = 1 ; # CD 0082
my $ coverbase = "http://" . $ hash - > { SBSERVER } . "/music/" ;
return unless defined ( $ hash - > { helper } { playlistIds } ) ; # CD 0082
my @ ids = split ( ',' , $ hash - > { helper } { playlistIds } ) ;
my $ ftuimedialist = "[" ;
# [ {"Artist":"abc", "Title":"def", "Album":"yxz", "Time":"123", "File":"spotify:track:123456", "Track":"1", "Cover":"https://...." }, {"Artist":"abc", ... ]
$ hash - > { helper } { playlistInfoRetries } - - ; # CD 0076
foreach ( @ ids ) {
if ( defined ( $ hash - > { helper } { playlistInfo } { $ _ } ) ) {
# CD 0082 Artist von Remote-Streams ersetzen
if ( ( $ _ < 0 ) && ( ReadingsVal ( $ name , 'playlistCurrentTrack' , 0 ) eq $ trackcounter ) ) {
$ hash - > { helper } { playlistInfo } { $ _ } { artist } = ReadingsVal ( $ name , 'currentArtist' , $ hash - > { helper } { playlistInfo } { $ _ } { artist } ) ;
}
if ( ( $ _ < 0 ) && ( ReadingsVal ( $ name , 'playlistCurrentTrack' , 0 ) eq $ trackcounter ) ) {
$ hash - > { helper } { playlistInfo } { $ _ } { title } = ReadingsVal ( $ name , 'currentTitle' , $ hash - > { helper } { playlistInfo } { $ _ } { title } ) ;
}
$ hash - > { helper } { playlistInfo } { $ _ } { artist } =~ s/\"//g ;
$ hash - > { helper } { playlistInfo } { $ _ } { title } =~ s/\"//g ;
$ hash - > { helper } { playlistInfo } { $ _ } { album } =~ s/\"//g ;
$ hash - > { helper } { playlistInfo } { $ _ } { artist } =~ s{\\} {\\\\}g ; # CD 0081
$ hash - > { helper } { playlistInfo } { $ _ } { title } =~ s{\\} {\\\\}g ; # CD 0081
$ hash - > { helper } { playlistInfo } { $ _ } { album } =~ s{\\} {\\\\}g ; # CD 0081
$ ftuimedialist . = "{\"Artist\":\"" . $ hash - > { helper } { playlistInfo } { $ _ } { artist } . "\"," ;
$ ftuimedialist . = "\"Title\":\"" . $ hash - > { helper } { playlistInfo } { $ _ } { title } . "\"," ;
$ ftuimedialist . = "\"Album\":\"" . $ hash - > { helper } { playlistInfo } { $ _ } { album } . "\"," ;
$ ftuimedialist . = "\"Time\":\"" . ( int ( $ hash - > { helper } { playlistInfo } { $ _ } { duration } ) ) . "\"," ;
$ ftuimedialist . = "\"File\":\"" . $ hash - > { helper } { playlistInfo } { $ _ } { url } . "\"," ;
$ ftuimedialist . = "\"Track\":\"" . $ hash - > { helper } { playlistInfo } { $ _ } { tracknum } . "\"," ;
if ( defined ( $ hash - > { helper } { playlistInfo } { $ _ } { artwork_url } ) && ( $ hash - > { helper } { playlistInfo } { $ _ } { artwork_url } ne "-" ) ) {
$ ftuimedialist . = "\"Cover\":\"" . $ hash - > { helper } { playlistInfo } { $ _ } { artwork_url } . "\"}," ;
} else {
# CD 0082 versuchen Cover von Remote-Streams zu ersetzen
if ( ( $ _ < 0 ) && ( ReadingsVal ( $ name , 'playlistCurrentTrack' , 0 ) eq $ trackcounter ) && ( ReadingsVal ( $ name , 'coverarturl' , 'x' ) !~ /radio\.png/ ) ) {
$ ftuimedialist . = "\"Cover\":\"" . ReadingsVal ( $ name , 'coverarturl' , $ coverbase . $ hash - > { helper } { playlistInfo } { $ _ } { coverid } . "/cover_50x50_o" ) . '"},' ;
} else {
# CD 0082 end
$ ftuimedialist . = "\"Cover\":\"" . $ coverbase . $ hash - > { helper } { playlistInfo } { $ _ } { coverid } . "/cover_50x50_o\"}," ;
}
}
} else {
$ ftuimedialist . = "{\"Artist\":\"-\"," ;
if ( $ hash - > { helper } { playlistInfoRetries } > 0 ) { # CD 0076
SB_PLAYER_SonginfoAddQueue ( $ hash , $ _ , $ wait ) unless ( $ _ == 0 ) ; # CD 0072 # CD 0076
$ wait = 0 ;
2017-08-26 19:46:07 +00:00
# CD 0084 start
if ( ReadingsVal ( $ name , 'playlistTracks' , 0 ) eq '0' ) {
$ ftuimedialist . = "\"Title\":\"-\"," ;
} else {
# CD 0084 end
$ ftuimedialist . = "\"Title\":\"loading...\"," ;
}
2017-07-26 19:25:07 +00:00
} else {
$ ftuimedialist . = "\"Title\":\"no data\"," ; # CD 0076
Log3 ( $ hash , 3 , "SB_PLAYER_Parse: $name: no songinfo for id $_" ) ; # CD 0072
}
2017-08-26 19:46:07 +00:00
$ ftuimedialist . = "\"Album\":\"-\"," ;
$ ftuimedialist . = "\"Time\":\"0\"," ;
$ ftuimedialist . = "\"File\":\"-\"," ;
$ ftuimedialist . = "\"Track\":\"0\"," ;
$ ftuimedialist . = "\"Cover\":\"-\"}," ;
2017-07-26 19:25:07 +00:00
}
$ trackcounter += 1 ; # CD 0082
}
$ ftuimedialist =~ s/,$/]/ ;
readingsBulkUpdate ( $ hash , "ftuiMedialist" , $ ftuimedialist ) ;
}
# CD 0082 end
2016-10-01 16:46:46 +00:00
# CD 0054
# ----------------------------------------------------------------------------
# check if value is in 'event-on-change-reading' list
# ----------------------------------------------------------------------------
sub SB_PLAYER_check_eocr ($$) {
my ( $ hash , $ reading ) = @ _ ;
my $ name = $ hash - > { NAME } ;
my $ attreocr = $ hash - > { ".attreocr" } ;
# determine whether the reading is listed in any of the attributes
my $ eocr = $ attreocr &&
( my @ eocrv = grep { my $ l = $ _ ; $ l =~ s/:.*// ;
( $ reading =~ m/^$l$/ ) ? $ _ : undef } @ { $ attreocr } ) ;
return ! ( $ attreocr ) || ( $ eocr ) ;
}
2015-03-19 20:37:01 +00:00
# CD 0030
# ----------------------------------------------------------------------------
# delay TTS
# ----------------------------------------------------------------------------
sub SB_PLAYER_tcb_TTSDelay ( $ ) {
my ( $ in ) = shift ;
my ( undef , $ name ) = split ( ':' , $ in ) ;
my $ hash = $ defs { $ name } ;
SB_PLAYER_SetTTSState ( $ hash , TTS_WAITFORPLAY , 0 , 0 ) ;
IOWrite ( $ hash , "$hash->{PLAYERMAC} play\n" ) ;
2016-10-01 16:46:46 +00:00
# CD 0038 Timeout hinzugef<65> gt
2015-06-18 20:23:54 +00:00
RemoveInternalTimer ( "TimeoutTTSWaitForPlay:$name" ) ;
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + 10.00 ,
2015-06-18 20:23:54 +00:00
"SB_PLAYER_tcb_TimeoutTTSWaitForPlay" ,
2017-05-28 19:14:57 +00:00
"TimeoutTTSWaitForPlay:$name" ,
2015-06-18 20:23:54 +00:00
0 ) ;
# CD 0038 end
2015-03-19 20:37:01 +00:00
}
# CD 0030
2015-06-18 20:23:54 +00:00
# CD 0038
# ----------------------------------------------------------------------------
# TTS 'wait for play' timeout
# ----------------------------------------------------------------------------
sub SB_PLAYER_tcb_TimeoutTTSWaitForPlay ( $ ) {
my ( $ in ) = shift ;
my ( undef , $ name ) = split ( ':' , $ in ) ;
my $ hash = $ defs { $ name } ;
if ( $ hash - > { helper } { ttsstate } == TTS_WAITFORPLAY ) {
readingsBeginUpdate ( $ hash ) ;
SB_PLAYER_TTSStopped ( $ hash ) ;
if ( AttrVal ( $ name , "donotnotify" , "false" ) eq "true" ) {
readingsEndUpdate ( $ hash , 0 ) ;
} else {
readingsEndUpdate ( $ hash , 1 ) ;
}
}
}
# ----------------------------------------------------------------------------
# TTS 'wait for power on' timeout
# ----------------------------------------------------------------------------
sub SB_PLAYER_tcb_TimeoutTTSWaitForPowerOn ( $ ) {
my ( $ in ) = shift ;
my ( undef , $ name ) = split ( ':' , $ in ) ;
my $ hash = $ defs { $ name } ;
if ( $ hash - > { helper } { ttsstate } == TTS_WAITFORPOWERON ) {
SB_PLAYER_SetTTSState ( $ hash , TTS_IDLE , 0 , 0 ) ;
}
}
# CD 0038
2015-04-07 19:48:18 +00:00
# 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
2015-06-18 20:23:54 +00:00
# CD 0042
# ----------------------------------------------------------------------------
# start tts after power on, wait if startup is not complete
# ----------------------------------------------------------------------------
sub SB_PLAYER_tcb_TTSStartAfterPowerOn ( $ ) {
my ( $ in ) = shift ;
my ( undef , $ name ) = split ( ':' , $ in ) ;
my $ hash = $ defs { $ name } ;
if ( ( $ hash - > { helper } { playerStatusOK } == 1 ) || ( $ hash - > { helper } { playerStatusOKCounter } > 10 ) ) {
SB_PLAYER_PrepareTalk ( $ hash ) ;
SB_PLAYER_LoadTalk ( $ hash ) ;
} else {
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + 1 ,
2015-06-18 20:23:54 +00:00
"SB_PLAYER_tcb_TTSStartAfterPowerOn" ,
2017-05-28 19:14:57 +00:00
"TTSStartAfterPowerOn:$name" ,
2015-06-18 20:23:54 +00:00
0 ) ;
$ hash - > { helper } { playerStatusOKCounter } + + ;
}
}
# CD 0042 end
2015-03-19 20:37:01 +00:00
# ----------------------------------------------------------------------------
# called when talk is stopped, check if there are queued elements
# ----------------------------------------------------------------------------
sub SB_PLAYER_TTSStopped ($) {
2015-04-07 19:48:18 +00:00
# readingsBulkUpdate muss aktiv sein
2015-03-19 20:37:01 +00:00
my ( $ hash ) = @ _ ;
my $ name = $ hash - > { NAME } ;
if ( defined ( $ hash - > { helper } { ttsqueue } ) ) {
SB_PLAYER_SetTTSState ( $ hash , TTS_LOADPLAYLIST , 1 , 0 ) ;
2015-04-07 19:48:18 +00:00
SB_PLAYER_LoadTalk ( $ hash ) ; # CD 0033
2015-03-19 20:37:01 +00:00
} else {
SB_PLAYER_SetTTSState ( $ hash , TTS_STOP , 1 , 0 ) ;
RemoveInternalTimer ( "TTSRestore:$name" ) ;
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + 0.01 ,
2015-03-19 20:37:01 +00:00
"SB_PLAYER_tcb_TTSRestore" ,
2017-05-28 19:14:57 +00:00
"TTSRestore:$name" ,
2015-03-19 20:37:01 +00:00
0 ) ;
}
}
2014-02-20 23:34:51 +00:00
# ----------------------------------------------------------------------------
# Undefinition of an SB_PLAYER
# called when undefining (delete) and element
# ----------------------------------------------------------------------------
sub SB_PLAYER_Undef ( $$$ ) {
my ( $ hash , $ arg ) = @ _ ;
2017-05-28 19:14:57 +00:00
2014-02-20 23:34:51 +00:00
Log3 ( $ hash , 5 , "SB_PLAYER_Undef: called" ) ;
2017-05-28 19:14:57 +00:00
2017-06-04 09:59:54 +00:00
SB_PLAYER_RemoveInternalTimers ( $ hash ) ;
2014-02-20 23:34:51 +00:00
2017-05-28 19:14:57 +00:00
# to be reviewed if that works.
2014-02-20 23:34:51 +00:00
# check for uc()
# what is $hash->{DEF}?
2017-05-28 19:14:57 +00:00
delete $ modules { SB_PLAYER } { defptr } { $ hash - > { FHEMUID } } ; # CD 0071 uc($hash->{DEF}) durch $hash->{FHEMUID} ersetzt
2014-02-20 23:34:51 +00:00
return ( undef ) ;
}
# ----------------------------------------------------------------------------
# Shutdown function - called before fhem shuts down
# ----------------------------------------------------------------------------
sub SB_PLAYER_Shutdown ( $$ ) {
my ( $ hash , $ dev ) = @ _ ;
2017-05-28 19:14:57 +00:00
2017-06-04 09:59:54 +00:00
SB_PLAYER_RemoveInternalTimers ( $ hash ) ;
2014-02-20 23:34:51 +00:00
Log3 ( $ hash , 5 , "SB_PLAYER_Shutdown: called" ) ;
return ( undef ) ;
}
# ----------------------------------------------------------------------------
# Get of a module
# called upon get <name> cmd, arg1, arg2, ....
# ----------------------------------------------------------------------------
sub SB_PLAYER_Get ( $@ ) {
my ( $ hash , @ a ) = @ _ ;
2017-05-28 19:14:57 +00:00
2014-07-23 06:22:52 +00:00
my $ name = $ hash - > { NAME } ;
2014-02-20 23:34:51 +00:00
2015-03-19 20:37:01 +00:00
Log3 ( $ hash , 4 , "SB_PLAYER_Get: called with @a" ) ;
2014-02-20 23:34:51 +00:00
2014-07-23 06:22:52 +00:00
if ( @ a < 2 ) {
2015-03-19 20:37:01 +00:00
my $ msg = "SB_PLAYER_Get: $name: wrong number of arguments" ;
Log3 ( $ hash , 5 , $ msg ) ;
return ( $ msg ) ;
2014-07-23 06:22:52 +00:00
}
2014-02-20 23:34:51 +00:00
2014-07-23 06:22:52 +00:00
#my $name = shift( @a );
shift ( @ a ) ; # name
2017-05-28 19:14:57 +00:00
my $ cmd = shift ( @ a ) ;
2014-02-20 23:34:51 +00:00
2014-07-23 06:22:52 +00:00
if ( $ cmd eq "?" ) {
2017-05-28 19:14:57 +00:00
my $ res = "Unknown argument ?, choose one of " .
2016-10-01 16:46:46 +00:00
"volume " . $ hash - > { FAVSET } . " savedStates alarmPlaylists" ; # CD 0045 alarmPlaylists hinzugef<65> gt
2015-03-19 20:37:01 +00:00
return ( $ res ) ;
2017-05-28 19:14:57 +00:00
2015-03-19 20:37:01 +00:00
} elsif ( ( $ cmd eq "volume" ) || ( $ cmd eq "volumeStraight" ) ) {
return ( scalar ( ReadingsVal ( "$name" , "volumeStraight" , 25 ) ) ) ;
2014-07-06 22:14:26 +00:00
} elsif ( $ cmd eq $ hash - > { FAVSET } ) {
2015-03-19 20:37:01 +00:00
return ( "$hash->{FAVSELECT}" ) ;
2014-07-06 22:14:26 +00:00
2015-06-18 20:23:54 +00:00
# CD 0036 start
} elsif ( $ cmd eq 'savedStates' ) {
my $ out = "" ;
if ( defined ( $ hash - > { helper } { savedPlayerState } ) ) {
foreach my $ pl ( keys % { $ hash - > { helper } { savedPlayerState } } ) {
$ out . = $ pl . "\n" unless ( $ pl =~ /xxTTSxx/ ) ;
}
}
return ( $ out ) ;
# CD 0036 end
2015-11-02 08:26:30 +00:00
# CD 0045 start
} elsif ( $ cmd eq 'alarmPlaylists' ) {
my $ out = "" ;
if ( defined ( $ hash - > { helper } { alarmPlaylists } ) ) {
foreach my $ e ( keys % { $ hash - > { helper } { alarmPlaylists } } ) {
$ out . = $ hash - > { helper } { alarmPlaylists } { $ e } { title } . "\n" ;
}
}
return ( $ out ) ;
# CD 0045 end
2014-02-20 23:34:51 +00:00
} else {
2015-03-19 20:37:01 +00:00
my $ msg = "SB_PLAYER_Get: $name: unkown argument" ;
Log3 ( $ hash , 5 , $ msg ) ;
return ( $ msg ) ;
2017-05-28 19:14:57 +00:00
}
2014-02-20 23:34:51 +00:00
return ( undef ) ;
}
2015-03-19 20:37:01 +00:00
# CD 0030 start
# ----------------------------------------------------------------------------
# Calculate delay for TTS
# ----------------------------------------------------------------------------
sub SB_PLAYER_GetTTSDelay ( $ ) {
my ( $ hash ) = @ _ ;
my $ name = $ hash - > { NAME } ;
2017-05-28 19:14:57 +00:00
2015-03-19 20:37:01 +00:00
# todo synced players
2017-05-28 19:14:57 +00:00
2015-03-19 20:37:01 +00:00
if ( defined ( $ hash - > { helper } { ttsDelay } ) ) {
if ( ReadingsVal ( $ name , "power" , "x" ) eq "on" ) {
return $ hash - > { helper } { ttsDelay } { PowerIsOn }
} else {
return $ hash - > { helper } { ttsDelay } { PowerIsOff }
}
} else {
return 0 ;
}
}
# CD 0030 end
2015-04-07 19:48:18 +00:00
# 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 } } ) ) {
2017-05-28 19:14:57 +00:00
# CD 0077 unbenutzte Attribute entfernen
$ modules { $ hash - > { TYPE } } { AttrList } =~ s/serverautoon.// ;
$ modules { $ hash - > { TYPE } } { AttrList } =~ s/idismac.// ;
2017-08-26 19:46:07 +00:00
# CD 0084
InternalTimer ( gettimeofday ( ) + 1.0 ,
"SB_PLAYER_tcb_SonginfoHandleQueue" ,
"SonginfoHandleQueue:$name" ,
0 ) ;
2015-04-07 19:48:18 +00:00
}
2015-06-18 20:23:54 +00:00
# CD 0036 start
2015-11-02 08:26:30 +00:00
if ( grep ( m/^SAVE$|^SHUTDOWN$/ , @ { $ dev_hash - > { CHANGED } } ) ) { # CD 0043 auch bei SHUTDOWN speichern
2017-05-28 19:14:57 +00:00
# CD 0077 unbenutzte Attribute entfernen
delete ( $ attr { $ name } { serverautoon } ) if ( defined ( $ attr { $ name } { serverautoon } ) ) ;
delete ( $ attr { $ name } { idismac } ) if ( defined ( $ attr { $ name } { idismac } ) ) ;
2015-06-18 20:23:54 +00:00
SB_PLAYER_SavePlayerStates ( $ hash ) if ( $ SB_PLAYER_hasDataDumper == 1 ) ;
}
# CD 0036 end
2017-05-28 19:14:57 +00:00
2015-04-07 19:48:18 +00:00
# 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 } ) ) ;
2017-05-28 19:14:57 +00:00
2015-04-07 19:48:18 +00:00
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" ) ;
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + 0.01 ,
2015-04-07 19:48:18 +00:00
"SB_PLAYER_tcb_StartT2STalk" ,
2017-05-28 19:14:57 +00:00
"StartTalk:$name" ,
2015-04-07 19:48:18 +00:00
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 ) ) {
2016-10-01 16:46:46 +00:00
# zu sp<73> t, weiter warten
2015-04-07 19:48:18 +00:00
} 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
}
2014-02-20 23:34:51 +00:00
# ----------------------------------------------------------------------------
# Set of a module
# called upon set <name> cmd, arg1, arg2, ....
# ----------------------------------------------------------------------------
sub SB_PLAYER_Set ( $@ ) {
my ( $ hash , $ name , $ cmd , @ arg ) = @ _ ;
#my $name = $hash->{NAME};
2015-06-18 20:23:54 +00:00
Log3 ( $ hash , 5 , "SB_PLAYER_Set: called with $cmd" ) ;
2014-02-20 23:34:51 +00:00
# check if we have received a command
2017-05-28 19:14:57 +00:00
if ( ! defined ( $ cmd ) ) {
2015-03-19 20:37:01 +00:00
my $ msg = "$name: set needs at least one parameter" ;
Log3 ( $ hash , 3 , $ msg ) ;
return ( $ msg ) ;
2014-02-20 23:34:51 +00:00
}
# now parse the commands
if ( $ cmd eq "?" ) {
2015-03-19 20:37:01 +00:00
# this one should give us a drop down list
2017-05-28 19:14:57 +00:00
my $ res = "Unknown argument ?, choose one of " .
"on off stop:noArg play:noArg pause:noArg " .
2015-06-18 20:23:54 +00:00
"save " . # CD 0014 # CD 0036 removed :noArg
2017-05-28 19:14:57 +00:00
"volume:slider,0,1,100 " .
"volumeStraight:slider,0,1,100 " .
"volumeUp:noArg volumeDown:noArg " .
"mute:noArg repeat:off,one,all show statusRequest:noArg " .
2016-10-01 16:46:46 +00:00
"shuffle:off,song,album next:noArg prev:noArg playlist sleep " . # CD 0017 song und album hinzugef<65> gt # CD 0052 shuffle on entfernt
2015-03-19 20:37:01 +00:00
"allalarms:enable,disable,statusRequest,delete,add " . # CD 0015 alarm1 alarm2 entfernt
2016-10-01 16:46:46 +00:00
"alarmsSnooze:slider,0,1,30 alarmsTimeout:slider,0,5,90 alarmsDefaultVolume:slider,0,1,100 alarmsFadeIn:on,off alarmsEnabled:on,off " . # CD 0016, von MM <20> bernommen, Namen ge<67> ndert
2017-07-26 19:25:07 +00:00
"alarmsFadeSeconds " . # CD 0082 hinzugef<65> gt
2017-05-28 19:14:57 +00:00
"cliraw talk sayText " . # CD 0014 sayText hinzugef<65> gt
2015-03-19 20:37:01 +00:00
"unsync:noArg " .
2016-10-01 16:46:46 +00:00
"currentTrackPosition " . # CD 0047 hinzugef<65> gt
"snooze:noArg " . # CD 0052 hinzugef<65> gt
2017-05-28 19:14:57 +00:00
"resetTTS:noArg " . # CD 0028 hinzugef<65> gt
"updateFTUImedialist:noArg " . # CD 0065 hinzugef<65> gt
"clearFTUIcache:noArg " . # CD 0065 hinzugef<65> gt
"track " . # CD 0065 hinzugef<65> gt
"tracknumber " ; # CD 0072 hinzugef<65> gt
2015-03-19 20:37:01 +00:00
# add the favorites
2016-10-01 16:46:46 +00:00
$ res . = $ hash - > { FAVSET } . ":-," . $ hash - > { FAVSTR } . " " ; # CD 0014 '-' hinzugef<65> gt
2015-03-19 20:37:01 +00:00
# add the syncmasters
$ res . = "sync:" . $ hash - > { SYNCMASTERS } . " " ;
# add the playlists
2016-10-01 16:46:46 +00:00
$ res . = "playlists:-," . $ hash - > { SERVERPLAYLISTS } . " " ; # CD 0014 '-' hinzugef<65> gt
2015-06-18 20:23:54 +00:00
# add player saved lists # CD 0036
my $ out = "" ;
if ( defined ( $ hash - > { helper } { savedPlayerState } ) ) {
foreach my $ pl ( keys % { $ hash - > { helper } { savedPlayerState } } ) {
2017-05-28 19:14:57 +00:00
$ out . = $ pl . "," unless ( ( $ pl =~ /xxTTSxx/ ) || ( $ pl =~ /^xxx_sss_.*/ ) ) ; # CD 0061 xxx_sss_ hinzugef<65> gt
2015-06-18 20:23:54 +00:00
}
$ out =~ s/,$// ;
}
$ res . = "recall:$out " ;
2015-03-19 20:37:01 +00:00
# CD 0016 start {ALARMSCOUNT} verschieben nach reload
if ( defined ( $ hash - > { ALARMSCOUNT } ) ) {
$ hash - > { helper } { ALARMSCOUNT } = $ hash - > { ALARMSCOUNT } ;
delete ( $ hash - > { ALARMSCOUNT } ) ;
}
# CD 0016 end
# CD 0015 - add the alarms
if ( defined ( $ hash - > { helper } { ALARMSCOUNT } ) && ( $ hash - > { helper } { ALARMSCOUNT } > 0 ) ) { # CD 0016 ALARMSCOUNT nach {helper} verschoben
for ( my $ i = 1 ; $ i <=$hash-> { helper } { ALARMSCOUNT } ; $ i + + ) { # CD 0016 ALARMSCOUNT nach {helper} verschoben
$ res . = "alarm$i " ;
}
}
return ( $ res ) ;
}
2015-06-18 20:23:54 +00:00
# CD 0038 Befehle ignorieren wenn Player nicht vorhanden ist
# CD 0040 wieder deaktiviert
# if(ReadingsVal($name,"presence","x") ne "present") {
# return "$name: player is not available";
# }
# CD 0038 end
2017-05-28 19:14:57 +00:00
2015-03-19 20:37:01 +00:00
my $ updateReadingsOnSet = AttrVal ( $ name , "updateReadingsOnSet" , false ) ; # CD 0017
my $ donotnotify = AttrVal ( $ name , "donotnotify" , "true" ) ; # CD 0017 # CD 0028 added "
2017-05-28 19:14:57 +00:00
2014-02-20 23:34:51 +00:00
# as we have some other command, we need to turn on the server
#if( AttrVal( $name, "serverautoon", "true" ) eq "true" ) {
2015-03-19 20:37:01 +00:00
#SB_PLAYER_ServerTurnOn( $hash );
#}
2014-02-20 23:34:51 +00:00
if ( ( $ cmd eq "Stop" ) || ( $ cmd eq "STOP" ) || ( $ cmd eq "stop" ) ) {
2015-03-19 20:37:01 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} stop\n" ) ;
2014-02-20 23:34:51 +00:00
} elsif ( ( $ cmd eq "Play" ) || ( $ cmd eq "PLAY" ) || ( $ cmd eq "play" ) ) {
2016-10-01 16:46:46 +00:00
my @ secbuf = split ( ',' , AttrVal ( $ name , "fadeinsecs" , '10,10' ) ) ; # CD 0050 split hinzugef<65> gt
$ secbuf [ 1 ] = $ secbuf [ 0 ] if ( @ secbuf == 1 ) ; # CD 0051
2015-03-19 20:37:01 +00:00
# CD 0030 wait until power on
if ( ReadingsVal ( $ name , "power" , "x" ) eq "on" ) {
2016-10-01 16:46:46 +00:00
# CD 0051 2. Wert von fadeinsecs bei pause -> play verwenden
if ( ReadingsVal ( $ name , "playStatus" , "?" ) eq 'paused' ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} play " . $ secbuf [ 1 ] . "\n" ) ;
} else {
IOWrite ( $ hash , "$hash->{PLAYERMAC} play " . $ secbuf [ 0 ] . "\n" ) ;
}
2015-03-19 20:37:01 +00:00
} else {
2016-10-01 16:46:46 +00:00
$ hash - > { helper } { playAfterPowerOn } = $ secbuf [ 0 ] ;
2015-03-19 20:37:01 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} power 1\n" ) ;
}
# CD 0030 end
2014-02-20 23:34:51 +00:00
} elsif ( ( $ cmd eq "Pause" ) || ( $ cmd eq "PAUSE" ) || ( $ cmd eq "pause" ) ) {
2016-10-01 16:46:46 +00:00
my @ secbuf = split ( ',' , AttrVal ( $ name , "fadeinsecs" , '10,10' ) ) ; # CD 0050 split hinzugef<65> gt
$ secbuf [ 1 ] = $ secbuf [ 0 ] if ( @ secbuf == 1 ) ; # CD 0050
2015-03-19 20:37:01 +00:00
if ( @ arg == 1 ) {
if ( $ arg [ 0 ] eq "1" ) {
# pause the player
2016-10-01 16:46:46 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} pause 1\n" ) ;
2015-03-19 20:37:01 +00:00
} else {
# unpause the player
2016-10-01 16:46:46 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} pause 0 " . $ secbuf [ 1 ] . "\n" ) ;
2015-03-19 20:37:01 +00:00
}
} else {
2016-10-01 16:46:46 +00:00
# IOWrite( $hash, "$hash->{PLAYERMAC} pause $secbuf\n" ); # CD 0050 deaktiviert, funktioniert so nicht, wenn $secbuf verwendet wird muss 0 oder 1 davorstehen
# CD 0050 start
if ( ReadingsVal ( $ name , "playStatus" , "?" ) eq 'playing' ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} pause 1\n" ) ;
} else {
IOWrite ( $ hash , "$hash->{PLAYERMAC} pause 0 " . $ secbuf [ 1 ] . "\n" ) ;
}
# CD 0050 end
2015-03-19 20:37:01 +00:00
}
2014-02-20 23:34:51 +00:00
2017-05-28 19:14:57 +00:00
} elsif ( ( $ cmd eq "next" ) || ( $ cmd eq "NEXT" ) || ( $ cmd eq "Next" ) ||
2015-03-19 20:37:01 +00:00
( $ cmd eq "channelUp" ) || ( $ cmd eq "CHANNELUP" ) ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist jump %2B1\n" ) ;
2014-02-20 23:34:51 +00:00
2017-05-28 19:14:57 +00:00
} elsif ( ( $ cmd eq "prev" ) || ( $ cmd eq "PREV" ) || ( $ cmd eq "Prev" ) ||
2015-03-19 20:37:01 +00:00
( $ cmd eq "channelDown" ) || ( $ cmd eq "CHANNELDOWN" ) ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist jump %2D1\n" ) ;
2014-02-20 23:34:51 +00:00
2017-05-28 19:14:57 +00:00
} elsif ( ( $ cmd eq "volume" ) || ( $ cmd eq "VOLUME" ) ||
2015-03-19 20:37:01 +00:00
( $ cmd eq "Volume" ) || ( $ cmd eq "volumeStraight" ) ) {
if ( ( @ arg != 1 ) && ( @ arg != 2 ) ) {
my $ msg = "SB_PLAYER_Set: no arguments for Vol given." ;
Log3 ( $ hash , 3 , $ msg ) ;
return ( $ msg ) ;
}
# set the volume to the desired level. Needs to be 0..100
# no error checking here, as the server does this
if ( $ arg [ 0 ] <= AttrVal ( $ name , "volumeLimit" , 100 ) ) {
2017-05-28 19:14:57 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} mixer volume " . SB_PLAYER_FHEM2LMSVolume ( $ hash , $ arg [ 0 ] ) . "\n" ) ; # CD 0065 SB_PLAYER_FHEM2LMSVolume
2015-03-19 20:37:01 +00:00
# CD 0007
2017-05-28 19:14:57 +00:00
SB_PLAYER_SetSyncedVolume ( $ hash , $ arg [ 0 ] , 1 ) if ( ! defined ( $ arg [ 1 ] ) ) ;
2015-03-19 20:37:01 +00:00
} else {
2017-05-28 19:14:57 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} mixer volume " .
SB_PLAYER_FHEM2LMSVolume ( $ hash , AttrVal ( $ name , "volumeLimit" , 50 ) ) . "\n" ) ; # CD 0065 SB_PLAYER_FHEM2LMSVolume
2015-03-19 20:37:01 +00:00
# CD 0007
2017-05-28 19:14:57 +00:00
SB_PLAYER_SetSyncedVolume ( $ hash , AttrVal ( $ name , "volumeLimit" , 50 ) , 1 ) if ( ! defined ( $ arg [ 1 ] ) ) ;
2015-03-19 20:37:01 +00:00
}
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq $ hash - > { FAVSET } ) {
2015-03-19 20:37:01 +00:00
if ( $ arg [ 0 ] ne '-' ) { # CD 0014
if ( defined ( $ hash - > { helper } { SB_PLAYER_Favs } { $ arg [ 0 ] } { ID } ) ) {
my $ fid = $ hash - > { helper } { SB_PLAYER_Favs } { $ arg [ 0 ] } { ID } ;
2017-05-28 19:14:57 +00:00
if ( $ hash - > { helper } { SB_PLAYER_Favs } { $ arg [ 0 ] } { SOURCE } eq 'LMS' ) { # CD 0070
IOWrite ( $ hash , "$hash->{PLAYERMAC} favorites playlist " .
"play item_id:$fid\n" ) ;
} else {
IOWrite ( $ hash , "$hash->{PLAYERMAC} $hash->{helper}{SB_PLAYER_Favs}{$arg[0]}{SOURCE} playlist play " .
"item_id:$fid\n" ) ;
}
2015-03-19 20:37:01 +00:00
$ hash - > { FAVSELECT } = $ arg [ 0 ] ;
readingsSingleUpdate ( $ hash , "$hash->{FAVSET}" , "$arg[ 0 ]" , 1 ) ;
2016-10-01 16:46:46 +00:00
# SB_PLAYER_GetStatus( $hash ); # CD 0021 deaktiviert, zu fr<66> h
2015-03-19 20:37:01 +00:00
}
} # CD 0014
2014-02-20 23:34:51 +00:00
2017-05-28 19:14:57 +00:00
} elsif ( ( $ cmd eq "volumeUp" ) || ( $ cmd eq "VOLUMEUP" ) ||
2015-03-19 20:37:01 +00:00
( $ cmd eq "VolumeUp" ) ) {
# increase volume
2017-05-28 19:14:57 +00:00
if ( ( ReadingsVal ( $ name , "volumeStraight" , 50 ) +
AttrVal ( $ name , "volumeStep" , 10 ) ) <=
2015-03-19 20:37:01 +00:00
AttrVal ( $ name , "volumeLimit" , 100 ) ) {
my $ volstr = sprintf ( "+%02d" , AttrVal ( $ name , "volumeStep" , 10 ) ) ;
IOWrite ( $ hash , "$hash->{PLAYERMAC} mixer volume $volstr\n" ) ;
# CD 0007
2017-05-28 19:14:57 +00:00
#SB_PLAYER_SetSyncedVolume($hash,$volstr); # CD 0065 deaktiviert, auf R<> ckmeldung warten
2015-03-19 20:37:01 +00:00
} else {
2017-05-28 19:14:57 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} mixer volume " .
SB_PLAYER_FHEM2LMSVolume ( $ hash , AttrVal ( $ name , "volumeLimit" , 50 ) ) . "\n" ) ; # CD 0065 SB_PLAYER_FHEM2LMSVolume
2015-03-19 20:37:01 +00:00
# CD 0007
2017-05-28 19:14:57 +00:00
SB_PLAYER_SetSyncedVolume ( $ hash , AttrVal ( $ name , "volumeLimit" , 50 ) , 1 ) ;
2015-03-19 20:37:01 +00:00
}
2014-02-20 23:34:51 +00:00
2017-05-28 19:14:57 +00:00
} elsif ( ( $ cmd eq "volumeDown" ) || ( $ cmd eq "VOLUMEDOWN" ) ||
2015-03-19 20:37:01 +00:00
( $ cmd eq "VolumeDown" ) ) {
my $ volstr = sprintf ( "-%02d" , AttrVal ( $ name , "volumeStep" , 10 ) ) ;
IOWrite ( $ hash , "$hash->{PLAYERMAC} mixer volume $volstr\n" ) ;
# CD 0007
2017-05-28 19:14:57 +00:00
#SB_PLAYER_SetSyncedVolume($hash,$volstr); # CD 0065 deaktiviert, auf R<> ckmeldung warten
2014-02-20 23:34:51 +00:00
} elsif ( ( $ cmd eq "mute" ) || ( $ cmd eq "MUTE" ) || ( $ cmd eq "Mute" ) ) {
2015-03-19 20:37:01 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} mixer muting toggle\n" ) ;
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "on" ) {
2015-03-19 20:37:01 +00:00
if ( $ hash - > { CANPOWEROFF } eq "0" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} play\n" ) ;
} else {
IOWrite ( $ hash , "$hash->{PLAYERMAC} power 1\n" ) ;
}
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "off" ) {
2015-03-19 20:37:01 +00:00
# off command to go here
if ( $ hash - > { CANPOWEROFF } eq "0" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} stop\n" ) ;
} else {
IOWrite ( $ hash , "$hash->{PLAYERMAC} power 0\n" ) ;
}
2014-02-20 23:34:51 +00:00
2017-05-28 19:14:57 +00:00
} elsif ( ( $ cmd eq "repeat" ) || ( $ cmd eq "REPEAT" ) ||
2015-03-19 20:37:01 +00:00
( $ cmd eq "Repeat" ) ) {
if ( @ arg != 1 ) {
my $ msg = "SB_PLAYER_Set: no arguments for repeat given." ;
Log3 ( $ hash , 3 , $ msg ) ;
return ( $ msg ) ;
}
if ( $ arg [ 0 ] eq "off" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist repeat 0\n" ) ;
readingsSingleUpdate ( $ hash , "repeat" , "off" , $ donotnotify ) if ( $ updateReadingsOnSet ) ; # CD 0017
} elsif ( $ arg [ 0 ] eq "one" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist repeat 1\n" ) ;
readingsSingleUpdate ( $ hash , "repeat" , "one" , $ donotnotify ) if ( $ updateReadingsOnSet ) ; # CD 0017
} elsif ( $ arg [ 0 ] eq "all" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist repeat 2\n" ) ;
readingsSingleUpdate ( $ hash , "repeat" , "all" , $ donotnotify ) if ( $ updateReadingsOnSet ) ; # CD 0017
} else {
my $ msg = "SB_PLAYER_Set: unknown argument for repeat given." ;
Log3 ( $ hash , 3 , $ msg ) ;
return ( $ msg ) ;
2017-05-28 19:14:57 +00:00
}
} elsif ( ( $ cmd eq "shuffle" ) || ( $ cmd eq "SHUFFLE" ) ||
2015-03-19 20:37:01 +00:00
( $ cmd eq "Shuffle" ) ) {
if ( @ arg != 1 ) {
my $ msg = "SB_PLAYER_Set: no arguments for shuffle given." ;
Log3 ( $ hash , 3 , $ msg ) ;
return ( $ msg ) ;
}
if ( $ arg [ 0 ] eq "off" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist shuffle 0\n" ) ;
readingsSingleUpdate ( $ hash , "shuffle" , "off" , $ donotnotify ) if ( $ updateReadingsOnSet ) ; # CD 0017
2016-10-01 16:46:46 +00:00
} elsif ( ( $ arg [ 0 ] eq "on" ) || ( $ arg [ 0 ] eq "song" ) ) { # CD 0017 'song' hinzugef<65> gt
2015-03-19 20:37:01 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist shuffle 1\n" ) ;
readingsSingleUpdate ( $ hash , "shuffle" , "song" , $ donotnotify ) if ( $ updateReadingsOnSet ) ; # CD 0017
# CD 0017 start
} elsif ( $ arg [ 0 ] eq "album" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist shuffle 2\n" ) ;
readingsSingleUpdate ( $ hash , "shuffle" , "album" , $ donotnotify ) if ( $ updateReadingsOnSet ) ;
# CD 0017 end
} else {
my $ msg = "SB_PLAYER_Set: unknown argument for shuffle given." ;
Log3 ( $ hash , 3 , $ msg ) ;
return ( $ msg ) ;
2017-05-28 19:14:57 +00:00
}
2014-02-20 23:34:51 +00:00
2017-05-28 19:14:57 +00:00
} elsif ( ( $ cmd eq "show" ) ||
( $ cmd eq "SHOW" ) ||
2015-03-19 20:37:01 +00:00
( $ cmd eq "Show" ) ) {
# set <name> show line1:text line2:text duration:ss
my $ v = join ( " " , @ arg ) ;
my @ buf = split ( "line1:" , $ v ) ;
@ buf = split ( "line2:" , $ buf [ 1 ] ) ;
my $ line1 = uri_escape ( $ buf [ 0 ] ) ;
@ buf = split ( "duration:" , $ buf [ 1 ] ) ;
my $ line2 = uri_escape ( $ buf [ 0 ] ) ;
my $ duration = $ buf [ 1 ] ;
my $ cmdstr = "$hash->{PLAYERMAC} display $line1 $line2 $duration\n" ;
IOWrite ( $ hash , $ cmdstr ) ;
2014-02-20 23:34:51 +00:00
2017-05-28 19:14:57 +00:00
} elsif ( ( $ cmd eq "talk" ) ||
( $ cmd eq "TALK" ) ||
2015-03-19 20:37:01 +00:00
( $ cmd eq "talk" ) ||
2016-10-01 16:46:46 +00:00
( lc ( $ cmd ) eq "saytext" ) ) { # CD 0014 hinzugef<65> gt
2015-04-07 19:48:18 +00:00
$ hash - > { helper } { ttsstate } = TTS_IDLE if ( ! defined ( $ hash - > { helper } { ttsstate } ) ) ;
$ hash - > { helper } { ttsExtstate } = TTS_IDLE if ( ! defined ( $ hash - > { helper } { ttsExtstate } ) ) ;
# CD 0032 - Text2Speech verwenden ?
2016-10-01 16:46:46 +00:00
# CD 0033 - <20> berarbeitet
2015-04-07 19:48:18 +00:00
my $ useText2Speech = 0 ;
my $ errMsg ;
if ( AttrVal ( $ name , "ttslink" , "none" ) =~ m/^Text2Speech/ ) {
my @ extTTS = split ( ":" , AttrVal ( $ name , "ttslink" , "none" ) ) ;
2016-10-01 16:46:46 +00:00
# Device <20> berhaupt verwendbar ?
2015-04-07 19:48:18 +00:00
if ( defined ( $ extTTS [ 1 ] ) && defined ( $ defs { $ extTTS [ 1 ] } ) ) {
my $ ttshash = $ defs { $ extTTS [ 1 ] } ;
2016-10-01 16:46:46 +00:00
if ( defined ( $ ttshash - > { TYPE } ) && ( ( $ ttshash - > { TYPE } eq 'Text2SpeechSB' ) || ( ( $ ttshash - > { TYPE } eq 'Text2Speech' ) && defined ( $ ttshash - > { helper } { supportsSBPlayer } ) ) ) ) { # CD 0048 Text2Speech (ohne SB) unterst<73> tzen
2015-04-07 19:48:18 +00:00
if ( defined ( $ ttshash - > { ALSADEVICE } ) && ( $ ttshash - > { ALSADEVICE } eq 'SB_PLAYER' ) ) {
2016-10-01 16:46:46 +00:00
if ( ( AttrVal ( $ ttshash - > { NAME } , "TTS_Ressource" , "x" ) =~ m/^(Google|VoiceRSS|SVOX-pico)$/ ) ) { # CD 0049 $ttshash korrigiert
2015-04-07 19:48:18 +00:00
$ 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 {
2016-10-01 16:46:46 +00:00
$ errMsg = "SB_PLAYER_Set: " . $ extTTS [ 1 ] . ": Text2Speech uses unsupported TTS_Ressource " . AttrVal ( $ ttshash - > { NAME } , "TTS_Ressource" , "x" ) ; # CD 0049 $ttshash korrigiert
2015-04-07 19:48:18 +00:00
}
} 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 ) ;
}
2016-10-01 16:46:46 +00:00
# CD 0028 start - komplett <20> berarbeitet
2015-03-19 20:37:01 +00:00
# prepare text
my $ ttstext = join ( " " , @ arg ) ;
2015-04-07 19:48:18 +00:00
$ ttstext = AttrVal ( $ name , "ttsPrefix" , "" ) . " " . $ ttstext ; # CD 0032
2015-03-19 20:37:01 +00:00
2016-10-01 16:46:46 +00:00
my % Sonderzeichen = ( "<22> " = > "ae" , "<22> " = > "Ae" , "<22> " = > "ue" , "<22> " = > "Ue" , "<22> " = > "oe" , "<22> " = > "Oe" , "<22> " = > "ss" ,
"<22> " = > "e" , "<22> " = > "e" , "<22> " = > "e" , "<22> " = > "a" , "<22> " = > "c" ) ;
2015-03-19 20:37:01 +00:00
my $ Sonderzeichenkeys = join ( "|" , keys ( % Sonderzeichen ) ) ;
2015-04-07 19:48:18 +00:00
if ( length ( $ ttstext ) == 0 ) {
2015-03-19 20:37:01 +00:00
my $ msg = "SB_PLAYER_Set: no text passed for synthesis." ;
Log3 ( $ hash , 3 , $ msg ) ;
return ( $ msg ) ;
2015-04-07 19:48:18 +00:00
}
$ ttstext . = "." unless ( $ ttstext =~ m/^.+[.,?!:;]$/ ) ;
2015-03-19 20:37:01 +00:00
my @ textlines ;
my $ tl = '' ;
2016-10-01 16:46:46 +00:00
# CD 0033 Unterst<73> tzung f<> r Dateien und URLs hinzugef<65> gt, teilweise aus 00_SONOS <20> bernommen
2015-04-07 19:48:18 +00:00
my $ targetSpeakMP3FileDir = AttrVal ( $ name , "ttsMP3FileDir" , "" ) ; # CD 0033
2015-06-18 20:23:54 +00:00
my $ filename ; # CD 0038
2017-05-28 19:14:57 +00:00
2015-03-19 20:37:01 +00:00
if ( length ( $ ttstext ) > 0 ) {
my @ words = split ( ' ' , $ ttstext ) ;
for my $ w ( @ words ) {
2016-10-01 16:46:46 +00:00
# CD 0033 Datei ?, teilweise aus 00_SONOS <20> bernommen
2015-04-07 19:48:18 +00:00
if ( $ w =~ m/\|(.*)\|/ ) {
push ( @ textlines , $ tl ) if ( $ tl ne '' ) ;
$ tl = '' ;
2017-05-28 19:14:57 +00:00
2015-06-18 20:23:54 +00:00
$ filename = $ 1 ;
2015-04-07 19:48:18 +00:00
$ filename = $ targetSpeakMP3FileDir . '/' . $ filename if ( $ filename !~ m/^(\/|[a-z]:)/i ) ;
$ filename = $ filename . '.mp3' if ( $ filename !~ m/\.mp3$/i ) ;
2015-06-18 20:23:54 +00:00
push ( @ textlines , '|' . $ filename . '|' ) ;
$ filename = undef ;
# CD 0038 Leerzeichen in Dateinamen zulassen
} elsif ( $ w =~ m/^\|(.*)/ ) {
$ filename = $ 1 ;
} elsif ( ( $ w =~ m/(.*)\|/ ) && defined ( $ filename ) ) {
$ filename . = " " . $ 1 ;
push ( @ textlines , $ tl ) if ( $ tl ne '' ) ;
$ tl = '' ;
2017-05-28 19:14:57 +00:00
2015-06-18 20:23:54 +00:00
$ filename = $ targetSpeakMP3FileDir . '/' . $ filename if ( $ filename !~ m/^(\/|[a-z]:)/i ) ;
$ filename = $ filename . '.mp3' if ( $ filename !~ m/\.mp3$/i ) ;
push ( @ textlines , '|' . $ filename . '|' ) ;
$ filename = undef ;
# CD 0038
2015-03-19 20:37:01 +00:00
} else {
2015-04-07 19:48:18 +00:00
$ w =~ s/[\\|*~<>^\n\(\)\[\]\{\}[:cntrl:]]/ /g ;
$ w =~ s/\s+/ /g ;
$ w =~ s/^\s|\s$//g ;
2016-10-01 16:46:46 +00:00
$ w =~ s/($Sonderzeichenkeys)/$Sonderzeichen{$1}/g if ( AttrVal ( $ name , "ttslink" , "x" ) !~ m/voicerss/i ) ; # CD 0045 Sonderzeichen f<> r VoiceRSS nicht ersetzen
$ w = uri_escape ( $ w ) if defined ( $ hash - > { helper } { ttsOptions } { doubleescape } ) ; # CD 0060
2015-04-07 19:48:18 +00:00
# CD 0032 end
if ( ( length ( $ tl ) + length ( $ w ) + 1 ) < 100 ) {
$ tl . = ' ' if ( length ( $ tl ) > 0 ) ;
$ tl . = $ w ;
} else {
push ( @ textlines , $ tl ) ;
$ tl = $ w ;
}
2015-03-19 20:37:01 +00:00
}
}
}
push ( @ textlines , $ tl ) if ( $ tl ne '' ) ;
if ( $ hash - > { helper } { ttsstate } == TTS_IDLE ) {
# talk ist nicht aktiv
2015-06-18 20:23:54 +00:00
# CD 0038 Player zuerst einschalten
if ( ReadingsVal ( $ name , "power" , "x" ) ne "on" ) {
SB_PLAYER_SetTTSState ( $ hash , TTS_WAITFORPOWERON , 0 , 0 ) ;
RemoveInternalTimer ( "TimeoutTTSWaitForPowerOn:$name" ) ;
if ( $ hash - > { helper } { playerStatusOK } == 1 ) { # CD 0042
IOWrite ( $ hash , "$hash->{PLAYERMAC} power 1\n" ) ;
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + 5.00 ,
2015-06-18 20:23:54 +00:00
"SB_PLAYER_tcb_TimeoutTTSWaitForPowerOn" ,
2017-05-28 19:14:57 +00:00
"TimeoutTTSWaitForPowerOn:$name" ,
2015-06-18 20:23:54 +00:00
0 ) ;
$ hash - > { helper } { ttsPowerWasOff } = 1 ;
# CD 0042 start
} else {
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + 10.00 ,
2015-06-18 20:23:54 +00:00
"SB_PLAYER_tcb_TimeoutTTSWaitForPowerOn" ,
2017-05-28 19:14:57 +00:00
"TimeoutTTSWaitForPowerOn:$name" ,
2015-06-18 20:23:54 +00:00
0 ) ;
}
# CD 0042 end
} else {
# CD 0038 end
SB_PLAYER_PrepareTalk ( $ hash ) ;
}
2015-03-19 20:37:01 +00:00
} else {
2017-05-28 19:14:57 +00:00
2015-03-19 20:37:01 +00:00
}
2015-04-07 19:48:18 +00:00
for my $ outstr ( @ textlines ) {
if ( $ outstr =~ m/\|(.*)\|/ ) { # CD 0033
2015-06-18 20:23:54 +00:00
Log3 ( $ hash , defined ( $ hash - > { helper } { ttsOptions } { debug } ) ? 0 : 6 , "SB_PLAYER_Set: $name: add to ttsqueue: $1" ) ; # CD 0036
2016-10-01 16:46:46 +00:00
push ( @ { $ hash - > { helper } { ttsqueue } } , uri_escape ( decode ( 'utf-8' , $ 1 ) ) ) ; # CD 0033 # CD 0038 uri_escape(decode... hinzugef<65> gt
2015-03-19 20:37:01 +00:00
} else {
2015-04-07 19:48:18 +00:00
$ outstr =~ s/\s/+/g ;
2016-10-01 16:46:46 +00:00
# CD 0054 versuchen Format zu erraten, funktioniert nicht f<> r telnet
if ( decode ( "utf8" , $ outstr ) =~ m/\x{fffd}/ ) {
Log3 ( $ hash , defined ( $ hash - > { helper } { ttsOptions } { debug } ) ? 0 : 6 , "SB_PLAYER_Set: $name: string is not utf-8, using iso-8859-1" ) ;
$ outstr = encode ( 'utf-8' , decode ( "iso-8859-1" , $ outstr ) ) ;
}
2017-05-28 19:14:57 +00:00
2015-04-07 19:48:18 +00:00
$ outstr = uri_escape ( $ outstr ) ;
2016-10-01 16:46:46 +00:00
#$outstr = uri_escape( $outstr ) if defined($hash->{helper}{ttsOptions}{doubleescape}); # CD 0059 # CD 0060 zu sp<73> t nach oben verschoben
2017-05-28 19:14:57 +00:00
2015-11-02 08:26:30 +00:00
# CD 0045
my $ ttslink = AttrVal ( $ name , "ttslink" , "" ) ;
if ( defined ( $ ttslink ) ) {
# Profile
my $ lang = AttrVal ( $ name , "ttslanguage" , "de" ) ;
if ( $ ttslink =~ m/voicerss/i ) { # CD 0047 Sprache auch bei voicerss innerhalb der URL anpassen
$ lang = "de-de" if ( $ lang eq "de" ) ;
$ lang = "en-us" if ( $ lang eq "en" ) ;
$ lang = "fr-fr" if ( $ lang eq "fr" ) ;
}
$ ttslink = "http://translate.google.com/translate_tts?ie=UTF-8&tl=<LANG>&q=<TEXT>&client=tw-ob" if ( $ ttslink eq 'http://translate.google.com/translate_tts?ie=UTF-8' ) ; # CD 0047, CD 0048 client=tw-ob verwenden
$ ttslink = "http://translate.google.com/translate_tts?ie=UTF-8&tl=<LANG>&q=<TEXT>&client=tw-ob" if ( $ ttslink eq "Google" ) ; # CD 0048 client=tw-ob verwenden
$ ttslink = "http://api.voicerss.org/?key=<APIKEY>&src=<TEXT>&hl=<LANG>" if ( $ ttslink eq "VoiceRSS" ) ;
# alte Links anpassen
if ( $ ttslink !~ m/<TEXT>/ ) {
$ ttslink . = "&tl=<LANG>" if ( $ ttslink !~ m/<LANG>/ ) ;
$ ttslink . = "&q=<TEXT>" ;
}
2017-05-28 19:14:57 +00:00
2015-11-02 08:26:30 +00:00
$ ttslink =~ s/<LANG>/$lang/ ;
$ ttslink =~ s/<TEXT>/$outstr/ ;
my $ apikey = AttrVal ( $ name , "ttsAPIKey" , undef ) ;
if ( ( $ ttslink =~ m/<APIKEY>/ ) && ! defined ( $ apikey ) ) {
Log3 ( $ hash , 2 , "SB_PLAYER_Set: $name: talk - missing API key" ) ;
SB_PLAYER_SetTTSState ( $ hash , TTS_IDLE , 0 , 0 ) ;
} else {
$ ttslink =~ s/<APIKEY>/$apikey/ ;
2017-05-28 19:14:57 +00:00
2015-11-02 08:26:30 +00:00
Log3 ( $ hash , defined ( $ hash - > { helper } { ttsOptions } { debug } ) ? 0 : 6 , "SB_PLAYER_Set: $name: add to ttsqueue: $ttslink" ) ; # CD 0036
push ( @ { $ hash - > { helper } { ttsqueue } } , $ ttslink ) ;
}
}
2015-03-19 20:37:01 +00:00
}
}
2017-05-28 19:14:57 +00:00
2016-10-01 16:46:46 +00:00
SB_PLAYER_LoadTalk ( $ hash ) if ( $ hash - > { helper } { ttsstate } == TTS_LOADPLAYLIST ) ; # CD 0033 # CD 0038 auf TTS_LOADPLAYLIST pr<70> fen
2015-04-07 19:48:18 +00:00
2015-03-19 20:37:01 +00:00
# CD 0028 end
2017-05-28 19:14:57 +00:00
} elsif ( ( $ cmd eq "playlist" ) ||
( $ cmd eq "PLAYLIST" ) ||
2015-03-19 20:37:01 +00:00
( $ cmd eq "Playlist" ) ) {
#if( ( @arg != 2 ) && ( @arg != 3 ) ) { # CD 0014 deaktiviert
if ( @ arg < 2 ) { # CD 0014
my $ msg = "SB_PLAYER_Set: no arguments for Playlist given." ;
Log3 ( $ hash , 3 , $ msg ) ;
return ( $ msg ) ;
}
# CD 0014 start
if ( @ arg > 1 ) {
my $ outstr = uri_escape ( decode ( 'utf-8' , join ( " " , @ arg [ 1 .. $# arg ] ) ) ) ; # CD 0017
Log3 ( $ hash , 5 , "SB_PLAYER_Set($name): playlists command = $arg[ 0 ] param = $outstr" ) ;
if ( $ arg [ 0 ] eq "track" ) {
2017-05-28 19:14:57 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist loadtracks " .
2015-03-19 20:37:01 +00:00
"track.titlesearch:$outstr\n" ) ;
} elsif ( $ arg [ 0 ] eq "album" ) {
2017-05-28 19:14:57 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist loadtracks " .
2015-03-19 20:37:01 +00:00
"album.titlesearch:$outstr\n" ) ;
} elsif ( $ arg [ 0 ] eq "artist" ) {
2017-05-28 19:14:57 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist loadtracks " .
2015-03-19 20:37:01 +00:00
"contributor.namesearch:$outstr\n" ) ; # CD 0014 'titlesearch' durch 'namesearch' ersetzt
} elsif ( $ arg [ 0 ] eq "play" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist play $outstr\n" ) ;
2015-06-18 20:23:54 +00:00
# CD 0038 start
} elsif ( $ arg [ 0 ] eq "add" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist add $outstr\n" ) ;
} elsif ( $ arg [ 0 ] eq "insert" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist insert $outstr\n" ) ;
# CD 0038 end
2015-03-19 20:37:01 +00:00
} elsif ( $ arg [ 0 ] eq "year" ) {
2017-05-28 19:14:57 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist loadtracks " .
2015-03-19 20:37:01 +00:00
"track.year:$outstr\n" ) ;
} elsif ( $ arg [ 0 ] eq "genre" ) {
2017-05-28 19:14:57 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist loadtracks " .
2015-03-19 20:37:01 +00:00
"genre.namesearch:$outstr\n" ) ;
#} elsif( $arg[ 0 ] eq "comment" ) { # CD 0014 funktioniert nicht
2017-05-28 19:14:57 +00:00
# IOWrite( $hash, "$hash->{PLAYERMAC} playlist loadtracks " .
2015-03-19 20:37:01 +00:00
# "comments.value:$outstr\n" );
2016-10-01 16:46:46 +00:00
# CD 0038 loadalbum wieder hergestellt und <20> berarbeitet
2015-03-19 20:37:01 +00:00
} else {
2015-06-18 20:23:54 +00:00
my $ genre = '*' ;
my $ album = '*' ;
my $ artist = '*' ;
my $ t = 0 ;
foreach ( @ arg ) {
if ( $ _ =~ /^(genre:)(.*)/ ) {
$ genre = $ 2 ;
$ t = 1 ;
} elsif ( $ _ =~ /^(album:)(.*)/ ) {
$ album = $ 2 ;
$ t = 2 ;
} elsif ( $ _ =~ /^(artist:)(.*)/ ) {
$ artist = $ 2 ;
$ t = 3 ;
} else {
$ genre . = " " . $ _ if ( $ t == 1 ) ;
$ album . = " " . $ _ if ( $ t == 2 ) ;
$ artist . = " " . $ _ if ( $ t == 3 ) ;
}
}
if ( $ t > 0 ) {
$ genre = uri_escape ( decode ( 'utf-8' , $ genre ) ) if ( $ genre ne '*' ) ;
$ album = uri_escape ( decode ( 'utf-8' , $ album ) ) if ( $ album ne '*' ) ;
$ artist = uri_escape ( decode ( 'utf-8' , $ artist ) ) if ( $ artist ne '*' ) ;
2017-05-28 19:14:57 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist loadalbum " .
2015-06-18 20:23:54 +00:00
"$genre $artist $album\n" ) ;
}
# CD 0038 end
2015-03-19 20:37:01 +00:00
}
# CD 0014 end
} else {
# what the f... we checked beforehand
}
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "allalarms" ) {
2015-03-19 20:37:01 +00:00
if ( $ arg [ 0 ] eq "enable" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playerpref alarmsEnabled 1\n" ) ; # MM 0016
readingsSingleUpdate ( $ hash , "alarmsEnabled" , "on" , $ donotnotify ) if ( $ updateReadingsOnSet ) ; # CD 0017
} elsif ( $ arg [ 0 ] eq "disable" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playerpref alarmsEnabled 0\n" ) ; # MM 0016
readingsSingleUpdate ( $ hash , "alarmsEnabled" , "off" , $ donotnotify ) if ( $ updateReadingsOnSet ) ; # CD 0017
} elsif ( $ arg [ 0 ] eq "statusRequest" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} alarms 0 200 tags:all filter:all\n" ) ; # CD 0015 filter added
# CD 0016 start
IOWrite ( $ hash , "$hash->{PLAYERMAC} playerpref alarmsEnabled ?\n" ) ;
IOWrite ( $ hash , "$hash->{PLAYERMAC} playerpref alarmDefaultVolume ?\n" ) ;
IOWrite ( $ hash , "$hash->{PLAYERMAC} playerpref alarmTimeoutSeconds ?\n" ) ;
IOWrite ( $ hash , "$hash->{PLAYERMAC} playerpref alarmSnoozeSeconds ?\n" ) ;
2017-07-26 19:25:07 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} playerpref alarmfadeseconds ?\n" ) ; # CD 0082
2015-03-19 20:37:01 +00:00
# CD 0016 end
# CD 0015 start
} elsif ( $ arg [ 0 ] eq "delete" ) {
$ hash - > { helper } { deleteAllAlarms } = 1 ;
for ( my $ i = 1 ; $ i <=$hash-> { helper } { ALARMSCOUNT } ; $ i + + ) { # CD 0016 ALARMSCOUNT nach {helper} verschoben
IOWrite ( $ hash , "$hash->{PLAYERMAC} alarm delete id:" . ReadingsVal ( $ name , "alarm" . $ i . "_id" , "0" ) . "\n" ) ;
}
IOWrite ( $ hash , "$hash->{PLAYERMAC} alarms 0 200 tags:all filter:all\n" ) ; # CD 0015 filter added
} elsif ( $ arg [ 0 ] eq "add" ) {
$ arg [ 0 ] = "set" ;
SB_PLAYER_Alarm ( $ hash , 0 , @ arg ) ;
# CD 0015 end
} else {
}
2016-10-01 16:46:46 +00:00
# CD 0016 start, von MM <20> bernommen, Namen ge<67> ndert
2015-03-19 20:37:01 +00:00
} elsif ( index ( $ cmd , "alarms" ) != - 1 ) {
if ( $ cmd eq "alarmsSnooze" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playerpref alarmSnoozeSeconds " . $ arg [ 0 ] * 60 . "\n" ) ;
readingsSingleUpdate ( $ hash , "alarmsSnooze" , $ arg [ 0 ] , $ donotnotify ) if ( $ updateReadingsOnSet ) ; # CD 0017
} elsif ( $ cmd eq "alarmsTimeout" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playerpref alarmTimeoutSeconds " . $ arg [ 0 ] * 60 . "\n" ) ;
readingsSingleUpdate ( $ hash , "alarmsTimeout" , $ arg [ 0 ] , $ donotnotify ) if ( $ updateReadingsOnSet ) ; # CD 0017
} elsif ( $ cmd eq "alarmsDefaultVolume" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playerpref alarmDefaultVolume " . $ arg [ 0 ] . "\n" ) ;
readingsSingleUpdate ( $ hash , "alarmsDefaultVolume" , $ arg [ 0 ] , $ donotnotify ) if ( $ updateReadingsOnSet ) ; # CD 0017
} elsif ( $ cmd eq "alarmsFadeIn" ) {
if ( $ arg [ 0 ] eq 'on' ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playerpref alarmfadeseconds 1\n" ) ;
readingsSingleUpdate ( $ hash , "alarmsFadeIn" , "on" , $ donotnotify ) if ( $ updateReadingsOnSet ) ; # CD 0017
} else {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playerpref alarmfadeseconds 0\n" ) ;
readingsSingleUpdate ( $ hash , "alarmsFadeIn" , "off" , $ donotnotify ) if ( $ updateReadingsOnSet ) ; # CD 0017
}
} elsif ( $ cmd eq "alarmsEnabled" ) {
if ( $ arg [ 0 ] eq "on" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playerpref alarmsEnabled 1\n" ) ;
readingsSingleUpdate ( $ hash , "alarmsEnabled" , "on" , $ donotnotify ) if ( $ updateReadingsOnSet ) ; # CD 0017
} else {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playerpref alarmsEnabled 0\n" ) ;
readingsSingleUpdate ( $ hash , "alarmsEnabled" , "off" , $ donotnotify ) if ( $ updateReadingsOnSet ) ; # CD 0017
}
2017-07-26 19:25:07 +00:00
# CD 0082 start
} elsif ( $ cmd eq "alarmsFadeSeconds" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playerpref alarmfadeseconds " . $ arg [ 0 ] . "\n" ) ;
readingsSingleUpdate ( $ hash , "alarmsFadeSeconds" , $ arg [ 0 ] , $ donotnotify ) if ( $ updateReadingsOnSet ) ;
2015-03-19 20:37:01 +00:00
}
2017-07-26 19:25:07 +00:00
# CD 0082 end
2015-03-19 20:37:01 +00:00
# CD 0016
2014-02-20 23:34:51 +00:00
} elsif ( index ( $ cmd , "alarm" ) != - 1 ) {
2015-03-19 20:37:01 +00:00
my $ alarmno = int ( substr ( $ cmd , 5 ) ) + 0 ;
Log3 ( $ hash , 5 , "SB_PLAYER_Set: $name: alarmid:$alarmno" ) ;
return ( SB_PLAYER_Alarm ( $ hash , $ alarmno , @ arg ) ) ;
2014-02-20 23:34:51 +00:00
} elsif ( ( $ cmd eq "sleep" ) || ( $ cmd eq "SLEEP" ) ||
2015-03-19 20:37:01 +00:00
( $ cmd eq "Sleep" ) ) {
# split the time string up
my @ buf = split ( ":" , $ arg [ 0 ] ) ;
if ( scalar ( @ buf ) != 3 ) {
my $ msg = "SB_PLAYER_Set: please use hh:mm:ss for sleep time." ;
Log3 ( $ hash , 3 , $ msg ) ;
return ( $ msg ) ;
2017-05-28 19:14:57 +00:00
}
2015-03-19 20:37:01 +00:00
my $ secs = ( $ buf [ 0 ] * 3600 ) + ( $ buf [ 1 ] * 60 ) + $ buf [ 2 ] ;
IOWrite ( $ hash , "$hash->{PLAYERMAC} sleep $secs\n" ) ;
return ( undef ) ;
2014-02-20 23:34:51 +00:00
} elsif ( ( $ cmd eq "cliraw" ) || ( $ cmd eq "CLIRAW" ) ||
2015-03-19 20:37:01 +00:00
( $ cmd eq "Cliraw" ) ) {
# write raw messages to the CLI interface per player
my $ v = join ( " " , @ arg ) ;
2014-02-20 23:34:51 +00:00
2017-05-28 19:14:57 +00:00
Log3 ( $ hash , 5 , "SB_PLAYER_Set: cliraw: $v " ) ;
2015-03-19 20:37:01 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} $v\n" ) ;
return ( undef ) ;
2014-02-20 23:34:51 +00:00
2015-03-19 20:37:01 +00:00
# CD 0014 start
2014-03-22 23:32:21 +00:00
} elsif ( ( $ cmd eq "save" ) || ( $ cmd eq "SAVE" ) ) {
2015-06-18 20:23:54 +00:00
if ( defined ( $ arg [ 0 ] ) ) {
SB_PLAYER_Save ( $ hash , $ arg [ 0 ] ) ;
} else {
SB_PLAYER_Save ( $ hash , "" ) ;
}
2014-03-22 23:32:21 +00:00
} elsif ( ( $ cmd eq "recall" ) || ( $ cmd eq "RECALL" ) ) {
2015-06-18 20:23:54 +00:00
if ( defined ( $ arg [ 0 ] ) ) {
SB_PLAYER_Recall ( $ hash , join ( " " , @ arg ) ) ;
} else {
SB_PLAYER_Recall ( $ hash , "" ) ;
}
2015-03-19 20:37:01 +00:00
# CD 0014 end
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "statusRequest" ) {
2015-03-19 20:37:01 +00:00
RemoveInternalTimer ( $ hash ) ;
2017-06-22 20:47:42 +00:00
delete ( $ hash - > { helper } { disableGetStatus } ) if defined ( $ hash - > { helper } { disableGetStatus } ) ; # CD 0079
2015-03-19 20:37:01 +00:00
SB_PLAYER_GetStatus ( $ hash ) ;
2014-07-06 22:14:26 +00:00
} elsif ( $ cmd eq "sync" ) {
2015-03-19 20:37:01 +00:00
# CD 0018 wenn der Player bereits in einer Gruppe ist und 'new' ist vorhanden, wird der Player zuerst aus der Gruppe entfernt
if ( ( @ arg == 2 ) && ( $ arg [ 1 ] eq "new" ) && ( $ hash - > { SYNCED } eq 'yes' ) ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} sync -\n" ) ;
# CD 0028 start
if ( $ hash - > { helper } { ttsstate } == TTS_SYNCGROUPACTIVE ) {
2017-05-28 19:14:57 +00:00
SB_PLAYER_SetTTSState ( $ hash , TTS_IDLE , 0 , 0 ) ; # CD 0066 single statt bulk update
2015-03-19 20:37:01 +00:00
}
# CD 0028 end
}
# CD 0018 end
2017-05-28 19:14:57 +00:00
# CD 0018 Synchronisation mehrerer Player
2015-03-19 20:37:01 +00:00
if ( ( @ arg == 1 ) || ( @ arg == 2 ) ) {
my $ msg ;
my $ dev ;
my @ dvs = ( ) ;
my $ doGetStatus = 0 ;
@ dvs = split ( "," , $ arg [ 0 ] ) ;
foreach ( @ dvs ) {
my $ dev = $ _ ;
2015-06-18 20:23:54 +00:00
my $ mac ;
2015-03-19 20:37:01 +00:00
# CD 0018 end
if ( defined ( $ hash - > { helper } { SB_PLAYER_SyncMasters } { $ dev } { MAC } ) ) {
2015-06-18 20:23:54 +00:00
$ mac = $ hash - > { helper } { SB_PLAYER_SyncMasters } { $ dev } { MAC } ;
2015-03-19 20:37:01 +00:00
} else {
2016-10-01 16:46:46 +00:00
# CD 0038 Player nicht gefunden, testen ob Name zu einem FHEM-Ger<65> t passt
2015-06-18 20:23:54 +00:00
if ( defined ( $ defs { $ dev } ) && defined ( $ defs { $ dev } { TYPE } ) && ( $ defs { $ dev } { TYPE } eq 'SB_PLAYER' ) && defined ( $ defs { $ dev } { PLAYERMAC } ) ) {
$ mac = $ defs { $ dev } { PLAYERMAC } ;
} else {
# CD 0038 end
my $ msg = "SB_PLAYER_Set: no MAC for player " . $ dev . "." ;
Log3 ( $ hash , 3 , $ msg ) ;
#return( $msg ); # CD 0018 wenn keine MAC vorhanden weitermachen
}
}
if ( defined ( $ mac ) ) {
2016-10-01 16:46:46 +00:00
# CD 0038 wenn asSlave angegeben ist, wird der erste Player zur Gruppe des 2. hinzugef<65> gt
2015-06-18 20:23:54 +00:00
if ( ( @ arg == 2 ) && ( $ arg [ 1 ] eq "asSlave" ) ) {
2017-05-28 19:14:57 +00:00
IOWrite ( $ hash , "$mac sync " .
2015-06-18 20:23:54 +00:00
"$hash->{PLAYERMAC}\n" ) ;
} else {
# CD 0038 end
2017-05-28 19:14:57 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} sync " .
2015-06-18 20:23:54 +00:00
"$mac\n" ) ;
}
$ doGetStatus = 1 ;
2015-03-19 20:37:01 +00:00
}
} # CD 0018
SB_PLAYER_GetStatus ( $ hash ) if ( $ doGetStatus == 1 ) ;
}
# CD 0018 end
2014-07-06 22:14:26 +00:00
} elsif ( $ cmd eq "unsync" ) {
2015-03-19 20:37:01 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} sync -\n" ) ;
SB_PLAYER_GetStatus ( $ hash ) ;
# CD 0028 start
if ( $ hash - > { helper } { ttsstate } == TTS_SYNCGROUPACTIVE ) {
2017-05-28 19:14:57 +00:00
SB_PLAYER_SetTTSState ( $ hash , TTS_IDLE , 0 , 0 ) ; # CD 0066 single statt bulk update
2015-03-19 20:37:01 +00:00
}
# CD 0028 end
2014-07-06 22:14:26 +00:00
} elsif ( $ cmd eq "playlists" ) {
2015-03-19 20:37:01 +00:00
if ( @ arg == 1 ) {
my $ msg ;
if ( defined ( $ hash - > { helper } { SB_PLAYER_Playlists } { $ arg [ 0 ] } { ID } ) ) {
2017-05-28 19:14:57 +00:00
if ( $ hash - > { helper } { SB_PLAYER_Playlists } { $ arg [ 0 ] } { SOURCE } eq 'LMS' ) { # CD 0070
$ msg = "$hash->{PLAYERMAC} playlistcontrol cmd:load " .
"playlist_id:$hash->{helper}{SB_PLAYER_Playlists}{$arg[0]}{ID}" ;
} else {
$ msg = "$hash->{PLAYERMAC} $hash->{helper}{SB_PLAYER_Playlists}{$arg[0]}{SOURCE} playlist play " .
"item_id:$hash->{helper}{SB_PLAYER_Playlists}{$arg[0]}{ID}" ;
}
Log3 ( $ hash , 5 , "SB_PLAYER_Set($name): playlists command = " .
2015-03-19 20:37:01 +00:00
$ msg . " ........ with $arg[0]" ) ;
IOWrite ( $ hash , $ msg . "\n" ) ;
readingsSingleUpdate ( $ hash , "playlists" , "$arg[ 0 ]" , 1 ) ;
SB_PLAYER_GetStatus ( $ hash ) ;
} else {
$ msg = "SB_PLAYER_Set: no name for playlist defined." ;
Log3 ( $ hash , 3 , $ msg ) ;
return ( $ msg ) ;
}
} else {
my $ msg = "SB_PLAYER_Set: no arguments for playlists given." ;
Log3 ( $ hash , 3 , $ msg ) ;
return ( $ msg ) ;
}
} elsif ( $ cmd eq "resetTTS" ) {
2016-10-01 16:46:46 +00:00
delete ( $ hash - > { helper } { saveLocked } ) if ( defined ( $ hash - > { helper } { saveLocked } ) ) ; # CD 0056
2017-05-28 19:14:57 +00:00
delete $ hash - > { helper } { sgTalkActive } if defined ( $ hash - > { helper } { sgTalkActive } ) ; # CD 0063
2015-03-19 20:37:01 +00:00
SB_PLAYER_SetTTSState ( $ hash , TTS_IDLE , 0 , 1 ) ;
2015-11-02 08:26:30 +00:00
# CD 0047 start
} elsif ( lc ( $ cmd ) eq "currenttrackposition" ) {
if ( defined ( $ arg [ 0 ] ) ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} time $arg[0]\n" ) ;
}
# CD 0047 end
2016-10-01 16:46:46 +00:00
# CD 0052 start
} elsif ( lc ( $ cmd ) eq "snooze" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} jivealarm snooze:1\n" ) ;
# CD 0052 end
2017-05-28 19:14:57 +00:00
# CD 0065 start
} elsif ( $ cmd eq "updateFTUImedialist" ) {
delete ( $ hash - > { SONGINFOQUEUE } ) if ( defined ( $ hash - > { SONGINFOQUEUE } ) ) ; # CD 0072
2017-08-26 19:46:07 +00:00
$ hash - > { helper } { songinfoquery } = '' ; # CD 0084
$ hash - > { helper } { songinfocounter } = 0 ; # CD 0084
$ hash - > { helper } { songinfopending } = 0 ; # CD 0084
2017-05-28 19:14:57 +00:00
2017-08-26 19:46:07 +00:00
if ( defined ( $ hash - > { helper } { ftuiSupport } { medialist } ) ) {
if ( defined ( $ hash - > { helper } { playlistIds } ) ) {
$ hash - > { helper } { playlistInfoRetries } = 5 ; # CD 0076
my @ ids = split ( ',' , $ hash - > { helper } { playlistIds } ) ;
foreach ( @ ids ) {
# CD 0084 verz<72> gert abfragen, ansonsten Probleme bei schwacher Hardware
SB_PLAYER_SonginfoAddQueue ( $ hash , $ _ , 0 ) unless ( defined ( $ hash - > { helper } { playlistInfo } { $ _ } ) && ! defined ( $ hash - > { helper } { playlistInfo } { $ _ } { remote } ) || ( $ _ == 0 ) ) ; # CD 0076 id 0 ignorieren
}
SB_PLAYER_SonginfoAddQueue ( $ hash , 0 , 0 ) ;
2017-05-28 19:14:57 +00:00
}
}
} elsif ( $ cmd eq "clearFTUIcache" ) {
delete $ hash - > { helper } { playlistInfo } if defined ( $ hash - > { helper } { playlistInfo } ) ;
} elsif ( ( $ cmd eq "track" ) || ( $ cmd eq "tracknumber" ) ) {
if ( @ arg != 1 ) {
my $ msg = "SB_PLAYER_Set: no arguments for track given." ;
Log3 ( $ hash , 3 , $ msg ) ;
return ( $ msg ) ;
}
if ( $ arg [ 0 ] =~ /^\d+$/ ) {
IOWrite ( $ hash , $ hash - > { PLAYERMAC } . " playlist index " . ( $ arg [ 0 ] - 1 ) . "\n" ) ;
} else {
IOWrite ( $ hash , $ hash - > { PLAYERMAC } . " playlist index " . $ arg [ 0 ] . "\n" ) ;
}
# CD 0065 end
2014-02-20 23:34:51 +00:00
} else {
2015-03-19 20:37:01 +00:00
my $ msg = "SB_PLAYER_Set: unsupported command given" ;
Log3 ( $ hash , 3 , $ msg ) ;
return ( $ msg ) ;
2014-02-20 23:34:51 +00:00
}
2017-05-28 19:14:57 +00:00
2014-02-20 23:34:51 +00:00
return ( undef ) ;
2017-05-28 19:14:57 +00:00
2014-02-20 23:34:51 +00:00
}
2016-10-01 16:46:46 +00:00
# CD 0033 hinzugef<65> gt
2015-04-07 19:48:18 +00:00
# ----------------------------------------------------------------------------
# add talk segments to playlist
# ----------------------------------------------------------------------------
sub SB_PLAYER_LoadTalk ($) {
2016-10-01 16:46:46 +00:00
# gespeicherte Elemente in Playlist einf<6E> gen
2015-04-07 19:48:18 +00:00
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
}
}
}
2016-10-01 16:46:46 +00:00
# CD 0033 hinzugef<65> gt
2015-04-07 19:48:18 +00:00
# ----------------------------------------------------------------------------
# prepare player for talk
# ----------------------------------------------------------------------------
sub SB_PLAYER_PrepareTalk ($) {
# kein readingsBulkUpdate
2016-10-01 16:46:46 +00:00
# aktuellen Stand abspeichern, playlist l<> schen, Lautst<73> rke setzen
2017-05-28 19:14:57 +00:00
2015-04-07 19:48:18 +00:00
my ( $ hash ) = @ _ ;
my $ name = $ hash - > { NAME } ;
# talk ist nicht aktiv
2017-05-28 19:14:57 +00:00
if ( ! defined ( $ hash - > { helper } { ttsOptions } { nosaverestore } ) && ! defined ( $ hash - > { helper } { sgTalkActive } ) ) { # CD 0063 sgTalkActive hinzugef<65> gt
2015-04-07 19:48:18 +00:00
SB_PLAYER_SetTTSState ( $ hash , TTS_SAVE , 0 , 0 ) ;
2015-06-18 20:23:54 +00:00
SB_PLAYER_Save ( $ hash , "xxTTSxx" ) if ( ! defined ( $ hash - > { helper } { saveLocked } ) ) ;
2015-04-07 19:48:18 +00:00
}
$ 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
2017-05-28 19:14:57 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} mixer volume " . SB_PLAYER_FHEM2LMSVolume ( $ hash , $ vol ) . "\n" ) ; # CD 0065 SB_PLAYER_FHEM2LMSVolume
SB_PLAYER_SetSyncedVolume ( $ hash , $ hash - > { helper } { ttsVolume } , 1 ) ;
2015-04-07 19:48:18 +00:00
}
SB_PLAYER_SetTTSState ( $ hash , TTS_LOADPLAYLIST , 0 , 0 ) ;
}
2015-03-19 20:37:01 +00:00
# CD 0014 start
# ----------------------------------------------------------------------------
# recall player state
2015-06-18 20:23:54 +00:00
#
# CD 0036 added $statename
2015-03-19 20:37:01 +00:00
# ----------------------------------------------------------------------------
2015-06-18 20:23:54 +00:00
sub SB_PLAYER_Recall ($$) {
my ( $ hash , $ arg ) = @ _ ; # CD 0036
2015-03-19 20:37:01 +00:00
my $ name = $ hash - > { NAME } ;
2017-05-28 19:14:57 +00:00
2015-06-18 20:23:54 +00:00
# CD 0036 start
my $ del = 0 ;
my $ delonly = 0 ;
my $ forceoff = 0 ;
my $ forceon = 0 ;
my $ forceplay = 0 ;
my $ forcestop = 0 ;
my $ statename ;
my @ args = split " " , $ arg ;
2017-05-28 19:14:57 +00:00
2015-06-18 20:23:54 +00:00
if ( defined ( $ args [ 0 ] ) ) {
$ statename = $ args [ 0 ] ;
} else {
$ statename = 'default' ;
}
2015-03-19 20:37:01 +00:00
2015-06-18 20:23:54 +00:00
# Optionen auswerten
for my $ opt ( @ args ) {
$ del = 1 if ( $ opt =~ m/^del$/ ) ;
$ delonly = 1 if ( $ opt =~ m/^delonly$/ ) ;
$ forceoff = 1 if ( $ opt =~ m/^off$/ ) ;
$ forceon = 1 if ( ( $ opt =~ m/^on$/ ) || ( $ opt =~ m/^play$/ ) ) ;
$ forceplay = 1 if ( $ opt =~ m/^play$/ ) ;
$ forcestop = 1 if ( $ opt =~ m/^stop$/ ) ;
}
2017-05-28 19:14:57 +00:00
2015-06-18 20:23:54 +00:00
$ forceoff = 0 if ( $ forceon == 1 ) ;
$ forcestop = 0 if ( $ forceplay == 1 ) ;
2017-05-28 19:14:57 +00:00
2015-06-18 20:23:54 +00:00
# CD 0036 end
2017-05-28 19:14:57 +00:00
2016-10-01 16:46:46 +00:00
# wurde <20> berhaupt etwas gespeichert ?
2015-06-18 20:23:54 +00:00
if ( defined ( $ hash - > { helper } { savedPlayerState } ) && defined ( $ hash - > { helper } { savedPlayerState } { $ statename } ) ) {
if ( $ delonly == 0 ) {
# CD 0029 start
if ( ( $ hash - > { helper } { ttsstate } != TTS_IDLE ) && defined ( $ hash - > { helper } { ttsOptions } { debugsaverestore } ) ) {
Log3 ( $ hash , 0 , "SB_PLAYER_Recall: $name: restoring..." ) ;
$ hash - > { helper } { ttsOptions } { logloaddone } = 1 ;
$ hash - > { helper } { ttsOptions } { logplay } = 1 ;
}
# CD 0029 end
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist shuffle 0\n" ) ;
if ( defined ( $ hash - > { helper } { savedPlayerState } { $ statename } { playlistIds } ) ) {
# wegen Shuffle Playlist neu erzeugen
# CD 0030 start
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist clear\n" ) ;
my @ playlistIds = split ( ',' , $ hash - > { helper } { savedPlayerState } { $ statename } { playlistIds } ) ;
2015-11-02 08:26:30 +00:00
my $ f = 0 ; # CD 0048
2015-06-18 20:23:54 +00:00
for my $ id ( @ playlistIds ) {
if ( $ id >= 0 ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlistcontrol cmd:add track_id:" . $ id . "\n" ) ;
2015-03-19 20:37:01 +00:00
} else {
2015-06-18 20:23:54 +00:00
if ( defined ( $ hash - > { helper } { savedPlayerState } { $ statename } { playlistUrls } ) && defined ( $ hash - > { helper } { savedPlayerState } { $ statename } { playlistUrls } { $ id } ) ) {
2015-11-02 08:26:30 +00:00
if ( defined ( $ hash - > { helper } { savedPlayerState } { $ statename } { path } ) && ( $ f == 0 ) ) { # CD 0048
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist add " . $ hash - > { helper } { savedPlayerState } { $ statename } { path } . "\n" ) ; # CD 0048
} else { # CD 0048
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist add " . $ hash - > { helper } { savedPlayerState } { $ statename } { playlistUrls } { $ id } . "\n" ) ;
} # CD 0048
2015-06-18 20:23:54 +00:00
} else {
Log3 ( $ hash , 2 , "SB_PLAYER_Recall: $name: no url found for id " . $ id ) ;
}
2015-03-19 20:37:01 +00:00
}
2015-11-02 08:26:30 +00:00
$ f = 1 ; # CD 0048
2015-03-19 20:37:01 +00:00
}
2015-06-18 20:23:54 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist index " . $ hash - > { helper } { savedPlayerState } { $ statename } { playlistCurrentTrack } . "\n" ) ;
# CD 0030 end
2015-03-19 20:37:01 +00:00
} else {
2015-06-18 20:23:54 +00:00
# auf dem Server gespeicherte Playlist fortsetzen
if ( $ hash - > { helper } { savedPlayerState } { $ statename } { playStatus } eq "playing" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist resume fhem_$hash->{NAME}_$statename\n" ) ;
} else {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist resume fhem_$hash->{NAME}_$statename noplay:1\n" ) ;
}
2015-03-19 20:37:01 +00:00
}
2015-06-18 20:23:54 +00:00
if ( $ hash - > { helper } { savedPlayerState } { $ statename } { volumeStraight } ne '?' ) {
2017-05-28 19:14:57 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} mixer volume " . SB_PLAYER_FHEM2LMSVolume ( $ hash , $ hash - > { helper } { savedPlayerState } { $ statename } { volumeStraight } ) . "\n" ) ; # CD 0065 SB_PLAYER_FHEM2LMSVolume
SB_PLAYER_SetSyncedVolume ( $ hash , $ hash - > { helper } { savedPlayerState } { $ statename } { volumeStraight } , 1 ) ;
2015-03-19 20:37:01 +00:00
}
2015-06-18 20:23:54 +00:00
if ( $ hash - > { helper } { savedPlayerState } { $ statename } { repeat } ne ReadingsVal ( $ name , "repeat" , "?" ) ) {
if ( $ hash - > { helper } { savedPlayerState } { $ statename } { repeat } eq "off" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist repeat 0\n" ) ;
} elsif ( $ hash - > { helper } { savedPlayerState } { $ statename } { repeat } eq "one" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist repeat 1\n" ) ;
} elsif ( $ hash - > { helper } { savedPlayerState } { $ statename } { repeat } eq "all" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist repeat 2\n" ) ;
}
2015-03-19 20:37:01 +00:00
}
2015-06-18 20:23:54 +00:00
# CD 0028 start
if ( ( ( $ hash - > { helper } { savedPlayerState } { $ statename } { power } eq "off" ) && ( $ forceon != 1 ) ) || ( $ forceoff == 1 ) ) { # CD 0036 added $forceon and $forceoff
IOWrite ( $ hash , "$hash->{PLAYERMAC} power 0\n" ) ;
2015-03-19 20:37:01 +00:00
if ( $ hash - > { helper } { ttsstate } == TTS_RESTORE ) {
SB_PLAYER_SetTTSState ( $ hash , TTS_IDLE , 0 , 1 ) ;
2016-10-01 16:46:46 +00:00
delete ( $ hash - > { helper } { saveLocked } ) if ( defined ( $ hash - > { helper } { saveLocked } ) ) ; # CD 0056
2015-03-19 20:37:01 +00:00
}
2015-06-18 20:23:54 +00:00
} else {
# CD 0028 end
if ( ( ( $ hash - > { helper } { savedPlayerState } { $ statename } { playStatus } eq "stopped" ) && ( $ forceplay != 1 ) ) || ( $ forcestop == 1 ) ) { # CD 0036 added $forceplay and $forcestop
IOWrite ( $ hash , "$hash->{PLAYERMAC} stop\n" ) ;
# CD 0028 start
if ( $ hash - > { helper } { ttsstate } == TTS_RESTORE ) {
SB_PLAYER_SetTTSState ( $ hash , TTS_IDLE , 0 , 1 ) ;
2016-10-01 16:46:46 +00:00
delete ( $ hash - > { helper } { saveLocked } ) if ( defined ( $ hash - > { helper } { saveLocked } ) ) ; # CD 0056
2015-06-18 20:23:54 +00:00
}
# CD 0028 end
} elsif ( ( $ hash - > { helper } { savedPlayerState } { $ statename } { playStatus } eq "playing" ) || ( $ forceplay == 1 ) ) { # CD 0036 added $forceplay
2016-10-01 16:46:46 +00:00
my @ secbuf = split ( ',' , AttrVal ( $ name , "fadeinsecs" , '10,10' ) ) ; # CD 0050 split hinzugef<65> gt
IOWrite ( $ hash , "$hash->{PLAYERMAC} play " . $ secbuf [ 0 ] . "\n" ) ;
2015-06-18 20:23:54 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} time $hash->{helper}{savedPlayerState}{$statename}{elapsedTime}\n" ) if ( defined ( $ hash - > { helper } { savedPlayerState } { $ statename } { elapsedTime } ) ) ;
# CD 0028 start
if ( $ hash - > { helper } { ttsstate } == TTS_RESTORE ) {
SB_PLAYER_SetTTSState ( $ hash , TTS_IDLE , 0 , 1 ) ;
}
# CD 0028 end
} elsif ( $ hash - > { helper } { savedPlayerState } { $ statename } { playStatus } eq "paused" ) {
# paused kann nicht aus stop erreicht werden -> Playlist starten und dann pausieren
$ hash - > { helper } { recallPause } = 1 ;
$ hash - > { helper } { recallPending } = 1 ;
2015-11-02 08:26:30 +00:00
$ hash - > { helper } { recallPendingElapsedTime } = $ hash - > { helper } { savedPlayerState } { $ statename } { elapsedTime } ; # CD 0047
2015-03-19 20:37:01 +00:00
}
}
2015-06-18 20:23:54 +00:00
# CD 0028 restore names
readingsSingleUpdate ( $ hash , "playlists" , $ hash - > { helper } { savedPlayerState } { $ statename } { playlist } , ( AttrVal ( $ name , "donotnotify" , "true" ) eq "true" ) ? 0 : 1 ) if ( defined ( $ hash - > { helper } { savedPlayerState } { $ statename } { playlist } ) ) ;
readingsSingleUpdate ( $ hash , "favorites" , $ hash - > { helper } { savedPlayerState } { $ statename } { favorite } , ( AttrVal ( $ name , "donotnotify" , "true" ) eq "true" ) ? 0 : 1 ) if ( defined ( $ hash - > { helper } { savedPlayerState } { $ statename } { favorite } ) ) ;
2015-03-19 20:37:01 +00:00
}
2015-06-18 20:23:54 +00:00
delete ( $ hash - > { helper } { savedPlayerState } { $ statename } ) if ( ( $ del == 1 ) || ( $ delonly == 1 ) ) ;
2016-10-01 16:46:46 +00:00
} else {
# CD 0056 start
if ( $ hash - > { helper } { ttsstate } == TTS_RESTORE ) {
SB_PLAYER_SetTTSState ( $ hash , TTS_IDLE , 0 , 1 ) ;
delete ( $ hash - > { helper } { saveLocked } ) if ( defined ( $ hash - > { helper } { saveLocked } ) ) ;
}
# CD 0056 end
2015-03-19 20:37:01 +00:00
}
}
2017-05-28 19:14:57 +00:00
# CD 0062 start
sub SB_PLAYER_tcb_TriggerTTSDone ($) {
my ( $ in ) = shift ;
my ( undef , $ name ) = split ( ':' , $ in ) ;
my $ hash = $ defs { $ name } ;
DoTrigger ( $ name , "ttsdone" ) ;
}
# CD 0062 end
# CD 0063 start
sub SB_PLAYER_tcb_TriggerPlaylistStop ($) {
my ( $ in ) = shift ;
my ( undef , $ name ) = split ( ':' , $ in ) ;
my $ hash = $ defs { $ name } ;
$ hash - > { helper } { noStopEventUntil } = 0 unless defined ( $ hash - > { helper } { noStopEventUntil } ) ;
if ( ( ReadingsVal ( $ name , "playStatus" , "x" ) eq "stopped" ) && ( time ( ) > $ hash - > { helper } { noStopEventUntil } ) && ( $ hash - > { helper } { ttsstate } == TTS_IDLE ) ) {
DoTrigger ( $ name , "playlistStop" ) ;
}
}
# CD 0063 end
2015-03-19 20:37:01 +00:00
sub SB_PLAYER_SetTTSState ($$$$) {
my ( $ hash , $ state , $ bulk , $ broadcast ) = @ _ ;
my $ name = $ hash - > { NAME } ;
return if ( $ state eq $ hash - > { helper } { ttsstate } ) ;
2017-05-28 19:14:57 +00:00
my $ oldstate = $ hash - > { helper } { ttsstate } ; # CD 0062
2015-03-19 20:37:01 +00:00
$ hash - > { helper } { ttsstate } = $ state ;
Log3 ( $ hash , defined ( $ hash - > { helper } { ttsOptions } { debug } ) ? 0 : 6 , "SB_PLAYER_SetTTSState: $name: ttsstate: " . $ ttsstates { $ hash - > { helper } { ttsstate } } ) ;
if ( $ bulk == 1 ) {
readingsBulkUpdate ( $ hash , "talkStatus" , $ ttsstates { $ hash - > { helper } { ttsstate } } ) ;
} else {
readingsSingleUpdate ( $ hash , "talkStatus" , $ ttsstates { $ hash - > { helper } { ttsstate } } , ( AttrVal ( $ name , "donotnotify" , "true" ) eq "true" ) ? 0 : 1 ) ;
}
if ( $ broadcast == 1 ) {
if ( $ state == TTS_IDLE ) {
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 ttsidle\n" ) ;
}
}
}
}
}
delete ( $ hash - > { helper } { ttsqueue } ) if ( defined ( $ hash - > { helper } { ttsqueue } ) && ( $ state == TTS_IDLE ) ) ;
2015-06-18 20:23:54 +00:00
delete ( $ hash - > { helper } { ttsPowerWasOff } ) if ( defined ( $ hash - > { helper } { ttsPowerWasOff } ) && ( $ state == TTS_IDLE ) ) ;
2017-05-28 19:14:57 +00:00
# CD 0062 start
if ( ( $ state == TTS_IDLE ) && ( $ oldstate != TTS_IDLE ) ) {
if ( defined ( $ hash - > { helper } { ttsOptions } { eventondone } ) ) {
RemoveInternalTimer ( "TriggerTTSDone:$name" ) ;
InternalTimer ( gettimeofday ( ) + 0.5 ,
"SB_PLAYER_tcb_TriggerTTSDone" ,
"TriggerTTSDone:$name" ,
0 ) ;
}
IOWrite ( $ hash , "$name fhemrelay ttsdone" ) ;
}
# CD 0062 end
2015-03-19 20:37:01 +00:00
}
# ----------------------------------------------------------------------------
# save player state
2017-05-28 19:14:57 +00:00
#
2015-06-18 20:23:54 +00:00
# CD 0036 added $statename
2015-03-19 20:37:01 +00:00
# ----------------------------------------------------------------------------
2015-06-18 20:23:54 +00:00
sub SB_PLAYER_Save ($$) {
my ( $ hash , $ statename ) = @ _ ;
2015-03-19 20:37:01 +00:00
my $ name = $ hash - > { NAME } ;
2015-06-18 20:23:54 +00:00
$ statename = 'default' unless defined ( $ statename ) ;
delete ( $ hash - > { helper } { savedPlayerState } { $ statename } ) if ( defined ( $ hash - > { helper } { savedPlayerState } ) && defined ( $ hash - > { helper } { savedPlayerState } { $ statename } ) ) ;
2015-03-19 20:37:01 +00:00
SB_PLAYER_EstimateElapsedTime ( $ hash ) ;
2015-06-18 20:23:54 +00:00
$ hash - > { helper } { savedPlayerState } { $ statename } { power } = ReadingsVal ( $ name , "power" , "on" ) ; # CD 0028
$ hash - > { helper } { savedPlayerState } { $ statename } { power } = "off" if ( ( $ statename eq "xxTTSxx" ) && defined ( $ hash - > { helper } { ttsPowerWasOff } ) ) ; # CD 0038
$ hash - > { helper } { savedPlayerState } { $ statename } { SYNCGROUP } = $ hash - > { SYNCGROUP } if ( defined ( $ hash - > { SYNCGROUP } ) ) ; # CD 0028
$ hash - > { helper } { savedPlayerState } { $ statename } { SYNCMASTER } = $ hash - > { SYNCMASTER } if ( defined ( $ hash - > { SYNCMASTER } ) ) ; # CD 0028
$ hash - > { helper } { savedPlayerState } { $ statename } { elapsedTime } = $ hash - > { helper } { elapsedTime } { VAL } ;
$ hash - > { helper } { savedPlayerState } { $ statename } { playlistCurrentTrack } = ReadingsVal ( $ name , "playlistCurrentTrack" , 1 ) - 1 ;
$ hash - > { helper } { savedPlayerState } { $ statename } { playStatus } = ReadingsVal ( $ name , "playStatus" , "?" ) ;
$ hash - > { helper } { savedPlayerState } { $ statename } { repeat } = ReadingsVal ( $ name , "repeat" , "?" ) ;
$ hash - > { helper } { savedPlayerState } { $ statename } { volumeStraight } = ReadingsVal ( $ name , "volumeStraight" , "?" ) ;
$ hash - > { helper } { savedPlayerState } { $ statename } { playlist } = ReadingsVal ( $ name , "playlists" , "-" ) ;
$ hash - > { helper } { savedPlayerState } { $ statename } { favorite } = ReadingsVal ( $ name , "favorites" , "-" ) ;
2015-11-02 08:26:30 +00:00
$ hash - > { helper } { savedPlayerState } { $ statename } { path } = $ hash - > { helper } { path } ; # CD 0048
2015-03-19 20:37:01 +00:00
# CD 0029 start
delete ( $ hash - > { helper } { ttsOptions } { logloaddone } ) if ( defined ( $ hash - > { helper } { ttsOptions } { logloaddone } ) ) ;
delete ( $ hash - > { helper } { ttsOptions } { logplay } ) if ( defined ( $ hash - > { helper } { ttsOptions } { logplay } ) ) ;
# CD 0029 end
2015-06-18 20:23:54 +00:00
# CD 0036 immer intern speichern
$ hash - > { helper } { savedPlayerState } { $ statename } { playlistIds } = $ hash - > { helper } { playlistIds } ;
$ hash - > { helper } { savedPlayerState } { $ statename } { playlistUrls } = $ hash - > { helper } { playlistUrls } ;
if ( ( $ hash - > { helper } { ttsstate } != TTS_IDLE ) && defined ( $ hash - > { helper } { ttsOptions } { debugsaverestore } ) ) {
Log3 ( $ hash , 0 , "SB_PLAYER_Save: $name: saving {helper}{playlistIds}: " . $ hash - > { helper } { playlistIds } ) if ( defined ( $ hash - > { helper } { playlistIds } ) ) ;
2015-03-19 20:37:01 +00:00
}
2015-06-18 20:23:54 +00:00
# CD 0036
2017-05-28 19:14:57 +00:00
2015-06-18 20:23:54 +00:00
# CD 0036, alte Version, deaktivert
# ---------------------------------
if ( 1 == 0 ) {
# nur 1 Track -> playlist save verwenden
if ( ( ReadingsVal ( $ name , "playlistTracks" , 1 ) <=1)&&(!defined($hash-> { helper } { ttsOptions } { internalsave } ) ) ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist save fhem_$hash->{NAME}_$statename silent:1\n" ) ;
# CD 0029 start
if ( ( $ hash - > { helper } { ttsstate } != TTS_IDLE ) && defined ( $ hash - > { helper } { ttsOptions } { debugsaverestore } ) ) {
Log3 ( $ hash , 0 , "SB_PLAYER_Save: $name: 1 track in playlist, using playlist save" ) ;
}
# CD 0029 end
} else {
2016-10-01 16:46:46 +00:00
# mehr als 1 Track, auf shuffle pr<70> fen (playlist resume funktioniert nicht richtig wenn shuffle nicht auf off steht)
2015-06-18 20:23:54 +00:00
# bei negativen Ids (Remote-Streams) und shuffle geht die vorherige Reihenfolge verloren, kein Workaround bekannt
2016-10-01 16:46:46 +00:00
# es werden maximal 500 Ids gespeichert, bei mehr als 500 Eintr<74> gen in der Playlists geht die vorherige Reihenfolge verloren (zu <20> ndern)
2015-06-18 20:23:54 +00:00
if ( ( ( ReadingsVal ( $ name , "shuffle" , "?" ) eq "off" ) ||
( ! defined ( $ hash - > { helper } { playlistIds } ) ) ||
( $ hash - > { helper } { playlistIds } =~ /-/ ) ||
( ReadingsVal ( $ name , "playlistTracks" , 0 ) > 500 ) ) && ! defined ( $ hash - > { helper } { ttsOptions } { internalsave } ) ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} playlist save fhem_$hash->{NAME}_$statename silent:1\n" ) ;
# CD 0029 start
if ( ( $ hash - > { helper } { ttsstate } != TTS_IDLE ) && defined ( $ hash - > { helper } { ttsOptions } { debugsaverestore } ) ) {
Log3 ( $ hash , 0 , "SB_PLAYER_Save: $name: multiple tracks in playlist, using playlist save" ) ;
}
# CD 0029 end
} else {
$ hash - > { helper } { savedPlayerState } { $ statename } { playlistIds } = $ hash - > { helper } { playlistIds } ;
$ hash - > { helper } { savedPlayerState } { $ statename } { playlistUrls } = $ hash - > { helper } { playlistUrls } ;
if ( ( $ hash - > { helper } { ttsstate } != TTS_IDLE ) && defined ( $ hash - > { helper } { ttsOptions } { debugsaverestore } ) ) {
# CD 0029 start
if ( defined ( $ hash - > { helper } { ttsOptions } { internalsave } ) ) {
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}=~ /-/);
} else {
Log3 ( $ hash , 0 , "SB_PLAYER_Save: $name: multiple tracks in playlist, shuffle active, using {helper}{playlistIds} (" . $ hash - > { helper } { playlistIds } . ")" ) ;
}
# CD 0029 end
}
}
}
}
# ---------------------------------
2015-03-19 20:37:01 +00:00
# CD 0029 start
if ( ( $ hash - > { helper } { ttsstate } != TTS_IDLE ) && defined ( $ hash - > { helper } { ttsOptions } { debugsaverestore } ) ) {
2015-06-18 20:23:54 +00:00
Log3 ( $ hash , 0 , "SB_PLAYER_Save: $name: power " . $ hash - > { helper } { savedPlayerState } { $ statename } { power } ) ;
Log3 ( $ hash , 0 , "SB_PLAYER_Save: $name: elapsedTime " . $ hash - > { helper } { savedPlayerState } { $ statename } { elapsedTime } ) if ( defined ( $ hash - > { helper } { savedPlayerState } { $ statename } { elapsedTime } ) ) ;
Log3 ( $ hash , 0 , "SB_PLAYER_Save: $name: playlistCurrentTrack " . $ hash - > { helper } { savedPlayerState } { $ statename } { playlistCurrentTrack } ) ;
Log3 ( $ hash , 0 , "SB_PLAYER_Save: $name: playStatus " . $ hash - > { helper } { savedPlayerState } { $ statename } { playStatus } ) ;
Log3 ( $ hash , 0 , "SB_PLAYER_Save: $name: repeat " . $ hash - > { helper } { savedPlayerState } { $ statename } { repeat } ) ;
Log3 ( $ hash , 0 , "SB_PLAYER_Save: $name: volumeStraight " . $ hash - > { helper } { savedPlayerState } { $ statename } { volumeStraight } ) ;
Log3 ( $ hash , 0 , "SB_PLAYER_Save: $name: playlist " . $ hash - > { helper } { savedPlayerState } { $ statename } { playlist } ) ;
Log3 ( $ hash , 0 , "SB_PLAYER_Save: $name: favorite " . $ hash - > { helper } { savedPlayerState } { $ statename } { favorite } ) ;
2015-03-19 20:37:01 +00:00
}
# CD 0029 end
}
# CD 0014 end
2014-02-20 23:34:51 +00:00
# ----------------------------------------------------------------------------
# set Alarms of the Player
# ----------------------------------------------------------------------------
2016-10-01 16:46:46 +00:00
# CD 0015 angepasst f<> r gr<67> <72> ere Anzahl an Alarmen
2014-02-20 23:34:51 +00:00
sub SB_PLAYER_Alarm ( $$@ ) {
my ( $ hash , $ n , @ arg ) = @ _ ;
my $ name = $ hash - > { NAME } ;
2015-03-19 20:37:01 +00:00
# CD 0015 deaktiviert
#if( ( $n != 1 ) && ( $n != 2 ) ) {
# Log3( $hash, 1, "SB_PLAYER_Alarm: $name: wrong ID given. Must be 1|2" );
# return;
2017-05-28 19:14:57 +00:00
#}
2014-02-20 23:34:51 +00:00
2015-03-19 20:37:01 +00:00
my $ id = ReadingsVal ( "$name" , "alarm" . $ n . "_id" , "none" ) ; # CD 0015 angepasst
my $ updateReadingsOnSet = AttrVal ( $ name , "updateReadingsOnSet" , false ) ; # CD 0017
my $ donotnotify = AttrVal ( $ name , "donotnotify" , true ) ; # CD 0017
2014-02-20 23:34:51 +00:00
Log3 ( $ hash , 5 , "SB_PLAYER_Alarm: $name: ID:$id, N:$n" ) ;
my $ cmdstr = "" ;
if ( $ arg [ 0 ] eq "set" ) {
2015-03-19 20:37:01 +00:00
# set <name> alarm set 0..6 hh:mm:ss playlist
if ( ( @ arg != 4 ) && ( @ arg != 3 ) ) {
my $ msg = "SB_PLAYER_Set: not enough arguments for alarm given." ;
Log3 ( $ hash , 3 , $ msg ) ;
return ( $ msg ) ;
}
2017-05-28 19:14:57 +00:00
2015-03-19 20:37:01 +00:00
if ( $ id ne "none" ) {
IOWrite ( $ hash , "$hash->{PLAYERMAC} alarm delete id:$id\n" ) ; # CD 0020 'id' fehlt
# readingsSingleUpdate( $hash, "alarmid$n", "none", 0 ); # CD 0015 deaktiviert
}
2017-05-28 19:14:57 +00:00
2016-10-01 16:46:46 +00:00
my $ dow = SB_PLAYER_CheckWeekdays ( $ arg [ 1 ] ) ; # CD 0016 hinzugef<65> gt
2017-05-28 19:14:57 +00:00
2015-03-19 20:37:01 +00:00
# split the time string up
my @ buf = split ( ":" , $ arg [ 2 ] ) ;
2016-10-01 16:46:46 +00:00
$ buf [ 2 ] = 0 if ( scalar ( @ buf ) == 2 ) ; # CD 0016, von MM <20> bernommen, ge<67> ndert
2015-03-19 20:37:01 +00:00
if ( scalar ( @ buf ) != 3 ) {
my $ msg = "SB_PLAYER_Set: please use hh:mm:ss for alarm time." ;
Log3 ( $ hash , 3 , $ msg ) ;
return ( $ msg ) ;
2017-05-28 19:14:57 +00:00
}
2015-03-19 20:37:01 +00:00
my $ secs = ( $ buf [ 0 ] * 3600 ) + ( $ buf [ 1 ] * 60 ) + $ buf [ 2 ] ;
2017-05-28 19:14:57 +00:00
$ cmdstr = "$hash->{PLAYERMAC} alarm add dow:$dow repeat:0 enabled:1" ;
2015-03-19 20:37:01 +00:00
if ( defined ( $ arg [ 3 ] ) ) {
# CD 0015 start
my $ url = join ( " " , @ arg [ 3 .. $# arg ] ) ;
if ( defined ( $ hash - > { helper } { alarmPlaylists } ) ) {
foreach my $ e ( keys % { $ hash - > { helper } { alarmPlaylists } } ) {
if ( $ url eq $ hash - > { helper } { alarmPlaylists } { $ e } { title } ) {
$ url = $ hash - > { helper } { alarmPlaylists } { $ e } { url } ;
last ;
}
}
}
# CD 0015 end
2016-10-01 16:46:46 +00:00
# CD 0034 <20> berpr<70> fen ob g<> ltige url, wenn nicht, versuchen file:// anzuh<75> ngen
2015-04-07 19:48:18 +00:00
if ( $ url !~ /:\/\// ) {
2016-10-01 16:46:46 +00:00
$ url = '/' . $ url if ( $ url =~ /^[a-zA-Z]:\\/ ) ; # f<> r Windows
2015-04-07 19:48:18 +00:00
$ url =~ s/\\/\//g ;
2017-05-28 19:14:57 +00:00
$ url = 'file://' . $ url ;
2015-04-07 19:48:18 +00:00
}
# CD 0034 end
2016-10-01 16:46:46 +00:00
$ cmdstr . = " url:" . uri_escape ( decode ( 'utf-8' , $ url ) ) ; # CD 0015 uri_escape und join hinzugef<65> gt # CD 0020 decode hinzugef<65> gt # CD 0034 playlist: in url: ge<67> ndert
2015-03-19 20:37:01 +00:00
}
$ cmdstr . = " time:$secs\n" ;
IOWrite ( $ hash , $ cmdstr ) ;
$ hash - > { LASTALARM } = $ n ;
2016-10-01 16:46:46 +00:00
} elsif ( ( $ arg [ 0 ] eq "enable" ) || ( $ arg [ 0 ] eq "on" ) ) { # CD 0015 'on' hinzugef<65> gt
2015-03-19 20:37:01 +00:00
if ( $ id ne "none" ) {
$ cmdstr = "$hash->{PLAYERMAC} alarm update id:$id " ;
$ cmdstr . = "enabled:1\n" ;
IOWrite ( $ hash , $ cmdstr ) ;
readingsSingleUpdate ( $ hash , "alarm" . $ n . "_state" , "on" , $ donotnotify ) if ( $ updateReadingsOnSet ) ; # CD 0017
}
2016-10-01 16:46:46 +00:00
} elsif ( ( $ arg [ 0 ] eq "disable" ) || ( $ arg [ 0 ] eq "off" ) ) { # CD 0015 'off' hinzugef<65> gt
2015-03-19 20:37:01 +00:00
if ( $ id ne "none" ) {
$ cmdstr = "$hash->{PLAYERMAC} alarm update id:$id " ;
$ cmdstr . = "enabled:0\n" ;
IOWrite ( $ hash , $ cmdstr ) ;
readingsSingleUpdate ( $ hash , "alarm" . $ n . "_state" , "off" , $ donotnotify ) if ( $ updateReadingsOnSet ) ; # CD 0017
}
2014-02-20 23:34:51 +00:00
} elsif ( $ arg [ 0 ] eq "volume" ) {
2015-03-19 20:37:01 +00:00
if ( $ id ne "none" ) {
$ cmdstr = "$hash->{PLAYERMAC} alarm update id:$id " ;
$ cmdstr . = "volume:" . $ arg [ 1 ] . "\n" ;
IOWrite ( $ hash , $ cmdstr ) ;
readingsSingleUpdate ( $ hash , "alarm" . $ n . "_volume" , $ arg [ 1 ] , $ donotnotify ) if ( $ updateReadingsOnSet ) ; # CD 0017
}
# CD 0015 start
} elsif ( $ arg [ 0 ] eq "sound" ) {
if ( $ id ne "none" ) {
if ( defined ( $ arg [ 1 ] ) ) {
$ cmdstr = "$hash->{PLAYERMAC} alarm update id:$id " ;
my $ url = join ( " " , @ arg [ 1 .. $# arg ] ) ;
readingsSingleUpdate ( $ hash , "alarm" . $ n . "_sound" , $ url , $ donotnotify ) if ( $ updateReadingsOnSet ) ; # CD 0017
if ( defined ( $ hash - > { helper } { alarmPlaylists } ) ) {
foreach my $ e ( keys % { $ hash - > { helper } { alarmPlaylists } } ) {
if ( $ url eq $ hash - > { helper } { alarmPlaylists } { $ e } { title } ) {
$ url = $ hash - > { helper } { alarmPlaylists } { $ e } { url } ;
last ;
}
}
}
2016-10-01 16:46:46 +00:00
# CD 0034 <20> berpr<70> fen ob g<> ltige url, wenn nicht, versuchen file:// anzuh<75> ngen
2015-04-07 19:48:18 +00:00
if ( $ url !~ /:\/\// ) {
2016-10-01 16:46:46 +00:00
$ url = '/' . $ url if ( $ url =~ /^[a-zA-Z]:\\/ ) ; # f<> r Windows
2015-04-07 19:48:18 +00:00
$ url =~ s/\\/\//g ;
2017-05-28 19:14:57 +00:00
$ url = 'file://' . $ url ;
2015-04-07 19:48:18 +00:00
}
# CD 0034 end
2016-10-01 16:46:46 +00:00
$ cmdstr . = "url:" . uri_escape ( decode ( 'utf-8' , $ url ) ) ; # CD 0017 decode hinzugef<65> gt # CD 0034 playlist: in url: ge<67> ndert
IOWrite ( $ hash , $ cmdstr . "\n" ) ; # CD 0017 reaktiviert # CD 0034 \n hinzugef<65> gt
2015-03-19 20:37:01 +00:00
} else {
my $ msg = "SB_PLAYER_Set: alarm, no value for sound." ;
Log3 ( $ hash , 3 , $ msg ) ;
return ( $ msg ) ;
}
}
} elsif ( $ arg [ 0 ] eq "repeat" ) {
if ( $ id ne "none" ) {
if ( defined ( $ arg [ 1 ] ) ) {
$ cmdstr = "$hash->{PLAYERMAC} alarm update id:$id " ;
if ( ( $ arg [ 1 ] eq "1" ) || ( $ arg [ 1 ] eq "on" ) || ( $ arg [ 1 ] eq "yes" ) ) {
$ cmdstr . = "repeat:1\n" ;
readingsSingleUpdate ( $ hash , "alarm" . $ n . "_repeat" , "on" , $ donotnotify ) if ( $ updateReadingsOnSet ) ; # CD 0017
} else {
$ cmdstr . = "repeat:0\n" ;
readingsSingleUpdate ( $ hash , "alarm" . $ n . "_repeat" , "off" , $ donotnotify ) if ( $ updateReadingsOnSet ) ; # CD 0017
}
IOWrite ( $ hash , $ cmdstr ) ;
} else {
my $ msg = "SB_PLAYER_Set: alarm, no value for repeat." ;
Log3 ( $ hash , 3 , $ msg ) ;
return ( $ msg ) ;
}
2017-05-28 19:14:57 +00:00
}
2015-03-19 20:37:01 +00:00
} elsif ( $ arg [ 0 ] eq "wdays" ) {
if ( $ id ne "none" ) {
if ( defined ( $ arg [ 1 ] ) ) {
$ cmdstr = "$hash->{PLAYERMAC} alarm update id:$id " ;
my $ dow = SB_PLAYER_CheckWeekdays ( join ( "" , @ arg [ 1 .. $# arg ] ) ) ; # CD 0017
$ cmdstr . = "dow:" . $ dow . "\n" ; # CD 0016 SB_PLAYER_CheckWeekdays verwenden
IOWrite ( $ hash , $ cmdstr ) ;
# CD 0017 start
if ( $ updateReadingsOnSet ) {
my $ rdaystr = "" ;
if ( $ dow ne "" ) {
$ rdaystr = "Mo" if ( index ( $ dow , "1" ) != - 1 ) ;
$ rdaystr . = " Tu" if ( index ( $ dow , "2" ) != - 1 ) ;
$ rdaystr . = " We" if ( index ( $ dow , "3" ) != - 1 ) ;
$ rdaystr . = " Th" if ( index ( $ dow , "4" ) != - 1 ) ;
$ rdaystr . = " Fr" if ( index ( $ dow , "5" ) != - 1 ) ;
$ rdaystr . = " Sa" if ( index ( $ dow , "6" ) != - 1 ) ;
$ rdaystr . = " Su" if ( index ( $ dow , "0" ) != - 1 ) ;
} else {
$ rdaystr = "none" ;
}
$ rdaystr =~ s/^\s+|\s+$//g ;
readingsSingleUpdate ( $ hash , "alarm" . $ n . "_wdays" , $ rdaystr , $ donotnotify ) ;
}
# CD 0017 end
} else {
my $ msg = "SB_PLAYER_Set: no weekdays specified for alarm." ;
Log3 ( $ hash , 3 , $ msg ) ;
return ( $ msg ) ;
}
}
} elsif ( $ arg [ 0 ] eq "time" ) {
if ( $ id ne "none" ) {
# split the time string up
if ( ! defined ( $ arg [ 1 ] ) ) {
my $ msg = "SB_PLAYER_Set: no alarm time given." ;
Log3 ( $ hash , 3 , $ msg ) ;
return ( $ msg ) ;
}
my @ buf = split ( ":" , $ arg [ 1 ] ) ;
2016-10-01 16:46:46 +00:00
$ buf [ 2 ] = 0 if ( scalar ( @ buf ) == 2 ) ; # CD 0016, von MM <20> bernommen, ge<67> ndert
2015-03-19 20:37:01 +00:00
if ( scalar ( @ buf ) != 3 ) {
my $ msg = "SB_PLAYER_Set: please use hh:mm:ss for alarm time." ;
Log3 ( $ hash , 3 , $ msg ) ;
return ( $ msg ) ;
2017-05-28 19:14:57 +00:00
}
2015-03-19 20:37:01 +00:00
my $ secs = ( $ buf [ 0 ] * 3600 ) + ( $ buf [ 1 ] * 60 ) + $ buf [ 2 ] ;
$ cmdstr = "$hash->{PLAYERMAC} alarm update id:$id " ;
$ cmdstr . = "time:" . $ secs . "\n" ;
IOWrite ( $ hash , $ cmdstr ) ;
# CD 0017 start
if ( $ updateReadingsOnSet ) {
2017-05-28 19:14:57 +00:00
my $ buf = sprintf ( "%02d:%02d:%02d" ,
2015-03-19 20:37:01 +00:00
int ( scalar ( $ secs ) / 3600 ) ,
int ( ( $ secs % 3600 ) / 60 ) ,
int ( $ secs % 60 ) ) ;
readingsSingleUpdate ( $ hash , "alarm" . $ n . "_time" , $ buf , $ donotnotify ) ;
}
# CD 0017 end
}
# CD 0015 end
2014-02-20 23:34:51 +00:00
} elsif ( $ arg [ 0 ] eq "delete" ) {
2015-03-19 20:37:01 +00:00
if ( $ id ne "none" ) {
$ cmdstr = "$hash->{PLAYERMAC} alarm delete id:$id\n" ;
IOWrite ( $ hash , $ cmdstr ) ;
# readingsSingleUpdate( $hash, "alarmid$n", "none", 1 ); # CD 0015 deaktiviert
}
2014-02-20 23:34:51 +00:00
2017-05-28 19:14:57 +00:00
} else {
2015-03-19 20:37:01 +00:00
my $ msg = "SB_PLAYER_Set: unkown argument " . $ arg [ 0 ] . " for alarm given." ;
Log3 ( $ hash , 3 , $ msg ) ;
return ( $ msg ) ;
2014-02-20 23:34:51 +00:00
}
return ( undef ) ;
}
2016-10-01 16:46:46 +00:00
# CD 0016, neu, von MM <20> bernommen
2015-03-19 20:37:01 +00:00
# ----------------------------------------------------------------------------
# Check weekdays string
# ----------------------------------------------------------------------------
sub SB_PLAYER_CheckWeekdays ( $ ) {
my ( $ wdayargs ) = @ _ ;
my $ weekdays = '' ;
if ( index ( $ wdayargs , "Mo" ) != - 1 || index ( $ wdayargs , "1" ) != - 1 )
{
$ weekdays . = '1,' ;
}
if ( index ( $ wdayargs , "Tu" ) != - 1 || index ( $ wdayargs , "Di" ) != - 1 || index ( $ wdayargs , "2" ) != - 1 )
{
$ weekdays . = '2,' ;
}
if ( index ( $ wdayargs , "We" ) != - 1 || index ( $ wdayargs , "Mi" ) != - 1 || index ( $ wdayargs , "3" ) != - 1 )
{
$ weekdays . = '3,' ;
}
if ( index ( $ wdayargs , "Th" ) != - 1 || index ( $ wdayargs , "Do" ) != - 1 || index ( $ wdayargs , "4" ) != - 1 )
{
$ weekdays . = '4,' ;
}
if ( index ( $ wdayargs , "Fr" ) != - 1 || index ( $ wdayargs , "5" ) != - 1 )
{
$ weekdays . = '5,' ;
}
if ( index ( $ wdayargs , "Sa" ) != - 1 || index ( $ wdayargs , "6" ) != - 1 )
{
$ weekdays . = '6,' ;
}
if ( index ( $ wdayargs , "Su" ) != - 1 || index ( $ wdayargs , "So" ) != - 1 || index ( $ wdayargs , "0" ) != - 1 )
{
$ weekdays . = '0' ;
}
if ( index ( $ wdayargs , "all" ) != - 1 || index ( $ wdayargs , "daily" ) != - 1 || index ( $ wdayargs , "7" ) != - 1 )
{
$ weekdays = '0,1,2,3,4,5,6' ;
}
2016-10-01 16:46:46 +00:00
if ( index ( $ wdayargs , "none" ) != - 1 ) # || index($wdayargs,"once") != -1) # CD 0016 once funktioniert so nicht, muss <20> ber repeat gemacht werden
2015-03-19 20:37:01 +00:00
{
$ weekdays = '7' ;
}
$ weekdays =~ s/,$// ; # CD 0019 letztes , entfernen
return $ weekdays ;
}
2014-02-20 23:34:51 +00:00
# ----------------------------------------------------------------------------
# Status update - just internal use and invoked by the timer
# ----------------------------------------------------------------------------
sub SB_PLAYER_GetStatus ( $ ) {
my ( $ hash ) = @ _ ;
my $ name = $ hash - > { NAME } ;
my $ strbuf = "" ;
Log3 ( $ hash , 5 , "SB_PLAYER_GetStatus: called" ) ;
2017-06-22 20:47:42 +00:00
return if ( defined ( $ hash - > { helper } { disableGetStatus } ) ) ;
2015-03-19 20:37:01 +00:00
# CD 0014 start - Anzahl Anfragen begrenzen
if ( ! defined ( $ hash - > { helper } { lastGetStatus } ) || ( $ hash - > { helper } { lastGetStatus } < gettimeofday ( ) - 0.5 ) ) {
#Log 0,"Querying status, last: $hash->{helper}{lastGetStatus}, now: ".gettimeofday();
$ hash - > { helper } { lastGetStatus } = gettimeofday ( ) ;
2017-05-28 19:14:57 +00:00
2015-03-19 20:37:01 +00:00
# we fire the respective questions and parse the answers in parse
2017-08-26 19:46:07 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} artist ?\n" .
"$hash->{PLAYERMAC} album ?\n" .
"$hash->{PLAYERMAC} title ?\n" .
"$hash->{PLAYERMAC} playlist url ?\n" .
"$hash->{PLAYERMAC} remote ?\n" .
"$hash->{PLAYERMAC} status 0 500 tags:Kcu\n" . # CD 0030 u added to tags
2016-10-01 16:46:46 +00:00
#IOWrite( $hash, "$hash->{PLAYERMAC} alarm playlists 0 200\n" ) if (!defined($hash->{helper}{alarmPlaylists})); # CD 0016 get available elements for alarms before querying the alarms # CD 0026 wird <20> ber Server verteilt
2017-08-26 19:46:07 +00:00
"$hash->{PLAYERMAC} alarms 0 200 tags:all filter:all\n" . # CD 0015 filter added
# MM 0016 start
"$hash->{PLAYERMAC} playerpref alarmsEnabled ?\n" .
"$hash->{PLAYERMAC} playerpref alarmDefaultVolume ?\n" .
"$hash->{PLAYERMAC} playerpref alarmTimeoutSeconds ?\n" .
"$hash->{PLAYERMAC} playerpref alarmSnoozeSeconds ?\n" .
"$hash->{PLAYERMAC} playerpref alarmfadeseconds ?\n" . # CD 0082
# MM 0016 end
"$hash->{PLAYERMAC} playerpref syncVolume ?\n" . # CD 0007
"$hash->{PLAYERMAC} playlist name ?\n" . # CD 0009
"$hash->{PLAYERMAC} playlist path 0 ?\n" . # CD 0048
"$hash->{PLAYERMAC} duration ?\n" ) ; # CD 0014
2015-03-19 20:37:01 +00:00
SB_PLAYER_QueryElapsedTime ( $ hash ) ;
} # CD 0014 end
2017-05-28 19:14:57 +00:00
# the other values below are provided by our server. we don't
2014-02-20 23:34:51 +00:00
# need to ask again
if ( $ hash - > { PLAYERIP } eq "?" ) {
2015-03-19 20:37:01 +00:00
# the server doesn't care about us
IOWrite ( $ hash , "$hash->{PLAYERMAC} player ip ?\n" ) ;
2014-02-20 23:34:51 +00:00
}
if ( $ hash - > { MODEL } eq "?" ) {
2015-03-19 20:37:01 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} player model ?\n" ) ;
2014-02-20 23:34:51 +00:00
}
if ( $ hash - > { CANPOWEROFF } eq "?" ) {
2015-03-19 20:37:01 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} player canpoweroff ?\n" ) ;
2014-02-20 23:34:51 +00:00
}
if ( $ hash - > { PLAYERNAME } eq "?" ) {
2015-03-19 20:37:01 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} name ?\n" ) ;
2014-02-20 23:34:51 +00:00
}
if ( ReadingsVal ( $ name , "state" , "?" ) eq "?" ) {
2015-03-19 20:37:01 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} power ?\n" ) ;
2014-02-20 23:34:51 +00:00
}
if ( ReadingsVal ( $ name , "connected" , "?" ) eq "?" ) {
2015-03-19 20:37:01 +00:00
IOWrite ( $ hash , "$hash->{PLAYERMAC} connected ?\n" ) ;
2014-02-20 23:34:51 +00:00
}
# do and update of the status
2015-03-19 20:37:01 +00:00
RemoveInternalTimer ( $ hash ) ; # CD 0014
2015-06-18 20:23:54 +00:00
my $ iv = AttrVal ( $ name , "statusRequestInterval" , 300 ) ; # CD 0037
2017-06-22 20:47:42 +00:00
if ( ReadingsVal ( $ name , "presence" , "x" ) eq "absent" ) { # CD 0079
$ iv = 0 ;
$ hash - > { helper } { disableGetStatus } = 1 ;
}
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + $ iv ,
"SB_PLAYER_GetStatus" ,
$ hash ,
2015-06-18 20:23:54 +00:00
0 ) if $ iv > 0 ;
2014-02-20 23:34:51 +00:00
Log3 ( $ hash , 5 , "SB_PLAYER_GetStatus: leaving" ) ;
return ( ) ;
}
# ----------------------------------------------------------------------------
# called from the IODev for Broadcastmessages
# ----------------------------------------------------------------------------
sub SB_PLAYER_RecBroadcast ( $$@ ) {
my ( $ hash , $ cmd , $ msg , $ bin ) = @ _ ;
my $ name = $ hash - > { NAME } ;
2017-05-28 19:14:57 +00:00
Log3 ( $ hash , 5 , "SB_PLAYER_Broadcast($name): called with $msg" ) ;
2014-02-20 23:34:51 +00:00
# let's see what we got. Split the data at the space
my @ args = split ( " " , $ msg ) ;
if ( $ cmd eq "SERVER" ) {
2015-03-19 20:37:01 +00:00
# a message from the server
if ( $ args [ 0 ] eq "OFF" ) {
# the server is off, so are we
RemoveInternalTimer ( $ hash ) ;
readingsSingleUpdate ( $ hash , "state" , "off" , 1 ) ;
readingsSingleUpdate ( $ hash , "power" , "off" , 1 ) ;
SB_PLAYER_Amplifier ( $ hash ) ;
} elsif ( $ args [ 0 ] eq "ON" ) {
# the server is back
2017-05-28 19:14:57 +00:00
#readingsSingleUpdate( $hash, "state", "on", 1 ); # CD 0011 ob der Player eingeschaltet ist, ist hier noch nicht bekannt, SB_PLAYER_GetStatus abwarten
#readingsSingleUpdate( $hash, "power", "on", 1 ); # CD 0011 ob der Player eingeschaltet ist, ist hier noch nicht bekannt, SB_PLAYER_GetStatus abwarten
2015-03-19 20:37:01 +00:00
# do and update of the status
RemoveInternalTimer ( $ hash ) ; # CD 0016
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + 10 ,
"SB_PLAYER_GetStatus" ,
$ hash ,
2015-03-19 20:37:01 +00:00
0 ) ;
} elsif ( $ args [ 0 ] eq "IP" ) {
$ hash - > { SBSERVER } = $ args [ 1 ] ;
2016-10-01 16:46:46 +00:00
# CD 0043 bei <20> nderung von Adresse oder Port COVERART aktualisieren
2015-11-02 08:26:30 +00:00
readingsBeginUpdate ( $ hash ) ;
SB_PLAYER_CoverArt ( $ hash ) ;
if ( AttrVal ( $ name , "donotnotify" , "false" ) eq "true" ) {
readingsEndUpdate ( $ hash , 0 ) ;
} else {
readingsEndUpdate ( $ hash , 1 ) ;
}
# CD 0043 end
2015-03-19 20:37:01 +00:00
} else {
# unkown broadcast message
}
2014-07-06 22:14:26 +00:00
2014-02-20 23:34:51 +00:00
} elsif ( $ cmd eq "FAVORITES" ) {
2015-03-19 20:37:01 +00:00
if ( $ args [ 0 ] eq "ADD" ) {
# format: ADD IODEVname ID shortentry
$ hash - > { helper } { SB_PLAYER_Favs } { $ args [ 3 ] } { ID } = $ args [ 2 ] ;
2016-10-01 16:46:46 +00:00
$ hash - > { helper } { SB_PLAYER_Favs } { $ args [ 3 ] } { URL } = $ args [ 4 ] ; # CD 0021 hinzugef<65> gt
2017-05-28 19:14:57 +00:00
$ hash - > { helper } { SB_PLAYER_Favs } { $ args [ 3 ] } { SOURCE } = $ args [ 5 ] ; # CD 0070 hinzugef<65> gt
2015-03-19 20:37:01 +00:00
if ( $ hash - > { FAVSTR } eq "" ) {
2016-10-01 16:46:46 +00:00
$ hash - > { FAVSTR } = $ args [ 3 ] ; # CD Test f<> r Leerzeichen join(" ",@args[ 4..$#args ]);
2015-03-19 20:37:01 +00:00
} else {
2016-10-01 16:46:46 +00:00
$ hash - > { FAVSTR } . = "," . $ args [ 3 ] ; # CD Test f<> r Leerzeichen join(" ",@args[ 4..$#args ]);
2015-03-19 20:37:01 +00:00
}
2017-05-28 19:14:57 +00:00
# CD 0064 start
if ( AttrVal ( $ name , "sortFavorites" , "0" ) eq "1" ) {
my @ radios = split ( ',' , $ hash - > { FAVSTR } ) ; # CD0064 Elektrolurch
$ hash - > { FAVSTR } = join ( ',' , sort { "\L$a" cmp "\L$b" } @ radios ) ; # CD0064 Elektrolurch
}
# CD 0064
# CD 0068 start
2017-08-26 19:46:07 +00:00
if ( defined ( $ hash - > { helper } { ftuiSupport } { favorites } ) ) {
2017-05-28 19:14:57 +00:00
my $ t = $ hash - > { FAVSTR } ;
$ t =~ s/,/:/g ;
readingsSingleUpdate ( $ hash , "ftuiFavoritesItems" , $ t , 1 ) ;
$ t =~ s/_/ /g ;
readingsSingleUpdate ( $ hash , "ftuiFavoritesAlias" , $ t , 1 ) ;
}
# CD 0068 end
2015-03-19 20:37:01 +00:00
# CD 0016 start, provisorisch um alarmPlaylists zu aktualisieren, TODO: muss von 97_SB_SERVER kommen
RemoveInternalTimer ( $ hash ) ; # CD 0016
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + 3 ,
"SB_PLAYER_GetStatus" ,
$ hash ,
2015-03-19 20:37:01 +00:00
0 ) ;
#end
} elsif ( $ args [ 0 ] eq "FLUSH" ) {
2017-05-28 19:14:57 +00:00
if ( $ args [ 1 ] eq 'all' ) {
undef ( % { $ hash - > { helper } { SB_PLAYER_Favs } } ) ;
$ hash - > { FAVSTR } = "" ;
delete ( $ hash - > { helper } { alarmPlaylists } ) if ( defined ( $ hash - > { helper } { alarmPlaylists } ) ) ; # CD 0016
} else {
# CD 0070 gezielt nach Plugin/App l<> schen
my $ doupdate = 0 ;
my $ favs = "" ;
foreach my $ fa ( keys % { $ hash - > { helper } { SB_PLAYER_Favs } } ) {
if ( $ hash - > { helper } { SB_PLAYER_Favs } { $ fa } { SOURCE } eq $ args [ 1 ] ) {
delete $ hash - > { helper } { SB_PLAYER_Favs } { $ fa } ;
$ doupdate = 1 ;
} else {
if ( $ favs eq "" ) {
$ favs = $ fa ;
} else {
$ favs . = "," . $ fa ;
}
}
}
if ( $ doupdate == 1 ) {
if ( AttrVal ( $ name , "sortFavorites" , "0" ) eq "1" ) {
my @ radios = split ( ',' , $ favs ) ;
$ hash - > { FAVSTR } = join ( ',' , sort { "\L$a" cmp "\L$b" } @ radios ) ;
} else {
$ hash - > { FAVSTR } = $ favs ;
}
2017-08-26 19:46:07 +00:00
if ( defined ( $ hash - > { helper } { ftuiSupport } { favorites } ) ) {
2017-05-28 19:14:57 +00:00
my $ t = $ hash - > { FAVSTR } ;
$ t =~ s/,/:/g ;
readingsSingleUpdate ( $ hash , "ftuiFavoritesItems" , $ t , 1 ) ;
$ t =~ s/_/ /g ;
readingsSingleUpdate ( $ hash , "ftuiFavoritesAlias" , $ t , 1 ) ;
}
}
}
2015-03-19 20:37:01 +00:00
} else {
}
2014-07-06 22:14:26 +00:00
} elsif ( $ cmd eq "SYNCMASTER" ) {
2015-03-19 20:37:01 +00:00
if ( $ args [ 0 ] eq "ADD" ) {
2016-10-01 16:46:46 +00:00
if ( ( $ args [ 1 ] ne $ hash - > { PLAYERNAME } ) || ( $ args [ 2 ] ne $ hash - > { PLAYERMAC } ) ) { # CD 0056 Name oder MAC m<> ssen unterschiedlich sein
# CD 0056 mehrere Player haben gleichen Namen -> Namen anpassen
if ( ( $ args [ 1 ] eq $ hash - > { PLAYERNAME } ) || ( defined ( $ hash - > { helper } { SB_PLAYER_SyncMasters } { $ args [ 1 ] } ) ) ) {
$ args [ 1 ] = $ args [ 1 ] . "_MAC_" . $ args [ 3 ] ;
}
# CD 0056 Ende
2015-03-19 20:37:01 +00:00
$ hash - > { helper } { SB_PLAYER_SyncMasters } { $ args [ 1 ] } { MAC } = $ args [ 2 ] ;
if ( $ hash - > { SYNCMASTERS } eq "" ) {
$ hash - > { SYNCMASTERS } = $ args [ 1 ] ;
} else {
$ hash - > { SYNCMASTERS } . = "," . $ args [ 1 ] ;
}
}
} elsif ( $ args [ 0 ] eq "FLUSH" ) {
undef ( % { $ hash - > { helper } { SB_PLAYER_SyncMasters } } ) ;
$ hash - > { SYNCMASTERS } = "" ;
2014-07-06 22:14:26 +00:00
2015-03-19 20:37:01 +00:00
} else {
}
2014-07-06 22:14:26 +00:00
} elsif ( $ cmd eq "PLAYLISTS" ) {
2015-03-19 20:37:01 +00:00
if ( $ args [ 0 ] eq "ADD" ) {
# CD 0014 Playlists mit fhem_* ignorieren
if ( $ args [ 3 ] =~ /^fhem_.*/ ) {
2015-06-18 20:23:54 +00:00
# CD 0036 start
if ( $ args [ 3 ] =~ /$name/ ) {
my $ plname = $ args [ 1 ] ;
# kein Name ?
if ( $ args [ 1 ] =~ /^fhem_$name$/ ) {
$ plname = 'default' ;
} else {
$ plname =~ s/^fhem_$name// ;
$ plname =~ s/^_// ;
}
2017-05-28 19:14:57 +00:00
Log3 ( $ hash , 4 , "SB_PLAYER_RecbroadCast($name): - adding - PLAYLISTS ADD " .
2015-06-18 20:23:54 +00:00
"name:$args[1] id:$args[2] uid:$plname" ) ;
$ hash - > { helper } { myPlaylists } { $ plname } { ID } = $ args [ 2 ] ;
$ hash - > { helper } { myPlaylists } { $ plname } { NAME } = $ args [ 1 ] ;
} else {
# CD 0036 end
2017-05-28 19:14:57 +00:00
Log3 ( $ hash , 5 , "SB_PLAYER_RecbroadCast($name): - ignoring - PLAYLISTS ADD " .
2015-03-19 20:37:01 +00:00
"name:$args[1] id:$args[2] uid:$args[3]" ) ;
2015-06-18 20:23:54 +00:00
}
2015-03-19 20:37:01 +00:00
} else {
# CD 0014 end
2017-05-28 19:14:57 +00:00
Log3 ( $ hash , 4 , "SB_PLAYER_RecbroadCast($name): PLAYLISTS ADD " .
2015-03-19 20:37:01 +00:00
"name:$args[1] id:$args[2] uid:$args[3]" ) ;
2017-05-28 19:14:57 +00:00
$ hash - > { helper } { SB_PLAYER_Playlists } { $ args [ 3 ] } { SOURCE } = $ args [ 4 ] ; # CD 0070
2015-03-19 20:37:01 +00:00
$ hash - > { helper } { SB_PLAYER_Playlists } { $ args [ 3 ] } { ID } = $ args [ 2 ] ;
$ hash - > { helper } { SB_PLAYER_Playlists } { $ args [ 3 ] } { NAME } = $ args [ 1 ] ;
if ( $ hash - > { SERVERPLAYLISTS } eq "" ) {
$ hash - > { SERVERPLAYLISTS } = $ args [ 3 ] ;
} else {
$ hash - > { SERVERPLAYLISTS } . = "," . $ args [ 3 ] ;
}
} # CD 0014
2017-05-28 19:14:57 +00:00
# CD 0064 start
if ( AttrVal ( $ name , "sortPlaylists" , "0" ) eq "1" ) {
my @ radios = split ( ',' , $ hash - > { SERVERPLAYLISTS } ) ;
$ hash - > { SERVERPLAYLISTS } = join ( ',' , sort { "\L$a" cmp "\L$b" } @ radios ) ;
}
# CD 0064
# CD 0068 start
2017-08-26 19:46:07 +00:00
if ( defined ( $ hash - > { helper } { ftuiSupport } { playlists } ) ) {
2017-05-28 19:14:57 +00:00
my $ t = $ hash - > { SERVERPLAYLISTS } ;
$ t =~ s/,/:/g ;
readingsSingleUpdate ( $ hash , "ftuiPlaylistsItems" , $ t , 1 ) ;
$ t =~ s/_/ /g ;
readingsSingleUpdate ( $ hash , "ftuiPlaylistsAlias" , $ t , 1 ) ;
}
# CD 0068 end
2015-03-19 20:37:01 +00:00
# CD 0016 start, provisorisch um alarmPlaylists zu aktualisieren, TODO: muss von 97_SB_SERVER kommen
RemoveInternalTimer ( $ hash ) ; # CD 0016
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + 3 ,
"SB_PLAYER_GetStatus" ,
$ hash ,
2015-03-19 20:37:01 +00:00
0 ) ;
#end
} elsif ( $ args [ 0 ] eq "FLUSH" ) {
2017-05-28 19:14:57 +00:00
if ( $ args [ 1 ] eq 'all' ) {
undef ( % { $ hash - > { helper } { SB_PLAYER_Playlists } } ) ;
undef ( % { $ hash - > { helper } { myPlaylists } } ) ; # CD 0036
$ hash - > { SERVERPLAYLISTS } = "" ;
delete ( $ hash - > { helper } { alarmPlaylists } ) if ( defined ( $ hash - > { helper } { alarmPlaylists } ) ) ; # CD 0016
} else {
# CD 0070 gezielt nach Plugin/App l<> schen
my $ doupdate = 0 ;
my $ pls = "" ;
foreach my $ pl ( keys % { $ hash - > { helper } { SB_PLAYER_Playlists } } ) {
if ( $ hash - > { helper } { SB_PLAYER_Playlists } { $ pl } { SOURCE } eq $ args [ 1 ] ) {
delete $ hash - > { helper } { SB_PLAYER_Playlists } { $ pl } ;
$ doupdate = 1 ;
} else {
if ( $ pls eq "" ) {
$ pls = $ pl ;
} else {
$ pls . = "," . $ pl ;
}
}
}
if ( $ doupdate == 1 ) {
if ( AttrVal ( $ name , "sortPlaylists" , "0" ) eq "1" ) {
my @ radios = split ( ',' , $ pls ) ;
$ hash - > { SERVERPLAYLISTS } = join ( ',' , sort { "\L$a" cmp "\L$b" } @ radios ) ;
} else {
$ hash - > { SERVERPLAYLISTS } = $ pls ;
}
2017-08-26 19:46:07 +00:00
if ( defined ( $ hash - > { helper } { ftuiSupport } { playlists } ) ) {
2017-05-28 19:14:57 +00:00
my $ t = $ hash - > { SERVERPLAYLISTS } ;
$ t =~ s/,/:/g ;
readingsSingleUpdate ( $ hash , "ftuiPlaylistsItems" , $ t , 1 ) ;
$ t =~ s/_/ /g ;
readingsSingleUpdate ( $ hash , "ftuiPlaylistsAlias" , $ t , 1 ) ;
}
}
}
2015-03-19 20:37:01 +00:00
} else {
}
# CD 0026 start
} elsif ( $ cmd eq "ALARMPLAYLISTS" ) {
if ( $ args [ 0 ] eq "ADD" ) {
$ hash - > { helper } { alarmPlaylists } { $ args [ 1 ] } { $ args [ 2 ] } = join ( " " , @ args [ 3 .. $# args ] ) ;
} elsif ( $ args [ 0 ] eq "FLUSH" ) {
delete ( $ hash - > { helper } { alarmPlaylists } ) if ( defined ( $ hash - > { helper } { alarmPlaylists } ) ) ;
}
# CD 0026 end
2014-02-20 23:34:51 +00:00
} else {
}
}
# ----------------------------------------------------------------------------
# parse the return on the alarms status
# ----------------------------------------------------------------------------
2015-03-19 20:37:01 +00:00
# wird von SB_PLAYER_Parse aufgerufen, readingsBeginUpdate ist aktiv
2014-07-06 22:14:26 +00:00
sub SB_PLAYER_ParseAlarms ( $@ ) {
2014-02-20 23:34:51 +00:00
my ( $ hash , @ data ) = @ _ ;
my $ name = $ hash - > { NAME } ;
2015-03-19 20:37:01 +00:00
# CD 0016 start {ALARMSCOUNT} verschieben nach reload
if ( defined ( $ hash - > { ALARMSCOUNT } ) ) {
$ hash - > { helper } { ALARMSCOUNT } = $ hash - > { ALARMSCOUNT } ;
delete ( $ hash - > { ALARMSCOUNT } ) ;
}
# CD 0016
my $ lastAlarmCount = $ hash - > { helper } { ALARMSCOUNT } ; # CD 0016 ALARMSCOUNT nach {helper} verschoben
2017-05-28 19:14:57 +00:00
2014-02-20 23:34:51 +00:00
if ( $ data [ 0 ] =~ /^([0-9])*/ ) {
2015-03-19 20:37:01 +00:00
shift ( @ data ) ;
2014-02-20 23:34:51 +00:00
}
if ( $ data [ 0 ] =~ /^([0-9])*/ ) {
2015-03-19 20:37:01 +00:00
shift ( @ data ) ;
2014-02-20 23:34:51 +00:00
}
2015-03-19 20:37:01 +00:00
fhem ( "deletereading $name alarmid.*" ) ; # CD 0015 alte readings entfernen
2014-02-20 23:34:51 +00:00
2015-03-19 20:37:01 +00:00
my $ alarmcounter = 0 ; # CD 0015
2017-05-28 19:14:57 +00:00
2015-03-19 20:37:01 +00:00
foreach ( @ data ) {
if ( $ _ =~ /^(id:)(\S{8})/ ) {
# id is 8 non-white-space characters
2017-05-28 19:14:57 +00:00
# example: id:0ac7f3a2
2015-03-19 20:37:01 +00:00
$ alarmcounter += 1 ; # CD 0015
readingsBulkUpdate ( $ hash , "alarm" . $ alarmcounter . "_id" , $ 2 ) ; # CD 0015
next ;
2016-10-01 16:46:46 +00:00
} elsif ( $ _ =~ /^(dow:)([0-9,]*)/ ) { # C 0016 + durch * ersetzt, f<> r dow: ohne Tage
2017-05-28 19:14:57 +00:00
# example: dow:1,2,4,5,6
2015-03-19 20:37:01 +00:00
my $ rdaystr = "" ; # CD 0015
if ( $ 2 ne "" ) { # CD 0016
if ( index ( $ 2 , "1" ) != - 1 ) {
$ rdaystr = "Mo" ; # CD 0015
}
if ( index ( $ 2 , "2" ) != - 1 ) {
$ rdaystr . = " Tu" ; # CD 0015
}
if ( index ( $ 2 , "3" ) != - 1 ) {
$ rdaystr . = " We" ; # CD 0015
}
if ( index ( $ 2 , "4" ) != - 1 ) {
$ rdaystr . = " Th" ; # CD 0015
}
if ( index ( $ 2 , "5" ) != - 1 ) {
$ rdaystr . = " Fr" ; # CD 0015
}
if ( index ( $ 2 , "6" ) != - 1 ) {
$ rdaystr . = " Sa" ; # CD 0015
2017-05-28 19:14:57 +00:00
}
2015-03-19 20:37:01 +00:00
if ( index ( $ 2 , "0" ) != - 1 ) {
$ rdaystr . = " Su" ; # CD 0015
}
} else { # CD 0016
$ rdaystr = "none" ; # CD 0016
} # CD 0016
$ rdaystr =~ s/^\s+|\s+$//g ; # CD 0015
readingsBulkUpdate ( $ hash , "alarm" . $ alarmcounter . "_wdays" , $ rdaystr ) ; # CD 0015
next ;
} elsif ( $ _ =~ /^(enabled:)([0|1])/ ) {
2017-05-28 19:14:57 +00:00
# example: enabled:1
2015-03-19 20:37:01 +00:00
if ( $ 2 eq "1" ) {
readingsBulkUpdate ( $ hash , "alarm" . $ alarmcounter . "_state" , "on" ) ; # CD 0015
} else {
readingsBulkUpdate ( $ hash , "alarm" . $ alarmcounter . "_state" , "off" ) ; # CD 0015
}
next ;
} elsif ( $ _ =~ /^(repeat:)([0|1])/ ) {
2017-05-28 19:14:57 +00:00
# example: repeat:1
2015-03-19 20:37:01 +00:00
if ( $ 2 eq "1" ) {
readingsBulkUpdate ( $ hash , "alarm" . $ alarmcounter . "_repeat" , "yes" ) ; # CD 0015
} else {
readingsBulkUpdate ( $ hash , "alarm" . $ alarmcounter . "_repeat" , "no" ) ; # CD 0015
}
next ;
} elsif ( $ _ =~ /^(time:)([0-9]+)/ ) {
2017-05-28 19:14:57 +00:00
# example: time:25200
my $ buf = sprintf ( "%02d:%02d:%02d" ,
2015-03-19 20:37:01 +00:00
int ( scalar ( $ 2 ) / 3600 ) ,
int ( ( $ 2 % 3600 ) / 60 ) ,
int ( $ 2 % 60 ) ) ;
readingsBulkUpdate ( $ hash , "alarm" . $ alarmcounter . "_time" , $ buf ) ; # CD 0015
next ;
} elsif ( $ _ =~ /^(volume:)(\d{1,2})/ ) {
2017-05-28 19:14:57 +00:00
# example: volume:50
2015-03-19 20:37:01 +00:00
readingsBulkUpdate ( $ hash , "alarm" . $ alarmcounter . "_volume" , $ 2 ) ; # CD 0015
next ;
} elsif ( $ _ =~ /^(url:)(\S+)/ ) {
# CD 0015 start
my $ pn = SB_SERVER_FavoritesName2UID ( uri_unescape ( $ 2 ) ) ;
if ( defined ( $ hash - > { helper } { alarmPlaylists } )
&& defined ( $ hash - > { helper } { alarmPlaylists } { $ pn } ) ) {
readingsBulkUpdate ( $ hash , "alarm" . $ alarmcounter . "_sound" , $ hash - > { helper } { alarmPlaylists } { $ pn } { title } ) ;
} else {
readingsBulkUpdate ( $ hash , "alarm" . $ alarmcounter . "_sound" , $ 2 ) ;
}
# CD 0015 end
next ;
# CD 0016 start
} elsif ( $ _ =~ /^(filter:)(\S+)/ ) {
next ;
# CD 0016 end
# MM 0016 start
} elsif ( $ _ =~ /^(tags:)(\S+)/ ) {
next ;
2017-07-26 19:25:07 +00:00
} elsif ( $ _ =~ /^(fade:)([0-9]+)/ ) { # CD 0082 playerpref alarmfadeseconds unterst<73> tzen
2017-05-28 19:14:57 +00:00
# example: fade:1
2017-07-26 19:25:07 +00:00
if ( $ 2 ne "0" ) {
2016-10-01 16:46:46 +00:00
readingsBulkUpdate ( $ hash , "alarmsFadeIn" , "on" ) ; # CD 0016 von MM <20> bernommen, Namen ge<67> ndert
2017-07-26 19:25:07 +00:00
readingsBulkUpdate ( $ hash , "alarmsFadeSeconds" , $ 2 ) ; # CD 0082
2015-03-19 20:37:01 +00:00
} else {
2016-10-01 16:46:46 +00:00
readingsBulkUpdate ( $ hash , "alarmsFadeIn" , "off" ) ; # CD 0016 von MM <20> bernommen, Namen ge<67> ndert
2015-03-19 20:37:01 +00:00
}
next ;
} elsif ( $ _ =~ /^(count:)([0-9]+)/ ) {
$ hash - > { helper } { ALARMSCOUNT } = $ 2 ; # CD 0016 ALARMSCOUNT nach {helper} verschoben
next ;
} else {
2017-07-26 19:25:07 +00:00
Log3 ( $ hash , 2 , "SB_PLAYER_Alarms($name): Unknown data ($_)" ) ;
2015-03-19 20:37:01 +00:00
next ;
}
# MM 0016 end
2014-02-20 23:34:51 +00:00
}
2016-10-01 16:46:46 +00:00
# CD 0015 nicht mehr vorhandene Alarme l<> schen
2015-03-19 20:37:01 +00:00
if ( $ lastAlarmCount > $ hash - > { helper } { ALARMSCOUNT } ) { # CD 0016 ALARMSCOUNT nach {helper} verschoben
for ( my $ i = $ hash - > { helper } { ALARMSCOUNT } + 1 ; $ i <= $ lastAlarmCount ; $ i + + ) { # CD 0016 ALARMSCOUNT nach {helper} verschoben
fhem ( "deletereading $name alarm" . $ i . "_.*" ) ;
}
2014-02-20 23:34:51 +00:00
}
}
2015-11-02 08:26:30 +00:00
# CD 0046 start
# ----------------------------------------------------------------------------
# search for LMS alarm id, return FHEM alarm number
# ----------------------------------------------------------------------------
sub SB_PLAYER_FindAlarmId ( $$ ) {
my ( $ hash , $ id ) = @ _ ;
my $ name = $ hash - > { NAME } ;
2014-02-20 23:34:51 +00:00
2015-11-02 08:26:30 +00:00
my $ n = 0 ;
for ( my $ i = 0 ; $ i <=$hash-> { helper } { ALARMSCOUNT } ; $ i + + ) {
if ( ReadingsVal ( $ name , "alarm" . $ i . "_id" , "xxxx" ) eq $ id ) {
$ n = $ i ;
last ;
}
}
return $ n ;
}
# CD 0046
2014-02-20 23:34:51 +00:00
# ----------------------------------------------------------------------------
# used for checking, if the string contains a valid MAC adress
# ----------------------------------------------------------------------------
sub SB_PLAYER_IsValidMAC ( $ ) {
my $ instr = shift ( @ _ ) ;
my $ d = "[0-9A-Fa-f]" ;
my $ dd = "$d$d" ;
if ( $ instr =~ /($dd([:-])$dd(\2$dd){4})/og ) {
2015-04-07 19:48:18 +00:00
if ( $ instr =~ /^(00[:-]){5}(00)$/ ) { # CD 0032 00:00:00:00:00:00 is not a valid MAC
return ( 0 ) ;
} else {
2015-03-19 20:37:01 +00:00
return ( 1 ) ;
2015-04-07 19:48:18 +00:00
}
2014-02-20 23:34:51 +00:00
} else {
2015-03-19 20:37:01 +00:00
return ( 0 ) ;
2014-02-20 23:34:51 +00:00
}
}
# ----------------------------------------------------------------------------
# used to turn on our server
# ----------------------------------------------------------------------------
sub SB_PLAYER_ServerTurnOn ( $ ) {
my ( $ hash ) = @ _ ;
my $ name = $ hash - > { NAME } ;
my $ servername ;
Log3 ( $ hash , 5 , "SB_PLAYER_ServerTurnOn($name): please implement me" ) ;
2017-05-28 19:14:57 +00:00
2014-02-20 23:34:51 +00:00
return ;
fhem ( "set $servername on" ) ;
}
2014-07-09 22:29:45 +00:00
# ----------------------------------------------------------------------------
# used to turn on a connected amplifier
# ----------------------------------------------------------------------------
2015-03-19 20:37:01 +00:00
# CD 0012 start
2016-10-01 16:46:46 +00:00
sub SB_PLAYER_tcb_DelayAmplifier ( $ ) { # CD 0014 Name ge<67> ndert
2015-03-19 20:37:01 +00:00
my ( $ in ) = shift ;
my ( undef , $ name ) = split ( ':' , $ in ) ;
my $ hash = $ defs { $ name } ;
#Log 0,"SB_PLAYER_DelayAmplifier";
$ hash - > { helper } { AMPLIFIERDELAYOFF } = 1 ;
SB_PLAYER_Amplifier ( $ hash ) ;
}
# CD 0012 end
2014-07-09 22:29:45 +00:00
sub SB_PLAYER_Amplifier ( $ ) {
my ( $ hash ) = @ _ ;
my $ name = $ hash - > { NAME } ;
2017-05-28 19:14:57 +00:00
if ( ( $ hash - > { AMPLIFIER } eq "none" ) ||
2015-03-19 20:37:01 +00:00
( ! defined ( $ defs { $ hash - > { AMPLIFIER } } ) ) ) {
2014-11-09 18:01:21 +00:00
# amplifier not specified
2015-03-19 20:37:01 +00:00
delete ( $ hash - > { helper } { AMPLIFIERDELAYOFF } ) if defined ( $ hash - > { helper } { AMPLIFIERDELAYOFF } ) ; # CD 0012
2014-11-09 18:01:21 +00:00
return ;
2014-07-09 22:29:45 +00:00
}
my $ setvalue = "off" ;
2015-11-02 08:26:30 +00:00
my $ delayAmp = 0.01 ; # CD 0043
2017-05-28 19:14:57 +00:00
2014-07-09 22:29:45 +00:00
Log3 ( $ hash , 4 , "SB_PLAYER_Amplifier($name): called" ) ;
if ( AttrVal ( $ name , "amplifier" , "play" ) eq "play" ) {
2014-11-09 18:01:21 +00:00
my $ thestatus = ReadingsVal ( $ name , "playStatus" , "pause" ) ;
2015-03-19 20:37:01 +00:00
2017-05-28 19:14:57 +00:00
Log3 ( $ hash , 5 , "SB_PLAYER_Amplifier($name): with mode play " .
2015-03-19 20:37:01 +00:00
"and status:$thestatus" ) ;
2015-11-02 08:26:30 +00:00
if ( ( $ thestatus eq "playing" ) || ( ( $ thestatus eq "paused" ) && ( $ hash - > { helper } { amplifierDelayOffPause } == 0 ) ) ) { # CD 0043 DelayOffPause abfragen
2014-11-09 18:01:21 +00:00
$ setvalue = "on" ;
2015-11-02 08:26:30 +00:00
# CD 0043 start
} elsif ( ( $ thestatus eq "paused" ) && ( $ hash - > { helper } { amplifierDelayOffPause } > 0 ) ) {
$ setvalue = "off" ;
$ delayAmp = $ hash - > { helper } { amplifierDelayOffPause } ;
# CD 0043 end
2015-03-19 20:37:01 +00:00
} elsif ( $ thestatus eq "stopped" ) {
2014-11-09 18:01:21 +00:00
$ setvalue = "off" ;
2015-11-02 08:26:30 +00:00
$ delayAmp = $ hash - > { helper } { amplifierDelayOffStop } ; # CD 0043
2017-05-28 19:14:57 +00:00
} else {
2014-11-09 18:01:21 +00:00
$ setvalue = "off" ;
2015-03-19 20:37:01 +00:00
}
2014-07-09 22:29:45 +00:00
} elsif ( AttrVal ( $ name , "amplifier" , "on" ) eq "on" ) {
2015-03-19 20:37:01 +00:00
my $ thestatus = ReadingsVal ( $ name , "power" , "off" ) ;
2017-05-28 19:14:57 +00:00
Log3 ( $ hash , 5 , "SB_PLAYER_Amplifier($name): with mode on " .
2015-03-19 20:37:01 +00:00
"and status:$thestatus" ) ;
if ( $ thestatus eq "on" ) {
2014-11-09 18:01:21 +00:00
$ setvalue = "on" ;
} else {
$ setvalue = "off" ;
2015-11-02 08:26:30 +00:00
$ delayAmp = $ hash - > { helper } { amplifierDelayOffPower } ; # CD 0043
2015-03-19 20:37:01 +00:00
}
2014-07-09 22:29:45 +00:00
} else {
2015-03-19 20:37:01 +00:00
Log3 ( $ hash , 1 , "SB_PLAYER_Amplifier($name): ATTR amplifier " .
2014-11-09 18:01:21 +00:00
"set to wrong value [on|play]" ) ;
2015-03-19 20:37:01 +00:00
return ;
2014-07-09 22:29:45 +00:00
}
2014-11-09 18:01:21 +00:00
my $ actualState = ReadingsVal ( "$hash->{AMPLIFIER}" , "state" , "off" ) ;
2014-07-09 22:29:45 +00:00
2017-05-28 19:14:57 +00:00
Log3 ( $ hash , 5 , "SB_PLAYER_Amplifier($name): actual:$actualState " .
2015-03-19 20:37:01 +00:00
"and set:$setvalue" ) ;
2014-11-09 18:01:21 +00:00
if ( $ actualState ne $ setvalue ) {
2016-10-01 16:46:46 +00:00
# CD 0012 start - Abschalten <20> ber Attribut verz<72> gern, generell verz<72> gern damit set-Event funktioniert
2015-11-02 08:26:30 +00:00
# my $delayAmp=($setvalue eq "off")?AttrVal( $name, "amplifierDelayOff", 0 ):0.1; # CD 0043 deaktiviert, wird oben behandelt
2015-03-19 20:37:01 +00:00
$ delayAmp = 0.01 if ( $ delayAmp == 0 ) ;
if ( ! defined ( $ hash - > { helper } { AMPLIFIERDELAYOFF } ) ) {
2016-10-01 16:46:46 +00:00
# CD 0043 Timer nicht neu starten wenn Zustand sich nicht ge<67> ndert hat
2015-11-02 08:26:30 +00:00
if ( ( ! defined ( $ hash - > { helper } { AMPLIFIERACTIVETIMER } ) ) || ( $ hash - > { helper } { AMPLIFIERACTIVETIMER } ne ( $ actualState . $ setvalue ) ) ) {
Log3 ( $ hash , 5 , "SB_PLAYER_Amplifier($name): delaying amplifier on/off by $delayAmp" ) ;
RemoveInternalTimer ( "DelayAmplifier:$name" ) ;
2017-05-28 19:14:57 +00:00
InternalTimer ( gettimeofday ( ) + $ delayAmp ,
2016-10-01 16:46:46 +00:00
"SB_PLAYER_tcb_DelayAmplifier" , # CD 0014 Name ge<67> ndert
2017-05-28 19:14:57 +00:00
"DelayAmplifier:$name" ,
2015-11-02 08:26:30 +00:00
0 ) ;
$ hash - > { helper } { AMPLIFIERACTIVETIMER } = $ actualState . $ setvalue ; # CD 0043
} else {
Log3 ( $ hash , 5 , "SB_PLAYER_Amplifier($name): delay already active" ) ;
}
2015-03-19 20:37:01 +00:00
return ;
}
# CD 0012 end
fhem ( "set $hash->{AMPLIFIER} $setvalue" ) ;
2017-05-28 19:14:57 +00:00
Log3 ( $ hash , 5 , "SB_PLAYER_Amplifier($name): amplifier changed to " .
2015-03-19 20:37:01 +00:00
$ setvalue ) ;
2014-11-09 18:01:21 +00:00
} else {
2017-05-28 19:14:57 +00:00
Log3 ( $ hash , 5 , "SB_PLAYER_Amplifier($name): no amplifier " .
2015-03-19 20:37:01 +00:00
"state change" ) ;
2014-11-09 18:01:21 +00:00
}
2015-03-19 20:37:01 +00:00
delete ( $ hash - > { helper } { AMPLIFIERDELAYOFF } ) if ( defined ( $ hash - > { helper } { AMPLIFIERDELAYOFF } ) ) ;
2015-11-02 08:26:30 +00:00
delete ( $ hash - > { helper } { AMPLIFIERACTIVETIMER } ) if ( defined ( $ hash - > { helper } { AMPLIFIERACTIVETIMER } ) ) ; # CD 0043
2014-07-09 22:29:45 +00:00
2014-11-09 18:01:21 +00:00
return ;
2014-07-09 22:29:45 +00:00
}
2014-11-09 18:01:21 +00:00
2014-07-09 22:29:45 +00:00
# ----------------------------------------------------------------------------
# update the coverart image
# ----------------------------------------------------------------------------
sub SB_PLAYER_CoverArt ( $ ) {
my ( $ hash ) = @ _ ;
my $ name = $ hash - > { NAME } ;
2015-03-19 20:37:01 +00:00
# return if (defined($hash->{helper}{CoverOk}) && ($hash->{helper}{CoverOk} == 1) && ( $hash->{ISREMOTESTREAM} eq "0" )); # CD 0026 added # CD 0027 removed
2017-05-28 19:14:57 +00:00
# CD 0003 fix missing server
2015-03-19 20:37:01 +00:00
if ( ! defined ( $ hash - > { SBSERVER } ) || ( $ hash - > { SBSERVER } eq '?' ) ) {
if ( ( defined ( $ hash - > { IODev } ) ) && ( defined ( $ hash - > { IODev } - > { IP } ) ) ) {
$ hash - > { SBSERVER } = $ hash - > { IODev } - > { IP } . ":" . AttrVal ( $ hash - > { IODev } , "httpport" , "9000" ) ;
}
}
# CD 0003 end
2014-07-09 22:29:45 +00:00
2015-03-19 20:37:01 +00:00
my $ lastCoverartUrl = $ hash - > { COVERARTURL } ; # CD 0013
2017-05-28 19:14:57 +00:00
2015-03-19 20:37:01 +00:00
# compile the link to the album cover
if ( ( $ hash - > { ISREMOTESTREAM } eq "0" ) || ( $ hash - > { ARTWORKURL } =~ /imageproxy%2F/ ) ) { # CD 0026 LMS 7.8/7.9
2017-05-28 19:14:57 +00:00
$ hash - > { COVERARTURL } = "http://" . $ hash - > { SBSERVER } . "/music/" .
"current/cover_" . AttrVal ( $ name , "coverartheight" , 50 ) .
"x" . AttrVal ( $ name , "coverartwidth" , 50 ) .
".jpg?player=$hash->{PLAYERMAC}&x=" . int ( rand ( 100000 ) ) ; # CD 0025 added rand() to force browser refresh
2015-03-19 20:37:01 +00:00
$ hash - > { helper } { CoverOk } = 1 ; # CD 0026 added
} elsif ( $ hash - > { ISREMOTESTREAM } eq "1" ) { # CD 0017 Abfrage || ( $hash->{ISREMOTESTREAM} == 1 ) entfernt
2016-10-01 16:46:46 +00:00
# CD 0011 <20> berpr<70> fen ob <20> berhaupt eine URL vorhanden ist
2015-03-19 20:37:01 +00:00
if ( $ hash - > { ARTWORKURL } ne "?" ) {
2016-10-01 16:46:46 +00:00
# CD 0034 Abfrage f<> r Spotify und LMS < 7.8, ungetest, #674, KernSani
# CD 0035 Code von KernSani <20> bernommen, #676
2015-04-07 19:48:18 +00:00
if ( $ hash - > { ARTWORKURL } =~ /spotifyimage%2Fspotify/ ) {
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 {
2017-05-28 19:14:57 +00:00
$ hash - > { COVERARTURL } = "http://www.mysqueezebox.com/public/" .
"imageproxy?u=" . $ hash - > { ARTWORKURL } .
"&h=" . AttrVal ( $ name , "coverartheight" , 50 ) .
2015-04-07 19:48:18 +00:00
"&w=" . AttrVal ( $ name , "coverartwidth" , 50 ) ;
}
2015-03-19 20:37:01 +00:00
} else {
$ hash - > { COVERARTURL } = "http://" . $ hash - > { SBSERVER } . "/music/" .
2017-05-28 19:14:57 +00:00
$ hash - > { COVERID } . "/cover_" . AttrVal ( $ name , "coverartheight" , 50 ) .
2015-03-19 20:37:01 +00:00
"x" . AttrVal ( $ name , "coverartwidth" , 50 ) . ".jpg" ;
}
# CD 0011 Ende
2014-07-09 22:29:45 +00:00
} else {
2017-05-28 19:14:57 +00:00
$ hash - > { COVERARTURL } = "http://" . $ hash - > { SBSERVER } . "/music/" .
2015-03-19 20:37:01 +00:00
$ hash - > { COVERID } . "/cover_" . AttrVal ( $ name , "coverartheight" , 50 ) . # CD 0011 -160206228 durch $hash->{COVERID} ersetzt
"x" . AttrVal ( $ name , "coverartwidth" , 50 ) . ".jpg" ;
2014-07-09 22:29:45 +00:00
}
2015-03-19 20:37:01 +00:00
# CD 0004, url as reading
readingsBulkUpdate ( $ hash , "coverarturl" , $ hash - > { COVERARTURL } ) ;
2017-05-28 19:14:57 +00:00
if ( ( $ hash - > { COVERARTLINK } eq "none" ) ||
( ! defined ( $ defs { $ hash - > { COVERARTLINK } } ) ) ||
2015-03-19 20:37:01 +00:00
( $ hash - > { COVERARTURL } eq "?" ) ) {
# weblink not specified
return ;
2014-07-09 22:29:45 +00:00
} else {
2016-10-01 16:46:46 +00:00
if ( $ lastCoverartUrl ne $ hash - > { COVERARTURL } ) { # CD 0013 nur bei <20> nderung aktualisieren
2017-05-28 19:14:57 +00:00
fhem ( "modify " . $ hash - > { COVERARTLINK } . " image " .
2015-03-19 20:37:01 +00:00
$ hash - > { COVERARTURL } ) ;
} # CD 0013
2014-07-09 22:29:45 +00:00
}
}
2014-07-23 06:22:52 +00:00
2014-07-06 22:14:26 +00:00
# ----------------------------------------------------------------------------
# Handle the return for a playerstatus query
# ----------------------------------------------------------------------------
2015-03-19 20:37:01 +00:00
sub SB_PLAYER_ParsePlayerStatus ( $$ ) {
2014-07-06 22:14:26 +00:00
my ( $ hash , $ dataptr ) = @ _ ;
2017-05-28 19:14:57 +00:00
2014-07-06 22:14:26 +00:00
my $ name = $ hash - > { NAME } ;
2015-03-19 20:37:01 +00:00
my $ leftover = "" ;
my $ cur = "" ;
my $ playlistIds = "" ; # CD 0014
my $ refreshIds = 0 ; # CD 0014
2015-06-18 20:23:54 +00:00
2014-07-06 22:14:26 +00:00
# typically the start index being a number
if ( $ dataptr - > [ 0 ] =~ /^([0-9])*/ ) {
2015-03-19 20:37:01 +00:00
shift ( @ { $ dataptr } ) ;
2014-07-06 22:14:26 +00:00
} else {
2015-03-19 20:37:01 +00:00
Log3 ( $ hash , 5 , "SB_PLAYER_ParsePlayerStatus($name): entry is " .
"not the start number" ) ;
return ;
2014-07-06 22:14:26 +00:00
}
# typically the max index being a number
if ( $ dataptr - > [ 0 ] =~ /^([0-9])*/ ) {
2015-03-19 20:37:01 +00:00
if ( $ dataptr - > [ 0 ] > 1 ) {
$ refreshIds = 1 ; # CD 0014
delete ( $ hash - > { helper } { playlistUrls } ) if ( defined ( $ hash - > { helper } { playlistUrls } ) ) ; # CD 0030
}
shift ( @ { $ dataptr } ) ;
2014-07-06 22:14:26 +00:00
} else {
2015-03-19 20:37:01 +00:00
Log3 ( $ hash , 5 , "SB_PLAYER_ParsePlayerStatus($name): entry is " .
"not the end number" ) ;
return ;
2014-07-06 22:14:26 +00:00
}
my $ datastr = join ( " " , @ { $ dataptr } ) ;
# replace funny stuff
2015-03-19 20:37:01 +00:00
# CD 0006 all keywords with spaces must be converted here
2014-07-06 22:14:26 +00:00
$ datastr =~ s/mixer volume/mixervolume/g ;
2015-03-19 20:37:01 +00:00
# CD 0006 replaced mixertreble with mixer treble
$ datastr =~ s/mixer treble/mixertreble/g ;
2014-07-06 22:14:26 +00:00
$ datastr =~ s/mixer bass/mixerbass/g ;
$ datastr =~ s/mixer pitch/mixerpitch/g ;
$ datastr =~ s/playlist repeat/playlistrepeat/g ;
$ datastr =~ s/playlist shuffle/playlistshuffle/g ;
$ datastr =~ s/playlist index/playlistindex/g ;
2015-03-19 20:37:01 +00:00
# CD 0003
$ datastr =~ s/playlist mode/playlistmode/g ;
2014-07-06 22:14:26 +00:00
2015-03-19 20:37:01 +00:00
Log3 ( $ hash , 5 , "SB_PLAYER_ParsePlayerStatus($name): data to parse: " .
$ datastr ) ;
2014-07-06 22:14:26 +00:00
my @ data1 = split ( " " , $ datastr ) ;
# the rest of the array should now have the data, we're interested in
2015-03-19 20:37:01 +00:00
# CD 0006 - deaktiviert, SB_PLAYER_ParsePlayerStatus kann nur von SB_PLAYER_Parse aufgerufen werden, dort ist readingsBeginUpdate aber bereits aktiv
#readingsBeginUpdate( $hash );
2014-07-06 22:14:26 +00:00
# set default values for stuff not always send
2016-10-01 16:46:46 +00:00
my $ oldsyncmaster = $ hash - > { SYNCMASTER } ; # CD 0056
2017-05-28 19:14:57 +00:00
my $ oldsyncgroup = "" ;
$ oldsyncgroup = $ hash - > { SYNCGROUP } if defined ( $ hash - > { SYNCGROUP } ) ; # CD 0065
2014-07-06 22:14:26 +00:00
$ hash - > { SYNCMASTER } = "none" ;
$ hash - > { SYNCGROUP } = "none" ;
2015-03-19 20:37:01 +00:00
$ hash - > { SYNCMASTERPN } = "none" ; # CD 0018
$ hash - > { SYNCGROUPPN } = "none" ; # CD 0018
2014-07-06 22:14:26 +00:00
$ hash - > { SYNCED } = "no" ;
2014-07-09 22:29:45 +00:00
$ hash - > { COVERID } = "?" ;
$ hash - > { ARTWORKURL } = "?" ;
$ hash - > { ISREMOTESTREAM } = "0" ;
2014-07-06 22:14:26 +00:00
# needed for scanning the MAC Adress
my $ d = "[0-9A-Fa-f]" ;
my $ dd = "$d$d" ;
# needed for scanning the IP adress
my $ e = "[0-9]" ;
my $ ee = "$e$e" ;
2015-03-19 20:37:01 +00:00
# CD 0003 start, fix handling of spaces
my @ data2 ;
my $ last_d = "" ;
2014-07-06 22:14:26 +00:00
# loop through the results
foreach ( @ data1 ) {
2015-03-19 20:37:01 +00:00
if ( index ( $ _ , ":" ) < 2 ) {
$ last_d = $ last_d . " " . $ _ ;
next ;
}
2014-07-09 22:29:45 +00:00
2015-03-19 20:37:01 +00:00
if ( $ last_d ne "" ) {
push @ data2 , $ last_d ;
}
$ last_d = $ _ ;
}
if ( $ last_d ne "" ) {
push @ data2 , $ last_d ;
}
# CD 0003 end
2017-05-28 19:14:57 +00:00
2015-03-19 20:37:01 +00:00
my $ lastId = 0 ; # CD 0030
2017-05-28 19:14:57 +00:00
2015-03-19 20:37:01 +00:00
# loop through the results
foreach ( @ data2 ) {
my $ cur = $ _ ;
if ( $ cur =~ /^(player_connected:)([0-9]*)/ ) {
if ( $ 2 == "1" ) {
readingsBulkUpdate ( $ hash , "connected" , $ 2 ) ;
readingsBulkUpdate ( $ hash , "presence" , "present" ) ;
} else {
readingsBulkUpdate ( $ hash , "connected" , $ 3 ) ;
readingsBulkUpdate ( $ hash , "presence" , "absent" ) ;
}
next ;
} elsif ( $ cur =~ /^(player_ip:)(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{3,5})/ ) {
if ( $ hash - > { PLAYERIP } ne "?" ) {
$ hash - > { PLAYERIP } = $ 2 ;
}
next ;
} elsif ( $ cur =~ /^(player_name:)(.*)/ ) {
if ( $ hash - > { PLAYERNAME } ne "?" ) {
$ hash - > { PLAYERNAME } = $ 2 ;
}
next ;
} elsif ( $ cur =~ /^(power:)([0-9\.]*)/ ) {
if ( $ 2 eq "1" ) {
2017-06-22 20:47:42 +00:00
if ( ReadingsVal ( $ name , 'presence' , 'absent' ) eq 'present' ) { # CD 0079 power nur auf 1 setzen wenn Player verbunden ist
readingsBulkUpdate ( $ hash , "state" , "on" ) ; # CD 0041 hinzugef<65> gt
readingsBulkUpdate ( $ hash , "power" , "on" ) ;
SB_PLAYER_Amplifier ( $ hash ) ;
# CD 0042 start
if ( $ hash - > { helper } { ttsstate } == TTS_WAITFORPOWERON ) {
RemoveInternalTimer ( "TTSStartAfterPowerOn:$name" ) ;
InternalTimer ( gettimeofday ( ) + 0.01 ,
"SB_PLAYER_tcb_TTSStartAfterPowerOn" ,
"TTSStartAfterPowerOn:$name" ,
0 ) ;
}
# CD 0042 end
2015-06-18 20:23:54 +00:00
}
2015-03-19 20:37:01 +00:00
} else {
2015-06-18 20:23:54 +00:00
# CD 0042 start
if ( ( $ hash - > { helper } { playerStatusOK } == 0 ) && ( $ hash - > { helper } { ttsstate } == TTS_WAITFORPOWERON ) ) {
$ hash - > { helper } { ttsPowerWasOff } = 1 ;
IOWrite ( $ hash , "$hash->{PLAYERMAC} power 1\n" ) ;
}
# CD 0042 end
2016-10-01 16:46:46 +00:00
readingsBulkUpdate ( $ hash , "state" , "off" ) ; # CD 0041 hinzugef<65> gt
2015-03-19 20:37:01 +00:00
readingsBulkUpdate ( $ hash , "power" , "off" ) ;
SB_PLAYER_Amplifier ( $ hash ) ;
}
next ;
} elsif ( $ cur =~ /^(signalstrength:)([0-9\.]*)/ ) {
if ( $ 2 eq "0" ) {
readingsBulkUpdate ( $ hash , "signalstrength" , "wired" ) ;
} else {
readingsBulkUpdate ( $ hash , "signalstrength" , "$2" ) ;
}
next ;
} elsif ( $ cur =~ /^(mode:)(.*)/ ) {
if ( $ 2 eq "play" ) {
readingsBulkUpdate ( $ hash , "playStatus" , "playing" ) ;
SB_PLAYER_Amplifier ( $ hash ) ;
} elsif ( $ 2 eq "stop" ) {
readingsBulkUpdate ( $ hash , "playStatus" , "stopped" ) ;
SB_PLAYER_Amplifier ( $ hash ) ;
} elsif ( $ 2 eq "pause" ) {
readingsBulkUpdate ( $ hash , "playStatus" , "paused" ) ;
SB_PLAYER_Amplifier ( $ hash ) ;
} else {
# unkown
}
next ;
} elsif ( $ cur =~ /^(sync_master:)($dd[:|-]$dd[:|-]$dd[:|-]$dd[:|-]$dd[:|-]$dd)/ ) {
2016-10-01 16:46:46 +00:00
# CD 0056 <20> berpr<70> fen ob Syncmaster gewechselt hat (passiert z.B. bei stop->play wenn aktueller Syncmaster aus ist)
my $ sm = $ 2 ;
if ( $ oldsyncmaster ne "none" ) {
if ( $ oldsyncmaster ne $ 2 ) {
Log3 ( $ hash , defined ( $ hash - > { helper } { ttsOptions } { debug } ) ? 0 : 6 , "SB_PLAYER_ParsePlayerStatus: $name: Syncmaster changed from $oldsyncmaster to $sm" ) ;
if ( defined ( $ oldsyncgroup ) && ( $ oldsyncgroup ne '?' ) && ( $ oldsyncmaster ne 'none' ) ) {
my @ pl = split ( "," , $ oldsyncgroup . "," . $ oldsyncmaster ) ;
foreach ( @ pl ) {
if ( $ hash - > { PLAYERMAC } ne $ _ ) {
IOWrite ( $ hash , "$_ status 0 500 tags:Kcu\n" ) ;
}
}
2017-05-28 19:14:57 +00:00
}
2016-10-01 16:46:46 +00:00
}
}
# CD 0056 end
$ hash - > { SYNCMASTER } = $ sm ;
2015-03-19 20:37:01 +00:00
$ hash - > { SYNCED } = "yes" ;
2016-10-01 16:46:46 +00:00
$ hash - > { SYNCMASTERPN } = SB_PLAYER_MACToLMSPlayername ( $ hash , $ sm ) ; # CD 0018
2015-03-19 20:37:01 +00:00
next ;
} elsif ( $ cur =~ /^(sync_slaves:)(.*)/ ) {
$ hash - > { SYNCGROUP } = $ 2 ;
# CD 0018 start
my @ macs = split ( "," , $ hash - > { SYNCGROUP } ) ;
my $ syncgroup ;
foreach ( @ macs ) {
my $ mac = $ _ ;
2016-10-01 16:46:46 +00:00
my $ dev = SB_PLAYER_MACToLMSPlayername ( $ hash , $ mac ) ;
2015-03-19 20:37:01 +00:00
$ syncgroup . = "," if ( defined ( $ syncgroup ) ) ;
if ( defined ( $ dev ) ) {
$ syncgroup . = $ dev ;
} else {
if ( $ mac eq $ hash - > { PLAYERMAC } ) {
2016-10-01 16:46:46 +00:00
$ syncgroup . = $ hash - > { PLAYERNAME } ; # CD 0055 FIX: PLAYERNAME verwenden
2015-03-19 20:37:01 +00:00
} else {
$ syncgroup . = $ mac ;
}
}
}
$ hash - > { SYNCGROUPPN } = $ syncgroup ;
# CD 0018 end
2016-10-01 16:46:46 +00:00
# CD 0055 start
if ( AttrVal ( $ name , "syncedNamesSource" , "LMS" ) eq "FHEM" ) {
my @ pn = split ',' , "$hash->{SYNCMASTERPN},$hash->{SYNCGROUPPN}" ;
my @ players = devspec2array ( "TYPE=SB_PLAYER" ) ;
$ syncgroup = undef ;
2017-05-28 19:14:57 +00:00
foreach my $ lmsn ( @ pn ) { # CD 0067
foreach ( @ players ) {
my $ pn = $ _ ;
my $ phash = $ defs { $ _ } ;
if ( $ phash - > { PLAYERNAME } eq $ lmsn ) { # CD 0067
$ syncgroup . = "," if ( defined ( $ syncgroup ) ) ;
$ syncgroup . = $ pn ;
last ;
}
2016-10-01 16:46:46 +00:00
}
}
readingsBulkUpdate ( $ hash , "synced" , $ syncgroup ) ;
} else {
# CD 0055 end
readingsBulkUpdate ( $ hash , "synced" , "$hash->{SYNCMASTERPN},$hash->{SYNCGROUPPN}" ) ; # Matthew 0019 hinzugef<65> gt
}
2015-03-19 20:37:01 +00:00
next ;
} elsif ( $ cur =~ /^(will_sleep_in:)([0-9\.]*)/ ) {
$ hash - > { WILLSLEEPIN } = "$2 secs" ;
next ;
} elsif ( $ cur =~ /^(mixervolume:)(.*)/ ) {
if ( ( index ( $ 2 , "+" ) != - 1 ) || ( index ( $ 2 , "-" ) != - 1 ) ) {
# that was a relative value. We do nothing and fire an update
IOWrite ( $ hash , "$hash->{PLAYERMAC} mixer volume ?\n" ) ;
} else {
SB_PLAYER_UpdateVolumeReadings ( $ hash , $ 2 , true ) ;
# CD 0007 start
if ( ( defined ( $ hash - > { helper } { setSyncVolume } ) && ( $ hash - > { helper } { setSyncVolume } != $ 2 ) ) || ( ! defined ( $ hash - > { helper } { setSyncVolume } ) ) ) {
2017-05-28 19:14:57 +00:00
SB_PLAYER_SetSyncedVolume ( $ hash , $ 2 , 0 ) ;
2015-03-19 20:37:01 +00:00
}
delete $ hash - > { helper } { setSyncVolume } ;
# CD 0007 end
}
next ;
} elsif ( $ cur =~ /^(playlistshuffle:)(.*)/ ) {
if ( $ 2 eq "0" ) {
readingsBulkUpdate ( $ hash , "shuffle" , "off" ) ;
} elsif ( $ 2 eq "1" ) {
readingsBulkUpdate ( $ hash , "shuffle" , "song" ) ;
} elsif ( $ 2 eq "2" ) {
readingsBulkUpdate ( $ hash , "shuffle" , "album" ) ;
} else {
readingsBulkUpdate ( $ hash , "shuffle" , "?" ) ;
}
next ;
} elsif ( $ cur =~ /^(playlistrepeat:)(.*)/ ) {
if ( $ 2 eq "0" ) {
readingsBulkUpdate ( $ hash , "repeat" , "off" ) ;
} elsif ( $ 2 eq "1" ) {
readingsBulkUpdate ( $ hash , "repeat" , "one" ) ;
} elsif ( $ 2 eq "2" ) {
readingsBulkUpdate ( $ hash , "repeat" , "all" ) ;
} else {
readingsBulkUpdate ( $ hash , "repeat" , "?" ) ;
}
next ;
} elsif ( $ cur =~ /^(playlistname:)(.*)/ ) {
readingsBulkUpdate ( $ hash , "currentPlaylistName" , $ 2 ) ;
next ;
} elsif ( $ cur =~ /^(artwork_url:)(.*)/ ) {
$ hash - > { ARTWORKURL } = uri_escape ( $ 2 ) ;
#Log 0,"Update Artwork: ".$hash->{ARTWORKURL};
#SB_PLAYER_CoverArt( $hash );
next ;
} elsif ( $ cur =~ /^(coverid:)(.*)/ ) {
$ hash - > { COVERID } = $ 2 ;
next ;
} elsif ( $ cur =~ /^(remote:)(.*)/ ) {
$ hash - > { ISREMOTESTREAM } = $ 2 ;
next ;
# CD 0014 start
} elsif ( $ cur =~ /^(duration:)(.*)/ ) {
readingsBulkUpdate ( $ hash , "duration" , $ 2 ) ;
next ;
} elsif ( $ cur =~ /^(time:)(.*)/ ) {
$ hash - > { helper } { elapsedTime } { VAL } = $ 2 ;
$ hash - > { helper } { elapsedTime } { TS } = gettimeofday ( ) ;
delete ( $ hash - > { helper } { saveLocked } ) if ( ( $ hash - > { helper } { ttsstate } == TTS_IDLE ) && defined ( $ hash - > { helper } { saveLocked } ) ) ;
2017-05-28 19:14:57 +00:00
readingsBulkUpdate ( $ hash , "currentTrackPosition" , int ( $ 2 + 0.5 ) ) ; # CD 0047
2015-03-19 20:37:01 +00:00
next ;
} elsif ( $ cur =~ /^(playlist_tracks:)(.*)/ ) {
readingsBulkUpdate ( $ hash , "playlistTracks" , $ 2 ) ;
2017-05-28 19:14:57 +00:00
$ hash - > { helper } { playlistIds } = '0' if ( $ 2 == 0 ) ; # CD 0071 wenn playlist leer ist internen Zustand zur<75> cksetzen
2015-03-19 20:37:01 +00:00
next ;
} elsif ( $ cur =~ /^(playlist_cur_index:)(.*)/ ) {
readingsBulkUpdate ( $ hash , "playlistCurrentTrack" , $ 2 + 1 ) ;
next ;
} elsif ( $ cur =~ /^(id:)(.*)/ ) {
if ( $ refreshIds == 1 ) {
if ( $ playlistIds ) {
$ playlistIds = $ playlistIds . ",$2" ;
} else {
$ playlistIds = $ 2 ;
}
$ hash - > { helper } { playlistIds } = $ playlistIds ;
}
$ lastId = $ 2 ; # CD 0030
next ;
# CD 0030 start
} elsif ( $ cur =~ /^(url:)(.*)/ ) {
if ( $ refreshIds == 1 ) {
if ( $ lastId < 0 ) {
$ hash - > { helper } { playlistUrls } { $ lastId } = $ 2 ;
}
}
next ;
# CD 0030 end
# CD 0014 end
} else {
next ;
}
}
2015-06-18 20:23:54 +00:00
$ hash - > { helper } { playerStatusOK } = 1 ; # CD 0042
2017-05-28 19:14:57 +00:00
# CD 0065 start
2017-08-26 19:46:07 +00:00
if ( defined ( $ hash - > { helper } { ftuiSupport } { medialist } ) ) {
2017-05-28 19:14:57 +00:00
delete ( $ hash - > { SONGINFOQUEUE } ) if ( defined ( $ hash - > { SONGINFOQUEUE } ) ) ; # CD 0072
2017-08-26 19:46:07 +00:00
$ hash - > { helper } { songinfoquery } = '' ; # CD 0084
$ hash - > { helper } { songinfocounter } = 0 ; # CD 0084
$ hash - > { helper } { songinfopending } = 0 ; # CD 0084
2017-05-28 19:14:57 +00:00
if ( defined ( $ hash - > { helper } { playlistIds } ) ) {
$ hash - > { helper } { playlistInfoRetries } = 5 ; # CD 0076
my @ ids = split ( ',' , $ hash - > { helper } { playlistIds } ) ;
foreach ( @ ids ) {
2017-08-26 19:46:07 +00:00
# SB_PLAYER_SonginfoAddQueue($hash,$_,0) unless ($_==0); # CD 0083
SB_PLAYER_SonginfoAddQueue ( $ hash , $ _ , 0 ) unless ( ( defined ( $ hash - > { helper } { playlistInfo } { $ _ } ) && ! defined ( $ hash - > { helper } { playlistInfo } { $ _ } { remote } ) ) || ( $ _ == 0 ) ) ; # CD 0084
2017-05-28 19:14:57 +00:00
}
2017-08-26 19:46:07 +00:00
SB_PLAYER_SonginfoAddQueue ( $ hash , 0 , 0 ) ;
2017-05-28 19:14:57 +00:00
}
}
# CD 0065 end
2015-03-19 20:37:01 +00:00
# Matthew 0019 start
if ( $ hash - > { SYNCED } ne "yes" ) {
readingsBulkUpdate ( $ hash , "synced" , "none" ) ;
}
# Matthew 0019 end
# CD 0003 moved before readingsEndUpdate
2014-07-09 22:29:45 +00:00
# update the cover art
SB_PLAYER_CoverArt ( $ hash ) ;
2015-03-19 20:37:01 +00:00
# CD 0006 - deaktiviert, SB_PLAYER_ParsePlayerStatus kann nur von SB_PLAYER_Parse aufgerufen werden, dort ist readingsBeginUpdate aber bereits aktiv
#readingsEndUpdate( $hash, 1 );
}
# CD 0018 start
# ----------------------------------------------------------------------------
2016-10-01 16:46:46 +00:00
# convert MAC to (LMS) playername
2015-03-19 20:37:01 +00:00
# ----------------------------------------------------------------------------
2016-10-01 16:46:46 +00:00
sub SB_PLAYER_MACToLMSPlayername ( $$ ) {
2015-03-19 20:37:01 +00:00
my ( $ hash , $ mac ) = @ _ ;
my $ name = $ hash - > { NAME } ;
return $ hash - > { PLAYERNAME } if ( $ hash - > { PLAYERMAC } eq $ mac ) ;
my $ dev ;
foreach my $ e ( keys % { $ hash - > { helper } { SB_PLAYER_SyncMasters } } ) {
2016-10-01 16:46:46 +00:00
if ( defined ( $ hash - > { helper } { SB_PLAYER_SyncMasters } { $ e } { MAC } ) && ( $ mac eq $ hash - > { helper } { SB_PLAYER_SyncMasters } { $ e } { MAC } ) ) { # 0056 defined hinzugef<65> gt
2015-03-19 20:37:01 +00:00
$ dev = $ e ;
last ;
}
}
return $ dev ;
2014-07-06 22:14:26 +00:00
}
2015-03-19 20:37:01 +00:00
# CD 0018 end
2014-07-06 22:14:26 +00:00
2015-03-19 20:37:01 +00:00
# CD 0014 start
# ----------------------------------------------------------------------------
# estimate elapsed time
# ----------------------------------------------------------------------------
sub SB_PLAYER_EstimateElapsedTime ( $ ) {
my ( $ hash ) = @ _ ;
my $ name = $ hash - > { NAME } ;
my $ d = ReadingsVal ( $ name , "duration" , 0 ) ;
# nur wenn duration>0
2015-04-07 19:48:18 +00:00
if ( ( $ d ne '?' ) && ( $ d > 0 ) ) { # CD 0033 check for '?'
2015-03-19 20:37:01 +00:00
# wenn {helper}{elapsedTime} bekannt ist als Basis verwenden
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 } { TS } = gettimeofday ( ) ;
} else {
my $ dTS = time_str2num ( ReadingsTimestamp ( $ name , "duration" , 0 ) ) ;
my $ n = gettimeofday ( ) ;
if ( ( $ n - $ dTS ) <= $ d ) {
$ hash - > { helper } { elapsedTime } { VAL } = gettimeofday ( ) - $ dTS ;
$ hash - > { helper } { elapsedTime } { TS } = gettimeofday ( ) ;
} else {
$ hash - > { helper } { elapsedTime } { VAL } = $ d ;
$ hash - > { helper } { elapsedTime } { TS } = gettimeofday ( ) ;
}
}
} else {
delete ( $ hash - > { helper } { elapsedTime } ) if ( defined ( $ hash - > { helper } { elapsedTime } ) ) ;
}
}
# CD 0014 end
2014-02-20 23:34:51 +00:00
2017-05-28 19:14:57 +00:00
# CD 0065 start
# ----------------------------------------------------------------------------
# convert volume from FHEM to LMS
# ----------------------------------------------------------------------------
sub SB_PLAYER_FHEM2LMSVolume ( $$ ) {
my ( $ hash , $ fhemvol ) = @ _ ;
my $ name = $ hash - > { NAME } ;
if ( $ fhemvol =~ /[+-]+.*/ ) { return $ fhemvol } ; # CD 0069
$ fhemvol = int ( $ fhemvol ) ;
my $ offset = AttrVal ( $ name , 'volumeOffset' , 0 ) ;
my $ lmsvol = $ fhemvol + $ offset ;
$ lmsvol = 0 if ( ( $ lmsvol < 0 ) && ( $ fhemvol >= 0 ) ) ;
$ lmsvol = 100 if ( $ lmsvol > 100 ) ;
$ lmsvol = - 100 if ( $ lmsvol < - 100 ) ;
return $ lmsvol ;
}
# CD 0065 end
2014-07-23 06:22:52 +00:00
# ----------------------------------------------------------------------------
# update the volume readings
# ----------------------------------------------------------------------------
2015-03-19 20:37:01 +00:00
sub SB_PLAYER_UpdateVolumeReadings ( $$$ ) {
2014-07-23 06:22:52 +00:00
my ( $ hash , $ vol , $ bulk ) = @ _ ;
2017-05-28 19:14:57 +00:00
2014-07-23 06:22:52 +00:00
my $ name = $ hash - > { NAME } ;
2015-03-19 20:37:01 +00:00
$ vol = int ( $ vol ) ; # MM 0016, Fix wegen AirPlay-Plugin
2017-05-28 19:14:57 +00:00
# CD 0065 start
$ hash - > { helper } { lmsvolume } = $ vol ;
my $ offset = AttrVal ( $ name , 'volumeOffset' , 0 ) ;
my $ fhemvol = $ vol - $ offset ;
$ fhemvol = 0 if ( ( $ fhemvol < 0 ) && ( $ vol >= 0 ) ) ;
$ fhemvol = 100 if ( $ fhemvol > 100 ) ;
$ fhemvol = - 100 if ( $ fhemvol < - 100 ) ;
# CD 0065 end
if ( $ bulk == true ) {
readingsBulkUpdate ( $ hash , "volumeStraight" , $ fhemvol ) ; # CD 0065 $fhemvol verwenden
2015-03-19 20:37:01 +00:00
if ( $ vol > 0 ) {
2017-05-28 19:14:57 +00:00
readingsBulkUpdate ( $ hash , "volume" , $ fhemvol ) ; # CD 0065 $fhemvol verwenden
2015-03-19 20:37:01 +00:00
} else {
readingsBulkUpdate ( $ hash , "volume" , "muted" ) ;
}
2014-07-23 06:22:52 +00:00
} else {
2017-05-28 19:14:57 +00:00
readingsSingleUpdate ( $ hash , "volumeStraight" , $ fhemvol , 0 ) ; # CD 0065 $fhemvol verwenden
2015-03-19 20:37:01 +00:00
if ( $ vol > 0 ) {
2017-05-28 19:14:57 +00:00
readingsSingleUpdate ( $ hash , "volume" , $ fhemvol , 0 ) ; # CD 0065 $fhemvol verwenden
2015-03-19 20:37:01 +00:00
} else {
readingsSingleUpdate ( $ hash , "volume" , "muted" , 0 ) ;
}
2014-07-23 06:22:52 +00:00
}
return ;
}
2015-03-19 20:37:01 +00:00
# ----------------------------------------------------------------------------
# set volume of synced players
# ----------------------------------------------------------------------------
2017-05-28 19:14:57 +00:00
sub SB_PLAYER_SetSyncedVolume ( $$$ ) {
my ( $ hash , $ vol , $ isFHEMvol ) = @ _ ;
2015-03-19 20:37:01 +00:00
my $ name = $ hash - > { NAME } ;
return if ( ! defined ( $ hash - > { SYNCED } ) || ( $ hash - > { SYNCED } ne "yes" ) ) ;
my $ sva = AttrVal ( $ name , "syncVolume" , undef ) ;
my $ t = $ hash - > { SYNCGROUP } . "," . $ hash - > { SYNCMASTER } ;
2017-05-28 19:14:57 +00:00
2015-03-19 20:37:01 +00:00
$ vol = int ( $ vol ) ; # MM 0016, Fix wegen AirPlay-Plugin
$ hash - > { helper } { setSyncVolume } = $ vol ;
2017-05-28 19:14:57 +00:00
2015-03-19 20:37:01 +00:00
if ( defined ( $ sva ) && ( $ sva ne "0" ) && ( $ sva ne "1" ) ) {
my @ pl = split ( "," , $ t ) ;
my @ chlds = devspec2array ( "TYPE=SB_PLAYER" ) ;
2017-05-28 19:14:57 +00:00
# CD 0065 start
if ( $ isFHEMvol == 0 ) {
my $ fhemvol = $ vol - AttrVal ( $ name , 'volumeOffset' , 0 ) ;
$ fhemvol = 0 if ( ( $ fhemvol < 0 ) && ( $ vol >= 0 ) ) ;
$ fhemvol = 100 if ( $ fhemvol > 100 ) ;
$ fhemvol = - 100 if ( $ fhemvol < - 100 ) ;
#Log 0,$name.": convert volume from ".$vol." to ".$fhemvol;
$ vol = $ fhemvol ;
}
# CD 0065 end
2015-03-19 20:37:01 +00:00
foreach ( @ pl ) {
if ( ( $ _ ne "?" ) && ( $ _ ne $ hash - > { PLAYERMAC } ) ) {
my $ mac = $ _ ;
foreach ( @ chlds ) {
my $ chash = $ defs { $ _ } ;
if ( defined ( $ chash ) && defined ( $ chash - > { PLAYERMAC } ) && ( $ chash - > { PLAYERMAC } eq $ mac ) ) {
my $ sva2 = AttrVal ( $ chash - > { NAME } , "syncVolume" , undef ) ;
if ( defined ( $ sva2 ) && ( $ sva eq $ sva2 ) ) {
if ( $ vol > 0 ) { # CD 0010
2017-05-28 19:14:57 +00:00
if ( ReadingsVal ( $ chash - > { NAME } , "volumeStraight" , $ vol ) ne $ vol ) {
2015-03-19 20:37:01 +00:00
#Log 0,$chash->{NAME}." setting volume to ".$vol." (from ".$hash->{NAME}.")";
$ chash - > { helper } { setSyncVolume } = $ vol ;
fhem "set " . $ chash - > { NAME } . " volumeStraight " . $ vol . " x" ;
}
# CD 0010 start
} else {
if ( ReadingsVal ( $ chash - > { NAME } , "volume" , "x" ) ne "muted" ) {
#Log 0,$chash->{NAME}." muting (from ".$hash->{NAME}.")";
IOWrite ( $ chash , "$chash->{PLAYERMAC} mixer muting 1\n" ) ;
}
# CD 0010 end
}
}
}
}
}
}
}
return ;
}
2014-07-23 06:22:52 +00:00
2015-06-18 20:23:54 +00:00
# ----------------------------------------------------------------------------
# load/save player state
#
# CD 0036
# ----------------------------------------------------------------------------
sub SB_PLAYER_PlayerStatefileName ($)
{
my ( $ name ) = @ _ ;
my $ statefile = $ attr { global } { statefile } ;
$ statefile = substr $ statefile , 0 , rindex ( $ statefile , '/' ) + 1 ;
return $ statefile . "sbps_$name.dd.save" ;
2017-05-28 19:14:57 +00:00
}
2015-06-18 20:23:54 +00:00
sub SB_PLAYER_SavePlayerStates ($)
{
my ( $ hash ) = @ _ ;
my $ name = $ hash - > { NAME } ;
return "No saved playlists found" unless ( defined ( $ hash - > { helper } { savedPlayerState } ) ) ;
return "No statefile specified" if ( ! $ attr { global } { statefile } ) ;
my $ statefile = SB_PLAYER_PlayerStatefileName ( $ name ) ;
if ( open ( FH , ">$statefile" ) ) {
my $ t = localtime ;
print FH "#$t\n" ;
my $ dumper = Data::Dumper - > new ( [] ) ;
$ dumper - > Terse ( 1 ) ;
$ dumper - > Values ( [ $ hash - > { helper } { savedPlayerState } ] ) ;
print FH $ dumper - > Dump ;
close ( FH ) ;
} else {
my $ msg = "SB_PLAYER_SavePlayerStates: Cannot open $statefile: $!" ;
Log3 $ hash , 1 , $ msg ;
}
return undef ;
2017-05-28 19:14:57 +00:00
}
2015-06-18 20:23:54 +00:00
sub SB_PLAYER_LoadPlayerStates ($)
{
my ( $ hash ) = @ _ ;
my $ name = $ hash - > { NAME } ;
return "No statefile specified" if ( ! $ attr { global } { statefile } ) ;
my $ statefile = SB_PLAYER_PlayerStatefileName ( $ name ) ;
if ( open ( FH , "<$statefile" ) ) {
my $ encoded ;
while ( my $ line = <FH> ) {
chomp $ line ;
next if ( $ line =~ m/^#.*$/ ) ;
$ encoded . = $ line ;
}
close ( FH ) ;
return if ( ! defined ( $ encoded ) ) ;
my $ decoded = eval $ encoded ;
$ hash - > { helper } { savedPlayerState } = $ decoded ;
} else {
my $ msg = "SB_PLAYER_LoadPlayerStates: no playlists file found" ;
Log3 undef , 4 , $ msg ;
}
return undef ;
2017-05-28 19:14:57 +00:00
}
# CD 0072 start
sub
SB_PLAYER_SonginfoAddQueue ( $$ $ ) ##################################################
{
my ( $ hash , $ id , $ wait ) = @ _ ;
my $ name = $ hash - > { NAME } ;
if ( ! $ hash - > { SONGINFOQUEUE } ) {
$ hash - > { SONGINFOQUEUE } = [ $ id ] ;
push ( @ { $ hash - > { SONGINFOQUEUE } } , $ id ) ;
RemoveInternalTimer ( "SonginfoHandleQueue:$name" ) ;
2017-08-26 19:46:07 +00:00
if ( $ init_done > 0 ) { # CD 0084
InternalTimer ( gettimeofday ( ) + ( $ wait == 1 ? 2.0 : 0.01 ) ,
"SB_PLAYER_tcb_SonginfoHandleQueue" ,
"SonginfoHandleQueue:$name" ,
0 ) ;
}
2017-05-28 19:14:57 +00:00
} else {
push ( @ { $ hash - > { SONGINFOQUEUE } } , "wait" ) if ( $ wait == 1 ) ;
push ( @ { $ hash - > { SONGINFOQUEUE } } , $ id ) ;
}
}
sub
SB_PLAYER_SonginfoHandleQueue ( $ ) ##################################################
{
my $ hash = shift ;
my $ name = $ hash - > { NAME } ;
my $ arr = $ hash - > { SONGINFOQUEUE } ;
if ( defined ( $ arr ) && @ { $ arr } > 0 ) {
2017-08-26 19:46:07 +00:00
if ( $ hash - > { helper } { songinfopending } < 50 ) {
shift ( @ { $ arr } ) ;
if ( @ { $ arr } == 0 ) {
if ( $ hash - > { helper } { songinfocounter } > 0 ) {
IOWrite ( $ hash , $ hash - > { helper } { songinfoquery } ) ;
$ hash - > { helper } { songinfopending } += $ hash - > { helper } { songinfocounter } ;
$ hash - > { helper } { songinfoquery } = '' ;
$ hash - > { helper } { songinfocounter } = 0 ;
}
IOWrite ( $ hash , $ hash - > { PLAYERMAC } . " FHEMupdatePlaylistInfoDone\n" ) ;
delete ( $ hash - > { SONGINFOQUEUE } ) ;
return ;
}
my $ id = $ arr - > [ 0 ] ;
if ( $ id ne "wait" ) {
if ( ( $ id eq "" ) || ( $ id == 0 ) ) { # CD 0076 id 0 ignorieren
SB_PLAYER_SonginfoHandleQueue ( $ hash ) ;
} else {
# CD 0084 Abfragen zusammenfassen
$ hash - > { helper } { songinfoquery } = $ hash - > { helper } { songinfoquery } . $ hash - > { PLAYERMAC } . " songinfo 0 100 track_id:" . $ id . " tags:acdltuxNK\n" ;
$ hash - > { helper } { songinfocounter } + + ;
if ( $ hash - > { helper } { songinfocounter } >= 10 ) {
IOWrite ( $ hash , $ hash - > { helper } { songinfoquery } ) ;
$ hash - > { helper } { songinfopending } += $ hash - > { helper } { songinfocounter } ;
$ hash - > { helper } { songinfoquery } = '' ;
$ hash - > { helper } { songinfocounter } = 0 ;
}
}
2017-05-28 19:14:57 +00:00
}
2017-08-26 19:46:07 +00:00
InternalTimer ( gettimeofday ( ) + ( ( $ id eq "wait" ) ? 2.0 : 0.01 ) ,
"SB_PLAYER_tcb_SonginfoHandleQueue" ,
"SonginfoHandleQueue:$name" ,
0 ) ;
} else {
InternalTimer ( gettimeofday ( ) + 0.05 ,
"SB_PLAYER_tcb_SonginfoHandleQueue" ,
"SonginfoHandleQueue:$name" ,
0 ) ;
2017-05-28 19:14:57 +00:00
}
}
}
sub SB_PLAYER_tcb_SonginfoHandleQueue ($) {
my ( $ in ) = shift ;
my ( undef , $ name ) = split ( ':' , $ in ) ;
my $ hash = $ defs { $ name } ;
SB_PLAYER_SonginfoHandleQueue ( $ hash ) ;
}
# CD 0072 end
2015-06-18 20:23:54 +00:00
2017-06-04 09:59:54 +00:00
# CD 0078 start
sub SB_PLAYER_RemoveInternalTimers ($) {
my ( $ hash ) = @ _ ;
my $ name = $ hash - > { NAME } ;
RemoveInternalTimer ( "DelayAmplifier:$name" ) ;
RemoveInternalTimer ( "QueryElapsedTime:$name" ) ;
RemoveInternalTimer ( "SonginfoHandleQueue:$name" ) ;
RemoveInternalTimer ( "StartTalk:$name" ) ;
RemoveInternalTimer ( "TTSDelay:$name" ) ;
RemoveInternalTimer ( "TTSRestore:$name" ) ;
RemoveInternalTimer ( "TTSStartAfterPowerOn:$name" ) ;
RemoveInternalTimer ( "TimeoutTTSWaitForPlay:$name" ) ;
RemoveInternalTimer ( "TimeoutTTSWaitForPowerOn:$name" ) ;
RemoveInternalTimer ( "TriggerPlaylistStop:$name" ) ;
RemoveInternalTimer ( "TriggerTTSDone:$name" ) ;
RemoveInternalTimer ( "recallPause:$name" ) ;
2017-08-26 19:46:07 +00:00
RemoveInternalTimer ( "ftuiMedialist:$name" ) ; # CD 0085
2017-06-04 09:59:54 +00:00
RemoveInternalTimer ( $ hash ) ;
}
# CD 0078 end
2015-03-19 20:37:01 +00:00
# ##############################################################################
2014-11-09 18:01:21 +00:00
# No PERL code beyond this line
2015-03-19 20:37:01 +00:00
# ##############################################################################
2014-02-20 23:34:51 +00:00
1 ;
= pod
2017-05-28 19:14:57 +00:00
= item device
2016-10-01 16:46:46 +00:00
= item summary control Squeezebox Media Players
2017-05-28 19:14:57 +00:00
= item summary_DE Ansteuerung von Squeezebox Media Playern
2014-11-09 18:01:21 +00:00
= begin html
2017-05-28 19:14:57 +00:00
2015-11-02 08:26:30 +00:00
< a name = "SB_PLAYER" > </a>
2014-11-09 18:01:21 +00:00
<h3> SB_PLAYER </h3>
<ul>
< a name = "SBplayerdefine" > </a>
<b> Define </b>
<ul>
2015-11-02 08:26:30 +00:00
<code> define & lt ; name & gt ; SB_PLAYER & lt ; player_mac_address & gt ; [ ampl: & lt ; ampl & gt ; ] [ coverart: & lt ; coverart & gt ; ] </code>
2014-02-20 23:34:51 +00:00
<br> <br>
2016-10-01 16:46:46 +00:00
This module controls Squeezebox Media Players connected to a defined Logitech Media Server ( LMS ) . A SB_SERVER device is required . <br>
2015-11-02 08:26:30 +00:00
Usually SB_PLAYER devices are created automatically by autocreate . <br> <br>
2014-11-09 18:01:21 +00:00
<ul>
2015-11-02 08:26:30 +00:00
<li> <code> & lt ; player_mac_address & gt ; </code> : Mac address of player as seen by LMS . </li>
</ul> <br>
2015-03-19 20:37:01 +00:00
<b> Optional </b> <br> <br>
2014-11-09 18:01:21 +00:00
<ul>
2015-11-02 08:26:30 +00:00
<li> <code> & lt ; [ ampl ] & gt ; </code> : A FHEM device to switch on or off when relevant events are received . The attribute
< a href = "#SBplayeramplifier" > amplifier </a> specifies whether to switch this device upon reception of on /off or play/ pause /stop events.</ li >
<li> <code> & lt ; [ coverart ] & gt ; </code> : A FHEM weblink to be updated with the current coverart .
This may be used to show coverart in a floorplan . </li>
2014-11-09 18:01:21 +00:00
</ul> <br> <br>
2015-03-19 20:37:01 +00:00
</ul>
2017-05-28 19:14:57 +00:00
2014-11-09 18:01:21 +00:00
< a name = "SBplayerset" > </a>
<b> Set </b>
<ul>
<code> set & lt ; name & gt ; & lt ; command & gt ; [ & lt ; parameter & gt ; ] </code>
2014-02-20 23:34:51 +00:00
<br> <br>
2017-05-28 19:14:57 +00:00
2015-03-19 20:37:01 +00:00
SB_Player related commands: <br> <br>
2014-11-09 18:01:21 +00:00
<ul>
2015-11-02 08:26:30 +00:00
<li> <b> play </b> - start playback ( might not work unless previously paused ) . </li>
2016-10-01 16:46:46 +00:00
<li> <b> pause [ 0 | 1 ] </b> - toggle between play and pause states . & ldquo ; pause 1 & rdquo ; and & ldquo ; pause 0 & rdquo ; respectively pause and resume play unconditionally . </li>
2015-11-02 08:26:30 +00:00
<li> <b> stop </b> - stop playback </li>
<li> <b> next | channelUp </b> - next track </li>
<li> <b> prev | channelDown </b> - previous track or the beginning of the current track . </li>
<li> <b> mute </b> - toggle mute . </li>
2017-05-28 19:14:57 +00:00
<li> <b> volume & lt ; n & gt ; </b> - set volume to & lt ; n & gt ; . & lt ; n & gt ; must be a number between 0 and 100 . </li>
<li> <b> volume + | - & lt ; n & gt ; </b> - increase | decrease volume by a value given with + | - & lt ; n & gt ; . & lt ; n & gt ; must be a number between 0 and 100 . </li>
2014-11-09 18:01:21 +00:00
<li> <b> volumeStraight & lt ; n & gt ; </b> - same as volume </li>
2017-05-28 19:14:57 +00:00
<li> <b> volumeDown </b> - reduce the volume by a number of steps given with the attribute volumeStep ; default 10 steps . </li>
<li> <b> volumeUp </b> - increase the volume by a number of steps given with the attribute volumeStep ; default 10 steps . </li>
2015-11-02 08:26:30 +00:00
<li> <b> on </b> - turn player on if possible . Issue play command otherwise . </li>
<li> <b> off </b> - turn player off if possible . Issue stop command otherwise . </li>
2016-10-01 16:46:46 +00:00
<li> <b> shuffle off | song | album </b> - enable /disable shuffle mode.</ li >
2015-11-02 08:26:30 +00:00
<li> <b> repeat one | all | off </b> - Set repeat mode . </li>
2016-10-01 16:46:46 +00:00
<li> <b> sleep & lt ; timespec & gt ; </b> - Set player off after & lt ; timespec & gt ; has expired , fading player volume down . & lt ; timespec & gt ; ' s format is hh:mm:ss .
2017-05-28 19:14:57 +00:00
& lt ; timespec & gt ; is a relative time specification . That means: <code> set & lt ; myPlayer & gt ; sleep 22 : 00 : 00 </code> doesn <EFBFBD> t switch the player off at 10 pm but after 22 hours </li>
2016-10-01 16:46:46 +00:00
<li> <b> favorites & lt ; favorite & gt ; </b> - Empty current playlist and start & lt ; favorite & gt ; .
2017-05-28 19:14:57 +00:00
& lt ; favorite & gt ; is a selected favorite from out of the favorite - list . The frontend may make favorites selectable by a dropdown list . </li>
2015-11-02 08:26:30 +00:00
<li> <b> talk | sayText & lt ; text & gt ; </b> - Save the playlist , speak & lt ; text & gt ; using Google TTS and resume saved playlist . </li>
<li> <b> playlist track | album | artist | genre | year & lt ; x & gt ; </b> - Empty current playlist and play given argument . </li>
<li> <b> playlist genre: & lt ; genre & gt ; artist: & lt ; artist & gt ; album: & lt ; album & gt ; </b> - Empty current playlist and play all tracks matching the parameters . A * acts as a wildcard for everything . </li>
2015-06-18 20:23:54 +00:00
<br> Example: <br>
<code> set myplayer playlist genre: * artist:Whigfield album: * </code> <br> <br>
2015-11-02 08:26:30 +00:00
<li> <b> playlist play & lt ; filename | playlistname & gt ; </b> - Empty current playlist and start the track or playlist . </li>
<li> <b> playlist add & lt ; filename | playlistname & gt ; </b> - Add the specified file or playlist at the end of the current playlist . </li>
<li> <b> playlist insert & lt ; filename | playlistname & gt ; </b> - Insert specified file or playlist after the current track into
the current playlist . </li>
2017-05-28 19:14:57 +00:00
<li> <b> track | tracknumber & lt ; n | + n | - n & gt ; </b> - Sets the track with the given tracknumber as the current title . An explicitly
positive or negative number may be used to jump to a song relative to the currently playing song .. </li>
2015-11-02 08:26:30 +00:00
<li> <b> statusRequest </b> - Update all readings . </li>
<li> <b> sync & lt ; playerName [ , playerName ... ] & gt ; [ new | asSlave ] </b> - Put playerName ( s ) into this player ' s multiroom group . Remove playerName ( s ) from their existing group ( s ) if necessary . Options: </li>
<ul>
2016-10-01 16:46:46 +00:00
<li> new - create a new group , removing this /these player(s) from any group.</ li >
2015-11-02 08:26:30 +00:00
<li> asSlave - add this player to a player or existing group </li>
</ul> <br>
2015-06-18 20:23:54 +00:00
Examples: <br>
2016-10-01 16:46:46 +00:00
<code> set playerA sync playerB </code> & nbsp ; & nbsp ; & nbsp ; & nbsp ; add playerB to playerA ' s group , both playing the content of playerA <br>
<code> set playerA sync playerB , playerC , playerD </code> & nbsp ; & nbsp ; & nbsp ; & nbsp ; add playerB , C and D to playerA ' s group , all playing the content of playerA <br>
<code> set playerA sync playerB new </code> & nbsp ; & nbsp ; & nbsp ; & nbsp ; create a new group with playerA and B , both playing playerA <EFBFBD> s content <br>
<code> set playerA sync playerB asSlave </code> & nbsp ; & nbsp ; & nbsp ; & nbsp ; add playerA to playerB ' s group , both playing now playerB <EFBFBD> s content <br> <br>
2015-11-02 08:26:30 +00:00
<li> <b> unsync </b> - Remove this player from any multiroom group </li>
2016-10-01 16:46:46 +00:00
<li> <b> playlists & lt ; name & gt ; </b> - Empty current playlist and start selected playlist . </li>
<li> <b> cliraw & lt ; command & gt ; </b> - Tell LMS to execute & lt ; command & gt ; using its command line interface .
The answer of the LMS ist written to the internal LASTANSWER . </li>
<li> <b> save [ & lt ; name & gt ; ] </b> - Save player state </li>
<li> <b> recall [ & lt ; name & gt ; ] [ options ] </b> - Recall a saved player state . Options: </li>
2015-11-02 08:26:30 +00:00
<ul>
<li> del - delete saved state after restore </li>
<li> delonly - delete saved state without restoring </li>
<li> off - ignore saved power setting , turn player off after restore </li>
<li> on - ignore saved power setting , turn player on after restore </li>
<li> play - ignore saved play state , start playing after restore </li>
<li> stop - ignore saved play state , stop playing after restore </li>
</ul>
2016-10-01 16:46:46 +00:00
<li> <b> show line1: & lt ; line1 & gt ; line2: [ & lt ; line2 & gt ; ] duration: & lt ; duration & gt ; </b> - show text on the display of the player for a certain duration .
If no 2 . row should be displayed , the command however must contain 'line2:' </li>
2015-11-02 08:26:30 +00:00
<ul>
2016-10-01 16:46:46 +00:00
<li> line1 - Text to be displayed in the first line </li>
<li> line2 - Text to be displayed in the second line </li>
2015-11-02 08:26:30 +00:00
<li> duration - Duration of display in seconds </li>
</ul>
2017-05-28 19:14:57 +00:00
<li> <b> currentTrackPosition & lt ; TimePosition & gt ; </b> - Sets the current timeposition inside the title to the given value . </li>
<li> <b> resetTTS </b> - Resets TTS , can be necessary if the output via TTS blocks . </li>
<li> <b> updateFTUImedialist </b> - Manually refresh the reading ftuiMedialist ( containing the current songs ) . </li>
<li> <b> clearFTUIcache </b> - Clear the cached data used for the FTUI - readings . </li>
2016-10-01 16:46:46 +00:00
</ul>
2015-11-02 08:26:30 +00:00
<br> Alarms <br>
2014-11-09 18:01:21 +00:00
<ul>
2015-11-02 08:26:30 +00:00
Multiple alarms may be defined .
2016-10-01 16:46:46 +00:00
<li> <b> allalarms add & lt ; weekdays & gt ; & lt ; alarm time & gt ; [ & lt ; playlist | URL & gt ; ] </b> - Add a new alarm </li>
<br> & lt ; weekdays & gt ; - Active days for this alarm . Format: 0 .. 7 | daily | all <br>
2015-11-02 08:26:30 +00:00
0 .. 6 for Sunday ( 0 ) through Saturday ( 6 ) , 7 for every day <br>
The first two letters of the english or german names may be used to specify days instead of a single digit . ( Su /So, Mo, Tu/ Di , We /Mi, Th/ Do , Fr , Sa ) <br>
2016-10-01 16:46:46 +00:00
& lt ; alarm time & gt ; Alarm time specified as hh:mm [ : ss ] <br> & lt ; playlist | URL & gt ; If this parameter in not set , the playlist CURRENT is used . <br> <br>
2015-11-02 08:26:30 +00:00
Example: <br>
<code> set player allalarms add 1 DiWe 06 : 30 AlarmPlaylist </code> - Add a new alarm to sound playlist AlarmPlaylist every Monday through Wednesday at 06 : 30 <br> <br>
2016-10-01 16:46:46 +00:00
<li> <b> allalarms enable | disable </b> - Set global enable / disable flag . Setting this to "disable" effectively
turns off all alarms . Setting this to "enable" allows alarms to honor their individual flags .
Identical to command alarmsEnabled on | off . </li>
2015-11-02 08:26:30 +00:00
<li> <b> allalarms delete </b> - Delete all alarms . </li>
<li> <b> allalarms statusRequest </b> - Update status of all alarms . </li>
<li> <b> alarmsSnooze & lt ; minutes & gt ; </b> - Set duration of any snooze in minutes . </li>
<li> <b> alarmsTimeout & lt ; minutes & gt ; </b> - Set duration of alarms in minutes . Setting this to 0 will disable the automatic timeout . </li>
<li> <b> alarmsDefaultVolume & lt ; vol & gt ; </b> - Set default volume level ( 0 - 100 ) of alarms . This can be overridden by individual levels per alarm . </li>
<li> <b> alarmsFadeIn on | off </b> - Whether alarms should fade in on this player </li>
2017-07-26 19:25:07 +00:00
<li> <b> alarmsFadeSeconds & lt ; seconds & gt ; </b> - Fade - in period in seconds for the alarms . </li>
2015-11-02 08:26:30 +00:00
<li> <b> alarmsEnabled on | off </b> - Whether any alarm can sound on this player . Set to off to prevent any alarm from sounding ; on to allow them to sound </li>
2016-10-01 16:46:46 +00:00
<li> <b> snooze </b> - Switch off a running alarm and start again after a certain time , defined by the reading alarmsSnooze . </li>
2015-11-02 08:26:30 +00:00
<br>
<li> <b> alarm & lt ; X & gt ; delete </b> - Delete alarm & lt ; X & gt ; </li>
<li> <b> alarm & lt ; X & gt ; volume & lt ; n & gt ; </b> - Set volume for alarm & lt ; X & gt ; to & lt ; n & gt ; </li>
<li> <b> alarm & lt ; X & gt ; enable | disable </b> - Enable or disable alarm & lt ; X & gt ; </li>
<li> <b> alarm & lt ; X & gt ; sound & lt ; playlist | URL & gt ; </b> - Define playlist or URL to be sounded by alarm & lt ; X & gt ; </li>
<li> <b> alarm & lt ; X & gt ; repeat 0 | off | no | 1 | on | yes </b> - Specify one - shot or repeating alarm </li>
2016-10-01 16:46:46 +00:00
<li> <b> alarm & lt ; X & gt ; wdays & lt ; weekdays & gt ; </b> - Specify active days for alarm & lt ; X & gt ; . Format: 0 .. 7 | daily | all <br>
2015-11-02 08:26:30 +00:00
0 .. 6 for Sunday ( 0 ) through Saturday ( 6 ) , 7 for every day <br>
The first two letters of the english or german names may be used to specify days instead of a single digit . ( Su /So, Mo, Tu/ Di , We /Mi, Th/ Do , Fr , Sa ) </li>
<li> <b> alarm & lt ; X & gt ; time hh:mm [ : ss ] </b> - Define alarm time </li>
</ul>
2014-11-09 18:01:21 +00:00
</ul>
<br>
<br> <br>
< a name = "SBplayerattr" > </a>
<b> Attributes </b>
<ul>
2016-10-01 16:46:46 +00:00
<li> IODev & lt ; servername & gt ; <br>
FHEM - Name of the SB_SERVER device controlling this player . </li>
<li> < a href = "#do_not_notify" > do_not_notify </a> true | false <br>
Disable FileLog /notify/i nform notification for a device . This affects the received signal , the set and trigger commands .
Possible values are true | false </li>
<li> < a name = "SBplayeramplifier" > amplifier </a> on | play <br>
2015-11-02 08:26:30 +00:00
Configure trigger for amplifier device . Possible values :
<ul>
<li> <code> on </code> : Switch on "on" and "off" events . </li>
<li> <code> play </code> : Switch on "play" , "pause" and "stop" events . </li>
</ul>
</li>
2016-10-01 16:46:46 +00:00
<li> amplifierDelayOff & lt ; sec1 & gt ; [ , & lt ; sec2 & gt ; ] <br>
2015-11-02 08:26:30 +00:00
Delay in seconds before turning the amplifier off after the player has stopped or been turned off . A second comma separated delay optionally enables switching off the amplifier after receiving a pause event . </li>
2016-10-01 16:46:46 +00:00
<li> coverartheight 50 | 100 | 200 <br> Display the coverart with a height of 50 , 100 or 200 pixels </li>
<li> coverartwidth 50 | 100 | 200 <br> Display the coverart with a width of 50 , 100 or 200 pixels </li>
<li> < a href = "#event-on-change-reading" > event - on - change - reading </a> & lt ; expression & gt ; <br> <br>
Example: <br>
<code> attr & lt ; playername & gt ; event - on - change - reading currentAlbum , currentArtist , currentTitle </code> <br>
Only changes in the readings currentAlbum , currentArtist , currentTitle cause an event . </li> <br>
<li> fadeinsecs & lt ; sec1 & gt ; [ , & lt ; sec2 & gt ; ] <br>
Fade - in period in seconds . A second comma separated value optionally specifies the period to use on unpause . </li>
2017-08-26 19:46:07 +00:00
<li> ftuiSupport 0 | 1 | favorites | playlists | medialist <br>
Create additional readings for FTUI integration . Warning: Using 1 or medialist may cause high cpu usage and unresponsiveness
on slower systems . </li>
2017-05-28 19:14:57 +00:00
<li> sortFavorites 0 | 1 <br>
If set to 1 the favorites will be sorted alphabetically . </li>
<li> sortPlaylists 0 | 1 <br>
If set to 1 the playlists will be sorted alphabetically . </li>
2016-10-01 16:46:46 +00:00
<li> statusRequestInterval & lt ; sec & gt ; <br>
2015-11-02 08:26:30 +00:00
Interval in seconds for automatic status requests . Default: 300 </li>
2016-10-01 16:46:46 +00:00
<li> syncedNamesSource FHEM | LMS <br>
Determines if the synced reading contains the LMS or FHEM names of the players </li>
<li> syncVolume 0 | 1 <br>
Defines whether the loudness of this player is synchronized with the other players of its group </li>
2017-05-28 19:14:57 +00:00
<li> trackPositionQueryInterval & lt ; sec & gt ; <br>
Interval in seconds for querying the current track position , 0 disables the periodic update of the track position </li>
2016-10-01 16:46:46 +00:00
<li> ttsAPIKey & lt ; API - key & gt ; <br>
For the use of T2Speech from the company VoiceRSS ( voicerss . org ) an API - key is needed . Not needed with Google <EFBFBD> s T2Speech . </li>
<li> ttsDelay & lt ; sec1 & gt ; [ , & lt ; sec2 & gt ; ] <br>
2015-11-02 08:26:30 +00:00
Delay in seconds before starting text to speech playback . A second comma separated delay may optionally be given to be used if the player is off . </li>
2016-10-01 16:46:46 +00:00
<li> ttslanguage de | en | fr <br>
Specifies the language of the voice output . A complete list of available languages using Google <EFBFBD> s TTS can be found at wikipedia . org . </li>
<li> ttslink & lt ; link & gt ; <br>
Enter the link to the TTS - Funktion . Google , VoiceRSS and <EFBFBD> with reservations - Text2Speech are supported . <br> <br>
Example of using Google <EFBFBD> s TTS: <br>
2017-05-28 19:14:57 +00:00
<code> attr & lt ; playername & gt ; ttslink http: // translate . google . com /translate_tts?ie=UTF-8&tl=<LANG>&q=<TEXT>&client=tw-ob</co de > </li> <br>
2016-10-01 16:46:46 +00:00
<li> ttsMP3FileDir & lt ; directory & gt ; <br>
Directory to be used by default for text - embedded MP3 - Files . </li> <br>
Example: <br>
<code> attr & lt ; SB_device & gt ; ttsMP3FileDir /volume1/m usic /sounds</co de > <br> <br>
<li> ttsOptions & lt ; options & gt ; <br> various options , comma - separated , for TTS - output .
<br> <br> Options: <ul>
<li> debug - Write additional information into the FHEM - logfile </li>
<li> debugsaverestore - Additional information about loading /saving of player<65> s status are written into the logfile</ li >
<li> nosaverestore - Do not save and restore the status of the player , thereby the normal playing stops after using TTS . </li>
<li> forcegroupon - Switch on all players of the group . </li>
2017-05-28 19:14:57 +00:00
<li> ignorevolumelimit - Ignore the attribute volumeLimit while using TTS - output . </li>
<li> eventondone - Fire an event at the end of the TTS output . </li>
2016-10-01 16:46:46 +00:00
</ul> </li>
<li> ttsPrefix & lt ; text & gt ; <br>
2015-11-02 08:26:30 +00:00
Text prepended to every text to speech output </li>
2016-10-01 16:46:46 +00:00
<li> ttsVolume & lt ; value & gt ; <br>
2015-11-02 08:26:30 +00:00
Volume for text to speech . Defaults to current volume . If the attribute <code> ttsoptions </code> contains <code> ignorevolumelimit </code>
2016-10-01 16:46:46 +00:00
any volume limit will be ignored for text to speech . Possible values : 0 - 100 </li>
<li> updateReadingsOnSet true | false <br>
If set to true , most readings are immediately updated when a set command is executed without waiting for a reply from the server . </li>
<li> volumeLimit & lt ; value & gt ; <br>
Upper limit for volume setting by FHEM . </li>
2017-05-28 19:14:57 +00:00
<li> volumeOffset & lt ; value & gt ; <br>
The offset is added to the volume sent to the server . It is subtracted from the volume returned by the server . </li>
2016-10-01 16:46:46 +00:00
<li> volumeStep & lt ; value & gt ; <br>
Sets the volume adjustment to a granularity given by & lt ; value & gt ; . Possible values : 1 <EFBFBD> 100 . Default value: 10 </li>
2014-11-09 18:01:21 +00:00
</ul>
</ul>
= end html
2016-10-01 16:46:46 +00:00
= begin html_DE
2017-05-28 19:14:57 +00:00
2016-10-01 16:46:46 +00:00
< a name = "SB_PLAYER" > </a>
<h3> SB_PLAYER </h3>
<ul>
< a name = "SBplayerdefine" > </a>
<b> Define </b>
<ul>
<code> define & lt ; name & gt ; SB_PLAYER & lt ; player_mac_address & gt ; [ ampl: & lt ; ampl & gt ; ] [ coverart: & lt ; coverart & gt ; ] </code>
<br> <br>
Dieses Modul steuert Squeezebox - Player , die mit einem bereits definiertem
Logitech Media Server ( LMS ) verbunden sind . Ein SB_SERVER - Device ist erforderlich .
Normalerweise wird das SB_PLAYER Device automatisch durch autocreate erzeugt . <br> <br>
<ul>
<li> <code> & lt ; player_mac_address & gt ; </code> : Die MAC - Adresse , wie der LMS den Player sieht . </li>
</ul> <br>
<b> Optional </b> <br> <br>
<ul>
<li> <code> & lt ; [ ampl ] & gt ; </code> : Ein FHEM - Device welches ein - oder ausgeschaltet werden soll , wenn
2017-05-28 19:14:57 +00:00
ein passendes Event empfangen wird . Das Attribut
2016-10-01 16:46:46 +00:00
< a href = "#SBplayeramplifier" > amplifier </a> gibt an , ob das passende Event on /off oder play/ pause sein soll . </li>
<li> <code> & lt ; [ coverart ] & gt ; </code> : Unter & lt ; coverart & gt ; gibt man den Namen eines FHEM weblink image
Elementes an . Der Player aktualisiert dann jeweils den Link auf das aktuelle Coverart Bild , so dass
man dieses z . B . im Floorplan anzeigen kann . </li>
</ul> <br> <br>
</ul>
2017-05-28 19:14:57 +00:00
2016-10-01 16:46:46 +00:00
< a name = "SBplayerset" > </a>
<b> Set </b>
<ul>
<code> set & lt ; Name & gt ; & lt ; Befehl & gt ; [ & lt ; Parameter & gt ; ] </code>
<br> <br>
2017-05-28 19:14:57 +00:00
2016-10-01 16:46:46 +00:00
Befehle zur Steuerung des Players: <br> <br>
<ul>
<li> <b> play </b> - Startet die Wiedergabe ( Es kann sein , dass die Wiedergabe nicht funktioniert ,
wenn kein pause - Befehl vorangegangen ist ) . </li>
<li> <b> pause [ 0 | 1 ] </b> - Schaltet zwischen play und pause hin und her ( Toggle - Funktion ) .
& ldquo ; pause 1 & rdquo ; und & ldquo ; pause 0 & rdquo ; schaltet bedingungslos auf Pause resp . Wiedergabe . </li>
<li> <b> stop </b> - Stoppt die Wiedergabe </li>
<li> <b> next | channelUp </b> - Springt zum n & auml ; chsten Track </li>
<li> <b> prev | channelDown </b> - Springt zum vorherigen Track bzw . zum Anfang des gegenw & auml ; rtig gespielten Tracks . </li>
<li> <b> mute </b> - Toggelt die Lautst & auml ; rke stumm und wieder zur & uuml ; ck . </li>
<li> <b> volume & lt ; n & gt ; </b> - Stellt die Lautst & auml ; rke auf einen Wert & lt ; n & gt ; ein . Dabei muss & lt ; n & gt ;
eine Zahl zwischen 0 und 100 sein . </li>
2017-05-28 19:14:57 +00:00
<li> <b> volume + | - & lt ; n & gt ; </b> - Erh & ouml ; ht oder vermindert die Lautst & auml ; rke um den Wert , der durch + | - & lt ; n & gt ;
vorgegeben wird . Dabei muss & lt ; n & gt ; eine Zahl zwischen 0 und 100 sein . </li>
2016-10-01 16:46:46 +00:00
<li> <b> volumeStraight & lt ; n & gt ; </b> - mit volume identisch </li>
<li> <b> volumeDown </b> - Verringert die Lautst & auml ; rke um eine bestimmte Anzahl von Schritten die mit dem Attribut
< a href = "#SBplayervolumeStep" > volumeStep </a> vorgegeben werden . Wird nichts vorgegeben , werden 10 Schritte verwendet </li>
<li> <b> volumeUp </b> - Erh & ouml ; ht die Lautst & auml ; rke um eine bestimmte Anzahl von Schritten , die mit dem Attribut
< a href = "#SBplayervolumeStep" > volumeStep </a> vorgegeben werden . Wird nichts vorgegeben , werden 10 Schritte verwendet </li>
<li> <b> on </b> - Schaltet den Player ein . Ist das nicht m & ouml ; glich , wird ein play - Befehl gesendet . </li>
<li> <b> off </b> - Schaltet den Player aus . Ist das nicht m & ouml ; glich , wird ein stop - Befehl gesendet . </li>
<li> <b> shuffle off | song | album </b> - Schaltet die zuf & auml ; llige Wiedergabe aus ( off ) ; f & uuml ; r Songs einer Wiedergabeliste ( song )
ein oder f & uuml ; r eine Liste von Alben ein ( album ) . </li>
<li> <b> repeat one | all | off </b> - Schaltet die Wiederholung von Tracks einer Wiedergabeliste aus ( off ) , f & uuml ; r ein Track
ein ( one ) oder f & uuml ; r alle St & uuml ; cke der Wiedergabeliste ein ( all ) . </li>
<li> <b> sleep & lt ; timespec & gt ; </b> - Dauer , nach der sich der Player ausschalten soll ,
Format hh:mm [ : ss ] . Bei der Zeitangabe handelt es sich um eine relative Zeitangabe ab
dem Aufruf . Das bedeutet:
<code> set & lt ; myPlayer & gt ; sleep 22 : 00 : 00 </code> schaltet den Player nicht um 10 Uhr abends aus ,
2017-05-28 19:14:57 +00:00
sondern erst 22 Stunden nach dem Aufruf ! </li>
2016-10-01 16:46:46 +00:00
<li> <b> favorites & lt ; favorite & gt ; </b> - L & ouml ; scht die aktuelle Wiedergabeliste und startet den Favoriten & lt ; favorite & gt ; .
& lt ; favorite & gt ; ist der ausgew & auml ; hlte Favorit aus einer Favoritenliste . Das Frontend kann eine
2017-05-28 19:14:57 +00:00
Dropdownliste zur Verf & uuml ; gung stellen , aus der der Favorit ausgew & auml ; hlt werden kann . </li>
2016-10-01 16:46:46 +00:00
<li> <b> talk | sayText & lt ; text & gt ; </b> - Speichert den aktuellen Stand der Playlist , sagt den Text
& lt ; text & gt ; unter Zuhilfenahme von GoogleTTS oder VoiceRSS an und setzt die Wiedergabe ab dem
gespeicherten Punkt fort . </li>
<li> <b> playlist track | album | artist | genre | year & lt ; x & gt ; </b> - L & ouml ; scht die aktuelle Wiedergabeliste
und gibt das vorgegebene Argument & lt ; x & gt ; wieder . </li>
2017-05-28 19:14:57 +00:00
<li> <b> playlist genre: & lt ; genre & gt ; artist: & lt ; artist & gt ; album: & lt ; album & gt ; </b> -
2016-10-01 16:46:46 +00:00
L & ouml ; scht die aktuelle Wiedergabeliste und gibt alle Tracks wieder , die den angegebenen Kriterien entsprechen .
Ein * steht f & uuml ; r beliebige Angaben . </li>
<br> Beispiel: <br>
<code> set myplayer playlist genre: * artist:Whigfield album: * </code> <br> <br>
<li> <b> playlist play & lt ; filename | playlistname & gt ; </b> - L & ouml ; scht die aktuelle Wiedergabeliste und
startet die Wiedergabe eines Track oder einer Playlist . </li>
<li> <b> playlist add & lt ; filename | playlistname & gt ; </b> - H & auml ; ngt die angegebene Datei oder Playlist
an das Ende der aktuellen Playlist an . </li>
<li> <b> playlist insert & lt ; filename | playlistname & gt ; </b> - F & uuml ; gt die angegebene Datei oder Playlist
hinter der aktuellen Datei oder Playlist in der aktuellen Playlist ein . </li>
2017-05-28 19:14:57 +00:00
<li> <b> track | tracknumber & lt ; n | + n | - n & gt ; </b> - Aktiviert einen bestimmten Titel der aktiven Playliste . Mit & lt ; n & gt ; ist
die laufende Nummer des Titels innerhalb dieser Playliste anzugeben . Ein explizierter Wert mit Vorzeichen ,
springt in der momentanen Playliste um & lt ; + n & gt ; oder & lt ; - n & gt ; Titel vor oder zur <EFBFBD> ck . </li>
2016-10-01 16:46:46 +00:00
<li> <b> statusRequest </b> - Aktualisierung aller Readings . </li>
<li> <b> sync & lt ; playerName [ , playerName ... ] & gt ; [ new | asSlave ] </b> - F & uuml ; gt den /die Player mit dem/ den Namen
& lt ; playerName & gt ; der Multiroom - Gruppe desjenigen Players hinzu , der diesen Befehl aufgerufen hat ;
entfernt aber bei Bedarf den Player & lt ; playerName & gt ; aus seiner bisherigen Gruppe . <br> Optionen: </li>
<ul>
<li> new - Bildet eine neue Gruppe und entfernt den /die Player aus seiner/i hren bisherigen Gruppe /n</ li >
<li> asSlave - F & uuml ; gt diesen Player zu einem anderen Player oder einer vorhandenen Gruppe hinzu . </li>
</ul> <br>
Examples: <br>
<code> set playerA sync playerB </code> & nbsp ; & nbsp ; & nbsp ; & nbsp ; F & uuml ; gt PlayerB der Gruppe von PlayerA hinzu ;
beide geben den Inhalt von PlayerA wieder . <br>
<code> set playerA sync playerB , playerC , playerD </code> & nbsp ; & nbsp ; & nbsp ; & nbsp ; F & uuml ; gt PlayerB , C and D der
Gruppe von PlayerA hinzu ; alle geben den Inhalt von PlayerA wieder . <br>
<code> set playerA sync playerB new </code> & nbsp ; & nbsp ; & nbsp ; & nbsp ; Bildet eine neue Gruppe mit PlayerA
und PlayerB , beide geben den Inhalt von PlayerA wieder . <br>
<code> set playerA sync playerB asSlave </code> & nbsp ; & nbsp ; & nbsp ; & nbsp ; F & uuml ; gt PlayerA der Gruppe von
PlayerB hinzu ; beide geben den Inhalt von PlayerB wieder . <br> <br>
<li> <b> unsync </b> - Entfernt diesen Player aus allen Multiroom - Gruppen </li>
<li> <b> playlists & lt ; name & gt ; </b> - L & ouml ; scht die aktuelle Playlist und startet die ausgew & auml ; hlte Playlist . </li>
<li> <b> cliraw & lt ; command & gt ; </b> - Kann direkte Befehle an das CLI Interface schicken . Die Antwort
steht dann im Internal LASTANSWER . </li>
<li> <b> save [ & lt ; name & gt ; ] </b> - Speichert den derzeitigen Player - Status unter dem Namen & lt ; name & gt ; . </li>
<li> <b> recall [ & lt ; name & gt ; ] [ options ] </b> - Ruft einen gespeicherten Player - Status auf . <br> Optionen: </li>
<ul>
<li> del - L & ouml ; scht nach dem Restore den gespeicherten Status </li>
<li> delonly - L & ouml ; scht den gespeicherten Status ohne vorherigem Restore </li>
<li> off - Beachtet die gespeicherten Einstellungen zum Betriebszustand nicht
sondern schaltet den Player nach Restore aus . </li>
<li> on - Beachtet die gespeicherten Einstellungen zum Betriebszustand nicht
sondern schaltet den Player nach Restore ein . </li>
<li> play - Beachtet den gespeicherten play - Status nicht sondern startet die Wiedergabe nach Restore . </li>
<li> stop - Beachtet den gespeicherten play - Status nicht sondern stoppt die Wiedergabe nach Restore . </li>
</ul>
<li> <b> show line1: & lt ; text1 & gt ; line2: [ & lt ; text2 & gt ; ] duration: & lt ; duration & gt ; </b> - Zeigt
einen beliebigen Text auf dem Display f & uuml ; r eine vorgegebene Dauer an . Wenn keine 2 . Zeile
angezeigt werden sollen , muss trotzdem 'line2:' im Aufruf enthalten sein </li>
<ul>
<li> text1 - Inhalt der ersten Zeile </li>
<li> text2 - Inhalt der zweiten Zeile </li>
<li> duration - Dauer der Anzeige auf dem Display in Sekunden </li>
</ul>
2017-05-28 19:14:57 +00:00
<li> <b> currentTrackPosition & lt ; TimePosition & gt ; </b> - Setzt die Abspielposition innerhalb des
2016-10-01 16:46:46 +00:00
Liedes auf den angegebenen Zeitwert ( z . B . 0 : 01 : 15 ) . </li>
2017-05-28 19:14:57 +00:00
<li> <b> resetTTS </b> - TTS zur & uuml ; cksetzen , kann n & ouml ; tig sein wenn die TTS - Ausgabe h & auml ; ngt . </li>
<li> <b> updateFTUImedialist </b> - Erzwingt die Aktualisierung des Readings ftuiMedialist ( enth & auml ; lt die aktuellen Songs ) . </li>
<li> <b> clearFTUIcache </b> - L & ouml ; scht alle zwischengespeicherten Daten f <EFBFBD> r die Erstellung der FTUI - Readings . </li>
2016-10-01 16:46:46 +00:00
</ul>
<br> Befehlsliste zur Steuerung der Wecker , mehrere Wecker k & ouml ; nnen definiert werden . <br> <br>
<ul>
<li> <b> allalarms add & lt ; weekdays & gt ; & lt ; alarm time & gt ; [ & lt ; playlist | URL & gt ; ] </b> - F & uuml ; gt einen neuen Wecker hinzu . </li>
<br> & lt ; weekdays & gt ; - Aktive Tage f & uuml ; r diesen Wecker . Format: [ 0 .. 7 | daily | all ]
0 bis 6 f & uuml ; r Sonntag bis Samstag . 7 , daily und all f & uuml ; r t & auml ; gliches Wecken .
Die Wochentage k & ouml ; nnen ebenfalls durch die ersten zwei Buchstaben des
Wochentages sowohl in deutscher und englischer Sprache angegeben werden
( Su /So, Mo, Tu/ Di , We /Mi, Th/ Do , Fr , Sa ) . <br> <br>
& lt ; alarm time & gt ; Weckzeit im Format hh:mm [ : ss ] <br>
& lt ; playlist | URL & gt ; Weckton , wenn dieser Parameter nicht gesetzt wird , wird die aktuelle Playlist verwendet . <br> <br>
Beispiel: <br>
<code> set player allalarms add 1 DiWe 06 : 30 AlarmPlaylist </code> - F & uuml ; gt einen
neuen Wecker hinzu . Der Wecker startet jeden Montag bis Mittwoch um 6 : 30 Uhr
und spielt die Playlist AlarmPlaylist ab . <br> <br>
<li> <b> allalarms enable | disable </b> - Setzt das globale einable / disable Flag f & uuml ; r alle Wecker .
"disable" deaktiviert alle Wecker . <EFBFBD> enable " gestattet allen
Weckern sich nach den individuellen Flags zu richten . Identisch mit dem Befehl alarmsEnabled on | off . </li>
<li> <b> allalarms delete </b> - L & ouml ; scht alle Wecker . </li>
<li> <b> allalarms statusRequest </b> - Aktualisiert den Zustand aller Wecker . </li>
<li> <b> alarmsSnooze & lt ; minutes & gt ; </b> - Setzt die Dauer der Weckwiederholung ( in Minuten ) . </li>
<li> <b> alarmsTimeout & lt ; minutes & gt ; </b> - Bestimmt , wie lange ein Wecker l & auml ; uft
bevor er automatisch beendet wird . Ist der Wert 0 , l & auml ; uft der Wecker , bis er manuell beendet wird . </li>
<li> <b> alarmsDefaultVolume & lt ; vol & gt ; </b> - Legt die generelle Lautst & auml ; rke ( 0 - 100 ) f & uuml ; r den Wecker fest .
Dieser Wert kann durch eine individuelle Lautst & auml ; rkeangabe je Alarm & uuml ; berschrieben werden ( siehe auch
< a href = "#SBplayeralarmxvolume" > alarm & lt ; X & gt ; volume & lt ; n & gt ; </a> ) </li>
2017-07-26 19:25:07 +00:00
<li> <b> alarmsFadeIn on | off </b> - Schaltet fadeIn f & uuml ; r die Wecker ein ( on ) oder aus ( off ) . </li>
<li> <b> alarmsFadeSeconds & lt ; seconds & gt ; </b> - Fade - in Dauer f & uuml ; r die Wecker . </li>
2016-10-01 16:46:46 +00:00
<li> <b> alarmsEnabled on | off </b> - Gibt an , ob die eingetragenen Wecker & uuml ; berhaupt abgespielt
werden sollen ( on ) oder nicht ( off ) . </li>
<li> <b> snooze </b> - Schaltet einen gerade laufenden Wecker aus und nach einer durch
das Reading alarmsSnooze definierten Zeit wieder ein .. </li>
<br>
</ul>
Befehle f & uuml ; r einzelne Wecker ( X entspricht der Nummer des Weckers )
<ul>
<br>
<li> <b> alarm & lt ; X & gt ; delete </b> - L & ouml ; scht den Wecker & lt ; X & gt ; aus der Weckerliste . </li>
<li> <b> < a name = "SBplayeralarmxvolume" > alarm & lt ; X & gt ; volume & lt ; n & gt ; </a> </b> - Stellt
die Lautst & auml ; rke des Weckers & lt ; X & gt ; auf den Wert & lt ; n & gt ; . </li>
<li> <b> alarm & lt ; X & gt ; enable | disable </b> - Aktiviert bzw . deaktiviert den Wecker & lt ; X & gt ; </li>
<li> <b> alarm & lt ; X & gt ; sound & lt ; playlist | URL & gt ; </b> - Bestimmt eine Playlist oder URL , die
beim Wecker & lt ; X & gt ; abgespielt werden soll . </li>
<li> <b> alarm & lt ; X & gt ; repeat 0 | off | no | 1 | on | yes </b> - Bestimmt , ob Wecker & lt ; X & gt ; einmalig
( 0 | off | no ) oder mehrfach ( 1 | on | yes ) ausgel & ouml ; st werden soll . </li>
<li> <b> alarm & lt ; X & gt ; wdays & lt ; weekdays & gt ; </b> - Aktive Tage f & uuml ; r diesen Wecker .
& lt ; weekdays & gt ; hat die m & ouml ; glichen Inhalte 0 bis 6 f & uuml ; r Sonntag bis Samstag , 7 ,
daily und all f & uuml ; r t & auml ; gliches Wecken . Die Wochentage k & ouml ; nnen ebenfalls durch die ersten
zwei Buchstaben des Wochentages sowohl in deutscher und englischer Sprache angegeben
werden ( Su /So, Mo, Tu/ Di , We /Mi, Th/ Do , Fr , Sa ) . </li>
<li> <b> alarm & lt ; X & gt ; time hh:mm [ : ss ] </b> - Weckzeit im Format hh:mm [ : ss ] . </li>
</ul>
</ul>
<br>
< a name = "SBplayerattr" > </a>
<b> Attribute </b>
<ul>
<li> IODev & lt ; servername & gt ; <br>
FHEM - Name des SB_SERVERS . </li>
<li> < a href = "#do_not_notify" > do_not_notify </a> true | false <br>
Mit diesem Attribut kann man einstellen , ob der Player ein FHEM Notify bei jeder & auml ; nderung eines Readings lostritt oder nicht . </li>
<li> < a name = "SBplayeramplifier" > amplifier </a> on | play <br>
Gibt an , mit welcher Funktion ein zuschaltbarer Verst & auml ; rkers eingeschaltet werden soll , entweder bei einem
Einschaltvorgang ( on ) oder bei einen Startvorgang zum Abspielen eines Files ( play ) .
</li>
<li> amplifierDelayOff & lt ; sec1 & gt ; [ , & lt ; sec2 & gt ; ] <br>
Stellt eine Verz & ouml ; gerung zwischen dem Ausschaltvorgang des Players und des Verst & auml ; rkers in Sekunden ein .
Wird eine optionale zweite Zeit durch Komma getrennt angegeben , so wird diese bei Pause verwendet . Fehlt
die zweite Zeitangabe , wird bei Pause nicht abgeschaltet . </li>
<li> coverartheight 50 | 100 | 200 <br> Stellt das Cover mit einer vertikalen Aufl & ouml ; sung von 50 , 100 oder 200 Pixel dar . </li>
<li> coverartwidth 50 | 100 | 200 <br> Stellt das Cover mit einer horizontalen Aufl & ouml ; sung von 50 , 100 oder 200 Pixel dar . </li>
<li> < a href = "#event-on-change-reading" > event - on - change - reading </a> & lt ; expression & gt ; <br> Wird < a href = "#do_not_notify" > do_not_notify </a>
auf false gesetzt , veranlasst jede & Auml ; nderung eines Readings ein Notify . Mit diesem Attribut k & ouml ; nnen
ausl & ouml ; sende Ereignisse gefiltert werden . <br> <br>
Beispiel: <br>
<code> attr & lt ; playername & gt ; event - on - change - reading currentAlbum , currentArtist , currentTitle </code> <br>
Nur & auml ; nderungen der Readings currentAlbum , currentArtist , currentTitle erzeugen Events . </li> <br>
<li> fadeinsecs & lt ; sec1 & gt ; [ , & lt ; sec2 & gt ; ] <br>
Fade in f & uuml ; r Beginn von Playlisten und neuen Soundfiles . Bezeichnet die Dauer des Vorganges , in der die
Lautst & auml ; rke auf den vorgegebenen Wert ansteigt und wird in Sekunden angegeben . Ein zweiter , durch Komma
getrennter optionaler Wert , gibt die Dauer des Fadein beim Verlassen des Pausenzustandes an . </li>
2017-08-26 19:46:07 +00:00
<li> ftuiSupport 0 | 1 | favorites | playlists | medialist <br>
Zus & auml ; tzliche Readings f & uuml ; r die Integration in FTUI erzeugen . Achtung: Die Verwendung von 1 oder medialist kann kurzzeitig zu
erh & ouml ; ter Systemlast und H & auml ; ngern auf langsamen Systemen f & uuml ; hren . </li>
2016-10-01 16:46:46 +00:00
<li> statusRequestInterval & lt ; sec & gt ; <br>
Aktualisierungsintervall der automatischen Status - Abfrage . Default: 300 </li>
2017-05-28 19:14:57 +00:00
<li> sortFavorites 0 | 1 <br>
Wenn das Attribut den Wert 1 hat wird die Liste der Favoriten alphabetisch sortiert . </li>
<li> sortPlaylists 0 | 1 <br>
Wenn das Attribut den Wert 1 hat wird die Liste der Wiedergabelisten alphabetisch sortiert . </li>
2016-10-01 16:46:46 +00:00
<li> syncedNamesSource FHEM | LMS <br>
Legt fest ob die FHEM - Ger & auml ; tenamen oder die LMS - Namen der Player im synced - Reading verwendet werden . </li>
<li> syncVolume 0 | 1 <br>
Legt fest ob die Lautst & auml ; rke des Players mit anderen Playern aus der Gruppe synchronisiert wird . </li>
2017-05-28 19:14:57 +00:00
<li> trackPositionQueryInterval & lt ; sec & gt ; <br>
Legt fest wie h <EFBFBD> ufig die abgespielte Zeit abgefragt wird , 0 deaktiviert das Abfragen . </li>
2016-10-01 16:46:46 +00:00
<li> ttsAPIKey & lt ; API - key & gt ; <br>
F & uuml ; r die Benutzung von T2Speech der Firma VoiceRSS ( voicerss . org ) ist ein API - Key erforderlich .
F & uuml ; r Googles T2Speech ist kein Key notwendig . </li>
<li> ttsDelay & lt ; sec1 & gt ; [ , & lt ; sec2 & gt ; ] <br>
Wartezeit in Sekunden bevor die TTS - Ausgabe gestartet wird . Optional kann eine 2 . Zeit durch
Komma getrennt angegeben werden . In diesem Fall wird die 1 . Zeit verwendet wenn der Player
eingeschaltet ist und die 2 . wenn er ausgeschaltet ist . </li>
<li> ttslanguage de | en | fr <br>
Stellt die gew & uuml ; nschte Sprache f & uuml ; r die Text - to - Speech Funktion ein . Eine vollst & auml ; ndige Liste
der verf & uuml ; gbaren Sprachen findet sich in wikipedia . org </li>
<li> ttslink & lt ; link & gt ; <br>
Link zur TTS - Funktion . Unterst & uuml ; tzt werden: Google , VoiceRSS ( API - Key wird ben & ouml ; tigt ) und mit Einschr & auml ; nkungen Text2Speech . <br> <br>
Beispiel f & uuml ; r Google <EFBFBD> s TTS: <br>
2017-05-28 19:14:57 +00:00
<code> attr & lt ; playername & gt ; ttslink http: // translate . google . com /translate_tts?ie=UTF-8&tl=<LANG>&q=<TEXT>&client=tw-ob</co de > </li> <br>
2016-10-01 16:46:46 +00:00
<li> ttsMP3FileDir & lt ; directory & gt ; <br>
Standard - Verzeichnis f & uuml ; r Musik - und Sprachdateien ( z . B . Gong , Sirene , Ansagen , ... )
im mp3 - Format , die beim TTS eingebunden werden sollen . </li> <br>
Beispiel: <br>
<code> attr & lt ; SB_device & gt ; ttsMP3FileDir /volume1/m usic /sounds</co de > <br> <br>
<li> ttsOptions & lt ; Optionen & gt ; <br> Verschiedene durch Komma getrennte Optionen f & uuml ; r die TTS - Ausgabe .
<br> <br> Optionen: <ul>
<li> debug - Schreibt zus & auml ; tzliche Meldungen zum TTS ins Log . </li>
<li> debugsaverestore - Schreibt zus & auml ; tzliche Meldungen zum Speichern /Laden des Playerzustandes ins Log.</ li >
<li> nosaverestore - Zustand des Players nicht sichern und wiederherstellen , dadurch stoppt die Wiedergabe nach Abspielen des TTS . </li>
<li> forcegroupon - Player in der Gruppe werden eingeschaltet . </li>
2017-05-28 19:14:57 +00:00
<li> ignorevolumelimit - Attribut volumeLimit f & uuml ; r die TTS - Ausgabe ignorieren . </li>
<li> eventondone - Erzeugt ein Event wenn die Sprachausgabe zu Ende ist . </li>
2016-10-01 16:46:46 +00:00
</ul> </li>
<li> ttsPrefix & lt ; text & gt ; <br>
Text , der vor jede TTS - Ausgabe gehangen wird </li>
<li> ttsVolume & lt ; value & gt ; <br>
Lautst & auml ; rke f & uuml ; r die TTS - Ausgabe . Standardwert ist die gegenw & auml ; rtige Lautst & auml ; rke . Wenn das Attribut
ttsOption ignorevolumelimit angegeben worden ist , wird das eingestellte Lautst & auml ; rkelimit bei
TTS nicht beachtet . </li>
<li> updateReadingsOnSet true | false <br>
Wird ein Befehl ausgef & uuml ; hrt , werden die Readings erst aktualisiert , wenn die Antwort des LMS eintrifft .
Ist dieses Attribut auf true gesetzt , wird die Antwort nicht abgewartet , sondern die Readings werden
soweit wie m & ouml ; glich sofort aktualisiert . </li>
<li> volumeLimit & lt ; value & gt ; <br>
Oberer Grenzwert zur Lautst & auml ; rkeeinstellung durch FHEM . </li>
2017-05-28 19:14:57 +00:00
<li> volumeOffset & lt ; value & gt ; <br>
Offset der zur Lautst <EFBFBD> rke die zum LMS geschickt wird addiert wird . F <EFBFBD> r die Anzeige der aktuellen Lautst <EFBFBD> rke wird der
Wert von der vom LMS geschickten Lautst <EFBFBD> rke abgezogen . </li>
2016-10-01 16:46:46 +00:00
<li> volumeStep & lt ; value & gt ; <br>
Hier wird die Granularit & auml ; t der Lautst & auml ; rkeregelung festgelegt . Default ist 10 </li>
</ul>
</ul>
= end html_DE
2014-11-09 18:01:21 +00:00
= cut