VulpesOS/gaia/apps/music/js/remote.js
OverSu b38dea0597 Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
2026-09-30 23:13:03 +02:00

179 lines
5.3 KiB
JavaScript
Executable file

/* exported Remote */
/* global LazyLoader, MediaRemoteControls, bridge */
'use strict';
var Remote = (function() {
const PLAY_STATUS_INTERRUPTED = 'mozinterruptbegin';
const PLAYSTATUS_STOPPED = 'STOPPED';
const PLAY_STATUS_PAUSED = 'PAUSED';
const PLAY_STATUS_PLAYING = 'PLAYING';
var Remote = {
enabled: false,
isSCOEnabled: false,
updateMetadata: function() {
if (Remote.enabled) {
client.method('getPlaybackStatus').then((status) => {
client.method('getSong', status.filePath).then((song) => {
if (!song) {
return;
}
client.method('getSongThumbnail', status.filePath).then((blob) => {
document.l10n.formatValues(
'unknownTitle', 'unknownArtist', 'unknownAlbum'
).then(([unknownTitle, unknownArtist, unknownAlbum]) => {
mrc.notifyMetadataChanged({
title: song.metadata.title || unknownTitle,
artist: song.metadata.artist || unknownArtist,
album: song.metadata.album || unknownAlbum,
mediaNumber: status.queueRawIndex,
totalMediaCount: status.queueLength,
duration: status.duration,
picture: blob
});
});
});
});
});
}
},
updatePlaybackStatus: function() {
if (Remote.enabled) {
client.method('getPlaybackStatus').then((status) => {
var playStatus = status.stopped ? PLAYSTATUS_STOPPED :
(status.paused ? PLAY_STATUS_PAUSED : PLAY_STATUS_PLAYING);
if (status.isInterrupted) {
playStatus = PLAY_STATUS_INTERRUPTED;
}
mrc.notifyStatusChanged({
playStatus: playStatus,
duration: status.duration,
position: status.elapsedTime
});
});
}
}
};
var mrc; // Lazy-initialized
var client = bridge.client({
service: 'music-service',
endpoint: window,
timeout: false
});
var commands = {
play: function(evt) {
commands.playpause(evt);
},
// 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(evt) {
var isResumedBySCO = Remote.isSCOEnabled;
Remote.isSCOEnabled = evt.detail.isSCOConnected;
client.method('getPlaybackStatus').then((status) => {
// Check if it's resumed by the SCO disconnection, if so, we need to
// recover the player to the original status.
if (isResumedBySCO) {
client.method(status.paused ? 'play' : 'pause');
} else {
// Play in shuffle order if music app is launched remotely.
if (!status.filePath) {
client.method('queuePlaylist', 'shuffle-all');
} else {
client.method(status.paused ? 'play' : 'pause');
}
}
});
},
pause: function(evt) {
Remote.isSCOEnabled = evt.detail.isSCOConnected;
client.method('pause');
},
stop: function() {
client.method('pause');
},
next: function() {
client.method('nextSong');
},
previous: function() {
client.method('previousSong');
},
seekpress: function(evt) {
client.method('startFastSeek', evt.detail.direction === -1);
},
seekrelease: function() {
client.method('stopFastSeek');
},
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.
Remote.updateMetadata();
},
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.
Remote.updatePlaybackStatus();
}
};
var scripts = [
'/shared/js/bluetooth_helper.js',
'/shared/js/media/remote_controls.js'
];
LazyLoader.load(scripts).then(() => {
mrc = new MediaRemoteControls();
for (var command in commands) {
mrc.addCommandListener(command, commands[command]);
}
mrc.start(() => {
if (Remote.enabled) {
mrc.getSCOStatus(status => Remote.isSCOEnabled = status);
}
});
mrc.notifyAppInfo({
origin: window.location.origin,
icon: window.location.origin + '/style/icons/music_84.png'
});
client.on('songChange', Remote.updateMetadata);
client.on('play', Remote.updatePlaybackStatus);
client.on('pause', Remote.updatePlaybackStatus);
client.on('stop', Remote.updatePlaybackStatus);
client.on('elapsedTimeChange', Remote.updatePlaybackStatus);
client.on('interruptBegin', Remote.updatePlaybackStatus);
client.on('interruptEnd', Remote.updatePlaybackStatus);
Remote.enabled = true;
});
return Remote;
})();