PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2 of the License,
+ by the Free Software Foundation; either version 2.1 of the License,
or (at your option) any later version.
PulseAudio is distributed in the hope that it will be useful, but
#endif
#include <pulse/context.h>
-#include <pulse/gccmacro.h>
+#include <pulse/fork-detect.h>
+#include <pulse/operation.h>
#include <pulsecore/macro.h>
#include <pulsecore/pstream-util.h>
#include "internal.h"
-
#include "ext-stream-restore.h"
enum {
goto finish;
if (command != PA_COMMAND_REPLY) {
- if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
+ if (pa_context_handle_error(o->context, command, t, false) < 0)
goto finish;
} else if (pa_tagstruct_getu32(t, &version) < 0 ||
pa_assert(c);
pa_assert(PA_REFCNT_VALUE(c) >= 1);
- pa_assert(cb);
+ 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, c->version >= 14, PA_ERR_NOTSUPPORTED);
goto finish;
if (command != PA_COMMAND_REPLY) {
- if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
+ if (pa_context_handle_error(o->context, command, t, false) < 0)
goto finish;
eol = -1;
while (!pa_tagstruct_eof(t)) {
pa_ext_stream_restore_info i;
- pa_bool_t mute = FALSE;
+ bool mute = false;
memset(&i, 0, sizeof(i));
pa_assert(c);
pa_assert(PA_REFCNT_VALUE(c) >= 1);
- pa_assert(cb);
+ 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, c->version >= 14, PA_ERR_NOTSUPPORTED);
pa_update_mode_t mode,
const pa_ext_stream_restore_info data[],
unsigned n,
- pa_bool_t apply_immediately,
+ int apply_immediately,
pa_context_success_cb_t cb,
void *userdata) {
uint32_t tag;
- pa_operation *o;
- pa_tagstruct *t;
+ pa_operation *o = NULL;
+ pa_tagstruct *t = NULL;
pa_assert(c);
pa_assert(PA_REFCNT_VALUE(c) >= 1);
pa_assert(mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE || mode == PA_UPDATE_SET);
pa_assert(data);
- pa_assert(cb);
+ 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, c->version >= 14, PA_ERR_NOTSUPPORTED);
pa_tagstruct_put_boolean(t, apply_immediately);
for (; n > 0; n--, data++) {
+ if (!data->name || !*data->name)
+ goto fail;
+
pa_tagstruct_puts(t, data->name);
+
+ if (data->volume.channels > 0 &&
+ !pa_cvolume_compatible_with_channel_map(&data->volume, &data->channel_map))
+ goto fail;
+
pa_tagstruct_put_channel_map(t, &data->channel_map);
pa_tagstruct_put_cvolume(t, &data->volume);
pa_tagstruct_puts(t, data->device);
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;
+
+fail:
+ pa_operation_cancel(o);
+ pa_operation_unref(o);
+
+ pa_tagstruct_free(t);
+
+ pa_context_set_error(c, PA_ERR_INVALID);
+ return NULL;
}
pa_operation *pa_ext_stream_restore_delete(
void *userdata) {
uint32_t tag;
- pa_operation *o;
- pa_tagstruct *t;
+ pa_operation *o = NULL;
+ pa_tagstruct *t = NULL;
const char *const *k;
pa_assert(c);
pa_assert(PA_REFCNT_VALUE(c) >= 1);
pa_assert(s);
- pa_assert(cb);
+ 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, c->version >= 14, PA_ERR_NOTSUPPORTED);
pa_tagstruct_puts(t, "module-stream-restore");
pa_tagstruct_putu32(t, SUBCOMMAND_DELETE);
- for (k = s; *k; k++)
+ for (k = s; *k; k++) {
+ if (!*k || !**k)
+ goto fail;
+
pa_tagstruct_puts(t, *k);
+ }
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;
+
+fail:
+ pa_operation_cancel(o);
+ pa_operation_unref(o);
+
+ pa_tagstruct_free(t);
+
+ pa_context_set_error(c, PA_ERR_INVALID);
+ return NULL;
}
pa_operation *pa_ext_stream_restore_subscribe(
pa_assert(c);
pa_assert(PA_REFCNT_VALUE(c) >= 1);
- pa_assert(cb);
+ 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, c->version >= 14, PA_ERR_NOTSUPPORTED);
pa_assert(c);
pa_assert(PA_REFCNT_VALUE(c) >= 1);
+ if (pa_detect_fork())
+ return;
+
c->ext_stream_restore.callback = cb;
c->ext_stream_restore.userdata = userdata;
}
if (c->ext_stream_restore.callback)
c->ext_stream_restore.callback(c, c->ext_stream_restore.userdata);
-
}