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 */ | 
