Merge branch 'master' of git://0pointer.de/pulseaudio into dbus-work

Conflicts:
	src/modules/module-stream-restore.c
This commit is contained in:
Tanu Kaskinen 2009-08-30 20:07:31 +03:00
commit 0ad2d55cbe
46 changed files with 720 additions and 173 deletions

View file

@ -833,7 +833,7 @@ libpulsecore_@PA_MAJORMINORMICRO@_la_SOURCES = \
pulsecore/play-memblockq.c pulsecore/play-memblockq.h \
pulsecore/play-memchunk.c pulsecore/play-memchunk.h \
pulsecore/remap.c pulsecore/remap.h \
pulsecore/remap_mmx.c \
pulsecore/remap_mmx.c pulsecore/remap_sse.c \
pulsecore/resampler.c pulsecore/resampler.h \
pulsecore/rtpoll.c pulsecore/rtpoll.h \
pulsecore/sample-util.c pulsecore/sample-util.h \
@ -843,6 +843,7 @@ libpulsecore_@PA_MAJORMINORMICRO@_la_SOURCES = \
pulsecore/svolume_mmx.c pulsecore/svolume_sse.c \
pulsecore/sconv-s16be.c pulsecore/sconv-s16be.h \
pulsecore/sconv-s16le.c pulsecore/sconv-s16le.h \
pulsecore/sconv_sse.c \
pulsecore/sconv.c pulsecore/sconv.h \
pulsecore/shared.c pulsecore/shared.h \
pulsecore/shm.c pulsecore/shm.h \
@ -1765,7 +1766,7 @@ daemon.conf: daemon/daemon.conf.in Makefile
-e 's,@PA_DEFAULT_CONFIG_FILE\@,$(DEFAULT_CONFIG_DIR),g' < $< > $@
install-exec-hook:
chown root $(DESTDIR)$(bindir)/pulseaudio ; true
-chown root $(DESTDIR)$(pulselibexecdir)/proximity-helper
-chmod u+s $(DESTDIR)$(pulselibexecdir)/proximity-helper
ln -sf pacat $(DESTDIR)$(bindir)/parec
ln -sf pacat $(DESTDIR)$(bindir)/pamon

View file

@ -662,6 +662,21 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
} else if (dbus_message_is_signal(m, "org.bluez.Device", "DisconnectRequested")) {
pa_bluetooth_device *d;
if ((d = pa_hashmap_get(y->devices, dbus_message_get_path(m)))) {
/* Device will disconnect in 2 sec */
d->audio_state = PA_BT_AUDIO_STATE_DISCONNECTED;
d->audio_sink_state = PA_BT_AUDIO_STATE_DISCONNECTED;
d->audio_source_state = PA_BT_AUDIO_STATE_DISCONNECTED;
d->headset_state = PA_BT_AUDIO_STATE_DISCONNECTED;
run_callback(y, d, FALSE);
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
} else if (dbus_message_is_signal(m, "org.freedesktop.DBus", "NameOwnerChanged")) {
const char *name, *old_owner, *new_owner;
@ -775,6 +790,7 @@ pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *c) {
"type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceRemoved'",
"type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceCreated'",
"type='signal',sender='org.bluez',interface='org.bluez.Device',member='PropertyChanged'",
"type='signal',sender='org.bluez',interface='org.bluez.Device',member='DisconnectRequested'",
"type='signal',sender='org.bluez',interface='org.bluez.Audio',member='PropertyChanged'",
"type='signal',sender='org.bluez',interface='org.bluez.Headset',member='PropertyChanged'",
"type='signal',sender='org.bluez',interface='org.bluez.AudioSink',member='PropertyChanged'",
@ -828,6 +844,7 @@ void pa_bluetooth_discovery_unref(pa_bluetooth_discovery *y) {
"type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceRemoved'",
"type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceCreated'",
"type='signal',sender='org.bluez',interface='org.bluez.Device',member='PropertyChanged'",
"type='signal',sender='org.bluez',interface='org.bluez.Device',member='DisconnectRequested'",
"type='signal',sender='org.bluez',interface='org.bluez.Audio',member='PropertyChanged'",
"type='signal',sender='org.bluez',interface='org.bluez.Headset',member='PropertyChanged'",
"type='signal',sender='org.bluez',interface='org.bluez.AudioSink',member='PropertyChanged'",

View file

@ -83,7 +83,6 @@ static pa_hook_result_t load_module_for_device(pa_bluetooth_discovery *y, const
mi = pa_hashmap_get(u->hashmap, d->path);
pa_log("dead: %d, device_connected: %d, audio_state: %d, audio_source_state: %d", d->dead, d->device_connected, d->audio_state, d->audio_source_state);
if (!d->dead &&
d->device_connected > 0 && (d->audio_state >= PA_BT_AUDIO_STATE_CONNECTED || d->audio_source_state >= PA_BT_AUDIO_STATE_CONNECTED)) {

View file

@ -844,8 +844,9 @@ static int output_create_sink_input(struct output *o) {
pa_sink_input_new_data_set_channel_map(&data, &o->userdata->sink->channel_map);
data.module = o->userdata->module;
data.resample_method = o->userdata->resample_method;
data.flags = PA_SINK_INPUT_VARIABLE_RATE|PA_SINK_INPUT_DONT_MOVE|PA_SINK_INPUT_NO_CREATE_ON_SUSPEND;
pa_sink_input_new(&o->sink_input, o->userdata->core, &data, PA_SINK_INPUT_VARIABLE_RATE|PA_SINK_INPUT_DONT_MOVE|PA_SINK_INPUT_NO_CREATE_ON_SUSPEND);
pa_sink_input_new(&o->sink_input, o->userdata->core, &data);
pa_sink_input_new_data_done(&data);

View file

@ -812,7 +812,7 @@ int pa__init(pa_module*m) {
pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
pa_sink_input_new_data_set_channel_map(&sink_input_data, &map);
pa_sink_input_new(&u->sink_input, m->core, &sink_input_data, 0);
pa_sink_input_new(&u->sink_input, m->core, &sink_input_data);
pa_sink_input_new_data_done(&sink_input_data);
if (!u->sink_input)

View file

@ -172,7 +172,7 @@ static void adjust_rates(struct userdata *u) {
(double) u->latency_snapshot.source_latency / PA_USEC_PER_MSEC,
((double) u->latency_snapshot.sink_latency + buffer_latency + u->latency_snapshot.source_latency) / PA_USEC_PER_MSEC);
pa_log_info("Should buffer %lu bytes, buffered at minimum %lu bytes",
pa_log_info("Should buffer %zu bytes, buffered at minimum %zu bytes",
u->latency_snapshot.max_request*2,
u->latency_snapshot.min_memblockq_length);
@ -676,8 +676,9 @@ int pa__init(pa_module *m) {
pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "abstract");
pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
pa_sink_input_new_data_set_channel_map(&sink_input_data, &map);
sink_input_data.flags = PA_SINK_INPUT_VARIABLE_RATE;
pa_sink_input_new(&u->sink_input, m->core, &sink_input_data, PA_SINK_INPUT_VARIABLE_RATE);
pa_sink_input_new(&u->sink_input, m->core, &sink_input_data);
pa_sink_input_new_data_done(&sink_input_data);
if (!u->sink_input)
@ -709,7 +710,7 @@ int pa__init(pa_module *m) {
pa_source_output_new_data_set_sample_spec(&source_output_data, &ss);
pa_sink_input_new_data_set_channel_map(&sink_input_data, &map);
pa_source_output_new(&u->source_output, m->core, &source_output_data, 0);
pa_source_output_new(&u->source_output, m->core, &source_output_data);
pa_source_output_new_data_done(&source_output_data);
if (!u->source_output)

View file

@ -406,8 +406,9 @@ int pa__init(pa_module*m) {
pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
pa_sink_input_new_data_set_channel_map(&sink_input_data, &stream_map);
sink_input_data.flags = (remix ? 0 : PA_SINK_INPUT_NO_REMIX);
pa_sink_input_new(&u->sink_input, m->core, &sink_input_data, (remix ? 0 : PA_SINK_INPUT_NO_REMIX));
pa_sink_input_new(&u->sink_input, m->core, &sink_input_data);
pa_sink_input_new_data_done(&sink_input_data);
if (!u->sink_input)

View file

@ -163,7 +163,7 @@ int pa__init(pa_module*m) {
pa_proplist_setf(data.proplist, "sine.hz", "%u", frequency);
pa_sink_input_new_data_set_sample_spec(&data, &ss);
pa_sink_input_new(&u->sink_input, m->core, &data, 0);
pa_sink_input_new(&u->sink_input, m->core, &data);
pa_sink_input_new_data_done(&data);
if (!u->sink_input)

View file

@ -1834,6 +1834,10 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio
data.data = &entry;
data.size = sizeof(entry);
pa_log_debug("Client %s changes entry %s.",
pa_strnull(pa_proplist_gets(pa_native_connection_get_client(c)->proplist, PA_PROP_APPLICATION_PROCESS_BINARY)),
name);
if (pa_database_set(u->database, &key, &data, mode == PA_UPDATE_REPLACE) == 0) {
#ifdef HAVE_DBUS
struct dbus_entry *de;
@ -1846,8 +1850,8 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio
send_device_updated_signal(de, &entry);
if ((old->volume_valid != entry.volume_valid)
|| (entry.volume_valid
&& (!pa_cvolume_equal(&entry.volume, &old->volume) || !pa_channel_map_equal(&entry.channel_map, &old->channel_map))))
|| (entry.volume_valid && (!pa_cvolume_equal(&entry.volume, &old->volume)
|| !pa_channel_map_equal(&entry.channel_map, &old->channel_map))))
send_volume_updated_signal(de, &entry);
if (!old->muted_valid || (entry.muted != old->muted))

View file

@ -145,6 +145,9 @@ static pa_hook_result_t sink_input_fixate_hook_cb(pa_core *c, pa_sink_input_new_
pa_assert(data);
pa_assert(u);
if (data->flags & PA_SINK_INPUT_START_CORKED)
return PA_HOOK_OK;
if ((d = pa_hashmap_get(u->device_infos, data->sink)))
resume(d);
@ -158,6 +161,9 @@ static pa_hook_result_t source_output_fixate_hook_cb(pa_core *c, pa_source_outpu
pa_assert(data);
pa_assert(u);
if (data->flags & PA_SOURCE_OUTPUT_START_CORKED)
return PA_HOOK_OK;
if (data->source->monitor_of)
d = pa_hashmap_get(u->device_infos, data->source->monitor_of);
else
@ -226,11 +232,16 @@ static pa_hook_result_t sink_input_move_start_hook_cb(pa_core *c, pa_sink_input
static pa_hook_result_t sink_input_move_finish_hook_cb(pa_core *c, pa_sink_input *s, struct userdata *u) {
struct device_info *d;
pa_sink_input_state_t state;
pa_assert(c);
pa_sink_input_assert_ref(s);
pa_assert(u);
state = pa_sink_input_get_state(s);
if (state != PA_SINK_INPUT_RUNNING && state != PA_SINK_INPUT_DRAINED)
return PA_HOOK_OK;
if ((d = pa_hashmap_get(u->device_infos, s->sink)))
resume(d);
@ -265,6 +276,9 @@ static pa_hook_result_t source_output_move_finish_hook_cb(pa_core *c, pa_source_
pa_source_output_assert_ref(s);
pa_assert(u);
if (pa_source_output_get_state(s) != PA_SOURCE_OUTPUT_RUNNING)
return PA_HOOK_OK;
if (s->source->monitor_of)
d = pa_hashmap_get(u->device_infos, s->source->monitor_of);
else
@ -279,6 +293,7 @@ static pa_hook_result_t source_output_move_finish_hook_cb(pa_core *c, pa_source_
static pa_hook_result_t sink_input_state_changed_hook_cb(pa_core *c, pa_sink_input *s, struct userdata *u) {
struct device_info *d;
pa_sink_input_state_t state;
pa_assert(c);
pa_sink_input_assert_ref(s);
pa_assert(u);
@ -292,15 +307,11 @@ static pa_hook_result_t sink_input_state_changed_hook_cb(pa_core *c, pa_sink_inp
}
static pa_hook_result_t source_output_state_changed_hook_cb(pa_core *c, pa_source_output *s, struct userdata *u) {
pa_source_output_state_t state;
pa_assert(c);
pa_source_output_assert_ref(s);
pa_assert(u);
state = pa_source_output_get_state(s);
if (state == PA_SOURCE_OUTPUT_RUNNING) {
if (pa_source_output_get_state(s) == PA_SOURCE_OUTPUT_RUNNING) {
struct device_info *d;
if (s->source->monitor_of)
@ -387,22 +398,17 @@ static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_object *o, s
pa_sink *s = PA_SINK(o);
pa_sink_state_t state = pa_sink_get_state(s);
if (pa_sink_check_suspend(s) <= 0) {
if (pa_sink_check_suspend(s) <= 0)
if (PA_SINK_IS_OPENED(state))
restart(d);
}
} else if (pa_source_isinstance(o)) {
pa_source *s = PA_SOURCE(o);
pa_source_state_t state = pa_source_get_state(s);
if (pa_source_check_suspend(s) <= 0) {
if (pa_source_check_suspend(s) <= 0)
if (PA_SOURCE_IS_OPENED(state))
restart(d);
}
}
return PA_HOOK_OK;

View file

@ -501,8 +501,9 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in
pa_proplist_setf(data.proplist, "rtp.payload", "%u", (unsigned) sdp_info->payload);
data.module = u->module;
pa_sink_input_new_data_set_sample_spec(&data, &sdp_info->sample_spec);
data.flags = PA_SINK_INPUT_VARIABLE_RATE;
pa_sink_input_new(&s->sink_input, u->module->core, &data, PA_SINK_INPUT_VARIABLE_RATE);
pa_sink_input_new(&s->sink_input, u->module->core, &data);
pa_sink_input_new_data_done(&data);
if (!s->sink_input) {

View file

@ -330,8 +330,9 @@ int pa__init(pa_module*m) {
data.source = s;
pa_source_output_new_data_set_sample_spec(&data, &ss);
pa_source_output_new_data_set_channel_map(&data, &cm);
data.flags = PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND;
pa_source_output_new(&o, m->core, &data, PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND);
pa_source_output_new(&o, m->core, &data);
pa_source_output_new_data_done(&data);
if (!o) {

View file

@ -214,11 +214,13 @@ static void line_callback(pa_ioline *line, const char *s, void *userdata) {
/* End of headers */
/* We will have a header left from our looping iteration, so add it in :) */
if (c->last_header) {
char *tmp = pa_strbuf_tostring_free(c->header_buffer);
/* This is not a continuation header so let's dump it into our proplist */
pa_headerlist_puts(c->response_headers, c->last_header, pa_strbuf_tostring_free(c->header_buffer));
pa_headerlist_puts(c->response_headers, c->last_header, tmp);
pa_xfree(tmp);
pa_xfree(c->last_header);
c->last_header = NULL;
c->header_buffer= NULL;
c->header_buffer = NULL;
}
pa_log_debug("Full response received. Dispatching");
@ -240,9 +242,11 @@ static void line_callback(pa_ioline *line, const char *s, void *userdata) {
}
if (c->last_header) {
char *tmp = pa_strbuf_tostring_free(c->header_buffer);
/* This is not a continuation header so let's dump the full
header/value into our proplist */
pa_headerlist_puts(c->response_headers, c->last_header, pa_strbuf_tostring_free(c->header_buffer));
pa_headerlist_puts(c->response_headers, c->last_header, tmp);
pa_xfree(tmp);
pa_xfree(c->last_header);
c->last_header = NULL;
c->header_buffer = NULL;

View file

@ -239,13 +239,10 @@ pa_operation *pa_ext_stream_restore_write(
return o;
fail:
if (o) {
pa_operation_cancel(o);
pa_operation_unref(o);
}
pa_operation_cancel(o);
pa_operation_unref(o);
if (t)
pa_tagstruct_free(t);
pa_tagstruct_free(t);
pa_context_set_error(c, PA_ERR_INVALID);
return NULL;
@ -290,13 +287,10 @@ pa_operation *pa_ext_stream_restore_delete(
return o;
fail:
if (o) {
pa_operation_cancel(o);
pa_operation_unref(o);
}
pa_operation_cancel(o);
pa_operation_unref(o);
if (t)
pa_tagstruct_free(t);
pa_tagstruct_free(t);
pa_context_set_error(c, PA_ERR_INVALID);
return NULL;

View file

@ -251,7 +251,7 @@ int pa_proplist_set(pa_proplist *p, const char *key, const void *data, size_t nb
pa_assert(p);
pa_assert(key);
pa_assert(data);
pa_assert(data || nbytes == 0);
if (!property_name_valid(key))
return -1;
@ -264,7 +264,8 @@ int pa_proplist_set(pa_proplist *p, const char *key, const void *data, size_t nb
pa_xfree(prop->value);
prop->value = pa_xmalloc(nbytes+1);
memcpy(prop->value, data, nbytes);
if (nbytes > 0)
memcpy(prop->value, data, nbytes);
((char*) prop->value)[nbytes] = 0;
prop->nbytes = nbytes;

View file

@ -232,6 +232,7 @@ char *pa_sink_list_to_string(pa_core *c) {
"\tflags: %s%s%s%s%s%s%s%s\n"
"\tstate: %s\n"
"\tsuspend cause: %s%s%s%s\n"
"\tpriority: %u\n"
"\tvolume: %s%s%s\n"
"\t balance %0.2f\n"
"\tbase volume: %s%s%s\n"
@ -262,6 +263,7 @@ char *pa_sink_list_to_string(pa_core *c) {
sink->suspend_cause & PA_SUSPEND_APPLICATION ? "APPLICATION " : "",
sink->suspend_cause & PA_SUSPEND_IDLE ? "IDLE " : "",
sink->suspend_cause & PA_SUSPEND_SESSION ? "SESSION" : "",
sink->priority,
pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink, FALSE)),
sink->flags & PA_SINK_DECIBEL_VOLUME ? "\n\t " : "",
sink->flags & PA_SINK_DECIBEL_VOLUME ? pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), pa_sink_get_volume(sink, FALSE)) : "",
@ -356,6 +358,7 @@ char *pa_source_list_to_string(pa_core *c) {
"\tflags: %s%s%s%s%s%s%s\n"
"\tstate: %s\n"
"\tsuspend cause: %s%s%s%s\n"
"\tpriority: %u\n"
"\tvolume: %s%s%s\n"
"\t balance %0.2f\n"
"\tbase volume: %s%s%s\n"
@ -383,6 +386,7 @@ char *pa_source_list_to_string(pa_core *c) {
source->suspend_cause & PA_SUSPEND_APPLICATION ? "APPLICATION " : "",
source->suspend_cause & PA_SUSPEND_IDLE ? "IDLE " : "",
source->suspend_cause & PA_SUSPEND_SESSION ? "SESSION" : "",
source->priority,
pa_cvolume_snprint(cv, sizeof(cv), pa_source_get_volume(source, FALSE)),
source->flags & PA_SOURCE_DECIBEL_VOLUME ? "\n\t " : "",
source->flags & PA_SOURCE_DECIBEL_VOLUME ? pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), pa_source_get_volume(source, FALSE)) : "",

View file

@ -1877,17 +1877,17 @@ char *pa_make_path_absolute(const char *p) {
static char *get_path(const char *fn, pa_bool_t prependmid, pa_bool_t rt) {
char *rtp;
if (pa_is_path_absolute(fn))
return pa_xstrdup(fn);
rtp = rt ? pa_get_runtime_dir() : pa_get_state_dir();
if (!rtp)
return NULL;
if (fn) {
char *r;
if (pa_is_path_absolute(fn))
return pa_xstrdup(fn);
if (!rtp)
return NULL;
if (prependmid) {
char *mid;

View file

@ -115,8 +115,11 @@ void pa_cpu_init_x86 (void) {
pa_remap_func_init_mmx (flags);
}
if (flags & PA_CPU_X86_SSE)
if (flags & PA_CPU_X86_SSE) {
pa_volume_func_init_sse (flags);
pa_remap_func_init_sse (flags);
pa_convert_func_init_sse (flags);
}
#endif /* defined (__i386__) || defined (__amd64__) */
}

View file

@ -64,5 +64,8 @@ void pa_volume_func_init_mmx(pa_cpu_x86_flag_t flags);
void pa_volume_func_init_sse(pa_cpu_x86_flag_t flags);
void pa_remap_func_init_mmx(pa_cpu_x86_flag_t flags);
void pa_remap_func_init_sse(pa_cpu_x86_flag_t flags);
void pa_convert_func_init_sse (pa_cpu_x86_flag_t flags);
#endif /* foocpux86hfoo */

View file

@ -107,4 +107,7 @@
#define PA_LLIST_FOREACH(i,head) \
for (i = (head); i; i = i->next)
#define PA_LLIST_FOREACH_SAFE(i,n,head) \
for (i = (head); i && ((n = i->next), 1); i = n)
#endif

View file

@ -80,6 +80,12 @@ static inline size_t PA_PAGE_ALIGN(size_t l) {
#define PA_ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))
#if defined(__GNUC__)
#define PA_DECLARE_ALIGNED(n,t,v) t v __attribute__ ((aligned (n)))
#else
#define PA_DECLARE_ALIGNED(n,t,v) t v
#endif
/* The users of PA_MIN and PA_MAX, PA_CLAMP, PA_ROUND_UP should be
* aware that these macros on non-GCC executed code with side effects
* twice. It is thus considered misuse to use code with side effects

View file

@ -57,6 +57,8 @@ static pa_bool_t is_valid_char(char c) {
pa_bool_t pa_namereg_is_valid_name(const char *name) {
const char *c;
pa_assert(name);
if (*name == 0)
return FALSE;
@ -70,6 +72,25 @@ pa_bool_t pa_namereg_is_valid_name(const char *name) {
return TRUE;
}
pa_bool_t pa_namereg_is_valid_name_or_wildcard(const char *name, pa_namereg_type_t type) {
pa_assert(name);
if (pa_namereg_is_valid_name(name))
return TRUE;
if (type == PA_NAMEREG_SINK &&
pa_streq(name, "@DEFAULT_SINK@"))
return TRUE;
if (type == PA_NAMEREG_SOURCE &&
(pa_streq(name, "@DEFAULT_SOURCE@") ||
pa_streq(name, "@DEFAULT_MONITOR@")))
return TRUE;
return FALSE;
}
char* pa_namereg_make_valid_name(const char *name) {
const char *a;
char *b, *n;
@ -191,7 +212,6 @@ void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type) {
if ((s = pa_namereg_get(c, NULL, PA_NAMEREG_SINK)))
return s->monitor_source;
}
if (!name)
@ -249,7 +269,7 @@ pa_source* pa_namereg_set_default_source(pa_core*c, pa_source *s) {
}
pa_sink *pa_namereg_get_default_sink(pa_core *c) {
pa_sink *s;
pa_sink *s, *best = NULL;
uint32_t idx;
pa_assert(c);
@ -257,18 +277,19 @@ pa_sink *pa_namereg_get_default_sink(pa_core *c) {
if (c->default_sink && PA_SINK_IS_LINKED(pa_sink_get_state(c->default_sink)))
return c->default_sink;
/* FIXME: the selection here should be based priority values on
* the sinks */
PA_IDXSET_FOREACH(s, c->sinks, idx)
if (PA_SINK_IS_LINKED(pa_sink_get_state(s)))
return pa_namereg_set_default_sink(c, s);
if (!best || s->priority > best->priority)
best = s;
if (best)
return pa_namereg_set_default_sink(c, best);
return NULL;
}
pa_source *pa_namereg_get_default_source(pa_core *c) {
pa_source *s;
pa_source *s, *best = NULL;
uint32_t idx;
pa_assert(c);
@ -279,12 +300,26 @@ pa_source *pa_namereg_get_default_source(pa_core *c) {
/* First, try to find one that isn't a monitor */
PA_IDXSET_FOREACH(s, c->sources, idx)
if (!s->monitor_of && PA_SOURCE_IS_LINKED(pa_source_get_state(s)))
return pa_namereg_set_default_source(c, s);
if (!best ||
s->priority > best->priority)
best = s;
if (best)
return pa_namereg_set_default_source(c, best);
/* Then, fallback to a monitor */
PA_IDXSET_FOREACH(s, c->sources, idx)
if (PA_SOURCE_IS_LINKED(pa_source_get_state(s)))
return pa_namereg_set_default_source(c, s);
if (!best ||
s->priority > best->priority ||
(s->priority == best->priority &&
s->monitor_of &&
best->monitor_of &&
s->monitor_of->priority > best->monitor_of->priority))
best = s;
if (best)
return pa_namereg_set_default_source(c, best);
return NULL;
}

View file

@ -45,6 +45,7 @@ pa_sink *pa_namereg_get_default_sink(pa_core *c);
pa_source *pa_namereg_get_default_source(pa_core *c);
pa_bool_t pa_namereg_is_valid_name(const char *name);
pa_bool_t pa_namereg_is_valid_name_or_wildcard(const char *name, pa_namereg_type_t type);
char* pa_namereg_make_valid_name(const char *name);
#endif

View file

@ -169,7 +169,7 @@ static const char *command_names[PA_COMMAND_MAX] = {
/* Supported since protocol v14 (0.9.12) */
[PA_COMMAND_EXTENSION] = "EXTENSION",
/* Supported since protocol v15 (0.9.15) */
[PA_COMMAND_GET_CARD_INFO] = "GET_CARD_INFO",
[PA_COMMAND_GET_CARD_INFO_LIST] = "GET_CARD_INFO_LIST",
[PA_COMMAND_SET_CARD_PROFILE] = "SET_CARD_PROFILE",
@ -180,7 +180,11 @@ static const char *command_names[PA_COMMAND_MAX] = {
/* SERVER->CLIENT */
[PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED] = "PLAYBACK_BUFFER_ATTR_CHANGED",
[PA_COMMAND_RECORD_BUFFER_ATTR_CHANGED] = "RECORD_BUFFER_ATTR_CHANGED"
[PA_COMMAND_RECORD_BUFFER_ATTR_CHANGED] = "RECORD_BUFFER_ATTR_CHANGED",
/* Supported since protocol v16 (0.9.16) */
[PA_COMMAND_SET_SINK_PORT] = "SET_SINK_PORT",
[PA_COMMAND_SET_SOURCE_PORT] = "SET_SOURCE_PORT"
};
#endif
@ -203,10 +207,10 @@ struct pa_pdispatch {
const pa_pdispatch_cb_t *callback_table;
unsigned n_commands;
PA_LLIST_HEAD(struct reply_info, replies);
pa_pdispatch_drain_callback drain_callback;
pa_pdispatch_drain_cb_t drain_callback;
void *drain_userdata;
const pa_creds *creds;
pa_bool_t use_rtclock:1;
pa_bool_t use_rtclock;
};
static void reply_info_free(struct reply_info *r) {
@ -225,19 +229,16 @@ static void reply_info_free(struct reply_info *r) {
pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *mainloop, pa_bool_t use_rtclock, const pa_pdispatch_cb_t *table, unsigned entries) {
pa_pdispatch *pd;
pa_assert(mainloop);
pa_assert(mainloop);
pa_assert((entries && table) || (!entries && !table));
pd = pa_xnew(pa_pdispatch, 1);
pd = pa_xnew0(pa_pdispatch, 1);
PA_REFCNT_INIT(pd);
pd->mainloop = mainloop;
pd->callback_table = table;
pd->n_commands = entries;
PA_LLIST_HEAD_INIT(struct reply_info, pd->replies);
pd->drain_callback = NULL;
pd->drain_userdata = NULL;
pd->creds = NULL;
pd->use_rtclock = use_rtclock;
return pd;
@ -317,7 +318,7 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_creds *creds,
if (command == PA_COMMAND_ERROR || command == PA_COMMAND_REPLY) {
struct reply_info *r;
for (r = pd->replies; r; r = r->next)
PA_LLIST_FOREACH(r, pd->replies)
if (r->tag == tag)
break;
@ -325,9 +326,9 @@ int pa_pdispatch_run(pa_pdispatch *pd, pa_packet*packet, const pa_creds *creds,
run_action(pd, r, command, ts);
} else if (pd->callback_table && (command < pd->n_commands) && pd->callback_table[command]) {
const pa_pdispatch_cb_t *c = pd->callback_table+command;
const pa_pdispatch_cb_t *cb = pd->callback_table+command;
(*c)(pd, command, tag, ts, userdata);
(*cb)(pd, command, tag, ts, userdata);
} else {
pa_log("Received unsupported command %u", command);
goto finish;
@ -375,7 +376,9 @@ void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa
r->free_cb = free_cb;
r->tag = tag;
pa_assert_se(r->time_event = pd->mainloop->time_new(pd->mainloop, pa_timeval_rtstore(&tv, pa_rtclock_now() + timeout * PA_USEC_PER_SEC, pd->use_rtclock), timeout_callback, r));
pa_assert_se(r->time_event = pd->mainloop->time_new(pd->mainloop,
pa_timeval_rtstore(&tv, pa_rtclock_now() + timeout * PA_USEC_PER_SEC, pd->use_rtclock),
timeout_callback, r));
PA_LLIST_PREPEND(struct reply_info, pd->replies, r);
}
@ -387,7 +390,7 @@ int pa_pdispatch_is_pending(pa_pdispatch *pd) {
return !!pd->replies;
}
void pa_pdispatch_set_drain_callback(pa_pdispatch *pd, void (*cb)(pa_pdispatch *pd, void *userdata), void *userdata) {
void pa_pdispatch_set_drain_callback(pa_pdispatch *pd, pa_pdispatch_drain_cb_t cb, void *userdata) {
pa_assert(pd);
pa_assert(PA_REFCNT_VALUE(pd) >= 1);
pa_assert(!cb || pa_pdispatch_is_pending(pd));
@ -402,12 +405,9 @@ void pa_pdispatch_unregister_reply(pa_pdispatch *pd, void *userdata) {
pa_assert(pd);
pa_assert(PA_REFCNT_VALUE(pd) >= 1);
for (r = pd->replies; r; r = n) {
n = r->next;
PA_LLIST_FOREACH_SAFE(r, n, pd->replies)
if (r->userdata == userdata)
reply_info_free(r);
}
}
void pa_pdispatch_unref(pa_pdispatch *pd) {

View file

@ -35,9 +35,9 @@
typedef struct pa_pdispatch pa_pdispatch;
typedef void (*pa_pdispatch_cb_t)(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
typedef void (*pa_pdispatch_drain_callback)(pa_pdispatch *pd, void *userdata);
typedef void (*pa_pdispatch_drain_cb_t)(pa_pdispatch *pd, void *userdata);
pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *m, pa_bool_t use_rtclock, const pa_pdispatch_cb_t*table, unsigned entries);
pa_pdispatch* pa_pdispatch_new(pa_mainloop_api *m, pa_bool_t use_rtclock, const pa_pdispatch_cb_t *table, unsigned entries);
void pa_pdispatch_unref(pa_pdispatch *pd);
pa_pdispatch* pa_pdispatch_ref(pa_pdispatch *pd);
@ -47,7 +47,7 @@ void pa_pdispatch_register_reply(pa_pdispatch *pd, uint32_t tag, int timeout, pa
int pa_pdispatch_is_pending(pa_pdispatch *pd);
void pa_pdispatch_set_drain_callback(pa_pdispatch *pd, pa_pdispatch_drain_callback callback, void *userdata);
void pa_pdispatch_set_drain_callback(pa_pdispatch *pd, pa_pdispatch_drain_cb_t callback, void *userdata);
/* Remove all reply slots with the give userdata parameter */
void pa_pdispatch_unregister_reply(pa_pdispatch *pd, void *userdata);

View file

@ -199,7 +199,7 @@ pa_sink_input* pa_memblockq_sink_input_new(
pa_sink_input_new_data_set_volume(&data, volume);
pa_proplist_update(data.proplist, PA_UPDATE_REPLACE, p);
pa_sink_input_new(&u->sink_input, sink->core, &data, 0);
pa_sink_input_new(&u->sink_input, sink->core, &data);
pa_sink_input_new_data_done(&data);
if (!u->sink_input)

View file

@ -429,7 +429,7 @@ static int esd_proto_stream_play(connection *c, esd_proto_t request, const void
sdata.sink = sink;
pa_sink_input_new_data_set_sample_spec(&sdata, &ss);
pa_sink_input_new(&c->sink_input, c->protocol->core, &sdata, 0);
pa_sink_input_new(&c->sink_input, c->protocol->core, &sdata);
pa_sink_input_new_data_done(&sdata);
CHECK_VALIDITY(c->sink_input, "Failed to create sink input.");
@ -525,7 +525,7 @@ static int esd_proto_stream_record(connection *c, esd_proto_t request, const voi
sdata.source = source;
pa_source_output_new_data_set_sample_spec(&sdata, &ss);
pa_source_output_new(&c->source_output, c->protocol->core, &sdata, 0);
pa_source_output_new(&c->source_output, c->protocol->core, &sdata);
pa_source_output_new_data_done(&sdata);
CHECK_VALIDITY(c->source_output, "Failed to create source output.");

View file

@ -533,7 +533,7 @@ static void handle_listen_prefix(struct connection *c, const char *source_name)
pa_source_output_new_data_set_sample_spec(&data, &ss);
pa_source_output_new_data_set_channel_map(&data, &cm);
pa_source_output_new(&c->source_output, c->protocol->core, &data, 0);
pa_source_output_new(&c->source_output, c->protocol->core, &data);
pa_source_output_new_data_done(&data);
if (!c->source_output) {

View file

@ -648,8 +648,9 @@ static record_stream* record_stream_new(
pa_source_output_new_data_set_channel_map(&data, map);
if (peak_detect)
data.resample_method = PA_RESAMPLER_PEAKS;
data.flags = flags;
*ret = -pa_source_output_new(&source_output, c->protocol->core, &data, flags);
*ret = -pa_source_output_new(&source_output, c->protocol->core, &data);
pa_source_output_new_data_done(&data);
@ -1050,8 +1051,9 @@ static playback_stream* playback_stream_new(
if (muted_set)
pa_sink_input_new_data_set_muted(&data, muted);
data.sync_base = ssync ? ssync->sink_input : NULL;
data.flags = flags;
*ret = -pa_sink_input_new(&sink_input, c->protocol->core, &data, flags);
*ret = -pa_sink_input_new(&sink_input, c->protocol->core, &data);
pa_sink_input_new_data_done(&data);
@ -1289,7 +1291,8 @@ static void handle_seek(playback_stream *s, int64_t indexw) {
pa_log_debug("Requesting rewind due to end of underrun.");
pa_sink_input_request_rewind(s->sink_input,
(size_t) (s->sink_input->thread_info.underrun_for == (size_t) -1 ? 0 : s->sink_input->thread_info.underrun_for),
(size_t) (s->sink_input->thread_info.underrun_for == (uint64_t) -1 ? 0 :
s->sink_input->thread_info.underrun_for),
FALSE, TRUE, FALSE);
}
@ -1865,7 +1868,7 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u
}
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
CHECK_VALIDITY(c->pstream, !sink_name || pa_namereg_is_valid_name(sink_name), tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, !sink_name || pa_namereg_is_valid_name_or_wildcard(sink_name, PA_NAMEREG_SINK), tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, sink_index == PA_INVALID_INDEX || !sink_name, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, !sink_name || sink_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
@ -2114,7 +2117,7 @@ static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uin
}
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
CHECK_VALIDITY(c->pstream, !source_name || pa_namereg_is_valid_name(source_name), tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, !source_name || pa_namereg_is_valid_name_or_wildcard(source_name, PA_NAMEREG_SOURCE), tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, source_index == PA_INVALID_INDEX || !source_name, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, !source_name || source_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
@ -2460,7 +2463,7 @@ static void command_lookup(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_
}
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name_or_wildcard(name, command == PA_COMMAND_LOOKUP_SINK ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE), tag, PA_ERR_INVALID);
if (command == PA_COMMAND_LOOKUP_SINK) {
pa_sink *sink;
@ -2731,7 +2734,7 @@ static void command_play_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag
return;
}
CHECK_VALIDITY(c->pstream, !sink_name || pa_namereg_is_valid_name(sink_name), tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, !sink_name || pa_namereg_is_valid_name_or_wildcard(sink_name, PA_NAMEREG_SINK), tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, sink_index == PA_INVALID_INDEX || !sink_name, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, !sink_name || sink_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
@ -3105,7 +3108,12 @@ static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, p
}
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, !name ||
(command == PA_COMMAND_GET_SINK_INFO &&
pa_namereg_is_valid_name_or_wildcard(name, PA_NAMEREG_SINK)) ||
(command == PA_COMMAND_GET_SOURCE_INFO &&
pa_namereg_is_valid_name_or_wildcard(name, PA_NAMEREG_SOURCE)) ||
pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
@ -3347,7 +3355,7 @@ static void command_set_volume(
}
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name_or_wildcard(name, command == PA_COMMAND_SET_SINK_VOLUME ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE), tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
@ -3385,10 +3393,10 @@ static void command_set_volume(
pa_log_debug("Client %s changes volume of sink %s.", client_name, sink->name);
pa_sink_set_volume(sink, &volume, TRUE, TRUE);
} else if (source) {
pa_log_debug("Client %s changes volume of sink %s.", client_name, source->name);
pa_log_debug("Client %s changes volume of source %s.", client_name, source->name);
pa_source_set_volume(source, &volume, TRUE);
} else if (si) {
pa_log_debug("Client %s changes volume of sink %s.",
pa_log_debug("Client %s changes volume of sink input %s.",
client_name,
pa_strnull(pa_proplist_gets(si->proplist, PA_PROP_MEDIA_NAME)));
pa_sink_input_set_volume(si, &volume, TRUE, TRUE);
@ -3410,7 +3418,7 @@ static void command_set_mute(
pa_sink *sink = NULL;
pa_source *source = NULL;
pa_sink_input *si = NULL;
const char *name = NULL;
const char *name = NULL, *client_name;
pa_native_connection_assert_ref(c);
pa_assert(t);
@ -3425,7 +3433,7 @@ static void command_set_mute(
}
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name_or_wildcard(name, command == PA_COMMAND_SET_SINK_MUTE ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE), tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
@ -3459,12 +3467,20 @@ static void command_set_mute(
CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY);
if (sink)
client_name = pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY));
if (sink) {
pa_log_debug("Client %s changes mute of sink %s.", client_name, sink->name);
pa_sink_set_mute(sink, mute, TRUE);
else if (source)
} else if (source) {
pa_log_debug("Client %s changes mute of source %s.", client_name, source->name);
pa_source_set_mute(source, mute, TRUE);
else if (si)
} else if (si) {
pa_log_debug("Client %s changes mute of sink input %s.",
client_name,
pa_strnull(pa_proplist_gets(si->proplist, PA_PROP_MEDIA_NAME)));
pa_sink_input_set_mute(si, mute, TRUE);
}
pa_pstream_send_simple_ack(c->pstream, tag);
}
@ -4083,7 +4099,7 @@ static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, !name_device || pa_namereg_is_valid_name(name_device), tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, !name_device || pa_namereg_is_valid_name_or_wildcard(name_device, command == PA_COMMAND_MOVE_SINK_INPUT ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE), tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, idx_device != PA_INVALID_INDEX || name_device, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, idx_device == PA_INVALID_INDEX || !name_device, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, !name_device || idx_device == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
@ -4147,7 +4163,7 @@ static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
}
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name) || *name == 0, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name_or_wildcard(name, command == PA_COMMAND_SUSPEND_SINK ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE) || *name == 0, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
@ -4307,7 +4323,7 @@ static void command_set_sink_or_source_port(pa_pdispatch *pd, uint32_t command,
}
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name_or_wildcard(name, command == PA_COMMAND_SET_SINK_PORT ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE), tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
@ -4842,3 +4858,9 @@ pa_pstream* pa_native_connection_get_pstream(pa_native_connection *c) {
return c->pstream;
}
pa_client* pa_native_connection_get_client(pa_native_connection *c) {
pa_native_connection_assert_ref(c);
return c->client;
}

View file

@ -47,7 +47,6 @@ typedef struct pa_native_options {
char *auth_group;
pa_ip_acl *auth_ip_acl;
pa_auth_cookie *auth_cookie;
} pa_native_options;
typedef enum pa_native_hook {
@ -80,6 +79,7 @@ int pa_native_protocol_install_ext(pa_native_protocol *p, pa_module *m, pa_nativ
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_client* pa_native_connection_get_client(pa_native_connection *c);
pa_native_options* pa_native_options_new(void);
pa_native_options* pa_native_options_ref(pa_native_options *o);

View file

@ -541,7 +541,7 @@ void pa_simple_protocol_connect(pa_simple_protocol *p, pa_iochannel *io, pa_simp
pa_proplist_update(data.proplist, PA_UPDATE_MERGE, c->client->proplist);
pa_sink_input_new_data_set_sample_spec(&data, &o->sample_spec);
pa_sink_input_new(&c->sink_input, p->core, &data, 0);
pa_sink_input_new(&c->sink_input, p->core, &data);
pa_sink_input_new_data_done(&data);
if (!c->sink_input) {
@ -593,7 +593,7 @@ void pa_simple_protocol_connect(pa_simple_protocol *p, pa_iochannel *io, pa_simp
pa_proplist_update(data.proplist, PA_UPDATE_MERGE, c->client->proplist);
pa_source_output_new_data_set_sample_spec(&data, &o->sample_spec);
pa_source_output_new(&c->source_output, p->core, &data, 0);
pa_source_output_new(&c->source_output, p->core, &data);
pa_source_output_new_data_done(&data);
if (!c->source_output) {
@ -627,8 +627,7 @@ void pa_simple_protocol_connect(pa_simple_protocol *p, pa_iochannel *io, pa_simp
return;
fail:
if (c)
connection_unlink(c);
connection_unlink(c);
}
void pa_simple_protocol_disconnect(pa_simple_protocol *p, pa_module *m) {

View file

@ -51,7 +51,7 @@
" punpckl"#s" %%mm4, %%mm4 \n\t" \
" punpckh"#s" %%mm5, %%mm5 \n\t" \
" punpckl"#s" %%mm6, %%mm6 \n\t" \
" punpckh"#s" %%mm7, %%mm7 \n\t" \
" punpckh"#s" %%mm7, %%mm7 \n\t"
#define STORE_SAMPLES \
" movq %%mm0, (%0) \n\t" \
@ -67,32 +67,31 @@
#define HANDLE_SINGLE(s) \
" movd (%1), %%mm0 \n\t" \
" movq %%mm0, %%mm1 \n\t" \
" punpckl"#s" %%mm0, %%mm0 \n\t" \
" movq %%mm0, (%0) \n\t" \
" add $4, %1 \n\t" \
" add $8, %0 \n\t"
#define MONO_TO_STEREO(s) \
" mov %3, %2 \n\t" \
" sar $3, %2 \n\t" \
" cmp $0, %2 \n\t" \
" je 2f \n\t" \
"1: \n\t" \
LOAD_SAMPLES \
UNPACK_SAMPLES(s) \
STORE_SAMPLES \
" dec %2 \n\t" \
" jne 1b \n\t" \
"2: \n\t" \
" mov %3, %2 \n\t" \
" and $7, %2 \n\t" \
" je 4f \n\t" \
"3: \n\t" \
HANDLE_SINGLE(s) \
" dec %2 \n\t" \
" jne 3b \n\t" \
"4: \n\t" \
#define MONO_TO_STEREO(s) \
" mov %3, %2 \n\t" \
" sar $3, %2 \n\t" \
" cmp $0, %2 \n\t" \
" je 2f \n\t" \
"1: \n\t" \
LOAD_SAMPLES \
UNPACK_SAMPLES(s) \
STORE_SAMPLES \
" dec %2 \n\t" \
" jne 1b \n\t" \
"2: \n\t" \
" mov %3, %2 \n\t" \
" and $7, %2 \n\t" \
" je 4f \n\t" \
"3: \n\t" \
HANDLE_SINGLE(s) \
" dec %2 \n\t" \
" jne 3b \n\t" \
"4: \n\t" \
" emms \n\t"
#if defined (__i386__) || defined (__amd64__)

146
src/pulsecore/remap_sse.c Normal file
View file

@ -0,0 +1,146 @@
/***
This file is part of PulseAudio.
Copyright 2004-2006 Lennart Poettering
Copyright 2009 Wim Taymans <wim.taymans@collabora.co.uk.com>
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.1 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 <string.h>
#include <pulse/sample.h>
#include <pulsecore/log.h>
#include <pulsecore/macro.h>
#include "cpu-x86.h"
#include "remap.h"
#define LOAD_SAMPLES \
" movdqu (%1), %%xmm0 \n\t" \
" movdqu 16(%1), %%xmm2 \n\t" \
" movdqu 32(%1), %%xmm4 \n\t" \
" movdqu 48(%1), %%xmm6 \n\t" \
" movdqa %%xmm0, %%xmm1 \n\t" \
" movdqa %%xmm2, %%xmm3 \n\t" \
" movdqa %%xmm4, %%xmm5 \n\t" \
" movdqa %%xmm6, %%xmm7 \n\t"
#define UNPACK_SAMPLES(s) \
" punpckl"#s" %%xmm0, %%xmm0 \n\t" \
" punpckh"#s" %%xmm1, %%xmm1 \n\t" \
" punpckl"#s" %%xmm2, %%xmm2 \n\t" \
" punpckh"#s" %%xmm3, %%xmm3 \n\t" \
" punpckl"#s" %%xmm4, %%xmm4 \n\t" \
" punpckh"#s" %%xmm5, %%xmm5 \n\t" \
" punpckl"#s" %%xmm6, %%xmm6 \n\t" \
" punpckh"#s" %%xmm7, %%xmm7 \n\t"
#define STORE_SAMPLES \
" movdqu %%xmm0, (%0) \n\t" \
" movdqu %%xmm1, 16(%0) \n\t" \
" movdqu %%xmm2, 32(%0) \n\t" \
" movdqu %%xmm3, 48(%0) \n\t" \
" movdqu %%xmm4, 64(%0) \n\t" \
" movdqu %%xmm5, 80(%0) \n\t" \
" movdqu %%xmm6, 96(%0) \n\t" \
" movdqu %%xmm7, 112(%0) \n\t" \
" add $64, %1 \n\t" \
" add $128, %0 \n\t"
#define HANDLE_SINGLE(s) \
" movd (%1), %%xmm0 \n\t" \
" punpckl"#s" %%xmm0, %%xmm0 \n\t" \
" movq %%xmm0, (%0) \n\t" \
" add $4, %1 \n\t" \
" add $8, %0 \n\t"
#define MONO_TO_STEREO(s) \
" mov %3, %2 \n\t" \
" sar $4, %2 \n\t" \
" cmp $0, %2 \n\t" \
" je 2f \n\t" \
"1: \n\t" \
LOAD_SAMPLES \
UNPACK_SAMPLES(s) \
STORE_SAMPLES \
" dec %2 \n\t" \
" jne 1b \n\t" \
"2: \n\t" \
" mov %3, %2 \n\t" \
" and $15, %2 \n\t" \
" je 4f \n\t" \
"3: \n\t" \
HANDLE_SINGLE(s) \
" dec %2 \n\t" \
" jne 3b \n\t" \
"4: \n\t"
static void remap_mono_to_stereo_sse (pa_remap_t *m, void *dst, const void *src, unsigned n) {
pa_reg_x86 temp;
switch (*m->format) {
case PA_SAMPLE_FLOAT32NE:
{
__asm__ __volatile__ (
MONO_TO_STEREO(dq) /* do doubles to quads */
: "+r" (dst), "+r" (src), "=&r" (temp)
: "r" ((pa_reg_x86)n)
: "cc"
);
break;
}
case PA_SAMPLE_S16NE:
{
__asm__ __volatile__ (
MONO_TO_STEREO(wd) /* do words to doubles */
: "+r" (dst), "+r" (src), "=&r" (temp)
: "r" ((pa_reg_x86)n)
: "cc"
);
break;
}
default:
pa_assert_not_reached();
}
}
/* set the function that will execute the remapping based on the matrices */
static void init_remap_sse (pa_remap_t *m) {
unsigned n_oc, n_ic;
n_oc = m->o_ss->channels;
n_ic = m->i_ss->channels;
/* find some common channel remappings, fall back to full matrix operation. */
if (n_ic == 1 && n_oc == 2 &&
m->map_table_f[0][0] >= 1.0 && m->map_table_f[1][0] >= 1.0) {
m->do_remap = (pa_do_remap_func_t) remap_mono_to_stereo_sse;
pa_log_info("Using SSE mono to stereo remapping");
}
}
void pa_remap_func_init_sse (pa_cpu_x86_flag_t flags) {
#if defined (__i386__) || defined (__amd64__)
pa_log_info("Initialising SSE optimized remappers.");
pa_set_init_remap_func ((pa_init_remap_func_t) init_remap_sse);
#endif /* defined (__i386__) || defined (__amd64__) */
}

View file

@ -299,8 +299,7 @@ pa_resampler* pa_resampler_new(
return r;
fail:
if (r)
pa_xfree(r);
pa_xfree(r);
return NULL;
}

View file

@ -137,7 +137,7 @@ static void calc_linear_float_volume(float linear[], const pa_cvolume *volume) {
static void calc_linear_integer_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_cvolume *volume, const pa_sample_spec *spec) {
unsigned k, channel;
float linear[PA_CHANNELS_MAX];
float linear[PA_CHANNELS_MAX + VOLUME_PADDING];
pa_assert(streams);
pa_assert(spec);
@ -156,7 +156,7 @@ static void calc_linear_integer_stream_volumes(pa_mix_info streams[], unsigned n
static void calc_linear_float_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_cvolume *volume, const pa_sample_spec *spec) {
unsigned k, channel;
float linear[PA_CHANNELS_MAX];
float linear[PA_CHANNELS_MAX + VOLUME_PADDING];
pa_assert(streams);
pa_assert(spec);

View file

@ -52,8 +52,8 @@ static void u8_from_float32ne(unsigned n, const float *a, uint8_t *b) {
for (; n > 0; n--, a++, b++) {
float v;
v = (*a * 127.0) + 128.0;
v = PA_CLAMP_UNLIKELY (v, 0.0, 255.0);
*b = rint (v);
v = PA_CLAMP_UNLIKELY (v, 0.0, 255.0);
*b = rint (v);
}
}

233
src/pulsecore/sconv_sse.c Normal file
View file

@ -0,0 +1,233 @@
/***
This file is part of PulseAudio.
Copyright 2004-2006 Lennart Poettering
Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
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.1 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 <stdio.h>
#include <stdlib.h>
#include <pulsecore/g711.h>
#include <pulsecore/macro.h>
#include "endianmacros.h"
#include "cpu-x86.h"
#include "sconv.h"
#if defined (__i386__) || defined (__amd64__)
static const PA_DECLARE_ALIGNED (16, float, one[4]) = { 1.0, 1.0, 1.0, 1.0 };
static const PA_DECLARE_ALIGNED (16, float, mone[4]) = { -1.0, -1.0, -1.0, -1.0 };
static const PA_DECLARE_ALIGNED (16, float, scale[4]) = { 0x7fff, 0x7fff, 0x7fff, 0x7fff };
static void pa_sconv_s16le_from_f32ne_sse(unsigned n, const float *a, int16_t *b) {
pa_reg_x86 temp, i;
__asm__ __volatile__ (
" movaps %5, %%xmm5 \n\t"
" movaps %6, %%xmm6 \n\t"
" movaps %7, %%xmm7 \n\t"
" xor %0, %0 \n\t"
" mov %4, %1 \n\t"
" sar $3, %1 \n\t" /* 8 floats at a time */
" cmp $0, %1 \n\t"
" je 2f \n\t"
"1: \n\t"
" movups (%2, %0, 2), %%xmm0 \n\t" /* read 8 floats */
" movups 16(%2, %0, 2), %%xmm2 \n\t"
" minps %%xmm5, %%xmm0 \n\t" /* clamp to 1.0 */
" minps %%xmm5, %%xmm2 \n\t"
" maxps %%xmm6, %%xmm0 \n\t" /* clamp to -1.0 */
" maxps %%xmm6, %%xmm2 \n\t"
" mulps %%xmm7, %%xmm0 \n\t" /* *= 0x7fff */
" mulps %%xmm7, %%xmm2 \n\t"
" cvtps2pi %%xmm0, %%mm0 \n\t" /* low part to int */
" cvtps2pi %%xmm2, %%mm2 \n\t"
" movhlps %%xmm0, %%xmm0 \n\t" /* bring high part in position */
" movhlps %%xmm2, %%xmm2 \n\t"
" cvtps2pi %%xmm0, %%mm1 \n\t" /* high part to int */
" cvtps2pi %%xmm2, %%mm3 \n\t"
" packssdw %%mm1, %%mm0 \n\t" /* pack parts */
" packssdw %%mm3, %%mm2 \n\t"
" movq %%mm0, (%3, %0) \n\t"
" movq %%mm2, 8(%3, %0) \n\t"
" add $16, %0 \n\t"
" dec %1 \n\t"
" jne 1b \n\t"
"2: \n\t"
" mov %4, %1 \n\t" /* prepare for leftovers */
" and $15, %1 \n\t"
" je 4f \n\t"
"3: \n\t"
" movss (%2, %0, 2), %%xmm0 \n\t"
" minss %%xmm5, %%xmm0 \n\t"
" maxss %%xmm6, %%xmm0 \n\t"
" mulss %%xmm7, %%xmm0 \n\t"
" cvtss2si %%xmm0, %4 \n\t"
" movw %w4, (%3, %0) \n\t"
" add $2, %0 \n\t"
" dec %1 \n\t"
" jne 3b \n\t"
"4: \n\t"
" emms \n\t"
: "=&r" (i), "=&r" (temp)
: "r" (a), "r" (b), "r" ((pa_reg_x86)n), "m" (*one), "m" (*mone), "m" (*scale)
: "cc", "memory"
);
}
static void pa_sconv_s16le_from_f32ne_sse2(unsigned n, const float *a, int16_t *b) {
pa_reg_x86 temp, i;
__asm__ __volatile__ (
" movaps %5, %%xmm5 \n\t"
" movaps %6, %%xmm6 \n\t"
" movaps %7, %%xmm7 \n\t"
" xor %0, %0 \n\t"
" mov %4, %1 \n\t"
" sar $3, %1 \n\t" /* 8 floats at a time */
" cmp $0, %1 \n\t"
" je 2f \n\t"
"1: \n\t"
" movups (%2, %0, 2), %%xmm0 \n\t" /* read 8 floats */
" movups 16(%2, %0, 2), %%xmm2 \n\t"
" minps %%xmm5, %%xmm0 \n\t" /* clamp to 1.0 */
" minps %%xmm5, %%xmm2 \n\t"
" maxps %%xmm6, %%xmm0 \n\t" /* clamp to -1.0 */
" maxps %%xmm6, %%xmm2 \n\t"
" mulps %%xmm7, %%xmm0 \n\t" /* *= 0x7fff */
" mulps %%xmm7, %%xmm2 \n\t"
" cvtps2dq %%xmm0, %%xmm0 \n\t"
" cvtps2dq %%xmm2, %%xmm2 \n\t"
" packssdw %%xmm2, %%xmm0 \n\t"
" movdqu %%xmm0, (%3, %0) \n\t"
" add $16, %0 \n\t"
" dec %1 \n\t"
" jne 1b \n\t"
"2: \n\t"
" mov %4, %1 \n\t" /* prepare for leftovers */
" and $15, %1 \n\t"
" je 4f \n\t"
"3: \n\t"
" movss (%2, %0, 2), %%xmm0 \n\t"
" minss %%xmm5, %%xmm0 \n\t"
" maxss %%xmm6, %%xmm0 \n\t"
" mulss %%xmm7, %%xmm0 \n\t"
" cvtss2si %%xmm0, %4 \n\t"
" movw %w4, (%3, %0) \n\t"
" add $2, %0 \n\t"
" dec %1 \n\t"
" jne 3b \n\t"
"4: \n\t"
: "=&r" (i), "=&r" (temp)
: "r" (a), "r" (b), "r" ((pa_reg_x86)n), "m" (*one), "m" (*mone), "m" (*scale)
: "cc", "memory"
);
}
#undef RUN_TEST
#ifdef RUN_TEST
#define SAMPLES 1019
#define TIMES 1000
static void run_test (void) {
int16_t samples[SAMPLES];
int16_t samples_ref[SAMPLES];
float floats[SAMPLES];
int i;
pa_usec_t start, stop;
pa_convert_func_t func;
printf ("checking SSE %zd\n", sizeof (samples));
memset (samples_ref, 0, sizeof (samples_ref));
memset (samples, 0, sizeof (samples));
for (i = 0; i < SAMPLES; i++) {
floats[i] = (rand()/(RAND_MAX+2.2)) - 1.1;
}
func = pa_get_convert_from_float32ne_function (PA_SAMPLE_S16LE);
func (SAMPLES, floats, samples_ref);
pa_sconv_s16le_from_f32ne_sse2 (SAMPLES, floats, samples);
for (i = 0; i < SAMPLES; i++) {
if (samples[i] != samples_ref[i]) {
printf ("%d: %04x != %04x (%f)\n", i, samples[i], samples_ref[i],
floats[i]);
}
}
start = pa_rtclock_now();
for (i = 0; i < TIMES; i++) {
pa_sconv_s16le_from_f32ne_sse2 (SAMPLES, floats, samples);
}
stop = pa_rtclock_now();
pa_log_info("SSE: %llu usec.", (long long unsigned int)(stop - start));
start = pa_rtclock_now();
for (i = 0; i < TIMES; i++) {
func (SAMPLES, floats, samples_ref);
}
stop = pa_rtclock_now();
pa_log_info("ref: %llu usec.", (long long unsigned int)(stop - start));
}
#endif
#endif /* defined (__i386__) || defined (__amd64__) */
void pa_convert_func_init_sse (pa_cpu_x86_flag_t flags) {
#if defined (__i386__) || defined (__amd64__)
pa_log_info("Initialising SSE optimized conversions.");
#ifdef RUN_TEST
run_test ();
#endif
if (flags & PA_CPU_X86_SSE2)
pa_set_convert_from_float32ne_function (PA_SAMPLE_S16LE, (pa_convert_func_t) pa_sconv_s16le_from_f32ne_sse2);
else
pa_set_convert_from_float32ne_function (PA_SAMPLE_S16LE, (pa_convert_func_t) pa_sconv_s16le_from_f32ne_sse);
#endif /* defined (__i386__) || defined (__amd64__) */
}

View file

@ -134,8 +134,7 @@ static void reset_callbacks(pa_sink_input *i) {
int pa_sink_input_new(
pa_sink_input **_i,
pa_core *core,
pa_sink_input_new_data *data,
pa_sink_input_flags_t flags) {
pa_sink_input_new_data *data) {
pa_sink_input *i;
pa_resampler *resampler = NULL;
@ -198,15 +197,15 @@ int pa_sink_input_new(
if (!data->muted_is_set)
data->muted = FALSE;
if (flags & PA_SINK_INPUT_FIX_FORMAT)
if (data->flags & PA_SINK_INPUT_FIX_FORMAT)
data->sample_spec.format = data->sink->sample_spec.format;
if (flags & PA_SINK_INPUT_FIX_RATE)
if (data->flags & PA_SINK_INPUT_FIX_RATE)
data->sample_spec.rate = data->sink->sample_spec.rate;
original_cm = data->channel_map;
if (flags & PA_SINK_INPUT_FIX_CHANNELS) {
if (data->flags & PA_SINK_INPUT_FIX_CHANNELS) {
data->sample_spec.channels = data->sink->sample_spec.channels;
data->channel_map = data->sink->channel_map;
}
@ -225,7 +224,7 @@ int pa_sink_input_new(
if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], data)) < 0)
return r;
if ((flags & PA_SINK_INPUT_NO_CREATE_ON_SUSPEND) &&
if ((data->flags & PA_SINK_INPUT_NO_CREATE_ON_SUSPEND) &&
pa_sink_get_state(data->sink) == PA_SINK_SUSPENDED) {
pa_log_warn("Failed to create sink input: sink is suspended.");
return -PA_ERR_BADSTATE;
@ -236,7 +235,7 @@ int pa_sink_input_new(
return -PA_ERR_TOOLARGE;
}
if ((flags & PA_SINK_INPUT_VARIABLE_RATE) ||
if ((data->flags & PA_SINK_INPUT_VARIABLE_RATE) ||
!pa_sample_spec_equal(&data->sample_spec, &data->sink->sample_spec) ||
!pa_channel_map_equal(&data->channel_map, &data->sink->channel_map)) {
@ -245,9 +244,9 @@ int pa_sink_input_new(
&data->sample_spec, &data->channel_map,
&data->sink->sample_spec, &data->sink->channel_map,
data->resample_method,
((flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
((flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
(core->disable_remixing || (flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
((data->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
((data->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
(core->disable_remixing || (data->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
(core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)))) {
pa_log_warn("Unsupported resampling operation.");
return -PA_ERR_NOTSUPPORTED;
@ -260,7 +259,7 @@ int pa_sink_input_new(
i->core = core;
i->state = PA_SINK_INPUT_INIT;
i->flags = flags;
i->flags = data->flags;
i->proplist = pa_proplist_copy(data->proplist);
i->driver = pa_xstrdup(pa_path_get_filename(data->driver));
i->module = data->module;
@ -1472,7 +1471,13 @@ pa_bool_t pa_sink_input_safe_to_remove(pa_sink_input *i) {
}
/* Called from IO context */
void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes /* in our sample spec */, pa_bool_t rewrite, pa_bool_t flush, pa_bool_t dont_rewind_render) {
void pa_sink_input_request_rewind(
pa_sink_input *i,
size_t nbytes /* in our sample spec */,
pa_bool_t rewrite,
pa_bool_t flush,
pa_bool_t dont_rewind_render) {
size_t lbq;
/* If 'rewrite' is TRUE the sink is rewound as far as requested
@ -1487,19 +1492,20 @@ void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes /* in our sam
* dont_rewind_render is TRUE then the render memblockq is not
* rewound. */
/* nbytes = 0 means maximum rewind request */
pa_sink_input_assert_ref(i);
pa_sink_input_assert_io_context(i);
nbytes = PA_MAX(i->thread_info.rewrite_nbytes, nbytes);
/* pa_log_debug("request rewrite %lu", (unsigned long) nbytes); */
pa_assert(rewrite || flush);
pa_assert(!dont_rewind_render || !rewrite);
/* We don't take rewind requests while we are corked */
if (i->thread_info.state == PA_SINK_INPUT_CORKED)
return;
pa_assert(rewrite || flush);
pa_assert(!dont_rewind_render || !rewrite);
nbytes = PA_MAX(i->thread_info.rewrite_nbytes, nbytes);
/* pa_log_debug("request rewrite %zu", nbytes); */
/* Calculate how much we can rewind locally without having to
* touch the sink */
@ -1519,6 +1525,7 @@ void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes /* in our sam
nbytes = pa_resampler_request(i->thread_info.resampler, nbytes);
}
/* Remember how much we actually want to rewrite */
if (i->thread_info.rewrite_nbytes != (size_t) -1) {
if (rewrite) {
/* Make sure to not overwrite over underruns */

View file

@ -212,7 +212,7 @@ struct pa_sink_input {
pa_bool_t attached:1; /* True only between ->attach() and ->detach() calls */
/* 0: rewrite nothing, (size_t) -1: rewrite everything, otherwise how many bytes to rewrite */
/* rewrite_nbytes: 0: rewrite nothing, (size_t) -1: rewrite everything, otherwise how many bytes to rewrite */
pa_bool_t rewrite_flush:1, dont_rewind_render:1;
size_t rewrite_nbytes;
uint64_t underrun_for, playing_for;
@ -256,6 +256,8 @@ typedef struct pa_sink_input_send_event_hook_data {
} pa_sink_input_send_event_hook_data;
typedef struct pa_sink_input_new_data {
pa_sink_input_flags_t flags;
pa_proplist *proplist;
const char *driver;
@ -298,8 +300,7 @@ void pa_sink_input_new_data_done(pa_sink_input_new_data *data);
int pa_sink_input_new(
pa_sink_input **i,
pa_core *core,
pa_sink_input_new_data *data,
pa_sink_input_flags_t flags);
pa_sink_input_new_data *data);
void pa_sink_input_put(pa_sink_input *i);
void pa_sink_input_unlink(pa_sink_input* i);

View file

@ -236,6 +236,7 @@ pa_sink* pa_sink_new(
s->core = core;
s->state = PA_SINK_INIT;
s->flags = flags;
s->priority = 0;
s->suspend_cause = 0;
s->name = pa_xstrdup(name);
s->proplist = pa_proplist_copy(data->proplist);
@ -243,6 +244,8 @@ pa_sink* pa_sink_new(
s->module = data->module;
s->card = data->card;
s->priority = pa_device_init_priority(s->proplist);
s->sample_spec = data->sample_spec;
s->channel_map = data->channel_map;
@ -2695,3 +2698,48 @@ pa_bool_t pa_device_init_intended_roles(pa_proplist *p) {
return FALSE;
}
unsigned pa_device_init_priority(pa_proplist *p) {
const char *s;
unsigned priority = 0;
pa_assert(p);
if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_CLASS))) {
if (pa_streq(s, "sound"))
priority += 9000;
else if (!pa_streq(s, "modem"))
priority += 1000;
}
if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR))) {
if (pa_streq(s, "internal"))
priority += 900;
else if (pa_streq(s, "speaker"))
priority += 500;
else if (pa_streq(s, "headphone"))
priority += 400;
}
if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_BUS))) {
if (pa_streq(s, "pci"))
priority += 50;
else if (pa_streq(s, "usb"))
priority += 40;
else if (pa_streq(s, "bluetooth"))
priority += 30;
}
if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_NAME))) {
if (pa_startswith(s, "analog-"))
priority += 9;
else if (pa_startswith(s, "iec958-"))
priority += 8;
}
return priority;
}

View file

@ -109,6 +109,8 @@ struct pa_sink {
pa_hashmap *ports;
pa_device_port *active_port;
unsigned priority;
/* Called when the main loop requests a state change. Called from
* main loop context. If returns -1 the state change will be
* inhibited */
@ -288,6 +290,7 @@ void pa_sink_update_flags(pa_sink *s, pa_sink_flags_t mask, pa_sink_flags_t valu
pa_bool_t pa_device_init_description(pa_proplist *p);
pa_bool_t pa_device_init_icon(pa_proplist *p, pa_bool_t is_sink);
pa_bool_t pa_device_init_intended_roles(pa_proplist *p);
unsigned pa_device_init_priority(pa_proplist *p);
/**** May be called by everyone, from main context */

View file

@ -311,7 +311,7 @@ int pa_play_file(
pa_proplist_sets(data.proplist, PA_PROP_MEDIA_FILENAME, fname);
pa_sndfile_init_proplist(u->sndfile, data.proplist);
pa_sink_input_new(&u->sink_input, sink->core, &data, 0);
pa_sink_input_new(&u->sink_input, sink->core, &data);
pa_sink_input_new_data_done(&data);
if (!u->sink_input)
@ -334,8 +334,7 @@ int pa_play_file(
return 0;
fail:
if (u)
file_stream_unref(u);
file_stream_unref(u);
if (fd >= 0)
pa_close(fd);

View file

@ -101,8 +101,7 @@ static void reset_callbacks(pa_source_output *o) {
int pa_source_output_new(
pa_source_output**_o,
pa_core *core,
pa_source_output_new_data *data,
pa_source_output_flags_t flags) {
pa_source_output_new_data *data) {
pa_source_output *o;
pa_resampler *resampler = NULL;
@ -146,13 +145,13 @@ int pa_source_output_new(
pa_return_val_if_fail(pa_channel_map_valid(&data->channel_map), -PA_ERR_INVALID);
pa_return_val_if_fail(pa_channel_map_compatible(&data->channel_map, &data->sample_spec), -PA_ERR_INVALID);
if (flags & PA_SOURCE_OUTPUT_FIX_FORMAT)
if (data->flags & PA_SOURCE_OUTPUT_FIX_FORMAT)
data->sample_spec.format = data->source->sample_spec.format;
if (flags & PA_SOURCE_OUTPUT_FIX_RATE)
if (data->flags & PA_SOURCE_OUTPUT_FIX_RATE)
data->sample_spec.rate = data->source->sample_spec.rate;
if (flags & PA_SOURCE_OUTPUT_FIX_CHANNELS) {
if (data->flags & PA_SOURCE_OUTPUT_FIX_CHANNELS) {
data->sample_spec.channels = data->source->sample_spec.channels;
data->channel_map = data->source->channel_map;
}
@ -168,7 +167,7 @@ int pa_source_output_new(
if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_FIXATE], data)) < 0)
return r;
if ((flags & PA_SOURCE_OUTPUT_NO_CREATE_ON_SUSPEND) &&
if ((data->flags & PA_SOURCE_OUTPUT_NO_CREATE_ON_SUSPEND) &&
pa_source_get_state(data->source) == PA_SOURCE_SUSPENDED) {
pa_log("Failed to create source output: source is suspended.");
return -PA_ERR_BADSTATE;
@ -179,7 +178,7 @@ int pa_source_output_new(
return -PA_ERR_TOOLARGE;
}
if ((flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ||
if ((data->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ||
!pa_sample_spec_equal(&data->sample_spec, &data->source->sample_spec) ||
!pa_channel_map_equal(&data->channel_map, &data->source->channel_map)) {
@ -188,9 +187,9 @@ int pa_source_output_new(
&data->source->sample_spec, &data->source->channel_map,
&data->sample_spec, &data->channel_map,
data->resample_method,
((flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
((flags & PA_SOURCE_OUTPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
(core->disable_remixing || (flags & PA_SOURCE_OUTPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
((data->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
((data->flags & PA_SOURCE_OUTPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
(core->disable_remixing || (data->flags & PA_SOURCE_OUTPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
(core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)))) {
pa_log_warn("Unsupported resampling operation.");
return -PA_ERR_NOTSUPPORTED;
@ -203,7 +202,7 @@ int pa_source_output_new(
o->core = core;
o->state = PA_SOURCE_OUTPUT_INIT;
o->flags = flags;
o->flags = data->flags;
o->proplist = pa_proplist_copy(data->proplist);
o->driver = pa_xstrdup(pa_path_get_filename(data->driver));
o->module = data->module;

View file

@ -201,6 +201,8 @@ typedef struct pa_source_output_send_event_hook_data {
} pa_source_output_send_event_hook_data;
typedef struct pa_source_output_new_data {
pa_source_output_flags_t flags;
pa_proplist *proplist;
pa_sink_input *direct_on_input;
@ -231,8 +233,7 @@ void pa_source_output_new_data_done(pa_source_output_new_data *data);
int pa_source_output_new(
pa_source_output**o,
pa_core *core,
pa_source_output_new_data *data,
pa_source_output_flags_t flags);
pa_source_output_new_data *data);
void pa_source_output_put(pa_source_output *o);
void pa_source_output_unlink(pa_source_output*o);

View file

@ -205,6 +205,7 @@ pa_source* pa_source_new(
s->core = core;
s->state = PA_SOURCE_INIT;
s->flags = flags;
s->priority = 0;
s->suspend_cause = 0;
s->name = pa_xstrdup(name);
s->proplist = pa_proplist_copy(data->proplist);
@ -212,6 +213,8 @@ pa_source* pa_source_new(
s->module = data->module;
s->card = data->card;
s->priority = pa_device_init_priority(s->proplist);
s->sample_spec = data->sample_spec;
s->channel_map = data->channel_map;

View file

@ -96,6 +96,8 @@ struct pa_source {
pa_hashmap *ports;
pa_device_port *active_port;
unsigned priority;
/* Called when the main loop requests a state change. Called from
* main loop context. If returns -1 the state change will be
* inhibited */