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.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View file

@ -0,0 +1,179 @@
/* 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;
})();