Add basic Jack session support.
parent
fa25596e6f
commit
a138c37a0e
31
jackdriver.c
31
jackdriver.c
|
@ -40,6 +40,7 @@
|
|||
#include <jack/jack.h>
|
||||
#include <jack/midiport.h>
|
||||
#include <jack/ringbuffer.h>
|
||||
#include <jack/session.h>
|
||||
#include "jackdriver.h"
|
||||
|
||||
|
||||
|
@ -369,13 +370,35 @@ int pop_midi(void* seqq, uint8_t msg[], uint8_t *port_no)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int jack_shutdown;
|
||||
int jack_quit;
|
||||
|
||||
void
|
||||
shutdown_callback()
|
||||
{
|
||||
// we can't do anything fancy here, just ping the main thread
|
||||
jack_shutdown = 1;
|
||||
jack_quit = -1;
|
||||
}
|
||||
|
||||
char *jack_command_line = "midizap";
|
||||
|
||||
void
|
||||
session_callback(jack_session_event_t *event, void *seqq)
|
||||
{
|
||||
JACK_SEQ* seq = (JACK_SEQ*)seqq;
|
||||
// XXXTODO: In order to better support Jack session management in the future
|
||||
// we may want to copy over the loaded midizaprc file and store it in the
|
||||
// session dir, so that we can reload it from there later. For the time
|
||||
// being, we simply record the command line here.
|
||||
//printf("path %s, uuid %s, type: %s\n", event->session_dir, event->client_uuid, event->type == JackSessionSave ? "save" : "quit");
|
||||
|
||||
event->command_line = strdup(jack_command_line);
|
||||
jack_session_reply(seq->jack_client, event);
|
||||
|
||||
if (event->type == JackSessionSaveAndQuit) {
|
||||
jack_quit = 1;
|
||||
}
|
||||
|
||||
jack_session_event_free (event);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
@ -409,6 +432,9 @@ init_jack(JACK_SEQ* seq, uint8_t verbose)
|
|||
if(verbose)printf("assigning shutdown callback...\n");
|
||||
jack_on_shutdown(seq->jack_client, shutdown_callback, (void*)seq);
|
||||
|
||||
if(verbose)printf("assigning session callback...\n");
|
||||
jack_set_session_callback(seq->jack_client, session_callback, (void*)seq);
|
||||
|
||||
if(verbose)printf("assigning process callback...\n");
|
||||
err = jack_set_process_callback(seq->jack_client, process_callback, (void*)seq);
|
||||
if (err)
|
||||
|
@ -519,4 +545,5 @@ void close_jack(JACK_SEQ* seq)
|
|||
for (k = 0; k < seq->n_in; k++)
|
||||
jack_ringbuffer_free(seq->ringbuffer_in[k]);
|
||||
}
|
||||
jack_client_close(seq->jack_client);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,9 @@ typedef struct _jseq
|
|||
uint8_t n_out;
|
||||
} JACK_SEQ;
|
||||
|
||||
extern int jack_shutdown;
|
||||
extern int jack_quit;
|
||||
// This is supposed to be set properly by main().
|
||||
extern char *jack_command_line;
|
||||
|
||||
int init_jack(JACK_SEQ* seq, uint8_t verbose);
|
||||
void close_jack(JACK_SEQ* seq);
|
||||
|
|
90
midizap.c
90
midizap.c
|
@ -798,6 +798,58 @@ void quitter()
|
|||
quit = 1;
|
||||
}
|
||||
|
||||
// Helper functions to process the command line, so that we can pass it to
|
||||
// Jack session management.
|
||||
|
||||
static char *command_line;
|
||||
static size_t len;
|
||||
|
||||
static void add_command(char *arg)
|
||||
{
|
||||
char *a = arg;
|
||||
// Do some simplistic quoting if the argument contains blanks. This won't do
|
||||
// the right thing if the argument also contains quotes. Oh well.
|
||||
if ((strchr(a, ' ') || strchr(a, '\t')) && !strchr(a, '"')) {
|
||||
a = malloc(strlen(arg)+3);
|
||||
sprintf(a, "\"%s\"", arg);
|
||||
}
|
||||
if (!command_line) {
|
||||
len = strlen(a);
|
||||
command_line = malloc(len+1);
|
||||
strcpy(command_line, a);
|
||||
} else {
|
||||
size_t l = strlen(a)+1;
|
||||
command_line = realloc(command_line, len+l+1);
|
||||
command_line[len] = ' ';
|
||||
strcpy(command_line+len+1, a);
|
||||
len += l;
|
||||
}
|
||||
if (a != arg) free(a);
|
||||
}
|
||||
|
||||
static char *absolute_path(char *name)
|
||||
{
|
||||
if (*name == '/') {
|
||||
return name;
|
||||
} else {
|
||||
// This is a relative pathname, we turn it into a canonicalized absolute
|
||||
// path. NOTE: This requires glibc. We should probably rewrite this code
|
||||
// to be more portable.
|
||||
char *pwd = getcwd(NULL, 0);
|
||||
if (!pwd) {
|
||||
perror("getcwd");
|
||||
return name;
|
||||
} else {
|
||||
char *path = malloc(strlen(pwd)+strlen(name)+2);
|
||||
static char abspath[PATH_MAX];
|
||||
sprintf(path, "%s/%s", pwd, name);
|
||||
realpath(path, abspath);
|
||||
free(path); free(pwd);
|
||||
return abspath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// poll interval in microsec (this shouldn't be too large to avoid jitter)
|
||||
#define POLL_INTERVAL 1000
|
||||
// how often we check the config file per sec (> 0, < 1000000/POLL_INTERVAL)
|
||||
|
@ -810,6 +862,9 @@ main(int argc, char **argv)
|
|||
uint8_t msg[3];
|
||||
int opt, count = 0;
|
||||
|
||||
// Start recording the command line to be passed to Jack session management.
|
||||
add_command(argv[0]);
|
||||
|
||||
while ((opt = getopt(argc, argv, "hko::d::j:r:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
|
@ -818,23 +873,29 @@ main(int argc, char **argv)
|
|||
case 'k':
|
||||
// see comment on -k and keydown_tracker above
|
||||
keydown_tracker = 1;
|
||||
add_command("-k");
|
||||
break;
|
||||
case 'o':
|
||||
jack_num_outputs = 1;
|
||||
if (optarg && *optarg) {
|
||||
const char *a = optarg;
|
||||
if (*a == '2') {
|
||||
if (!strcmp(a, "2")) {
|
||||
jack_num_outputs = 2;
|
||||
} else if (*a && *a != '1') {
|
||||
add_command("-o2");
|
||||
} else if (strcmp(a, "1")) {
|
||||
fprintf(stderr, "%s: wrong port number (-o), must be 1 or 2\n", argv[0]);
|
||||
fprintf(stderr, "Try -h for help.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
} else
|
||||
add_command("-o1");
|
||||
} else
|
||||
add_command("-o");
|
||||
break;
|
||||
case 'd':
|
||||
if (optarg && *optarg) {
|
||||
const char *a = optarg;
|
||||
const char *a = optarg; char buf[100];
|
||||
snprintf(buf, 100, "-d%s", optarg);
|
||||
add_command(buf);
|
||||
while (*a) {
|
||||
switch (*a) {
|
||||
case 'r':
|
||||
|
@ -863,13 +924,20 @@ main(int argc, char **argv)
|
|||
default_debug_regex = default_debug_strokes = default_debug_keys =
|
||||
default_debug_midi = 1;
|
||||
debug_jack = 1;
|
||||
add_command("-d");
|
||||
}
|
||||
break;
|
||||
case 'j':
|
||||
jack_client_name = optarg;
|
||||
add_command("-j");
|
||||
add_command(optarg);
|
||||
break;
|
||||
case 'r':
|
||||
config_file_name = optarg;
|
||||
add_command("-r");
|
||||
// We need to convert this to an absolute pathname for Jack session
|
||||
// management.
|
||||
add_command(absolute_path(optarg));
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Try -h for help.\n");
|
||||
|
@ -882,6 +950,8 @@ main(int argc, char **argv)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if (command_line) jack_command_line = command_line;
|
||||
|
||||
initdisplay();
|
||||
|
||||
// Force the config file to be loaded initially, so that we pick up the Jack
|
||||
|
@ -897,11 +967,14 @@ main(int argc, char **argv)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
int do_flush = debug_regex || debug_strokes || debug_keys || debug_midi ||
|
||||
debug_jack;
|
||||
signal(SIGINT, quitter);
|
||||
while (!quit) {
|
||||
uint8_t portno;
|
||||
if (jack_shutdown) {
|
||||
fprintf(stderr, "%s: jack shutting down, exiting\n", argv[0]);
|
||||
if (jack_quit) {
|
||||
printf("[jack %s, exiting]\n",
|
||||
(jack_quit>0)?"asked us to quit":"shutting down");
|
||||
close_jack(&seq);
|
||||
exit(0);
|
||||
}
|
||||
|
@ -918,6 +991,9 @@ main(int argc, char **argv)
|
|||
if (read_config_file()) last_focused_window = 0;
|
||||
count = 0;
|
||||
}
|
||||
// Make sure that debugging output gets flushed every once in a while (may
|
||||
// be buffered when midizap is running inside a QjackCtl session).
|
||||
if (do_flush) fflush(NULL);
|
||||
}
|
||||
printf(" [exiting]\n");
|
||||
close_jack(&seq);
|
||||
|
|
Loading…
Reference in New Issue