Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit 14717ef

Browse files
committed
Merge branch 'main' of github.com:Moosync/Moosync
2 parents 26cbdc2 + 1929350 commit 14717ef

File tree

16 files changed

+1417
-2771
lines changed

16 files changed

+1417
-2771
lines changed

package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"@types/jest": "^29.5.11",
3737
"@types/js-yaml": "^4.0.9",
3838
"@types/markdown-it": "^13.0.7",
39-
"@types/node": "^20.11.5",
39+
"@types/node": "^20.11.6",
4040
"@types/tail": "^2.2.3",
4141
"@types/usetube": "^2.1.2",
4242
"@types/uuid": "^9.0.7",
@@ -54,7 +54,7 @@
5454
"@vue/eslint-config-typescript": "^12.0.0",
5555
"adm-zip": "^0.5.10",
5656
"animate.css": "^4.1.1",
57-
"axios": "^1.6.5",
57+
"axios": "^1.6.6",
5858
"axios-rate-limit": "^1.3.0",
5959
"axios-retry": "^4.0.0",
6060
"babel-loader": "^9.1.3",
@@ -69,8 +69,8 @@
6969
"cross-env": "^7.0.3",
7070
"dashjs": "^4.7.3",
7171
"deepmerge": "^4.3.1",
72-
"dotenv": "^16.4.0",
73-
"electron": "28.1.4",
72+
"dotenv": "^16.4.1",
73+
"electron": "28.2.0",
7474
"electron-devtools-installer": "^3.2.0",
7575
"electron-store": "^8.1.0",
7676
"electron-updater": "^6.1.7",
@@ -102,6 +102,7 @@
102102
"qs": "^6.11.2",
103103
"reflect-metadata": "^0.2.1",
104104
"replace": "^1.2.2",
105+
"rodio-audio-backend": "https://github.com/Moosync/node-rodio-backend",
105106
"sass": "~1.70.0",
106107
"sass-loader": "14.0.0",
107108
"scanner-native": "git+https://github.com/Moosync/file-scanner.git",

src/mainWindow/components/musicbar/components/AudioStream.vue

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ import { EventBus } from '@/utils/main/ipc/constants'
6868
import { nextTick } from 'vue'
6969
import { convertProxy } from '@/utils/ui/common'
7070
import { RepeatState } from '../../../../utils/commonConstants';
71+
import { RodioPlayer } from '../../../../utils/ui/players/rodio';
7172
7273
@Component({
7374
emits: ['onTimeUpdate']
@@ -223,6 +224,7 @@ export default class AudioStream extends mixins(
223224
if (player) {
224225
console.debug('Initializing player', player.key)
225226
await this.initializePlayer(player)
227+
console.debug('Initialized player', player.key)
226228
227229
this.activePlayer = player
228230
@@ -326,6 +328,7 @@ export default class AudioStream extends mixins(
326328
const players = await new Promise<Player[]>((resolve) => {
327329
const players: Player[] = []
328330
331+
players.push(new RodioPlayer())
329332
players.push(new LocalPlayer())
330333
players.push(new DashPlayer())
331334
players.push(new HLSPlayer())
@@ -378,7 +381,7 @@ export default class AudioStream extends mixins(
378381
return
379382
}
380383
381-
if (player instanceof SpotifyPlayer) {
384+
if (player instanceof SpotifyPlayer || player instanceof RodioPlayer) {
382385
await player.initialize()
383386
}
384387
@@ -464,7 +467,7 @@ export default class AudioStream extends mixins(
464467
}
465468
}
466469
467-
if (time >= this.currentSong.duration - this.timeSkipSeconds) {
470+
if (this.timeSkipSeconds && time >= this.currentSong.duration - this.timeSkipSeconds) {
468471
this.onSongEnded()
469472
}
470473
}

src/types/declarations/ipc.d.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,3 +342,17 @@ declare namespace NotifierRequests {
342342
mainWindow: boolean | 'both'
343343
}
344344
}
345+
346+
declare namespace RodioRequests {
347+
interface SetSrc {
348+
path: string
349+
}
350+
351+
interface Volume {
352+
volume: number
353+
}
354+
355+
interface Seek {
356+
pos: number
357+
}
358+
}

src/types/declarations/window.d.ts

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
* See LICENSE in the project root for license information.
88
*/
99

10+
import { RodioEvents } from '@/utils/main/ipc/constants'
11+
1012
/**
1113
* Utils related to database operations
1214
*/
@@ -365,18 +367,32 @@ interface spotifyPlayer {
365367
getToken: (scopes: TokenScope[]) => Promise<import('librespot-node').Token>
366368
}
367369

368-
interface Window {
369-
DBUtils: DBUtils
370-
SearchUtils: searchUtils
371-
FileUtils: fileUtils
372-
PreferenceUtils: preferenceUtils
373-
WindowUtils: windowUtils
374-
Store: store
375-
LoggerUtils: loggerUtils
376-
NotifierUtils: notifierUtils
377-
ExtensionUtils: extensionUtils
378-
ThemeUtils: themeUtils
379-
UpdateUtils: updateUtils
380-
MprisUtils: mprisUtils
381-
SpotifyPlayer: spotifyPlayer
370+
interface rodioUtils {
371+
initialize: () => Promise<void>
372+
setSrc: (path: string) => Promise<void>
373+
play: () => Promise<void>
374+
pause: () => Promise<void>
375+
stop: () => Promise<void>
376+
seek: (pos: number) => Promise<void>
377+
setVolume: (volume: number) => Promise<void>
378+
listenEvents: (callback: (event: RodioEvents) => void) => void
379+
}
380+
381+
declare global {
382+
interface Window {
383+
DBUtils: DBUtils
384+
SearchUtils: searchUtils
385+
FileUtils: fileUtils
386+
PreferenceUtils: preferenceUtils
387+
WindowUtils: windowUtils
388+
Store: store
389+
LoggerUtils: loggerUtils
390+
NotifierUtils: notifierUtils
391+
ExtensionUtils: extensionUtils
392+
ThemeUtils: themeUtils
393+
UpdateUtils: updateUtils
394+
MprisUtils: mprisUtils
395+
SpotifyPlayer: spotifyPlayer
396+
RodioUtils: rodioUtils
397+
}
382398
}

src/utils/main/ipc/constants.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export enum IpcEvents {
2626
UPDATE = 'update',
2727
MPRIS = 'mpris',
2828
SPOTIFY = 'spotify',
29+
RODIO = 'rodio',
2930
}
3031

3132
export enum StoreEvents {
@@ -206,6 +207,26 @@ export enum MprisEvents {
206207
ON_BUTTON_PRESSED = 'onButtonPressed',
207208
}
208209

210+
export enum RodioEvents {
211+
INITIALIZE = 'initialize',
212+
SET_SRC = 'setSrc',
213+
PLAY = 'play',
214+
PAUSE = 'pause',
215+
STOP = 'stop',
216+
SET_VOLUME = 'setVolume',
217+
GET_VOLUME = 'getVolume',
218+
GET_POSITION = 'getPosition',
219+
SEEK = 'seek',
220+
221+
ON_PLAY = 'onPlay',
222+
ON_PAUSE = 'onPause',
223+
ON_STOP = 'onStop',
224+
ON_TIME_UPDATE = 'onTimeUpdate',
225+
ON_LOADED = 'onLoaded',
226+
ON_ENDED = 'onEnded',
227+
ON_ERROR = 'onError',
228+
}
229+
209230
export enum ExtensionHostEvents {
210231
GET_ALL_EXTENSIONS = 'getAllExtensions',
211232
INSTALL = 'install',

src/utils/main/ipc/index.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,26 @@
77
* See LICENSE in the project root for license information.
88
*/
99

10+
import { BrowserWindowChannel } from './window'
1011
import { ExtensionHostChannel } from './extensionHost'
1112
import { LoggerChannel } from './logger'
1213
import { MprisChannel } from './mpris'
1314
import { NotifierChannel } from './notifier'
1415
import { PlaylistsChannel } from './playlists'
1516
import { PreferenceChannel } from './preferences'
17+
import { RodioChannel } from './rodio'
1618
import { ScannerChannel } from './scanner'
1719
import { SearchChannel } from './search'
1820
import { SongsChannel } from './songs'
1921
import { SpotifyPlayerChannel } from './spotifyPlayer'
2022
import { StoreChannel } from './store'
2123
import { UpdateChannel } from './update'
22-
import { BrowserWindowChannel } from './window'
2324
import { ipcMain } from 'electron'
2425

2526
let scannerChannel: ScannerChannel | undefined = undefined
2627
let updateChannel: UpdateChannel | undefined = undefined
2728
let extensionChannel: ExtensionHostChannel | undefined = undefined
29+
let rodioChannel: RodioChannel | undefined = undefined
2830
let preferenceChannel: PreferenceChannel | undefined = undefined
2931
let storeChannel: StoreChannel | undefined = undefined
3032
let mprisChannel: MprisChannel | undefined = undefined
@@ -45,10 +47,18 @@ export function registerIpcChannels() {
4547
new NotifierChannel(),
4648
getMprisChannel(),
4749
getSpotifyPlayerChannel(),
50+
getRodioChannel(),
4851
]
4952
ipcChannels.forEach((channel) => ipcMain.on(channel.name, (event, request) => channel.handle(event, request)))
5053
}
5154

55+
export function getRodioChannel() {
56+
if (!rodioChannel) {
57+
rodioChannel = new RodioChannel()
58+
}
59+
return rodioChannel
60+
}
61+
5262
export function getExtensionHostChannel() {
5363
if (!extensionChannel) {
5464
extensionChannel = new ExtensionHostChannel()

src/utils/main/ipc/rodio.ts

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*
2+
* mpris.ts is a part of Moosync.
3+
*
4+
* Copyright 2022 by Sahil Gupte <[email protected]>. All rights reserved.
5+
* Licensed under the GNU General Public License.
6+
*
7+
* See LICENSE in the project root for license information.
8+
*/
9+
10+
import { IpcEvents, RodioEvents } from './constants'
11+
12+
import { RodioBackend } from 'rodio-audio-backend'
13+
import { WindowHandler } from '../windowManager'
14+
15+
export class RodioChannel implements IpcChannelInterface {
16+
name = IpcEvents.RODIO
17+
18+
isStarted = false
19+
private rodioInstance: RodioBackend | undefined
20+
21+
handle(event: Electron.IpcMainEvent, request: IpcRequest): void {
22+
switch (request.type) {
23+
case RodioEvents.INITIALIZE:
24+
this.initialize(event, request)
25+
break
26+
case RodioEvents.SET_SRC:
27+
this.setSrc(event, request as IpcRequest<RodioRequests.SetSrc>)
28+
break
29+
case RodioEvents.PLAY:
30+
this.play(event, request)
31+
break
32+
case RodioEvents.PAUSE:
33+
this.pause(event, request)
34+
break
35+
case RodioEvents.STOP:
36+
this.stop(event, request)
37+
break
38+
case RodioEvents.SEEK:
39+
this.seek(event, request as IpcRequest<RodioRequests.Seek>)
40+
break
41+
case RodioEvents.SET_VOLUME:
42+
this.setVolume(event, request as IpcRequest<RodioRequests.Volume>)
43+
break
44+
}
45+
}
46+
47+
private async initialize(event: Electron.IpcMainEvent, request: IpcRequest) {
48+
console.debug('Initializing Rodio backend')
49+
this.rodioInstance = new RodioBackend()
50+
this.registerListeners()
51+
52+
event.reply(request.responseChannel)
53+
}
54+
55+
private async setSrc(event: Electron.IpcMainEvent, request: IpcRequest<RodioRequests.SetSrc>) {
56+
if (request.params.path) {
57+
try {
58+
await this.rodioInstance?.setSrc(request.params.path)
59+
} catch (e) {
60+
this.emitError(e)
61+
}
62+
}
63+
64+
event.reply(request.responseChannel)
65+
}
66+
67+
private async play(event: Electron.IpcMainEvent, request: IpcRequest) {
68+
try {
69+
await this.rodioInstance?.play()
70+
} catch (e) {
71+
this.emitError(e)
72+
}
73+
event.reply(request.responseChannel)
74+
}
75+
76+
private async pause(event: Electron.IpcMainEvent, request: IpcRequest) {
77+
try {
78+
await this.rodioInstance?.pause()
79+
} catch (e) {
80+
this.emitError(e)
81+
}
82+
event.reply(request.responseChannel)
83+
}
84+
85+
public async stop(event?: Electron.IpcMainEvent, request?: IpcRequest) {
86+
try {
87+
await this.rodioInstance?.stop()
88+
} catch (e) {
89+
this.emitError(e)
90+
}
91+
event?.reply(request?.responseChannel ?? '')
92+
}
93+
94+
private async setVolume(event: Electron.IpcMainEvent, request: IpcRequest<RodioRequests.Volume>) {
95+
if (request.params.volume) {
96+
try {
97+
await this.rodioInstance?.setVolume(request.params.volume)
98+
} catch (e) {
99+
this.emitError(e)
100+
}
101+
}
102+
103+
event.reply(request.responseChannel)
104+
}
105+
106+
private async seek(event: Electron.IpcMainEvent, request: IpcRequest<RodioRequests.Seek>) {
107+
if (request.params.pos) {
108+
try {
109+
await this.rodioInstance?.seek(request.params.pos)
110+
} catch (e) {
111+
this.emitError(e)
112+
}
113+
}
114+
115+
event.reply(request.responseChannel)
116+
}
117+
118+
private emitError(e: unknown) {
119+
WindowHandler.getWindow(true)?.webContents.send(IpcEvents.RODIO, RodioEvents.ON_ERROR, e)
120+
}
121+
122+
private registerListeners() {
123+
this.rodioInstance?.on('play', () => {
124+
WindowHandler.getWindow(true)?.webContents.send(IpcEvents.RODIO, RodioEvents.ON_PLAY)
125+
})
126+
127+
this.rodioInstance?.on('pause', () => {
128+
WindowHandler.getWindow(true)?.webContents.send(IpcEvents.RODIO, RodioEvents.ON_PAUSE)
129+
})
130+
131+
this.rodioInstance?.on('stop', () => {
132+
WindowHandler.getWindow(true)?.webContents.send(IpcEvents.RODIO, RodioEvents.ON_STOP)
133+
})
134+
135+
this.rodioInstance?.on('loaded', () => {
136+
WindowHandler.getWindow(true)?.webContents.send(IpcEvents.RODIO, RodioEvents.ON_LOADED)
137+
})
138+
139+
this.rodioInstance?.on('ended', () => {
140+
WindowHandler.getWindow(true)?.webContents.send(IpcEvents.RODIO, RodioEvents.ON_ENDED)
141+
})
142+
143+
this.rodioInstance?.on('timeUpdate', (val) => {
144+
WindowHandler.getWindow(true)?.webContents.send(IpcEvents.RODIO, RodioEvents.ON_TIME_UPDATE, val / 1000)
145+
})
146+
}
147+
}

0 commit comments

Comments
 (0)