[pulseaudio-discuss] [PATCH 07/11] Add device prototype support to the core

Tanu Kaskinen tanu.kaskinen at linux.intel.com
Sat Nov 23 21:58:04 PST 2013


This patch adds device prototypes to cards and modifies sinks and
sources so that they set the sink/source pointer in the prototype when
the device is created or deleted. This way sink and source
implementations don't need to manage the pointer lifecycle themselves,
they just need to tell the sink or source that they are associated
with a device prototype. By the way, it's perfectly valid for a sink
or source to not have a prototype, because the prototypes are only
relevant for devices that are created by cards.
---
 src/pulsecore/card.c   |  5 +++++
 src/pulsecore/card.h   |  1 +
 src/pulsecore/sink.c   | 15 +++++++++++++++
 src/pulsecore/sink.h   |  6 ++++++
 src/pulsecore/source.c | 15 +++++++++++++++
 src/pulsecore/source.h |  6 ++++++
 6 files changed, 48 insertions(+)

diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c
index 7637c39..a0196ae 100644
--- a/src/pulsecore/card.c
+++ b/src/pulsecore/card.c
@@ -30,6 +30,7 @@
 #include <pulse/xmalloc.h>
 #include <pulse/util.h>
 
+#include <pulsecore/device-prototype.h>
 #include <pulsecore/log.h>
 #include <pulsecore/macro.h>
 #include <pulsecore/router.h>
@@ -50,6 +51,7 @@ pa_card_profile *pa_card_profile_new(const char *name, const char *description,
     c->description = pa_xstrdup(description);
 
     c->priority = 0;
+    c->device_prototypes = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
     c->n_sinks = c->n_sources = 0;
     c->max_sink_channels = c->max_source_channels = 0;
     c->available = PA_AVAILABLE_UNKNOWN;
@@ -60,6 +62,9 @@ pa_card_profile *pa_card_profile_new(const char *name, const char *description,
 void pa_card_profile_free(pa_card_profile *c) {
     pa_assert(c);
 
+    if (c->device_prototypes)
+        pa_hashmap_free(c->device_prototypes);
+
     pa_xfree(c->name);
     pa_xfree(c->description);
     pa_xfree(c);
diff --git a/src/pulsecore/card.h b/src/pulsecore/card.h
index 8516d2f..6ed8b31 100644
--- a/src/pulsecore/card.h
+++ b/src/pulsecore/card.h
@@ -44,6 +44,7 @@ typedef struct pa_card_profile {
 
     unsigned priority;
     pa_available_t available; /* PA_AVAILABLE_UNKNOWN, PA_AVAILABLE_NO or PA_AVAILABLE_YES */
+    pa_hashmap *device_prototypes; /* pa_device_prototype -> pa_device_prototype (hashmap-as-a-set) */
 
     /* We probably want to have different properties later on here */
     unsigned n_sinks;
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 1783c95..cb22630 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -37,6 +37,7 @@
 #include <pulse/rtclock.h>
 #include <pulse/internal.h>
 
+#include <pulsecore/device-prototype.h>
 #include <pulsecore/i18n.h>
 #include <pulsecore/sink-input.h>
 #include <pulsecore/namereg.h>
@@ -139,6 +140,12 @@ void pa_sink_new_data_set_port(pa_sink_new_data *data, const char *port) {
     data->active_port = pa_xstrdup(port);
 }
 
+void pa_sink_new_data_set_prototype(pa_sink_new_data *data, pa_device_prototype *prototype) {
+    pa_assert(data);
+
+    data->prototype = prototype;
+}
+
 void pa_sink_new_data_done(pa_sink_new_data *data) {
     pa_assert(data);
 
@@ -313,6 +320,8 @@ pa_sink* pa_sink_new(
             &s->sample_spec,
             0);
 
+    s->prototype = data->prototype;
+
     s->thread_info.rtpoll = NULL;
     s->thread_info.inputs = pa_hashmap_new_full(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func, NULL,
                                                 (pa_free_cb_t) pa_sink_input_unref);
@@ -640,6 +649,9 @@ void pa_sink_put(pa_sink* s) {
          * place where he is supposed to place his changes.  */
         s->reference_volume = s->real_volume;
 
+    if (s->prototype)
+        pa_device_prototype_set_sink(s->prototype, s);
+
     s->thread_info.soft_volume = s->soft_volume;
     s->thread_info.soft_muted = s->muted;
     pa_sw_cvolume_multiply(&s->thread_info.current_hw_volume, &s->soft_volume, &s->real_volume);
@@ -694,6 +706,9 @@ void pa_sink_unlink(pa_sink* s) {
     if (s->node)
         pa_node_unlink(s->node);
 
+    if (s->prototype)
+        pa_device_prototype_set_sink(s->prototype, NULL);
+
     if (s->state != PA_SINK_UNLINKED && s->name)
         pa_namereg_unregister(s->core, s->name);
 
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index 0a4b25e..5da613e 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -49,6 +49,8 @@ typedef struct pa_sink_volume_change pa_sink_volume_change;
 #include <pulsecore/thread-mq.h>
 #include <pulsecore/sink-input.h>
 
+typedef struct pa_device_prototype pa_device_prototype;
+
 #define PA_MAX_INPUTS_PER_SINK 32
 
 /* Returns true if sink is linked: registered and accessible from client side. */
@@ -119,6 +121,7 @@ struct pa_sink {
     int64_t latency_offset;
 
     unsigned priority;
+    pa_device_prototype *prototype;
 
     /* Called when the main loop requests a state change. Called from
      * main loop context. If returns -1 the state change will be
@@ -360,6 +363,8 @@ typedef struct pa_sink_new_data {
     bool save_volume:1;
     bool save_muted:1;
 
+    pa_device_prototype *prototype;
+
     pa_node_new_data node_data;
 } pa_sink_new_data;
 
@@ -371,6 +376,7 @@ void pa_sink_new_data_set_alternate_sample_rate(pa_sink_new_data *data, const ui
 void pa_sink_new_data_set_volume(pa_sink_new_data *data, const pa_cvolume *volume);
 void pa_sink_new_data_set_muted(pa_sink_new_data *data, bool mute);
 void pa_sink_new_data_set_port(pa_sink_new_data *data, const char *port);
+void pa_sink_new_data_set_prototype(pa_sink_new_data *data, pa_device_prototype *prototype);
 void pa_sink_new_data_done(pa_sink_new_data *data);
 
 /*** To be called exclusively by the sink driver, from main context */
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 0fc3e81..123ca02 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -36,6 +36,7 @@
 #include <pulse/internal.h>
 
 #include <pulsecore/core-util.h>
+#include <pulsecore/device-prototype.h>
 #include <pulsecore/source-output.h>
 #include <pulsecore/namereg.h>
 #include <pulsecore/core-subscribe.h>
@@ -136,6 +137,12 @@ void pa_source_new_data_set_port(pa_source_new_data *data, const char *port) {
     data->active_port = pa_xstrdup(port);
 }
 
+void pa_source_new_data_set_prototype(pa_source_new_data *data, pa_device_prototype *prototype) {
+    pa_assert(data);
+
+    data->prototype = prototype;
+}
+
 void pa_source_new_data_done(pa_source_new_data *data) {
     pa_assert(data);
 
@@ -307,6 +314,8 @@ pa_source* pa_source_new(
             &s->sample_spec,
             0);
 
+    s->prototype = data->prototype;
+
     s->thread_info.rtpoll = NULL;
     s->thread_info.outputs = pa_hashmap_new_full(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func, NULL,
                                                  (pa_free_cb_t) pa_source_output_unref);
@@ -602,6 +611,9 @@ void pa_source_put(pa_source *s) {
          * place where he is supposed to place his changes.  */
         s->reference_volume = s->real_volume;
 
+    if (s->prototype)
+        pa_device_prototype_set_source(s->prototype, s);
+
     s->thread_info.soft_volume = s->soft_volume;
     s->thread_info.soft_muted = s->muted;
     pa_sw_cvolume_multiply(&s->thread_info.current_hw_volume, &s->soft_volume, &s->real_volume);
@@ -643,6 +655,9 @@ void pa_source_unlink(pa_source *s) {
     if (s->node)
         pa_node_unlink(s->node);
 
+    if (s->prototype)
+        pa_device_prototype_set_source(s->prototype, NULL);
+
     if (s->state != PA_SOURCE_UNLINKED && s->name)
         pa_namereg_unregister(s->core, s->name);
 
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index 3c43df8..9e7d223 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -49,6 +49,8 @@ typedef struct pa_source_volume_change pa_source_volume_change;
 #include <pulsecore/thread-mq.h>
 #include <pulsecore/source-output.h>
 
+typedef struct pa_device_prototype pa_device_prototype;
+
 #define PA_MAX_OUTPUTS_PER_SOURCE 32
 
 /* Returns true if source is linked: registered and accessible from client side. */
@@ -119,6 +121,7 @@ struct pa_source {
     int64_t latency_offset;
 
     unsigned priority;
+    pa_device_prototype *prototype;
 
     /* Called when the main loop requests a state change. Called from
      * main loop context. If returns -1 the state change will be
@@ -298,6 +301,8 @@ typedef struct pa_source_new_data {
     bool save_volume:1;
     bool save_muted:1;
 
+    pa_device_prototype *prototype;
+
     pa_node_new_data node_data;
 } pa_source_new_data;
 
@@ -310,6 +315,7 @@ void pa_source_new_data_set_monitor_of(pa_source_new_data *data, pa_sink *monito
 void pa_source_new_data_set_volume(pa_source_new_data *data, const pa_cvolume *volume);
 void pa_source_new_data_set_muted(pa_source_new_data *data, bool mute);
 void pa_source_new_data_set_port(pa_source_new_data *data, const char *port);
+void pa_source_new_data_set_prototype(pa_source_new_data *data, pa_device_prototype *prototype);
 void pa_source_new_data_done(pa_source_new_data *data);
 
 /*** To be called exclusively by the source driver, from main context */
-- 
1.8.3.1



More information about the pulseaudio-discuss mailing list