<html dir="ltr"><head></head><body style="text-align:left; direction:ltr;"><div>I am only writing for Jack2: I absolutely need to be able to "plug and unplug" jack clients while audio is running. </div><div>However, I decided to use spin-locks to make sure my jack_port_id queue is write concurrent safe. That seemed like a good compromise, considering how little time the locks are held, and that the hold time is deterministic.</div><div><br></div><div>I am porting a radio automation system I originally wrote of OS X/Core Audio. I made design decision to make all the media players and recorders/encoders there own processes that connect to the mixer-core via jack. So jack connections are being made to the mixer and then removed periodically, and that needs to happen without audio drop-out. So far, working well.</div><div><br></div><div>The recorder/encoder process, which I am working on right now, needs to be optionally able to reconnect to the mixer, or a processing chain connected to the mixer if it goes away and is restarted. That is what this was all about.</div><div><br></div><div>I will likely give the core mixer/control program similar persistent functionality next.</div><div><br></div><div>Thanks,</div><div>Ethan...</div><div><br></div><div><br></div><div><br></div><div>On Fri, 2019-08-09 at 14:50 -0400, Tim wrote:</div><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><pre>On 8/9/19 12:01 PM, Ethan Funk wrote:</pre><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><pre>Yes, what you describe is what I am implementing. I have also called it </pre><pre>"persistence" in my application. Normally, when all audio ports are </pre><pre>disconnected, my application quits. But I have an command line option to </pre><pre>keep it running and have it "persist," not quit, try to reconnect.</pre></blockquote><pre><br></pre><pre>I took it one step further and the 'persistence' is stored in the</pre><pre> song file so that the next time the song is loaded, MusE does not</pre><pre> complain that this or that is missing and will be removed, instead</pre><pre> it simply chugs along happily and when the device reappears,</pre><pre> everything works as before.</pre><pre><br></pre><pre>I have slowly adopted a policy of "nothing is removed from a song</pre><pre> behind the user's back unless they specifically say so, even if it</pre><pre> is ultimately missing some component, such as a port is missing</pre><pre> or a plugin is missing on the system".</pre><pre>Thus, persistent... everything! across sessions is the goal.</pre><pre><br></pre><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><pre>I just implemented a simple queue of jack_port_ids. Callbacks add their </pre><pre>relevant port_ids into the queue, with my main thread checking the queue </pre><pre>periodically, to further check the queued ports for re-connection. This </pre><pre>was not as hard as I though it would be, and works well so far. Just </pre><pre>queueing the port id is a lot simpler that what you are doing in MusE, </pre><pre>but it is sufficient for my application.</pre></blockquote><pre><br></pre><pre>Yes, as you might see, I actually store a few callback types in our</pre><pre> callback queue and I must 'review' the queue when something happens</pre><pre> to carefully determine what exactly took place, for example</pre><pre> did a port disconnection happen before an unregistration or</pre><pre> was it an unregistration alone, etc.</pre><pre>It was tricky. Those port ID functions sure help though.</pre><pre><br></pre><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><pre>One remaining question: Am I safe assuming that jack2 will call my </pre><pre>callbacks one at a time from a single thread, or do I need to make my </pre><pre>port id queue writing function thread safe, just in case jack2 calls my </pre><pre>callbacks concurrently?</pre></blockquote><pre><br></pre><pre>Don't quote me, I might be getting this wrong, if I recall correctly ;-)</pre><pre>Jack 1 issues all callbacks in the realtime audio thread.</pre><pre>Jack 2 issues some important callbacks, such as the Sync callback,</pre><pre> in the realtime audio thread, but most other callbacks are</pre><pre> issued in ONE separate thread.</pre><pre>Therefore I don't think it could call them concurrently,</pre><pre> but I'm not an expert here...</pre><pre>I think our queue is multi-writer anyway so I probably might not</pre><pre> have noticed if they were concurrent, but I don't think I</pre><pre> noticed anything unusual.</pre><pre><br></pre><pre>Tim.</pre><pre><br></pre><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><pre><br></pre><pre>Ethan...</pre><pre><br></pre><pre>On Fri, 2019-08-09 at 01:52 -0400, Tim wrote:</pre><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><pre>On 8/8/19 10:20 PM, Ethan Funk wrote:</pre><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><pre>In an application I am writing, I am getting an error message out stderr</pre><pre>(see email subject), and a connection failure return result, when I try</pre><pre>to use jack_connect() from inside a jack_set_port_registration_callback</pre><pre>function, using Jack2. My goal is to have the application remember and</pre><pre>re-connect to a disconnected port if/when it "comes back." Am I going to</pre><pre>need to create a mostly sleeping thread just for port re-connections</pre><pre>attempts, or is there something obvious I am missing?</pre><pre><br></pre><pre>Thanks,</pre><pre>Ethan...</pre></blockquote><pre><br></pre><pre>If I understand your goal, I did this in MusE.</pre><pre>I called it 'persistent connections', or 'persistent ports'.</pre><pre><br></pre><pre>For example you can unplug a USB midi device currently</pre><pre> in use by MusE as a 'Jack device', then re-plug it,</pre><pre> and MusE will automatically reconnect to its ports</pre><pre> as if nothing happened and you may continue playing.</pre><pre>(I made our 'ALSA devices' do the same thing!)</pre><pre>It should also work with other Jack clients.</pre><pre><br></pre><pre>Look in our driver/jack.cpp, at:</pre><pre> static void registration_callback(...),</pre><pre> static void port_connect_callback(...),</pre><pre> and</pre><pre> static int graph_callback(...),</pre><pre> // This is called in the gui context,</pre><pre> // triggered by graph_callback()</pre><pre> void JackAudioDevice::graphChanged().</pre><pre><br></pre><pre>It was complicated. Very. I needed to support Jack 1 and 2.</pre><pre>So there are a few sequences of calls and resulting</pre><pre> sequences of callbacks for example that are different</pre><pre> in Jack 1 and 2. Several tricks and traps. See comments.</pre><pre><br></pre><pre>My system relies HEAVILY on the jack port 'alias names',</pre><pre> because it was pretty much the ONLY thing you can rely on,</pre><pre> because the regular port names and port numbers change</pre><pre> upon re-plugging. It automatically chooses which alias is</pre><pre> best or falls back to the not so good canonical port name.</pre><pre><br></pre><pre>So, that's what it 'remembers' between device plug ins -</pre><pre> simply the port alias or name text.</pre><pre><br></pre><pre>HTH.</pre><pre>Tim.</pre><pre>_______________________________________________</pre><pre>Jack-Devel mailing list</pre><a href="mailto:Jack-Devel@lists.jackaudio.org"><pre>Jack-Devel@lists.jackaudio.org</pre></a><pre><br></pre><pre> <mailto:</pre><a href="mailto:Jack-Devel@lists.jackaudio.org"><pre>Jack-Devel@lists.jackaudio.org</pre></a><pre>></pre><pre><br></pre><a href="http://lists.jackaudio.org/listinfo.cgi/jack-devel-jackaudio.org"><pre>http://lists.jackaudio.org/listinfo.cgi/jack-devel-jackaudio.org</pre></a><pre><br></pre><pre><br></pre></blockquote></blockquote></blockquote></body></html>