diff options
Diffstat (limited to 'src')
32 files changed, 511 insertions, 83 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 6544e2aa..de15a8f2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -137,8 +137,10 @@ EXTRA_DIST = \ 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 diff --git a/src/daemon/main.c b/src/daemon/main.c index 2e16c187..c006badb 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -423,21 +423,24 @@ int main(int argc, char *argv[]) { pa_set_env("LD_BIND_NOW", "1"); - canonical_rp = pa_realpath(PA_BINARY); + if ((canonical_rp = pa_realpath(PA_BINARY))) { - if ((rp = pa_readlink("/proc/self/exe"))) { + if ((rp = pa_readlink("/proc/self/exe"))) { - if (pa_streq(rp, canonical_rp)) - pa_assert_se(execv(rp, argv) == 0); - else - pa_log_warn("/proc/self/exe does not point to %s, cannot self execute. Are you playing games?", canonical_rp); + if (pa_streq(rp, canonical_rp)) + pa_assert_se(execv(rp, argv) == 0); + else + pa_log_warn("/proc/self/exe does not point to %s, cannot self execute. Are you playing games?", canonical_rp); - pa_xfree(rp); + pa_xfree(rp); - } else - pa_log_warn("Couldn't read /proc/self/exe, cannot self execute. Running in a chroot()?"); + } else + pa_log_warn("Couldn't read /proc/self/exe, cannot self execute. Running in a chroot()?"); + + pa_xfree(canonical_rp); - pa_xfree(canonical_rp); + } else + pa_log_warn("Couldn't canonicalize binary path, cannot self execute."); } #endif @@ -748,6 +751,8 @@ int main(int argc, char *argv[]) { pa_log_debug(_("Running in valgrind mode: %s"), pa_yes_no(pa_in_valgrind())); + pa_log_debug(_("Running in VM: %s"), pa_yes_no(pa_running_in_vm())); + #ifdef __OPTIMIZE__ pa_log_debug(_("Optimized build: yes")); #else diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c index f3ce681f..8b13239c 100644 --- a/src/modules/alsa/alsa-mixer.c +++ b/src/modules/alsa/alsa-mixer.c @@ -1712,7 +1712,9 @@ static int option_verify(pa_alsa_option *o) { { "input-boost-on", N_("Boost") }, { "input-boost-off", N_("No Boost") }, { "output-amplifier-on", N_("Amplifier") }, - { "output-amplifier-off", N_("No Amplifier") } + { "output-amplifier-off", N_("No Amplifier") }, + { "output-speaker", N_("Speaker") }, + { "output-headphones", N_("Headphones") } }; pa_assert(o); @@ -1770,15 +1772,17 @@ static int element_verify(pa_alsa_element *e) { static int path_verify(pa_alsa_path *p) { static const struct description_map well_known_descriptions[] = { - { "analog-input", N_("Analog Input") }, - { "analog-input-microphone", N_("Analog Microphone") }, - { "analog-input-linein", N_("Analog Line-In") }, - { "analog-input-radio", N_("Analog Radio") }, - { "analog-input-video", N_("Analog Video") }, - { "analog-output", N_("Analog Output") }, - { "analog-output-headphones", N_("Analog Headphones") }, - { "analog-output-lfe-on-mono", N_("Analog Output (LFE)") }, - { "analog-output-mono", N_("Analog Mono Output") } + { "analog-input", N_("Analog Input") }, + { "analog-input-microphone", N_("Analog Microphone") }, + { "analog-input-linein", N_("Analog Line-In") }, + { "analog-input-radio", N_("Analog Radio") }, + { "analog-input-video", N_("Analog Video") }, + { "analog-output", N_("Analog Output") }, + { "analog-output-headphones", N_("Analog Headphones") }, + { "analog-output-lfe-on-mono", N_("Analog Output (LFE)") }, + { "analog-output-mono", N_("Analog Mono Output") }, + { "analog-output-headphones-2", N_("Analog Headphones 2") }, + { "analog-output-speaker", N_("Analog Speaker") } }; pa_alsa_element *e; diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c index 22e88b4a..856adb14 100644 --- a/src/modules/alsa/alsa-sink.c +++ b/src/modules/alsa/alsa-sink.c @@ -927,7 +927,7 @@ static int update_sw_params(struct userdata *u) { pa_log_debug("setting avail_min=%lu", (unsigned long) avail_min); - if ((err = pa_alsa_set_sw_params(u->pcm_handle, avail_min)) < 0) { + if ((err = pa_alsa_set_sw_params(u->pcm_handle, avail_min, !u->use_tsched)) < 0) { pa_log("Failed to set software parameters: %s", pa_alsa_strerror(err)); return err; } @@ -1698,10 +1698,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca goto fail; } - if (use_tsched && !pa_rtclock_hrtimer()) { - pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel."); - use_tsched = FALSE; - } + use_tsched = pa_alsa_may_tsched(use_tsched); u = pa_xnew0(struct userdata, 1); u->core = m->core; diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c index fa3ac0aa..e775b20c 100644 --- a/src/modules/alsa/alsa-source.c +++ b/src/modules/alsa/alsa-source.c @@ -877,7 +877,7 @@ static int update_sw_params(struct userdata *u) { pa_log_debug("setting avail_min=%lu", (unsigned long) avail_min); - if ((err = pa_alsa_set_sw_params(u->pcm_handle, avail_min)) < 0) { + if ((err = pa_alsa_set_sw_params(u->pcm_handle, avail_min, !u->use_tsched)) < 0) { pa_log("Failed to set software parameters: %s", pa_alsa_strerror(err)); return err; } @@ -1541,10 +1541,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p goto fail; } - if (use_tsched && !pa_rtclock_hrtimer()) { - pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel."); - use_tsched = FALSE; - } + use_tsched = pa_alsa_may_tsched(use_tsched); u = pa_xnew0(struct userdata, 1); u->core = m->core; diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c index 43a8e829..b8d13575 100644 --- a/src/modules/alsa/alsa-util.c +++ b/src/modules/alsa/alsa-util.c @@ -43,6 +43,7 @@ #include <pulsecore/once.h> #include <pulsecore/thread.h> #include <pulsecore/conf-parser.h> +#include <pulsecore/core-rtclock.h> #include "alsa-util.h" #include "alsa-mixer.h" @@ -403,7 +404,7 @@ finish: return ret; } -int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min) { +int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, pa_bool_t period_event) { snd_pcm_sw_params_t *swparams; snd_pcm_uframes_t boundary; int err; @@ -417,7 +418,7 @@ int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min) { return err; } - if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, 0)) < 0) { + if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, period_event)) < 0) { pa_log_warn("Unable to disable period event: %s\n", pa_alsa_strerror(err)); return err; } @@ -1308,3 +1309,26 @@ const char* pa_alsa_strerror(int errnum) { return translated; } + +pa_bool_t pa_alsa_may_tsched(pa_bool_t want) { + + if (!want) + return FALSE; + + if (!pa_rtclock_hrtimer()) { + /* We cannot depend on being woken up in time when the timers + are inaccurate, so let's fallback to classic IO based playback + then. */ + pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel."); + return FALSE; } + + if (pa_running_in_vm()) { + /* We cannot depend on being woken up when we ask for in a VM, + * so let's fallback to classic IO based playback then. */ + pa_log_notice("Disabling timer-based scheduling because running inside a VM."); + return FALSE; + } + + + return TRUE; +} diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h index 265cd28c..1d1256bd 100644 --- a/src/modules/alsa/alsa-util.h +++ b/src/modules/alsa/alsa-util.h @@ -51,7 +51,8 @@ int pa_alsa_set_hw_params( int pa_alsa_set_sw_params( snd_pcm_t *pcm, - snd_pcm_uframes_t avail_min); + snd_pcm_uframes_t avail_min, + pa_bool_t period_event); /* Picks a working mapping from the profile set based on the specified ss/map */ snd_pcm_t *pa_alsa_open_by_device_id_auto( @@ -141,4 +142,6 @@ pa_bool_t pa_alsa_pcm_is_modem(snd_pcm_t *pcm); const char* pa_alsa_strerror(int errnum); +pa_bool_t pa_alsa_may_tsched(pa_bool_t want); + #endif diff --git a/src/modules/alsa/mixer/paths/analog-input.conf.common b/src/modules/alsa/mixer/paths/analog-input.conf.common index 87af38b3..951e11fa 100644 --- a/src/modules/alsa/mixer/paths/analog-input.conf.common +++ b/src/modules/alsa/mixer/paths/analog-input.conf.common @@ -98,7 +98,11 @@ priority = 18 name = input-docking priority = 17 -;;; ' Capture Source' +[Option Input Source:AUX IN] +name = input +priority = 10 + +;;; 'Capture Source' [Element Capture Source] enumeration = select @@ -244,6 +248,31 @@ name = input-docking [Option Capture Source:Dock Mic] name = input-docking-microphone +;;; 'Mic Jack Mode' + +[Element Mic Jack Mode] +enumeration = select + +[Option Mic Jack Mode:Mic In] +name = input-microphone + +[Option Mic Jack Mode:Line In] +name = input-linein + +;;; 'Digital Input Source' + +[Element Digital Input Source] +enumeration = select + +[Option Digital Input Source:Analog Inputs] +name = input + +[Option Digital Input Source:Digital Mic 1] +name = input-microphone + +[Option Digital Input Source:Digital Mic 2] +name = input-microphone + ;;; Various Boosts [Element Capture Boost] diff --git a/src/modules/alsa/mixer/paths/analog-output-headphones-2.conf b/src/modules/alsa/mixer/paths/analog-output-headphones-2.conf new file mode 100644 index 00000000..f2fd31c7 --- /dev/null +++ b/src/modules/alsa/mixer/paths/analog-output-headphones-2.conf @@ -0,0 +1,82 @@ +# This file is part of PulseAudio. +# +# PulseAudio is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of the +# License, or (at your option) any later version. +# +# PulseAudio is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with PulseAudio; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + +; Path for mixers that have a 'Headphone2' control +; +; See analog-output.conf.common for an explanation on the directives + +[General] +priority = 89 + +[Element Hardware Master] +switch = mute +volume = merge +override-map.1 = all +override-map.2 = all-left,all-right + +[Element Master] +switch = mute +volume = merge +override-map.1 = all +override-map.2 = all-left,all-right + +[Element Master Mono] +switch = off +volume = off + +; This profile path is intended to control the second headphones, not +; the first headphones. But it should not hurt if we leave the +; headphone jack enabled nonetheless. +[Element Headphone] +switch = mute +volume = zero + +[Element Headphone2] +required = any +switch = mute +volume = merge +override-map.1 = all +override-map.2 = all-left,all-right + +[Element Speaker] +switch = off +volume = off + +[Element Front] +switch = off +volume = off + +[Element Rear] +switch = off +volume = off + +[Element Surround] +switch = off +volume = off + +[Element Side] +switch = off +volume = off + +[Element Center] +switch = off +volume = off + +[Element LFE] +switch = off +volume = off + +.include analog-output.conf.common diff --git a/src/modules/alsa/mixer/paths/analog-output-headphones.conf b/src/modules/alsa/mixer/paths/analog-output-headphones.conf index 61d2e297..2131cfe8 100644 --- a/src/modules/alsa/mixer/paths/analog-output-headphones.conf +++ b/src/modules/alsa/mixer/paths/analog-output-headphones.conf @@ -44,6 +44,13 @@ volume = merge override-map.1 = all override-map.2 = all-left,all-right +; This profile path is intended to control the first headphones, not +; the second headphones. But it should not hurt if we leave the second +; headphone jack enabled nonetheless. +[Element Headphone2] +switch = mute +volume = zero + [Element Speaker] switch = off volume = off diff --git a/src/modules/alsa/mixer/paths/analog-output-lfe-on-mono.conf b/src/modules/alsa/mixer/paths/analog-output-lfe-on-mono.conf index 911361d7..0a43e271 100644 --- a/src/modules/alsa/mixer/paths/analog-output-lfe-on-mono.conf +++ b/src/modules/alsa/mixer/paths/analog-output-lfe-on-mono.conf @@ -48,6 +48,10 @@ override-map.2 = lfe,lfe switch = mute volume = zero +[Element Headphone2] +switch = mute +volume = zero + [Element Speaker] switch = mute volume = merge diff --git a/src/modules/alsa/mixer/paths/analog-output-mono.conf b/src/modules/alsa/mixer/paths/analog-output-mono.conf index 2fbc60b7..542edc40 100644 --- a/src/modules/alsa/mixer/paths/analog-output-mono.conf +++ b/src/modules/alsa/mixer/paths/analog-output-mono.conf @@ -45,6 +45,10 @@ override-map.2 = all-left,all-right switch = mute volume = zero +[Element Headphone2] +switch = mute +volume = zero + [Element Speaker] switch = mute volume = merge diff --git a/src/modules/alsa/mixer/paths/analog-output-speaker.conf b/src/modules/alsa/mixer/paths/analog-output-speaker.conf new file mode 100644 index 00000000..aea78534 --- /dev/null +++ b/src/modules/alsa/mixer/paths/analog-output-speaker.conf @@ -0,0 +1,94 @@ +# This file is part of PulseAudio. +# +# PulseAudio is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of the +# License, or (at your option) any later version. +# +# PulseAudio is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with PulseAudio; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + +; Path for mixers that have a 'Speaker' control +; +; See analog-output.conf.common for an explanation on the directives + +[General] +priority = 100 + +[Element Hardware Master] +switch = mute +volume = merge +override-map.1 = all +override-map.2 = all-left,all-right + +[Element Master] +switch = mute +volume = merge +override-map.1 = all +override-map.2 = all-left,all-right + +[Element Master Mono] +switch = off +volume = off + +; This profile path is intended to control the speaker, not the +; headphones. But it should not hurt if we leave the headphone jack +; enabled nonetheless. +[Element Headphone] +switch = mute +volume = zero + +[Element Headphone2] +switch = mute +volume = zero + +[Element Speaker] +required = any +switch = mute +volume = merge +override-map.1 = all +override-map.2 = all-left,all-right + +[Element Front] +switch = mute +volume = merge +override-map.1 = all-front +override-map.2 = front-left,front-right + +[Element Rear] +switch = mute +volume = merge +override-map.1 = all-rear +override-map.2 = rear-left,rear-right + +[Element Surround] +switch = mute +volume = merge +override-map.1 = all-rear +override-map.2 = rear-left,rear-right + +[Element Side] +switch = mute +volume = merge +override-map.1 = all-side +override-map.2 = side-left,side-right + +[Element Center] +switch = mute +volume = merge +override-map.1 = all-center +override-map.2 = all-center,all-center + +[Element LFE] +switch = mute +volume = merge +override-map.1 = lfe +override-map.2 = lfe,lfe + +.include analog-output.conf.common diff --git a/src/modules/alsa/mixer/paths/analog-output.conf b/src/modules/alsa/mixer/paths/analog-output.conf index f71a05a1..d7c1223b 100644 --- a/src/modules/alsa/mixer/paths/analog-output.conf +++ b/src/modules/alsa/mixer/paths/analog-output.conf @@ -14,12 +14,13 @@ # along with PulseAudio; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -; Intended for the 'default' output +; Intended for the 'default' output. Note that a-o-speaker.conf has a +; higher priority than this ; ; See analog-output.conf.common for an explanation on the directives [General] -priority = 100 +priority = 99 [Element Hardware Master] switch = mute @@ -37,18 +38,20 @@ override-map.2 = all-left,all-right switch = off volume = off -; This profile path is intended to control the speaker, not the +; This profile path is intended to control the default output, not the ; headphones. But it should not hurt if we leave the headphone jack ; enabled nonetheless. [Element Headphone] switch = mute volume = zero +[Element Headphone2] +switch = mute +volume = zero + [Element Speaker] switch = mute -volume = merge -override-map.1 = all -override-map.2 = all-left,all-right +volume = off [Element Front] switch = mute diff --git a/src/modules/alsa/mixer/paths/analog-output.conf.common b/src/modules/alsa/mixer/paths/analog-output.conf.common index 3c6ce803..fd7f0cfb 100644 --- a/src/modules/alsa/mixer/paths/analog-output.conf.common +++ b/src/modules/alsa/mixer/paths/analog-output.conf.common @@ -109,3 +109,20 @@ priority = 10 [Option External Amplifier:off] name = output-amplifier-off priority = 0 + +;;; 'Analog Output' + +[Element Analog Output] +enumeration = select + +[Option Analog Output:Speakers] +name = output-speaker +priority = 10 + +[Option Analog Output:Headphones] +name = output-headphones +priority = 9 + +[Option Analog Output:FP Headphones] +name = output-headphones +priority = 8 diff --git a/src/modules/alsa/mixer/profile-sets/default.conf b/src/modules/alsa/mixer/profile-sets/default.conf index ac41a8d3..046938fc 100644 --- a/src/modules/alsa/mixer/profile-sets/default.conf +++ b/src/modules/alsa/mixer/profile-sets/default.conf @@ -62,42 +62,42 @@ auto-profiles = yes [Mapping analog-mono] device-strings = hw:%f channel-map = mono -paths-output = analog-output analog-output-headphones analog-output-mono analog-output-lfe-on-mono +paths-output = analog-output analog-output-speaker analog-output-headphones analog-output-headphones-2 analog-output-mono analog-output-lfe-on-mono paths-input = analog-input analog-input-mic analog-input-linein analog-input-aux analog-input-video analog-input-tvtuner analog-input-fm analog-input-mic-line priority = 1 [Mapping analog-stereo] device-strings = front:%f hw:%f channel-map = left,right -paths-output = analog-output analog-output-headphones analog-output-mono analog-output-lfe-on-mono +paths-output = analog-output analog-output-speaker analog-output-headphones analog-output-headphones-2 analog-output-mono analog-output-lfe-on-mono paths-input = analog-input analog-input-mic analog-input-linein analog-input-aux analog-input-video analog-input-tvtuner analog-input-fm analog-input-mic-line priority = 10 [Mapping analog-surround-40] device-strings = surround40:%f channel-map = front-left,front-right,rear-left,rear-right -paths-output = analog-output analog-output-lfe-on-mono +paths-output = analog-output analog-output-speaker analog-output-lfe-on-mono priority = 7 direction = output [Mapping analog-surround-41] device-strings = surround41:%f channel-map = front-left,front-right,rear-left,rear-right,lfe -paths-output = analog-output analog-output-lfe-on-mono +paths-output = analog-output analog-output-speaker analog-output-lfe-on-mono priority = 8 direction = output [Mapping analog-surround-50] device-strings = surround50:%f channel-map = front-left,front-right,rear-left,rear-right,front-center -paths-output = analog-output analog-output-lfe-on-mono +paths-output = analog-output analog-output-speaker analog-output-lfe-on-mono priority = 7 direction = output [Mapping analog-surround-51] device-strings = surround51:%f channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe -paths-output = analog-output analog-output-lfe-on-mono +paths-output = analog-output analog-output-speaker analog-output-lfe-on-mono priority = 8 direction = output @@ -105,7 +105,7 @@ direction = output device-strings = surround71:%f channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe,side-left,side-right description = Analog Surround 7.1 -paths-output = analog-output analog-output-lfe-on-mono +paths-output = analog-output analog-output-speaker analog-output-lfe-on-mono priority = 7 direction = output diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c index f8c5b778..47d62005 100644 --- a/src/modules/bluetooth/bluetooth-util.c +++ b/src/modules/bluetooth/bluetooth-util.c @@ -723,12 +723,14 @@ const pa_bluetooth_device* pa_bluetooth_discovery_get_by_address(pa_bluetooth_di while ((d = pa_hashmap_iterate(y->devices, &state, NULL))) if (pa_streq(d->address, address)) - return d; + return device_is_audio(d) ? d : NULL; return NULL; } const pa_bluetooth_device* pa_bluetooth_discovery_get_by_path(pa_bluetooth_discovery *y, const char* path) { + pa_bluetooth_device *d; + pa_assert(y); pa_assert(PA_REFCNT_VALUE(y) > 0); pa_assert(path); @@ -736,7 +738,11 @@ const pa_bluetooth_device* pa_bluetooth_discovery_get_by_path(pa_bluetooth_disco if (!pa_hook_is_firing(&y->hook)) pa_bluetooth_discovery_sync(y); - return pa_hashmap_get(y->devices, path); + if ((d = pa_hashmap_get(y->devices, path))) + if (device_is_audio(d)) + return d; + + return NULL; } static int setup_dbus(pa_bluetooth_discovery *y) { diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c index 4592fca1..0ba1421b 100644 --- a/src/modules/bluetooth/module-bluetooth-device.c +++ b/src/modules/bluetooth/module-bluetooth-device.c @@ -74,7 +74,8 @@ PA_MODULE_USAGE( "profile=<a2dp|hsp> " "rate=<sample rate> " "channels=<number of channels> " - "path=<device object path>"); + "path=<device object path> " + "auto_connect=<automatically connect?>"); /* #ifdef NOKIA @@ -98,6 +99,7 @@ static const char* const valid_modargs[] = { "rate", "channels", "path", + "auto_connect", #ifdef NOKIA "sco_sink", "sco_source", @@ -141,6 +143,7 @@ struct userdata { char *address; char *path; pa_bluetooth_discovery *discovery; + pa_bool_t auto_connect; pa_dbus_connection *connection; @@ -399,7 +402,7 @@ static int get_caps(struct userdata *u, uint8_t seid) { pa_assert(u->profile == PROFILE_HSP); msg.getcaps_req.transport = BT_CAPABILITIES_TRANSPORT_SCO; } - msg.getcaps_req.flags = BT_FLAG_AUTOCONNECT; + msg.getcaps_req.flags = u->auto_connect ? BT_FLAG_AUTOCONNECT : 0; if (service_send(u, &msg.getcaps_req.h) < 0) return -1; @@ -2363,6 +2366,12 @@ int pa__init(pa_module* m) { goto fail; } + u->auto_connect = TRUE; + if (pa_modargs_get_value_boolean(ma, "auto_connect", &u->auto_connect)) { + pa_log("Failed to parse auto_connect= argument"); + goto fail; + } + channels = u->sample_spec.channels; if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || channels <= 0 || channels > PA_CHANNELS_MAX) { diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c index 02fd4240..0085fa8e 100644 --- a/src/modules/bluetooth/module-bluetooth-discover.c +++ b/src/modules/bluetooth/module-bluetooth-discover.c @@ -117,7 +117,7 @@ static pa_hook_result_t load_module_for_device(pa_bluetooth_discovery *y, const #endif if (d->audio_source_state >= PA_BT_AUDIO_STATE_CONNECTED) - args = pa_sprintf_malloc("%s profile=\"a2dp_source\"", args); + args = pa_sprintf_malloc("%s profile=\"a2dp_source\" auto_connect=no", args); pa_log_debug("Loading module-bluetooth-device %s", args); m = pa_module_load(u->module->core, "module-bluetooth-device", args); diff --git a/src/modules/jack/module-jack-sink.c b/src/modules/jack/module-jack-sink.c index fc976fa7..9f3e071f 100644 --- a/src/modules/jack/module-jack-sink.c +++ b/src/modules/jack/module-jack-sink.c @@ -334,7 +334,7 @@ int pa__init(pa_module*m) { goto fail; } - ports = jack_get_ports(u->client, NULL, NULL, JackPortIsPhysical|JackPortIsInput); + ports = jack_get_ports(u->client, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical|JackPortIsInput); channels = 0; for (p = ports; *p; p++) diff --git a/src/modules/jack/module-jack-source.c b/src/modules/jack/module-jack-source.c index a898e0e5..6c68527b 100644 --- a/src/modules/jack/module-jack-source.c +++ b/src/modules/jack/module-jack-source.c @@ -286,7 +286,7 @@ int pa__init(pa_module*m) { goto fail; } - ports = jack_get_ports(u->client, NULL, NULL, JackPortIsPhysical|JackPortIsOutput); + ports = jack_get_ports(u->client, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical|JackPortIsOutput); channels = 0; for (p = ports; *p; p++) diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c index 29c3ddab..bb0182b0 100644 --- a/src/modules/module-loopback.c +++ b/src/modules/module-loopback.c @@ -102,7 +102,7 @@ struct userdata { static const char* const valid_modargs[] = { "source", "sink", - "latency", + "latency_msec", "format", "rate", "channels", diff --git a/src/modules/module-position-event-sounds.c b/src/modules/module-position-event-sounds.c index 7221b14f..ee4c8c88 100644 --- a/src/modules/module-position-event-sounds.c +++ b/src/modules/module-position-event-sounds.c @@ -74,7 +74,7 @@ static int parse_pos(const char *pos, double *f) { } static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *core, pa_sink_input_new_data *data, struct userdata *u) { - const char *hpos, *vpos, *role; + const char *hpos, *vpos, *role, *id; double f; char t[PA_CVOLUME_SNPRINT_MAX]; pa_cvolume v; @@ -87,6 +87,22 @@ static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *core, pa_sink_i if (!pa_streq(role, "event")) return PA_HOOK_OK; + if ((id = pa_proplist_gets(data->proplist, PA_PROP_EVENT_ID))) { + + /* The test sounds should never be positioned in space, since + * they might be trigered themselves to configure the speakers + * in space, which we don't want to mess up. */ + + if (pa_startswith(id, "audio-channel-")) + return PA_HOOK_OK; + + if (pa_streq(id, "audio-volume-change")) + return PA_HOOK_OK; + + if (pa_streq(id, "audio-test-signal")) + return PA_HOOK_OK; + } + if (!(hpos = pa_proplist_gets(data->proplist, PA_PROP_EVENT_MOUSE_HPOS))) hpos = pa_proplist_gets(data->proplist, PA_PROP_WINDOW_HPOS); diff --git a/src/pulse/ext-stream-restore.h b/src/pulse/ext-stream-restore.h index 0b5d8eb6..54516f63 100644 --- a/src/pulse/ext-stream-restore.h +++ b/src/pulse/ext-stream-restore.h @@ -24,6 +24,8 @@ #include <pulse/context.h> #include <pulse/version.h> +#include <pulse/volume.h> +#include <pulse/channelmap.h> /** \file * diff --git a/src/pulse/stream.h b/src/pulse/stream.h index 21dd0a85..bc54a118 100644 --- a/src/pulse/stream.h +++ b/src/pulse/stream.h @@ -31,6 +31,8 @@ #include <pulse/def.h> #include <pulse/cdecl.h> #include <pulse/operation.h> +#include <pulse/context.h> +#include <pulse/proplist.h> /** \page streams Audio Streams * @@ -399,7 +401,22 @@ int pa_stream_is_suspended(pa_stream *s); * not, and negative on error. \since 0.9.11 */ int pa_stream_is_corked(pa_stream *s); -/** Connect the stream to a sink */ +/** Connect the stream to a sink. It is strongly recommended to pass + * NULL in both dev and volume and not to set either + * PA_STREAM_START_MUTED nor PA_STREAM_START_UNMUTED -- unless these + * options are directly dependant on user input or configuration. If + * you follow this rule then the sound server will have the full + * flexibility to choose the device, volume and mute status + * automatically, based on server-side policies, heuristics and stored + * information from previous uses. Also the server may choose to + * reconfigure audio devices to make other sinks/sources or + * capabilities available to be able to accept the stream. Before + * 0.9.20 it was not defined whether the 'volume' parameter was + * interpreted relative to the sink's current volume or treated as + * absolute device volume. Since 0.9.20 it is an absolute volume when + * the sink is in flat volume mode, and relative otherwise, thus + * making sure the volume passed here has always the same semantics as + * the volume passed to pa_context_set_sink_input_volume(). */ int pa_stream_connect_playback( pa_stream *s /**< The stream to connect to a sink */, const char *dev /**< Name of the sink to connect to, or NULL for default */ , diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 8e98e857..258e8eec 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -117,6 +117,7 @@ #include <pulsecore/strbuf.h> #include <pulsecore/usergroup.h> #include <pulsecore/strlist.h> +#include <pulsecore/cpu-x86.h> #include "core-util.h" @@ -2867,3 +2868,93 @@ const char *pa_get_temp_dir(void) { return "/tmp"; } + +char *pa_read_line_from_file(const char *fn) { + FILE *f; + char ln[256] = "", *r; + + if (!(f = fopen(fn, "r"))) + return NULL; + + r = fgets(ln, sizeof(ln)-1, f); + fclose(f); + + if (!r) { + errno = EIO; + return NULL; + } + + pa_strip_nl(ln); + return pa_xstrdup(ln); +} + +pa_bool_t pa_running_in_vm(void) { + +#if defined(__i386__) || defined(__x86_64__) + + /* Both CPUID and DMI are x86 specific interfaces... */ + + uint32_t eax = 0x40000000; + union { + uint32_t sig32[3]; + char text[13]; + } sig; + +#ifdef __linux__ + const char *const dmi_vendors[] = { + "/sys/class/dmi/id/sys_vendor", + "/sys/class/dmi/id/board_vendor", + "/sys/class/dmi/id/bios_vendor" + }; + + unsigned i; + + for (i = 0; i < PA_ELEMENTSOF(dmi_vendors); i++) { + char *s; + + if ((s = pa_read_line_from_file(dmi_vendors[i]))) { + + if (pa_startswith(s, "QEMU") || + /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */ + pa_startswith(s, "VMware") || + pa_startswith(s, "VMW") || + pa_startswith(s, "Microsoft Corporation") || + pa_startswith(s, "innotek GmbH") || + pa_startswith(s, "Xen")) { + + pa_xfree(s); + return TRUE; + } + + pa_xfree(s); + } + } + +#endif + + /* http://lwn.net/Articles/301888/ */ + pa_zero(sig); + + __asm__ __volatile__ ( + /* ebx/rbx is being used for PIC! */ + " push %%"PA_REG_b" \n\t" + " cpuid \n\t" + " mov %%ebx, %1 \n\t" + " pop %%"PA_REG_b" \n\t" + + : "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2]) + : "0" (eax) + ); + + if (pa_streq(sig.text, "XenVMMXenVMM") || + pa_streq(sig.text, "KVMKVMKVM") || + /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */ + pa_streq(sig.text, "VMwareVMware") || + /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */ + pa_streq(sig.text, "Microsoft Hv")) + return TRUE; + +#endif + + return FALSE; +} diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index 84752d4d..eba1b404 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -251,4 +251,7 @@ pa_bool_t pa_run_from_build_tree(void); const char *pa_get_temp_dir(void); +char *pa_read_line_from_file(const char *fn); +pa_bool_t pa_running_in_vm(void); + #endif diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index d06dd4eb..6e357624 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -1044,13 +1044,21 @@ static playback_stream* playback_stream_new( data.driver = __FILE__; data.module = c->options->module; data.client = c->client; - data.sink = sink; + if (sink) { + data.sink = sink; + data.save_sink = TRUE; + } pa_sink_input_new_data_set_sample_spec(&data, ss); pa_sink_input_new_data_set_channel_map(&data, map); - if (volume) + if (volume) { pa_sink_input_new_data_set_volume(&data, volume); - if (muted_set) + data.volume_is_absolute = TRUE; + data.save_volume = TRUE; + } + if (muted_set) { pa_sink_input_new_data_set_muted(&data, muted); + data.save_muted = TRUE; + } data.sync_base = ssync ? ssync->sink_input : NULL; data.flags = flags; @@ -2612,7 +2620,7 @@ static void command_get_record_latency(pa_pdispatch *pd, uint32_t command, uint3 pa_tagstruct_put_usec(reply, s->current_monitor_latency); pa_tagstruct_put_usec(reply, s->current_source_latency + - pa_bytes_to_usec(s->on_the_fly_snapshot, &s->source_output->sample_spec)); + pa_bytes_to_usec(s->on_the_fly_snapshot, &s->source_output->source->sample_spec)); pa_tagstruct_put_boolean(reply, pa_source_get_state(s->source_output->source) == PA_SOURCE_RUNNING && pa_source_output_get_state(s->source_output) == PA_SOURCE_OUTPUT_RUNNING); diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 1af2823f..aa84ccb1 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -717,14 +717,15 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, p pa_memchunk rchunk; pa_resampler_run(i->thread_info.resampler, &wchunk, &rchunk); - if (nvfs) { - pa_memchunk_make_writable(&rchunk, 0); - pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &i->volume_factor_sink); - } - /* pa_log_debug("pushing %lu", (unsigned long) rchunk.length); */ if (rchunk.memblock) { + + if (nvfs) { + pa_memchunk_make_writable(&rchunk, 0); + pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &i->volume_factor_sink); + } + pa_memblockq_push_align(i->thread_info.render_memblockq, &rchunk); pa_memblock_unref(rchunk.memblock); } diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index bda92fcc..e6d718f7 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -926,18 +926,16 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume); - if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&volume)) { - if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume)) { - pa_memblock_unref(result->memblock); - pa_silence_memchunk_get(&s->core->silence_cache, - s->core->mempool, - result, - &s->sample_spec, - result->length); - } else { - pa_memchunk_make_writable(result, 0); - pa_volume_memchunk(result, &s->sample_spec, &volume); - } + if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume)) { + pa_memblock_unref(result->memblock); + pa_silence_memchunk_get(&s->core->silence_cache, + s->core->mempool, + result, + &s->sample_spec, + result->length); + } else if (!pa_cvolume_is_norm(&volume)) { + pa_memchunk_make_writable(result, 0); + pa_volume_memchunk(result, &s->sample_spec, &volume); } } else { void *ptr; diff --git a/src/pulsecore/svolume_mmx.c b/src/pulsecore/svolume_mmx.c index 1768eb50..46923ed3 100644 --- a/src/pulsecore/svolume_mmx.c +++ b/src/pulsecore/svolume_mmx.c @@ -60,7 +60,9 @@ " movq "#s", %%mm5 \n\t" \ " pmulhw "#v", "#s" \n\t" /* .. | 0 | vl*p0 | */ \ " paddw %%mm4, "#s" \n\t" /* .. | 0 | vl*p0 | + sign correct */ \ + " pslld $16, "#s" \n\t" /* .. | vl*p0 | 0 | */ \ " psrld $16, "#v" \n\t" /* .. | 0 | vh | */ \ + " psrad $16, "#s" \n\t" /* .. | vl*p0 | sign extend */ \ " pmaddwd %%mm5, "#v" \n\t" /* .. | p0 * vh | */ \ " paddd "#s", "#v" \n\t" /* .. | p0 * v0 | */ \ " packssdw "#v", "#v" \n\t" /* .. | p1*v1 | p0*v0 | */ @@ -152,7 +154,7 @@ pa_volume_s16ne_mmx (int16_t *samples, int32_t *volumes, unsigned channels, unsi " emms \n\t" : "+r" (samples), "+r" (volumes), "+r" (length), "=D" ((pa_reg_x86)channel), "=&r" (temp) - : "X" ((pa_reg_x86)channels) + : "rm" ((pa_reg_x86)channels) : "cc" ); } @@ -228,7 +230,7 @@ pa_volume_s16re_mmx (int16_t *samples, int32_t *volumes, unsigned channels, unsi " emms \n\t" : "+r" (samples), "+r" (volumes), "+r" (length), "=D" ((pa_reg_x86)channel), "=&r" (temp) - : "X" ((pa_reg_x86)channels) + : "rm" ((pa_reg_x86)channels) : "cc" ); } @@ -255,11 +257,14 @@ static void run_test (void) { printf ("checking MMX %zd\n", sizeof (samples)); pa_random (samples, sizeof (samples)); + /* for (i = 0; i < SAMPLES; i++) + samples[i] = -1; */ memcpy (samples_ref, samples, sizeof (samples)); memcpy (samples_orig, samples, sizeof (samples)); for (i = 0; i < CHANNELS; i++) volumes[i] = rand() >> 1; + /* volumes[i] = 0x0000ffff; */ for (padding = 0; padding < PADDING; padding++, i++) volumes[i] = volumes[padding]; @@ -267,7 +272,7 @@ static void run_test (void) { pa_volume_s16ne_mmx (samples, volumes, CHANNELS, sizeof (samples)); for (i = 0; i < SAMPLES; i++) { if (samples[i] != samples_ref[i]) { - printf ("%d: %04x != %04x (%04x * %04x)\n", i, samples[i], samples_ref[i], + printf ("%d: %04x != %04x (%04x * %08x)\n", i, samples[i], samples_ref[i], samples_orig[i], volumes[i % CHANNELS]); } } diff --git a/src/pulsecore/svolume_sse.c b/src/pulsecore/svolume_sse.c index ab9394fb..1cc4e0aa 100644 --- a/src/pulsecore/svolume_sse.c +++ b/src/pulsecore/svolume_sse.c @@ -149,7 +149,7 @@ pa_volume_s16ne_sse2 (int16_t *samples, int32_t *volumes, unsigned channels, uns "8: \n\t" : "+r" (samples), "+r" (volumes), "+r" (length), "=D" (channel), "=&r" (temp) - : "X" ((pa_reg_x86)channels) + : "rm" ((pa_reg_x86)channels) : "cc" ); } @@ -237,7 +237,7 @@ pa_volume_s16re_sse2 (int16_t *samples, int32_t *volumes, unsigned channels, uns "8: \n\t" : "+r" (samples), "+r" (volumes), "+r" (length), "=D" (channel), "=&r" (temp) - : "X" ((pa_reg_x86)channels) + : "rm" ((pa_reg_x86)channels) : "cc" ); } |