diff options
author | Wim Taymans <wtaymans@redhat.com> | 2020-01-30 17:21:33 +0100 |
---|---|---|
committer | Wim Taymans <wtaymans@redhat.com> | 2020-01-30 17:21:33 +0100 |
commit | cd21f5292b4520884285a6ab2e32014039e4f0a5 (patch) | |
tree | 03bf9374bc944a801fe011cefefddfc29e71c0d9 | |
parent | 9f0c5d403e4e3ce59758545aff7c1c223b397385 (diff) |
context: emit events for driver
Make new private events to monitor the state of driver nodes. This
can be used to implement profiling.
-rw-r--r-- | src/pipewire/context.c | 1 | ||||
-rw-r--r-- | src/pipewire/impl-node.c | 7 | ||||
-rw-r--r-- | src/pipewire/private.h | 36 |
3 files changed, 35 insertions, 9 deletions
diff --git a/src/pipewire/context.c b/src/pipewire/context.c index aa814f6f..e5b039b8 100644 --- a/src/pipewire/context.c +++ b/src/pipewire/context.c @@ -257,6 +257,7 @@ struct pw_context *pw_context_new(struct pw_loop *main_loop, spa_list_init(&this->export_list); spa_list_init(&this->driver_list); spa_hook_list_init(&this->listener_list); + spa_hook_list_init(&this->driver_listener_list); this->core = pw_context_create_core(this, pw_properties_copy(properties), 0); if (this->core == NULL) { diff --git a/src/pipewire/impl-node.c b/src/pipewire/impl-node.c index f754796a..415d7e0f 100644 --- a/src/pipewire/impl-node.c +++ b/src/pipewire/impl-node.c @@ -780,7 +780,7 @@ static void dump_states(struct pw_impl_node *driver) a->finish_time, a->awake_time - a->signal_time, a->finish_time - a->awake_time, - t->activation->status, t->activation->pending_sync); + a->status, a->pending_sync); } } @@ -1285,6 +1285,7 @@ static void update_position(struct pw_impl_node *node, int all_ready) if (a->position.state == SPA_IO_POSITION_STATE_STARTING) { if (!all_ready && --a->sync_left == 0) { pw_log_warn(NAME" %p: sync timeout, going to RUNNING", node); + pw_context_driver_emit_timeout(node->context, node); dump_states(node); all_ready = true; } @@ -1313,9 +1314,11 @@ static int node_ready(void *data, int status) if (a->state[0].pending != 0) { pw_log_warn(NAME" %p: graph not finished", node); + pw_context_driver_emit_incomplete(node->context, node); dump_states(node); node->rt.target.signal(node->rt.target.data); } + pw_context_driver_emit_start(node->context, node); sync_type = check_updates(node, &reposition_owner); owner[0] = ATOMIC_LOAD(a->segment_owner[0]); @@ -1400,6 +1403,8 @@ static int node_xrun(void *data, uint64_t trigger, uint64_t delay, struct spa_po pw_log_debug(NAME" %p: XRun! count:%u time:%"PRIu64" delay:%"PRIu64" max:%"PRIu64, this, a->xrun_count, trigger, delay, a->max_delay); + pw_context_driver_emit_xrun(this->context, this); + return 0; } diff --git a/src/pipewire/private.h b/src/pipewire/private.h index 4b22b792..61197805 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -185,14 +185,6 @@ struct pw_global { struct spa_list resource_list; /**< The list of resources of this global */ }; -#define pw_context_emit(o,m,v,...) spa_hook_list_call(&o->listener_list, struct pw_context_events, m, v, ##__VA_ARGS__) -#define pw_context_emit_destroy(c) pw_context_emit(c, destroy, 0) -#define pw_context_emit_free(c) pw_context_emit(c, free, 0) -#define pw_context_emit_info_changed(c,i) pw_context_emit(c, info_changed, 0, i) -#define pw_context_emit_check_access(c,cl) pw_context_emit(c, check_access, 0, cl) -#define pw_context_emit_global_added(c,g) pw_context_emit(c, global_added, 0, g) -#define pw_context_emit_global_removed(c,g) pw_context_emit(c, global_removed, 0, g) - #define pw_core_resource(r,m,v,...) pw_resource_call(r, struct pw_core_events, m, v, ##__VA_ARGS__) #define pw_core_resource_info(r,...) pw_core_resource(r,info,0,__VA_ARGS__) #define pw_core_resource_done(r,...) pw_core_resource(r,done,0,__VA_ARGS__) @@ -223,10 +215,37 @@ pw_core_resource_errorf(struct pw_resource *resource, uint32_t id, int seq, va_end(args); } +#define pw_context_driver_emit(c,m,v,...) spa_hook_list_call_simple(&c->driver_listener_list, struct pw_context_driver_events, m, v, ##__VA_ARGS__) +#define pw_context_driver_emit_start(c,n) pw_context_driver_emit(c, start, 0, n) +#define pw_context_driver_emit_xrun(c,n) pw_context_driver_emit(c, xrun, 0, n) +#define pw_context_driver_emit_incomplete(c,n) pw_context_driver_emit(c, incomplete, 0, n) +#define pw_context_driver_emit_timeout(c,n) pw_context_driver_emit(c, timeout, 0, n) + +struct pw_context_driver_events { +#define PW_VERSION_CONTEXT_DRIVER_EVENTS 0 + uint32_t version; + + /** The driver graph is started */ + void (*start) (void *data, struct pw_impl_node *node); + /** The driver under/overruns */ + void (*xrun) (void *data, struct pw_impl_node *node); + /** The driver could not complete the graph */ + void (*incomplete) (void *data, struct pw_impl_node *node); + /** The driver got a sync timeout */ + void (*timeout) (void *data, struct pw_impl_node *node); +}; + #define pw_registry_resource(r,m,v,...) pw_resource_call(r, struct pw_registry_events,m,v,##__VA_ARGS__) #define pw_registry_resource_global(r,...) pw_registry_resource(r,global,0,__VA_ARGS__) #define pw_registry_resource_global_remove(r,...) pw_registry_resource(r,global_remove,0,__VA_ARGS__) +#define pw_context_emit(o,m,v,...) spa_hook_list_call(&o->listener_list, struct pw_context_events, m, v, ##__VA_ARGS__) +#define pw_context_emit_destroy(c) pw_context_emit(c, destroy, 0) +#define pw_context_emit_free(c) pw_context_emit(c, free, 0) +#define pw_context_emit_info_changed(c,i) pw_context_emit(c, info_changed, 0, i) +#define pw_context_emit_check_access(c,cl) pw_context_emit(c, check_access, 0, cl) +#define pw_context_emit_global_added(c,g) pw_context_emit(c, global_added, 0, g) +#define pw_context_emit_global_removed(c,g) pw_context_emit(c, global_removed, 0, g) struct pw_context { struct pw_impl_core *core; /**< core object */ @@ -254,6 +273,7 @@ struct pw_context { struct spa_list export_list; /**< list of export types */ struct spa_list driver_list; /**< list of driver nodes */ + struct spa_hook_list driver_listener_list; struct spa_hook_list listener_list; struct pw_loop *main_loop; /**< main loop for control */ |