[PATCH] JACK 0.109.2 alsa device disconnect patch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxxxxxxxxx
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-user

[Index of Archives]     [Linux Sound]     [ALSA Users]     [Pulse Audio]     [ALSA Devel]     [Sox Users]     [Linux Media]     [Kernel]     [Photo Sharing]     [Gimp]     [Yosemite News]     [Linux Media]

  Powered by Linux