@@ -30,7 +30,7 @@ function sepiaFW_build_client_controls(sepiaSessionId){
3030 //Wait for opportunity and send a message (e.g. "some text" or "<error_client_control_0a>") and optionally show info fallback.
3131 function sendFollowUpMessage ( msgOrAnswerTag , info , deliveredCallback , fallbackCallback , sourceTag , blockIfScheduled ) {
3232 var minWait = 2000 ;
33- var maxWait = 30000 ;
33+ var maxWait = 20000 ;
3434 if ( sourceTag && blockIfScheduled ) {
3535 if ( followUpsRunning [ sourceTag ] && ( new Date ( ) . getTime ( ) - followUpsRunning [ sourceTag ] ) <= maxWait ) {
3636 //block
@@ -59,6 +59,29 @@ function sepiaFW_build_client_controls(sepiaSessionId){
5959 }
6060 var followUpsRunning = { } ;
6161
62+ //Media player/search error follow-up messages
63+ Controls . sendMediaPlayerErrorFollowUpMessage = function ( errorType , deliveredCallback , fallbackCallback ) {
64+ if ( errorType == "notPossible" ) {
65+ //"can't execute" - alt.: <error_client_control_0a>: "control function could not be executed"
66+ sendFollowUpMessage (
67+ SepiaFW . local . g ( 'cant_execute' ) , SepiaFW . local . g ( 'cant_execute' ) ,
68+ deliveredCallback , fallbackCallback , "controls.mediaSearch.notPossible" , true
69+ ) ;
70+ } else if ( errorType == "notFound" ) {
71+ //"found nothing to play"
72+ sendFollowUpMessage (
73+ "<error_media_player_0b>" , SepiaFW . local . g ( 'no_media_found' ) ,
74+ deliveredCallback , fallbackCallback , "controls.mediaSearch.notFound" , true
75+ ) ;
76+ } else {
77+ //"media playback error"
78+ sendFollowUpMessage (
79+ "<error_media_player_0a>" , SepiaFW . local . g ( 'cant_execute' ) ,
80+ deliveredCallback , fallbackCallback , "controls.mediaSearch.error" , true
81+ ) ;
82+ }
83+ }
84+
6285 //Open/close settings menu
6386 Controls . settings = function ( controlData ) {
6487 if ( controlData && controlData . action ) {
@@ -158,6 +181,8 @@ function sepiaFW_build_client_controls(sepiaSessionId){
158181 //2) client player (outside app but with full or partial fade support)
159182 //3) remote player (no fade control, but start/stop etc.)
160183 SepiaFW . debug . info ( "Client controls - Media action: " + controlData . action ) ;
184+
185+ var emp = SepiaFW . ui . cards . embed . getActiveMediaPlayer ( ) ;
161186
162187 //STOP
163188 if ( controlData . action == "stop" || controlData . action == "pause" || controlData . action == "close" ) {
@@ -169,14 +194,15 @@ function sepiaFW_build_client_controls(sepiaSessionId){
169194 }
170195 //Player and platform specific additional STOP methods
171196 var sentAdditionalEvent = false ;
172- if ( SepiaFW . ui . cards . youTubePlayerGetState ( ) == 1 || SepiaFW . ui . cards . youTubePlayerIsOnHold ( ) ) {
173- //YouTube embedded player
174- SepiaFW . debug . info ( "Client controls - Media: stopping YouTube media player" ) ;
175- sentAdditionalEvent = ( SepiaFW . ui . cards . youTubePlayerControls ( "stop" ) > 0 ) ;
197+ if ( emp && ( emp . isPlaying ( ) || emp . isOnHold ( ) ) ) {
198+ //Embedded media player
199+ emp . pause ( ) ;
200+ sentAdditionalEvent = true ;
201+ SepiaFW . debug . info ( "Client controls - Media: stopping embedded media player" ) ;
176202 } else if ( SepiaFW . ui . isAndroid ) {
177203 //we do this only if we have a recent Android media event - otherwhise it will activate all music apps
178204 var requireMediaAppPackage = true ;
179- SepiaFW . debug . info ( "Client controls - Media: stopping Android media player" ) ;
205+ SepiaFW . debug . info ( "Client controls - Media: trying to stop Android media player" ) ;
180206 sentAdditionalEvent = SepiaFW . android . broadcastMediaButtonDownUpIntent ( 127 , requireMediaAppPackage ) ;
181207 //127: KEYCODE_MEDIA_PAUSE
182208 }
@@ -197,31 +223,37 @@ function sepiaFW_build_client_controls(sepiaSessionId){
197223 //try to find last active player
198224 var lastActivePlayer = SepiaFW . audio . getLastActiveAudioStreamPlayer ( ) ;
199225 var isAnyPlayerStreaming = SepiaFW . audio . isAnyAudioSourceActive ( ) ;
226+ var sentEvent = false ;
227+
200228 if ( ! isAnyPlayerStreaming ) {
201- var sentAdditionalEvent = false ;
202-
203- //try right order first
229+ //find last active player to resume
204230 if ( ! lastActivePlayer ) {
205231 //TODO: ?
206232
207233 } else if ( lastActivePlayer == "stream" ) {
208234 //Internal stream
209- sentAdditionalEvent = SepiaFW . audio . resumeLastAudioStream ( ) ;
235+ SepiaFW . debug . info ( "Client controls - Media: resuming internal media player" ) ;
236+ sentEvent = SepiaFW . audio . resumeLastAudioStream ( ) ;
210237
211- } else if ( lastActivePlayer == "youtube-embedded" && SepiaFW . ui . cards . youTubePlayerGetState ( ) == 2 ) { //2: paused
212- //YouTube embedded player
213- sentAdditionalEvent = ( SepiaFW . ui . cards . youTubePlayerControls ( "resume" ) > 0 ) ;
238+ } else if ( lastActivePlayer == "embedded-media-player" ) {
239+ //Embedded media player
240+ if ( emp && ( emp . isPaused ( ) || emp . isReady ( ) ) ) {
241+ SepiaFW . debug . info ( "Client controls - Media: resuming embedded media player" ) ;
242+ sentEvent = true ;
243+ emp . play ( ) ;
244+ }
214245
215246 } else if ( lastActivePlayer == "android-intent" && SepiaFW . ui . isAndroid ) {
216247 //we do this only if we have a recent Android media event - otherwhise it will activate all music apps
248+ SepiaFW . debug . info ( "Client controls - Media: trying to resume Android media player" ) ;
217249 var requireMediaAppPackage = true ;
218- sentAdditionalEvent = SepiaFW . android . broadcastMediaButtonDownUpIntent ( 126 , requireMediaAppPackage ) ;
250+ sentEvent = SepiaFW . android . broadcastMediaButtonDownUpIntent ( 126 , requireMediaAppPackage ) ;
219251 //126: KEYCODE_MEDIA_PLAY
220252 }
221253 }
222254 //TODO: add iOS and Windows?
223255 //TODO: we could use a Mesh-Node and the sendMessage API in Windows
224- if ( ! isInternalPlayerStreaming && ! sentAdditionalEvent && ! controlData . skipFollowUp ) {
256+ if ( ! isAnyPlayerStreaming && ! sentEvent && ! controlData . skipFollowUp ) {
225257 //The user has probably tried to resume an external app but that was not possible
226258 var blockMultiple = true ;
227259 var source = "controls.media.resume" ;
@@ -233,36 +265,40 @@ function sepiaFW_build_client_controls(sepiaSessionId){
233265
234266 //NEXT
235267 } else if ( controlData . action == "next" ) {
236- SepiaFW . audio . startNextMusicStreamOfQueue ( function ( ) { } , function ( err ) {
237- //Failed to execute NEXT on internal player:
238-
239- //Player or platform specific additional NEXT methods
240- if ( SepiaFW . ui . cards . youTubePlayerGetState ( ) > 0 ) {
241- //YouTube embedded player
242- SepiaFW . ui . cards . youTubePlayerControls ( "next" ) ;
268+ //try to find last active player
269+ var lastActivePlayer = SepiaFW . audio . getLastActiveAudioStreamPlayer ( ) ;
270+ var sentEvent = false ;
243271
244- } else if ( SepiaFW . ui . isAndroid ) {
245- //Stop internal player
246- if ( SepiaFW . audio . isMusicPlayerStreaming ( ) ) {
247- SepiaFW . audio . stop ( SepiaFW . audio . getMusicPlayer ( ) ) ;
248- }
249- //we do this only if we have a recent Android media event - otherwhise it will activate all music apps
250- var requireMediaAppPackage = true ;
251- SepiaFW . android . broadcastMediaButtonDownUpIntent ( 87 , requireMediaAppPackage ) ; //87: KEYCODE_MEDIA_NEXT
252-
253- //Out of options ... for now
254- } else if ( ! controlData . skipFollowUp ) {
255- var blockMultiple = true ;
256- var source = "controls.media.next" ;
257- sendFollowUpMessage (
258- "<default_under_construction_0b>" , SepiaFW . local . g ( 'no_client_support' ) + " Media: NEXT" ,
259- undefined , undefined , source , blockMultiple
260- ) ;
261- SepiaFW . debug . error ( "Client controls - Unsupported action in 'media': " + controlData . action ) ;
272+ //find right player
273+ if ( ! lastActivePlayer || lastActivePlayer == "stream" ) {
274+ //NOTE: internal stream has no queue (yet?)
275+
276+ } else if ( lastActivePlayer == "embedded-media-player" ) {
277+ //Embedded media player
278+ if ( emp && emp . isReady ( ) ) {
279+ SepiaFW . debug . info ( "Client controls - Media: triggering 'next' via embedded media player" ) ;
280+ sentEvent = true ;
281+ emp . next ( ) ;
262282 }
263- //TODO: add iOS and Windows?
264- //TODO: we could use a Mesh-Node and the sendMessage API in Windows
265- } ) ;
283+
284+ } else if ( lastActivePlayer == "android-intent" && SepiaFW . ui . isAndroid ) {
285+ //we do this only if we have a recent Android media event - otherwhise it will activate all music apps
286+ SepiaFW . debug . info ( "Client controls - Media: trying to trigger 'next' via Android media player" ) ;
287+ var requireMediaAppPackage = true ;
288+ sentEvent = SepiaFW . android . broadcastMediaButtonDownUpIntent ( 87 , requireMediaAppPackage ) ; //87: KEYCODE_MEDIA_NEXT
289+ }
290+ //TODO: add iOS and Windows?
291+ //TODO: we could use a Mesh-Node and the sendMessage API in Windows
292+ if ( ! sentEvent && ! controlData . skipFollowUp ) {
293+ //Out of options ... for now
294+ var blockMultiple = true ;
295+ var source = "controls.media.next" ;
296+ sendFollowUpMessage (
297+ "<default_under_construction_0b>" , SepiaFW . local . g ( 'no_client_support' ) + " Media: NEXT" ,
298+ undefined , undefined , source , blockMultiple
299+ ) ;
300+ SepiaFW . debug . error ( "Client controls - Unsupported action in 'media': " + controlData . action ) ;
301+ }
266302
267303 } else {
268304 var blockMultiple = true ;
@@ -305,27 +341,46 @@ function sepiaFW_build_client_controls(sepiaSessionId){
305341 skipFollowUp : true
306342 } ) ;
307343
308- //Embedded Player - TODO: check if service has web-player support
309- if ( controlData . uri && ( SepiaFW . ui . cards . canEmbedWebPlayer ( controlData . service ) || controlData . service . indexOf ( "_embedded" ) > 0 ) ) {
310- //just skip, cards will do the rest...
311- //YouTube
312- //if (controlData.service.indexOf("youtube") == 0){}
344+ //Embedded Player
345+ if ( controlData . service && ( controlData . service == "embedded" || controlData . service . indexOf ( "_embedded" ) >= 0 )
346+ && SepiaFW . ui . cards . canEmbedWebPlayer ( controlData . service ) ) {
347+ //NOTE: this should be handled by attached cards request...
348+ //TODO: if we want to use this via remote-action (not supported atm) we need to build the card by hand ...
349+ //console.error("Controls.searchForMusic", controlData); //DEBUG
313350
314351 //Android Intent music search
315352 } else if ( SepiaFW . ui . isAndroid && ( ! controlData . service || controlData . service . indexOf ( "_link" ) == - 1 ) ) {
316353 var allowSpecificService = true ;
317354 SepiaFW . android . startMusicSearchActivity ( controlData , allowSpecificService , function ( err ) {
318355 //error callback
319356 if ( err . code == 1 ) {
320- sendFollowUpMessage ( "<error_client_control_0a>" , SepiaFW . local . g ( 'cant_execute' ) ) ;
357+ var blockMultiple = true ;
358+ var source = "controls.searchForMusic.error" ;
359+ //"problem with the music player"
360+ sendFollowUpMessage (
361+ "<server_music_0b>" , SepiaFW . local . g ( 'cant_execute' ) , //alt.: <error_client_control_0a>: "control function could not be executed"
362+ undefined , undefined , source , blockMultiple
363+ ) ;
321364 } else if ( err . code == 2 ) {
322- sendFollowUpMessage ( "<music_0b>" , SepiaFW . local . g ( 'no_music_playing' ) ) ;
365+ var blockMultiple = true ;
366+ var source = "controls.searchForMusic.notFound" ;
367+ //"music not found"
368+ sendFollowUpMessage (
369+ "<music_0b>" , SepiaFW . local . g ( 'no_music_playing' ) ,
370+ undefined , undefined , source , blockMultiple
371+ ) ;
323372 }
373+ //NOTE: we could use 'Controls.sendMediaPlayerErrorFollowUpMessage' instead
324374 } ) ;
325375
326376 //Supported app?
327377 } else if ( controlData . service && ! SepiaFW . config . getMusicAppCollection ( ) [ controlData . service ] ) {
328- sendFollowUpMessage ( SepiaFW . local . g ( 'cant_execute' ) , SepiaFW . local . g ( 'cant_execute' ) ) ; //"<error_client_control_0a>"
378+ var blockMultiple = true ;
379+ var source = "controls.searchForMusic.notPossible" ;
380+ sendFollowUpMessage (
381+ SepiaFW . local . g ( 'cant_execute' ) , SepiaFW . local . g ( 'cant_execute' ) , //"<error_client_control_0a>"
382+ undefined , undefined , source , blockMultiple
383+ ) ;
329384 SepiaFW . debug . error ( "Client controls - 'searchForMusic' is trying to use an app that is not supported by this client!" ) ;
330385
331386 //Common URI fallback or fail
@@ -337,8 +392,13 @@ function sepiaFW_build_client_controls(sepiaSessionId){
337392 }
338393 SepiaFW . ui . actions . openUrlAutoTarget ( controlData . uri ) ;
339394 } else {
340- //Feedback (to server and user)
341- sendFollowUpMessage ( "<music_0b>" , SepiaFW . local . g ( 'cant_execute' ) ) ; //<error_client_control_0a>
395+ var blockMultiple = true ;
396+ var source = "controls.searchForMusic.notFound" ;
397+ //"music not found"
398+ sendFollowUpMessage (
399+ "<music_0b>" , SepiaFW . local . g ( 'cant_execute' ) , //alt.: <error_client_control_0a>: "control function could not be executed"
400+ undefined , undefined , source , blockMultiple
401+ ) ;
342402 SepiaFW . debug . error ( "Client controls - 'searchForMusic' is missing URI data and has no other options to search for music!" ) ;
343403 }
344404 }
0 commit comments