@@ -25,8 +25,9 @@ | |||
#include "alsathread.h" | |||
Jackclient::Jackclient (jack_client_t* cl, const char*jserv, int mode, int nchan) : | |||
Jackclient::Jackclient (jack_client_t* cl, const char*jserv, int mode, int nchan, void *arg) : | |||
_client (cl), | |||
_arg (arg), | |||
_mode (mode), | |||
_nchan (nchan), | |||
_state (INIT), | |||
@@ -31,7 +31,7 @@ class Jackclient | |||
{ | |||
public: | |||
Jackclient (jack_client_t*, const char *jserv, int mode, int nchan); | |||
Jackclient (jack_client_t*, const char *jserv, int mode, int nchan, void *arg); | |||
virtual ~Jackclient (void); | |||
enum { PLAY, CAPT }; | |||
@@ -51,6 +51,7 @@ public: | |||
int bsize (void) const { return _bsize; } | |||
int rprio (void) const { return _rprio; } | |||
void register_ports (int nports); | |||
void *getarg(void) const { return _arg; } | |||
private: | |||
@@ -80,6 +81,7 @@ private: | |||
jack_client_t *_client; | |||
jack_port_t *_ports [256]; | |||
void *_arg; | |||
const char *_jname; | |||
int _mode; | |||
int _nchan; | |||
@@ -27,25 +27,7 @@ | |||
#include "jackclient.h" | |||
#include "lfqueue.h" | |||
static Lfq_int32 commq (16); | |||
static Lfq_adata alsaq (256); | |||
static Lfq_jdata infoq (256); | |||
static Lfq_audio *audioq = 0; | |||
static bool stop = false; | |||
static const char *clopt = "hvLj:d:r:p:n:c:Q:I:"; | |||
static bool v_opt = false; | |||
static bool L_opt = false; | |||
static const char *jname = APPNAME; | |||
static const char *device = 0; | |||
static int fsamp = 0; // try to get from server if unspecified | |||
static int bsize = 0; // try to get from server if unspecified | |||
static int nfrag = 2; | |||
static int nchan = 2; | |||
static int rqual = 48; | |||
static int ltcor = 0; | |||
static const char *clopt = "hvLj:d:r:p:n:c:Q:I:"; | |||
static void help (void) | |||
{ | |||
@@ -68,57 +50,101 @@ static void help (void) | |||
exit (1); | |||
} | |||
static int procoptions (int ac, const char *av []) | |||
class zita_a2j | |||
{ | |||
int k; | |||
optind = 1; | |||
opterr = 0; | |||
while ((k = getopt (ac, (char **) av, (char *) clopt)) != -1) | |||
Lfq_int32 *commq; | |||
Lfq_adata *alsaq; | |||
Lfq_jdata *infoq; | |||
Lfq_audio *audioq; | |||
bool stop; | |||
bool v_opt; | |||
bool L_opt; | |||
char *jname; | |||
char *device; | |||
int fsamp; | |||
int bsize; | |||
int nfrag; | |||
int nchan; | |||
int rqual; | |||
int ltcor; | |||
public: | |||
zita_a2j() | |||
{ | |||
commq = new Lfq_int32(16); | |||
alsaq = new Lfq_adata(256); | |||
infoq = new Lfq_jdata(256); | |||
audioq = 0; | |||
stop = false; | |||
v_opt = false; | |||
L_opt = false; | |||
jname = strdup(APPNAME); | |||
device = 0; | |||
fsamp = 0; | |||
bsize = 0; | |||
nfrag = 2; | |||
nchan = 2; | |||
rqual = 48; | |||
ltcor = 0; | |||
A = 0; | |||
C = 0; | |||
J = 0; | |||
} | |||
private: | |||
int procoptions (int ac, const char *av []) | |||
{ | |||
if (optarg && (*optarg == '-')) | |||
int k; | |||
optind = 1; | |||
opterr = 0; | |||
while ((k = getopt (ac, (char **) av, (char *) clopt)) != -1) | |||
{ | |||
fprintf (stderr, " Missing argument for '-%c' option.\n", k); | |||
fprintf (stderr, " Use '-h' to see all options.\n"); | |||
exit (1); | |||
if (optarg && (*optarg == '-')) | |||
{ | |||
fprintf (stderr, " Missing argument for '-%c' option.\n", k); | |||
fprintf (stderr, " Use '-h' to see all options.\n"); | |||
exit (1); | |||
} | |||
switch (k) | |||
{ | |||
case 'h' : help (); exit (0); | |||
case 'v' : v_opt = true; break; | |||
case 'L' : L_opt = true; break; | |||
case 'j' : jname = optarg; break; | |||
case 'd' : device = optarg; break; | |||
case 'r' : fsamp = atoi (optarg); break; | |||
case 'p' : bsize = atoi (optarg); break; | |||
case 'n' : nfrag = atoi (optarg); break; | |||
case 'c' : nchan = atoi (optarg); break; | |||
case 'Q' : rqual = atoi (optarg); break; | |||
case 'I' : ltcor = atoi (optarg); break; | |||
case '?': | |||
if (optopt != ':' && strchr (clopt, optopt)) | |||
{ | |||
fprintf (stderr, " Missing argument for '-%c' option.\n", optopt); | |||
} | |||
else if (isprint (optopt)) | |||
{ | |||
fprintf (stderr, " Unknown option '-%c'.\n", optopt); | |||
} | |||
else | |||
{ | |||
fprintf (stderr, " Unknown option character '0x%02x'.\n", optopt & 255); | |||
} | |||
fprintf (stderr, " Use '-h' to see all options.\n"); | |||
return 1; | |||
default: | |||
return 1; | |||
} | |||
} | |||
switch (k) | |||
{ | |||
case 'h' : help (); exit (0); | |||
case 'v' : v_opt = true; break; | |||
case 'L' : L_opt = true; break; | |||
case 'j' : jname = optarg; break; | |||
case 'd' : device = optarg; break; | |||
case 'r' : fsamp = atoi (optarg); break; | |||
case 'p' : bsize = atoi (optarg); break; | |||
case 'n' : nfrag = atoi (optarg); break; | |||
case 'c' : nchan = atoi (optarg); break; | |||
case 'Q' : rqual = atoi (optarg); break; | |||
case 'I' : ltcor = atoi (optarg); break; | |||
case '?': | |||
if (optopt != ':' && strchr (clopt, optopt)) | |||
{ | |||
fprintf (stderr, " Missing argument for '-%c' option.\n", optopt); | |||
} | |||
else if (isprint (optopt)) | |||
{ | |||
fprintf (stderr, " Unknown option '-%c'.\n", optopt); | |||
} | |||
else | |||
{ | |||
fprintf (stderr, " Unknown option character '0x%02x'.\n", optopt & 255); | |||
} | |||
fprintf (stderr, " Use '-h' to see all options.\n"); | |||
return 1; | |||
default: | |||
return 1; | |||
} | |||
return 0; | |||
} | |||
return 0; | |||
} | |||
static int parse_options (const char* load_init) | |||
{ | |||
int parse_options (const char* load_init) | |||
{ | |||
int argsz; | |||
int argc = 0; | |||
const char** argv; | |||
@@ -127,8 +153,8 @@ static int parse_options (const char* load_init) | |||
char* ptr = args; | |||
char* savep; | |||
if (!load_init) { | |||
return 0; | |||
if (!load_init) { | |||
return 0; | |||
} | |||
argsz = 8; /* random guess at "maxargs" */ | |||
@@ -137,149 +163,166 @@ static int parse_options (const char* load_init) | |||
argv[argc++] = APPNAME; | |||
while (1) { | |||
if ((token = strtok_r (ptr, " ", &savep)) == NULL) { | |||
break; | |||
} | |||
if (argc == argsz) { | |||
argsz *= 2; | |||
argv = (const char **) realloc (argv, sizeof (char *) * argsz); | |||
} | |||
argv[argc++] = token; | |||
ptr = NULL; | |||
if ((token = strtok_r (ptr, " ", &savep)) == NULL) { | |||
break; | |||
} | |||
if (argc == argsz) { | |||
argsz *= 2; | |||
argv = (const char **) realloc (argv, sizeof (char *) * argsz); | |||
} | |||
argv[argc++] = token; | |||
ptr = NULL; | |||
} | |||
return procoptions (argc, argv); | |||
} | |||
static void printinfo (void) | |||
{ | |||
int n; | |||
double e, r; | |||
Jdata *J; | |||
} | |||
n = 0; | |||
e = r = 0; | |||
while (infoq.rd_avail ()) | |||
void printinfo (void) | |||
{ | |||
J = infoq.rd_datap (); | |||
if (J->_state == Jackclient::TERM) | |||
{ | |||
printf ("Fatal error condition, terminating.\n"); | |||
stop = true; | |||
return; | |||
} | |||
else if (J->_state == Jackclient::WAIT) | |||
{ | |||
printf ("Detected excessive timing errors, waiting 15 seconds.\n"); | |||
printf ("This may happen with current Jack1 after freewheeling.\n"); | |||
n = 0; | |||
} | |||
else if (J->_state == Jackclient::SYNC0) | |||
{ | |||
printf ("Starting synchronisation.\n"); | |||
} | |||
else if (v_opt) | |||
{ | |||
n++; | |||
e += J->_error; | |||
r += J->_ratio; | |||
} | |||
infoq.rd_commit (); | |||
} | |||
if (n) printf ("%8.3lf %10.6lf\n", e / n, r / n); | |||
} | |||
int n; | |||
double e, r; | |||
Jdata *J; | |||
n = 0; | |||
e = r = 0; | |||
while (infoq->rd_avail ()) | |||
{ | |||
J = infoq->rd_datap (); | |||
if (J->_state == Jackclient::TERM) | |||
{ | |||
printf ("Fatal error condition, terminating.\n"); | |||
stop = true; | |||
return; | |||
} | |||
else if (J->_state == Jackclient::WAIT) | |||
{ | |||
printf ("Detected excessive timing errors, waiting 15 seconds.\n"); | |||
printf ("This may happen with current Jack1 after freewheeling.\n"); | |||
n = 0; | |||
} | |||
else if (J->_state == Jackclient::SYNC0) | |||
{ | |||
printf ("Starting synchronisation.\n"); | |||
} | |||
else if (v_opt) | |||
{ | |||
n++; | |||
e += J->_error; | |||
r += J->_ratio; | |||
} | |||
infoq->rd_commit (); | |||
} | |||
if (n) printf ("%8.3lf %10.6lf\n", e / n, r / n); | |||
} | |||
static Alsa_pcmi *A = 0; | |||
static Alsathread *C = 0; | |||
static Jackclient *J = 0; | |||
extern "C" { | |||
Alsa_pcmi *A; | |||
Alsathread *C; | |||
Jackclient *J; | |||
int | |||
jack_initialize (jack_client_t* client, const char* load_init) | |||
{ | |||
int k, k_del, opts; | |||
double t_jack; | |||
double t_alsa; | |||
double t_del; | |||
if (parse_options (load_init)) { | |||
fprintf (stderr, "parse options failed\n"); | |||
return 1; | |||
} | |||
public: | |||
if (device == 0) help (); | |||
if (rqual < 16) rqual = 16; | |||
if (rqual > 96) rqual = 96; | |||
if ((fsamp && fsamp < 8000) || (bsize && bsize < 16) || (nfrag < 2) || (nchan < 1)) | |||
int | |||
jack_initialize (jack_client_t* client, const char* load_init) | |||
{ | |||
fprintf (stderr, "Illegal parameter value(s).\n"); | |||
return 1; | |||
} | |||
int k, k_del, opts; | |||
double t_jack; | |||
double t_alsa; | |||
double t_del; | |||
if (parse_options (load_init)) { | |||
fprintf (stderr, "parse options failed\n"); | |||
return 1; | |||
} | |||
J = new Jackclient (client, 0, Jackclient::CAPT, 0); | |||
usleep (100000); | |||
if (device == 0) help (); | |||
if (rqual < 16) rqual = 16; | |||
if (rqual > 96) rqual = 96; | |||
if ((fsamp && fsamp < 8000) || (bsize && bsize < 16) || (nfrag < 2) || (nchan < 1)) | |||
{ | |||
fprintf (stderr, "Illegal parameter value(s).\n"); | |||
return 1; | |||
} | |||
/* if SR and/or bufsize are unspecified, use the same values | |||
as the JACK server. | |||
*/ | |||
if (fsamp == 0) | |||
{ | |||
fsamp = J->fsamp(); | |||
} | |||
J = new Jackclient (client, 0, Jackclient::CAPT, 0, this); | |||
usleep (100000); | |||
if (bsize == 0) | |||
{ | |||
bsize = J->bsize(); | |||
} | |||
/* if SR and/or bufsize are unspecified, use the same values | |||
as the JACK server. | |||
*/ | |||
if (fsamp == 0) | |||
{ | |||
fsamp = J->fsamp(); | |||
} | |||
opts = 0; | |||
if (v_opt) opts |= Alsa_pcmi::DEBUG_ALL; | |||
if (L_opt) opts |= Alsa_pcmi::FORCE_16B | Alsa_pcmi::FORCE_2CH; | |||
A = new Alsa_pcmi (0, device, 0, fsamp, bsize, nfrag, opts); | |||
if (A->state ()) | |||
{ | |||
fprintf (stderr, "Can't open ALSA capture device '%s'.\n", device); | |||
return 1; | |||
if (bsize == 0) | |||
{ | |||
bsize = J->bsize(); | |||
} | |||
opts = 0; | |||
if (v_opt) opts |= Alsa_pcmi::DEBUG_ALL; | |||
if (L_opt) opts |= Alsa_pcmi::FORCE_16B | Alsa_pcmi::FORCE_2CH; | |||
A = new Alsa_pcmi (0, device, 0, fsamp, bsize, nfrag, opts); | |||
if (A->state ()) | |||
{ | |||
fprintf (stderr, "Can't open ALSA capture device '%s'.\n", device); | |||
return 1; | |||
} | |||
if (v_opt) A->printinfo (); | |||
if (nchan > A->ncapt ()) | |||
{ | |||
nchan = A->ncapt (); | |||
fprintf (stderr, "Warning: only %d channels are available.\n", nchan); | |||
} | |||
C = new Alsathread (A, Alsathread::CAPT); | |||
J->register_ports (nchan); | |||
t_alsa = (double) bsize / fsamp; | |||
if (t_alsa < 1e-3) t_alsa = 1e-3; | |||
t_jack = (double) J->bsize () / J->fsamp (); | |||
t_del = 1.5 * t_alsa + t_jack; | |||
k_del = (int)(t_del * fsamp); | |||
for (k = 256; k < k_del + J->bsize (); k *= 2); | |||
audioq = new Lfq_audio (k, nchan); | |||
C->start (audioq, commq, alsaq, J->rprio () + 10); | |||
J->start (audioq, commq, alsaq, infoq, J->fsamp () / (double) fsamp, k_del, ltcor, rqual); | |||
return 0; | |||
} | |||
if (v_opt) A->printinfo (); | |||
if (nchan > A->ncapt ()) | |||
void jack_finish (void* arg) | |||
{ | |||
nchan = A->ncapt (); | |||
fprintf (stderr, "Warning: only %d channels are available.\n", nchan); | |||
commq->wr_int32 (Alsathread::TERM); | |||
usleep (100000); | |||
delete C; | |||
delete A; | |||
delete J; | |||
delete audioq; | |||
} | |||
C = new Alsathread (A, Alsathread::CAPT); | |||
J->register_ports (nchan); | |||
t_alsa = (double) bsize / fsamp; | |||
if (t_alsa < 1e-3) t_alsa = 1e-3; | |||
t_jack = (double) J->bsize () / J->fsamp (); | |||
t_del = 1.5 * t_alsa + t_jack; | |||
k_del = (int)(t_del * fsamp); | |||
for (k = 256; k < k_del + J->bsize (); k *= 2); | |||
audioq = new Lfq_audio (k, nchan); | |||
C->start (audioq, &commq, &alsaq, J->rprio () + 10); | |||
J->start (audioq, &commq, &alsaq, &infoq, J->fsamp () / (double) fsamp, k_del, ltcor, rqual); | |||
return 0; | |||
}; | |||
extern "C" { | |||
int | |||
jack_initialize (jack_client_t* client, const char* load_init) | |||
{ | |||
zita_a2j *c = new zita_a2j(); | |||
c->jack_initialize(client, load_init); | |||
} | |||
void jack_finish (void* arg) | |||
{ | |||
commq.wr_int32 (Alsathread::TERM); | |||
usleep (100000); | |||
delete C; | |||
delete A; | |||
delete J; | |||
delete audioq; | |||
Jackclient *J = (Jackclient *)arg; | |||
zita_a2j *c = (zita_a2j *)J->getarg(); | |||
c->jack_finish(arg); | |||
delete c; | |||
} | |||
} /* extern "C" */ |
@@ -27,25 +27,7 @@ | |||
#include "jackclient.h" | |||
#include "lfqueue.h" | |||
static Lfq_int32 commq (16); | |||
static Lfq_adata alsaq (256); | |||
static Lfq_jdata infoq (256); | |||
static Lfq_audio *audioq = 0; | |||
static bool stop = false; | |||
static const char *clopt = "hvLj:d:r:p:n:c:Q:O:"; | |||
static bool v_opt = false; | |||
static bool L_opt = false; | |||
static const char *jname = APPNAME; | |||
static const char *device = 0; | |||
static int fsamp = 0; | |||
static int bsize = 0; | |||
static int nfrag = 2; | |||
static int nchan = 2; | |||
static int rqual = 48; | |||
static int ltcor = 0; | |||
static const char *clopt = "hvLj:d:r:p:n:c:Q:I:"; | |||
static void help (void) | |||
{ | |||
@@ -68,58 +50,102 @@ static void help (void) | |||
exit (1); | |||
} | |||
static int procoptions (int ac, const char *av []) | |||
class zita_j2a | |||
{ | |||
int k; | |||
optind = 1; | |||
opterr = 0; | |||
while ((k = getopt (ac, (char **) av, (char *) clopt)) != -1) | |||
Lfq_int32 *commq; | |||
Lfq_adata *alsaq; | |||
Lfq_jdata *infoq; | |||
Lfq_audio *audioq; | |||
bool stop; | |||
bool v_opt; | |||
bool L_opt; | |||
char *jname; | |||
char *device; | |||
int fsamp; | |||
int bsize; | |||
int nfrag; | |||
int nchan; | |||
int rqual; | |||
int ltcor; | |||
public: | |||
zita_j2a() | |||
{ | |||
commq = new Lfq_int32(16); | |||
alsaq = new Lfq_adata(256); | |||
infoq = new Lfq_jdata(256); | |||
audioq = 0; | |||
stop = false; | |||
v_opt = false; | |||
L_opt = false; | |||
jname = strdup(APPNAME); | |||
device = 0; | |||
fsamp = 0; | |||
bsize = 0; | |||
nfrag = 2; | |||
nchan = 2; | |||
rqual = 48; | |||
ltcor = 0; | |||
A = 0; | |||
P = 0; | |||
J = 0; | |||
} | |||
private: | |||
int procoptions (int ac, const char *av []) | |||
{ | |||
if (optarg && (*optarg == '-')) | |||
int k; | |||
optind = 1; | |||
opterr = 0; | |||
while ((k = getopt (ac, (char **) av, (char *) clopt)) != -1) | |||
{ | |||
fprintf (stderr, " Missing argument for '-%c' option.\n", k); | |||
fprintf (stderr, " Use '-h' to see all options.\n"); | |||
exit (1); | |||
if (optarg && (*optarg == '-')) | |||
{ | |||
fprintf (stderr, " Missing argument for '-%c' option.\n", k); | |||
fprintf (stderr, " Use '-h' to see all options.\n"); | |||
exit (1); | |||
} | |||
switch (k) | |||
{ | |||
case 'h' : help (); exit (0); | |||
case 'v' : v_opt = true; break; | |||
case 'L' : L_opt = true; break; | |||
case 'j' : jname = optarg; break; | |||
case 'd' : device = optarg; break; | |||
case 'r' : fsamp = atoi (optarg); break; | |||
case 'p' : bsize = atoi (optarg); break; | |||
case 'n' : nfrag = atoi (optarg); break; | |||
case 'c' : nchan = atoi (optarg); break; | |||
case 'Q' : rqual = atoi (optarg); break; | |||
case 'O' : ltcor = atoi (optarg); break; | |||
case '?': | |||
if (optopt != ':' && strchr (clopt, optopt)) | |||
{ | |||
fprintf (stderr, " Missing argument for '-%c' option.\n", optopt); | |||
} | |||
else if (isprint (optopt)) | |||
{ | |||
fprintf (stderr, " Unknown option '-%c'.\n", optopt); | |||
} | |||
else | |||
{ | |||
fprintf (stderr, " Unknown option character '0x%02x'.\n", optopt & 255); | |||
} | |||
fprintf (stderr, " Use '-h' to see all options.\n"); | |||
return 1; | |||
default: | |||
return 1; | |||
} | |||
} | |||
switch (k) | |||
{ | |||
case 'h' : help (); exit (0); | |||
case 'v' : v_opt = true; break; | |||
case 'L' : L_opt = true; break; | |||
case 'j' : jname = optarg; break; | |||
case 'd' : device = optarg; break; | |||
case 'r' : fsamp = atoi (optarg); break; | |||
case 'p' : bsize = atoi (optarg); break; | |||
case 'n' : nfrag = atoi (optarg); break; | |||
case 'c' : nchan = atoi (optarg); break; | |||
case 'Q' : rqual = atoi (optarg); break; | |||
case 'O' : ltcor = atoi (optarg); break; | |||
case '?': | |||
if (optopt != ':' && strchr (clopt, optopt)) | |||
{ | |||
fprintf (stderr, " Missing argument for '-%c' option.\n", optopt); | |||
} | |||
else if (isprint (optopt)) | |||
{ | |||
fprintf (stderr, " Unknown option '-%c'.\n", optopt); | |||
} | |||
else | |||
{ | |||
fprintf (stderr, " Unknown option character '0x%02x'.\n", optopt & 255); | |||
} | |||
fprintf (stderr, " Use '-h' to see all options.\n"); | |||
return 1; | |||
default: | |||
return 1; | |||
} | |||
} | |||
return 0; | |||
} | |||
return 0; | |||
} | |||
static int parse_options (const char* load_init) | |||
{ | |||
int parse_options (const char* load_init) | |||
{ | |||
int argsz; | |||
int argc = 0; | |||
const char** argv; | |||
@@ -128,8 +154,8 @@ static int parse_options (const char* load_init) | |||
char* ptr = args; | |||
char* savep; | |||
if (!load_init) { | |||
return 0; | |||
if (!load_init) { | |||
return 0; | |||
} | |||
argsz = 8; /* random guess at "maxargs" */ | |||
@@ -138,144 +164,162 @@ static int parse_options (const char* load_init) | |||
argv[argc++] = APPNAME; | |||
while (1) { | |||
if ((token = strtok_r (ptr, " ", &savep)) == NULL) { | |||
break; | |||
} | |||
if (argc == argsz) { | |||
argsz *= 2; | |||
argv = (const char **) realloc (argv, sizeof (char *) * argsz); | |||
} | |||
argv[argc++] = token; | |||
ptr = NULL; | |||
if ((token = strtok_r (ptr, " ", &savep)) == NULL) { | |||
break; | |||
} | |||
if (argc == argsz) { | |||
argsz *= 2; | |||
argv = (const char **) realloc (argv, sizeof (char *) * argsz); | |||
} | |||
argv[argc++] = token; | |||
ptr = NULL; | |||
} | |||
return procoptions (argc, argv); | |||
} | |||
static void printinfo (void) | |||
{ | |||
int n; | |||
double e, r; | |||
Jdata *J; | |||
} | |||
n = 0; | |||
e = r = 0; | |||
while (infoq.rd_avail ()) | |||
void printinfo (void) | |||
{ | |||
J = infoq.rd_datap (); | |||
if (J->_state == Jackclient::TERM) | |||
{ | |||
printf ("Fatal error condition, terminating.\n"); | |||
stop = true; | |||
return; | |||
} | |||
else if (J->_state == Jackclient::WAIT) | |||
{ | |||
printf ("Detected excessive timing errors, waiting 15 seconds.\n"); | |||
printf ("This may happen with current Jack1 after freewheeling.\n"); | |||
n = 0; | |||
} | |||
else if (J->_state == Jackclient::SYNC0) | |||
{ | |||
printf ("Starting synchronisation.\n"); | |||
} | |||
else if (v_opt) | |||
{ | |||
n++; | |||
e += J->_error; | |||
r += J->_ratio; | |||
} | |||
infoq.rd_commit (); | |||
int n; | |||
double e, r; | |||
Jdata *J; | |||
n = 0; | |||
e = r = 0; | |||
while (infoq->rd_avail ()) | |||
{ | |||
J = infoq->rd_datap (); | |||
if (J->_state == Jackclient::TERM) | |||
{ | |||
printf ("Fatal error condition, terminating.\n"); | |||
stop = true; | |||
return; | |||
} | |||
else if (J->_state == Jackclient::WAIT) | |||
{ | |||
printf ("Detected excessive timing errors, waiting 15 seconds.\n"); | |||
printf ("This may happen with current Jack1 after freewheeling.\n"); | |||
n = 0; | |||
} | |||
else if (J->_state == Jackclient::SYNC0) | |||
{ | |||
printf ("Starting synchronisation.\n"); | |||
} | |||
else if (v_opt) | |||
{ | |||
n++; | |||
e += J->_error; | |||
r += J->_ratio; | |||
} | |||
infoq->rd_commit (); | |||
} | |||
if (n) printf ("%8.3lf %10.6lf\n", e / n, r / n); | |||
} | |||
if (n) printf ("%8.3lf %10.6lf\n", e / n, r / n); | |||
} | |||
Alsa_pcmi *A = 0; | |||
Alsathread *P = 0; | |||
Jackclient *J = 0; | |||
Alsa_pcmi *A; | |||
Alsathread *P; | |||
Jackclient *J; | |||
public: | |||
extern "C" { | |||
int jack_initialize (jack_client_t* client, const char* load_init) | |||
{ | |||
int k, k_del, opts; | |||
double t_jack; | |||
double t_alsa; | |||
double t_del; | |||
int jack_initialize (jack_client_t* client, const char* load_init) | |||
{ | |||
int k, k_del, opts; | |||
double t_jack; | |||
double t_alsa; | |||
double t_del; | |||
if (parse_options (load_init)) { | |||
return 1; | |||
} | |||
if (parse_options (load_init)) { | |||
if (device == 0) help (); | |||
if (rqual < 16) rqual = 16; | |||
if (rqual > 96) rqual = 96; | |||
if ((fsamp && fsamp < 8000) || (bsize && bsize < 16) || (nfrag < 2) || (nchan < 1)) | |||
{ | |||
fprintf (stderr, "Illegal parameter value(s).\n"); | |||
return 1; | |||
} | |||
} | |||
if (device == 0) help (); | |||
if (rqual < 16) rqual = 16; | |||
if (rqual > 96) rqual = 96; | |||
if ((fsamp && fsamp < 8000) || (bsize && bsize < 16) || (nfrag < 2) || (nchan < 1)) | |||
{ | |||
fprintf (stderr, "Illegal parameter value(s).\n"); | |||
return 1; | |||
} | |||
J = new Jackclient (client, 0, Jackclient::PLAY, 0, this); | |||
usleep (100000); | |||
J = new Jackclient (client, 0, Jackclient::PLAY, 0); | |||
usleep (100000); | |||
/* if SR and/or bufsize are unspecified, use the same values | |||
as the JACK server. | |||
*/ | |||
/* if SR and/or bufsize are unspecified, use the same values | |||
as the JACK server. | |||
*/ | |||
if (fsamp == 0) | |||
{ | |||
fsamp = J->fsamp(); | |||
} | |||
if (fsamp == 0) | |||
{ | |||
fsamp = J->fsamp(); | |||
} | |||
if (bsize == 0) | |||
{ | |||
bsize = J->bsize(); | |||
} | |||
if (bsize == 0) | |||
{ | |||
bsize = J->bsize(); | |||
} | |||
opts = 0; | |||
if (v_opt) opts |= Alsa_pcmi::DEBUG_ALL; | |||
if (L_opt) opts |= Alsa_pcmi::FORCE_16B | Alsa_pcmi::FORCE_2CH; | |||
A = new Alsa_pcmi (device, 0, 0, fsamp, bsize, nfrag, opts); | |||
if (A->state ()) | |||
{ | |||
fprintf (stderr, "Can't open ALSA playback device '%s'.\n", device); | |||
return 1; | |||
opts = 0; | |||
if (v_opt) opts |= Alsa_pcmi::DEBUG_ALL; | |||
if (L_opt) opts |= Alsa_pcmi::FORCE_16B | Alsa_pcmi::FORCE_2CH; | |||
A = new Alsa_pcmi (device, 0, 0, fsamp, bsize, nfrag, opts); | |||
if (A->state ()) | |||
{ | |||
fprintf (stderr, "Can't open ALSA playback device '%s'.\n", device); | |||
return 1; | |||
} | |||
if (v_opt) A->printinfo (); | |||
if (nchan > A->nplay ()) | |||
{ | |||
nchan = A->nplay (); | |||
fprintf (stderr, "Warning: only %d channels are available.\n", nchan); | |||
} | |||
P = new Alsathread (A, Alsathread::PLAY); | |||
J->register_ports (nchan); | |||
t_alsa = (double) bsize / fsamp; | |||
if (t_alsa < 1e-3) t_alsa = 1e-3; | |||
t_jack = (double) J->bsize () / J->fsamp (); | |||
t_del = 1.5 * t_alsa + t_jack; | |||
k_del = (int)(t_del * fsamp); | |||
for (k = 256; k < k_del + J->bsize (); k *= 2); | |||
audioq = new Lfq_audio (k, nchan); | |||
P->start (audioq, commq, alsaq, J->rprio () + 10); | |||
J->start (audioq, commq, alsaq, infoq, (double) fsamp / J->fsamp (), k_del, ltcor, rqual); | |||
return 0; | |||
} | |||
if (v_opt) A->printinfo (); | |||
if (nchan > A->nplay ()) | |||
void jack_finish (void* arg) | |||
{ | |||
nchan = A->nplay (); | |||
fprintf (stderr, "Warning: only %d channels are available.\n", nchan); | |||
commq->wr_int32 (Alsathread::TERM); | |||
usleep (100000); | |||
delete P; | |||
delete A; | |||
delete J; | |||
delete audioq; | |||
} | |||
P = new Alsathread (A, Alsathread::PLAY); | |||
J->register_ports (nchan); | |||
t_alsa = (double) bsize / fsamp; | |||
if (t_alsa < 1e-3) t_alsa = 1e-3; | |||
t_jack = (double) J->bsize () / J->fsamp (); | |||
t_del = 1.5 * t_alsa + t_jack; | |||
k_del = (int)(t_del * fsamp); | |||
for (k = 256; k < k_del + J->bsize (); k *= 2); | |||
audioq = new Lfq_audio (k, nchan); | |||
}; | |||
P->start (audioq, &commq, &alsaq, J->rprio () + 10); | |||
J->start (audioq, &commq, &alsaq, &infoq, (double) fsamp / J->fsamp (), k_del, ltcor, rqual); | |||
extern "C" { | |||
return 0; | |||
int | |||
jack_initialize (jack_client_t* client, const char* load_init) | |||
{ | |||
zita_j2a *c = new zita_j2a(); | |||
c->jack_initialize(client, load_init); | |||
} | |||
void jack_finish (void* arg) | |||
{ | |||
commq.wr_int32 (Alsathread::TERM); | |||
usleep (100000); | |||
delete P; | |||
delete A; | |||
delete J; | |||
delete audioq; | |||
Jackclient *J = (Jackclient *)arg; | |||
zita_j2a *c = (zita_j2a *)J->getarg(); | |||
c->jack_finish(arg); | |||
delete c; | |||
} | |||
} /* extern "C" */ |