Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
189 lines
5.2 KiB
JavaScript
Executable file
189 lines
5.2 KiB
JavaScript
Executable file
/* 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));
|
|
}
|
|
}
|
|
};
|