JACK device disconnect patch [UPDATED]

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

JACK device disconnect patch [UPDATED]

Salvatore Di Pietro
Hi all,

I just fitted Sean Meiners' alsa device disconnect patch for jack svn
HEAD (I did for 0.103.0 as well, see my other post).

It enables jack to detach from the ALSA device, letting its use by other
non-JACK programs whilst in the middle of a jack session, without
closing jack 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.

You get an additional example client: jack_device_connect which you use
to make jack release and re-hook to the audio card. All audio from jack
is of course muted and jack apps frozen while jack has released the
device, they unfreeze upon jack re-attaching to the audio device.

It seems to be working OK, maybe someone wants to try it?
Any chance it will be merged in?

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



diff -Naur jack.orig/drivers/alsa/alsa_driver.c jack-disc/drivers/alsa/alsa_driver.c
--- jack.orig/drivers/alsa/alsa_driver.c 2007-11-22 17:01:24.000000000 +0100
+++ jack-disc/drivers/alsa/alsa_driver.c 2007-11-22 17:06:44.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 -Naur jack.orig/drivers/alsa/alsa_driver.h jack-disc/drivers/alsa/alsa_driver.h
--- jack.orig/drivers/alsa/alsa_driver.h 2007-11-22 17:01:24.000000000 +0100
+++ jack-disc/drivers/alsa/alsa_driver.h 2007-11-22 17:06:44.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 -Naur jack.orig/example-clients/Makefile.am jack-disc/example-clients/Makefile.am
--- jack.orig/example-clients/Makefile.am 2007-11-22 17:01:12.000000000 +0100
+++ jack-disc/example-clients/Makefile.am 2007-11-23 17:56:42.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 -Naur jack.orig/example-clients/device_connect.c jack-disc/example-clients/device_connect.c
--- jack.orig/example-clients/device_connect.c 1970-01-01 01:00:00.000000000 +0100
+++ jack-disc/example-clients/device_connect.c 2007-11-22 17:08:40.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 -Naur jack.orig/jack/driver.h jack-disc/jack/driver.h
--- jack.orig/jack/driver.h 2007-11-22 17:01:21.000000000 +0100
+++ jack-disc/jack/driver.h 2007-11-22 17:08:40.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 -Naur jack.orig/jack/engine.h jack-disc/jack/engine.h
--- jack.orig/jack/engine.h 2007-11-22 17:01:21.000000000 +0100
+++ jack-disc/jack/engine.h 2007-11-22 17:08:40.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 -Naur jack.orig/jack/internal.h jack-disc/jack/internal.h
--- jack.orig/jack/internal.h 2007-11-22 17:01:21.000000000 +0100
+++ jack-disc/jack/internal.h 2007-11-23 18:06:27.000000000 +0100
@@ -172,7 +172,9 @@
   StartFreewheel,
   StopFreewheel,
   ClientRegistered,
-  ClientUnregistered
+  ClientUnregistered,
+  Connected,
+  Disconnected
 } JackEventType;
 
 typedef struct {
@@ -337,7 +339,9 @@
  IntClientName = 21,
  IntClientUnload = 22,
  RecomputeTotalLatencies = 23,
- RecomputeTotalLatency = 24
+ RecomputeTotalLatency = 24,
+ Connect = 42,
+ Disconnect = 43
 } RequestType;
 
 struct _jack_request {
diff -Naur jack.orig/jack/jack.h jack-disc/jack/jack.h
--- jack.orig/jack/jack.h 2007-11-22 17:01:21.000000000 +0100
+++ jack-disc/jack/jack.h 2007-11-22 17:08:40.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 -Naur jack.orig/jackd/engine.c jack-disc/jackd/engine.c
--- jack.orig/jackd/engine.c 2007-11-22 17:01:22.000000000 +0100
+++ jack-disc/jackd/engine.c 2007-11-23 18:11: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");
 
@@ -1308,6 +1314,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);
@@ -1663,6 +1677,8 @@
 
  engine->clients = 0;
 
+ engine->connected = 0;
+
  engine->pfd_size = 16;
  engine->pfd_max = 0;
  engine->pfd = (struct pollfd *) malloc (sizeof (struct pollfd)
@@ -1989,6 +2005,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)
@@ -3425,6 +3506,7 @@
  if (engine->driver) {
  engine->driver->detach (engine->driver, engine);
  engine->driver = 0;
+ engine->connected = 0;
  }
 
  if (driver) {
@@ -3436,6 +3518,7 @@
  }
 
  engine->driver = driver;
+ engine->connected = 1;
  return 0;
 }
 
diff -Naur jack.orig/libjack/client.c jack-disc/libjack/client.c
--- jack.orig/libjack/client.c 2007-11-22 17:01:14.000000000 +0100
+++ jack-disc/libjack/client.c 2007-11-22 17:12:06.000000000 +0100
@@ -1155,6 +1155,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 -Naur jack.orig/libjack/driver.c jack-disc/libjack/driver.c
--- jack.orig/libjack/driver.c 2007-11-22 17:01:14.000000000 +0100
+++ jack-disc/libjack/driver.c 2007-11-22 17:12:06.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;

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: JACK device disconnect patch [UPDATED]

Pieter Palmers
Salvatore Di Pietro wrote:

> Hi all,
>
> I just fitted Sean Meiners' alsa device disconnect patch for jack svn
> HEAD (I did for 0.103.0 as well, see my other post).
>
> It enables jack to detach from the ALSA device, letting its use by other
> non-JACK programs whilst in the middle of a jack session, without
> closing jack 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.
>
> You get an additional example client: jack_device_connect which you use
> to make jack release and re-hook to the audio card. All audio from jack
> is of course muted and jack apps frozen while jack has released the
> device, they unfreeze upon jack re-attaching to the audio device.
How does this interact with realtime watchdogs?

>
> It seems to be working OK, maybe someone wants to try it?
> Any chance it will be merged in?

I like the idea, but I think it should be implemented such that the
system is switched over to a dummy driver instead of freezing everything.

Greets,

Pieter

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: JACK device disconnect patch [UPDATED]

Salvatore Di Pietro
Pieter Palmers wrote:

[cut]

> How does this interact with realtime watchdogs?

Not sure to get what you mean here. Do you mean jackd watchdog or
das_watchdog ? They both aren't triggered, the jackd one because it is
"frozen" as well (I think), das_watchdog because the "frozen" clients
give up the CPU, don't hog it. Double quotes round "frozen" because
AFAIK the processes are not really stopped (like with a SIGSTOP), they
just stop producing and consuming audio, and the transport pauses
(including XMMS seekbar, even if it's not a transport capable app)

It just (not always) triggers an XRUN upon reattaching to the alsa device.

> I like the idea, but I think it should be implemented such that the
> system is switched over to a dummy driver instead of freezing everything.

Why? Wouldn't be more convenient to stop the audio stream and the transport?

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

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: JACK device disconnect patch [UPDATED]

Pieter Palmers
Salvatore Di Pietro wrote:

> Pieter Palmers wrote:
>
> [cut]
>
>> How does this interact with realtime watchdogs?
>
> Not sure to get what you mean here. Do you mean jackd watchdog or
> das_watchdog ? They both aren't triggered, the jackd one because it is
> "frozen" as well (I think), das_watchdog because the "frozen" clients
> give up the CPU, don't hog it. Double quotes round "frozen" because
> AFAIK the processes are not really stopped (like with a SIGSTOP), they
> just stop producing and consuming audio, and the transport pauses
> (including XMMS seekbar, even if it's not a transport capable app)
>
> It just (not always) triggers an XRUN upon reattaching to the alsa device.
>
>> I like the idea, but I think it should be implemented such that the
>> system is switched over to a dummy driver instead of freezing everything.
>
> Why? Wouldn't be more convenient to stop the audio stream and the transport?

An RT watchdog is usually implemented as a high-priority RT thread that
checks whether a lower priority RT thread updates a variable in time. e.g.:

high prio thread:
while(1) {
        keepalive = false;
        sleep(WATCHDOG_TIMEOUT);
        if (!keepalive) {
                error("watchdog timeout!");
        }
}

the monitored thread:
while(1) {
        doWork();
        keepalive = true;
}

This makes that if doWork() is not finished within WATCHDOG_TIMEOUT
(when the sleep call returns), the watchdog variable is still false and
the watchdog thread kicks in and kills the thread.

If the watchdog variable update is done in e.g. the jackd process call
and your patch 'freezes' by stopping the call to process(), it will
trigger the watchdog of applications.

das_watchdog works along the same principle, but only kicks in if a
process actually hogs the CPU. However, applications relying on the
process() call to provide the keepalive feedback can have their watchdog
kick in without hogging the cpu.

Greets,

Pieter

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel