Merge pull request #1456 from ciderapp/enhancement/mediaSessionAPI
Enhancement/media session api
This commit is contained in:
commit
ef06ab8fd2
4 changed files with 151 additions and 58 deletions
4
.github/workflows/pr-chores.yml
vendored
4
.github/workflows/pr-chores.yml
vendored
|
@ -29,9 +29,9 @@ jobs:
|
||||||
|
|
||||||
- name: Install dependencies 👨🏻💻
|
- name: Install dependencies 👨🏻💻
|
||||||
run: pnpm install
|
run: pnpm install
|
||||||
|
|
||||||
- name: Run linter 👀
|
- name: Run linter 👀
|
||||||
uses: wearerequired/lint-action@v2
|
uses: wearerequired/lint-action@v2
|
||||||
with:
|
with:
|
||||||
prettier: true
|
prettier: true
|
||||||
prettier_args: "'**/*.{js,json,ts,css,vue,less}'"
|
prettier_args: "'src/**/*.{js,json,ts,css,vue,less}'"
|
||||||
|
|
|
@ -200,15 +200,11 @@ export class wsapi {
|
||||||
response.message = "Unmuted";
|
response.message = "Unmuted";
|
||||||
break;
|
break;
|
||||||
case "next":
|
case "next":
|
||||||
this._win.webContents.executeJavaScript(`if (MusicKit.getInstance().queue.nextPlayableItemIndex != -1 && MusicKit.getInstance().queue.nextPlayableItemIndex != null) {
|
this._win.webContents.executeJavaScript(`MusicKitInterop.next()`);
|
||||||
try {
|
|
||||||
app.prevButtonBackIndicator = false;
|
|
||||||
} catch (e) { }
|
|
||||||
MusicKit.getInstance().changeToMediaAtIndex(MusicKit.getInstance().queue.nextPlayableItemIndex);}`);
|
|
||||||
response.message = "Next";
|
response.message = "Next";
|
||||||
break;
|
break;
|
||||||
case "previous":
|
case "previous":
|
||||||
this._win.webContents.executeJavaScript(`if (MusicKit.getInstance().queue.previousPlayableItemIndex != -1 && MusicKit.getInstance().queue.previousPlayableItemIndex != null) {MusicKit.getInstance().changeToMediaAtIndex(MusicKit.getInstance().queue.previousPlayableItemIndex)}`);
|
this._win.webContents.executeJavaScript(`MusicKitInterop.previous()`);
|
||||||
response.message = "Previous";
|
response.message = "Previous";
|
||||||
break;
|
break;
|
||||||
case "musickit-api":
|
case "musickit-api":
|
||||||
|
|
|
@ -10,6 +10,7 @@ const MusicKitInterop = {
|
||||||
MusicKit.getInstance().addEventListener(MusicKit.Events.playbackStateDidChange, () => {
|
MusicKit.getInstance().addEventListener(MusicKit.Events.playbackStateDidChange, () => {
|
||||||
const attributes = MusicKitInterop.getAttributes();
|
const attributes = MusicKitInterop.getAttributes();
|
||||||
if (!attributes) return;
|
if (!attributes) return;
|
||||||
|
MusicKitInterop.updateMediaState(attributes);
|
||||||
if (MusicKitInterop.filterTrack(attributes, true, false)) {
|
if (MusicKitInterop.filterTrack(attributes, true, false)) {
|
||||||
global.ipcRenderer.send("playbackStateDidChange", attributes);
|
global.ipcRenderer.send("playbackStateDidChange", attributes);
|
||||||
global.ipcRenderer.send("wsapi-updatePlaybackState", attributes);
|
global.ipcRenderer.send("wsapi-updatePlaybackState", attributes);
|
||||||
|
@ -35,6 +36,7 @@ const MusicKitInterop = {
|
||||||
const attributes = MusicKitInterop.getAttributes();
|
const attributes = MusicKitInterop.getAttributes();
|
||||||
if (!attributes) return;
|
if (!attributes) return;
|
||||||
ipcRenderer.send("playbackTimeDidChange", attributes);
|
ipcRenderer.send("playbackTimeDidChange", attributes);
|
||||||
|
MusicKitInterop.updatePositionState(attributes);
|
||||||
});
|
});
|
||||||
|
|
||||||
/* MusicKit.Events.nowPlayingItemDidChange */
|
/* MusicKit.Events.nowPlayingItemDidChange */
|
||||||
|
@ -43,6 +45,7 @@ const MusicKitInterop = {
|
||||||
if (!attributes) return;
|
if (!attributes) return;
|
||||||
attributes.primaryArtist = app.cfg.connectivity.lastfm.remove_featured ? await this.fetchSongRelationships() : attributes.artistName;
|
attributes.primaryArtist = app.cfg.connectivity.lastfm.remove_featured ? await this.fetchSongRelationships() : attributes.artistName;
|
||||||
|
|
||||||
|
MusicKitInterop.updateMediaSession(attributes);
|
||||||
global.ipcRenderer.send("nowPlayingItemDidChange", attributes);
|
global.ipcRenderer.send("nowPlayingItemDidChange", attributes);
|
||||||
|
|
||||||
if (MusicKitInterop.filterTrack(attributes, false, true)) {
|
if (MusicKitInterop.filterTrack(attributes, false, true)) {
|
||||||
|
@ -142,7 +145,7 @@ const MusicKitInterop = {
|
||||||
|
|
||||||
attributes.songId = attributes.songId ?? attributes.playParams?.catalogId ?? attributes.playParams?.id;
|
attributes.songId = attributes.songId ?? attributes.playParams?.catalogId ?? attributes.playParams?.id;
|
||||||
attributes.type = nowPlayingItem?.type ?? "";
|
attributes.type = nowPlayingItem?.type ?? "";
|
||||||
attributes.status = isPlayingExport ?? null;
|
attributes.status = nowPlayingItem == null ? null : !!isPlayingExport;
|
||||||
attributes.name = attributes?.name ?? "no-title-found";
|
attributes.name = attributes?.name ?? "no-title-found";
|
||||||
attributes.artwork = attributes?.artwork ?? { url: "" };
|
attributes.artwork = attributes?.artwork ?? { url: "" };
|
||||||
attributes.artwork.url = (attributes?.artwork?.url ?? "").replace(`{f}`, "png");
|
attributes.artwork.url = (attributes?.artwork?.url ?? "").replace(`{f}`, "png");
|
||||||
|
@ -205,22 +208,139 @@ const MusicKitInterop = {
|
||||||
},
|
},
|
||||||
|
|
||||||
next: () => {
|
next: () => {
|
||||||
// try {
|
if (app) {
|
||||||
// app.prevButtonBackIndicator = false;
|
app.skipToNextItem();
|
||||||
// } catch (e) { }
|
} else {
|
||||||
// if (MusicKit.getInstance().queue.nextPlayableItemIndex != -1 && MusicKit.getInstance().queue.nextPlayableItemIndex != null)
|
MusicKit.getInstance()
|
||||||
// MusicKit.getInstance().changeToMediaAtIndex(MusicKit.getInstance().queue.nextPlayableItemIndex);
|
.skipToNextItem()
|
||||||
MusicKit.getInstance()
|
.then((r) => console.debug(`[cider:preload] [next] Skipping to Next ${r}`));
|
||||||
.skipToNextItem()
|
}
|
||||||
.then((r) => console.debug(`[cider:preload] [next] Skipping to Next ${r}`));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
previous: () => {
|
previous: () => {
|
||||||
// if (MusicKit.getInstance().queue.previousPlayableItemIndex != -1 && MusicKit.getInstance().queue.previousPlayableItemIndex != null)
|
if (app) {
|
||||||
// MusicKit.getInstance().changeToMediaAtIndex(MusicKit.getInstance().queue.previousPlayableItemIndex);
|
app.skipToPreviousItem();
|
||||||
MusicKit.getInstance()
|
} else {
|
||||||
.skipToPreviousItem()
|
MusicKit.getInstance()
|
||||||
.then((r) => console.debug(`[cider:preload] [previous] Skipping to Previous ${r}`));
|
.skipToPreviousItem()
|
||||||
|
.then((r) => console.debug(`[cider:preload] [previous] Skipping to Previous ${r}`));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
initMediaSession: () => {
|
||||||
|
if ("mediaSession" in navigator) {
|
||||||
|
const defaultSkipTime = 10;
|
||||||
|
|
||||||
|
console.debug("[cider:preload] [initMediaSession] Media Session API supported");
|
||||||
|
navigator.mediaSession.setActionHandler("play", () => {
|
||||||
|
MusicKitInterop.play();
|
||||||
|
console.log("[cider:preload] [initMediaSession] Play");
|
||||||
|
});
|
||||||
|
navigator.mediaSession.setActionHandler("pause", () => {
|
||||||
|
MusicKitInterop.pause();
|
||||||
|
console.log("[cider:preload] [initMediaSession] Pause");
|
||||||
|
});
|
||||||
|
navigator.mediaSession.setActionHandler("stop", () => {
|
||||||
|
MusicKit.getInstance().stop();
|
||||||
|
console.log("[cider:preload] [initMediaSession] Stop");
|
||||||
|
});
|
||||||
|
navigator.mediaSession.setActionHandler("seekbackward", (details) => {
|
||||||
|
const skipTime = details.seekOffset || defaultSkipTime;
|
||||||
|
MusicKit.getInstance().seekToTime(Math.max(MusicKit.getInstance().currentPlaybackTime - skipTime, 0));
|
||||||
|
console.log(`[cider:preload] [initMediaSession] Seek Backward ${skipTime}`);
|
||||||
|
});
|
||||||
|
navigator.mediaSession.setActionHandler("seekforward", (details) => {
|
||||||
|
const skipTime = details.seekOffset || defaultSkipTime;
|
||||||
|
MusicKit.getInstance().seekToTime(Math.max(MusicKit.getInstance().currentPlaybackTime + skipTime, 0));
|
||||||
|
console.log(`[cider:preload] [initMediaSession] Seek Forward ${skipTime}`);
|
||||||
|
});
|
||||||
|
navigator.mediaSession.setActionHandler("seekto", ({ seekTime, fastSeek }) => {
|
||||||
|
MusicKit.getInstance().seekToTime(seekTime);
|
||||||
|
console.log(`[cider:preload] [initMediaSession] Seek To ${seekTime}`);
|
||||||
|
});
|
||||||
|
navigator.mediaSession.setActionHandler("previoustrack", () => {
|
||||||
|
MusicKitInterop.previous();
|
||||||
|
console.log("[cider:preload] [initMediaSession] Previous Track");
|
||||||
|
});
|
||||||
|
navigator.mediaSession.setActionHandler("nexttrack", () => {
|
||||||
|
MusicKitInterop.next();
|
||||||
|
console.log("[cider:preload] [initMediaSession] Next Track");
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.debug("[cider:preload] [initMediaSession] Media Session API not supported");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
updateMediaSession: (a) => {
|
||||||
|
if ("mediaSession" in navigator) {
|
||||||
|
navigator.mediaSession.metadata = new MediaMetadata({
|
||||||
|
title: a.name,
|
||||||
|
artist: a.artistName,
|
||||||
|
album: a.albumName,
|
||||||
|
artwork: [
|
||||||
|
{
|
||||||
|
src: a.artwork.url.replace("/{w}x{h}bb", "/96x96bb").replace("/2000x2000bb", "/35x35bb"),
|
||||||
|
sizes: "96x96",
|
||||||
|
type: "image/jpeg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: a.artwork.url.replace("/{w}x{h}bb", "/128x128bb").replace("/2000x2000bb", "/35x35bb"),
|
||||||
|
sizes: "128x128",
|
||||||
|
type: "image/jpeg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: a.artwork.url.replace("/{w}x{h}bb", "/192x192bb").replace("/2000x2000bb", "/35x35bb"),
|
||||||
|
sizes: "192x192",
|
||||||
|
type: "image/jpeg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: a.artwork.url.replace("/{w}x{h}bb", "/256x256bb").replace("/2000x2000bb", "/35x35bb"),
|
||||||
|
sizes: "256x256",
|
||||||
|
type: "image/jpeg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: a.artwork.url.replace("/{w}x{h}bb", "/384x384bb").replace("/2000x2000bb", "/35x35bb"),
|
||||||
|
sizes: "384x384",
|
||||||
|
type: "image/jpeg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: a.artwork.url.replace("/{w}x{h}bb", "/512x512bb").replace("/2000x2000bb", "/35x35bb"),
|
||||||
|
sizes: "512x512",
|
||||||
|
type: "image/jpeg",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
updateMediaState: (a) => {
|
||||||
|
if ("mediaSession" in navigator) {
|
||||||
|
console.log("[cider:preload] [updateMediaState] Updating Media State to " + a.status);
|
||||||
|
switch (a.status) {
|
||||||
|
default:
|
||||||
|
case null:
|
||||||
|
navigator.mediaSession.playbackState = "none";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case false:
|
||||||
|
navigator.mediaSession.playbackState = "paused";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case true:
|
||||||
|
navigator.mediaSession.playbackState = "playing";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
updatePositionState: (a) => {
|
||||||
|
if ("mediaSession" in navigator && a.currentPlaybackTime <= a.durationInMillis / 1000 && a.currentPlaybackTime >= 0) {
|
||||||
|
navigator.mediaSession.setPositionState({
|
||||||
|
duration: a.durationInMillis / 1000,
|
||||||
|
playbackRate: app?.cfg?.audio?.playbackRate ?? 1,
|
||||||
|
position: a.currentPlaybackTime,
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -195,7 +195,6 @@ const app = new Vue({
|
||||||
type: "",
|
type: "",
|
||||||
},
|
},
|
||||||
MVsource: null,
|
MVsource: null,
|
||||||
prevButtonBackIndicator: false,
|
|
||||||
currentSongInfo: {},
|
currentSongInfo: {},
|
||||||
page: "",
|
page: "",
|
||||||
pageHistory: [],
|
pageHistory: [],
|
||||||
|
@ -2249,40 +2248,20 @@ const app = new Vue({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
prevButton() {
|
prevButton() {
|
||||||
if (!app.prevButtonBackIndicator && app.mk.nowPlayingItem && app.mk.currentPlaybackTime > 2) {
|
if (app.mk.nowPlayingItem && app.mk.currentPlaybackTime > 2) {
|
||||||
app.prevButtonBackIndicator = true;
|
|
||||||
try {
|
|
||||||
clearTimeout(app.pauseButtonTimer);
|
|
||||||
} catch (e) {}
|
|
||||||
app.mk.seekToTime(0);
|
app.mk.seekToTime(0);
|
||||||
app.pauseButtonTimer = setTimeout(() => {
|
|
||||||
app.prevButtonBackIndicator = false;
|
|
||||||
}, 3000);
|
|
||||||
} else {
|
} else {
|
||||||
try {
|
|
||||||
clearTimeout(app.pauseButtonTimer);
|
|
||||||
} catch (e) {}
|
|
||||||
app.prevButtonBackIndicator = false;
|
|
||||||
app.skipToPreviousItem();
|
app.skipToPreviousItem();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
isDisabled() {
|
isDisabled() {
|
||||||
if (!app.mk.nowPlayingItem || app.mk.nowPlayingItem.attributes.playParams.kind == "radioStation") {
|
return !app.mk.nowPlayingItem || app.mk.nowPlayingItem.attributes.playParams.kind === "radioStation";
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
isPrevDisabled() {
|
isPrevDisabled() {
|
||||||
if (this.isDisabled() || (app.mk.queue._position == 0 && app.mk.currentPlaybackTime <= 2)) {
|
return this.isDisabled() || (app.mk.queue._position === 0 && app.mk.currentPlaybackTime <= 2);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
isNextDisabled() {
|
isNextDisabled() {
|
||||||
if (this.isDisabled() || app.mk.queue._position + 1 == app.mk.queue.length) {
|
return this.isDisabled() || app.mk.queue._position + 1 === app.mk.queue.length;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
async getNowPlayingItemDetailed(target) {
|
async getNowPlayingItemDetailed(target) {
|
||||||
|
@ -5098,21 +5077,19 @@ const app = new Vue({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
skipToNextItem() {
|
skipToNextItem() {
|
||||||
app.prevButtonBackIndicator = false;
|
if (this.mk.queue.nextPlayableItemIndex !== -1 && this.mk.queue.nextPlayableItemIndex != null) this.mk.changeToMediaAtIndex(this.mk.queue.nextPlayableItemIndex);
|
||||||
// app.mk.skipToNextItem() is buggy somehow so use this
|
|
||||||
if (this.mk.queue.nextPlayableItemIndex != -1 && this.mk.queue.nextPlayableItemIndex != null) this.mk.changeToMediaAtIndex(this.mk.queue.nextPlayableItemIndex);
|
|
||||||
},
|
},
|
||||||
skipToPreviousItem() {
|
skipToPreviousItem() {
|
||||||
// app.mk.skipToPreviousItem() is buggy somehow so use this
|
if (this.mk.queue.previousPlayableItemIndex !== -1 && this.mk.queue.previousPlayableItemIndex != null) this.mk.changeToMediaAtIndex(this.mk.queue.previousPlayableItemIndex);
|
||||||
if (this.mk.queue.previousPlayableItemIndex != -1 && this.mk.queue.previousPlayableItemIndex != null) this.mk.changeToMediaAtIndex(this.mk.queue.previousPlayableItemIndex);
|
|
||||||
},
|
},
|
||||||
mediaKeyFixes() {
|
mediaKeyFixes() {
|
||||||
navigator.mediaSession.setActionHandler("previoustrack", function () {
|
MusicKitInterop.initMediaSession();
|
||||||
app.prevButton();
|
// navigator.mediaSession.setActionHandler("previoustrack", function () {
|
||||||
});
|
// app.skipToPreviousItem();
|
||||||
navigator.mediaSession.setActionHandler("nexttrack", function () {
|
// });
|
||||||
app.skipToNextItem();
|
// navigator.mediaSession.setActionHandler("nexttrack", function () {
|
||||||
});
|
// app.skipToNextItem();
|
||||||
|
// });
|
||||||
},
|
},
|
||||||
authCC() {
|
authCC() {
|
||||||
ipcRenderer.send("cc-auth");
|
ipcRenderer.send("cc-auth");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue