mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-21 22:15:40 +00:00
fix: v1.25.1 — Opus playback, single-instance enforcement
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [1.25.1] - 2026-04-01
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Opus playback** *(reported by [@powerfool](https://github.com/powerfool))*: `.opus` files were silently skipped because Symphonia has no Opus decoder. Opus tracks are now transcoded server-side to FLAC via the Subsonic `format=flac` parameter, avoiding any additional lossy encoding step.
|
||||
- **Single-instance enforcement** *(reported by [@netherguy4](https://github.com/netherguy4))*: Re-launching the app while it was already running (including minimized to tray) would spawn a new independent process, leading to playback conflicts and state divergence. Integrated `tauri-plugin-single-instance` — subsequent launches are intercepted, the existing window is shown, unminimized, and focused instead.
|
||||
|
||||
---
|
||||
|
||||
## [1.25.0] - 2026-04-01
|
||||
|
||||
### Added
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "psysonic",
|
||||
"version": "1.25.0",
|
||||
"version": "1.25.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Maintainer: Psychotoxic <psychotoxic@gmx.de>
|
||||
pkgname=psysonic
|
||||
pkgver=1.25.0
|
||||
pkgver=1.25.1
|
||||
pkgrel=1
|
||||
pkgdesc="Desktop music player for Subsonic API-compatible servers (Navidrome, Gonic, etc.)"
|
||||
arch=('x86_64')
|
||||
|
||||
Generated
+164
-11
@@ -85,6 +85,18 @@ dependencies = [
|
||||
"futures-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-broadcast"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532"
|
||||
dependencies = [
|
||||
"event-listener 5.4.1",
|
||||
"event-listener-strategy",
|
||||
"futures-core",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-channel"
|
||||
version = "2.5.0"
|
||||
@@ -198,6 +210,24 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-process"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"async-io 2.6.0",
|
||||
"async-lock 3.4.2",
|
||||
"async-signal",
|
||||
"async-task",
|
||||
"blocking",
|
||||
"cfg-if",
|
||||
"event-listener 5.4.1",
|
||||
"futures-lite 2.6.1",
|
||||
"rustix 1.1.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-recursion"
|
||||
version = "1.1.1"
|
||||
@@ -1059,6 +1089,12 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "endi"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099"
|
||||
|
||||
[[package]]
|
||||
name = "enumflags2"
|
||||
version = "0.7.12"
|
||||
@@ -3377,6 +3413,7 @@ dependencies = [
|
||||
"tauri-plugin-fs",
|
||||
"tauri-plugin-global-shortcut",
|
||||
"tauri-plugin-shell",
|
||||
"tauri-plugin-single-instance",
|
||||
"tauri-plugin-store",
|
||||
"tauri-plugin-window-state",
|
||||
"tokio",
|
||||
@@ -4279,8 +4316,8 @@ dependencies = [
|
||||
"pollster",
|
||||
"thiserror 1.0.69",
|
||||
"windows 0.44.0",
|
||||
"zbus",
|
||||
"zvariant",
|
||||
"zbus 3.15.2",
|
||||
"zvariant 3.15.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4827,6 +4864,21 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-single-instance"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc61e4822b8f74d68278e09161d3e3fdd1b14b9eb781e24edccaabf10c420e8c"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tauri",
|
||||
"thiserror 2.0.18",
|
||||
"tracing",
|
||||
"windows-sys 0.60.2",
|
||||
"zbus 5.14.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-store"
|
||||
version = "2.4.2"
|
||||
@@ -6569,12 +6621,12 @@ version = "3.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "675d170b632a6ad49804c8cf2105d7c31eddd3312555cffd4b740e08e97c25e6"
|
||||
dependencies = [
|
||||
"async-broadcast",
|
||||
"async-broadcast 0.5.1",
|
||||
"async-executor",
|
||||
"async-fs",
|
||||
"async-io 1.13.0",
|
||||
"async-lock 2.8.0",
|
||||
"async-process",
|
||||
"async-process 1.8.1",
|
||||
"async-recursion",
|
||||
"async-task",
|
||||
"async-trait",
|
||||
@@ -6599,9 +6651,44 @@ dependencies = [
|
||||
"uds_windows",
|
||||
"winapi",
|
||||
"xdg-home",
|
||||
"zbus_macros",
|
||||
"zbus_names",
|
||||
"zvariant",
|
||||
"zbus_macros 3.15.2",
|
||||
"zbus_names 2.6.1",
|
||||
"zvariant 3.15.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zbus"
|
||||
version = "5.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca82f95dbd3943a40a53cfded6c2d0a2ca26192011846a1810c4256ef92c60bc"
|
||||
dependencies = [
|
||||
"async-broadcast 0.7.2",
|
||||
"async-executor",
|
||||
"async-io 2.6.0",
|
||||
"async-lock 3.4.2",
|
||||
"async-process 2.5.0",
|
||||
"async-recursion",
|
||||
"async-task",
|
||||
"async-trait",
|
||||
"blocking",
|
||||
"enumflags2",
|
||||
"event-listener 5.4.1",
|
||||
"futures-core",
|
||||
"futures-lite 2.6.1",
|
||||
"hex",
|
||||
"libc",
|
||||
"ordered-stream",
|
||||
"rustix 1.1.4",
|
||||
"serde",
|
||||
"serde_repr",
|
||||
"tracing",
|
||||
"uds_windows",
|
||||
"uuid",
|
||||
"windows-sys 0.61.2",
|
||||
"winnow 0.7.15",
|
||||
"zbus_macros 5.14.0",
|
||||
"zbus_names 4.3.1",
|
||||
"zvariant 5.10.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6615,7 +6702,22 @@ dependencies = [
|
||||
"quote",
|
||||
"regex",
|
||||
"syn 1.0.109",
|
||||
"zvariant_utils",
|
||||
"zvariant_utils 1.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zbus_macros"
|
||||
version = "5.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "897e79616e84aac4b2c46e9132a4f63b93105d54fe8c0e8f6bffc21fa8d49222"
|
||||
dependencies = [
|
||||
"proc-macro-crate 3.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.117",
|
||||
"zbus_names 4.3.1",
|
||||
"zvariant 5.10.0",
|
||||
"zvariant_utils 3.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6626,7 +6728,18 @@ checksum = "437d738d3750bed6ca9b8d423ccc7a8eb284f6b1d6d4e225a0e4e6258d864c8d"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"static_assertions",
|
||||
"zvariant",
|
||||
"zvariant 3.15.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zbus_names"
|
||||
version = "4.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffd8af6d5b78619bab301ff3c560a5bd22426150253db278f164d6cf3b72c50f"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"winnow 0.7.15",
|
||||
"zvariant 5.10.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6726,7 +6839,21 @@ dependencies = [
|
||||
"libc",
|
||||
"serde",
|
||||
"static_assertions",
|
||||
"zvariant_derive",
|
||||
"zvariant_derive 3.15.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zvariant"
|
||||
version = "5.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5708299b21903bbe348e94729f22c49c55d04720a004aa350f1f9c122fd2540b"
|
||||
dependencies = [
|
||||
"endi",
|
||||
"enumflags2",
|
||||
"serde",
|
||||
"winnow 0.7.15",
|
||||
"zvariant_derive 5.10.0",
|
||||
"zvariant_utils 3.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6739,7 +6866,20 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"zvariant_utils",
|
||||
"zvariant_utils 1.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zvariant_derive"
|
||||
version = "5.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b59b012ebe9c46656f9cc08d8da8b4c726510aef12559da3e5f1bf72780752c"
|
||||
dependencies = [
|
||||
"proc-macro-crate 3.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.117",
|
||||
"zvariant_utils 3.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6752,3 +6892,16 @@ dependencies = [
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zvariant_utils"
|
||||
version = "3.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f75c23a64ef8f40f13a6989991e643554d9bef1d682a281160cf0c1bc389c5e9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"syn 2.0.117",
|
||||
"winnow 0.7.15",
|
||||
]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "psysonic"
|
||||
version = "1.25.0"
|
||||
version = "1.25.1"
|
||||
description = "Psysonic Desktop Music Player"
|
||||
authors = []
|
||||
license = ""
|
||||
@@ -22,6 +22,7 @@ tauri-build = { version = "2", features = [] }
|
||||
|
||||
[dependencies]
|
||||
tauri = { version = "2", features = ["tray-icon", "image-png"] }
|
||||
tauri-plugin-single-instance = "2"
|
||||
tauri-plugin-shell = "2"
|
||||
tauri-plugin-global-shortcut = "2"
|
||||
tauri-plugin-store = "2"
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
"core:window:allow-set-fullscreen",
|
||||
"core:window:allow-is-fullscreen",
|
||||
"core:window:allow-create",
|
||||
"core:webview:allow-create-webview-window"
|
||||
"core:webview:allow-create-webview-window",
|
||||
"single-instance:default"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -302,6 +302,12 @@ pub fn run() {
|
||||
.plugin(tauri_plugin_store::Builder::default().build())
|
||||
.plugin(tauri_plugin_dialog::init())
|
||||
.plugin(tauri_plugin_fs::init())
|
||||
.plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| {
|
||||
let window = app.get_webview_window("main").expect("no main window");
|
||||
let _ = window.show();
|
||||
let _ = window.unminimize();
|
||||
let _ = window.set_focus();
|
||||
}))
|
||||
|
||||
.setup(|app| {
|
||||
// ── System tray ───────────────────────────────────────────────
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "Psysonic",
|
||||
"version": "1.25.0",
|
||||
"version": "1.25.1",
|
||||
"identifier": "dev.psysonic.player",
|
||||
"build": {
|
||||
"beforeDevCommand": "npm run dev",
|
||||
|
||||
+6
-1
@@ -325,7 +325,7 @@ export async function reportNowPlaying(id: string): Promise<void> {
|
||||
}
|
||||
|
||||
// ─── Stream URL ───────────────────────────────────────────────
|
||||
export function buildStreamUrl(id: string): string {
|
||||
export function buildStreamUrl(id: string, suffix?: string): string {
|
||||
const { getBaseUrl, getActiveServer } = useAuthStore.getState();
|
||||
const server = getActiveServer();
|
||||
const baseUrl = getBaseUrl();
|
||||
@@ -336,6 +336,11 @@ export function buildStreamUrl(id: string): string {
|
||||
u: server?.username ?? '',
|
||||
t: token, s: salt, v: '1.16.1', c: 'psysonic', f: 'json',
|
||||
});
|
||||
|
||||
if (suffix === 'opus') {
|
||||
p.set('format', 'flac'); // Transcode OPUS to FLAC since Rust/Symphonia has no Opus decoder
|
||||
}
|
||||
|
||||
return `${baseUrl}/rest/stream.view?${p.toString()}`;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user