00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "AudioSource.h"
00033
00034 #ifdef SUPPORT_JACK_DSP
00035
00036
00037 #ifdef HAVE_CONFIG_H
00038 #include "config.h"
00039 #endif
00040
00041 #ifdef HAVE_UNISTD_H
00042 #include <unistd.h>
00043 #else
00044 #error need unistd.h
00045 #endif
00046
00047 #ifdef HAVE_STRING_H
00048 #include <string.h>
00049 #else
00050 #error need string.h
00051 #endif
00052
00053 #ifdef HAVE_SYS_TYPES_H
00054 #include <sys/types.h>
00055 #else
00056 #error need sys/types.h
00057 #endif
00058
00059 #ifdef HAVE_MATH_H
00060 #include <math.h>
00061 #else
00062 #error need math.h
00063 #endif
00064
00065 #include "Util.h"
00066 #include "Exception.h"
00067 #include "JackDspSource.h"
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 static const char fileid[] = "$Id: JackDspSource.cpp,v 1.1 2005/04/04 08:36:17 darkeye Exp $";
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 void
00090 JackDspSource :: init ( const char* name ) throw ( Exception )
00091 {
00092
00093 ports[0] = NULL;
00094 ports[1] = NULL;
00095 rb[0] = NULL;
00096 rb[1] = NULL;
00097 client = NULL;
00098 auto_connect = false;
00099 tmp_buffer = NULL;
00100
00101
00102 if ( Util::strEq( name, "jack_auto", 9) ) {
00103 auto_connect = true;
00104 }
00105
00106
00107 if (getBitsPerSample() != 16) {
00108 throw Exception( __FILE__, __LINE__,
00109 "JackDspSource doesn't support non 16-bit samples");
00110 }
00111 }
00112
00113
00114
00115
00116
00117
00118 void
00119 JackDspSource :: strip ( void ) throw ( Exception )
00120 {
00121 if ( isOpen() ) {
00122 close();
00123 }
00124
00125
00126 if (tmp_buffer) {
00127 free(tmp_buffer);
00128 tmp_buffer = NULL;
00129 }
00130
00131 }
00132
00133
00134
00135
00136
00137 void
00138 JackDspSource :: do_auto_connect ( void ) throw ( Exception )
00139 {
00140 const char **all_ports;
00141 unsigned int ch = 0;
00142 int i;
00143
00144 Reporter::reportEvent( 10, "JackDspSource :: do_auto_connect");
00145
00146
00147 all_ports = jack_get_ports (client, NULL, NULL, JackPortIsOutput);
00148 if (!ports) {
00149 throw Exception( __FILE__, __LINE__, "jack_get_ports() returned NULL.");
00150 }
00151
00152
00153 for (i = 0; all_ports[i]; ++i) {
00154
00155 const char* in = all_ports[i];
00156 const char* out = jack_port_name( ports[ch] );
00157
00158 Reporter::reportEvent( 2, "Connecting", in, "to", out);
00159
00160 if (jack_connect(client, in, out)) {
00161 throw Exception( __FILE__, __LINE__,
00162 "Failed to jack_connect() ports", in, out);
00163 }
00164
00165
00166 if (++ch >= getChannel()) break;
00167 }
00168
00169 free( all_ports );
00170
00171 }
00172
00173
00174
00175
00176
00177 bool
00178 JackDspSource :: open ( void ) throw ( Exception )
00179 {
00180 char client_name[255];
00181 size_t rb_size;
00182 unsigned int c;
00183
00184 if ( isOpen() ) {
00185 return false;
00186 }
00187
00188
00189 snprintf(client_name, 255, "darkice-%d", getpid());
00190 if ((client = jack_client_new(client_name)) == NULL) {
00191 throw Exception( __FILE__, __LINE__, "JACK server not running?");
00192 }
00193 Reporter::reportEvent( 1, "Registering as JACK client", client_name);
00194
00195
00196
00197 if (jack_get_sample_rate( client ) != (jack_nframes_t)getSampleRate()) {
00198 throw Exception( __FILE__, __LINE__,
00199 "JACK server sample rate is different than "
00200 "sample rate in darkice config file");
00201 }
00202
00203
00204
00205 if (getChannel() == 1) {
00206 if (!(ports[0] = jack_port_register(client,
00207 "mono",
00208 JACK_DEFAULT_AUDIO_TYPE,
00209 JackPortIsInput,
00210 0))) {
00211 throw Exception( __FILE__, __LINE__,
00212 "Cannot register input port", "mono");
00213 }
00214 } else if (getChannel() == 2) {
00215 if (!(ports[0] = jack_port_register(client,
00216 "left",
00217 JACK_DEFAULT_AUDIO_TYPE,
00218 JackPortIsInput,
00219 0))) {
00220 throw Exception( __FILE__, __LINE__,
00221 "Cannot register input port", "left");
00222 }
00223 if (!(ports[1] = jack_port_register(client,
00224 "right",
00225 JACK_DEFAULT_AUDIO_TYPE,
00226 JackPortIsInput, 0))) {
00227 throw Exception( __FILE__, __LINE__,
00228 "Cannot register input port", "right");
00229 }
00230 } else {
00231 throw Exception( __FILE__, __LINE__,
00232 "Invalid number of channels", getChannel());
00233 }
00234
00235
00236
00237 rb_size = 2
00238 * jack_get_sample_rate(client)
00239 * sizeof (jack_default_audio_sample_t);
00240 for (c=0; c<getChannel(); c++) {
00241 rb[c] = jack_ringbuffer_create(rb_size);
00242 if (!rb[c]) {
00243 throw Exception( __FILE__, __LINE__,
00244 "Failed to create ringbuffer for", "channel", c);
00245 }
00246 }
00247
00248
00249
00250 jack_on_shutdown(client, JackDspSource::shutdown_callback, (void*)this);
00251 if (jack_set_process_callback(client,
00252 JackDspSource::process_callback,
00253 (void*)this)) {
00254 throw Exception( __FILE__, __LINE__, "Failed to set process callback");
00255 }
00256
00257
00258 if (jack_activate(client)) {
00259 throw Exception( __FILE__, __LINE__, "Can't activate client");
00260 }
00261
00262
00263 if (auto_connect) {
00264 do_auto_connect();
00265 }
00266
00267 return true;
00268 }
00269
00270
00271
00272
00273
00274 bool
00275 JackDspSource :: canRead ( unsigned int sec,
00276 unsigned int usec ) throw ( Exception )
00277 {
00278 size_t available=0;
00279
00280 if ( !isOpen() ) {
00281 return false;
00282 }
00283
00284
00285 available = jack_ringbuffer_read_space( rb[0] );
00286 if (available) return true;
00287
00288
00289
00290 usleep( (sec*1000000) + usec );
00291
00292 available = jack_ringbuffer_read_space( rb[0] );
00293 if (available) {
00294 return true;
00295 } else {
00296 return false;
00297 }
00298 }
00299
00300
00301
00302
00303
00304 unsigned int
00305 JackDspSource :: read ( void * buf,
00306 unsigned int len ) throw ( Exception )
00307 {
00308 jack_nframes_t samples = len / 2 / getChannel();
00309 jack_nframes_t samples_read[2] = {0,0};
00310 short * output = (short*)buf;
00311 unsigned int c, n;
00312
00313 if ( !isOpen() ) {
00314 return 0;
00315 }
00316
00317
00318
00319 tmp_buffer = (jack_default_audio_sample_t*)realloc(tmp_buffer,
00320 samples * sizeof( jack_default_audio_sample_t ) );
00321 if (!tmp_buffer) {
00322 throw Exception( __FILE__, __LINE__, "realloc on tmp_buffer failed");
00323 }
00324
00325
00326 for (c=0; c<getChannel(); c++)
00327 {
00328
00329
00330 int bytes_read = jack_ringbuffer_read(rb[c],
00331 (char*)tmp_buffer,
00332 samples * sizeof( jack_default_audio_sample_t ));
00333 samples_read[c] = bytes_read / sizeof( jack_default_audio_sample_t );
00334
00335
00336
00337 for(n=0; n<samples_read[c]; n++) {
00338 int tmp = lrintf(tmp_buffer[n] * 32768.0f);
00339 if (tmp > SHRT_MAX) {
00340 output[n*getChannel()+c] = SHRT_MAX;
00341 } else if (tmp < SHRT_MIN) {
00342 output[n*getChannel()+c] = SHRT_MIN;
00343 } else {
00344 output[n*getChannel()+c] = (short) tmp;
00345 }
00346 }
00347 }
00348
00349
00350 if (getChannel() == 2 && samples_read[0] != samples_read[1]) {
00351 Reporter::reportEvent( 2,
00352 "Warning: Read a different number of samples "
00353 "for left and right channels");
00354 }
00355
00356
00357 return samples_read[0] * 2 * getChannel();
00358 }
00359
00360
00361
00362
00363
00364 void
00365 JackDspSource :: close ( void ) throw ( Exception )
00366 {
00367 unsigned int i;
00368
00369 if ( !isOpen() ) {
00370 return;
00371 }
00372
00373 for(i = 0; i < getChannel(); i++) {
00374
00375 if ( ports[i] ) {
00376 jack_port_unregister( client, ports[i] );
00377 ports[i] = NULL;
00378 }
00379
00380
00381 if ( rb[i] ) {
00382 jack_ringbuffer_free( rb[i] );
00383 rb[i] = NULL;
00384 }
00385 }
00386
00387
00388 if (client) {
00389 jack_client_close(client);
00390 client = NULL;
00391 }
00392
00393 }
00394
00395
00396
00397
00398
00399
00400
00401
00402 int
00403 JackDspSource :: process_callback( jack_nframes_t nframes, void *arg )
00404 {
00405 JackDspSource* self = (JackDspSource*)arg;
00406 size_t to_write = sizeof (jack_default_audio_sample_t) * nframes;
00407 unsigned int c;
00408
00409
00410 if (self->client == NULL) {
00411 return 0;
00412 }
00413
00414
00415 for (c=0; c < self->getChannel(); c++) {
00416 char *buf = (char*)jack_port_get_buffer(self->ports[c], nframes);
00417 size_t len = jack_ringbuffer_write(self->rb[c], buf, to_write);
00418 if (len < to_write) {
00419 Reporter::reportEvent( 1, "failed to write to ring ruffer");
00420 return 1;
00421 }
00422 }
00423
00424
00425 return 0;
00426 }
00427
00428
00429
00430
00431 void
00432 JackDspSource :: shutdown_callback( void *arg )
00433 {
00434
00435
00436 Reporter::reportEvent( 1, "JackDspSource :: shutdown_callback");
00437 }
00438
00439
00440 #endif // SUPPORT_JACK_DSP
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454