mirror of
https://github.com/jeffvli/feishin.git
synced 2026-07-21 18:06:30 +02:00
feat: add jukebox player engine for server-side playback (#2109)
* feat: add jukebox player engine for server-side playback --------- Co-authored-by: jeffvli <jeffvictorli@gmail.com>
This commit is contained in:
@@ -762,6 +762,18 @@ export const controller: GeneralController = {
|
||||
server.type,
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
jukeboxControl(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
|
||||
if (!server) {
|
||||
throw new Error(`${i18n.t('error.apiRouteError')}: jukeboxControl`);
|
||||
}
|
||||
|
||||
const fn = apiController('jukeboxControl', server.type);
|
||||
return fn
|
||||
? fn(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }))
|
||||
: Promise.resolve(null);
|
||||
},
|
||||
movePlaylistItem(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
|
||||
|
||||
@@ -745,6 +745,7 @@ export const NavidromeController: InternalControllerEndpoint = {
|
||||
...navidromeFeatures,
|
||||
publicPlaylist: [1],
|
||||
[ServerFeature.ALBUM_YES_NO_RATING_FILTER]: [1],
|
||||
[ServerFeature.JUKEBOX]: [1],
|
||||
[ServerFeature.MUSIC_FOLDER_MULTISELECT]: [1],
|
||||
};
|
||||
|
||||
@@ -866,12 +867,12 @@ export const NavidromeController: InternalControllerEndpoint = {
|
||||
totalRecordCount: albums.totalRecordCount,
|
||||
};
|
||||
},
|
||||
|
||||
getSongListCount: async ({ apiClientProps, query }) =>
|
||||
NavidromeController.getSongList({
|
||||
apiClientProps,
|
||||
query: { ...query, limit: 1, startIndex: 0 },
|
||||
}).then((result) => result!.totalRecordCount!),
|
||||
|
||||
getStreamUrl: SubsonicController.getStreamUrl,
|
||||
getStructuredLyrics: SubsonicController.getStructuredLyrics,
|
||||
getTagList: async (args) => {
|
||||
@@ -1008,6 +1009,7 @@ export const NavidromeController: InternalControllerEndpoint = {
|
||||
totalRecordCount: Number(res.body.headers.get('x-total-count') || 0),
|
||||
};
|
||||
},
|
||||
jukeboxControl: SubsonicController.jukeboxControl,
|
||||
movePlaylistItem: async (args) => {
|
||||
const { apiClientProps, query } = args;
|
||||
|
||||
|
||||
@@ -274,6 +274,14 @@ export const contract = c.router({
|
||||
200: ssType._response.user,
|
||||
},
|
||||
},
|
||||
jukeboxControl: {
|
||||
method: 'GET',
|
||||
path: 'jukeboxControl.view',
|
||||
query: ssType._parameters.jukeboxControl,
|
||||
responses: {
|
||||
200: ssType._response.jukeboxControl,
|
||||
},
|
||||
},
|
||||
ping: {
|
||||
method: 'GET',
|
||||
path: 'ping.view',
|
||||
|
||||
@@ -1395,6 +1395,22 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
if (subsonicFeatures[SubsonicExtensions.PLAYBACK_REPORT]) {
|
||||
features.reportPlayback = [1];
|
||||
}
|
||||
try {
|
||||
const jukeboxStatus = await ssApiClient(apiClientProps).jukeboxControl({
|
||||
query: { action: 'status' },
|
||||
});
|
||||
|
||||
if (jukeboxStatus.status === 200 && !(jukeboxStatus.body as any)?.error) {
|
||||
features[ServerFeature.JUKEBOX] = [1];
|
||||
} else {
|
||||
console.log(
|
||||
'Jukebox endpoint returned an error payload:',
|
||||
(jukeboxStatus.body as any)?.error,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Jukebox is not supported by this server:', error);
|
||||
}
|
||||
|
||||
return { features, id: apiClientProps.server?.id, version: ping.body.serverVersion };
|
||||
},
|
||||
@@ -2052,6 +2068,25 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
name: res.body.user.username,
|
||||
};
|
||||
},
|
||||
jukeboxControl: async (args) => {
|
||||
const { apiClientProps, query } = args;
|
||||
|
||||
const res = await ssApiClient(apiClientProps).jukeboxControl({
|
||||
query: {
|
||||
action: query.action,
|
||||
gain: query.gain,
|
||||
id: query.id,
|
||||
index: query.index,
|
||||
offset: query.offset,
|
||||
},
|
||||
});
|
||||
|
||||
if (res.status !== 200) {
|
||||
throw new Error('Failed to control jukebox');
|
||||
}
|
||||
|
||||
return res.body;
|
||||
},
|
||||
removeFromPlaylist: async ({ apiClientProps, query }) => {
|
||||
const res = await ssApiClient(apiClientProps).updatePlaylist({
|
||||
query: {
|
||||
|
||||
Reference in New Issue
Block a user