Re: [LAD] [Jack-Devel] jack2's dbus name
On Mon, Jun 15, 2009 at 04:37:09PM +0200, Lennart Poettering wrote: > On Mon, 15.06.09 15:34, Stéphane Letz (l...@grame.fr) wrote: > > > What I'm personally trying to achieve is a more "flexible" way (compared > > to what is currently a bit hard-coded in JAKC2 SVN) so that a DBus > > control component can be coded as a "plugin" to be possibly loaded in > > JACK server process. This new plugin model allows to keep basically 2 > > ways of using JACK server : the "old way" (typically starting the jackd > > server using Qjackctl control application) or the new way using DBus > > based control applications (after the DBus control plug-in has been > > properly loaded in JACK server). (Keeping the "old-way" is also > > important on others platforms JACK2 runs on.) > > Distributions will certainly enable the D-Bus code in JACK if they > ship it. So, I have no problem with depending on a dbus'ified jack for > this logic to work. After all crazy folks who disable the dbus support > in jack because they think it's an abomination probably think that PA > is an even worse abomination anyway, so there's not need to cater for > them. > > > If this new "control plugin" model is finally accepted by JACK > > community, then we'll distribute/package JACK2 compiled with the 1) > > option, so that it (at least) cooperates with PulseAudio. But 2) would > > then be optional, so PA can not rely on the DBus control plug-in to > > always be present. > > > > The 1) code uses "org.freedesktop.ReserveDevice1.AudioXX" name, and 2) > > optional DBus plugin uses "org.jackaudio.service" name. If we want to > > implement your proposal, the we would need to request another name in 1) > > part, is that correct? > > I think org.jackaudio.service should be fine. I don't think this > automatic logic needs to work on non-D-Bus jack builds. As I see it > you don't need to make any changes on jack for this to work. All I > need is the guarantee that by the time the service name is registered > on the bus jack is fully accessible. Otherwise we had a race here: if > PA looks for the org.jackaudio.service name to appear on the bus and > then imemdiately connects to it while jack isn't fully accessible yet > PA would fail. the existence of org.jackaudio.service object does not guarantee, that jackd is connectable. i guess we need a signal, which tells that a server has been started, but i leave this to the dbus guys. my primary concern is to have the pa jack backend fixed. lennart himself said its a TOY. and it really is. i dont really understand why it works, but its pretty broken, for sure. static int jack_process(jack_nframes_t nframes, void *arg) { struct userdata *u = arg; unsigned c; jack_nframes_t frame_time; pa_assert(u); /* We just forward the request to our other RT thread */ for (c = 0; c < u->channels; c++) pa_assert_se(u->buffer[c] = jack_port_get_buffer(u->port[c], nframes)); frame_time = jack_frame_time(u->client); pa_assert_se(pa_asyncmsgq_send(u->jack_msgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_RENDER, &frame_time, nframes, NULL) == 0); return 0; } it needs to be decoupled using a ringbuffer. and maybe pulse should be running with a higher blocksize than jack ? > > Lennart > > -- > Lennart PoetteringRed Hat, Inc. > lennart [at] poettering [dot] net > http://0pointer.net/lennart/ GnuPG 0x1A015CC4 > ___ > Jack-Devel mailing list > jack-de...@lists.jackaudio.org > http://lists.jackaudio.org/listinfo.cgi/jack-devel-jackaudio.org -- torben Hohn http://galan.sourceforge.net -- The graphical Audio language ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
On Thu, 18.06.09 16:09, torb...@gmx.de (torb...@gmx.de) wrote: > > I think org.jackaudio.service should be fine. I don't think this > > automatic logic needs to work on non-D-Bus jack builds. As I see it > > you don't need to make any changes on jack for this to work. All I > > need is the guarantee that by the time the service name is registered > > on the bus jack is fully accessible. Otherwise we had a race here: if > > PA looks for the org.jackaudio.service name to appear on the bus and > > then imemdiately connects to it while jack isn't fully accessible yet > > PA would fail. > > the existence of org.jackaudio.service object does not guarantee, > that jackd is connectable. I'd consider that brokeness in Jack then. Taking the name on the bus sould be the last step during initialization. Otherwise you'll always be in racy situations where clients try to talk to JACK while JACK is only half-way initialized. > > i guess we need a signal, which tells that a server has been started, > but i leave this to the dbus guys. Nope. That is the wrong approach. > my primary concern is to have the pa jack backend fixed. > lennart himself said its a TOY. and it really is. Aha. > i dont really understand why it works, but its pretty broken, for > sure. Aha. > static int jack_process(jack_nframes_t nframes, void *arg) { > struct userdata *u = arg; > unsigned c; > jack_nframes_t frame_time; > pa_assert(u); > > /* We just forward the request to our other RT thread */ > > for (c = 0; c < u->channels; c++) > pa_assert_se(u->buffer[c] = jack_port_get_buffer(u->port[c], > nframes)); > > frame_time = jack_frame_time(u->client); > > pa_assert_se(pa_asyncmsgq_send(u->jack_msgq, PA_MSGOBJECT(u->sink), > SINK_MESSAGE_RENDER, &frame_time, nframes, NULL) == 0); > return 0; > } > > > it needs to be decoupled using a ringbuffer. Uh? That is actually what happens. This is a bit more complex than you might think. Jack's thread management is very unflexible and insists on controlling the entire thread life cycle, only calling into client code in very few occasions. This is a bit too limited for PA which needs better control on the RT loops so that it can properly priorize/order the work it needs to do in it. To work around that I decided to run two RT threads, one where PA does its own RT looping, and the one jack controls. The latter then simply relays the process requests synchronously to the former. This of course comes at the cost of a needless context switch, however both threads are RT. The normal PA RT loop thread communicates lock-free and asynchronously with the rest of the PA code. Yes, having to work around JACK's API like this is certainly not nice. But aside from the extra context switch this shouldn't be too bad. Of course it would great if JACK would be more flexible with its RT loop handling. What I am missing is basically a way to asynchronously/lock-free trigger execution of a callback function in the RT loop at a suitable place. By a "suitable place" I mean that the RT loop delays execution of this callback until a time where its impact would be minimal, i.e. right after a completed process() and a quick verification that the next process() cycle is still a bit away. Why does pa need those callbacks? In contrast to JACK we need to be able to modify our pipelines during playback without having that cause drop-outs in any way. To accomplish that updates to pipeline related data structures that need to be accessed by the RT loop are as far as possible done in the main thread, however usually the last remaining bit for activating those changes is left for the RT loop to do itself, asynchronously and only when it can be sure that nothing else needs to be done. That way we can have those data structures implemented lock-free without really having to implement them with all that lock-free complexity. > and maybe pulse should be running with a higher blocksize than jack ? PA does not use fixed block sizes. We always use the largest chunk sizes the applications pass to us and break them up into smaller pieces only when really necessary. We really try our best not having to touch/convert/split/copy user supplied PCM data if we don't have to. Lennart -- Lennart PoetteringRed Hat, Inc. lennart [at] poettering [dot] net http://0pointer.net/lennart/ GnuPG 0x1A015CC4 ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
Lennart Poettering wrote: > PA does not use fixed block sizes. We always use the largest chunk > sizes the applications pass to us and break them up into smaller > pieces only when really necessary. We really try our best not having > to touch/convert/split/copy user supplied PCM data if we don't have > to. This is quite different from the goals of JACK, where the purpose is to minimize input -> output latency and thus use as small as possible blocks. Typically there's: [input] --> [processing] --> [output] [generation] --^ Where input is typically live sound or MIDI, processing can be effects processing or similar (guitar distortion or such) while generator can be a softsynth, beatbox or something similar. Both have to naturally run precisely in-sync. While minimizing the latency from input to output is crucial for playing and has to run in-sync with all the rest of the softsynths. Playing a piano with couple of notes lag before you hear the sound is annoying... - Jussi ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
On Thu, Jun 18, 2009 at 12:21 PM, Lennart Poettering wrote: > > > This is a bit more complex than you might think. Jack's thread > management is very unflexible and insists on controlling the entire > thread life cycle, only calling into client code in very few > occasions. You might want to check out the more recent API additions: jack_cycle_wait() jack_cycle_signal() which were created for precisely the sort of reasons you are describing. > > Of course it would great if JACK would be more flexible with its RT > loop handling. What I am missing is basically a way to > asynchronously/lock-free trigger execution of a callback function in > the RT loop at a suitable place. By a "suitable place" I mean that the > RT loop delays execution of this callback until a time where its > impact would be minimal, i.e. right after a completed process() and a > quick verification that the next process() cycle is still a bit away. e.g. right after jack_cycle_signal() ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
On Thu, 18.06.09 13:51, Paul Davis (p...@linuxaudiosystems.com) wrote: > On Thu, Jun 18, 2009 at 12:21 PM, Lennart Poettering wrote: > > > > > > > This is a bit more complex than you might think. Jack's thread > > management is very unflexible and insists on controlling the entire > > thread life cycle, only calling into client code in very few > > occasions. > > > You might want to check out the more recent API additions: > > jack_cycle_wait() > jack_cycle_signal() > > which were created for precisely the sort of reasons you are describing. That sounds like it was what I need. So, how would I use this? I figure something like this: void* my_thread(void*arg) { for (;;) { n = jack_cycle_wait(client); process_my_data(n); jack_cycle_signal(client, 0); do_my_other_work_if_there_is_any(); } } jack_set_process_thread(client, foo_func); Is that the rough idea? Hmm, with the other RT loops I have in PA I usually just dispatch a single my own events and then immediately check the IO device again, possibly dealing with the IO stuff first, and only after finishing that I dispatch the next of my own events and immediately check for IO again. That way I make sure that IO always takes priority over dispatching those events. i.e. something along the lines of: void *my_thread(void *arg) { for (;;) { n = how_much_shall_i_process(); if (n > 0) { process_my_data(n); continue; } n = how_many_events_to_dispatch(); if (n > 0) { process_one_event(); continue; } wait_for_io(); } So, to map this to JACK, I would prefer if jack_cycle_wait() would also exist in a non-blocking variant. i.e. something that can return 0 if there's nothing to process, but doesn't necessarily wait. (we probably should stop the cross-posting, though) Lennart -- Lennart PoetteringRed Hat, Inc. lennart [at] poettering [dot] net http://0pointer.net/lennart/ GnuPG 0x1A015CC4 ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
On Thu, Jun 18, 2009 at 2:45 PM, Lennart Poettering wrote: > > So, how would I use this? I figure something like this: > > > void* my_thread(void*arg) { > for (;;) { > n = jack_cycle_wait(client); > process_my_data(n); > jack_cycle_signal(client, 0); > do_my_other_work_if_there_is_any(); > } > } yep. > So, to map this to JACK, I would prefer if jack_cycle_wait() would > also exist in a non-blocking variant. i.e. something that can return 0 > if there's nothing to process, but doesn't necessarily wait. that's not possible. the thread has to be ready to respond to the start of the JACK process cycle with RT-friendly timing. thats why "do_my_other_work_if_there_is_any()" is still under RT constraints *AND* needs to be designed knowing that it may be stealing processor time from other parts of the process cycle. you cannot just "dip into JACK and see if its time to process() - you must be ready for it when that time comes. > (we probably should stop the cross-posting, though) truncated to LAD. ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
On Thu, 18.06.09 20:12, Jussi Laako (ju...@sonarnerd.net) wrote: > > Lennart Poettering wrote: > > PA does not use fixed block sizes. We always use the largest chunk > > sizes the applications pass to us and break them up into smaller > > pieces only when really necessary. We really try our best not having > > to touch/convert/split/copy user supplied PCM data if we don't have > > to. > > This is quite different from the goals of JACK, where the purpose is to > minimize input -> output latency and thus use as small as possible blocks. Uh. No. That's bogus. If an application can send PA data in larger blocks then we are happy about it and take it. Of course, if the application needs low latencies then it shouldn't pass huge blocks to us, but instead many smaller ones. The block size the app chooses is entirely up to it, and it may actually set the size of every block differently at free will. The general rule for block sizes is to choose them as large as possible however, as small as necessary and. For example, When you play data from a file source the block size can safely be chosen very large, while at the same time DSP data that is passed through needs much smaller block sizes. In PA I generally try to cater both for lower latencies and for minimal CPU usage/wakeups. How to choose buffer sizes highly depends on the application accessing PA so we do our best to dynamically adjust to it and try to accept whatever the apps give us. Even when that means that one app passes us huge blocks while another one passes us small ones at the same time. The big difference between JACK and PA here is that in JACK the transfer of data is mostly done synchronously while in PA we do that asynchronously. Which is the case because we need to make sure that no misbheaving client can easily trigger dropouts or even make audio stop entirely -- which is something much less important for JACK. Lennart -- Lennart PoetteringRed Hat, Inc. lennart [at] poettering [dot] net http://0pointer.net/lennart/ GnuPG 0x1A015CC4 ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
On Thu, 18.06.09 14:49, Paul Davis (p...@linuxaudiosystems.com) wrote: > > So, to map this to JACK, I would prefer if jack_cycle_wait() would > > also exist in a non-blocking variant. i.e. something that can return 0 > > if there's nothing to process, but doesn't necessarily wait. > > that's not possible. the thread has to be ready to respond to the > start of the JACK process cycle with RT-friendly timing. > thats why "do_my_other_work_if_there_is_any()" is still under RT > constraints *AND* needs to be designed knowing that > it may be stealing processor time from other parts of the process > cycle. In PA's ALSA module we use snd_pcm_avail() for this: only if it is below a certain threshold we process those private events. If it is not, then we go back to IO directly, assuming that it is too risky trying to dispatch another event. On Jack we have jack_frames_since_cycle_start(), would it be considered an ugly hack if I use that to implement a similar logic? for (;;) { n = jack_client_wait() process(n); jack_cycle_signal(); while (jack_frames_since_cycle_start() < threshold) process_one_of_my_private_event(); } Just ugly? Or *too* ugly? Is jack_frames_since_cycle_start() costly? Lennart -- Lennart PoetteringRed Hat, Inc. lennart [at] poettering [dot] net http://0pointer.net/lennart/ GnuPG 0x1A015CC4 ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
Lennart Poettering wrote: > If an application can send PA data in larger blocks then we are happy > about it and take it. Of course, if the application needs low > latencies then it shouldn't pass huge blocks to us, but instead many No, generally data needs to be fed _to_ application immediately when it becomes available after A/D conversion (PCI DMA completion interrupt). Application(s) process the data and it is ought to go to D/A conversion on next hardware interrupt (PCI DMA reprogram interrupt), along with time-synchronous data from other applications. This creates total latency of inputhw+blocksize+outputhw. Generally input and output latencies should be around few tens of samples (due to delta-sigma converter resampling filters etc). And generally blocksize is also kept around 64 or so. > The big difference between JACK and PA here is that in JACK the > transfer of data is mostly done synchronously while in PA we do that > asynchronously. Which is the case because we need to make sure that no Yes, and this is because all applications are ought to work in harmony as a whole construct, just like a symphony orchestra, following the pace set by conductor. - Jussi ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
On Thu, 18.06.09 23:27, Jussi Laako (ju...@sonarnerd.net) wrote: > > Lennart Poettering wrote: > > If an application can send PA data in larger blocks then we are happy > > about it and take it. Of course, if the application needs low > > latencies then it shouldn't pass huge blocks to us, but instead many > > No, generally data needs to be fed _to_ application immediately when it > becomes available after A/D conversion (PCI DMA completion interrupt). > Application(s) process the data and it is ought to go to D/A conversion > on next hardware interrupt (PCI DMA reprogram interrupt), along with > time-synchronous data from other applications. This creates total > latency of inputhw+blocksize+outputhw. Generally input and output > latencies should be around few tens of samples (due to delta-sigma > converter resampling filters etc). And generally blocksize is also kept > around 64 or so. Yeah? And this matters how to PA? Lennart -- Lennart PoetteringRed Hat, Inc. lennart [at] poettering [dot] net http://0pointer.net/lennart/ GnuPG 0x1A015CC4 ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
Hi, On 18.06.2009, at 22:27, Jussi Laako wrote: > No, generally data needs to be fed _to_ application immediately when > it > becomes available after A/D conversion (PCI DMA completion interrupt). > Application(s) process the data and it is ought to go to D/A > conversion > on next hardware interrupt (PCI DMA reprogram interrupt), along with > time-synchronous data from other applications. This creates total > latency of inputhw+blocksize+outputhw. Generally input and output > latencies should be around few tens of samples (due to delta-sigma > converter resampling filters etc). And generally blocksize is also > kept > around 64 or so. > I think this is incorrect. The total latency should be inputhw +2*blocksize+outputhw. At timeoffset 0 the soundcard will start to capture samples. Until the first sample makes it into the buffer there is a delay of inputhw (A/ D, transfer etc). You can't access the buffer until at least blocksize samples have been captured. So the first buffer switch takes place at timeoffset inputhw + blocksize. Now you do your processing. No matter how fast you can do that you'll have to wait until the next buffer switch will take place, which will happen at timeoffset inputhw + blocksize + blocksize. Transfer + D/A will add outputhw to the mix and you end out with the first sample at your speakers at timeoffset inputhw + blocksize + blocksize + outputhw. Best, Florian ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
On Thu, Jun 18, 2009 at 3:12 PM, Lennart Poettering wrote: > > On Jack we have jack_frames_since_cycle_start(), would it be > considered an ugly hack if I use that to implement a similar logic? > > for (;;) { > n = jack_client_wait() > process(n); > jack_cycle_signal(); > while (jack_frames_since_cycle_start() < threshold) > process_one_of_my_private_event(); > } > > Just ugly? Or *too* ugly? Is jack_frames_since_cycle_start() costly? Its (a) ugly (b) illegal - frames_since_cycle_start() is legal only within the process() cycle but your code is not bounded by it (c) fundamentally incompatible with basic RT programming. You're in a thread which is competing for cycles with other JACK client threads, and up against the deadline of the next cycle. I don't see any reason why you cannot do what every other app that is fundamentally not interested in real time does: put all your normal code behind a ringbuffer, and just have your jack process cycle pull/push from/to the ringbuffer. the closest example i've seen to what you seem to want to do is something which does FFT on the incoming signal. FFT has a certain window size, and its costly in cycles, so you either cause spikes in the RT load periodically (every time there is enough data to process - assuming you're not using a sliding window) or you push the FFT out to another thread and make the RT thread simply notify the FFT thread that there is more data available. ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
On Thu, 18.06.09 17:41, Paul Davis (p...@linuxaudiosystems.com) wrote: > > On Thu, Jun 18, 2009 at 3:12 PM, Lennart Poettering wrote: > > > > On Jack we have jack_frames_since_cycle_start(), would it be > > considered an ugly hack if I use that to implement a similar logic? > > > > for (;;) { > > n = jack_client_wait() > > process(n); > > jack_cycle_signal(); > > while (jack_frames_since_cycle_start() < threshold) > > process_one_of_my_private_event(); > > } > > > > Just ugly? Or *too* ugly? Is jack_frames_since_cycle_start() costly? > > Its (a) ugly (b) illegal - frames_since_cycle_start() is legal only > within the process() cycle but your code is not bounded by it (c) > fundamentally incompatible with basic RT programming. You're in a > thread which is competing for cycles with other JACK client threads, > and up against the deadline of the next cycle. "Basic RT programming". Uh? I mean, seriously, you can do RT on many levels. I mean, when developing JACK you don't do real CPU cycle counting, do you? Or do you really verify the influences of the cache on your RT code? No, you don't. Wouldn't make much sense anyway. So you still have a lot variables in the whole thing. And that is fine that way, this is after all very soft RT. And that's true for PA certainly even more than JACK. For example, PA doesn't lock itself into memory because most of the time it is just one process among many and we cannot afford taking away all that many from all other processes. Now, the closest thing that comes to counting CPU cycles is counting actual time. Which the code I suggested above does. After all our deadlines are based on time, not CPU cycles. So what makes more sense than actually taking up a tiny bit of CPU time -- up to a specific worst case limit as protection -- if there is something to do? Please understand that the events that are dispatched there are not CPU intensive in any way, and only *very seldomly* actually triggered. Usually it's just adding an entry to a hash table here, removing an entry from a list there, or doing other data structure work that is quick and takes constant or O(log(N)) and very few data accesses. Having that time limit there like I proposed is mostly just a protection against dispatching too many events at once, in the unlikely event that we get more than a handful queued up. In almost all iterartions of the RT loop we'll have exactly 0 queued up. Regarding competing with other clients or deadlines, this is really just a matter of picking the right threshold. That threshold is after all just a boundary for the worst case, in almost all cycles we'll not even iterate around it once. > I don't see any reason why you cannot do what every other app that is > fundamentally not interested in real time does: put all your normal > code behind a ringbuffer, and just have your jack process cycle > pull/push from/to the ringbuffer. This is basically what happens. However in PA we are much more dynamic than JACK generally is. JACK clients generally just have a single stream of PCM data which is passed between the RT and the non-RT threads. However, PA is not as simple as that. We have streams coming and going all the time, our control data changes. That's why we need to change our internal pipeline and other shared meta data often while streaming. In JACK the answer to pipeline changes is considering them something that doesn't normally happen and when it happens then drop-outs are fine. That doesn't really work for PA. If we'd drop out each time someone triggeres a stupid event sound to be played then uh, that would make people very unhappy. So, in PA that line is blurred and we do change our pipeline while streaming, which means communication between the control and the RT threads needs to go beyond simple passing of PCM data. We need to be able to make changes to the control stuff too. And some of that we do in asynchronous fashion, by asynchronously triggering something in the RT loop to be executed when the RT loop thinks it's a good time and verified that a bit of is timeslace is available. Lennart -- Lennart PoetteringRed Hat, Inc. lennart [at] poettering [dot] net http://0pointer.net/lennart/ GnuPG 0x1A015CC4 ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
Lennart Poettering wrote: > Yeah? And this matters how to PA? Only in a way as I said, goals of JACK and PA are different, they try to solve different problem and naturally use different means to achieve these goals. - Jussi ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
On Fri, 19.06.09 01:56, Jussi Laako (ju...@sonarnerd.net) wrote: > > Lennart Poettering wrote: > > Yeah? And this matters how to PA? > > Only in a way as I said, goals of JACK and PA are different, they try to > solve different problem and naturally use different means to achieve > these goals. This is absolutely true. Lennart -- Lennart PoetteringRed Hat, Inc. lennart [at] poettering [dot] net http://0pointer.net/lennart/ GnuPG 0x1A015CC4 ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
Florian Schirmer wrote: > I think this is incorrect. The total latency should be inputhw > +2*blocksize+outputhw. Ahh, yes, sure. I seem to be a bit tired today... And most of the time there's just one interrupt which can be thought as "buffer switch" interrupt. Unless there are two different cards running out of same word clock (slightly problematic case anyway). Thus even more important to keep blocksize as small as possible... - Jussi ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
On Fri, Jun 19, 2009 at 12:33:24AM +0200, Lennart Poettering wrote: > This is basically what happens. However in PA we are much more dynamic > than JACK generally is. JACK clients generally just have a single > stream of PCM data which is passed between the RT and the non-RT > threads. However, PA is not as simple as that. We have streams coming > and going all the time, our control data changes. That's why we need > to change our internal pipeline and other shared meta data often while > streaming. In JACK the answer to pipeline changes is considering them > something that doesn't normally happen and when it happens then > drop-outs are fine. That doesn't really work for PA. If we'd drop out > each time someone triggeres a stupid event sound to be played then uh, > that would make people very unhappy. So, in PA that line is blurred > and we do change our pipeline while streaming, which means > communication between the control and the RT threads needs to go > beyond simple passing of PCM data. We need to be able to make changes > to the control stuff too. And some of that we do in asynchronous > fashion, by asynchronously triggering something in the RT loop to be > executed when the RT loop thinks it's a good time and verified that a > bit of is timeslace is available. What I don't understand is this: - You wait, e.g. using frames_since_cycle_start(), until near the end of the current period, then give up if nothing wants your attention. - Since it has to be 'until near the end' and not 'exactly the end', this doesn't exclude that some event could still happen within the current period but after you stopped waiting for it. - Such an event then has to be handled in the next period. If this is acceptable, why wouldn't it be acceptable for things that happened just a bit earlier ? Which would mean you could afford to wait less. - In the limit you don't have to wait at all after the normal callbackk processing has been done, everything that happens later will be dealt with in the next period. Jack periods are rarely > 1024 samples. What am I missing ? Ciao, -- FA Io lo dico sempre: l'Italia è troppo stretta e lunga. ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
On Fri, 19.06.09 01:23, Fons Adriaensen (f...@kokkinizita.net) wrote: > > On Fri, Jun 19, 2009 at 12:33:24AM +0200, Lennart Poettering wrote: > > > This is basically what happens. However in PA we are much more dynamic > > than JACK generally is. JACK clients generally just have a single > > stream of PCM data which is passed between the RT and the non-RT > > threads. However, PA is not as simple as that. We have streams coming > > and going all the time, our control data changes. That's why we need > > to change our internal pipeline and other shared meta data often while > > streaming. In JACK the answer to pipeline changes is considering them > > something that doesn't normally happen and when it happens then > > drop-outs are fine. That doesn't really work for PA. If we'd drop out > > each time someone triggeres a stupid event sound to be played then uh, > > that would make people very unhappy. So, in PA that line is blurred > > and we do change our pipeline while streaming, which means > > communication between the control and the RT threads needs to go > > beyond simple passing of PCM data. We need to be able to make changes > > to the control stuff too. And some of that we do in asynchronous > > fashion, by asynchronously triggering something in the RT loop to be > > executed when the RT loop thinks it's a good time and verified that a > > bit of is timeslace is available. > > What I don't understand is this: > > - You wait, e.g. using frames_since_cycle_start(), until near the > end of the current period, then give up if nothing wants your > attention. No. I don't "wait" and not for the end of the current period. All I do is set a maximum limit to how much non-IO work I do in the RT loop per iteration. Uh, I actually admit that the pseudocode I posted in http://lists.linuxaudio.org/pipermail/linux-audio-dev/2009-June/023380.html is completely broken. Sorry for the confusion. The one I was describing down on http://lists.linuxaudio.org/pipermail/linux-audio-dev/2009-June/023370.html was correct. So, another try: for (;;) { n = jack_client_wait() process(n); jack_cycle_signal(); while (jack_frames_since_cycle_start() < threshold) { if (no_private_events_to_process()) break; process_one_of_my_private_events(); } } The early exit in the inner loop when there's nothing to do (which is the usual case) is the key point here, I guess. Sorry for the confusion. Lennart -- Lennart PoetteringRed Hat, Inc. lennart [at] poettering [dot] net http://0pointer.net/lennart/ GnuPG 0x1A015CC4 ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
On Thu, Jun 18, 2009 at 7:43 PM, Lennart Poettering wrote: > > > for (;;) { > n = jack_client_wait() > process(n); > jack_cycle_signal(); > while (jack_frames_since_cycle_start() < threshold) { > if (no_private_events_to_process()) > break; > process_one_of_my_private_events(); > } > } > how is this functionally different than adding 1 period of latency to every event, then processing every event marked to occur during a given process cycle *within* that process cycle? this is precisely what happens with MIDI and OSC sequencing. i.e: now = 0; for (;;) { n = jack_cycle_wait (); while (events_to_process (now, now+n)) { process_event (); } process_data (); now += n; jack_cycle_signal (); } as i mentioned, this is fundamentally what any MIDI sequencer that uses JACK MIDI is doing. the latency of the event is fixed, and there is close to zero jitter. no "waiting after", no potential stealing of cycles outside the process cycle, no scheduling issues. ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
On Thu, 18.06.09 19:57, Paul Davis (p...@linuxaudiosystems.com) wrote: > > On Thu, Jun 18, 2009 at 7:43 PM, Lennart Poettering wrote: > > > > > > for (;;) { > > n = jack_client_wait() > > process(n); > > jack_cycle_signal(); > > while (jack_frames_since_cycle_start() < threshold) { > > if (no_private_events_to_process()) > > break; > > process_one_of_my_private_events(); > > } > > } > > > > how is this functionally different than adding 1 period of latency > to every event, then processing every event marked to occur during a > given process cycle *within* that process cycle? My events are not time critical. As long as they are dispatched, it doesn't matter if they are dispatched now or 5ms later. Doing IO should take priority over processing them. Then, generally I think it is a good idea to signal the other threads as quickly as possibly after having finished with the processing IO. While that probably doesn't matter that much if we only have one CPU and our thread is RT, this actually does make a difference on SMP, i.e. practically all modern CPUs sold today. > this is precisely what happens with MIDI and OSC sequencing. i.e: > > now = 0; > for (;;) { > n = jack_cycle_wait (); > while (events_to_process (now, now+n)) { >process_event (); > } > process_data (); > now += n; > jack_cycle_signal (); > } > > as i mentioned, this is fundamentally what any MIDI sequencer that > uses JACK MIDI is doing. the latency of the event is fixed, and there > is close to zero jitter. > > no "waiting after", no potential stealing of cycles outside the > process cycle, no scheduling issues. But for MIDI time is critical. For my control events it is not. That's why I'd like to handle them after the _signal() invocation. Lennart -- Lennart PoetteringRed Hat, Inc. lennart [at] poettering [dot] net http://0pointer.net/lennart/ GnuPG 0x1A015CC4 ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
On Thu, Jun 18, 2009 at 8:27 PM, Lennart Poettering wrote: > > But for MIDI time is critical. For my control events it is not. That's > why I'd like to handle them after the _signal() invocation. fair enough, but you definitely cannot use jack_frames_since_cycle_start() there. there is no guarantee that you will avoid retrograde values in return value - if you happen to overshoot the start of the next cycle, the return value will go backwards. as mentioned the functioned was designed under the assumption that is only ever called within the process cycle, so using it outside of it (even if from some perspective, it is still active) is going to lead to potential errors. i still think you'd be better off semop-ing another thread and letting it get on with the event handling, and just head back into jack_cycle_wait(). --p ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
> > No. I don't "wait" and not for the end of the current period. All I do > is set a maximum limit to how much non-IO work I do in the RT loop per > iteration. > > Uh, I actually admit that the pseudocode I posted in > http://lists.linuxaudio.org/pipermail/linux-audio-dev/2009-June/ > 023380.html > > is completely broken. Sorry for the confusion. The one I was > describing down on > > http://lists.linuxaudio.org/pipermail/linux-audio-dev/2009-June/ > 023370.html > > was correct. > > So, another try: > > > for (;;) { > n = jack_client_wait() > process(n); > jack_cycle_signal(); > while (jack_frames_since_cycle_start() < threshold) { > if (no_private_events_to_process()) > break; > process_one_of_my_private_events(); > } > } > > > The early exit in the inner loop when there's nothing to do (which is > the usual case) is the key point here, I guess. > > Sorry for the confusion. > > Lennart > > -- > Lennart PoetteringRed Hat, Inc. > lennart [at] poettering [dot] net > http://0pointer.net/lennart/ GnuPG 0x1A015CC4 > ___ > Linux-audio-dev mailing list > Linux-audio-dev@lists.linuxaudio.org > http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev But why using a "timing" condition to know about "how much of this event dispacthing" is going to be done? Would it make sense to just process up to a specified number of "waiting" events? So basically if events are waiting *now*, you process some of them, and the one coming between now and the end of the cycle would be processed next cycle. , for (;;) { n = jack_cycle_wait(); process(n); jack_cycle_signal(); process_SOME_of_my_private_events(E); } Stephane ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
On Fri, Jun 19, 2009 at 08:45:12AM +0200, Stéphane Letz wrote: > > > > > No. I don't "wait" and not for the end of the current period. All I do > > is set a maximum limit to how much non-IO work I do in the RT loop per > > iteration. > > > > Uh, I actually admit that the pseudocode I posted in > > http://lists.linuxaudio.org/pipermail/linux-audio-dev/2009-June/ > > 023380.html > > > > is completely broken. Sorry for the confusion. The one I was > > describing down on > > > > http://lists.linuxaudio.org/pipermail/linux-audio-dev/2009-June/ > > 023370.html > > > > was correct. > > > > So, another try: > > > > > > for (;;) { > > n = jack_client_wait() > > process(n); > > jack_cycle_signal(); > > while (jack_frames_since_cycle_start() < threshold) { > > if (no_private_events_to_process()) > > break; > > process_one_of_my_private_events(); > > } > > } > > > > > > The early exit in the inner loop when there's nothing to do (which is > > the usual case) is the key point here, I guess. > > > > Sorry for the confusion. this discussion seems to go away from the real issue to implementation details of pa. however the deeper i read into stuff which is being called, the more malloc and mutex_lock() i see. even with jack_cycle_signal we are having a thread, which is running at the same priority as other jack threads, so it still has a certein potential to choke the other jack clients. first of all lets assume jack is running with -p64 -n2 (~3ms latency) i am not sure if lennart is aware that jack often runs with such latencies. i dont really care for event processing inside the RT loop. however you cant know how many clients are following in the process cycle, so you cant know a sane threshold value. what i am asking for is that events are either passed into your RT loop via lock-free fifos, or you decouple your soft-RT stuff from jacks RT stuff, which is not as soft as you think. at least nobody is creating semaphores in jack_process code. if you insist on soft-RT behaviour, just decouple and do what you want. > > > > Lennart > > > > -- > > Lennart PoetteringRed Hat, Inc. > > lennart [at] poettering [dot] net > > http://0pointer.net/lennart/ GnuPG 0x1A015CC4 > > ___ > > Linux-audio-dev mailing list > > Linux-audio-dev@lists.linuxaudio.org > > http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev > > But why using a "timing" condition to know about "how much of this > event dispacthing" is going to be done? > > Would it make sense to just process up to a specified number of > "waiting" events? So basically if events are waiting *now*, you > process some of them, and the one coming between now and the end of > the cycle would be processed next cycle. > > , for (;;) { > n = jack_cycle_wait(); > process(n); > jack_cycle_signal(); > process_SOME_of_my_private_events(E); > } > > > > Stephane > ___ > Linux-audio-dev mailing list > Linux-audio-dev@lists.linuxaudio.org > http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev -- torben Hohn http://galan.sourceforge.net -- The graphical Audio language ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
On Fri, 19.06.09 08:45, Stéphane Letz (l...@grame.fr) wrote: > But why using a "timing" condition to know about "how much of this event > dispacthing" is going to be done? Because in the end it's a time deadline we need to fulfill. > Would it make sense to just process up to a specified number of > "waiting" events? So basically if events are waiting *now*, you process > some of them, and the one coming between now and the end of the cycle > would be processed next cycle. Sure, but how do you define "some"? What is to define "some" based on time, since that's what the deadline is about in the end. Lennart -- Lennart PoetteringRed Hat, Inc. lennart [at] poettering [dot] net http://0pointer.net/lennart/ GnuPG 0x1A015CC4 ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
On Fri, 19.06.09 14:31, torb...@gmx.de (torb...@gmx.de) wrote: > > > > > > for (;;) { > > > n = jack_client_wait() > > > process(n); > > > jack_cycle_signal(); > > > while (jack_frames_since_cycle_start() < threshold) { > > > if (no_private_events_to_process()) > > > break; > > > process_one_of_my_private_events(); > > > } > > > } > > > > > > > > > The early exit in the inner loop when there's nothing to do (which is > > > the usual case) is the key point here, I guess. > > > > > > Sorry for the confusion. > > this discussion seems to go away from the real issue to implementation > details of pa. > however the deeper i read into stuff which is being called, the more > malloc and mutex_lock() i see. We use mutexes at some places and malloc at quite a few too. However, those are confined to the non-RT threads, with very few exceptions. Those exceptions usually are irrelevant for the RT case however. e.g. the writer side of our lock-free async queue actually takes a lock. Which however doesn't matter, since that's simply there to make a single-reader-single-writer queue useful for multiple writers -- it simply protects writers against each other, it's not a lock that is shared with the reader side. Now, since we allocate a seperate queue for each of our RT cases this lock in the end will never block, because there is noone else this could block against. The only reason we have this lock there is that this queue is used at various places, and for some having multi-writer queues is really useful. At least on Linux taking an uncontended lock is relatively cheap and doesn't even need a change to kernel mode. Regarding malloc(): preallocating and locking memory is not really an option for the usual PA use case: we simply cannot afford taking away all that memory from other processes all the time, since PA is just process among many on most setups. As a compromise PA uses lock-free free lists for all data that is allocated from the RT threads, in the hope we seldomly have to actually ask for memory, and in the hope to keep the memory we already allocated "hot". PA and JACK have different purposes. PA is not a textbook RT application. Far from that. We have to make compromises at many places where JACK doesn't have to. After all, on a desktop (and even more on embedded devices), PA is there to handle 'just' audio which is just something among a lot of other stuff fighting for resources. OTOH on a pro audio workstation JACK is at the center of everything, and the resources available are available only and exclusively for the use of audio applications. I mean, I am not saying PA had a flawless design, it certainly hasn't. But uh, maybe LAD is not the place to discuss those. And I think I have quite good reasons for most compromises I made. > even with jack_cycle_signal we are having a thread, which is running at > the same priority as other jack threads, so it still has a certein > potential to choke the other jack clients. Sure, but doing those things after _signal() is still better than before _signal(). > first of all lets assume jack is running with -p64 -n2 > (~3ms latency) > > i am not sure if lennart is aware that jack often runs with such > latencies. i dont really care for event processing inside the RT loop. > however you cant know how many clients are following in the process > cycle, so you cant know a sane threshold value. But that information could be made available, couldn't it? I mean, the Jack server has information about the graph, so it could make that information available to the clients. > what i am asking for is that events are either passed into your RT loop > via lock-free fifos As mentioned, this is what happens. that lock-free q is called pa_asyncmsgq. Lennart -- Lennart PoetteringRed Hat, Inc. lennart [at] poettering [dot] net http://0pointer.net/lennart/ GnuPG 0x1A015CC4 ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
> >> first of all lets assume jack is running with -p64 -n2 >> (~3ms latency) >> >> i am not sure if lennart is aware that jack often runs with such >> latencies. i dont really care for event processing inside the RT >> loop. >> however you cant know how many clients are following in the process >> cycle, so you cant know a sane threshold value. > > But that information could be made available, couldn't it? I mean, the > Jack server has information about the graph, so it could make that > information available to the clients. Hum...even if this info would be available, it does not say what *actual* duration would take the following clients ... > >> what i am asking for is that events are either passed into your RT >> loop >> via lock-free fifos > > As mentioned, this is what happens. that lock-free q is called > pa_asyncmsgq. > > Lennart > I think we should go back to the beginning of the discussion: allow PA based audio desktop application be used in the JACK graph. It don't think it make sense to over-complexify JACK or JACK/PA interaction just to avoid a thread context switch. Better keep the current separated simple solution, until it can be proven it is a real bottleneck. Stephane ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
On Fri, 19.06.09 15:59, Stéphane Letz (l...@grame.fr) wrote: > >> >>> first of all lets assume jack is running with -p64 -n2 >>> (~3ms latency) >>> >>> i am not sure if lennart is aware that jack often runs with such >>> latencies. i dont really care for event processing inside the RT >>> loop. >>> however you cant know how many clients are following in the process >>> cycle, so you cant know a sane threshold value. >> >> But that information could be made available, couldn't it? I mean, the >> Jack server has information about the graph, so it could make that >> information available to the clients. > > Hum...even if this info would be available, it does not say what > *actual* duration would take the following clients ... That doesn't matter. Everything that is needed is an upper boundary. > Better keep the current separated simple solution, until it can be > proven it is a real bottleneck. I guess I can agree to that. Lennart -- Lennart PoetteringRed Hat, Inc. lennart [at] poettering [dot] net http://0pointer.net/lennart/ GnuPG 0x1A015CC4 ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
On Fri, Jun 19, 2009 at 04:12:32PM +0200, Lennart Poettering wrote: > On Fri, 19.06.09 15:59, Stéphane Letz (l...@grame.fr) wrote: > > > > >> > >>> first of all lets assume jack is running with -p64 -n2 > >>> (~3ms latency) > >>> > >>> i am not sure if lennart is aware that jack often runs with such > >>> latencies. i dont really care for event processing inside the RT > >>> loop. > >>> however you cant know how many clients are following in the process > >>> cycle, so you cant know a sane threshold value. > >> > >> But that information could be made available, couldn't it? I mean, the > >> Jack server has information about the graph, so it could make that > >> information available to the clients. > > > > Hum...even if this info would be available, it does not say what > > *actual* duration would take the following clients ... > > That doesn't matter. Everything that is needed is an upper boundary. > > > Better keep the current separated simple solution, until it can be > > proven it is a real bottleneck. > > I guess I can agree to that. oh well... i guess i shut up. maybe you can find out yourself why pulseaudio wants to connect to midi-ports. maybe my intial mail was too offensive, whatever. i apologise for reading your code. > > Lennart > > -- > Lennart PoetteringRed Hat, Inc. > lennart [at] poettering [dot] net > http://0pointer.net/lennart/ GnuPG 0x1A015CC4 > ___ > Linux-audio-dev mailing list > Linux-audio-dev@lists.linuxaudio.org > http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev -- torben Hohn http://galan.sourceforge.net -- The graphical Audio language ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Re: [LAD] [Jack-Devel] jack2's dbus name
Lennart Poettering writes: > On Thu, 18.06.09 16:09, torb...@gmx.de (torb...@gmx.de) wrote: > >> > I think org.jackaudio.service should be fine. I don't think this >> > automatic logic needs to work on non-D-Bus jack builds. As I see it >> > you don't need to make any changes on jack for this to work. All I >> > need is the guarantee that by the time the service name is registered >> > on the bus jack is fully accessible. Otherwise we had a race here: if >> > PA looks for the org.jackaudio.service name to appear on the bus and >> > then imemdiately connects to it while jack isn't fully accessible yet >> > PA would fail. >> >> the existence of org.jackaudio.service object does not guarantee, >> that jackd is connectable. > > I'd consider that brokeness in Jack then. Taking the name on the bus > sould be the last step during initialization. Otherwise you'll always > be in racy situations where clients try to talk to JACK while JACK is > only half-way initialized. I'd like to clarify something, org.jackaudio.service exposes the controller object. It is not the server, it is the controller, a peristent endpoint that can be used to start and stop the server on user request. jack clients are usually not supposed to check whether jack server is started. It will be either autostarted or libjack "initialization" will fail if autostart is disabled and jack server is stopped. The dbus object name that is used for cooperation with PA is different thing. -- Nedko Arnaudov pgpYvuq5rBqbJ.pgp Description: PGP signature ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev