summaryrefslogtreecommitdiff
path: root/src/audio-impl-pw.cpp
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-07-08 10:00:28 -0400
committerJonathan Bradley <jcb@pikum.xyz>2025-07-08 10:00:28 -0400
commit2bf896106c8923e7fae38641a8ad80ddee2f5fe5 (patch)
treee6a396061546b61039c06af8555218b192b7681e /src/audio-impl-pw.cpp
parent34863f5b702c0dbb00d8db5c00efd43d895fcd4c (diff)
pke: audio-pw: link consistently + cleanup
Diffstat (limited to 'src/audio-impl-pw.cpp')
-rw-r--r--src/audio-impl-pw.cpp51
1 files changed, 36 insertions, 15 deletions
diff --git a/src/audio-impl-pw.cpp b/src/audio-impl-pw.cpp
index 628976e..53953ba 100644
--- a/src/audio-impl-pw.cpp
+++ b/src/audio-impl-pw.cpp
@@ -177,6 +177,10 @@ void pke_audio_pw_teardown() {
pw_deinit();
pk_delete<char>(pke_audio_pw.default_sink_name, PKE_AUDIO_PW_NAME_RESERVE_LEN, pke_audio_pw.bkt);
pk_delete<uint8_t>(pke_audio_pw.pod_buffer, pke_audio_mstr.channel_count * PKE_AUDIO_POD_BUFFER_LEN, pke_audio_pw.bkt);
+ pk_arr_reset(&pke_audio_pw.created_objects);
+ pke_audio_pw.created_objects.bkt = nullptr;
+ pk_arr_reset(&pke_audio_pw.pw_objects);
+ pke_audio_pw.pw_objects.bkt = nullptr;
pk_mem_bucket_destroy(pke_audio_pw.bkt);
pke_audio_pw.bkt = CAFE_BABE(pk_membucket);
pke_audio_mstr.mtx_buffer.unlock();
@@ -188,6 +192,7 @@ void pke_audio_pw_remap_outputs() {
uint32_t port_count = {0};
void *created_obj = {0};
if (pke_audio_pw.pw_objects.data == nullptr) return;
+ if (pke_audio_pw.default_sink_name == nullptr || pke_audio_pw.default_sink_name[0] == '\0') return;
pw_properties *props = pw_properties_new(NULL, NULL);
pke_audio_pw_object *objs = (pke_audio_pw_object *)pke_audio_pw.pw_objects.data;
const char *str;
@@ -244,6 +249,10 @@ void pke_audio_pw_remap_outputs() {
// do links
{
for (i = 0; i < pke_audio_mstr.channel_count; ++i) {
+ if (out_ports[i] == 0) {
+ goto remap_done;
+ }
+ fprintf(stdout, "[pke_audio_pw_remap_outputs] Mapping (out:in): %d:%d\n", out_ports[i], in_ports[i]);
pw_properties_clear(props);
pw_properties_setf(props, PW_KEY_LINK_OUTPUT_PORT, "%d", out_ports[i]);
pw_properties_setf(props, PW_KEY_LINK_INPUT_PORT, "%d", in_ports[i % port_count]);
@@ -469,7 +478,7 @@ void on_pipewire_stream_param_changed(void *, uint32_t id, const struct spa_pod
/* call a helper function to parse the format for us. */
spa_format_audio_raw_parse(param, &pke_audio_pw.format.info.raw);
- fprintf(stdout, "\r\ncapturing rate changed:%d channels:%d\n", pke_audio_pw.format.info.raw.rate, pke_audio_pw.format.info.raw.channels);
+ fprintf(stdout, "capturing rate changed:%d channels:%d\n", pke_audio_pw.format.info.raw.rate, pke_audio_pw.format.info.raw.channels);
return;
}
@@ -486,7 +495,7 @@ int metadata_event_property(void *data, uint32_t subject, const char *key, const
}
}
}
- fprintf(stdout, "\r\nPW_METADATA_CB: data: %p, subject: %d, key: '%s', type: '%s', value: '%s'\n", data, subject, key, type, value);
+ fprintf(stdout, "PW_METADATA_CB: data: %p, subject: %d, key: '%s', type: '%s', value: '%s'\n", data, subject, key, type, value);
return 0;
}
@@ -499,12 +508,12 @@ void on_registry_event_global(void *data, uint32_t id, uint32_t permissions, con
// if (props == NULL) return; // why
if (props == NULL) {
- printf("\r\nPW CALLBACK: NULL PROPS: object: id:%u type:%s/%d\n", id, type, version);
+ printf("PW CALLBACK: NULL PROPS: object: id:%u type:%s/%d\n", id, type, version);
return; // why - in what scenario does this happen?
}
if (spa_streq(type, PW_TYPE_INTERFACE_Node)) {
- printf("\r\nPW CALLBACK NODE: object: id:%u type:%s/%d\n", id, type, version);
+ printf("PW CALLBACK NODE: object: id:%u type:%s/%d\n", id, type, version);
obj.type = PKE_AUDIO_PW_OBJECT_TYPE_NODE;
} else if (spa_streq(type, PW_TYPE_INTERFACE_Port)) {
obj.type = PKE_AUDIO_PW_OBJECT_TYPE_PORT;
@@ -522,14 +531,14 @@ void on_registry_event_global(void *data, uint32_t id, uint32_t permissions, con
return;
}
if (res = pk_stn(&obj.data.port.node, str, 0), res != PK_STN_RES_SUCCESS) {
- fprintf(stderr, "\r\nPW_CALLBACK: failed to parse port node from str: '%s', PK_STN_RES: %i\n", str, res);
+ fprintf(stderr, "PW_CALLBACK: failed to parse port node from str: '%s', PK_STN_RES: %i\n", str, res);
return;
}
if ((str = spa_dict_lookup(props, PW_KEY_PORT_ID)) == NULL) {
return;
}
if (res = pk_stn(&obj.data.port.id, str, 0), res != PK_STN_RES_SUCCESS) {
- fprintf(stderr, "\r\nPW_CALLBACK: failed to parse port id from str: '%s', PK_STN_RES: %i\n", str, res);
+ fprintf(stderr, "PW_CALLBACK: failed to parse port id from str: '%s', PK_STN_RES: %i\n", str, res);
return;
}
} else if (spa_streq(type, PW_TYPE_INTERFACE_Link)) {
@@ -538,14 +547,14 @@ void on_registry_event_global(void *data, uint32_t id, uint32_t permissions, con
return;
}
if (res = pk_stn(&obj.data.link.output_port, str, 0), res != PK_STN_RES_SUCCESS) {
- fprintf(stderr, "\r\nPW_CALLBACK: failed to parse link output port from str: '%s', PK_STN_RES: %i\n", str, res);
+ fprintf(stderr, "PW_CALLBACK: failed to parse link output port from str: '%s', PK_STN_RES: %i\n", str, res);
return;
}
if ((str = spa_dict_lookup(props, PW_KEY_LINK_INPUT_PORT)) == NULL) {
return;
}
if (res = pk_stn(&obj.data.link.input_port, str, 0), res != PK_STN_RES_SUCCESS) {
- fprintf(stderr, "\r\nPW_CALLBACK: failed to parse link input port from str: '%s', PK_STN_RES: %i\n", str, res);
+ fprintf(stderr, "PW_CALLBACK: failed to parse link input port from str: '%s', PK_STN_RES: %i\n", str, res);
return;
}
} else if (spa_streq(type, PW_TYPE_INTERFACE_Metadata)) {
@@ -568,33 +577,45 @@ void on_registry_event_global(void *data, uint32_t id, uint32_t permissions, con
#if 0
int i;
for (i = 0; i < props->n_items; ++i) {
- printf("\r\n\t'%s': '%s'", props->items[i].key, props->items[i].value);
+ printf("\t'%s': '%s'", props->items[i].key, props->items[i].value);
}
- printf("\r\n");
+ printf("");
#endif
obj.id = id;
obj.props = pw_properties_new_dict(props);
- printf("\r\nPW CALLBACK: object: id:%u type:%s/%d\n", id, type, version);
+ printf("PW CALLBACK: object: id:%u type:%s/v%d\n", id, type, version);
pk_arr_append_t(&pke_audio_pw.pw_objects, obj);
+ // TODO 2025-07-07 JCB
+ // I don't know if this logic is ever true.
+ // Specifically, on startup we don't have default_sink_id yet.
+ // So the only time this catches is if ports on our default node change during runtime?
+ // I feel like this was the right idea, but maybe the wrong place for it?
+ // The bug I was trying to fix at the time was a race condition where we were
+ // trying to link output ports that didn't exist yet.
+ // The correct answer was to validate the data before making the links.
+ /*
+ if (obj.type == PKE_AUDIO_PW_OBJECT_TYPE_PORT
+ && obj.data.port.node == pke_audio_pw.default_sink_id) {
+ pke_audio_pw.is_needing_output_remapped = true;
+ }
+ */
return;
}
void on_registry_event_global_removal(void *data, uint32_t id) {
(void)data;
uint32_t i;
- // printf("\r\nPW CALLBACK: object remove: id:%u ...", id);
+ // printf("PW CALLBACK: object remove: id:%u ...", id);
if (i = pk_arr_find_first_index(&pke_audio_pw.pw_objects, &id, pw_objects_find_pw_object_by_id), i != 0xFFFFFFFF)
{
- if (pke_audio_pw.pw_objects[i].type != PKE_AUDIO_PW_OBJECT_TYPE_LINK) {
- pke_audio_pw.is_needing_output_remapped = true;
- }
if (pke_audio_pw.pw_objects[i].id == pke_audio_pw.default_sink_id) {
// we just lost our target audio device
pke_audio_pw.default_sink_id = 0;
pke_audio_pw.default_sink_name[0] = '\0';
+ pke_audio_pw.is_needing_output_remapped = true;
}
pk_arr_remove_at(&pke_audio_pw.pw_objects, i);
// printf(" removed.\n");