diff options
author | Tanu Kaskinen <tanuk@iki.fi> | 2009-08-30 20:07:31 +0300 |
---|---|---|
committer | Tanu Kaskinen <tanuk@iki.fi> | 2009-08-30 20:07:31 +0300 |
commit | 0ad2d55cbe86d13d5cd355f2b5d59360d681ccc2 (patch) | |
tree | 42c290cd1f1c05c687d8134e40b63244d4fba4e9 | |
parent | 0e096632c53b746b9f4b4c0249d9e5a18c1c543d (diff) | |
parent | 8bf2e3fe94e0dcd0a39a67c461b787d79adcd0dd (diff) |
Merge branch 'master' of git://0pointer.de/pulseaudio into dbus-work
Conflicts:
src/modules/module-stream-restore.c
46 files changed, 720 insertions, 173 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 16834ee9..623cef57 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c index d0c89aab..f8c5b778 100644 --- a/src/modules/bluetooth/bluetooth-util.c +++ b/src/modules/bluetooth/bluetooth-util.c @@ -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'", diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c index 7571e48a..02fd4240 100644 --- a/src/modules/bluetooth/module-bluetooth-discover.c +++ b/src/modules/bluetooth/module-bluetooth-discover.c @@ -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)) { diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index 4a57ce2d..a186c899 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -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); diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c index aa28f7fd..933fb182 100644 --- a/src/modules/module-ladspa-sink.c +++ b/src/modules/module-ladspa-sink.c @@ -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) diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c index d9edbac0..29c3ddab 100644 --- a/src/modules/module-loopback.c +++ b/src/modules/module-loopback.c @@ -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) diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c index becff55c..6cfd0d15 100644 --- a/src/modules/module-remap-sink.c +++ b/src/modules/module-remap-sink.c @@ -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) diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c index 0be1d722..69b20028 100644 --- a/src/modules/module-sine.c +++ b/src/modules/module-sine.c @@ -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) diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c index d45cf792..8389be67 100644 --- a/src/modules/module-stream-restore.c +++ b/src/modules/module-stream-restore.c @@ -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)) diff --git a/src/modules/module-suspend-on-idle.c b/src/modules/module-suspend-on-idle.c index 70a7b049..7adaa0b1 100644 --- a/src/modules/module-suspend-on-idle.c +++ b/src/modules/module-suspend-on-idle.c @@ -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; diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index c195c045..1a05f57d 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -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) { diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index f147364d..8e1cfe36 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -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) { diff --git a/src/modules/rtp/rtsp_client.c b/src/modules/rtp/rtsp_client.c index 72d304e8..ba657f74 100644 --- a/src/modules/rtp/rtsp_client.c +++ b/src/modules/rtp/rtsp_client.c @@ -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; diff --git a/src/pulse/ext-stream-restore.c b/src/pulse/ext-stream-restore.c index 63c911f8..10e9fd5d 100644 --- a/src/pulse/ext-stream-restore.c +++ b/src/pulse/ext-stream-restore.c @@ -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; diff --git a/src/pulse/proplist.c b/src/pulse/proplist.c index 8b5b6538..faa98b79 100644 --- a/src/pulse/proplist.c +++ b/src/pulse/proplist.c @@ -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; diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c index c7a178d6..23a57d37 100644 --- a/src/pulsecore/cli-text.c +++ b/src/pulsecore/cli-text.c @@ -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)) : "", diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 63751f53..d576d01d 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -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; diff --git a/src/pulsecore/cpu-x86.c b/src/pulsecore/cpu-x86.c index bc093ec0..1ba9f1a4 100644 --- a/src/pulsecore/cpu-x86.c +++ b/src/pulsecore/cpu-x86.c @@ -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__) */ } diff --git a/src/pulsecore/cpu-x86.h b/src/pulsecore/cpu-x86.h index f3f9e56e..f6484c59 100644 --- a/src/pulsecore/cpu-x86.h +++ b/src/pulsecore/cpu-x86.h @@ -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 */ diff --git a/src/pulsecore/llist.h b/src/pulsecore/llist.h index 58b51c68..27f174a9 100644 --- a/src/pulsecore/llist.h +++ b/src/pulsecore/llist.h @@ -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 diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h index 87684ad3..bffcc264 100644 --- a/src/pulsecore/macro.h +++ b/src/pulsecore/macro.h @@ -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 diff --git a/src/pulsecore/namereg.c b/src/pulsecore/namereg.c index e26923d4..37755777 100644 --- a/src/pulsecore/namereg.c +++ b/src/pulsecore/namereg.c @@ -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; } diff --git a/src/pulsecore/namereg.h b/src/pulsecore/namereg.h index 38fae6f5..b5a976d7 100644 --- a/src/pulsecore/namereg.h +++ b/src/pulsecore/namereg.h @@ -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 diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c index fc8ce76f..f15466ce 100644 --- a/src/pulsecore/pdispatch.c +++ b/src/pulsecore/pdispatch.c @@ -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) { diff --git a/src/pulsecore/pdispatch.h b/src/pulsecore/pdispatch.h index dae475af..c5431c2e 100644 --- a/src/pulsecore/pdispatch.h +++ b/src/pulsecore/pdispatch.h @@ -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); diff --git a/src/pulsecore/play-memblockq.c b/src/pulsecore/play-memblockq.c index b0d76993..f528c496 100644 --- a/src/pulsecore/play-memblockq.c +++ b/src/pulsecore/play-memblockq.c @@ -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) diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index cfbaee6f..480af6d5 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -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."); diff --git a/src/pulsecore/protocol-http.c b/src/pulsecore/protocol-http.c index 5220cc91..c09e5348 100644 --- a/src/pulsecore/protocol-http.c +++ b/src/pulsecore/protocol-http.c @@ -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) { diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 6678d847..a5e952a3 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -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; +} diff --git a/src/pulsecore/protocol-native.h b/src/pulsecore/protocol-native.h index 8a8d601c..97126274 100644 --- a/src/pulsecore/protocol-native.h +++ b/src/pulsecore/protocol-native.h @@ -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); diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c index 95ec6ac8..d66db4b7 100644 --- a/src/pulsecore/protocol-simple.c +++ b/src/pulsecore/protocol-simple.c @@ -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) { diff --git a/src/pulsecore/remap_mmx.c b/src/pulsecore/remap_mmx.c index 00252dac..b5fe82ee 100644 --- a/src/pulsecore/remap_mmx.c +++ b/src/pulsecore/remap_mmx.c @@ -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__) diff --git a/src/pulsecore/remap_sse.c b/src/pulsecore/remap_sse.c new file mode 100644 index 00000000..97f2476e --- /dev/null +++ b/src/pulsecore/remap_sse.c @@ -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__) */ +} diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c index f1bfa156..bed5a20d 100644 --- a/src/pulsecore/resampler.c +++ b/src/pulsecore/resampler.c @@ -299,8 +299,7 @@ pa_resampler* pa_resampler_new( return r; fail: - if (r) - pa_xfree(r); + pa_xfree(r); return NULL; } diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c index 6e97e5a9..5fae1928 100644 --- a/src/pulsecore/sample-util.c +++ b/src/pulsecore/sample-util.c @@ -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); diff --git a/src/pulsecore/sconv.c b/src/pulsecore/sconv.c index d06d6985..301f08b4 100644 --- a/src/pulsecore/sconv.c +++ b/src/pulsecore/sconv.c @@ -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); } } diff --git a/src/pulsecore/sconv_sse.c b/src/pulsecore/sconv_sse.c new file mode 100644 index 00000000..ef78fc26 --- /dev/null +++ b/src/pulsecore/sconv_sse.c @@ -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__) */ +} diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 0ad95e6f..d3e7a45c 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -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 */ diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index fe6cf75c..59eabe36 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -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); diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 5cec7747..48c50b0b 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -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; +} diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h index b5284b71..ba547fc3 100644 --- a/src/pulsecore/sink.h +++ b/src/pulsecore/sink.h @@ -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 */ diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c index f41c53f3..16de4923 100644 --- a/src/pulsecore/sound-file-stream.c +++ b/src/pulsecore/sound-file-stream.c @@ -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); diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index 43733400..1509807b 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -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; diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h index aca9ddf2..273b78fc 100644 --- a/src/pulsecore/source-output.h +++ b/src/pulsecore/source-output.h @@ -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); diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 3026654e..1c77e0b9 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -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; diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h index df3f99df..e3e56bc4 100644 --- a/src/pulsecore/source.h +++ b/src/pulsecore/source.h @@ -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 */ |