Browse Source

many critical changes, plus jackrec client

git-svn-id: svn+ssh://jackaudio.org/trunk/jack@46 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/0.109.0
pbd 23 years ago
parent
commit
0038270fba
11 changed files with 545 additions and 91 deletions
  1. +1
    -0
      .cvsignore
  2. +5
    -2
      Makefile.am
  3. +7
    -3
      alsa_driver.c
  4. +319
    -0
      capture_client.c
  5. +22
    -5
      client.c
  6. +7
    -2
      configure.in
  7. +145
    -60
      engine.c
  8. +8
    -9
      fltk_client.cc
  9. +1
    -1
      jack/alsa_driver.h
  10. +22
    -1
      jack/jack.h
  11. +8
    -8
      simple_client.c

+ 1
- 0
.cvsignore View File

@@ -7,6 +7,7 @@ libtool
jackd
jack_simple_client
jack_monitor_client
jackrec
*.la
*.pc
Makefile


+ 5
- 2
Makefile.am View File

@@ -4,9 +4,9 @@ MAINTAINERCLEANFILES = Makefile.in aclocal.m4 configure config.h.in \
missing install-sh config.sub ltconfig \
ltmain.sh acinclude.m4

SUBDIRS = jack doc
SUBDIRS = jack

EXTRA_PROGRAMS = jack_fltk_client
EXTRA_PROGRAMS = jack_fltk_client jackrec

bin_PROGRAMS = jackd jack_simple_client jack_monitor_client @XTRA@

@@ -26,6 +26,9 @@ jack_monitor_client_LDFLAGS = -L. -ljack -lltdl -lpthread
jack_fltk_client_SOURCES = fltk_client.cc
jack_fltk_client_LDFLAGS = -L. -L/usr/X11R6/lib -lfltk -lX11 -lXext -ljack -lltdl -lpthread

jackrec_SOURCES = capture_client.c
jackrec_LDFLAGS = -L. -lsndfile -ljack -lltdl -lpthread

lib_LTLIBRARIES = libjack.la jack_alsa.la

libjack_la_SOURCES = client.c pool.c driver.c


+ 7
- 3
alsa_driver.c View File

@@ -38,9 +38,9 @@
static int config_max_level = 0;
static int config_min_level = 0;

static unsigned long current_usecs () {
unsigned long now;
rdtscl (now);
static unsigned long long current_usecs () {
unsigned long long now;
rdtscll (now);
return now / 450;
}

@@ -704,6 +704,7 @@ alsa_driver_wait (alsa_driver_t *driver)
channel_t chn;
GSList *node;
sample_t *buffer;
// unsigned long long end;

again:
if (poll (&driver->pfd, 1, 1000) < 0) {
@@ -844,6 +845,9 @@ alsa_driver_wait (alsa_driver_t *driver)
avail -= contiguous;
}

// end = current_usecs();
// printf ("entire cycle took %f usecs\n", ((float)(end - driver->time_at_interrupt))/450.0f);

return 0;
}



+ 319
- 0
capture_client.c View File

@@ -0,0 +1,319 @@
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sndfile.h>
#include <pthread.h>
#include <glib.h>

#include <jack/jack.h>

typedef struct _thread_info {
pthread_t thread_id;
SNDFILE *sf;
nframes_t duration;
jack_client_t *client;
unsigned int channels;
int can_capture;
char *path;
int status;
int process_go;
} thread_info_t;

unsigned int nports;
jack_port_t **ports;

pthread_mutex_t buffer_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t data_ready = PTHREAD_COND_INITIALIZER;

typedef struct _sample_buffer {
nframes_t nframes;
sample_t **data;
} sample_buffer_t;

sample_buffer_t *
sample_buffer_new (nframes_t nframes, unsigned int nchans)
{
sample_buffer_t *buf;
unsigned int i;

buf = (sample_buffer_t *) malloc (sizeof (sample_buffer_t));
buf->nframes = nframes;
buf->data = (sample_t **) malloc (sizeof (sample_t *) * nchans);

for (i = 0; i < nchans; i++) {
buf->data[i] = (sample_t *) malloc (sizeof (sample_t) * nframes);
}

return buf;
}

GSList *pending_writes = NULL;
GSList *free_buffers = NULL;

sample_buffer_t *
get_free_buffer (nframes_t nframes, unsigned int nchans)
{
sample_buffer_t *buf;

if (free_buffers == NULL) {
buf = sample_buffer_new (nframes, nchans);
} else {
buf = (sample_buffer_t *) free_buffers->data;
free_buffers = g_slist_next (free_buffers);
}

return buf;
}

sample_buffer_t *
get_write_buffer ()
{
sample_buffer_t *buf;

if (pending_writes == NULL) {
return NULL;
}

buf = (sample_buffer_t *) pending_writes->data;
pending_writes = g_slist_next (pending_writes);

return buf;
}

void
put_write_buffer (sample_buffer_t *buf)
{
pending_writes = g_slist_append (pending_writes, buf);
}

void
put_free_buffer (sample_buffer_t *buf)
{
free_buffers = g_slist_prepend (free_buffers, buf);
}

void *
disk_thread (void *arg)
{
sample_buffer_t *buf;
thread_info_t *info = (thread_info_t *) arg;
int i;
unsigned int chn;
nframes_t total_captured = 0;
int done = 0;
double *fbuf;

pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
pthread_mutex_lock (&buffer_lock);

/* preload the buffer cache */

for (i = 0; i < 5; i++) {
buf = sample_buffer_new (jack_get_buffer_size (info->client), info->channels);
put_free_buffer (buf);
}

info->status = 0;

while (!done) {
pthread_cond_wait (&data_ready, &buffer_lock);

while ((buf = get_write_buffer ()) != 0) {
pthread_mutex_unlock (&buffer_lock);

/* grrr ... libsndfile doesn't do float data yet, only double */
if (info->can_capture) {

fbuf = (double *) malloc (sizeof (double) * buf->nframes * info->channels);

for (chn = 0; chn < info->channels; chn++) {
for (i = 0; i < buf->nframes; i++) {
fbuf[chn+(i*info->channels)] = buf->data[chn][i];
}
}
if (sf_writef_double (info->sf, fbuf, buf->nframes, 1) != buf->nframes) {
char errstr[256];
sf_error_str (0, errstr, sizeof (errstr) - 1);
fprintf (stderr, "cannot write data to sndfile (%s)\n", errstr);
info->status = -1;
done = 1;
break;
}
free (fbuf);
total_captured += buf->nframes;

if (total_captured >= info->duration) {
printf ("disk thread finished\n");
done = 1;
break;
}
}

pthread_mutex_lock (&buffer_lock);
put_free_buffer (buf);
}
}

pthread_mutex_unlock (&buffer_lock);
return 0;
}
int
process (nframes_t nframes, void *arg)

{
thread_info_t *info = (thread_info_t *) arg;
sample_t *in;
sample_buffer_t *buf;
unsigned int i;

if (!info->process_go) {
return 0;
}

pthread_mutex_lock (&buffer_lock);

buf = get_free_buffer (nframes, nports);

for (i = 0; i < nports; i++) {
in = (sample_t *) jack_port_get_buffer (ports[i], nframes);
memcpy (buf->data[i], in, sizeof (sample_t) * nframes);
}

/* we don't like taking locks, but until we have a lock
free ringbuffer written in C, this is what has to be done
*/

put_write_buffer (buf);

/* tell the disk thread that there is work to do */
pthread_cond_signal (&data_ready);
pthread_mutex_unlock (&buffer_lock);

return 0;
}

void
jack_shutdown (void *arg)
{
fprintf (stderr, "JACK shutdown\n");
exit (0);
}

void
setup_disk_thread (thread_info_t *info)
{
SF_INFO sf_info;

sf_info.samplerate = jack_get_sample_rate (info->client);
sf_info.channels = info->channels;
sf_info.format = SF_FORMAT_WAV|SF_FORMAT_PCM;
sf_info.pcmbitwidth = 16;
// sf_info.samples = info->duration * sf_info.samplerate;

if ((info->sf = sf_open_write (info->path, &sf_info)) == NULL) {
char errstr[256];
sf_error_str (0, errstr, sizeof (errstr) - 1);
fprintf (stderr, "cannot open sndfile \"%s\" for output (%s)\n", info->path, errstr);
jack_client_close (info->client);
exit (1);
}

info->duration = 2 * 48000;
info->can_capture = 0;

pthread_create (&info->thread_id, NULL, disk_thread, info);
}

void
run_disk_thread (thread_info_t *info)
{
info->can_capture = 1;
pthread_join (info->thread_id, NULL);
sf_close (info->sf);
if (info->status) {
unlink (info->path);
}
}

void
setup_ports (int argc, char *argv[], thread_info_t *info)
{
char **source_names;
int i;

nports = argc - 2;

source_names = (char **) malloc (sizeof (char **) * nports);
ports = (jack_port_t **) malloc (sizeof (jack_port_t *) * nports);

for (i = 2; i < argc; i++) {
source_names[i-2] = argv[i];
}

for (i = 0; i < nports; i++) {
char name[64];

sprintf (name, "input%d\n", i+1);

if ((ports[i] = jack_port_register (info->client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0)) == 0) {
fprintf (stderr, "cannot register input port \"%s\"!\n", name);
jack_client_close (info->client);
exit (1);
}
}

for (i = 0; i < nports; i++) {
if (jack_port_connect (info->client, source_names[i], jack_port_name (ports[i]))) {
fprintf (stderr, "cannot connect input port %s to %s\n", jack_port_name (ports[i]), source_names[i]);
jack_client_close (info->client);
exit (1);
}
}

info->process_go = 1;
free (source_names);
}

int
main (int argc, char *argv[])

{
jack_client_t *client;
thread_info_t thread_info;

if (argc < 3) {
fprintf (stderr, "usage: jackrec filename port1 [ port2 ... ]\n");
return 1;
}
if ((client = jack_client_new ("jackrec")) == 0) {
fprintf (stderr, "jack server not running?\n");
return 1;
}

thread_info.client = client;
thread_info.path = argv[1];
thread_info.channels = argc - 2;
thread_info.process_go = 0;

setup_disk_thread (&thread_info);

jack_set_process_callback (client, process, &thread_info);
jack_on_shutdown (client, jack_shutdown, NULL);

if (jack_activate (client)) {
fprintf (stderr, "cannot activate client");
}

setup_ports (argc, argv, &thread_info);

run_disk_thread (&thread_info);

jack_client_close (client);
exit (0);
}

+ 22
- 5
client.c View File

@@ -53,6 +53,8 @@ struct _jack_client {
GSList *ports;
pthread_t thread;
char fifo_prefix[FIFO_NAME_SIZE+1];
void (*on_shutdown)(void *arg);
void *on_shutdown_arg;
char thread_ok : 1;
char first_active : 1;
};
@@ -100,7 +102,7 @@ jack_client_alloc ()
client->control = 0;
client->thread_ok = FALSE;
client->first_active = TRUE;
client->on_shutdown = NULL;
return client;
}

@@ -234,7 +236,7 @@ jack_handle_reorder (jack_client_t *client, jack_event_t *event)
jack_error ("cannot open specified fifo [%s] for writing (%s)", path, strerror (errno));
return -1;
}
return 0;
}
@@ -478,6 +480,9 @@ jack_client_thread (void *arg)

if (client->pollfd[0].revents & ~POLLIN) {
jack_error ("engine has shut down socket; thread exiting");
if (client->on_shutdown) {
client->on_shutdown (client->on_shutdown_arg);
}
pthread_exit (0);
}

@@ -575,11 +580,11 @@ jack_client_thread (void *arg)
}

/* this may fail. if it does, the engine will discover
that for itcontrol due a cycle timeout, which is about
it due a cycle timeout, which is about
the best we can do without a lot of mostly wasted
effort.
*/
write (client->graph_next_fd, &c, 1);
}
}
@@ -960,7 +965,7 @@ jack_port_connect (jack_client_t *client, const char *source_port, const char *d
jack_error ("cannot read port connection result from server");
return -1;
}
return req.status;
}

@@ -1220,3 +1225,15 @@ jack_port_request_monitor (jack_client_t *client, const char *port_name, int ono
return req.status;
}
const char *
jack_port_name (const jack_port_t *port)
{
return port->shared->name;
}

void
jack_on_shutdown (jack_client_t *client, void (*function)(void *arg), void *arg)
{
client->on_shutdown = function;
client->on_shutdown_arg = arg;
}

+ 7
- 2
configure.in View File

@@ -23,7 +23,7 @@ AC_SUBST(JACK_RELEASE)

AM_INIT_AUTOMAKE(jack,${JACK_VERSION})

AM_PATH_GLIB(1.0.0,,[AC_MSG_ERROR([*** JACK requires glib, but it doesn't appear to be installed])])
AM_PATH_GLIB(1.0.0,,[AC_MSG_ERROR([*** JACK requires glib, but it does not appear to be installed])])

JACK_CFLAGS="-g -Wall -D_REENTRANT"
JACK_OPT_CFLAGS="-D_REENTRANT -O6 -Wall -fomit-frame-pointer -ffast-math -fstrength-reduce -funroll-loops -fmove-all-movables"
@@ -42,10 +42,15 @@ AC_ARG_ENABLE(fltk-client,
if test "x$enable_fltk_client" != "xno" ; then
AC_CHECK_LIB(fltk,main,
[ XTRA="$XTRA jack_fltk_client" ],
[ AC_MSG_ERROR([*** you can't build the FLTK client without the FLTK library])],
[ AC_MSG_ERROR([*** you cannot build the FLTK client without the FLTK library])],
[ -L/usr/X11R6/lib -lX11 -lXext ])
fi

AC_CHECK_LIB(sndfile,main,
[ XTRA="$XTRA jackrec" ],
[AC_MSG_WARN([*** the jackrec client will be skipped since you do not see to have libsndfile installed])]
)

AC_SUBST(XTRA)

AC_PROG_CXX


+ 145
- 60
engine.c View File

@@ -57,12 +57,13 @@ typedef struct _jack_client_internal {
int subgraph_start_fd;
int subgraph_wait_fd;
GSList *ports; /* protected by engine->graph_lock */
GSList *fed_by; /* protected by engine->graph_lock */
int shm_id;
int shm_key;
unsigned long rank;
struct _jack_client_internal *next_client; /* not a linked list! */
dlhandle handle;
} jack_client_internal_t;

static int jack_port_assign_buffer (jack_engine_t *, jack_port_internal_t *);
@@ -246,14 +247,17 @@ jack_cleanup_clients (jack_engine_t *engine)
x++;

pthread_mutex_lock (&engine->graph_lock);
for (node = engine->clients; node; node = g_slist_next (node)) {

for (node = engine->clients; node; node = g_slist_next (node)) {
client = (jack_client_internal_t *) node->data;
ctl = client->control;
printf ("client %s state = %d\n", ctl->name, ctl->state);
if (ctl->state > JACK_CLIENT_STATE_NOT_TRIGGERED) {
remove = g_slist_prepend (remove, node->data);
printf ("%d: removing failed client %s\n", x, client->control->name);
printf ("%d: removing failed client %s\n", x, ctl->name);
}
}
pthread_mutex_unlock (&engine->graph_lock);
@@ -370,7 +374,7 @@ jack_process (jack_engine_t *engine, nframes_t nframes)
struct pollfd pollfd[1];
char c;

// unsigned long then, now;
unsigned long then, now;
// rdtscl (then);

if (pthread_mutex_trylock (&engine->graph_lock) != 0) {
@@ -430,15 +434,18 @@ jack_process (jack_engine_t *engine, nframes_t nframes)
pollfd[0].fd = client->subgraph_wait_fd;
pollfd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL;

rdtscl (then);
if (poll (pollfd, 1, engine->driver->period_interval) < 0) {
jack_error ("engine cannot poll for graph completion (%s)", strerror (errno));
err++;
break;
}

rdtscl (now);
if (pollfd[0].revents == 0) {
jack_error ("subgraph starting at %s timed out (state = %d)",
client->control->name, client->control->state);
jack_error ("subgraph starting at %s timed out (state = %d) (time = %f usecs)",
client->control->name, client->control->state,
((float)(now - then))/450.0f);
err++;
break;
} else if (pollfd[0].revents & ~POLLIN) {
@@ -463,7 +470,6 @@ jack_process (jack_engine_t *engine, nframes_t nframes)
}
}
}
pthread_mutex_unlock (&engine->graph_lock);
if (err) {
@@ -726,6 +732,8 @@ jack_client_disconnect (jack_engine_t *engine, jack_client_internal_t *client)
}

g_slist_free (client->ports);
g_slist_free (client->fed_by);
client->fed_by = 0;
client->ports = 0;
}

@@ -738,16 +746,12 @@ jack_client_deactivate (jack_engine_t *engine, jack_client_id_t id, int to_wait)

pthread_mutex_lock (&engine->graph_lock);

printf ("trying ... deactivating client id %d\n", id);

for (node = engine->clients; node; node = g_slist_next (node)) {

jack_client_internal_t *client = (jack_client_internal_t *) node->data;

if (client->control->id == id) {
printf ("deactivating client id %d\n", id);

if (client == engine->timebase_client) {
engine->timebase_client = 0;
engine->control->frame_time = 0;
@@ -1192,7 +1196,7 @@ jack_audio_thread (void *arg)
{
jack_engine_t *engine = (jack_engine_t *) arg;
jack_driver_t *driver = engine->driver;
unsigned long start, end;
// unsigned long start, end;

if (engine->control->real_time) {
jack_become_real_time (pthread_self(), engine->rtpriority);
@@ -1207,11 +1211,11 @@ jack_audio_thread (void *arg)
}

while (1) {
start = end;
// start = end;
if (driver->wait (driver)) {
break;
}
rdtscl (end);
// rdtscl (end);
// printf ("driver cycle time: %.6f usecs\n", ((float) (end - start)) / 450.00f);
}

@@ -1298,6 +1302,7 @@ jack_client_internal_new (jack_engine_t *engine, int fd, jack_client_connect_req
client->request_fd = fd;
client->event_fd = -1;
client->ports = 0;
client->fed_by = 0;
client->rank = UINT_MAX;
client->next_client = NULL;
client->handle = NULL;
@@ -1378,7 +1383,6 @@ jack_remove_client (jack_engine_t *engine, jack_client_internal_t *client)
}

jack_client_disconnect (engine, client);
jack_client_do_deactivate (engine, client);

for (node = engine->clients; node; node = g_slist_next (node)) {
if (((jack_client_internal_t *) node->data)->control->id == client->control->id) {
@@ -1388,6 +1392,8 @@ jack_remove_client (jack_engine_t *engine, jack_client_internal_t *client)
}
}

jack_client_do_deactivate (engine, client);

/* rearrange the pollfd array so that things work right the
next time we go into poll(2).
*/
@@ -1395,7 +1401,7 @@ jack_remove_client (jack_engine_t *engine, jack_client_internal_t *client)
for (i = 0; i < engine->pfd_max; i++) {
if (engine->pfd[i].fd == client->request_fd) {
if (i+1 < engine->pfd_max) {
memcpy (&engine->pfd[i], &engine->pfd[i+1], sizeof (struct pollfd) * (engine->pfd_max - i));
memmove (&engine->pfd[i], &engine->pfd[i+1], sizeof (struct pollfd) * (engine->pfd_max - i));
}
engine->pfd_max--;
}
@@ -1584,6 +1590,12 @@ jack_rechain_graph (jack_engine_t *engine, int take_lock)
}

if (jack_client_is_inprocess (client)) {

/* break the chain for the current subgraph. the server
will wait for chain on the nth FIFO, and will
then execute this in-process client.
*/

if (subgraph_client) {
subgraph_client->subgraph_wait_fd = jack_get_fifo_fd (engine, n);
}
@@ -1593,10 +1605,15 @@ jack_rechain_graph (jack_engine_t *engine, int take_lock)
} else {

if (subgraph_client == 0) {

/* start a new subgraph. the engine will start the chain
by writing to the nth FIFO.
*/

subgraph_client = client;
subgraph_client->subgraph_start_fd = jack_get_fifo_fd (engine, n);
}
}
if (set) {
jack_client_set_order (engine, client);
}
@@ -1631,73 +1648,138 @@ jack_rechain_graph (jack_engine_t *engine, int take_lock)
return err;
}

int
jack_client_connected (jack_client_internal_t *a, jack_client_internal_t *b)
static void
jack_trace_terminal (jack_client_internal_t *c1, jack_client_internal_t *rbase)
{
jack_client_internal_t *c2;

/* make a copy of the existing list of routes that feed c1 */

GSList *existing;
GSList *node;

if (c1->fed_by == 0) {
return;
}

existing = g_slist_copy (c1->fed_by);

/* for each route that feeds c1, recurse, marking it as feeding
rbase as well.
*/

for (node = existing; node; node = g_slist_next (node)) {

c2 = (jack_client_internal_t *) node->data;

/* c2 is a route that feeds c1 which somehow feeds base. mark
base as being fed by c2
*/

rbase->fed_by = g_slist_prepend (rbase->fed_by, c2);

if (c2 != rbase && c2 != c1) {

/* now recurse, so that we can mark base as being fed by
all routes that feed c2
*/

jack_trace_terminal (c2, rbase);
}

}
}

static int
jack_client_sort (jack_client_internal_t *a, jack_client_internal_t *b)

{
GSList *pnode, *cnode;
int ret = 0;
/* the driver client always comes after everything else */

if (a->control->type == ClientDriver) {
return 1;
}

/* Check every port on the first client for a connection to
the second client.
if (b->control->type == ClientDriver) {
return -1;
}

Return -1 if a should execute before b
Return 1 if a should execute after b
Return 0 if they are not connected (ie. it doesn't matter)
if (g_slist_find (a->fed_by, b)) {
/* a comes after b */
return 1;
} else if (g_slist_find (b->fed_by, a)) {
/* b comes after a */
return -1;
} else {
/* we don't care */
return 0;
}
}

static int
jack_client_feeds (jack_client_internal_t *might, jack_client_internal_t *target)
{
GSList *pnode, *cnode;

If there is a feedback loop between a and b, the result
is undefined (the first connected port will be used to
determine the result). This is "OK", since there is no
correct execution order in that case.
/* Check every port of `might' for an outbound connection to `target'
*/

for (pnode = a->ports; pnode; pnode = g_slist_next (pnode)) {
for (pnode = might->ports; pnode; pnode = g_slist_next (pnode)) {

jack_port_internal_t *port;
port = (jack_port_internal_t *) pnode->data;

for (cnode = port->connections; cnode; cnode = g_slist_next (cnode)) {

jack_connection_internal_t *c;

c = (jack_connection_internal_t *) cnode->data;
if (c->source->shared->client_id == b->control->id) {
/* b is the source, so a should be
executed *after* b.
*/

ret = 1;
break;

} else if (c->source->shared->client_id == a->control->id) {

/* a is the source, so a should be
executed *before* b
*/

ret = -1;
break;
if (c->source->shared->client_id == might->control->id &&
c->destination->shared->client_id == target->control->id) {
return 1;
}
}

if (ret) {
break;
}
}
return ret;
return 0;
}

static void
jack_sort_graph (jack_engine_t *engine, int take_lock)

{
GSList *node, *onode;
jack_client_internal_t *client;
jack_client_internal_t *oclient;

if (take_lock) {
pthread_mutex_lock (&engine->graph_lock);
}

engine->clients = g_slist_sort (engine->clients, (GCompareFunc) jack_client_connected);
for (node = engine->clients; node; node = g_slist_next (node)) {

client = (jack_client_internal_t *) node->data;

g_slist_free (client->fed_by);
client->fed_by = 0;

for (onode = engine->clients; onode; onode = g_slist_next (onode)) {
oclient = (jack_client_internal_t *) onode->data;

if (jack_client_feeds (oclient, client)) {
client->fed_by = g_slist_prepend (client->fed_by, oclient);
}
}
}

for (node = engine->clients; node; node = g_slist_next (node)) {
jack_trace_terminal ((jack_client_internal_t *) node->data,
(jack_client_internal_t *) node->data);
}

engine->clients = g_slist_sort (engine->clients, (GCompareFunc) jack_client_sort);
jack_rechain_graph (engine, FALSE);

if (take_lock) {
@@ -1755,6 +1837,7 @@ jack_port_do_connect (jack_engine_t *engine,
if (dstport->shared->type_info.mixdown == NULL && dstport->connections) {
jack_error ("cannot make multiple connections to a port of type [%s]", dstport->shared->type_info.type_name);
free (connection);
return -1;
} else {
dstport->connections = g_slist_prepend (dstport->connections, connection);
srcport->connections = g_slist_prepend (srcport->connections, connection);
@@ -1811,6 +1894,10 @@ jack_port_disconnect_internal (jack_engine_t *engine,
jack_sort_graph (engine, FALSE);
}

if (ret == -1) {
printf ("disconnect failed\n");
}

return ret;
}

@@ -1887,7 +1974,7 @@ jack_get_fifo_fd (jack_engine_t *engine, int which_fifo)
return -1;
}
}
return engine->fifo[which_fifo];
}

@@ -2191,8 +2278,6 @@ jack_send_connection_notification (jack_engine_t *engine, jack_client_id_t clien
return -1;
}

fprintf (stderr, "sending connection to client %s\n", client->control->name);

event.type = (connected ? PortConnected : PortDisconnected);
event.x.self_id = self_id;
event.y.other_id = other_id;


+ 8
- 9
fltk_client.cc View File

@@ -11,8 +11,8 @@ extern "C"
#include <FL/Fl_Window.H>
#include <FL/Fl_Slider.H>

jack_port_t *my_input_port;
jack_port_t *my_output_port;
jack_port_t *input_port;
jack_port_t *output_port;

float gain = 0.0; /* slider starts out with zero gain */

@@ -20,8 +20,8 @@ int
process (nframes_t nframes, void *arg)

{
sample_t *out = (sample_t *) jack_port_get_buffer (my_output_port, nframes);
sample_t *in = (sample_t *) jack_port_get_buffer (my_input_port, nframes);
sample_t *out = (sample_t *) jack_port_get_buffer (output_port, nframes);
sample_t *in = (sample_t *) jack_port_get_buffer (input_port, nframes);

while (nframes--)
out[nframes] = in[nframes] * gain;
@@ -72,8 +72,8 @@ main (int argc, char *argv[])

printf ("engine sample rate: %lu\n", jack_get_sample_rate (client));

my_input_port = jack_port_register (client, "myinput", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
my_output_port = jack_port_register (client, "myoutput", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
input_port = jack_port_register (client, "input", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
output_port = jack_port_register (client, "output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);

if (jack_activate (client)) {
fprintf (stderr, "cannot activate client");
@@ -81,12 +81,11 @@ main (int argc, char *argv[])

printf ("client activated\n");


if (jack_port_connect (client, "ALSA I/O:Input 1", "myinput")) {
if (jack_port_connect (client, "ALSA I/O:Input 1", jack_port_name (input_port))) {
fprintf (stderr, "cannot connect input ports\n");
}

if (jack_port_connect (client, "myoutput", "ALSA I/O:Output 1")) {
if (jack_port_connect (client, jack_port_name (output_port), "ALSA I/O:Output 1")) {
fprintf (stderr, "cannot connect output ports\n");
}



+ 1
- 1
jack/alsa_driver.h View File

@@ -49,7 +49,7 @@ typedef struct {
char **capture_addr;
const snd_pcm_channel_area_t *capture_areas;
const snd_pcm_channel_area_t *playback_areas;
unsigned long time_at_interrupt;
unsigned long long time_at_interrupt;
struct pollfd pfd;
unsigned long interleave_unit;
unsigned long capture_interleave_skip;


+ 22
- 1
jack/jack.h View File

@@ -29,7 +29,23 @@ extern "C" {
#include <jack/error.h>

jack_client_t *jack_client_new (const char *client_name);
int jack_client_close (jack_client_t *client);
int jack_client_close (jack_client_t *client);

/* register a function (and argument) to be called if and when the
JACK server shuts down the client thread. the function must
be written as if it were an asynchonrous POSIX signal
handler - use only async functions, and remember that it
is executed from another thread. a typical function might
set a flag or write to a pipe so that the rest of the
application knows that the JACK client thread has shut
down.

NOTE: clients do not need to call this. it exists only
to help more complex clients understand what is going
on. if called, it must be called before jack_client_activate().
*/

void jack_on_shutdown (jack_client_t *, void (*function)(void *arg), void *arg);

int jack_set_process_callback (jack_client_t *, JackProcessCallback, void *arg);
int jack_set_buffer_size_callback (jack_client_t *, JackBufferSizeCallback, void *arg);
@@ -107,6 +123,10 @@ jack_port_register (jack_client_t *,

int jack_port_unregister (jack_client_t *, jack_port_t *);

/* a port is an opaque type, and its name is not inferable */

const char * jack_port_name (const jack_port_t *port);

/* This returns a pointer to the memory area associated with the
specified port. It can only be called from within the client's
"process" callback. For an output port, it will be a memory area
@@ -217,6 +237,7 @@ jack_port_t **jack_get_ports (jack_client_t *,
int jack_engine_takeover_timebase (jack_client_t *);
void jack_update_time (jack_client_t *, nframes_t);


#ifdef __cplusplus
}
#endif


+ 8
- 8
simple_client.c View File

@@ -4,15 +4,15 @@

#include <jack/jack.h>

jack_port_t *my_input_port;
jack_port_t *my_output_port;
jack_port_t *input_port;
jack_port_t *output_port;

int
process (nframes_t nframes, void *arg)

{
sample_t *out = (sample_t *) jack_port_get_buffer (my_output_port, nframes);
sample_t *in = (sample_t *) jack_port_get_buffer (my_input_port, nframes);
sample_t *out = (sample_t *) jack_port_get_buffer (output_port, nframes);
sample_t *in = (sample_t *) jack_port_get_buffer (input_port, nframes);

memcpy (out, in, sizeof (sample_t) * nframes);

@@ -57,8 +57,8 @@ main (int argc, char *argv[])

printf ("engine sample rate: %lu\n", jack_get_sample_rate (client));

my_input_port = jack_port_register (client, "myinput", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
my_output_port = jack_port_register (client, "myoutput", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
input_port = jack_port_register (client, "input", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
output_port = jack_port_register (client, "output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);

if (jack_activate (client)) {
fprintf (stderr, "cannot activate client");
@@ -66,11 +66,11 @@ main (int argc, char *argv[])

printf ("client activated\n");

if (jack_port_connect (client, "ALSA I/O:Input 1", "myinput")) {
if (jack_port_connect (client, "ALSA I/O:Input 1", jack_port_name (input_port))) {
fprintf (stderr, "cannot connect input ports\n");
}
if (jack_port_connect (client, "myoutput", "ALSA I/O:Output 1")) {
if (jack_port_connect (client, jack_port_name (output_port), "ALSA I/O:Output 1")) {
fprintf (stderr, "cannot connect output ports\n");
}



Loading…
Cancel
Save