Add websocket control for grouped items

This commit is contained in:
Manuel 2022-12-27 16:50:03 +01:00 committed by GitHub
parent 538b2451f6
commit 9ecce22f14
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 85 additions and 27 deletions

View File

@ -95,6 +95,7 @@ export class JellyfinSearchService {
const searchApi = getItemsApi(api); const searchApi = getItemsApi(api);
const { data } = await searchApi.getItems({ const { data } = await searchApi.getItems({
ids: [id], ids: [id],
userId: this.jellyfinService.getUserId(),
}); });
if (data.Items.length !== 1) { if (data.Items.length !== 1) {

View File

@ -8,6 +8,7 @@ import { PlaybackService } from '../../playback/playback.service';
import { JellyfinSearchService } from './jellyfin.search.service'; import { JellyfinSearchService } from './jellyfin.search.service';
import { JellyfinStreamBuilderService } from './jellyfin.stream.builder.service'; import { JellyfinStreamBuilderService } from './jellyfin.stream.builder.service';
import { Track } from '../../types/track'; import { Track } from '../../types/track';
import { PlayNowCommand } from '../../types/websocket';
@Injectable() @Injectable()
export class JellyfinWebSocketService implements OnModuleDestroy { export class JellyfinWebSocketService implements OnModuleDestroy {
@ -87,28 +88,47 @@ export class JellyfinWebSocketService implements OnModuleDestroy {
); );
break; break;
case SessionMessageType[SessionMessageType.Play]: case SessionMessageType[SessionMessageType.Play]:
const data = msg.Data as { ItemIds: string[]; StartIndex: number }; const data = msg.Data as PlayNowCommand;
const ids = data.ItemIds; data.hasSelection = PlayNowCommand.prototype.hasSelection;
data.getSelection = PlayNowCommand.prototype.getSelection;
const ids = data.getSelection();
this.jellyfinSearchService this.logger.debug(
.getById(ids[data.StartIndex]) `Adding ${ids.length} ids to the queue using controls from the websocket`,
.then((response) => { );
const track: Track = {
name: response.Name, ids.forEach((id, index) => {
durationInMilliseconds: response.RunTimeTicks / 1000, this.jellyfinSearchService
jellyfinId: response.Id, .getById(id)
streamUrl: this.jellyfinStreamBuilderService.buildStreamUrl( .then((response) => {
response.Id, const track: Track = {
96000, name: response.Name,
), durationInMilliseconds: response.RunTimeTicks / 10000,
remoteImages: { jellyfinId: response.Id,
Images: [], streamUrl: this.jellyfinStreamBuilderService.buildStreamUrl(
Providers: [], response.Id,
TotalRecordCount: 0, 96000,
}, ),
}; remoteImages: {
this.playbackService.enqueTrackAndInstantyPlay(track); Images: [],
}); Providers: [],
TotalRecordCount: 0,
},
};
const trackId = this.playbackService.enqueueTrack(track);
if (index !== 0) {
return;
}
this.playbackService.setActiveTrack(trackId);
this.playbackService.getActiveTrackAndEmitEvent();
})
.catch((err) => {
this.logger.error(err);
});
});
break; break;
default: default:
this.logger.warn( this.logger.warn(

View File

@ -43,7 +43,7 @@ export class PlaybackService {
const newKey = keys[index + 1]; const newKey = keys[index + 1];
this.setActiveTrack(newKey); this.setActiveTrack(newKey);
this.controlAudioPlayer(); this.getActiveTrackAndEmitEvent();
return true; return true;
} }
@ -60,7 +60,7 @@ export class PlaybackService {
const keys = this.getTrackIds(); const keys = this.getTrackIds();
const newKey = keys[index - 1]; const newKey = keys[index - 1];
this.setActiveTrack(newKey); this.setActiveTrack(newKey);
this.controlAudioPlayer(); this.getActiveTrackAndEmitEvent();
return true; return true;
} }
@ -80,10 +80,10 @@ export class PlaybackService {
if (emptyBefore) { if (emptyBefore) {
this.setActiveTrack(this.playlist.tracks.find((x) => x.id === uuid).id); this.setActiveTrack(this.playlist.tracks.find((x) => x.id === uuid).id);
this.controlAudioPlayer(); this.getActiveTrackAndEmitEvent();
} }
return this.playlist.tracks.findIndex((x) => x.id === uuid); return uuid;
} }
enqueTrackAndInstantyPlay(track: Track) { enqueTrackAndInstantyPlay(track: Track) {
@ -95,7 +95,7 @@ export class PlaybackService {
}); });
this.setActiveTrack(uuid); this.setActiveTrack(uuid);
this.controlAudioPlayer(); this.getActiveTrackAndEmitEvent();
} }
set(tracks: Track[]) { set(tracks: Track[]) {
@ -133,7 +133,7 @@ export class PlaybackService {
return this.getTrackIds().indexOf(this.playlist.activeTrack); return this.getTrackIds().indexOf(this.playlist.activeTrack);
} }
private controlAudioPlayer() { getActiveTrackAndEmitEvent() {
const activeTrack = this.getActiveTrack(); const activeTrack = this.getActiveTrack();
this.logger.debug( this.logger.debug(
`A new track (${activeTrack.id}) was requested and will be emmitted as an event`, `A new track (${activeTrack.id}) was requested and will be emmitted as an event`,

37
src/types/websocket.ts Normal file
View File

@ -0,0 +1,37 @@
export class PlayNowCommand {
/**
* A list of all items available in the parent element.
* Usually, this is a list of all tracks in an album or playlist.
*/
ItemIds: string[];
/**
* A nullable index, that references an item in the ItemIds array.
* If this index is present, the command sender wishes to play only this specific item.
* If there is no index present, the sender would like to play all items in the ItemIds array.
*/
StartIndex?: number;
/**
* An enum of possible play modes.
* PlayNow: Play the selection immideatly
*/
PlayCommand: 'PlayNow';
/**
* The user who has sent the command via web socket
*/
ControllingUserId: string;
hasSelection() {
return this.StartIndex !== undefined;
}
getSelection(): string[] {
if (this.hasSelection()) {
return [this.ItemIds[this.StartIndex]];
}
return this.ItemIds;
}
}