introspect: Add functions to handle the latency offset.

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.
This commit is contained in:
poljar (Damir Jelic) 2012-06-28 15:00:45 +02:00 committed by Tanu Kaskinen
parent 86996b4cc8
commit 529a5949fb
7 changed files with 101 additions and 6 deletions

View file

@ -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. 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 #### If you just changed the protocol, read this
## module-tunnel depends on the sink/source/sink-input/source-input protocol ## module-tunnel depends on the sink/source/sink-input/source-input protocol

View file

@ -36,7 +36,7 @@ AC_SUBST(PA_MINOR, pa_minor)
AC_SUBST(PA_MAJORMINOR, pa_major.pa_minor) AC_SUBST(PA_MAJORMINOR, pa_major.pa_minor)
AC_SUBST(PA_API_VERSION, 12) 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 # The stable ABI for client applications, for the version info x:y:z
# always will hold y=z # always will hold y=z

View file

@ -59,6 +59,7 @@ pa_context_get_source_info_by_name;
pa_context_get_source_info_list; pa_context_get_source_info_list;
pa_context_get_source_output_info; pa_context_get_source_output_info;
pa_context_get_source_output_info_list; pa_context_get_source_output_info_list;
pa_context_set_port_latency_offset;
pa_context_get_state; pa_context_get_state;
pa_context_get_tile_size; pa_context_get_tile_size;
pa_context_is_local; pa_context_is_local;

View file

@ -763,8 +763,7 @@ pa_operation* pa_context_get_client_info_list(pa_context *c, pa_client_info_cb_t
/*** Card info ***/ /*** Card info ***/
static void card_info_free(pa_card_info* i) static void card_info_free(pa_card_info* i) {
{
if (i->proplist) if (i->proplist)
pa_proplist_free(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; uint32_t j, k, l;
if (pa_tagstruct_getu32(t, &i->n_ports) < 0) 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; 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; 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 (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); pa_context_fail(o->context, PA_ERR_PROTOCOL);
card_info_free(&i); card_info_free(&i);
goto finish; 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); 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 ***/ /*** Autoload stuff ***/
PA_WARN_REFERENCE(pa_context_get_autoload_info_by_name, "Module auto-loading no longer supported."); PA_WARN_REFERENCE(pa_context_get_autoload_info_by_name, "Module auto-loading no longer supported.");

View file

@ -466,6 +466,7 @@ typedef struct pa_card_port_info {
uint32_t n_profiles; /**< Number of entries in profile array */ 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_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 */ 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; } pa_card_port_info;
/** Stores information about cards. Please note that this structure /** 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 */ /** 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); 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 */ /** @{ \name Sink Inputs */

View file

@ -173,6 +173,9 @@ enum {
PA_COMMAND_SET_SOURCE_OUTPUT_VOLUME, PA_COMMAND_SET_SOURCE_OUTPUT_VOLUME,
PA_COMMAND_SET_SOURCE_OUTPUT_MUTE, PA_COMMAND_SET_SOURCE_OUTPUT_MUTE,
/* Supported since protocol v27 (3.0) */
PA_COMMAND_SET_PORT_LATENCY_OFFSET,
PA_COMMAND_MAX PA_COMMAND_MAX
}; };

View 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_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_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_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] = { static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
[PA_COMMAND_ERROR] = NULL, [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_SINK_PORT] = command_set_sink_or_source_port,
[PA_COMMAND_SET_SOURCE_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 [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_HASHMAP_FOREACH(p, port->profiles, state2)
pa_tagstruct_puts(t, p->name); 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); 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 ***/ /*** pstream callbacks ***/
static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) { static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) {