mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-11 10:31:47 +00:00
feat(api-server): add endpoint to get shuffle state (#2792)
This commit is contained in:
@ -173,7 +173,24 @@ const routes = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
getShuffleState: createRoute({
|
||||||
|
method: 'get',
|
||||||
|
path: `/api/${API_VERSION}/shuffle`,
|
||||||
|
summary: 'get shuffle state',
|
||||||
|
description: 'Get the current shuffle state',
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
description: 'Success',
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: z.object({
|
||||||
|
state: z.boolean().nullable(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
shuffle: createRoute({
|
shuffle: createRoute({
|
||||||
method: 'post',
|
method: 'post',
|
||||||
path: `/api/${API_VERSION}/shuffle`,
|
path: `/api/${API_VERSION}/shuffle`,
|
||||||
@ -581,6 +598,25 @@ export const register = (
|
|||||||
ctx.status(204);
|
ctx.status(204);
|
||||||
return ctx.body(null);
|
return ctx.body(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.openapi(routes.getShuffleState, async (ctx) => {
|
||||||
|
const stateResponsePromise = new Promise<boolean>((resolve) => {
|
||||||
|
ipcMain.once(
|
||||||
|
'ytmd:get-shuffle-response',
|
||||||
|
(_, isShuffled: boolean | undefined) => {
|
||||||
|
return resolve(!!isShuffled);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
controller.requestShuffleInformation();
|
||||||
|
});
|
||||||
|
|
||||||
|
const isShuffled = await stateResponsePromise;
|
||||||
|
|
||||||
|
ctx.status(200);
|
||||||
|
return ctx.json({ state: isShuffled });
|
||||||
|
});
|
||||||
|
|
||||||
app.openapi(routes.shuffle, (ctx) => {
|
app.openapi(routes.shuffle, (ctx) => {
|
||||||
controller.shuffle();
|
controller.shuffle();
|
||||||
|
|
||||||
|
|||||||
2
src/plugins/shortcuts/mpris-service.d.ts
vendored
2
src/plugins/shortcuts/mpris-service.d.ts
vendored
@ -86,7 +86,7 @@ declare module '@jellybrick/mpris-service' {
|
|||||||
supportedMimeTypes: string[];
|
supportedMimeTypes: string[];
|
||||||
canQuit: boolean;
|
canQuit: boolean;
|
||||||
canRaise: boolean;
|
canRaise: boolean;
|
||||||
canSetFullscreen?: boolean;
|
canUsePlayerControls?: boolean;
|
||||||
desktopEntry?: string;
|
desktopEntry?: string;
|
||||||
hasTrackList: boolean;
|
hasTrackList: boolean;
|
||||||
|
|
||||||
|
|||||||
@ -77,7 +77,7 @@ function setupMPRIS() {
|
|||||||
|
|
||||||
instance.canRaise = true;
|
instance.canRaise = true;
|
||||||
instance.canQuit = false;
|
instance.canQuit = false;
|
||||||
instance.canSetFullscreen = true;
|
instance.canUsePlayerControls = true;
|
||||||
instance.supportedUriSchemes = ['http', 'https'];
|
instance.supportedUriSchemes = ['http', 'https'];
|
||||||
instance.desktopEntry = 'youtube-music';
|
instance.desktopEntry = 'youtube-music';
|
||||||
return instance;
|
return instance;
|
||||||
@ -93,6 +93,7 @@ function registerMPRIS(win: BrowserWindow) {
|
|||||||
shuffle,
|
shuffle,
|
||||||
switchRepeat,
|
switchRepeat,
|
||||||
setFullscreen,
|
setFullscreen,
|
||||||
|
requestShuffleInformation,
|
||||||
requestFullscreenInformation,
|
requestFullscreenInformation,
|
||||||
requestQueueInformation,
|
requestQueueInformation,
|
||||||
} = songControls;
|
} = songControls;
|
||||||
@ -126,8 +127,10 @@ function registerMPRIS(win: BrowserWindow) {
|
|||||||
win.webContents.send('ytmd:setup-time-changed-listener', 'mpris');
|
win.webContents.send('ytmd:setup-time-changed-listener', 'mpris');
|
||||||
win.webContents.send('ytmd:setup-repeat-changed-listener', 'mpris');
|
win.webContents.send('ytmd:setup-repeat-changed-listener', 'mpris');
|
||||||
win.webContents.send('ytmd:setup-volume-changed-listener', 'mpris');
|
win.webContents.send('ytmd:setup-volume-changed-listener', 'mpris');
|
||||||
|
win.webContents.send('ytmd:setup-shuffle-changed-listener', 'mpris');
|
||||||
win.webContents.send('ytmd:setup-fullscreen-changed-listener', 'mpris');
|
win.webContents.send('ytmd:setup-fullscreen-changed-listener', 'mpris');
|
||||||
win.webContents.send('ytmd:setup-autoplay-changed-listener', 'mpris');
|
win.webContents.send('ytmd:setup-autoplay-changed-listener', 'mpris');
|
||||||
|
requestShuffleInformation();
|
||||||
requestFullscreenInformation();
|
requestFullscreenInformation();
|
||||||
requestQueueInformation();
|
requestQueueInformation();
|
||||||
});
|
});
|
||||||
@ -156,8 +159,16 @@ function registerMPRIS(win: BrowserWindow) {
|
|||||||
requestQueueInformation();
|
requestQueueInformation();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcMain.on('ytmd:shuffle-changed', (_, shuffleEnabled: boolean) => {
|
||||||
|
if (player.shuffle === undefined || !player.canUsePlayerControls) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
player.shuffle = shuffleEnabled ?? !player.shuffle;
|
||||||
|
});
|
||||||
|
|
||||||
ipcMain.on('ytmd:fullscreen-changed', (_, changedTo: boolean) => {
|
ipcMain.on('ytmd:fullscreen-changed', (_, changedTo: boolean) => {
|
||||||
if (player.fullscreen === undefined || !player.canSetFullscreen) {
|
if (player.fullscreen === undefined || !player.canUsePlayerControls) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,7 +179,7 @@ function registerMPRIS(win: BrowserWindow) {
|
|||||||
ipcMain.on(
|
ipcMain.on(
|
||||||
'ytmd:set-fullscreen',
|
'ytmd:set-fullscreen',
|
||||||
(_, isFullscreen: boolean | undefined) => {
|
(_, isFullscreen: boolean | undefined) => {
|
||||||
if (!player.canSetFullscreen || isFullscreen === undefined) {
|
if (!player.canUsePlayerControls || isFullscreen === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,7 +190,7 @@ function registerMPRIS(win: BrowserWindow) {
|
|||||||
ipcMain.on(
|
ipcMain.on(
|
||||||
'ytmd:fullscreen-changed-supported',
|
'ytmd:fullscreen-changed-supported',
|
||||||
(_, isFullscreenSupported: boolean) => {
|
(_, isFullscreenSupported: boolean) => {
|
||||||
player.canSetFullscreen = isFullscreenSupported;
|
player.canUsePlayerControls = isFullscreenSupported;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
ipcMain.on('ytmd:autoplay-changed', (_) => {
|
ipcMain.on('ytmd:autoplay-changed', (_) => {
|
||||||
@ -272,6 +283,12 @@ function registerMPRIS(win: BrowserWindow) {
|
|||||||
player.on('position', seekTo);
|
player.on('position', seekTo);
|
||||||
|
|
||||||
player.on('shuffle', (enableShuffle) => {
|
player.on('shuffle', (enableShuffle) => {
|
||||||
|
if (!player.canUsePlayerControls || enableShuffle === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
player.shuffle = enableShuffle;
|
||||||
|
|
||||||
if (enableShuffle) {
|
if (enableShuffle) {
|
||||||
shuffle();
|
shuffle();
|
||||||
requestQueueInformation();
|
requestQueueInformation();
|
||||||
|
|||||||
@ -62,6 +62,9 @@ export default (win: BrowserWindow) => {
|
|||||||
win.webContents.send('ytmd:seek-by', seconds);
|
win.webContents.send('ytmd:seek-by', seconds);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
requestShuffleInformation: () => {
|
||||||
|
win.webContents.send('ytmd:get-shuffle');
|
||||||
|
},
|
||||||
shuffle: () => win.webContents.send('ytmd:shuffle'),
|
shuffle: () => win.webContents.send('ytmd:shuffle'),
|
||||||
switchRepeat: (n: ArgsType<number> = 1) => {
|
switchRepeat: (n: ArgsType<number> = 1) => {
|
||||||
const repeat = parseNumberFromArgsType(n);
|
const repeat = parseNumberFromArgsType(n);
|
||||||
|
|||||||
@ -87,6 +87,28 @@ export const setupVolumeChangedListener = singleton((api: YoutubePlayer) => {
|
|||||||
window.ipcRenderer.send('ytmd:volume-changed', api.getVolume());
|
window.ipcRenderer.send('ytmd:volume-changed', api.getVolume());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const setupShuffleChangedListener = singleton(() => {
|
||||||
|
const playerBar = document.querySelector('ytmusic-player-bar');
|
||||||
|
|
||||||
|
if (!playerBar) {
|
||||||
|
window.ipcRenderer.send('ytmd:shuffle-changed-supported', false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const observer = new MutationObserver(() => {
|
||||||
|
window.ipcRenderer.send(
|
||||||
|
'ytmd:shuffle-changed',
|
||||||
|
(playerBar?.attributes.getNamedItem('shuffle-on') ?? null) !== null,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(playerBar, {
|
||||||
|
attributes: true,
|
||||||
|
childList: false,
|
||||||
|
subtree: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
export const setupFullScreenChangedListener = singleton(() => {
|
export const setupFullScreenChangedListener = singleton(() => {
|
||||||
const playerBar = document.querySelector('ytmusic-player-bar');
|
const playerBar = document.querySelector('ytmusic-player-bar');
|
||||||
|
|
||||||
@ -139,6 +161,10 @@ export default (api: YoutubePlayer) => {
|
|||||||
setupVolumeChangedListener(api);
|
setupVolumeChangedListener(api);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
window.ipcRenderer.on('ytmd:setup-shuffle-changed-listener', () => {
|
||||||
|
setupShuffleChangedListener();
|
||||||
|
});
|
||||||
|
|
||||||
window.ipcRenderer.on('ytmd:setup-fullscreen-changed-listener', () => {
|
window.ipcRenderer.on('ytmd:setup-fullscreen-changed-listener', () => {
|
||||||
setupFullScreenChangedListener();
|
setupFullScreenChangedListener();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -80,6 +80,20 @@ async function onApiLoaded() {
|
|||||||
>('ytmusic-player-bar')
|
>('ytmusic-player-bar')
|
||||||
?.queue.shuffle();
|
?.queue.shuffle();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const isShuffled = () => {
|
||||||
|
const isShuffled =
|
||||||
|
document
|
||||||
|
.querySelector<HTMLElement>('ytmusic-player-bar')
|
||||||
|
?.attributes.getNamedItem('shuffle-on') ?? null;
|
||||||
|
|
||||||
|
return isShuffled !== null;
|
||||||
|
};
|
||||||
|
|
||||||
|
window.ipcRenderer.on('ytmd:get-shuffle', () => {
|
||||||
|
window.ipcRenderer.send('ytmd:get-shuffle-response', isShuffled());
|
||||||
|
});
|
||||||
|
|
||||||
window.ipcRenderer.on(
|
window.ipcRenderer.on(
|
||||||
'ytmd:update-like',
|
'ytmd:update-like',
|
||||||
(_, status: 'LIKE' | 'DISLIKE' = 'LIKE') => {
|
(_, status: 'LIKE' | 'DISLIKE' = 'LIKE') => {
|
||||||
|
|||||||
Reference in New Issue
Block a user