Skip to content

Instantly share code, notes, and snippets.

@CarterLi
Last active October 13, 2023 03:14
Show Gist options
  • Save CarterLi/b316aaa818de3862eba037c2120051eb to your computer and use it in GitHub Desktop.
Save CarterLi/b316aaa818de3862eba037c2120051eb to your computer and use it in GitHub Desktop.
Pipewire: enum audio devices
// -lpipewire-0.3
#include <common/library.h>
#include <pipewire/pipewire.h>
#include <util/stringUtils.h>
struct roundtrip_data {
int pending;
struct pw_main_loop *loop;
};
static void on_core_done(void *data, uint32_t id, int seq)
{
struct roundtrip_data *d = data;
if (id == PW_ID_CORE && seq == d->pending)
pw_main_loop_quit(d->loop);
}
static void roundtrip(struct pw_core *core, struct pw_main_loop *loop)
{
static const struct pw_core_events core_events = {
PW_VERSION_CORE_EVENTS,
.done = on_core_done,
};
struct roundtrip_data d = { .loop = loop };
struct spa_hook core_listener;
pw_core_add_listener(core, &core_listener, &core_events, &d);
d.pending = pw_core_sync(core, PW_ID_CORE, 0);
pw_main_loop_run(loop);
spa_hook_remove(&core_listener);
}
static void registry_event_global(void *data, uint32_t id,
uint32_t permissions, const char *type, uint32_t version,
const struct spa_dict *props)
{
if (!ffStrEquals(type, PW_TYPE_INTERFACE_Device)) return;
bool found = false;
for (uint32_t i = 0; i < props->n_items; ++i)
{
const struct spa_dict_item* item = &props->items[i];
if (ffStrEquals(item->key, PW_KEY_MEDIA_CLASS))
{
if (!ffStrEquals(item->value, "Audio/Device")) return;
found = true;
break;
}
}
if (!found)
return;
const char* deviceName = NULL;
for (uint32_t i = 0; i < props->n_items; ++i)
{
const struct spa_dict_item* item = &props->items[i];
if (ffStrEquals(item->key, PW_KEY_DEVICE_DESCRIPTION))
{
deviceName = item->value;
break;
}
}
printf("object: id:%u type:%s/%d name=%s\n", id, type, version, deviceName ? deviceName : "unknown");
}
static const char* detectSoundWithPipeWire(FFlist* devices)
{
pw_init(NULL, NULL);
struct pw_main_loop* mainloop = pw_main_loop_new(NULL);
if (!mainloop) return "Failed to create pipewire mainloop";
struct pw_context* context = pw_context_new(pw_main_loop_get_loop(mainloop), NULL, 0);
struct pw_core* core = pw_context_connect(context, NULL, 0);
struct pw_registry* registry = pw_core_get_registry(core, PW_VERSION_REGISTRY, 0);
struct spa_hook registry_listener;
spa_zero(registry_listener);
pw_registry_add_listener(registry, &registry_listener, &(struct pw_registry_events) {
.version = PW_VERSION_REGISTRY_EVENTS,
.global = registry_event_global,
}, NULL);
// pw_core_sync(core, PW_ID_CORE, 0);
roundtrip(core, mainloop);
pw_proxy_destroy((struct pw_proxy*) registry);
pw_core_disconnect(core);
pw_context_destroy(context);
pw_main_loop_quit(mainloop);
pw_deinit();
return NULL;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment