discord-jellyfin-bot/src/playbackmanager.js

172 lines
4.9 KiB
JavaScript
Raw Normal View History

2020-09-23 16:47:12 +02:00
const discordclientmanager = require("./discordclientmanager");
const {
2020-09-21 05:30:39 +02:00
getAudioDispatcher,
setAudioDispatcher
} = require("./dispachermanager");
2020-09-23 16:47:12 +02:00
const {
ticksToSeconds
} = require("./util");
var currentPlayingItemId;
var progressInterval;
var isPaused;
2020-09-23 16:47:12 +02:00
var _disconnectOnFinish;
var _seek;
2020-09-21 05:30:39 +02:00
const jellyfinClientManager = require("./jellyfinclientmanager");
function streamURLbuilder (itemID, bitrate) {
// so the server transcodes. Seems appropriate as it has the source file.
const supportedCodecs = "opus";
const supportedContainers = "ogg,opus";
return `${jellyfinClientManager.getJellyfinClient().serverAddress()}/Audio/${itemID}/universal?UserId=${jellyfinClientManager.getJellyfinClient().getCurrentUserId()}&DeviceId=${jellyfinClientManager.getJellyfinClient().deviceId()}&MaxStreamingBitrate=${bitrate}&Container=${supportedContainers}&AudioCodec=${supportedCodecs}&api_key=${jellyfinClientManager.getJellyfinClient().accessToken()}&TranscodingContainer=ts&TranscodingProtocol=hls`;
}
2020-09-23 16:47:12 +02:00
function startPlaying (voiceconnection = discordclientmanager.getDiscordClient().user.client.voice.connections.first(), itemID = currentPlayingItemId, seekTo, disconnectOnFinish = _disconnectOnFinish) {
2020-09-21 05:30:39 +02:00
isPaused = false;
2020-09-23 16:47:12 +02:00
currentPlayingItemId = itemID;
_disconnectOnFinish = disconnectOnFinish;
2020-09-23 17:06:20 +02:00
_seek = seekTo * 1000;
2020-09-21 05:30:39 +02:00
async function playasync () {
const url = streamURLbuilder(itemID, voiceconnection.channel.bitrate);
2020-09-23 17:06:20 +02:00
setAudioDispatcher(voiceconnection.play(url, { seek: seekTo }));
if (seekTo) {
2020-09-23 16:47:12 +02:00
jellyfinClientManager.getJellyfinClient().reportPlaybackProgress(getProgressPayload());
2020-09-23 17:06:20 +02:00
} else {
jellyfinClientManager.getJellyfinClient().reportPlaybackStart({ userID: `${jellyfinClientManager.getJellyfinClient().getCurrentUserId()}`, itemID: `${itemID}`, canSeek: true, playSessionId: getPlaySessionId(), playMethod: getPlayMethod() });
2020-09-23 16:47:12 +02:00
}
2020-09-21 05:30:39 +02:00
getAudioDispatcher().on("finish", () => {
if (disconnectOnFinish) {
stop(voiceconnection);
} else {
stop();
}
});
}
2020-09-23 17:06:20 +02:00
playasync().catch((rsn) => { console.error(rsn); });
}
2020-09-23 16:47:12 +02:00
/**
* @param {Number} toSeek - where to seek in ticks
*/
2020-09-23 17:06:20 +02:00
function seek (toSeek = 0) {
if (getAudioDispatcher()) {
startPlaying(undefined, undefined, ticksToSeconds(toSeek), _disconnectOnFinish);
2020-09-23 16:47:12 +02:00
jellyfinClientManager.getJellyfinClient().reportPlaybackProgress(getProgressPayload());
2020-09-23 17:42:13 +02:00
} else {
2020-09-23 17:39:41 +02:00
throw Error("No Song Playing");
2020-09-23 16:47:12 +02:00
}
}
/**
* @param {Object=} disconnectVoiceConnection - Optional The voice Connection do disconnect from
*/
2020-09-21 05:30:39 +02:00
function stop (disconnectVoiceConnection) {
isPaused = true;
if (disconnectVoiceConnection) {
disconnectVoiceConnection.disconnect();
}
2020-09-23 17:06:20 +02:00
jellyfinClientManager.getJellyfinClient().reportPlaybackStopped({ userId: jellyfinClientManager.getJellyfinClient().getCurrentUserId(), itemId: currentPlayingItemId, playSessionId: getPlaySessionId() });
2020-09-21 05:30:39 +02:00
if (getAudioDispatcher()) { getAudioDispatcher().destroy(); }
setAudioDispatcher(undefined);
clearInterval(progressInterval);
}
2020-09-21 05:30:39 +02:00
function pause () {
isPaused = true;
jellyfinClientManager.getJellyfinClient().reportPlaybackProgress(getProgressPayload());
getAudioDispatcher().pause(true);
}
2020-09-21 05:30:39 +02:00
function resume () {
isPaused = false;
jellyfinClientManager.getJellyfinClient().reportPlaybackProgress(getProgressPayload());
getAudioDispatcher().resume();
}
2020-09-21 05:30:39 +02:00
function playPause () {
if (getAudioDispatcher().paused) { resume(); } else { pause(); }
}
2020-09-21 05:30:39 +02:00
function getPostitionTicks () {
// this is very sketchy but i dont know how else to do it
2020-09-23 17:06:20 +02:00
return (_seek + getAudioDispatcher().streamTime - getAudioDispatcher().pausedTime) * 10000;
}
2020-09-21 05:30:39 +02:00
function getPlayMethod () {
// TODO figure out how to figure this out
2020-09-23 16:47:12 +02:00
return 0;
}
2020-09-21 05:30:39 +02:00
function getRepeatMode () {
return "RepeatNone";
}
2020-09-21 05:30:39 +02:00
function getPlaylistItemId () {
// as I curently dont support Playlists
return "playlistItem0";
}
2020-09-21 05:30:39 +02:00
function getPlaySessionId () {
// i think its just a number which you dont need to retrieve but need to report
return "ae2436edc6b91b11d72aeaa67f84e0ea";
}
2020-09-21 05:30:39 +02:00
function getNowPLayingQueue () {
return [{
Id: currentPlayingItemId,
// as I curently dont support Playlists
PlaylistItemId: getPlaylistItemId()
}];
}
2020-09-21 05:30:39 +02:00
function getCanSeek () {
2020-09-23 16:47:12 +02:00
return true;
}
2020-09-21 05:30:39 +02:00
function getIsMuted () {
return false;
}
2020-09-21 05:30:39 +02:00
function getVolumeLevel () {
return 100;
}
2020-09-21 05:30:39 +02:00
function getItemId () {
return currentPlayingItemId;
}
2020-09-21 05:30:39 +02:00
function getIsPaused () {
// AudioDispacker Paused is to slow
2020-09-21 05:30:39 +02:00
if (isPaused === undefined) {
isPaused = false;
}
return isPaused;
}
2020-09-21 05:30:39 +02:00
function getProgressPayload () {
const payload = {
CanSeek: getCanSeek(),
IsMuted: getIsMuted(),
IsPaused: getIsPaused(),
ItemId: getItemId(),
MediaSourceId: getItemId(),
NowPlayingQueue: getNowPLayingQueue(),
PlayMethod: getPlayMethod(),
PlaySessionId: getPlaySessionId(),
PlaylistItemId: getPlaylistItemId(),
PositionTicks: getPostitionTicks(),
RepeatMode: getRepeatMode(),
2020-09-21 09:56:46 +02:00
VolumeLevel: getVolumeLevel(),
EventName: "pauseplayupdate"
2020-09-21 05:30:39 +02:00
};
return payload;
}
module.exports = {
2020-09-21 05:30:39 +02:00
startPlaying,
stop,
playPause,
resume,
2020-09-23 16:47:12 +02:00
pause,
seek
2020-09-21 05:30:39 +02:00
};