[LAU] [PATCH] JACK 0.109.2 alsa device disconnect patch

From: Salvatore Di Pietro <salvuz_78@email-addr-hidden>
Date: Fri Mar 14 2008 - 17:32:48 EET

Hi all,
I just fitted Sean Meiners' alsa device disconnect patch for JACK 0.109.2.

It enables jackd to detach from the ALSA device, letting its use by
other non-JACK programs whilst in the middle of a jack session, without
closing jackd and its clients. IMHO very useful for i.e common builtin
laptop soundcards which don't support more than one alsa-direct audio
app at once (also commonly known as "no hardware mixing soundcards").

You get an additional example client: jack_device_connect (based on
jack_freewheel, its arguments are "y" or "n") which you use to make jack
release and re-hook to the audio card. Time is paused and all audio from
jack is of course muted and jackd and its client applications are put
into this fake-freewheel mode while jack has released the device; they
continue producing and consuming audio upon jackd re-attaching to the
audio device, with the command "jack_device_connect y".

The original version was for jack 0.100.0, I just modified it to make it
patch successfully on jack 0.109.2. I don't have so advanced programming
skills to understand its inner working, but from a quick read of the
code, for what I can understand, I saw it mainly adds some functions in
jackd (jack_device_disconnect() and jack_device_connect()in
jackd/engine.c) and libjack (jack_set_connected() in client.c,
jack_driver_nt_disconnect() and jack_driver_nt_connect() in driver.c) to
dis/connect to the alsa device.

I was asked on this list about the interaction of this patch with
realtime watchdogs. I didn't encounter any problem, they were never
triggered (and no crashes or weird things ;) ) as in normal operation,
because they enter this freewheeling-like mode.
I contacted Sean and asked him if it was this way, and he replied:

>As I remember, that's pretty much it. It puts jack into something like
>freewheel mode (so that jack clients don't freeze up). And then shuts
>down the alsa driver. As for the watchdog, I don't remember anything
>about that, but if I had to guess I'd say it's because jack is put
into >a fake-freewheel mode.

Hope it is useful to who wants to try it: just use

jack_device_connect n

and voila, you can watch youtube videos or use that strange non-jack
aware application you need in that moment, _without_ closing any jack
program.
When you're done, just use

jack_device_connect y

and enjoy all your JACK work just where you left it.

I should perhaps rename the jack_device_connect jack_alsa_connect...

Wanna try it?
Happy JACKing to all, ciao!

-- 
           salvuz
      POST FATA RESVRGO
  Linux registered user #291700 | machine #174619
  get counted on ---> http://counter.li.org/ <---

diff -Nur jack-audio-connection-kit-0.109.2/drivers/alsa/alsa_driver.c jack-audio-connection-kit-0.109.2-alsa-disconnect/drivers/alsa/alsa_driver.c
--- jack-audio-connection-kit-0.109.2/drivers/alsa/alsa_driver.c 2008-01-30 19:23:52.000000000 +0100
+++ jack-audio-connection-kit-0.109.2-alsa-disconnect/drivers/alsa/alsa_driver.c 2008-03-01 13:40:27.000000000 +0100
@@ -53,6 +53,8 @@
 /* Delay (in process calls) before jackd will report an xrun */
 #define XRUN_REPORT_DELAY 0
 
+static int alsa_driver_connect (alsa_driver_t *driver);
+
 static void
 alsa_driver_release_channel_dependent_memory (alsa_driver_t *driver)
 {
@@ -130,6 +132,7 @@
                 jack_error ("control hardware info \"%s\" (%s)",
                             driver->alsa_name_playback, snd_strerror (err));
                 snd_ctl_close (driver->ctl_handle);
+ driver->ctl_handle = 0;
         }
 
         driver->alsa_driver = strdup(snd_ctl_card_info_get_driver (card_info));
@@ -964,6 +967,9 @@
         snd_pcm_uframes_t poffset, pavail;
         channel_t chn;
 
+ if(!driver->connected)
+ return 0;
+
         driver->poll_last = 0;
         driver->poll_next = 0;
 
@@ -1092,6 +1098,8 @@
         /* silence all capture port buffers, because we might
            be entering offline mode.
         */
+ if (!driver->connected)
+ return 0;
 
         for (chn = 0, node = driver->capture_ports; node;
              node = jack_slist_next (node), chn++) {
@@ -1157,6 +1165,9 @@
         snd_pcm_status_t *status;
         int res;
 
+ if (!driver->connected)
+ return 0;
+
         snd_pcm_status_alloca(&status);
 
         if (driver->capture_handle) {
@@ -1198,6 +1209,9 @@
         jack_nframes_t buffer_frames =
                 driver->frames_per_cycle * driver->playback_nperiods;
 
+ if(!driver->connected)
+ return;
+
         for (chn = 0; chn < driver->playback_nchannels; chn++) {
                 if (bitset_contains (driver->channels_not_done, chn)) {
                         if (driver->silent[chn] < buffer_frames) {
@@ -1924,8 +1938,8 @@
 }
 #endif
 
-static void
-alsa_driver_delete (alsa_driver_t *driver)
+static int
+alsa_driver_disconnect (alsa_driver_t *driver)
 {
         JSList *node;
 
@@ -1945,7 +1959,7 @@
 
         if (driver->playback_handle) {
                 snd_pcm_close (driver->playback_handle);
- driver->capture_handle = 0;
+ driver->playback_handle = 0;
         }
         
         if (driver->capture_hw_params) {
@@ -1968,16 +1982,34 @@
                 driver->playback_sw_params = 0;
         }
 
+ if(driver->ctl_handle) {
+ snd_ctl_close(driver->ctl_handle);
+ driver->ctl_handle = 0;
+ }
+
         if (driver->pfd) {
                 free (driver->pfd);
+ driver->pfd = 0;
         }
-
+
         if (driver->hw) {
                 driver->hw->release (driver->hw);
                 driver->hw = 0;
         }
+
+ driver->connected = 0;
+
+ return 0;
+}
+
+static void
+alsa_driver_delete (alsa_driver_t *driver)
+{
+ alsa_driver_disconnect(driver);
+
         free(driver->alsa_name_playback);
         free(driver->alsa_name_capture);
+
         free(driver->alsa_driver);
 
         alsa_driver_release_channel_dependent_memory (driver);
@@ -2007,8 +2039,6 @@
                  alsa_midi_t *midi_driver
                  )
 {
- int err;
-
         alsa_driver_t *driver;
 
         printf ("creating alsa driver ... %s|%s|%" PRIu32 "|%" PRIu32
@@ -2036,6 +2066,8 @@
         driver->nt_start = (JackDriverNTStartFunction) alsa_driver_start;
         driver->nt_stop = (JackDriverNTStopFunction) alsa_driver_stop;
         driver->nt_run_cycle = (JackDriverNTRunCycleFunction) alsa_driver_run_cycle;
+ driver->nt_connect = (JackDriverNTConnectFunction) alsa_driver_connect;
+ driver->nt_disconnect = (JackDriverNTDisconnectFunction) alsa_driver_disconnect;
 
         driver->playback_handle = NULL;
         driver->capture_handle = NULL;
@@ -2095,11 +2127,47 @@
                 return NULL;
         }
 
- alsa_driver_hw_specific (driver, hw_monitoring, hw_metering);
+ alsa_driver_hw_specific (driver, driver->hw_monitoring, driver->hw_metering);
+
+ driver->alsa_name_playback = strdup (playback_alsa_device);
+ driver->alsa_name_capture = strdup (capture_alsa_device);
+
+ driver->name = strdup (name);
+
+ driver->playback = playing;
+ driver->capture = capturing;
+
+ driver->frames_per_cycle = frames_per_cycle;
+ driver->user_nperiods = user_nperiods;
+ driver->frame_rate = rate;
+
+ driver->client = client;
+
+ driver->connected = 0;
+
+ // if we don't connect now then the hardware capability detection bits won't
+ // get run before we're asked to register our ports. and if that happens
+ // our capture & playback port numbers will be 0 causing us to not register anything
+ // and that's bad.
+ if (alsa_driver_connect(driver) != 0) {
+ alsa_driver_delete (driver);
+ return NULL;
+ }
+
+ return (jack_driver_t *)driver;
+}
 
- if (playing) {
+static int
+alsa_driver_connect (alsa_driver_t *driver)
+{
+ int err;
+
+ if (driver->connected)
+ return 0;
+
+ if (driver->playback) {
                 if (snd_pcm_open (&driver->playback_handle,
- playback_alsa_device,
+ driver->alsa_name_playback,
                                   SND_PCM_STREAM_PLAYBACK,
                                   SND_PCM_NONBLOCK) < 0) {
                         switch (errno) {
@@ -2108,17 +2176,25 @@
                                             "already in use. Please stop the"
                                             " application using it and "
                                             "run JACK again",
- playback_alsa_device);
- alsa_driver_delete (driver);
- return NULL;
+ driver->alsa_name_playback);
+ return -1;
                                 break;
 
                         case EPERM:
                                 jack_error ("you do not have permission to open "
                                             "the audio device \"%s\" for playback",
- playback_alsa_device);
- alsa_driver_delete (driver);
- return NULL;
+ driver->alsa_name_playback);
+ return -1;
+ break;
+
+ default:
+ if (errno) {
+ char *str = strerror(errno);
+ jack_error ("the playback device \"%s\" could not be opened"
+ " because of: \"%s\"\n",
+ driver->alsa_name_playback,str);
+ return -1;
+ }
                                 break;
                         }
                         
@@ -2130,9 +2206,9 @@
                 }
         }
 
- if (capturing) {
+ if (driver->capture) {
                 if (snd_pcm_open (&driver->capture_handle,
- capture_alsa_device,
+ driver->alsa_name_capture,
                                   SND_PCM_STREAM_CAPTURE,
                                   SND_PCM_NONBLOCK) < 0) {
                         switch (errno) {
@@ -2141,17 +2217,25 @@
                                             "already in use. Please stop the"
                                             " application using it and "
                                             "run JACK again",
- capture_alsa_device);
- alsa_driver_delete (driver);
- return NULL;
+ driver->alsa_name_capture);
+ return -1;
                                 break;
 
                         case EPERM:
                                 jack_error ("you do not have permission to open "
                                             "the audio device \"%s\" for capture",
- capture_alsa_device);
- alsa_driver_delete (driver);
- return NULL;
+ driver->alsa_name_capture);
+ return -1;
+ break;
+
+ default:
+ if (errno) {
+ char *str = strerror(errno);
+ jack_error ("the capture device \"%s\" could not be opened"
+ " because of: \"%s\"\n",
+ driver->alsa_name_playback,str);
+ return -1;
+ }
                                 break;
                         }
 
@@ -2164,40 +2248,38 @@
         }
 
         if (driver->playback_handle == NULL) {
- if (playing) {
+ if (driver->playback) {
 
                         /* they asked for playback, but we can't do it */
 
                         jack_error ("ALSA: Cannot open PCM device %s for "
                                     "playback. Falling back to capture-only"
- " mode", name);
+ " mode", driver->name);
 
                         if (driver->capture_handle == NULL) {
                                 /* can't do anything */
- alsa_driver_delete (driver);
- return NULL;
+ return -1;
                         }
                         
- playing = FALSE;
+ driver->playback = FALSE;
                 }
         }
 
         if (driver->capture_handle == NULL) {
- if (capturing) {
+ if (driver->capture) {
 
                         /* they asked for capture, but we can't do it */
                         
                         jack_error ("ALSA: Cannot open PCM device %s for "
                                     "capture. Falling back to playback-only"
- " mode", name);
+ " mode", driver->name);
                         
                         if (driver->playback_handle == NULL) {
                                 /* can't do anything */
- alsa_driver_delete (driver);
- return NULL;
+ return -1;
                         }
 
- capturing = FALSE;
+ driver->capture = FALSE;
                 }
         }
 
@@ -2211,16 +2293,14 @@
                              &driver->playback_hw_params)) < 0) {
                         jack_error ("ALSA: could not allocate playback hw"
                                     " params structure");
- alsa_driver_delete (driver);
- return NULL;
+ return -1;
                 }
 
                 if ((err = snd_pcm_sw_params_malloc (
                              &driver->playback_sw_params)) < 0) {
                         jack_error ("ALSA: could not allocate playback sw"
                                     " params structure");
- alsa_driver_delete (driver);
- return NULL;
+ return -1;
                 }
         }
 
@@ -2229,23 +2309,20 @@
                              &driver->capture_hw_params)) < 0) {
                         jack_error ("ALSA: could not allocate capture hw"
                                     " params structure");
- alsa_driver_delete (driver);
- return NULL;
+ return -1;
                 }
 
                 if ((err = snd_pcm_sw_params_malloc (
                              &driver->capture_sw_params)) < 0) {
                         jack_error ("ALSA: could not allocate capture sw"
                                     " params structure");
- alsa_driver_delete (driver);
- return NULL;
+ return -1;
                 }
         }
 
- if (alsa_driver_set_parameters (driver, frames_per_cycle,
- user_nperiods, rate)) {
- alsa_driver_delete (driver);
- return NULL;
+ if (alsa_driver_set_parameters (driver, driver->frames_per_cycle,
+ driver->user_nperiods, driver->frame_rate)) {
+ return -1;
         }
 
         driver->capture_and_playback_not_synced = FALSE;
@@ -2257,9 +2334,9 @@
                 }
         }
 
- driver->client = client;
+ driver->connected = 1;
 
- return (jack_driver_t *) driver;
+ return 0;
 }
 
 int
diff -Nur jack-audio-connection-kit-0.109.2/drivers/alsa/alsa_driver.h jack-audio-connection-kit-0.109.2-alsa-disconnect/drivers/alsa/alsa_driver.h
--- jack-audio-connection-kit-0.109.2/drivers/alsa/alsa_driver.h 2008-01-30 19:23:52.000000000 +0100
+++ jack-audio-connection-kit-0.109.2-alsa-disconnect/drivers/alsa/alsa_driver.h 2008-03-01 13:40:27.000000000 +0100
@@ -136,6 +136,12 @@
     pthread_mutex_t clock_sync_lock;
     unsigned long next_clock_sync_listener_id;
 
+ char playback : 1;
+ char capture : 1;
+ char connected : 1;
+
+ char *name;
+
     int running;
     int run;
 
diff -Nur jack-audio-connection-kit-0.109.2/example-clients/Makefile.am jack-audio-connection-kit-0.109.2-alsa-disconnect/example-clients/Makefile.am
--- jack-audio-connection-kit-0.109.2/example-clients/Makefile.am 2008-01-30 19:23:43.000000000 +0100
+++ jack-audio-connection-kit-0.109.2-alsa-disconnect/example-clients/Makefile.am 2008-03-01 13:40:27.000000000 +0100
@@ -36,6 +36,7 @@
                jack_bufsize \
                jack_lsp \
                jack_freewheel \
+ jack_device_connect \
                jack_evmon \
                jack_alias \
                $(JACKREC) \
@@ -101,6 +102,10 @@
 jack_freewheel_LDFLAGS = @OS_LDFLAGS@
 jack_freewheel_LDADD = ../libjack/libjack.la
 
+jack_device_connect_SOURCES = device_connect.c
+jack_device_connect_LDFLAGS = @OS_LDFLAGS@
+jack_device_connect_LDADD = ../libjack/libjack.la
+
 if HAVE_SNDFILE
 jackrec_SOURCES = capture_client.c
 jackrec_LDFLAGS = @SNDFILE_LIBS@ @OS_LDFLAGS@
diff -Nur jack-audio-connection-kit-0.109.2/example-clients/Makefile.in jack-audio-connection-kit-0.109.2-alsa-disconnect/example-clients/Makefile.in
--- jack-audio-connection-kit-0.109.2/example-clients/Makefile.in 2008-01-30 19:24:36.000000000 +0100
+++ jack-audio-connection-kit-0.109.2-alsa-disconnect/example-clients/Makefile.in 2008-03-01 13:48:04.000000000 +0100
@@ -40,7 +40,7 @@
 target_triplet = @target@
 bin_PROGRAMS = jack_load$(EXEEXT) jack_unload$(EXEEXT) \
         jack_simple_client$(EXEEXT) jack_monitor_client$(EXEEXT) \
- jack_impulse_grabber$(EXEEXT) jack_connect$(EXEEXT) \
+ jack_impulse_grabber$(EXEEXT) jack_connect$(EXEEXT) jack_device_connect$(EXEEXT) \
         jack_disconnect$(EXEEXT) jack_metro$(EXEEXT) \
         jack_showtime$(EXEEXT) jack_bufsize$(EXEEXT) jack_lsp$(EXEEXT) \
         jack_freewheel$(EXEEXT) jack_evmon$(EXEEXT) \
@@ -85,6 +85,9 @@
 am_jack_connect_OBJECTS = connect.$(OBJEXT)
 jack_connect_OBJECTS = $(am_jack_connect_OBJECTS)
 jack_connect_DEPENDENCIES = ../libjack/libjack.la
+am_jack_device_connect_OBJECTS = device_connect.$(OBJEXT)
+jack_device_connect_OBJECTS = $(am_jack_device_connect_OBJECTS)
+jack_device_connect_DEPENDENCIES = ../libjack/libjack.la
 am_jack_disconnect_OBJECTS = connect.$(OBJEXT)
 jack_disconnect_OBJECTS = $(am_jack_disconnect_OBJECTS)
 jack_disconnect_DEPENDENCIES = ../libjack/libjack.la
@@ -149,7 +152,7 @@
         $(AM_LDFLAGS) $(LDFLAGS) -o $@
 SOURCES = $(inprocess_la_SOURCES) $(intime_la_SOURCES) \
         $(jack_alias_SOURCES) $(jack_bufsize_SOURCES) \
- $(jack_connect_SOURCES) $(jack_disconnect_SOURCES) \
+ $(jack_connect_SOURCES) $(jack_device_connect_SOURCES) $(jack_disconnect_SOURCES) \
         $(jack_evmon_SOURCES) $(jack_freewheel_SOURCES) \
         $(jack_impulse_grabber_SOURCES) $(jack_load_SOURCES) \
         $(jack_lsp_SOURCES) $(jack_metro_SOURCES) \
@@ -160,7 +163,7 @@
         $(jackrec_SOURCES)
 DIST_SOURCES = $(inprocess_la_SOURCES) $(intime_la_SOURCES) \
         $(jack_alias_SOURCES) $(jack_bufsize_SOURCES) \
- $(jack_connect_SOURCES) $(jack_disconnect_SOURCES) \
+ $(jack_connect_SOURCES) $(jack_device_connect_SOURCES) $(jack_disconnect_SOURCES) \
         $(jack_evmon_SOURCES) $(jack_freewheel_SOURCES) \
         $(jack_impulse_grabber_SOURCES) $(jack_load_SOURCES) \
         $(jack_lsp_SOURCES) $(jack_metro_SOURCES) \
@@ -351,6 +354,9 @@
 jack_connect_SOURCES = connect.c
 jack_connect_LDFLAGS = @OS_LDFLAGS@
 jack_connect_LDADD = ../libjack/libjack.la
+jack_device_connect_SOURCES = connect.c
+jack_device_connect_LDFLAGS = @OS_LDFLAGS@
+jack_device_connect_LDADD = ../libjack/libjack.la
 jack_disconnect_SOURCES = connect.c
 jack_disconnect_LDFLAGS = @OS_LDFLAGS@
 jack_disconnect_LDADD = ../libjack/libjack.la
@@ -524,6 +530,9 @@
 jack_connect$(EXEEXT): $(jack_connect_OBJECTS) $(jack_connect_DEPENDENCIES)
         @rm -f jack_connect$(EXEEXT)
         $(LINK) $(jack_connect_LDFLAGS) $(jack_connect_OBJECTS) $(jack_connect_LDADD) $(LIBS)
+jack_device_connect$(EXEEXT): $(jack_device_connect_OBJECTS) $(jack_device_connect_DEPENDENCIES)
+ @rm -f jack_device_connect$(EXEEXT)
+ $(LINK) $(jack_device_connect_LDFLAGS) $(jack_device_connect_OBJECTS) $(jack_device_connect_LDADD) $(LIBS)
 jack_disconnect$(EXEEXT): $(jack_disconnect_OBJECTS) $(jack_disconnect_DEPENDENCIES)
         @rm -f jack_disconnect$(EXEEXT)
         $(LINK) $(jack_disconnect_LDFLAGS) $(jack_disconnect_OBJECTS) $(jack_disconnect_LDADD) $(LIBS)
diff -Nur jack-audio-connection-kit-0.109.2/example-clients/device_connect.c jack-audio-connection-kit-0.109.2-alsa-disconnect/example-clients/device_connect.c
--- jack-audio-connection-kit-0.109.2/example-clients/device_connect.c 1970-01-01 01:00:00.000000000 +0100
+++ jack-audio-connection-kit-0.109.2-alsa-disconnect/example-clients/device_connect.c 2008-03-01 13:40:27.000000000 +0100
@@ -0,0 +1,86 @@
+/*
+ * freewheel - start/stop JACK "freewheeling" mode
+ *
+ * Copyright (C) 2003 Paul Davis.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <jack/jack.h>
+#include <jack/transport.h>
+
+char *package; /* program name */
+jack_client_t *client;
+int onoff;
+
+void jack_shutdown(void *arg)
+{
+ fprintf(stderr, "JACK shut down, exiting ...\n");
+ exit(1);
+}
+
+void signal_handler(int sig)
+{
+ jack_client_close(client);
+ fprintf(stderr, "signal received, exiting ...\n");
+ exit(0);
+}
+
+void parse_arguments(int argc, char *argv[])
+{
+ if (argc < 2) {
+ fprintf(stderr, "usage: %s y|n\n", package);
+ exit(9);
+ }
+
+ if (argv[1][0] == 'y' || argv[1][0] == 'Y' || argv[1][0] == '1') {
+ onoff = 1;
+ } else {
+ onoff = 0;
+ }
+}
+
+int
+main (int argc, char *argv[])
+{
+ parse_arguments (argc, argv);
+
+ /* become a JACK client */
+ if ((client = jack_client_new ("device_connect")) == 0) {
+ fprintf (stderr, "JACK server not running?\n");
+ exit(1);
+ }
+
+ signal (SIGQUIT, signal_handler);
+ signal (SIGTERM, signal_handler);
+ signal (SIGHUP, signal_handler);
+ signal (SIGINT, signal_handler);
+
+ jack_on_shutdown (client, jack_shutdown, 0);
+
+ if (jack_set_connected (client, onoff)) {
+ fprintf (stderr, "failed to reset connect state\n");
+ }
+
+ jack_client_close(client);
+
+ return 0;
+}
diff -Nur jack-audio-connection-kit-0.109.2/jack/driver.h jack-audio-connection-kit-0.109.2-alsa-disconnect/jack/driver.h
--- jack-audio-connection-kit-0.109.2/jack/driver.h 2008-01-30 19:23:50.000000000 +0100
+++ jack-audio-connection-kit-0.109.2-alsa-disconnect/jack/driver.h 2008-03-01 13:40:27.000000000 +0100
@@ -60,6 +60,9 @@
 typedef int (*JackDriverStartFunction)(struct _jack_driver *);
 typedef int (*JackDriverBufSizeFunction)(struct _jack_driver *,
                                                jack_nframes_t nframes);
+typedef int (*JackDriverConnectFunction)(struct _jack_driver *);
+typedef int (*JackDriverDisconnectFunction)(struct _jack_driver *);
+
 /*
    Call sequence summary:
 
@@ -221,7 +224,9 @@
     JackDriverNullCycleFunction null_cycle; \
     JackDriverStopFunction stop; \
     JackDriverStartFunction start; \
- JackDriverBufSizeFunction bufsize;
+ JackDriverBufSizeFunction bufsize; \
+ JackDriverConnectFunction connect; \
+ JackDriverDisconnectFunction disconnect;
 
     JACK_DRIVER_DECL /* expand the macro */
 
@@ -273,6 +278,8 @@
 typedef int (*JackDriverNTBufSizeFunction)(struct _jack_driver_nt *,
                                                jack_nframes_t nframes);
 typedef int (*JackDriverNTRunCycleFunction)(struct _jack_driver_nt *);
+typedef int (*JackDriverNTConnectFunction)(struct _jack_driver_nt *);
+typedef int (*JackDriverNTDisconnectFunction)(struct _jack_driver_nt *);
 
 typedef struct _jack_driver_nt {
 
@@ -287,7 +294,9 @@
     JackDriverNTStopFunction nt_stop; \
     JackDriverNTStartFunction nt_start; \
     JackDriverNTBufSizeFunction nt_bufsize; \
- JackDriverNTRunCycleFunction nt_run_cycle;
+ JackDriverNTRunCycleFunction nt_run_cycle; \
+ JackDriverNTConnectFunction nt_connect; \
+ JackDriverNTDisconnectFunction nt_disconnect;
 #define nt_read read
 #define nt_write write
 #define nt_null_cycle null_cycle
diff -Nur jack-audio-connection-kit-0.109.2/jack/engine.h jack-audio-connection-kit-0.109.2-alsa-disconnect/jack/engine.h
--- jack-audio-connection-kit-0.109.2/jack/engine.h 2008-01-30 19:23:50.000000000 +0100
+++ jack-audio-connection-kit-0.109.2-alsa-disconnect/jack/engine.h 2008-03-01 13:40:27.000000000 +0100
@@ -109,6 +109,7 @@
     unsigned long external_client_cnt;
     int rtpriority;
     char freewheeling;
+ char connected;
     char verbose;
     char do_munlock;
     const char *server_name;
diff -Nur jack-audio-connection-kit-0.109.2/jack/internal.h jack-audio-connection-kit-0.109.2-alsa-disconnect/jack/internal.h
--- jack-audio-connection-kit-0.109.2/jack/internal.h 2008-01-30 19:23:50.000000000 +0100
+++ jack-audio-connection-kit-0.109.2-alsa-disconnect/jack/internal.h 2008-03-01 13:40:27.000000000 +0100
@@ -172,7 +172,9 @@
   StartFreewheel,
   StopFreewheel,
   ClientRegistered,
- ClientUnregistered
+ ClientUnregistered,
+ Connected,
+ Disconnected
 } JackEventType;
 
 typedef struct {
@@ -338,7 +340,9 @@
         IntClientName = 21,
         IntClientUnload = 22,
         RecomputeTotalLatencies = 23,
- RecomputeTotalLatency = 24
+ RecomputeTotalLatency = 24,
+ Connect = 42,
+ Disconnect = 43
 } RequestType;
 
 struct _jack_request {
diff -Nur jack-audio-connection-kit-0.109.2/jack/jack.h jack-audio-connection-kit-0.109.2-alsa-disconnect/jack/jack.h
--- jack-audio-connection-kit-0.109.2/jack/jack.h 2008-01-30 19:23:50.000000000 +0100
+++ jack-audio-connection-kit-0.109.2-alsa-disconnect/jack/jack.h 2008-03-01 13:40:27.000000000 +0100
@@ -246,6 +246,8 @@
  */
 int jack_set_freewheel(jack_client_t* client, int onoff);
 
+int jack_set_connected(jack_client_t* client, int connected);
+
 /**
  * Change the buffer size passed to the @a process_callback.
  *
diff -Nur jack-audio-connection-kit-0.109.2/jackd/engine.c jack-audio-connection-kit-0.109.2-alsa-disconnect/jackd/engine.c
--- jack-audio-connection-kit-0.109.2/jackd/engine.c 2008-01-30 19:23:51.000000000 +0100
+++ jack-audio-connection-kit-0.109.2-alsa-disconnect/jackd/engine.c 2008-03-01 13:40:27.000000000 +0100
@@ -128,6 +128,8 @@
 static void jack_check_acyclic (jack_engine_t* engine);
 static void jack_compute_all_port_total_latencies (jack_engine_t *engine);
 static void jack_compute_port_total_latency (jack_engine_t *engine, jack_port_shared_t*);
+static int jack_device_connect (jack_engine_t *engine);
+static int jack_device_disconnect (jack_engine_t *engine);
 
 
 static inline int
@@ -911,7 +913,11 @@
 
         while (1) {
                 usleep (1000 * JACKD_WATCHDOG_TIMEOUT);
- if (!engine->freewheeling && engine->watchdog_check == 0) {
+ if ( ! engine->connected ) {
+ // cheap trick to avoid a potential race condition when we reconnect
+ engine->watchdog_check = 1;
+ }
+ else if (!engine->freewheeling && engine->watchdog_check == 0) {
 
                         jack_error ("jackd watchdog: timeout - killing jackd");
 
@@ -1270,6 +1276,14 @@
                 req->status = jack_stop_freewheeling (engine);
                 break;
 
+ case Connect:
+ req->status = jack_device_connect (engine);
+ break;
+
+ case Disconnect:
+ req->status = jack_device_disconnect (engine);
+ break;
+
         case SetBufferSize:
                 req->status = jack_set_buffer_size_request (engine,
                                                            req->x.nframes);
@@ -1630,6 +1644,8 @@
 
         engine->clients = 0;
 
+ engine->connected = 0;
+
         engine->pfd_size = 16;
         engine->pfd_max = 0;
         engine->pfd = (struct pollfd *) malloc (sizeof (struct pollfd)
@@ -1956,6 +1972,71 @@
         return 0;
 }
 
+static int jack_device_connect (jack_engine_t *engine)
+{
+ jack_event_t event;
+ void *ftstatus;
+
+ if (engine->connected) {
+ VERBOSE (engine, "connect when already connected\n");
+ return 0;
+ }
+
+ if (engine->driver == NULL) {
+ jack_error ("cannot connect without a driver!");
+ return -1;
+ }
+
+ if(engine->driver->connect (engine->driver))
+ {
+ jack_error ("driver will not connect");
+ return -1;
+ }
+
+ if(engine->driver->start (engine->driver))
+ {
+ jack_error ("driver will not start after disconnection");
+ return -1;
+ }
+
+ engine->connected = 1;
+ /* tell everyone we've connected */
+
+ event.type = Connected;
+ jack_deliver_event_to_all (engine, &event);
+
+ return 0;
+}
+
+static int jack_device_disconnect (jack_engine_t *engine)
+{
+ jack_event_t event;
+
+ if(!engine->connected)
+ {
+ VERBOSE (engine, "disconnect when already disconnected\n");
+ return 0;
+ }
+
+ if (engine->driver == NULL) {
+ jack_error ("cannot disconnect without a driver!");
+ return -1;
+ }
+
+ if (engine->driver->stop (engine->driver)) {
+ jack_error ("could not stop driver for disconnection");
+ return -1;
+ }
+
+ engine->driver->disconnect (engine->driver);
+ engine->connected = 0;
+
+ event.type = Disconnected;
+ jack_deliver_event_to_all (engine, &event);
+
+ return 0;
+}
+
 static int
 jack_run_one_cycle (jack_engine_t *engine, jack_nframes_t nframes,
                     float delayed_usecs)
@@ -3398,6 +3479,7 @@
         if (engine->driver) {
                 engine->driver->detach (engine->driver, engine);
                 engine->driver = 0;
+ engine->connected = 0;
         }
 
         engine->driver = driver;
@@ -3409,7 +3491,7 @@
                 engine->rolling_interval =
                         jack_rolling_interval (driver->period_usecs);
         }
-
+ engine->connected = 1;
         return 0;
 }
 
diff -Nur jack-audio-connection-kit-0.109.2/libjack/client.c jack-audio-connection-kit-0.109.2-alsa-disconnect/libjack/client.c
--- jack-audio-connection-kit-0.109.2/libjack/client.c 2008-01-30 19:23:43.000000000 +0100
+++ jack-audio-connection-kit-0.109.2-alsa-disconnect/libjack/client.c 2008-03-01 13:40:27.000000000 +0100
@@ -1205,6 +1205,14 @@
         return jack_client_deliver_request (client, &request);
 }
 
+int
+jack_set_connected(jack_client_t* client, int connected)
+{
+ jack_request_t request;
+ request.type = connected ? Connect : Disconnect;
+ return jack_client_deliver_request (client, &request);
+}
+
 void
 jack_start_freewheel (jack_client_t* client)
 {
diff -Nur jack-audio-connection-kit-0.109.2/libjack/driver.c jack-audio-connection-kit-0.109.2-alsa-disconnect/libjack/driver.c
--- jack-audio-connection-kit-0.109.2/libjack/driver.c 2008-01-30 19:23:43.000000000 +0100
+++ jack-audio-connection-kit-0.109.2-alsa-disconnect/libjack/driver.c 2008-03-01 13:40:27.000000000 +0100
@@ -46,6 +46,8 @@
                           jack_nframes_t nframes) {return 0;}
 static int dummy_stop (jack_driver_t *drv) { return 0; }
 static int dummy_start (jack_driver_t *drv) { return 0; }
+static int dummy_connect (jack_driver_t *drv) { return 0; }
+static int dummy_disconnect (jack_driver_t *drv) { return 0; }
 
 void
 jack_driver_init (jack_driver_t *driver)
@@ -60,6 +62,8 @@
         driver->bufsize = dummy_bufsize;
         driver->start = dummy_start;
         driver->stop = dummy_stop;
+ driver->connect = dummy_connect;
+ driver->disconnect = dummy_disconnect;
 }
 
 
@@ -199,6 +203,34 @@
 }
 
 static int
+jack_driver_nt_connect (jack_driver_nt_t * driver)
+{
+ int err;
+
+ err = driver->nt_connect (driver);
+ if (err) {
+ jack_error ("DRIVER NT: could not connect driver");
+ return err;
+ }
+
+ return 0;
+}
+
+static int
+jack_driver_nt_disconnect (jack_driver_nt_t * driver)
+{
+ int err;
+
+ err = driver->nt_disconnect (driver);
+ if (err) {
+ jack_error ("DRIVER NT: could not disconnect driver");
+ return err;
+ }
+
+ return 0;
+}
+
+static int
 jack_driver_nt_bufsize (jack_driver_nt_t * driver, jack_nframes_t nframes)
 {
         int err;
@@ -235,10 +267,14 @@
         driver->bufsize = (JackDriverBufSizeFunction) jack_driver_nt_bufsize;
         driver->stop = (JackDriverStartFunction) jack_driver_nt_stop;
         driver->start = (JackDriverStopFunction) jack_driver_nt_start;
+ driver->connect = (JackDriverConnectFunction) jack_driver_nt_connect;
+ driver->disconnect = (JackDriverDisconnectFunction)jack_driver_nt_disconnect;
 
         driver->nt_bufsize = (JackDriverNTBufSizeFunction) dummy_bufsize;
         driver->nt_start = (JackDriverNTStartFunction) dummy_start;
         driver->nt_stop = (JackDriverNTStopFunction) dummy_stop;
+ driver->nt_connect = (JackDriverNTConnectFunction) dummy_connect;
+ driver->nt_disconnect= (JackDriverNTDisconnectFunction)dummy_connect;
         driver->nt_attach = dummy_nt_attach;
         driver->nt_detach = dummy_nt_detach;
         driver->nt_run_cycle = dummy_nt_run_cycle;

_______________________________________________
Linux-audio-user mailing list
Linux-audio-user@email-addr-hidden
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-user
Received on Fri Mar 14 20:15:04 2008

This archive was generated by hypermail 2.1.8 : Fri Mar 14 2008 - 20:15:10 EET