Created
May 15, 2021 12:44
-
-
Save saivert/c940cad1745d53f53d2c4f5857d3fb4e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <pipewire/pipewire.h> | |
| #include <strings.h> | |
| static int roundtrip(struct pw_core *core, struct pw_main_loop *loop) | |
| { | |
| struct spa_hook core_listener; | |
| int pending, done = 0; | |
| void core_event_done(void *object, uint32_t id, int seq) { | |
| if (id == PW_ID_CORE && seq == pending) { | |
| done = 1; | |
| pw_main_loop_quit(loop); | |
| } | |
| } | |
| const struct pw_core_events core_events = { | |
| PW_VERSION_CORE_EVENTS, | |
| .done = core_event_done, | |
| }; | |
| spa_zero(core_listener); | |
| pw_core_add_listener(core, &core_listener, | |
| &core_events, NULL); | |
| pending = pw_core_sync(core, PW_ID_CORE, 0); | |
| while (!done) { | |
| pw_main_loop_run(loop); | |
| } | |
| spa_hook_remove(&core_listener); | |
| return 0; | |
| } | |
| struct proxy_data; | |
| typedef void (*info_func_t) (struct proxy_data *pd); | |
| struct proxy_data { | |
| struct remote_data *rd; | |
| struct global *global; | |
| struct pw_proxy *proxy; | |
| void *info; | |
| info_func_t info_func; | |
| pw_destroy_t destroy; | |
| struct spa_hook proxy_listener; | |
| struct spa_hook object_listener; | |
| }; | |
| struct pw_registry *registry; | |
| struct pw_proxy *_proxy; | |
| struct proxy_data *pd; | |
| static void print_properties(struct spa_dict *props, char mark, bool header) | |
| { | |
| const struct spa_dict_item *item; | |
| if (header) | |
| fprintf(stdout, "%c\tproperties:\n", mark); | |
| if (props == NULL || props->n_items == 0) { | |
| if (header) | |
| fprintf(stdout, "\t\tnone\n"); | |
| return; | |
| } | |
| spa_dict_for_each(item, props) { | |
| fprintf(stdout, "%c\t\t%s = \"%s\"\n", mark, item->key, item->value); | |
| } | |
| } | |
| static void node_event_info(void *object, const struct pw_node_info *info) | |
| { | |
| struct proxy_data *pd = object; | |
| struct remote_data *rd = pd->rd; | |
| if (pd->info) | |
| fprintf(stdout, "node %d changed\n", info->id); | |
| pd->info = pw_node_info_update(pd->info, info); | |
| print_properties (((struct pw_node_info *)pd->info)->props, ' ', true); | |
| } | |
| static const struct pw_node_events node_events = { | |
| PW_VERSION_NODE_EVENTS, | |
| .info = node_event_info | |
| }; | |
| 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 (!strcmp(type, PW_TYPE_INTERFACE_Node) && props) | |
| { | |
| // const char *media_class; | |
| // media_class = spa_dict_lookup(props, PW_KEY_MEDIA_CLASS); | |
| // if (media_class && !strcmp(media_class, "Audio/Sink")) | |
| // { | |
| // const char *nick, *name; | |
| // nick = spa_dict_lookup(props, PW_KEY_NODE_NICK); | |
| // name = spa_dict_lookup(props, PW_KEY_NODE_NAME); | |
| // printf("%d: %s: %s\n", id, nick ? nick : "(No Nick)", name ? name : "(No Name)"); | |
| // } | |
| const char *name; | |
| name = spa_dict_lookup(props, PW_KEY_NODE_NAME); | |
| if (!strcmp(name, "DeaDBeeF Music Player")) { | |
| _proxy = pw_registry_bind(registry, | |
| id, | |
| type, | |
| PW_VERSION_NODE, | |
| sizeof(struct proxy_data)); | |
| pd = pw_proxy_get_user_data(_proxy); | |
| pw_proxy_add_object_listener(_proxy, &pd->object_listener, &node_events, pd); | |
| // struct spa_dict *dict = ((struct pw_node_info *)pd->info)->props; | |
| } | |
| } | |
| // printf("object: id:%u type:%s/%d\n", id, type, version); | |
| // const struct spa_dict_item *item; | |
| // if (props) | |
| // spa_dict_for_each(item, props) | |
| // printf("\t\t%s: \"%s\"\n", item->key, item->value); | |
| } | |
| static const struct pw_registry_events registry_events = { | |
| PW_VERSION_REGISTRY_EVENTS, | |
| .global = registry_event_global, | |
| }; | |
| int main(int argc, char *argv[]) | |
| { | |
| struct pw_main_loop *loop; | |
| struct pw_context *context; | |
| struct pw_core *core; | |
| struct spa_hook registry_listener; | |
| pw_init(&argc, &argv); | |
| loop = pw_main_loop_new(NULL /* properties */); | |
| context = pw_context_new(pw_main_loop_get_loop(loop), | |
| NULL /* properties */, | |
| 0 /* user_data size */); | |
| core = pw_context_connect(context, | |
| NULL /* properties */, | |
| 0 /* user_data size */); | |
| registry = pw_core_get_registry(core, PW_VERSION_REGISTRY, | |
| 0 /* user_data size */); | |
| spa_zero(registry_listener); | |
| pw_registry_add_listener(registry, ®istry_listener, | |
| ®istry_events, NULL); | |
| // Very dirty hack to get a few roundtrips so the node events get to fire | |
| roundtrip(core, loop); | |
| roundtrip(core, loop); | |
| roundtrip(core, loop); | |
| roundtrip(core, loop); | |
| // pw_main_loop_run(loop); | |
| pw_proxy_destroy((struct pw_proxy*)registry); | |
| pw_core_disconnect(core); | |
| pw_context_destroy(context); | |
| pw_main_loop_destroy(loop); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment