summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wtaymans@redhat.com>2020-01-30 17:21:33 +0100
committerWim Taymans <wtaymans@redhat.com>2020-01-30 17:21:33 +0100
commitcd21f5292b4520884285a6ab2e32014039e4f0a5 (patch)
tree03bf9374bc944a801fe011cefefddfc29e71c0d9
parent9f0c5d403e4e3ce59758545aff7c1c223b397385 (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.c1
-rw-r--r--src/pipewire/impl-node.c7
-rw-r--r--src/pipewire/private.h36
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 */