Skip to content

Commit 72cfd8d

Browse files
committed
improved client media controls; embedded player beta upgrade (wip);
1 parent 87d5934 commit 72cfd8d

9 files changed

+271
-265
lines changed

www/scripts/sepiaFW.audio.js

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -231,13 +231,6 @@ function sepiaFW_build_audio(){
231231
&& !player.ended
232232
&& player.readyState > 2;
233233
}
234-
AudioPlayer.startNextMusicStreamOfQueue = function(successCallback, errorCallback){
235-
//TODO: Currently the only thing 'player' can do is stream radio or URL, so this will always return ERROR for now.
236-
if (errorCallback) errorCallback({
237-
error: "No next stream available",
238-
status: 1
239-
});
240-
}
241234
AudioPlayer.getEffectsPlayer = function(){
242235
return player2;
243236
}
@@ -249,10 +242,11 @@ function sepiaFW_build_audio(){
249242
AudioPlayer.isAnyAudioSourceActive = function(){
250243
//Stop internal player
251244
var isInternalPlayerStreaming = Stream.isLoading || AudioPlayer.isMusicPlayerStreaming() || AudioPlayer.isMainOnHold() || TTS.isPlaying;
252-
var isYouTubePlayerStreaming = SepiaFW.ui.cards.youTubePlayerGetState() == 1 || SepiaFW.ui.cards.youTubePlayerIsOnHold();
245+
var emp = SepiaFW.ui.cards.embed.getActiveMediaPlayer();
246+
var isEmbeddedMediaPlayerStreaming = emp && emp.isActive();
253247
var isAndroidPlayerStreaming = SepiaFW.ui.isAndroid && SepiaFW.android.lastReceivedMediaData && SepiaFW.android.lastReceivedMediaData.playing
254248
&& ((new Date().getTime() - SepiaFW.android.lastReceivedMediaAppTS) < (1000*60*15)); //This is pure guessing ...
255-
return isInternalPlayerStreaming || isYouTubePlayerStreaming || isAndroidPlayerStreaming;
249+
return isInternalPlayerStreaming || isEmbeddedMediaPlayerStreaming || isAndroidPlayerStreaming;
256250
}
257251
AudioPlayer.getLastActiveAudioStreamPlayer = function(){
258252
return lastAudioPlayerEventSource;
@@ -323,10 +317,10 @@ function sepiaFW_build_audio(){
323317
AudioPlayer.broadcastAudioEvent = function(source, action, playerObject){
324318
//stream, effects, tts-player, unknown - prepare, start, stop, error, fadeOut, fadeIn
325319
//android-intent - stop, start
326-
//youtube-embedded - start, resume, pause, hold
320+
//embedded-media-player - start, resume, pause, hold
327321
source = source.toLowerCase();
328322
action = action.toLowerCase();
329-
if (source == "stream" || source.indexOf("youtube") >= 0 || source.indexOf("android") >= 0){
323+
if (source == "stream" || source == "embedded-media-player" || source.indexOf("android") >= 0){
330324
lastAudioPlayerEventSource = source;
331325
}
332326
var event = new CustomEvent('sepia_audio_player_event', { detail: {
@@ -705,7 +699,7 @@ function sepiaFW_build_audio(){
705699
SepiaFW.debug.error("AudioPlayer.registerNewFadeListener - not a valid object to register!");
706700
//valid obejct example:
707701
/* {
708-
id: "youtube",
702+
id: "embedded-media-player",
709703
isOnHold: myFunA, (return true/false)
710704
onFadeOutRequest: myFunB, (return true/false, param: force)
711705
onFadeInRequest: myFunC (return true/false)

www/scripts/sepiaFW.client.controls.js

Lines changed: 113 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

www/scripts/sepiaFW.frames.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ function sepiaFW_build_frames(){
156156

157157
Frames.setup = function(info, finishCallback){
158158
//get HTML - is there a language dependent version?
159-
var framePage = Frames.getLocalOrDefaultPage(info.pageUrl, SepiaFW.config.appLanguage);
159+
var framePage = Frames.getLocalOrDefaultPage(info.pageUrl, SepiaFW.config.appLanguage).trim();
160160
var isRemote = (framePage.indexOf("http:") == 0) || (framePage.indexOf("https:") == 0) || (framePage.indexOf("ftp:") == 0);
161161
if (isRemote){
162162
var isSameOrigin = SepiaFW.tools.isSameOrigin(framePage);

www/scripts/sepiaFW.local.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ function sepiaFW_build_strings(){
169169
//Service and action texts
170170
StringsDE.opening_link = "Link wird geöffnet.";
171171
StringsDE.no_music_playing = "Kannst du was hören? Wahrscheinlich wurde keine Musik gefunden.";
172+
StringsDE.no_media_found = "Es wurde nichts zum Abspielen gefunden.";
172173
StringsDE.remote_action = "Remote-Zugriff";
173174
StringsDE.remote_action_audio_stream = "ich habe einen Audio Stream via Remote-Zugriff empfangen. Stream wird gestartet.";
174175
StringsDE.remote_action_notify = "ich habe eine Benachrichtigung für dich.";
@@ -380,6 +381,7 @@ function sepiaFW_build_strings(){
380381
//Service and action texts
381382
StringsEN.opening_link = "Opening link.";
382383
StringsEN.no_music_playing = "Can you hear something? Probably no music found.";
384+
StringsEN.no_media_found = "Found no media to play.";
383385
StringsEN.remote_action = "Remote access";
384386
StringsEN.remote_action_audio_stream = "I've received an audio stream via remote access. Starting now.";
385387
StringsEN.remote_action_notify = "I have a message for you.";

0 commit comments

Comments
 (0)