Skip to content

Commit

Permalink
DiscordRPC - Actually works?
Browse files Browse the repository at this point in the history
  • Loading branch information
Inrixia committed Jun 25, 2024
1 parent 0407345 commit 72dd679
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 36 deletions.
28 changes: 22 additions & 6 deletions plugins/DiscordRPC/src/DiscordRPC.native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,29 @@ export class DiscordRPC {
return !!this.rpcClient?.transport?.socket;
}
async ensureRPC(): Promise<Client> {
if (this.rpcClient && this.isConnected()) return this.rpcClient;
this.rpcClient = await new Client({ transport: "ipc" }).login({ clientId: this.clientId });
if (!this.isConnected()) return this.ensureRPC();
return this.rpcClient;
try {
if (this.rpcClient && this.isConnected()) return this.rpcClient;
await this.cleanp(true);
this.rpcClient = new Client({ transport: "ipc" });
const ready = new Promise<void>((res, rej) => {
const rejTimeout = setTimeout(() => rej(new Error("Timed out waiting for RPC to be ready")), 5000);
this.rpcClient!.once("ready", () => {
clearTimeout(rejTimeout);
res();
});
});
this.rpcClient = await this.rpcClient.login({ clientId: this.clientId });
await ready;
if (!this.isConnected()) return this.ensureRPC();
return this.rpcClient;
} catch (err) {
await this.cleanp(true);
throw err;
}
}
async cleanp(clearActivity?: false) {
if (this.isConnected() && clearActivity) await this.rpcClient!.clearActivity().catch(onCleanupErr);
async cleanp(clearActivity: boolean = true) {
if (clearActivity) await this.rpcClient?.clearActivity().catch(onCleanupErr);
await this.rpcClient?.destroy().catch(onCleanupErr);
delete this.rpcClient;
}
}
17 changes: 17 additions & 0 deletions plugins/DiscordRPC/src/Settings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { html } from "@neptune/voby";
import { getSettings } from "@inrixia/lib/storage";
import { SwitchSetting } from "@inrixia/lib/components/SwitchSetting";
import { onTimeUpdate } from ".";

export const settings = getSettings({
keepRpcOnPause: false,
});

export const Settings = () => html`<${SwitchSetting}
checked=${settings.keepRpcOnPause}
onClick=${() => {
onTimeUpdate(!settings.keepRpcOnPause).catch(() => {});
settings.keepRpcOnPause = !settings.keepRpcOnPause;
}}
title="Keep RPC on pause"
/>`;
55 changes: 27 additions & 28 deletions plugins/DiscordRPC/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,38 @@
import { intercept } from "@neptune";
import { html } from "@neptune/voby";

// @ts-expect-error Types dont include @plugin
import { storage } from "@plugin";
import { Tracer } from "@inrixia/lib/trace";
const trace = Tracer("DiscordRPC");

import { settings } from "./Settings";
export { Settings } from "./Settings";

import { SwitchSetting } from "@inrixia/lib/components/SwitchSetting";
import getPlaybackControl from "@inrixia/lib/getPlaybackControl";
import { TrackItemCache } from "@inrixia/lib/Caches/TrackItemCache";
import { updateRPC } from "./updateRPC.native";

enum AudioQuality {
HiRes = "HI_RES_LOSSLESS",
MQA = "HI_RES",
High = "LOSSLESS",
Low = "HIGH",
Lowest = "LOW",
}
export const onUnload = intercept("playbackControls/TIME_UPDATE", ([current]) => {
onTimeUpdate();
});
const onTimeUpdate = async () => {
const { playbackContext, playbackState, latestCurrentTime } = getPlaybackControl();
if (!playbackState || !latestCurrentTime || !playbackContext) return;
import { onRpcCleanup, updateRPC } from "./updateRPC.native";
import { type PlaybackContext } from "@inrixia/lib/AudioQualityTypes";

const mediaItemId = playbackContext.actualProductId;
if (mediaItemId === undefined) return;
let currentPlaybackContext: PlaybackContext | undefined;
export const onTimeUpdate = async (keepRpcOnPause: boolean, newTime?: number) => {
let { playbackContext, playbackState } = getPlaybackControl();
if (!playbackState) return;

const currentlyPlaying = await TrackItemCache.ensure(mediaItemId);
const currentlyPlaying = await TrackItemCache.ensure((currentPlaybackContext ?? playbackContext)?.actualProductId);
if (currentlyPlaying === undefined) return;

updateRPC(currentlyPlaying, playbackState, latestCurrentTime, storage.keepRpcOnPause);
updateRPC(currentlyPlaying, playbackState, keepRpcOnPause, newTime);
};
onTimeUpdate();

storage.keepRpcOnPause ??= false;
export function Settings() {
return html` <${SwitchSetting} checked=${storage.keepRpcOnPause} onClick=${() => (storage.keepRpcOnPause = !storage.keepRpcOnPause)} title="Keep RPC on pause" /> `;
}
const onUnloadTimeUpdate = intercept("playbackControls/TIME_UPDATE", ([newTime]) => {
onTimeUpdate(settings.keepRpcOnPause, newTime).catch(trace.msg.err.withContext("Failed to update"));
});
const onUnloadNewTrack = intercept("playbackControls/MEDIA_PRODUCT_TRANSITION", ([{ playbackContext }]) => {
currentPlaybackContext = <any>playbackContext;
console.log("SET", currentPlaybackContext?.actualProductId);
onTimeUpdate(settings.keepRpcOnPause).catch(trace.msg.err.withContext("Failed to update"));
});
onTimeUpdate(settings.keepRpcOnPause).catch(trace.msg.err.withContext("Failed to update"));
export const onUnload = () => {
onUnloadTimeUpdate();
onUnloadNewTrack();
onRpcCleanup();
};
5 changes: 3 additions & 2 deletions plugins/DiscordRPC/src/updateRPC.native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ const formatLongString = (s?: string) => {
};
const getMediaURLFromID = (id?: string, path = "/1280x1280.jpg") => (id ? "https://resources.tidal.com/images/" + id.split("-").join("/") + path : undefined);

export const updateRPC = async (currentlyPlaying: TrackItem, playbackState: PlaybackState, currentTime: number, keepRpcOnPause: boolean) => {
export const onRpcCleanup = () => rpcClient.cleanp();
export const updateRPC = async (currentlyPlaying: TrackItem, playbackState: PlaybackState, keepRpcOnPause: boolean, currentTime?: number) => {
const _rpcClient = await rpcClient.ensureRPC();
if (_rpcClient === undefined) return;
if (_rpcClient === undefined) throw new Error("Failed to obtain RPC client");

const activityState: Presence = {
buttons: [{ url: currentlyPlaying.url ?? `https://tidal.com/browse/track/${currentlyPlaying.id}?u`, label: "Play on Tidal" }],
Expand Down

0 comments on commit 72dd679

Please sign in to comment.