Browse Source

add jack_transport example client

git-svn-id: svn+ssh://jackaudio.org/trunk/jack@411 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/0.109.0
joq 23 years ago
parent
commit
e2183da65d
3 changed files with 364 additions and 2 deletions
  1. +7
    -1
      configure.in
  2. +20
    -1
      example-clients/Makefile.am
  3. +337
    -0
      example-clients/transport.c

+ 7
- 1
configure.in View File

@@ -14,7 +14,7 @@ dnl changes are made
dnl ---
JACK_MAJOR_VERSION=0
JACK_MINOR_VERSION=72
JACK_MICRO_VERSION=0
JACK_MICRO_VERSION=1

dnl ---
dnl HOWTO: updating the jack protocal version
@@ -247,6 +247,11 @@ if test x$HAVE_SNDFILE = xfalse; then
AC_MSG_WARN([*** the jackrec example client will not be built])
fi

AC_CHECK_LIB(readline, readline, [HAVE_READLINE=true], [HAVE_READLINE=false])
if test x$HAVE_READLINE = xfalse; then
AC_MSG_WARN([*** the jack_transport example client will not be built])
fi

# you need doxygen to make dist.
AC_CHECK_PROG(HAVE_DOXYGEN, doxygen, true, false)
if test $HAVE_DOXYGEN = "false"; then
@@ -254,6 +259,7 @@ if test $HAVE_DOXYGEN = "false"; then
fi

AM_CONDITIONAL(HAVE_SNDFILE, $HAVE_SNDFILE)
AM_CONDITIONAL(HAVE_READLINE, $HAVE_READLINE)
AM_CONDITIONAL(HAVE_DOXYGEN, $HAVE_DOXYGEN)
AM_CONDITIONAL(USE_CAPABILITIES, $USE_CAPABILITIES)
AM_CONDITIONAL(STRIPPED_JACKD, $STRIPPED_JACKD)


+ 20
- 1
example-clients/Makefile.am View File

@@ -12,6 +12,18 @@ dist-check-sndfile:
@false
endif

if HAVE_READLINE
JACK_TRANSPORT = jack_transport
dist-check-readline:
else
JACK_TRANSPORT =
dist-check-readline:
@echo
@echo ' ******' You need readline installed to make dist.' ******'
@echo
@false
endif

bin_PROGRAMS = jack_load \
jack_unload \
jack_simple_client \
@@ -22,7 +34,8 @@ bin_PROGRAMS = jack_load \
jack_metro \
jack_showtime \
jack_lsp \
jackrec
jackrec \
$(JACK_TRANSPORT)

if HAVE_SNDFILE
# note! jackrec_CFLAGS syntax not supported by automake-1.4
@@ -67,6 +80,12 @@ jackrec_LDFLAGS = @SNDFILE_LIBS@ -lrt -ldl -lpthread
jackrec_LDADD = ../libjack/libjack.la
endif

if HAVE_READLINE
jack_transport_SOURCES = transport.c
jack_transport_LDFLAGS = -lhistory -lreadline -lrt -ldl -lpthread
jack_transport_LDADD = ../libjack/libjack.la
endif

jack_impulse_grabber_SOURCES = impulse_grabber.c
jack_impulse_grabber_LDFLAGS = -lrt -ldl -lpthread -lm
jack_impulse_grabber_LDADD = ../libjack/libjack.la


+ 337
- 0
example-clients/transport.c View File

@@ -0,0 +1,337 @@
/*
* transport.c -- JACK transport master example client.
*
* Copyright (C) 2003 Jack O'Quin.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/* To compile:
* cc -o transport transport.c -lhistory -lreadline `pkg-config --libs jack`
*/

#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <jack/jack.h>
#include <jack/transport.h>

char *package; /* program name */
int done = 0;

jack_client_t *client;
jack_transport_info_t tinfo; /* multi-threaded access */


/* JACK process() handler.
*
* Runs in a separate realtime thread. Must not wait.
*/
int process(jack_nframes_t nframes, void *arg)
{
jack_set_transport_info(client, &tinfo);

/* frame number for next cycle */
if (tinfo.transport_state == JackTransportRolling)
tinfo.frame += nframes;

return 0;
}

void jack_shutdown(void *arg)
{
exit(1);
}

void signal_handler(int sig)
{
jack_client_close(client);
fprintf(stderr, "signal received, exiting ...\n");
exit(0);
}


/* command functions in alphabetical order */

void com_exit(char *arg)
{
done = 1;
}

void com_help(char *); /* forward declaration */

void com_play(char *arg)
{
tinfo.transport_state = JackTransportRolling;
}

void com_rewind(char *arg)
{
tinfo.transport_state = JackTransportStopped;
tinfo.frame = 0;
}

void com_stop(char *arg)
{
tinfo.transport_state = JackTransportStopped;
}


/* Command parsing based on GNU readline info examples. */

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. */
} command_t;
command_t commands[] = {
{ "exit", com_exit, "Exit transport program" },
{ "help", com_help, "Display help text" },
{ "play", com_play, "Start transport rolling" },
{ "quit", com_exit, "Synonym for `exit'"},
{ "rewind", com_rewind, "Reset transport position to beginning" },
{ "stop", com_stop, "Stop transport" },
{ "?", com_help, "Synonym for `help'" },
{ (char *)NULL, (cmd_function_t *)NULL, (char *)NULL }
};
command_t *find_command(char *name)
{
register int i;
for (i = 0; commands[i].name; i++)
if (strcmp (name, commands[i].name) == 0)
return (&commands[i]);
return ((command_t *)NULL);
}

void com_help(char *arg)
{
register int i;
int printed = 0;

/* print help for command arg */
for (i = 0; commands[i].name; i++) {
if (!*arg || (strcmp (arg, commands[i].name) == 0)) {
printf("%s\t\t%s.\n", commands[i].name, commands[i].doc);
printed++;
}
}

if (!printed) {

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

printf ("%s\t", commands[i].name);
printed++;
}

printf("\n\nType `help [command]\' for more information.\n");
}
}

void execute_command(char *line)
{
register int i;
command_t *command;
char *word;
/* Isolate the command word. */
i = 0;
while (line[i] && whitespace(line[i]))
i++;
word = line + i;
while (line[i] && !whitespace(line[i]))
i++;
if (line[i])
line[i++] = '\0';
command = find_command(word);
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++;
word = line + i;
/* invoke the command function. */
(*command->func)(word);
}


/* Strip whitespace from the start and end of string. */
char *stripwhite(char *string)
{
register char *s, *t;

s = string;
while (whitespace(*s))
s++;

if (*s == '\0')
return s;
t = s + strlen (s) - 1;
while (t > s && whitespace(*t))
t--;
*++t = '\0';
return s;
}
char *dupstr(char *s)
{
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;
/* 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++;
if (strncmp(name, text, len) == 0)
return dupstr(name);
}
return (char *) NULL; /* No names matched. */
}

void command_loop()
{
char *line, *cmd;
char prompt[32];

snprintf(prompt, sizeof(prompt), "%s> ", package);

/* Allow conditional parsing of the ~/.inputrc file. */
rl_readline_name = package;
/* Define a custom completion function. */
rl_completion_entry_function = command_generator;

/* Read and execute commands until the user quits. */
while (!done) {

line = readline(prompt);
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);
}
free(line); /* realine() called malloc() */
}
}

void initialize_transport()
{
/* must run before jack_activate */
tinfo.valid = JackTransportState | JackTransportPosition;
com_rewind(NULL);
}


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

if (jack_engine_takeover_timebase(client) != 0) {
fprintf(stderr, "Unable to take over timebase.\n");
fprintf(stderr, "Is another transport master already running?\n");
return 1;
}

jack_set_process_callback(client, process, 0);
jack_on_shutdown(client, jack_shutdown, 0);

initialize_transport();

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

/* execute commands until done */
command_loop();

jack_client_close(client);
exit(0);
}

Loading…
Cancel
Save