diff options
Diffstat (limited to 'src')
31 files changed, 1833 insertions, 542 deletions
| diff --git a/src/Makefile.am b/src/Makefile.am index f0d5a5e8..3be28692 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -125,28 +125,7 @@ EXTRA_DIST = \  		daemon/pulseaudio.desktop.in \  		daemon/pulseaudio-kde.desktop.in \  		map-file \ -		daemon/pulseaudio-system.conf \ -		modules/alsa/mixer/profile-sets/default.conf \ -		modules/alsa/mixer/profile-sets/native-instruments-audio4dj.conf \ -		modules/alsa/mixer/profile-sets/native-instruments-audio8dj.conf \ -		modules/alsa/mixer/profile-sets/90-pulseaudio.rules \ -		modules/alsa/mixer/paths/analog-input-aux.conf \ -		modules/alsa/mixer/paths/analog-input.conf \ -		modules/alsa/mixer/paths/analog-input.conf.common \ -		modules/alsa/mixer/paths/analog-input-fm.conf \ -		modules/alsa/mixer/paths/analog-input-linein.conf \ -		modules/alsa/mixer/paths/analog-input-mic.conf \ -		modules/alsa/mixer/paths/analog-input-mic.conf.common \ -		modules/alsa/mixer/paths/analog-input-mic-line.conf \ -		modules/alsa/mixer/paths/analog-input-tvtuner.conf \ -		modules/alsa/mixer/paths/analog-input-video.conf \ -		modules/alsa/mixer/paths/analog-output.conf \ -		modules/alsa/mixer/paths/analog-output-speaker.conf \ -		modules/alsa/mixer/paths/analog-output.conf.common \ -		modules/alsa/mixer/paths/analog-output-headphones.conf \ -		modules/alsa/mixer/paths/analog-output-headphones-2.conf \ -		modules/alsa/mixer/paths/analog-output-lfe-on-mono.conf \ -		modules/alsa/mixer/paths/analog-output-mono.conf +		daemon/pulseaudio-system.conf  pulseconf_DATA = \  		default.pa \ @@ -1088,17 +1067,17 @@ modlibexec_LTLIBRARIES += \  		module-alsa-source.la \  		module-alsa-card.la -alsaprofilesets_DATA = \ +dist_alsaprofilesets_DATA = \  		modules/alsa/mixer/profile-sets/default.conf \  		modules/alsa/mixer/profile-sets/native-instruments-audio4dj.conf \  		modules/alsa/mixer/profile-sets/native-instruments-audio8dj.conf  if HAVE_UDEV -udevrules_DATA = \ +dist_udevrules_DATA = \  		modules/alsa/mixer/profile-sets/90-pulseaudio.rules  endif -alsapaths_DATA = \ +dist_alsapaths_DATA = \  		modules/alsa/mixer/paths/analog-input-aux.conf \  		modules/alsa/mixer/paths/analog-input.conf \  		modules/alsa/mixer/paths/analog-input.conf.common \ @@ -1110,8 +1089,10 @@ alsapaths_DATA = \  		modules/alsa/mixer/paths/analog-input-tvtuner.conf \  		modules/alsa/mixer/paths/analog-input-video.conf \  		modules/alsa/mixer/paths/analog-output.conf \ +		modules/alsa/mixer/paths/analog-output-speaker.conf \  		modules/alsa/mixer/paths/analog-output.conf.common \  		modules/alsa/mixer/paths/analog-output-headphones.conf \ +		modules/alsa/mixer/paths/analog-output-headphones-2.conf \  		modules/alsa/mixer/paths/analog-output-lfe-on-mono.conf \  		modules/alsa/mixer/paths/analog-output-mono.conf @@ -1204,6 +1185,7 @@ endif  if HAVE_FFTW  modlibexec_LTLIBRARIES += \  		module-equalizer-sink.la +bin_SCRIPTS += utils/qpaeq  endif  # These are generated by an M4 script diff --git a/src/daemon/main.c b/src/daemon/main.c index 48911827..e6568364 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -537,6 +537,12 @@ int main(int argc, char *argv[]) {              goto finish;          case PA_CMD_DUMP_CONF: { + +            if (d < argc) { +                pa_log("Too many arguments.\n"); +                goto finish; +            } +              s = pa_daemon_conf_dump(conf);              fputs(s, stdout);              pa_xfree(s); @@ -547,6 +553,11 @@ int main(int argc, char *argv[]) {          case PA_CMD_DUMP_RESAMPLE_METHODS: {              int i; +            if (d < argc) { +                pa_log("Too many arguments.\n"); +                goto finish; +            } +              for (i = 0; i < PA_RESAMPLER_MAX; i++)                  if (pa_resample_method_supported(i))                      printf("%s\n", pa_resample_method_to_string(i)); @@ -561,6 +572,12 @@ int main(int argc, char *argv[]) {              goto finish;          case PA_CMD_VERSION : + +            if (d < argc) { +                pa_log("Too many arguments.\n"); +                goto finish; +            } +              printf(PACKAGE_NAME" "PACKAGE_VERSION"\n");              retval = 0;              goto finish; @@ -568,6 +585,11 @@ int main(int argc, char *argv[]) {          case PA_CMD_CHECK: {              pid_t pid; +            if (d < argc) { +                pa_log("Too many arguments.\n"); +                goto finish; +            } +              if (pa_pid_file_check_running(&pid, "pulseaudio") < 0)                  pa_log_info(_("Daemon not running"));              else { @@ -580,6 +602,11 @@ int main(int argc, char *argv[]) {          }          case PA_CMD_KILL: +            if (d < argc) { +                pa_log("Too many arguments.\n"); +                goto finish; +            } +              if (pa_pid_file_kill(SIGINT, NULL, "pulseaudio") < 0)                  pa_log(_("Failed to kill daemon: %s"), pa_cstrerror(errno));              else @@ -589,6 +616,11 @@ int main(int argc, char *argv[]) {          case PA_CMD_CLEANUP_SHM: +            if (d < argc) { +                pa_log("Too many arguments.\n"); +                goto finish; +            } +              if (pa_shm_cleanup() >= 0)                  retval = 0; @@ -598,6 +630,11 @@ int main(int argc, char *argv[]) {              pa_assert(conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START);      } +    if (d < argc) { +        pa_log("Too many arguments.\n"); +        goto finish; +    } +      if (getuid() == 0 && !conf->system_instance)          pa_log_warn(_("This program is not intended to be run as root (unless --system is specified)."));  #ifndef HAVE_DBUS /* A similar, only a notice worthy check was done earlier, if D-Bus is enabled. */ diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c index 856adb14..ed16c834 100644 --- a/src/modules/alsa/alsa-sink.c +++ b/src/modules/alsa/alsa-sink.c @@ -983,7 +983,7 @@ static int unsuspend(struct userdata *u) {          buffer_size*u->frame_size != u->hwbuf_size) {          pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu/%lu, New %lu/%lu)",                      (unsigned long) u->hwbuf_size, (unsigned long) u->fragment_size, -                    (unsigned long) (buffer_size*u->fragment_size), (unsigned long) (period_size*u->frame_size)); +                    (unsigned long) (buffer_size*u->frame_size), (unsigned long) (period_size*u->frame_size));          goto fail;      } diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c index e775b20c..157698e3 100644 --- a/src/modules/alsa/alsa-source.c +++ b/src/modules/alsa/alsa-source.c @@ -930,7 +930,7 @@ static int unsuspend(struct userdata *u) {          buffer_size*u->frame_size != u->hwbuf_size) {          pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu/%lu, New %lu/%lu)",                      (unsigned long) u->hwbuf_size, (unsigned long) u->fragment_size, -                    (unsigned long) (buffer_size*u->fragment_size), (unsigned long) (period_size*u->frame_size)); +                    (unsigned long) (buffer_size*u->frame_size), (unsigned long) (period_size*u->frame_size));          goto fail;      } diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c index b8d13575..52f12599 100644 --- a/src/modules/alsa/alsa-util.c +++ b/src/modules/alsa/alsa-util.c @@ -259,6 +259,10 @@ int pa_alsa_set_hw_params(          goto finish;      } +    /* We ignore very small sampling rate deviations */ +    if (_ss.rate >= ss->rate*.95 && _ss.rate <= ss->rate*1.05) +        _ss.rate = ss->rate; +      if (require_exact_channel_number) {          if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, _ss.channels)) < 0) {              pa_log_debug("snd_pcm_hw_params_set_channels(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret)); @@ -303,7 +307,7 @@ int pa_alsa_set_hw_params(              if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&                  set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&                  snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) { -                pa_log_debug("Set buffer size first, period size second."); +                pa_log_debug("Set buffer size first (to %lu samples), period size second (to %lu samples).", (unsigned long) _buffer_size, (unsigned long) _period_size);                  goto success;              } @@ -311,7 +315,7 @@ int pa_alsa_set_hw_params(              if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&                  set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&                  snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) { -                pa_log_debug("Set period size first, buffer size second."); +                pa_log_debug("Set period size first (to %lu samples), buffer size second (to %lu samples).", (unsigned long) _period_size, (unsigned long) _buffer_size);                  goto success;              }          } @@ -322,7 +326,7 @@ int pa_alsa_set_hw_params(              /* Third try: set only buffer size */              if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&                  snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) { -                pa_log_debug("Set only buffer size second."); +                pa_log_debug("Set only buffer size (to %lu samples).", (unsigned long) _buffer_size);                  goto success;              }          } @@ -333,7 +337,7 @@ int pa_alsa_set_hw_params(              /* Fourth try: set only period size */              if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&                  snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) { -                pa_log_debug("Set only period size second."); +                pa_log_debug("Set only period size (to %lu samples).", (unsigned long) _period_size);                  goto success;              }          } @@ -374,9 +378,7 @@ success:          goto finish;      } -    /* If the sample rate deviates too much, we need to resample */ -    if (_ss.rate < ss->rate*.95 || _ss.rate > ss->rate*1.05) -        ss->rate = _ss.rate; +    ss->rate = _ss.rate;      ss->channels = _ss.channels;      ss->format = _ss.format; diff --git a/src/modules/dbus/iface-card.c b/src/modules/dbus/iface-card.c index 1714df36..d99c8b95 100644 --- a/src/modules/dbus/iface-card.c +++ b/src/modules/dbus/iface-card.c @@ -452,7 +452,7 @@ static void handle_get_profile_by_name(DBusConnection *conn, DBusMessage *msg, v  static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {      pa_dbusiface_card *c = userdata; -    DBusMessage *signal = NULL; +    DBusMessage *signal_msg = NULL;      pa_assert(core);      pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_CARD); @@ -472,14 +472,14 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3          c->active_profile = c->card->active_profile;          object_path = pa_dbusiface_card_profile_get_path(pa_hashmap_get(c->profiles, c->active_profile->name)); -        pa_assert_se(signal = dbus_message_new_signal(c->path, -                                                      PA_DBUSIFACE_CARD_INTERFACE, -                                                      signals[SIGNAL_ACTIVE_PROFILE_UPDATED].name)); -        pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); +        pa_assert_se(signal_msg = dbus_message_new_signal(c->path, +							  PA_DBUSIFACE_CARD_INTERFACE, +							  signals[SIGNAL_ACTIVE_PROFILE_UPDATED].name)); +        pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); -        pa_dbus_protocol_send_signal(c->dbus_protocol, signal); -        dbus_message_unref(signal); -        signal = NULL; +        pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); +        dbus_message_unref(signal_msg); +        signal_msg = NULL;      }      if (!pa_proplist_equal(c->proplist, c->card->proplist)) { @@ -487,15 +487,15 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3          pa_proplist_update(c->proplist, PA_UPDATE_SET, c->card->proplist); -        pa_assert_se(signal = dbus_message_new_signal(c->path, -                                                      PA_DBUSIFACE_CARD_INTERFACE, -                                                      signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); -        dbus_message_iter_init_append(signal, &msg_iter); +        pa_assert_se(signal_msg = dbus_message_new_signal(c->path, +							  PA_DBUSIFACE_CARD_INTERFACE, +							  signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); +        dbus_message_iter_init_append(signal_msg, &msg_iter);          pa_dbus_append_proplist(&msg_iter, c->proplist); -        pa_dbus_protocol_send_signal(c->dbus_protocol, signal); -        dbus_message_unref(signal); -        signal = NULL; +        pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); +        dbus_message_unref(signal_msg); +        signal_msg = NULL;      }  } diff --git a/src/modules/dbus/iface-client.c b/src/modules/dbus/iface-client.c index 546370f9..31924487 100644 --- a/src/modules/dbus/iface-client.c +++ b/src/modules/dbus/iface-client.c @@ -391,7 +391,7 @@ static void handle_remove_properties(DBusConnection *conn, DBusMessage *msg, voi  static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {      pa_dbusiface_client *c = userdata; -    DBusMessage *signal = NULL; +    DBusMessage *signal_msg = NULL;      pa_assert(core);      pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_CLIENT); @@ -410,15 +410,15 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3          pa_proplist_update(c->proplist, PA_UPDATE_SET, c->client->proplist); -        pa_assert_se(signal = dbus_message_new_signal(c->path, -                                                      PA_DBUSIFACE_CLIENT_INTERFACE, -                                                      signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); -        dbus_message_iter_init_append(signal, &msg_iter); +        pa_assert_se(signal_msg = dbus_message_new_signal(c->path, +							  PA_DBUSIFACE_CLIENT_INTERFACE, +							  signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); +        dbus_message_iter_init_append(signal_msg, &msg_iter);          pa_dbus_append_proplist(&msg_iter, c->proplist); -        pa_dbus_protocol_send_signal(c->dbus_protocol, signal); -        dbus_message_unref(signal); -        signal = NULL; +        pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); +        dbus_message_unref(signal_msg); +        signal_msg = NULL;      }  } diff --git a/src/modules/dbus/iface-core.c b/src/modules/dbus/iface-core.c index 169e8e55..497b59b5 100644 --- a/src/modules/dbus/iface-core.c +++ b/src/modules/dbus/iface-core.c @@ -1488,7 +1488,7 @@ static void handle_exit(DBusConnection *conn, DBusMessage *msg, void *userdata)  static void handle_listen_for_signal(DBusConnection *conn, DBusMessage *msg, void *userdata) {      pa_dbusiface_core *c = userdata; -    const char *signal; +    const char *signal_str;      char **objects = NULL;      int n_objects; @@ -1497,11 +1497,11 @@ static void handle_listen_for_signal(DBusConnection *conn, DBusMessage *msg, voi      pa_assert(c);      pa_assert_se(dbus_message_get_args(msg, NULL, -                                       DBUS_TYPE_STRING, &signal, +                                       DBUS_TYPE_STRING, &signal_str,                                         DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &objects, &n_objects,                                         DBUS_TYPE_INVALID)); -    pa_dbus_protocol_add_signal_listener(c->dbus_protocol, conn, *signal ? signal : NULL, objects, n_objects); +    pa_dbus_protocol_add_signal_listener(c->dbus_protocol, conn, *signal_str ? signal_str : NULL, objects, n_objects);      pa_dbus_send_empty_reply(conn, msg); @@ -1510,15 +1510,15 @@ static void handle_listen_for_signal(DBusConnection *conn, DBusMessage *msg, voi  static void handle_stop_listening_for_signal(DBusConnection *conn, DBusMessage *msg, void *userdata) {      pa_dbusiface_core *c = userdata; -    const char *signal; +    const char *signal_str;      pa_assert(conn);      pa_assert(msg);      pa_assert(c); -    pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &signal, DBUS_TYPE_INVALID)); +    pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &signal_str, DBUS_TYPE_INVALID)); -    pa_dbus_protocol_remove_signal_listener(c->dbus_protocol, conn, *signal ? signal : NULL); +    pa_dbus_protocol_remove_signal_listener(c->dbus_protocol, conn, *signal_str ? signal_str : NULL);      pa_dbus_send_empty_reply(conn, msg);  } @@ -1531,7 +1531,7 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3      pa_dbusiface_sample *sample_iface = NULL;      pa_dbusiface_module *module_iface = NULL;      pa_dbusiface_client *client_iface = NULL; -    DBusMessage *signal = NULL; +    DBusMessage *signal_msg = NULL;      const char *object_path = NULL;      pa_sink *new_fallback_sink = NULL;      pa_source *new_fallback_source = NULL; @@ -1552,21 +1552,21 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3                      && (device_iface = pa_hashmap_get(c->sinks_by_index, PA_UINT32_TO_PTR(new_fallback_sink->index)))) {                      object_path = pa_dbusiface_device_get_path(device_iface); -                    pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                                   PA_DBUS_CORE_INTERFACE, -                                                                   signals[SIGNAL_FALLBACK_SINK_UPDATED].name))); -                    pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); -                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal); -                    dbus_message_unref(signal); -                    signal = NULL; +                    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +								       PA_DBUS_CORE_INTERFACE, +								       signals[SIGNAL_FALLBACK_SINK_UPDATED].name))); +                    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); +                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); +                    dbus_message_unref(signal_msg); +                    signal_msg = NULL;                  } else if (!new_fallback_sink) { -                    pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                                   PA_DBUS_CORE_INTERFACE, -                                                                   signals[SIGNAL_FALLBACK_SINK_UNSET].name))); -                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal); -                    dbus_message_unref(signal); -                    signal = NULL; +                    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +								       PA_DBUS_CORE_INTERFACE, +								       signals[SIGNAL_FALLBACK_SINK_UNSET].name))); +                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); +                    dbus_message_unref(signal_msg); +                    signal_msg = NULL;                  }              } @@ -1579,21 +1579,21 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3                      && (device_iface = pa_hashmap_get(c->sources_by_index, PA_UINT32_TO_PTR(new_fallback_source->index)))) {                      object_path = pa_dbusiface_device_get_path(device_iface); -                    pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                                   PA_DBUS_CORE_INTERFACE, -                                                                   signals[SIGNAL_FALLBACK_SOURCE_UPDATED].name))); -                    pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); -                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal); -                    dbus_message_unref(signal); -                    signal = NULL; +                    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +								       PA_DBUS_CORE_INTERFACE, +								       signals[SIGNAL_FALLBACK_SOURCE_UPDATED].name))); +                    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); +                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); +                    dbus_message_unref(signal_msg); +                    signal_msg = NULL;                  } else if (!new_fallback_source) { -                    pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                                   PA_DBUS_CORE_INTERFACE, -                                                                   signals[SIGNAL_FALLBACK_SOURCE_UNSET].name))); -                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal); -                    dbus_message_unref(signal); -                    signal = NULL; +                    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +								       PA_DBUS_CORE_INTERFACE, +								       signals[SIGNAL_FALLBACK_SOURCE_UNSET].name))); +                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); +                    dbus_message_unref(signal_msg); +                    signal_msg = NULL;                  }              }              break; @@ -1612,10 +1612,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3                  object_path = pa_dbusiface_card_get_path(card_iface); -                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                               PA_DBUS_CORE_INTERFACE, -                                                               signals[SIGNAL_NEW_CARD].name))); -                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); +                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +								   PA_DBUS_CORE_INTERFACE, +								   signals[SIGNAL_NEW_CARD].name))); +                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));              } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {                  if (!(card_iface = pa_hashmap_remove(c->cards, PA_UINT32_TO_PTR(idx)))) @@ -1623,10 +1623,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3                  object_path = pa_dbusiface_card_get_path(card_iface); -                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                               PA_DBUS_CORE_INTERFACE, -                                                               signals[SIGNAL_CARD_REMOVED].name))); -                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); +                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +								   PA_DBUS_CORE_INTERFACE, +								   signals[SIGNAL_CARD_REMOVED].name))); +                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));                  pa_dbusiface_card_free(card_iface);              } @@ -1647,28 +1647,28 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3                  object_path = pa_dbusiface_device_get_path(device_iface); -                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                               PA_DBUS_CORE_INTERFACE, -                                                               signals[SIGNAL_NEW_SINK].name))); -                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); +                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +								   PA_DBUS_CORE_INTERFACE, +								   signals[SIGNAL_NEW_SINK].name))); +                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); -                pa_dbus_protocol_send_signal(c->dbus_protocol, signal); -                dbus_message_unref(signal); -                signal = NULL; +                pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); +                dbus_message_unref(signal_msg); +                signal_msg = NULL;                  if (c->fallback_sink && pa_streq(c->fallback_sink->name, sink->name)) {                      /* We have got default sink change event, but at that point                       * the D-Bus sink object wasn't created yet. Now that the                       * object is created, let's send the fallback sink change                       * signal. */ -                    pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                                   PA_DBUS_CORE_INTERFACE, -                                                                   signals[SIGNAL_FALLBACK_SINK_UPDATED].name))); -                    pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); - -                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal); -                    dbus_message_unref(signal); -                    signal = NULL; +                    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +								       PA_DBUS_CORE_INTERFACE, +								       signals[SIGNAL_FALLBACK_SINK_UPDATED].name))); +                    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + +                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); +                    dbus_message_unref(signal_msg); +                    signal_msg = NULL;                  }              } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { @@ -1678,10 +1678,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3                  object_path = pa_dbusiface_device_get_path(device_iface);                  pa_assert_se(pa_hashmap_remove(c->sinks_by_path, object_path)); -                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                               PA_DBUS_CORE_INTERFACE, -                                                               signals[SIGNAL_SINK_REMOVED].name))); -                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); +                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +								   PA_DBUS_CORE_INTERFACE, +								   signals[SIGNAL_SINK_REMOVED].name))); +                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));                  pa_dbusiface_device_free(device_iface);              } @@ -1702,28 +1702,28 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3                  object_path = pa_dbusiface_device_get_path(device_iface); -                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                               PA_DBUS_CORE_INTERFACE, -                                                               signals[SIGNAL_NEW_SOURCE].name))); -                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); +                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +								   PA_DBUS_CORE_INTERFACE, +								   signals[SIGNAL_NEW_SOURCE].name))); +                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); -                pa_dbus_protocol_send_signal(c->dbus_protocol, signal); -                dbus_message_unref(signal); -                signal = NULL; +                pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); +                dbus_message_unref(signal_msg); +                signal_msg = NULL;                  if (c->fallback_source && pa_streq(c->fallback_source->name, source->name)) {                      /* We have got default source change event, but at that                       * point the D-Bus source object wasn't created yet. Now                       * that the object is created, let's send the fallback                       * source change signal. */ -                    pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                                   PA_DBUS_CORE_INTERFACE, -                                                                   signals[SIGNAL_FALLBACK_SOURCE_UPDATED].name))); -                    pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); - -                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal); -                    dbus_message_unref(signal); -                    signal = NULL; +                    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +								       PA_DBUS_CORE_INTERFACE, +								       signals[SIGNAL_FALLBACK_SOURCE_UPDATED].name))); +                    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + +                    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); +                    dbus_message_unref(signal_msg); +                    signal_msg = NULL;                  }              } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { @@ -1733,10 +1733,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3                  object_path = pa_dbusiface_device_get_path(device_iface);                  pa_assert_se(pa_hashmap_remove(c->sources_by_path, object_path)); -                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                               PA_DBUS_CORE_INTERFACE, -                                                               signals[SIGNAL_SOURCE_REMOVED].name))); -                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); +                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +								   PA_DBUS_CORE_INTERFACE, +								   signals[SIGNAL_SOURCE_REMOVED].name))); +                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));                  pa_dbusiface_device_free(device_iface);              } @@ -1756,10 +1756,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3                  object_path = pa_dbusiface_stream_get_path(stream_iface); -                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                               PA_DBUS_CORE_INTERFACE, -                                                               signals[SIGNAL_NEW_PLAYBACK_STREAM].name))); -                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); +                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +								   PA_DBUS_CORE_INTERFACE, +								   signals[SIGNAL_NEW_PLAYBACK_STREAM].name))); +                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));              } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {                  if (!(stream_iface = pa_hashmap_remove(c->playback_streams, PA_UINT32_TO_PTR(idx)))) @@ -1767,10 +1767,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3                  object_path = pa_dbusiface_stream_get_path(stream_iface); -                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                               PA_DBUS_CORE_INTERFACE, -                                                               signals[SIGNAL_PLAYBACK_STREAM_REMOVED].name))); -                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); +                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +								   PA_DBUS_CORE_INTERFACE, +								   signals[SIGNAL_PLAYBACK_STREAM_REMOVED].name))); +                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));                  pa_dbusiface_stream_free(stream_iface);              } @@ -1790,10 +1790,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3                  object_path = pa_dbusiface_stream_get_path(stream_iface); -                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                               PA_DBUS_CORE_INTERFACE, -                                                               signals[SIGNAL_NEW_RECORD_STREAM].name))); -                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); +                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +								   PA_DBUS_CORE_INTERFACE, +								   signals[SIGNAL_NEW_RECORD_STREAM].name))); +                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));              } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {                  if (!(stream_iface = pa_hashmap_remove(c->record_streams, PA_UINT32_TO_PTR(idx)))) @@ -1801,10 +1801,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3                  object_path = pa_dbusiface_stream_get_path(stream_iface); -                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                               PA_DBUS_CORE_INTERFACE, -                                                               signals[SIGNAL_RECORD_STREAM_REMOVED].name))); -                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); +                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +								   PA_DBUS_CORE_INTERFACE, +								   signals[SIGNAL_RECORD_STREAM_REMOVED].name))); +                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));                  pa_dbusiface_stream_free(stream_iface);              } @@ -1824,10 +1824,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3                  object_path = pa_dbusiface_sample_get_path(sample_iface); -                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                               PA_DBUS_CORE_INTERFACE, -                                                               signals[SIGNAL_NEW_SAMPLE].name))); -                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); +                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +								   PA_DBUS_CORE_INTERFACE, +								   signals[SIGNAL_NEW_SAMPLE].name))); +                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));              } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {                  if (!(sample_iface = pa_hashmap_remove(c->samples, PA_UINT32_TO_PTR(idx)))) @@ -1835,10 +1835,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3                  object_path = pa_dbusiface_sample_get_path(sample_iface); -                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                               PA_DBUS_CORE_INTERFACE, -                                                               signals[SIGNAL_SAMPLE_REMOVED].name))); -                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); +                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +								   PA_DBUS_CORE_INTERFACE, +								   signals[SIGNAL_SAMPLE_REMOVED].name))); +                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));                  pa_dbusiface_sample_free(sample_iface);              } @@ -1858,10 +1858,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3                  object_path = pa_dbusiface_module_get_path(module_iface); -                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                               PA_DBUS_CORE_INTERFACE, -                                                               signals[SIGNAL_NEW_MODULE].name))); -                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); +                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +								   PA_DBUS_CORE_INTERFACE, +								   signals[SIGNAL_NEW_MODULE].name))); +                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));              } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {                  if (!(module_iface = pa_hashmap_remove(c->modules, PA_UINT32_TO_PTR(idx)))) @@ -1869,10 +1869,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3                  object_path = pa_dbusiface_module_get_path(module_iface); -                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                               PA_DBUS_CORE_INTERFACE, -                                                               signals[SIGNAL_MODULE_REMOVED].name))); -                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); +                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +								   PA_DBUS_CORE_INTERFACE, +								   signals[SIGNAL_MODULE_REMOVED].name))); +                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));                  pa_dbusiface_module_free(module_iface);              } @@ -1892,10 +1892,10 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3                  object_path = pa_dbusiface_client_get_path(client_iface); -                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                               PA_DBUS_CORE_INTERFACE, -                                                               signals[SIGNAL_NEW_CLIENT].name))); -                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); +                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +								   PA_DBUS_CORE_INTERFACE, +								   signals[SIGNAL_NEW_CLIENT].name))); +                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));              } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {                  if (!(client_iface = pa_hashmap_remove(c->clients, PA_UINT32_TO_PTR(idx)))) @@ -1903,37 +1903,37 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3                  object_path = pa_dbusiface_client_get_path(client_iface); -                pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                               PA_DBUS_CORE_INTERFACE, -                                                               signals[SIGNAL_CLIENT_REMOVED].name))); -                pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); +                pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +								   PA_DBUS_CORE_INTERFACE, +								   signals[SIGNAL_CLIENT_REMOVED].name))); +                pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));                  pa_dbusiface_client_free(client_iface);              }              break;      } -    if (signal) { -        pa_dbus_protocol_send_signal(c->dbus_protocol, signal); -        dbus_message_unref(signal); +    if (signal_msg) { +        pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); +        dbus_message_unref(signal_msg);      }  }  static pa_hook_result_t extension_registered_cb(void *hook_data, void *call_data, void *slot_data) {      pa_dbusiface_core *c = slot_data;      const char *ext_name = call_data; -    DBusMessage *signal = NULL; +    DBusMessage *signal_msg = NULL;      pa_assert(c);      pa_assert(ext_name); -    pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                   PA_DBUS_CORE_INTERFACE, -                                                   signals[SIGNAL_NEW_EXTENSION].name))); -    pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_STRING, &ext_name, DBUS_TYPE_INVALID)); +    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +						       PA_DBUS_CORE_INTERFACE, +						       signals[SIGNAL_NEW_EXTENSION].name))); +    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_STRING, &ext_name, DBUS_TYPE_INVALID)); -    pa_dbus_protocol_send_signal(c->dbus_protocol, signal); -    dbus_message_unref(signal); +    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); +    dbus_message_unref(signal_msg);      return PA_HOOK_OK;  } @@ -1941,18 +1941,18 @@ static pa_hook_result_t extension_registered_cb(void *hook_data, void *call_data  static pa_hook_result_t extension_unregistered_cb(void *hook_data, void *call_data, void *slot_data) {      pa_dbusiface_core *c = slot_data;      const char *ext_name = call_data; -    DBusMessage *signal = NULL; +    DBusMessage *signal_msg = NULL;      pa_assert(c);      pa_assert(ext_name); -    pa_assert_se((signal = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, -                                                   PA_DBUS_CORE_INTERFACE, -                                                   signals[SIGNAL_EXTENSION_REMOVED].name))); -    pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_STRING, &ext_name, DBUS_TYPE_INVALID)); +    pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, +						       PA_DBUS_CORE_INTERFACE, +						       signals[SIGNAL_EXTENSION_REMOVED].name))); +    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_STRING, &ext_name, DBUS_TYPE_INVALID)); -    pa_dbus_protocol_send_signal(c->dbus_protocol, signal); -    dbus_message_unref(signal); +    pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); +    dbus_message_unref(signal_msg);      return PA_HOOK_OK;  } diff --git a/src/modules/dbus/iface-device.c b/src/modules/dbus/iface-device.c index 3a747a44..bb91d71f 100644 --- a/src/modules/dbus/iface-device.c +++ b/src/modules/dbus/iface-device.c @@ -1063,7 +1063,7 @@ static void handle_source_get_all(DBusConnection *conn, DBusMessage *msg, void *  static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {      pa_dbusiface_device *d = userdata; -    DBusMessage *signal = NULL; +    DBusMessage *signal_msg = NULL;      const pa_cvolume *new_volume = NULL;      pa_bool_t new_mute = FALSE;      pa_sink_state_t new_sink_state = 0; @@ -1099,16 +1099,16 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t          for (i = 0; i < d->volume.channels; ++i)              volume[i] = d->volume.values[i]; -        pa_assert_se(signal = dbus_message_new_signal(d->path, -                                                      PA_DBUSIFACE_DEVICE_INTERFACE, -                                                      signals[SIGNAL_VOLUME_UPDATED].name)); -        pa_assert_se(dbus_message_append_args(signal, +        pa_assert_se(signal_msg = dbus_message_new_signal(d->path, +							  PA_DBUSIFACE_DEVICE_INTERFACE, +							  signals[SIGNAL_VOLUME_UPDATED].name)); +        pa_assert_se(dbus_message_append_args(signal_msg,                                                DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &volume_ptr, d->volume.channels,                                                DBUS_TYPE_INVALID)); -        pa_dbus_protocol_send_signal(d->dbus_protocol, signal); -        dbus_message_unref(signal); -        signal = NULL; +        pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg); +        dbus_message_unref(signal_msg); +        signal_msg = NULL;      }      new_mute = (d->type == DEVICE_TYPE_SINK) ? pa_sink_get_mute(d->sink, FALSE) : pa_source_get_mute(d->source, FALSE); @@ -1116,14 +1116,14 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t      if (d->mute != new_mute) {          d->mute = new_mute; -        pa_assert_se(signal = dbus_message_new_signal(d->path, -                                                      PA_DBUSIFACE_DEVICE_INTERFACE, -                                                      signals[SIGNAL_MUTE_UPDATED].name)); -        pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_BOOLEAN, &d->mute, DBUS_TYPE_INVALID)); +        pa_assert_se(signal_msg = dbus_message_new_signal(d->path, +							  PA_DBUSIFACE_DEVICE_INTERFACE, +							  signals[SIGNAL_MUTE_UPDATED].name)); +        pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_BOOLEAN, &d->mute, DBUS_TYPE_INVALID)); -        pa_dbus_protocol_send_signal(d->dbus_protocol, signal); -        dbus_message_unref(signal); -        signal = NULL; +        pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg); +        dbus_message_unref(signal_msg); +        signal_msg = NULL;      }      if (d->type == DEVICE_TYPE_SINK) @@ -1142,14 +1142,14 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t          state = (d->type == DEVICE_TYPE_SINK) ? d->sink_state : d->source_state; -        pa_assert_se(signal = dbus_message_new_signal(d->path, -                                                      PA_DBUSIFACE_DEVICE_INTERFACE, -                                                      signals[SIGNAL_STATE_UPDATED].name)); -        pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID)); +        pa_assert_se(signal_msg = dbus_message_new_signal(d->path, +							  PA_DBUSIFACE_DEVICE_INTERFACE, +							  signals[SIGNAL_STATE_UPDATED].name)); +        pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID)); -        pa_dbus_protocol_send_signal(d->dbus_protocol, signal); -        dbus_message_unref(signal); -        signal = NULL; +        pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg); +        dbus_message_unref(signal_msg); +        signal_msg = NULL;      }      new_active_port = (d->type == DEVICE_TYPE_SINK) ? d->sink->active_port : d->source->active_port; @@ -1160,14 +1160,14 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t          d->active_port = new_active_port;          object_path = pa_dbusiface_device_port_get_path(pa_hashmap_get(d->ports, d->active_port->name)); -        pa_assert_se(signal = dbus_message_new_signal(d->path, -                                                      PA_DBUSIFACE_DEVICE_INTERFACE, -                                                      signals[SIGNAL_ACTIVE_PORT_UPDATED].name)); -        pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); +        pa_assert_se(signal_msg = dbus_message_new_signal(d->path, +							  PA_DBUSIFACE_DEVICE_INTERFACE, +							  signals[SIGNAL_ACTIVE_PORT_UPDATED].name)); +        pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); -        pa_dbus_protocol_send_signal(d->dbus_protocol, signal); -        dbus_message_unref(signal); -        signal = NULL; +        pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg); +        dbus_message_unref(signal_msg); +        signal_msg = NULL;      }      new_proplist = (d->type == DEVICE_TYPE_SINK) ? d->sink->proplist : d->source->proplist; @@ -1177,15 +1177,15 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t          pa_proplist_update(d->proplist, PA_UPDATE_SET, new_proplist); -        pa_assert_se(signal = dbus_message_new_signal(d->path, -                                                      PA_DBUSIFACE_DEVICE_INTERFACE, -                                                      signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); -        dbus_message_iter_init_append(signal, &msg_iter); +        pa_assert_se(signal_msg = dbus_message_new_signal(d->path, +							  PA_DBUSIFACE_DEVICE_INTERFACE, +							  signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); +        dbus_message_iter_init_append(signal_msg, &msg_iter);          pa_dbus_append_proplist(&msg_iter, d->proplist); -        pa_dbus_protocol_send_signal(d->dbus_protocol, signal); -        dbus_message_unref(signal); -        signal = NULL; +        pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg); +        dbus_message_unref(signal_msg); +        signal_msg = NULL;      }  } diff --git a/src/modules/dbus/iface-module.c b/src/modules/dbus/iface-module.c index e8aea50f..9973166c 100644 --- a/src/modules/dbus/iface-module.c +++ b/src/modules/dbus/iface-module.c @@ -268,7 +268,7 @@ static void handle_unload(DBusConnection *conn, DBusMessage *msg, void *userdata  static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {      pa_dbusiface_module *m = userdata; -    DBusMessage *signal = NULL; +    DBusMessage *signal_msg = NULL;      pa_assert(core);      pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_MODULE); @@ -287,15 +287,15 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3          pa_proplist_update(m->proplist, PA_UPDATE_SET, m->module->proplist); -        pa_assert_se(signal = dbus_message_new_signal(m->path, -                                                      PA_DBUSIFACE_MODULE_INTERFACE, -                                                      signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); -        dbus_message_iter_init_append(signal, &msg_iter); +        pa_assert_se(signal_msg = dbus_message_new_signal(m->path, +							  PA_DBUSIFACE_MODULE_INTERFACE, +							  signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); +        dbus_message_iter_init_append(signal_msg, &msg_iter);          pa_dbus_append_proplist(&msg_iter, m->proplist); -        pa_dbus_protocol_send_signal(m->dbus_protocol, signal); -        dbus_message_unref(signal); -        signal = NULL; +        pa_dbus_protocol_send_signal(m->dbus_protocol, signal_msg); +        dbus_message_unref(signal_msg); +        signal_msg = NULL;      }  } diff --git a/src/modules/dbus/iface-sample.c b/src/modules/dbus/iface-sample.c index b0542a60..c1fa193c 100644 --- a/src/modules/dbus/iface-sample.c +++ b/src/modules/dbus/iface-sample.c @@ -450,7 +450,7 @@ static void handle_remove(DBusConnection *conn, DBusMessage *msg, void *userdata  static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {      pa_dbusiface_sample *s = userdata; -    DBusMessage *signal = NULL; +    DBusMessage *signal_msg = NULL;      pa_assert(c);      pa_assert(s); @@ -468,15 +468,15 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t          pa_proplist_update(s->proplist, PA_UPDATE_SET, s->sample->proplist); -        pa_assert_se(signal = dbus_message_new_signal(s->path, -                                                      PA_DBUSIFACE_SAMPLE_INTERFACE, -                                                      signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); -        dbus_message_iter_init_append(signal, &msg_iter); +        pa_assert_se(signal_msg = dbus_message_new_signal(s->path, +							  PA_DBUSIFACE_SAMPLE_INTERFACE, +							  signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); +        dbus_message_iter_init_append(signal_msg, &msg_iter);          pa_dbus_append_proplist(&msg_iter, s->proplist); -        pa_dbus_protocol_send_signal(s->dbus_protocol, signal); -        dbus_message_unref(signal); -        signal = NULL; +        pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); +        dbus_message_unref(signal_msg); +        signal_msg = NULL;      }  } diff --git a/src/modules/dbus/iface-stream.c b/src/modules/dbus/iface-stream.c index 04a45e6c..0255be4b 100644 --- a/src/modules/dbus/iface-stream.c +++ b/src/modules/dbus/iface-stream.c @@ -632,7 +632,7 @@ static void handle_kill(DBusConnection *conn, DBusMessage *msg, void *userdata)  static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {      pa_dbusiface_stream *s = userdata; -    DBusMessage *signal = NULL; +    DBusMessage *signal_msg = NULL;      const char *new_device_path = NULL;      uint32_t new_sample_rate = 0;      pa_proplist *new_proplist = NULL; @@ -662,14 +662,14 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t              new_device_path = pa_dbusiface_core_get_sink_path(s->core, new_sink); -            pa_assert_se(signal = dbus_message_new_signal(s->path, -                                                          PA_DBUSIFACE_STREAM_INTERFACE, -                                                          signals[SIGNAL_DEVICE_UPDATED].name)); -            pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID)); +            pa_assert_se(signal_msg = dbus_message_new_signal(s->path, +							      PA_DBUSIFACE_STREAM_INTERFACE, +							      signals[SIGNAL_DEVICE_UPDATED].name)); +            pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID)); -            pa_dbus_protocol_send_signal(s->dbus_protocol, signal); -            dbus_message_unref(signal); -            signal = NULL; +            pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); +            dbus_message_unref(signal_msg); +            signal_msg = NULL;          }      } else {          pa_source *new_source = s->source_output->source; @@ -680,14 +680,14 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t              new_device_path = pa_dbusiface_core_get_source_path(s->core, new_source); -            pa_assert_se(signal = dbus_message_new_signal(s->path, -                                                          PA_DBUSIFACE_STREAM_INTERFACE, -                                                          signals[SIGNAL_DEVICE_UPDATED].name)); -            pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID)); +            pa_assert_se(signal_msg = dbus_message_new_signal(s->path, +							      PA_DBUSIFACE_STREAM_INTERFACE, +							      signals[SIGNAL_DEVICE_UPDATED].name)); +            pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID)); -            pa_dbus_protocol_send_signal(s->dbus_protocol, signal); -            dbus_message_unref(signal); -            signal = NULL; +            pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); +            dbus_message_unref(signal_msg); +            signal_msg = NULL;          }      } @@ -696,14 +696,14 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t      if (s->sample_rate != new_sample_rate) {          s->sample_rate = new_sample_rate; -        pa_assert_se(signal = dbus_message_new_signal(s->path, -                                                      PA_DBUSIFACE_STREAM_INTERFACE, -                                                      signals[SIGNAL_SAMPLE_RATE_UPDATED].name)); -        pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_UINT32, &s->sample_rate, DBUS_TYPE_INVALID)); +        pa_assert_se(signal_msg = dbus_message_new_signal(s->path, +							  PA_DBUSIFACE_STREAM_INTERFACE, +							  signals[SIGNAL_SAMPLE_RATE_UPDATED].name)); +        pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_UINT32, &s->sample_rate, DBUS_TYPE_INVALID)); -        pa_dbus_protocol_send_signal(s->dbus_protocol, signal); -        dbus_message_unref(signal); -        signal = NULL; +        pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); +        dbus_message_unref(signal_msg); +        signal_msg = NULL;      }      if (s->type == STREAM_TYPE_PLAYBACK) { @@ -721,16 +721,16 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t              for (i = 0; i < s->volume.channels; ++i)                  volume[i] = s->volume.values[i]; -            pa_assert_se(signal = dbus_message_new_signal(s->path, -                                                          PA_DBUSIFACE_STREAM_INTERFACE, -                                                          signals[SIGNAL_VOLUME_UPDATED].name)); -            pa_assert_se(dbus_message_append_args(signal, +            pa_assert_se(signal_msg = dbus_message_new_signal(s->path, +							      PA_DBUSIFACE_STREAM_INTERFACE, +							      signals[SIGNAL_VOLUME_UPDATED].name)); +            pa_assert_se(dbus_message_append_args(signal_msg,                                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &volume_ptr, s->volume.channels,                                                    DBUS_TYPE_INVALID)); -            pa_dbus_protocol_send_signal(s->dbus_protocol, signal); -            dbus_message_unref(signal); -            signal = NULL; +            pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); +            dbus_message_unref(signal_msg); +            signal_msg = NULL;          }          new_mute = pa_sink_input_get_mute(s->sink_input); @@ -738,14 +738,14 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t          if (s->mute != new_mute) {              s->mute = new_mute; -            pa_assert_se(signal = dbus_message_new_signal(s->path, -                                                          PA_DBUSIFACE_STREAM_INTERFACE, -                                                          signals[SIGNAL_MUTE_UPDATED].name)); -            pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_BOOLEAN, &s->mute, DBUS_TYPE_INVALID)); +            pa_assert_se(signal_msg = dbus_message_new_signal(s->path, +							      PA_DBUSIFACE_STREAM_INTERFACE, +							      signals[SIGNAL_MUTE_UPDATED].name)); +            pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_BOOLEAN, &s->mute, DBUS_TYPE_INVALID)); -            pa_dbus_protocol_send_signal(s->dbus_protocol, signal); -            dbus_message_unref(signal); -            signal = NULL; +            pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); +            dbus_message_unref(signal_msg); +            signal_msg = NULL;          }      } @@ -756,21 +756,21 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t          pa_proplist_update(s->proplist, PA_UPDATE_SET, new_proplist); -        pa_assert_se(signal = dbus_message_new_signal(s->path, -                                                      PA_DBUSIFACE_STREAM_INTERFACE, -                                                      signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); -        dbus_message_iter_init_append(signal, &msg_iter); +        pa_assert_se(signal_msg = dbus_message_new_signal(s->path, +							  PA_DBUSIFACE_STREAM_INTERFACE, +							  signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); +        dbus_message_iter_init_append(signal_msg, &msg_iter);          pa_dbus_append_proplist(&msg_iter, s->proplist); -        pa_dbus_protocol_send_signal(s->dbus_protocol, signal); -        dbus_message_unref(signal); -        signal = NULL; +        pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); +        dbus_message_unref(signal_msg); +        signal_msg = NULL;      }  }  static pa_hook_result_t send_event_cb(void *hook_data, void *call_data, void *slot_data) {      pa_dbusiface_stream *s = slot_data; -    DBusMessage *signal = NULL; +    DBusMessage *signal_msg = NULL;      DBusMessageIter msg_iter;      const char *name = NULL;      pa_proplist *property_list = NULL; @@ -796,15 +796,15 @@ static pa_hook_result_t send_event_cb(void *hook_data, void *call_data, void *sl          property_list = data->data;      } -    pa_assert_se(signal = dbus_message_new_signal(s->path, -                                                  PA_DBUSIFACE_STREAM_INTERFACE, -                                                  signals[SIGNAL_STREAM_EVENT].name)); -    dbus_message_iter_init_append(signal, &msg_iter); +    pa_assert_se(signal_msg = dbus_message_new_signal(s->path, +						      PA_DBUSIFACE_STREAM_INTERFACE, +						      signals[SIGNAL_STREAM_EVENT].name)); +    dbus_message_iter_init_append(signal_msg, &msg_iter);      pa_assert_se(dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &name));      pa_dbus_append_proplist(&msg_iter, property_list); -    pa_dbus_protocol_send_signal(s->dbus_protocol, signal); -    dbus_message_unref(signal); +    pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); +    dbus_message_unref(signal_msg);      return PA_HOOK_OK;  } diff --git a/src/modules/dbus/module-dbus-protocol.c b/src/modules/dbus/module-dbus-protocol.c index 11064c33..acc6ca04 100644 --- a/src/modules/dbus/module-dbus-protocol.c +++ b/src/modules/dbus/module-dbus-protocol.c @@ -126,7 +126,7 @@ static void client_kill_cb(pa_client *c) {  /* Called from pa_client_send_event(). */  static void client_send_event_cb(pa_client *c, const char *name, pa_proplist *data) {      struct connection *conn = NULL; -    DBusMessage *signal = NULL; +    DBusMessage *signal_msg = NULL;      DBusMessageIter msg_iter;      pa_assert(c); @@ -136,15 +136,15 @@ static void client_send_event_cb(pa_client *c, const char *name, pa_proplist *da      conn = c->userdata; -    pa_assert_se(signal = dbus_message_new_signal(pa_dbusiface_core_get_client_path(conn->server->userdata->core_iface, c), -                                                  PA_DBUSIFACE_CLIENT_INTERFACE, -                                                  "ClientEvent")); -    dbus_message_iter_init_append(signal, &msg_iter); +    pa_assert_se(signal_msg = dbus_message_new_signal(pa_dbusiface_core_get_client_path(conn->server->userdata->core_iface, c), +						      PA_DBUSIFACE_CLIENT_INTERFACE, +						      "ClientEvent")); +    dbus_message_iter_init_append(signal_msg, &msg_iter);      pa_assert_se(dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &name));      pa_dbus_append_proplist(&msg_iter, data); -    pa_assert_se(dbus_connection_send(pa_dbus_wrap_connection_get(conn->wrap_conn), signal, NULL)); -    dbus_message_unref(signal); +    pa_assert_se(dbus_connection_send(pa_dbus_wrap_connection_get(conn->wrap_conn), signal_msg, NULL)); +    dbus_message_unref(signal_msg);  }  /* Called by D-Bus at the authentication phase. */ diff --git a/src/modules/module-device-manager.c b/src/modules/module-device-manager.c index 3991043d..8d61ff4c 100644 --- a/src/modules/module-device-manager.c +++ b/src/modules/module-device-manager.c @@ -1032,27 +1032,27 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio          if ((e = read_entry(u, name))) {              uint32_t idx; -            char *devname; +            char *device_name;              uint32_t found_index = PA_INVALID_INDEX; -            if ((devname = get_name(name, "sink:"))) { +            if ((device_name = get_name(name, "sink:"))) {                  pa_sink* s;                  PA_IDXSET_FOREACH(s, u->core->sinks, idx) { -                    if (strcmp(s->name, devname) == 0) { +                    if (strcmp(s->name, device_name) == 0) {                          found_index = s->index;                          break;                      }                  } -                pa_xfree(devname); -            } else if ((devname = get_name(name, "source:"))) { +                pa_xfree(device_name); +            } else if ((device_name = get_name(name, "source:"))) {                  pa_source* s;                  PA_IDXSET_FOREACH(s, u->core->sources, idx) { -                    if (strcmp(s->name, devname) == 0) { +                    if (strcmp(s->name, device_name) == 0) {                          found_index = s->index;                          break;                      }                  } -                pa_xfree(devname); +                pa_xfree(device_name);              }              pa_tagstruct_puts(reply, name); diff --git a/src/modules/module-equalizer-sink.c b/src/modules/module-equalizer-sink.c index 7c0ccd3a..0a2860b0 100644 --- a/src/modules/module-equalizer-sink.c +++ b/src/modules/module-equalizer-sink.c @@ -113,8 +113,11 @@ struct userdata {      float **Xs;      float ***Hs;//thread updatable copies of the freq response filters (magintude based)      pa_aupdate **a_H; -    pa_memchunk conv_buffer;      pa_memblockq *input_q; +    char *output_buffer; +    size_t output_buffer_length; +    size_t output_buffer_max_length; +    pa_memblockq *output_q;      pa_bool_t first_iteration;      pa_dbus_protocol *dbus_protocol; @@ -250,10 +253,11 @@ static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t of                  pa_sink_get_latency_within_thread(u->sink_input->sink) +                  /* Add the latency internal to our sink input on top */ -                pa_bytes_to_usec(pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq), &u->sink_input->sink->sample_spec); +                pa_bytes_to_usec(pa_memblockq_get_length(u->output_q), &u->sink_input->sink->sample_spec) + +                pa_bytes_to_usec(pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq), &u->sink_input->sink->sample_spec) + +                pa_bytes_to_usec(pa_memblockq_get_length(u->input_q), &u->sink_input->sink->sample_spec);              //    pa_bytes_to_usec(u->samples_gathered * fs, &u->sink->sample_spec);              //+ pa_bytes_to_usec(u->latency * fs, ss) -            //+ pa_bytes_to_usec(pa_memblockq_get_length(u->input_q), ss);              return 0;          }      } @@ -337,7 +341,7 @@ static void sink_set_mute_cb(pa_sink *s) {      pa_sink_input_set_mute(u->sink_input, s->muted, s->save_muted);  } -#ifndef __SSE2__ +#if 1  //reference implementation  static void dsp_logic(      float * restrict dst,//used as a temp array too, needs to be fft_length! @@ -489,18 +493,42 @@ static void dsp_logic(  }  #endif -static void process_samples(struct userdata *u, pa_memchunk *tchunk){ +static void flatten_to_memblockq(struct userdata *u){ +    size_t mbs = pa_mempool_block_size_max(u->sink->core->mempool); +    pa_memchunk tchunk; +    char *dst; +    size_t i = 0; +    while(i < u->output_buffer_length){ +        tchunk.index = 0; +        tchunk.length = PA_MIN((u->output_buffer_length - i), mbs); +        tchunk.memblock = pa_memblock_new(u->sink->core->mempool, tchunk.length); +        //pa_log_debug("pushing %ld into the q", tchunk.length); +        dst = pa_memblock_acquire(tchunk.memblock); +        memcpy(dst, u->output_buffer + i, tchunk.length); +        pa_memblock_release(tchunk.memblock); +        pa_memblockq_push(u->output_q, &tchunk); +        pa_memblock_unref(tchunk.memblock); +        i += tchunk.length; +    } +} + +static void process_samples(struct userdata *u){      size_t fs = pa_frame_size(&(u->sink->sample_spec)); -    float *dst;      unsigned a_i;      float *H, X;      size_t iterations, offset;      pa_assert(u->samples_gathered >= u->window_size);      iterations = (u->samples_gathered - u->overlap_size) / u->R; -    tchunk->index = 0; -    tchunk->length = iterations * u->R * fs; -    tchunk->memblock = pa_memblock_new(u->sink->core->mempool, tchunk->length); -    dst = ((float*) pa_memblock_acquire(tchunk->memblock)); +    //make sure there is enough buffer memory allocated +    if(iterations * u->R * fs > u->output_buffer_max_length){ +        u->output_buffer_max_length = iterations * u->R * fs; +        if(u->output_buffer){ +            pa_xfree(u->output_buffer); +        } +        u->output_buffer = pa_xmalloc(u->output_buffer_max_length); +    } +    u->output_buffer_length = iterations * u->R * fs; +      for(size_t iter = 0; iter < iterations; ++iter){          offset = iter * u->R * fs;          for(size_t c = 0;c < u->channels; c++) { @@ -526,14 +554,14 @@ static void process_samples(struct userdata *u, pa_memchunk *tchunk){                      u->work_buffer[i] = u->W[i] <= FLT_EPSILON ? u->work_buffer[i] : u->work_buffer[i] / u->W[i];                  }              } -            pa_sample_clamp(PA_SAMPLE_FLOAT32NE, (uint8_t *) (dst + c) + offset, fs, u->work_buffer, sizeof(float), u->R); +            pa_sample_clamp(PA_SAMPLE_FLOAT32NE, (uint8_t *) (((float *)u->output_buffer) + c) + offset, fs, u->work_buffer, sizeof(float), u->R);          }          if(u->first_iteration){              u->first_iteration = FALSE;          }          u->samples_gathered -= u->R;      } -    pa_memblock_release(tchunk->memblock); +    flatten_to_memblockq(u);  }  static void input_buffer(struct userdata *u, pa_memchunk *in){ @@ -556,7 +584,8 @@ static void input_buffer(struct userdata *u, pa_memchunk *in){  /* Called from I/O thread context */  static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {      struct userdata *u; -    size_t fs, target_samples, mbs; +    size_t fs, target_samples; +    size_t mbs;      //struct timeval start, end;      pa_memchunk tchunk;      pa_sink_input_assert_ref(i); @@ -564,13 +593,17 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk      pa_assert(chunk);      pa_assert(u->sink);      fs = pa_frame_size(&(u->sink->sample_spec)); -    nbytes = PA_MIN(nbytes, pa_mempool_block_size_max(u->sink->core->mempool)); -    target_samples = PA_ROUND_UP(nbytes / fs, u->R);      mbs = pa_mempool_block_size_max(u->sink->core->mempool); -    //pa_log_debug("vanilla mbs = %ld",mbs); -    mbs = PA_ROUND_DOWN(mbs / fs, u->R); -    mbs = PA_MAX(mbs, u->R); -    target_samples = PA_MAX(target_samples, mbs); +    if(pa_memblockq_get_length(u->output_q) > 0){ +        //pa_log_debug("qsize is %ld", pa_memblockq_get_length(u->output_q)); +        goto END; +    } +    //nbytes = PA_MIN(nbytes, pa_mempool_block_size_max(u->sink->core->mempool)); +    target_samples = PA_ROUND_UP(nbytes / fs, u->R); +    ////pa_log_debug("vanilla mbs = %ld",mbs); +    //mbs = PA_ROUND_DOWN(mbs / fs, u->R); +    //mbs = PA_MAX(mbs, u->R); +    //target_samples = PA_MAX(target_samples, mbs);      //pa_log_debug("target samples: %ld", target_samples);      if(u->first_iteration){          //allocate request_size @@ -594,7 +627,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk          pa_assert(input_remaining > 0);          while(pa_memblockq_peek(u->input_q, &tchunk) < 0){              //pa_sink_render(u->sink, input_remaining * fs, &tchunk); -            pa_sink_render_full(u->sink, input_remaining * fs, &tchunk); +            pa_sink_render_full(u->sink, PA_MIN(input_remaining * fs, mbs), &tchunk);              pa_assert(tchunk.memblock);              pa_memblockq_push(u->input_q, &tchunk);              pa_memblock_unref(tchunk.memblock); @@ -619,11 +652,13 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk      pa_assert(u->R < u->window_size);      //pa_rtclock_get(&start);      /* process a block */ -    process_samples(u, chunk); +    process_samples(u);      //pa_rtclock_get(&end);      //pa_log_debug("Took %0.6f seconds to process", (double) pa_timeval_diff(&end, &start) / PA_USEC_PER_SEC); - +END: +    pa_assert_se(pa_memblockq_peek(u->output_q, chunk) >= 0);      pa_assert(chunk->memblock); +    pa_memblockq_drop(u->output_q, chunk->length);      //pa_log_debug("gave %ld", chunk->length/fs);      //pa_log_debug("end pop");      return 0; @@ -1143,6 +1178,10 @@ int pa__init(pa_module*m) {      u->sink->set_mute = sink_set_mute_cb;      u->sink->userdata = u;      u->input_q = pa_memblockq_new(0,  MEMBLOCKQ_MAXLENGTH, 0, fs, 1, 1, 0, &u->sink->silence); +    u->output_q = pa_memblockq_new(0,  MEMBLOCKQ_MAXLENGTH, 0, fs, 1, 1, 0, NULL); +    u->output_buffer = NULL; +    u->output_buffer_length = 0; +    u->output_buffer_max_length = 0;      pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq);      //pa_sink_set_fixed_latency(u->sink, pa_bytes_to_usec(u->R*fs, &ss)); @@ -1255,6 +1294,10 @@ void pa__done(pa_module*m) {      if (u->sink)          pa_sink_unref(u->sink); +    if(u->output_buffer){ +        pa_xfree(u->output_buffer); +    } +    pa_memblockq_free(u->output_q);      pa_memblockq_free(u->input_q);      fftwf_destroy_plan(u->inverse_plan); diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c index 10cc3415..7a4e730f 100644 --- a/src/modules/module-pipe-sink.c +++ b/src/modules/module-pipe-sink.c @@ -34,6 +34,10 @@  #include <sys/ioctl.h>  #include <poll.h> +#ifdef HAVE_SYS_FILIO_H +#include <sys/filio.h> +#endif +  #include <pulse/xmalloc.h>  #include <pulsecore/core-error.h> @@ -101,9 +105,10 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse          case PA_SINK_MESSAGE_GET_LATENCY: {              size_t n = 0; -            int l;  #ifdef FIONREAD +            int l; +              if (ioctl(u->fd, FIONREAD, &l) >= 0 && l > 0)                  n = (size_t) l;  #endif diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c index de680933..933f0294 100644 --- a/src/modules/module-pipe-source.c +++ b/src/modules/module-pipe-source.c @@ -34,6 +34,10 @@  #include <sys/ioctl.h>  #include <sys/poll.h> +#ifdef HAVE_SYS_FILIO_H +#include <sys/filio.h> +#endif +  #include <pulse/xmalloc.h>  #include <pulsecore/core-error.h> @@ -105,9 +109,10 @@ static int source_process_msg(          case PA_SOURCE_MESSAGE_GET_LATENCY: {              size_t n = 0; -            int l;  #ifdef FIONREAD +            int l; +              if (ioctl(u->fd, FIONREAD, &l) >= 0 && l > 0)                  n = (size_t) l;  #endif diff --git a/src/modules/module-rygel-media-server.c b/src/modules/module-rygel-media-server.c index 4c02e958..82bcd14c 100644 --- a/src/modules/module-rygel-media-server.c +++ b/src/modules/module-rygel-media-server.c @@ -464,8 +464,18 @@ static char **child_array(struct userdata *u, const char *path, unsigned *n) {      if (pa_streq(path, OBJECT_SINKS))          m = pa_idxset_size(u->core->sinks); -    else +    else { +        unsigned k; +          m = pa_idxset_size(u->core->sources); +        k = pa_idxset_size(u->core->sinks); + +        pa_assert(m >= k); + +        /* Subtract the monitor sources from the numbers of +         * sources. There is one monitor source for each sink */ +        m -= k; +    }      array = pa_xnew(char*, m);      *n = 0; @@ -473,14 +483,20 @@ static char **child_array(struct userdata *u, const char *path, unsigned *n) {      if (pa_streq(path, OBJECT_SINKS)) {          pa_sink *sink; -        PA_IDXSET_FOREACH(sink, u->core->sinks, idx) +        PA_IDXSET_FOREACH(sink, u->core->sinks, idx) { +            pa_assert((*n) < m);              array[(*n)++] = pa_sprintf_malloc(OBJECT_SINKS "/%u", sink->index); +        }      } else {          pa_source *source; -        PA_IDXSET_FOREACH(source, u->core->sources, idx) -            if (!source->monitor_of) +        PA_IDXSET_FOREACH(source, u->core->sources, idx) { + +            if (!source->monitor_of) { +                pa_assert((*n) < m);                  array[(*n)++] = pa_sprintf_malloc(OBJECT_SOURCES "/%u", source->index); +            } +        }      }      pa_assert((*n) <= m); @@ -529,16 +545,20 @@ static DBusHandlerResult sinks_and_sources_handler(DBusConnection *c, DBusMessag              free_child_array(array, n);          } else if (message_is_property_get(m, "org.gnome.UPnP.MediaContainer1", "ItemCount")) { +            unsigned n, k; + +            n = pa_idxset_size(u->core->sinks); +            k = pa_idxset_size(u->core->sources); +            pa_assert(k >= n); +              pa_assert_se(r = dbus_message_new_method_return(m));              append_variant_unsigned(r, NULL, -                                    pa_streq(path, OBJECT_SINKS) ? -                                    pa_idxset_size(u->core->sinks) : -                                    pa_idxset_size(u->core->sources)); +                                    pa_streq(path, OBJECT_SINKS) ? n : k - n);          } else if (message_is_property_get_all(m, "org.gnome.UPnP.MediaContainer1")) {              DBusMessageIter iter, sub;              char **array; -            unsigned n; +            unsigned n, k;              pa_assert_se(r = dbus_message_new_method_return(m));              dbus_message_iter_init_append(r, &iter); @@ -550,10 +570,13 @@ static DBusHandlerResult sinks_and_sources_handler(DBusConnection *c, DBusMessag              array = child_array(u, path, &n);              append_property_dict_entry_object_array(r, &sub, "Items", (const char**) array, n);              free_child_array(array, n); + +            n = pa_idxset_size(u->core->sinks); +            k = pa_idxset_size(u->core->sources); +            pa_assert(k >= n); +              append_property_dict_entry_unsigned(r, &sub, "ItemCount", -                                                pa_streq(path, OBJECT_SINKS) ? -                                                pa_idxset_size(u->core->sinks) : -                                                pa_idxset_size(u->core->sources)); +                                                pa_streq(path, OBJECT_SINKS) ? n : k - n);              pa_assert_se(dbus_message_iter_close_container(&iter, &sub)); diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c index 955997ba..396094ce 100644 --- a/src/modules/module-solaris.c +++ b/src/modules/module-solaris.c @@ -327,7 +327,7 @@ static int open_audio_device(struct userdata *u, pa_sample_spec *ss) {      pa_assert(u);      pa_assert(ss); -    if ((u->fd = pa_open_cloexec(u->device_name, u->mode | O_NONBLOCK)) < 0) { +    if ((u->fd = pa_open_cloexec(u->device_name, u->mode | O_NONBLOCK, 0)) < 0) {          pa_log_warn("open %s failed (%s)", u->device_name, pa_cstrerror(errno));          return -1;      } diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c index 788f458b..02c312e3 100644 --- a/src/modules/module-stream-restore.c +++ b/src/modules/module-stream-restore.c @@ -433,29 +433,29 @@ static void append_volume_variant(DBusMessageIter *iter, struct entry *e) {  }  static void send_new_entry_signal(struct dbus_entry *entry) { -    DBusMessage *signal; +    DBusMessage *signal_msg;      pa_assert(entry); -    pa_assert_se(signal = dbus_message_new_signal(OBJECT_PATH, INTERFACE_STREAM_RESTORE, signals[SIGNAL_NEW_ENTRY].name)); -    pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &entry->object_path, DBUS_TYPE_INVALID)); -    pa_dbus_protocol_send_signal(entry->userdata->dbus_protocol, signal); -    dbus_message_unref(signal); +    pa_assert_se(signal_msg = dbus_message_new_signal(OBJECT_PATH, INTERFACE_STREAM_RESTORE, signals[SIGNAL_NEW_ENTRY].name)); +    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &entry->object_path, DBUS_TYPE_INVALID)); +    pa_dbus_protocol_send_signal(entry->userdata->dbus_protocol, signal_msg); +    dbus_message_unref(signal_msg);  }  static void send_entry_removed_signal(struct dbus_entry *entry) { -    DBusMessage *signal; +    DBusMessage *signal_msg;      pa_assert(entry); -    pa_assert_se(signal = dbus_message_new_signal(OBJECT_PATH, INTERFACE_STREAM_RESTORE, signals[SIGNAL_ENTRY_REMOVED].name)); -    pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &entry->object_path, DBUS_TYPE_INVALID)); -    pa_dbus_protocol_send_signal(entry->userdata->dbus_protocol, signal); -    dbus_message_unref(signal); +    pa_assert_se(signal_msg = dbus_message_new_signal(OBJECT_PATH, INTERFACE_STREAM_RESTORE, signals[SIGNAL_ENTRY_REMOVED].name)); +    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &entry->object_path, DBUS_TYPE_INVALID)); +    pa_dbus_protocol_send_signal(entry->userdata->dbus_protocol, signal_msg); +    dbus_message_unref(signal_msg);  }  static void send_device_updated_signal(struct dbus_entry *de, struct entry *e) { -    DBusMessage *signal; +    DBusMessage *signal_msg;      const char *device;      pa_assert(de); @@ -463,28 +463,28 @@ static void send_device_updated_signal(struct dbus_entry *de, struct entry *e) {      device = e->device_valid ? e->device : ""; -    pa_assert_se(signal = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_DEVICE_UPDATED].name)); -    pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_STRING, &device, DBUS_TYPE_INVALID)); -    pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal); -    dbus_message_unref(signal); +    pa_assert_se(signal_msg = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_DEVICE_UPDATED].name)); +    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_STRING, &device, DBUS_TYPE_INVALID)); +    pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal_msg); +    dbus_message_unref(signal_msg);  }  static void send_volume_updated_signal(struct dbus_entry *de, struct entry *e) { -    DBusMessage *signal; +    DBusMessage *signal_msg;      DBusMessageIter msg_iter;      pa_assert(de);      pa_assert(e); -    pa_assert_se(signal = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_VOLUME_UPDATED].name)); -    dbus_message_iter_init_append(signal, &msg_iter); +    pa_assert_se(signal_msg = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_VOLUME_UPDATED].name)); +    dbus_message_iter_init_append(signal_msg, &msg_iter);      append_volume(&msg_iter, e); -    pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal); -    dbus_message_unref(signal); +    pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal_msg); +    dbus_message_unref(signal_msg);  }  static void send_mute_updated_signal(struct dbus_entry *de, struct entry *e) { -    DBusMessage *signal; +    DBusMessage *signal_msg;      dbus_bool_t muted;      pa_assert(de); @@ -494,10 +494,10 @@ static void send_mute_updated_signal(struct dbus_entry *de, struct entry *e) {      muted = e->muted; -    pa_assert_se(signal = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_MUTE_UPDATED].name)); -    pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_BOOLEAN, &muted, DBUS_TYPE_INVALID)); -    pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal); -    dbus_message_unref(signal); +    pa_assert_se(signal_msg = dbus_message_new_signal(de->object_path, INTERFACE_ENTRY, entry_signals[ENTRY_SIGNAL_MUTE_UPDATED].name)); +    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_BOOLEAN, &muted, DBUS_TYPE_INVALID)); +    pa_dbus_protocol_send_signal(de->userdata->dbus_protocol, signal_msg); +    dbus_message_unref(signal_msg);  }  static void handle_get_interface_revision(DBusConnection *conn, DBusMessage *msg, void *userdata) { diff --git a/src/pulse/ext-device-manager.h b/src/pulse/ext-device-manager.h index 8264b8f7..df0ab92f 100644 --- a/src/pulse/ext-device-manager.h +++ b/src/pulse/ext-device-manager.h @@ -39,7 +39,7 @@ typedef struct pa_ext_device_manager_role_priority_info {  } pa_ext_device_manager_role_priority_info;  /** Stores information about one device in the device database that is - * maintained by module-device-manager. \since 0.9.20 */ + * maintained by module-device-manager. \since 0.9.21 */  typedef struct pa_ext_device_manager_info {      const char *name;            /**< Identifier string of the device. A string like "sink:" or similar followed by the name of the device. */      const char *description;     /**< The description of the device when it was last seen, if applicable and saved */ @@ -49,32 +49,32 @@ typedef struct pa_ext_device_manager_info {      pa_ext_device_manager_role_priority_info *role_priorities; /**< An array of role priority structures or NULL */  } pa_ext_device_manager_info; -/** Callback prototype for pa_ext_device_manager_test(). \since 0.9.20 */ +/** Callback prototype for pa_ext_device_manager_test(). \since 0.9.21 */  typedef void (*pa_ext_device_manager_test_cb_t)(          pa_context *c,          uint32_t version,          void *userdata); -/** Test if this extension module is available in the server. \since 0.9.20 */ +/** Test if this extension module is available in the server. \since 0.9.21 */  pa_operation *pa_ext_device_manager_test(          pa_context *c,          pa_ext_device_manager_test_cb_t cb,          void *userdata); -/** Callback prototype for pa_ext_device_manager_read(). \since 0.9.20 */ +/** Callback prototype for pa_ext_device_manager_read(). \since 0.9.21 */  typedef void (*pa_ext_device_manager_read_cb_t)(          pa_context *c,          const pa_ext_device_manager_info *info,          int eol,          void *userdata); -/** Read all entries from the device database. \since 0.9.20 */ +/** Read all entries from the device database. \since 0.9.21 */  pa_operation *pa_ext_device_manager_read(          pa_context *c,          pa_ext_device_manager_read_cb_t cb,          void *userdata); -/** Sets the description for a device. \since 0.9.20 */ +/** Sets the description for a device. \since 0.9.21 */  pa_operation *pa_ext_device_manager_set_device_description(          pa_context *c,          const char* device, @@ -82,21 +82,21 @@ pa_operation *pa_ext_device_manager_set_device_description(          pa_context_success_cb_t cb,          void *userdata); -/** Delete entries from the device database. \since 0.9.20 */ +/** Delete entries from the device database. \since 0.9.21 */  pa_operation *pa_ext_device_manager_delete(          pa_context *c,          const char *const s[],          pa_context_success_cb_t cb,          void *userdata); -/** Enable the role-based device-priority routing mode. \since 0.9.20 */ +/** Enable the role-based device-priority routing mode. \since 0.9.21 */  pa_operation *pa_ext_device_manager_enable_role_device_priority_routing(          pa_context *c,          int enable,          pa_context_success_cb_t cb,          void *userdata); -/** Prefer a given device in the priority list. \since 0.9.20 */ +/** Prefer a given device in the priority list. \since 0.9.21 */  pa_operation *pa_ext_device_manager_reorder_devices_for_role(          pa_context *c,          const char* role, @@ -104,20 +104,20 @@ pa_operation *pa_ext_device_manager_reorder_devices_for_role(          pa_context_success_cb_t cb,          void *userdata); -/** Subscribe to changes in the device database. \since 0.9.20 */ +/** Subscribe to changes in the device database. \since 0.9.21 */  pa_operation *pa_ext_device_manager_subscribe(          pa_context *c,          int enable,          pa_context_success_cb_t cb,          void *userdata); -/** Callback prototype for pa_ext_device_manager_set_subscribe_cb(). \since 0.9.20 */ +/** Callback prototype for pa_ext_device_manager_set_subscribe_cb(). \since 0.9.21 */  typedef void (*pa_ext_device_manager_subscribe_cb_t)(          pa_context *c,          void *userdata);  /** Set the subscription callback that is called when - * pa_ext_device_manager_subscribe() was called. \since 0.9.20 */ + * pa_ext_device_manager_subscribe() was called. \since 0.9.21 */  void pa_ext_device_manager_set_subscribe_cb(          pa_context *c,          pa_ext_device_manager_subscribe_cb_t cb, diff --git a/src/pulse/stream.c b/src/pulse/stream.c index 29979625..4dea5670 100644 --- a/src/pulse/stream.c +++ b/src/pulse/stream.c @@ -387,9 +387,26 @@ static void check_smoother_status(pa_stream *s, pa_bool_t aposteriori, pa_bool_t      if (s->suspended || s->corked || force_stop)          pa_smoother_pause(s->smoother, x); -    else if (force_start || s->buffer_attr.prebuf == 0) -        pa_smoother_resume(s->smoother, x, TRUE); +    else if (force_start || s->buffer_attr.prebuf == 0) { + +        if (!s->timing_info_valid && +            !aposteriori && +            !force_start && +            !force_stop && +            s->context->version >= 13) { + +            /* If the server supports STARTED events we take them as +             * indications when audio really starts/stops playing, if +             * we don't have any timing info yet -- instead of trying +             * to be smart and guessing the server time. Otherwise the +             * unknown transport delay add too much noise to our time +             * calculations. */ + +            return; +        } +        pa_smoother_resume(s->smoother, x, TRUE); +    }      /* Please note that we have no idea if playback actually started       * if prebuf is non-zero! */ @@ -1465,6 +1482,11 @@ pa_operation * pa_stream_drain(pa_stream *s, pa_stream_success_cb_t cb, void *us      PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);      PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE); +    /* Ask for a timing update before we cork/uncork to get the best +     * accuracy for the transport latency suitable for the +     * check_smoother_status() call in the started callback */ +    request_auto_timing_update(s, TRUE); +      o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);      t = pa_tagstruct_command(s->context, PA_COMMAND_DRAIN_PLAYBACK_STREAM, &tag); @@ -1472,6 +1494,10 @@ pa_operation * pa_stream_drain(pa_stream *s, pa_stream_success_cb_t cb, void *us      pa_pstream_send_tagstruct(s->context->pstream, t);      pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); +    /* This might cause the read index to conitnue again, hence +     * let's request a timing update */ +    request_auto_timing_update(s, TRUE); +      return o;  } @@ -2020,6 +2046,11 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, voi      PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);      PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); +    /* Ask for a timing update before we cork/uncork to get the best +     * accuracy for the transport latency suitable for the +     * check_smoother_status() call in the started callback */ +    request_auto_timing_update(s, TRUE); +      s->corked = b;      o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata); @@ -2035,8 +2066,8 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, voi      check_smoother_status(s, FALSE, FALSE, FALSE); -    /* This might cause the indexes to hang/start again, hence -     * let's request a timing update */ +    /* This might cause the indexes to hang/start again, hence let's +     * request a timing update, after the cork/uncork, too */      request_auto_timing_update(s, TRUE);      return o; @@ -2073,6 +2104,11 @@ pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *use      PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);      PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE); +    /* Ask for a timing update *before* the flush, so that the +     * transport usec is as up to date as possible when we get the +     * underflow message and update the smoother status*/ +    request_auto_timing_update(s, TRUE); +      if (!(o = stream_send_simple_command(s, (uint32_t) (s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM), cb, userdata)))          return NULL; @@ -2107,6 +2143,11 @@ pa_operation* pa_stream_prebuf(pa_stream *s, pa_stream_success_cb_t cb, void *us      PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE);      PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->buffer_attr.prebuf > 0, PA_ERR_BADSTATE); +    /* Ask for a timing update before we cork/uncork to get the best +     * accuracy for the transport latency suitable for the +     * check_smoother_status() call in the started callback */ +    request_auto_timing_update(s, TRUE); +      if (!(o = stream_send_simple_command(s, PA_COMMAND_PREBUF_PLAYBACK_STREAM, cb, userdata)))          return NULL; @@ -2128,6 +2169,11 @@ pa_operation* pa_stream_trigger(pa_stream *s, pa_stream_success_cb_t cb, void *u      PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE);      PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->buffer_attr.prebuf > 0, PA_ERR_BADSTATE); +    /* Ask for a timing update before we cork/uncork to get the best +     * accuracy for the transport latency suitable for the +     * check_smoother_status() call in the started callback */ +    request_auto_timing_update(s, TRUE); +      if (!(o = stream_send_simple_command(s, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, cb, userdata)))          return NULL; @@ -2379,6 +2425,11 @@ pa_operation* pa_stream_set_buffer_attr(pa_stream *s, const pa_buffer_attr *attr      PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);      PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->context->version >= 12, PA_ERR_NOTSUPPORTED); +    /* Ask for a timing update before we cork/uncork to get the best +     * accuracy for the transport latency suitable for the +     * check_smoother_status() call in the started callback */ +    request_auto_timing_update(s, TRUE); +      o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);      t = pa_tagstruct_command( diff --git a/src/pulse/util.c b/src/pulse/util.c index 9440f5de..ca766dab 100644 --- a/src/pulse/util.c +++ b/src/pulse/util.c @@ -189,7 +189,18 @@ char *pa_get_binary_name(char *s, size_t l) {              return s;          }      } +#endif +#ifdef __FreeBSD__ +    { +        char *rp; + +	if ((rp = pa_readlink("/proc/curproc/file"))) { +	    pa_strlcpy(s, pa_path_get_filename(rp), l); +	    pa_xfree(rp); +	    return s; +	} +    }  #endif  #if defined(HAVE_SYS_PRCTL_H) && defined(PR_GET_NAME) diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h index 119c445b..51d08210 100644 --- a/src/pulsecore/atomic.h +++ b/src/pulsecore/atomic.h @@ -180,6 +180,110 @@ static inline pa_bool_t pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, v      return r == old_p;  } +#elif defined(__FreeBSD__) + +#include <sys/cdefs.h> +#include <sys/types.h> +#include <sys/param.h> +#include <machine/atomic.h> + +#if __FreeBSD_version < 600000 +#if defined(__i386__) || defined(__amd64__) +#if defined(__amd64__) +#define atomic_load_acq_64      atomic_load_acq_long +#endif +static inline u_int atomic_fetchadd_int(volatile u_int *p, u_int v) { +    __asm __volatile( +            "   " __XSTRING(MPLOCKED) "         " +            "   xaddl   %0, %1 ;        " +            "# atomic_fetchadd_int" +            : "+r" (v), +            "=m" (*p) +            : "m" (*p)); + +    return (v); +} +#elif defined(__sparc64__) +#define atomic_load_acq_64      atomic_load_acq_long +#define atomic_fetchadd_int     atomic_add_int +#elif defined(__ia64__) +#define atomic_load_acq_64      atomic_load_acq_long +static inline uint32_t +atomic_fetchadd_int(volatile uint32_t *p, uint32_t v) { +    uint32_t value; + +    do { +        value = *p; +    } while (!atomic_cmpset_32(p, value, value + v)); +    return (value); +} +#endif +#endif + +typedef struct pa_atomic { +    volatile unsigned long value; +} pa_atomic_t; + +#define PA_ATOMIC_INIT(v) { .value = (v) } + +static inline int pa_atomic_load(const pa_atomic_t *a) { +    return (int) atomic_load_acq_int((unsigned int *) &a->value); +} + +static inline void pa_atomic_store(pa_atomic_t *a, int i) { +    atomic_store_rel_int((unsigned int *) &a->value, i); +} + +static inline int pa_atomic_add(pa_atomic_t *a, int i) { +    return atomic_fetchadd_int((unsigned int *) &a->value, i); +} + +static inline int pa_atomic_sub(pa_atomic_t *a, int i) { +    return atomic_fetchadd_int((unsigned int *) &a->value, -(i)); +} + +static inline int pa_atomic_inc(pa_atomic_t *a) { +    return atomic_fetchadd_int((unsigned int *) &a->value, 1); +} + +static inline int pa_atomic_dec(pa_atomic_t *a) { +    return atomic_fetchadd_int((unsigned int *) &a->value, -1); +} + +static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { +    return atomic_cmpset_int((unsigned int *) &a->value, old_i, new_i); +} + +typedef struct pa_atomic_ptr { +    volatile unsigned long value; +} pa_atomic_ptr_t; + +#define PA_ATOMIC_PTR_INIT(v) { .value = (unsigned long) (v) } + +static inline void* pa_atomic_ptr_load(const pa_atomic_ptr_t *a) { +#ifdef atomic_load_acq_64 +    return (void*) atomic_load_acq_ptr((unsigned long *) &a->value); +#else +    return (void*) atomic_load_acq_ptr((unsigned int *) &a->value); +#endif +} + +static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) { +#ifdef atomic_load_acq_64 +    atomic_store_rel_ptr(&a->value, (unsigned long) p); +#else +    atomic_store_rel_ptr((unsigned int *) &a->value, (unsigned int) p); +#endif +} + +static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { +#ifdef atomic_load_acq_64 +    return atomic_cmpset_ptr(&a->value, (unsigned long) old_p, (unsigned long) new_p); +#else +    return atomic_cmpset_ptr((unsigned int *) &a->value, (unsigned int) old_p, (unsigned int) new_p); +#endif +} +  #elif defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__))  #warn "The native atomic operations implementation for AMD64 has not been tested thoroughly. libatomic_ops is known to not work properly on AMD64 and your gcc version is too old for the gcc-builtin atomic ops support. You have three options now: test the native atomic operations implementation for AMD64, fix libatomic_ops, or upgrade your GCC." diff --git a/src/pulsecore/envelope.c b/src/pulsecore/envelope.c index fd6a9487..0eca8115 100644 --- a/src/pulsecore/envelope.c +++ b/src/pulsecore/envelope.c @@ -177,7 +177,7 @@ static int32_t item_get_int(pa_envelope_item *i, pa_usec_t x) {      pa_assert(i->j > 0);      pa_assert(i->def->points_x[i->j-1] <= x); -    pa_assert(x < i->def->points_x[i->j]); +    pa_assert(x <= i->def->points_x[i->j]);      return linear_interpolate_int(i->def->points_x[i->j-1], i->def->points_y.i[i->j-1],                                    i->def->points_x[i->j], i->def->points_y.i[i->j], x); @@ -200,7 +200,7 @@ static float item_get_float(pa_envelope_item *i, pa_usec_t x) {      pa_assert(i->j > 0);      pa_assert(i->def->points_x[i->j-1] <= x); -    pa_assert(x < i->def->points_x[i->j]); +    pa_assert(x <= i->def->points_x[i->j]);      return linear_interpolate_float(i->def->points_x[i->j-1], i->def->points_y.f[i->j-1],                                      i->def->points_x[i->j], i->def->points_y.f[i->j], x); @@ -550,7 +550,7 @@ static int32_t linear_get_int(pa_envelope *e, int v) {          e->points[v].cached_valid = TRUE;      } -    return e->points[v].y.i[e->points[v].n_current] + (e->points[v].cached_dy_i * (int32_t) (e->x - e->points[v].x[e->points[v].n_current])) / (int32_t) e->points[v].cached_dx; +	return e->points[v].y.i[e->points[v].n_current] + ((float)e->points[v].cached_dy_i * (int32_t) (e->x - e->points[v].x[e->points[v].n_current])) / (int32_t) e->points[v].cached_dx;  }  static float linear_get_float(pa_envelope *e, int v) { @@ -597,34 +597,60 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) {          fs = pa_frame_size(&e->sample_spec);          n = chunk->length; +        pa_log_debug("Envelop position %d applying factor %d=%f, sample spec is %d, chunk's length is %d, fs is %d\n", e->x, linear_get_int(e, v), ((float) linear_get_int(e,v))/0x10000, e->sample_spec.format, n, fs); +          switch (e->sample_spec.format) {              case PA_SAMPLE_U8: { -                uint8_t *t; +                uint8_t *d, *s; +                unsigned channel; +                int32_t factor = linear_get_int(e, v); -                for (t = p; n > 0; n -= fs) { -                    int32_t factor = linear_get_int(e, v); -                    unsigned c; -                    e->x += fs; +                s = (uint8_t*) p + n; -                    for (c = 0; c < e->sample_spec.channels; c++, t++) -                        *t = (uint8_t) (((factor * ((int16_t) *t - 0x80)) / 0x10000) + 0x80); +                for (channel = 0, d = p; d < s; d++) { +                    int32_t t, hi, lo; + +                    hi = factor >> 16; +                    lo = factor & 0xFFFF; + +                    t = (int32_t) *d - 0x80; +                    t = ((t * lo) >> 16) + (t * hi); +                    t = PA_CLAMP_UNLIKELY(t, -0x80, 0x7F); +                    *d = (uint8_t) (t + 0x80); + +                    if (PA_UNLIKELY(++channel >= e->sample_spec.channels)) { +                        channel = 0; +                        e->x += fs; +                        factor = linear_get_int(e, v); +                    }                  }                  break;              }              case PA_SAMPLE_ULAW: { -                uint8_t *t; +                uint8_t *d, *s; +                unsigned channel; +                int32_t factor = linear_get_int(e, v); -                for (t = p; n > 0; n -= fs) { -                    int32_t factor = linear_get_int(e, v); -                    unsigned c; -                    e->x += fs; +                s = (uint8_t*) p + n; -                    for (c = 0; c < e->sample_spec.channels; c++, t++) { -                        int16_t k = st_ulaw2linear16(*t); -                        *t = (uint8_t) st_14linear2ulaw((int16_t) (((factor * k) / 0x10000) >> 2)); +                for (channel = 0, d = p; d < s; d++) { +                    int32_t t, hi, lo; + +                    hi = factor >> 16; +                    lo = factor & 0xFFFF; + +                    t = (int32_t) st_ulaw2linear16(*d); +                    t = ((t * lo) >> 16) + (t * hi); +                    t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF); +                    *d = (uint8_t) st_14linear2ulaw((int16_t) t >> 2); + +                     if (PA_UNLIKELY(++channel >= e->sample_spec.channels)) { +                        channel = 0; +                        e->x += fs; +                        factor = linear_get_int(e, v);                      }                  } @@ -632,16 +658,27 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) {              }              case PA_SAMPLE_ALAW: { -                uint8_t *t; +                uint8_t *d, *s; +                unsigned channel; +                int32_t factor = linear_get_int(e, v); -                for (t = p; n > 0; n -= fs) { -                    int32_t factor = linear_get_int(e, v); -                    unsigned c; -                    e->x += fs; +                s = (uint8_t*) p + n; -                    for (c = 0; c < e->sample_spec.channels; c++, t++) { -                        int16_t k = st_alaw2linear16(*t); -                        *t = (uint8_t) st_13linear2alaw((int16_t) (((factor * k) / 0x10000) >> 3)); +                for (channel = 0, d = p; d < s; d++) { +                    int32_t t, hi, lo; + +                    hi = factor >> 16; +                    lo = factor & 0xFFFF; + +                    t = (int32_t) st_alaw2linear16(*d); +                    t = ((t * lo) >> 16) + (t * hi); +                    t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF); +                    *d = (uint8_t) st_13linear2alaw((int16_t) t >> 3); + +                    if (PA_UNLIKELY(++channel >= e->sample_spec.channels)) { +                        channel = 0; +                        e->x += fs; +                        factor = linear_get_int(e, v);                      }                  } @@ -649,31 +686,55 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) {              }              case PA_SAMPLE_S16NE: { -                int16_t *t; +                int16_t *d, *s; +                unsigned channel; +                int32_t factor = linear_get_int(e, v); -                for (t = p; n > 0; n -= fs) { -                    int32_t factor = linear_get_int(e, v); -                    unsigned c; -                    e->x += fs; +                s = (int16_t*) p + n/sizeof(int16_t); -                    for (c = 0; c < e->sample_spec.channels; c++, t++) -                        *t = (int16_t) ((factor * *t) / 0x10000); +                for (channel = 0, d = p; d < s; d++) { +                    int32_t t, hi, lo; + +                    hi = factor >> 16; +                    lo = factor & 0xFFFF; + +                    t = (int32_t)(*d); +                    t = ((t * lo) >> 16) + (t * hi); +                    t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF); +                    *d = (int16_t) t; + +                    if (PA_UNLIKELY(++channel >= e->sample_spec.channels)) { +                        channel = 0; +                        e->x += fs; +                        factor = linear_get_int(e, v); +                    }                  }                  break;              }              case PA_SAMPLE_S16RE: { -                int16_t *t; +                int16_t *d, *s; +                unsigned channel; +                int32_t factor = linear_get_int(e, v); -                for (t = p; n > 0; n -= fs) { -                    int32_t factor = linear_get_int(e, v); -                    unsigned c; -                    e->x += fs; +                s = (int16_t*) p + n/sizeof(int16_t); -                    for (c = 0; c < e->sample_spec.channels; c++, t++) { -                        int16_t r = (int16_t) ((factor * PA_INT16_SWAP(*t)) / 0x10000); -                        *t = PA_INT16_SWAP(r); +                for (channel = 0, d = p; d < s; d++) { +                    int32_t t, hi, lo; + +                    hi = factor >> 16; +                    lo = factor & 0xFFFF; + +                    t = (int32_t) PA_INT16_SWAP(*d); +                    t = ((t * lo) >> 16) + (t * hi); +                    t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF); +                    *d = PA_INT16_SWAP((int16_t) t); + +                    if (PA_UNLIKELY(++channel >= e->sample_spec.channels)) { +                        channel = 0; +                        e->x += fs; +                        factor = linear_get_int(e, v);                      }                  } @@ -681,31 +742,49 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) {              }              case PA_SAMPLE_S32NE: { -                int32_t *t; +                int32_t *d, *s; +                unsigned channel; +                int32_t factor = linear_get_int(e, v); -                for (t = p; n > 0; n -= fs) { -                    int32_t factor = linear_get_int(e, v); -                    unsigned c; -                    e->x += fs; +                s = (int32_t*) p + n/sizeof(int32_t); -                    for (c = 0; c < e->sample_spec.channels; c++, t++) -                        *t = (int32_t) (((int64_t) factor * (int64_t) *t) / 0x10000); +                for (channel = 0, d = p; d < s; d++) { +                    int64_t t; + +                    t = (int64_t)(*d); +                    t = (t * factor) >> 16; +                    t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL); +                    *d = (int32_t) t; + +                    if (PA_UNLIKELY(++channel >= e->sample_spec.channels)) { +                        channel = 0; +                        e->x += fs; +                        factor = linear_get_int(e, v); +                    }                  }                  break;              }              case PA_SAMPLE_S32RE: { -                int32_t *t; +                int32_t *d, *s; +                unsigned channel; +                int32_t factor = linear_get_int(e, v); -                for (t = p; n > 0; n -= fs) { -                    int32_t factor = linear_get_int(e, v); -                    unsigned c; -                    e->x += fs; +                s = (int32_t*) p + n/sizeof(int32_t); -                    for (c = 0; c < e->sample_spec.channels; c++, t++) { -                        int32_t r = (int32_t) (((int64_t) factor * (int64_t) PA_INT32_SWAP(*t)) / 0x10000); -                        *t = PA_INT32_SWAP(r); +                for (channel = 0, d = p; d < s; d++) { +                    int64_t t; + +                    t = (int64_t) PA_INT32_SWAP(*d); +                    t = (t * factor) >> 16; +                    t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL); +                    *d = PA_INT32_SWAP((int32_t) t); + +                    if (PA_UNLIKELY(++channel >= e->sample_spec.channels)) { +                        channel = 0; +                        e->x += fs; +                        factor = linear_get_int(e, v);                      }                  } @@ -713,6 +792,7 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) {              }              case PA_SAMPLE_FLOAT32NE: { +            /*Seems the FLOAT32NE part of pa_volume_memchunk not right, do not reuse here*/                  float *t;                  for (t = p; n > 0; n -= fs) { @@ -728,6 +808,7 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) {              }              case PA_SAMPLE_FLOAT32RE: { +            /*Seems the FLOAT32RE part of pa_volume_memchunk not right, do not reuse here*/                  float *t;                  for (t = p; n > 0; n -= fs) { @@ -744,10 +825,101 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) {                  break;              } -            case PA_SAMPLE_S24LE: -            case PA_SAMPLE_S24BE: -            case PA_SAMPLE_S24_32LE: -            case PA_SAMPLE_S24_32BE: +            case PA_SAMPLE_S24NE: { +                uint8_t *d, *s; +                unsigned channel; +                int32_t factor = linear_get_int(e, v); + +                s = (uint8_t*) p + n/3; + +                for (channel = 0, d = p; d < s; d++) { +                    int64_t t; + +                    t = (int64_t)((int32_t) (PA_READ24NE(d) << 8)); +                    t = (t * factor) >> 16; +                    t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL); +                    PA_WRITE24NE(d, ((uint32_t) (int32_t) t) >> 8); + +                    if (PA_UNLIKELY(++channel >= e->sample_spec.channels)) { +                            channel = 0; +                            e->x += fs; +                            factor = linear_get_int(e, v); +                    } +                } + +                break; +            } +            case PA_SAMPLE_S24RE: { +                uint8_t *d, *s; +                unsigned channel; +                int32_t factor = linear_get_int(e, v); + +                s = (uint8_t*) p + n/3; + +                for (channel = 0, d = p; d < s; d++) { +                    int64_t t; + +                    t = (int64_t)((int32_t) (PA_READ24RE(d) << 8)); +                    t = (t * factor) >> 16; +                    t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL); +                    PA_WRITE24RE(d, ((uint32_t) (int32_t) t) >> 8); + +                    if (PA_UNLIKELY(++channel >= e->sample_spec.channels)) { +                            channel = 0; +                            e->x += fs; +                            factor = linear_get_int(e, v); +                    } +                } + +                break; +            } +            case PA_SAMPLE_S24_32NE: { +                uint32_t *d, *s; +                unsigned channel; +                int32_t factor = linear_get_int(e, v); + +                s = (uint32_t*) p + n/sizeof(uint32_t); + +                for (channel = 0, d = p; d < s; d++) { +                    int64_t t; + +                    t = (int64_t) ((int32_t) (*d << 8)); +                    t = (t * factor) >> 16; +                    t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL); +                    *d = ((uint32_t) ((int32_t) t)) >> 8; + +                    if (PA_UNLIKELY(++channel >= e->sample_spec.channels)) { +                            channel = 0; +                            e->x += fs; +                            factor = linear_get_int(e, v); +                    } +                } + +                break; +            } +            case PA_SAMPLE_S24_32RE: { +                uint32_t *d, *s; +                unsigned channel; +                int32_t factor = linear_get_int(e, v); + +                s = (uint32_t*) p + n/sizeof(uint32_t); + +                for (channel = 0, d = p; d < s; d++) { +                    int64_t t; + +                    t = (int64_t) ((int32_t) (PA_UINT32_SWAP(*d) << 8)); +                    t = (t * factor) >> 16; +                    t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL); +                    *d = PA_UINT32_SWAP(((uint32_t) ((int32_t) t)) >> 8); + +                    if (PA_UNLIKELY(++channel >= e->sample_spec.channels)) { +                            channel = 0; +                            e->x += fs; +                            factor = linear_get_int(e, v); +                    } +                } +                break; +            }                  /* FIXME */                  pa_assert_not_reached(); @@ -757,8 +929,6 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) {          }          pa_memblock_release(chunk->memblock); - -        e->x += chunk->length;      } else {          /* When we have no envelope to apply we reset our origin */          e->x = 0; @@ -774,13 +944,48 @@ void pa_envelope_rewind(pa_envelope *e, size_t n_bytes) {      envelope_begin_read(e, &v); -    if (n_bytes < e->x) -        e->x -= n_bytes; +    if (e->x - n_bytes <= e->points[v].x[0]) +        e->x = e->points[v].x[0];      else -        e->x = 0; +        e->x -= n_bytes;      e->points[v].n_current = 0;      e->points[v].cached_valid = FALSE;      envelope_commit_read(e, v);  } + +void pa_envelope_restart(pa_envelope* e) { +    int v; +    pa_assert(e); + +    envelope_begin_read(e, &v); +    e->x = e->points[v].x[0]; +    envelope_commit_read(e, v); +} + +pa_bool_t pa_envelope_is_finished(pa_envelope* e) { +    pa_assert(e); + +    int v; +    pa_bool_t finished; + +    envelope_begin_read(e, &v); +    finished = (e->x >=  e->points[v].x[e->points[v].n_points-1]); +    envelope_commit_read(e, v); + +    return finished; +} + +int32_t pa_envelope_length(pa_envelope *e) { +    pa_assert(e); + +    int v; +    size_t size; + +    envelope_begin_read(e, &v); +    size = e->points[v].x[e->points[v].n_points-1] - e->points[v].x[0]; +    envelope_commit_read(e, v); + +    return size; +} diff --git a/src/pulsecore/envelope.h b/src/pulsecore/envelope.h index 5296415a..4fa36579 100644 --- a/src/pulsecore/envelope.h +++ b/src/pulsecore/envelope.h @@ -49,5 +49,8 @@ pa_envelope_item *pa_envelope_replace(pa_envelope *e, pa_envelope_item *i, const  void pa_envelope_remove(pa_envelope *e, pa_envelope_item *i);  void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk);  void pa_envelope_rewind(pa_envelope *e, size_t n_bytes); +void pa_envelope_restart(pa_envelope* e); +pa_bool_t pa_envelope_is_finished(pa_envelope* e); +int32_t pa_envelope_length(pa_envelope *e);  #endif diff --git a/src/pulsecore/protocol-dbus.c b/src/pulsecore/protocol-dbus.c index 5c1127be..e427bb19 100644 --- a/src/pulsecore/protocol-dbus.c +++ b/src/pulsecore/protocol-dbus.c @@ -958,7 +958,7 @@ pa_client *pa_dbus_protocol_get_client(pa_dbus_protocol *p, DBusConnection *conn  void pa_dbus_protocol_add_signal_listener(          pa_dbus_protocol *p,          DBusConnection *conn, -        const char *signal, +        const char *signal_name,          char **objects,          unsigned n_objects) {      struct connection_entry *conn_entry; @@ -978,18 +978,18 @@ void pa_dbus_protocol_add_signal_listener(      while ((object_path = pa_idxset_steal_first(conn_entry->all_signals_objects, NULL)))          pa_xfree(object_path); -    if (signal) { +    if (signal_name) {          conn_entry->listening_for_all_signals = FALSE;          /* Replace the old object list with a new one. */ -        if ((object_set = pa_hashmap_remove(conn_entry->listening_signals, signal))) +        if ((object_set = pa_hashmap_remove(conn_entry->listening_signals, signal_name)))              pa_idxset_free(object_set, free_listened_object_name_cb, NULL);          object_set = pa_idxset_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);          for (i = 0; i < n_objects; ++i)              pa_idxset_put(object_set, pa_xstrdup(objects[i]), NULL); -        pa_hashmap_put(conn_entry->listening_signals, signal, object_set); +        pa_hashmap_put(conn_entry->listening_signals, signal_name, object_set);      } else {          conn_entry->listening_for_all_signals = TRUE; @@ -1004,7 +1004,7 @@ void pa_dbus_protocol_add_signal_listener(      }  } -void pa_dbus_protocol_remove_signal_listener(pa_dbus_protocol *p, DBusConnection *conn, const char *signal) { +void pa_dbus_protocol_remove_signal_listener(pa_dbus_protocol *p, DBusConnection *conn, const char *signal_name) {      struct connection_entry *conn_entry;      pa_idxset *object_set; @@ -1013,8 +1013,8 @@ void pa_dbus_protocol_remove_signal_listener(pa_dbus_protocol *p, DBusConnection      pa_assert_se((conn_entry = pa_hashmap_get(p->connections, conn))); -    if (signal) { -        if ((object_set = pa_hashmap_get(conn_entry->listening_signals, signal))) +    if (signal_name) { +        if ((object_set = pa_hashmap_get(conn_entry->listening_signals, signal_name)))              pa_idxset_free(object_set, free_listened_object_name_cb, NULL);      } else { @@ -1030,7 +1030,7 @@ void pa_dbus_protocol_remove_signal_listener(pa_dbus_protocol *p, DBusConnection      }  } -void pa_dbus_protocol_send_signal(pa_dbus_protocol *p, DBusMessage *signal) { +void pa_dbus_protocol_send_signal(pa_dbus_protocol *p, DBusMessage *signal_name) {      struct connection_entry *conn_entry;      void *state = NULL;      pa_idxset *object_set; @@ -1038,24 +1038,24 @@ void pa_dbus_protocol_send_signal(pa_dbus_protocol *p, DBusMessage *signal) {      char *signal_string;      pa_assert(p); -    pa_assert(signal); -    pa_assert(dbus_message_get_type(signal) == DBUS_MESSAGE_TYPE_SIGNAL); -    pa_assert_se(dbus_message_get_interface(signal)); -    pa_assert_se(dbus_message_get_member(signal)); +    pa_assert(signal_name); +    pa_assert(dbus_message_get_type(signal_name) == DBUS_MESSAGE_TYPE_SIGNAL); +    pa_assert_se(dbus_message_get_interface(signal_name)); +    pa_assert_se(dbus_message_get_member(signal_name)); -    signal_string = pa_sprintf_malloc("%s.%s", dbus_message_get_interface(signal), dbus_message_get_member(signal)); +    signal_string = pa_sprintf_malloc("%s.%s", dbus_message_get_interface(signal_name), dbus_message_get_member(signal_name));      PA_HASHMAP_FOREACH(conn_entry, p->connections, state) {          if ((conn_entry->listening_for_all_signals /* Case 1: listening for all signals */ -             && (pa_idxset_get_by_data(conn_entry->all_signals_objects, dbus_message_get_path(signal), NULL) +             && (pa_idxset_get_by_data(conn_entry->all_signals_objects, dbus_message_get_path(signal_name), NULL)                   || pa_idxset_isempty(conn_entry->all_signals_objects)))              || (!conn_entry->listening_for_all_signals /* Case 2: not listening for all signals */                  && (object_set = pa_hashmap_get(conn_entry->listening_signals, signal_string)) -                && (pa_idxset_get_by_data(object_set, dbus_message_get_path(signal), NULL) +                && (pa_idxset_get_by_data(object_set, dbus_message_get_path(signal_name), NULL)                      || pa_idxset_isempty(object_set)))) { -            pa_assert_se(signal_copy = dbus_message_copy(signal)); +            pa_assert_se(signal_copy = dbus_message_copy(signal_name));              pa_assert_se(dbus_connection_send(conn_entry->connection, signal_copy, NULL));              dbus_message_unref(signal_copy);          } diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index aa84ccb1..35e3d4a9 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -38,6 +38,7 @@  #include <pulsecore/play-memblockq.h>  #include <pulsecore/namereg.h>  #include <pulsecore/core-util.h> +#include <pulse/timeval.h>  #include "sink-input.h" @@ -48,6 +49,11 @@ PA_DEFINE_PUBLIC_CLASS(pa_sink_input, pa_msgobject);  static void sink_input_free(pa_object *o);  static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v); +static void sink_input_set_ramping_info(pa_sink_input* i, pa_volume_t  pre_virtual_volume, pa_volume_t target_virtual_volume, pa_usec_t t); +static void sink_input_set_ramping_info_for_mute(pa_sink_input* i, pa_bool_t mute, pa_usec_t t); +static void sink_input_volume_ramping(pa_sink_input* i, pa_memchunk* chunk); +static void sink_input_rewind_ramp_info(pa_sink_input *i, size_t nbytes); +static void sink_input_release_envelope(pa_sink_input *i);  pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data) {      pa_assert(data); @@ -323,6 +329,16 @@ int pa_sink_input_new(      reset_callbacks(i);      i->userdata = NULL; +    /* Set Ramping info */ +    i->thread_info.ramp_info.is_ramping = FALSE; +    i->thread_info.ramp_info.envelope_dead = TRUE; +    i->thread_info.ramp_info.envelope = NULL; +    i->thread_info.ramp_info.item = NULL; +    i->thread_info.ramp_info.envelope_dying = 0; + +    pa_atomic_store(&i->before_ramping_v, 0); +    pa_atomic_store(&i->before_ramping_m, 0); +      i->thread_info.state = i->state;      i->thread_info.attached = FALSE;      pa_atomic_store(&i->thread_info.drained, 1); @@ -510,6 +526,12 @@ static void sink_input_free(pa_object *o) {       * "half-moved" or are connected to sinks that have no asyncmsgq       * and are hence half-destructed themselves! */ +    if (i->thread_info.ramp_info.envelope) { +        pa_log_debug ("Freeing envelope\n"); +        pa_envelope_free(i->thread_info.ramp_info.envelope); +        i->thread_info.ramp_info.envelope = NULL; +    } +      if (i->thread_info.render_memblockq)          pa_memblockq_free(i->thread_info.render_memblockq); @@ -597,6 +619,7 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i, pa_usec_t *sink_latency) {  void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa_memchunk *chunk, pa_cvolume *volume) {      pa_bool_t do_volume_adj_here, need_volume_factor_sink;      pa_bool_t volume_is_norm; +    pa_bool_t ramping;      size_t block_size_max_sink, block_size_max_sink_input;      size_t ilength; @@ -641,7 +664,7 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, p       * to adjust the volume *before* we resample. Otherwise we can do       * it after and leave it for the sink code */ -    do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map); +    do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map) || i->thread_info.ramp_info.is_ramping;      volume_is_norm = pa_cvolume_is_norm(&i->thread_info.soft_volume) && !i->thread_info.muted;      need_volume_factor_sink = !pa_cvolume_is_norm(&i->volume_factor_sink); @@ -684,7 +707,7 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, p                  wchunk.length = block_size_max_sink_input;              /* It might be necessary to adjust the volume here */ -            if (do_volume_adj_here && !volume_is_norm) { +            if (do_volume_adj_here && !volume_is_norm && !i->thread_info.ramp_info.is_ramping) {                  pa_memchunk_make_writable(&wchunk, 0);                  if (i->thread_info.muted) { @@ -750,6 +773,23 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, p      if (chunk->length > block_size_max_sink)          chunk->length = block_size_max_sink; +    ramping = i->thread_info.ramp_info.is_ramping; +    if (ramping) +        sink_input_volume_ramping(i, chunk); + +    if (!i->thread_info.ramp_info.envelope_dead) { +        i->thread_info.ramp_info.envelope_dying += chunk->length; +        pa_log_debug("Envelope dying is %d, chunk length is %d, dead thresholder is %d\n", i->thread_info.ramp_info.envelope_dying, +                chunk->length, +                i->sink->thread_info.max_rewind + pa_envelope_length(i->thread_info.ramp_info.envelope)); + +        if (i->thread_info.ramp_info.envelope_dying >= (i->sink->thread_info.max_rewind + pa_envelope_length(i->thread_info.ramp_info.envelope))) { +            pa_log_debug("RELEASE Envelop"); +            i->thread_info.ramp_info.envelope_dead = TRUE; +            sink_input_release_envelope(i); +        } +    } +      /* Let's see if we had to apply the volume adjustment ourselves,       * or if this can be done by the sink for us */ @@ -794,6 +834,7 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam      if (nbytes > 0 && !i->thread_info.dont_rewind_render) {          pa_log_debug("Have to rewind %lu bytes on render memblockq.", (unsigned long) nbytes);          pa_memblockq_rewind(i->thread_info.render_memblockq, nbytes); +        sink_input_rewind_ramp_info(i, nbytes);      }      if (i->thread_info.rewrite_nbytes == (size_t) -1) { @@ -979,59 +1020,8 @@ static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v) {  /* Called from main context */  void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_bool_t save, pa_bool_t absolute) { -    pa_cvolume v; - -    pa_sink_input_assert_ref(i); -    pa_assert_ctl_context(); -    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); -    pa_assert(volume); -    pa_assert(pa_cvolume_valid(volume)); -    pa_assert(volume->channels == 1 || pa_cvolume_compatible(volume, &i->sample_spec)); - -    if ((i->sink->flags & PA_SINK_FLAT_VOLUME) && !absolute) { -        v = i->sink->reference_volume; -        pa_cvolume_remap(&v, &i->sink->channel_map, &i->channel_map); - -        if (pa_cvolume_compatible(volume, &i->sample_spec)) -            volume = pa_sw_cvolume_multiply(&v, &v, volume); -        else -            volume = pa_sw_cvolume_multiply_scalar(&v, &v, pa_cvolume_max(volume)); -    } else { - -        if (!pa_cvolume_compatible(volume, &i->sample_spec)) { -            v = i->volume; -            volume = pa_cvolume_scale(&v, pa_cvolume_max(volume)); -        } -    } - -    if (pa_cvolume_equal(volume, &i->volume)) { -        i->save_volume = i->save_volume || save; -        return; -    } - -    i->volume = *volume; -    i->save_volume = save; - -    if (i->sink->flags & PA_SINK_FLAT_VOLUME) -        /* We are in flat volume mode, so let's update all sink input -         * volumes and update the flat volume of the sink */ - -        pa_sink_set_volume(i->sink, NULL, TRUE, save); - -    else { -        /* OK, we are in normal volume mode. The volume only affects -         * ourselves */ -        set_real_ratio(i, volume); - -        /* Copy the new soft_volume to the thread_info struct */ -        pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, NULL, 0, NULL) == 0); -    } - -    /* The volume changed, let's tell people so */ -    if (i->volume_changed) -        i->volume_changed(i); - -    pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); +    /* test ramping -> return pa_sink_input_set_volume_with_ramping(i, volume, save, absolute, 2000 * PA_USEC_PER_MSEC); */ +    return pa_sink_input_set_volume_with_ramping(i, volume, save, absolute, 0);  }  /* Called from main context */ @@ -1050,23 +1040,8 @@ pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i, pa_cvolume *volume, pa_bo  /* Called from main context */  void pa_sink_input_set_mute(pa_sink_input *i, pa_bool_t mute, pa_bool_t save) { -    pa_sink_input_assert_ref(i); -    pa_assert_ctl_context(); -    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); - -    if (!i->muted == !mute) -        return; - -    i->muted = mute; -    i->save_muted = save; - -    pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE, NULL, 0, NULL) == 0); - -    /* The mute status changed, let's tell people so */ -    if (i->mute_changed) -        i->mute_changed(i); - -    pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); +    /* test ramping -> return pa_sink_input_set_mute_with_ramping(i, mute, save, 2000 * PA_USEC_PER_MSEC); */ +    return pa_sink_input_set_mute_with_ramping(i, mute, save, 0);  }  /* Called from main context */ @@ -1442,15 +1417,23 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t      switch (code) {          case PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME: +            if (pa_atomic_load(&i->before_ramping_v)) +                i->thread_info.future_soft_volume = i->soft_volume; +              if (!pa_cvolume_equal(&i->thread_info.soft_volume, &i->soft_volume)) { -                i->thread_info.soft_volume = i->soft_volume; +                if (!pa_atomic_load(&i->before_ramping_v)) +                    i->thread_info.soft_volume = i->soft_volume;                  pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE);              }              return 0;          case PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE: +            if (pa_atomic_load(&i->before_ramping_m)) +                i->thread_info.future_muted = i->muted; +              if (i->thread_info.muted != i->muted) { -                i->thread_info.muted = i->muted; +                if (!pa_atomic_load(&i->before_ramping_m)) +                    i->thread_info.muted = i->muted;                  pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE);              }              return 0; @@ -1498,6 +1481,26 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t              *r = i->thread_info.requested_sink_latency;              return 0;          } + +        case PA_SINK_INPUT_MESSAGE_SET_ENVELOPE: { +            if (!i->thread_info.ramp_info.envelope) +                i->thread_info.ramp_info.envelope = pa_envelope_new(&i->sink->sample_spec); + +            if (i->thread_info.ramp_info.envelope && i->thread_info.ramp_info.item) { +                pa_envelope_remove(i->thread_info.ramp_info.envelope, i->thread_info.ramp_info.item); +                i->thread_info.ramp_info.item = NULL; +            } + +            i->thread_info.ramp_info.item = pa_envelope_add(i->thread_info.ramp_info.envelope, &i->using_def); +            i->thread_info.ramp_info.is_ramping = TRUE; +            i->thread_info.ramp_info.envelope_dead = FALSE; +            i->thread_info.ramp_info.envelope_dying = 0; + +            if (i->thread_info.ramp_info.envelope) +                pa_envelope_restart(i->thread_info.ramp_info.envelope); + +            return 0; +        }      }      return -PA_ERR_NOTIMPLEMENTED; @@ -1660,3 +1663,235 @@ finish:      if (pl)          pa_proplist_free(pl);  } + +/* Called from IO context */ +static void sink_input_volume_ramping(pa_sink_input* i, pa_memchunk* chunk) { +    pa_assert(i); +    pa_assert(chunk); +    pa_assert(chunk->memblock); +    pa_assert(i->thread_info.ramp_info.is_ramping); + +    /* Volume is adjusted with ramping effect here */ +    pa_envelope_apply(i->thread_info.ramp_info.envelope, chunk); + +    if (pa_envelope_is_finished(i->thread_info.ramp_info.envelope)) { +        i->thread_info.ramp_info.is_ramping = FALSE; +        if (pa_atomic_load(&i->before_ramping_v)) { +            i->thread_info.soft_volume = i->thread_info.future_soft_volume; +            pa_atomic_store(&i->before_ramping_v, 0); +        } +        else if (pa_atomic_load(&i->before_ramping_m)) { +            i->thread_info.muted = i->thread_info.future_muted; +            pa_atomic_store(&i->before_ramping_m, 0); +        } +    } +} + +/* + * Called from main context + * This function should be called inside pa_sink_input_set_volume_with_ramping + * should be called after soft_volume of sink_input and sink are all adjusted + */ +static void sink_input_set_ramping_info(pa_sink_input* i, pa_volume_t  pre_virtual_volume, pa_volume_t target_virtual_volume, pa_usec_t t) { + +    int32_t target_abs_vol, target_apply_vol, pre_apply_vol; +    pa_assert(i); + +    pa_log_debug("Sink input's soft volume is %d= %f ", pa_cvolume_avg(&i->soft_volume), pa_sw_volume_to_linear(pa_cvolume_avg(&i->soft_volume))); + +    /* Calculation formula are target_abs_vol := i->soft_volume +     *                                   target_apply_vol := lrint(pa_sw_volume_to_linear(target_abs_vol) * 0x10000) +     *                                   pre_apply_vol := ( previous_virtual_volume / target_virtual_volume ) * target_apply_vol +     * +     * Will do volume adjustment inside pa_sink_input_peek +     */ +    target_abs_vol = pa_cvolume_avg(&i->soft_volume); +    target_apply_vol = (int32_t) lrint(pa_sw_volume_to_linear(target_abs_vol) * 0x10000); +    pre_apply_vol = (int32_t) ((pa_sw_volume_to_linear(pre_virtual_volume) / pa_sw_volume_to_linear(target_virtual_volume)) * target_apply_vol); + +    i->using_def.n_points = 2; +    i->using_def.points_x[0] = 0; +    i->using_def.points_x[1] = t; +    i->using_def.points_y.i[0] = pre_apply_vol; +    i->using_def.points_y.i[1] = target_apply_vol; +    i->using_def.points_y.f[0] = ((float) i->using_def.points_y.i[0]) /0x10000; +    i->using_def.points_y.f[1] = ((float) i->using_def.points_y.i[1]) /0x10000; + +    pa_log_debug("Volume Ramping: Point 1 is %d=%f, Point 2 is %d=%f\n", i->using_def.points_y.i[0], i->using_def.points_y.f[0], +                                   i->using_def.points_y.i[1], i->using_def.points_y.f[1]); + +    pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_ENVELOPE, NULL, 0, NULL) == 0); +} + +/* Called from main context */ +static void sink_input_set_ramping_info_for_mute(pa_sink_input* i, pa_bool_t mute, pa_usec_t t) { + +    int32_t cur_vol; +    pa_assert(i); + +    i->using_def.n_points = 2; +    i->using_def.points_x[0] = 0; +    i->using_def.points_x[1] = t; +    cur_vol = (int32_t) lrint( pa_sw_volume_to_linear(pa_cvolume_avg(&i->soft_volume)) * 0x10000); + +    if (mute) { +        i->using_def.points_y.i[0] = cur_vol; +        i->using_def.points_y.i[1] = 0; +    } else { +        i->using_def.points_y.i[0] = 0; +        i->using_def.points_y.i[1] = cur_vol; +    } + +    i->using_def.points_y.f[0] = ((float) i->using_def.points_y.i[0]) /0x10000; +    i->using_def.points_y.f[1] = ((float) i->using_def.points_y.i[1]) /0x10000; + +    pa_log_debug("Mute Ramping: Point 1 is %d=%f, Point 2 is %d=%f\n", i->using_def.points_y.i[0], i->using_def.points_y.f[0], +                   i->using_def.points_y.i[1], i->using_def.points_y.f[1]); + +    pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_ENVELOPE, NULL, 0, NULL) == 0); +} + +/* Called from IO context */ +static void sink_input_release_envelope(pa_sink_input *i) { +    pa_assert(i); +    pa_assert(!i->thread_info.ramp_info.is_ramping); +    pa_assert(i->thread_info.ramp_info.envelope_dead); + +    pa_envelope_free(i->thread_info.ramp_info.envelope); +    i->thread_info.ramp_info.envelope = NULL; +    i->thread_info.ramp_info.item = NULL; +} + +/* Called from IO context */ +static void sink_input_rewind_ramp_info(pa_sink_input *i, size_t nbytes) { +    pa_assert(i); + +    if (!i->thread_info.ramp_info.envelope_dead) { +        pa_assert(i->thread_info.ramp_info.envelope); + +        int32_t envelope_length = pa_envelope_length(i->thread_info.ramp_info.envelope); + +        if (i->thread_info.ramp_info.envelope_dying > envelope_length) { +            if ((i->thread_info.ramp_info.envelope_dying - nbytes) < envelope_length) { +                pa_log_debug("Envelope Become Alive"); +                pa_envelope_rewind(i->thread_info.ramp_info.envelope, envelope_length - (i->thread_info.ramp_info.envelope_dying - nbytes)); +                i->thread_info.ramp_info.is_ramping = TRUE; +            } +        } else if (i->thread_info.ramp_info.envelope_dying < envelope_length) { +            if ((i->thread_info.ramp_info.envelope_dying - nbytes) <= 0) { +                pa_log_debug("Envelope Restart"); +                pa_envelope_restart(i->thread_info.ramp_info.envelope); +            } +            else { +                pa_log_debug("Envelope Simple Rewind"); +                pa_envelope_rewind(i->thread_info.ramp_info.envelope, nbytes); +            } +        } + +        i->thread_info.ramp_info.envelope_dying -= nbytes; +        if (i->thread_info.ramp_info.envelope_dying <= 0) +            i->thread_info.ramp_info.envelope_dying = 0; +    } +} + +void pa_sink_input_set_volume_with_ramping(pa_sink_input *i, const pa_cvolume *volume, pa_bool_t save, pa_bool_t absolute, pa_usec_t t){ +    pa_cvolume v; +    pa_volume_t previous_virtual_volume, target_virtual_volume; + +    pa_sink_input_assert_ref(i); +    pa_assert_ctl_context(); +    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); +    pa_assert(volume); +    pa_assert(pa_cvolume_valid(volume)); +    pa_assert(volume->channels == 1 || pa_cvolume_compatible(volume, &i->sample_spec)); + +    if ((i->sink->flags & PA_SINK_FLAT_VOLUME) && !absolute) { +        v = i->sink->reference_volume; +        pa_cvolume_remap(&v, &i->sink->channel_map, &i->channel_map); + +        if (pa_cvolume_compatible(volume, &i->sample_spec)) +            volume = pa_sw_cvolume_multiply(&v, &v, volume); +        else +            volume = pa_sw_cvolume_multiply_scalar(&v, &v, pa_cvolume_max(volume)); +    } else { + +        if (!pa_cvolume_compatible(volume, &i->sample_spec)) { +            v = i->volume; +            volume = pa_cvolume_scale(&v, pa_cvolume_max(volume)); +        } +    } + +    if (pa_cvolume_equal(volume, &i->volume)) { +        i->save_volume = i->save_volume || save; +        return; +    } + +    previous_virtual_volume = pa_cvolume_avg(&i->volume); +    target_virtual_volume = pa_cvolume_avg(volume); + +    if (t > 0 && target_virtual_volume > 0) +        pa_log_debug("SetVolumeWithRamping: Virtual Volume From %u=%f to %u=%f\n", previous_virtual_volume, pa_sw_volume_to_linear(previous_virtual_volume), +                                             target_virtual_volume, pa_sw_volume_to_linear(target_virtual_volume)); + +    i->volume = *volume; +    i->save_volume = save; + +    /* Set this flag before the following code modify i->thread_info.soft_volume */ +    if (t > 0 && target_virtual_volume > 0) +        pa_atomic_store(&i->before_ramping_v, 1); + +    if (i->sink->flags & PA_SINK_FLAT_VOLUME) { +        /* We are in flat volume mode, so let's update all sink input +         * volumes and update the flat volume of the sink */ + +        pa_sink_set_volume(i->sink, NULL, TRUE, save); + +    } else { +        /* OK, we are in normal volume mode. The volume only affects +         * ourselves */ +        set_real_ratio(i, volume); + +        /* Copy the new soft_volume to the thread_info struct */ +        pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, NULL, 0, NULL) == 0); +    } + +    if (t > 0 && target_virtual_volume > 0) +        sink_input_set_ramping_info(i, previous_virtual_volume, target_virtual_volume, t); + +    /* The volume changed, let's tell people so */ +    if (i->volume_changed) +        i->volume_changed(i); + +    /* The virtual volume changed, let's tell people so */ +    pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); +} + +void pa_sink_input_set_mute_with_ramping(pa_sink_input *i, pa_bool_t mute, pa_bool_t save, pa_usec_t t){ + +    pa_sink_input_assert_ref(i); +    pa_assert_ctl_context(); +    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); + +    if (!i->muted == !mute) { +        i->save_muted = i->save_muted || mute; +        return; +    } + +    i->muted = mute; +    i->save_muted = save; + +    /* Set this flag before the following code modify i->thread_info.muted, otherwise distortion will be heard */ +    if (t > 0) +        pa_atomic_store(&i->before_ramping_m, 1); + +    pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE, NULL, 0, NULL) == 0); + +    if (t > 0) +        sink_input_set_ramping_info_for_mute(i, mute, t); + +    /* The mute status changed, let's tell people so */ +    if (i->mute_changed) +        i->mute_changed(i); + +    pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); +} diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index 415a801f..56ac3d60 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -35,6 +35,7 @@ typedef struct pa_sink_input pa_sink_input;  #include <pulsecore/client.h>  #include <pulsecore/sink.h>  #include <pulsecore/core.h> +#include <pulsecore/envelope.h>  typedef enum pa_sink_input_state {      PA_SINK_INPUT_INIT,         /*< The stream is not active yet, because pa_sink_put() has not been called yet */ @@ -232,8 +233,23 @@ struct pa_sink_input {          pa_usec_t requested_sink_latency;          pa_hashmap *direct_outputs; + +        struct { +            pa_bool_t is_ramping:1; +            pa_bool_t envelope_dead:1; +            int32_t envelope_dying; /* Increasing while envelop is not dead.  Reduce it while process_rewind. */ +            pa_envelope *envelope; +            pa_envelope_item *item; +        } ramp_info; +        pa_cvolume future_soft_volume; +        pa_bool_t future_muted; +      } thread_info; +    pa_atomic_t before_ramping_v;  /* Indicates future volume */ +    pa_atomic_t before_ramping_m;  /* Indicates future mute */ +    pa_envelope_def using_def; +      void *userdata;  }; @@ -248,6 +264,7 @@ enum {      PA_SINK_INPUT_MESSAGE_SET_STATE,      PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY,      PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY, +    PA_SINK_INPUT_MESSAGE_SET_ENVELOPE,      PA_SINK_INPUT_MESSAGE_MAX  }; @@ -384,4 +401,8 @@ pa_memchunk* pa_sink_input_get_silence(pa_sink_input *i, pa_memchunk *ret);  #define pa_sink_input_assert_io_context(s) \      pa_assert(pa_thread_mq_get() || !PA_SINK_INPUT_IS_LINKED((s)->state)) +/* Volume ramping*/ +void pa_sink_input_set_volume_with_ramping(pa_sink_input *i, const pa_cvolume *volume, pa_bool_t save, pa_bool_t absolute, pa_usec_t t); +void pa_sink_input_set_mute_with_ramping(pa_sink_input *i, pa_bool_t mute, pa_bool_t save, pa_usec_t t); +  #endif diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 971436d3..24fad34d 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -1731,10 +1731,14 @@ static void sync_input_volumes_within_thread(pa_sink *s) {      pa_sink_assert_io_context(s);      PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state) { +        if (pa_atomic_load(&i->before_ramping_v)) +            i->thread_info.future_soft_volume = i->soft_volume; +          if (pa_cvolume_equal(&i->thread_info.soft_volume, &i->soft_volume))              continue; -        i->thread_info.soft_volume = i->soft_volume; +        if (!pa_atomic_load(&i->before_ramping_v)) +            i->thread_info.soft_volume = i->soft_volume;          pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE);      }  } diff --git a/src/utils/qpaeq b/src/utils/qpaeq new file mode 100755 index 00000000..a8a9fda8 --- /dev/null +++ b/src/utils/qpaeq @@ -0,0 +1,560 @@ +#!/usr/bin/env python +#    qpaeq is a equalizer interface for pulseaudio's equalizer sinks +#    Copyright (C) 2009  Jason Newton <nevion@gmail.com +# +#    This program is free software: you can redistribute it and/or modify +#    it under the terms of the GNU Affero General Public License as +#    published by the Free Software Foundation, either version 3 of the +#    License, or (at your option) any later version. +# +#    This program 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 Affero General Public License for more details. +# +#    You should have received a copy of the GNU Affero General Public License +#    along with this program.  If not, see <http://www.gnu.org/licenses/>. + + +import os,math,sys +try: +    import PyQt4,sip +    from PyQt4 import QtGui,QtCore +    import dbus.mainloop.qt +    import dbus +except ImportError,e: +    print 'There was an error importing need libraries' +    print 'Make sure you haveqt4 and dbus forthon installed' +    print 'The error that occured was' +    print '\t%s' %(str(e)) +    import sys +    sys.exit(-1) + +from functools import partial + +import signal +signal.signal(signal.SIGINT, signal.SIG_DFL) +SYNC_TIMEOUT = 4*1000 + +CORE_PATH = "/org/pulseaudio/core1" +CORE_IFACE = "org.PulseAudio.Core1" +def connect(): +    try: +        if 'PULSE_DBUS_SERVER' in os.environ: +            address = os.environ['PULSE_DBUS_SERVER'] +        else: +            bus = dbus.SessionBus() # Should be UserBus, but D-Bus doesn't implement that yet. +            server_lookup = bus.get_object('org.PulseAudio1', '/org/pulseaudio/server_lookup1') +            address = server_lookup.Get('org.PulseAudio.ServerLookup1', 'Address', dbus_interface='org.freedesktop.DBus.Properties') +        return dbus.connection.Connection(address) +    except Exception,e: +        print 'There was an error connecting to pulseaudio, please make sure you have the pulseaudio dbus' +        print 'and equalizer modules loaded, exiting...' +        import sys +        sys.exit(-1) + + +#TODO: signals: sink Filter changed, sink reconfigured (window size) (sink iface) +#TODO: manager signals: new sink, removed sink, new profile, removed profile +#TODO: add support for changing of window_size 1000-fft_size (adv option) +#TODO: reconnect support loop 1 second trying to reconnect +#TODO: just resample the filters for profiles when loading to different sizes +#TODO: add preamp +prop_iface='org.freedesktop.DBus.Properties' +eq_iface='org.PulseAudio.Ext.Equalizing1.Equalizer' +device_iface='org.PulseAudio.Core1.Device' +class QPaeq(QtGui.QWidget): +    manager_path='/org/pulseaudio/equalizing1' +    manager_iface='org.PulseAudio.Ext.Equalizing1.Manager' +    core_iface='org.PulseAudio.Core1' +    core_path='/org/pulseaudio/core1' +    def __init__(self): +        QtGui.QWidget.__init__(self) +        self.setWindowTitle('qpaeq') +        self.slider_widget=None +        self.sink_name=None +        self.filter_state=None + +        self.create_layout() + +        self.set_connection() +        self.connect_to_sink(self.sinks[0]) +        self.set_callbacks() +        self.setMinimumSize(self.sizeHint()) + +    def create_layout(self): +        self.main_layout=QtGui.QVBoxLayout() +        self.setLayout(self.main_layout) +        toprow_layout=QtGui.QHBoxLayout() +        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Fixed) +        sizePolicy.setHorizontalStretch(0) +        sizePolicy.setVerticalStretch(0) +        #sizePolicy.setHeightForWidth(self.profile_box.sizePolicy().hasHeightForWidth()) + +        toprow_layout.addWidget(QtGui.QLabel('Sink')) +        self.sink_box = QtGui.QComboBox() +        self.sink_box.setSizePolicy(sizePolicy) +        self.sink_box.setDuplicatesEnabled(False) +        self.sink_box.setInsertPolicy(QtGui.QComboBox.InsertAlphabetically) +        #self.sink_box.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents) +        toprow_layout.addWidget(self.sink_box) + +        toprow_layout.addWidget(QtGui.QLabel('Channel')) +        self.channel_box = QtGui.QComboBox() +        self.channel_box.setSizePolicy(sizePolicy) +        toprow_layout.addWidget(self.channel_box) + +        toprow_layout.addWidget(QtGui.QLabel('Preset')) +        self.profile_box = QtGui.QComboBox() +        self.profile_box.setSizePolicy(sizePolicy) +        self.profile_box.setInsertPolicy(QtGui.QComboBox.InsertAlphabetically) +        #self.profile_box.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents) +        toprow_layout.addWidget(self.profile_box) + +        large_icon_size=self.style().pixelMetric(QtGui.QStyle.PM_LargeIconSize) +        large_icon_size=QtCore.QSize(large_icon_size,large_icon_size) +        save_profile=QtGui.QToolButton() +        save_profile.setIcon(self.style().standardIcon(QtGui.QStyle.SP_DriveFDIcon)) +        save_profile.setIconSize(large_icon_size) +        save_profile.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly) +        save_profile.clicked.connect(self.save_profile) +        remove_profile=QtGui.QToolButton() +        remove_profile.setIcon(self.style().standardIcon(QtGui.QStyle.SP_TrashIcon)) +        remove_profile.setIconSize(large_icon_size) +        remove_profile.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly) +        remove_profile.clicked.connect(self.remove_profile) +        toprow_layout.addWidget(save_profile) +        toprow_layout.addWidget(remove_profile) + +        reset_button = QtGui.QPushButton('Reset') +        reset_button.clicked.connect(self.reset) +        toprow_layout.addStretch() +        toprow_layout.addWidget(reset_button) +        self.layout().addLayout(toprow_layout) + +        self.profile_box.activated.connect(self.load_profile) +        self.channel_box.activated.connect(self.select_channel) +    def connect_to_sink(self,name): +        #TODO: clear slots for profile buttons + +        #flush any pending saves for other sinks +        if self.filter_state is not None: +            self.filter_state.flush_state() +        sink=self.connection.get_object(object_path=name) +        self.sink_props=dbus.Interface(sink,dbus_interface=prop_iface) +        self.sink=dbus.Interface(sink,dbus_interface=eq_iface) +        self.filter_state=FilterState(sink) +        #sample_rate,filter_rate,channels,channel) + +        self.channel_box.clear() +        self.channel_box.addItem('All',self.filter_state.channels) +        for i in xrange(self.filter_state.channels): +            self.channel_box.addItem('%d' %(i+1,),i) +        self.setMinimumSize(self.sizeHint()) + +        self.set_slider_widget(SliderArray(self.filter_state)) + +        self.sink_name=name +        #set the signal listener for this sink +        core=self._get_core() +        #temporary hack until signal filtering works properly +        core.ListenForSignal('',[dbus.ObjectPath(self.sink_name),dbus.ObjectPath(self.manager_path)]) +        #for x in ['FilterChanged']: +        #    core.ListenForSignal("%s.%s" %(self.eq_iface,x),[dbus.ObjectPath(self.sink_name)]) +        #core.ListenForSignal(self.eq_iface,[dbus.ObjectPath(self.sink_name)]) +        self.sink.connect_to_signal('FilterChanged',self.read_filter) + +    def set_slider_widget(self,widget): +        layout=self.layout() +        if self.slider_widget is not None: +            i=layout.indexOf(self.slider_widget) +            layout.removeWidget(self.slider_widget) +            self.slider_widget.deleteLater() +            layout.insertWidget(i,self.slider_widget) +        else: +            layout.addWidget(widget) +        self.slider_widget=widget +        self.read_filter() +    def _get_core(self): +        core_obj=self.connection.get_object(object_path=self.core_path) +        core=dbus.Interface(core_obj,dbus_interface=self.core_iface) +        return core +    def sink_added(self,sink): +        #TODO: preserve selected sink +        self.update_sinks() +    def sink_removed(self,sink): +        #TODO: preserve selected sink, try connecting to backup otherwise +        if sink==self.sink_name: +            #connect to new sink? +            pass +        self.update_sinks() +    def save_profile(self): +        #popup dialog box for name +        current=self.profile_box.currentIndex() +        profile,ok=QtGui.QInputDialog.getItem(self,'Preset Name','Preset',self.profiles,current) +        if not ok or profile=='': +            return +        if profile in self.profiles: +            mbox=QtGui.QMessageBox(self) +            mbox.setText('%s preset already exists'%(profile,)) +            mbox.setInformativeText('Do you want to save over it?') +            mbox.setStandardButtons(mbox.Save|mbox.Discard|mbox.Cancel) +            mbox.setDefaultButton(mbox.Save) +            ret=mbox.exec_() +            if ret!=mbox.Save: +                return +        self.sink.SaveProfile(self.filter_state.channel,dbus.String(profile)) +        if self.filter_state.channel==self.filter_state.channels: +            for x in range(1,self.filter_state.channels): +                self.sink.LoadProfile(x,dbus.String(profile)) +    def remove_profile(self): +        #find active profile name, remove it +        profile=self.profile_box.currentText() +        manager=dbus.Interface(self.manager_obj,dbus_interface=self.manager_iface) +        manager.RemoveProfile(dbus.String(profile)) +    def load_profile(self,x): +        profile=self.profile_box.itemText(x) +        self.filter_state.load_profile(profile) +    def select_channel(self,x): +        self.filter_state.channel = self.channel_box.itemData(x).toPyObject() +        self._set_profile_name() +        self.filter_state.readback() + +    #TODO: add back in preamp! +    #print frequencies +    #main_layout.addLayout(self.create_slider(partial(self.update_coefficient,0), +    #    'Preamp')[0] +    #) +    def set_connection(self): +        self.connection=connect() +        self.manager_obj=self.connection.get_object(object_path=self.manager_path) +        manager_props=dbus.Interface(self.manager_obj,dbus_interface=prop_iface) +        self.sinks=manager_props.Get(self.manager_iface,'EqualizedSinks') +    def set_callbacks(self): +        manager=dbus.Interface(self.manager_obj,dbus_interface=self.manager_iface) +        manager.connect_to_signal('ProfilesChanged',self.update_profiles) +        manager.connect_to_signal('SinkAdded',self.sink_added) +        manager.connect_to_signal('SinkRemoved',self.sink_removed) +        #self._get_core().ListenForSignal(self.manager_iface,[]) +        #self._get_core().ListenForSignal(self.manager_iface,[dbus.ObjectPath(self.manager_path)]) +        #core=self._get_core() +        #for x in ['ProfilesChanged','SinkAdded','SinkRemoved']: +        #    core.ListenForSignal("%s.%s" %(self.manager_iface,x),[dbus.ObjectPath(self.manager_path)]) +        self.update_profiles() +        self.update_sinks() +    def update_profiles(self): +        #print 'update profiles called!' +        manager_props=dbus.Interface(self.manager_obj,dbus_interface=prop_iface) +        self.profiles=manager_props.Get(self.manager_iface,'Profiles') +        self.profile_box.blockSignals(True) +        self.profile_box.clear() +        self.profile_box.addItems(self.profiles) +        self.profile_box.blockSignals(False) +        self._set_profile_name() +    def update_sinks(self): +        self.sink_box.blockSignals(True) +        self.sink_box.clear() +        for x in self.sinks: +            sink=self.connection.get_object(object_path=x) +            sink_props=dbus.Interface(sink,dbus_interface=prop_iface) +            simple_name=sink_props.Get(device_iface,'Name') +            self.sink_box.addItem(simple_name,x) +        self.sink_box.blockSignals(False) +        self.sink_box.setMinimumSize(self.sink_box.sizeHint()) +    def read_filter(self): +        #print self.filter_frequencies +        self.filter_state.readback() +    def reset(self): +        coefs=dbus.Array([1/math.sqrt(2.0)]*(self.filter_state.filter_rate//2+1)) +        preamp=1.0 +        self.filter_state.set_filter(preamp,coefs) +    def _set_profile_name(self): +        self.profile_box.blockSignals(True) +        profile_name=self.sink.BaseProfile(self.filter_state.channel) +        if profile_name is not None: +            i=self.profile_box.findText(profile_name) +            if i>=0: +                self.profile_box.setCurrentIndex(i) +        self.profile_box.blockSignals(False) + + +class SliderArray(QtGui.QWidget): +    def __init__(self,filter_state,parent=None): +        super(SliderArray,self).__init__(parent) +        #self.setStyleSheet('padding: 0px; border-width: 0px; margin: 0px;') +        #self.setStyleSheet('font-size: 7pt; font-family: monospace;'+outline%('blue')) +        self.filter_state=filter_state +        self.setLayout(QtGui.QHBoxLayout()) +        self.sub_array=None +        self.set_sub_array(SliderArraySub(self.filter_state)) +        self.inhibit_resize=0 +    def set_sub_array(self,widget): +        if self.sub_array is not None: +            self.layout().removeWidget(self.sub_array) +            self.sub_array.disconnect_signals() +            self.sub_array.deleteLater() +        self.sub_array=widget +        self.layout().addWidget(self.sub_array) +        self.sub_array.connect_signals() +        self.filter_state.readback() +    def resizeEvent(self,event): +        super(SliderArray,self).resizeEvent(event) +        if self.inhibit_resize==0: +            self.inhibit_resize+=1 +            #self.add_sliders_to_fit() +            t=QtCore.QTimer(self) +            t.setSingleShot(True) +            t.setInterval(0) +            t.timeout.connect(partial(self.add_sliders_to_fit,event)) +            t.start() +    def add_sliders_to_fit(self,event): +        if event.oldSize().width()>0 and event.size().width()>0: +            i=len(self.filter_state.frequencies)*int(round(float(event.size().width())/event.oldSize().width())) +        else: +            i=len(self.filter_state.frequencies) + +        t_w=self.size().width() +        def evaluate(filter_state, target, variable): +            base_freqs=self.filter_state.freq_proper(self.filter_state.DEFAULT_FREQUENCIES) +            filter_state._set_frequency_values(subdivide(base_freqs,variable)) +            new_widget=SliderArraySub(filter_state) +            w=new_widget.sizeHint().width() +            return w-target +        def searcher(initial,evaluator): +            i=initial +            def d(e): return 1 if e>=0 else -1 +            error=evaluator(i) +            old_direction=d(error) +            i-=old_direction +            while True: +                error=evaluator(i) +                direction=d(error) +                if direction!=old_direction: +                    k=i-1 +                    #while direction<0 and error!=0: +                    #    k-=1 +                    #    error=evaluator(i) +                    #    direction=d(error) +                    return k, evaluator(k) +                i-=direction +                old_direction=direction +        searcher(i,partial(evaluate,self.filter_state,t_w)) +        self.set_sub_array(SliderArraySub(self.filter_state)) +        self.inhibit_resize-=1 + +class SliderArraySub(QtGui.QWidget): +    def __init__(self,filter_state,parent=None): +        super(SliderArraySub,self).__init__(parent) +        self.filter_state=filter_state +        self.setLayout(QtGui.QGridLayout()) +        self.slider=[None]*len(self.filter_state.frequencies) +        self.label=[None]*len(self.slider) +        #self.setStyleSheet('padding: 0px; border-width: 0px; margin: 0px;') +        #self.setStyleSheet('font-size: 7pt; font-family: monospace;'+outline%('blue')) +        qt=QtCore.Qt +        #self.layout().setHorizontalSpacing(1) +        def add_slider(slider,label, c): +            self.layout().addWidget(slider,0,c,qt.AlignHCenter) +            self.layout().addWidget(label,1,c,qt.AlignHCenter) +            self.layout().setColumnMinimumWidth(c,max(label.sizeHint().width(),slider.sizeHint().width())) +        def create_slider(slider_label): +            slider=QtGui.QSlider(QtCore.Qt.Vertical,self) +            label=SliderLabel(slider_label,filter_state,self) +            slider.setRange(-1000,2000) +            slider.setSingleStep(1) +            return (slider,label) +        self.preamp_slider,self.preamp_label=create_slider('Preamp') +        add_slider(self.preamp_slider,self.preamp_label,0) +        for i,hz in enumerate(self.filter_state.frequencies): +            slider,label=create_slider(self.hz2label(hz)) +            self.slider[i]=slider +            #slider.setStyleSheet('font-size: 7pt; font-family: monospace;'+outline%('red',)) +            self.label[i]=label +            c=i+1 +            add_slider(slider,label,i+1) +    def hz2label(self, hz): +        if hz==0: +            label_text='DC' +        elif hz==self.filter_state.sample_rate//2: +            label_text='Coda' +        else: +            label_text=hz2str(hz) +        return label_text + +    def connect_signals(self): +        def connect(writer,reader,slider,label): +            slider.valueChanged.connect(writer) +            self.filter_state.readFilter.connect(reader) +            label_cb=partial(slider.setValue,0) +            label.clicked.connect(label_cb) +            return label_cb + +        self.preamp_writer_cb=self.write_preamp +        self.preamp_reader_cb=self.sync_preamp +        self.preamp_label_cb=connect(self.preamp_writer_cb, +                self.preamp_reader_cb, +                self.preamp_slider, +                self.preamp_label) +        self.writer_callbacks=[None]*len(self.slider) +        self.reader_callbacks=[None]*len(self.slider) +        self.label_callbacks=[None]*len(self.label) +        for i in range(len(self.slider)): +            self.writer_callbacks[i]=partial(self.write_coefficient,i) +            self.reader_callbacks[i]=partial(self.sync_coefficient,i) +            self.label_callbacks[i]=connect(self.writer_callbacks[i], +                    self.reader_callbacks[i], +                    self.slider[i], +                    self.label[i]) +    def disconnect_signals(self): +        def disconnect(writer,reader,label_cb,slider,label): +            slider.valueChanged.disconnect(writer) +            self.filter_state.readFilter.disconnect(reader) +            label.clicked.disconnect(label_cb) +        disconnect(self.preamp_writer_cb, self.preamp_reader_cb, +                self.preamp_label_cb, self.preamp_slider, self.preamp_label) +        for i in range(len(self.slider)): +            disconnect(self.writer_callbacks[i], +                    self.reader_callbacks[i], +                    self.label_callbacks[i], +                    self.slider[i], +                    self.label[i]) + +    def write_preamp(self, v): +        self.filter_state.preamp=self.slider2coef(v) +        self.filter_state.seed() +    def sync_preamp(self): +        self.preamp_slider.blockSignals(True) +        self.preamp_slider.setValue(self.coef2slider(self.filter_state.preamp)) +        self.preamp_slider.blockSignals(False) + + +    def write_coefficient(self,i,v): +        self.filter_state.coefficients[i]=self.slider2coef(v)/math.sqrt(2.0) +        self.filter_state.seed() +    def sync_coefficient(self,i): +        slider=self.slider[i] +        slider.blockSignals(True) +        slider.setValue(self.coef2slider(math.sqrt(2.0)*self.filter_state.coefficients[i])) +        slider.blockSignals(False) +    @staticmethod +    def slider2coef(x): +        return (1.0+(x/1000.0)) +    @staticmethod +    def coef2slider(x): +        return int((x-1.0)*1000) +outline='border-width: 1px; border-style: solid; border-color: %s;' + +class SliderLabel(QtGui.QLabel): +    clicked=QtCore.pyqtSignal() +    def __init__(self,label_text,filter_state,parent=None): +        super(SliderLabel,self).__init__(parent) +        self.setStyleSheet('font-size: 7pt; font-family: monospace;') +        self.setText(label_text) +        self.setMinimumSize(self.sizeHint()) +    def mouseDoubleClickEvent(self, event): +        self.clicked.emit() +        super(SliderLabel,self).mouseDoubleClickEvent(event) + +#until there are server side state savings, do it in the client but try and avoid +#simulaneous broadcasting situations +class FilterState(QtCore.QObject): +    #DEFAULT_FREQUENCIES=map(float,[25,50,75,100,150,200,300,400,500,800,1e3,1.5e3,3e3,5e3,7e3,10e3,15e3,20e3]) +    DEFAULT_FREQUENCIES=[31.75,63.5,125,250,500,1e3,2e3,4e3,8e3,16e3] +    readFilter=QtCore.pyqtSignal() +    def __init__(self,sink): +        super(FilterState,self).__init__() +        self.sink_props=dbus.Interface(sink,dbus_interface=prop_iface) +        self.sink=dbus.Interface(sink,dbus_interface=eq_iface) +        self.sample_rate=self.get_eq_attr('SampleRate') +        self.filter_rate=self.get_eq_attr('FilterSampleRate') +        self.channels=self.get_eq_attr('NChannels') +        self.channel=self.channels +        self.set_frequency_values(self.DEFAULT_FREQUENCIES) +        self.sync_timer=QtCore.QTimer() +        self.sync_timer.setSingleShot(True) +        self.sync_timer.timeout.connect(self.save_state) + +    def get_eq_attr(self,attr): +        return self.sink_props.Get(eq_iface,attr) +    def freq_proper(self,xs): +        return [0]+xs+[self.sample_rate//2] +    def _set_frequency_values(self,freqs): +        self.frequencies=freqs +        #print 'base',self.frequencies +        self.filter_frequencies=map(lambda x: int(round(x)), \ +                self.translate_rates(self.filter_rate,self.sample_rate, +                    self.frequencies) \ +                ) +        self.coefficients=[0.0]*len(self.frequencies) +        self.preamp=1.0 +    def set_frequency_values(self,freqs): +        self._set_frequency_values(self.freq_proper(freqs)) +    @staticmethod +    def translate_rates(dst,src,rates): +        return list(map(lambda x: x*dst/src,rates)) +    def seed(self): +        self.sink.SeedFilter(self.channel,self.filter_frequencies,self.coefficients,self.preamp) +        self.sync_timer.start(SYNC_TIMEOUT) +    def readback(self): +        coefs,preamp=self.sink.FilterAtPoints(self.channel,self.filter_frequencies) +        self.coefficients=coefs +        self.preamp=preamp +        self.readFilter.emit() +    def set_filter(self,preamp,coefs): +        self.sink.SetFilter(self.channel,dbus.Array(coefs),self.preamp) +        self.sync_timer.start(SYNC_TIMEOUT) +    def save_state(self): +        print 'saving state' +        self.sink.SaveState() +    def load_profile(self,profile): +        self.sink.LoadProfile(self.channel,dbus.String(profile)) +        self.sync_timer.start(SYNC_TIMEOUT) +    def flush_state(self): +        if self.sync_timer.isActive(): +            self.sync_timer.stop() +            self.save_state() + + +def safe_log(k,b): +    i=0 +    while k//b!=0: +        i+=1 +        k=k//b +    return i +def hz2str(hz): +    p=safe_log(hz,10.0) +    if p<3: +        return '%dHz' %(hz,) +    elif hz%1000==0: +        return '%dKHz' %(hz/(10.0**3),) +    else: +        return '%.1fKHz' %(hz/(10.0**3),) + +def subdivide(xs, t_points): +    while len(xs)<t_points: +        m=[0]*(2*len(xs)-1) +        m[0:len(m):2]=xs +        for i in range(1,len(m),2): +            m[i]=(m[i-1]+m[i+1])//2 +        xs=m +    p_drop=len(xs)-t_points +    p_drop_left=p_drop//2 +    p_drop_right=p_drop-p_drop_left +    #print 'xs',xs +    #print 'dropping %d, %d left, %d right' %(p_drop,p_drop_left,p_drop_right) +    c=len(xs)//2 +    left=xs[0:p_drop_left*2:2]+xs[p_drop_left*2:c] +    right=list(reversed(xs[c:])) +    right=right[0:p_drop_right*2:2]+right[p_drop_right*2:] +    right=list(reversed(right)) +    return left+right + +def main(): +    dbus.mainloop.qt.DBusQtMainLoop(set_as_default=True) +    app=QtGui.QApplication(sys.argv) +    qpaeq_main=QPaeq() +    qpaeq_main.show() +    sys.exit(app.exec_()) + +if __name__=='__main__': +    main() | 
