fix: property inspector - always show channels/sample rate, show 'default' if unknown

- Removed duplicated/broken code from property parsing
- Always shows Channels and Sample Rate for audio nodes
- Shows 'default' if sample rate not available on node
- Latency shows ms calculation when sample rate known
- Added fallback: clock.rate, api.alsa.rate
This commit is contained in:
joren
2026-03-30 00:40:09 +02:00
parent 4cc6f554af
commit 535ee058f2
2 changed files with 32 additions and 13 deletions

View File

@@ -690,10 +690,12 @@
<tr><td class="pk">Class</td><td>{nd.mode} / {nd.node_type}</td></tr>
<tr><td class="pk">Volume</td><td>{Math.round(nd.volume * 100)}% {nd.mute ? '(muted)' : ''}</td></tr>
<tr><td class="pk">Ports</td><td>{nd.port_ids.length}</td></tr>
{#if nd.sample_rate > 0}<tr><td class="pk">Sample Rate</td><td>{nd.sample_rate} Hz</td></tr>{/if}
{#if nd.channels > 0}<tr><td class="pk">Channels</td><td>{nd.channels}</td></tr>{/if}
{#if nd.node_type === 'audio' || nd.channels > 0}
<tr><td class="pk">Channels</td><td>{nd.channels > 0 ? nd.channels : '-'}</td></tr>
<tr><td class="pk">Sample Rate</td><td>{nd.sample_rate > 0 ? nd.sample_rate + ' Hz' : 'default'}</td></tr>
{#if nd.quantum > 0}<tr><td class="pk">Latency</td><td>{nd.quantum} samples{#if nd.sample_rate > 0} ({(nd.quantum / nd.sample_rate * 1000).toFixed(1)} ms){/if}</td></tr>{/if}
{/if}
{#if nd.format}<tr><td class="pk">Format</td><td>{nd.format}</td></tr>{/if}
{#if nd.quantum > 0}<tr><td class="pk">Latency</td><td>{nd.quantum} samples @ {nd.sample_rate} Hz</td></tr>{/if}
{#if nd.rate > 0}<tr><td class="pk">Period Size</td><td>{nd.rate}</td></tr>{/if}
{#if nd.device_name}<tr><td class="pk">Device</td><td>{nd.device_name}</td></tr>{/if}
{#if nd.device_bus}<tr><td class="pk">Bus</td><td>{nd.device_bus}</td></tr>{/if}

View File

@@ -102,10 +102,22 @@ static void on_node_info(void *data, const struct pw_node_info *info) {
const char *str;
str = spa_dict_lookup(info->props, "default.clock.rate");
if (str) nobj->node.sample_rate = (uint32_t)atoi(str);
if (str && strlen(str) > 0) nobj->node.sample_rate = (uint32_t)atoi(str);
str = spa_dict_lookup(info->props, "default.clock.quantum");
if (str) nobj->node.quantum = (uint32_t)atoi(str);
if (str && strlen(str) > 0) nobj->node.quantum = (uint32_t)atoi(str);
// Also try clock.rate (set on some devices)
if (nobj->node.sample_rate == 0) {
str = spa_dict_lookup(info->props, "clock.rate");
if (str && strlen(str) > 0) nobj->node.sample_rate = (uint32_t)atoi(str);
}
// Also try api.alsa.rate
if (nobj->node.sample_rate == 0) {
str = spa_dict_lookup(info->props, "api.alsa.rate");
if (str && strlen(str) > 0) nobj->node.sample_rate = (uint32_t)atoi(str);
}
str = spa_dict_lookup(info->props, "audio.channels");
if (str) nobj->node.channels = (uint32_t)atoi(str);
@@ -125,26 +137,31 @@ static void on_node_info(void *data, const struct pw_node_info *info) {
str = spa_dict_lookup(info->props, "priority.driver");
if (str) nobj->node.priority = atoi(str);
// Latency info
// Latency: "256/48000" format
str = spa_dict_lookup(info->props, "node.latency");
if (str) {
// Format: "256/48000" -> quantum=256 rate=48000
uint32_t q = 0, r = 0;
if (sscanf(str, "%u/%u", &q, &r) == 2) {
nobj->node.quantum = q;
nobj->node.sample_rate = r;
if (nobj->node.quantum == 0) nobj->node.quantum = q;
if (nobj->node.sample_rate == 0 && r > 0) nobj->node.sample_rate = r;
}
}
// Fallback: read clock rate from device props
// ALSA period size
str = spa_dict_lookup(info->props, "api.alsa.period-size");
if (str) nobj->node.rate = (uint32_t)atoi(str);
// Fallback: clock.rate
if (nobj->node.sample_rate == 0) {
str = spa_dict_lookup(info->props, "clock.rate");
if (str) nobj->node.sample_rate = (uint32_t)atoi(str);
}
// ALSA latency
str = spa_dict_lookup(info->props, "api.alsa.period-size");
if (str) nobj->node.rate = (uint32_t)atoi(str); // reuse rate field for period-size
// Fallback: api.alsa.rate
if (nobj->node.sample_rate == 0) {
str = spa_dict_lookup(info->props, "api.alsa.rate");
if (str) nobj->node.sample_rate = (uint32_t)atoi(str);
}
}
}