00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <iostream>
00023 #include <unistd.h>
00024 #include <math.h>
00025 #include <stdio.h>
00026 #include <memory.h>
00027 #include <unistd.h>
00028 #include <stdlib.h>
00029 #include <errno.h>
00030 #include <stdarg.h>
00031 #include <signal.h>
00032 #include <sys/types.h>
00033 #include <sys/time.h>
00034 #include <regex.h>
00035 #include <string.h>
00036
00037 #include "JackFreebobDriver.h"
00038 #include "JackEngineControl.h"
00039 #include "JackClientControl.h"
00040 #include "JackPort.h"
00041 #include "JackGraphManager.h"
00042 #include "JackLockedEngine.h"
00043
00044 namespace Jack
00045 {
00046
00047 #define jack_get_microseconds GetMicroSeconds
00048
00049 #define SAMPLE_MAX_24BIT 8388608.0f
00050 #define SAMPLE_MAX_16BIT 32768.0f
00051
00052 int
00053 JackFreebobDriver::freebob_driver_read (freebob_driver_t * driver, jack_nframes_t nframes)
00054 {
00055 jack_default_audio_sample_t* buf = NULL;
00056 freebob_sample_t nullbuffer[nframes];
00057 void *addr_of_nullbuffer = (void *)nullbuffer;
00058
00059 freebob_streaming_stream_type stream_type;
00060
00061 printEnter();
00062
00063
00064 for (unsigned int i = 0; i < driver->capture_nchannels; i++) {
00065 stream_type = freebob_streaming_get_playback_stream_type(driver->dev, i);
00066 if (stream_type == freebob_stream_type_audio) {
00067 freebob_streaming_set_playback_stream_buffer(driver->dev, i,
00068 (char *)(nullbuffer), freebob_buffer_type_float);
00069 } else if (stream_type == freebob_stream_type_midi) {
00070
00071 } else {
00072 freebob_streaming_set_playback_stream_buffer(driver->dev, i,
00073 (char *)(nullbuffer), freebob_buffer_type_uint24);
00074 }
00075 }
00076
00077 for (int i = 0; i < fCaptureChannels; i++) {
00078 stream_type = freebob_streaming_get_capture_stream_type(driver->dev, i);
00079 if (stream_type == freebob_stream_type_audio) {
00080
00081 if (fGraphManager->GetConnectionsNum(fCapturePortList[i]) > 0) {
00082 buf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fCapturePortList[i], nframes);
00083
00084 if (!buf) {
00085 buf = (jack_default_audio_sample_t *)addr_of_nullbuffer;
00086 }
00087
00088 freebob_streaming_set_capture_stream_buffer(driver->dev, i, (char *)(buf), freebob_buffer_type_float);
00089 }
00090 } else if (stream_type == freebob_stream_type_midi) {
00091
00092 } else {
00093 freebob_streaming_set_capture_stream_buffer(driver->dev, i, (char *)(nullbuffer), freebob_buffer_type_uint24);
00094 }
00095
00096 }
00097
00098
00099 freebob_streaming_transfer_capture_buffers(driver->dev);
00100 printExit();
00101 return 0;
00102 }
00103
00104 int
00105 JackFreebobDriver::freebob_driver_write (freebob_driver_t * driver, jack_nframes_t nframes)
00106 {
00107 jack_default_audio_sample_t* buf = NULL;
00108
00109 freebob_streaming_stream_type stream_type;
00110
00111 freebob_sample_t nullbuffer[nframes];
00112 void *addr_of_nullbuffer = (void*)nullbuffer;
00113
00114 memset(&nullbuffer, 0, nframes*sizeof(freebob_sample_t));
00115
00116 printEnter();
00117 driver->process_count++;
00118 assert(driver->dev);
00119
00120
00121 for (unsigned int i = 0; i < driver->playback_nchannels; i++) {
00122 stream_type = freebob_streaming_get_playback_stream_type(driver->dev, i);
00123 if (stream_type == freebob_stream_type_audio) {
00124 freebob_streaming_set_playback_stream_buffer(driver->dev, i,
00125 (char *)(nullbuffer), freebob_buffer_type_float);
00126 } else if (stream_type == freebob_stream_type_midi) {
00127
00128 } else {
00129 freebob_streaming_set_playback_stream_buffer(driver->dev, i,
00130 (char *)(nullbuffer), freebob_buffer_type_uint24);
00131 }
00132 }
00133
00134 for (int i = 0; i < fPlaybackChannels; i++) {
00135 stream_type = freebob_streaming_get_playback_stream_type(driver->dev, i);
00136 if (stream_type == freebob_stream_type_audio) {
00137
00138 if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) {
00139 buf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fPlaybackPortList[i], nframes);
00140 if (!buf) {
00141 buf = (jack_default_audio_sample_t *)addr_of_nullbuffer;
00142 }
00143 freebob_streaming_set_playback_stream_buffer(driver->dev, i, (char *)(buf), freebob_buffer_type_float);
00144 }
00145 }
00146 }
00147
00148 freebob_streaming_transfer_playback_buffers(driver->dev);
00149 printExit();
00150 return 0;
00151 }
00152
00153 jack_nframes_t
00154 JackFreebobDriver::freebob_driver_wait (freebob_driver_t *driver, int extra_fd, int *status,
00155 float *delayed_usecs)
00156 {
00157 int nframes;
00158 jack_time_t wait_enter;
00159 jack_time_t wait_ret;
00160
00161 printEnter();
00162
00163 wait_enter = jack_get_microseconds ();
00164 if (wait_enter > driver->wait_next) {
00165
00166
00167
00168
00169
00170 driver->wait_next = 0;
00171 driver->wait_late++;
00172 }
00173
00174
00175
00176
00177 nframes = freebob_streaming_wait(driver->dev);
00178
00179 wait_ret = jack_get_microseconds ();
00180
00181 if (driver->wait_next && wait_ret > driver->wait_next) {
00182 *delayed_usecs = wait_ret - driver->wait_next;
00183 }
00184 driver->wait_last = wait_ret;
00185 driver->wait_next = wait_ret + driver->period_usecs;
00186
00187
00188 if (nframes < 0) {
00189 *status = 0;
00190 return 0;
00191 }
00192
00193 *status = 0;
00194 fBeginDateUst = wait_ret;
00195
00196
00197 *delayed_usecs = 0;
00198 printExit();
00199 return nframes - nframes % driver->period_size;
00200 }
00201
00202 int
00203 JackFreebobDriver::freebob_driver_start (freebob_driver_t *driver)
00204 {
00205 int retval = 0;
00206
00207 #ifdef FREEBOB_DRIVER_WITH_MIDI
00208 if (driver->midi_handle) {
00209 if ((retval = freebob_driver_midi_start(driver->midi_handle))) {
00210 printError("Could not start MIDI threads");
00211 return retval;
00212 }
00213 }
00214 #endif
00215
00216 if ((retval = freebob_streaming_start(driver->dev))) {
00217 printError("Could not start streaming threads");
00218 #ifdef FREEBOB_DRIVER_WITH_MIDI
00219 if (driver->midi_handle) {
00220 freebob_driver_midi_stop(driver->midi_handle);
00221 }
00222 #endif
00223 return retval;
00224 }
00225
00226 return 0;
00227 }
00228
00229 int
00230 JackFreebobDriver::freebob_driver_stop (freebob_driver_t *driver)
00231 {
00232 int retval = 0;
00233
00234 #ifdef FREEBOB_DRIVER_WITH_MIDI
00235 if (driver->midi_handle) {
00236 if ((retval = freebob_driver_midi_stop(driver->midi_handle))) {
00237 printError("Could not stop MIDI threads");
00238 return retval;
00239 }
00240 }
00241 #endif
00242 if ((retval = freebob_streaming_stop(driver->dev))) {
00243 printError("Could not stop streaming threads");
00244 return retval;
00245 }
00246
00247 return 0;
00248 }
00249
00250 int
00251 JackFreebobDriver::freebob_driver_restart (freebob_driver_t *driver)
00252 {
00253 if (Stop())
00254 return -1;
00255 return Start();
00256 }
00257
00258 int
00259 JackFreebobDriver::SetBufferSize (jack_nframes_t nframes)
00260 {
00261 printError("Buffer size change requested but not supported!!!");
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 return -1;
00274 }
00275
00276 typedef void (*JackDriverFinishFunction) (jack_driver_t *);
00277
00278 freebob_driver_t *
00279 JackFreebobDriver::freebob_driver_new (char *name,
00280 freebob_jack_settings_t *params)
00281 {
00282 freebob_driver_t *driver;
00283
00284 assert(params);
00285
00286 if (freebob_get_api_version() != 1) {
00287 printMessage("Incompatible libfreebob version! (%s)", freebob_get_version());
00288 return NULL;
00289 }
00290
00291 printMessage("Starting Freebob backend (%s)", freebob_get_version());
00292
00293 driver = (freebob_driver_t*)calloc (1, sizeof (freebob_driver_t));
00294
00295
00296 jack_driver_nt_init ((jack_driver_nt_t *) driver);
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310 memcpy(&driver->settings, params, sizeof(freebob_jack_settings_t));
00311
00312
00313 driver->sample_rate = params->sample_rate;
00314 driver->period_size = params->period_size;
00315 fBeginDateUst = 0;
00316
00317 driver->period_usecs =
00318 (jack_time_t) floor ((((float) driver->period_size) * 1000000.0f) / driver->sample_rate);
00319
00320
00321 driver->engine = NULL;
00322
00323 memset(&driver->device_options, 0, sizeof(driver->device_options));
00324 driver->device_options.sample_rate = params->sample_rate;
00325 driver->device_options.period_size = params->period_size;
00326 driver->device_options.nb_buffers = params->buffer_size;
00327 driver->device_options.node_id = params->node_id;
00328 driver->device_options.port = params->port;
00329 driver->capture_frame_latency = params->capture_frame_latency;
00330 driver->playback_frame_latency = params->playback_frame_latency;
00331
00332 if (!params->capture_ports) {
00333 driver->device_options.directions |= FREEBOB_IGNORE_CAPTURE;
00334 }
00335
00336 if (!params->playback_ports) {
00337 driver->device_options.directions |= FREEBOB_IGNORE_PLAYBACK;
00338 }
00339
00340 debugPrint(DEBUG_LEVEL_STARTUP, " Driver compiled on %s %s", __DATE__, __TIME__);
00341 debugPrint(DEBUG_LEVEL_STARTUP, " Created driver %s", name);
00342 debugPrint(DEBUG_LEVEL_STARTUP, " period_size: %d", driver->period_size);
00343 debugPrint(DEBUG_LEVEL_STARTUP, " period_usecs: %d", driver->period_usecs);
00344 debugPrint(DEBUG_LEVEL_STARTUP, " sample rate: %d", driver->sample_rate);
00345
00346 return (freebob_driver_t *) driver;
00347 }
00348
00349 void
00350 JackFreebobDriver::freebob_driver_delete (freebob_driver_t *driver)
00351 {
00352 free (driver);
00353 }
00354
00355 #ifdef FREEBOB_DRIVER_WITH_MIDI
00356
00357
00358
00359
00360
00361
00362 void *
00363 JackFreebobDriver::freebob_driver_midi_queue_thread(void *arg)
00364 {
00365 freebob_driver_midi_handle_t *m = (freebob_driver_midi_handle_t *)arg;
00366 assert(m);
00367 snd_seq_event_t *ev;
00368 unsigned char work_buffer[MIDI_TRANSMIT_BUFFER_SIZE];
00369 int bytes_to_send;
00370 int b;
00371 int i;
00372
00373 printMessage("MIDI queue thread started");
00374
00375 while (1) {
00376
00377 while ((snd_seq_event_input(m->seq_handle, &ev) > 0)) {
00378
00379 freebob_midi_port_t *port = NULL;
00380 for (i = 0;i < m->nb_output_ports;i++) {
00381 if (m->output_ports[i]->seq_port_nr == ev->dest.port) {
00382 port = m->output_ports[i];
00383 break;
00384 }
00385 }
00386
00387 if (!port) {
00388 printError(" Could not find target port for event: dst=%d src=%d", ev->dest.port, ev->source.port);
00389 break;
00390 }
00391
00392
00393 if ((bytes_to_send = snd_midi_event_decode ( port->parser,
00394 work_buffer,
00395 MIDI_TRANSMIT_BUFFER_SIZE,
00396 ev)) < 0) {
00397 printError(" Error decoding event for port %d (errcode=%d)", port->seq_port_nr, bytes_to_send);
00398 bytes_to_send = 0;
00399
00400 }
00401
00402 for (b = 0;b < bytes_to_send;b++) {
00403 freebob_sample_t tmp_event = work_buffer[b];
00404 if (freebob_streaming_write(m->dev, port->stream_nr, &tmp_event, 1) < 1) {
00405 printError(" Midi send buffer overrun");
00406 }
00407 }
00408 }
00409
00410
00411 usleep(MIDI_THREAD_SLEEP_TIME_USECS);
00412 }
00413 return NULL;
00414 }
00415
00416
00417 void *
00418 JackFreebobDriver::freebob_driver_midi_dequeue_thread (void *arg)
00419 {
00420 freebob_driver_midi_handle_t *m = (freebob_driver_midi_handle_t *)arg;
00421
00422 int i;
00423 int s;
00424 int samples_read;
00425
00426 assert(m);
00427
00428 while (1) {
00429
00430
00431 for (i = 0;i < m->nb_input_ports;i++) {
00432 unsigned int buff[64];
00433 freebob_midi_port_t *port = m->input_ports[i];
00434 if (!port) {
00435 printError(" something went wrong when setting up the midi input port map (%d)", i);
00436 }
00437
00438 do {
00439 samples_read = freebob_streaming_read(m->dev, port->stream_nr, buff, 64);
00440
00441 for (s = 0;s < samples_read;s++) {
00442 unsigned int *byte = (buff + s) ;
00443 snd_seq_event_t ev;
00444 if ((snd_midi_event_encode_byte(port->parser, (*byte) & 0xFF, &ev)) > 0) {
00445
00446 snd_seq_ev_set_subs(&ev);
00447 snd_seq_ev_set_direct(&ev);
00448 snd_seq_ev_set_source(&ev, port->seq_port_nr);
00449 snd_seq_event_output_direct(port->seq_handle, &ev);
00450 }
00451 }
00452 } while (samples_read > 0);
00453 }
00454
00455
00456 usleep(MIDI_THREAD_SLEEP_TIME_USECS);
00457 }
00458 return NULL;
00459 }
00460
00461 freebob_driver_midi_handle_t *
00462 JackFreebobDriver::freebob_driver_midi_init(freebob_driver_t *driver)
00463 {
00464 char buf[256];
00465 channel_t chn;
00466 int nchannels;
00467 int i = 0;
00468
00469 freebob_device_t *dev = driver->dev;
00470 assert(dev);
00471
00472 freebob_driver_midi_handle_t *m = calloc(1, sizeof(freebob_driver_midi_handle_t));
00473 if (!m) {
00474 printError("not enough memory to create midi structure");
00475 return NULL;
00476 }
00477
00478 if (snd_seq_open(&m->seq_handle, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK) < 0) {
00479 printError("Error opening ALSA sequencer.");
00480 free(m);
00481 return NULL;
00482 }
00483
00484 snd_seq_set_client_name(m->seq_handle, "FreeBoB Jack MIDI");
00485
00486
00487 nchannels = freebob_streaming_get_nb_capture_streams(dev);
00488 m->nb_input_ports = 0;
00489
00490 for (chn = 0; chn < nchannels; chn++) {
00491 if (freebob_streaming_get_capture_stream_type(dev, chn) == freebob_stream_type_midi) {
00492 m->nb_input_ports++;
00493 }
00494 }
00495
00496 m->input_ports = calloc(m->nb_input_ports, sizeof(freebob_midi_port_t *));
00497 if (!m->input_ports) {
00498 printError("not enough memory to create midi structure");
00499 free(m);
00500 return NULL;
00501 }
00502
00503 i = 0;
00504 for (chn = 0; chn < nchannels; chn++) {
00505 if (freebob_streaming_get_capture_stream_type(dev, chn) == freebob_stream_type_midi) {
00506 m->input_ports[i] = calloc(1, sizeof(freebob_midi_port_t));
00507 if (!m->input_ports[i]) {
00508
00509 printError("Could not allocate memory for seq port");
00510 continue;
00511 }
00512
00513 freebob_streaming_get_capture_stream_name(dev, chn, buf, sizeof(buf));
00514 printMessage("Register MIDI IN port %s", buf);
00515
00516 m->input_ports[i]->seq_port_nr = snd_seq_create_simple_port(m->seq_handle, buf,
00517 SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ,
00518 SND_SEQ_PORT_TYPE_MIDI_GENERIC);
00519
00520 if (m->input_ports[i]->seq_port_nr < 0) {
00521 printError("Could not create seq port");
00522 m->input_ports[i]->stream_nr = -1;
00523 m->input_ports[i]->seq_port_nr = -1;
00524 } else {
00525 m->input_ports[i]->stream_nr = chn;
00526 m->input_ports[i]->seq_handle = m->seq_handle;
00527 if (snd_midi_event_new ( ALSA_SEQ_BUFF_SIZE, &(m->input_ports[i]->parser)) < 0) {
00528 printError("could not init parser for MIDI IN port %d", i);
00529 m->input_ports[i]->stream_nr = -1;
00530 m->input_ports[i]->seq_port_nr = -1;
00531 }
00532 }
00533
00534 i++;
00535 }
00536 }
00537
00538
00539 nchannels = freebob_streaming_get_nb_playback_streams(dev);
00540
00541 m->nb_output_ports = 0;
00542
00543 for (chn = 0; chn < nchannels; chn++) {
00544 if (freebob_streaming_get_playback_stream_type(dev, chn) == freebob_stream_type_midi) {
00545 m->nb_output_ports++;
00546 }
00547 }
00548
00549 m->output_ports = calloc(m->nb_output_ports, sizeof(freebob_midi_port_t *));
00550 if (!m->output_ports) {
00551 printError("not enough memory to create midi structure");
00552 for (i = 0; i < m->nb_input_ports; i++) {
00553 free(m->input_ports[i]);
00554 }
00555 free(m->input_ports);
00556 free(m);
00557 return NULL;
00558 }
00559
00560 i = 0;
00561 for (chn = 0; chn < nchannels; chn++) {
00562 if (freebob_streaming_get_playback_stream_type(dev, chn) == freebob_stream_type_midi) {
00563 m->output_ports[i] = calloc(1, sizeof(freebob_midi_port_t));
00564 if (!m->output_ports[i]) {
00565
00566 printError("Could not allocate memory for seq port");
00567 continue;
00568 }
00569
00570 freebob_streaming_get_playback_stream_name(dev, chn, buf, sizeof(buf));
00571 printMessage("Register MIDI OUT port %s", buf);
00572
00573 m->output_ports[i]->seq_port_nr = snd_seq_create_simple_port(m->seq_handle, buf,
00574 SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE,
00575 SND_SEQ_PORT_TYPE_MIDI_GENERIC);
00576
00577 if (m->output_ports[i]->seq_port_nr < 0) {
00578 printError("Could not create seq port");
00579 m->output_ports[i]->stream_nr = -1;
00580 m->output_ports[i]->seq_port_nr = -1;
00581 } else {
00582 m->output_ports[i]->stream_nr = chn;
00583 m->output_ports[i]->seq_handle = m->seq_handle;
00584 if (snd_midi_event_new ( ALSA_SEQ_BUFF_SIZE, &(m->output_ports[i]->parser)) < 0) {
00585 printError("could not init parser for MIDI OUT port %d", i);
00586 m->output_ports[i]->stream_nr = -1;
00587 m->output_ports[i]->seq_port_nr = -1;
00588 }
00589 }
00590
00591 i++;
00592 }
00593 }
00594
00595 m->dev = dev;
00596 m->driver = driver;
00597 return m;
00598 }
00599
00600 int
00601 JackFreebobDriver::freebob_driver_midi_start (freebob_driver_midi_handle_t *m)
00602 {
00603 assert(m);
00604
00605
00606 m->queue_thread_realtime = (m->driver->engine->control->real_time ? 1 : 0);
00607 m->queue_thread_priority =
00608 m->driver->engine->control->client_priority +
00609 FREEBOB_RT_PRIORITY_MIDI_RELATIVE;
00610
00611 if (m->queue_thread_priority > 98) {
00612 m->queue_thread_priority = 98;
00613 }
00614 if (m->queue_thread_realtime) {
00615 printMessage("MIDI threads running with Realtime scheduling, priority %d",
00616 m->queue_thread_priority);
00617 } else {
00618 printMessage("MIDI threads running without Realtime scheduling");
00619 }
00620
00621 if (jack_client_create_thread(NULL, &m->queue_thread, m->queue_thread_priority, m->queue_thread_realtime, freebob_driver_midi_queue_thread, (void *)m)) {
00622 printError(" cannot create midi queueing thread");
00623 return -1;
00624 }
00625
00626 if (jack_client_create_thread(NULL, &m->dequeue_thread, m->queue_thread_priority, m->queue_thread_realtime, freebob_driver_midi_dequeue_thread, (void *)m)) {
00627 printError(" cannot create midi dequeueing thread");
00628 return -1;
00629 }
00630 return 0;
00631 }
00632
00633 int
00634 JackFreebobDriver::freebob_driver_midi_stop (freebob_driver_midi_handle_t *m)
00635 {
00636 assert(m);
00637
00638 pthread_cancel (m->queue_thread);
00639 pthread_join (m->queue_thread, NULL);
00640
00641 pthread_cancel (m->dequeue_thread);
00642 pthread_join (m->dequeue_thread, NULL);
00643 return 0;
00644 }
00645
00646 void
00647 JackFreebobDriver::freebob_driver_midi_finish (freebob_driver_midi_handle_t *m)
00648 {
00649 assert(m);
00650
00651 int i;
00652
00653
00654 for (i = 0;i < m->nb_input_ports;i++) {
00655 free(m->input_ports[i]);
00656 }
00657 free(m->input_ports);
00658
00659 for (i = 0;i < m->nb_output_ports;i++) {
00660 free(m->output_ports[i]);
00661 }
00662 free(m->output_ports);
00663 free(m);
00664 }
00665 #endif
00666
00667 int JackFreebobDriver::Attach()
00668 {
00669 JackPort* port;
00670 jack_port_id_t port_index;
00671
00672 char buf[REAL_JACK_PORT_NAME_SIZE];
00673 char portname[REAL_JACK_PORT_NAME_SIZE];
00674 jack_latency_range_t range;
00675
00676 freebob_driver_t* driver = (freebob_driver_t*)fDriver;
00677
00678 jack_log("JackFreebobDriver::Attach fBufferSize %ld fSampleRate %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
00679
00680 g_verbose = (fEngineControl->fVerbose ? 1 : 0);
00681 driver->device_options.verbose = (fEngineControl->fVerbose ? 1 : 0);
00682
00683
00684 driver->device_options.realtime = (fEngineControl->fRealTime ? 1 : 0);
00685
00686 driver->device_options.packetizer_priority = fEngineControl->fServerPriority +
00687 FREEBOB_RT_PRIORITY_PACKETIZER_RELATIVE;
00688 if (driver->device_options.packetizer_priority > 98) {
00689 driver->device_options.packetizer_priority = 98;
00690 }
00691
00692
00693 driver->dev = freebob_streaming_init(&driver->device_info, driver->device_options);
00694
00695 if (!driver->dev) {
00696 printError("FREEBOB: Error creating virtual device");
00697 return -1;
00698 }
00699
00700 #ifdef FREEBOB_DRIVER_WITH_MIDI
00701 driver->midi_handle = freebob_driver_midi_init(driver);
00702 if (!driver->midi_handle) {
00703 printError("-----------------------------------------------------------");
00704 printError("Error creating midi device!");
00705 printError("FreeBob will run without MIDI support.");
00706 printError("Consult the above error messages to solve the problem. ");
00707 printError("-----------------------------------------------------------\n\n");
00708 }
00709 #endif
00710
00711 if (driver->device_options.realtime) {
00712 printMessage("Streaming thread running with Realtime scheduling, priority %d",
00713 driver->device_options.packetizer_priority);
00714 } else {
00715 printMessage("Streaming thread running without Realtime scheduling");
00716 }
00717
00718
00719
00720
00721 driver->capture_nchannels = freebob_streaming_get_nb_capture_streams(driver->dev);
00722 driver->capture_nchannels_audio = 0;
00723
00724 for (unsigned int i = 0; i < driver->capture_nchannels; i++) {
00725
00726 freebob_streaming_get_capture_stream_name(driver->dev, i, portname, sizeof(portname));
00727 snprintf(buf, sizeof(buf), "%s:%s", fClientControl.fName, portname);
00728
00729 if (freebob_streaming_get_capture_stream_type(driver->dev, i) != freebob_stream_type_audio) {
00730 printMessage ("Don't register capture port %s", buf);
00731 } else {
00732 printMessage ("Registering capture port %s", buf);
00733
00734 if (fEngine->PortRegister(fClientControl.fRefNum, buf,
00735 JACK_DEFAULT_AUDIO_TYPE,
00736 CaptureDriverFlags,
00737 fEngineControl->fBufferSize, &port_index) < 0) {
00738 jack_error("driver: cannot register port for %s", buf);
00739 return -1;
00740 }
00741 port = fGraphManager->GetPort(port_index);
00742 range.min = range.max = driver->period_size + driver->capture_frame_latency;
00743 port->SetLatencyRange(JackCaptureLatency, &range);
00744 fCapturePortList[i] = port_index;
00745 jack_log("JackFreebobDriver::Attach fCapturePortList[i] %ld ", port_index);
00746 driver->capture_nchannels_audio++;
00747 }
00748 }
00749
00750
00751 driver->playback_nchannels = freebob_streaming_get_nb_playback_streams(driver->dev);
00752 driver->playback_nchannels_audio = 0;
00753
00754 for (unsigned int i = 0; i < driver->playback_nchannels; i++) {
00755
00756 freebob_streaming_get_playback_stream_name(driver->dev, i, portname, sizeof(portname));
00757 snprintf(buf, sizeof(buf), "%s:%s", fClientControl.fName, portname);
00758
00759 if (freebob_streaming_get_playback_stream_type(driver->dev, i) != freebob_stream_type_audio) {
00760 printMessage ("Don't register playback port %s", buf);
00761 } else {
00762 printMessage ("Registering playback port %s", buf);
00763 if (fEngine->PortRegister(fClientControl.fRefNum, buf,
00764 JACK_DEFAULT_AUDIO_TYPE,
00765 PlaybackDriverFlags,
00766 fEngineControl->fBufferSize, &port_index) < 0) {
00767 jack_error("driver: cannot register port for %s", buf);
00768 return -1;
00769 }
00770 port = fGraphManager->GetPort(port_index);
00771
00772 range.min = range.max = (driver->period_size * (driver->device_options.nb_buffers - 1)) + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency;
00773 port->SetLatencyRange(JackPlaybackLatency, &range);
00774 fPlaybackPortList[i] = port_index;
00775 jack_log("JackFreebobDriver::Attach fPlaybackPortList[i] %ld ", port_index);
00776 driver->playback_nchannels_audio++;
00777 }
00778 }
00779
00780 fCaptureChannels = driver->capture_nchannels_audio;
00781 fPlaybackChannels = driver->playback_nchannels_audio;
00782
00783 assert(fCaptureChannels < DRIVER_PORT_NUM);
00784 assert(fPlaybackChannels < DRIVER_PORT_NUM);
00785
00786
00787 assert(fCaptureChannels + fPlaybackChannels > 0);
00788 return 0;
00789 }
00790
00791 int JackFreebobDriver::Detach()
00792 {
00793 freebob_driver_t* driver = (freebob_driver_t*)fDriver;
00794 jack_log("JackFreebobDriver::Detach");
00795
00796
00797 freebob_streaming_finish(driver->dev);
00798 driver->dev = NULL;
00799
00800 #ifdef FREEBOB_DRIVER_WITH_MIDI
00801 if (driver->midi_handle) {
00802 freebob_driver_midi_finish(driver->midi_handle);
00803 }
00804 driver->midi_handle = NULL;
00805 #endif
00806
00807 return JackAudioDriver::Detach();
00808 }
00809
00810 int JackFreebobDriver::Open(freebob_jack_settings_t *params)
00811 {
00812
00813 if (JackAudioDriver::Open(
00814 params->period_size, params->sample_rate,
00815 params->playback_ports, params->playback_ports,
00816 0, 0, 0, "", "",
00817 params->capture_frame_latency, params->playback_frame_latency) != 0) {
00818 return -1;
00819 }
00820
00821 fDriver = (jack_driver_t *)freebob_driver_new ((char*)"freebob_pcm", params);
00822
00823 if (fDriver) {
00824
00825 fCaptureChannels = ((freebob_driver_t *)fDriver)->capture_nchannels_audio;
00826 fPlaybackChannels = ((freebob_driver_t *)fDriver)->playback_nchannels_audio;
00827 return 0;
00828 } else {
00829 JackAudioDriver::Close();
00830 return -1;
00831 }
00832 }
00833
00834 int JackFreebobDriver::Close()
00835 {
00836
00837 int res = JackAudioDriver::Close();
00838
00839 freebob_driver_delete((freebob_driver_t*)fDriver);
00840 return res;
00841 }
00842
00843 int JackFreebobDriver::Start()
00844 {
00845 int res = JackAudioDriver::Start();
00846 if (res >= 0) {
00847 res = freebob_driver_start((freebob_driver_t *)fDriver);
00848 if (res < 0) {
00849 JackAudioDriver::Stop();
00850 }
00851 }
00852 return res;
00853 }
00854
00855 int JackFreebobDriver::Stop()
00856 {
00857 int res = freebob_driver_stop((freebob_driver_t *)fDriver);
00858 if (JackAudioDriver::Stop() < 0) {
00859 res = -1;
00860 }
00861 return res;
00862 }
00863
00864 int JackFreebobDriver::Read()
00865 {
00866 printEnter();
00867
00868
00869 freebob_driver_t* driver = (freebob_driver_t*)fDriver;
00870 int wait_status = 0;
00871 fDelayedUsecs = 0.f;
00872
00873 retry:
00874
00875 jack_nframes_t nframes = freebob_driver_wait (driver, -1, &wait_status,
00876 &fDelayedUsecs);
00877
00878 if ((wait_status < 0)) {
00879 printError( "wait status < 0! (= %d)", wait_status);
00880 return -1;
00881 }
00882
00883 if (nframes == 0) {
00884
00885
00886
00887 jack_log("FreeBoB XRun");
00888 NotifyXRun(fBeginDateUst, fDelayedUsecs);
00889 goto retry;
00890 }
00891
00892 if (nframes != fEngineControl->fBufferSize)
00893 jack_log("JackFreebobDriver::Read warning nframes = %ld", nframes);
00894
00895
00896 JackDriver::CycleIncTime();
00897
00898 printExit();
00899 return freebob_driver_read((freebob_driver_t *)fDriver, fEngineControl->fBufferSize);
00900 }
00901
00902 int JackFreebobDriver::Write()
00903 {
00904 printEnter();
00905 int res = freebob_driver_write((freebob_driver_t *)fDriver, fEngineControl->fBufferSize);
00906 printExit();
00907 return res;
00908 }
00909
00910 void
00911 JackFreebobDriver::jack_driver_init (jack_driver_t *driver)
00912 {
00913 memset (driver, 0, sizeof (*driver));
00914
00915 driver->attach = 0;
00916 driver->detach = 0;
00917 driver->write = 0;
00918 driver->read = 0;
00919 driver->null_cycle = 0;
00920 driver->bufsize = 0;
00921 driver->start = 0;
00922 driver->stop = 0;
00923 }
00924
00925 void
00926 JackFreebobDriver::jack_driver_nt_init (jack_driver_nt_t * driver)
00927 {
00928 memset (driver, 0, sizeof (*driver));
00929
00930 jack_driver_init ((jack_driver_t *) driver);
00931
00932 driver->attach = 0;
00933 driver->detach = 0;
00934 driver->bufsize = 0;
00935 driver->stop = 0;
00936 driver->start = 0;
00937
00938 driver->nt_bufsize = 0;
00939 driver->nt_start = 0;
00940 driver->nt_stop = 0;
00941 driver->nt_attach = 0;
00942 driver->nt_detach = 0;
00943 driver->nt_run_cycle = 0;
00944 }
00945
00946 }
00947
00948 #ifdef __cplusplus
00949 extern "C"
00950 {
00951 #endif
00952
00953 const jack_driver_desc_t *
00954 driver_get_descriptor () {
00955 jack_driver_desc_t * desc;
00956 jack_driver_desc_filler_t filler;
00957 jack_driver_param_value_t value;
00958
00959 desc = jack_driver_descriptor_construct("freebob", JackDriverMaster, "Linux FreeBob API based audio backend", &filler);
00960
00961 strcpy(value.str, "hw:0");
00962 jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "The FireWire device to use. Format is: 'hw:port[,node]'.", NULL);
00963
00964 value.ui = 1024;
00965 jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
00966
00967 value.ui = 3;
00968 jack_driver_descriptor_add_parameter(desc, &filler, "nperiods", 'n', JackDriverParamUInt, &value, NULL, "Number of periods of playback latency", NULL);
00969
00970 value.ui = 48000U;
00971 jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
00972
00973 value.i = 0;
00974 jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamBool, &value, NULL, "Provide capture ports.", NULL);
00975 jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamBool, &value, NULL, "Provide playback ports.", NULL);
00976
00977 value.i = 1;
00978 jack_driver_descriptor_add_parameter(desc, &filler, "duplex", 'D', JackDriverParamBool, &value, NULL, "Provide both capture and playback ports.", NULL);
00979
00980 value.ui = 0;
00981 jack_driver_descriptor_add_parameter(desc, &filler, "input-latency", 'I', JackDriverParamUInt, &value, NULL, "Extra input latency (frames)", NULL);
00982 jack_driver_descriptor_add_parameter(desc, &filler, "output-latency", 'O', JackDriverParamUInt, &value, NULL, "Extra output latency (frames)", NULL);
00983
00984 value.ui = 0;
00985 jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamUInt, &value, NULL, "Number of input channels to provide (note: currently ignored)", NULL);
00986 jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamUInt, &value, NULL, "Number of output channels to provide (note: currently ignored)", NULL);
00987
00988 return desc;
00989 }
00990
00991 Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) {
00992 unsigned int port = 0;
00993 unsigned int node_id = -1;
00994 int nbitems;
00995
00996 const JSList * node;
00997 const jack_driver_param_t * param;
00998
00999 freebob_jack_settings_t cmlparams;
01000
01001 const char *device_name = "hw:0";
01002
01003 cmlparams.period_size_set = 0;
01004 cmlparams.sample_rate_set = 0;
01005 cmlparams.buffer_size_set = 0;
01006 cmlparams.port_set = 0;
01007 cmlparams.node_id_set = 0;
01008
01009
01010 cmlparams.period_size = 1024;
01011 cmlparams.sample_rate = 48000;
01012 cmlparams.buffer_size = 3;
01013 cmlparams.port = 0;
01014 cmlparams.node_id = -1;
01015 cmlparams.playback_ports = 0;
01016 cmlparams.capture_ports = 0;
01017 cmlparams.playback_frame_latency = 0;
01018 cmlparams.capture_frame_latency = 0;
01019
01020 for (node = params; node; node = jack_slist_next (node)) {
01021 param = (jack_driver_param_t *) node->data;
01022
01023 switch (param->character) {
01024 case 'd':
01025 device_name = param->value.str;
01026 break;
01027 case 'p':
01028 cmlparams.period_size = param->value.ui;
01029 cmlparams.period_size_set = 1;
01030 break;
01031 case 'n':
01032 cmlparams.buffer_size = param->value.ui;
01033 cmlparams.buffer_size_set = 1;
01034 break;
01035 case 'r':
01036 cmlparams.sample_rate = param->value.ui;
01037 cmlparams.sample_rate_set = 1;
01038 break;
01039 case 'C':
01040 cmlparams.capture_ports = 1;
01041 break;
01042 case 'P':
01043 cmlparams.playback_ports = 1;
01044 break;
01045 case 'D':
01046 cmlparams.capture_ports = 1;
01047 cmlparams.playback_ports = 1;
01048 break;
01049 case 'I':
01050 cmlparams.capture_frame_latency = param->value.ui;
01051 break;
01052 case 'O':
01053 cmlparams.playback_frame_latency = param->value.ui;
01054 break;
01055
01056 case 'i':
01057 break;
01058 case 'o':
01059 break;
01060 }
01061 }
01062
01063
01064 if (!cmlparams.playback_ports && !cmlparams.capture_ports) {
01065 cmlparams.playback_ports = TRUE;
01066 cmlparams.capture_ports = TRUE;
01067 }
01068
01069 nbitems = sscanf(device_name, "hw:%u,%u", &port, &node_id);
01070 if (nbitems < 2) {
01071 nbitems = sscanf(device_name, "hw:%u", &port);
01072
01073 if (nbitems < 1) {
01074 printError("device (-d) argument not valid\n");
01075 return NULL;
01076 } else {
01077 cmlparams.port = port;
01078 cmlparams.port_set = 1;
01079
01080 cmlparams.node_id = -1;
01081 cmlparams.node_id_set = 0;
01082 }
01083 } else {
01084 cmlparams.port = port;
01085 cmlparams.port_set = 1;
01086
01087 cmlparams.node_id = node_id;
01088 cmlparams.node_id_set = 1;
01089 }
01090
01091 jack_error("Freebob using Firewire port %d, node %d", cmlparams.port, cmlparams.node_id);
01092
01093 Jack::JackFreebobDriver* freebob_driver = new Jack::JackFreebobDriver("system", "freebob_pcm", engine, table);
01094 Jack::JackDriverClientInterface* threaded_driver = new Jack::JackThreadedDriver(freebob_driver);
01095
01096 if (freebob_driver->Open(&cmlparams) == 0) {
01097 return threaded_driver;
01098 } else {
01099 delete threaded_driver;
01100 return NULL;
01101 }
01102 }
01103
01104 #ifdef __cplusplus
01105 }
01106 #endif
01107
01108