diff --git a/client/src/components/BottomNav.tsx b/client/src/components/BottomNav.tsx
index e72dfda..4d6809d 100644
--- a/client/src/components/BottomNav.tsx
+++ b/client/src/components/BottomNav.tsx
@@ -1,7 +1,7 @@
/* ============================================================
BOTTOM NAV — Luxsin X9 Controller (Mobile)
Design: iOS/Android App-style bottom tab bar
- 5 tabs — labels from locales/bottomNav, language = deviceState.language (同系统页)
+ 3 个入口(社区/主页/我的 AI),文案来自 locales/bottomNav,语言跟随 deviceState.language
- 社区:移动端进入 /community 引导复制链接;桌面(lg+)点击仍 window.open 论坛
- Active tab: cyan icon + top indicator bar
- Inactive: muted icon + label
@@ -13,13 +13,7 @@ import { useIsLgUp } from "@/hooks/useIsLgUp";
import localeZh from "@/locales/data-zh.json";
import localeEn from "@/locales/data-en.json";
import { resolveLocalePack } from "@/locales/resolveLocale";
-import {
- Activity,
- Bot,
- Home,
- MessageSquare,
- Sliders,
-} from "lucide-react";
+import { Bot, Home, MessageSquare } from "lucide-react";
import { Link, useLocation } from "wouter";
import { useMemo } from "react";
import { bottomNavInnerClass, bottomNavOuterClass } from "@/lib/appShell";
@@ -36,9 +30,7 @@ const FORUM_URL = "https://forum.zidoo.tv/index.php";
const NAV_ITEMS: NavItem[] = [
{ path: "/community", icon: MessageSquare, labelKey: "community" },
- { path: "/eq", icon: Sliders, labelKey: "hpEq" },
{ path: "/", icon: Home, labelKey: "home" },
- { path: "/effects", icon: Activity, labelKey: "effects" },
{ path: "/ai", icon: Bot, labelKey: "myAi" },
];
@@ -66,7 +58,7 @@ export default function BottomNav() {
paddingBottom: "env(safe-area-inset-bottom, 8px)",
}}
>
-
+
{NAV_ITEMS.map((item) => {
const isActive =
item.path === "/ai"
diff --git a/client/src/config/firmwareFeatures.ts b/client/src/config/firmwareFeatures.ts
index 91f9925..264957e 100644
--- a/client/src/config/firmwareFeatures.ts
+++ b/client/src/config/firmwareFeatures.ts
@@ -5,8 +5,8 @@
* Adjust thresholds here instead of hardcoding in page components.
*/
export const FIRMWARE_FEATURE_MIN_VERSION = {
- /** Boot sound: indices 7–10 (-35…-50 dB); legacy firmware caps at index 6. */
- bootSoundExtendedSteps: 26,
+ /** BH9 与 BD9 一致,默认提供开机音量索引 7–10(-35…-50 dB),不按固件版本隐藏。 */
+ bootSoundExtendedSteps: 0,
/** Subwoofer LPF/HPF full-range toggles on the Effects page. */
subwooferFullRange: 2001,
/** PEQ preset rename (peqRename) and reorder (peqSoft) in manage dialog. */
diff --git a/client/src/contexts/DeviceContext.tsx b/client/src/contexts/DeviceContext.tsx
index 527f9cf..52a572f 100644
--- a/client/src/contexts/DeviceContext.tsx
+++ b/client/src/contexts/DeviceContext.tsx
@@ -1,6 +1,7 @@
import React, { createContext, useCallback, useContext, useEffect, useRef, useState } from "react";
import {
DeviceState,
+ getHomeVolumeMax,
LuxsinAPI,
MOCK_DEVICE_STATE,
MOCK_PEQ_STATE,
@@ -211,10 +212,15 @@ export function DeviceProvider({ children }: { children: React.ReactNode }) {
}, [api, isDemoMode, applyPeqFiltersToState]);
// Optimistic setters
+ const maxVolumeRef = useRef(getHomeVolumeMax(deviceState));
+ maxVolumeRef.current = getHomeVolumeMax(deviceState);
const setVolume = useCallback((v: number) => {
- setDeviceState(prev => prev ? { ...prev, volume: v } : prev);
+ if (!Number.isFinite(v)) return;
+ // 拖动监听器也读取最新上限,乐观状态与实际下发值保持一致。
+ const volume = Math.max(0, Math.min(maxVolumeRef.current, Math.round(v)));
+ setDeviceState(prev => prev ? { ...prev, volume } : prev);
if (!isDemoMode && api) {
- api.setVolume(v).catch(console.error);
+ api.setVolume(volume).catch(console.error);
}
}, [api, isDemoMode]);
diff --git a/client/src/lib/luxsinApi.ts b/client/src/lib/luxsinApi.ts
index 0d62bd8..800d0be 100644
--- a/client/src/lib/luxsinApi.ts
+++ b/client/src/lib/luxsinApi.ts
@@ -21,6 +21,28 @@ export function volumeToDb(vol: number): number {
return (vol - 200) / 2;
}
+/** 耳机音量档位:缺失或非法值回退 0,其余截断并限制到合法范围。 */
+export function normalizeHpVolumeIndex(value: unknown, maxIndex: 7 | 10): number {
+ const index = Number(value ?? 0);
+ return Number.isFinite(index) ? Math.max(0, Math.min(maxIndex, Math.trunc(index))) : 0;
+}
+
+/** 仅耳机输出(协议索引 2)应用最大音量;每档 5dB 对应 10 个设备音量单位。 */
+export function getHomeVolumeMax(
+ state: Pick | null | undefined,
+): number {
+ if (state?.output !== 2) return 200;
+ return dbToVolume(-5 * normalizeHpVolumeIndex(state.hpMaxVolume, 10));
+}
+
+/** 耳机输出且设置低于 0dB 时返回提示值,其他情况不显示提示。 */
+export function getHeadphoneMaxVolumeDb(
+ state: Pick | null | undefined,
+): number | null {
+ if (state?.output !== 2 || normalizeHpVolumeIndex(state.hpMaxVolume, 10) === 0) return null;
+ return volumeToDb(getHomeVolumeMax(state));
+}
+
export function decodeCustomBase64(encoded: string): string {
let translated = "";
for (let i = 0; i < encoded.length; i++) {
@@ -95,6 +117,10 @@ export interface DeviceState {
dacGain: number;
dacArc: number;
dacImpedance: number;
+ /** 耳机最大音量:0 = 0dB,1 = -5dB … 10 = -50dB;旧固件可能不返回。 */
+ hpMaxVolume?: number;
+ /** 耳机启动音量:0 = 默认,1 = -20dB … 7 = -50dB;旧固件可能不返回。 */
+ hpStartupVolume?: number;
dacVolumeDirect: number;
analogGain: number;
effect_enable: number;
@@ -261,7 +287,7 @@ export interface PeqSoftPayload {
// ============================================================
// Input/Output Labels
// ============================================================
-export const INPUT_LABELS = ["USB", "USB-C", "Coaxial", "Optical", "Bluetooth", "IIS", "RCA"];
+export const INPUT_LABELS = ["XLR", "RCA"];
export const OUTPUT_LABELS = ["XLR", "RCA", "Headset", "XLR/RCA"];
/** Device `input` index for Bluetooth source. */
@@ -582,6 +608,8 @@ export const MOCK_DEVICE_STATE: DeviceState = {
dacGain: 0,
dacArc: 0,
dacImpedance: 0,
+ hpMaxVolume: 0,
+ hpStartupVolume: 0,
dacVolumeDirect: 0,
analogGain: 0,
effect_enable: 0,
diff --git a/client/src/locales/data-de.json b/client/src/locales/data-de.json
index c0a479a..6eae18e 100644
--- a/client/src/locales/data-de.json
+++ b/client/src/locales/data-de.json
@@ -28,6 +28,7 @@
"volumePassthroughBlocked": "Lautstärke-Durchleitung ist aktiv ({mode}). Kopfhörerlautstärke ist fest. Schalten Sie die Durchleitung in den Audioeinstellungen aus.",
"volumePassthroughMode0dB": "0dB",
"volumePassthroughMode12dB": "-12dB",
+ "hpMaxVolumeHint": "Die maximale Kopfhörerlautstärke ist eingestellt. Maximum: {db}dB",
"powerOffToastDemo": "Demomodus: Vom Gerät getrennt.",
"powerOffToastSent": "Abschaltbefehl gesendet.",
"doubleClickHint": "Doppelklick zum Eintreten",
@@ -56,7 +57,7 @@
"pageTitle": "I/O",
"inputSection": "Eingang",
"outputSection": "Ausgang",
- "inputOptions": ["USB-B", "USB-C", "Koaxial", "Optisch", "Bluetooth", "IIS", "RCA", "Lokaler Eingang"],
+ "inputOptions": ["Symmetrisch XLR", "Analog RCA"],
"outputOptions": ["XLR", "RCA", "XLR/RCA", "Kopfhörer"],
"input": {
"coaxial": "KOAXIAL",
@@ -389,6 +390,7 @@
"dac": {
"sectionBalanceSensitivity": "Balance & Empfindlichkeit",
"sectionOutput": "Ausgangsmerkmale",
+ "sectionHpSettings": "Kopfhörer-Einstellungen",
"sectionIisSettings": "IIS-Einstellungen",
"sectionSystemInterface": "System & Schnittstelle",
"balance": "Links-Rechts-Balance",
@@ -435,6 +437,35 @@
]
},
"volumeStep": "Lautstärkestufe",
+ "hpMaxVolume": {
+ "label": "Max. Kopfhörerlautstärke",
+ "options": [
+ { "index": 0, "label": "0dB" },
+ { "index": 1, "label": "-5dB" },
+ { "index": 2, "label": "-10dB" },
+ { "index": 3, "label": "-15dB" },
+ { "index": 4, "label": "-20dB" },
+ { "index": 5, "label": "-25dB" },
+ { "index": 6, "label": "-30dB" },
+ { "index": 7, "label": "-35dB" },
+ { "index": 8, "label": "-40dB" },
+ { "index": 9, "label": "-45dB" },
+ { "index": 10, "label": "-50dB" }
+ ]
+ },
+ "hpStartupVolume": {
+ "label": "Kopfhörer-Startlautstärke",
+ "options": [
+ { "index": 0, "label": "Standard" },
+ { "index": 1, "label": "-20dB" },
+ { "index": 2, "label": "-25dB" },
+ { "index": 3, "label": "-30dB" },
+ { "index": 4, "label": "-35dB" },
+ { "index": 5, "label": "-40dB" },
+ { "index": 6, "label": "-45dB" },
+ { "index": 7, "label": "-50dB" }
+ ]
+ },
"bootVolume": {
"label": "Startlautstärke",
"options": [
diff --git a/client/src/locales/data-en.json b/client/src/locales/data-en.json
index edba42f..548f7e6 100644
--- a/client/src/locales/data-en.json
+++ b/client/src/locales/data-en.json
@@ -28,6 +28,7 @@
"volumePassthroughBlocked": "Volume passthrough is active ({mode}). Headphone volume is fixed. Turn passthrough off in Audio settings.",
"volumePassthroughMode0dB": "0dB",
"volumePassthroughMode12dB": "-12dB",
+ "hpMaxVolumeHint": "Headphone max volume is set. Maximum: {db}dB",
"powerOffToastDemo": "Demo mode: disconnected from the device.",
"powerOffToastSent": "Shutdown command sent.",
"doubleClickHint": "Double-click to enter",
@@ -56,7 +57,7 @@
"pageTitle": "I/O",
"inputSection": "Input",
"outputSection": "Output",
- "inputOptions": ["USB-B", "USB-C", "Coaxial", "Optical", "Bluetooth", "IIS", "RCA", "Local Input"],
+ "inputOptions": ["Balanced XLR", "Analog RCA"],
"outputOptions": ["XLR", "RCA", "XLR/RCA", "Headset"],
"input": {
"coaxial": "COAXIAL",
@@ -389,6 +390,7 @@
"dac": {
"sectionBalanceSensitivity": "Balance & sensitivity",
"sectionOutput": "Output characteristics",
+ "sectionHpSettings": "Headphone settings",
"sectionIisSettings": "IIS settings",
"sectionSystemInterface": "System & interface",
"balance": "Left-right balance",
@@ -435,6 +437,35 @@
]
},
"volumeStep": "Volume step",
+ "hpMaxVolume": {
+ "label": "Max headphone volume",
+ "options": [
+ { "index": 0, "label": "0dB" },
+ { "index": 1, "label": "-5dB" },
+ { "index": 2, "label": "-10dB" },
+ { "index": 3, "label": "-15dB" },
+ { "index": 4, "label": "-20dB" },
+ { "index": 5, "label": "-25dB" },
+ { "index": 6, "label": "-30dB" },
+ { "index": 7, "label": "-35dB" },
+ { "index": 8, "label": "-40dB" },
+ { "index": 9, "label": "-45dB" },
+ { "index": 10, "label": "-50dB" }
+ ]
+ },
+ "hpStartupVolume": {
+ "label": "Headphone startup volume",
+ "options": [
+ { "index": 0, "label": "Default" },
+ { "index": 1, "label": "-20dB" },
+ { "index": 2, "label": "-25dB" },
+ { "index": 3, "label": "-30dB" },
+ { "index": 4, "label": "-35dB" },
+ { "index": 5, "label": "-40dB" },
+ { "index": 6, "label": "-45dB" },
+ { "index": 7, "label": "-50dB" }
+ ]
+ },
"bootVolume": {
"label": "Boot volume",
"options": [
diff --git a/client/src/locales/data-es.json b/client/src/locales/data-es.json
index 7fd1a53..2430cee 100644
--- a/client/src/locales/data-es.json
+++ b/client/src/locales/data-es.json
@@ -28,6 +28,7 @@
"volumePassthroughBlocked": "El paso de volumen está activo ({mode}). El volumen de los auriculares es fijo. Desactive el paso en la configuración de audio.",
"volumePassthroughMode0dB": "0dB",
"volumePassthroughMode12dB": "-12dB",
+ "hpMaxVolumeHint": "Se ha establecido el volumen máximo de los auriculares. Máximo: {db}dB",
"powerOffToastDemo": "Modo demo: desconectado del dispositivo.",
"powerOffToastSent": "Comando de apagado enviado.",
"doubleClickHint": "Doble clic para entrar",
@@ -56,7 +57,7 @@
"pageTitle": "E/S",
"inputSection": "Entrada",
"outputSection": "Salida",
- "inputOptions": ["USB-B", "USB-C", "Coaxial", "Óptico", "Bluetooth", "IIS", "RCA", "Entrada local"],
+ "inputOptions": ["XLR balanceado", "RCA analógico"],
"outputOptions": ["XLR", "RCA", "XLR/RCA", "Auriculares"],
"input": {
"coaxial": "COAXIAL",
@@ -389,6 +390,7 @@
"dac": {
"sectionBalanceSensitivity": "Balance y sensibilidad",
"sectionOutput": "Características de salida",
+ "sectionHpSettings": "Ajustes de auriculares",
"sectionIisSettings": "Configuración IIS",
"sectionSystemInterface": "Sistema e interfaz",
"balance": "Balance izquierda-derecha",
@@ -435,6 +437,35 @@
]
},
"volumeStep": "Paso de volumen",
+ "hpMaxVolume": {
+ "label": "Volumen máx. de auriculares",
+ "options": [
+ { "index": 0, "label": "0dB" },
+ { "index": 1, "label": "-5dB" },
+ { "index": 2, "label": "-10dB" },
+ { "index": 3, "label": "-15dB" },
+ { "index": 4, "label": "-20dB" },
+ { "index": 5, "label": "-25dB" },
+ { "index": 6, "label": "-30dB" },
+ { "index": 7, "label": "-35dB" },
+ { "index": 8, "label": "-40dB" },
+ { "index": 9, "label": "-45dB" },
+ { "index": 10, "label": "-50dB" }
+ ]
+ },
+ "hpStartupVolume": {
+ "label": "Volumen de inicio de auriculares",
+ "options": [
+ { "index": 0, "label": "Predeterminado" },
+ { "index": 1, "label": "-20dB" },
+ { "index": 2, "label": "-25dB" },
+ { "index": 3, "label": "-30dB" },
+ { "index": 4, "label": "-35dB" },
+ { "index": 5, "label": "-40dB" },
+ { "index": 6, "label": "-45dB" },
+ { "index": 7, "label": "-50dB" }
+ ]
+ },
"bootVolume": {
"label": "Volumen de inicio",
"options": [
diff --git a/client/src/locales/data-fr.json b/client/src/locales/data-fr.json
index 5665630..9e86a27 100644
--- a/client/src/locales/data-fr.json
+++ b/client/src/locales/data-fr.json
@@ -28,6 +28,7 @@
"volumePassthroughBlocked": "Le passage de volume est actif ({mode}). Le volume du casque est fixe. Désactivez le passage dans les réglages audio.",
"volumePassthroughMode0dB": "0dB",
"volumePassthroughMode12dB": "-12dB",
+ "hpMaxVolumeHint": "Le volume maximal du casque est réglé. Maximum : {db}dB",
"powerOffToastDemo": "Mode démo : déconnecté de l'appareil.",
"powerOffToastSent": "Commande d'extinction envoyée.",
"doubleClickHint": "Double-clic pour entrer",
@@ -56,7 +57,7 @@
"pageTitle": "E/S",
"inputSection": "Entrée",
"outputSection": "Sortie",
- "inputOptions": ["USB-B", "USB-C", "Coaxial", "Optique", "Bluetooth", "IIS", "RCA", "Entrée locale"],
+ "inputOptions": ["XLR symétrique", "RCA analogique"],
"outputOptions": ["XLR", "RCA", "XLR/RCA", "Casque"],
"input": {
"coaxial": "COAXIAL",
@@ -389,6 +390,7 @@
"dac": {
"sectionBalanceSensitivity": "Balance et sensibilité",
"sectionOutput": "Caractéristiques de sortie",
+ "sectionHpSettings": "Réglages du casque",
"sectionIisSettings": "Paramètres IIS",
"sectionSystemInterface": "Système et interface",
"balance": "Balance gauche-droite",
@@ -435,6 +437,35 @@
]
},
"volumeStep": "Pas de volume",
+ "hpMaxVolume": {
+ "label": "Volume max. du casque",
+ "options": [
+ { "index": 0, "label": "0dB" },
+ { "index": 1, "label": "-5dB" },
+ { "index": 2, "label": "-10dB" },
+ { "index": 3, "label": "-15dB" },
+ { "index": 4, "label": "-20dB" },
+ { "index": 5, "label": "-25dB" },
+ { "index": 6, "label": "-30dB" },
+ { "index": 7, "label": "-35dB" },
+ { "index": 8, "label": "-40dB" },
+ { "index": 9, "label": "-45dB" },
+ { "index": 10, "label": "-50dB" }
+ ]
+ },
+ "hpStartupVolume": {
+ "label": "Volume de démarrage du casque",
+ "options": [
+ { "index": 0, "label": "Par défaut" },
+ { "index": 1, "label": "-20dB" },
+ { "index": 2, "label": "-25dB" },
+ { "index": 3, "label": "-30dB" },
+ { "index": 4, "label": "-35dB" },
+ { "index": 5, "label": "-40dB" },
+ { "index": 6, "label": "-45dB" },
+ { "index": 7, "label": "-50dB" }
+ ]
+ },
"bootVolume": {
"label": "Volume de démarrage",
"options": [
diff --git a/client/src/locales/data-zh-HK.json b/client/src/locales/data-zh-HK.json
index cb0a393..0073e81 100644
--- a/client/src/locales/data-zh-HK.json
+++ b/client/src/locales/data-zh-HK.json
@@ -28,6 +28,7 @@
"volumePassthroughBlocked": "目前為音量直通模式({mode}),無法調節耳機音量。請在音訊設定中關閉直通或改為「關閉」。",
"volumePassthroughMode0dB": "0dB",
"volumePassthroughMode12dB": "-12dB",
+ "hpMaxVolumeHint": "已設定耳機最大音量,最大音量為:{db}dB",
"powerOffToastDemo": "演示模式:已中斷與裝置的連線",
"powerOffToastSent": "已傳送關機指令",
"doubleClickHint": "按兩下進入",
@@ -56,7 +57,7 @@
"pageTitle": "輸入/輸出",
"inputSection": "輸入",
"outputSection": "輸出",
- "inputOptions": ["USB-B", "USB-C", "同軸", "光纖", "藍牙", "IIS", "類比RCA", "本地輸入"],
+ "inputOptions": ["平衡 XLR", "類比 RCA"],
"outputOptions": ["XLR", "RCA", "XLR/RCA", "耳機"],
"input": { "coaxial": "同軸", "optical": "光纖", "bluetooth": "藍牙", "rca": "類比RCA" },
"output": { "headset": "耳機" }
@@ -383,6 +384,7 @@
"dac": {
"sectionBalanceSensitivity": "平衡與靈敏度",
"sectionOutput": "輸出特性",
+ "sectionHpSettings": "耳機設定",
"sectionIisSettings": "IIS設定",
"sectionSystemInterface": "系統與介面",
"balance": "左右平衡",
@@ -429,6 +431,35 @@
]
},
"volumeStep": "音量級距",
+ "hpMaxVolume": {
+ "label": "耳機最大音量",
+ "options": [
+ { "index": 0, "label": "0dB" },
+ { "index": 1, "label": "-5dB" },
+ { "index": 2, "label": "-10dB" },
+ { "index": 3, "label": "-15dB" },
+ { "index": 4, "label": "-20dB" },
+ { "index": 5, "label": "-25dB" },
+ { "index": 6, "label": "-30dB" },
+ { "index": 7, "label": "-35dB" },
+ { "index": 8, "label": "-40dB" },
+ { "index": 9, "label": "-45dB" },
+ { "index": 10, "label": "-50dB" }
+ ]
+ },
+ "hpStartupVolume": {
+ "label": "耳機啟動音量",
+ "options": [
+ { "index": 0, "label": "預設" },
+ { "index": 1, "label": "-20dB" },
+ { "index": 2, "label": "-25dB" },
+ { "index": 3, "label": "-30dB" },
+ { "index": 4, "label": "-35dB" },
+ { "index": 5, "label": "-40dB" },
+ { "index": 6, "label": "-45dB" },
+ { "index": 7, "label": "-50dB" }
+ ]
+ },
"bootVolume": {
"label": "開機音量",
"options": [
diff --git a/client/src/locales/data-zh.json b/client/src/locales/data-zh.json
index a63a1d4..4c4602e 100644
--- a/client/src/locales/data-zh.json
+++ b/client/src/locales/data-zh.json
@@ -28,6 +28,7 @@
"volumePassthroughBlocked": "当前为音量直通模式({mode}),无法调节耳机音量。请在音频设置中关闭直通或改为「关闭」。",
"volumePassthroughMode0dB": "0dB",
"volumePassthroughMode12dB": "-12dB",
+ "hpMaxVolumeHint": "已设置耳机最大音量,最大音量为:{db}dB",
"powerOffToastDemo": "演示模式:已断开与设备的连接",
"powerOffToastSent": "已发送关机指令",
"doubleClickHint": "双击进入",
@@ -56,7 +57,7 @@
"pageTitle": "输入输出",
"inputSection": "输入",
"outputSection": "输出",
- "inputOptions": ["USB-B", "USB-C", "同轴", "光纤", "蓝牙", "IIS", "模拟RCA", "本地输入"],
+ "inputOptions": ["平衡 XLR", "模拟 RCA"],
"outputOptions": ["XLR", "RCA", "XLR/RCA", "耳机"],
"input": { "coaxial": "同轴", "optical": "光纤", "bluetooth": "蓝牙", "rca": "模拟RCA" },
"output": { "headset": "耳机" }
@@ -383,6 +384,7 @@
"dac": {
"sectionBalanceSensitivity": "平衡与灵敏度",
"sectionOutput": "输出特性",
+ "sectionHpSettings": "耳机设定",
"sectionIisSettings": "IIS设置",
"sectionSystemInterface": "系统与接口",
"balance": "左右平衡",
@@ -429,6 +431,35 @@
]
},
"volumeStep": "音量幅度",
+ "hpMaxVolume": {
+ "label": "耳机最大音量",
+ "options": [
+ { "index": 0, "label": "0dB" },
+ { "index": 1, "label": "-5dB" },
+ { "index": 2, "label": "-10dB" },
+ { "index": 3, "label": "-15dB" },
+ { "index": 4, "label": "-20dB" },
+ { "index": 5, "label": "-25dB" },
+ { "index": 6, "label": "-30dB" },
+ { "index": 7, "label": "-35dB" },
+ { "index": 8, "label": "-40dB" },
+ { "index": 9, "label": "-45dB" },
+ { "index": 10, "label": "-50dB" }
+ ]
+ },
+ "hpStartupVolume": {
+ "label": "耳机启动音量",
+ "options": [
+ { "index": 0, "label": "默认" },
+ { "index": 1, "label": "-20dB" },
+ { "index": 2, "label": "-25dB" },
+ { "index": 3, "label": "-30dB" },
+ { "index": 4, "label": "-35dB" },
+ { "index": 5, "label": "-40dB" },
+ { "index": 6, "label": "-45dB" },
+ { "index": 7, "label": "-50dB" }
+ ]
+ },
"bootVolume": {
"label": "开机音量",
"options": [
diff --git a/client/src/pages/AudioPage.tsx b/client/src/pages/AudioPage.tsx
index a67bfbc..e78e451 100644
--- a/client/src/pages/AudioPage.tsx
+++ b/client/src/pages/AudioPage.tsx
@@ -2,10 +2,10 @@
AUDIO PAGE — Audio Settings
Design: Reference luxsin_x8_音频设置.png
Sections:
- - 平衡与灵敏度: 左右平衡, VU灵敏度, 模拟输入增益 sliders
- - 输出特性: 滤波特性, 耳机增益, 音量幅度
- - IIS设置: IIS静音电平, IIS模式
- - 系统与接口: 开机音量, XLR极性
+ - 平衡与灵敏度: 左右平衡, VU灵敏度 sliders
+ - 输出特性: 前级输出音量直通, 音量幅度
+ - 耳机设定: 耳机增益, 自动检测耳机阻抗, 耳机最大音量, 耳机启动音量
+ - 系统与接口: 开机音量
All list rows → navigate to /select page
============================================================ */
import { useDevice } from "@/contexts/DeviceContext";
@@ -17,6 +17,7 @@ import { navigateToSelect } from "./SelectPage";
import {
getBootSoundMaxIndex,
normalizeBootSound,
+ normalizeHpVolumeIndex,
parseFirmwareVersion,
readBootSoundFromState,
} from "@/lib/luxsinApi";
@@ -111,22 +112,19 @@ type LocaleDac = {
dac?: {
sectionBalanceSensitivity?: string;
sectionOutput?: string;
- sectionIisSettings?: string;
+ sectionHpSettings?: string;
sectionSystemInterface?: string;
balance?: string;
sensitivity?: string;
- analogInputGain?: string;
autoImpedanceDetection?: string;
filters?: { label?: string; options?: Array<{ index: number; label: string }> };
dacGain?: { label?: string; options?: Array<{ index: number; label: string }> };
+ hpMaxVolume?: { label?: string; options?: Array<{ index: number; label: string }> };
+ hpStartupVolume?: { label?: string; options?: Array<{ index: number; label: string }> };
dacVolumeDirect?: { label?: string; options?: Array<{ index: number; label: string }> };
dacArc?: { label?: string; options?: Array<{ index: number; label: string }> };
volumeStep?: string;
bootVolume?: string | { label?: string; options?: Array<{ index: number; label: string }> };
- xlr?: { label?: string; options?: Array<{ index: number; label: string }> };
- mutePolar?: { label?: string; options?: Array<{ index: number; label: string }> };
- IISMode?: { label?: string; options?: Array<{ index: number; label: string }> };
- uacVer?: { label?: string; options?: Array<{ index: number; label: string }> };
};
home?: { audioSet?: string };
};
@@ -191,22 +189,15 @@ export default function AudioPage() {
const balanceVal = ds?.balance !== undefined ? ds.balance / 10 : 0;
// vuSensor 从接口获取的是放大 2 倍的值,需要除以 2 显示(例如:20 → +10dB)
const vuSensVal = vuSensor !== undefined ? vuSensor / 2 : 0;
- // analogGain 从接口获取的是放大 2 倍的值,需要除以 2 显示(例如:-6 → -3dB)
- const analogGainVal = ds?.analogGain !== undefined ? ds.analogGain / 2 : 0;
const bootSoundFromApi = readBootSoundFromState(ds);
const [localBootSound, setLocalBootSound] = useState(bootSoundFromApi);
const [localBalance, setLocalBalance] = useState(balanceVal);
const [localVuSens, setLocalVuSens] = useState(0);
- const [localAnalogGain, setLocalAnalogGain] = useState(analogGainVal);
const isBalanceDragging = useRef(false);
const isVuDragging = useRef(false);
- const isAnalogGainDragging = useRef(false);
useEffect(() => { if (!isBalanceDragging.current) setLocalBalance(balanceVal); }, [balanceVal]);
useEffect(() => { if (!isVuDragging.current) setLocalVuSens(vuSensVal); }, [vuSensVal]);
- useEffect(() => {
- if (!isAnalogGainDragging.current) setLocalAnalogGain(analogGainVal);
- }, [analogGainVal]);
useEffect(() => {
setLocalBootSound(readBootSoundFromState(ds));
}, [ds?.bootSound]);
@@ -225,14 +216,12 @@ export default function AudioPage() {
const gainIdx = ds?.dacGain ?? 0;
const autoImpedanceOn = (ds?.dacImpedance ?? 0) === 1;
+ const hpMaxVolumeIdx = normalizeHpVolumeIndex(ds?.hpMaxVolume, 10);
+ const hpStartupVolumeIdx = normalizeHpVolumeIndex(ds?.hpStartupVolume, 7);
const dacVolumeDirectIdx = ds?.dacVolumeDirect ?? 0;
const dacArcIdx = ds?.dacArc ?? 0;
const stepIdx = ds?.soundStep ?? 1;
const filterIdx = ds?.pcm ?? 0;
- const xlrIdx = ds?.xlr ?? 0;
- const mutePolarIdx = (ds as ({ hdmimutepolar?: number } | null))?.hdmimutepolar ?? 0;
- const iisModeIdx = (ds as ({ hdmiType?: number } | null))?.hdmiType ?? 0;
- const uacVerIdx = (ds as ({ uac_ver?: number } | null))?.uac_ver ?? 0;
const bootSoundVal = normalizeBootSound(localBootSound);
const firmwareVersion = parseFirmwareVersion(ds?.version);
const bootSoundMaxIdx = getBootSoundMaxIndex(firmwareVersion);
@@ -243,10 +232,12 @@ export default function AudioPage() {
const GAIN_OPTIONS = optionLabels(dacText.dacGain?.options, ["低", "中", "高"]);
const DAC_VOLUME_DIRECT_OPTIONS = optionLabels(dacText.dacVolumeDirect?.options, ["关闭", "0dB", "-12dB"]);
const DAC_ARC_OPTIONS = optionLabels(dacText.dacArc?.options, ["ARC", "EARC"]);
- const XLR_OPTIONS = optionLabels(dacText.xlr?.options, ["正常", "反转"]);
- const MUTE_POLAR_OPTIONS = optionLabels(dacText.mutePolar?.options, ["低电平", "高电平"]);
- const IIS_MODE_OPTIONS = optionLabels(dacText.IISMode?.options, ["模式1", "模式2", "模式3", "模式4", "模式5", "模式6", "模式7", "模式8"]);
- const UAC_VER_OPTIONS = optionLabels(dacText.uacVer?.options, ["UAC 2.0", "UAC 1.0"]);
+ const HP_MAX_VOLUME_OPTIONS = optionLabels(dacText.hpMaxVolume?.options, [
+ "0dB", "-5dB", "-10dB", "-15dB", "-20dB", "-25dB", "-30dB", "-35dB", "-40dB", "-45dB", "-50dB",
+ ]);
+ const HP_STARTUP_VOLUME_OPTIONS = optionLabels(dacText.hpStartupVolume?.options, [
+ "默认", "-20dB", "-25dB", "-30dB", "-35dB", "-40dB", "-45dB", "-50dB",
+ ]);
const pageTitle = usePageTitleWithConnection(localeData.home?.audioSet ?? "Audio");
@@ -318,30 +309,6 @@ export default function AudioPage() {
}}
/>
-
-
-
- {dacText.analogInputGain ?? "模拟输入增益"}
-
- {localAnalogGain >= 0 ? `+${localAnalogGain.toFixed(1)}` : localAnalogGain.toFixed(1)} dB
-
-
-
{
- isAnalogGainDragging.current = true;
- setLocalAnalogGain(v);
- }}
- onRelease={(v) => {
- isAnalogGainDragging.current = false;
- setLocalAnalogGain(v);
- updateSetting({ analogGain: Math.round(v * 2) });
- }}
- />
-
{/* ── 输出特性 ── */}
@@ -354,17 +321,6 @@ export default function AudioPage() {
onClick={() => goSelect(dacText.filters?.label ?? "选择滤波特性", FILTER_OPTIONS, filterIdx, "filterCharacteristic")}
/>
)}
-