]> code.delx.au - pulseaudio/commitdiff
introspect: Add functions to handle the latency offset.
authorpoljar (Damir Jelic) <poljarinho@gmail.com>
Thu, 28 Jun 2012 13:00:45 +0000 (15:00 +0200)
committerTanu Kaskinen <tanuk@iki.fi>
Sat, 30 Jun 2012 11:41:08 +0000 (14:41 +0300)
This includes updating the native protocol and the client API.
A new command was added to allow setting the latency offset.

Also the card list command now shows the latency offset if there
are ports available.

Update protocol to 27.

PROTOCOL
configure.ac
src/map-file
src/pulse/introspect.c
src/pulse/introspect.h
src/pulsecore/native-common.h
src/pulsecore/protocol-native.c

index bfbd23bd553d39826e4b6b9829c69d5d05bd5cc4..01abeed518090d713561ecd40c842af5a0f0c1ce 100644 (file)
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -321,6 +321,17 @@ PA_COMMAND_GET_CARD_INFO_LIST), the following is added:
 
 Profile names must match earlier sent profile names for the same card.
 
+## v27, implemented by >= 3.0
+
+New opcodes:
+    PA_COMMAND_SET_PORT_LATENCY_OFFSET
+
+New field in the card commands that send/receive port introspection data
+PA_COMMAND_GET_CARD_INFO(_LIST)):
+
+    int64_t latency_offset
+
+The field is added once for every port.
 
 #### If you just changed the protocol, read this
 ## module-tunnel depends on the sink/source/sink-input/source-input protocol
index 5e1a4c57456955ca67457b60238b46699a7b2747..0290fa01e4c4a09f468e8b3a9e93ab791bec6a5a 100644 (file)
@@ -36,7 +36,7 @@ AC_SUBST(PA_MINOR, pa_minor)
 AC_SUBST(PA_MAJORMINOR, pa_major.pa_minor)
 
 AC_SUBST(PA_API_VERSION, 12)
-AC_SUBST(PA_PROTOCOL_VERSION, 26)
+AC_SUBST(PA_PROTOCOL_VERSION, 27)
 
 # The stable ABI for client applications, for the version info x:y:z
 # always will hold y=z
index c6676bbb2c15b8a7553a1a1a916a52542d5bb32a..a20314c248f86a826c69bbf0c7e31c26756bfd77 100644 (file)
@@ -59,6 +59,7 @@ pa_context_get_source_info_by_name;
 pa_context_get_source_info_list;
 pa_context_get_source_output_info;
 pa_context_get_source_output_info_list;
+pa_context_set_port_latency_offset;
 pa_context_get_state;
 pa_context_get_tile_size;
 pa_context_is_local;
index 6e07494cdaae0224f9f46ec09132d02485eb46f9..9ca3fd367af3ae10c3150dd6046a984439d170c7 100644 (file)
@@ -763,8 +763,7 @@ pa_operation* pa_context_get_client_info_list(pa_context *c, pa_client_info_cb_t
 
 /*** Card info ***/
 
-static void card_info_free(pa_card_info* i)
-{
+static void card_info_free(pa_card_info* i) {
     if (i->proplist)
         pa_proplist_free(i->proplist);
 
@@ -787,8 +786,7 @@ static void card_info_free(pa_card_info* i)
     }
 }
 
-static int fill_card_port_info(pa_tagstruct* t, pa_card_info* i)
-{
+static int fill_card_port_info(pa_context *context, pa_tagstruct* t, pa_card_info* i) {
     uint32_t j, k, l;
 
     if (pa_tagstruct_getu32(t, &i->n_ports) < 0)
@@ -849,6 +847,11 @@ static int fill_card_port_info(pa_tagstruct* t, pa_card_info* i)
                     return -PA_ERR_PROTOCOL;
             }
         }
+        if (context->version >= 27) {
+            if (pa_tagstruct_gets64(t, &port->latency_offset) < 0)
+                return -PA_ERR_PROTOCOL;
+        } else
+            port->latency_offset = 0;
     }
 
     return 0;
@@ -931,7 +934,7 @@ static void context_get_card_info_callback(pa_pdispatch *pd, uint32_t command, u
             }
 
             if (o->context->version >= 26) {
-                if (fill_card_port_info(t, &i) < 0) {
+                if (fill_card_port_info(o->context, t, &i) < 0) {
                     pa_context_fail(o->context, PA_ERR_PROTOCOL);
                     card_info_free(&i);
                     goto finish;
@@ -1868,6 +1871,33 @@ pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, pa_context_s
     return command_kill(c, PA_COMMAND_UNLOAD_MODULE, idx, cb, userdata);
 }
 
+pa_operation* pa_context_set_port_latency_offset(pa_context *c, const char *card_name, const char *port_name, int64_t offset, pa_context_success_cb_t cb, void *userdata) {
+    pa_operation *o;
+    pa_tagstruct *t;
+    uint32_t tag;
+
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+    PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, card_name && *card_name, PA_ERR_INVALID);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, port_name && *port_name, PA_ERR_INVALID);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 27, PA_ERR_NOTSUPPORTED);
+
+    o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+
+    t = pa_tagstruct_command(c, PA_COMMAND_SET_PORT_LATENCY_OFFSET, &tag);
+    pa_tagstruct_putu32(t, PA_INVALID_INDEX);
+    pa_tagstruct_puts(t, card_name);
+    pa_tagstruct_puts(t, port_name);
+    pa_tagstruct_puts64(t, offset);
+    pa_pstream_send_tagstruct(c->pstream, t);
+    pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+
+    return o;
+}
+
 /*** Autoload stuff ***/
 
 PA_WARN_REFERENCE(pa_context_get_autoload_info_by_name, "Module auto-loading no longer supported.");
index 0072f5deb7a9aa88784262a530a60d41a93c0e2c..6ea4536127eaa7a817c644613f7b5ef6664d1a72 100644 (file)
@@ -466,6 +466,7 @@ typedef struct pa_card_port_info {
     uint32_t n_profiles;                /**< Number of entries in profile array */
     pa_card_profile_info** profiles;    /**< Array of pointers to available profiles, or NULL. Array is terminated by an entry set to NULL. */
     pa_proplist *proplist;              /**< Property list */
+    int64_t latency_offset;             /**< Latency offset of the port that gets added to the sink/source latency when the port is active. \since 3.0 */
 } pa_card_port_info;
 
 /** Stores information about cards. Please note that this structure
@@ -502,6 +503,9 @@ pa_operation* pa_context_set_card_profile_by_index(pa_context *c, uint32_t idx,
 /** Change the profile of a card. \since 0.9.15 */
 pa_operation* pa_context_set_card_profile_by_name(pa_context *c, const char*name, const char*profile, pa_context_success_cb_t cb, void *userdata);
 
+/** Set the latency offset of a port. \since 3.0 */
+pa_operation* pa_context_set_port_latency_offset(pa_context *c, const char *card_name, const char *port_name, int64_t offset, pa_context_success_cb_t cb, void *userdata);
+
 /** @} */
 
 /** @{ \name Sink Inputs */
index 8fde0236f548c0b285bfb4a684c1f844c2612b26..dad82e0e72f4948149d3660415909ecba3e28be7 100644 (file)
@@ -173,6 +173,9 @@ enum {
     PA_COMMAND_SET_SOURCE_OUTPUT_VOLUME,
     PA_COMMAND_SET_SOURCE_OUTPUT_MUTE,
 
+    /* Supported since protocol v27 (3.0) */
+    PA_COMMAND_SET_PORT_LATENCY_OFFSET,
+
     PA_COMMAND_MAX
 };
 
index 3e9c91149def510f9ce8b28be8f53255ea21f492..c39efc6f02a91501d7134ac86de499298df6ec55 100644 (file)
@@ -292,6 +292,7 @@ static void command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t
 static void command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 static void command_set_card_profile(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 static void command_set_sink_or_source_port(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
+static void command_set_port_latency_offset(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 
 static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
     [PA_COMMAND_ERROR] = NULL,
@@ -393,6 +394,8 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
     [PA_COMMAND_SET_SINK_PORT] = command_set_sink_or_source_port,
     [PA_COMMAND_SET_SOURCE_PORT] = command_set_sink_or_source_port,
 
+    [PA_COMMAND_SET_PORT_LATENCY_OFFSET] = command_set_port_latency_offset,
+
     [PA_COMMAND_EXTENSION] = command_extension
 };
 
@@ -3272,6 +3275,9 @@ static void card_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_car
 
         PA_HASHMAP_FOREACH(p, port->profiles, state2)
             pa_tagstruct_puts(t, p->name);
+
+        if (c->version >= 27)
+            pa_tagstruct_puts64(t, port->latency_offset);
     }
 }
 
@@ -4719,6 +4725,46 @@ static void command_set_sink_or_source_port(pa_pdispatch *pd, uint32_t command,
     pa_pstream_send_simple_ack(c->pstream, tag);
 }
 
+static void command_set_port_latency_offset(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
+    pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
+    const char *port_name, *card_name;
+    uint32_t idx = PA_INVALID_INDEX;
+    int64_t offset;
+    pa_card *card = NULL;
+    pa_device_port *port = NULL;
+
+    pa_native_connection_assert_ref(c);
+    pa_assert(t);
+
+    if (pa_tagstruct_getu32(t, &idx) < 0 ||
+        pa_tagstruct_gets(t, &card_name) < 0 ||
+        pa_tagstruct_gets(t, &port_name) < 0 ||
+        pa_tagstruct_gets64(t, &offset) < 0 ||
+        !pa_tagstruct_eof(t)) {
+        protocol_error(c);
+    }
+
+    CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
+    CHECK_VALIDITY(c->pstream, !card_name || pa_namereg_is_valid_name(card_name), tag, PA_ERR_INVALID);
+    CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || card_name, tag, PA_ERR_INVALID);
+    CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !card_name, tag, PA_ERR_INVALID);
+    CHECK_VALIDITY(c->pstream, port_name, tag, PA_ERR_INVALID);
+
+    if (idx != PA_INVALID_INDEX)
+        card = pa_idxset_get_by_index(c->protocol->core->cards, idx);
+    else
+        card = pa_namereg_get(c->protocol->core, card_name, PA_NAMEREG_CARD);
+
+    CHECK_VALIDITY(c->pstream, card, tag, PA_ERR_NOENTITY);
+
+    port = pa_hashmap_get(card->ports, port_name);
+    CHECK_VALIDITY(c->pstream, port, tag, PA_ERR_NOENTITY);
+
+    pa_device_port_set_latency_offset(port, offset);
+
+    pa_pstream_send_simple_ack(c->pstream, tag);
+}
+
 /*** pstream callbacks ***/
 
 static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) {