]> code.delx.au - pulseaudio/commitdiff
Merge branch 'master' of git://0pointer.de/pulseaudio
authorDaniel Mack <daniel@caiaq.de>
Wed, 11 Nov 2009 09:48:39 +0000 (10:48 +0100)
committerDaniel Mack <daniel@caiaq.de>
Wed, 11 Nov 2009 09:48:39 +0000 (10:48 +0100)
20 files changed:
man/Makefile.am
src/daemon/main.c
src/map-file
src/modules/alsa/alsa-mixer.c
src/modules/alsa/alsa-sink.c
src/modules/alsa/alsa-source.c
src/modules/alsa/alsa-util.c
src/modules/alsa/alsa-util.h
src/modules/alsa/mixer/paths/analog-output.conf.common
src/modules/jack/module-jack-sink.c
src/modules/jack/module-jack-source.c
src/modules/module-lirc.c
src/modules/module-mmkbd-evdev.c
src/pulse/ext-device-manager.h
src/pulse/volume.c
src/pulse/volume.h
src/pulsecore/core-util.c
src/pulsecore/core-util.h
src/pulsecore/protocol-native.c
src/pulsecore/sink-input.c

index 9b229f52a8856a15d8470f75ac82baa9a6d9a3a1..7793fe7d4df14cbcc6bce56cfc3000c124bff871 100644 (file)
@@ -20,21 +20,6 @@ pulseconfdir=$(sysconfdir)/pulse
 CLEANFILES = \
        $(noinst_DATA)
 
-dist_man_MANS = \
-       pulseaudio.1 \
-       esdcompat.1 \
-       pax11publish.1 \
-       paplay.1 \
-       pacat.1 \
-       pacmd.1 \
-       pactl.1 \
-       pasuspender.1 \
-       padsp.1 \
-       pabrowse.1 \
-       pulse-daemon.conf.5 \
-       pulse-client.conf.5 \
-       default.pa.5
-
 noinst_DATA = \
        pulseaudio.1.xml \
        esdcompat.1.xml \
@@ -50,24 +35,39 @@ noinst_DATA = \
        pulse-client.conf.5.xml \
        default.pa.5.xml
 
-if BUILD_MANPAGES
-
-CLEANFILES += \
-       $(dist_man_MANS)
-
 %.xml: %.xml.in Makefile
        sed -e 's,@pulseconfdir\@,$(pulseconfdir),g' \
            -e 's,@PACKAGE_BUGREPORT\@,$(PACKAGE_BUGREPORT),g' \
             -e 's,@PACKAGE_URL\@,$(PACKAGE_URL),g' $< > $@
 
-%: %.xml Makefile
-       perl $(srcdir)/xmltoman $< > $@ || rm -f $@
-
 xmllint: $(noinst_DATA)
        for f in $(noinst_DATA) ; do \
                        xmllint --noout --valid "$$f" || exit 1 ; \
        done
 
+if BUILD_MANPAGES
+
+dist_man_MANS = \
+       pulseaudio.1 \
+       esdcompat.1 \
+       pax11publish.1 \
+       paplay.1 \
+       pacat.1 \
+       pacmd.1 \
+       pactl.1 \
+       pasuspender.1 \
+       padsp.1 \
+       pabrowse.1 \
+       pulse-daemon.conf.5 \
+       pulse-client.conf.5 \
+       default.pa.5
+
+CLEANFILES += \
+       $(dist_man_MANS)
+
+%: %.xml Makefile
+       perl $(srcdir)/xmltoman $< > $@ || rm -f $@
+
 endif
 
 EXTRA_DIST = \
index cc6f24bdcd0a9a8ae9d11654928a5d7fecd2304f..4891182733cf1285a1556391d156b6266b53c22f 100644 (file)
@@ -648,7 +648,6 @@ int main(int argc, char *argv[]) {
 
     if (conf->daemonize) {
         pid_t child;
-        int tty_fd;
 
         if (pa_stdio_acquire() < 0) {
             pa_log(_("Failed to acquire stdio."));
@@ -781,6 +780,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
index 50111224c24467046dde68a3f81a052ade88b164..1fffaff986982d33cc314e2683455cd30e80c6c9 100644 (file)
@@ -130,6 +130,7 @@ pa_cvolume_get_balance;
 pa_cvolume_get_fade;
 pa_cvolume_get_position;
 pa_cvolume_inc;
+pa_cvolume_inc_clamp;
 pa_cvolume_init;
 pa_cvolume_max;
 pa_cvolume_max_mask;
index f3ce681f55124ed9d253f730272ec73f0564be4c..8b13239ca566e016d630c8e8008161cddd0185bc 100644 (file)
@@ -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;
index 37419d98c426f21d7cb2860b66667e7495ff2351..856adb144f78cfa5f592b6d5b1a39d43a74fdb77 100644 (file)
@@ -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;
index 37dd64765bbed33cd5f2d0a6651a24dd3f6ef720..e775b20c60df34864fe19463dfea9c47c6252146 100644 (file)
@@ -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;
index 0e22d17e467aaca47d8f004940a3a5461717204d..b8d135758439bc18c80a2b245f69cb3e7a21df44 100644 (file)
@@ -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"
@@ -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;
+}
index f6206fe23631a71e43fe76320ccbf5df46a792a0..1d1256bd38dfde7b71b5452bb95cbf9b7316ca4b 100644 (file)
@@ -142,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
index 3c6ce80366fde0b74a2a56efe4bef4d50d7b1305..fd7f0cfb1c759b19cfd2daf7ecdf7b7392a4621d 100644 (file)
@@ -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
index fc976fa72a6d1def62e5e0817e1596df6e637895..9f3e071fd6d0a073e0546c7abeff82c3d0c7f58c 100644 (file)
@@ -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++)
index a898e0e5ac8430df5d637fb475981caea41c3eb0..6c68527b63932a4e65683c72cbcb15e564a2663c 100644 (file)
@@ -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++)
index d0e902f69b3b080e34b9005d68d30af49aa9fbc5..e97786206066c2412a27063ff95c68798085cd62 100644 (file)
@@ -45,12 +45,14 @@ PA_MODULE_AUTHOR("Lennart Poettering");
 PA_MODULE_DESCRIPTION("LIRC volume control");
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(TRUE);
-PA_MODULE_USAGE("config=<config file> sink=<sink name> appname=<lirc application name>");
+PA_MODULE_USAGE("config=<config file> sink=<sink name> appname=<lirc application name> volume_limit=<volume limit> volume_step=<volume change step>");
 
 static const char* const valid_modargs[] = {
     "config",
     "sink",
     "appname",
+    "volume_limit",
+    "volume_step",
     NULL,
 };
 
@@ -61,10 +63,10 @@ struct userdata {
     char *sink_name;
     pa_module *module;
     float mute_toggle_save;
+    pa_volume_t volume_limit;
+    pa_volume_t volume_step;
 };
 
-#define DELTA (PA_VOLUME_NORM/20)
-
 static void io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event_flags_t events, void*userdata) {
     struct userdata *u = userdata;
     char *name = NULL, *code = NULL;
@@ -125,12 +127,12 @@ static void io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event
 
                     switch (volchange) {
                         case UP:
-                            pa_cvolume_inc(&cv, DELTA);
+                            pa_cvolume_inc_clamp(&cv, u->volume_step, u->volume_limit);
                             pa_sink_set_volume(s, &cv, TRUE, TRUE);
                             break;
 
                         case DOWN:
-                            pa_cvolume_dec(&cv, DELTA);
+                            pa_cvolume_dec(&cv, u->volume_step);
                             pa_sink_set_volume(s, &cv, TRUE, TRUE);
                             break;
 
@@ -170,6 +172,8 @@ fail:
 int pa__init(pa_module*m) {
     pa_modargs *ma = NULL;
     struct userdata *u;
+    pa_volume_t volume_limit = PA_VOLUME_NORM*3/2;
+    pa_volume_t volume_step = PA_VOLUME_NORM/20;
 
     pa_assert(m);
 
@@ -178,6 +182,16 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
+    if (pa_modargs_get_value_u32(ma, "volume_limit", &volume_limit) < 0) {
+        pa_log("Failed to parse volume limit");
+        goto fail;
+    }
+
+    if (pa_modargs_get_value_u32(ma, "volume_step", &volume_step) < 0) {
+        pa_log("Failed to parse volume step");
+        goto fail;
+    }
+
     m->userdata = u = pa_xnew(struct userdata, 1);
     u->module = m;
     u->io = NULL;
@@ -185,6 +199,8 @@ int pa__init(pa_module*m) {
     u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));
     u->lirc_fd = -1;
     u->mute_toggle_save = 0;
+    u->volume_limit = volume_limit;
+    u->volume_step = volume_step;
 
     if ((u->lirc_fd = lirc_init((char*) pa_modargs_get_value(ma, "appname", "pulseaudio"), 1)) < 0) {
         pa_log("lirc_init() failed.");
index 14a9dd3d5cad89ac35a4045f949191526205b93b..193c1f40ae7f89f0a80717c9c51b450bfa879047 100644 (file)
@@ -48,13 +48,15 @@ PA_MODULE_AUTHOR("Lennart Poettering");
 PA_MODULE_DESCRIPTION("Multimedia keyboard support via Linux evdev");
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(FALSE);
-PA_MODULE_USAGE("device=<evdev device> sink=<sink name>");
+PA_MODULE_USAGE("device=<evdev device> sink=<sink name> volume_limit=<volume limit> volume_step=<volume change step>");
 
 #define DEFAULT_DEVICE "/dev/input/event0"
 
 static const char* const valid_modargs[] = {
     "device",
     "sink",
+    "volume_limit",
+    "volume_step",
     NULL,
 };
 
@@ -63,10 +65,10 @@ struct userdata {
     pa_io_event *io;
     char *sink_name;
     pa_module *module;
+    pa_volume_t volume_limit;
+    pa_volume_t volume_step;
 };
 
-#define DELTA (PA_VOLUME_NORM/20)
-
 static void io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event_flags_t events, void*userdata) {
     struct userdata *u = userdata;
 
@@ -120,12 +122,12 @@ static void io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event
 
                     switch (volchange) {
                         case UP:
-                            pa_cvolume_inc(&cv, DELTA);
+                            pa_cvolume_inc_clamp(&cv, u->volume_step, u->volume_limit);
                             pa_sink_set_volume(s, &cv, TRUE, TRUE);
                             break;
 
                         case DOWN:
-                            pa_cvolume_dec(&cv, DELTA);
+                            pa_cvolume_dec(&cv, u->volume_step);
                             pa_sink_set_volume(s, &cv, TRUE, TRUE);
                             break;
 
@@ -160,6 +162,8 @@ int pa__init(pa_module*m) {
     struct input_id input_id;
     char name[256];
     uint8_t evtype_bitmask[EV_MAX/8 + 1];
+    pa_volume_t volume_limit = PA_VOLUME_NORM*3/2;
+    pa_volume_t volume_step = PA_VOLUME_NORM/20;
 
     pa_assert(m);
 
@@ -168,12 +172,24 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
+    if (pa_modargs_get_value_u32(ma, "volume_limit", &volume_limit) < 0) {
+        pa_log("Failed to parse volume limit");
+        goto fail;
+    }
+
+    if (pa_modargs_get_value_u32(ma, "volume_step", &volume_step) < 0) {
+        pa_log("Failed to parse volume step");
+        goto fail;
+    }
+
     m->userdata = u = pa_xnew(struct userdata, 1);
     u->module = m;
     u->io = NULL;
     u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));
     u->fd = -1;
     u->fd_type = 0;
+    u->volume_limit = volume_limit;
+    u->volume_step = volume_step;
 
     if ((u->fd = pa_open_cloexec(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), O_RDONLY, 0)) < 0) {
         pa_log("Failed to open evdev device: %s", pa_cstrerror(errno));
index 1442a1a9e94fa2fa7cccd65ef7c46db3f2143216..8264b8f7a950ae0013cbca1533cc5bc9e85bd823 100644 (file)
@@ -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.19 */
+ * maintained by module-device-manager. \since 0.9.20 */
 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.19 */
+/** Callback prototype for pa_ext_device_manager_test(). \since 0.9.20 */
 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.19 */
+/** Test if this extension module is available in the server. \since 0.9.20 */
 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.19 */
+/** Callback prototype for pa_ext_device_manager_read(). \since 0.9.20 */
 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.19 */
+/** Read all entries from the device database. \since 0.9.20 */
 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.19 */
+/** Sets the description for a device. \since 0.9.20 */
 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.19 */
+/** Delete entries from the device database. \since 0.9.20 */
 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.19 */
+/** Enable the role-based device-priority routing mode. \since 0.9.20 */
 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.19 */
+/** Prefer a given device in the priority list. \since 0.9.20 */
 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.19 */
+/** Subscribe to changes in the device database. \since 0.9.20 */
 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.19 */
+/** Callback prototype for pa_ext_device_manager_set_subscribe_cb(). \since 0.9.20 */
 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.19 */
+ * pa_ext_device_manager_subscribe() was called. \since 0.9.20 */
 void pa_ext_device_manager_set_subscribe_cb(
         pa_context *c,
         pa_ext_device_manager_subscribe_cb_t cb,
index 2d2bba2506defa3b878040801a07880f715213d5..59e9a18906777f19b659b734986d8f9e18d2f4ab 100644 (file)
@@ -885,7 +885,7 @@ pa_cvolume* pa_cvolume_merge(pa_cvolume *dest, const pa_cvolume *a, const pa_cvo
     return dest;
 }
 
-pa_cvolume* pa_cvolume_inc(pa_cvolume *v, pa_volume_t inc) {
+pa_cvolume* pa_cvolume_inc_clamp(pa_cvolume *v, pa_volume_t inc, pa_volume_t limit) {
     pa_volume_t m;
 
     pa_assert(v);
@@ -895,14 +895,18 @@ pa_cvolume* pa_cvolume_inc(pa_cvolume *v, pa_volume_t inc) {
 
     m = pa_cvolume_max(v);
 
-    if (m >= PA_VOLUME_MAX - inc)
-        m = PA_VOLUME_MAX;
+    if (m >= limit - inc)
+        m = limit;
     else
         m += inc;
 
     return pa_cvolume_scale(v, m);
 }
 
+pa_cvolume* pa_cvolume_inc(pa_cvolume *v, pa_volume_t inc){
+    return pa_cvolume_inc_clamp(v, inc, PA_VOLUME_MAX);
+}
+
 pa_cvolume* pa_cvolume_dec(pa_cvolume *v, pa_volume_t dec) {
     pa_volume_t m;
 
index c964020ac4e5e3bda205f7483585b168793643fd..ded4422e81e60223026a1f8f0ee2e74a03199354 100644 (file)
@@ -348,6 +348,10 @@ pa_volume_t pa_cvolume_get_position(pa_cvolume *cv, const pa_channel_map *map, p
  * and dest may point to the same structure. \since 0.9.16 */
 pa_cvolume* pa_cvolume_merge(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b);
 
+/** Increase the volume passed in by 'inc', but not exceeding 'limit'.
+ * The proportions between the channels are kept. \since 0.9.19 */
+pa_cvolume* pa_cvolume_inc_clamp(pa_cvolume *v, pa_volume_t inc, pa_volume_t limit);
+
 /** Increase the volume passed in by 'inc'. The proportions between
  * the channels are kept. \since 0.9.16 */
 pa_cvolume* pa_cvolume_inc(pa_cvolume *v, pa_volume_t inc);
index 2b0a60a802c6ee4f430b24d0da0e24a78542a556..d596c481a9b3c1f5336867b8854b2b9a3a34fbcc 100644 (file)
 #include <pulsecore/strbuf.h>
 #include <pulsecore/usergroup.h>
 #include <pulsecore/strlist.h>
+#include <pulsecore/cpu-x86.h>
 
 #include "core-util.h"
 
@@ -2944,6 +2945,7 @@ int pa_pipe_cloexec(int pipefd[2]) {
 
     if (errno != EINVAL && errno != ENOSYS)
         return r;
+
 #endif
 
     if ((r = pipe(pipefd)) < 0)
@@ -2965,6 +2967,7 @@ int pa_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
 
     if (errno != EINVAL && errno != ENOSYS)
         return fd;
+
 #endif
 
     if ((fd = accept(sockfd, addr, addrlen)) < 0)
@@ -3015,3 +3018,93 @@ void pa_nullify_stdfds(void) {
 #endif
 
 }
+
+char *pa_read_line_from_file(const char *fn) {
+    FILE *f;
+    char ln[256] = "", *r;
+
+    if (!(f = pa_fopen_cloexec(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;
+}
index 9c9cf78ab97ebf30456eebf059050c09ff9bccc3..31a83bcc2336e0cb304395899cd901edeeeee4cb 100644 (file)
@@ -267,4 +267,7 @@ FILE* pa_fopen_cloexec(const char *path, const char *mode);
 
 void pa_nullify_stdfds(void);
 
+char *pa_read_line_from_file(const char *fn);
+pa_bool_t pa_running_in_vm(void);
+
 #endif
index bb29a196dfca478b10a2828a96f9691f748c2d12..d49a78e5d3b902b453893b1b3e21953312264087 100644 (file)
@@ -2631,7 +2631,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);
index 1af2823f91a06cfbf4651d036f60d07c9b46db45..aa84ccb1e566f43e64c146ab3a9316637776258a 100644 (file)
@@ -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);
                 }