Add playback reporting at Jellyfin (#139)

This commit is contained in:
Manuel 2023-03-28 20:58:58 +02:00 committed by GitHub
parent 091ca0b65f
commit acf4cf19f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 45 additions and 9 deletions

View File

@ -41,7 +41,7 @@ export class DiscordVoiceService {
private readonly eventEmitter: EventEmitter2, private readonly eventEmitter: EventEmitter2,
) {} ) {}
@OnEvent('internal.audio.announce') @OnEvent('internal.audio.track.announce')
handleOnNewTrack(track: Track) { handleOnNewTrack(track: Track) {
const resource = createAudioResource( const resource = createAudioResource(
track.getStreamUrl(this.jellyfinStreamBuilder), track.getStreamUrl(this.jellyfinStreamBuilder),
@ -264,9 +264,12 @@ export class DiscordVoiceService {
this.logger.debug(`Audio player finished playing old resource`); this.logger.debug(`Audio player finished playing old resource`);
const hasNextTrack = this.playbackService const playlist = this.playbackService.getPlaylistOrDefault();
.getPlaylistOrDefault() const finishedTrack = playlist.getActiveTrack();
.hasNextTrackInPlaylist();
this.eventEmitter.emit('internal.audio.track.finish', finishedTrack);
const hasNextTrack = playlist.hasNextTrackInPlaylist();
this.logger.debug( this.logger.debug(
`Playlist has next track: ${hasNextTrack ? 'yes' : 'no'}`, `Playlist has next track: ${hasNextTrack ? 'yes' : 'no'}`,

View File

@ -10,9 +10,9 @@ import { getSessionApi } from '@jellyfin/sdk/lib/utils/api/session-api';
import { Injectable, Logger } from '@nestjs/common'; import { Injectable, Logger } from '@nestjs/common';
import { OnEvent } from '@nestjs/event-emitter'; import { OnEvent } from '@nestjs/event-emitter';
import { Track } from 'src/models/shared/Track';
import { PlaybackService } from '../../playback/playback.service'; import { PlaybackService } from '../../playback/playback.service';
import { Track } from '../../types/track';
@Injectable() @Injectable()
export class JellyinPlaystateService { export class JellyinPlaystateService {
@ -46,11 +46,28 @@ export class JellyinPlaystateService {
this.logger.debug('Reported playback capabilities sucessfully'); this.logger.debug('Reported playback capabilities sucessfully');
} }
@OnEvent('playback.newTrack') @OnEvent('internal.audio.track.announce')
private async onPlaybackNewTrack(track: Track) { private async onPlaybackNewTrack(track: Track) {
this.logger.debug(`Reporting playback start on track '${track.id}'`);
await this.playstateApi.reportPlaybackStart({ await this.playstateApi.reportPlaybackStart({
playbackStartInfo: { playbackStartInfo: {
ItemId: track.jellyfinId, ItemId: track.id,
},
});
}
@OnEvent('internal.audio.track.finish')
private async onPlaybackFinished(track: Track) {
if (!track) {
this.logger.error(
`Unable to report playback because finished track was undefined`,
);
return;
}
this.logger.debug(`Reporting playback finish on track '${track.id}'`);
await this.playstateApi.reportPlaybackStopped({
playbackStopInfo: {
ItemId: track.id,
}, },
}); });
} }

View File

@ -30,8 +30,8 @@ export class StopPlaybackCommand {
? 'In addition, your playlist has been cleared' ? 'In addition, your playlist has been cleared'
: 'There is no active track in the queue'; : 'There is no active track in the queue';
if (hasActiveTrack) { if (hasActiveTrack) {
this.playbackService.getPlaylistOrDefault().clear();
this.discordVoiceService.stop(false); this.discordVoiceService.stop(false);
// this.playbackService.getPlaylistOrDefault().clear();
} }
await interaction.reply({ await interaction.reply({

View File

@ -49,6 +49,8 @@ export class Playlist {
* @returns if the track has been changed successfully * @returns if the track has been changed successfully
*/ */
setNextTrackAsActiveTrack(): boolean { setNextTrackAsActiveTrack(): boolean {
this.announceTrackFinishIfSet();
if (this.activeTrackIndex >= this.tracks.length) { if (this.activeTrackIndex >= this.tracks.length) {
return false; return false;
} }
@ -66,6 +68,8 @@ export class Playlist {
* @returns if the track has been changed successfully * @returns if the track has been changed successfully
*/ */
setPreviousTrackAsActiveTrack(): boolean { setPreviousTrackAsActiveTrack(): boolean {
this.announceTrackFinishIfSet();
if (this.activeTrackIndex <= 0) { if (this.activeTrackIndex <= 0) {
return false; return false;
} }
@ -124,12 +128,24 @@ export class Playlist {
this.activeTrackIndex = undefined; this.activeTrackIndex = undefined;
} }
private announceTrackFinishIfSet() {
if (this.activeTrackIndex === undefined) {
return;
}
const currentTrack = this.getActiveTrack();
this.eventEmitter.emit('internal.audio.track.finish', currentTrack);
}
private announceTrackChange() { private announceTrackChange() {
if (!this.activeTrackIndex) { if (!this.activeTrackIndex) {
this.activeTrackIndex = 0; this.activeTrackIndex = 0;
} }
this.eventEmitter.emit('internal.audio.announce', this.getActiveTrack()); this.eventEmitter.emit(
'internal.audio.track.announce',
this.getActiveTrack(),
);
} }
private isActiveTrackOutOfSync(): boolean { private isActiveTrackOutOfSync(): boolean {