2020-09-23 16:47:12 +02:00
|
|
|
const discordclientmanager = require("./discordclientmanager");
|
2020-09-21 04:05:49 +02:00
|
|
|
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");
|
2020-09-21 04:05:49 +02:00
|
|
|
|
2020-09-24 13:34:39 +02:00
|
|
|
|
|
|
|
//this whole thing should be a class but its probably too late now.
|
|
|
|
|
|
|
|
var currentPlayingPlaylist;
|
|
|
|
var currentPlayingPlaylistIndex;
|
2020-09-21 04:05:49 +02:00
|
|
|
var progressInterval;
|
|
|
|
var isPaused;
|
2020-09-24 13:34:39 +02:00
|
|
|
var isRepeat;
|
2020-09-23 16:47:12 +02:00
|
|
|
var _disconnectOnFinish;
|
|
|
|
var _seek;
|
2020-09-21 04:05:49 +02:00
|
|
|
|
2020-09-21 05:30:39 +02:00
|
|
|
const jellyfinClientManager = require("./jellyfinclientmanager");
|
2020-09-24 13:34:39 +02:00
|
|
|
|
|
|
|
function streamURLbuilder(itemID, bitrate) {
|
2020-09-21 05:30:39 +02:00
|
|
|
// 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-24 13:34:39 +02:00
|
|
|
function startPlaying(voiceconnection = discordclientmanager.getDiscordClient().user.client.voice.connections.first(), itemIDPlaylist = currentPlayingPlaylist, playlistIndex = currentPlayingPlaylistIndex, seekTo, disconnectOnFinish = _disconnectOnFinish) {
|
2020-09-21 05:30:39 +02:00
|
|
|
isPaused = false;
|
2020-09-24 13:34:39 +02:00
|
|
|
currentPlayingPlaylist = itemIDPlaylist;
|
|
|
|
currentPlayingPlaylistIndex = playlistIndex;
|
2020-09-23 16:47:12 +02:00
|
|
|
_disconnectOnFinish = disconnectOnFinish;
|
2020-09-23 17:06:20 +02:00
|
|
|
_seek = seekTo * 1000;
|
2020-09-24 13:34:39 +02:00
|
|
|
async function playasync() {
|
|
|
|
const url = streamURLbuilder(itemIDPlaylist[playlistIndex], voiceconnection.channel.bitrate);
|
|
|
|
setAudioDispatcher(voiceconnection.play(url, {
|
|
|
|
seek: seekTo
|
|
|
|
}));
|
2020-09-23 17:06:20 +02:00
|
|
|
if (seekTo) {
|
2020-09-23 16:47:12 +02:00
|
|
|
jellyfinClientManager.getJellyfinClient().reportPlaybackProgress(getProgressPayload());
|
2020-09-23 17:06:20 +02:00
|
|
|
} else {
|
2020-09-24 13:34:39 +02:00
|
|
|
jellyfinClientManager.getJellyfinClient().reportPlaybackStart({
|
|
|
|
userID: `${jellyfinClientManager.getJellyfinClient().getCurrentUserId()}`,
|
|
|
|
itemID: `${itemIDPlaylist[playlistIndex]}`,
|
|
|
|
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", () => {
|
2020-09-24 13:34:39 +02:00
|
|
|
if (currentPlayingPlaylist.length < playlistIndex) {
|
|
|
|
console.log("PLAYLIST END")
|
|
|
|
|
|
|
|
if (disconnectOnFinish) {
|
|
|
|
stop(voiceconnection, currentPlayingPlaylist[playlistIndex - 1]);
|
|
|
|
}else {
|
|
|
|
stop(undefined, currentPlayingPlaylist[playlistIndex - 1]);
|
|
|
|
}
|
|
|
|
|
2020-09-21 05:30:39 +02:00
|
|
|
} else {
|
2020-09-24 13:34:39 +02:00
|
|
|
startPlaying(voiceconnection, itemIDPlaylist, currentPlayingPlaylistIndex+1, 0)
|
2020-09-21 05:30:39 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2020-09-24 13:34:39 +02:00
|
|
|
playasync().catch((rsn) => {
|
|
|
|
console.error(rsn);
|
|
|
|
});
|
2020-09-21 04:05:49 +02:00
|
|
|
}
|
2020-09-23 16:47:12 +02:00
|
|
|
/**
|
|
|
|
* @param {Number} toSeek - where to seek in ticks
|
|
|
|
*/
|
2020-09-24 13:34:39 +02:00
|
|
|
function seek(toSeek = 0) {
|
2020-09-23 17:06:20 +02:00
|
|
|
if (getAudioDispatcher()) {
|
2020-09-24 13:34:39 +02:00
|
|
|
startPlaying(undefined, 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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-24 13:34:39 +02:00
|
|
|
function nextTrack(){
|
|
|
|
//console.log(currentPlayingPlaylistIndex + 1, currentPlayingPlaylist.length);
|
|
|
|
if(!(currentPlayingPlaylist)){
|
|
|
|
throw Error("There is currently nothing playing");
|
|
|
|
}else if(currentPlayingPlaylistIndex + 1 >= currentPlayingPlaylist.length){
|
|
|
|
throw Error("This is the Last song");
|
|
|
|
}
|
|
|
|
startPlaying(undefined, undefined, currentPlayingPlaylistIndex + 1, 0, _disconnectOnFinish)
|
|
|
|
}
|
|
|
|
|
|
|
|
function previousTrack(){
|
|
|
|
if(ticksToSeconds(getPostitionTicks())<10){
|
|
|
|
console.log(currentPlayingPlaylistIndex , currentPlayingPlaylist.length);
|
|
|
|
if(!(currentPlayingPlaylist)){
|
|
|
|
throw Error("There is currently nothing playing");
|
|
|
|
}else if(currentPlayingPlaylistIndex -1 < 0){
|
|
|
|
startPlaying(undefined, undefined, currentPlayingPlaylistIndex, 0, _disconnectOnFinish)
|
|
|
|
throw Error("This is the First song");
|
|
|
|
}
|
|
|
|
startPlaying(undefined, undefined, currentPlayingPlaylistIndex - 1, 0, _disconnectOnFinish)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-21 04:05:49 +02:00
|
|
|
/**
|
|
|
|
* @param {Object=} disconnectVoiceConnection - Optional The voice Connection do disconnect from
|
|
|
|
*/
|
2020-09-24 13:34:39 +02:00
|
|
|
function stop(disconnectVoiceConnection, itemId = getItemId()) {
|
|
|
|
console.log("im getting called");
|
|
|
|
console
|
2020-09-21 05:30:39 +02:00
|
|
|
isPaused = true;
|
|
|
|
if (disconnectVoiceConnection) {
|
|
|
|
disconnectVoiceConnection.disconnect();
|
|
|
|
}
|
2020-09-24 13:34:39 +02:00
|
|
|
jellyfinClientManager.getJellyfinClient().reportPlaybackStopped({
|
|
|
|
userId: jellyfinClientManager.getJellyfinClient().getCurrentUserId(),
|
|
|
|
itemId: itemId,
|
|
|
|
playSessionId: getPlaySessionId()
|
|
|
|
});
|
|
|
|
if (getAudioDispatcher()) {
|
|
|
|
getAudioDispatcher().destroy();
|
|
|
|
}
|
2020-09-21 05:30:39 +02:00
|
|
|
setAudioDispatcher(undefined);
|
|
|
|
clearInterval(progressInterval);
|
2020-09-21 04:05:49 +02:00
|
|
|
}
|
2020-09-24 13:34:39 +02:00
|
|
|
|
|
|
|
function pause() {
|
2020-09-21 05:30:39 +02:00
|
|
|
isPaused = true;
|
|
|
|
jellyfinClientManager.getJellyfinClient().reportPlaybackProgress(getProgressPayload());
|
|
|
|
getAudioDispatcher().pause(true);
|
2020-09-21 04:05:49 +02:00
|
|
|
}
|
2020-09-24 13:34:39 +02:00
|
|
|
|
|
|
|
function resume() {
|
2020-09-21 05:30:39 +02:00
|
|
|
isPaused = false;
|
|
|
|
jellyfinClientManager.getJellyfinClient().reportPlaybackProgress(getProgressPayload());
|
|
|
|
getAudioDispatcher().resume();
|
2020-09-21 04:05:49 +02:00
|
|
|
}
|
2020-09-24 13:34:39 +02:00
|
|
|
|
|
|
|
function playPause() {
|
|
|
|
if(!(getAudioDispatcher())){
|
|
|
|
throw Error("There is nothing Playing right now!");
|
|
|
|
}
|
|
|
|
if (getAudioDispatcher().paused) {
|
|
|
|
resume();
|
|
|
|
} else {
|
|
|
|
pause();
|
|
|
|
}
|
2020-09-21 04:05:49 +02:00
|
|
|
}
|
|
|
|
|
2020-09-24 13:34:39 +02:00
|
|
|
function getPostitionTicks() {
|
2020-09-21 05:30:39 +02:00
|
|
|
// this is very sketchy but i dont know how else to do it
|
2020-09-24 13:34:39 +02:00
|
|
|
console.log((_seek + getAudioDispatcher().streamTime - getAudioDispatcher().pausedTime) * 10000);
|
2020-09-23 17:06:20 +02:00
|
|
|
return (_seek + getAudioDispatcher().streamTime - getAudioDispatcher().pausedTime) * 10000;
|
2020-09-21 04:05:49 +02:00
|
|
|
}
|
|
|
|
|
2020-09-24 13:34:39 +02:00
|
|
|
function getPlayMethod() {
|
2020-09-21 05:30:39 +02:00
|
|
|
// TODO figure out how to figure this out
|
2020-09-24 13:34:39 +02:00
|
|
|
return "Transcode";
|
2020-09-21 04:05:49 +02:00
|
|
|
}
|
|
|
|
|
2020-09-24 13:34:39 +02:00
|
|
|
function getRepeatMode() {
|
|
|
|
if(isRepeat){
|
|
|
|
return "RepeatOne";
|
|
|
|
}else{
|
|
|
|
return "RepeatNone";
|
|
|
|
}
|
2020-09-21 04:05:49 +02:00
|
|
|
}
|
|
|
|
|
2020-09-24 13:34:39 +02:00
|
|
|
function getPlaylistItemId() {
|
|
|
|
return getItemId();
|
2020-09-21 04:05:49 +02:00
|
|
|
}
|
|
|
|
|
2020-09-24 13:34:39 +02:00
|
|
|
function getPlaySessionId() {
|
2020-09-21 05:30:39 +02:00
|
|
|
// i think its just a number which you dont need to retrieve but need to report
|
|
|
|
return "ae2436edc6b91b11d72aeaa67f84e0ea";
|
2020-09-21 04:05:49 +02:00
|
|
|
}
|
|
|
|
|
2020-09-24 13:34:39 +02:00
|
|
|
function getNowPLayingQueue() {
|
2020-09-21 05:30:39 +02:00
|
|
|
return [{
|
2020-09-24 13:34:39 +02:00
|
|
|
Id: getItemId(),
|
2020-09-21 05:30:39 +02:00
|
|
|
// as I curently dont support Playlists
|
|
|
|
PlaylistItemId: getPlaylistItemId()
|
|
|
|
}];
|
2020-09-21 04:05:49 +02:00
|
|
|
}
|
|
|
|
|
2020-09-24 13:34:39 +02:00
|
|
|
function getCanSeek() {
|
2020-09-23 16:47:12 +02:00
|
|
|
return true;
|
2020-09-21 04:05:49 +02:00
|
|
|
}
|
|
|
|
|
2020-09-24 13:34:39 +02:00
|
|
|
function getIsMuted() {
|
2020-09-21 05:30:39 +02:00
|
|
|
return false;
|
2020-09-21 04:05:49 +02:00
|
|
|
}
|
|
|
|
|
2020-09-24 13:34:39 +02:00
|
|
|
function getVolumeLevel() {
|
2020-09-21 05:30:39 +02:00
|
|
|
return 100;
|
2020-09-21 04:05:49 +02:00
|
|
|
}
|
|
|
|
|
2020-09-24 13:34:39 +02:00
|
|
|
function getItemId() {
|
|
|
|
return currentPlayingPlaylist[currentPlayingPlaylistIndex];
|
2020-09-21 04:05:49 +02:00
|
|
|
}
|
|
|
|
|
2020-09-24 13:34:39 +02:00
|
|
|
function getIsPaused() {
|
2020-09-21 05:30:39 +02:00
|
|
|
// AudioDispacker Paused is to slow
|
2020-09-21 04:05:49 +02:00
|
|
|
|
2020-09-21 05:30:39 +02:00
|
|
|
if (isPaused === undefined) {
|
|
|
|
isPaused = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return isPaused;
|
2020-09-21 04:05:49 +02:00
|
|
|
}
|
|
|
|
|
2020-09-24 13:34:39 +02:00
|
|
|
function setIsRepeat(arg){
|
|
|
|
isRepeat=arg;
|
|
|
|
}
|
|
|
|
|
|
|
|
function getProgressPayload() {
|
2020-09-21 05:30:39 +02:00
|
|
|
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;
|
2020-09-21 04:05:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = {
|
2020-09-21 05:30:39 +02:00
|
|
|
startPlaying,
|
|
|
|
stop,
|
|
|
|
playPause,
|
|
|
|
resume,
|
2020-09-23 16:47:12 +02:00
|
|
|
pause,
|
2020-09-24 13:34:39 +02:00
|
|
|
seek,
|
|
|
|
setIsRepeat,
|
|
|
|
nextTrack,
|
|
|
|
previousTrack,
|
|
|
|
getPostitionTicks
|
|
|
|
};
|