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...
Inter process synchronization using using Mach semaphore.
Locked Engine, access to methods is serialized using a mutex.
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,...)