Skip to content

Commit 5fa3d69

Browse files
committed
get signal levels
1 parent 81195f8 commit 5fa3d69

File tree

5 files changed

+114
-16
lines changed

5 files changed

+114
-16
lines changed

src/app/model/camilla-dsp.model.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
2-
3-
41
export interface CamillaDspConfig {
52
title: string | null;
63
description: string | null;
@@ -64,3 +61,10 @@ export interface Pipeline {
6461
bypassed: boolean | null;
6562
}
6663

64+
export interface SignalLevels {
65+
playback_rms: number[];
66+
playback_peak: number[];
67+
capture_rms: number[];
68+
capture_peak: number[];
69+
}
70+

src/app/pages/camilla-dsp/camilla-dsp.page.html

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<ion-header [translucent]="true">
22
<ion-toolbar>
3+
<ion-buttons slot="start">
4+
<ion-back-button defaultHref="menu"></ion-back-button>
5+
</ion-buttons>
36
<ion-title>camilla-dsp</ion-title>
47
</ion-toolbar>
58
</ion-header>
@@ -14,15 +17,43 @@
1417
<div class="p-4">
1518
<h1 class="text-2xl font-bold mb-4">CamillaDSP Control</h1>
1619
<p class="mb-2">Connection Status: <strong>{{ connectionStatus }}</strong></p>
17-
<button (click)="connect()" class="bg-blue-500 text-white p-2 rounded mr-2">Connect</button>
18-
<button (click)="disconnect()" class="bg-red-500 text-white p-2 rounded mr-2">Disconnect</button>
19-
<button (click)="getState()" class="bg-green-500 text-white p-2 rounded">Get State</button>
20-
<button (click)="getConfigJson()" class="bg-purple-500 text-white p-2 rounded ml-2">Get Config JSON</button>
21-
<button (click)="getConfigYaml()" class="bg-yellow-500 text-white p-2 rounded ml-2">Get Config YAML</button>
20+
<ion-button (click)="connect()" >Connect</ion-button>
21+
<ion-button (click)="disconnect()">Disconnect</ion-button>
22+
<ion-button (click)="getState()" >Get State</ion-button>
23+
<ion-button (click)="getConfigJson()">Get Config JSON</ion-button>
24+
<ion-button (click)="getConfigYaml()" >Get Config YAML</ion-button>
25+
<ion-button (click)="getUpdateInterval()" >Get Update Interval</ion-button>
26+
<ion-button (click)="getCaptureSignalLevels()" >Get Capture Signal Levels</ion-button>
27+
<ion-button (click)="setUpdateInterval(100)" >Set update Interval</ion-button>
2228

2329
<pre class="bg-gray-100 p-4 rounded mt-4 overflow-auto">{{ lastMessage | json }}</pre>
2430
<pre class="bg-gray-100 p-4 rounded mt-4 overflow-auto">{{ parsedConfig | json }}</pre>
2531
</div>
32+
<div *ngIf="levels" class="ion-margin">
33+
<h2 class="text-xl font-bold mb-2">Signal Levels</h2>
34+
<div *ngIf="levels" class="ion-margin">
35+
<h2>Capture (Snapcast Signal)</h2>
36+
<p>Capture RMS 0{{ levels.capture_rms[0] }} dB</p>
37+
<div class="bar" [style.width]="levels.capture_rms[0] + 600+ 'px'"></div>
38+
<p>Capture RMS 1{{ levels.capture_rms[1] }} dB</p>
39+
<div class="bar" [style.width]="levels.capture_rms[1] + 600+ 'px'"></div>
40+
<p>Capture Peak 0{{ levels.capture_peak[0] }} dB</p>
41+
<div class="bar" [style.width]="levels.capture_peak[0] + 600+ 'px'"></div>
42+
<p>Capture Peak 1 {{ levels.capture_peak[1] }} dB</p>
43+
<div class="bar" [style.width]="levels.capture_peak[1] + 600+ 'px'"></div>
44+
45+
<h2>Playback</h2>
46+
47+
<p>Playback RMS 0{{ levels.playback_rms[0] }} dB</p>
48+
<div class="bar" [style.width]="levels.playback_rms[0] + 600+ 'px'"></div>
49+
<p>Playback RMS 1{{ levels.playback_rms[1] }} dB</p>
50+
<div class="bar" [style.width]="levels.playback_rms[1] + 600+ 'px'"></div>
51+
<p>Playback Peak 0{{ levels.playback_peak[0] }} dB</p>
52+
<div class="bar" [style.width]="levels.playback_peak[0] + 600+ 'px'"></div>
53+
<p>Playback Peak 1 {{ levels.playback_peak[1] }} dB</p>
54+
<div class="bar" [style.width]="levels.playback_peak[1] + 600+ 'px'"></div>
55+
</div>
56+
</div>
2657
<div *ngIf="parsedConfig" class="ion-margin">
2758
<h2 class="text-xl font-bold mb-2">Parsed Configuration</h2>
2859
<div *ngFor="let filter of parsedConfig.filters | keyvalue" >
@@ -32,13 +63,17 @@ <h2 class="text-xl font-bold mb-2">Parsed Configuration</h2>
3263
</ion-item>
3364
<ion-item>
3465
Gain: {{ filter.value.parameters.gain }}
66+
<ion-range min="-24" max="24" step="0.1" [(ngModel)]="filter.value.parameters.gain" (ionChange)="updateFilterParameter(filter.key, 'gain', filter.value.parameters.gain)"></ion-range>
3567
</ion-item>
3668
<ion-item>
3769
Frequency: {{ filter.value.parameters.freq }}
3870
</ion-item>
39-
<ion-item *ngFor="let param of filter.value.parameters | keyvalue">
71+
<ion-item>
72+
Q: {{ filter.value.parameters.q }}
73+
</ion-item>
74+
<!-- <ion-item *ngFor="let param of filter.value.parameters | keyvalue">
4075
{{ param.key }}: {{ param.value }}
41-
<!-- <ion-range min="0" max="1" step="0.01" [(ngModel)]="param.value" (ionChange)="updateFilterParameter(filter.key, param.key, param.value)"></ion-range> -->
76+
<ion-range min="0" max="1" step="0.01" [(ngModel)]="param.value" (ionChange)="updateFilterParameter(filter.key, param.key, param.value)"></ion-range>
4277
<ion-input type="number" [(ngModel)]="param.value" (ionChange)="updateFilterParameter(filter.key, param.key, param.value)"></ion-input>
43-
</ion-item>
78+
</ion-item> -->
4479
</div>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.bar {
2+
height: 20px;
3+
background-color: var(--ion-color-primary);
4+
margin: 2px 0;
5+
// transition: width 0.01s;
6+
width: 20px;
7+
}

src/app/pages/camilla-dsp/camilla-dsp.page.ts

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Component, OnDestroy, OnInit } from '@angular/core';
2+
import { set } from 'lodash-es';
23
import { Subscription } from 'rxjs';
3-
import { CamillaDspConfig } from 'src/app/model/camilla-dsp.model';
4+
import { CamillaDspConfig, SignalLevels } from 'src/app/model/camilla-dsp.model';
45
import { CamillaDspService, ConnectionStatus } from 'src/app/services/camilla-dsp.service';
56

67
@Component({
@@ -18,8 +19,11 @@ export class CamillaDspPage implements OnInit, OnDestroy {
1819
parsedConfig: CamillaDspConfig | null = null;
1920
// Your CamillaDSP URL
2021
private readonly CAMILLA_URL = 'ws://beatnik-client-amp.local:1234';
22+
levels: SignalLevels | null = null;
2123

22-
constructor(private camillaService: CamillaDspService) {}
24+
private levelSubscription: Subscription | undefined;
25+
26+
constructor(private camillaService: CamillaDspService) { }
2327

2428
ngOnInit() {
2529
// Subscribe to connection status changes
@@ -45,9 +49,18 @@ export class CamillaDspPage implements OnInit, OnDestroy {
4549
} catch (error) {
4650
console.error('Error parsing Config JSON:', error);
4751
}
52+
} else if (message.GetSignalLevels) {
53+
this.levels = message.GetSignalLevels.value;
54+
console.log('Signal Levels received:', this.levels);
4855
}
4956
})
5057
);
58+
59+
this.levelSubscription = this.camillaService.signalLevels$.subscribe(message => {
60+
console.log('Received message in component:', message);
61+
this.levels = message.SignalLevels.value;
62+
console.log('Signal Levels received:', this.levels);
63+
});
5164
}
5265

5366
connect() {
@@ -95,7 +108,23 @@ export class CamillaDspPage implements OnInit, OnDestroy {
95108
// send the full configJson back to CamillaDSP
96109
this.camillaService.sendCommand('SetConfigJson', JSON.stringify(this.parsedConfig));
97110

98-
}
111+
}
112+
113+
getUpdateInterval() {
114+
this.camillaService.sendCommand('GetUpdateInterval');
115+
}
116+
117+
getCaptureSignalLevels() {
118+
const interval = 50; // e.g., 100 ms
119+
setInterval(() => {
120+
this.camillaService.sendCommand('GetSignalLevels');
121+
}, interval);
122+
}
123+
124+
setUpdateInterval(interval: number) {
125+
this.camillaService.startLevelUpdates(interval);
126+
}
127+
99128
ngOnDestroy() {
100129
// Clean up subscriptions to prevent memory leaks
101130
this.subscriptions.unsubscribe();

src/app/services/camilla-dsp.service.ts

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Injectable } from '@angular/core';
22
import { webSocket, WebSocketSubject } from 'rxjs/webSocket';
33
import { Subject, Observable, BehaviorSubject, timer, of } from 'rxjs';
4-
import { retryWhen, switchMap, tap, delayWhen } from 'rxjs/operators';
4+
import { retryWhen, switchMap, tap, delayWhen, filter } from 'rxjs/operators';
55

66
// Defines the possible connection states
77
export type ConnectionStatus = 'Connected' | 'Connecting' | 'Disconnected' | 'Error';
@@ -24,8 +24,13 @@ export class CamillaDspService {
2424
// Public observables for components to subscribe to
2525
public messages$: Observable<any> = this.messagesSubject.asObservable();
2626
public connectionStatus$: Observable<ConnectionStatus> = this.connectionStatusSubject.asObservable();
27+
public signalLevels$: Observable<any>;
2728

28-
constructor() {}
29+
constructor() {
30+
this.signalLevels$ = this.messages$.pipe(
31+
filter(msg => msg && msg.SignalLevels)
32+
);
33+
}
2934

3035
/**
3136
* Establishes a connection to the CamillaDSP WebSocket server.
@@ -98,11 +103,29 @@ export class CamillaDspService {
98103
this.socket$.next(commandToSend);
99104
}
100105

106+
/**
107+
* Tells CamillaDSP to start sending SignalLevels messages periodically.
108+
* @param intervalMs The update interval in milliseconds.
109+
*/
110+
public startLevelUpdates(intervalMs: number): void {
111+
if (intervalMs > 0) {
112+
this.sendCommand('SetUpdateInterval', intervalMs);
113+
}
114+
}
115+
116+
/**
117+
* Tells CamillaDSP to stop sending SignalLevels messages.
118+
*/
119+
public stopLevelUpdates(): void {
120+
this.sendCommand('SetUpdateInterval', { value: 0 });
121+
}
122+
101123
/**
102124
* Closes the WebSocket connection gracefully.
103125
*/
104126
public disconnect(): void {
105127
if (this.socket$) {
128+
this.stopLevelUpdates();
106129
this.socket$.complete(); // This will trigger the closeObserver
107130
}
108131
}

0 commit comments

Comments
 (0)