[pulseaudio-commits] [SCM] PulseAudio Sound Server branch, master, updated. v0.9.11-48-g0cc674d
Lennart Poettering
gitmailer-noreply at 0pointer.de
Mon Aug 4 10:02:41 PDT 2008
This is an automated email from the git hooks/post-receive script. It was
generated because of a push to the "PulseAudio Sound Server" repository.
The master branch has been updated
from 5f69b5d7fd84fbbd2db84178985db3ada11b683f (commit)
- Log -----------------------------------------------------------------
0cc674d... wrap protocol extension of module-stream-restore
88c3db6... add protocol extension to module-stream-restore
6cc3a61... store channel map in database and remap volumes if necessary
eec623a... add hooks for connection creation/deletion, for that export pa_native_connection
c01f0bc... split out save trigger function
32cf9db... store channel map in database and remap volumes if ncessary
5880516... add new API function pa_cvolume_remap()
cd5afb8... don't hit an assert if when process_rewind() is called with nbytes=0
-----------------------------------------------------------------------
Summary of changes:
src/Makefile.am | 6 +-
src/modules/module-device-restore.c | 54 +++--
src/modules/module-stream-restore.c | 365 ++++++++++++++++++++++++++++--
src/modules/module-x11-publish.c | 2 +-
src/pulse/context.c | 37 +++-
src/pulse/ext-stream-restore.c | 331 +++++++++++++++++++++++++++
src/pulse/ext-stream-restore.h | 86 +++++++
src/pulse/internal.h | 9 +
src/pulse/subscribe.c | 1 -
src/pulse/volume.c | 85 +++++++
src/pulse/volume.h | 4 +
src/pulsecore/play-memblockq.c | 1 -
src/pulsecore/protocol-native.c | 429 ++++++++++++++++++----------------
src/pulsecore/protocol-native.h | 23 ++-
src/pulsecore/sound-file-stream.c | 3 -
15 files changed, 1185 insertions(+), 251 deletions(-)
create mode 100644 src/pulse/ext-stream-restore.c
create mode 100644 src/pulse/ext-stream-restore.h
-----------------------------------------------------------------------
commit cd5afb80f791f10d82519aed6f9e4ffabea1b5c9
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Aug 4 15:33:41 2008 +0200
don't hit an assert if when process_rewind() is called with nbytes=0
diff --git a/src/pulsecore/play-memblockq.c b/src/pulsecore/play-memblockq.c
index 8b3e79b..86edfe9 100644
--- a/src/pulsecore/play-memblockq.c
+++ b/src/pulsecore/play-memblockq.c
@@ -146,7 +146,6 @@ static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
memblockq_stream *u;
pa_sink_input_assert_ref(i);
- pa_assert(nbytes > 0);
u = MEMBLOCKQ_STREAM(i->userdata);
memblockq_stream_assert_ref(u);
diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index 8eedf83..8b2a29b 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -206,12 +206,9 @@ static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
file_stream *u;
pa_sink_input_assert_ref(i);
- pa_assert(nbytes > 0);
u = FILE_STREAM(i->userdata);
file_stream_assert_ref(u);
- pa_log("backwards %lu", (unsigned long) nbytes);
-
if (!u->memblockq)
return;
commit 5880516076843edb60c96ea622f966ca2fb4e9e6
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Aug 4 18:40:53 2008 +0200
add new API function pa_cvolume_remap()
diff --git a/src/pulse/volume.c b/src/pulse/volume.c
index 70d6f86..625eb19 100644
--- a/src/pulse/volume.c
+++ b/src/pulse/volume.c
@@ -176,3 +176,88 @@ int pa_cvolume_valid(const pa_cvolume *v) {
return 1;
}
+
+static pa_bool_t on_left(pa_channel_position_t p) {
+
+ return
+ p == PA_CHANNEL_POSITION_FRONT_LEFT ||
+ p == PA_CHANNEL_POSITION_REAR_LEFT ||
+ p == PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER ||
+ p == PA_CHANNEL_POSITION_SIDE_LEFT ||
+ p == PA_CHANNEL_POSITION_TOP_FRONT_LEFT ||
+ p == PA_CHANNEL_POSITION_TOP_REAR_LEFT;
+}
+
+static pa_bool_t on_right(pa_channel_position_t p) {
+
+ return
+ p == PA_CHANNEL_POSITION_FRONT_RIGHT ||
+ p == PA_CHANNEL_POSITION_REAR_RIGHT ||
+ p == PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER ||
+ p == PA_CHANNEL_POSITION_SIDE_RIGHT ||
+ p == PA_CHANNEL_POSITION_TOP_FRONT_RIGHT ||
+ p == PA_CHANNEL_POSITION_TOP_REAR_RIGHT;
+}
+
+static pa_bool_t on_center(pa_channel_position_t p) {
+
+ return
+ p == PA_CHANNEL_POSITION_FRONT_CENTER ||
+ p == PA_CHANNEL_POSITION_REAR_CENTER ||
+ p == PA_CHANNEL_POSITION_TOP_CENTER ||
+ p == PA_CHANNEL_POSITION_TOP_FRONT_CENTER ||
+ p == PA_CHANNEL_POSITION_TOP_REAR_CENTER;
+}
+
+static pa_bool_t on_lfe(pa_channel_position_t p) {
+ return
+ p == PA_CHANNEL_POSITION_LFE;
+}
+
+pa_cvolume *pa_cvolume_remap(pa_cvolume *v, pa_channel_map *from, pa_channel_map *to) {
+ int a, b;
+ pa_cvolume result;
+
+ pa_assert(v);
+ pa_assert(from);
+ pa_assert(to);
+ pa_assert(v->channels == from->channels);
+
+ if (pa_channel_map_equal(from, to))
+ return v;
+
+ result.channels = to->channels;
+
+ for (b = 0; b < to->channels; b++) {
+ pa_volume_t k = 0;
+ int n = 0;
+
+ for (a = 0; a < from->channels; a++)
+ if (from->map[a] == to->map[b]) {
+ k += v->values[a];
+ n ++;
+ }
+
+ if (n <= 0) {
+ for (a = 0; a < from->channels; a++)
+ if ((on_left(from->map[a]) && on_left(to->map[b])) ||
+ (on_right(from->map[a]) && on_right(to->map[b])) ||
+ (on_center(from->map[a]) && on_center(to->map[b])) ||
+ (on_lfe(from->map[a]) && on_lfe(to->map[b]))) {
+
+ k += v->values[a];
+ n ++;
+ }
+ }
+
+ if (n <= 0)
+ k = pa_cvolume_avg(v);
+ else
+ k /= n;
+
+ result.values[b] = k;
+ }
+
+ *v = result;
+ return v;
+}
diff --git a/src/pulse/volume.h b/src/pulse/volume.h
index 3befb1d..4fdbf65 100644
--- a/src/pulse/volume.h
+++ b/src/pulse/volume.h
@@ -28,6 +28,7 @@
#include <pulse/cdecl.h>
#include <pulse/gccmacro.h>
#include <pulse/sample.h>
+#include <pulse/channelmap.h>
/** \page volume Volume Control
*
@@ -170,6 +171,9 @@ double pa_sw_volume_to_linear(pa_volume_t v) PA_GCC_CONST;
#define PA_DECIBEL_MININFTY ((double) -200.0)
#endif
+/** Remap a volume from one channel mapping to a different channel mapping. \since 0.9.12 */
+pa_cvolume *pa_cvolume_remap(pa_cvolume *v, pa_channel_map *from, pa_channel_map *to);
+
PA_C_DECL_END
#endif
commit 32cf9db43475b33fd43f28897e4fa9ca149aba2c
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Aug 4 18:55:50 2008 +0200
store channel map in database and remap volumes if ncessary
diff --git a/src/modules/module-device-restore.c b/src/modules/module-device-restore.c
index c0d2ddb..d93b9e6 100644
--- a/src/modules/module-device-restore.c
+++ b/src/modules/module-device-restore.c
@@ -1,7 +1,7 @@
/***
This file is part of PulseAudio.
- Copyright 2006 Lennart Poettering
+ Copyright 2006-2008 Lennart Poettering
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
@@ -64,6 +64,7 @@ static const char* const valid_modargs[] = {
struct userdata {
pa_core *core;
+ pa_module *module;
pa_subscription *subscription;
pa_hook_slot
*sink_fixate_hook_slot,
@@ -76,6 +77,7 @@ struct userdata {
};
struct entry {
+ pa_channel_map channel_map;
pa_cvolume volume;
pa_bool_t muted:1;
};
@@ -123,6 +125,16 @@ static struct entry* read_entry(struct userdata *u, char *name) {
goto fail;
}
+ if (!(pa_channel_map_valid(&e->channel_map))) {
+ pa_log_warn("Invalid channel map stored in database for device %s", name);
+ goto fail;
+ }
+
+ if (e->volume.channels != e->channel_map.channels) {
+ pa_log_warn("Volume and channel map don't match in database entry for device %s", name);
+ goto fail;
+ }
+
return e;
fail:
@@ -153,6 +165,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
return;
name = pa_sprintf_malloc("sink:%s", sink->name);
+ entry.channel_map = sink->channel_map;
entry.volume = *pa_sink_get_volume(sink);
entry.muted = pa_sink_get_mute(sink);
@@ -165,13 +178,14 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
return;
name = pa_sprintf_malloc("source:%s", source->name);
+ entry.channel_map = source->channel_map;
entry.volume = *pa_source_get_volume(source);
entry.muted = pa_source_get_mute(source);
}
if ((old = read_entry(u, name))) {
- if (pa_cvolume_equal(&old->volume, &entry.volume) &&
+ if (pa_cvolume_equal(pa_cvolume_remap(&old->volume, &old->channel_map, &entry.channel_map), &entry.volume) &&
!old->muted == !entry.muted) {
pa_xfree(old);
@@ -212,11 +226,9 @@ static pa_hook_result_t sink_fixate_hook_callback(pa_core *c, pa_sink_new_data *
if ((e = read_entry(u, name))) {
- if (u->restore_volume &&
- e->volume.channels == new_data->sample_spec.channels) {
-
+ if (u->restore_volume) {
pa_log_info("Restoring volume for sink %s.", new_data->name);
- pa_sink_new_data_set_volume(new_data, &e->volume);
+ pa_sink_new_data_set_volume(new_data, pa_cvolume_remap(&e->volume, &e->channel_map, &new_data->channel_map));
}
if (u->restore_muted) {
@@ -242,11 +254,9 @@ static pa_hook_result_t source_fixate_hook_callback(pa_core *c, pa_source_new_da
if ((e = read_entry(u, name))) {
- if (u->restore_volume &&
- e->volume.channels == new_data->sample_spec.channels) {
-
+ if (u->restore_volume) {
pa_log_info("Restoring volume for source %s.", new_data->name);
- pa_source_new_data_set_volume(new_data, &e->volume);
+ pa_source_new_data_set_volume(new_data, pa_cvolume_remap(&e->volume, &e->channel_map, &new_data->channel_map));
}
if (u->restore_muted) {
@@ -290,9 +300,11 @@ int pa__init(pa_module*m) {
m->userdata = u = pa_xnew(struct userdata, 1);
u->core = m->core;
+ u->module = m;
u->save_time_event = NULL;
u->restore_volume = restore_volume;
u->restore_muted = restore_muted;
+ u->gdbm_file = NULL;
u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK|PA_SUBSCRIPTION_MASK_SOURCE, subscribe_callback, u);
commit c01f0bc01ff1c4bdd3cbb66ae79e45c73add5011
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Aug 4 18:56:12 2008 +0200
split out save trigger function
diff --git a/src/modules/module-device-restore.c b/src/modules/module-device-restore.c
index d93b9e6..fcd4021 100644
--- a/src/modules/module-device-restore.c
+++ b/src/modules/module-device-restore.c
@@ -143,6 +143,17 @@ fail:
return NULL;
}
+static void trigger_save(struct userdata *u) {
+ struct timeval tv;
+
+ if (u->save_time_event)
+ return;
+
+ pa_gettimeofday(&tv);
+ tv.tv_sec += SAVE_INTERVAL;
+ u->save_time_event = u->core->mainloop->time_new(u->core->mainloop, &tv, save_time_callback, u);
+}
+
static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
struct userdata *u = userdata;
struct entry entry, *old;
@@ -158,6 +169,8 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
t != (PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE))
return;
+ memset(&entry, 0, sizeof(entry));
+
if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK) {
pa_sink *sink;
@@ -206,14 +219,9 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
gdbm_store(u->gdbm_file, key, data, GDBM_REPLACE);
- if (!u->save_time_event) {
- struct timeval tv;
- pa_gettimeofday(&tv);
- tv.tv_sec += SAVE_INTERVAL;
- u->save_time_event = u->core->mainloop->time_new(u->core->mainloop, &tv, save_time_callback, u);
- }
-
pa_xfree(name);
+
+ trigger_save(u);
}
static pa_hook_result_t sink_fixate_hook_callback(pa_core *c, pa_sink_new_data *new_data, struct userdata *u) {
commit eec623a23b6c30508d8bb4ecbdd1fff7c715a3f8
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Aug 4 18:58:29 2008 +0200
add hooks for connection creation/deletion, for that export pa_native_connection
diff --git a/src/modules/module-x11-publish.c b/src/modules/module-x11-publish.c
index c29535e..1dbc939 100644
--- a/src/modules/module-x11-publish.c
+++ b/src/modules/module-x11-publish.c
@@ -152,7 +152,7 @@ int pa__init(pa_module*m) {
u->x11_client = NULL;
u->x11_wrapper = NULL;
- u->hook_slot = pa_hook_connect(pa_native_protocol_servers_changed(u->protocol), PA_HOOK_NORMAL, servers_changed_cb, u);
+ u->hook_slot = pa_hook_connect(&pa_native_protocol_hooks(u->protocol)[PA_NATIVE_HOOK_SERVERS_CHANGED], PA_HOOK_NORMAL, servers_changed_cb, u);
if (!(u->auth_cookie = pa_auth_cookie_get(m->core, pa_modargs_get_value(ma, "cookie", PA_NATIVE_COOKIE_FILE), PA_NATIVE_COOKIE_LENGTH)))
goto fail;
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index ef56a6f..0eac3c2 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -73,13 +73,12 @@
#define DEFAULT_PROCESS_MSEC 20 /* 20ms */
#define DEFAULT_FRAGSIZE_MSEC DEFAULT_TLENGTH_MSEC
-typedef struct connection connection;
struct pa_native_protocol;
typedef struct record_stream {
pa_msgobject parent;
- connection *connection;
+ pa_native_connection *connection;
uint32_t index;
pa_source_output *source_output;
@@ -103,7 +102,7 @@ static PA_DEFINE_CHECK_TYPE(output_stream, pa_msgobject);
typedef struct playback_stream {
output_stream parent;
- connection *connection;
+ pa_native_connection *connection;
uint32_t index;
pa_sink_input *sink_input;
@@ -129,7 +128,7 @@ static PA_DEFINE_CHECK_TYPE(playback_stream, output_stream);
typedef struct upload_stream {
output_stream parent;
- connection *connection;
+ pa_native_connection *connection;
uint32_t index;
pa_memchunk memchunk;
@@ -144,7 +143,7 @@ PA_DECLARE_CLASS(upload_stream);
#define UPLOAD_STREAM(o) (upload_stream_cast(o))
static PA_DEFINE_CHECK_TYPE(upload_stream, output_stream);
-struct connection {
+struct pa_native_connection {
pa_msgobject parent;
pa_native_protocol *protocol;
pa_native_options *options;
@@ -160,9 +159,9 @@ struct connection {
pa_time_event *auth_timeout_event;
};
-PA_DECLARE_CLASS(connection);
-#define CONNECTION(o) (connection_cast(o))
-static PA_DEFINE_CHECK_TYPE(connection, pa_msgobject);
+PA_DECLARE_CLASS(pa_native_connection);
+#define PA_NATIVE_CONNECTION(o) (pa_native_connection_cast(o))
+static PA_DEFINE_CHECK_TYPE(pa_native_connection, pa_msgobject);
struct pa_native_protocol {
PA_REFCNT_DECLARE;
@@ -171,10 +170,9 @@ struct pa_native_protocol {
pa_idxset *connections;
pa_strlist *servers;
- pa_hook servers_changed;
+ pa_hook hooks[PA_NATIVE_HOOK_MAX];
pa_hashmap *extensions;
-
};
enum {
@@ -212,8 +210,8 @@ static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes);
static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes);
static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes);
-static void send_memblock(connection *c);
-static void request_bytes(struct playback_stream*s);
+static void native_connection_send_memblock(pa_native_connection *c);
+static void playback_stream_request_bytes(struct playback_stream*s);
static void source_output_kill_cb(pa_source_output *o);
static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk);
@@ -389,7 +387,7 @@ static void upload_stream_free(pa_object *o) {
}
static upload_stream* upload_stream_new(
- connection *c,
+ pa_native_connection *c,
const pa_sample_spec *ss,
const pa_channel_map *map,
const char *name,
@@ -464,7 +462,7 @@ static int record_stream_process_msg(pa_msgobject *o, int code, void*userdata, i
}
if (!pa_pstream_is_pending(s->connection->pstream))
- send_memblock(s->connection);
+ native_connection_send_memblock(s->connection);
break;
}
@@ -531,7 +529,7 @@ static void fix_record_buffer_attr_post(record_stream *s, uint32_t *maxlength, u
}
static record_stream* record_stream_new(
- connection *c,
+ pa_native_connection *c,
pa_source *source,
pa_sample_spec *ss,
pa_channel_map *map,
@@ -615,6 +613,17 @@ static record_stream* record_stream_new(
return s;
}
+static void record_stream_send_killed(record_stream *r) {
+ pa_tagstruct *t;
+ record_stream_assert_ref(r);
+
+ t = pa_tagstruct_new(NULL, 0);
+ pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_KILLED);
+ pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
+ pa_tagstruct_putu32(t, r->index);
+ pa_pstream_send_tagstruct(r->connection->pstream, t);
+}
+
static void playback_stream_unlink(playback_stream *s) {
pa_assert(s);
@@ -846,7 +855,7 @@ static void fix_playback_buffer_attr_post(playback_stream *s, uint32_t *maxlengt
}
static playback_stream* playback_stream_new(
- connection *c,
+ pa_native_connection *c,
pa_sink *sink,
pa_sample_spec *ss,
pa_channel_map *map,
@@ -974,9 +983,42 @@ static playback_stream* playback_stream_new(
return s;
}
-static int connection_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
- connection *c = CONNECTION(o);
- connection_assert_ref(c);
+
+/* Called from thread context */
+static void playback_stream_request_bytes(playback_stream *s) {
+ size_t m, previous_missing;
+
+ playback_stream_assert_ref(s);
+
+ m = pa_memblockq_pop_missing(s->memblockq);
+
+ if (m <= 0)
+ return;
+
+/* pa_log("request_bytes(%lu)", (unsigned long) m); */
+
+ previous_missing = pa_atomic_add(&s->missing, m);
+
+ if (pa_memblockq_prebuf_active(s->memblockq) ||
+ (previous_missing < s->minreq && previous_missing+m >= s->minreq))
+ pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
+}
+
+
+static void playback_stream_send_killed(playback_stream *p) {
+ pa_tagstruct *t;
+ playback_stream_assert_ref(p);
+
+ t = pa_tagstruct_new(NULL, 0);
+ pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_KILLED);
+ pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
+ pa_tagstruct_putu32(t, p->index);
+ pa_pstream_send_tagstruct(p->connection->pstream, t);
+}
+
+static int native_connection_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
+ pa_native_connection *c = PA_NATIVE_CONNECTION(o);
+ pa_native_connection_assert_ref(c);
if (!c->protocol)
return -1;
@@ -995,7 +1037,7 @@ static int connection_process_msg(pa_msgobject *o, int code, void*userdata, int6
return 0;
}
-static void connection_unlink(connection *c) {
+static void native_connection_unlink(pa_native_connection *c) {
record_stream *r;
output_stream *o;
@@ -1004,6 +1046,8 @@ static void connection_unlink(connection *c) {
if (!c->protocol)
return;
+ pa_hook_fire(&c->protocol->hooks[PA_NATIVE_HOOK_CONNECTION_UNLINK], c);
+
if (c->options)
pa_native_options_unref(c->options);
@@ -1029,15 +1073,15 @@ static void connection_unlink(connection *c) {
pa_assert_se(pa_idxset_remove_by_data(c->protocol->connections, c, NULL) == c);
c->protocol = NULL;
- connection_unref(c);
+ pa_native_connection_unref(c);
}
-static void connection_free(pa_object *o) {
- connection *c = CONNECTION(o);
+static void native_connection_free(pa_object *o) {
+ pa_native_connection *c = PA_NATIVE_CONNECTION(o);
pa_assert(c);
- connection_unlink(c);
+ native_connection_unlink(c);
pa_idxset_free(c->record_streams, NULL, NULL);
pa_idxset_free(c->output_streams, NULL, NULL);
@@ -1049,27 +1093,7 @@ static void connection_free(pa_object *o) {
pa_xfree(c);
}
-/* Called from thread context */
-static void request_bytes(playback_stream *s) {
- size_t m, previous_missing;
-
- playback_stream_assert_ref(s);
-
- m = pa_memblockq_pop_missing(s->memblockq);
-
- if (m <= 0)
- return;
-
-/* pa_log("request_bytes(%lu)", (unsigned long) m); */
-
- previous_missing = pa_atomic_add(&s->missing, m);
-
- if (pa_memblockq_prebuf_active(s->memblockq) ||
- (previous_missing < s->minreq && previous_missing+m >= s->minreq))
- pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
-}
-
-static void send_memblock(connection *c) {
+static void native_connection_send_memblock(pa_native_connection *c) {
uint32_t start;
record_stream *r;
@@ -1101,28 +1125,6 @@ static void send_memblock(connection *c) {
}
}
-static void send_playback_stream_killed(playback_stream *p) {
- pa_tagstruct *t;
- playback_stream_assert_ref(p);
-
- t = pa_tagstruct_new(NULL, 0);
- pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_KILLED);
- pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
- pa_tagstruct_putu32(t, p->index);
- pa_pstream_send_tagstruct(p->connection->pstream, t);
-}
-
-static void send_record_stream_killed(record_stream *r) {
- pa_tagstruct *t;
- record_stream_assert_ref(r);
-
- t = pa_tagstruct_new(NULL, 0);
- pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_KILLED);
- pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
- pa_tagstruct_putu32(t, r->index);
- pa_pstream_send_tagstruct(r->connection->pstream, t);
-}
-
/*** sink input callbacks ***/
static void handle_seek(playback_stream *s, int64_t indexw) {
@@ -1159,7 +1161,7 @@ static void handle_seek(playback_stream *s, int64_t indexw) {
}
}
- request_bytes(s);
+ playback_stream_request_bytes(s);
}
/* Called from thread context */
@@ -1321,7 +1323,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
s->is_underrun = TRUE;
- request_bytes(s);
+ playback_stream_request_bytes(s);
}
/* This call will not fail with prebuf=0, hence we check for
@@ -1335,7 +1337,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_STARTED, NULL, 0, NULL, NULL);
pa_memblockq_drop(s->memblockq, chunk->length);
- request_bytes(s);
+ playback_stream_request_bytes(s);
return 0;
}
@@ -1386,7 +1388,7 @@ static void sink_input_kill_cb(pa_sink_input *i) {
s = PLAYBACK_STREAM(i->userdata);
playback_stream_assert_ref(s);
- send_playback_stream_killed(s);
+ playback_stream_send_killed(s);
playback_stream_unlink(s);
}
@@ -1475,7 +1477,7 @@ static void source_output_kill_cb(pa_source_output *o) {
s = RECORD_STREAM(o->userdata);
record_stream_assert_ref(s);
- send_record_stream_killed(s);
+ record_stream_send_killed(s);
record_stream_unlink(s);
}
@@ -1550,9 +1552,9 @@ static void source_output_moved_cb(pa_source_output *o) {
/*** pdispatch callbacks ***/
-static void protocol_error(connection *c) {
+static void protocol_error(pa_native_connection *c) {
pa_log("protocol error, kicking client");
- connection_unlink(c);
+ native_connection_unlink(c);
}
#define CHECK_VALIDITY(pstream, expression, tag, error) do { \
@@ -1572,7 +1574,7 @@ static pa_tagstruct *reply_new(uint32_t tag) {
}
static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
playback_stream *s;
uint32_t maxlength, tlength, prebuf, minreq, sink_index, syncid, missing;
const char *name = NULL, *sink_name;
@@ -1596,7 +1598,7 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
pa_sink_input_flags_t flags = 0;
pa_proplist *p;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if ((c->version < 13 && (pa_tagstruct_gets(t, &name) < 0 || !name)) ||
@@ -1735,10 +1737,10 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
}
static void command_delete_stream(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
uint32_t channel;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_getu32(t, &channel) < 0 ||
@@ -1793,7 +1795,7 @@ static void command_delete_stream(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma
}
static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
record_stream *s;
uint32_t maxlength, fragment_size;
uint32_t source_index;
@@ -1818,7 +1820,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
uint32_t direct_on_input_idx = PA_INVALID_INDEX;
pa_sink_input *direct_on_input = NULL;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if ((c->version < 13 && (pa_tagstruct_gets(t, &name) < 0 || !name)) ||
@@ -1953,9 +1955,9 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
}
static void command_exit(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (!pa_tagstruct_eof(t)) {
@@ -1970,12 +1972,12 @@ static void command_exit(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t
}
static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
const void*cookie;
pa_tagstruct *reply;
pa_bool_t shm_on_remote, do_shm;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_getu32(t, &c->version) < 0 ||
@@ -1992,7 +1994,7 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t
}
/* Starting with protocol version 13 the MSB of the version tag
- reflects if shm is available for this connection or
+ reflects if shm is available for this pa_native_connection or
not. */
if (c->version >= 13) {
shm_on_remote = !!(c->version & 0x80000000U);
@@ -2101,12 +2103,12 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t
}
static void command_set_client_name(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
const char *name = NULL;
pa_proplist *p;
pa_tagstruct *reply;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
p = pa_proplist_new();
@@ -2141,11 +2143,11 @@ static void command_set_client_name(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE
}
static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
const char *name;
uint32_t idx = PA_IDXSET_INVALID;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_gets(t, &name) < 0 ||
@@ -2179,11 +2181,11 @@ static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uin
}
static void command_drain_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
uint32_t idx;
playback_stream *s;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_getu32(t, &idx) < 0 ||
@@ -2201,11 +2203,11 @@ static void command_drain_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC
}
static void command_stat(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
pa_tagstruct *reply;
const pa_mempool_stat *stat;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (!pa_tagstruct_eof(t)) {
@@ -2227,14 +2229,14 @@ static void command_stat(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t
}
static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
pa_tagstruct *reply;
playback_stream *s;
struct timeval tv, now;
uint32_t idx;
pa_usec_t latency;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_getu32(t, &idx) < 0 ||
@@ -2273,13 +2275,13 @@ static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
}
static void command_get_record_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
pa_tagstruct *reply;
record_stream *s;
struct timeval tv, now;
uint32_t idx;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_getu32(t, &idx) < 0 ||
@@ -2305,7 +2307,7 @@ static void command_get_record_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UN
}
static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
upload_stream *s;
uint32_t length;
const char *name = NULL;
@@ -2314,7 +2316,7 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
pa_tagstruct *reply;
pa_proplist *p;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_gets(t, &name) < 0 ||
@@ -2360,12 +2362,12 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
}
static void command_finish_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
uint32_t channel;
upload_stream *s;
uint32_t idx;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_getu32(t, &channel) < 0 ||
@@ -2389,7 +2391,7 @@ static void command_finish_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
}
static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
uint32_t sink_index;
pa_volume_t volume;
pa_sink *sink;
@@ -2398,7 +2400,7 @@ static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui
pa_proplist *p;
pa_tagstruct *reply;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
@@ -2447,10 +2449,10 @@ static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui
}
static void command_remove_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
const char *name;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_gets(t, &name) < 0 ||
@@ -2470,7 +2472,7 @@ static void command_remove_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED
pa_pstream_send_simple_ack(c->pstream, tag);
}
-static void fixup_sample_spec(connection *c, pa_sample_spec *fixed, const pa_sample_spec *original) {
+static void fixup_sample_spec(pa_native_connection *c, pa_sample_spec *fixed, const pa_sample_spec *original) {
pa_assert(c);
pa_assert(fixed);
pa_assert(original);
@@ -2488,7 +2490,7 @@ static void fixup_sample_spec(connection *c, pa_sample_spec *fixed, const pa_sam
}
}
-static void sink_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink *sink) {
+static void sink_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sink *sink) {
pa_sample_spec fixed_ss;
pa_assert(t);
@@ -2519,7 +2521,7 @@ static void sink_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink *sink) {
}
}
-static void source_fill_tagstruct(connection *c, pa_tagstruct *t, pa_source *source) {
+static void source_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_source *source) {
pa_sample_spec fixed_ss;
pa_assert(t);
@@ -2551,7 +2553,7 @@ static void source_fill_tagstruct(connection *c, pa_tagstruct *t, pa_source *sou
}
-static void client_fill_tagstruct(connection *c, pa_tagstruct *t, pa_client *client) {
+static void client_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_client *client) {
pa_assert(t);
pa_assert(client);
@@ -2576,7 +2578,7 @@ static void module_fill_tagstruct(pa_tagstruct *t, pa_module *module) {
pa_tagstruct_put_boolean(t, module->auto_unload);
}
-static void sink_input_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink_input *s) {
+static void sink_input_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sink_input *s) {
pa_sample_spec fixed_ss;
pa_usec_t sink_latency;
@@ -2603,7 +2605,7 @@ static void sink_input_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink_in
pa_tagstruct_put_proplist(t, s->proplist);
}
-static void source_output_fill_tagstruct(connection *c, pa_tagstruct *t, pa_source_output *s) {
+static void source_output_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_source_output *s) {
pa_sample_spec fixed_ss;
pa_usec_t source_latency;
@@ -2628,7 +2630,7 @@ static void source_output_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sour
pa_tagstruct_put_proplist(t, s->proplist);
}
-static void scache_fill_tagstruct(connection *c, pa_tagstruct *t, pa_scache_entry *e) {
+static void scache_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_scache_entry *e) {
pa_sample_spec fixed_ss;
pa_assert(t);
@@ -2654,7 +2656,7 @@ static void scache_fill_tagstruct(connection *c, pa_tagstruct *t, pa_scache_entr
}
static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
uint32_t idx;
pa_sink *sink = NULL;
pa_source *source = NULL;
@@ -2666,7 +2668,7 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u
const char *name;
pa_tagstruct *reply;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_getu32(t, &idx) < 0 ||
@@ -2733,13 +2735,13 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u
}
static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
pa_idxset *i;
uint32_t idx;
void *p;
pa_tagstruct *reply;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (!pa_tagstruct_eof(t)) {
@@ -2793,13 +2795,13 @@ static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma
}
static void command_get_server_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
pa_tagstruct *reply;
char txt[256];
const char *n;
pa_sample_spec fixed_ss;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (!pa_tagstruct_eof(t)) {
@@ -2830,9 +2832,9 @@ static void command_get_server_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE
static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint32_t idx, void *userdata) {
pa_tagstruct *t;
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
t = pa_tagstruct_new(NULL, 0);
pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE_EVENT);
@@ -2843,10 +2845,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint3
}
static void command_subscribe(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
pa_subscription_mask_t m;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_getu32(t, &m) < 0 ||
@@ -2877,7 +2879,7 @@ static void command_set_volume(
pa_tagstruct *t,
void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
uint32_t idx;
pa_cvolume volume;
pa_sink *sink = NULL;
@@ -2885,7 +2887,7 @@ static void command_set_volume(
pa_sink_input *si = NULL;
const char *name = NULL;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_getu32(t, &idx) < 0 ||
@@ -2944,7 +2946,7 @@ static void command_set_mute(
pa_tagstruct *t,
void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
uint32_t idx;
pa_bool_t mute;
pa_sink *sink = NULL;
@@ -2952,7 +2954,7 @@ static void command_set_mute(
pa_sink_input *si = NULL;
const char *name = NULL;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_getu32(t, &idx) < 0 ||
@@ -3007,12 +3009,12 @@ static void command_set_mute(
}
static void command_cork_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
uint32_t idx;
pa_bool_t b;
playback_stream *s;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_getu32(t, &idx) < 0 ||
@@ -3033,11 +3035,11 @@ static void command_cork_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
}
static void command_trigger_or_flush_or_prebuf_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
uint32_t idx;
playback_stream *s;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_getu32(t, &idx) < 0 ||
@@ -3073,12 +3075,12 @@ static void command_trigger_or_flush_or_prebuf_playback_stream(PA_GCC_UNUSED pa_
}
static void command_cork_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
uint32_t idx;
record_stream *s;
pa_bool_t b;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_getu32(t, &idx) < 0 ||
@@ -3098,11 +3100,11 @@ static void command_cork_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UN
}
static void command_flush_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
uint32_t idx;
record_stream *s;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_getu32(t, &idx) < 0 ||
@@ -3120,12 +3122,12 @@ static void command_flush_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_U
}
static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
uint32_t idx;
uint32_t maxlength, tlength, prebuf, minreq, fragsize;
pa_tagstruct *reply;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_getu32(t, &idx) < 0) {
@@ -3207,11 +3209,11 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u
}
static void command_update_stream_sample_rate(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
uint32_t idx;
uint32_t rate;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_getu32(t, &idx) < 0 ||
@@ -3247,12 +3249,12 @@ static void command_update_stream_sample_rate(pa_pdispatch *pd, uint32_t command
}
static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
uint32_t idx;
uint32_t mode;
pa_proplist *p;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
@@ -3312,13 +3314,13 @@ static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t
}
static void command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
uint32_t idx;
unsigned changed = 0;
pa_proplist *p;
pa_strlist *l = NULL;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
@@ -3409,10 +3411,10 @@ static void command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t
}
static void command_set_default_sink_or_source(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
const char *s;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_gets(t, &s) < 0 ||
@@ -3429,11 +3431,11 @@ static void command_set_default_sink_or_source(PA_GCC_UNUSED pa_pdispatch *pd, u
}
static void command_set_stream_name(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
uint32_t idx;
const char *name;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_getu32(t, &idx) < 0 ||
@@ -3469,10 +3471,10 @@ static void command_set_stream_name(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t com
}
static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
uint32_t idx;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_getu32(t, &idx) < 0 ||
@@ -3489,7 +3491,7 @@ static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint3
client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
CHECK_VALIDITY(c->pstream, client, tag, PA_ERR_NOENTITY);
- connection_ref(c);
+ pa_native_connection_ref(c);
pa_client_kill(client);
} else if (command == PA_COMMAND_KILL_SINK_INPUT) {
@@ -3498,7 +3500,7 @@ static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint3
s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
- connection_ref(c);
+ pa_native_connection_ref(c);
pa_sink_input_kill(s);
} else {
pa_source_output *s;
@@ -3508,21 +3510,21 @@ static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint3
s = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
- connection_ref(c);
+ pa_native_connection_ref(c);
pa_source_output_kill(s);
}
pa_pstream_send_simple_ack(c->pstream, tag);
- connection_unref(c);
+ pa_native_connection_unref(c);
}
static void command_load_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
pa_module *m;
const char *name, *argument;
pa_tagstruct *reply;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_gets(t, &name) < 0 ||
@@ -3547,11 +3549,11 @@ static void command_load_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui
}
static void command_unload_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
uint32_t idx;
pa_module *m;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_getu32(t, &idx) < 0 ||
@@ -3569,13 +3571,13 @@ static void command_unload_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED
}
static void command_add_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
const char *name, *module, *argument;
uint32_t type;
uint32_t idx;
pa_tagstruct *reply;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_gets(t, &name) < 0 ||
@@ -3604,12 +3606,12 @@ static void command_add_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED u
}
static void command_remove_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
const char *name = NULL;
uint32_t type, idx = PA_IDXSET_INVALID;
int r;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if ((pa_tagstruct_getu32(t, &idx) < 0 &&
@@ -3645,13 +3647,13 @@ static void autoload_fill_tagstruct(pa_tagstruct *t, const pa_autoload_entry *e)
}
static void command_get_autoload_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
const pa_autoload_entry *a = NULL;
uint32_t type, idx;
const char *name;
pa_tagstruct *reply;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if ((pa_tagstruct_getu32(t, &idx) < 0 &&
@@ -3679,10 +3681,10 @@ static void command_get_autoload_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNU
}
static void command_get_autoload_info_list(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
pa_tagstruct *reply;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (!pa_tagstruct_eof(t)) {
@@ -3706,11 +3708,11 @@ static void command_get_autoload_info_list(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
}
static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
uint32_t idx = PA_INVALID_INDEX, idx_device = PA_INVALID_INDEX;
const char *name = NULL;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_getu32(t, &idx) < 0 ||
@@ -3767,12 +3769,12 @@ static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag
}
static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
uint32_t idx = PA_INVALID_INDEX;
const char *name = NULL;
pa_bool_t b;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_getu32(t, &idx) < 0 ||
@@ -3841,13 +3843,13 @@ static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
}
static void command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
uint32_t idx = PA_INVALID_INDEX;
const char *name = NULL;
pa_module *m;
pa_native_protocol_ext_cb_t cb;
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(t);
if (pa_tagstruct_getu32(t, &idx) < 0 ||
@@ -3873,32 +3875,33 @@ static void command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag,
cb = (pa_native_protocol_ext_cb_t) pa_hashmap_get(c->protocol->extensions, m);
CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOEXTENSION);
- cb(c->protocol, m, c->pstream, tag, t);
+ if (cb(c->protocol, m, c, tag, t) < 0)
+ protocol_error(c);
}
/*** pstream callbacks ***/
static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
pa_assert(p);
pa_assert(packet);
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0) {
pa_log("invalid packet.");
- connection_unlink(c);
+ native_connection_unlink(c);
}
}
static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
output_stream *stream;
pa_assert(p);
pa_assert(chunk);
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
if (!(stream = OUTPUT_STREAM(pa_idxset_get_by_index(c->output_streams, channel)))) {
pa_log("client sent block for invalid stream.");
@@ -3954,22 +3957,22 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o
}
static void pstream_die_callback(pa_pstream *p, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
pa_assert(p);
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
- connection_unlink(c);
- pa_log_info("connection died.");
+ native_connection_unlink(c);
+ pa_log_info("Connection died.");
}
static void pstream_drain_callback(pa_pstream *p, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
pa_assert(p);
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
- send_memblock(c);
+ native_connection_send_memblock(c);
}
static void pstream_revoke_callback(pa_pstream *p, uint32_t block_id, void *userdata) {
@@ -3995,25 +3998,28 @@ static void pstream_release_callback(pa_pstream *p, uint32_t block_id, void *use
static void client_kill_cb(pa_client *c) {
pa_assert(c);
- connection_unlink(CONNECTION(c->userdata));
+ native_connection_unlink(PA_NATIVE_CONNECTION(c->userdata));
+ pa_log_info("Connection killed.");
}
/*** module entry points ***/
static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) {
- connection *c = CONNECTION(userdata);
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
pa_assert(m);
pa_assert(tv);
- connection_assert_ref(c);
+ pa_native_connection_assert_ref(c);
pa_assert(c->auth_timeout_event == e);
- if (!c->authorized)
- connection_unlink(c);
+ if (!c->authorized) {
+ native_connection_unlink(c);
+ pa_log_info("Connection terminated due to authentication timeout.");
+ }
}
void pa_native_protocol_connect(pa_native_protocol *p, pa_iochannel *io, pa_native_options *o) {
- connection *c;
+ pa_native_connection *c;
char cname[256], pname[128];
pa_assert(p);
@@ -4026,9 +4032,9 @@ void pa_native_protocol_connect(pa_native_protocol *p, pa_iochannel *io, pa_nati
return;
}
- c = pa_msgobject_new(connection);
- c->parent.parent.free = connection_free;
- c->parent.process_msg = connection_process_msg;
+ c = pa_msgobject_new(pa_native_connection);
+ c->parent.parent.free = native_connection_free;
+ c->parent.process_msg = native_connection_process_msg;
c->protocol = p;
c->options = pa_native_options_ref(o);
c->authorized = FALSE;
@@ -4087,10 +4093,12 @@ void pa_native_protocol_connect(pa_native_protocol *p, pa_iochannel *io, pa_nati
if (pa_iochannel_creds_supported(io))
pa_iochannel_creds_enable(io);
#endif
+
+ pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_CONNECTION_PUT], c);
}
void pa_native_protocol_disconnect(pa_native_protocol *p, pa_module *m) {
- connection *c;
+ pa_native_connection *c;
void *state = NULL;
pa_assert(p);
@@ -4098,11 +4106,12 @@ void pa_native_protocol_disconnect(pa_native_protocol *p, pa_module *m) {
while ((c = pa_idxset_iterate(p->connections, &state, NULL)))
if (c->options->module == m)
- connection_unlink(c);
+ native_connection_unlink(c);
}
static pa_native_protocol* native_protocol_new(pa_core *c) {
pa_native_protocol *p;
+ pa_native_hook_t h;
pa_assert(c);
@@ -4112,7 +4121,11 @@ static pa_native_protocol* native_protocol_new(pa_core *c) {
p->connections = pa_idxset_new(NULL, NULL);
p->servers = NULL;
- pa_hook_init(&p->servers_changed, p);
+
+ p->extensions = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
+
+ for (h = 0; h < PA_NATIVE_HOOK_MAX; h++)
+ pa_hook_init(&p->hooks[h], p);
pa_assert_se(pa_shared_set(c, "native-protocol", p) >= 0);
@@ -4138,7 +4151,9 @@ pa_native_protocol* pa_native_protocol_ref(pa_native_protocol *p) {
}
void pa_native_protocol_unref(pa_native_protocol *p) {
- connection *c;
+ pa_native_connection *c;
+ pa_native_hook_t h;
+
pa_assert(p);
pa_assert(PA_REFCNT_VALUE(p) >= 1);
@@ -4146,12 +4161,16 @@ void pa_native_protocol_unref(pa_native_protocol *p) {
return;
while ((c = pa_idxset_first(p->connections, NULL)))
- connection_unlink(c);
+ native_connection_unlink(c);
pa_idxset_free(p->connections, NULL, NULL);
pa_strlist_free(p->servers);
- pa_hook_done(&p->servers_changed);
+
+ for (h = 0; h < PA_NATIVE_HOOK_MAX; h++)
+ pa_hook_done(&p->hooks[h]);
+
+ pa_hashmap_free(p->extensions, NULL, NULL);
pa_assert_se(pa_shared_remove(p->core, "native-protocol") >= 0);
@@ -4165,7 +4184,7 @@ void pa_native_protocol_add_server_string(pa_native_protocol *p, const char *nam
p->servers = pa_strlist_prepend(p->servers, name);
- pa_hook_fire(&p->servers_changed, p->servers);
+ pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_SERVERS_CHANGED], p->servers);
}
void pa_native_protocol_remove_server_string(pa_native_protocol *p, const char *name) {
@@ -4175,14 +4194,14 @@ void pa_native_protocol_remove_server_string(pa_native_protocol *p, const char *
p->servers = pa_strlist_remove(p->servers, name);
- pa_hook_fire(&p->servers_changed, p->servers);
+ pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_SERVERS_CHANGED], p->servers);
}
-pa_hook *pa_native_protocol_servers_changed(pa_native_protocol *p) {
+pa_hook *pa_native_protocol_hooks(pa_native_protocol *p) {
pa_assert(p);
pa_assert(PA_REFCNT_VALUE(p) >= 1);
- return &p->servers_changed;
+ return p->hooks;
}
pa_strlist *pa_native_protocol_servers(pa_native_protocol *p) {
@@ -4314,3 +4333,9 @@ int pa_native_options_parse(pa_native_options *o, pa_core *c, pa_modargs *ma) {
return 0;
}
+
+pa_pstream* pa_native_connection_get_pstream(pa_native_connection *c) {
+ pa_native_connection_assert_ref(c);
+
+ return c->pstream;
+}
diff --git a/src/pulsecore/protocol-native.h b/src/pulsecore/protocol-native.h
index b3db305..06731c0 100644
--- a/src/pulsecore/protocol-native.h
+++ b/src/pulsecore/protocol-native.h
@@ -36,6 +36,8 @@
typedef struct pa_native_protocol pa_native_protocol;
+typedef struct pa_native_connection pa_native_connection;
+
typedef struct pa_native_options {
PA_REFCNT_DECLARE;
@@ -48,22 +50,37 @@ typedef struct pa_native_options {
} pa_native_options;
+typedef enum pa_native_hook {
+ PA_NATIVE_HOOK_SERVERS_CHANGED,
+ PA_NATIVE_HOOK_CONNECTION_PUT,
+ PA_NATIVE_HOOK_CONNECTION_UNLINK,
+ PA_NATIVE_HOOK_MAX
+} pa_native_hook_t;
+
pa_native_protocol* pa_native_protocol_get(pa_core *core);
pa_native_protocol* pa_native_protocol_ref(pa_native_protocol *p);
void pa_native_protocol_unref(pa_native_protocol *p);
void pa_native_protocol_connect(pa_native_protocol *p, pa_iochannel *io, pa_native_options *a);
void pa_native_protocol_disconnect(pa_native_protocol *p, pa_module *m);
+pa_hook *pa_native_protocol_hooks(pa_native_protocol *p);
+
void pa_native_protocol_add_server_string(pa_native_protocol *p, const char *name);
void pa_native_protocol_remove_server_string(pa_native_protocol *p, const char *name);
-
-pa_hook *pa_native_protocol_servers_changed(pa_native_protocol *p);
pa_strlist *pa_native_protocol_servers(pa_native_protocol *p);
-typedef void (*pa_native_protocol_ext_cb_t)(pa_native_protocol *p, pa_module *m, pa_pstream *ps, uint32_t tag, pa_tagstruct *t);
+typedef int (*pa_native_protocol_ext_cb_t)(
+ pa_native_protocol *p,
+ pa_module *m,
+ pa_native_connection *c,
+ uint32_t tag,
+ pa_tagstruct *t);
+
int pa_native_protocol_install_ext(pa_native_protocol *p, pa_module *m, pa_native_protocol_ext_cb_t cb);
void pa_native_protocol_remove_ext(pa_native_protocol *p, pa_module *m);
+pa_pstream* pa_native_connection_get_pstream(pa_native_connection *c);
+
pa_native_options* pa_native_options_new(void);
pa_native_options* pa_native_options_ref(pa_native_options *o);
void pa_native_options_unref(pa_native_options *o);
commit 6cc3a615fa4f2c0f53e77d431d77422433cda1f0
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Aug 4 19:00:43 2008 +0200
store channel map in database and remap volumes if necessary
diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c
index 22e2ff6..cac8a9b 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -65,6 +65,7 @@ static const char* const valid_modargs[] = {
struct userdata {
pa_core *core;
+ pa_module *module;
pa_subscription *subscription;
pa_hook_slot
*sink_input_new_hook_slot,
@@ -79,8 +80,9 @@ struct userdata {
};
struct entry {
- pa_cvolume volume;
char device[PA_NAME_MAX];
+ pa_channel_map channel_map;
+ pa_cvolume volume;
pa_bool_t muted:1;
};
@@ -146,7 +148,17 @@ static struct entry* read_entry(struct userdata *u, char *name) {
}
if (!(pa_cvolume_valid(&e->volume))) {
- pa_log_warn("Invalid volume stored in database for device %s", name);
+ pa_log_warn("Invalid volume stored in database for stream %s", name);
+ goto fail;
+ }
+
+ if (!(pa_channel_map_valid(&e->channel_map))) {
+ pa_log_warn("Invalid channel map stored in database for stream %s", name);
+ goto fail;
+ }
+
+ if (e->volume.channels != e->channel_map.channels) {
+ pa_log_warn("Volume and channel map don't match in database entry for stream %s", name);
goto fail;
}
@@ -182,6 +194,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
if (!(name = get_name(sink_input->proplist, "sink-input")))
return;
+ entry.channel_map = sink_input->channel_map;
entry.volume = *pa_sink_input_get_volume(sink_input);
entry.muted = pa_sink_input_get_mute(sink_input);
pa_strlcpy(entry.device, sink_input->sink->name, sizeof(entry.device));
@@ -197,15 +210,16 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
if (!(name = get_name(source_output->proplist, "source-output")))
return;
- memset(&entry.volume, 0, sizeof(entry.volume));
- entry.muted = FALSE;
-
+ /* The following fields are filled in to make the entry valid
+ * according to read_entry(). They are otherwise useless */
+ entry.channel_map = source_output->channel_map;
+ pa_cvolume_reset(&entry.volume, entry.channel_map.channels);
pa_strlcpy(entry.device, source_output->source->name, sizeof(entry.device));
}
if ((old = read_entry(u, name))) {
- if (pa_cvolume_equal(&old->volume, &entry.volume) &&
+ if (pa_cvolume_equal(pa_cvolume_remap(&old->volume, &old->channel_map, &entry.channel_map), &entry.volume) &&
!old->muted == !entry.muted &&
strcmp(old->device, entry.device) == 0) {
@@ -276,11 +290,9 @@ static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_inpu
if ((e = read_entry(u, name))) {
- if (u->restore_volume &&
- e->volume.channels == new_data->sample_spec.channels) {
-
+ if (u->restore_volume) {
pa_log_info("Restoring volume for sink input %s.", name);
- pa_sink_input_new_data_set_volume(new_data, &e->volume);
+ pa_sink_input_new_data_set_volume(new_data, pa_cvolume_remap(&e->volume, &e->channel_map, &new_data->channel_map));
}
if (u->restore_muted) {
@@ -353,6 +365,7 @@ int pa__init(pa_module*m) {
m->userdata = u = pa_xnew(struct userdata, 1);
u->core = m->core;
+ u->module = m;
u->save_time_event = NULL;
u->restore_device = restore_device;
u->restore_volume = restore_volume;
commit 88c3db6636988e39c99220ba4969625b709e97ed
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Aug 4 19:01:13 2008 +0200
add protocol extension to module-stream-restore
diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c
index cac8a9b..ee6fab4 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -46,6 +46,9 @@
#include <pulsecore/sink-input.h>
#include <pulsecore/source-output.h>
#include <pulsecore/namereg.h>
+#include <pulsecore/protocol-native.h>
+#include <pulsecore/pstream.h>
+#include <pulsecore/pstream-util.h>
#include "module-stream-restore-symdef.h"
@@ -70,13 +73,17 @@ struct userdata {
pa_hook_slot
*sink_input_new_hook_slot,
*sink_input_fixate_hook_slot,
- *source_output_new_hook_slot;
+ *source_output_new_hook_slot,
+ *connection_unlink_hook_slot;
pa_time_event *save_time_event;
GDBM_FILE gdbm_file;
pa_bool_t restore_device:1;
pa_bool_t restore_volume:1;
pa_bool_t restore_muted:1;
+
+ pa_native_protocol *protocol;
+ pa_idxset *subscribed;
};
struct entry {
@@ -86,6 +93,16 @@ struct entry {
pa_bool_t muted:1;
};
+
+enum {
+ SUBCOMMAND_TEST,
+ SUBCOMMAND_READ,
+ SUBCOMMAND_WRITE,
+ SUBCOMMAND_DELETE,
+ SUBCOMMAND_SUBSCRIBE,
+ SUBCOMMAND_EVENT
+};
+
static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata) {
struct userdata *u = userdata;
@@ -170,6 +187,32 @@ fail:
return NULL;
}
+static void trigger_save(struct userdata *u) {
+ struct timeval tv;
+ pa_native_connection *c;
+ uint32_t idx;
+
+ for (c = pa_idxset_first(u->subscribed, &idx); c; c = pa_idxset_next(u->subscribed, &idx)) {
+ pa_tagstruct *t;
+
+ t = pa_tagstruct_new(NULL, 0);
+ pa_tagstruct_putu32(t, PA_COMMAND_EXTENSION);
+ pa_tagstruct_putu32(t, 0);
+ pa_tagstruct_putu32(t, u->module->index);
+ pa_tagstruct_puts(t, u->module->name);
+ pa_tagstruct_putu32(t, SUBCOMMAND_EVENT);
+
+ pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), t);
+ }
+
+ if (u->save_time_event)
+ return;
+
+ pa_gettimeofday(&tv);
+ tv.tv_sec += SAVE_INTERVAL;
+ u->save_time_event = u->core->mainloop->time_new(u->core->mainloop, &tv, save_time_callback, u);
+}
+
static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
struct userdata *u = userdata;
struct entry entry, *old;
@@ -185,6 +228,8 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE))
return;
+ memset(&entry, 0, sizeof(entry));
+
if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) {
pa_sink_input *sink_input;
@@ -241,14 +286,9 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
gdbm_store(u->gdbm_file, key, data, GDBM_REPLACE);
- if (!u->save_time_event) {
- struct timeval tv;
- pa_gettimeofday(&tv);
- tv.tv_sec += SAVE_INTERVAL;
- u->save_time_event = u->core->mainloop->time_new(u->core->mainloop, &tv, save_time_callback, u);
- }
-
pa_xfree(name);
+
+ trigger_save(u);
}
static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_new_data *new_data, struct userdata *u) {
@@ -264,7 +304,6 @@ static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_n
pa_sink *s;
if (u->restore_device &&
- e->device[0] &&
(s = pa_namereg_get(c, e->device, PA_NAMEREG_SINK, TRUE))) {
pa_log_info("Restoring device for stream %s.", name);
@@ -321,7 +360,6 @@ static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_ou
pa_source *s;
if (u->restore_device &&
- e->device[0] &&
(s = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE, TRUE))) {
pa_log_info("Restoring device for stream %s.", name);
@@ -336,6 +374,262 @@ static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_ou
return PA_HOOK_OK;
}
+#define EXT_VERSION 1
+
+static void clear_db(struct userdata *u) {
+ datum key;
+
+ pa_assert(u);
+
+ key = gdbm_firstkey(u->gdbm_file);
+ while (key.dptr) {
+ datum next_key;
+ next_key = gdbm_nextkey(u->gdbm_file, key);
+
+ gdbm_delete(u->gdbm_file, key);
+ pa_xfree(key.dptr);
+
+ key = next_key;
+ }
+
+ gdbm_reorganize(u->gdbm_file);
+}
+
+static void apply_entry(struct userdata *u, const char *name, struct entry *e) {
+ pa_sink_input *si;
+ pa_source_output *so;
+ uint32_t idx;
+
+ pa_assert(u);
+ pa_assert(name);
+ pa_assert(e);
+
+ for (si = pa_idxset_first(u->core->sink_inputs, &idx); si; si = pa_idxset_next(u->core->sink_inputs, &idx)) {
+ char *n;
+ pa_sink *s;
+
+ if (!(n = get_name(si->proplist, "sink_input")))
+ continue;
+
+ if (strcmp(name, n)) {
+ pa_xfree(n);
+ continue;
+ }
+
+ if (u->restore_volume) {
+ pa_log_info("Restoring volume for sink input %s.", name);
+ pa_sink_input_set_volume(si, pa_cvolume_remap(&e->volume, &e->channel_map, &si->channel_map));
+ }
+
+ if (u->restore_muted) {
+ pa_log_info("Restoring mute state for sink input %s.", name);
+ pa_sink_input_set_mute(si, e->muted);
+ }
+
+ if (u->restore_device &&
+ (s = pa_namereg_get(u->core, e->device, PA_NAMEREG_SOURCE, TRUE))) {
+
+ pa_log_info("Restoring device for stream %s.", name);
+ pa_sink_input_move_to(si, s);
+ }
+ }
+
+ for (so = pa_idxset_first(u->core->source_outputs, &idx); so; so = pa_idxset_next(u->core->source_outputs, &idx)) {
+ char *n;
+ pa_source *s;
+
+ if (!(n = get_name(so->proplist, "source-output")))
+ continue;
+
+ if (strcmp(name, n)) {
+ pa_xfree(n);
+ continue;
+ }
+
+ if (u->restore_device &&
+ (s = pa_namereg_get(u->core, e->device, PA_NAMEREG_SOURCE, TRUE))) {
+
+ pa_log_info("Restoring device for stream %s.", name);
+ pa_source_output_move_to(so, s);
+ }
+ }
+}
+
+static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connection *c, uint32_t tag, pa_tagstruct *t) {
+ struct userdata *u;
+ uint32_t command;
+ pa_tagstruct *reply;
+
+ pa_assert(p);
+ pa_assert(m);
+ pa_assert(c);
+ pa_assert(t);
+
+ u = m->userdata;
+
+ if (pa_tagstruct_getu32(t, &command) < 0)
+ goto fail;
+
+ reply = pa_tagstruct_new(NULL, 0);
+ pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
+ pa_tagstruct_putu32(reply, tag);
+
+ switch (command) {
+ case SUBCOMMAND_TEST: {
+ if (!pa_tagstruct_eof(t))
+ goto fail;
+
+ pa_tagstruct_putu32(reply, EXT_VERSION);
+ break;
+ }
+
+ case SUBCOMMAND_READ: {
+ datum key;
+
+ if (!pa_tagstruct_eof(t))
+ goto fail;
+
+ key = gdbm_firstkey(u->gdbm_file);
+ while (key.dptr) {
+ datum next_key;
+ struct entry *e;
+ char *name;
+
+ next_key = gdbm_nextkey(u->gdbm_file, key);
+
+ name = pa_xstrndup(key.dptr, key.dsize);
+ pa_xfree(key.dptr);
+
+ if ((e = read_entry(u, name))) {
+ pa_tagstruct_puts(reply, name);
+ pa_tagstruct_put_channel_map(reply, &e->channel_map);
+ pa_tagstruct_put_cvolume(reply, &e->volume);
+ pa_tagstruct_puts(reply, e->device);
+ pa_tagstruct_put_boolean(reply, e->muted);
+
+ pa_xfree(e);
+ }
+
+ pa_xfree(name);
+
+ key = next_key;
+ }
+
+ break;
+ }
+
+ case SUBCOMMAND_WRITE: {
+ uint32_t mode;
+ pa_bool_t apply_immediately;
+
+ if (pa_tagstruct_getu32(t, &mode) < 0 ||
+ pa_tagstruct_get_boolean(t, &apply_immediately) < 0)
+ goto fail;
+
+ if (mode != PA_UPDATE_MERGE &&
+ mode != PA_UPDATE_REPLACE &&
+ mode != PA_UPDATE_SET)
+ goto fail;
+
+ if (mode == PA_UPDATE_SET)
+ clear_db(u);
+
+ while (!pa_tagstruct_eof(t)) {
+ const char *name, *device;
+ pa_bool_t muted;
+ struct entry entry;
+ datum key, data;
+
+ memset(&entry, 0, sizeof(entry));
+
+ if (pa_tagstruct_gets(t, &name) < 0 ||
+ pa_tagstruct_get_channel_map(t, &entry.channel_map) ||
+ pa_tagstruct_get_cvolume(t, &entry.volume) < 0 ||
+ pa_tagstruct_gets(t, &device) < 0 ||
+ pa_tagstruct_get_boolean(t, &muted) < 0)
+ goto fail;
+
+ if (entry.channel_map.channels != entry.volume.channels)
+ goto fail;
+
+ entry.muted = muted;
+ pa_strlcpy(entry.device, device, sizeof(entry.device));
+
+ key.dptr = (void*) name;
+ key.dsize = strlen(name);
+
+ data.dptr = (void*) &entry;
+ data.dsize = sizeof(entry);
+
+ if (gdbm_store(u->gdbm_file, key, data, mode == PA_UPDATE_REPLACE ? GDBM_REPLACE : GDBM_INSERT) == 1)
+ if (apply_immediately)
+ apply_entry(u, name, &entry);
+ }
+
+ trigger_save(u);
+
+ break;
+ }
+
+ case SUBCOMMAND_DELETE:
+
+ while (!pa_tagstruct_eof(t)) {
+ const char *name;
+ datum key;
+
+ if (pa_tagstruct_gets(t, &name) < 0)
+ goto fail;
+
+ key.dptr = (void*) name;
+ key.dsize = strlen(name);
+
+ gdbm_delete(u->gdbm_file, key);
+ }
+
+ trigger_save(u);
+
+ break;
+
+ case SUBCOMMAND_SUBSCRIBE: {
+
+ pa_bool_t enabled;
+
+ if (pa_tagstruct_get_boolean(t, &enabled) < 0 ||
+ !pa_tagstruct_eof(t))
+ goto fail;
+
+ if (enabled)
+ pa_idxset_put(u->subscribed, c, NULL);
+ else
+ pa_idxset_remove_by_data(u->subscribed, c, NULL);
+
+ break;
+ }
+
+ default:
+ goto fail;
+ }
+
+ pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), reply);
+ return 0;
+
+fail:
+
+ if (reply)
+ pa_tagstruct_free(reply);
+
+ return -1;
+}
+
+static pa_hook_result_t connection_unlink_hook_cb(pa_native_protocol *p, pa_native_connection *c, struct userdata *u) {
+ pa_assert(p);
+ pa_assert(c);
+ pa_assert(u);
+
+ pa_idxset_remove_by_data(u->subscribed, c, NULL);
+ return PA_HOOK_OK;
+}
+
int pa__init(pa_module*m) {
pa_modargs *ma = NULL;
struct userdata *u;
@@ -370,6 +664,13 @@ int pa__init(pa_module*m) {
u->restore_device = restore_device;
u->restore_volume = restore_volume;
u->restore_muted = restore_muted;
+ u->gdbm_file = NULL;
+ u->subscribed = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
+
+ u->protocol = pa_native_protocol_get(m->core);
+ pa_native_protocol_install_ext(u->protocol, m, extension_cb);
+
+ u->connection_unlink_hook_slot = pa_hook_connect(&pa_native_protocol_hooks(u->protocol)[PA_NATIVE_HOOK_CONNECTION_UNLINK], PA_HOOK_NORMAL, (pa_hook_cb_t) connection_unlink_hook_cb, u);
u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u);
@@ -436,11 +737,22 @@ void pa__done(pa_module*m) {
if (u->source_output_new_hook_slot)
pa_hook_slot_free(u->source_output_new_hook_slot);
+ if (u->connection_unlink_hook_slot)
+ pa_hook_slot_free(u->connection_unlink_hook_slot);
+
if (u->save_time_event)
u->core->mainloop->time_free(u->save_time_event);
if (u->gdbm_file)
gdbm_close(u->gdbm_file);
+ if (u->protocol) {
+ pa_native_protocol_remove_ext(u->protocol, m);
+ pa_native_protocol_unref(u->protocol);
+ }
+
+ if (u->subscribed)
+ pa_idxset_free(u->subscribed, NULL, NULL);
+
pa_xfree(u);
}
commit 0cc674d96198b26cec81b38c32232e95735e4cca
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Aug 4 19:02:20 2008 +0200
wrap protocol extension of module-stream-restore
diff --git a/src/Makefile.am b/src/Makefile.am
index 55b6fb3..f6828b3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -479,7 +479,8 @@ pulseinclude_HEADERS = \
pulse/volume.h \
pulse/xmalloc.h \
pulse/proplist.h \
- pulse/gccmacro.h
+ pulse/gccmacro.h \
+ pulse/ext-stream-restore.h
if HAVE_AVAHI
pulseinclude_HEADERS += \
@@ -530,7 +531,8 @@ libpulse_la_SOURCES = \
pulse/util.c pulse/util.h \
pulse/volume.c pulse/volume.h \
pulse/xmalloc.c pulse/xmalloc.h \
- pulse/proplist.c pulse/proplist.h
+ pulse/proplist.c pulse/proplist.h \
+ pulse/ext-stream-restore.c pulse/ext-stream-restore.h
# Internal stuff that is shared with libpulsecore
libpulse_la_SOURCES += \
diff --git a/src/pulse/context.c b/src/pulse/context.c
index f56cb24..b20093d 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -82,6 +82,8 @@
#define AUTOSPAWN_LOCK "autospawn.lock"
+void pa_command_extension(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_REQUEST] = pa_command_request,
[PA_COMMAND_OVERFLOW] = pa_command_overflow_or_underflow,
@@ -93,7 +95,8 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
[PA_COMMAND_PLAYBACK_STREAM_SUSPENDED] = pa_command_stream_suspended,
[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_SUBSCRIBE_EVENT] = pa_command_subscribe_event,
+ [PA_COMMAND_EXTENSION] = pa_command_extension
};
static void unlock_autospawn_lock_file(pa_context *c) {
@@ -126,6 +129,9 @@ static void reset_callbacks(pa_context *c) {
c->subscribe_callback = NULL;
c->subscribe_userdata = NULL;
+
+ c->ext_stream_restore.callback = NULL;
+ c->ext_stream_restore.userdata = NULL;
}
pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *name, pa_proplist *p) {
@@ -1230,3 +1236,32 @@ pa_operation *pa_context_proplist_remove(pa_context *c, const char *const keys[]
return o;
}
+
+void pa_command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
+ pa_context *c = userdata;
+ uint32_t idx;
+ const char *name;
+
+ pa_assert(pd);
+ pa_assert(command == PA_COMMAND_EXTENSION);
+ pa_assert(t);
+ pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+ pa_context_ref(c);
+
+ if (pa_tagstruct_getu32(t, &idx) < 0 ||
+ pa_tagstruct_gets(t, &name) < 0 ||
+ !pa_tagstruct_eof(t)) {
+ pa_context_fail(c, PA_ERR_PROTOCOL);
+ goto finish;
+ }
+
+ if (!strcmp(name, "module-stream-restore"))
+ pa_ext_stream_restore_command(c, tag, t);
+ else
+ pa_log("Received message for unknown extension '%s'", name);
+
+finish:
+ pa_context_unref(c);
+}
diff --git a/src/pulse/ext-stream-restore.c b/src/pulse/ext-stream-restore.c
new file mode 100644
index 0000000..d64f79d
--- /dev/null
+++ b/src/pulse/ext-stream-restore.c
@@ -0,0 +1,331 @@
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2008 Lennart Poettering
+
+ 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,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pulse/context.h>
+#include <pulse/gccmacro.h>
+
+#include <pulsecore/macro.h>
+#include <pulsecore/pstream-util.h>
+
+#include "internal.h"
+
+#include "ext-stream-restore.h"
+
+enum {
+ SUBCOMMAND_TEST,
+ SUBCOMMAND_READ,
+ SUBCOMMAND_WRITE,
+ SUBCOMMAND_DELETE,
+ SUBCOMMAND_SUBSCRIBE,
+ SUBCOMMAND_EVENT
+};
+
+static void ext_stream_restore_test_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
+ pa_operation *o = userdata;
+ uint32_t version = PA_INVALID_INDEX;
+
+ pa_assert(pd);
+ pa_assert(o);
+ pa_assert(PA_REFCNT_VALUE(o) >= 1);
+
+ if (!o->context)
+ goto finish;
+
+ if (command != PA_COMMAND_REPLY) {
+ if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
+ goto finish;
+
+ } else if (pa_tagstruct_getu32(t, &version) < 0 ||
+ !pa_tagstruct_eof(t)) {
+
+ pa_context_fail(o->context, PA_ERR_PROTOCOL);
+ goto finish;
+ }
+
+ if (o->callback) {
+ pa_ext_stream_restore_test_cb_t cb = (pa_ext_stream_restore_test_cb_t) o->callback;
+ cb(o->context, version, o->userdata);
+ }
+
+finish:
+ pa_operation_done(o);
+ pa_operation_unref(o);
+}
+
+pa_operation *pa_ext_stream_restore_test(
+ pa_context *c,
+ pa_ext_stream_restore_test_cb_t cb,
+ void *userdata) {
+
+ uint32_t tag;
+ pa_operation *o;
+ pa_tagstruct *t;
+
+ pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) >= 1);
+ pa_assert(cb);
+
+ 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);
+
+ o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+
+ t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
+ pa_tagstruct_putu32(t, PA_INVALID_INDEX);
+ pa_tagstruct_puts(t, "module-stream-restore");
+ pa_tagstruct_putu32(t, SUBCOMMAND_TEST);
+ pa_pstream_send_tagstruct(c->pstream, t);
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, ext_stream_restore_test_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+
+ return o;
+}
+
+static void ext_stream_restore_read_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
+ pa_operation *o = userdata;
+ int eol = 1;
+
+ pa_assert(pd);
+ pa_assert(o);
+ pa_assert(PA_REFCNT_VALUE(o) >= 1);
+
+ if (!o->context)
+ goto finish;
+
+ if (command != PA_COMMAND_REPLY) {
+ if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
+ goto finish;
+
+ eol = -1;
+ } else {
+
+ while (!pa_tagstruct_eof(t)) {
+ pa_ext_stream_restore_info i;
+ pa_bool_t mute = FALSE;
+
+ memset(&i, 0, sizeof(i));
+
+ if (pa_tagstruct_gets(t, &i.name) < 0 ||
+ pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
+ pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
+ pa_tagstruct_gets(t, &i.device) < 0 ||
+ pa_tagstruct_get_boolean(t, &mute) < 0) {
+
+ pa_context_fail(o->context, PA_ERR_PROTOCOL);
+ goto finish;
+ }
+
+ i.mute = (int) mute;
+
+ if (o->callback) {
+ pa_ext_stream_restore_read_cb_t cb = (pa_ext_stream_restore_read_cb_t) o->callback;
+ cb(o->context, &i, 0, o->userdata);
+ }
+ }
+ }
+
+ if (o->callback) {
+ pa_ext_stream_restore_read_cb_t cb = (pa_ext_stream_restore_read_cb_t) o->callback;
+ cb(o->context, NULL, eol, o->userdata);
+ }
+
+finish:
+ pa_operation_done(o);
+ pa_operation_unref(o);
+}
+
+pa_operation *pa_ext_stream_restore_read(
+ pa_context *c,
+ pa_ext_stream_restore_read_cb_t cb,
+ void *userdata) {
+
+ uint32_t tag;
+ pa_operation *o;
+ pa_tagstruct *t;
+
+ pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) >= 1);
+ pa_assert(cb);
+
+ 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);
+
+ o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+
+ t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
+ pa_tagstruct_putu32(t, PA_INVALID_INDEX);
+ pa_tagstruct_puts(t, "module-stream-restore");
+ pa_tagstruct_putu32(t, SUBCOMMAND_READ);
+ pa_pstream_send_tagstruct(c->pstream, t);
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, ext_stream_restore_read_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+
+ return o;
+}
+
+pa_operation *pa_ext_stream_restore_write(
+ pa_context *c,
+ pa_update_mode_t mode,
+ const pa_ext_stream_restore_info data[],
+ unsigned n,
+ pa_bool_t apply_immediately,
+ pa_context_success_cb_t cb,
+ void *userdata) {
+
+ uint32_t tag;
+ pa_operation *o;
+ pa_tagstruct *t;
+
+ 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, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
+ PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
+
+ o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+
+ t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
+ pa_tagstruct_putu32(t, PA_INVALID_INDEX);
+ pa_tagstruct_puts(t, "module-stream-restore");
+ pa_tagstruct_putu32(t, SUBCOMMAND_WRITE);
+
+ pa_tagstruct_putu32(t, mode);
+ pa_tagstruct_put_boolean(t, apply_immediately);
+
+ for (; n > 0; n--, data++) {
+ pa_tagstruct_puts(t, data->name);
+ pa_tagstruct_put_channel_map(t, &data->channel_map);
+ pa_tagstruct_put_cvolume(t, &data->volume);
+ pa_tagstruct_puts(t, data->device);
+ pa_tagstruct_put_boolean(t, data->mute);
+ }
+
+ 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;
+}
+
+pa_operation *pa_ext_stream_restore_delete(
+ pa_context *c,
+ const char *const s[],
+ pa_context_success_cb_t cb,
+ void *userdata) {
+
+ uint32_t tag;
+ pa_operation *o;
+ pa_tagstruct *t;
+ 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, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
+ PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
+
+ o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+
+ t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
+ pa_tagstruct_putu32(t, PA_INVALID_INDEX);
+ pa_tagstruct_puts(t, "module-stream-restore");
+ pa_tagstruct_putu32(t, SUBCOMMAND_DELETE);
+
+ for (k = s; *k; k++)
+ 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;
+}
+
+pa_operation *pa_ext_stream_restore_subscribe(
+ pa_context *c,
+ int enable,
+ pa_context_success_cb_t cb,
+ void *userdata) {
+
+ uint32_t tag;
+ pa_operation *o;
+ pa_tagstruct *t;
+
+ pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) >= 1);
+ pa_assert(cb);
+
+ 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);
+
+ o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+
+ t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
+ pa_tagstruct_putu32(t, PA_INVALID_INDEX);
+ pa_tagstruct_puts(t, "module-stream-restore");
+ pa_tagstruct_putu32(t, SUBCOMMAND_SUBSCRIBE);
+ pa_tagstruct_put_boolean(t, enable);
+ 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;
+}
+
+void pa_ext_stream_restore_set_subscribe_cb(
+ pa_context *c,
+ pa_ext_stream_restore_subscribe_cb_t cb,
+ void *userdata) {
+
+ pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+ c->ext_stream_restore.callback = cb;
+ c->ext_stream_restore.userdata = userdata;
+}
+
+void pa_ext_stream_restore_command(pa_context *c, uint32_t tag, pa_tagstruct *t) {
+ uint32_t subcommand;
+
+ pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) >= 1);
+ pa_assert(t);
+
+ if (pa_tagstruct_getu32(t, &subcommand) < 0 ||
+ !pa_tagstruct_eof(t)) {
+
+ pa_context_fail(c, PA_ERR_PROTOCOL);
+ return;
+ }
+
+ if (subcommand != SUBCOMMAND_EVENT) {
+ pa_context_fail(c, PA_ERR_PROTOCOL);
+ return;
+ }
+
+ if (c->ext_stream_restore.callback)
+ c->ext_stream_restore.callback(c, c->ext_stream_restore.userdata);
+
+}
diff --git a/src/pulse/ext-stream-restore.h b/src/pulse/ext-stream-restore.h
new file mode 100644
index 0000000..3c77b46
--- /dev/null
+++ b/src/pulse/ext-stream-restore.h
@@ -0,0 +1,86 @@
+#ifndef foopulseextstreamrestorehfoo
+#define foopulseextstreamrestorehfoo
+
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2008 Lennart Poettering
+
+ 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,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#include <pulse/context.h>
+
+typedef struct pa_ext_stream_restore_info {
+ const char *name;
+ pa_channel_map channel_map;
+ pa_cvolume volume;
+ const char *device;
+ int mute;
+} pa_ext_stream_restore_info;
+
+typedef void (*pa_ext_stream_restore_test_cb_t)(
+ pa_context *c,
+ uint32_t version,
+ void *userdata);
+
+pa_operation *pa_ext_stream_restore_test(
+ pa_context *c,
+ pa_ext_stream_restore_test_cb_t cb,
+ void *userdata);
+
+typedef void (*pa_ext_stream_restore_read_cb_t)(
+ pa_context *c,
+ const pa_ext_stream_restore_info *info,
+ int eol,
+ void *userdata);
+
+pa_operation *pa_ext_stream_restore_read(
+ pa_context *c,
+ pa_ext_stream_restore_read_cb_t cb,
+ void *userdata);
+
+pa_operation *pa_ext_stream_restore_write(
+ pa_context *c,
+ pa_update_mode_t mode,
+ const pa_ext_stream_restore_info data[],
+ unsigned n,
+ pa_bool_t apply_immediately,
+ pa_context_success_cb_t cb,
+ void *userdata);
+
+pa_operation *pa_ext_stream_restore_delete(
+ pa_context *c,
+ const char *const s[],
+ pa_context_success_cb_t cb,
+ void *userdata);
+
+pa_operation *pa_ext_stream_restore_subscribe(
+ pa_context *c,
+ int enable,
+ pa_context_success_cb_t cb,
+ void *userdata);
+
+typedef void (*pa_ext_stream_restore_subscribe_cb_t)(
+ pa_context *c,
+ void *userdata);
+
+void pa_ext_stream_restore_set_subscribe_cb(
+ pa_context *c,
+ pa_ext_stream_restore_subscribe_cb_t cb,
+ void *userdata);
+
+#endif
diff --git a/src/pulse/internal.h b/src/pulse/internal.h
index 9ed541d..bfe888e 100644
--- a/src/pulse/internal.h
+++ b/src/pulse/internal.h
@@ -28,6 +28,7 @@
#include <pulse/stream.h>
#include <pulse/operation.h>
#include <pulse/subscribe.h>
+#include <pulse/ext-stream-restore.h>
#include <pulsecore/socket-client.h>
#include <pulsecore/pstream.h>
@@ -86,6 +87,12 @@ struct pa_context {
pa_client_conf *conf;
uint32_t client_index;
+
+ /* Extension specific data */
+ struct {
+ pa_ext_stream_restore_subscribe_cb_t callback;
+ void *userdata;
+ } ext_stream_restore;
};
#define PA_MAX_WRITE_INDEX_CORRECTIONS 32
@@ -233,4 +240,6 @@ pa_tagstruct *pa_tagstruct_command(pa_context *c, uint32_t command, uint32_t *ta
#define PA_CHECK_VALIDITY_RETURN_NULL(context, expression, error) PA_CHECK_VALIDITY_RETURN_ANY(context, expression, error, NULL)
+void pa_ext_stream_restore_command(pa_context *c, uint32_t tag, pa_tagstruct *t);
+
#endif
diff --git a/src/pulse/subscribe.c b/src/pulse/subscribe.c
index d9c06b7..b8d3be8 100644
--- a/src/pulse/subscribe.c
+++ b/src/pulse/subscribe.c
@@ -61,7 +61,6 @@ finish:
pa_context_unref(c);
}
-
pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, pa_context_success_cb_t cb, void *userdata) {
pa_operation *o;
pa_tagstruct *t;
--
hooks/post-receive
PulseAudio Sound Server
More information about the pulseaudio-commits
mailing list