mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-05 13:29:57 -05:00
allow sending meta/policy events to clients
This commit is contained in:
parent
4bd9737725
commit
823431e447
17 changed files with 369 additions and 2 deletions
|
|
@ -95,7 +95,10 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
|
|||
[PA_COMMAND_RECORD_STREAM_SUSPENDED] = pa_command_stream_suspended,
|
||||
[PA_COMMAND_STARTED] = pa_command_stream_started,
|
||||
[PA_COMMAND_SUBSCRIBE_EVENT] = pa_command_subscribe_event,
|
||||
[PA_COMMAND_EXTENSION] = pa_command_extension
|
||||
[PA_COMMAND_EXTENSION] = pa_command_extension,
|
||||
[PA_COMMAND_PLAYBACK_STREAM_EVENT] = pa_command_stream_event,
|
||||
[PA_COMMAND_RECORD_STREAM_EVENT] = pa_command_stream_event,
|
||||
[PA_COMMAND_CLIENT_EVENT] = pa_command_client_event
|
||||
};
|
||||
static void context_free(pa_context *c);
|
||||
|
||||
|
|
@ -112,6 +115,9 @@ static void reset_callbacks(pa_context *c) {
|
|||
c->subscribe_callback = NULL;
|
||||
c->subscribe_userdata = NULL;
|
||||
|
||||
c->event_callback = NULL;
|
||||
c->event_userdata = NULL;
|
||||
|
||||
c->ext_stream_restore.callback = NULL;
|
||||
c->ext_stream_restore.userdata = NULL;
|
||||
}
|
||||
|
|
@ -917,6 +923,17 @@ void pa_context_set_state_callback(pa_context *c, pa_context_notify_cb_t cb, voi
|
|||
c->state_userdata = userdata;
|
||||
}
|
||||
|
||||
void pa_context_set_event_callback(pa_context *c, pa_context_event_cb_t cb, void *userdata) {
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
if (c->state == PA_CONTEXT_TERMINATED || c->state == PA_CONTEXT_FAILED)
|
||||
return;
|
||||
|
||||
c->event_callback = cb;
|
||||
c->event_userdata = userdata;
|
||||
}
|
||||
|
||||
int pa_context_is_pending(pa_context *c) {
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
|
@ -1245,6 +1262,11 @@ void pa_command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_t
|
|||
|
||||
pa_context_ref(c);
|
||||
|
||||
if (c->version < 15) {
|
||||
pa_context_fail(c, PA_ERR_PROTOCOL);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (pa_tagstruct_getu32(t, &idx) < 0 ||
|
||||
pa_tagstruct_gets(t, &name) < 0) {
|
||||
pa_context_fail(c, PA_ERR_PROTOCOL);
|
||||
|
|
@ -1259,3 +1281,41 @@ void pa_command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_t
|
|||
finish:
|
||||
pa_context_unref(c);
|
||||
}
|
||||
|
||||
|
||||
void pa_command_client_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_context *c = userdata;
|
||||
pa_proplist *pl = NULL;
|
||||
const char *event;
|
||||
|
||||
pa_assert(pd);
|
||||
pa_assert(command == PA_COMMAND_CLIENT_EVENT);
|
||||
pa_assert(t);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
pa_context_ref(c);
|
||||
|
||||
if (c->version < 15) {
|
||||
pa_context_fail(c, PA_ERR_PROTOCOL);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
pl = pa_proplist_new();
|
||||
|
||||
if (pa_tagstruct_gets(t, &event) < 0 ||
|
||||
pa_tagstruct_get_proplist(t, pl) < 0 ||
|
||||
!pa_tagstruct_eof(t) || !event) {
|
||||
pa_context_fail(c, PA_ERR_PROTOCOL);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (c->event_callback)
|
||||
c->event_callback(c, event, pl, c->event_userdata);
|
||||
|
||||
finish:
|
||||
pa_context_unref(c);
|
||||
|
||||
if (pl)
|
||||
pa_proplist_free(pl);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,6 +164,13 @@ typedef void (*pa_context_notify_cb_t)(pa_context *c, void *userdata);
|
|||
/** A generic callback for operation completion */
|
||||
typedef void (*pa_context_success_cb_t) (pa_context *c, int success, void *userdata);
|
||||
|
||||
/** A callback for asynchronous meta/policy event messages. The set
|
||||
* of defined events can be extended at any time. Also, server modules
|
||||
* may introduce additional message types so make sure that your
|
||||
* callback function ignores messages it doesn't know. \since
|
||||
* 0.9.15 */
|
||||
typedef void (*pa_context_event_cb_t)(pa_context *c, const char *name, pa_proplist *p, void *userdata);
|
||||
|
||||
/** Instantiate a new connection context with an abstract mainloop API
|
||||
* and an application name. It is recommended to use pa_context_new_with_proplist()
|
||||
* instead and specify some initial properties.*/
|
||||
|
|
@ -183,6 +190,10 @@ pa_context* pa_context_ref(pa_context *c);
|
|||
/** Set a callback function that is called whenever the context status changes */
|
||||
void pa_context_set_state_callback(pa_context *c, pa_context_notify_cb_t cb, void *userdata);
|
||||
|
||||
/** Set a callback function that is called whenver a meta/policy
|
||||
* control event is received. \since 0.9.15 */
|
||||
void pa_context_set_event_callback(pa_context *p, pa_context_event_cb_t cb, void *userdata);
|
||||
|
||||
/** Return the error number of the last failed operation */
|
||||
int pa_context_errno(pa_context *c);
|
||||
|
||||
|
|
|
|||
|
|
@ -840,6 +840,16 @@ static inline int PA_SOURCE_IS_OPENED(pa_source_state_t x) {
|
|||
/** A generic free() like callback prototype */
|
||||
typedef void (*pa_free_cb_t)(void *p);
|
||||
|
||||
/** A stream policy/meta event requesting that an application should
|
||||
* cork a specific stream. See pa_stream_event_cb_t for more
|
||||
* information, \since 0.9.15 */
|
||||
#define PA_STREAM_EVENT_REQUEST_CORK "request-cork"
|
||||
|
||||
/** A stream policy/meta event requesting that an application should
|
||||
* cork a specific stream. See pa_stream_event_cb_t for more
|
||||
* information, \since 0.9.15 */
|
||||
#define PA_STREAM_EVENT_REQUEST_UNCORK "request-uncork"
|
||||
|
||||
PA_C_DECL_END
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ struct pa_context {
|
|||
void *state_userdata;
|
||||
pa_context_subscribe_cb_t subscribe_callback;
|
||||
void *subscribe_userdata;
|
||||
pa_context_event_cb_t event_callback;
|
||||
void *event_userdata;
|
||||
|
||||
pa_mempool *mempool;
|
||||
|
||||
|
|
@ -181,6 +183,8 @@ struct pa_stream {
|
|||
void *suspended_userdata;
|
||||
pa_stream_notify_cb_t started_callback;
|
||||
void *started_userdata;
|
||||
pa_stream_event_cb_t event_callback;
|
||||
void *event_userdata;
|
||||
};
|
||||
|
||||
typedef void (*pa_operation_cb_t)(void);
|
||||
|
|
@ -207,6 +211,9 @@ void pa_command_overflow_or_underflow(pa_pdispatch *pd, uint32_t command, uint32
|
|||
void pa_command_stream_suspended(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
|
||||
void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
|
||||
void pa_command_stream_started(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
|
||||
void pa_command_stream_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
|
||||
void pa_command_client_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
|
||||
|
||||
pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t callback, void *userdata);
|
||||
void pa_operation_done(pa_operation *o);
|
||||
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ static void reset_callbacks(pa_stream *s) {
|
|||
s->suspended_userdata = NULL;
|
||||
s->started_callback = NULL;
|
||||
s->started_userdata = NULL;
|
||||
s->event_callback = NULL;
|
||||
s->event_userdata = NULL;
|
||||
}
|
||||
|
||||
pa_stream *pa_stream_new_with_proplist(
|
||||
|
|
@ -565,6 +567,52 @@ finish:
|
|||
pa_context_unref(c);
|
||||
}
|
||||
|
||||
void pa_command_stream_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_context *c = userdata;
|
||||
pa_stream *s;
|
||||
uint32_t channel;
|
||||
pa_proplist *pl = NULL;
|
||||
const char *event;
|
||||
|
||||
pa_assert(pd);
|
||||
pa_assert(command == PA_COMMAND_PLAYBACK_STREAM_EVENT || command == PA_COMMAND_RECORD_STREAM_EVENT);
|
||||
pa_assert(t);
|
||||
pa_assert(c);
|
||||
pa_assert(PA_REFCNT_VALUE(c) >= 1);
|
||||
|
||||
pa_context_ref(c);
|
||||
|
||||
if (c->version < 15) {
|
||||
pa_context_fail(c, PA_ERR_PROTOCOL);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
pl = pa_proplist_new();
|
||||
|
||||
if (pa_tagstruct_getu32(t, &channel) < 0 ||
|
||||
pa_tagstruct_gets(t, &event) < 0 ||
|
||||
pa_tagstruct_get_proplist(t, pl) < 0 ||
|
||||
!pa_tagstruct_eof(t) || !event) {
|
||||
pa_context_fail(c, PA_ERR_PROTOCOL);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_EVENT ? c->playback_streams : c->record_streams, channel)))
|
||||
goto finish;
|
||||
|
||||
if (s->state != PA_STREAM_READY)
|
||||
goto finish;
|
||||
|
||||
if (s->event_callback)
|
||||
s->event_callback(s, event, pl, s->event_userdata);
|
||||
|
||||
finish:
|
||||
pa_context_unref(c);
|
||||
|
||||
if (pl)
|
||||
pa_proplist_free(pl);
|
||||
}
|
||||
|
||||
void pa_command_request(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_stream *s;
|
||||
pa_context *c = userdata;
|
||||
|
|
@ -1696,6 +1744,17 @@ void pa_stream_set_started_callback(pa_stream *s, pa_stream_notify_cb_t cb, void
|
|||
s->started_userdata = userdata;
|
||||
}
|
||||
|
||||
void pa_stream_set_event_callback(pa_stream *s, pa_stream_event_cb_t cb, void *userdata) {
|
||||
pa_assert(s);
|
||||
pa_assert(PA_REFCNT_VALUE(s) >= 1);
|
||||
|
||||
if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
|
||||
return;
|
||||
|
||||
s->event_callback = cb;
|
||||
s->event_userdata = userdata;
|
||||
}
|
||||
|
||||
void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
|
||||
pa_operation *o = userdata;
|
||||
int success = 1;
|
||||
|
|
|
|||
|
|
@ -324,6 +324,14 @@ typedef void (*pa_stream_request_cb_t)(pa_stream *p, size_t bytes, void *userdat
|
|||
/** A generic notification callback */
|
||||
typedef void (*pa_stream_notify_cb_t)(pa_stream *p, void *userdata);
|
||||
|
||||
/** A callback for asynchronous meta/policy event messages. Well known
|
||||
* event names are PA_STREAM_EVENT_REQUEST_CORK and
|
||||
* PA_STREAM_EVENT_REQUEST_UNCORK. The set of defined events can be
|
||||
* extended at any time. Also, server modules may introduce additional
|
||||
* message types so make sure that your callback function ignores messages
|
||||
* it doesn't know. \since 0.9.15 */
|
||||
typedef void (*pa_stream_event_cb_t)(pa_stream *p, const char *name, pa_proplist *pl, void *userdata);
|
||||
|
||||
/** Create a new, unconnected stream with the specified name and
|
||||
* sample type. It is recommended to use pa_stream_new_with_proplist()
|
||||
* instead and specify some initial properties. */
|
||||
|
|
@ -500,6 +508,10 @@ void pa_stream_set_moved_callback(pa_stream *p, pa_stream_notify_cb_t cb, void *
|
|||
* 0.9.8. \since 0.9.8 */
|
||||
void pa_stream_set_suspended_callback(pa_stream *p, pa_stream_notify_cb_t cb, void *userdata);
|
||||
|
||||
/** Set the callback function that is called whenver a meta/policy
|
||||
* control event is received.\since 0.9.15 */
|
||||
void pa_stream_set_event_callback(pa_stream *p, pa_stream_event_cb_t cb, void *userdata);
|
||||
|
||||
/** Pause (or resume) playback of this stream temporarily. Available on both playback and recording streams. */
|
||||
pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, void *userdata);
|
||||
|
||||
|
|
@ -518,7 +530,7 @@ pa_operation* pa_stream_prebuf(pa_stream *s, pa_stream_success_cb_t cb, void *us
|
|||
* temporarily. Available for playback streams only. */
|
||||
pa_operation* pa_stream_trigger(pa_stream *s, pa_stream_success_cb_t cb, void *userdata);
|
||||
|
||||
/** Rename the stream. */
|
||||
/** Rename the stream.*/
|
||||
pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_success_cb_t cb, void *userdata);
|
||||
|
||||
/** Return the current playback/recording time. This is based on the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue