Smarter/more granular event handling

This commit is contained in:
2025-02-23 16:37:39 -08:00
parent fe05a27b51
commit 687a7fc555
6 changed files with 81 additions and 99 deletions

View File

@@ -4,11 +4,21 @@ import { WebSocket } from "ws";
import { getLinkPreview } from "link-preview-js";
import { PlaylistItem, LinkMetadata } from './types';
import { FavoritesStore } from "./FavoritesStore";
interface PendingCommand {
resolve: (value: any) => void;
reject: (reason: any) => void;
}
enum UserEvent {
PlaylistUpdate = "playlist_update",
NowPlayingUpdate = "now_playing_update",
VolumeUpdate = "volume_update",
FavoritesUpdate = "favorites_update",
MetadataUpdate = "metadata_update",
MPDUpdate = "mpd_update",
}
export class MediaPlayer {
private playerProcess: ChildProcess;
private socket: Socket;
@@ -43,7 +53,7 @@ export class MediaPlayer {
this.favoritesStore = new FavoritesStore();
this.favoritesStore.onFavoritesChanged = (favorites) => {
this.handleEvent("favorites_update", { favorites });
this.handleEvent(UserEvent.FavoritesUpdate, { favorites });
};
}
@@ -123,31 +133,31 @@ export class MediaPlayer {
}
public async play() {
return this.modify(() => this.writeCommand("set_property", ["pause", false]));
return this.modify(UserEvent.NowPlayingUpdate, () => this.writeCommand("set_property", ["pause", false]));
}
public async pause() {
return this.modify(() => this.writeCommand("set_property", ["pause", true]));
return this.modify(UserEvent.NowPlayingUpdate, () => this.writeCommand("set_property", ["pause", true]));
}
public async skip() {
return this.modify(() => this.writeCommand("playlist-next", []));
return this.modify(UserEvent.PlaylistUpdate, () => this.writeCommand("playlist-next", []));
}
public async skipTo(index: number) {
return this.modify(() => this.writeCommand("playlist-play-index", [index]));
return this.modify(UserEvent.PlaylistUpdate, () => this.writeCommand("playlist-play-index", [index]));
}
public async previous() {
return this.modify(() => this.writeCommand("playlist-prev", []));
return this.modify(UserEvent.PlaylistUpdate, () => this.writeCommand("playlist-prev", []));
}
public async deletePlaylistItem(index: number) {
return this.modify(() => this.writeCommand("playlist-remove", [index]));
return this.modify(UserEvent.PlaylistUpdate, () => this.writeCommand("playlist-remove", [index]));
}
public async setVolume(volume: number) {
return this.modify(() => this.writeCommand("set_property", ["volume", volume]));
return this.modify(UserEvent.VolumeUpdate, () => this.writeCommand("set_property", ["volume", volume]));
}
public subscribe(ws: WebSocket) {
@@ -175,18 +185,18 @@ export class MediaPlayer {
}
private async loadFile(url: string, mode: string) {
this.modify(() => this.writeCommand("loadfile", [url, mode]));
this.modify(UserEvent.PlaylistUpdate, () => this.writeCommand("loadfile", [url, mode]));
this.fetchMetadataAndNotify(url).catch(error => {
console.warn(`Failed to fetch metadata for ${url}:`, error);
});
}
private async modify<T>(func: () => Promise<T>): Promise<T> {
private async modify<T>(event: UserEvent, func: () => Promise<T>): Promise<T> {
return func()
.then((result) => {
// Notify all subscribers
this.handleEvent("user_modify", {});
this.handleEvent(event, {});
return result;
});
}
@@ -230,7 +240,7 @@ export class MediaPlayer {
console.log(this.metadata.get(url));
// Notify clients that metadata has been updated
this.handleEvent("metadata_update", {
this.handleEvent(UserEvent.MetadataUpdate, {
url,
metadata: this.metadata.get(url)
});
@@ -272,7 +282,7 @@ export class MediaPlayer {
this.pendingCommands.delete(response.request_id);
}
} else if (response.event) {
this.handleEvent(response.event, response);
this.handleEvent(UserEvent.MPDUpdate, response);
} else {
console.log(response);
}