Skip to content

Commit e367129

Browse files
committed
Mabey fix linux playback
1 parent 3e4fd6f commit e367129

7 files changed

Lines changed: 51 additions & 12 deletions

File tree

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "just-another-music-client",
33
"private": true,
4-
"version": "1.2.71",
4+
"version": "1.2.72",
55
"type": "module",
66
"scripts": {
77
"dev": "vite",

src-tauri/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src-tauri/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "just-another-music-client"
3-
version = "1.2.71"
3+
version = "1.2.72"
44
description = "A desktop music client"
55
authors = ["you"]
66
edition = "2021"

src-tauri/tauri.conf.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://schema.tauri.app/config/2",
33
"productName": "Just Another Music Client",
4-
"version": "1.2.71",
4+
"version": "1.2.72",
55
"identifier": "com.justanothermusicclient.desktop",
66
"build": {
77
"beforeDevCommand": "npm run dev",

src/player/AudioEngine.ts

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,8 @@ let playbackClaimId = 0;
5858
let playbackOwner: AudioEngine | null = null;
5959

6060
function shouldUseNativeAudio(): boolean {
61-
// Native audio playback is disabled on macOS/Linux because the backend
62-
// download path (getStreamData) can fail with 403 errors. The iframe-based
63-
// YouTube player is more reliable across all platforms.
61+
// The maintained playback path is the YouTube iframe player. Native audio is
62+
// kept as an explicit fallback for player errors that are specific to a webview.
6463
return false;
6564
}
6665

@@ -141,6 +140,7 @@ export class AudioEngine {
141140
}
142141

143142
const requestId = ++this.loadRequestId;
143+
this.releaseNativeAudio();
144144
const player = await this.ensurePlayer();
145145
if (requestId !== this.loadRequestId) return;
146146
if (this.currentVideoId === videoId) return;
@@ -155,18 +155,34 @@ export class AudioEngine {
155155
videoId,
156156
);
157157
player.cueVideoById(videoId);
158-
await cued;
158+
try {
159+
await cued;
160+
} catch (error) {
161+
if (requestId === this.loadRequestId && this.currentVideoId === videoId) {
162+
this.currentVideoId = null;
163+
}
164+
throw error;
165+
}
159166
if (requestId !== this.loadRequestId || this.currentVideoId !== videoId) return;
160167
logInternalInfo("AudioEngine.loadTrack cued", { videoId });
161168
}
162169

170+
async loadNativeFallback(
171+
videoId: string,
172+
audioData: ArrayBuffer,
173+
mimeType?: string,
174+
): Promise<void> {
175+
this.player?.stopVideo();
176+
await this.loadNativeAudio(videoId, audioData, mimeType);
177+
}
178+
163179
setOnEnded(listener: (() => void) | null): void {
164180
this.onEnded = listener;
165181
}
166182

167183
async play(): Promise<boolean> {
168184
const claimId = this.claimPlayback();
169-
if (this.useNativeAudio) {
185+
if (this.useNativeAudio || this.audio) {
170186
if (!this.audio || !this.currentVideoId) {
171187
throw new Error("No audio track is loaded.");
172188
}
@@ -401,6 +417,7 @@ export class AudioEngine {
401417
}
402418

403419
private pauseForPlaybackClaim(): void {
420+
this.audio?.pause();
404421
this.player?.pauseVideo();
405422
}
406423

src/player/PlayerController.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ export interface PlayerSession {
3636

3737
type Listener = () => void;
3838

39+
function isYouTubePlayerError5(error: unknown): boolean {
40+
const message = error instanceof Error ? error.message : String(error);
41+
return /\bYouTube player error 5\b/.test(message);
42+
}
43+
3944
function normalizePlaybackOrderMode(mode: unknown): PlaybackOrderMode {
4045
if (mode === "shuffle") return "shuffle";
4146
if (mode === "repeat-one" || mode === "repeat-all") return "repeat-one";
@@ -608,7 +613,24 @@ export class PlayerController {
608613
if (this.audioEngine.usesNativeAudio() && !audioData) {
609614
throw new Error("The data source does not support native audio playback.");
610615
}
611-
await this.audioEngine.loadTrack(track.id, audioData?.bytes, audioData?.mimeType);
616+
try {
617+
await this.audioEngine.loadTrack(track.id, audioData?.bytes, audioData?.mimeType);
618+
} catch (error) {
619+
if (!isYouTubePlayerError5(error) || !this.dataSource.getStreamData) {
620+
throw error;
621+
}
622+
623+
logInternalWarn("PlayerController.ensureTrackLoaded falling back to native audio", {
624+
trackId: track.id,
625+
error: error instanceof Error ? error.message : String(error),
626+
});
627+
const fallbackAudioData = await this.dataSource.getStreamData(track);
628+
await this.audioEngine.loadNativeFallback(
629+
track.id,
630+
fallbackAudioData.bytes,
631+
fallbackAudioData.mimeType,
632+
);
633+
}
612634

613635
this.loadedTrackId = track.id;
614636
if (this.pendingSeekTime !== null) {

0 commit comments

Comments
 (0)