Re: [pulseaudio-discuss] [PATCH] fix the assumption that volume is always positive
On Thu, 2011-05-26 at 09:50 +0100, Colin Guthrie wrote: 'Twas brillig, and Lu Guanqun at 26/05/11 09:49 did gyre and gimble: Add a variable to track whether the actual volume is set or not. Suppose this: min volume: -126max volume: 0 then when user wants to set some constant volume to -10, it would fail. Tanu, are you OK with this patch? Maybe, maybe not. I posted a question to alsa-devel: http://mailman.alsa-project.org/pipermail/alsa-devel/2011-May/040213.html If negative steps are allowed, I expect there to be more bugs. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] How to change profile of bluetooth headset for different applications?
On Mon, 2011-05-23 at 18:18 +0100, Colin Guthrie wrote: How about this: Define a new card property similar in concept to PA_PROP_DEVICE_INTENDED_ROLES (device.intended_roles) called PA_PROP_DEVICE_INTENDED_PROFILE (device.intended_profile). In bluetooth device, when loading a headset that has both HSP and A2DP, populate the device with the following code: if (supports_hsp supports_a2dp) { char *k; k = pa_sprintf_malloc(%s.%s, PA_PROP_DEVICE_INTENDED_PROFILE, music); pa_proplist_sets(card_data.proplist, k, a2dp); pa_xfree(k); k = pa_sprintf_malloc(%s.%s, PA_PROP_DEVICE_INTENDED_PROFILE, video); pa_proplist_sets(card_data.proplist, k, a2dp); pa_xfree(k); k = pa_sprintf_malloc(%s.%s, PA_PROP_DEVICE_INTENDED_PROFILE, phone); pa_proplist_sets(card_data.proplist, k, hsp); pa_xfree(k); } This should result in pacmd list-cards dumping a proplist that includes: device.intended_profile.music = a2dp device.intended_profile.video = a2dp device.intended_profile.phone = hsp Then a separate module (module-intended-profiles?) could take care of listening quite generically for streams landing on sink and do the following logic: if (!si-sink || !si-sink-card) return PA_HOOK_OK; char *role = pa_proplist_gets(si-proplist, PA_PROP_MEDIA_ROLE); if (!role) return PA_HOOK_OK; char *k = pa_sprintf_malloc(%s.%s, PA_PROP_DEVICE_INTENDED_PROFILE, role); pa_card *card = si-sink-card; char *profile = pa_proplist_gets(card-proplist, k); pa_xfree(k); if (!profile) return PA_HOOK_OK; if (!pa_streq(card-active_profile, profile)) { /* Save the current profile for later restoration */ ... if (pa_card_set_profile(card, profile, FALSE) 0) /* Find the sink of this card as the above call will likely have changed it */ sink = pa_idxset_first(card-sinks, NULL); pa_sink_input_move_to(si, sink, FALSE); } This code is then completely generic. I'm not 100% sure how well this will work in practice as there may be some nasty races etc. but I think this general approach could work... Perhaps others (i.e. Tanu :D) have better suggestions? If the priority lists would exist already, the module deciding the routing could examine the stream properties and pick the sink+port with the highest priority that can be made available - if the sink+port isn't immediately available, but can be made available, then the routing module would change the profile and port as needed. But the priority lists are not available. I believe the logic that you propose is otherwise good, except that I don't see how the stream could land on the bluetooth (a2dp) sink automatically on phone calls. module-bluetooth-device tags only hsp sinks with the phone tag, not a2dp sinks, so module-intended-roles can't do the required magic. If the hsp sink doesn't exist because the a2dp profile is selected, I don't think there's currently any logic to route the stream to the bluetooth sink. If, however, by some magic the phone stream would be routed to the a2dp sink, then I think your proposal would work fine. For better suggestions, I don't think I have any. Except that use the policy framework - Lin posted from an intel.com address, so I assume he or she (sorry, I don't know Chinese names) is working on Meego, and I've thought that Meego got the policy framework from Maemo. In Maemo the routing is handled by module-policy-enforcement (which gets the command to enable the bluetooth-hsp routing mode from the policy framework), and it works pretty nicely for this kind of use cases. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [PATCH] fix the assumption that volume is always positive
On Thu, 2011-05-26 at 14:08 +0300, Tanu Kaskinen wrote: On Thu, 2011-05-26 at 09:50 +0100, Colin Guthrie wrote: 'Twas brillig, and Lu Guanqun at 26/05/11 09:49 did gyre and gimble: Add a variable to track whether the actual volume is set or not. Suppose this: min volume: -126max volume: 0 then when user wants to set some constant volume to -10, it would fail. Tanu, are you OK with this patch? Maybe, maybe not. I posted a question to alsa-devel: http://mailman.alsa-project.org/pipermail/alsa-devel/2011-May/040213.html If negative steps are allowed, I expect there to be more bugs. I got a confirmation that negative volumes are allowed, so the patch should be fine. Somebody should review the alsa mixer code for other cases of the invalid assumption (I plan to do it in the indefinite future, if nobody else does it). -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [PATCH 1/2] alsa: add jack detection support
Sorry for late reply... On Fri, 2011-05-20 at 09:14 -0500, Jorge Eduardo Candelaria wrote: +if (event-value) +pa_hook_fire(u-core-hooks[PA_CORE_HOOK_JACK_INSERT], jack); +else +pa_hook_fire(u-core-hooks[PA_CORE_HOOK_JACK_REMOVE], jack); Firing core hooks directly from modules looks a bit dirty to me. I'm actually not very familiar with hooks, however do we need to signal the jack insertion/removal events from jack_report(). What would be a more clean solution? Adding just a couple of trivial functions to the core would probably suffice: void pa_jack_inserted(pa_core *c, pa_jack_event *e); void pa_jack_removed(pa_core *c, pa_jack_event *e); Those functions would do nothing but call pa_hook_fire(), so this is a purely cosmetic thing... -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [PATCH 2/2] alsa: load jack detection module
On Thu, 2011-05-19 at 11:44 -0500, Jorge Eduardo Candelaria wrote: From: Margarita Olaya Cabrera m...@slimlogic.co.uk This patch adds support for udev detection of sound card jack event devices. When a new card is detected, the code now also checks for the presence of any associated input device via udev, and report the device to module-alsa-card via its jack_id parameter. Jack support development was kindly sponsored by Wolfson Microelectronics PLC Signed-off-by: Margarita Olaya Cabrera m...@slimlogic.co.uk Signed-off-by: Jorge Eduardo Candelaria j...@slimlogic.co.uk --- src/modules/module-udev-detect.c | 68 ++--- 1 files changed, 62 insertions(+), 6 deletions(-) diff --git a/src/modules/module-udev-detect.c b/src/modules/module-udev-detect.c index 63ad195..4321b32 100644 --- a/src/modules/module-udev-detect.c +++ b/src/modules/module-udev-detect.c @@ -71,6 +71,8 @@ struct userdata { int inotify_fd; pa_io_event *inotify_io; + +char *card_name; This doesn't really seem to be used for anything. }; static const char* const valid_modargs[] = { @@ -163,6 +165,21 @@ static pa_bool_t pcm_is_modem(const char *card_idx, const char *pcm) { return is_modem; } +static pa_bool_t input_node_belongs_to_device( +struct device *d, +const char *node) { + +char *cd; +pa_bool_t b; + +cd = pa_sprintf_malloc(/sys%s, d-path); + +b = pa_startswith(node, cd); +pa_xfree(cd); + +return b; +} + static pa_bool_t is_card_busy(const char *id) { char *card_path = NULL, *pcm_path = NULL, *sub_status = NULL; DIR *card_dir = NULL, *pcm_dir = NULL; @@ -352,11 +369,26 @@ static void verify_access(struct userdata *u, struct device *d) { } } +static const char *jack_get_input_id(const char *path) { +int i; + +for( i = 0; i strlen(path); i++) { strlen() is called in each iteration - it would be better to save its return value outside the loop. +if (pa_startswith(path + i, /input)) +return path + i + 6; +} + +return NULL; +} + static void card_changed(struct userdata *u, struct udev_device *dev) { struct device *d; +struct udev_enumerate *enumerate; +struct udev_list_entry *item, *first; const char *path; const char *t; char *n; +char *jack_path; +char *jack_input; pa_assert(u); pa_assert(dev); @@ -383,6 +415,28 @@ static void card_changed(struct userdata *u, struct udev_device *dev) { n = pa_namereg_make_valid_name(t); d-card_name = pa_sprintf_malloc(alsa_card.%s, n); + +if (!(enumerate = udev_enumerate_new(u-udev))) +pa_log(Failed to initialize udev enumerator); +else { +if (!udev_enumerate_add_match_subsystem(enumerate, input)) +pa_log_debug(Failed to match to subsystem input); + +if (udev_enumerate_scan_devices(enumerate)) +pa_log_debug(Failed to scan for devices); Should these two errors abort the enumeration, or is a debug message really good enough error handling here? + +first = udev_enumerate_get_list_entry(enumerate); +udev_list_entry_foreach(item, first) { +jack_path = udev_list_entry_get_name(item); +if (input_node_belongs_to_device(d, jack_path)) { +jack_input = pa_xstrdup(jack_get_input_id(jack_path)); +pa_log_debug(jack is %s\n, jack_input); jack_input can, at least in theory, be null (or if it can't, you should add an assertion to jack_get_input_id() instead of returning NULL). I'm not sure what happens if you pass a null pointer as a string to the log functions - does it crash, or does it work? There's the pa_strnull() function that returns the string (null) if the argument is null, and the function is being used in similar contexts as this one. Either you should call pa_strnull() here, or the other uses of pa_strnull() are redundant. +break; +} +} +udev_enumerate_unref(enumerate); +} + d-args = pa_sprintf_malloc(device_id=\%s\ name=\%s\ card_name=\%s\ @@ -390,15 +444,19 @@ static void card_changed(struct userdata *u, struct udev_device *dev) { tsched=%s ignore_dB=%s sync_volume=%s +jack_id=\%s\ card_properties=\module-udev-detect.discovered=1\, path_get_card_id(path), n, d-card_name, pa_yes_no(u-use_tsched), pa_yes_no(u-ignore_dB), -pa_yes_no(u-sync_volume)); -pa_xfree(n); +
Re: [pulseaudio-discuss] How to debug a protocol error message?
Sorry for joining the discussion late... I haven't read Pulseaudio mail since last Thursday. On Tue, 2011-05-24 at 09:20 +0100, Colin Guthrie wrote: Yup Maarten's advice is good there. But what is interesting is that our official 0.9.15 version ships with protocol 15, not 16... Your debug suggests the the remote end is protocol 16.. This suggests to me that the extensions in the Maemo version are non-standard and therefore require consultation with their lists. You should check their code to see what commits changed the protocol version to 16. It could be that they just backported the changes from our version 16 shipped in 0.9.16 (which was an API to select client side API detection) or it could be something completely custom. As I'm not familiar with their modifications, I cannot really help. Fremantle's Pulseaudio protocol is not compatible with upstream versions greater than 0.9.15. The changes that bumped the protocol version number to 16 were originally supposed to go upstream, but the work never got finished, and the incompatibilities didn't get fixed in time either. I'm sorry for messing that up. Quinn asked whether it's possible to force Pulseaudio to use an older protocol version. That's not currently possible, but maybe it would make sense to add such a feature? I imagine it wouldn't be too hard. I don't think there are any other reasonably easy solutions. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] Glitches on null sink?
On Fri, 2011-05-20 at 21:28 +0200, mar...@saepia.net wrote: Hi, I continue to develop my radio audio routing software so I continue to encounter strange bugs. General idea that lies behind my project is to split some processing parts into separate processes. There are many reasons why this architecture has to be like this, it something fundamental and won't change. For processing individual elements I use GStreamer (no external bindings, my code is in C). There're many advanced dedicated input sources, such as RTP/VoIP/shoutcast. All of them load their own null sink module, and perform output on one. Other modules that broadcast the signal to the FM/net just leech from their .monitor PA sources. To this moment everything works flawlessly, even if I load huge amount of sources. The problem is when I try to perform some audio processing or/and mixing. Currently I do that in the following way: 1. Load another null sink module for mix output. 2. Run GStreamer's pipelines (each is also a separate process), e.g.: a) pulsesrc device=source1.monitor ! processor1 ! processor2 ! pulsesink device=mix b) pulsesrc device=source2.monitor ! processor3 ! processor4 ! pulsesink device=mix It generally works ok, but from time to time, output (captured from mix.monitor) becomes full of glitches. Sounds like something lost synchronisation. And it's really hard to reproduce. Sometimes I run that kind of pipeline and it works for a long time and then it starts doing weird things, sometimes it starts it from the beginning. When it starts producing glitches, pulsesrc element in the GStreamer pipeline throws an error that it cannot read samples fast enough. What is interesting, when it starts doing that, any other audio that I pass to this mix sink also sounds bad from the begin. Only reloading module helps. My theory is that I have to use module-combine to perform such mixing. Am I correct? I don't think module-combine is relevant here. It should do mixing in the exact same way as module-null-sink and all other sinks. I don't guarantee that anyone will volunteer debugging this problem (it doesn't sound easy), but could you upload somewhere a sample recording of the glitchy audio? I wanted to avoid that as I am unable to dynamically add its slaves, but if it's the only way to perform such mix, I will do that, and reload it when my dedicated sources' list changes... It's not too pretty as it would produce short drops, but it's still acceptable. I just want you to ask if I am seeking for the problem in the correct place, just before I spend a week on refactoring my code. Maybe pipeline like shown above (pulseaudio - GStreamer - pulseaudio) also is a wrong approach? Generally pulseaudio - app - pulseaudio is a non-optimal approach, because the source and the sink usually have different clocks, and therefore they drift. There should be some adaptive resampling to mitigate the drift. I have an impression that GStreamer provides this kind of resampling, though. If you don't already have one, you could try adding a queue element in the GStreamer pipelines (this may be completely bogus advice, though, as I'm not a GStreamer expert). -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [PATCH] alsa-mixer: When setting hw volume, round always up with playback and always down with capture.
On Tue, 2011-05-17 at 19:40 +0100, Colin Guthrie wrote: Just to report that a modified version of that patch does indeed fix the problem for me. What do you think overall? Should we try and hunt down the problems with the conversion or should this patch be included? I think it would make sense to save the intermediate volume as integer millibels - that way there couldn't be any rounding errors, because no rounding would happen. The patch works, though, so I'm not against applying it. That would be the easier way forward - from a quick glance at the code it seems that changing the volume format will involve more than just changing a variable type. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [PATCH] alsa-mixer: When setting hw volume, round always up with playback and always down with capture.
On Tue, 2011-05-17 at 12:13 +0100, Colin Guthrie wrote: Thanks, I'll test this patch and see if it helps with my test case. Assuming that it does, is this something we should really push to alsa lib? When I first encountered the problem I did start hacking away at alsa lib looking for the problem. Perhaps a new direction argument -2 and +2 for nearest below bias and nearest above bias respectively? (the bias only coming into play when there you are exactly inbetween two possible values). Nah, if we need rounding to the nearest step only for working around rounding errors that are caused by ourselves due to not-entirely-necessary format conversions, I don't think alsa-lib should be changed just for that. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] Jack detection (was: Re: [PATCHv3 0/4] Read and store UCM data as proplist)
On Tue, 2011-05-17 at 13:44 +0200, David Henningsson wrote: Agree with the port property. About the port vs profile question, I think we might think that backwards from a user's perspective. Conceptually I'd say we select port first (manually or automatic; doesn't matter for this reasoning), then we evaluate what profiles make sense to try. If we're on headphones, only stereo profile makes sense, if we're on line-out, we might want to consider surround profiles. At least I would want it to work that way in the UI. Could you elaborate on having profiles without ports? IIRC Pulseaudio would fail in this case. No, Pulseaudio doesn't fail in the scenario that I'm talking about - the no ports situation is an optimization for the case when there would be only one port to select from. If the profile (or more precisely the mapping associated with that profile) has only one path in the mixer configuration, then the sink or source will not export any ports at all. The reasoning for that is probably that having a single port on a sink would be redundant, because currently the only functionality ports offer is that the user can change between them. However, if the available property is added to ports, then exposing even just one port on a sink will not be redundant. I'm not sure what you are proposing with regards to selecting ports. Did I understand correctly that the user should be presented with all ports of all sinks and sources of a card in one big list? Pulseaudio should have an abstraction for jacks. Jack objects would be created by whatever alsa module is appropriate for that. Maybe module-alsa-card would be the best choice, or maybe not. There exists hardware where physical jacks are shared between multiple alsa cards. Really? Is that some embedded scenario? Yep. Simplifying a bit, one card handles the playback uses of the jack, and one card handles the capture uses of the jack. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [PATCH 1/2] alsa: add jack detection support
I tried to apply the patch for easier review in meld, but unfortunately it seems that some helpful software has eaten the first space on lines that begin with one or more spaces. Because of that, git am doesn't accept the patch. I'll review this anyway, without meld. Overall comments: there is some confusion about whether the jack stuff is a core concept (hooks in pa_core) or an alsa specific thing (all jack related type definitions are in alsa-jack.h). I think it probably makes sense to keep alsa-jack.h as an alsa specific thing, but then the core hooks shouldn't be tied to alsa-jack.h like they are now. In the longer term I hope the thing how policy modules interact with jack detection will be monitoring the (currently not existing) available status of the port objects. However, if you don't want to start working on that now, I'd just move alsa-jack.h under pulsecore (and of course rename it). The only major issue in my opinion is the jack_fd reading. It should be made non-blocking. -- Tanu On Thu, 2011-05-19 at 11:44 -0500, Jorge Eduardo Candelaria wrote: From: Margarita Olaya Cabrera m...@slimlogic.co.uk This patch adds support to module-alsa-card so that we can read jack insertion and removal events using the input device subsystem. i.e. we can detect headphone insertions and removals. This patch adds a new module parameter called jack_id that contains the ID of the jack input device associated with this sound card. If we receive a valid jack_id during module init then we start a reader thread that will read the jack input device and fire a hook on every removal and insertion event. Jack support development was kindly sponsored by Wolfson Microelectronics PLC Signed-off-by: Margarita Olaya Cabrera m...@slimlogic.co.uk Signed-off-by: Jorge Eduardo Candelaria j...@slimlogic.co.uk --- src/modules/alsa/alsa-jack.h| 42 src/modules/alsa/module-alsa-card.c | 120 +++ src/pulsecore/core.h|2 + 3 files changed, 164 insertions(+), 0 deletions(-) create mode 100644 src/modules/alsa/alsa-jack.h diff --git a/src/modules/alsa/alsa-jack.h b/src/modules/alsa/alsa-jack.h new file mode 100644 index 000..4fc67c6 --- /dev/null +++ b/src/modules/alsa/alsa-jack.h @@ -0,0 +1,42 @@ +#ifndef foopulsejackdetecthfoo +#define foopulsejackdetecthfoo + +/*** + This file is part of PulseAudio. + + Copyright 2011 Wolfson Microelectronics PLC + Author Margarita Olaya m...@slimlogic.co.uk + + 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. +***/ + +#include inttypes.h + +typedef enum pa_jack_event { +PA_JACK_HEADPHONES, +PA_JACK_HEADSET, +PA_JACK_MICROPHONE, +PA_JACK_LINEOUT, +PA_JACK_UNKNOWN, +PA_JACK_MAX +} pa_jack_event_t; + +typedef struct pa_jack_detect { +pa_jack_event_t event; +char *card; Instead of the card name, would it be better to store a pa_card pointer here? It seems that you have the card object available when you initialize this struct. +} pa_jack_detect_t; Structs shouldn't have the _t suffix. (Enum typedefs should, so the pa_jack_event_t name is correct.) If this is alsa specific, like it seems to be, judging from the file location and name, I recommend prefixing the types with pa_alsa_jack_, because all other alsa stuff uses pa_alsa_ prefix too. Hmm... on the other hand, this struct is passed to a core hook, so maybe these types are not really alsa specific, and should be defined in a header under src/pulsecore/? Also, I think pa_jack_event would be a better name for what you've now named pa_jack_detect, and the enum could be pa_jack_type_t. +#endif diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c index e60aa5e..75202fb 100644 --- a/src/modules/alsa/module-alsa-card.c +++ b/src/modules/alsa/module-alsa-card.c @@ -29,6 +29,9 @@ #include pulsecore/core-util.h #include pulsecore/modargs.h #include pulsecore/queue.h +#include pulsecore/thread.h + +#include linux/input.h #include modules/reserve-wrap.h @@ -39,6 +42,7 @@ #include alsa-util.h #include alsa-sink.h #include alsa-source.h +#include alsa-jack.h #include module-alsa-card-symdef.h PA_MODULE_AUTHOR(Lennart Poettering); @@ -55,6 +59,7 @@
Re: [pulseaudio-discuss] [PATCH] alsa-mixer: When setting hw volume, round always up with playback and always down with capture.
On Mon, 2011-05-16 at 21:22 +0100, Colin Guthrie wrote: OK, here is the debug output from my run using this volume approach As you can see there are several points where the message: Written HW volume did not match with the request is shown. This is shown quite clearly when writing the volumes to h/w I suspect this problem arrises due to the use of pa_cvolume_divide() which is based around PA_VOLUME_NORM, when the second argument (the software volume) is PA_VOLUME_NORM. Any thoughts on this are welcome. I'll quote the log: D: protocol-native.c: Client pavucontrol changes volume of source alsa_input.pci-_00_1b.0.analog-stereo. D: alsa-source.c: Requested volume: 0: 45% 1: 45% D: alsa-source.c:in dB: 0: -20.71 dB 1: -20.71 dB D: alsa-source.c: Got hardware volume: 0: 45% 1: 45% D: alsa-source.c: in dB: 0: -21.00 dB 1: -21.00 dB D: alsa-source.c: Calculated software volume: 0: 101% 1: 101% (accurate-enough=no) D: alsa-source.c: in dB: 0: 0.29 dB 1: 0.29 dB D: source.c: Volume going up to 29273 at 270475970821 D: source.c: Volume change to 29273 at 270475970821 was written 34 usec late D: alsa-source.c: Written HW volume did not match with the request: 0: 45% 1: 45% (request) != 0: 42% 1: 42% D: alsa-source.c:in dB: 0: -21.00 dB 1: -21.00 dB (request) != 0: -22.50 dB 1: -22.50 dB Looking at the last line, the requested volume seems to hit exactly the right step (-21.00dB), but for some reason Alsa decides to choose something else. I'm pretty sure that this happens because of rounding errors. In the first phase we ask Alsa what dB value we should set, and it returns -21.00 dB. The value is given as a long int, but we convert that to pa_cvolume. Then when we set the volume, we convert the pa_cvolume value back to a long integer. At this point I believe it gets converted to -2101. This is not visible in the debug message for some reason - the rounding algorithm must be different from what was used with the pa_cvolume - long conversion. Here's a patch that should fix the problem: http://meego.gitorious.org/maemo-multimedia/pulseaudio/commit/a88c2b1d9f8c2088a430a257470a70efeaaf4b34 -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH] alsa-mixer: When setting hw volume, round always up with playback and always down with capture.
This was discussed on the mailing list: https://tango.0pointer.de/pipermail/pulseaudio-discuss/2011-May/010091.html --- src/modules/alsa/alsa-mixer.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c index f236da0..8375a2f 100644 --- a/src/modules/alsa/alsa-mixer.c +++ b/src/modules/alsa/alsa-mixer.c @@ -893,7 +893,7 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann if (e-has_dB) { long value = to_alsa_dB(f); -int rounding = value 0 ? -1 : +1; +int rounding = e-direction == PA_ALSA_DIRECTION_OUTPUT ? +1 : -1; if (e-volume_limit = 0 value (e-max_dB * 100)) value = e-max_dB * 100; -- 1.7.5.1 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH] bluetooth: Add missing return statement.
--- src/modules/bluetooth/module-bluetooth-device.c |2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c index 086fce9..ae522bc 100644 --- a/src/modules/bluetooth/module-bluetooth-device.c +++ b/src/modules/bluetooth/module-bluetooth-device.c @@ -1957,6 +1957,8 @@ static int sco_over_pcm_state_update(struct userdata *u, pa_bool_t changed) { return 0; } + +return 0; } static pa_hook_result_t sink_state_changed_cb(pa_core *c, pa_sink *s, struct userdata *u) { -- 1.7.5.1 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH] loopback: Add a modarg for disabling remixing.
--- src/modules/module-loopback.c | 18 +- 1 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c index 9a8640b..024337f 100644 --- a/src/modules/module-loopback.c +++ b/src/modules/module-loopback.c @@ -59,7 +59,8 @@ PA_MODULE_USAGE( sink_input_role=media.role for the sink input source_output_role=media.role for the source output source_dont_move=boolean -sink_dont_move=boolean); +sink_dont_move=boolean +remix=remix channels? ); #define DEFAULT_LATENCY_MSEC 200 @@ -120,6 +121,7 @@ static const char* const valid_modargs[] = { source_output_role, source_dont_move, sink_dont_move, +remix, NULL, }; @@ -407,7 +409,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk u-in_pop = FALSE; if (pa_memblockq_peek(u-memblockq, chunk) 0) { -pa_log_info(Coud not peek into queue); +pa_log_info(Could not peek into queue); return -1; } @@ -645,6 +647,7 @@ int pa__init(pa_module *m) { pa_memchunk silence; uint32_t adjust_time_sec; const char *n; +pa_bool_t remix = TRUE; pa_assert(m); @@ -663,6 +666,11 @@ int pa__init(pa_module *m) { goto fail; } +if (pa_modargs_get_value_boolean(ma, remix, remix) 0) { +pa_log(Invalid boolean remix parameter); +goto fail; +} + ss = sink-sample_spec; map = sink-channel_map; if (pa_modargs_get_sample_spec_and_channel_map(ma, ss, map, PA_CHANNEL_MAP_DEFAULT) 0) { @@ -713,7 +721,7 @@ int pa__init(pa_module *m) { pa_sink_input_new_data_set_sample_spec(sink_input_data, ss); pa_sink_input_new_data_set_channel_map(sink_input_data, map); -sink_input_data.flags = PA_SINK_INPUT_VARIABLE_RATE; +sink_input_data.flags = PA_SINK_INPUT_VARIABLE_RATE | (remix ? 0 : PA_SINK_INPUT_NO_REMIX); sink_dont_move = FALSE; if (pa_modargs_get_value_boolean(ma, sink_dont_move, sink_dont_move) 0) { @@ -764,8 +772,8 @@ int pa__init(pa_module *m) { pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_ICON_NAME, n); pa_source_output_new_data_set_sample_spec(source_output_data, ss); -pa_sink_input_new_data_set_channel_map(sink_input_data, map); -source_output_data.flags = (pa_source_output_flags_t)0; +pa_source_output_new_data_set_channel_map(source_output_data, map); +source_output_data.flags = (remix ? 0 : PA_SOURCE_OUTPUT_NO_REMIX); source_dont_move = FALSE; if (pa_modargs_get_value_boolean(ma, source_dont_move, source_dont_move) 0) { -- 1.7.5.1 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] Reverting ade0a6f88464d8aecf83982d400ccfc402341920
Hello, Should this commit be reverted? http://git.0pointer.de/?p=pulseaudio.git;a=commit;h=ade0a6f88464d8aecf83982d400ccfc402341920 I don't know what problem that commit solves, but it introduces a new problem: if Pulseaudio requests a volume that is above 0dB in the alsa volume element scale, then it can easily happen that alsa will round the request down. That rounding is then compensated with software volume, which in this case is amplification. We don't want software amplification, or do we? -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] Is there any way to remap source channels?
On Fri, 2011-05-13 at 11:30 +0200, mar...@saepia.net wrote: Hi, is there any way to remap source channels? I need the same functionality as provided by module-remap-sink, but for sources - I use multichannel soundcard (RME Hammerfall) and I want to create virtual sources that map to stereo pairs of my inputs. Then I want to use their names in my application. module-remap-source would be nice to have. But we don't have it. A very ugly hack, which I'm not sure even works, would be to configure the channel map of the sound card to have only aux channels (required to prevent remixing), then load a null sink with two channels (channel map matched to the desired channels on the sound card), then load module-loopback that loops the sound card to the null sink. Then you can record from the null sink's monitor. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] Is there any way to remap source channels?
On Fri, 2011-05-13 at 14:14 +0200, mar...@saepia.net wrote: Why should I prevent remixing? Can't I just use module-loopback with channel_map set? I think this is what happens (I haven't tested): if you have non-aux channels on the sound card, let's say front-left, front-right, rear-left and rear-right, and you try to loop back just rear-left and rear-right, the resampler (which really takes care of more conversion than just sample rate) will try to be smart and mix some of front-left and front-right into the rear-left and rear-right channels. The same logic is involved always when a stream - be it capture or playback - is connected to a device that doesn't have the same parameters as the stream. Configuring the device to use aux channels should disable the intelligent remixing - only the channels specified by the stream will be taken from the source. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] Reverting ade0a6f88464d8aecf83982d400ccfc402341920
On Fri, 2011-05-13 at 17:29 +0200, David Henningsson wrote: In short; if we e g have Mic Boost levels at (0dB, 20dB, 40dB and 60dB) and the user wants 30 dB, better have 20dB in hardware and +10dB in software than 40dB in hardware and -10dB in software, as the latter one is more likely to have digital distortion when the signal passes through the ADC. There is a longer email on this list a while back, explaining more of the philosophy behind, but I can't seem to find it right now. Ok, I think I understand why rounding down makes sense when recording. With playback, however, rounding towards 0 dB is definetely broken. My ability to think clearly happens to be currently a bit weakened, so I have to ask you: what's so magic about 0 dB? With playback rounding should always be done up - would it make sense to round always down with capture? -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] Is there any way to remap source channels?
On Fri, 2011-05-13 at 17:05 +0100, Colin Guthrie wrote: FWIW, some modules, like module-remap-sink take a remix=yes|no argument to control this behaviour even when using standard channel names. module-loopback should have a similar argument, but it doesn't... -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] realtime kernel RLIMIT_RTTIME crashes, rewinds
Sorry for the delayed reply. On Wed, 2011-04-27 at 13:23 +0300, Dan Muresan wrote: I've patched (as in attachment) src/daemon/main.c to set the soft rttime limit lower than the hard limit. This way I was able to get a backtrace in gdb when pulseaudio received SIGXCPU due to excessive real-time CPU usage: #0 0x0012d422 in ?? () #1 0x00475edb in write () at ../sysdeps/unix/syscall-template.S:82 #2 0x00153a55 in pa_fdsem_post (f=0x806e178) at pulsecore/fdsem.c:205 #3 0x0013cb0f in push (l=0x8071bc8, p=0x8, wait_op=false) at pulsecore/asyncq.c:161 #4 0x0013d291 in pa_asyncq_post (l=0x8071bc8, p=0x80736d8) at pulsecore/asyncq.c:203 #5 0x0013c1ee in pa_asyncmsgq_post (a=0x8071a90, object=0xb6a16a08, code=7, userdata=0x0, offset=0, chunk=0xb590, free_cb=0) at pulsecore/asyncmsgq.c:139 #6 0x009811d7 in pstream_memblock_callback (p=0x808cf78, channel=0, offset=0, seek=PA_SEEK_RELATIVE, chunk=0xb590, userdata=0x80b6480) at pulsecore/protocol-native.c:4445 #7 0x001dd20b in ?? () from /usr/lib/libpulsecommon-0.9.22.so #8 0x001c823e in ?? () from /usr/lib/libpulsecommon-0.9.22.so #9 0x0021b5fb in pa_mainloop_dispatch () from /usr/lib/libpulse.so.0 #10 0x0021bb11 in pa_mainloop_iterate () from /usr/lib/libpulse.so.0 #11 0x0021bbd4 in pa_mainloop_run () from /usr/lib/libpulse.so.0 #12 0x08052e85 in main (argc=1, argv=0xb854) at daemon/main.c:974 Can someone point out the likely cause, or is this not enough information? This is pulseaudio 0.9.22 from Ubuntu Natty. I would guess that the excessive cpu use is caused by doing rewinds in rapid succession. That's just a guess, though - the backtrace doesn't really give any clue. There have been issues with rewinds happening in some kind of a loop. David Henningson has been working on this problem and he has made at least a few patches that help with the problem. The patches are in Pulseaudio's git repository at least. Since David works for Canonical, I would expect the fixes to be also in Ubuntu, but I don't know for sure. David, what's the status of the fighting rewinds patches in Ubuntu Natty? Is the problem supposed to be fixed already? -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH] match: Support for both merging and replacing proplist updates.
This patch adds a new update mode specifier that can be optionally given in match rules after the regexp. Propertly list updates triggered by the rule will honour the given mode. The two allowed modes are 'merge' and 'replace', corresponding to PA_UPDATE_MERGE and PA_UPDATE_REPLACE respectively. If omitted, the mode defaults to PA_UPDATE_MERGE, ie. to the original behavior. For example, to force 'media.role' to be overwritten with 'bar' for streams matching foo you can use an entry like this: foo replace bar This will really overwrite media.role to bar even if it has already been set to something else by the application. Thanks to Krisztian Litkey for the original patch and the description above. In addition to implementing the new feature, this patch fixes a number of bugs in the parsing code. --- src/modules/module-match.c | 97 +++- 1 files changed, 60 insertions(+), 37 deletions(-) diff --git a/src/modules/module-match.c b/src/modules/module-match.c index b3316d4..c94ef79 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -60,6 +60,9 @@ PA_MODULE_USAGE(table=filename #define DEFAULT_MATCH_TABLE_FILE PA_DEFAULT_CONFIG_DIR/match.table #define DEFAULT_MATCH_TABLE_FILE_USER match.table +#define UPDATE_REPLACE replace +#define UPDATE_MERGE merge + static const char* const valid_modargs[] = { table, key, @@ -70,6 +73,7 @@ struct rule { regex_t regex; pa_volume_t volume; pa_proplist *proplist; +pa_update_mode_t mode; struct rule *next; }; @@ -101,13 +105,14 @@ static int load_rules(struct userdata *u, const char *filename) { pa_lock_fd(fileno(f), 1); while (!feof(f)) { -char *d, *v; +char *token_end, *value_str; pa_volume_t volume = PA_VOLUME_NORM; uint32_t k; regex_t regex; char ln[256]; struct rule *rule; pa_proplist *proplist = NULL; +pa_update_mode_t mode = (pa_update_mode_t) -1; if (!fgets(ln, sizeof(ln), f)) break; @@ -119,51 +124,72 @@ static int load_rules(struct userdata *u, const char *filename) { if (ln[0] == '#' || !*ln ) continue; -d = ln+strcspn(ln, WHITESPACE); -v = d+strspn(d, WHITESPACE); +token_end = ln + strcspn(ln, WHITESPACE); +value_str = token_end + strspn(token_end, WHITESPACE); +*token_end = 0; +if (!*ln) { +pa_log([%s:%u] failed to parse line - missing regexp, fn, n); +goto finish; +} -if (!*v) { -pa_log(__FILE__ : [%s:%u] failed to parse line - too few words, filename, n); +if (!*value_str) { +pa_log([%s:%u] failed to parse line - too few words, fn, n); goto finish; } -*d = 0; -if (pa_atou(v, k) = 0) { +if (pa_atou(value_str, k) = 0) volume = (pa_volume_t) PA_CLAMP_VOLUME(k); -} else if (*v == '') { -char *e; - -e = strchr(v+1, ''); -if (!e) { -pa_log(__FILE__ : [%s:%u] failed to parse line - missing role closing quote, filename, n); -goto finish; -} - -*e = '\0'; -e = pa_sprintf_malloc(media.role=\%s\, v+1); -proplist = pa_proplist_from_string(e); -pa_xfree(e); -} else { -char *e; - -e = v+strspn(v, WHITESPACE); -if (!*e) { -pa_log(__FILE__ : [%s:%u] failed to parse line - missing end of property list, filename, n); -goto finish; -} -*e = '\0'; -proplist = pa_proplist_from_string(v); +else { +size_t len; + +token_end = value_str + strcspn(value_str, WHITESPACE); + +len = token_end - value_str; +if (len == (sizeof(UPDATE_REPLACE) - 1) !strncmp(value_str, UPDATE_REPLACE, len)) +mode = PA_UPDATE_REPLACE; +else if (len == (sizeof(UPDATE_MERGE) - 1) !strncmp(value_str, UPDATE_MERGE, len)) +mode = PA_UPDATE_MERGE; + +if (mode != (pa_update_mode_t) -1) { +value_str = token_end + strspn(token_end, WHITESPACE); + +if (!*value_str) { +pa_log([%s:%u] failed to parse line - too few words, fn, n); +goto finish; +} +} else +mode = PA_UPDATE_MERGE; + +if (*value_str == '') { +value_str++; + +token_end = strchr(value_str, ''); +if (!token_end) { +pa_log([%s:%u] failed to parse line - missing role closing quote, fn, n); +goto finish; +} +} else +token_end = value_str + strcspn(value_str, WHITESPACE); + +*token_end = 0; + +
[pulseaudio-discuss] [PATCH 0/2] Fixing module-dbus-protocol unloading
There were a couple of crash bugs in the module-dbus-protocol unloading code, which became visible when unloading the module while there were still clients connected. Tanu Kaskinen (2): dbus: Fix connection idxset freeing when unloading the module. dbus: Fix the order of freeing stuff when unloading module-dbus-protocol. src/modules/dbus/module-dbus-protocol.c | 29 +++-- 1 files changed, 15 insertions(+), 14 deletions(-) -- 1.7.4.2 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH 2/2] dbus: Fix the order of freeing stuff when unloading module-dbus-protocol.
--- src/modules/dbus/module-dbus-protocol.c | 12 +--- 1 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/modules/dbus/module-dbus-protocol.c b/src/modules/dbus/module-dbus-protocol.c index 276c6ba..4969585 100644 --- a/src/modules/dbus/module-dbus-protocol.c +++ b/src/modules/dbus/module-dbus-protocol.c @@ -592,14 +592,20 @@ void pa__done(pa_module *m) { if (u-core_iface) pa_dbusiface_core_free(u-core_iface); -if (u-cleanup_event) -m-core-mainloop-defer_free(u-cleanup_event); - while ((c = pa_idxset_steal_first(u-connections, NULL))) connection_free(c); pa_idxset_free(u-connections, NULL, NULL); +/* This must not be called before the connections are freed, because if + * there are any connections left, they will emit the + * org.freedesktop.DBus.Local.Disconnected signal, and + * disconnection_filter_cb() will be called. disconnection_filter_cb() then + * tries to enable the defer event, and if it's already freed, an assertion + * will be hit in mainloop.c. */ +if (u-cleanup_event) +m-core-mainloop-defer_free(u-cleanup_event); + if (u-tcp_server) server_free(u-tcp_server); -- 1.7.4.2 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH 1/2] dbus: Fix connection idxset freeing when unloading the module.
If u-connections isn't empty when module-dbus-protocol is unloaded, then connection_free() is called for the remaining connections when the idxset is freed. connection_free() tries to remove the connection from the idxset, but that fails, because the item has already been removed from the idxset in this scenario. The problem is solved by not trying to remove the connection from the idxset in connection_free(). Instead, whoever wants to delete connections, has to remove the connection from the idxset in addition to calling connection_free(). --- src/modules/dbus/module-dbus-protocol.c | 21 - 1 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/modules/dbus/module-dbus-protocol.c b/src/modules/dbus/module-dbus-protocol.c index aa11cdf..276c6ba 100644 --- a/src/modules/dbus/module-dbus-protocol.c +++ b/src/modules/dbus/module-dbus-protocol.c @@ -105,7 +105,6 @@ static void connection_free(struct connection *c) { pa_assert_se(pa_dbus_protocol_unregister_connection(c-server-userdata-dbus_protocol, pa_dbus_wrap_connection_get(c-wrap_conn)) = 0); pa_client_free(c-client); -pa_assert_se(pa_idxset_remove_by_data(c-server-userdata-connections, c, NULL)); pa_dbus_wrap_connection_free(c-wrap_conn); pa_xfree(c); } @@ -514,8 +513,10 @@ static void cleanup_cb(pa_mainloop_api *a, pa_defer_event *e, void *userdata) { uint32_t idx; PA_IDXSET_FOREACH(conn, u-connections, idx) { -if (!dbus_connection_get_is_connected(pa_dbus_wrap_connection_get(conn-wrap_conn))) +if (!dbus_connection_get_is_connected(pa_dbus_wrap_connection_get(conn-wrap_conn))) { +pa_idxset_remove_by_data(u-connections, conn, NULL); connection_free(conn); +} } u-module-core-mainloop-defer_enable(e, 0); @@ -579,17 +580,9 @@ fail: return -1; } -/* Called by idxset when the connection set is freed. */ -static void connection_free_cb(void *p, void *userdata) { -struct connection *conn = p; - -pa_assert(conn); - -connection_free(conn); -} - void pa__done(pa_module *m) { struct userdata *u; +struct connection *c; pa_assert(m); @@ -602,8 +595,10 @@ void pa__done(pa_module *m) { if (u-cleanup_event) m-core-mainloop-defer_free(u-cleanup_event); -if (u-connections) -pa_idxset_free(u-connections, connection_free_cb, NULL); +while ((c = pa_idxset_steal_first(u-connections, NULL))) +connection_free(c); + +pa_idxset_free(u-connections, NULL, NULL); if (u-tcp_server) server_free(u-tcp_server); -- 1.7.4.2 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [PATCH] stream-restore: Enable database dumping if DEBUG_VOLUME is defined.
On Thu, 2011-04-28 at 12:48 +0300, Colin Guthrie wrote: 'Twas brillig, and Tanu Kaskinen at 27/04/11 11:08 did gyre and gimble: From: Tanu Kaskinen ext-tanu.kaski...@nokia.com --- src/modules/module-stream-restore.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c index c1baf8f..56672f7 100644 --- a/src/modules/module-stream-restore.c +++ b/src/modules/module-stream-restore.c @@ -1778,8 +1778,8 @@ static void apply_entry(struct userdata *u, const char *name, struct entry *e) { } } -#if 0 -static void dump_database(struct userdata *u) { +#ifdef DEBUG_VOLUME +PA_GCC_UNUSED static void stream_restore_dump_database(struct userdata *u) { pa_datum key; pa_bool_t done; Forgive my ignorance here but I cannot see where this is called... Is there some magic way to call this function? You can call it in gdb. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH] stream-restore: Enable database dumping if DEBUG_VOLUME is defined.
From: Tanu Kaskinen ext-tanu.kaski...@nokia.com --- src/modules/module-stream-restore.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c index c1baf8f..56672f7 100644 --- a/src/modules/module-stream-restore.c +++ b/src/modules/module-stream-restore.c @@ -1778,8 +1778,8 @@ static void apply_entry(struct userdata *u, const char *name, struct entry *e) { } } -#if 0 -static void dump_database(struct userdata *u) { +#ifdef DEBUG_VOLUME +PA_GCC_UNUSED static void stream_restore_dump_database(struct userdata *u) { pa_datum key; pa_bool_t done; -- 1.7.4.2 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH] module: new null-source module
From: Marc-André Lureau marcandre.lur...@gmail.com --- src/Makefile.am |6 + src/modules/module-null-source.c | 294 ++ 2 files changed, 300 insertions(+), 0 deletions(-) create mode 100644 src/modules/module-null-source.c diff --git a/src/Makefile.am b/src/Makefile.am index fb846cd..275334d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1024,6 +1024,7 @@ modlibexec_LTLIBRARIES += \ module-simple-protocol-tcp.la \ module-null-sink.la \ module-sine-source.la \ + module-null-source.la \ module-detect.la \ module-volume-restore.la \ module-device-manager.la \ @@ -1289,6 +1290,7 @@ SYMDEF_FILES = \ module-tunnel-source-symdef.h \ module-null-sink-symdef.h \ module-sine-source-symdef.h \ + module-null-source-symdef.h \ module-esound-sink-symdef.h \ module-zeroconf-publish-symdef.h \ module-zeroconf-discover-symdef.h \ @@ -1481,6 +1483,10 @@ module_sine_source_la_SOURCES = modules/module-sine-source.c module_sine_source_la_LDFLAGS = $(MODULE_LDFLAGS) module_sine_source_la_LIBADD = $(MODULE_LIBADD) +module_null_source_la_SOURCES = modules/module-null-source.c +module_null_source_la_LDFLAGS = $(MODULE_LDFLAGS) +module_null_source_la_LIBADD = $(MODULE_LIBADD) + # Couplings module_combine_la_SOURCES = modules/module-combine.c diff --git a/src/modules/module-null-source.c b/src/modules/module-null-source.c new file mode 100644 index 000..358ffc6 --- /dev/null +++ b/src/modules/module-null-source.c @@ -0,0 +1,294 @@ +/*** + This file is part of PulseAudio. + + Copyright 2004-2008 Lennart Poettering + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). + + 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 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include config.h +#endif + +#include stdlib.h +#include sys/stat.h +#include stdio.h +#include errno.h +#include string.h +#include fcntl.h +#include unistd.h +#include limits.h + +#include pulse/rtclock.h +#include pulse/timeval.h +#include pulse/xmalloc.h + +#include pulsecore/core-error.h +#include pulsecore/core-rtclock.h +#include pulsecore/core-util.h +#include pulsecore/log.h +#include pulsecore/macro.h +#include pulsecore/modargs.h +#include pulsecore/module.h +#include pulsecore/rtpoll.h +#include pulsecore/source.h +#include pulsecore/thread-mq.h +#include pulsecore/thread.h + +#include module-null-source-symdef.h + +PA_MODULE_AUTHOR(Lennart Poettering Marc-Andre Lureau); +PA_MODULE_DESCRIPTION(Clocked NULL source); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); +PA_MODULE_USAGE( +format=sample format +channels=number of channels +rate=sample rate +source_name=name of source +channel_map=channel map +description=description for the source +latency_time=latency time in ms); + +#define DEFAULT_SOURCE_NAME source.null +#define DEFAULT_LATENCY_TIME 20 +#define MAX_LATENCY_USEC (PA_USEC_PER_SEC * 2) + +struct userdata { +pa_core *core; +pa_module *module; +pa_source *source; + +pa_thread *thread; +pa_thread_mq thread_mq; +pa_rtpoll *rtpoll; + +size_t block_size; + +pa_usec_t block_usec; +pa_usec_t timestamp; +pa_usec_t latency_time; +}; + +static const char* const valid_modargs[] = { +rate, +format, +channels, +source_name, +channel_map, +description, +latency_time, +NULL +}; + +static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { +struct userdata *u = PA_SOURCE(o)-userdata; + +switch (code) { +case PA_SOURCE_MESSAGE_SET_STATE: + +if (PA_PTR_TO_UINT(data) == PA_SOURCE_RUNNING) +u-timestamp = pa_rtclock_now(); + +break; + +case PA_SOURCE_MESSAGE_GET_LATENCY: { +pa_usec_t now; + +now = pa_rtclock_now(); +*((pa_usec_t*) data) = u-timestamp now ? u-timestamp - now : 0; + +return 0; +} +} + +return pa_source_process_msg(o, code, data, offset, chunk); +} + +static void
Re: [pulseaudio-discuss] [PATCH] module: new null-source module
On Wed, 2011-04-27 at 14:50 +0300, Tanu Kaskinen wrote: From: Marc-André Lureau marcandre.lur...@gmail.com --- src/Makefile.am |6 + src/modules/module-null-source.c | 294 ++ 2 files changed, 300 insertions(+), 0 deletions(-) create mode 100644 src/modules/module-null-source.c This module isn't actually used by anyone currently. We (at Nokia) switched to null-sink's monitor a long time ago (for reasons unknown to me), so the code hasn't had much testing lately. Even though there are no users for the module currently, I'm sending the patch anyway, just in case people think that the module might be useful in some situation. I quickly tested that I can record silence with parec from source.null - I can't give any further guarantees that the code is correct. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] how to set buffer attributes in 0.9.15
On Thu, 2011-04-21 at 22:48 -0700, sohail abbasi wrote: hi everyone, I am stuck in the pulseaudio programing, I am adding pulseaudio support in my existing application.Design of the application is synchronous and multithreaded. I need exactly 320 samples (320*4 bytes) for reading and writing. While using pulseaudio 0.9.14 , below parameters works fine but with 0.9.15 readablesize is not as expecting :( . If 0.9.14 worked as you want, the switch to timer-based scheduling probably caused the change in behavior. If this application is used only on systems where you can dictate the pulseaudio daemon settings, then adding tsched=0 to the line in /etc/pulse/default.pa where module-hal-detect is loaded may help. If you can't control the pulseaudio configuration of your users, then I believe you can't get the behavior anymore that you got with 0.9.14. According to the documentation, the fragsize buffer attribute should do what you want for capture streams, but apparently that's not the case in practice (based on what you've told - I haven't done any tests myself). Does anyone know what fragsize actually does? Does it have any meaning anymore? The documentation should be fixed... I'm fairly sure that you are able to fake fixed-size fragments in your pulseaudio support code, though. Just buffer the data locally, and transfer only 320 at a time with the rest of the application. One more thing , are playattributes and record attributes related to each other or have any effect on one another ? No, they don't have any effect on each other. *** PLAYBACK ATTRIBUTES: play_attributes = (pa_buffer_attr*) malloc (sizeof (pa_buffer_attr)); play_attributes-maxlength = pa_usec_to_bytes(21*PA_USEC_PER_MSEC,_sample_spec); This doesn't seem like a good idea. Maxlength doesn't affect the request size. What does 21 ms mean anyway? How many samples is it? play_attributes-tlength = (uint32_t) -1; play_attributes-prebuf = 0; play_attributes-fragsize = pa_usec_to_bytes (20 * PA_USEC_PER_MSEC, _sample_spec); Fragsize is only for capture streams. It doesn't have any meaning for playback streams. See http://0pointer.de/lennart/projects/pulseaudio/doxygen/structpa__buffer__attr.html play_attributes-minreq = (uint32_t) -1; If you set the PA_STREAM_EARLY_REQUESTS, you can use minreq to get requests of some constant size, like you seem to want to do. See the flag description at http://0pointer.de/lennart/projects/pulseaudio/doxygen/def_8h.html#a6966d809483170bc6d2e6c16188850fc RECORD ATTRIBUTES: record_attributes = (pa_buffer_attr*) malloc (sizeof (pa_buffer_attr)); record_attributes-maxlength = pa_usec_to_bytes (21 * PA_USEC_PER_MSEC, _sample_spec); Set maxlength to -1 here too. record_attributes-tlength = (uint32_t) -1; tlength doesn't have any effect on capture streams (-1 is probably a fine initialization value, though). record_attributes-prebuf = (uint32_t) 0; Prebuf doesn't have any effect on capture streams either. record_attributes-fragsize = pa_usec_to_bytes (20 * PA_USEC_PER_MSEC, _sample_spec); Is your samplerate 16 kHz? record_attributes-minreq =pa_usec_to_bytes(1*PA_USEC_PER_SEC,_sample_spec); Minreq doesn't have any effect on capture streams. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH] stream-restore: simple fallback volume table
From: Marc-André Lureau marcandre.lur...@gmail.com Comment from Tanu Kaskinen: I made a few tweaks, so blame me if the patch contains bugs. --- src/modules/module-stream-restore.c | 97 ++- 1 files changed, 95 insertions(+), 2 deletions(-) diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c index 4d1ea04..c1baf8f 100644 --- a/src/modules/module-stream-restore.c +++ b/src/modules/module-stream-restore.c @@ -68,17 +68,24 @@ PA_MODULE_USAGE( restore_volume=Save/restore volumes? restore_muted=Save/restore muted states? on_hotplug=When new device becomes available, recheck streams? -on_rescue=When device becomes unavailable, recheck streams?); +on_rescue=When device becomes unavailable, recheck streams? +fallback_table=filename); #define SAVE_INTERVAL (10 * PA_USEC_PER_SEC) #define IDENTIFICATION_PROPERTY module-stream-restore.id +#define DEFAULT_FALLBACK_FILE PA_DEFAULT_CONFIG_DIR/stream-restore.table +#define DEFAULT_FALLBACK_FILE_USER stream-restore.table + +#define WHITESPACE \n\r \t + static const char* const valid_modargs[] = { restore_device, restore_volume, restore_muted, on_hotplug, on_rescue, +fallback_table, NULL }; @@ -1596,7 +1603,88 @@ static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *sourc return PA_HOOK_OK; } -#define EXT_VERSION 1 +static int fill_db(struct userdata *u, const char *filename) { +FILE *f; +int n = 0; +int ret = -1; +char *fn = NULL; + +pa_assert(u); + +if (filename) +f = fopen(fn = pa_xstrdup(filename), r); +else +f = pa_open_config_file(DEFAULT_FALLBACK_FILE, DEFAULT_FALLBACK_FILE_USER, NULL, fn); + +if (!f) { +if (filename) +pa_log(Failed to open %s: %s, filename, pa_cstrerror(errno)); +else +ret = 0; + +goto finish; +} + +while (!feof(f)) { +char ln[256]; +char *d, *v; +double db; + +if (!fgets(ln, sizeof(ln), f)) +break; + +n++; + +pa_strip_nl(ln); + +if (ln[0] == '#' || !*ln ) +continue; + +d = ln+strcspn(ln, WHITESPACE); +v = d+strspn(d, WHITESPACE); + +if (!*v) { +pa_log([%s:%u] failed to parse line - too few words, fn, n); +goto finish; +} + +*d = 0; +if (pa_atod(v, db) = 0) { +if (db = 0.0) { +pa_datum key, data; +struct entry e; + +pa_zero(e); +e.version = ENTRY_VERSION; +e.volume_valid = TRUE; +pa_cvolume_set(e.volume, 1, pa_sw_volume_from_dB(db)); +pa_channel_map_init_mono(e.channel_map); + +key.data = (void *) ln; +key.size = strlen(ln); + +data.data = (void *) e; +data.size = sizeof(e); + +if (pa_database_set(u-database, key, data, FALSE) == 0) +pa_log_debug(Setting %s to %0.2f dB., ln, db); +} else +pa_log_warn([%s:%u] Positive dB values are not allowed, not setting entry %s., fn, n, ln); +} else +pa_log_warn([%s:%u] Couldn't parse '%s' as a double, not setting entry %s., fn, n, v, ln); +} + +trigger_save(u); +ret = 0; + +finish: +if (f) +fclose(f); + +pa_xfree(fn); + +return ret; +} static void apply_entry(struct userdata *u, const char *name, struct entry *e) { pa_sink_input *si; @@ -1724,6 +1812,8 @@ static void dump_database(struct userdata *u) { } #endif +#define EXT_VERSION 1 + static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connection *c, uint32_t tag, pa_tagstruct *t) { struct userdata *u; uint32_t command; @@ -2063,6 +2153,9 @@ int pa__init(pa_module*m) { pa_log_info(Successfully opened database file '%s'., fname); pa_xfree(fname); +if (fill_db(u, pa_modargs_get_value(ma, fallback_table, NULL)) 0) +goto fail; + #ifdef HAVE_DBUS u-dbus_protocol = pa_dbus_protocol_get(u-core); u-dbus_entries = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); -- 1.7.4.2 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [PATCH] stream-restore: simple fallback volume table
On Thu, 2011-04-21 at 14:31 +0300, Tanu Kaskinen wrote: From: Marc-André Lureau marcandre.lur...@gmail.com Comment from Tanu Kaskinen: I made a few tweaks, so blame me if the patch contains bugs. The commit message is a bit short... The purpose of this patch is to make it possible to configure stream volumes before pulseaudio is run for the first time. This is useful, for example, in embedded products where the default volumes have to be sensible already in the first boot. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [PATCH v2] call-state-tracker: New component.
On Wed, 2011-04-20 at 11:36 +0300, Colin Guthrie wrote: The api object header could be located in src/extra_apis - that would make the api not directly dependent on a particular module. If the API is not dependant on a particular module, what code calls pa_extra_api_register? I'd be happy enough defining this extra API as an IMC (c.f. IPC) system and thus make it very much tied to modules. Hmm... did you get the impression that these apis would not necessarily be tied to any modules at all? That was not the idea - the apis would be implemented always by modules, but not necessarily by any particular module. For example, if there was an api for getting the current call state, it could be implemented by multiple modules, each of which would use different logic for determining whether a call is active or not. The modules would of course conflict with each other, so they could not be loaded at the same time. This would be handled by pa_extra_api_register() - only one module could have the api registered at any given time, the other modules would get an error when they try to call pa_extra_api_register(). I've been using the term extra api here. I don't think it's the greatest name in the world, but that's the best I could think of. I'd like extension more, but that word is already used for other purposes. Yeah extension is already in use for protocol extensions I guess. How about pa_imc_*? (for inter-module comms) or is that perhaps too cryptic? Yeah, it's cryptic, but it's also shorter. And extra api isn't an obvious name either. I'm not sure which I like more. Probably imc. Regarding function names, they will actually have form pa_imc_manager_* or pa_extra_api_manager_* if I get to decide... The functions can be methods of either some manager object or pa_core. If they're implemented directly by pa_core, then the prefix will of course be pa_core_, but I'd prefer having a separate manager object. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH] match: don't double free in case of missing table file
From: Marc-André Lureau marcandre.lur...@gmail.com --- src/modules/module-match.c |1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/src/modules/module-match.c b/src/modules/module-match.c index c8f2706..3eba149 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -95,7 +95,6 @@ static int load_rules(struct userdata *u, const char *filename) { f = pa_open_config_file(DEFAULT_MATCH_TABLE_FILE, DEFAULT_MATCH_TABLE_FILE_USER, NULL, fn); if (!f) { -pa_xfree(fn); pa_log(Failed to open file config file: %s, pa_cstrerror(errno)); goto finish; } -- 1.7.4.2 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH] match: match rule earlier, in SINK_INPUT_NEW
From: Marc-André Lureau marcandre.lur...@gmail.com --- src/modules/module-match.c | 35 +-- 1 files changed, 13 insertions(+), 22 deletions(-) diff --git a/src/modules/module-match.c b/src/modules/module-match.c index 3eba149..b3316d4 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -43,7 +43,6 @@ #include pulsecore/core-util.h #include pulsecore/modargs.h #include pulsecore/log.h -#include pulsecore/core-subscribe.h #include pulsecore/sink-input.h #include pulsecore/core-util.h @@ -77,7 +76,7 @@ struct rule { struct userdata { struct rule *rules; char *property_key; -pa_subscription *subscription; +pa_hook_slot *sink_input_new_hook_slot; }; static int load_rules(struct userdata *u, const char *filename) { @@ -191,23 +190,15 @@ finish: return ret; } -static void callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { -struct userdata *u = userdata; -pa_sink_input *si; +static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_new_data *si, struct userdata *u) { struct rule *r; const char *n; pa_assert(c); pa_assert(u); -if (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW)) -return; - -if (!(si = pa_idxset_get_by_index(c-sink_inputs, idx))) -return; - if (!(n = pa_proplist_gets(si-proplist, u-property_key))) -return; +return PA_HOOK_OK; pa_log_debug(Matching with %s, n); @@ -216,14 +207,17 @@ static void callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, v if (r-proplist) { pa_log_debug(updating proplist of sink input '%s', n); pa_proplist_update(si-proplist, PA_UPDATE_MERGE, r-proplist); -} else { +} else if (si-volume_writable) { pa_cvolume cv; pa_log_debug(changing volume of sink input '%s' to 0x%03x, n, r-volume); pa_cvolume_set(cv, si-sample_spec.channels, r-volume); -pa_sink_input_set_volume(si, cv, TRUE, FALSE); -} +pa_sink_input_new_data_set_volume(si, cv); +} else +pa_log_debug(the volume of sink input '%s' is not writable, can't change it, n); } } + +return PA_HOOK_OK; } int pa__init(pa_module*m) { @@ -239,7 +233,6 @@ int pa__init(pa_module*m) { u = pa_xnew(struct userdata, 1); u-rules = NULL; -u-subscription = NULL; m-userdata = u; u-property_key = pa_xstrdup(pa_modargs_get_value(ma, key, PA_PROP_MEDIA_NAME)); @@ -247,10 +240,8 @@ int pa__init(pa_module*m) { if (load_rules(u, pa_modargs_get_value(ma, table, NULL)) 0) goto fail; -/* FIXME: Doing this asynchronously is just broken. This needs to - * use a hook! */ - -u-subscription = pa_subscription_new(m-core, PA_SUBSCRIPTION_MASK_SINK_INPUT, callback, u); +/* hook EARLY - 1, to match before stream-restore */ +u-sink_input_new_hook_slot = pa_hook_connect(m-core-hooks[PA_CORE_HOOK_SINK_INPUT_NEW], PA_HOOK_EARLY - 1, (pa_hook_cb_t) sink_input_new_hook_callback, u); pa_modargs_free(ma); return 0; @@ -272,8 +263,8 @@ void pa__done(pa_module*m) { if (!(u = m-userdata)) return; -if (u-subscription) -pa_subscription_free(u-subscription); +if (u-sink_input_new_hook_slot) +pa_hook_slot_free(u-sink_input_new_hook_slot); if (u-property_key) pa_xfree(u-property_key); -- 1.7.4.2 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [PATCH v2] call-state-tracker: New component.
On Wed, 2011-04-20 at 15:19 +0300, Colin Guthrie wrote: OK, so the manager object is separate but kept in the core? Seems fine by me to keep things neatly separated. Yep. I thinking of taking a pop at this at some point soon (if you don't beat me to it), so can we decide on the name now? Anyone got any better naming suggestions? pa_imc_manager_* (Pro: short, Con: Inter Module Comms cryptic) pa_extra_api_manager_* (Pro: clear, Con: long, Extension vs. Extra which is which and for what purpose?) pa_xapi_manager_* (Pro: short, Con: might be confused with X11) pa_mxapi_manager_* (Pro: quite short, Con: Module eXtension API but still quite cryptic) I'm not really blown away by any of them :s I'll vote for pa_imc_manager_*. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] RFC: Filter module loader
On Fri, 2011-04-15 at 20:55 +0200, Colin Guthrie wrote: Also, I had to apply this patch to equalizer-sink to prevent it from crashing the server on unload: diff --git a/src/modules/module-equalizer-sink.c b/src/modules/module-equalizer-sink.c index 0bbb23a..611f7dd 100644 --- a/src/modules/module-equalizer-sink.c +++ b/src/modules/module-equalizer-sink.c @@ -1286,7 +1286,7 @@ void pa__done(pa_module*m) { save_state(u); -dbus_done(u); +//dbus_done(u); for(c = 0; c u-channels; ++c) pa_xfree(u-base_profiles[c]); I mentioned this in another thread... hopefully someone more familiar with dbus can take a look at the underlying issue here :) I took a look. The issue was that the dbus protocol used a string from the equalizer module as a key to an internal hashmap, instead a copy of the string. This caused trouble when the equalizer module freed the string. A patch is coming. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH] protocol-dbus: Fix some memory management bugs.
There were several memory leaks. In addition to those, pa_dbus_protocol_add_interface() used a string from the caller as a key to a hashmap, instead of a copy of the string. This caused trouble when the caller freed the string while the key was still in use in the hashmap. --- src/pulsecore/protocol-dbus.c | 12 ++-- 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/pulsecore/protocol-dbus.c b/src/pulsecore/protocol-dbus.c index c329915..8784c34 100644 --- a/src/pulsecore/protocol-dbus.c +++ b/src/pulsecore/protocol-dbus.c @@ -742,7 +742,7 @@ int pa_dbus_protocol_add_interface(pa_dbus_protocol *p, obj_entry-interfaces = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); obj_entry-introspection = NULL; -pa_hashmap_put(p-objects, path, obj_entry); +pa_hashmap_put(p-objects, obj_entry-path, obj_entry); obj_entry_created = TRUE; } @@ -770,11 +770,6 @@ int pa_dbus_protocol_add_interface(pa_dbus_protocol *p, return 0; fail: -if (obj_entry_created) { -pa_hashmap_remove(p-objects, path); -pa_xfree(obj_entry); -} - return -1; } @@ -804,6 +799,7 @@ static void method_handler_free_cb(void *p, void *userdata) { } pa_xfree((pa_dbus_arg_info *) h-arguments); +pa_xfree(h); } static void method_signature_free_cb(void *p, void *userdata) { @@ -945,6 +941,7 @@ static void signal_paths_entry_free(struct signal_paths_entry *e) { while ((path = pa_idxset_steal_first(e-paths, NULL))) pa_xfree(path); +pa_idxset_free(e-paths, NULL, NULL); pa_xfree(e); } @@ -966,9 +963,12 @@ int pa_dbus_protocol_unregister_connection(pa_dbus_protocol *p, DBusConnection * while ((object_path = pa_idxset_steal_first(conn_entry-all_signals_objects, NULL))) pa_xfree(object_path); +pa_idxset_free(conn_entry-all_signals_objects, NULL, NULL); + while ((signal_paths_entry = pa_hashmap_steal_first(conn_entry-listening_signals))) signal_paths_entry_free(signal_paths_entry); +pa_hashmap_free(conn_entry-listening_signals, NULL, NULL); pa_xfree(conn_entry); return 0; -- 1.7.4.4 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] glib functions on PA
On Thu, 2011-04-21 at 10:13 +0530, Arun Raghavan wrote: On Wed, 2011-04-20 at 23:26 -0500, Margarita Olaya wrote: Hi, The initial implementation of jack detection is using threads and simple file operations like open, close and read currently I'm looking into using pa_threads and glib functions. First step It is simple enough e.g change threads by pa_threads and for file operations I have u-fd = g_open(u-device_id, O_RDONLY) ioch = g_io_channel_unix_new(u-fd); then use g_io_channel_read_chars() instead of read. I'm wonder if it is the beast approach or I'm missing any PA function that fits better for this purpose. I'm not aware of any PA code that uses glib for this. module-pipe-sink seems to do most of the things you need so that might serve as a good starting point. Also, the server side code doesn't use glib for anything - the glib dependency has been avoided on purpose. (I don't know or remember the details why Lennart has been avoiding glib - is it only to keep the amount of dependencies low, or are there some other reasons why PA shouldn't use glib.) -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH] tests: improve resampler test
From: Marc-André Lureau marcandre.lur...@gmail.com --- src/tests/resampler-test.c | 207 +-- 1 files changed, 197 insertions(+), 10 deletions(-) diff --git a/src/tests/resampler-test.c b/src/tests/resampler-test.c index 82198b5..69d7ab0 100644 --- a/src/tests/resampler-test.c +++ b/src/tests/resampler-test.c @@ -22,7 +22,13 @@ #endif #include stdio.h +#include getopt.h +#include locale.h +#include pulse/i18n.h +#include pulse/pulseaudio.h + +#include pulse/rtclock.h #include pulse/sample.h #include pulse/volume.h @@ -31,6 +37,8 @@ #include pulsecore/endianmacros.h #include pulsecore/memblock.h #include pulsecore/sample-util.h +#include pulsecore/core-rtclock.h +#include pulsecore/core-util.h static void dump_block(const pa_sample_spec *ss, const pa_memchunk *chunk) { void *d; @@ -241,10 +249,78 @@ static pa_memblock* generate_block(pa_mempool *pool, const pa_sample_spec *ss) { return r; } +static void help(const char *argv0) { +printf(_(%s [options]\n\n + -h, --helpShow this help\n + -v, --verbose Print debug messages\n + --from-rate=SAMPLERATE From sample rate in Hz (defaults to 44100)\n + --from-format=SAMPLEFORMAT From sample type (defaults to s16le)\n + --from-channels=CHANNELSFrom number of channels (defaults to 1)\n + --to-rate=SAMPLERATETo sample rate in Hz (defaults to 44100)\n + --to-format=SAMPLEFORMATTo sample type (defaults to s16le)\n + --to-channels=CHANNELS To number of channels (defaults to 1)\n + --resample-method=METHODResample method (defaults to auto)\n + --seconds=SECONDS From stream duration (defaults to 60)\n + \n + If the formats are not specified, the test performs all formats combinations,\n + back and forth.\n + \n + Sample type must be one of s16le, s16be, u8, float32le, float32be, ulaw, alaw,\n + 32le, s32be (defaults to s16ne)\n + \n + See --dump-resample-methods for possible values of resample methods.\n), + argv0); +} + +enum { +ARG_VERSION = 256, +ARG_FROM_SAMPLERATE, +ARG_FROM_SAMPLEFORMAT, +ARG_FROM_CHANNELS, +ARG_TO_SAMPLERATE, +ARG_TO_SAMPLEFORMAT, +ARG_TO_CHANNELS, +ARG_SECONDS, +ARG_RESAMPLE_METHOD, +ARG_DUMP_RESAMPLE_METHODS +}; + +static void dump_resample_methods(void) { +int i; + +for (i = 0; i PA_RESAMPLER_MAX; i++) +if (pa_resample_method_supported(i)) +printf(%s\n, pa_resample_method_to_string(i)); + +} + int main(int argc, char *argv[]) { -pa_mempool *pool; +pa_mempool *pool = NULL; pa_sample_spec a, b; pa_cvolume v; +int ret = 1, verbose = 0, c; +pa_bool_t all_formats = TRUE; +pa_resample_method_t method; +int seconds; + +static const struct option long_options[] = { +{help, 0, NULL, 'h'}, +{verbose, 0, NULL, 'v'}, +{version, 0, NULL, ARG_VERSION}, +{from-rate, 1, NULL, ARG_FROM_SAMPLERATE}, +{from-format, 1, NULL, ARG_FROM_SAMPLEFORMAT}, +{from-channels, 1, NULL, ARG_FROM_CHANNELS}, +{to-rate, 1, NULL, ARG_TO_SAMPLERATE}, +{to-format, 1, NULL, ARG_TO_SAMPLEFORMAT}, +{to-channels, 1, NULL, ARG_TO_CHANNELS}, +{seconds, 1, NULL, ARG_SECONDS}, +{resample-method, 1, NULL, ARG_RESAMPLE_METHOD}, +{dump-resample-methods, 0, NULL, ARG_DUMP_RESAMPLE_METHODS}, +{NULL,0, NULL, 0} +}; + +setlocale(LC_ALL, ); +bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR); pa_log_set_level(PA_LOG_DEBUG); @@ -252,22 +328,131 @@ int main(int argc, char *argv[]) { a.channels = b.channels = 1; a.rate = b.rate = 44100; - +a.format = b.format = PA_SAMPLE_S16LE; v.channels = a.channels; v.values[0] = pa_sw_volume_from_linear(0.5); +method = PA_RESAMPLER_AUTO; +seconds = 60; + +while ((c = getopt_long(argc, argv, hv, long_options, NULL)) != -1) { + +switch (c) { +case 'h' : +help(argv[0]); +ret = 0; +goto quit; + +case 'v': +pa_log_set_level(PA_LOG_DEBUG); +verbose = 1; +ret = 0; +break; + +case ARG_VERSION: +printf(_(%s %s\n), argv[0], PACKAGE_VERSION); +ret = 0; +goto quit; + +case ARG_DUMP_RESAMPLE_METHODS: +dump_resample_methods(); +ret = 0; +
Re: [pulseaudio-discuss] [PATCH v2] call-state-tracker: New component.
On Mon, 2011-04-18 at 11:35 +0300, Colin Guthrie wrote: I'd be interested in implementing at some point (no promises or timelines) a small framework for making inter-module communication easier, or at least cleaner (this kind of hacks in pulsecore are actually very easy to work with, but clean they are not). The main motivation for this would be ripping out the dbus stuff from module-stream-restore. The dbus API implementation in module-stream-restore.c takes about a half of the whole file, which makes reading the stream-restore code more difficult than it should be. I'd like to keep the dbus interface implementation in module-dbus-protocol only. For this to be possible, there would need to be some way for the modules to talk to each other. It could be solved in a similar way as this call-state-tracker is done, but I'd prefer a generic framework that modules could use to publish extra APIs that other modules can then use. Which probably makes my comments seem a little more sane :D Do you have any specific requirements for this inter-module IPC? Do we just need a hook system with random data pointer + userdata? The random data pointer would be specific to the caller/callee pair and the userdata would be as per usual. Anything more specific than that needed? I'm not sure what you exactly mean. This is what I had in mind for the stuff that needs to be added to the core, I guess it's pretty close to what you described: For publishing APIs: /* Returns a negative error code if the extra api is already registered. */ int pa_extra_api_register(const char *name, void *api); void pa_extra_api_unregister(const_char *name); For consuming APIs: /* Returns the currently registered api object, * or NULL if the api isn't registered right now. */ void *pa_extra_api_get(const char *name); Additionally, there would be a couple of hooks defined for getting notifications about APIs getting registered and unregistered. The api object would be a struct with function pointers. The API provider would create instances of that struct and provide the function implementation. The API consumer would talk to the provider using those function pointers. The api object header could be located in src/extra_apis - that would make the api not directly dependent on a particular module. I don't really have real-world requirements for generic apis that could be provided by multiple modules, but I can't see any costs either for this genericity, other than some minimal added clutter in the src directory. I've been using the term extra api here. I don't think it's the greatest name in the world, but that's the best I could think of. I'd like extension more, but that word is already used for other purposes. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH] sink-input: Check flat volume with pa_sink_flat_volume_enabled().
Checking just the flag doesn't work if the sink uses volume sharing, because such sinks never have PA_SINK_FLAT_VOLUME set. --- src/pulsecore/sink-input.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 46f26f9..1931d99 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -1020,7 +1020,7 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_boo pa_assert(volume-channels == 1 || pa_cvolume_compatible(volume, i-sample_spec)); pa_assert(i-volume_writable); -if ((i-sink-flags PA_SINK_FLAT_VOLUME) !absolute) { +if (!absolute pa_sink_flat_volume_enabled(i-sink)) { v = i-sink-reference_volume; pa_cvolume_remap(v, i-sink-channel_map, i-channel_map); @@ -1043,7 +1043,7 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_boo i-volume = *volume; i-save_volume = save; -if (i-sink-flags PA_SINK_FLAT_VOLUME) { +if (pa_sink_flat_volume_enabled(i-sink)) { /* We are in flat volume mode, so let's update all sink input * volumes and update the flat volume of the sink */ -- 1.7.4.1 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] pulseaudio
On Tue, 2011-04-12 at 12:30 -0400, Sean McNamara wrote: Hi, On Tue, Apr 12, 2011 at 12:15 PM, duportail po...@telenet.be wrote: Try to test the new xubuntu 11.04 with kde on a multi-user system. The first user (for example user1) can log in and gets a default sink from pulse. The second user(for example user2) that will log in gets a auto_null because pulse did not found any sinks. If i log out user1, than user2 can get a default sink by kill and start pulse. Where should be the reason? This is the classic multi-user problem: you're using a soundcard without hardware mixing, so only one ALSA application can take direct control of the hardware device at a time. user1's pulseaudio daemon takes control of it, so obviously user2's PA daemon will just get Device or resource busy when trying to snd_pcm_open() on hw:0 (for example). This problem has existed since ALSA existed. There's no direct fix without scrapping the API and rewriting it. Actually, this situation is supposed to be handled just fine (unless duportail expects both users to be able to use the audio hw simultaneously, which he doesn't mention). If this doesn't work, xubuntu is broken. Some things that can cause this problem: the users are in the audio group, consolekit isn't running or consolekit's udev-acl isn't in use. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [PATCH] sink-input: Don't assert while trying to get non-readable volume
On Sun, 2011-04-10 at 16:52 +0530, Arun Raghavan wrote: Since no clients currently handle non-readable volumes, we handle this condition more gracefully (return PA_VOLUME_NORM). In the future, this could probably changed into an error return instead of an assert so that a non-conformant client doesn't bring the daemon down. When I added the assertion, the idea was that whatever code calls pa_sink_input_get_volume() calls first pa_sink_input_is_volume_readable(). And I at least tried to add those checks everywhere. How are you able to hit the assertion? My current plan for non-readable volume is a slightly different, btw. Instead of having a volume_readable property, I plan to have a volume_enabled property. When volume_enabled is false, within the daemon the volume is still readable and writable (unless volume_writable is false), it just doesn't have any effect. This gets rid of the problem of how to restore the old volume after the volume is re-enabled when switching between passthrough and normal modes. To the clients this is not a very visible change - they still can not read (or they get always PA_VOLUME_NORM as the value) or write the sink volume when it's in the passthrough mode. But this behavior is implemented within protocol-native etc, not enforced by the core. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [PATCH] call-state-tracker: New component.
On Wed, 2011-04-06 at 00:57 +0300, Maarten Bosmans wrote: What are the users of this state tracker? Is it only some out-of-tree Meego modules? Are you planning to submit those too? At least a snippet of how it should be used would be nice. The users are mentioned in call-state-tracker.h. I guess I should have said See call-state-tracker.h for details. in the commit message. (Colin, feel free to add that sentence in the commit message, if you decide to accept this patch.) So yes, only some out-of-tree Meego modules use the call state tracker. About upstreaming those - there are no concrete plans that I'm aware of. I guess the only issue is that we are not confident that the code is clean enough... If I read correctly it is a global boolean state tracker that is a thin wrapper around pa_shared. Is it possible to add the update-hook capability pa_shared and just use that from the modules. It would probably mean a couple of lines more in the modules, but the functionality in pulsecore would be more generic and more widely usable then. Adding an update hook to pa_shared would cover part of this, but it wouldn't take care of the lifecycle management. pa_shared must be empty when the daemon is shut down. The two modules that use the call state tracker can (at least in theory) be loaded completely independently and in any order. How should they take care of removing the item from pa_shared? The most sensible way that I can see is reference counting, and implementing that is easiest to do by having the code in libpulsecore. I'd argue this is not in any significant way different from what is done also by protocol-native.c and protocol-dbus.c etc. Anyway, I do agree that it's not nice to clutter pulsecore with these inter-module libraries. I sent the following message as a reply to the patch yesterday, but from a wrong email address, so it got stuck in the moderation queue: This is sort of ugly - I think pulsecore isn't really the right place for this kind of things. But take it if you don't think it's too ugly. We depend on this patch on Maemo (and Meego too, I believe). I'd be interested in implementing at some point (no promises or timelines) a small framework for making inter-module communication easier, or at least cleaner (this kind of hacks in pulsecore are actually very easy to work with, but clean they are not). The main motivation for this would be ripping out the dbus stuff from module-stream-restore. The dbus API implementation in module-stream-restore.c takes about a half of the whole file, which makes reading the stream-restore code more difficult than it should be. I'd like to keep the dbus interface implementation in module-dbus-protocol only. For this to be possible, there would need to be some way for the modules to talk to each other. It could be solved in a similar way as this call-state-tracker is done, but I'd prefer a generic framework that modules could use to publish extra APIs that other modules can then use. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH v2] call-state-tracker: New component.
From: Tanu Kaskinen ext-tanu.kaski...@nokia.com See call-state-tracker.h for details. Changed in patch v2: Don't take a reference of pa_core. The previous version would have reintroduced the bug that was fixed in 1e381fbf. --- src/Makefile.am|1 + src/pulsecore/call-state-tracker.c | 125 src/pulsecore/call-state-tracker.h | 54 +++ 3 files changed, 180 insertions(+), 0 deletions(-) create mode 100644 src/pulsecore/call-state-tracker.c create mode 100644 src/pulsecore/call-state-tracker.h diff --git a/src/Makefile.am b/src/Makefile.am index bdedded..85c5602 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -835,6 +835,7 @@ libpulsecore_@PA_MAJORMINOR@_la_SOURCES = \ pulsecore/asyncmsgq.c pulsecore/asyncmsgq.h \ pulsecore/asyncq.c pulsecore/asyncq.h \ pulsecore/auth-cookie.c pulsecore/auth-cookie.h \ + pulsecore/call-state-tracker.c pulsecore/call-state-tracker.h \ pulsecore/cli-command.c pulsecore/cli-command.h \ pulsecore/cli-text.c pulsecore/cli-text.h \ pulsecore/client.c pulsecore/client.h \ diff --git a/src/pulsecore/call-state-tracker.c b/src/pulsecore/call-state-tracker.c new file mode 100644 index 000..0ac9be5 --- /dev/null +++ b/src/pulsecore/call-state-tracker.c @@ -0,0 +1,125 @@ +/*** + This file is part of PulseAudio. + + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include config.h +#endif + +#include pulsecore/core.h +#include pulsecore/hook-list.h +#include pulsecore/log.h +#include pulsecore/macro.h +#include pulsecore/refcnt.h +#include pulsecore/shared.h + +#include call-state-tracker.h + +struct pa_call_state_tracker { +PA_REFCNT_DECLARE; + +pa_core *core; +pa_bool_t active; +pa_hook hooks[PA_CALL_STATE_HOOK_MAX]; +}; + +static pa_call_state_tracker* call_state_tracker_new(pa_core *c) { +pa_call_state_tracker *t; +pa_call_state_hook_t h; + +pa_assert(c); + +t = pa_xnew0(pa_call_state_tracker, 1); +PA_REFCNT_INIT(t); +t-core = c; +t-active = FALSE; + +for (h = 0; h PA_CALL_STATE_HOOK_MAX; h++) +pa_hook_init(t-hooks[h], t); + +pa_assert_se(pa_shared_set(c, call-state-tracker, t) = 0); + +return t; +} + +pa_call_state_tracker *pa_call_state_tracker_get(pa_core *core) { +pa_call_state_tracker *t; + +if ((t = pa_shared_get(core, call-state-tracker))) +return pa_call_state_tracker_ref(t); + +return call_state_tracker_new(core); +} + +pa_call_state_tracker *pa_call_state_tracker_ref(pa_call_state_tracker *t) { +pa_assert(t); +pa_assert(PA_REFCNT_VALUE(t) = 1); + +PA_REFCNT_INC(t); + +return t; +} + +void pa_call_state_tracker_unref(pa_call_state_tracker *t) { +pa_call_state_hook_t h; + +pa_assert(t); +pa_assert(PA_REFCNT_VALUE(t) = 1); + +if (PA_REFCNT_DEC(t) 0) +return; + +for (h = 0; h PA_CALL_STATE_HOOK_MAX; h++) +pa_hook_done(t-hooks[h]); + +pa_assert_se(pa_shared_remove(t-core, call-state-tracker) = 0); + +pa_xfree(t); +} + +pa_bool_t pa_call_state_tracker_get_active(pa_call_state_tracker *t) { +pa_assert(t); +pa_assert(PA_REFCNT_VALUE(t) = 1); + +return t-active; +} + +void pa_call_state_tracker_set_active(pa_call_state_tracker *t, pa_bool_t active) { +pa_bool_t changed; + +pa_assert(t); +pa_assert(PA_REFCNT_VALUE(t) = 1); + +changed = active != t-active; + +t-active = active; + +if (changed) +pa_hook_fire(t-hooks[PA_CALL_STATE_HOOK_CHANGED], (void *) active); + +pa_log_debug(Call state set %s (%s), active ? active : inactive, changed ? changed : not changed); +} + +pa_hook *pa_call_state_tracker_hooks(pa_call_state_tracker *t) { +pa_assert(t); +pa_assert(PA_REFCNT_VALUE(t) = 1); + +return t-hooks; +} diff --git a/src/pulsecore/call-state-tracker.h b/src/pulsecore/call-state-tracker.h new file mode 100644 index 000..9a6c60b --- /dev/null +++ b/src/pulsecore/call-state-tracker.h @@ -0,0 +1,54 @@ +#ifndef foocallstatetrackerhfoo +#define foocallstatetrackerhfoo + +/*** + This file is part of PulseAudio. + + Copyright
Re: [pulseaudio-discuss] [PATCH] call-state-tracker: New component.
On Wed, 2011-04-06 at 11:41 +0300, Tanu Kaskinen wrote: On Wed, 2011-04-06 at 00:57 +0300, Maarten Bosmans wrote: What are the users of this state tracker? Is it only some out-of-tree Meego modules? Are you planning to submit those too? At least a snippet of how it should be used would be nice. The users are mentioned in call-state-tracker.h. I guess I should have said See call-state-tracker.h for details. in the commit message. (Colin, feel free to add that sentence in the commit message, if you decide to accept this patch.) So yes, only some out-of-tree Meego modules use the call state tracker. About upstreaming those - there are no concrete plans that I'm aware of. I guess the only issue is that we are not confident that the code is clean enough... I was reminded that we actually already have libmeego-common (a support library for the out-of-tree modules) in the package that provides the meego modules, and this feature would arguably fit better in libmeego-common than libpulsecore. I would still like to see as much stuff in upstream as possible, so I won't recommend that you reject the patch, but it really isn't a big deal if you do. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [PATCH v2] call-state-tracker: New component.
On Wed, 2011-04-06 at 14:23 +0100, Colin Guthrie wrote: 'Twas brillig, and Tanu Kaskinen at 06/04/11 12:33 did gyre and gimble: +/* This is a shared singleton object, currently used by Meego's voice and + * policy enforcement modules. The purpose of the object is just to maintain + * a boolean state of call is active or call is not active, and to provide + * notification hooks for tracking state changes. So one module will be setting + * the state (the voice module) and one or more modules will follow the state + * through the hooks (the policy enforcement module). */ Could I use this approach to, for example, extend module-stream-restore and module-device-restore, to save particular keys in a stream, or device proplist? snip I don't see any reason why you couldn't. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH] stream-restore: add version to new entry.
From: Harri Mähönen ext-harri.maho...@nokia.com --- src/modules/module-stream-restore.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c index 8edfee0..d27982b 100644 --- a/src/modules/module-stream-restore.c +++ b/src/modules/module-stream-restore.c @@ -650,6 +650,7 @@ static void handle_add_entry(DBusConnection *conn, DBusMessage *msg, void *userd pa_assert_se(pa_hashmap_put(u-dbus_entries, dbus_entry-entry_name, dbus_entry) == 0); e = pa_xnew0(struct entry, 1); +e-version = ENTRY_VERSION; e-muted_valid = TRUE; e-volume_valid = !!map.channels; e-device_valid = !!device[0]; -- 1.7.4.2 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH] call-state-tracker: New component.
From: Tanu Kaskinen ext-tanu.kaski...@nokia.com --- src/Makefile.am|1 + src/pulsecore/call-state-tracker.c | 127 src/pulsecore/call-state-tracker.h | 54 +++ 3 files changed, 182 insertions(+), 0 deletions(-) create mode 100644 src/pulsecore/call-state-tracker.c create mode 100644 src/pulsecore/call-state-tracker.h diff --git a/src/Makefile.am b/src/Makefile.am index bdedded..85c5602 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -835,6 +835,7 @@ libpulsecore_@PA_MAJORMINOR@_la_SOURCES = \ pulsecore/asyncmsgq.c pulsecore/asyncmsgq.h \ pulsecore/asyncq.c pulsecore/asyncq.h \ pulsecore/auth-cookie.c pulsecore/auth-cookie.h \ + pulsecore/call-state-tracker.c pulsecore/call-state-tracker.h \ pulsecore/cli-command.c pulsecore/cli-command.h \ pulsecore/cli-text.c pulsecore/cli-text.h \ pulsecore/client.c pulsecore/client.h \ diff --git a/src/pulsecore/call-state-tracker.c b/src/pulsecore/call-state-tracker.c new file mode 100644 index 000..a605685 --- /dev/null +++ b/src/pulsecore/call-state-tracker.c @@ -0,0 +1,127 @@ +/*** + This file is part of PulseAudio. + + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include config.h +#endif + +#include pulsecore/core.h +#include pulsecore/hook-list.h +#include pulsecore/log.h +#include pulsecore/macro.h +#include pulsecore/refcnt.h +#include pulsecore/shared.h + +#include call-state-tracker.h + +struct pa_call_state_tracker { +PA_REFCNT_DECLARE; + +pa_core *core; +pa_bool_t active; +pa_hook hooks[PA_CALL_STATE_HOOK_MAX]; +}; + +static pa_call_state_tracker* call_state_tracker_new(pa_core *c) { +pa_call_state_tracker *t; +pa_call_state_hook_t h; + +pa_assert(c); + +t = pa_xnew0(pa_call_state_tracker, 1); +PA_REFCNT_INIT(t); +t-core = pa_core_ref(c); +t-active = FALSE; + +for (h = 0; h PA_CALL_STATE_HOOK_MAX; h++) +pa_hook_init(t-hooks[h], t); + +pa_assert_se(pa_shared_set(c, call-state-tracker, t) = 0); + +return t; +} + +pa_call_state_tracker *pa_call_state_tracker_get(pa_core *core) { +pa_call_state_tracker *t; + +if ((t = pa_shared_get(core, call-state-tracker))) +return pa_call_state_tracker_ref(t); + +return call_state_tracker_new(core); +} + +pa_call_state_tracker *pa_call_state_tracker_ref(pa_call_state_tracker *t) { +pa_assert(t); +pa_assert(PA_REFCNT_VALUE(t) = 1); + +PA_REFCNT_INC(t); + +return t; +} + +void pa_call_state_tracker_unref(pa_call_state_tracker *t) { +pa_call_state_hook_t h; + +pa_assert(t); +pa_assert(PA_REFCNT_VALUE(t) = 1); + +if (PA_REFCNT_DEC(t) 0) +return; + +for (h = 0; h PA_CALL_STATE_HOOK_MAX; h++) +pa_hook_done(t-hooks[h]); + +pa_assert_se(pa_shared_remove(t-core, call-state-tracker) = 0); + +pa_core_unref(t-core); + +pa_xfree(t); +} + +pa_bool_t pa_call_state_tracker_get_active(pa_call_state_tracker *t) { +pa_assert(t); +pa_assert(PA_REFCNT_VALUE(t) = 1); + +return t-active; +} + +void pa_call_state_tracker_set_active(pa_call_state_tracker *t, pa_bool_t active) { +pa_bool_t changed; + +pa_assert(t); +pa_assert(PA_REFCNT_VALUE(t) = 1); + +changed = active != t-active; + +t-active = active; + +if (changed) +pa_hook_fire(t-hooks[PA_CALL_STATE_HOOK_CHANGED], (void *) active); + +pa_log_debug(Call state set %s (%s), active ? active : inactive, changed ? changed : not changed); +} + +pa_hook *pa_call_state_tracker_hooks(pa_call_state_tracker *t) { +pa_assert(t); +pa_assert(PA_REFCNT_VALUE(t) = 1); + +return t-hooks; +} diff --git a/src/pulsecore/call-state-tracker.h b/src/pulsecore/call-state-tracker.h new file mode 100644 index 000..9a6c60b --- /dev/null +++ b/src/pulsecore/call-state-tracker.h @@ -0,0 +1,54 @@ +#ifndef foocallstatetrackerhfoo +#define foocallstatetrackerhfoo + +/*** + This file is part of PulseAudio. + + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + + PulseAudio is free software; you can redistribute it and/or modify
[pulseaudio-discuss] [PATCH] bluetooth: drop data every 500ms on oor condition
From: Marc-André Lureau marc-andre.lur...@nokia.com --- src/modules/bluetooth/module-bluetooth-device.c | 25 -- 1 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c index e4a2cef..bd1511b 100644 --- a/src/modules/bluetooth/module-bluetooth-device.c +++ b/src/modules/bluetooth/module-bluetooth-device.c @@ -1671,17 +1671,20 @@ static void thread_func(void *userdata) { writable = FALSE; } -if ((!u-source || !PA_SOURCE_IS_LINKED(u-source-thread_info.state)) do_write = 0 writable) { -pa_usec_t time_passed, next_write_at, sleep_for; - -/* Hmm, there is no input stream we could synchronize - * to. So let's estimate when we need to wake up the latest */ - -time_passed = pa_rtclock_now() - u-started_at; -next_write_at = pa_bytes_to_usec(u-write_index, u-sample_spec); -sleep_for = time_passed next_write_at ? next_write_at - time_passed : 0; - -/* pa_log(Sleeping for %lu; time passed %lu, next write at %lu, (unsigned long) sleep_for, (unsigned long) time_passed, (unsigned long)next_write_at); */ +if ((!u-source || !PA_SOURCE_IS_LINKED(u-source-thread_info.state)) do_write = 0) { +pa_usec_t sleep_for; +pa_usec_t time_passed, next_write_at; + +if (writable) { +/* Hmm, there is no input stream we could synchronize + * to. So let's estimate when we need to wake up the latest */ +time_passed = pa_rtclock_now() - u-started_at; +next_write_at = pa_bytes_to_usec(u-write_index, u-sample_spec); +sleep_for = time_passed next_write_at ? next_write_at - time_passed : 0; +/* pa_log(Sleeping for %lu; time passed %lu, next write at %lu, (unsigned long) sleep_for, (unsigned long) time_passed, (unsigned long)next_write_at); */ +} else +/* drop stream every 500 ms */ +sleep_for = PA_USEC_PER_MSEC * 500; pa_rtpoll_set_timer_relative(u-rtpoll, sleep_for); disable_timer = FALSE; -- 1.7.4.2 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH] alsa: Fix log output to inform about positive base volumes correctly.
This fix was done for _set_port_cb() already, but the first fix didn't fix setup_mixer(). Now that's done too. --- src/modules/alsa/alsa-sink.c |5 + src/modules/alsa/alsa-source.c |5 + 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c index 9ed4d4d..ccbc062 100644 --- a/src/modules/alsa/alsa-sink.c +++ b/src/modules/alsa/alsa-sink.c @@ -1724,10 +1724,7 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB, pa_bool_t sync_v u-sink-base_volume = pa_sw_volume_from_dB(-u-mixer_path-max_dB); u-sink-n_volume_steps = PA_VOLUME_NORM+1; -if (u-mixer_path-max_dB 0.0) -pa_log_info(Fixing base volume to %0.2f dB, pa_sw_volume_to_dB(u-sink-base_volume)); -else -pa_log_info(No particular base volume set, fixing to 0 dB); +pa_log_info(Fixing base volume to %0.2f dB, pa_sw_volume_to_dB(u-sink-base_volume)); } else { pa_log_info(Hardware volume ranges from %li to %li., u-mixer_path-min_volume, u-mixer_path-max_volume); diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c index 6d18e60..3355fbd 100644 --- a/src/modules/alsa/alsa-source.c +++ b/src/modules/alsa/alsa-source.c @@ -1465,10 +1465,7 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) { u-source-base_volume = pa_sw_volume_from_dB(-u-mixer_path-max_dB); u-source-n_volume_steps = PA_VOLUME_NORM+1; -if (u-mixer_path-max_dB 0.0) -pa_log_info(Fixing base volume to %0.2f dB, pa_sw_volume_to_dB(u-source-base_volume)); -else -pa_log_info(No particular base volume set, fixing to 0 dB); +pa_log_info(Fixing base volume to %0.2f dB, pa_sw_volume_to_dB(u-source-base_volume)); } else { pa_log_info(Hardware volume ranges from %li to %li., u-mixer_path-min_volume, u-mixer_path-max_volume); -- 1.7.4.2 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] how to read exactly 320 samples
On Mon, 2011-04-04 at 00:27 -0700, sohail abbasi wrote: Hi , everyone I am new to audio programing(as well pulseaudio). I have to add pulseaudio support in an application already working with ALSA and OSS. the designe of my application is such that I have to read 320 samples in read function each time. stream attributes are 16bit , 16khz , and 2 channels. So I need to read 1280 bytes in pa_stream_peek. But I am unable to read 320 samples each time. some time more , some time less ,and some time 0. How can I set buffer attributes to force pa_stream_read to read 320 samples each time. Hmm... The documentation for the fragsize field of pa_buffer_attr seems to imply that the fragment size is always a constant, which according to your experience is not true. That's the only parameter for controlling the fragment sizes when recording, so there's probably no way you can make Pulseaudio give you constant size fragments. You probably can and have to do some buffering in the pulseaudio support component for the application you're working on. So when you get a fragment from pulseaudio, you copy the data to an internal buffer and give data to the application only if there's at least 1280 bytes available, and of course exactly 1280 bytes at a time - any leftovers will be saved until the next fragment arrives. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [PATCH 5/5] bluetooth: Refuse to use the HSP profile if there is some other HSP device active.
On Thu, 2011-03-31 at 15:30 +0300, Tanu Kaskinen wrote: On Thu, 2011-03-31 at 15:11 +0300, Tanu Kaskinen wrote: If no volunteers pop up, I guess I'll have to get a bluetooth dongle for my desktop so that I can test this myself. Never mind, I found a dongle already - I'll test it tomorrow. Ok, tests are now done. I couldn't get any audio in the HSP mode (A2DP worked fine). The sink seemed to be running and there were no errors, the problem seemed to be just that the sink was not getting any wakeups from the hardware. Before any BT hardware was connected, module-bluetooth-discover printed some errors at startup, but apart from this no-audio-with-hsp problem the errors didn't seem to cause any trouble. The behavior was identical with the current git master and with my patches applied. Even though I got no audio, looking at pulseaudio logs it seemed like sink_set_volume_cb was working alright, which was the only thing I wanted to test anyway. So, I suggest now that patches 1-4 get merged, along with the bluetooth: Fix HSP volume handling patch. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH] bluetooth: Fix HSP volume handling.
Previously the userdata for the volume callbacks was saved to pa_core.shared only once when loading module-bluetooth-device, and only when the SCO over PCM feature was used. That breaks volume handling in cases where the HSP profile is used without the SCO over PCM setup. Now the userdata is set always when a sink or source is created, and removed when a sink or source is removed. --- src/modules/bluetooth/module-bluetooth-device.c | 101 +++--- 1 files changed, 69 insertions(+), 32 deletions(-) diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c index 540d48c..fd82ece 100644 --- a/src/modules/bluetooth/module-bluetooth-device.c +++ b/src/modules/bluetooth/module-bluetooth-device.c @@ -1961,6 +1961,8 @@ static pa_hook_result_t source_state_changed_cb(pa_core *c, pa_source *s, struct /* Run from main thread */ static int add_sink(struct userdata *u) { +char *k; + if (USE_SCO_OVER_PCM(u)) { pa_proplist *p; @@ -2014,6 +2016,10 @@ static int add_sink(struct userdata *u) { if (u-profile == PROFILE_HSP) { u-sink-set_volume = sink_set_volume_cb; u-sink-n_volume_steps = 16; + +k = pa_sprintf_malloc(bluetooth-device@%p, (void*) u-sink); +pa_shared_set(u-core, k, u); +pa_xfree(k); } return 0; @@ -2021,6 +2027,8 @@ static int add_sink(struct userdata *u) { /* Run from main thread */ static int add_source(struct userdata *u) { +char *k; + if (USE_SCO_OVER_PCM(u)) { u-source = u-hsp.sco_source; pa_proplist_sets(u-source-proplist, bluetooth.protocol, hsp); @@ -2079,6 +2087,10 @@ static int add_source(struct userdata *u) { if (u-profile == PROFILE_HSP) { u-source-set_volume = source_set_volume_cb; u-source-n_volume_steps = 16; + +k = pa_sprintf_malloc(bluetooth-device@%p, (void*) u-source); +pa_shared_set(u-core, k, u); +pa_xfree(k); } return 0; @@ -2325,6 +2337,8 @@ static int init_profile(struct userdata *u) { /* Run from main thread */ static void stop_thread(struct userdata *u) { +char *k; + pa_assert(u); if (u-thread) { @@ -2349,11 +2363,23 @@ static void stop_thread(struct userdata *u) { } if (u-sink) { +if (u-profile == PROFILE_HSP) { +k = pa_sprintf_malloc(bluetooth-device@%p, (void*) u-sink); +pa_shared_remove(u-core, k); +pa_xfree(k); +} + pa_sink_unref(u-sink); u-sink = NULL; } if (u-source) { +if (u-profile == PROFILE_HSP) { +k = pa_sprintf_malloc(bluetooth-device@%p, (void*) u-source); +pa_shared_remove(u-core, k); +pa_xfree(k); +} + pa_source_unref(u-source); u-source = NULL; } @@ -2383,8 +2409,20 @@ static int start_thread(struct userdata *u) { if (USE_SCO_OVER_PCM(u)) { if (sco_over_pcm_state_update(u) 0) { -u-sink = NULL; -u-source = NULL; +char *k; + +if (u-sink) { +k = pa_sprintf_malloc(bluetooth-device@%p, (void*) u-sink); +pa_shared_remove(u-core, k); +pa_xfree(k); +u-sink = NULL; +} +if (u-source) { +k = pa_sprintf_malloc(bluetooth-device@%p, (void*) u-source); +pa_shared_remove(u-core, k); +pa_xfree(k); +u-source = NULL; +} return -1; } @@ -2421,6 +2459,22 @@ static int start_thread(struct userdata *u) { return 0; } +static void save_sco_volume_callbacks(struct userdata *u) { +pa_assert(u); +pa_assert(USE_SCO_OVER_PCM(u)); + +u-hsp.sco_sink_set_volume = u-hsp.sco_sink-set_volume; +u-hsp.sco_source_set_volume = u-hsp.sco_source-set_volume; +} + +static void restore_sco_volume_callbacks(struct userdata *u) { +pa_assert(u); +pa_assert(USE_SCO_OVER_PCM(u)); + +u-hsp.sco_sink-set_volume = u-hsp.sco_sink_set_volume; +u-hsp.sco_source-set_volume = u-hsp.sco_source_set_volume; +} + /* Run from main thread */ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) { struct userdata *u; @@ -2474,9 +2528,15 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) { stop_thread(u); shutdown_bt(u); +if (USE_SCO_OVER_PCM(u)) +restore_sco_volume_callbacks(u); + u-profile = *d; u-sample_spec = u-requested_sample_spec; +if (USE_SCO_OVER_PCM(u)) +save_sco_volume_callbacks(u); + init_bt(u); if (u-profile != PROFILE_OFF) @@ -2641,6 +2701,9 @@ static int add_card(struct userdata *u, const pa_bluetooth_device *device) { d = PA_CARD_PROFILE_DATA(u-card-active_profile); u-profile = *d; +if (USE_SCO_OVER_PCM(u)) +save_sco_volume_callbacks(u); + return 0; } @@ -2704,7
Re: [pulseaudio-discuss] [PATCH 5/5] bluetooth: Refuse to use the HSP profile if there is some other HSP device active.
On Thu, 2011-03-31 at 15:11 +0300, Tanu Kaskinen wrote: If no volunteers pop up, I guess I'll have to get a bluetooth dongle for my desktop so that I can test this myself. Never mind, I found a dongle already - I'll test it tomorrow. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [PATCH 5/5] bluetooth: Refuse to use the HSP profile if there is some other HSP device active.
On Mon, 2011-03-28 at 18:17 +0300, Luiz Augusto von Dentz wrote: There is a similar policy in BlueZ already for this and it is configurable via /etc/bluetooth/audio.conf, so I don't think hardcoding this on PA would do any better. Ah, excellent, I didn't know that. So the HSP profile locking part is unnecessary. It seems that I also put some fixes for the userdata handling of the volume callbacks in the same patch - I'll make a new patch for that part. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [PATCH 5/5] bluetooth: Refuse to use the HSP profile if there is some other HSP device active.
On Tue, 2011-03-29 at 23:16 +0300, Colin Guthrie wrote: 'Twas brillig, and Luiz Augusto von Dentz at 28/03/11 16:17 did gyre and gimble: There is a similar policy in BlueZ already for this and it is configurable via /etc/bluetooth/audio.conf, so I don't think hardcoding this on PA would do any better. Tanu, what's the best route forward? Patches 1-4 still OK/valid or? Yep, they're good (although it seems that the volume callbacks' userdata handling needed some tuning still in the fifth patch, but I propose you take the four patches and I send a new patch that fixes what there is to fix). -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH 0/5] SCO over PCM fixes
Here are some fixes for the bluetooth SCO over PCM functionality. The patches are old (except the one that removes the #ifdefs), so they should be pretty well tested in Maemo. Rebasing on top of new upstream code isn't tested, though, because I don't have a good setup for that. Marc-André Lureau (3): bluetooth: use sco_sink/source to start with right state bluetooth: fix set_volume_cb on sco over pcm bluetooth: restore original sco_{sink,src}-set_volume when unloading Tanu Kaskinen (2): bluetooth: Drop all #ifdef NOKIA directives. bluetooth: Refuse to use the HSP profile if there is some other HSP device active. src/modules/bluetooth/module-bluetooth-device.c | 217 +++ 1 files changed, 145 insertions(+), 72 deletions(-) -- 1.7.4.1 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH 1/5] bluetooth: Drop all #ifdef NOKIA directives.
The #ifdefs only added clutter. I don't see any reason to not compile the SCO over PCM support in all the time. --- src/modules/bluetooth/module-bluetooth-device.c | 57 +++--- 1 files changed, 8 insertions(+), 49 deletions(-) diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c index ac0f16f..af08003 100644 --- a/src/modules/bluetooth/module-bluetooth-device.c +++ b/src/modules/bluetooth/module-bluetooth-device.c @@ -78,14 +78,9 @@ PA_MODULE_USAGE( rate=sample rate channels=number of channels path=device object path -auto_connect=automatically connect?); - -/* -#ifdef NOKIA +auto_connect=automatically connect? sco_sink=SCO over PCM sink name -sco_source=SCO over PCM source name -#endif -*/ +sco_source=SCO over PCM source name); /* TODO: not close fd when entering suspend mode in a2dp */ @@ -103,10 +98,8 @@ static const char* const valid_modargs[] = { channels, path, auto_connect, -#ifdef NOKIA sco_sink, sco_source, -#endif NULL }; @@ -126,10 +119,8 @@ struct a2dp_info { struct hsp_info { pcm_capabilities_t pcm_capabilities; -#ifdef NOKIA pa_sink *sco_sink; pa_source *sco_source; -#endif pa_hook_slot *sink_state_changed_slot; pa_hook_slot *source_state_changed_slot; }; @@ -191,9 +182,7 @@ struct userdata { #define MAX_PLAYBACK_CATCH_UP_USEC (100*PA_USEC_PER_MSEC) -#ifdef NOKIA #define USE_SCO_OVER_PCM(u) (u-profile == PROFILE_HSP (u-hsp.sco_sink u-hsp.sco_source)) -#endif static int init_bt(struct userdata *u); static int init_profile(struct userdata *u); @@ -1884,8 +1873,6 @@ static char *get_name(const char *type, pa_modargs *ma, const char *device_id, p return pa_sprintf_malloc(bluez_%s.%s, type, n); } -#ifdef NOKIA - static void sco_over_pcm_state_update(struct userdata *u) { pa_assert(u); pa_assert(USE_SCO_OVER_PCM(u)); @@ -1948,12 +1935,8 @@ static pa_hook_result_t source_state_changed_cb(pa_core *c, pa_source *s, struct return PA_HOOK_OK; } -#endif - /* Run from main thread */ static int add_sink(struct userdata *u) { - -#ifdef NOKIA if (USE_SCO_OVER_PCM(u)) { pa_proplist *p; @@ -1966,10 +1949,7 @@ static int add_sink(struct userdata *u) { if (!u-hsp.sink_state_changed_slot) u-hsp.sink_state_changed_slot = pa_hook_connect(u-core-hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) sink_state_changed_cb, u); -} else -#endif - -{ +} else { pa_sink_new_data data; pa_bool_t b; @@ -2017,8 +1997,6 @@ static int add_sink(struct userdata *u) { /* Run from main thread */ static int add_source(struct userdata *u) { - -#ifdef NOKIA if (USE_SCO_OVER_PCM(u)) { u-source = u-hsp.sco_source; pa_proplist_sets(u-source-proplist, bluetooth.protocol, hsp); @@ -2026,10 +2004,7 @@ static int add_source(struct userdata *u) { if (!u-hsp.source_state_changed_slot) u-hsp.source_state_changed_slot = pa_hook_connect(u-core-hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) source_state_changed_cb, u); -} else -#endif - -{ +} else { pa_source_new_data data; pa_bool_t b; @@ -2290,12 +2265,10 @@ static int setup_bt(struct userdata *u) { pa_log_debug(Connection to the device configured); -#ifdef NOKIA if (USE_SCO_OVER_PCM(u)) { pa_log_debug(Configured to use SCO over PCM); return 0; } -#endif pa_log_debug(Got the stream socket); @@ -2384,7 +2357,6 @@ static int start_thread(struct userdata *u) { u-rtpoll = pa_rtpoll_new(); pa_thread_mq_init(u-thread_mq, u-core-mainloop, u-rtpoll); -#ifdef NOKIA if (USE_SCO_OVER_PCM(u)) { if (u-transport) { if (bt_transport_acquire(u, TRUE) 0) @@ -2397,7 +2369,6 @@ static int start_thread(struct userdata *u) { /* FIXME: monitor stream_fd error */ return 0; } -#endif if (!(u-thread = pa_thread_new(bluetooth, thread_func, u))) { pa_log_error(Failed to create IO thread); @@ -2464,17 +2435,15 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) { if (u-sink) { inputs = pa_sink_move_all_start(u-sink, NULL); -#ifdef NOKIA + if (!USE_SCO_OVER_PCM(u)) -#endif pa_sink_unlink(u-sink); } if (u-source) { outputs = pa_source_move_all_start(u-source, NULL); -#ifdef NOKIA + if (!USE_SCO_OVER_PCM(u)) -#endif pa_source_unlink(u-source); } @@ -2731,7 +2700,6 @@ int pa__init(pa_module* m) { u-sample_spec = m-core-default_sample_spec; u-modargs = ma; -#ifdef NOKIA if (pa_modargs_get_value(ma, sco_sink, NULL) !(u-hsp.sco_sink = pa_namereg_get(m-core, pa_modargs_get_value(ma, sco_sink, NULL),
[pulseaudio-discuss] [PATCH 2/5] bluetooth: use sco_sink/source to start with right state
From: Marc-André Lureau marc-andre.lur...@nokia.com Note from Tanu Kaskinen: I resolved some conflicts with newer upstream code, so if this patch is broken, blame me.. --- src/modules/bluetooth/module-bluetooth-device.c | 39 +- 1 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c index af08003..10fb5ed 100644 --- a/src/modules/bluetooth/module-bluetooth-device.c +++ b/src/modules/bluetooth/module-bluetooth-device.c @@ -1873,39 +1873,46 @@ static char *get_name(const char *type, pa_modargs *ma, const char *device_id, p return pa_sprintf_malloc(bluez_%s.%s, type, n); } -static void sco_over_pcm_state_update(struct userdata *u) { +static int sco_over_pcm_state_update(struct userdata *u) { pa_assert(u); pa_assert(USE_SCO_OVER_PCM(u)); if (PA_SINK_IS_OPENED(pa_sink_get_state(u-hsp.sco_sink)) || PA_SOURCE_IS_OPENED(pa_source_get_state(u-hsp.sco_source))) { -if (u-service_fd = 0) -return; +if (u-service_fd = 0 u-stream_fd = 0) +return 0; init_bt(u); pa_log_debug(Resuming SCO over PCM); -if (init_profile(u) 0) +if (init_profile(u) 0) { pa_log(Can't resume SCO over PCM); +return -1; +} if (u-transport) -bt_transport_acquire(u, TRUE); +return bt_transport_acquire(u, TRUE); else -start_stream_fd(u); +return start_stream_fd(u); + } else { +if (u-service_fd 0 u-stream_fd 0) +return 0; -if (u-service_fd 0) -return; +pa_log_debug(Closing SCO over PCM); if (u-transport) bt_transport_release(u); -else +else if (u-stream_fd = 0) stop_stream_fd(u); -pa_log_debug(Closing SCO over PCM); -pa_close(u-service_fd); -u-service_fd = -1; +if (u-service_fd = 0) { +pa_close(u-service_fd); +u-service_fd = -1; +} + +return 0; } } @@ -2358,11 +2365,11 @@ static int start_thread(struct userdata *u) { pa_thread_mq_init(u-thread_mq, u-core-mainloop, u-rtpoll); if (USE_SCO_OVER_PCM(u)) { -if (u-transport) { -if (bt_transport_acquire(u, TRUE) 0) -return -1; -} else if (start_stream_fd(u) 0) +if (sco_over_pcm_state_update(u) 0) { +u-sink = NULL; +u-source = NULL; return -1; +} pa_sink_ref(u-sink); pa_source_ref(u-source); -- 1.7.4.1 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH 4/5] bluetooth: restore original sco_{sink, src}-set_volume when unloading
From: Marc-André Lureau marc-andre.lur...@nokia.com --- src/modules/bluetooth/module-bluetooth-device.c |6 ++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c index 455a53a..540d48c 100644 --- a/src/modules/bluetooth/module-bluetooth-device.c +++ b/src/modules/bluetooth/module-bluetooth-device.c @@ -121,7 +121,9 @@ struct a2dp_info { struct hsp_info { pcm_capabilities_t pcm_capabilities; pa_sink *sco_sink; +void (*sco_sink_set_volume)(pa_sink *s); pa_source *sco_source; +void (*sco_source_set_volume)(pa_source *s); pa_hook_slot *sink_state_changed_slot; pa_hook_slot *source_state_changed_slot; }; @@ -2804,12 +2806,14 @@ int pa__init(pa_module* m) { init_bt(u); if (u-hsp.sco_sink) { +u-hsp.sco_sink_set_volume = u-hsp.sco_sink-set_volume; k = pa_sprintf_malloc(bluetooth-device@%p, (void*) u-hsp.sco_sink); pa_shared_set(u-core, k, u); pa_xfree(k); } if (u-hsp.sco_source) { +u-hsp.sco_source_set_volume = u-hsp.sco_source-set_volume; k = pa_sprintf_malloc(bluetooth-device@%p, (void*) u-hsp.sco_source); pa_shared_set(u-core, k, u); pa_xfree(k); @@ -2890,12 +2894,14 @@ void pa__done(pa_module *m) { shutdown_bt(u); if (u-hsp.sco_sink) { +u-hsp.sco_sink-set_volume = u-hsp.sco_sink_set_volume; k = pa_sprintf_malloc(bluetooth-device@%p, (void*) u-hsp.sco_sink); pa_shared_remove(u-core, k); pa_xfree(k); } if (u-hsp.sco_source) { +u-hsp.sco_source-set_volume = u-hsp.sco_source_set_volume; k = pa_sprintf_malloc(bluetooth-device@%p, (void*) u-hsp.sco_source); pa_shared_remove(u-core, k); pa_xfree(k); -- 1.7.4.1 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH 3/5] bluetooth: fix set_volume_cb on sco over pcm
From: Marc-André Lureau marc-andre.lur...@nokia.com The current implementation is totally bogus, it cast the over_sink userdata to the bluetooth-device userdata... It was failing nicely because the previous code had a gentle safe-guard in u-profile == PROFILE_HSP, and u-profile was just random. There is no easy way to associate additional data to a sink or source. Two solutions seems possible: looking up loaded modules and check which one was handling the sink/source, or using pa_shared. I went for the second solution. --- src/modules/bluetooth/module-bluetooth-device.c | 59 +++ 1 files changed, 50 insertions(+), 9 deletions(-) diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c index 10fb5ed..455a53a 100644 --- a/src/modules/bluetooth/module-bluetooth-device.c +++ b/src/modules/bluetooth/module-bluetooth-device.c @@ -39,6 +39,7 @@ #include pulsecore/core-rtclock.h #include pulsecore/core-util.h #include pulsecore/core-error.h +#include pulsecore/shared.h #include pulsecore/socket-util.h #include pulsecore/thread.h #include pulsecore/thread-mq.h @@ -1798,14 +1799,21 @@ fail: /* Run from main thread */ static void sink_set_volume_cb(pa_sink *s) { -struct userdata *u = s-userdata; DBusMessage *m; dbus_uint16_t gain; +struct userdata *u; +char *k; -pa_assert(u); +pa_assert(s); +pa_assert(s-core); -if (u-profile != PROFILE_HSP) -return; +k = pa_sprintf_malloc(bluetooth-device@%p, (void*) s); +u = pa_shared_get(s-core, k); +pa_xfree(k); + +pa_assert(u); +pa_assert(u-sink == s); +pa_assert(u-profile == PROFILE_HSP); gain = (pa_cvolume_max(s-real_volume) * 15) / PA_VOLUME_NORM; @@ -1822,14 +1830,21 @@ static void sink_set_volume_cb(pa_sink *s) { /* Run from main thread */ static void source_set_volume_cb(pa_source *s) { -struct userdata *u = s-userdata; DBusMessage *m; dbus_uint16_t gain; +struct userdata *u; +char *k; -pa_assert(u); +pa_assert(s); +pa_assert(s-core); -if (u-profile != PROFILE_HSP) -return; +k = pa_sprintf_malloc(bluetooth-device@%p, (void*) s); +u = pa_shared_get(s-core, k); +pa_xfree(k); + +pa_assert(u); +pa_assert(u-source == s); +pa_assert(u-profile == PROFILE_HSP); gain = (pa_cvolume_max(s-volume) * 15) / PA_VOLUME_NORM; @@ -2687,7 +2702,7 @@ int pa__init(pa_module* m) { struct userdata *u; const char *address, *path; DBusError err; -char *mike, *speaker, *transport; +char *mike, *speaker, *transport, *k; const pa_bluetooth_device *device; pa_assert(m); @@ -2788,6 +2803,18 @@ int pa__init(pa_module* m) { /* Connect to the BT service */ init_bt(u); +if (u-hsp.sco_sink) { +k = pa_sprintf_malloc(bluetooth-device@%p, (void*) u-hsp.sco_sink); +pa_shared_set(u-core, k, u); +pa_xfree(k); +} + +if (u-hsp.sco_source) { +k = pa_sprintf_malloc(bluetooth-device@%p, (void*) u-hsp.sco_source); +pa_shared_set(u-core, k, u); +pa_xfree(k); +} + if (u-profile != PROFILE_OFF) if (init_profile(u) 0) goto fail; @@ -2820,6 +2847,8 @@ int pa__get_n_used(pa_module *m) { void pa__done(pa_module *m) { struct userdata *u; +char *k; + pa_assert(m); if (!(u = m-userdata)) @@ -2860,6 +2889,18 @@ void pa__done(pa_module *m) { shutdown_bt(u); +if (u-hsp.sco_sink) { +k = pa_sprintf_malloc(bluetooth-device@%p, (void*) u-hsp.sco_sink); +pa_shared_remove(u-core, k); +pa_xfree(k); +} + +if (u-hsp.sco_source) { +k = pa_sprintf_malloc(bluetooth-device@%p, (void*) u-hsp.sco_source); +pa_shared_remove(u-core, k); +pa_xfree(k); +} + if (u-a2dp.buffer) pa_xfree(u-a2dp.buffer); -- 1.7.4.1 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH 5/5] bluetooth: Refuse to use the HSP profile if there is some other HSP device active.
From: Tanu Kaskinen ext-tanu.kaski...@nokia.com --- src/modules/bluetooth/module-bluetooth-device.c | 126 +-- 1 files changed, 93 insertions(+), 33 deletions(-) diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c index 540d48c..1154651 100644 --- a/src/modules/bluetooth/module-bluetooth-device.c +++ b/src/modules/bluetooth/module-bluetooth-device.c @@ -185,6 +185,8 @@ struct userdata { #define MAX_PLAYBACK_CATCH_UP_USEC (100*PA_USEC_PER_MSEC) +#define CURRENT_HSP_DEVICE_KEY current-hsp-device /* Key to core-shared. */ + #define USE_SCO_OVER_PCM(u) (u-profile == PROFILE_HSP (u-hsp.sco_sink u-hsp.sco_source)) static int init_bt(struct userdata *u); @@ -1961,6 +1963,8 @@ static pa_hook_result_t source_state_changed_cb(pa_core *c, pa_source *s, struct /* Run from main thread */ static int add_sink(struct userdata *u) { +char *k; + if (USE_SCO_OVER_PCM(u)) { pa_proplist *p; @@ -2014,6 +2018,10 @@ static int add_sink(struct userdata *u) { if (u-profile == PROFILE_HSP) { u-sink-set_volume = sink_set_volume_cb; u-sink-n_volume_steps = 16; + +k = pa_sprintf_malloc(bluetooth-device@%p, (void*) u-sink); +pa_shared_set(u-core, k, u); +pa_xfree(k); } return 0; @@ -2021,6 +2029,8 @@ static int add_sink(struct userdata *u) { /* Run from main thread */ static int add_source(struct userdata *u) { +char *k; + if (USE_SCO_OVER_PCM(u)) { u-source = u-hsp.sco_source; pa_proplist_sets(u-source-proplist, bluetooth.protocol, hsp); @@ -2079,6 +2089,10 @@ static int add_source(struct userdata *u) { if (u-profile == PROFILE_HSP) { u-source-set_volume = source_set_volume_cb; u-source-n_volume_steps = 16; + +k = pa_sprintf_malloc(bluetooth-device@%p, (void*) u-source); +pa_shared_set(u-core, k, u); +pa_xfree(k); } return 0; @@ -2325,6 +2339,8 @@ static int init_profile(struct userdata *u) { /* Run from main thread */ static void stop_thread(struct userdata *u) { +char *k; + pa_assert(u); if (u-thread) { @@ -2349,11 +2365,23 @@ static void stop_thread(struct userdata *u) { } if (u-sink) { +if (u-profile == PROFILE_HSP) { +k = pa_sprintf_malloc(bluetooth-device@%p, (void*) u-sink); +pa_shared_remove(u-core, k); +pa_xfree(k); +} + pa_sink_unref(u-sink); u-sink = NULL; } if (u-source) { +if (u-profile == PROFILE_HSP) { +k = pa_sprintf_malloc(bluetooth-device@%p, (void*) u-source); +pa_shared_remove(u-core, k); +pa_xfree(k); +} + pa_source_unref(u-source); u-source = NULL; } @@ -2383,8 +2411,20 @@ static int start_thread(struct userdata *u) { if (USE_SCO_OVER_PCM(u)) { if (sco_over_pcm_state_update(u) 0) { -u-sink = NULL; -u-source = NULL; +char *k; + +if (u-sink) { +k = pa_sprintf_malloc(bluetooth-device@%p, (void*) u-sink); +pa_shared_remove(u-core, k); +pa_xfree(k); +u-sink = NULL; +} +if (u-source) { +k = pa_sprintf_malloc(bluetooth-device@%p, (void*) u-source); +pa_shared_remove(u-core, k); +pa_xfree(k); +u-source = NULL; +} return -1; } @@ -2421,9 +2461,25 @@ static int start_thread(struct userdata *u) { return 0; } +static void save_sco_volume_callbacks(struct userdata *u) { +pa_assert(u); +pa_assert(USE_SCO_OVER_PCM(u)); + +u-hsp.sco_sink_set_volume = u-hsp.sco_sink-set_volume; +u-hsp.sco_source_set_volume = u-hsp.sco_source-set_volume; +} + +static void restore_sco_volume_callbacks(struct userdata *u) { +pa_assert(u); +pa_assert(USE_SCO_OVER_PCM(u)); + +u-hsp.sco_sink-set_volume = u-hsp.sco_sink_set_volume; +u-hsp.sco_source-set_volume = u-hsp.sco_source_set_volume; +} + /* Run from main thread */ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) { -struct userdata *u; +struct userdata *u, *other_hsp_device; enum profile *d; pa_queue *inputs = NULL, *outputs = NULL; const pa_bluetooth_device *device; @@ -2439,6 +2495,9 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) { return -PA_ERR_IO; } +if (u-profile == PROFILE_HSP) +pa_shared_remove(u-core, CURRENT_HSP_DEVICE_KEY); + /* The state signal is sent by bluez, so it is racy to check strictly for CONNECTED, we should also accept STREAMING state as being good enough. However, if the profile is used @@ -2448,6 +2507,10 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) { pa_log_warn(HSP
[pulseaudio-discuss] [PATCH] .gitignore: Add ChangeLog and src/envelope-test to the ignore list
--- .gitignore |1 + src/.gitignore |1 + 2 files changed, 2 insertions(+), 0 deletions(-) diff --git a/.gitignore b/.gitignore index 85c0fe5..3a840d9 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ libtool ltmain.sh missing stamp-* +ChangeLog diff --git a/src/.gitignore b/src/.gitignore index e56c225..1f959ec 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -66,3 +66,4 @@ start-pulseaudio-x11 start-pulseaudio-kde vector-test *-symdef.h +envelope-test -- 1.7.4.1 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [PATCH] .gitignore: Add ChangeLog and src/envelope-test to the ignore list
On Sun, 2011-03-27 at 20:19 +0530, Arun Raghavan wrote: On Sun, 2011-03-27 at 17:39 +0300, Tanu Kaskinen wrote: [...] diff --git a/src/.gitignore b/src/.gitignore index e56c225..1f959ec 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -66,3 +66,4 @@ start-pulseaudio-x11 start-pulseaudio-kde vector-test *-symdef.h +envelope-test This test has been removed. Probably a stale binary in your tree. Oops, you're right. I'll send a fixed patch. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH] .gitignore: Add ChangeLog to the ignore list.
--- .gitignore |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.gitignore b/.gitignore index 85c0fe5..3a840d9 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ libtool ltmain.sh missing stamp-* +ChangeLog -- 1.7.4.1 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH] alsa-mixer: Get rid of a compiler warning.
On 64-bit systems LONG_MAX is greater than the largest possible value of a uint32_t variable, which caused the compiler to warn about a comparison that is always false. On 32-bit systems pa_atou() can return a value that will overflow when assigned to e-volume_limit, which has type long, so the comparison was necessary. This dilemma is resolved by using pa_atol() instead of pa_atou(). --- src/modules/alsa/alsa-mixer.c |4 ++-- src/pulsecore/core-util.c | 30 +++--- src/pulsecore/core-util.h |1 + 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c index 286931f..3b13879 100644 --- a/src/modules/alsa/alsa-mixer.c +++ b/src/modules/alsa/alsa-mixer.c @@ -1920,14 +1920,14 @@ static int element_parse_volume_limit( pa_alsa_path *p = userdata; pa_alsa_element *e; -uint32_t volume_limit; +long volume_limit; if (!(e = element_get(p, section, TRUE))) { pa_log([%s:%u] volume-limit makes no sense in '%s', filename, line, section); return -1; } -if (pa_atou(rvalue, volume_limit) 0 || volume_limit LONG_MAX) { +if (pa_atol(rvalue, volume_limit) 0 || volume_limit 0) { pa_log([%s:%u] Invalid value for volume-limit, filename, line); return -1; } diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 4823198..890efde 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -2018,14 +2018,8 @@ int pa_atoi(const char *s, int32_t *ret_i) { pa_assert(s); pa_assert(ret_i); -errno = 0; -l = strtol(s, x, 0); - -if (!x || *x || errno) { -if (!errno) -errno = EINVAL; +if (pa_atol(s, l) 0) return -1; -} if ((int32_t) l != l) { errno = ERANGE; @@ -2064,6 +2058,28 @@ int pa_atou(const char *s, uint32_t *ret_u) { return 0; } +/* Convert the string s to a signed long integer in *ret_l. */ +int pa_atol(const char *s, long *ret_l) { +char *x = NULL; +long l; + +pa_assert(s); +pa_assert(ret_l); + +errno = 0; +l = strtol(s, x, 0); + +if (!x || *x || errno) { +if (!errno) +errno = EINVAL; +return -1; +} + +*ret_l = l; + +return 0; +} + #ifdef HAVE_STRTOF_L static locale_t c_locale = NULL; diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index 32641a3..0b34a18 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -135,6 +135,7 @@ char *pa_state_path(const char *fn, pa_bool_t prepend_machine_id); int pa_atoi(const char *s, int32_t *ret_i); int pa_atou(const char *s, uint32_t *ret_u); +int pa_atol(const char *s, long *ret_l); int pa_atod(const char *s, double *ret_d); size_t pa_snprintf(char *str, size_t size, const char *format, ...); -- 1.7.4.1 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [PATCH] alsa-mixer: Get rid of a compiler warning.
On Sun, 2011-03-27 at 21:20 +0300, Tanu Kaskinen wrote: @@ -2018,14 +2018,8 @@ int pa_atoi(const char *s, int32_t *ret_i) { pa_assert(s); pa_assert(ret_i); -errno = 0; -l = strtol(s, x, 0); - -if (!x || *x || errno) { -if (!errno) -errno = EINVAL; +if (pa_atol(s, l) 0) return -1; -} if ((int32_t) l != l) { errno = ERANGE; Damn, this causes another warning: x is now an unused variable. Fixup coming... -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH] alsa-mixer: Get rid of a compiler warning.
On 64-bit systems LONG_MAX is greater than the largest possible value of a uint32_t variable, which caused the compiler to warn about a comparison that is always false. On 32-bit systems pa_atou() can return a value that will overflow when assigned to e-volume_limit, which has type long, so the comparison was necessary. This dilemma is resolved by using pa_atol() instead of pa_atou(). --- src/modules/alsa/alsa-mixer.c |4 ++-- src/pulsecore/core-util.c | 31 +++ src/pulsecore/core-util.h |1 + 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c index 286931f..3b13879 100644 --- a/src/modules/alsa/alsa-mixer.c +++ b/src/modules/alsa/alsa-mixer.c @@ -1920,14 +1920,14 @@ static int element_parse_volume_limit( pa_alsa_path *p = userdata; pa_alsa_element *e; -uint32_t volume_limit; +long volume_limit; if (!(e = element_get(p, section, TRUE))) { pa_log([%s:%u] volume-limit makes no sense in '%s', filename, line, section); return -1; } -if (pa_atou(rvalue, volume_limit) 0 || volume_limit LONG_MAX) { +if (pa_atol(rvalue, volume_limit) 0 || volume_limit 0) { pa_log([%s:%u] Invalid value for volume-limit, filename, line); return -1; } diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c index 4823198..f769b32 100644 --- a/src/pulsecore/core-util.c +++ b/src/pulsecore/core-util.c @@ -2012,20 +2012,13 @@ char *pa_state_path(const char *fn, pa_bool_t appendmid) { /* Convert the string s to a signed integer in *ret_i */ int pa_atoi(const char *s, int32_t *ret_i) { -char *x = NULL; long l; pa_assert(s); pa_assert(ret_i); -errno = 0; -l = strtol(s, x, 0); - -if (!x || *x || errno) { -if (!errno) -errno = EINVAL; +if (pa_atol(s, l) 0) return -1; -} if ((int32_t) l != l) { errno = ERANGE; @@ -2064,6 +2057,28 @@ int pa_atou(const char *s, uint32_t *ret_u) { return 0; } +/* Convert the string s to a signed long integer in *ret_l. */ +int pa_atol(const char *s, long *ret_l) { +char *x = NULL; +long l; + +pa_assert(s); +pa_assert(ret_l); + +errno = 0; +l = strtol(s, x, 0); + +if (!x || *x || errno) { +if (!errno) +errno = EINVAL; +return -1; +} + +*ret_l = l; + +return 0; +} + #ifdef HAVE_STRTOF_L static locale_t c_locale = NULL; diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h index 32641a3..0b34a18 100644 --- a/src/pulsecore/core-util.h +++ b/src/pulsecore/core-util.h @@ -135,6 +135,7 @@ char *pa_state_path(const char *fn, pa_bool_t prepend_machine_id); int pa_atoi(const char *s, int32_t *ret_i); int pa_atou(const char *s, uint32_t *ret_u); +int pa_atol(const char *s, long *ret_l); int pa_atod(const char *s, double *ret_d); size_t pa_snprintf(char *str, size_t size, const char *format, ...); -- 1.7.4.1 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH] sink-input: Add volume_writable to pa_sink_input.
This is pretty cosmetic change; there's no actual functionality added. Previously the volume_writable information was available through the pa_sink_input_is_volume_writable() function, but I find it cleaner to have a real variable. The sink input introspection variable name was also changed from read_only_volume to volume_writable for consistency. --- PROTOCOL|2 +- src/modules/dbus/iface-stream.c | 10 src/modules/module-stream-restore.c |6 ++-- src/pulse/introspect.c |6 ++-- src/pulse/introspect.h |2 +- src/pulsecore/cli-command.c |2 +- src/pulsecore/protocol-native.c |4 +- src/pulsecore/sink-input.c | 36 ++ src/pulsecore/sink-input.h |6 +++- 9 files changed, 27 insertions(+), 47 deletions(-) diff --git a/PROTOCOL b/PROTOCOL index c2bb209..a15d116 100644 --- a/PROTOCOL +++ b/PROTOCOL @@ -212,4 +212,4 @@ New flag at the end of sink input and source output introspection data: Two new flags at the end of sink input introspection data: bool has_volume -bool read_only_volume +bool volume_writable diff --git a/src/modules/dbus/iface-stream.c b/src/modules/dbus/iface-stream.c index e3464fd..d9f1237 100644 --- a/src/modules/dbus/iface-stream.c +++ b/src/modules/dbus/iface-stream.c @@ -57,7 +57,6 @@ struct pa_dbusiface_stream { pa_proplist *proplist; pa_bool_t has_volume; -pa_bool_t read_only_volume; pa_dbus_protocol *dbus_protocol; pa_subscription *subscription; @@ -357,6 +356,7 @@ static void handle_get_volume(DBusConnection *conn, DBusMessage *msg, void *user static void handle_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { pa_dbusiface_stream *s = userdata; +pa_bool_t volume_writable = TRUE; DBusMessageIter array_iter; int stream_channels = 0; dbus_uint32_t *volume = NULL; @@ -369,12 +369,14 @@ static void handle_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessag pa_assert(iter); pa_assert(s); -if (!s-has_volume || s-read_only_volume) { +volume_writable = (s-type == STREAM_TYPE_PLAYBACK) ? s-sink_input-volume_writable : FALSE; + +if (!s-has_volume || !volume_writable) { char *str = stream_to_string(s); if (!s-has_volume) pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, %s doesn't have volume., str); -else if (s-read_only_volume) +else if (!volume_writable) pa_dbus_send_error(conn, msg, DBUS_ERROR_ACCESS_DENIED, %s has read-only volume., str); pa_xfree(str); @@ -853,7 +855,6 @@ pa_dbusiface_stream *pa_dbusiface_stream_new_playback(pa_dbusiface_core *core, p s-sink = pa_sink_ref(sink_input-sink); s-sample_rate = sink_input-sample_spec.rate; s-has_volume = pa_sink_input_is_volume_readable(sink_input); -s-read_only_volume = s-has_volume ? !pa_sink_input_is_volume_writable(sink_input) : FALSE; if (s-has_volume) pa_sink_input_get_volume(sink_input, s-volume, TRUE); @@ -891,7 +892,6 @@ pa_dbusiface_stream *pa_dbusiface_stream_new_record(pa_dbusiface_core *core, pa_ s-mute = FALSE; s-proplist = pa_proplist_copy(source_output-proplist); s-has_volume = FALSE; -s-read_only_volume = FALSE; s-dbus_protocol = pa_dbus_protocol_get(source_output-core); s-subscription = pa_subscription_new(source_output-core, PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscription_cb, s); s-send_event_slot = pa_hook_connect(source_output-core-hooks[PA_CORE_HOOK_SOURCE_OUTPUT_SEND_EVENT], diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c index df48dce..8edfee0 100644 --- a/src/modules/module-stream-restore.c +++ b/src/modules/module-stream-restore.c @@ -1168,7 +1168,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 } if (sink_input-save_volume) { -pa_assert(pa_sink_input_is_volume_writable(sink_input)); +pa_assert(sink_input-volume_writable); entry.channel_map = sink_input-channel_map; pa_sink_input_get_volume(sink_input, entry.volume, FALSE); @@ -1329,7 +1329,7 @@ static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_inpu if ((e = read_entry(u, name))) { if (u-restore_volume e-volume_valid) { -if (!pa_sink_input_new_data_is_volume_writable(new_data)) +if (!new_data-volume_writable) pa_log_debug(Not restoring volume for sink input %s, because its volume can't be changed., name); else if (new_data-volume_is_set) pa_log_debug(Not restoring volume for sink input %s, because already set., name); @@ -1619,7 +1619,7 @@ static void apply_entry(struct userdata *u, const char *name, struct entry *e) { }
Re: [pulseaudio-discuss] Current problems with git master
On Fri, 2011-03-25 at 09:11 +, Colin Guthrie wrote: This patch should fix up these issues right? Yep, seems correct to me. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] Current problems with git master
On Fri, 2011-03-25 at 23:09 +, Colin Guthrie wrote: Does this patch look OK to everyone (especially Tanu!) Looks ok to me! Thanks for fixing this. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] Current problems with git master
On Sat, 2011-03-26 at 00:13 +, Colin Guthrie wrote: FWIW, the attached patch seems to work for me... simply not ref'ing the core. If this is OK, then I'll push it. Yep, my bad. I think there's a rule that object A shall not ref object B if B owns A. And here core owns everything, including the dbus objects. Nobody should ref core. It's then a bit strange why the core is refcounted in the first place, but I guess it's because the intention is to make the Pulseaudio core pluggable into other programs, and those other programs may want to have multiple references to the Pulseaudio core object. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH] loopback: Always use the trivial resampler.
Adjusting the sample rate is done in the IO thread, which can cause interruptions in the audio if the adjustment requires heavy computation. The trivial resampler is guaranteed to be light on the cpu. It would be better to adjust the sample rate in some other thread (FWIW, module-combine uses the main thread), but this quick hack fixes the immediate problem of spending too much time in the IO thread. --- src/modules/module-loopback.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c index 9a8640b..3ade248 100644 --- a/src/modules/module-loopback.c +++ b/src/modules/module-loopback.c @@ -714,6 +714,7 @@ int pa__init(pa_module *m) { pa_sink_input_new_data_set_sample_spec(sink_input_data, ss); pa_sink_input_new_data_set_channel_map(sink_input_data, map); sink_input_data.flags = PA_SINK_INPUT_VARIABLE_RATE; +sink_input_data.resample_method = PA_RESAMPLER_TRIVIAL; sink_dont_move = FALSE; if (pa_modargs_get_value_boolean(ma, sink_dont_move, sink_dont_move) 0) { -- 1.7.4.1 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [PATCH] loopback: Always use the trivial resampler.
On Thu, 2011-03-24 at 15:31 +0200, pl bossart wrote: On Thu, Mar 24, 2011 at 8:16 AM, Tanu Kaskinen tanu.kaski...@digia.com wrote: Adjusting the sample rate is done in the IO thread, which can cause interruptions in the audio if the adjustment requires heavy computation. The trivial resampler is guaranteed to be light on the cpu. It would be better to adjust the sample rate in some other thread (FWIW, module-combine uses the main thread), but this quick hack fixes the immediate problem of spending too much time in the IO thread. I don't think it's the right or only way to solve the problem. If you are using the loopback and SRC is required, the assumption is that you don't care too much about latency. If the audio events are spaced enough, there should be plenty of time to run the resampling. we should instead adjust the sink/source latencies to reduce the number of events and not compromize on quality. Aren't you assuming here that the resampling adjustment timeout happens right after the buffers are filled, and never when the buffer is running low and a refill is scheduled right after the adjustment timeout? This trivial resampler should only be used if for some reason you want both real-time behavior and low-latency while using an SRC. I fail to see in what cases you would care? In what practical cases did you encounter underflows? The sink may be running in a low-latency mode even if the loopback stream doesn't have any latency requirements - there may be other streams active at the same time with stricter timing requirements. FWIW, the practical case here was a very simple test of looping null sink's monitor to a hw sink with default settings on Harmattan. It may be that our setup is more suspectible to this kind of problems than normal systems, but I still think that non-realtime-safe stuff should be kept out of the IO threads, regardless of the setup, especially if such stuff can very well be done outside the IO thread. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [PATCH 1/2] pactl: Accept more volume specification formats
On Thu, 2011-03-24 at 22:22 +0530, Arun Raghavan wrote: On Thu, 2011-03-24 at 13:07 +, Colin Guthrie wrote: 'Twas brillig, and Maarten Bosmans at 24/03/11 12:44 did gyre and gimble: 2011/3/24 Maarten Bosmans mkbosm...@gmail.com: With this you can specify the volume with 6554, 10%, 0.001 or -60dB, all resulting in the same volume change. I was also going to add relative volumes, such as +3dB and -5%, by detecting a + or - sign in the volume. But that clashes with the absolute dB scale (insofar a dB can ever be absolute) that can also be negative. Any suggestions for graceful handling of this? How about if the first letter of the volume change is an i or a d then this indicated increment or decrement relative volume? It's not as clean as the +/- labelling sadly but such is life. Alternatively your absolute dB volumes could be specified as 60-dB or 7+dB (where 7dB implies 7+dB)... That way the prefix +/- notation could be used for relative adjustments. The only downside there is that setting absolute dB volumes is more confusing (you'd never need to use anything other than XdB for relative adjustments anyway). Personally I'd go for the later as I think relative adjustments are probably more common, so it's syntax should be neatest, but I could be very wrong :D Or maybe just do this as a separate set-volume-step command (or -increment or something better named)? I agree - I think a separate command is a good idea. For command naming, I suggest increase-sink-volume and decrease-sink-volume. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [PATCH] loopback: Always use the trivial resampler.
On Thu, 2011-03-24 at 09:09 -0500, pl bossart wrote: The sink may be running in a low-latency mode even if the loopback stream doesn't have any latency requirements - there may be other streams active at the same time with stricter timing requirements. FWIW, the practical case here was a very simple test of looping null sink's monitor to a hw sink with default settings on Harmattan. It may be that our setup is more suspectible to this kind of problems than normal systems, but I still think that non-realtime-safe stuff should be kept out of the IO threads, regardless of the setup, especially if such stuff can very well be done outside the IO thread. if you are still using 10ms periods on the hw sinks, then yes it's an artifical use case in a constrained environment that doesn't use timer-based scheduling... I don't disagree that doing SRC in an io thread is not that kosher, but keep in mind that we also do mixing and volume control in the IO thread. There is some amount of DSP in this thread which will impact response time to hw events. It might be that you have misunderstood the reason for the patch. Now that I read the patch description again, it indeed isn't entirely clear: the problem that I'm having is that the periodic (every 10 seconds) reinitialization of the resampler takes too much CPU time. The resampling itself is fine - I don't think it's even possible to move that out of the IO thread, or if it's possible, it probably wouldn't bring any benefits. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] Current problems with git master
On Thu, 2011-03-24 at 21:30 +, Colin Guthrie wrote: If someone could double check, I'd appreciate it (seeing as I'd rather any bugs in my commit last less than a year and a half!!) Problems found: The first process: daemon_pipe is not closed if the first fork() call fails. Even if it doesn't fail, the first process never closes daemon_pipe[0]. The second process: daemon_pipe[1] is not closed if anything fails between the first and the second fork() call. Also, if the second fork fails, then the finish section writes to daemon_pipe2[1], even though only the third process should do that. Also, if anything fails between the first and the second fork, then the second process never writes anything to daemon_pipe[1]. I don't know what happens in the first process in this case - does it get an error or does pa_loop_read() get stuck. The third process: No problems :) -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH 0/2] Rebased bluetooth patches
Colin wrote: Can you rebase these two on git master please? I just merged a whole bunch of changes from BT guys and these both fail now. Sure, refreshed patches coming. Tanu Kaskinen (2): bluetooth: Don't log an error if an endpoint type is disabled. bluetooth: Get rid of warnings about unused stuff when building against a D-Bus version that doesn't have fd-passing support. src/modules/bluetooth/bluetooth-util.c | 43 +++- src/modules/bluetooth/bluetooth-util.h |2 + 2 files changed, 33 insertions(+), 12 deletions(-) -- 1.7.4.1 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH 1/2 rebased] bluetooth: Don't log an error if an endpoint type is disabled.
It's perfectly normal for BlueZ to disable some endpoint types, so printing a log message at error level isn't a good idea. For facilitating an informative message in case some endpoint type is disabled, the send_and_add_to_pending() function interface is also changed to be more generic (the pa_bluetooth_device pointer is replaced with a void pointer). --- src/modules/bluetooth/bluetooth-util.c | 33 --- src/modules/bluetooth/bluetooth-util.h |2 + 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c index 293e024..a79ff91 100644 --- a/src/modules/bluetooth/bluetooth-util.c +++ b/src/modules/bluetooth/bluetooth-util.c @@ -73,7 +73,7 @@ struct pa_bluetooth_discovery { }; static void get_properties_reply(DBusPendingCall *pending, void *userdata); -static pa_dbus_pending* send_and_add_to_pending(pa_bluetooth_discovery *y, pa_bluetooth_device *d, DBusMessage *m, DBusPendingCallNotifyFunction func); +static pa_dbus_pending* send_and_add_to_pending(pa_bluetooth_discovery *y, DBusMessage *m, DBusPendingCallNotifyFunction func, void *call_data); static pa_bt_audio_state_t pa_bt_audio_state_from_string(const char* value) { pa_assert(value); @@ -280,21 +280,21 @@ static int parse_device_property(pa_bluetooth_discovery *y, pa_bluetooth_device /* Vudentz said the interfaces are here when the UUIDs are announced */ if (strcasecmp(HSP_AG_UUID, value) == 0 || strcasecmp(HFP_AG_UUID, value) == 0) { pa_assert_se(m = dbus_message_new_method_call(org.bluez, d-path, org.bluez.HandsfreeGateway, GetProperties)); -send_and_add_to_pending(y, d, m, get_properties_reply); +send_and_add_to_pending(y, m, get_properties_reply, d); } else if (strcasecmp(HSP_HS_UUID, value) == 0 || strcasecmp(HFP_HS_UUID, value) == 0) { pa_assert_se(m = dbus_message_new_method_call(org.bluez, d-path, org.bluez.Headset, GetProperties)); -send_and_add_to_pending(y, d, m, get_properties_reply); +send_and_add_to_pending(y, m, get_properties_reply, d); } else if (strcasecmp(A2DP_SINK_UUID, value) == 0) { pa_assert_se(m = dbus_message_new_method_call(org.bluez, d-path, org.bluez.AudioSink, GetProperties)); -send_and_add_to_pending(y, d, m, get_properties_reply); +send_and_add_to_pending(y, m, get_properties_reply, d); } else if (strcasecmp(A2DP_SOURCE_UUID, value) == 0) { pa_assert_se(m = dbus_message_new_method_call(org.bluez, d-path, org.bluez.AudioSource, GetProperties)); -send_and_add_to_pending(y, d, m, get_properties_reply); +send_and_add_to_pending(y, m, get_properties_reply, d); } /* this might eventually be racy if .Audio is not there yet, but the State change will come anyway later, so this call is for cold-detection mostly */ pa_assert_se(m = dbus_message_new_method_call(org.bluez, d-path, org.bluez.Audio, GetProperties)); -send_and_add_to_pending(y, d, m, get_properties_reply); +send_and_add_to_pending(y, m, get_properties_reply, d); if (!dbus_message_iter_next(ai)) break; @@ -394,7 +394,7 @@ static pa_bluetooth_device *found_device(pa_bluetooth_discovery *y, const char* pa_hashmap_put(y-devices, d-path, d); pa_assert_se(m = dbus_message_new_method_call(org.bluez, path, org.bluez.Device, GetProperties)); -send_and_add_to_pending(y, d, m, get_properties_reply); +send_and_add_to_pending(y, m, get_properties_reply, d); /* Before we read the other properties (Audio, AudioSink, AudioSource, * Headset) we wait that the UUID is read */ @@ -503,7 +503,7 @@ finish2: pa_dbus_pending_free(p); } -static pa_dbus_pending* send_and_add_to_pending(pa_bluetooth_discovery *y, pa_bluetooth_device *d, DBusMessage *m, DBusPendingCallNotifyFunction func) { +static pa_dbus_pending* send_and_add_to_pending(pa_bluetooth_discovery *y, DBusMessage *m, DBusPendingCallNotifyFunction func, void *call_data) { pa_dbus_pending *p; DBusPendingCall *call; @@ -512,7 +512,7 @@ static pa_dbus_pending* send_and_add_to_pending(pa_bluetooth_discovery *y, pa_bl pa_assert_se(dbus_connection_send_with_reply(pa_dbus_connection_get(y-connection), m, call, -1)); -p = pa_dbus_pending_new(pa_dbus_connection_get(y-connection), m, call, y, d); +p = pa_dbus_pending_new(pa_dbus_connection_get(y-connection), m, call, y, call_data); PA_LLIST_PREPEND(pa_dbus_pending, y-pending, p); dbus_pending_call_set_notify(call,
[pulseaudio-discuss] [PATCH 2/2 rebased] bluetooth: Get rid of warnings about unused stuff when building against a D-Bus version that doesn't have fd-passing support.
--- src/modules/bluetooth/bluetooth-util.c | 10 ++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c index a79ff91..f1c7c4c 100644 --- a/src/modules/bluetooth/bluetooth-util.c +++ b/src/modules/bluetooth/bluetooth-util.c @@ -519,6 +519,7 @@ static pa_dbus_pending* send_and_add_to_pending(pa_bluetooth_discovery *y, DBusM return p; } +#ifdef DBUS_TYPE_UNIX_FD static void register_endpoint_reply(DBusPendingCall *pending, void *userdata) { DBusError e; DBusMessage *r; @@ -559,6 +560,7 @@ finish: pa_xfree(endpoint); } +#endif static void list_devices_reply(DBusPendingCall *pending, void *userdata) { DBusError e; @@ -607,6 +609,7 @@ finish: pa_dbus_pending_free(p); } +#ifdef DBUS_TYPE_UNIX_FD static void register_endpoint(pa_bluetooth_discovery *y, const char *path, const char *endpoint, const char *uuid) { DBusMessage *m; DBusMessageIter i, d; @@ -654,6 +657,7 @@ static void register_endpoint(pa_bluetooth_discovery *y, const char *path, const send_and_add_to_pending(y, m, register_endpoint_reply, pa_xstrdup(endpoint)); } +#endif static void found_adapter(pa_bluetooth_discovery *y, const char *path) { DBusMessage *m; @@ -1042,7 +1046,9 @@ int pa_bluetooth_transport_acquire(const pa_bluetooth_transport *t, const char * if (omtu) *omtu = o; +#ifdef DBUS_TYPE_UNIX_FD fail: +#endif dbus_message_unref(r); return ret; } @@ -1083,6 +1089,7 @@ static int setup_dbus(pa_bluetooth_discovery *y) { return 0; } +#ifdef DBUS_TYPE_UNIX_FD static pa_bluetooth_transport *transport_new(pa_bluetooth_discovery *y, const char *path, enum profile p, const uint8_t *config, int size) { pa_bluetooth_transport *t; @@ -1435,13 +1442,16 @@ static DBusHandlerResult endpoint_handler(DBusConnection *c, DBusMessage *m, voi return DBUS_HANDLER_RESULT_HANDLED; } +#endif /* DBUS_TYPE_UNIX_FD */ pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *c) { DBusError err; pa_bluetooth_discovery *y; +#ifdef DBUS_TYPE_UNIX_FD static const DBusObjectPathVTable vtable_endpoint = { .message_function = endpoint_handler, }; +#endif pa_assert(c); -- 1.7.4.1 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH] alsa-mixer: Check that the kernel driver returns consistent limits with both snd_mixer_selem_get_*_dB_range() and _ask_*_vol_dB().
The check is inspired by a driver that returned higher dB limit from snd_mixer_selem_get_playback_dB_range() than what _ask_playback_vol_dB() returned at maximum integer volume. --- src/modules/alsa/alsa-mixer.c | 37 + 1 files changed, 37 insertions(+), 0 deletions(-) diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c index 51a6cd6..b425ce5 100644 --- a/src/modules/alsa/alsa-mixer.c +++ b/src/modules/alsa/alsa-mixer.c @@ -1398,6 +1398,43 @@ static int element_probe(pa_alsa_element *e, snd_mixer_t *m) { else e-has_dB = snd_mixer_selem_get_capture_dB_range(me, min_dB, max_dB) = 0; +/* Check that the kernel driver returns consistent limits with + * both _get_*_dB_range() and _ask_*_vol_dB(). */ +if (e-has_dB !e-db_fix) { +long min_dB_checked = 0; +long max_dB_checked = 0; + +if (e-direction == PA_ALSA_DIRECTION_OUTPUT) +r = snd_mixer_selem_ask_playback_vol_dB(me, e-min_volume, min_dB_checked); +else +r = snd_mixer_selem_ask_capture_vol_dB(me, e-min_volume, min_dB_checked); + +if (r 0) { +pa_log_warn(Failed to query the dB value for %s at volume level %li, e-alsa_name, e-min_volume); +return -1; +} + +if (e-direction == PA_ALSA_DIRECTION_OUTPUT) +r = snd_mixer_selem_ask_playback_vol_dB(me, e-max_volume, max_dB_checked); +else +r = snd_mixer_selem_ask_capture_vol_dB(me, e-max_volume, max_dB_checked); + +if (r 0) { +pa_log_warn(Failed to query the dB value for %s at volume level %li, e-alsa_name, e-max_volume); +return -1; +} + +if (min_dB != min_dB_checked || max_dB != max_dB_checked) { +pa_log_warn(Your kernel driver is broken: the reported dB range for %s (from %0.2f dB to %0.2f dB) +doesn't match the dB values at minimum and maximum volume levels: %0.2f dB at level %li, +%0.2f dB at level %li., +e-alsa_name, +min_dB / 100.0, max_dB / 100.0, +min_dB_checked / 100.0, e-min_volume, max_dB_checked / 100.0, e-max_volume); +return -1; +} +} + if (e-has_dB) { #ifdef HAVE_VALGRIND_MEMCHECK_H VALGRIND_MAKE_MEM_DEFINED(min_dB, sizeof(min_dB)); -- 1.7.4.1 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH] alsa-mixer: Make sure that SND_MIXER_SCHN_UNKNOWN isn't used when indexing e-masks.
SND_MIXER_SCHN_UNKNOWN is defined as -1, so that's not a good array index... --- src/modules/alsa/alsa-mixer.c | 13 +++-- 1 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c index b425ce5..c9adbb0 100644 --- a/src/modules/alsa/alsa-mixer.c +++ b/src/modules/alsa/alsa-mixer.c @@ -1490,8 +1490,13 @@ static int element_probe(pa_alsa_element *e, snd_mixer_t *m) { e-n_channels = 1; if (!e-override_map) { -for (p = PA_CHANNEL_POSITION_FRONT_LEFT; p PA_CHANNEL_POSITION_MAX; p++) +for (p = PA_CHANNEL_POSITION_FRONT_LEFT; p PA_CHANNEL_POSITION_MAX; p++) { +if (alsa_channel_ids[p] == SND_MIXER_SCHN_UNKNOWN) +continue; + e-masks[alsa_channel_ids[p]][e-n_channels-1] = 0; +} + e-masks[SND_MIXER_SCHN_MONO][e-n_channels-1] = PA_CHANNEL_POSITION_MASK_ALL; } @@ -1531,8 +1536,12 @@ static int element_probe(pa_alsa_element *e, snd_mixer_t *m) { } e-merged_mask = 0; -for (p = PA_CHANNEL_POSITION_FRONT_LEFT; p PA_CHANNEL_POSITION_MAX; p++) +for (p = PA_CHANNEL_POSITION_FRONT_LEFT; p PA_CHANNEL_POSITION_MAX; p++) { +if (alsa_channel_ids[p] == SND_MIXER_SCHN_UNKNOWN) +continue; + e-merged_mask |= e-masks[alsa_channel_ids[p]][e-n_channels-1]; +} } } } -- 1.7.4.1 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] ALSA or PulseAudio for low-latency voice?
On Sun, 2011-03-20 at 11:07 +0100, David Henningsson wrote: On 2011-03-19 17:45, Philip Jägenstedt wrote: Hi PulseAudionauts, I've been meaning to experiment a bit with low-latency voice codecs and naturally want to add as little latency as possible to what is imposed by the codec on both capture and playback. (My guess is that the latency added would be between min(capture_latency, playback_latency) and capture_latency+playback_latency, depending on how well capture end and playback begin are synchronized.) Q: Does it matters for latency if I program against ALSA or PulseAudio? Well, that kind of depends on what scale you're on. If you need latencies under say - and this is just a qualified guess - ~ 10-20 ms, you'll need to program against ALSA or Jack. Above that and you'll be good with PulseAudio. This is assuming a setup like on Ubuntu, where the default ALSA device is using a PulseAudio backend. (Portability and code complexity may favor one solution or the other, but that's not what I'm asking.) When I say program against ALSA above, I mean directly against an ALSA sound card, i e bypassing Pulseaudio. As for if ALSA plugin - PulseAudio - ALSA - HW gives worse latency than PulseAudio - ALSA - HW, I don't think that matters much. A while back I discussed in IRC with someone who wanted to have low latency with Pulseaudio. According to his experiments, it seemed like libpulse enforces for some reason a minimum client-side buffering of 100 ms or so, unless pa_stream_begin_write() is used when writing data. The alsa plugin doesn't use that function (I don't know why, maybe it just can't use it for some reason), so I would guess that it's impossible to get lower than 100 ms latencies through the alsa plugin. You can of course try, and results of such experiment would be interesting regardless of the outcome. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [PATCH 1/5] module-coreaudio-detect: fix pa__done()
On Sun, 2011-03-20 at 18:39 +0100, Daniel Mack wrote: void pa__done(pa_module *m) { -struct userdata *u; +struct userdata *u = m-userdata; struct ca_device *dev = u-devices; AudioObjectPropertyAddress property_address; -pa_assert(m); -pa_assert_se(u = m-userdata); - property_address.mSelector = kAudioHardwarePropertyDevices; property_address.mScope = kAudioObjectPropertyScopeGlobal; property_address.mElement = kAudioObjectPropertyElementMaster; I think the old assertions were good. I'd rather initialize dev after the assertions. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] More patches for OS X
On Sun, 2011-03-20 at 18:39 +0100, Daniel Mack wrote: osx: re-order module locations This patch didn't reach the list for some reason. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [PATCH 3/5] osx: add -headerpad_max_install_names to LDFLAGS
On Sun, 2011-03-20 at 18:39 +0100, Daniel Mack wrote: This is needed for sufficient padding of library names in linked binaries. --- src/Makefile.am |5 + 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index ff98ddb..c182483 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -82,6 +82,11 @@ FOREIGN_CFLAGS = -w MODULE_LDFLAGS = $(AM_LDFLAGS) -module -disable-static -avoid-version $(LDFLAGS_NOUNDEFINED) MODULE_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINOR@.la libpulsecommon-@PA_MAJORMINOR@.la libpulse.la +if OS_IS_DARWIN +AM_LDFLAGS+=-headerpad_max_install_names +MODULE_LDFLAGS+=-headerpad_max_install_names +endif If you put this block before MODULE_LDFLAGS is defined, then you don't need to touch MODULE_LDFLAGS, because they include AM_LDFLAGS automatically. Cosmetic: spaces around += would be nice (it seems that it wasn't entirely consistent before either...) -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH 2/2] bluetooth: Get rid of warnings about unused stuff when building against a D-Bus version that doesn't have fd-passing support.
--- src/modules/bluetooth/bluetooth-util.c | 10 -- 1 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c index 68ee808..cae7f16 100644 --- a/src/modules/bluetooth/bluetooth-util.c +++ b/src/modules/bluetooth/bluetooth-util.c @@ -519,6 +519,7 @@ static pa_dbus_pending* send_and_add_to_pending(pa_bluetooth_discovery *y, DBusM return p; } +#ifdef DBUS_TYPE_UNIX_FD static void register_endpoint_reply(DBusPendingCall *pending, void *userdata) { DBusError e; DBusMessage *r; @@ -559,6 +560,7 @@ finish: pa_xfree(endpoint); } +#endif static void list_devices_reply(DBusPendingCall *pending, void *userdata) { DBusError e; @@ -607,6 +609,7 @@ finish: pa_dbus_pending_free(p); } +#ifdef DBUS_TYPE_UNIX_FD static void register_endpoint(pa_bluetooth_discovery *y, const char *path, const char *endpoint, const char *uuid) { DBusMessage *m; DBusMessageIter i, d; @@ -654,6 +657,7 @@ static void register_endpoint(pa_bluetooth_discovery *y, const char *path, const send_and_add_to_pending(y, m, register_endpoint_reply, pa_xstrdup(endpoint)); } +#endif static void found_adapter(pa_bluetooth_discovery *y, const char *path) { DBusMessage *m; @@ -968,11 +972,9 @@ int pa_bluetooth_transport_acquire(const pa_bluetooth_transport *t, const char * pa_log(Failed to parse org.bluez.MediaTransport.Acquire(): %s, err.message); ret = -1; dbus_error_free(err); -goto fail; } #endif -fail: dbus_message_unref(r); return ret; } @@ -1013,6 +1015,7 @@ static int setup_dbus(pa_bluetooth_discovery *y) { return 0; } +#ifdef DBUS_TYPE_UNIX_FD static pa_bluetooth_transport *transport_new(pa_bluetooth_discovery *y, const char *path, enum profile p, const uint8_t *config, int size) { pa_bluetooth_transport *t; @@ -1358,13 +1361,16 @@ static DBusHandlerResult endpoint_handler(DBusConnection *c, DBusMessage *m, voi return DBUS_HANDLER_RESULT_HANDLED; } +#endif /* DBUS_TYPE_UNIX_FD */ pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *c) { DBusError err; pa_bluetooth_discovery *y; +#ifdef DBUS_TYPE_UNIX_FD static const DBusObjectPathVTable vtable_endpoint = { .message_function = endpoint_handler, }; +#endif pa_assert(c); -- 1.7.4.1 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH 2/2] alsa-mixer: Refactoring: merge element_mute_volume(), element_zero_volume() and element_apply_constant_volume() into a single function.
--- src/modules/alsa/alsa-mixer.c | 102 ++--- 1 files changed, 35 insertions(+), 67 deletions(-) diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c index 2893b47..aa3422a 100644 --- a/src/modules/alsa/alsa-mixer.c +++ b/src/modules/alsa/alsa-mixer.c @@ -1084,10 +1084,14 @@ int pa_alsa_path_set_mute(pa_alsa_path *p, snd_mixer_t *m, pa_bool_t muted) { return 0; } -static int element_mute_volume(pa_alsa_element *e, snd_mixer_t *m) { -snd_mixer_elem_t *me; -snd_mixer_selem_id_t *sid; -int r; +/* Depending on whether e-volume_use is _OFF, _ZERO or _CONSTANT, this + * function sets all channels of the volume element to e-min_volume, 0 dB or + * e-constant_volume. */ +static int element_set_constant_volume(pa_alsa_element *e, snd_mixer_t *m) { +snd_mixer_elem_t *me = NULL; +snd_mixer_selem_id_t *sid = NULL; +int r = 0; +long volume = -1; pa_assert(m); pa_assert(e); @@ -1098,74 +1102,44 @@ static int element_mute_volume(pa_alsa_element *e, snd_mixer_t *m) { return -1; } -if (e-direction == PA_ALSA_DIRECTION_OUTPUT) -r = snd_mixer_selem_set_playback_volume_all(me, e-min_volume); -else -r = snd_mixer_selem_set_capture_volume_all(me, e-min_volume); - -if (r 0) -pa_log_warn(Failed to set volume to muted of %s: %s, e-alsa_name, pa_alsa_strerror(errno)); +switch (e-volume_use) { +case PA_ALSA_VOLUME_OFF: +volume = e-min_volume; +break; -return r; -} +case PA_ALSA_VOLUME_ZERO: +if (e-db_fix) { +long dB = 0; -/* The volume to 0dB */ -static int element_zero_volume(pa_alsa_element *e, snd_mixer_t *m) { -snd_mixer_elem_t *me; -snd_mixer_selem_id_t *sid; -int r; +volume = decibel_fix_get_step(e-db_fix, dB, +1); +} +break; -pa_assert(m); -pa_assert(e); +case PA_ALSA_VOLUME_CONSTANT: +volume = e-constant_volume; +break; -SELEM_INIT(sid, e-alsa_name); -if (!(me = snd_mixer_find_selem(m, sid))) { -pa_log_warn(Element %s seems to have disappeared., e-alsa_name); -return -1; +default: +pa_assert_not_reached(); } -if (e-direction == PA_ALSA_DIRECTION_OUTPUT) -if (e-db_fix) { -long value = 0; +if (volume = 0) { +if (e-direction == PA_ALSA_DIRECTION_OUTPUT) +r = snd_mixer_selem_set_playback_volume_all(me, volume); +else +r = snd_mixer_selem_set_capture_volume_all(me, volume); +} else { +pa_assert(e-volume_use == PA_ALSA_VOLUME_ZERO); +pa_assert(!e-db_fix); -r = snd_mixer_selem_set_playback_volume_all(me, decibel_fix_get_step(e-db_fix, value, +1)); -} else +if (e-direction == PA_ALSA_DIRECTION_OUTPUT) r = snd_mixer_selem_set_playback_dB_all(me, 0, +1); -else -if (e-db_fix) { -long value = 0; - -r = snd_mixer_selem_set_capture_volume_all(me, decibel_fix_get_step(e-db_fix, value, +1)); -} else +else r = snd_mixer_selem_set_capture_dB_all(me, 0, +1); - -if (r 0) -pa_log_warn(Failed to set volume to 0dB of %s: %s, e-alsa_name, pa_alsa_strerror(errno)); - -return r; -} - -static int element_apply_constant_volume(pa_alsa_element *e, snd_mixer_t *m) { -snd_mixer_elem_t *me; -snd_mixer_selem_id_t *sid; -int r; - -pa_assert(m); -pa_assert(e); - -SELEM_INIT(sid, e-alsa_name); -if (!(me = snd_mixer_find_selem(m, sid))) { -pa_log_warn(Element %s seems to have disappeared., e-alsa_name); -return -1; } -if (e-direction == PA_ALSA_DIRECTION_OUTPUT) -r = snd_mixer_selem_set_playback_volume_all(me, e-constant_volume); -else -r = snd_mixer_selem_set_capture_volume_all(me, e-constant_volume); - if (r 0) -pa_log_warn(Failed to set volume to %li of %s: %s, e-constant_volume, e-alsa_name, pa_alsa_strerror(errno)); +pa_log_warn(Failed to set volume of %s: %s, e-alsa_name, pa_alsa_strerror(errno)); return r; } @@ -1203,15 +1177,9 @@ int pa_alsa_path_select(pa_alsa_path *p, snd_mixer_t *m) { switch (e-volume_use) { case PA_ALSA_VOLUME_OFF: -r = element_mute_volume(e, m); -break; - case PA_ALSA_VOLUME_ZERO: -r = element_zero_volume(e, m); -break; - case PA_ALSA_VOLUME_CONSTANT: -r = element_apply_constant_volume(e, m); +r = element_set_constant_volume(e, m); break; case PA_ALSA_VOLUME_MERGE: -- 1.7.4.1 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [WIP] Passthrough support
On Tue, 2011-03-15 at 17:36 -0500, pl bossart wrote: I pushed your change along with a fix for the assert you saw to my tree as well. I tested the latest batch of patches with AC3/SPDIF this time. Works well in general, however I found some interesting points: - in Rhythmbox, the passthrough mode is only enabled if the first file of playlist is compressed. If you start with PCM/WAV, it always uses the PCM mode. - in Totem, the passthrough mode works when the visual effects are disabled. I see a nice DD on my receiver...However the playback stops if you play with the volume slider. I get a pop-up error window saying 'an error occurred: pa_stream_set_sink_input_volume(): invalid argument' On a related note, maybe we want to change the approach to volume control. Depending on the sink, there might be ways of using side/in-band channels to send volume control information to the decoder. It's going to be protocol-specific. So maybe we need to provide the client with an information coming from the sink on whether volume control is actually supported or not. Yes, that information will be provided in the sink and source introspection data. Somewhat related: I've been thinking that maybe the volume channels should be separate from the stream channels. For example, maybe it's possible that some future sink implementation can only provide a simple single-channel volume interface, while the actual audio stream has multiple channels. Are you aware of any real-world cases where this separation would be beneficial? -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] 2ch - 6ch upmixing with flatvolumes
On Sat, 2011-03-12 at 14:46 +, Colin Guthrie wrote: Hi, I was working with Valodim on IRC and stumbled on an issue with flat volumes on 5.1 sinks when playing a 2ch sink input. I try to adjust the Rear left+right to be 0, but it just doesn't let me. It seems the flat volume logic somehow forces it back to the same as the other channels. I'm not sure what you mean by it just doesn't let me. I could try and see for myself, but I'm too lazy... I did read some code a bit, and I didn't find out what could cause the volume to get stuck in a user-visible way. The remapping stuff is a bit complicated to think about, though, so I didn't gain confidence that the volume couldn't get stuck, either. What I knew beforehand, however, was that if a sink has streams that don't have the same channel map as the sink, then the real volume of the sink is forced to be flat - all channels have the same volume. This probably in some way causes the trouble that you're having. I got the impression that you're setting the sink volume in pavucontrol, and the sliders would be stuck in some value. When the sink volume is adjusted, the reference volume is set before the real volume is calculated, so when the real volume is forced to be flat, that shouldn't be visible in the GUI (which shows the reference volume). There's this comment in cvolume_remap_minimal_impact() in sink.c: /* Much like pa_cvolume_remap(), but tries to minimize impact when * mapping from sink input to sink volumes: * * If template is a possible remapping from v it is used instead * of remapping anew. * * If the channel maps don't match we set an all-channel volume on * the sink to ensure that changing a volume on one stream has no * effect that cannot be compensated for in another stream that * does not have the same channel map as the sink. */ I wonder if that all-channel volume part is really needed. I find the current implementation really hard to reason about, but I think forcing the real volume to be flat wouldn't be needed at least if the volumes were handled a bit differently: - Sink inputs would maintain two copies of their volume variables: one set of variables for the sink input's channel map and one set for the sink's channel map. When a volume variable in either set is updated, the corresponding variable in the other set is updated too, using the normal remapping function. - When the sink has to calculate its real volume from the sink inputs, it would look only at the sink input volume that uses the sink's channel map. This way there's no need to do do any remapping at this phase - each channel of the real volume would simply be set to the maximum found in all sink inputs for that channel. There's no way any stream could step on some other stream's toes either. It would be nice to know what scenario the comment refers to, when it says that without that precaution there can be a situation where one stream's volume change can't be compensated for in some other stream. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] [RFC] allow conditionals in config input files like default.pa.in
Hi Maarten, Did you ever get any feedback? At least there are no replies on the mailing list. On Fri, 2011-03-04 at 00:26 +0100, Maarten Bosmans wrote: It would be nice to have the ability to use @if HAVE_FEATURE@ in the configuration file templates. You could see it either as an extension of the current @VARIABLE@ replacement or as a compile-time variant of .ifexists. Incidentally, does anybody know why these files are currently generated in the Makefile using sed, instead of being included in AC_CONFIG_FILES? At least I don't know. Adding that ability has several advantages: - The default.pa.in and default.pa.win32 files can be merged. - The BSDs still use module-hal-detect, so it can be included in default.pa without littering it with [.ifexists module-hal-detect\n load-module module-hal-detect\n .endif] for Linux users, so they cannot be confused by it. - And thirdly, if sys/resource.h is not found the daemon does not understand the --rlimit-* options, so in that case those lines should be omitted from daemon.conf. Would this be a good change, or are we then preprocessing at too many levels? Sounds useful to me. In case my opinion matters, you have my acceptance :) -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH 1/2] alsa-mixer: Implement support for setting element specific upper limits for volume.
From: Tanu Kaskinen ext-tanu.kaski...@nokia.com This feature is mainly useful in embedded systems that have built-in speakers. In such situations the full audio path is known beforehand, so it's possible to know what is the maximum sensible volume, and any higher volume can be disabled. The volume limit is set in path configuration files in the [Element] section, using option volume-limit. The value is the desired maximum volume step of the volume element. --- src/modules/alsa/alsa-mixer.c | 68 +++- src/modules/alsa/alsa-mixer.h |1 + .../alsa/mixer/paths/analog-output.conf.common |1 + 3 files changed, 69 insertions(+), 1 deletions(-) diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c index 9a7e045..41997a7 100644 --- a/src/modules/alsa/alsa-mixer.c +++ b/src/modules/alsa/alsa-mixer.c @@ -895,6 +895,9 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann long value = to_alsa_dB(f); int rounding = value 0 ? -1 : +1; +if (e-volume_limit = 0 value (e-max_dB * 100)) +value = e-max_dB * 100; + if (e-direction == PA_ALSA_DIRECTION_OUTPUT) { /* If we call set_playback_volume() without checking first * if the channel is available, ALSA behaves very @@ -1284,6 +1287,7 @@ static int element_probe(pa_alsa_element *e, snd_mixer_t *m) { pa_assert(m); pa_assert(e); +pa_assert(e-path); SELEM_INIT(sid, e-alsa_name); @@ -1407,6 +1411,36 @@ static int element_probe(pa_alsa_element *e, snd_mixer_t *m) { } } +if (e-volume_limit = 0) { +if (e-volume_limit = e-min_volume || e-volume_limit e-max_volume) +pa_log_warn(Volume limit for element %s of path %s is invalid: %li isn't within the valid range +%li-%li. The volume limit is ignored., +e-alsa_name, e-path-name, e-volume_limit, e-min_volume + 1, e-max_volume); + +else { +e-max_volume = e-volume_limit; + +if (e-has_dB) { +if (e-db_fix) { +e-db_fix-max_step = e-max_volume; +e-max_dB = ((double) e-db_fix-db_values[e-db_fix-max_step - e-db_fix-min_step]) / 100.0; + +} else { +if (e-direction == PA_ALSA_DIRECTION_OUTPUT) +r = snd_mixer_selem_ask_playback_vol_dB(me, e-max_volume, max_dB); +else +r = snd_mixer_selem_ask_capture_vol_dB(me, e-max_volume, max_dB); + +if (r 0) { +pa_log_warn(Failed to get dB value of %s: %s, e-alsa_name, pa_alsa_strerror(r)); +e-has_dB = FALSE; +} else +e-max_dB = ((double) max_dB) / 100.0; +} +} +} +} + if (e-direction == PA_ALSA_DIRECTION_OUTPUT) is_mono = snd_mixer_selem_is_playback_mono(me) 0; else @@ -1530,6 +1564,7 @@ static pa_alsa_element* element_get(pa_alsa_path *p, const char *section, pa_boo e-path = p; e-alsa_name = pa_xstrdup(section); e-direction = p-direction; +e-volume_limit = -1; PA_LLIST_INSERT_AFTER(pa_alsa_element, p-elements, p-last_element, e); @@ -1864,6 +1899,33 @@ static int element_parse_direction_try_other( return 0; } +static int element_parse_volume_limit( +const char *filename, +unsigned line, +const char *section, +const char *lvalue, +const char *rvalue, +void *data, +void *userdata) { + +pa_alsa_path *p = userdata; +pa_alsa_element *e; +uint32_t volume_limit; + +if (!(e = element_get(p, section, TRUE))) { +pa_log([%s:%u] volume-limit makes no sense in '%s', filename, line, section); +return -1; +} + +if (pa_atou(rvalue, volume_limit) 0 || volume_limit LONG_MAX) { +pa_log([%s:%u] Invalid value for volume-limit, filename, line); +return -1; +} + +e-volume_limit = volume_limit; +return 0; +} + static pa_channel_position_mask_t parse_mask(const char *m) { pa_channel_position_mask_t v; @@ -2141,6 +2203,7 @@ pa_alsa_path* pa_alsa_path_new(const char *fname, pa_alsa_direction_t direction) { required-absent, element_parse_required,NULL, NULL }, { direction, element_parse_direction, NULL, NULL }, { direction-try-other
[pulseaudio-discuss] [PATCH 2/2] alsa-mixer: When figuring out the max_dB of a path, use only channels that are used by the path elements.
Without this, p-max_dB could never be less than 0 dB, because the loop at the end of pa_alsa_path_probe() would reset p-max_dB to 0 as soon as the loop encountered a channel that wasn't touched by any element. --- src/modules/alsa/alsa-mixer.c | 13 + 1 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c index 41997a7..3eef5f9 100644 --- a/src/modules/alsa/alsa-mixer.c +++ b/src/modules/alsa/alsa-mixer.c @@ -2400,6 +2400,7 @@ int pa_alsa_path_probe(pa_alsa_path *p, snd_mixer_t *m, pa_bool_t ignore_dB) { pa_alsa_element *e; double min_dB[PA_CHANNEL_POSITION_MAX], max_dB[PA_CHANNEL_POSITION_MAX]; pa_channel_position_t t; +pa_channel_position_mask_t path_volume_channels = 0; pa_assert(p); pa_assert(m); @@ -2436,6 +2437,7 @@ int pa_alsa_path_probe(pa_alsa_path *p, snd_mixer_t *m, pa_bool_t ignore_dB) { if (PA_CHANNEL_POSITION_MASK(t) e-merged_mask) { min_dB[t] = e-min_dB; max_dB[t] = e-max_dB; +path_volume_channels |= PA_CHANNEL_POSITION_MASK(t); } p-has_dB = TRUE; @@ -2446,6 +2448,7 @@ int pa_alsa_path_probe(pa_alsa_path *p, snd_mixer_t *m, pa_bool_t ignore_dB) { if (PA_CHANNEL_POSITION_MASK(t) e-merged_mask) { min_dB[t] += e-min_dB; max_dB[t] += e-max_dB; +path_volume_channels |= PA_CHANNEL_POSITION_MASK(t); } } else { /* Hmm, there's another element before us @@ -2484,11 +2487,13 @@ int pa_alsa_path_probe(pa_alsa_path *p, snd_mixer_t *m, pa_bool_t ignore_dB) { p-max_dB = -INFINITY; for (t = 0; t PA_CHANNEL_POSITION_MAX; t++) { -if (p-min_dB min_dB[t]) -p-min_dB = min_dB[t]; +if (path_volume_channels PA_CHANNEL_POSITION_MASK(t)) { +if (p-min_dB min_dB[t]) +p-min_dB = min_dB[t]; -if (p-max_dB max_dB[t]) -p-max_dB = max_dB[t]; +if (p-max_dB max_dB[t]) +p-max_dB = max_dB[t]; +} } return 0; -- 1.7.4.1 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH 2/7 v2] alsa-mixer: Use decibel fixes when getting and setting decibel volumes.
From: Tanu Kaskinen ext-tanu.kaski...@nokia.com --- src/modules/alsa/alsa-mixer.c | 260 - src/modules/alsa/alsa-mixer.h |8 +- 2 files changed, 212 insertions(+), 56 deletions(-) diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c index c0bbaa0..340e063 100644 --- a/src/modules/alsa/alsa-mixer.c +++ b/src/modules/alsa/alsa-mixer.c @@ -491,6 +491,15 @@ static void option_free(pa_alsa_option *o) { pa_xfree(o); } +static void decibel_fix_free(pa_alsa_decibel_fix *db_fix) { +pa_assert(db_fix); + +pa_xfree(db_fix-name); +pa_xfree(db_fix-db_values); + +pa_xfree(db_fix); +} + static void element_free(pa_alsa_element *e) { pa_alsa_option *o; pa_assert(e); @@ -500,6 +509,9 @@ static void element_free(pa_alsa_element *e) { option_free(o); } +if (e-db_fix) +decibel_fix_free(e-db_fix); + pa_xfree(e-alsa_name); pa_xfree(e); } @@ -593,14 +605,60 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann long value = 0; if (e-direction == PA_ALSA_DIRECTION_OUTPUT) { -if (snd_mixer_selem_has_playback_channel(me, c)) -r = snd_mixer_selem_get_playback_dB(me, c, value); -else +if (snd_mixer_selem_has_playback_channel(me, c)) { +if (e-db_fix) { +if ((r = snd_mixer_selem_get_playback_volume(me, c, value)) = 0) { +/* If the channel volume is outside the limits set + * by the dB fix, we clamp the hw volume to be + * within the limits. */ +if (value e-db_fix-min_step) { +value = e-db_fix-min_step; +snd_mixer_selem_set_playback_volume(me, c, value); +pa_log_debug(Playback volume for element %s channel %i was below the dB fix limit. + Volume reset to %0.2f dB., e-alsa_name, c, + e-db_fix-db_values[value - e-db_fix-min_step] / 100.0); +} else if (value e-db_fix-max_step) { +value = e-db_fix-max_step; +snd_mixer_selem_set_playback_volume(me, c, value); +pa_log_debug(Playback volume for element %s channel %i was over the dB fix limit. + Volume reset to %0.2f dB., e-alsa_name, c, + e-db_fix-db_values[value - e-db_fix-min_step] / 100.0); +} + +/* Volume step - dB value conversion. */ +value = e-db_fix-db_values[value - e-db_fix-min_step]; +} +} else +r = snd_mixer_selem_get_playback_dB(me, c, value); +} else r = -1; } else { -if (snd_mixer_selem_has_capture_channel(me, c)) -r = snd_mixer_selem_get_capture_dB(me, c, value); -else +if (snd_mixer_selem_has_capture_channel(me, c)) { +if (e-db_fix) { +if ((r = snd_mixer_selem_get_capture_volume(me, c, value)) = 0) { +/* If the channel volume is outside the limits set + * by the dB fix, we clamp the hw volume to be + * within the limits. */ +if (value e-db_fix-min_step) { +value = e-db_fix-min_step; +snd_mixer_selem_set_capture_volume(me, c, value); +pa_log_debug(Capture volume for element %s channel %i was below the dB fix limit. + Volume reset to %0.2f dB., e-alsa_name, c, + e-db_fix-db_values[value - e-db_fix-min_step] / 100.0); +} else if (value e-db_fix-max_step) { +value = e-db_fix-max_step; +snd_mixer_selem_set_capture_volume(me, c, value); +pa_log_debug(Capture volume for element %s channel %i was over the dB fix limit. + Volume reset to %0.2f dB., e-alsa_name, c, + e-db_fix-db_values[value - e-db_fix-min_step] / 100.0); +} + +/* Volume step - dB value conversion. */ +value = e-db_fix-db_values[value - e-db_fix-min_step
Re: [pulseaudio-discuss] [PATCH 0/7] Working around bad decibel information
On Wed, 2011-03-09 at 12:53 +0200, David Henningsson wrote: On 2011-03-04 16:42, Tanu Kaskinen wrote: Here's a pile of patches. The first two implement the concept of decibel fixes for alsa devices. A decibel fix is basically a table that maps the raw volume steps of a mixer element to manually configured decibel values. Hmm, taking Lennart's hat on, shouldn't bad decibel information be fixed in the kernel, rather than in Pulseaudio? Then other non-PA applications would benefit from the change as well. Yes, the fixes should be pushed to alsa. Maybe the DecibelFix documentation in profile-sets/default.conf should even say that if you're using this feature and not actively pushing the fixes to alsa, then you're doing it wrong. But if the kernel driver is already correct in the sense that it follows the chip specifications, then I believe this feature is useful for convincing the alsa developers to fix the driver - if the decibel mapping has been tested in Pulseaudio already, we can give a ready-made table to the alsa devs and they don't need to bother with the measurement part. I think measuring the correct levels is quite practical to do with pulseaudio: the flat volume and sync volume features make it possible to easily compare the subjective volume difference between hw attenuation and with sw attenuation. If you play a quiet stream (eg. pacat --volume=1 /dev/urandom) and then play short clips of silence at full volume, the flat volume feature switches smoothly between hw and sw attenuation for the quiet stream, and incorrect dB information is easy to observe. Based on some personal experience, I believe subjective measurement is even more accurate than measuring the levels using an oscilloscope - at low volume levels the background noise can make getting an accurate measurement really hard with an oscilloscope. It's possible that this feature will lead to lowered pressure to report dB problems to alsa, and if that means less fixes in alsa, then these patches should be removed. But since anyone can try out tweaking the dB values in pulseaudio's configuration easily (relative to hacking alsa drivers), maybe this will actually increase the amount of fixes in alsa... These patches are old (only now I got around to polishing them and sending them to upstream), and I've actually already asked Lennart's opinion of this feature about a year ago. At that time he ok'd the concept. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
Re: [pulseaudio-discuss] Volume algorithm
On Sat, 2011-03-05 at 11:29 +, Tarantism wrote: On Sat, 2011-03-05 at 11:08 +, Colin Guthrie wrote: 'Twas brillig, and Tarantism at 04/03/11 22:23 did gyre and gimble: I need to implement a volume scaling in a pulse module. I have 0-100 input values. What algorithm does pulse usually implement for this so that I can match it? Can you explain a little more what you're trying to do? You shouldn't generally need to worry about volume scaling in PA modules. The module is a signal source for the default sink (based on module-sine.c) so it creates a sink_input and provides pop (etc) callbacks for that. I'm using it to produce low latency sound on Maemo. Are you planning to use the module outside Maemo 5 (I assume you're talking about Maemo 5)? I ask because Pulseaudio's internal API that modules use isn't stable, so modules that aren't part of Pulseaudio itself break very likely if you try to use them with any other version of Pulseaudio than what they were compiled against. If Maemo 5 is enough for you, then you probably won't have problems - I don't think Pulseaudio will get significant updates on that OS anymore. I had expected that system volume would be handled downstream of the sink_input but changing system volume has no effect. I've managed to hook up to the system volume level by dbus and just want to know how to scale my data correctly. The volume system on Maemo is a bit peculiar. The system volume doesn't touch any sink volumes (except with bluetooth in HSP/HFP mode), all volume control is done by adjusting stream volumes. If you want to use the same volume as eg. the music player, set the media.role property of the sink input to x-maemo. That's a special role for pretty much everything else than phone and event sound streams. -- Tanu ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH 0/7] Working around bad decibel information
Here's a pile of patches. The first two implement the concept of decibel fixes for alsa devices. A decibel fix is basically a table that maps the raw volume steps of a mixer element to manually configured decibel values. The rest of the patches are random fixes that have piled up while testing the decibel fix patches. The pacat memory leak fix hasn't been verified that it works (it's just a quick fix to a seemingly obvious, but difficult to test bug), otherwise I have tested the fixes. Tanu Kaskinen (7): alsa-mixer: Add DecibelFix section to the profile set config file format. alsa-mixer: Use decibel fixes when getting and setting decibel volumes. pacat: Fix memory leak when draining the context. alsa-mixer: Add a default case for a switch, so that the compiler won't complain about unhandled cases. alsa-card: Print the profile set configuration when loading the card. dbusiface-stream: Fix crash when there's no resampling used. dbus: Always accept mono volumes when setting device or stream volume. src/modules/alsa/alsa-mixer.c| 500 +++--- src/modules/alsa/alsa-mixer.h| 27 +- src/modules/alsa/mixer/profile-sets/default.conf | 49 ++- src/modules/alsa/module-alsa-card.c |1 + src/modules/dbus/iface-device.c |9 +- src/modules/dbus/iface-stream.c | 14 +- src/utils/pacat.c|4 +- 7 files changed, 517 insertions(+), 87 deletions(-) -- 1.7.4.1 ___ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss
[pulseaudio-discuss] [PATCH 1/7] alsa-mixer: Add DecibelFix section to the profile set config file format.
From: Tanu Kaskinen ext-tanu.kaski...@nokia.com This commit only implements the parser, the decibel fix data is not yet used for anything. --- src/modules/alsa/alsa-mixer.c| 223 +- src/modules/alsa/alsa-mixer.h| 19 ++ src/modules/alsa/mixer/profile-sets/default.conf | 49 - 3 files changed, 277 insertions(+), 14 deletions(-) diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c index fa07674..c0bbaa0 100644 --- a/src/modules/alsa/alsa-mixer.c +++ b/src/modules/alsa/alsa-mixer.c @@ -2640,6 +2640,15 @@ static void profile_free(pa_alsa_profile *p) { pa_xfree(p); } +static void decibel_fix_free(pa_alsa_decibel_fix *db_fix) { +pa_assert(db_fix); + +pa_xfree(db_fix-name); +pa_xfree(db_fix-db_values); + +pa_xfree(db_fix); +} + void pa_alsa_profile_set_free(pa_alsa_profile_set *ps) { pa_assert(ps); @@ -2661,6 +2670,15 @@ void pa_alsa_profile_set_free(pa_alsa_profile_set *ps) { pa_hashmap_free(ps-mappings, NULL, NULL); } +if (ps-decibel_fixes) { +pa_alsa_decibel_fix *db_fix; + +while ((db_fix = pa_hashmap_steal_first(ps-decibel_fixes))) +decibel_fix_free(db_fix); + +pa_hashmap_free(ps-decibel_fixes, NULL, NULL); +} + pa_xfree(ps); } @@ -2705,6 +2723,26 @@ static pa_alsa_profile *profile_get(pa_alsa_profile_set *ps, const char *name) { return p; } +static pa_alsa_decibel_fix *decibel_fix_get(pa_alsa_profile_set *ps, const char *name) { +pa_alsa_decibel_fix *db_fix; + +if (!pa_startswith(name, DecibelFix )) +return NULL; + +name += 11; + +if ((db_fix = pa_hashmap_get(ps-decibel_fixes, name))) +return db_fix; + +db_fix = pa_xnew0(pa_alsa_decibel_fix, 1); +db_fix-profile_set = ps; +db_fix-name = pa_xstrdup(name); + +pa_hashmap_put(ps-decibel_fixes, db_fix-name, db_fix); + +return db_fix; +} + static int mapping_parse_device_strings( const char *filename, unsigned line, @@ -2975,6 +3013,130 @@ static int profile_parse_skip_probe( return 0; } +static int decibel_fix_parse_db_values( +const char *filename, +unsigned line, +const char *section, +const char *lvalue, +const char *rvalue, +void *data, +void *userdata) { + +pa_alsa_profile_set *ps = userdata; +pa_alsa_decibel_fix *db_fix; +char **items; +char *item; +long *db_values; +unsigned n = 8; /* Current size of the db_values table. */ +unsigned min_step = 0; +unsigned max_step = 0; +unsigned i = 0; /* Index to the items table. */ +unsigned prev_step = 0; +double prev_db = 0; + +pa_assert(filename); +pa_assert(section); +pa_assert(lvalue); +pa_assert(rvalue); +pa_assert(ps); + +if (!(db_fix = decibel_fix_get(ps, section))) { +pa_log([%s:%u] %s invalid in section %s, filename, line, lvalue, section); +return -1; +} + +if (!(items = pa_split_spaces_strv(rvalue))) { +pa_log([%s:%u] Value missing, pa_strnull(filename), line); +return -1; +} + +db_values = pa_xnew(long, n); + +while ((item = items[i++])) { +char *s = item; /* Step value string. */ +char *d = item; /* dB value string. */ +uint32_t step; +double db; + +/* Move d forward until it points to a colon or to the end of the item. */ +for (; *d *d != ':'; ++d); + +if (d == s) { +/* item started with colon. */ +pa_log([%s:%u] No step value found in %s, filename, line, item); +goto fail; +} + +if (!*d || !*(d + 1)) { +/* No colon found, or it was the last character in item. */ +pa_log([%s:%u] No dB value found in %s, filename, line, item); +goto fail; +} + +/* pa_atou() needs a null-terminating string. Let's replace the colon + * with a zero byte. */ +*d++ = '\0'; + +if (pa_atou(s, step) 0) { +pa_log([%s:%u] Invalid step value: %s, filename, line, s); +goto fail; +} + +if (pa_atod(d, db) 0) { +pa_log([%s:%u] Invalid dB value: %s, filename, line, d); +goto fail; +} + +if (step = prev_step i != 1) { +pa_log([%s:%u] Step value %u not greater than the previous value %u, filename, line, step, prev_step); +goto fail; +} + +if (db prev_db i != 1) { +pa_log([%s:%u] Decibel value %0.2f less than the previous value %0.2f, filename, line, db, prev_db); +goto fail; +} + +if (i == 1) { +min_step = step; +db_values[0] = (long) (db * 100.0); +prev_step = step; +prev_db = db; +} else { +/* Interpolate linearly. */ +double db_increment = (db - prev_db