32 #include <sys/types.h>    37 #include "JackFreebobDriver.h"    38 #include "JackEngineControl.h"    39 #include "JackClientControl.h"    41 #include "JackGraphManager.h"    42 #include "JackLockedEngine.h"    47 #define jack_get_microseconds GetMicroSeconds    49 #define SAMPLE_MAX_24BIT  8388608.0f    50 #define SAMPLE_MAX_16BIT  32768.0f    53 JackFreebobDriver::freebob_driver_read (
freebob_driver_t * driver, jack_nframes_t nframes)
    55     jack_default_audio_sample_t* buf = NULL;
    56     freebob_sample_t nullbuffer[nframes];
    57     void *addr_of_nullbuffer = (
void *)nullbuffer;
    59     freebob_streaming_stream_type stream_type;
    64     for (
unsigned int i = 0; i < driver->capture_nchannels; i++) {
    65         stream_type = freebob_streaming_get_playback_stream_type(driver->dev, i);
    66         if (stream_type == freebob_stream_type_audio) {
    67             freebob_streaming_set_playback_stream_buffer(driver->dev, i,
    68                     (
char *)(nullbuffer), freebob_buffer_type_float);
    69         } 
else if (stream_type == freebob_stream_type_midi) {
    72             freebob_streaming_set_playback_stream_buffer(driver->dev, i,
    73                     (
char *)(nullbuffer), freebob_buffer_type_uint24);
    77     for (
int i = 0; i < fCaptureChannels; i++) {
    78         stream_type = freebob_streaming_get_capture_stream_type(driver->dev, i);
    79         if (stream_type == freebob_stream_type_audio) {
    81             if (fGraphManager->GetConnectionsNum(fCapturePortList[i]) > 0) {
    82                 buf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fCapturePortList[i],  nframes);
    85                     buf = (jack_default_audio_sample_t *)addr_of_nullbuffer;
    88                 freebob_streaming_set_capture_stream_buffer(driver->dev, i, (
char *)(buf), freebob_buffer_type_float);
    90         } 
else if (stream_type == freebob_stream_type_midi) {
    93             freebob_streaming_set_capture_stream_buffer(driver->dev, i, (
char *)(nullbuffer), freebob_buffer_type_uint24);
    99     freebob_streaming_transfer_capture_buffers(driver->dev);
   105 JackFreebobDriver::freebob_driver_write (
freebob_driver_t * driver, jack_nframes_t nframes)
   107     jack_default_audio_sample_t* buf = NULL;
   109     freebob_streaming_stream_type stream_type;
   111     freebob_sample_t nullbuffer[nframes];
   112     void *addr_of_nullbuffer = (
void*)nullbuffer;
   114     memset(&nullbuffer, 0, nframes*
sizeof(freebob_sample_t));
   117     driver->process_count++;
   121     for (
unsigned int i = 0; i < driver->playback_nchannels; i++) {
   122         stream_type = freebob_streaming_get_playback_stream_type(driver->dev, i);
   123         if (stream_type == freebob_stream_type_audio) {
   124             freebob_streaming_set_playback_stream_buffer(driver->dev, i,
   125                     (
char *)(nullbuffer), freebob_buffer_type_float);
   126         } 
else if (stream_type == freebob_stream_type_midi) {
   129             freebob_streaming_set_playback_stream_buffer(driver->dev, i,
   130                     (
char *)(nullbuffer), freebob_buffer_type_uint24);
   134     for (
int i = 0; i < fPlaybackChannels; i++) {
   135         stream_type = freebob_streaming_get_playback_stream_type(driver->dev, i);
   136         if (stream_type == freebob_stream_type_audio) {
   138             if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) {
   139                 buf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fPlaybackPortList[i], nframes);
   141                     buf = (jack_default_audio_sample_t *)addr_of_nullbuffer;
   143                 freebob_streaming_set_playback_stream_buffer(driver->dev, i, (
char *)(buf), freebob_buffer_type_float);
   148     freebob_streaming_transfer_playback_buffers(driver->dev);
   154 JackFreebobDriver::freebob_driver_wait (
freebob_driver_t *driver, 
int extra_fd, 
int *status,
   155                                         float *delayed_usecs)
   158     jack_time_t wait_enter;
   159     jack_time_t wait_ret;
   163     wait_enter = jack_get_microseconds ();
   164     if (wait_enter > driver->wait_next) {
   170         driver->wait_next = 0;
   177     nframes = freebob_streaming_wait(driver->dev);
   179     wait_ret = jack_get_microseconds ();
   181     if (driver->wait_next && wait_ret > driver->wait_next) {
   182         *delayed_usecs = wait_ret - driver->wait_next;
   184     driver->wait_last = wait_ret;
   185     driver->wait_next = wait_ret + driver->period_usecs;
   194     fBeginDateUst = wait_ret;
   199     return nframes - nframes % driver->period_size;
   207 #ifdef FREEBOB_DRIVER_WITH_MIDI   208     if (driver->midi_handle) {
   209         if ((retval = freebob_driver_midi_start(driver->midi_handle))) {
   210             printError(
"Could not start MIDI threads");
   216     if ((retval = freebob_streaming_start(driver->dev))) {
   217         printError(
"Could not start streaming threads");
   218 #ifdef FREEBOB_DRIVER_WITH_MIDI   219         if (driver->midi_handle) {
   220             freebob_driver_midi_stop(driver->midi_handle);
   234 #ifdef FREEBOB_DRIVER_WITH_MIDI   235     if (driver->midi_handle) {
   236         if ((retval = freebob_driver_midi_stop(driver->midi_handle))) {
   237             printError(
"Could not stop MIDI threads");
   242     if ((retval = freebob_streaming_stop(driver->dev))) {
   243         printError(
"Could not stop streaming threads");
   259 JackFreebobDriver::SetBufferSize (jack_nframes_t nframes)
   261     printError(
"Buffer size change requested but not supported!!!");
   279 JackFreebobDriver::freebob_driver_new (
char *name,
   286     if (freebob_get_api_version() != 1) {
   287         printMessage(
"Incompatible libfreebob version! (%s)", freebob_get_version());
   291     printMessage(
"Starting Freebob backend (%s)", freebob_get_version());
   313     driver->sample_rate = params->sample_rate;
   314     driver->period_size = params->period_size;
   317     driver->period_usecs =
   318         (jack_time_t) floor ((((
float) driver->period_size) * 1000000.0f) / driver->sample_rate);
   321     driver->engine = NULL;
   323     memset(&driver->device_options, 0, 
sizeof(driver->device_options));
   324     driver->device_options.sample_rate = params->sample_rate;
   325     driver->device_options.period_size = params->period_size;
   326     driver->device_options.nb_buffers = params->buffer_size;
   327     driver->device_options.node_id = params->node_id;
   328     driver->device_options.port = params->port;
   329     driver->capture_frame_latency = params->capture_frame_latency;
   330     driver->playback_frame_latency = params->playback_frame_latency;
   332     if (!params->capture_ports) {
   333         driver->device_options.directions |= FREEBOB_IGNORE_CAPTURE;
   336     if (!params->playback_ports) {
   337         driver->device_options.directions |= FREEBOB_IGNORE_PLAYBACK;
   340     debugPrint(DEBUG_LEVEL_STARTUP, 
" Driver compiled on %s %s", __DATE__, __TIME__);
   341     debugPrint(DEBUG_LEVEL_STARTUP, 
" Created driver %s", name);
   342     debugPrint(DEBUG_LEVEL_STARTUP, 
"            period_size: %d", driver->period_size);
   343     debugPrint(DEBUG_LEVEL_STARTUP, 
"            period_usecs: %d", driver->period_usecs);
   344     debugPrint(DEBUG_LEVEL_STARTUP, 
"            sample rate: %d", driver->sample_rate);
   355 #ifdef FREEBOB_DRIVER_WITH_MIDI   363 JackFreebobDriver::freebob_driver_midi_queue_thread(
void *arg)
   365     freebob_driver_midi_handle_t *m = (freebob_driver_midi_handle_t *)arg;
   368     unsigned char work_buffer[MIDI_TRANSMIT_BUFFER_SIZE];
   373     printMessage(
"MIDI queue thread started");
   377         while ((snd_seq_event_input(m->seq_handle, &ev) > 0)) {
   379             freebob_midi_port_t *port = NULL;
   380             for (i = 0;i < m->nb_output_ports;i++) {
   381                 if (m->output_ports[i]->seq_port_nr == ev->dest.port) {
   382                     port = m->output_ports[i];
   388                 printError(
" Could not find target port for event: dst=%d src=%d", ev->dest.port, ev->source.port);
   393             if ((bytes_to_send = snd_midi_event_decode ( port->parser,
   395                                  MIDI_TRANSMIT_BUFFER_SIZE,
   397                 printError(
" Error decoding event for port %d (errcode=%d)", port->seq_port_nr, bytes_to_send);
   402             for (b = 0;b < bytes_to_send;b++) {
   403                 freebob_sample_t tmp_event = work_buffer[b];
   404                 if (freebob_streaming_write(m->dev, port->stream_nr, &tmp_event, 1) < 1) {
   405                     printError(
" Midi send buffer overrun");
   411         usleep(MIDI_THREAD_SLEEP_TIME_USECS);
   418 JackFreebobDriver::freebob_driver_midi_dequeue_thread (
void *arg)
   420     freebob_driver_midi_handle_t *m = (freebob_driver_midi_handle_t *)arg;
   431         for (i = 0;i < m->nb_input_ports;i++) {
   432             unsigned int buff[64];
   433             freebob_midi_port_t *port = m->input_ports[i];
   435                 printError(
" something went wrong when setting up the midi input port map (%d)", i);
   439                 samples_read = freebob_streaming_read(m->dev, port->stream_nr, buff, 64);
   441                 for (s = 0;s < samples_read;s++) {
   442                     unsigned int *byte = (buff + s) ;
   444                     if ((snd_midi_event_encode_byte(port->parser, (*byte) & 0xFF, &ev)) > 0) {
   446                         snd_seq_ev_set_subs(&ev);
   447                         snd_seq_ev_set_direct(&ev);
   448                         snd_seq_ev_set_source(&ev, port->seq_port_nr);
   449                         snd_seq_event_output_direct(port->seq_handle, &ev);
   452             } 
while (samples_read > 0);
   456         usleep(MIDI_THREAD_SLEEP_TIME_USECS);
   461 freebob_driver_midi_handle_t *
   469     freebob_device_t *dev = driver->dev;
   472     freebob_driver_midi_handle_t *m = calloc(1, 
sizeof(freebob_driver_midi_handle_t));
   474         printError(
"not enough memory to create midi structure");
   478     if (snd_seq_open(&m->seq_handle, 
"default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK) < 0) {
   479         printError(
"Error opening ALSA sequencer.");
   484     snd_seq_set_client_name(m->seq_handle, 
"FreeBoB Jack MIDI");
   487     nchannels = freebob_streaming_get_nb_capture_streams(dev);
   488     m->nb_input_ports = 0;
   490     for (chn = 0; chn < nchannels; chn++) {
   491         if (freebob_streaming_get_capture_stream_type(dev, chn) == freebob_stream_type_midi) {
   496     m->input_ports = calloc(m->nb_input_ports, 
sizeof(freebob_midi_port_t *));
   497     if (!m->input_ports) {
   498         printError(
"not enough memory to create midi structure");
   504     for (chn = 0; chn < nchannels; chn++) {
   505         if (freebob_streaming_get_capture_stream_type(dev, chn) == freebob_stream_type_midi) {
   506             m->input_ports[i] = calloc(1, 
sizeof(freebob_midi_port_t));
   507             if (!m->input_ports[i]) {
   509                 printError(
"Could not allocate memory for seq port");
   513             freebob_streaming_get_capture_stream_name(dev, chn, buf, 
sizeof(buf));
   514             printMessage(
"Register MIDI IN port %s", buf);
   516             m->input_ports[i]->seq_port_nr = snd_seq_create_simple_port(m->seq_handle, buf,
   517                                              SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ,
   518                                              SND_SEQ_PORT_TYPE_MIDI_GENERIC);
   520             if (m->input_ports[i]->seq_port_nr < 0) {
   521                 printError(
"Could not create seq port");
   522                 m->input_ports[i]->stream_nr = -1;
   523                 m->input_ports[i]->seq_port_nr = -1;
   525                 m->input_ports[i]->stream_nr = chn;
   526                 m->input_ports[i]->seq_handle = m->seq_handle;
   527                 if (snd_midi_event_new  ( ALSA_SEQ_BUFF_SIZE, &(m->input_ports[i]->parser)) < 0) {
   528                     printError(
"could not init parser for MIDI IN port %d", i);
   529                     m->input_ports[i]->stream_nr = -1;
   530                     m->input_ports[i]->seq_port_nr = -1;
   539     nchannels = freebob_streaming_get_nb_playback_streams(dev);
   541     m->nb_output_ports = 0;
   543     for (chn = 0; chn < nchannels; chn++) {
   544         if (freebob_streaming_get_playback_stream_type(dev, chn) == freebob_stream_type_midi) {
   545             m->nb_output_ports++;
   549     m->output_ports = calloc(m->nb_output_ports, 
sizeof(freebob_midi_port_t *));
   550     if (!m->output_ports) {
   551         printError(
"not enough memory to create midi structure");
   552         for (i = 0; i < m->nb_input_ports; i++) {
   553             free(m->input_ports[i]);
   555         free(m->input_ports);
   561     for (chn = 0; chn < nchannels; chn++) {
   562         if (freebob_streaming_get_playback_stream_type(dev, chn) == freebob_stream_type_midi) {
   563             m->output_ports[i] = calloc(1, 
sizeof(freebob_midi_port_t));
   564             if (!m->output_ports[i]) {
   566                 printError(
"Could not allocate memory for seq port");
   570             freebob_streaming_get_playback_stream_name(dev, chn, buf, 
sizeof(buf));
   571             printMessage(
"Register MIDI OUT port %s", buf);
   573             m->output_ports[i]->seq_port_nr = snd_seq_create_simple_port(m->seq_handle, buf,
   574                                               SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE,
   575                                               SND_SEQ_PORT_TYPE_MIDI_GENERIC);
   577             if (m->output_ports[i]->seq_port_nr < 0) {
   578                 printError(
"Could not create seq port");
   579                 m->output_ports[i]->stream_nr = -1;
   580                 m->output_ports[i]->seq_port_nr = -1;
   582                 m->output_ports[i]->stream_nr = chn;
   583                 m->output_ports[i]->seq_handle = m->seq_handle;
   584                 if (snd_midi_event_new  ( ALSA_SEQ_BUFF_SIZE, &(m->output_ports[i]->parser)) < 0) {
   585                     printError(
"could not init parser for MIDI OUT port %d", i);
   586                     m->output_ports[i]->stream_nr = -1;
   587                     m->output_ports[i]->seq_port_nr = -1;
   601 JackFreebobDriver::freebob_driver_midi_start (freebob_driver_midi_handle_t *m)
   606     m->queue_thread_realtime = (m->driver->engine->control->real_time ? 1 : 0);
   607     m->queue_thread_priority =
   608         m->driver->engine->control->client_priority +
   609         FREEBOB_RT_PRIORITY_MIDI_RELATIVE;
   611     if (m->queue_thread_priority > 98) {
   612         m->queue_thread_priority = 98;
   614     if (m->queue_thread_realtime) {
   615         printMessage(
"MIDI threads running with Realtime scheduling, priority %d",
   616                      m->queue_thread_priority);
   618         printMessage(
"MIDI threads running without Realtime scheduling");
   621     if (
jack_client_create_thread(NULL, &m->queue_thread, m->queue_thread_priority, m->queue_thread_realtime, freebob_driver_midi_queue_thread, (
void *)m)) {
   622         printError(
" cannot create midi queueing thread");
   626     if (
jack_client_create_thread(NULL, &m->dequeue_thread, m->queue_thread_priority, m->queue_thread_realtime, freebob_driver_midi_dequeue_thread, (
void *)m)) {
   627         printError(
" cannot create midi dequeueing thread");
   634 JackFreebobDriver::freebob_driver_midi_stop (freebob_driver_midi_handle_t *m)
   638     pthread_cancel (m->queue_thread);
   639     pthread_join (m->queue_thread, NULL);
   641     pthread_cancel (m->dequeue_thread);
   642     pthread_join (m->dequeue_thread, NULL);
   647 JackFreebobDriver::freebob_driver_midi_finish (freebob_driver_midi_handle_t *m)
   654     for (i = 0;i < m->nb_input_ports;i++) {
   655         free(m->input_ports[i]);
   657     free(m->input_ports);
   659     for (i = 0;i < m->nb_output_ports;i++) {
   660         free(m->output_ports[i]);
   662     free(m->output_ports);
   667 int JackFreebobDriver::Attach()
   670     jack_port_id_t port_index;
   672     char buf[REAL_JACK_PORT_NAME_SIZE];
   673     char portname[REAL_JACK_PORT_NAME_SIZE];
   678     jack_log(
"JackFreebobDriver::Attach fBufferSize %ld fSampleRate %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
   680     g_verbose = (fEngineControl->fVerbose ? 1 : 0);
   681     driver->device_options.verbose = (fEngineControl->fVerbose ? 1 : 0);
   684     driver->device_options.realtime = (fEngineControl->fRealTime ? 1 : 0);
   686     driver->device_options.packetizer_priority = fEngineControl->fServerPriority +
   687             FREEBOB_RT_PRIORITY_PACKETIZER_RELATIVE;
   688     if (driver->device_options.packetizer_priority > 98) {
   689         driver->device_options.packetizer_priority = 98;
   693     driver->dev = freebob_streaming_init(&driver->device_info, driver->device_options);
   696         printError(
"FREEBOB: Error creating virtual device");
   700 #ifdef FREEBOB_DRIVER_WITH_MIDI   701     driver->midi_handle = freebob_driver_midi_init(driver);
   702     if (!driver->midi_handle) {
   703         printError(
"-----------------------------------------------------------");
   704         printError(
"Error creating midi device!");
   705         printError(
"FreeBob will run without MIDI support.");
   706         printError(
"Consult the above error messages to solve the problem. ");
   707         printError(
"-----------------------------------------------------------\n\n");
   711     if (driver->device_options.realtime) {
   712         printMessage(
"Streaming thread running with Realtime scheduling, priority %d",
   713                      driver->device_options.packetizer_priority);
   715         printMessage(
"Streaming thread running without Realtime scheduling");
   721     driver->capture_nchannels = freebob_streaming_get_nb_capture_streams(driver->dev);
   722     driver->capture_nchannels_audio = 0;
   724     for (
unsigned int i = 0; i < driver->capture_nchannels; i++) {
   726         freebob_streaming_get_capture_stream_name(driver->dev, i, portname, 
sizeof(portname));
   727         snprintf(buf, 
sizeof(buf), 
"%s:%s", fClientControl.fName, portname);
   729         if (freebob_streaming_get_capture_stream_type(driver->dev, i) != freebob_stream_type_audio) {
   730             printMessage (
"Don't register capture port %s", buf);
   732             printMessage (
"Registering capture port %s", buf);
   734             if (fEngine->PortRegister(fClientControl.fRefNum, buf,
   735                               JACK_DEFAULT_AUDIO_TYPE,
   737                               fEngineControl->fBufferSize, &port_index) < 0) {
   738                 jack_error(
"driver: cannot register port for %s", buf);
   741             port = fGraphManager->GetPort(port_index);
   742             range.
min = range.
max = driver->period_size + driver->capture_frame_latency;
   743             port->SetLatencyRange(JackCaptureLatency, &range);
   744             fCapturePortList[i] = port_index;
   745             jack_log(
"JackFreebobDriver::Attach fCapturePortList[i] %ld ", port_index);
   746             driver->capture_nchannels_audio++;
   751     driver->playback_nchannels = freebob_streaming_get_nb_playback_streams(driver->dev);
   752     driver->playback_nchannels_audio = 0;
   754     for (
unsigned int i = 0; i < driver->playback_nchannels; i++) {
   756         freebob_streaming_get_playback_stream_name(driver->dev, i, portname, 
sizeof(portname));
   757         snprintf(buf, 
sizeof(buf), 
"%s:%s", fClientControl.fName, portname);
   759         if (freebob_streaming_get_playback_stream_type(driver->dev, i) != freebob_stream_type_audio) {
   760             printMessage (
"Don't register playback port %s", buf);
   762             printMessage (
"Registering playback port %s", buf);
   763             if (fEngine->PortRegister(fClientControl.fRefNum, buf,
   764                               JACK_DEFAULT_AUDIO_TYPE,
   766                               fEngineControl->fBufferSize, &port_index) < 0) {
   767                 jack_error(
"driver: cannot register port for %s", buf);
   770             port = fGraphManager->GetPort(port_index);
   772             range.
min = range.
max = (driver->period_size * (driver->device_options.nb_buffers - 1)) + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency;
   773             port->SetLatencyRange(JackPlaybackLatency, &range);
   774             fPlaybackPortList[i] = port_index;
   775             jack_log(
"JackFreebobDriver::Attach fPlaybackPortList[i] %ld ", port_index);
   776             driver->playback_nchannels_audio++;
   780     fCaptureChannels = driver->capture_nchannels_audio;
   781     fPlaybackChannels = driver->playback_nchannels_audio;
   783     assert(fCaptureChannels < DRIVER_PORT_NUM);
   784     assert(fPlaybackChannels < DRIVER_PORT_NUM);
   787     assert(fCaptureChannels + fPlaybackChannels > 0);
   791 int JackFreebobDriver::Detach()
   794     jack_log(
"JackFreebobDriver::Detach");
   797     freebob_streaming_finish(driver->dev);
   800 #ifdef FREEBOB_DRIVER_WITH_MIDI   801     if (driver->midi_handle) {
   802         freebob_driver_midi_finish(driver->midi_handle);
   804     driver->midi_handle = NULL;
   807     return JackAudioDriver::Detach();  
   813     if (JackAudioDriver::Open(
   814                 params->period_size, params->sample_rate,
   815                 params->playback_ports, params->playback_ports,
   817                 params->capture_frame_latency, params->playback_frame_latency) != 0) {
   821     fDriver = (
jack_driver_t *)freebob_driver_new ((
char*)
"freebob_pcm", params);
   826         fPlaybackChannels = ((
freebob_driver_t *)fDriver)->playback_nchannels_audio;
   829         JackAudioDriver::Close();
   834 int JackFreebobDriver::Close()
   837     int res = JackAudioDriver::Close();
   843 int JackFreebobDriver::Start()
   845     int res = JackAudioDriver::Start();
   849             JackAudioDriver::Stop();
   855 int JackFreebobDriver::Stop()
   858     if (JackAudioDriver::Stop() < 0) {
   864 int JackFreebobDriver::Read()
   875     jack_nframes_t nframes = freebob_driver_wait (driver, -1, &wait_status,
   878     if ((wait_status < 0)) {
   879         printError( 
"wait status < 0! (= %d)", wait_status);
   888         NotifyXRun(fBeginDateUst, fDelayedUsecs);
   892     if (nframes != fEngineControl->fBufferSize)
   893         jack_log(
"JackFreebobDriver::Read warning nframes = %ld", nframes);
   896     JackDriver::CycleIncTime();
   899     return freebob_driver_read((
freebob_driver_t *)fDriver, fEngineControl->fBufferSize);
   902 int JackFreebobDriver::Write()
   905     int res = freebob_driver_write((
freebob_driver_t *)fDriver, fEngineControl->fBufferSize);
   913     memset (driver, 0, 
sizeof (*driver));
   919     driver->null_cycle = 0;
   928     memset (driver, 0, 
sizeof (*driver));
   938     driver->nt_bufsize = 0;
   939     driver->nt_start = 0;
   941     driver->nt_attach = 0;
   942     driver->nt_detach = 0;
   943     driver->nt_run_cycle = 0;
   954     driver_get_descriptor () {
   959         desc = jack_driver_descriptor_construct(
"freebob", JackDriverMaster, 
"Linux FreeBob API based audio backend", &filler);
   961         strcpy(value.str, 
"hw:0");
   962         jack_driver_descriptor_add_parameter(desc, &filler, 
"device", 
'd', JackDriverParamString, &value, NULL, 
"The FireWire device to use. Format is: 'hw:port[,node]'.", NULL);
   965         jack_driver_descriptor_add_parameter(desc, &filler, 
"period", 
'p', JackDriverParamUInt, &value, NULL, 
"Frames per period", NULL);
   968         jack_driver_descriptor_add_parameter(desc, &filler, 
"nperiods", 
'n', JackDriverParamUInt, &value, NULL, 
"Number of periods of playback latency", NULL);
   971         jack_driver_descriptor_add_parameter(desc, &filler, 
"rate", 
'r', JackDriverParamUInt, &value, NULL, 
"Sample rate", NULL);
   974         jack_driver_descriptor_add_parameter(desc, &filler, 
"capture", 
'C', JackDriverParamBool, &value, NULL, 
"Provide capture ports.", NULL);
   975         jack_driver_descriptor_add_parameter(desc, &filler, 
"playback", 
'P', JackDriverParamBool, &value, NULL, 
"Provide playback ports.", NULL);
   978         jack_driver_descriptor_add_parameter(desc, &filler, 
"duplex", 
'D', JackDriverParamBool, &value, NULL, 
"Provide both capture and playback ports.", NULL);
   981         jack_driver_descriptor_add_parameter(desc, &filler, 
"input-latency", 
'I', JackDriverParamUInt, &value, NULL, 
"Extra input latency (frames)", NULL);
   982         jack_driver_descriptor_add_parameter(desc, &filler, 
"output-latency", 
'O', JackDriverParamUInt, &value, NULL, 
"Extra output latency (frames)", NULL);
   985         jack_driver_descriptor_add_parameter(desc, &filler, 
"inchannels", 
'i', JackDriverParamUInt, &value, NULL, 
"Number of input channels to provide (note: currently ignored)", NULL);
   986         jack_driver_descriptor_add_parameter(desc, &filler, 
"outchannels", 
'o', JackDriverParamUInt, &value, NULL, 
"Number of output channels to provide (note: currently ignored)", NULL);
   992         unsigned int port = 0;
   993         unsigned int node_id = -1;
  1001         const char *device_name = 
"hw:0";
  1003         cmlparams.period_size_set = 0;
  1004         cmlparams.sample_rate_set = 0;
  1005         cmlparams.buffer_size_set = 0;
  1006         cmlparams.port_set = 0;
  1007         cmlparams.node_id_set = 0;
  1010         cmlparams.period_size = 1024;
  1011         cmlparams.sample_rate = 48000;
  1012         cmlparams.buffer_size = 3;
  1014         cmlparams.node_id = -1;
  1015         cmlparams.playback_ports = 0;
  1016         cmlparams.capture_ports = 0;
  1017         cmlparams.playback_frame_latency = 0;
  1018         cmlparams.capture_frame_latency = 0;
  1020         for (node = params; node; node = jack_slist_next (node)) {
  1023             switch (param->character) {
  1025                     device_name = param->value.str;
  1028                     cmlparams.period_size = param->value.ui;
  1029                     cmlparams.period_size_set = 1;
  1032                     cmlparams.buffer_size = param->value.ui;
  1033                     cmlparams.buffer_size_set = 1;
  1036                     cmlparams.sample_rate = param->value.ui;
  1037                     cmlparams.sample_rate_set = 1;
  1040                     cmlparams.capture_ports = 1;
  1043                     cmlparams.playback_ports = 1;
  1046                     cmlparams.capture_ports = 1;
  1047                     cmlparams.playback_ports = 1;
  1050                     cmlparams.capture_frame_latency = param->value.ui;
  1053                     cmlparams.playback_frame_latency = param->value.ui;
  1064         if (!cmlparams.playback_ports && !cmlparams.capture_ports) {
  1065             cmlparams.playback_ports = TRUE;
  1066             cmlparams.capture_ports = TRUE;
  1069         nbitems = sscanf(device_name, 
"hw:%u,%u", &port, &node_id);
  1071             nbitems = sscanf(device_name, 
"hw:%u", &port);
  1074                 printError(
"device (-d) argument not valid\n");
  1077                 cmlparams.port = port;
  1078                 cmlparams.port_set = 1;
  1080                 cmlparams.node_id = -1;
  1081                 cmlparams.node_id_set = 0;
  1084             cmlparams.port = port;
  1085             cmlparams.port_set = 1;
  1087             cmlparams.node_id = node_id;
  1088             cmlparams.node_id_set = 1;
  1091         jack_error(
"Freebob using Firewire port %d, node %d", cmlparams.port, cmlparams.node_id);
  1096         if (freebob_driver->Open(&cmlparams) == 0) {
  1097             return threaded_driver;
  1099             delete threaded_driver; 
 The base class for threaded drivers using a "decorator" pattern. Threaded drivers are used with block...
Locked Engine, access to methods is serialized using a mutex. 
Inter process synchronization using POSIX semaphore. 
SERVER_EXPORT void jack_error(const char *fmt,...)
LIB_EXPORT int jack_client_create_thread(jack_client_t *client, jack_native_thread_t *thread, int priority, int realtime, thread_routine routine, void *arg)
The base interface for drivers clients. 
SERVER_EXPORT void jack_log(const char *fmt,...)