Skip to content

Commit d37cd24

Browse files
JellyBrickTotto16
andauthored
fix: fix bugs in MPRIS, and improve MPRIS (#1760)
Co-authored-by: JellyBrick <[email protected]> Co-authored-by: Totto <[email protected]>
1 parent 8bd05f5 commit d37cd24

File tree

15 files changed

+516
-300
lines changed

15 files changed

+516
-300
lines changed

src/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,9 @@ app.whenReady().then(async () => {
673673
);
674674
}
675675

676-
handleProtocol(command);
676+
const splited = decodeURIComponent(command).split(' ');
677+
678+
handleProtocol(splited.shift()!, splited);
677679
return;
678680
}
679681

src/plugins/music-together/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { t } from '@/i18n';
66
import { createPlugin } from '@/utils';
77
import promptOptions from '@/providers/prompt-options';
88

9-
import { type AppElement, getDefaultProfile, type Permission, type Profile, type VideoData } from './types';
9+
import { getDefaultProfile, type Permission, type Profile, type VideoData } from './types';
1010
import { Queue } from './queue';
1111
import { Connection, type ConnectionEventUnion } from './connection';
1212
import { createHostPopup } from './ui/host';
@@ -19,6 +19,7 @@ import style from './style.css?inline';
1919
import type { YoutubePlayer } from '@/types/youtube-player';
2020
import type { RendererContext } from '@/types/contexts';
2121
import type { VideoDataChanged } from '@/types/video-data-changed';
22+
import type { AppElement } from '@/types/queue';
2223

2324
type RawAccountData = {
2425
accountName: {

src/plugins/music-together/queue/queue.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ import { mapQueueItem } from './utils';
44
import { t } from '@/i18n';
55

66
import type { ConnectionEventUnion } from '@/plugins/music-together/connection';
7-
import type { Profile, QueueElement, VideoData } from '../types';
7+
import type { Profile, VideoData } from '../types';
88
import type { QueueItem } from '@/types/datahost-get-state';
9+
import type { QueueElement } from '@/types/queue';
910

1011
const getHeaderPayload = (() => {
1112
let payload: {

src/plugins/music-together/types.ts

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,3 @@
1-
import type { YoutubePlayer } from '@/types/youtube-player';
2-
import type { GetState, QueueItem } from '@/types/datahost-get-state';
3-
4-
type StoreState = GetState;
5-
type Store = {
6-
dispatch: (obj: {
7-
type: string;
8-
payload?: {
9-
items?: QueueItem[];
10-
};
11-
}) => void;
12-
13-
getState: () => StoreState;
14-
replaceReducer: (param1: unknown) => unknown;
15-
subscribe: (callback: () => void) => unknown;
16-
}
17-
18-
export type QueueElement = HTMLElement & {
19-
dispatch(obj: {
20-
type: string;
21-
payload?: unknown;
22-
}): void;
23-
queue: QueueAPI;
24-
};
25-
export type QueueAPI = {
26-
getItems(): unknown[];
27-
store: {
28-
store: Store,
29-
};
30-
continuation?: string;
31-
autoPlaying?: boolean;
32-
};
33-
export type AppElement = HTMLElement & AppAPI;
34-
export type AppAPI = {
35-
queue_: QueueAPI;
36-
playerApi_: YoutubePlayer;
37-
openToast: (message: string) => void;
38-
39-
// TODO: Add more
40-
};
41-
421
export type Profile = {
432
id: string;
443
handleId: string;

src/plugins/notifications/interactive.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,9 +307,9 @@ export default (
307307
savedNotification?.close();
308308
});
309309

310-
changeProtocolHandler((cmd) => {
310+
changeProtocolHandler((cmd, args) => {
311311
if (Object.keys(songControls).includes(cmd)) {
312-
songControls[cmd as keyof typeof songControls]();
312+
songControls[cmd as keyof typeof songControls](args as never);
313313
if (
314314
config().refreshOnPlayPause &&
315315
(cmd === 'pause' || (cmd === 'play' && !config().unpauseNotification))

src/plugins/shortcuts/mpris-service.d.ts

Lines changed: 93 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ declare module '@jellybrick/mpris-service' {
44
import { interface as dbusInterface } from 'dbus-next';
55

66
interface RootInterfaceOptions {
7-
identity: string;
8-
supportedUriSchemes: string[];
9-
supportedMimeTypes: string[];
10-
desktopEntry: string;
7+
identity?: string;
8+
supportedUriSchemes?: string[];
9+
supportedMimeTypes?: string[];
10+
desktopEntry?: string;
1111
}
1212

1313
export interface Track {
@@ -35,6 +35,32 @@ declare module '@jellybrick/mpris-service' {
3535
'xesam:userRating'?: number;
3636
}
3737

38+
export type PlayBackStatus = 'Playing' | 'Paused' | 'Stopped';
39+
40+
export type LoopStatus = 'None' | 'Track' | 'Playlist';
41+
42+
export const PLAYBACK_STATUS_PLAYING: 'Playing';
43+
export const PLAYBACK_STATUS_PAUSED: 'Paused';
44+
export const PLAYBACK_STATUS_STOPPED: 'Stopped';
45+
46+
export const LOOP_STATUS_NONE: 'None';
47+
export const LOOP_STATUS_TRACK: 'Track';
48+
export const LOOP_STATUS_PLAYLIST: 'Playlist';
49+
50+
export type Interfaces = 'player' | 'trackList' | 'playlists';
51+
52+
export interface AdditionalPlayerOptions {
53+
name: string;
54+
supportedInterfaces: Interfaces[];
55+
}
56+
57+
export type PlayerOptions = RootInterfaceOptions & AdditionalPlayerOptions;
58+
59+
export interface Position {
60+
trackId: string;
61+
position: number;
62+
}
63+
3864
declare class Player extends EventEmitter {
3965
constructor(opts: {
4066
name: string;
@@ -43,18 +69,44 @@ declare module '@jellybrick/mpris-service' {
4369
supportedInterfaces?: string[];
4470
});
4571

72+
//RootInterface
73+
on(event: 'quit', listener: () => void): this;
74+
on(event: 'raise', listener: () => void): this;
75+
on(
76+
event: 'fullscreen',
77+
listener: (fullscreenEnabled: boolean) => void,
78+
): this;
79+
80+
emit(type: string, ...args: unknown[]): unknown;
81+
4682
name: string;
4783
identity: string;
48-
fullscreen: boolean;
84+
fullscreen?: boolean;
4985
supportedUriSchemes: string[];
5086
supportedMimeTypes: string[];
5187
canQuit: boolean;
5288
canRaise: boolean;
53-
canSetFullscreen: boolean;
89+
canSetFullscreen?: boolean;
90+
desktopEntry?: string;
5491
hasTrackList: boolean;
55-
desktopEntry: string;
56-
playbackStatus: string;
57-
loopStatus: string;
92+
93+
// PlayerInterface
94+
on(event: 'next', listener: () => void): this;
95+
on(event: 'previous', listener: () => void): this;
96+
on(event: 'pause', listener: () => void): this;
97+
on(event: 'playpause', listener: () => void): this;
98+
on(event: 'stop', listener: () => void): this;
99+
on(event: 'play', listener: () => void): this;
100+
on(event: 'seek', listener: (offset: number) => void): this;
101+
on(event: 'open', listener: ({ uri: string }) => void): this;
102+
on(event: 'loopStatus', listener: (status: LoopStatus) => void): this;
103+
on(event: 'rate', listener: () => void): this;
104+
on(event: 'shuffle', listener: (enableShuffle: boolean) => void): this;
105+
on(event: 'volume', listener: (newVolume: number) => void): this;
106+
on(event: 'position', listener: (position: Position) => void): this;
107+
108+
playbackStatus: PlayBackStatus;
109+
loopStatus: LoopStatus;
58110
shuffle: boolean;
59111
metadata: Track;
60112
volume: number;
@@ -67,9 +119,40 @@ declare module '@jellybrick/mpris-service' {
67119
rate: number;
68120
minimumRate: number;
69121
maximumRate: number;
70-
playlists: unknown[];
122+
123+
abstract getPosition(): number;
124+
125+
seeked(position: number): void;
126+
127+
// TracklistInterface
128+
on(event: 'addTrack', listener: () => void): this;
129+
on(event: 'removeTrack', listener: () => void): this;
130+
on(event: 'goTo', listener: () => void): this;
131+
132+
tracks: Track[];
133+
canEditTracks: boolean;
134+
135+
on(event: '*', a: unknown[]): this;
136+
137+
addTrack(track: string): void;
138+
139+
removeTrack(trackId: string): void;
140+
141+
// PlaylistsInterface
142+
on(event: 'activatePlaylist', listener: () => void): this;
143+
144+
playlists: Playlist[];
71145
activePlaylist: string;
72146

147+
setPlaylists(playlists: Playlist[]): void;
148+
149+
setActivePlaylist(playlistId: string): void;
150+
151+
// Player methods
152+
constructor(opts: PlayerOptions);
153+
154+
on(event: 'error', listener: (error: Error) => void): this;
155+
73156
init(opts: RootInterfaceOptions): void;
74157

75158
objectPath(subpath?: string): string;
@@ -91,13 +174,6 @@ declare module '@jellybrick/mpris-service' {
91174
setPlaylists(playlists: Track[]): void;
92175

93176
setActivePlaylist(playlistId: string): void;
94-
95-
static PLAYBACK_STATUS_PLAYING: 'Playing';
96-
static PLAYBACK_STATUS_PAUSED: 'Paused';
97-
static PLAYBACK_STATUS_STOPPED: 'Stopped';
98-
static LOOP_STATUS_NONE: 'None';
99-
static LOOP_STATUS_TRACK: 'Track';
100-
static LOOP_STATUS_PLAYLIST: 'Playlist';
101177
}
102178

103179
interface MprisInterface extends dbusInterface.Interface {

0 commit comments

Comments
 (0)