|
- /* -*- mode: c; c-file-style: "linux"; -*- */
- /*
- Copyright (C) 2001-2003 Paul Davis
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- */
-
- #include <config.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdarg.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <errno.h>
-
- #include <jack/internal.h>
- #include <jack/driver.h>
- #include <jack/engine.h>
- #include <jack/thread.h>
-
- #ifdef USE_MLOCK
- #include <sys/mman.h>
- #endif /* USE_MLOCK */
-
- static int dummy_attach (jack_driver_t *drv, jack_engine_t *eng) { return 0; }
- static int dummy_detach (jack_driver_t *drv, jack_engine_t *eng) { return 0; }
- static int dummy_write (jack_driver_t *drv,
- jack_nframes_t nframes) { return 0; }
- static int dummy_read (jack_driver_t *drv, jack_nframes_t nframes) { return 0; }
- static int dummy_null_cycle (jack_driver_t *drv,
- jack_nframes_t nframes) { return 0; }
- static int dummy_bufsize (jack_driver_t *drv,
- 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; }
-
- void
- jack_driver_init (jack_driver_t *driver)
- {
- memset (driver, 0, sizeof (*driver));
-
- driver->attach = dummy_attach;
- driver->detach = dummy_detach;
- driver->write = dummy_write;
- driver->read = dummy_read;
- driver->null_cycle = dummy_null_cycle;
- driver->bufsize = dummy_bufsize;
- driver->start = dummy_start;
- driver->stop = dummy_stop;
- }
-
-
-
- /****************************
- *** Non-Threaded Drivers ***
- ****************************/
-
- static int dummy_nt_run_cycle (jack_driver_nt_t *drv) { return 0; }
- static int dummy_nt_attach (jack_driver_nt_t *drv) { return 0; }
- static int dummy_nt_detach (jack_driver_nt_t *drv) { return 0; }
-
-
- /*
- * These are used in driver->nt_run for controlling whether or not
- * driver->engine->driver_exit() gets called (EXIT = call it, PAUSE = don't)
- */
- #define DRIVER_NT_RUN 0
- #define DRIVER_NT_EXIT 1
- #define DRIVER_NT_PAUSE 2
- #define DRIVER_NT_DYING 3
-
- static int
- jack_driver_nt_attach (jack_driver_nt_t * driver, jack_engine_t * engine)
- {
- driver->engine = engine;
- return driver->nt_attach (driver);
- }
-
- static int
- jack_driver_nt_detach (jack_driver_nt_t * driver, jack_engine_t * engine)
- {
- int ret;
-
- ret = driver->nt_detach (driver);
- driver->engine = NULL;
-
- return ret;
- }
-
- static void *
- jack_driver_nt_thread (void * arg)
- {
- jack_driver_nt_t * driver = (jack_driver_nt_t *) arg;
- int rc = 0;
- int run;
-
- /* This thread may start running before pthread_create()
- * actually stores the driver->nt_thread value. It's safer to
- * store it here as well.
- */
-
- driver->nt_thread = pthread_self();
-
- pthread_mutex_lock (&driver->nt_run_lock);
-
- while ((run = driver->nt_run) == DRIVER_NT_RUN) {
- pthread_mutex_unlock (&driver->nt_run_lock);
-
- if ((rc = driver->nt_run_cycle (driver)) != 0) {
- jack_error ("DRIVER NT: could not run driver cycle");
- goto out;
- }
-
- pthread_mutex_lock (&driver->nt_run_lock);
- }
-
- pthread_mutex_unlock (&driver->nt_run_lock);
-
- out:
- if (rc) {
- driver->nt_run = DRIVER_NT_DYING;
- driver->engine->driver_exit (driver->engine);
- }
- pthread_exit (NULL);
- }
-
- static int
- jack_driver_nt_start (jack_driver_nt_t * driver)
- {
- int err;
-
- /* stop the new thread from really starting until the driver has
- been started.
- */
-
- pthread_mutex_lock (&driver->nt_run_lock);
- driver->nt_run = DRIVER_NT_RUN;
-
- if ((err = jack_client_create_thread (NULL,
- &driver->nt_thread,
- driver->engine->rtpriority,
- driver->engine->control->real_time,
- jack_driver_nt_thread, driver)) != 0) {
- jack_error ("DRIVER NT: could not start driver thread!");
- return err;
- }
-
- if ((err = driver->nt_start (driver)) != 0) {
- /* make the thread run and exit immediately */
- driver->nt_run = DRIVER_NT_EXIT;
- pthread_mutex_unlock (&driver->nt_run_lock);
- jack_error ("DRIVER NT: could not start driver");
- return err;
- }
-
- /* let the thread run, since the underlying "device" has now been started */
-
- pthread_mutex_unlock (&driver->nt_run_lock);
-
- return 0;
- }
-
- static int
- jack_driver_nt_do_stop (jack_driver_nt_t * driver, int run)
- {
- int err;
-
- pthread_mutex_lock (&driver->nt_run_lock);
- if(driver->nt_run != DRIVER_NT_DYING) {
- driver->nt_run = run;
- }
- pthread_mutex_unlock (&driver->nt_run_lock);
-
- /* detect when called while the thread is shutting itself down */
- if (driver->nt_thread && driver->nt_run != DRIVER_NT_DYING
- && (err = pthread_join (driver->nt_thread, NULL)) != 0) {
- jack_error ("DRIVER NT: error waiting for driver thread: %s",
- strerror (err));
- return err;
- }
-
- if ((err = driver->nt_stop (driver)) != 0) {
- jack_error ("DRIVER NT: error stopping driver");
- return err;
- }
-
- return 0;
- }
-
- static int
- jack_driver_nt_stop (jack_driver_nt_t * driver)
- {
- return jack_driver_nt_do_stop (driver, DRIVER_NT_EXIT);
- }
-
- static int
- jack_driver_nt_bufsize (jack_driver_nt_t * driver, jack_nframes_t nframes)
- {
- int err;
- int ret;
-
- err = jack_driver_nt_do_stop (driver, DRIVER_NT_PAUSE);
- if (err) {
- jack_error ("DRIVER NT: could not stop driver to change buffer size");
- driver->engine->driver_exit (driver->engine);
- return err;
- }
-
- ret = driver->nt_bufsize (driver, nframes);
-
- err = jack_driver_nt_start (driver);
- if (err) {
- jack_error ("DRIVER NT: could not restart driver during buffer size change");
- driver->engine->driver_exit (driver->engine);
- return err;
- }
-
- return ret;
- }
-
- void
- jack_driver_nt_init (jack_driver_nt_t * driver)
- {
- memset (driver, 0, sizeof (*driver));
-
- jack_driver_init ((jack_driver_t *) driver);
-
- driver->attach = (JackDriverAttachFunction) jack_driver_nt_attach;
- driver->detach = (JackDriverDetachFunction) jack_driver_nt_detach;
- driver->bufsize = (JackDriverBufSizeFunction) jack_driver_nt_bufsize;
- driver->stop = (JackDriverStopFunction) jack_driver_nt_stop;
- driver->start = (JackDriverStartFunction) jack_driver_nt_start;
-
- driver->nt_bufsize = (JackDriverNTBufSizeFunction) dummy_bufsize;
- driver->nt_start = (JackDriverNTStartFunction) dummy_start;
- driver->nt_stop = (JackDriverNTStopFunction) dummy_stop;
- driver->nt_attach = dummy_nt_attach;
- driver->nt_detach = dummy_nt_detach;
- driver->nt_run_cycle = dummy_nt_run_cycle;
-
-
- pthread_mutex_init (&driver->nt_run_lock, NULL);
- }
-
- void
- jack_driver_nt_finish (jack_driver_nt_t * driver)
- {
- pthread_mutex_destroy (&driver->nt_run_lock);
- }
|