Add basic Jack session support.

master
Albert Graef 2018-08-16 00:10:41 +02:00
parent fa25596e6f
commit a138c37a0e
4 changed files with 116 additions and 10 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -2,6 +2,7 @@
// Copyright 2013 Eric Messick (FixedImagePhoto.com/Contact)
// Copyright 2018 Albert Graef <aggraef@gmail.com>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>