unstable
This commit is contained in:
@@ -46,7 +46,6 @@ pub struct DSP408Snapshot {
|
|||||||
pub state: types::DSPState,
|
pub state: types::DSPState,
|
||||||
pub input_meters: types::InputMeters,
|
pub input_meters: types::InputMeters,
|
||||||
pub output_meters: types::OutputMeters,
|
pub output_meters: types::OutputMeters,
|
||||||
pub mode: types::DSPMode,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
@@ -104,7 +103,6 @@ pub async fn get_dsp_snapshot(
|
|||||||
state: device.dsp.state().clone(),
|
state: device.dsp.state().clone(),
|
||||||
input_meters: device.dsp.input_meters().clone(),
|
input_meters: device.dsp.input_meters().clone(),
|
||||||
output_meters: device.dsp.output_meters().clone(),
|
output_meters: device.dsp.output_meters().clone(),
|
||||||
mode: device.dsp.mode(),
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
import { useState, useEffect, useRef } from 'react';
|
import { useState, useEffect, useRef } from 'react';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
import { DSP, AppPage } from './types';
|
import { DSP, AppPage, isConnected } from './types';
|
||||||
import TopBar from './components/Topbar/Topbar';
|
import TopBar from './components/Topbar/Topbar';
|
||||||
import DSPPage from './pages/DspPage/DspPage';
|
import DSPPage from './pages/DspPage/DspPage';
|
||||||
import AddDSPForm from './pages/AddDspPage/AddDspPage';
|
import AddDSPForm from './pages/AddDspPage/AddDspPage';
|
||||||
@@ -17,7 +17,7 @@ function App() {
|
|||||||
const [selected, setSelected] = useState<number | null>(null);
|
const [selected, setSelected] = useState<number | null>(null);
|
||||||
const [page, setPage] = useState<AppPage>('home');
|
const [page, setPage] = useState<AppPage>('home');
|
||||||
const { notifications, notify, removeNotification, hoverNotification } = useNotifications();
|
const { notifications, notify, removeNotification, hoverNotification } = useNotifications();
|
||||||
const connectedDspCount = dsps.filter((dsp) => dsp.status === 'connected').length;
|
const connectedDspCount = dsps.filter((dsp) => isConnected(dsp)).length;
|
||||||
|
|
||||||
const activeDsp = dsps.find((d) => d.id === selected) ?? null;
|
const activeDsp = dsps.find((d) => d.id === selected) ?? null;
|
||||||
const activeInstance = activeDsp ? createDSPInstance(activeDsp, setDsps, notify) : null;
|
const activeInstance = activeDsp ? createDSPInstance(activeDsp, setDsps, notify) : null;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
import { DSP, AppPage } from '../../types';
|
import { DSP, AppPage, isConnected } from '../../types';
|
||||||
import AnimatedLogo from '../../assets/icons/AnimatedLogo';
|
import AnimatedLogo from '../../assets/icons/AnimatedLogo';
|
||||||
import { PlusIcon } from '../../assets/icons/PlusIcon';
|
import { PlusIcon } from '../../assets/icons/PlusIcon';
|
||||||
import { CrownIcon } from '../../assets/icons/CrownIcon';
|
import { CrownIcon } from '../../assets/icons/CrownIcon';
|
||||||
@@ -36,7 +36,7 @@ function Tab({
|
|||||||
onDisconnect: (dsp: DSP) => void;
|
onDisconnect: (dsp: DSP) => void;
|
||||||
actions?: React.ReactNode;
|
actions?: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
const isConnected = dsp.status === 'connected';
|
const isDspConnected = isConnected(dsp);
|
||||||
|
|
||||||
const handleTabKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
|
const handleTabKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
|
||||||
if (e.key === 'Enter' || e.key === ' ') {
|
if (e.key === 'Enter' || e.key === ' ') {
|
||||||
@@ -60,18 +60,26 @@ function Tab({
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="tab-led"
|
className="tab-led"
|
||||||
aria-label={isConnected ? `Disconnect ${dsp.name}` : `Connect ${dsp.name}`}
|
aria-label={isDspConnected ? `Disconnect ${dsp.name}` : `Connect ${dsp.name}`}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
if (isConnected) {
|
if (isDspConnected) {
|
||||||
onDisconnect(dsp);
|
onDisconnect(dsp);
|
||||||
} else {
|
} else {
|
||||||
onConnect(dsp);
|
onConnect(dsp);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Led status={dsp.status} />
|
<Led
|
||||||
|
status={
|
||||||
|
dsp.isConnecting
|
||||||
|
? 'connecting'
|
||||||
|
: isConnected(dsp)
|
||||||
|
? 'connected'
|
||||||
|
: 'disconnected'
|
||||||
|
}
|
||||||
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<span className="tab-name" title={dsp.name}>
|
<span className="tab-name" title={dsp.name}>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { DSP } from '../../../../types';
|
import { DSP, isConnected } from '../../../../types';
|
||||||
import Button from '../../../../components/Button/Button';
|
import Button from '../../../../components/Button/Button';
|
||||||
import Card from '../../../../components/Card/Card';
|
import Card from '../../../../components/Card/Card';
|
||||||
import Led from '../../../../components/Led/Led';
|
import Led from '../../../../components/Led/Led';
|
||||||
@@ -15,12 +15,19 @@ function ConnectionPanel({
|
|||||||
onDisconnect: () => void;
|
onDisconnect: () => void;
|
||||||
}) {
|
}) {
|
||||||
const statusLabel =
|
const statusLabel =
|
||||||
dsp.status === 'connected'
|
isConnected(dsp)
|
||||||
? 'Connected'
|
? 'Connected'
|
||||||
: dsp.status === 'connecting'
|
: dsp.isConnecting
|
||||||
? 'Connecting…'
|
? 'Connecting…'
|
||||||
: 'Disconnected';
|
: 'Disconnected';
|
||||||
|
|
||||||
|
console.log('ConnectionPanel render:', {
|
||||||
|
id: dsp.id,
|
||||||
|
connection: dsp.type === 'DSP408' ? dsp.state.connection : undefined,
|
||||||
|
isConnected: isConnected(dsp),
|
||||||
|
isConnecting: dsp.isConnecting,
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="connection-section">
|
<div className="connection-section">
|
||||||
<Card className="connection-panel">
|
<Card className="connection-panel">
|
||||||
@@ -35,10 +42,10 @@ function ConnectionPanel({
|
|||||||
|
|
||||||
<div className="connection-panel__status">
|
<div className="connection-panel__status">
|
||||||
<span className="connection-panel__led">
|
<span className="connection-panel__led">
|
||||||
<Led status={dsp.status} />
|
{/* <Led status={dsp.status} /> */}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span className={`status-label status-label--${dsp.status}`}>{statusLabel}</span>
|
{/* <span className={`status-label status-label--${dsp.status}`}>{statusLabel}</span> */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -64,13 +71,13 @@ function ConnectionPanel({
|
|||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<div className="connection-panel__actions">
|
<div className="connection-panel__actions">
|
||||||
{dsp.status === 'connected' ? (
|
{isConnected(dsp) ? (
|
||||||
<Button variant="outline" onClick={onDisconnect}>
|
<Button variant="outline" onClick={onDisconnect}>
|
||||||
Disconnect
|
Disconnect
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<Button variant="primary" onClick={onConnect} disabled={dsp.status === 'connecting'}>
|
<Button variant="primary" onClick={onConnect} disabled={dsp.isConnecting}>
|
||||||
{dsp.status === 'connecting' ? 'Connecting…' : 'Connect'}
|
{dsp.isConnecting ? 'Connecting…' : 'Connect'}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
PEQBand,
|
PEQBand,
|
||||||
InputSource,
|
InputSource,
|
||||||
DSP408Snapshot,
|
DSP408Snapshot,
|
||||||
|
DSPMode,
|
||||||
} from './types';
|
} from './types';
|
||||||
import { SetDsps, NotifyFn, updateDSP, setPollingPaused } from '../../dsp/dspShared';
|
import { SetDsps, NotifyFn, updateDSP, setPollingPaused } from '../../dsp/dspShared';
|
||||||
import { registerPollStopper } from '../../dsp/pollRegistry';
|
import { registerPollStopper } from '../../dsp/pollRegistry';
|
||||||
@@ -117,8 +118,8 @@ export async function create(params: {
|
|||||||
ip: params.ip,
|
ip: params.ip,
|
||||||
port: params.port,
|
port: params.port,
|
||||||
deviceId: params.deviceId,
|
deviceId: params.deviceId,
|
||||||
mode: snapshot.mode,
|
mode: params.demo ? DSPMode.Demo: DSPMode.Normal,
|
||||||
status: 'disconnected',
|
isConnecting: false,
|
||||||
pollingPaused: true,
|
pollingPaused: true,
|
||||||
state: snapshot.state,
|
state: snapshot.state,
|
||||||
input_meters: snapshot.input_meters,
|
input_meters: snapshot.input_meters,
|
||||||
@@ -130,6 +131,7 @@ export function forDSP408(dsp: DSP408, setDsps: SetDsps, notify: NotifyFn) {
|
|||||||
async function updateDSPState(): Promise<DSP408['state']> {
|
async function updateDSPState(): Promise<DSP408['state']> {
|
||||||
try {
|
try {
|
||||||
const state = await invoke<DSP408['state']>('get_dsp_state', { id: dsp.id });
|
const state = await invoke<DSP408['state']>('get_dsp_state', { id: dsp.id });
|
||||||
|
|
||||||
updateDSP(setDsps, dsp.id, (d) => ({ ...d, state }) as DSP408);
|
updateDSP(setDsps, dsp.id, (d) => ({ ...d, state }) as DSP408);
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
@@ -143,11 +145,11 @@ export function forDSP408(dsp: DSP408, setDsps: SetDsps, notify: NotifyFn) {
|
|||||||
|
|
||||||
async function abortLocked() {
|
async function abortLocked() {
|
||||||
await invoke('disconnect_dsp408', { id: dsp.id }).catch(() => {});
|
await invoke('disconnect_dsp408', { id: dsp.id }).catch(() => {});
|
||||||
updateDSP(setDsps, dsp.id, (d) => ({ ...d, status: 'disconnected', passwordRequired: true }));
|
updateDSP(setDsps, dsp.id, (d) => ({ ...d, passwordRequired: true }));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function connectInternal(password?: string) {
|
async function connectInternal(password?: string) {
|
||||||
updateDSP(setDsps, dsp.id, (d) => ({ ...d, status: 'connecting', passwordRequired: false }));
|
updateDSP(setDsps, dsp.id, (d) => ({ ...d, isConnecting: true, passwordRequired: false }));
|
||||||
try {
|
try {
|
||||||
await invoke('connect_dsp408', { id: dsp.id });
|
await invoke('connect_dsp408', { id: dsp.id });
|
||||||
|
|
||||||
@@ -159,13 +161,10 @@ export function forDSP408(dsp: DSP408, setDsps: SetDsps, notify: NotifyFn) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
let r = await invoke('unlock_device', { id: dsp.id, password });
|
||||||
await invoke('unlock_device', { id: dsp.id, password }); // adjust name/signature
|
|
||||||
} catch {
|
|
||||||
// wrong password
|
|
||||||
}
|
|
||||||
|
|
||||||
state = await updateDSPState();
|
state = await updateDSPState();
|
||||||
|
|
||||||
if (isLocked(state)) {
|
if (isLocked(state)) {
|
||||||
await abortLocked();
|
await abortLocked();
|
||||||
notify('Wrong password', 'error', dsp.name);
|
notify('Wrong password', 'error', dsp.name);
|
||||||
@@ -173,11 +172,11 @@ export function forDSP408(dsp: DSP408, setDsps: SetDsps, notify: NotifyFn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateDSP(setDsps, dsp.id, (d) => ({ ...d, status: 'connected', pollingPaused: false }));
|
updateDSP(setDsps, dsp.id, (d) => ({ ...d, isConnecting: false, pollingPaused: false }));
|
||||||
notify('Connected', 'success', dsp.name);
|
notify('Connected', 'success', dsp.name);
|
||||||
startPolling(dsp, setDsps);
|
startPolling(dsp, setDsps);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
updateDSP(setDsps, dsp.id, (d) => ({ ...d, status: 'disconnected' }));
|
updateDSP(setDsps, dsp.id, (d) => ({ ...d, isConnecting: false }));
|
||||||
notify(`Connection failed: ${String(err)}`, 'error', dsp.name);
|
notify(`Connection failed: ${String(err)}`, 'error', dsp.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -216,7 +215,6 @@ export function forDSP408(dsp: DSP408, setDsps: SetDsps, notify: NotifyFn) {
|
|||||||
|
|
||||||
updateDSP(setDsps, dsp.id, (d) => ({
|
updateDSP(setDsps, dsp.id, (d) => ({
|
||||||
...d,
|
...d,
|
||||||
status: 'disconnected',
|
|
||||||
pollingPaused: true,
|
pollingPaused: true,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@@ -243,15 +243,23 @@ export type DSPState = {
|
|||||||
flags: DeviceFlags;
|
flags: DeviceFlags;
|
||||||
presets: PresetBank;
|
presets: PresetBank;
|
||||||
current_config: DSPConfigState;
|
current_config: DSPConfigState;
|
||||||
|
connection: ConnectionStatus,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type DSPMode = 'demo' | 'disconnected' | 'connected';
|
export enum ConnectionStatus {
|
||||||
|
Connected,
|
||||||
|
Disconnected,
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum DSPMode {
|
||||||
|
Demo,
|
||||||
|
Normal,
|
||||||
|
}
|
||||||
|
|
||||||
export type DSP408Snapshot = {
|
export type DSP408Snapshot = {
|
||||||
state: DSPState;
|
state: DSPState;
|
||||||
input_meters: DSP408InputMeters;
|
input_meters: DSP408InputMeters;
|
||||||
output_meters: DSP408OutputMeters;
|
output_meters: DSP408OutputMeters;
|
||||||
mode: DSPMode;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface Meter {
|
export interface Meter {
|
||||||
|
|||||||
+7
-5
@@ -3,10 +3,9 @@ import {
|
|||||||
DSPMode,
|
DSPMode,
|
||||||
DSP408OutputMeters,
|
DSP408OutputMeters,
|
||||||
DSP408InputMeters,
|
DSP408InputMeters,
|
||||||
|
ConnectionStatus,
|
||||||
} from './features/dsp408/types';
|
} from './features/dsp408/types';
|
||||||
|
|
||||||
export type DSPStatus = 'connected' | 'connecting' | 'disconnected';
|
|
||||||
|
|
||||||
export type NotificationType = 'success' | 'error' | 'warning';
|
export type NotificationType = 'success' | 'error' | 'warning';
|
||||||
export type Notification = {
|
export type Notification = {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -39,12 +38,15 @@ interface DSPBase {
|
|||||||
mode: DSPMode;
|
mode: DSPMode;
|
||||||
|
|
||||||
passwordRequired?: boolean;
|
passwordRequired?: boolean;
|
||||||
|
isConnecting: boolean;
|
||||||
status: DSPStatus;
|
|
||||||
|
|
||||||
pollingPaused: boolean;
|
pollingPaused: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isConnected(dsp: DSP): boolean {
|
||||||
|
return dsp.type === 'DSP408'
|
||||||
|
&& dsp.state.connection === ConnectionStatus.Connected;
|
||||||
|
}
|
||||||
|
|
||||||
export type DSP408 = DSPBase & {
|
export type DSP408 = DSPBase & {
|
||||||
type: 'DSP408';
|
type: 'DSP408';
|
||||||
state: DSP408State;
|
state: DSP408State;
|
||||||
|
|||||||
Reference in New Issue
Block a user