|
|
|
@@ -50,76 +50,77 @@ volatile int time_reset = 1; /* true when time values change */ |
|
|
|
void timebase(jack_transport_state_t state, jack_nframes_t nframes, |
|
|
|
jack_position_t *pos, int new_pos, void *arg) |
|
|
|
{ |
|
|
|
double min; /* minutes since frame 0 */ |
|
|
|
long abs_tick; /* ticks since frame 0 */ |
|
|
|
long abs_beat; /* beats since frame 0 */ |
|
|
|
double min; /* minutes since frame 0 */ |
|
|
|
long abs_tick; /* ticks since frame 0 */ |
|
|
|
long abs_beat; /* beats since frame 0 */ |
|
|
|
|
|
|
|
if (new_pos || time_reset) { |
|
|
|
if (new_pos || time_reset) { |
|
|
|
|
|
|
|
pos->valid = JackPositionBBT; |
|
|
|
pos->beats_per_bar = time_beats_per_bar; |
|
|
|
pos->beat_type = time_beat_type; |
|
|
|
pos->ticks_per_beat = time_ticks_per_beat; |
|
|
|
pos->beats_per_minute = time_beats_per_minute; |
|
|
|
pos->valid = JackPositionBBT; |
|
|
|
pos->beats_per_bar = time_beats_per_bar; |
|
|
|
pos->beat_type = time_beat_type; |
|
|
|
pos->ticks_per_beat = time_ticks_per_beat; |
|
|
|
pos->beats_per_minute = time_beats_per_minute; |
|
|
|
|
|
|
|
time_reset = 0; /* time change complete */ |
|
|
|
time_reset = 0; /* time change complete */ |
|
|
|
|
|
|
|
/* Compute BBT info from frame number. This is relatively |
|
|
|
* simple here, but would become complex if we supported tempo |
|
|
|
* or time signature changes at specific locations in the |
|
|
|
* transport timeline. */ |
|
|
|
/* Compute BBT info from frame number. This is relatively |
|
|
|
* simple here, but would become complex if we supported tempo |
|
|
|
* or time signature changes at specific locations in the |
|
|
|
* transport timeline. */ |
|
|
|
|
|
|
|
min = pos->frame / ((double) pos->frame_rate * 60.0); |
|
|
|
abs_tick = min * pos->beats_per_minute * pos->ticks_per_beat; |
|
|
|
abs_beat = abs_tick / pos->ticks_per_beat; |
|
|
|
min = pos->frame / ((double) pos->frame_rate * 60.0); |
|
|
|
abs_tick = min * pos->beats_per_minute * pos->ticks_per_beat; |
|
|
|
abs_beat = abs_tick / pos->ticks_per_beat; |
|
|
|
|
|
|
|
pos->bar = abs_beat / pos->beats_per_bar; |
|
|
|
pos->beat = abs_beat - (pos->bar * pos->beats_per_bar) + 1; |
|
|
|
pos->tick = abs_tick - (abs_beat * pos->ticks_per_beat); |
|
|
|
pos->bar_start_tick = pos->bar * pos->beats_per_bar * |
|
|
|
pos->ticks_per_beat; |
|
|
|
pos->bar++; /* adjust start to bar 1 */ |
|
|
|
pos->bar = abs_beat / pos->beats_per_bar; |
|
|
|
pos->beat = abs_beat - (pos->bar * pos->beats_per_bar) + 1; |
|
|
|
pos->tick = abs_tick - (abs_beat * pos->ticks_per_beat); |
|
|
|
pos->bar_start_tick = pos->bar * pos->beats_per_bar * |
|
|
|
pos->ticks_per_beat; |
|
|
|
pos->bar++; /* adjust start to bar 1 */ |
|
|
|
|
|
|
|
#if 0 |
|
|
|
/* some debug code... */ |
|
|
|
fprintf(stderr, "\nnew position: %" PRIu32 "\tBBT: %3" |
|
|
|
PRIi32 "|%" PRIi32 "|%04" PRIi32 "\n", |
|
|
|
pos->frame, pos->bar, pos->beat, pos->tick); |
|
|
|
/* some debug code... */ |
|
|
|
fprintf(stderr, "\nnew position: %" PRIu32 "\tBBT: %3" |
|
|
|
PRIi32 "|%" PRIi32 "|%04" PRIi32 "\n", |
|
|
|
pos->frame, pos->bar, pos->beat, pos->tick); |
|
|
|
#endif |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
/* Compute BBT info based on previous period. */ |
|
|
|
pos->tick += |
|
|
|
nframes * pos->ticks_per_beat * pos->beats_per_minute |
|
|
|
/ (pos->frame_rate * 60); |
|
|
|
|
|
|
|
while (pos->tick >= pos->ticks_per_beat) { |
|
|
|
pos->tick -= pos->ticks_per_beat; |
|
|
|
if (++pos->beat > pos->beats_per_bar) { |
|
|
|
pos->beat = 1; |
|
|
|
++pos->bar; |
|
|
|
pos->bar_start_tick += |
|
|
|
pos->beats_per_bar * pos->ticks_per_beat; |
|
|
|
} |
|
|
|
} else { |
|
|
|
|
|
|
|
/* Compute BBT info based on previous period. */ |
|
|
|
pos->tick += |
|
|
|
nframes * pos->ticks_per_beat * pos->beats_per_minute |
|
|
|
/ (pos->frame_rate * 60); |
|
|
|
|
|
|
|
while (pos->tick >= pos->ticks_per_beat) { |
|
|
|
pos->tick -= pos->ticks_per_beat; |
|
|
|
if (++pos->beat > pos->beats_per_bar) { |
|
|
|
pos->beat = 1; |
|
|
|
++pos->bar; |
|
|
|
pos->bar_start_tick += |
|
|
|
pos->beats_per_bar |
|
|
|
* pos->ticks_per_beat; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void jack_shutdown(void *arg) |
|
|
|
{ |
|
|
|
#if defined(RL_READLINE_VERSION) && RL_READLINE_VERSION >= 0x0400 |
|
|
|
rl_cleanup_after_signal(); |
|
|
|
rl_cleanup_after_signal(); |
|
|
|
#endif |
|
|
|
fprintf(stderr, "JACK shut down, exiting ...\n"); |
|
|
|
exit(1); |
|
|
|
fprintf(stderr, "JACK shut down, exiting ...\n"); |
|
|
|
exit(1); |
|
|
|
} |
|
|
|
|
|
|
|
void signal_handler(int sig) |
|
|
|
{ |
|
|
|
jack_client_close(client); |
|
|
|
fprintf(stderr, "signal received, exiting ...\n"); |
|
|
|
exit(0); |
|
|
|
jack_client_close(client); |
|
|
|
fprintf(stderr, "signal received, exiting ...\n"); |
|
|
|
exit(0); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@@ -127,65 +128,65 @@ void signal_handler(int sig) |
|
|
|
|
|
|
|
void com_exit(char *arg) |
|
|
|
{ |
|
|
|
done = 1; |
|
|
|
done = 1; |
|
|
|
} |
|
|
|
|
|
|
|
void com_help(char *); /* forward declaration */ |
|
|
|
|
|
|
|
void com_locate(char *arg) |
|
|
|
{ |
|
|
|
jack_nframes_t frame = 0; |
|
|
|
jack_nframes_t frame = 0; |
|
|
|
|
|
|
|
if (*arg != '\0') |
|
|
|
frame = atoi(arg); |
|
|
|
if (*arg != '\0') |
|
|
|
frame = atoi(arg); |
|
|
|
|
|
|
|
jack_transport_locate(client, frame); |
|
|
|
jack_transport_locate(client, frame); |
|
|
|
} |
|
|
|
|
|
|
|
void com_master(char *arg) |
|
|
|
{ |
|
|
|
int cond = (*arg != '\0'); |
|
|
|
if (jack_set_timebase_callback(client, cond, timebase, NULL) != 0) |
|
|
|
fprintf(stderr, "Unable to take over timebase.\n"); |
|
|
|
int cond = (*arg != '\0'); |
|
|
|
if (jack_set_timebase_callback(client, cond, timebase, NULL) != 0) |
|
|
|
fprintf(stderr, "Unable to take over timebase.\n"); |
|
|
|
} |
|
|
|
|
|
|
|
void com_play(char *arg) |
|
|
|
{ |
|
|
|
jack_transport_start(client); |
|
|
|
jack_transport_start(client); |
|
|
|
} |
|
|
|
|
|
|
|
void com_release(char *arg) |
|
|
|
{ |
|
|
|
jack_release_timebase(client); |
|
|
|
jack_release_timebase(client); |
|
|
|
} |
|
|
|
|
|
|
|
void com_stop(char *arg) |
|
|
|
{ |
|
|
|
jack_transport_stop(client); |
|
|
|
jack_transport_stop(client); |
|
|
|
} |
|
|
|
|
|
|
|
/* Change the tempo for the entire timeline, not just from the current |
|
|
|
* location. */ |
|
|
|
void com_tempo(char *arg) |
|
|
|
{ |
|
|
|
float tempo = 120.0; |
|
|
|
float tempo = 120.0; |
|
|
|
|
|
|
|
if (*arg != '\0') |
|
|
|
tempo = atof(arg); |
|
|
|
if (*arg != '\0') |
|
|
|
tempo = atof(arg); |
|
|
|
|
|
|
|
time_beats_per_minute = tempo; |
|
|
|
time_reset = 1; |
|
|
|
time_beats_per_minute = tempo; |
|
|
|
time_reset = 1; |
|
|
|
} |
|
|
|
|
|
|
|
/* Set sync timeout in seconds. */ |
|
|
|
void com_timeout(char *arg) |
|
|
|
{ |
|
|
|
double timeout = 2.0; |
|
|
|
double timeout = 2.0; |
|
|
|
|
|
|
|
if (*arg != '\0') |
|
|
|
timeout = atof(arg); |
|
|
|
if (*arg != '\0') |
|
|
|
timeout = atof(arg); |
|
|
|
|
|
|
|
jack_set_sync_timeout(client, (jack_time_t) (timeout*1000000)); |
|
|
|
jack_set_sync_timeout(client, (jack_time_t) (timeout*1000000)); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@@ -195,241 +196,244 @@ typedef void cmd_function_t(char *); /* command function type */ |
|
|
|
|
|
|
|
/* Transport command table. */ |
|
|
|
typedef struct { |
|
|
|
char *name; /* User printable name of the function. */ |
|
|
|
cmd_function_t *func; /* Function to call to do the job. */ |
|
|
|
char *doc; /* Documentation for this function. */ |
|
|
|
char *name; /* user printable name */ |
|
|
|
cmd_function_t *func; /* function to call */ |
|
|
|
char *doc; /* documentation */ |
|
|
|
} command_t; |
|
|
|
|
|
|
|
/* command table must be in alphabetical order */ |
|
|
|
command_t commands[] = { |
|
|
|
{ "exit", com_exit, "Exit transport program" }, |
|
|
|
{ "help", com_help, "Display help text [<command>]" }, |
|
|
|
{ "locate", com_locate, "Locate to frame <position>" }, |
|
|
|
{ "master", com_master, "Become timebase master [<conditionally>]" }, |
|
|
|
{ "play", com_play, "Start transport rolling" }, |
|
|
|
{ "quit", com_exit, "Synonym for `exit'"}, |
|
|
|
{ "release", com_release, "Release timebase" }, |
|
|
|
{ "stop", com_stop, "Stop transport" }, |
|
|
|
{ "tempo", com_tempo, "Set beat tempo <beats_per_min>" }, |
|
|
|
{ "timeout", com_timeout, "Set sync timeout in <seconds>" }, |
|
|
|
{ "?", com_help, "Synonym for `help'" }, |
|
|
|
{ (char *)NULL, (cmd_function_t *)NULL, (char *)NULL } |
|
|
|
{"exit", com_exit, "Exit transport program"}, |
|
|
|
{"help", com_help, "Display help text [<command>]"}, |
|
|
|
{"locate", com_locate, "Locate to frame <position>"}, |
|
|
|
{"master", com_master, "Become timebase master " |
|
|
|
"[<conditionally>]"}, |
|
|
|
{"play", com_play, "Start transport rolling"}, |
|
|
|
{"quit", com_exit, "Synonym for `exit'"}, |
|
|
|
{"release", com_release, "Release timebase"}, |
|
|
|
{"stop", com_stop, "Stop transport"}, |
|
|
|
{"tempo", com_tempo, "Set beat tempo <beats_per_min>"}, |
|
|
|
{"timeout", com_timeout, "Set sync timeout in <seconds>"}, |
|
|
|
{"?", com_help, "Synonym for `help'" }, |
|
|
|
{(char *)NULL, (cmd_function_t *)NULL, (char *)NULL } |
|
|
|
}; |
|
|
|
|
|
|
|
command_t *find_command(char *name) |
|
|
|
{ |
|
|
|
register int i; |
|
|
|
size_t namelen; |
|
|
|
register int i; |
|
|
|
size_t namelen; |
|
|
|
|
|
|
|
if ((name == NULL) || (*name == '\0')) |
|
|
|
return ((command_t *)NULL); |
|
|
|
|
|
|
|
namelen = strlen(name); |
|
|
|
for (i = 0; commands[i].name; i++) |
|
|
|
if (strncmp(name, commands[i].name, namelen) == 0) { |
|
|
|
|
|
|
|
/* make sure the match is unique */ |
|
|
|
if ((commands[i+1].name) && |
|
|
|
(strncmp(name, commands[i+1].name, namelen) == 0)) |
|
|
|
if ((name == NULL) || (*name == '\0')) |
|
|
|
return ((command_t *)NULL); |
|
|
|
else |
|
|
|
return (&commands[i]); |
|
|
|
} |
|
|
|
|
|
|
|
namelen = strlen(name); |
|
|
|
for (i = 0; commands[i].name; i++) |
|
|
|
if (strncmp(name, commands[i].name, namelen) == 0) { |
|
|
|
|
|
|
|
/* make sure the match is unique */ |
|
|
|
if ((commands[i+1].name) && |
|
|
|
(strncmp(name, commands[i+1].name, namelen) == 0)) |
|
|
|
return ((command_t *)NULL); |
|
|
|
else |
|
|
|
return (&commands[i]); |
|
|
|
} |
|
|
|
|
|
|
|
return ((command_t *)NULL); |
|
|
|
return ((command_t *)NULL); |
|
|
|
} |
|
|
|
|
|
|
|
void com_help(char *arg) |
|
|
|
{ |
|
|
|
register int i; |
|
|
|
command_t *cmd; |
|
|
|
register int i; |
|
|
|
command_t *cmd; |
|
|
|
|
|
|
|
if (!*arg) { |
|
|
|
/* print help for all commands */ |
|
|
|
for (i = 0; commands[i].name; i++) { |
|
|
|
printf("%s\t\t%s.\n", commands[i].name, commands[i].doc); |
|
|
|
} |
|
|
|
if (!*arg) { |
|
|
|
/* print help for all commands */ |
|
|
|
for (i = 0; commands[i].name; i++) { |
|
|
|
printf("%s\t\t%s.\n", commands[i].name, |
|
|
|
commands[i].doc); |
|
|
|
} |
|
|
|
|
|
|
|
} else if ((cmd = find_command(arg))) { |
|
|
|
printf("%s\t\t%s.\n", cmd->name, cmd->doc); |
|
|
|
} else if ((cmd = find_command(arg))) { |
|
|
|
printf("%s\t\t%s.\n", cmd->name, cmd->doc); |
|
|
|
|
|
|
|
} else { |
|
|
|
int printed = 0; |
|
|
|
} else { |
|
|
|
int printed = 0; |
|
|
|
|
|
|
|
printf("No `%s' command. Valid command names are:\n", arg); |
|
|
|
printf("No `%s' command. Valid command names are:\n", arg); |
|
|
|
|
|
|
|
for (i = 0; commands[i].name; i++) { |
|
|
|
/* Print in six columns. */ |
|
|
|
if (printed == 6) { |
|
|
|
printed = 0; |
|
|
|
printf ("\n"); |
|
|
|
} |
|
|
|
for (i = 0; commands[i].name; i++) { |
|
|
|
/* Print in six columns. */ |
|
|
|
if (printed == 6) { |
|
|
|
printed = 0; |
|
|
|
printf ("\n"); |
|
|
|
} |
|
|
|
|
|
|
|
printf ("%s\t", commands[i].name); |
|
|
|
printed++; |
|
|
|
} |
|
|
|
printf ("%s\t", commands[i].name); |
|
|
|
printed++; |
|
|
|
} |
|
|
|
|
|
|
|
printf("\n\nTry `help [command]\' for more information.\n"); |
|
|
|
} |
|
|
|
printf("\n\nTry `help [command]\' for more information.\n"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void execute_command(char *line) |
|
|
|
{ |
|
|
|
register int i; |
|
|
|
command_t *command; |
|
|
|
char *word; |
|
|
|
register int i; |
|
|
|
command_t *command; |
|
|
|
char *word; |
|
|
|
|
|
|
|
/* Isolate the command word. */ |
|
|
|
i = 0; |
|
|
|
while (line[i] && whitespace(line[i])) |
|
|
|
i++; |
|
|
|
word = line + i; |
|
|
|
/* Isolate the command word. */ |
|
|
|
i = 0; |
|
|
|
while (line[i] && whitespace(line[i])) |
|
|
|
i++; |
|
|
|
word = line + i; |
|
|
|
|
|
|
|
while (line[i] && !whitespace(line[i])) |
|
|
|
i++; |
|
|
|
while (line[i] && !whitespace(line[i])) |
|
|
|
i++; |
|
|
|
|
|
|
|
if (line[i]) |
|
|
|
line[i++] = '\0'; |
|
|
|
if (line[i]) |
|
|
|
line[i++] = '\0'; |
|
|
|
|
|
|
|
command = find_command(word); |
|
|
|
command = find_command(word); |
|
|
|
|
|
|
|
if (!command) { |
|
|
|
fprintf(stderr, "%s: No such command. There is `help\'.\n", word); |
|
|
|
return; |
|
|
|
} |
|
|
|
if (!command) { |
|
|
|
fprintf(stderr, "%s: No such command. There is `help\'.\n", |
|
|
|
word); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
/* Get argument to command, if any. */ |
|
|
|
while (whitespace(line[i])) |
|
|
|
i++; |
|
|
|
/* Get argument to command, if any. */ |
|
|
|
while (whitespace(line[i])) |
|
|
|
i++; |
|
|
|
|
|
|
|
word = line + i; |
|
|
|
word = line + i; |
|
|
|
|
|
|
|
/* invoke the command function. */ |
|
|
|
(*command->func)(word); |
|
|
|
/* invoke the command function. */ |
|
|
|
(*command->func)(word); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Strip whitespace from the start and end of string. */ |
|
|
|
char *stripwhite(char *string) |
|
|
|
{ |
|
|
|
register char *s, *t; |
|
|
|
register char *s, *t; |
|
|
|
|
|
|
|
s = string; |
|
|
|
while (whitespace(*s)) |
|
|
|
s++; |
|
|
|
s = string; |
|
|
|
while (whitespace(*s)) |
|
|
|
s++; |
|
|
|
|
|
|
|
if (*s == '\0') |
|
|
|
return s; |
|
|
|
if (*s == '\0') |
|
|
|
return s; |
|
|
|
|
|
|
|
t = s + strlen (s) - 1; |
|
|
|
while (t > s && whitespace(*t)) |
|
|
|
t--; |
|
|
|
*++t = '\0'; |
|
|
|
t = s + strlen (s) - 1; |
|
|
|
while (t > s && whitespace(*t)) |
|
|
|
t--; |
|
|
|
*++t = '\0'; |
|
|
|
|
|
|
|
return s; |
|
|
|
return s; |
|
|
|
} |
|
|
|
|
|
|
|
char *dupstr(char *s) |
|
|
|
{ |
|
|
|
char *r = malloc(strlen(s) + 1); |
|
|
|
strcpy(r, s); |
|
|
|
return r; |
|
|
|
char *r = malloc(strlen(s) + 1); |
|
|
|
strcpy(r, s); |
|
|
|
return r; |
|
|
|
} |
|
|
|
|
|
|
|
/* Readline generator function for command completion. */ |
|
|
|
char *command_generator (const char *text, int state) |
|
|
|
{ |
|
|
|
static int list_index, len; |
|
|
|
char *name; |
|
|
|
static int list_index, len; |
|
|
|
char *name; |
|
|
|
|
|
|
|
/* If this is a new word to complete, initialize now. This |
|
|
|
includes saving the length of TEXT for efficiency, and |
|
|
|
initializing the index variable to 0. */ |
|
|
|
if (!state) { |
|
|
|
list_index = 0; |
|
|
|
len = strlen (text); |
|
|
|
} |
|
|
|
/* If this is a new word to complete, initialize now. This |
|
|
|
includes saving the length of TEXT for efficiency, and |
|
|
|
initializing the index variable to 0. */ |
|
|
|
if (!state) { |
|
|
|
list_index = 0; |
|
|
|
len = strlen (text); |
|
|
|
} |
|
|
|
|
|
|
|
/* Return the next name which partially matches from the |
|
|
|
command list. */ |
|
|
|
while ((name = commands[list_index].name)) { |
|
|
|
list_index++; |
|
|
|
/* Return the next name which partially matches from the |
|
|
|
command list. */ |
|
|
|
while ((name = commands[list_index].name)) { |
|
|
|
list_index++; |
|
|
|
|
|
|
|
if (strncmp(name, text, len) == 0) |
|
|
|
return dupstr(name); |
|
|
|
} |
|
|
|
if (strncmp(name, text, len) == 0) |
|
|
|
return dupstr(name); |
|
|
|
} |
|
|
|
|
|
|
|
return (char *) NULL; /* No names matched. */ |
|
|
|
return (char *) NULL; /* No names matched. */ |
|
|
|
} |
|
|
|
|
|
|
|
void command_loop() |
|
|
|
{ |
|
|
|
char *line, *cmd; |
|
|
|
char prompt[32]; |
|
|
|
char *line, *cmd; |
|
|
|
char prompt[32]; |
|
|
|
|
|
|
|
snprintf(prompt, sizeof(prompt), "%s> ", package); |
|
|
|
snprintf(prompt, sizeof(prompt), "%s> ", package); |
|
|
|
|
|
|
|
/* Allow conditional parsing of the ~/.inputrc file. */ |
|
|
|
rl_readline_name = package; |
|
|
|
/* Allow conditional parsing of the ~/.inputrc file. */ |
|
|
|
rl_readline_name = package; |
|
|
|
|
|
|
|
/* Define a custom completion function. */ |
|
|
|
rl_completion_entry_function = command_generator; |
|
|
|
/* Define a custom completion function. */ |
|
|
|
rl_completion_entry_function = command_generator; |
|
|
|
|
|
|
|
/* Read and execute commands until the user quits. */ |
|
|
|
while (!done) { |
|
|
|
/* Read and execute commands until the user quits. */ |
|
|
|
while (!done) { |
|
|
|
|
|
|
|
line = readline(prompt); |
|
|
|
line = readline(prompt); |
|
|
|
|
|
|
|
if (line == NULL) { /* EOF? */ |
|
|
|
printf("\n"); /* close out prompt */ |
|
|
|
done = 1; |
|
|
|
break; |
|
|
|
} |
|
|
|
if (line == NULL) { /* EOF? */ |
|
|
|
printf("\n"); /* close out prompt */ |
|
|
|
done = 1; |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
/* Remove leading and trailing whitespace from the line. */ |
|
|
|
cmd = stripwhite(line); |
|
|
|
|
|
|
|
/* If anything left, add to history and execute it. */ |
|
|
|
if (*cmd) |
|
|
|
{ |
|
|
|
add_history(cmd); |
|
|
|
execute_command(cmd); |
|
|
|
} |
|
|
|
/* Remove leading and trailing whitespace from the line. */ |
|
|
|
cmd = stripwhite(line); |
|
|
|
|
|
|
|
/* If anything left, add to history and execute it. */ |
|
|
|
if (*cmd) |
|
|
|
{ |
|
|
|
add_history(cmd); |
|
|
|
execute_command(cmd); |
|
|
|
} |
|
|
|
|
|
|
|
free(line); /* realine() called malloc() */ |
|
|
|
} |
|
|
|
free(line); /* realine() called malloc() */ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
int main(int argc, char *argv[]) |
|
|
|
{ |
|
|
|
/* basename $0 */ |
|
|
|
package = strrchr(argv[0], '/'); |
|
|
|
if (package == 0) |
|
|
|
package = argv[0]; |
|
|
|
else |
|
|
|
package++; |
|
|
|
|
|
|
|
/* become a new client of the JACK server */ |
|
|
|
if ((client = jack_client_new(package)) == 0) { |
|
|
|
fprintf(stderr, "jack server not running?\n"); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
signal(SIGQUIT, signal_handler); |
|
|
|
signal(SIGTERM, signal_handler); |
|
|
|
signal(SIGHUP, signal_handler); |
|
|
|
signal(SIGINT, signal_handler); |
|
|
|
|
|
|
|
jack_on_shutdown(client, jack_shutdown, 0); |
|
|
|
|
|
|
|
if (jack_activate(client)) { |
|
|
|
fprintf(stderr, "cannot activate client"); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
/* execute commands until done */ |
|
|
|
command_loop(); |
|
|
|
|
|
|
|
jack_client_close(client); |
|
|
|
exit(0); |
|
|
|
/* basename $0 */ |
|
|
|
package = strrchr(argv[0], '/'); |
|
|
|
if (package == 0) |
|
|
|
package = argv[0]; |
|
|
|
else |
|
|
|
package++; |
|
|
|
|
|
|
|
/* become a new client of the JACK server */ |
|
|
|
if ((client = jack_client_new(package)) == 0) { |
|
|
|
fprintf(stderr, "jack server not running?\n"); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
signal(SIGQUIT, signal_handler); |
|
|
|
signal(SIGTERM, signal_handler); |
|
|
|
signal(SIGHUP, signal_handler); |
|
|
|
signal(SIGINT, signal_handler); |
|
|
|
|
|
|
|
jack_on_shutdown(client, jack_shutdown, 0); |
|
|
|
|
|
|
|
if (jack_activate(client)) { |
|
|
|
fprintf(stderr, "cannot activate client"); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
/* execute commands until done */ |
|
|
|
command_loop(); |
|
|
|
|
|
|
|
jack_client_close(client); |
|
|
|
exit(0); |
|
|
|
} |