From 9121e36367f3a3d6fa2cc198a85a57abc113d058 Mon Sep 17 00:00:00 2001 From: paul Date: Tue, 17 Apr 2007 18:47:57 +0000 Subject: [PATCH] new thread_wait implementation to better match the specs; add JACK_PROMISCUOUS_SERVER handling (any user can connect to jackd, if umask of starting user was correct) git-svn-id: svn+ssh://jackaudio.org/trunk/jack@1028 0c269be4-1314-0410-8aa9-9f06e86f4224 --- jack/jack.h | 29 +--------- jackd/engine.c | 10 +++- libjack/client.c | 145 +++++++++++++++++++++++------------------------ 3 files changed, 81 insertions(+), 103 deletions(-) diff --git a/jack/jack.h b/jack/jack.h index 0cc7b65..7b430db 100644 --- a/jack/jack.h +++ b/jack/jack.h @@ -180,36 +180,11 @@ void jack_on_shutdown (jack_client_t *client, int jack_set_process_callback (jack_client_t *client, JackProcessCallback process_callback, void *arg); - /** * Block until this JACK client should process data. * - * This is an alternative API for clients whose internal - * architecture doesn't suit a callback model. They should - * instead contain a core loop that looks something like - * - * \code - * jack_nframes_t nframes; - * - * // wait for the first time we should do something - * - * nframes = jack_thread_wait (client, 0); - * - * while (TRUE) { - * nframes = jack_thread_wait (client, do_some_processing (nframes)); - * } - * \endcode - * - * The function do_some_processing() should return zero if - * the client should keep interacting with JACK, and non-zero - * if it is finished. Note that passing a non-zero status - * will terminate the calling thread. Therefore, this loop should - * run in its own thread which should probably have - * been created with @function jack_client_create_thread(). - * - * Clients using this call should probably not call - * @function jack_set_process_callback although it is not - * an error for them to do so. + * The @a status argument typically indicates the result + * of some recent data processing. * * @param client - pointer to a JACK client structure * @param status - if non-zero, calling thread should exit diff --git a/jackd/engine.c b/jackd/engine.c index 16ede31..a3f746c 100644 --- a/jackd/engine.c +++ b/jackd/engine.c @@ -174,7 +174,15 @@ make_directory (const char *path) if (stat (path, &statbuf)) { if (errno == ENOENT) { - if (mkdir (path, 0700) < 0){ + int mode; + + if (getenv ("JACK_PROMISCUOUS_SERVER")) { + mode = 0777; + } else { + mode = 0700; + } + + if (mkdir (path, mode) < 0){ jack_error ("cannot create %s directory (%s)\n", path, strerror (errno)); return -1; diff --git a/libjack/client.c b/libjack/client.c index 1146f7f..64bc66e 100644 --- a/libjack/client.c +++ b/libjack/client.c @@ -1158,8 +1158,13 @@ jack_user_dir (void) /* format the path name on the first call */ if (user_dir[0] == '\0') { - snprintf (user_dir, sizeof (user_dir), "%s/jack-%d", - jack_tmpdir, getuid ()); + if (getenv ("JACK_PROMISCUOUS_SERVER")) { + snprintf (user_dir, sizeof (user_dir), "%s/jack", + jack_tmpdir); + } else { + snprintf (user_dir, sizeof (user_dir), "%s/jack-%d", + jack_tmpdir, getuid ()); + } } return user_dir; @@ -1378,26 +1383,12 @@ jack_client_process_events (jack_client_t* client) return 0; } - -jack_nframes_t -jack_thread_wait (jack_client_t* client, int status) -{ - /* this function waits for either event notifications from the server - (all platforms) or process notifications from the server (with - non-threaded backends like ALSA and OSS). it will process the - event notifications, and return whenever a process notification - arrives. - - if passed a non-zero status code, it will terminate the thread - in which it is called. - */ +static int +jack_client_core_wait (jack_client_t* client) +{ jack_client_control_t *control = client->control; - if (status || client->engine->engine_ok == 0) { - return 0; - } - DEBUG ("client polling on %s", client->pollmax == 2 ? "event_fd and graph_wait_fd..." : "event_fd only"); @@ -1409,7 +1400,7 @@ jack_thread_wait (jack_client_t* client, int status) } jack_error ("poll failed in client (%s)", strerror (errno)); - return 0; + return -1; } pthread_testcancel(); @@ -1476,11 +1467,10 @@ jack_thread_wait (jack_client_t* client, int status) if (client->control->dead || client->pollfd[EVENT_POLL_INDEX].revents & ~POLLIN) { DEBUG ("client appears dead or event pollfd has error status\n"); - return 0; + return -1; } - DEBUG("thread wait returns %u\n", control->nframes); - return control->nframes; + return 0; } static int @@ -1513,45 +1503,25 @@ jack_wake_next_client (jack_client_t* client) return 0; } -static int -jack_client_run_process_callback (jack_client_t* client) +static jack_nframes_t +jack_thread_first_wait (jack_client_t* client) +{ + if (jack_client_core_wait (client)) { + return 0; + } + return client->control->nframes; +} + +jack_nframes_t +jack_thread_wait (jack_client_t* client, int status) { jack_client_control_t *control = client->control; -#ifdef JACK_USE_MACH_THREADS - /* this is done in a dedicated thread on OS X */ - return control->nframes; -#endif + /* SECTION ONE: HOUSEKEEPING/CLEANUP FROM LAST DATA PROCESSING */ - DEBUG ("client %d signalled at %" PRIu64 - ", awake for process at %" PRIu64 - " (delay = %" PRIu64 - " usecs) (wakeup on graph_wait_fd==%d)", - getpid(), - control->signalled_at, - control->awake_at, - control->awake_at - control->signalled_at, - client->pollfd[WAIT_POLL_INDEX].fd); - - control->state = Running; - - /* begin preemption checking */ - CHECK_PREEMPTION (client->engine, TRUE); - - if (control->sync_cb) - jack_call_sync_client (client); - - if (control->process) { - if (control->process (control->nframes, - control->process_arg) - == 0) { - control->state = Finished; - } - } else { - control->state = Finished; - } - - if (control->timebase_cb) { + /* housekeeping/cleanup after data processing */ + + if (status == 0 && control->timebase_cb) { jack_call_timebase_master (client); } @@ -1560,26 +1530,39 @@ jack_client_run_process_callback (jack_client_t* client) control->finished_at = jack_get_microseconds(); - DEBUG ("client finished processing at %" PRIu64 - " (elapsed = %" PRIu64 - " usecs), writing on graph_next_fd==%d", - control->finished_at, - control->finished_at - control->awake_at, - client->graph_next_fd); - /* wake the next client in the chain (could be the server), and check if we were killed during the process cycle. */ - if (jack_wake_next_client (client) || client->control->dead) { + if (jack_wake_next_client (client)) { DEBUG("client cannot wake next, or is dead\n"); - return -1; + return 0; } - DEBUG("process cycle fully complete\n"); + if (status || client->control->dead || !client->engine->engine_ok) { + return 0; + } - return 0; + /* SECTION TWO: WAIT FOR NEXT DATA PROCESSING TIME */ + + if (jack_client_core_wait (client)) { + return 0; + } + + /* SECTION THREE: START NEXT DATA PROCESSING TIME */ + + /* Time to do data processing */ + + control->state = Running; + + /* begin preemption checking */ + CHECK_PREEMPTION (client->engine, TRUE); + + if (control->sync_cb) + jack_call_sync_client (client); + + return control->nframes; } static void * @@ -1594,20 +1577,32 @@ jack_client_thread (void *arg) pthread_cond_signal (&client_ready); pthread_mutex_unlock (&client_lock); - client->control->pid = getpid(); - client->control->pgrp = getpgrp(); + control->pid = getpid(); + control->pgrp = getpgrp(); DEBUG ("client thread is now running"); - if (client->control->thread_init) { + if (control->thread_init) { DEBUG ("calling client thread init callback"); - client->control->thread_init (client->control->thread_init_arg); + control->thread_init (control->thread_init_arg); } /* wait for first wakeup from server */ - if (jack_thread_wait (client, 0) == control->nframes) { - while (jack_thread_wait (client, jack_client_run_process_callback (client)) == control->nframes); + if (jack_thread_first_wait (client) == control->nframes) { + /* now run till we're done */ + if (control->process) { + /* run process callback, then wait... ad-infinitum */ + while (jack_thread_wait (client, + control->process (control->nframes, + control->process_arg)) == + control->nframes) + ; + } else { + /* no process handling but still need to process events */ + while (jack_thread_wait (client, 0) == control->nframes) + ; + } } jack_client_thread_suicide (client);