Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
189 lines
5.2 KiB
JavaScript
189 lines
5.2 KiB
JavaScript
/* exported MusicComms */
|
|
/* global Database, INTERRUPT_BEGIN, MediaRemoteControls, ModeManager,
|
|
MODE_PLAYER, PlaybackQueue, PlayerView, PLAYSTATUS_PLAYING,
|
|
PLAYSTATUS_STOPPED */
|
|
'use strict';
|
|
|
|
var MusicComms = {
|
|
commands: {
|
|
play: function(event) {
|
|
this.commands.playpause.call(this, event);
|
|
},
|
|
|
|
// For those bluetooth devices that do not keep, request or receive
|
|
// the play status, because the play status may not sync with the player,
|
|
// they will just send "play" or "playpause" when pressing the "playpause"
|
|
// button, so for the "play" and "playpause" commands, we will check
|
|
// the play status for the player then decide we should play or pause.
|
|
playpause: function(event) {
|
|
this._getPlayerReady(() => {
|
|
var isResumedBySCO = this.isSCOEnabled;
|
|
this.isSCOEnabled = event.detail.isSCOConnected;
|
|
|
|
// Check if it's resumed by the SCO disconnection, if so, we need to
|
|
// recover the player to the original status.
|
|
if (isResumedBySCO) {
|
|
if (this._statusBeforeSCO === PLAYSTATUS_PLAYING ||
|
|
this._statusBeforeSCO === INTERRUPT_BEGIN) {
|
|
PlayerView.play();
|
|
} else {
|
|
PlayerView.pause();
|
|
}
|
|
} else {
|
|
// Play in shuffle order if music app is launched remotely.
|
|
if (PlayerView.playStatus === PLAYSTATUS_STOPPED) {
|
|
Database.count('metadata.title', null, (count) => {
|
|
var info = {
|
|
key: 'metadata.title',
|
|
range: null,
|
|
direction: 'next',
|
|
option: 'title',
|
|
count: count
|
|
};
|
|
|
|
PlaybackQueue.shuffle = true;
|
|
PlayerView.activate(new PlaybackQueue.DynamicQueue(info));
|
|
PlayerView.start();
|
|
});
|
|
} else if (PlayerView.playStatus === PLAYSTATUS_PLAYING) {
|
|
PlayerView.pause();
|
|
} else {
|
|
PlayerView.play();
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
pause: function(event) {
|
|
this.isSCOEnabled = event.detail.isSCOConnected;
|
|
|
|
if (!this._isPlayerActivated()) {
|
|
return;
|
|
}
|
|
|
|
// Record the current play status so that we can recover the player to
|
|
// the original status after SCO is disconnected.
|
|
if (this.isSCOEnabled) {
|
|
this._statusBeforeSCO = PlayerView.playStatus;
|
|
}
|
|
|
|
PlayerView.pause();
|
|
},
|
|
|
|
stop: function(event) {
|
|
if (!this._isPlayerActivated()) {
|
|
return;
|
|
}
|
|
|
|
PlayerView.stop();
|
|
},
|
|
|
|
next: function(event) {
|
|
if (!this._isPlayerActivated()) {
|
|
return;
|
|
}
|
|
|
|
PlayerView.next();
|
|
},
|
|
|
|
previous: function(event) {
|
|
if (!this._isPlayerActivated()) {
|
|
return;
|
|
}
|
|
|
|
PlayerView.previous();
|
|
},
|
|
|
|
seekpress: function(event) {
|
|
if (!this._isPlayerActivated()) {
|
|
return;
|
|
}
|
|
|
|
if (!PlayerView.isTouching) {
|
|
PlayerView.startFastSeeking(event.detail.direction);
|
|
}
|
|
},
|
|
|
|
seekrelease: function(event) {
|
|
if (!this._isPlayerActivated()) {
|
|
return;
|
|
}
|
|
|
|
PlayerView.stopFastSeeking();
|
|
},
|
|
|
|
updatemetadata: function() {
|
|
// After A2DP is connected, some bluetooth devices will try to synchronize
|
|
// the playing metadata with the player, if the player is not ready, we
|
|
// have to initial the player to have the metadata, even the player is
|
|
// stopped.
|
|
this._getPlayerReady(function() {
|
|
PlayerView.updateRemoteMetadata();
|
|
});
|
|
},
|
|
|
|
updateplaystatus: function() {
|
|
// After A2DP is connected, some bluetooth devices will try to synchronize
|
|
// the playstatus with the player, if the player is not ready, we have to
|
|
// initial the player to have the play status.
|
|
this._getPlayerReady(function() {
|
|
PlayerView.updateRemotePlayStatus();
|
|
});
|
|
}
|
|
},
|
|
|
|
enabled: false,
|
|
|
|
isSCOEnabled: false,
|
|
|
|
_statusBeforeSCO: null,
|
|
|
|
init: function() {
|
|
// The Media Remote Controls object will handle the remote commands.
|
|
this.mrc = new MediaRemoteControls();
|
|
// Add command listeners base on what commands the MusicComms has.
|
|
for (var command in this.commands) {
|
|
this.mrc.addCommandListener(command, this.commands[command].bind(this));
|
|
}
|
|
|
|
// Update the SCO status after the mrc is ready, so that we can know the
|
|
// current SCO connection and reflect it to the player.
|
|
this.mrc.start(this.updateSCOStatus.bind(this));
|
|
|
|
this.mrc.notifyAppInfo({
|
|
origin: window.location.origin,
|
|
icon: window.location.origin + '/style/icons/default_84.png'
|
|
});
|
|
|
|
this.enabled = true;
|
|
},
|
|
|
|
_getPlayerReady: function(callback) {
|
|
ModeManager.waitForView(MODE_PLAYER, callback);
|
|
},
|
|
|
|
_isPlayerActivated: function() {
|
|
return (typeof PlayerView !== 'undefined' &&
|
|
PlayerView.playStatus !== PLAYSTATUS_STOPPED);
|
|
},
|
|
|
|
notifyMetadataChanged: function(metadata) {
|
|
if (this.enabled) {
|
|
this.mrc.notifyMetadataChanged(metadata);
|
|
}
|
|
},
|
|
|
|
notifyStatusChanged: function(info) {
|
|
if (this.enabled) {
|
|
this.mrc.notifyStatusChanged(info);
|
|
}
|
|
},
|
|
|
|
updateSCOStatus: function() {
|
|
if (this.enabled) {
|
|
this.mrc.getSCOStatus(function(status) {
|
|
this.isSCOEnabled = status;
|
|
}.bind(this));
|
|
}
|
|
}
|
|
};
|