Browse Source

Pieter Palmers FFADO patch.

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@1882 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/0.71
sletz 17 years ago
parent
commit
4910f66f70
6 changed files with 425 additions and 625 deletions
  1. +1
    -1
      ChangeLog
  2. +1
    -1
      SConstruct
  3. +2
    -2
      common/SConscript
  4. +311
    -473
      linux/firewire/JackFFADODriver.cpp
  5. +0
    -7
      linux/firewire/JackFFADODriver.h
  6. +110
    -141
      linux/firewire/ffado_driver.h

+ 1
- 1
ChangeLog View File

@@ -19,7 +19,7 @@ Tim Blechmann


2008-02-25 Stephane Letz <letz@grame.fr> 2008-02-25 Stephane Letz <letz@grame.fr>
* Correct Linux makefile.
* Correct Linux makefile. Pieter Palmers FFADO patch.


2008-02-22 Stephane Letz <letz@grame.fr> 2008-02-22 Stephane Letz <letz@grame.fr>


+ 1
- 1
SConstruct View File

@@ -176,7 +176,7 @@ install the needed packages (remember to also install the *-devel packages)
env['ENABLE_FREEBOB'] = False env['ENABLE_FREEBOB'] = False


if build_for_linux and env['ENABLE_FIREWIRE']: if build_for_linux and env['ENABLE_FIREWIRE']:
env['FFADO_FLAGS'] = conf.GetPKGFlags( 'libffado', '1.999.7' )
env['FFADO_FLAGS'] = conf.GetPKGFlags( 'libffado', '1.999.14' )
if env['FFADO_FLAGS'] == 0: if env['FFADO_FLAGS'] == 0:
print " Disabling 'firewire' backend since no useful FFADO installation found." print " Disabling 'firewire' backend since no useful FFADO installation found."
env['ENABLE_FIREWIRE'] = False env['ENABLE_FIREWIRE'] = False


+ 2
- 2
common/SConscript View File

@@ -38,10 +38,10 @@ srcfiles_common_serverlib = env.Split( '\
JackActivationCount.cpp JackAPI.cpp JackAudioDriver.cpp JackClient.cpp JackConnectionManager.cpp \ JackActivationCount.cpp JackAPI.cpp JackAudioDriver.cpp JackClient.cpp JackConnectionManager.cpp \
JackDriver.cpp JackEngine.cpp JackEngineControl.cpp JackError.c JackExternalClient.cpp JackFrameTimer.cpp \ JackDriver.cpp JackEngine.cpp JackEngineControl.cpp JackError.c JackExternalClient.cpp JackFrameTimer.cpp \
JackFreewheelDriver.cpp JackGlobalsServer.cpp JackGraphManager.cpp JackInternalClient.cpp JackPort.cpp JackPosixSemaphore.cpp \ JackFreewheelDriver.cpp JackGlobalsServer.cpp JackGraphManager.cpp JackInternalClient.cpp JackPort.cpp JackPosixSemaphore.cpp \
JackPosixThread.cpp JackFifo.cpp JackLoopbackDriver.cpp JackPortType.cpp JackAudioPort.cpp JackMidiPort.cpp \
JackPosixThread.cpp JackFifo.cpp JackLoopbackDriver.cpp JackPortType.cpp JackAudioPort.cpp JackMidiPort.cpp JackMidiAPI.cpp \
JackServer.cpp JackShmMem.cpp JackThreadedDriver.cpp shm.c JackSocket.cpp JackSocketServerChannel.cpp JackSocketNotifyChannel.cpp \ JackServer.cpp JackShmMem.cpp JackThreadedDriver.cpp shm.c JackSocket.cpp JackSocketServerChannel.cpp JackSocketNotifyChannel.cpp \
JackSocketServerNotifyChannel.cpp JackTime.c JackServerAPI.cpp JackGlobals.cpp JackDriverLoader.cpp JackDebugClient.cpp \ JackSocketServerNotifyChannel.cpp JackTime.c JackServerAPI.cpp JackGlobals.cpp JackDriverLoader.cpp JackDebugClient.cpp \
JackTransportEngine.cpp JackServerGlobals.cpp JackServerLaunch.cpp timestamps.c JackTools.cpp \
JackTransportEngine.cpp JackServerGlobals.cpp JackServerLaunch.cpp timestamps.c JackTools.cpp ringbuffer.c \
') ')


srcfiles_common_clientlib = env.Split( '\ srcfiles_common_clientlib = env.Split( '\


+ 311
- 473
linux/firewire/JackFFADODriver.cpp View File

@@ -44,7 +44,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
namespace Jack namespace Jack
{ {


#define FIREWIRE_REQUIRED_FFADO_API_VERSION 5
#define FIREWIRE_REQUIRED_FFADO_API_VERSION 7


#define jack_get_microseconds GetMicroSeconds #define jack_get_microseconds GetMicroSeconds


@@ -54,56 +54,72 @@ namespace Jack
int int
JackFFADODriver::ffado_driver_read (ffado_driver_t * driver, jack_nframes_t nframes) JackFFADODriver::ffado_driver_read (ffado_driver_t * driver, jack_nframes_t nframes)
{ {
unsigned int chn;
jack_default_audio_sample_t* buf = NULL; jack_default_audio_sample_t* buf = NULL;
// channel_t chn;
// JSList *node;
// jack_port_t* port;

ffado_sample_t nullbuffer[nframes];
void *addr_of_nullbuffer = (void *)nullbuffer;

ffado_streaming_stream_type stream_type;


printEnter(); printEnter();

//make sure all buffers have a valid buffer if not connected
for (unsigned int i = 0; i < driver->capture_nchannels; i++) {
stream_type = ffado_streaming_get_capture_stream_type(driver->dev, i);
if (stream_type == ffado_stream_type_audio) {
ffado_streaming_set_capture_stream_buffer(driver->dev, i, (char *)(nullbuffer));
ffado_streaming_capture_stream_onoff(driver->dev, i, 0);
} else if (stream_type == ffado_stream_type_midi) {
// these should be read/written with the per-stream functions
} else { // empty other buffers without doing something with them
ffado_streaming_set_capture_stream_buffer(driver->dev, i, (char *)(nullbuffer));
ffado_streaming_capture_stream_onoff(driver->dev, i, 0);
for (chn = 0; chn < driver->capture_nchannels; chn++) {
// if nothing connected, don't process
if(fGraphManager->GetConnectionsNum(fCapturePortList[chn]) == 0) {
buf=(jack_default_audio_sample_t*)driver->scratchbuffer;
// we always have to specify a valid buffer
ffado_streaming_set_capture_stream_buffer(driver->dev, chn, (char *)(buf));
// notify the streaming system that it can (but doesn't have to) skip
// this channel
ffado_streaming_capture_stream_onoff(driver->dev, chn, 0);
} else {
if(driver->capture_channels[chn].stream_type == ffado_stream_type_audio) {
buf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fCapturePortList[chn], nframes);

/* if the returned buffer is invalid, use the dummy buffer */
if(!buf) buf=(jack_default_audio_sample_t*)driver->scratchbuffer;
ffado_streaming_set_capture_stream_buffer(driver->dev, chn, (char *)(buf));
ffado_streaming_capture_stream_onoff(driver->dev, chn, 1);
} else if (driver->capture_channels[chn].stream_type == ffado_stream_type_midi) {
ffado_streaming_set_capture_stream_buffer(driver->dev, chn,
(char *)(driver->capture_channels[chn].midi_buffer));
ffado_streaming_capture_stream_onoff(driver->dev, chn, 1);
} else { // always have a valid buffer
ffado_streaming_set_capture_stream_buffer(driver->dev, chn, (char *)(driver->scratchbuffer));
// don't process what we don't use
ffado_streaming_capture_stream_onoff(driver->dev, chn, 0);
}
} }
} }


for (int i = 0; i < fCaptureChannels; i++) {
stream_type = ffado_streaming_get_capture_stream_type(driver->dev, i);
if (stream_type == ffado_stream_type_audio) {

if (fGraphManager->GetConnectionsNum(fCapturePortList[i]) > 0) {
buf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fCapturePortList[i], nframes);
/* now transfer the buffers */
ffado_streaming_transfer_capture_buffers(driver->dev);


if (!buf) {
buf = (jack_default_audio_sample_t *)addr_of_nullbuffer;
/* process the midi data */
for (chn = 0; chn < driver->capture_nchannels; chn++) {
if (driver->capture_channels[chn].stream_type == ffado_stream_type_midi) {
int i;
int done;
uint32_t *midi_buffer = driver->capture_channels[chn].midi_buffer;
midi_unpack_t *midi_unpack = &driver->capture_channels[chn].midi_unpack;
buf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fCapturePortList[chn], nframes);
jack_midi_clear_buffer(buf);

/* if the returned buffer is invalid, discard the midi data */
if(!buf) continue;
/* else unpack
note that libffado guarantees that midi bytes are on 8-byte aligned indexes
*/
for(i=0; i<nframes; i+=8) {
if(midi_buffer[i] & 0xFF000000) {
done=midi_unpack_buf(midi_unpack, (unsigned char *)(midi_buffer+i), 1, buf, i);
if (done != 1) {
printError("buffer overflow in channel %d\n", chn);
break;
}
printMessage("MIDI IN: %08X (i=%d)", midi_buffer[i], i);
} }
ffado_streaming_set_capture_stream_buffer(driver->dev, i, (char *)(buf));
ffado_streaming_capture_stream_onoff(driver->dev, i, 1);

} }
} else if (stream_type == ffado_stream_type_midi) {
// these should be read/written with the per-stream functions
} else { // empty other buffers without doing something with them
ffado_streaming_set_capture_stream_buffer(driver->dev, i, (char *)(nullbuffer));
ffado_streaming_capture_stream_onoff(driver->dev, i, 0);
} }
} }


// now transfer the buffers
ffado_streaming_transfer_capture_buffers(driver->dev);
printExit(); printExit();
return 0; return 0;
} }
@@ -111,52 +127,112 @@ JackFFADODriver::ffado_driver_read (ffado_driver_t * driver, jack_nframes_t nfra
int int
JackFFADODriver::ffado_driver_write (ffado_driver_t * driver, jack_nframes_t nframes) JackFFADODriver::ffado_driver_write (ffado_driver_t * driver, jack_nframes_t nframes)
{ {
jack_default_audio_sample_t* buf = NULL;
ffado_streaming_stream_type stream_type;

ffado_sample_t nullbuffer[nframes];
void *addr_of_nullbuffer = (void*)nullbuffer;

memset(&nullbuffer, 0, nframes*sizeof(ffado_sample_t));

unsigned int chn;
jack_default_audio_sample_t* buf;
printEnter(); printEnter();


driver->process_count++; driver->process_count++;


assert(driver->dev);

// make sure all buffers output silence if not connected
for (unsigned int i = 0; i < driver->playback_nchannels; i++) {
stream_type = ffado_streaming_get_playback_stream_type(driver->dev, i);
if (stream_type == ffado_stream_type_audio) {
ffado_streaming_set_playback_stream_buffer(driver->dev, i, (char *)(nullbuffer));
ffado_streaming_playback_stream_onoff(driver->dev, i, 0);
} else if (stream_type == ffado_stream_type_midi) {
// these should be read/written with the per-stream functions
} else { // empty other buffers without doing something with them
ffado_streaming_set_playback_stream_buffer(driver->dev, i, (char *)(nullbuffer));
ffado_streaming_playback_stream_onoff(driver->dev, i, 0);
}
}

for (int i = 0; i < fPlaybackChannels; i++) {
stream_type = ffado_streaming_get_playback_stream_type(driver->dev, i);
if (stream_type == ffado_stream_type_audio) {
// Ouput ports
if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) {
buf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fPlaybackPortList[i], nframes);
for (chn = 0; chn < driver->playback_nchannels; chn++) {
if(fGraphManager->GetConnectionsNum(fPlaybackPortList[chn]) == 0) {
buf=(jack_default_audio_sample_t*)driver->nullbuffer;
// we always have to specify a valid buffer
ffado_streaming_set_playback_stream_buffer(driver->dev, chn, (char *)(buf));
// notify the streaming system that it can (but doesn't have to) skip
// this channel
ffado_streaming_playback_stream_onoff(driver->dev, chn, 0);
} else {
if(driver->playback_channels[chn].stream_type == ffado_stream_type_audio) {
buf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fPlaybackPortList[chn], nframes);
/* use the silent buffer if there is no valid jack buffer */
if(!buf) buf=(jack_default_audio_sample_t*)driver->nullbuffer;
ffado_streaming_set_playback_stream_buffer(driver->dev, chn, (char *)(buf));

} else if (driver->playback_channels[chn].stream_type == ffado_stream_type_midi) {
int nevents;
int i;
midi_pack_t *midi_pack = &driver->playback_channels[chn].midi_pack;
uint32_t *midi_buffer = driver->playback_channels[chn].midi_buffer;
buf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fPlaybackPortList[chn], nframes);
int min_next_pos=0;

memset(midi_buffer, 0, nframes * sizeof(uint32_t));
ffado_streaming_set_playback_stream_buffer(driver->dev, chn, (char *)(midi_buffer));

/* if the returned buffer is invalid, continue */
if(!buf) {
ffado_streaming_playback_stream_onoff(driver->dev, chn, 0);
continue;
}
ffado_streaming_playback_stream_onoff(driver->dev, chn, 1);


if (!buf) {
buf = (jack_default_audio_sample_t *)addr_of_nullbuffer;
// check if we still have to process bytes from the previous period
if(driver->playback_channels[chn].nb_overflow_bytes) {
printMessage("have to process %d bytes from previous period", driver->playback_channels[chn].nb_overflow_bytes);
}
for (i=0; i<driver->playback_channels[chn].nb_overflow_bytes; ++i) {
midi_buffer[min_next_pos] = 0x01000000 | (driver->playback_channels[chn].overflow_buffer[i] & 0xFF);
min_next_pos += 8;
}
driver->playback_channels[chn].nb_overflow_bytes=0;

// process the events in this period
nevents = jack_midi_get_event_count(buf);
//if (nevents)
// printMessage("MIDI: %d events in ch %d", nevents, chn);
for (i=0; i<nevents; ++i) {
int j;
jack_midi_event_t event;
jack_midi_event_get(&event, buf, i);
midi_pack_event(midi_pack, &event);
// floor the initial position to be a multiple of 8
int pos = event.time & 0xFFFFFFF8;
for(j = 0; j < event.size; j++) {
// make sure we don't overwrite a previous byte
while(pos < min_next_pos && pos < nframes) {
pos += 8;
printMessage("have to correct pos to %d", pos);
}

if(pos >= nframes) {
int f;
printMessage("midi message crosses period boundary");
driver->playback_channels[chn].nb_overflow_bytes = event.size - j;
if(driver->playback_channels[chn].nb_overflow_bytes > MIDI_OVERFLOW_BUFFER_SIZE) {
printError("too much midi bytes cross period boundary");
driver->playback_channels[chn].nb_overflow_bytes = MIDI_OVERFLOW_BUFFER_SIZE;
}
// save the bytes that still have to be transmitted in the next period
for(f=0; f<driver->playback_channels[chn].nb_overflow_bytes; f++) {
driver->playback_channels[chn].overflow_buffer[f] = event.buffer[j+f];
}
// exit since we can't transmit anything anymore.
// the rate should be controlled
if(i<nevents-1) {
printError("%d midi events lost due to period crossing", nevents-i-1);
}
break;
} else {
midi_buffer[pos] = 0x01000000 | (event.buffer[j] & 0xFF);
pos += 8;
min_next_pos = pos;
}
}
//printMessage("MIDI: sent %d-byte event at %ld", (int)event.size, (long)event.time);
} }


ffado_streaming_set_playback_stream_buffer(driver->dev, i, (char *)(buf));
ffado_streaming_playback_stream_onoff(driver->dev, i, 1);
} else { // always have a valid buffer
ffado_streaming_set_playback_stream_buffer(driver->dev, chn, (char *)(driver->nullbuffer));
ffado_streaming_playback_stream_onoff(driver->dev, chn, 0);
} }
} }
} }


ffado_streaming_transfer_playback_buffers(driver->dev); ffado_streaming_transfer_playback_buffers(driver->dev);

printExit(); printExit();
return 0; return 0;
} }
@@ -168,6 +244,7 @@ JackFFADODriver::ffado_driver_wait (ffado_driver_t *driver, int extra_fd, int *s
int nframes; int nframes;
jack_time_t wait_enter; jack_time_t wait_enter;
jack_time_t wait_ret; jack_time_t wait_ret;
ffado_wait_response response;


printEnter(); printEnter();


@@ -185,7 +262,7 @@ JackFFADODriver::ffado_driver_wait (ffado_driver_t *driver, int extra_fd, int *s
// *status = -3; timeout // *status = -3; timeout
// *status = -4; extra FD // *status = -4; extra FD


nframes = ffado_streaming_wait(driver->dev);
response = ffado_streaming_wait(driver->dev);


wait_ret = jack_get_microseconds (); wait_ret = jack_get_microseconds ();


@@ -196,18 +273,22 @@ JackFFADODriver::ffado_driver_wait (ffado_driver_t *driver, int extra_fd, int *s
driver->wait_next = wait_ret + driver->period_usecs; driver->wait_next = wait_ret + driver->period_usecs;
// driver->engine->transport_cycle_start (driver->engine, wait_ret); // driver->engine->transport_cycle_start (driver->engine, wait_ret);


if (nframes < 0) {
*status = 0;
if (response == ffado_wait_xrun) {
// xrun happened, but it's handled
*status=0;
return 0;
} else if (response == ffado_wait_error) {
// an error happened (unhandled xrun)
// this should be fatal
*status=-1;
return 0; return 0;
} }


*status = 0; *status = 0;
fLastWaitUst = wait_ret; fLastWaitUst = wait_ret;


// FIXME: this should do something more usefull
*delayed_usecs = 0;
printExit(); printExit();
return nframes - nframes % driver->period_size;
return driver->period_size;
} }


int int
@@ -215,25 +296,11 @@ JackFFADODriver::ffado_driver_start (ffado_driver_t *driver)
{ {
int retval = 0; int retval = 0;


#ifdef FFADO_DRIVER_WITH_MIDI
if (driver->midi_handle) {
if ((retval = ffado_driver_midi_start(driver->midi_handle))) {
printError("Could not start MIDI threads");
return retval;
}
}
#endif

if ((retval = ffado_streaming_start(driver->dev))) { if ((retval = ffado_streaming_start(driver->dev))) {
printError("Could not start streaming threads"); printError("Could not start streaming threads");
#ifdef FFADO_DRIVER_WITH_MIDI
if (driver->midi_handle) {
ffado_driver_midi_stop(driver->midi_handle);
}
#endif

return retval; return retval;
} }

return 0; return 0;
} }


@@ -242,14 +309,6 @@ JackFFADODriver::ffado_driver_stop (ffado_driver_t *driver)
{ {
int retval = 0; int retval = 0;


#ifdef FFADO_DRIVER_WITH_MIDI
if (driver->midi_handle) {
if ((retval = ffado_driver_midi_stop(driver->midi_handle))) {
printError("Could not stop MIDI threads");
return retval;
}
}
#endif
if ((retval = ffado_streaming_stop(driver->dev))) { if ((retval = ffado_streaming_stop(driver->dev))) {
printError("Could not stop streaming threads"); printError("Could not stop streaming threads");
return retval; return retval;
@@ -355,327 +414,6 @@ JackFFADODriver::ffado_driver_delete (ffado_driver_t *driver)
free (driver); free (driver);
} }


#ifdef FFADO_DRIVER_WITH_MIDI
/*
* MIDI support
*/

// the thread that will queue the midi events from the seq to the stream buffers

void *
JackFFADODriver::ffado_driver_midi_queue_thread(void *arg)
{
ffado_driver_midi_handle_t *m = (ffado_driver_midi_handle_t *)arg;
assert(m);
snd_seq_event_t *ev;
unsigned char work_buffer[MIDI_TRANSMIT_BUFFER_SIZE];
int bytes_to_send;
int b;
int i;

printMessage("MIDI queue thread started");

while (1) {
// get next event, if one is present
while ((snd_seq_event_input(m->seq_handle, &ev) > 0)) {
// get the port this event is originated from
ffado_midi_port_t *port = NULL;
for (i = 0;i < m->nb_output_ports;i++) {
if (m->output_ports[i]->seq_port_nr == ev->dest.port) {
port = m->output_ports[i];
break;
}
}

if (!port) {
printError(" Could not find target port for event: dst=%d src=%d", ev->dest.port, ev->source.port);

break;
}

// decode it to the work buffer
if ((bytes_to_send = snd_midi_event_decode ( port->parser,
work_buffer,
MIDI_TRANSMIT_BUFFER_SIZE,
ev)) < 0) { // failed
printError(" Error decoding event for port %d (errcode=%d)", port->seq_port_nr, bytes_to_send);
bytes_to_send = 0;
//return -1;
}

for (b = 0;b < bytes_to_send;b++) {
ffado_sample_t tmp_event = work_buffer[b];
if (ffado_streaming_write(m->dev, port->stream_nr, &tmp_event, 1) < 1) {
printError(" Midi send buffer overrun");
}
}

}

// sleep for some time
usleep(MIDI_THREAD_SLEEP_TIME_USECS);
}
return NULL;
}

// the dequeue thread (maybe we need one thread per stream)
void *
JackFFADODriver::ffado_driver_midi_dequeue_thread (void *arg)
{
ffado_driver_midi_handle_t *m = (ffado_driver_midi_handle_t *)arg;

int i;
int s;
int samples_read;

assert(m);

while (1) {
// read incoming events

for (i = 0;i < m->nb_input_ports;i++) {
unsigned int buff[64];

ffado_midi_port_t *port = m->input_ports[i];

if (!port) {
printError(" something went wrong when setting up the midi input port map (%d)", i);
}

do {
samples_read = ffado_streaming_read(m->dev, port->stream_nr, buff, 64);

for (s = 0;s < samples_read;s++) {
unsigned int *byte = (buff + s) ;
snd_seq_event_t ev;
if ((snd_midi_event_encode_byte(port->parser, (*byte) & 0xFF, &ev)) > 0) {
// a midi message is complete, send it out to ALSA
snd_seq_ev_set_subs(&ev);
snd_seq_ev_set_direct(&ev);
snd_seq_ev_set_source(&ev, port->seq_port_nr);
snd_seq_event_output_direct(port->seq_handle, &ev);
}
}
} while (samples_read > 0);
}

// sleep for some time
usleep(MIDI_THREAD_SLEEP_TIME_USECS);
}
return NULL;
}

ffado_driver_midi_handle_t *
JackFFADODriver::ffado_driver_midi_init(ffado_driver_t *driver)
{
// int err;

char buf[256];
channel_t chn;
int nchannels;
int i = 0;

ffado_device_t *dev = driver->dev;

assert(dev);

ffado_driver_midi_handle_t *m = calloc(1, sizeof(ffado_driver_midi_handle_t));
if (!m) {
printError("not enough memory to create midi structure");
return NULL;
}

if (snd_seq_open(&m->seq_handle, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK) < 0) {
printError("Error opening ALSA sequencer.");
free(m);
return NULL;
}

snd_seq_set_client_name(m->seq_handle, "FFADO Jack MIDI");

// find out the number of midi in/out ports we need to setup
nchannels = ffado_streaming_get_nb_capture_streams(dev);

m->nb_input_ports = 0;

for (chn = 0; chn < nchannels; chn++) {
if (ffado_streaming_get_capture_stream_type(dev, chn) == ffado_stream_type_midi) {
m->nb_input_ports++;
}
}

m->input_ports = calloc(m->nb_input_ports, sizeof(ffado_midi_port_t *));
if (!m->input_ports) {
printError("not enough memory to create midi structure");
free(m);
return NULL;
}

i = 0;
for (chn = 0; chn < nchannels; chn++) {
if (ffado_streaming_get_capture_stream_type(dev, chn) == ffado_stream_type_midi) {
m->input_ports[i] = calloc(1, sizeof(ffado_midi_port_t));
if (!m->input_ports[i]) {
// fixme
printError("Could not allocate memory for seq port");
continue;
}

ffado_streaming_get_capture_stream_name(dev, chn, buf, sizeof(buf) - 1);
printMessage("Register MIDI IN port %s", buf);

m->input_ports[i]->seq_port_nr = snd_seq_create_simple_port(m->seq_handle, buf,
SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ,
SND_SEQ_PORT_TYPE_MIDI_GENERIC);

if (m->input_ports[i]->seq_port_nr < 0) {
printError("Could not create seq port");
m->input_ports[i]->stream_nr = -1;
m->input_ports[i]->seq_port_nr = -1;
} else {
m->input_ports[i]->stream_nr = chn;
m->input_ports[i]->seq_handle = m->seq_handle;
if (snd_midi_event_new ( ALSA_SEQ_BUFF_SIZE, &(m->input_ports[i]->parser)) < 0) {
printError("could not init parser for MIDI IN port %d", i);
m->input_ports[i]->stream_nr = -1;
m->input_ports[i]->seq_port_nr = -1;
}
}

i++;
}
}

// playback
nchannels = ffado_streaming_get_nb_playback_streams(dev);

m->nb_output_ports = 0;

for (chn = 0; chn < nchannels; chn++) {
if (ffado_streaming_get_playback_stream_type(dev, chn) == ffado_stream_type_midi) {
m->nb_output_ports++;
}
}

m->output_ports = calloc(m->nb_output_ports, sizeof(ffado_midi_port_t *));
if (!m->output_ports) {
printError("not enough memory to create midi structure");
for (i = 0; i < m->nb_input_ports; i++) {
free(m->input_ports[i]);
}
free(m->input_ports);
free(m);
return NULL;
}

i = 0;
for (chn = 0; chn < nchannels; chn++) {
if (ffado_streaming_get_playback_stream_type(dev, chn) == ffado_stream_type_midi) {
m->output_ports[i] = calloc(1, sizeof(ffado_midi_port_t));
if (!m->output_ports[i]) {
// fixme
printError("Could not allocate memory for seq port");
continue;
}

ffado_streaming_get_playback_stream_name(dev, chn, buf, sizeof(buf) - 1);
printMessage("Register MIDI OUT port %s", buf);

m->output_ports[i]->seq_port_nr = snd_seq_create_simple_port(m->seq_handle, buf,
SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE,
SND_SEQ_PORT_TYPE_MIDI_GENERIC);


if (m->output_ports[i]->seq_port_nr < 0) {
printError("Could not create seq port");
m->output_ports[i]->stream_nr = -1;
m->output_ports[i]->seq_port_nr = -1;
} else {
m->output_ports[i]->stream_nr = chn;
m->output_ports[i]->seq_handle = m->seq_handle;
if (snd_midi_event_new ( ALSA_SEQ_BUFF_SIZE, &(m->output_ports[i]->parser)) < 0) {
printError("could not init parser for MIDI OUT port %d", i);
m->output_ports[i]->stream_nr = -1;
m->output_ports[i]->seq_port_nr = -1;
}
}

i++;
}
}

m->dev = dev;
m->driver = driver;
return m;
}

int
JackFFADODriver::ffado_driver_midi_start (ffado_driver_midi_handle_t *m)
{
assert(m);
// start threads

m->queue_thread_realtime = (m->driver->engine->control->real_time ? 1 : 0);
m->queue_thread_priority =
m->driver->engine->control->client_priority +
FFADO_RT_PRIORITY_MIDI_RELATIVE;

if (m->queue_thread_priority > 98) {
m->queue_thread_priority = 98;
}
if (m->queue_thread_realtime) {
printMessage("MIDI threads running with Realtime scheduling, priority %d",
m->queue_thread_priority);
} else {
printMessage("MIDI threads running without Realtime scheduling");
}

if (jack_client_create_thread(NULL, &m->queue_thread, m->queue_thread_priority, m->queue_thread_realtime, ffado_driver_midi_queue_thread, (void *)m)) {
printError(" cannot create midi queueing thread");
return -1;
}

if (jack_client_create_thread(NULL, &m->dequeue_thread, m->queue_thread_priority, m->queue_thread_realtime, ffado_driver_midi_dequeue_thread, (void *)m)) {
printError(" cannot create midi dequeueing thread");
return -1;
}
return 0;
}

int
JackFFADODriver::ffado_driver_midi_stop (ffado_driver_midi_handle_t *m)
{
assert(m);

pthread_cancel (m->queue_thread);
pthread_join (m->queue_thread, NULL);

pthread_cancel (m->dequeue_thread);
pthread_join (m->dequeue_thread, NULL);
return 0;
}

void
JackFFADODriver::ffado_driver_midi_finish (ffado_driver_midi_handle_t *m)
{
assert(m);

int i;
// TODO: add state info here, if not stopped then stop

for (i = 0;i < m->nb_input_ports;i++) {
free(m->input_ports[i]);
}
free(m->input_ports);

for (i = 0;i < m->nb_output_ports;i++) {
free(m->output_ports[i]);
}
free(m->output_ports);
free(m);
}
#endif

int JackFFADODriver::Attach() int JackFFADODriver::Attach()
{ {
JackPort* port; JackPort* port;
@@ -691,6 +429,25 @@ int JackFFADODriver::Attach()


g_verbose = (fEngineControl->fVerbose ? 1 : 0); g_verbose = (fEngineControl->fVerbose ? 1 : 0);


/* preallocate some buffers such that they don't have to be allocated
in RT context (or from the stack)
*/
/* the null buffer is a buffer that contains one period of silence */
driver->nullbuffer = (ffado_sample_t *)calloc(driver->period_size, sizeof(ffado_sample_t));
if(driver->nullbuffer == NULL) {
printError("could not allocate memory for null buffer");
return -1;
}
/* calloc should do this, but it can't hurt to be sure */
memset(driver->nullbuffer, 0, driver->period_size*sizeof(ffado_sample_t));
/* the scratch buffer is a buffer of one period that can be used as dummy memory */
driver->scratchbuffer = (ffado_sample_t *)calloc(driver->period_size, sizeof(ffado_sample_t));
if(driver->scratchbuffer == NULL) {
printError("could not allocate memory for scratch buffer");
return -1;
}

/* packetizer thread options */ /* packetizer thread options */
driver->device_options.realtime = (fEngineControl->fRealTime ? 1 : 0); driver->device_options.realtime = (fEngineControl->fRealTime ? 1 : 0);


@@ -708,17 +465,6 @@ int JackFFADODriver::Attach()
return -1; return -1;
} }


#ifdef FFADO_DRIVER_WITH_MIDI
driver->midi_handle = ffado_driver_midi_init(driver);
if (!driver->midi_handle) {
printError("-----------------------------------------------------------");
printError("Error creating midi device!");
printError("FFADO will run without MIDI support.");
printError("Consult the above error messages to solve the problem. ");
printError("-----------------------------------------------------------\n\n");
}
#endif

if (driver->device_options.realtime) { if (driver->device_options.realtime) {
printMessage("Streaming thread running with Realtime scheduling, priority %d", printMessage("Streaming thread running with Realtime scheduling, priority %d",
driver->device_options.packetizer_priority); driver->device_options.packetizer_priority);
@@ -726,40 +472,80 @@ int JackFFADODriver::Attach()
printMessage("Streaming thread running without Realtime scheduling"); printMessage("Streaming thread running without Realtime scheduling");
} }


ffado_streaming_set_audio_datatype(driver->dev, ffado_audio_datatype_float);

/* ports */ /* ports */


// capture // capture
port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal; port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal;


driver->capture_nchannels = ffado_streaming_get_nb_capture_streams(driver->dev); driver->capture_nchannels = ffado_streaming_get_nb_capture_streams(driver->dev);
driver->capture_nchannels_audio = 0;

for (unsigned int i = 0; i < driver->capture_nchannels; i++) {
driver->capture_channels=(ffado_capture_channel_t *)calloc(driver->capture_nchannels, sizeof(ffado_capture_channel_t));
if(driver->capture_channels==NULL) {
printError("could not allocate memory for capture channel list");
return -1;
}


ffado_streaming_get_capture_stream_name(driver->dev, i, portname, sizeof(portname) - 1);
snprintf(buf, sizeof(buf) - 1, "%s:%s", fClientControl->fName, portname);
fCaptureChannels=0;
for (unsigned int chn = 0; chn < driver->capture_nchannels; chn++) {
ffado_streaming_get_capture_stream_name(driver->dev, chn, portname, sizeof(portname) - 1);


if (ffado_streaming_get_capture_stream_type(driver->dev, i) != ffado_stream_type_audio) {
printMessage ("Don't register capture port %s", buf);
} else {
printMessage ("Registering capture port %s", buf);
driver->capture_channels[chn].stream_type=ffado_streaming_get_capture_stream_type(driver->dev, chn);
if(driver->capture_channels[chn].stream_type == ffado_stream_type_audio) {
snprintf(buf, sizeof(buf) - 1, "%s:AC%d_%s", fClientControl->fName, (int)chn, portname);
printMessage ("Registering audio capture port %s", buf);
if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, buf, if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, buf,
JACK_DEFAULT_AUDIO_TYPE, JACK_DEFAULT_AUDIO_TYPE,
(JackPortFlags)port_flags, (JackPortFlags)port_flags,
fEngineControl->fBufferSize)) == NO_PORT) {
fEngineControl->fBufferSize)) == NO_PORT) {
jack_error("driver: cannot register port for %s", buf);
return -1;
}

// setup port parameters
if (ffado_streaming_set_capture_stream_buffer(driver->dev, chn, NULL)) {
printError(" cannot configure initial port buffer for %s", buf);
}
ffado_streaming_capture_stream_onoff(driver->dev, chn, 0);

port = fGraphManager->GetPort(port_index);
port->SetLatency(driver->period_size + driver->capture_frame_latency);
fCapturePortList[chn] = port_index;
JackLog("JackFFADODriver::Attach fCapturePortList[i] %ld \n", port_index);
fCaptureChannels++;

} else if(driver->capture_channels[chn].stream_type == ffado_stream_type_midi) {
snprintf(buf, sizeof(buf) - 1, "%s:MC%d_%s", fClientControl->fName, (int)chn, portname);
printMessage ("Registering midi capture port %s", buf);
if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, buf,
JACK_DEFAULT_MIDI_TYPE,
(JackPortFlags)port_flags,
fEngineControl->fBufferSize)) == NO_PORT) {
jack_error("driver: cannot register port for %s", buf); jack_error("driver: cannot register port for %s", buf);
return -1; return -1;
} }


ffado_streaming_set_capture_buffer_type(driver->dev, i, ffado_buffer_type_float);
ffado_streaming_capture_stream_onoff(driver->dev, i, 0);
// setup port parameters
if (ffado_streaming_set_capture_stream_buffer(driver->dev, chn, NULL)) {
printError(" cannot configure initial port buffer for %s", buf);
}
if(ffado_streaming_capture_stream_onoff(driver->dev, chn, 0)) {
printError(" cannot enable port %s", buf);
}
// setup midi unpacker
midi_unpack_init(&driver->capture_channels[chn].midi_unpack);
midi_unpack_reset(&driver->capture_channels[chn].midi_unpack);
// setup the midi buffer
driver->capture_channels[chn].midi_buffer = (uint32_t *)calloc(driver->period_size, sizeof(uint32_t));


port = fGraphManager->GetPort(port_index); port = fGraphManager->GetPort(port_index);
port->SetLatency(driver->period_size + driver->capture_frame_latency); port->SetLatency(driver->period_size + driver->capture_frame_latency);
fCapturePortList[i] = port_index;
fCapturePortList[chn] = port_index;
JackLog("JackFFADODriver::Attach fCapturePortList[i] %ld \n", port_index); JackLog("JackFFADODriver::Attach fCapturePortList[i] %ld \n", port_index);
driver->capture_nchannels_audio++;
fCaptureChannels++;
} else {
printMessage ("Don't register capture port %s", portname);
} }
} }


@@ -767,39 +553,75 @@ int JackFFADODriver::Attach()
port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal; port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal;


driver->playback_nchannels = ffado_streaming_get_nb_playback_streams(driver->dev); driver->playback_nchannels = ffado_streaming_get_nb_playback_streams(driver->dev);
driver->playback_nchannels_audio = 0;
driver->playback_channels=(ffado_playback_channel_t *)calloc(driver->playback_nchannels, sizeof(ffado_playback_channel_t));
if(driver->playback_channels==NULL) {
printError("could not allocate memory for playback channel list");
return -1;
}


for (unsigned int i = 0; i < driver->playback_nchannels; i++) {
fPlaybackChannels=0;
for (unsigned int chn = 0; chn < driver->playback_nchannels; chn++) {
ffado_streaming_get_playback_stream_name(driver->dev, chn, portname, sizeof(portname) - 1);


ffado_streaming_get_playback_stream_name(driver->dev, i, portname, sizeof(portname) - 1);
snprintf(buf, sizeof(buf) - 1, "%s:%s", fClientControl->fName, portname);
driver->playback_channels[chn].stream_type=ffado_streaming_get_playback_stream_type(driver->dev, chn);


if (ffado_streaming_get_playback_stream_type(driver->dev, i) != ffado_stream_type_audio) {
printMessage ("Don't register playback port %s", buf);
} else {
printMessage ("Registering playback port %s", buf);
if(driver->playback_channels[chn].stream_type == ffado_stream_type_audio) {
snprintf(buf, sizeof(buf) - 1, "%s:AP%d_%s", fClientControl->fName, (int)chn, portname);
printMessage ("Registering audio playback port %s", buf);
if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, buf, if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, buf,
JACK_DEFAULT_AUDIO_TYPE, JACK_DEFAULT_AUDIO_TYPE,
(JackPortFlags)port_flags, (JackPortFlags)port_flags,
fEngineControl->fBufferSize)) == NO_PORT) {
fEngineControl->fBufferSize)) == NO_PORT) {
jack_error("driver: cannot register port for %s", buf); jack_error("driver: cannot register port for %s", buf);
return -1; return -1;
} }


ffado_streaming_set_playback_buffer_type(driver->dev, i, ffado_buffer_type_float);
ffado_streaming_playback_stream_onoff(driver->dev, i, 0);
// setup port parameters
if (ffado_streaming_set_playback_stream_buffer(driver->dev, chn, NULL)) {
printError(" cannot configure initial port buffer for %s", buf);
}
if(ffado_streaming_playback_stream_onoff(driver->dev, chn, 0)) {
printError(" cannot enable port %s", buf);
}


port = fGraphManager->GetPort(port_index); port = fGraphManager->GetPort(port_index);
port->SetLatency((driver->period_size * (driver->device_options.nb_buffers - 1)) + driver->playback_frame_latency); port->SetLatency((driver->period_size * (driver->device_options.nb_buffers - 1)) + driver->playback_frame_latency);
fPlaybackPortList[i] = port_index;
fPlaybackPortList[chn] = port_index;
JackLog("JackFFADODriver::Attach fPlaybackPortList[i] %ld \n", port_index); JackLog("JackFFADODriver::Attach fPlaybackPortList[i] %ld \n", port_index);
driver->playback_nchannels_audio++;
fPlaybackChannels++;
} else if(driver->playback_channels[chn].stream_type == ffado_stream_type_midi) {
snprintf(buf, sizeof(buf) - 1, "%s:MP%d_%s", fClientControl->fName, (int)chn, portname);
printMessage ("Registering midi playback port %s", buf);
if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, buf,
JACK_DEFAULT_MIDI_TYPE,
(JackPortFlags)port_flags,
fEngineControl->fBufferSize)) == NO_PORT) {
jack_error("driver: cannot register port for %s", buf);
return -1;
}

// setup port parameters
if (ffado_streaming_set_playback_stream_buffer(driver->dev, chn, NULL)) {
printError(" cannot configure initial port buffer for %s", buf);
}
if(ffado_streaming_playback_stream_onoff(driver->dev, chn, 0)) {
printError(" cannot enable port %s", buf);
}
// setup midi packer
midi_pack_reset(&driver->playback_channels[chn].midi_pack);
// setup the midi buffer
driver->playback_channels[chn].midi_buffer = (uint32_t *)calloc(driver->period_size, sizeof(uint32_t));

port = fGraphManager->GetPort(port_index);
port->SetLatency((driver->period_size * (driver->device_options.nb_buffers - 1)) + driver->playback_frame_latency);
fPlaybackPortList[chn] = port_index;
JackLog("JackFFADODriver::Attach fPlaybackPortList[i] %ld \n", port_index);
fPlaybackChannels++;
} else {
printMessage ("Don't register playback port %s", portname);
} }
} }


fCaptureChannels = driver->capture_nchannels_audio;
fPlaybackChannels = driver->playback_nchannels_audio;

assert(fCaptureChannels < PORT_NUM); assert(fCaptureChannels < PORT_NUM);
assert(fPlaybackChannels < PORT_NUM); assert(fPlaybackChannels < PORT_NUM);


@@ -815,6 +637,7 @@ int JackFFADODriver::Attach()


int JackFFADODriver::Detach() int JackFFADODriver::Detach()
{ {
unsigned int chn;
ffado_driver_t* driver = (ffado_driver_t*)fDriver; ffado_driver_t* driver = (ffado_driver_t*)fDriver;
JackLog("JackFFADODriver::Detach\n"); JackLog("JackFFADODriver::Detach\n");


@@ -822,12 +645,21 @@ int JackFFADODriver::Detach()
ffado_streaming_finish(driver->dev); ffado_streaming_finish(driver->dev);
driver->dev = NULL; driver->dev = NULL;


#ifdef FFADO_DRIVER_WITH_MIDI
if (driver->midi_handle) {
ffado_driver_midi_finish(driver->midi_handle);
// free all internal buffers
for (chn = 0; chn < driver->capture_nchannels; chn++) {
if(driver->capture_channels[chn].midi_buffer)
free(driver->capture_channels[chn].midi_buffer);
} }
driver->midi_handle = NULL;
#endif
free(driver->capture_channels);
for (chn = 0; chn < driver->playback_nchannels; chn++) {
if(driver->playback_channels[chn].midi_buffer)
free(driver->playback_channels[chn].midi_buffer);
}
free(driver->playback_channels);

free(driver->nullbuffer);
free(driver->scratchbuffer);


return JackAudioDriver::Detach(); // Generic JackAudioDriver Detach return JackAudioDriver::Detach(); // Generic JackAudioDriver Detach
} }
@@ -847,8 +679,8 @@ int JackFFADODriver::Open(ffado_jack_settings_t *params)


if (fDriver) { if (fDriver) {
// FFADO driver may have changed the in/out values // FFADO driver may have changed the in/out values
fCaptureChannels = ((ffado_driver_t *)fDriver)->capture_nchannels_audio;
fPlaybackChannels = ((ffado_driver_t *)fDriver)->playback_nchannels_audio;
//fCaptureChannels = ((ffado_driver_t *)fDriver)->capture_nchannels_audio;
//fPlaybackChannels = ((ffado_driver_t *)fDriver)->playback_nchannels_audio;
return 0; return 0;
} else { } else {
return -1; return -1;
@@ -881,7 +713,7 @@ int JackFFADODriver::Read()
int wait_status = 0; int wait_status = 0;
float delayed_usecs = 0.0; float delayed_usecs = 0.0;


jack_nframes_t nframes = ffado_driver_wait (driver, -1, &wait_status,
jack_nframes_t nframes = ffado_driver_wait(driver, -1, &wait_status,
&delayed_usecs); &delayed_usecs);


if ((wait_status < 0)) { if ((wait_status < 0)) {
@@ -1098,6 +930,12 @@ extern "C"
cmlparams.playback_frame_latency = 0; cmlparams.playback_frame_latency = 0;
cmlparams.capture_frame_latency = 0; cmlparams.capture_frame_latency = 0;


cmlparams.verbose_level = 0;

cmlparams.slave_mode = 0;
cmlparams.snoop_mode = 0;
cmlparams.device_info = NULL;

for (node = params; node; node = jack_slist_next (node)) { for (node = params; node; node = jack_slist_next (node)) {
param = (jack_driver_param_t *) node->data; param = (jack_driver_param_t *) node->data;




+ 0
- 7
linux/firewire/JackFFADODriver.h View File

@@ -58,13 +58,6 @@ class JackFFADODriver : public JackAudioDriver
ffado_driver_t *ffado_driver_new (char *name, ffado_jack_settings_t *params); ffado_driver_t *ffado_driver_new (char *name, ffado_jack_settings_t *params);
void ffado_driver_delete (ffado_driver_t *driver); void ffado_driver_delete (ffado_driver_t *driver);


#ifdef FREEBOB_DRIVER_WITH_MIDI
ffado_driver_midi_handle_t *ffado_driver_midi_init(ffado_driver_t *driver);
void ffado_driver_midi_finish (ffado_driver_midi_handle_t *m);
int ffado_driver_midi_start (ffado_driver_midi_handle_t *m);
int ffado_driver_midi_stop (ffado_driver_midi_handle_t *m);
#endif

void jack_driver_init (jack_driver_t *driver); void jack_driver_init (jack_driver_t *driver);
void jack_driver_nt_init (jack_driver_nt_t * driver); void jack_driver_nt_init (jack_driver_nt_t * driver);


+ 110
- 141
linux/firewire/ffado_driver.h View File

@@ -1,14 +1,14 @@
/* ffado_driver.h
*
* FreeBob Backend for Jack
* FreeBob = Firewire (pro-)audio for linux
/*
* FireWire Backend for Jack
* using FFADO
* FFADO = Firewire (pro-)audio for linux
* *
* adapted for jackmp
* http://www.ffado.org
* http://www.jackaudio.org
* *
* http://freebob.sf.net
* http://jackit.sf.net
* Copyright (C) 2005-2007 Pieter Palmers
* *
* Copyright (C) 2005,2006,2007 Pieter Palmers <pieterpalmers@users.sourceforge.net>
* adapted for JackMP by Pieter Palmers
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -25,17 +25,14 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */


/*
/*
* Main Jack driver entry routines * Main Jack driver entry routines
* *
*/
*/
#ifndef __JACK_FFADO_DRIVER_H__ #ifndef __JACK_FFADO_DRIVER_H__
#define __JACK_FFADO_DRIVER_H__ #define __JACK_FFADO_DRIVER_H__


// #define FFADO_DRIVER_WITH_MIDI
// #define DEBUG_ENABLED

#include <libffado/ffado.h> #include <libffado/ffado.h>


#include <string.h> #include <string.h>
@@ -53,10 +50,12 @@
#include <driver.h> #include <driver.h>
#include <types.h> #include <types.h>


#ifdef FFADO_DRIVER_WITH_MIDI
#include <JackPosixThread.h>
#include <alsa/asoundlib.h>
#endif
#include <assert.h>
#include <jack/midiport.h>
// #include "JackPort.h"
// #include "JackMidiPort.h"
#include <../alsa/midi_pack.h>
#include <../alsa/midi_unpack.h>


// debug print control flags // debug print control flags
#define DEBUG_LEVEL_BUFFERS (1<<0) #define DEBUG_LEVEL_BUFFERS (1<<0)
@@ -70,59 +69,47 @@
#define DEBUG_LEVEL_STARTUP (1<<17) #define DEBUG_LEVEL_STARTUP (1<<17)
#define DEBUG_LEVEL_THREADS (1<<18) #define DEBUG_LEVEL_THREADS (1<<18)


//#define DEBUG_ENABLED
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED


// default debug level
#define DEBUG_LEVEL ( DEBUG_LEVEL_RUN_CYCLE | \
// default debug level
#define DEBUG_LEVEL ( DEBUG_LEVEL_RUN_CYCLE | \
(DEBUG_LEVEL_XRUN_RECOVERY)| DEBUG_LEVEL_STARTUP | DEBUG_LEVEL_WAIT | DEBUG_LEVEL_PACKETCOUNTER) (DEBUG_LEVEL_XRUN_RECOVERY)| DEBUG_LEVEL_STARTUP | DEBUG_LEVEL_WAIT | DEBUG_LEVEL_PACKETCOUNTER)


#warning Building debug build!
#define printMessage(format, args...) jack_error( "FFADO MSG: %s:%d (%s): " format, __FILE__, __LINE__, __FUNCTION__, ##args )
#define printError(format, args...) jack_error( "FFADO ERR: %s:%d (%s): " format, __FILE__, __LINE__, __FUNCTION__, ##args )
/* #define printEnter() jack_error( "FBDRV ENTERS: %s (%s)", __FUNCTION__, __FILE__)
#define printExit() jack_error( "FBDRV EXITS: %s (%s)", __FUNCTION__, __FILE__)*/
#define printEnter()
#define printExit()
#define debugError(format, args...) jack_error( "FFADO ERR: %s:%d (%s): " format, __FILE__, __LINE__, __FUNCTION__, ##args )
#define debugPrint(Level, format, args...) if(DEBUG_LEVEL & (Level)) jack_error("DEBUG %s:%d (%s) :" format, __FILE__, __LINE__, __FUNCTION__, ##args );
#define debugPrintShort(Level, format, args...) if(DEBUG_LEVEL & (Level)) jack_error( format,##args );
#define debugPrintWithTimeStamp(Level, format, args...) if(DEBUG_LEVEL & (Level)) jack_error( "%16lu: "format, debugGetCurrentUTime(),##args );
#define SEGFAULT int *test=NULL; *test=1;
#warning Building debug build!
#define printMessage(format, args...) jack_error( "firewire MSG: %s:%d (%s): " format, __FILE__, __LINE__, __FUNCTION__, ##args )
#define printError(format, args...) jack_error( "firewire ERR: %s:%d (%s): " format, __FILE__, __LINE__, __FUNCTION__, ##args )
#define printEnter() jack_error( "FWDRV ENTERS: %s (%s)\n", __FUNCTION__, __FILE__)
#define printExit() jack_error( "FWDRV EXITS: %s (%s)\n", __FUNCTION__, __FILE__)
#define printEnter()
#define printExit()
#define debugError(format, args...) jack_error( "firewire ERR: %s:%d (%s): " format, __FILE__, __LINE__, __FUNCTION__, ##args )
#define debugPrint(Level, format, args...) if(DEBUG_LEVEL & (Level)) jack_error("DEBUG %s:%d (%s) :" format, __FILE__, __LINE__, __FUNCTION__, ##args );
#define debugPrintShort(Level, format, args...) if(DEBUG_LEVEL & (Level)) jack_error( format,##args );
#define debugPrintWithTimeStamp(Level, format, args...) if(DEBUG_LEVEL & (Level)) jack_error( "%16lu: "format, debugGetCurrentUTime(),##args );
#define SEGFAULT int *test=NULL; *test=1;
#else #else
#define DEBUG_LEVEL
#define printMessage(format, args...) if(g_verbose) \
jack_error("FFADO MSG: " format, ##args )
#define printError(format, args...) jack_error("FFADO ERR: " format, ##args )
#define printEnter()
#define printExit()
#define debugError(format, args...)
#define debugPrint(Level, format, args...)
#define debugPrintShort(Level, format, args...)
#define debugPrintWithTimeStamp(Level, format, args...)
#define DEBUG_LEVEL
#define printMessage(format, args...) if(g_verbose) \
jack_error("firewire MSG: " format, ##args )
#define printError(format, args...) jack_error("firewire ERR: " format, ##args )
#define printEnter()
#define printExit()
#define debugError(format, args...)
#define debugPrint(Level, format, args...)
#define debugPrintShort(Level, format, args...)
#define debugPrintWithTimeStamp(Level, format, args...)
#endif #endif


// thread priority setup // thread priority setup
#define FFADO_RT_PRIORITY_PACKETIZER_RELATIVE 5 #define FFADO_RT_PRIORITY_PACKETIZER_RELATIVE 5


#ifdef FFADO_DRIVER_WITH_MIDI

#define ALSA_SEQ_BUFF_SIZE 1024
#define MIDI_TRANSMIT_BUFFER_SIZE 1024
#define MIDI_THREAD_SLEEP_TIME_USECS 100
// midi priority should be higher than the audio priority in order to
// make sure events are not only delivered on period boundarys
// but I think it should be smaller than the packetizer thread in order not
// to lose any packets
#define FFADO_RT_PRIORITY_MIDI_RELATIVE 4

#endif

typedef struct _ffado_driver ffado_driver_t; typedef struct _ffado_driver ffado_driver_t;


/* /*
@@ -130,109 +117,91 @@ typedef struct _ffado_driver ffado_driver_t;
*/ */


typedef struct _ffado_jack_settings ffado_jack_settings_t; typedef struct _ffado_jack_settings ffado_jack_settings_t;
struct _ffado_jack_settings
{
struct _ffado_jack_settings {
int verbose_level;

int period_size_set; int period_size_set;
jack_nframes_t period_size; jack_nframes_t period_size;
int sample_rate_set; int sample_rate_set;
int sample_rate; int sample_rate;
int buffer_size_set; int buffer_size_set;
jack_nframes_t buffer_size; jack_nframes_t buffer_size;


int playback_ports; int playback_ports;
int capture_ports; int capture_ports;

int verbose_level;

jack_nframes_t capture_frame_latency; jack_nframes_t capture_frame_latency;
jack_nframes_t playback_frame_latency; jack_nframes_t playback_frame_latency;

ffado_handle_t fb_handle;
int slave_mode;
int snoop_mode;
char *device_info;
}; };


#ifdef FFADO_DRIVER_WITH_MIDI

typedef struct
{
int stream_nr;
int seq_port_nr;
snd_midi_event_t *parser;
snd_seq_t *seq_handle;
}
ffado_midi_port_t;

typedef struct _ffado_driver_midi_handle
typedef struct _ffado_capture_channel
{ {
ffado_device_t *dev;
ffado_driver_t *driver;
snd_seq_t *seq_handle;
ffado_streaming_stream_type stream_type;
midi_unpack_t midi_unpack;
uint32_t *midi_buffer;
} ffado_capture_channel_t;


pthread_t queue_thread;
pthread_t dequeue_thread;
int queue_thread_realtime;
int queue_thread_priority;

int nb_input_ports;
int nb_output_ports;

ffado_midi_port_t **input_ports;
ffado_midi_port_t **output_ports;

ffado_midi_port_t **input_stream_port_map;
int *output_port_stream_map;
}
ffado_driver_midi_handle_t;
#define MIDI_OVERFLOW_BUFFER_SIZE 4
typedef struct _ffado_playback_channel
{
ffado_streaming_stream_type stream_type;
midi_pack_t midi_pack;
uint32_t *midi_buffer;
// to hold the midi bytes that couldn't be transferred
// during the previous period
char overflow_buffer[MIDI_OVERFLOW_BUFFER_SIZE];
unsigned int nb_overflow_bytes;
} ffado_playback_channel_t;


#endif
/* /*
* JACK driver structure * JACK driver structure
*/ */

struct _ffado_driver struct _ffado_driver
{ {
JACK_DRIVER_NT_DECL
jack_nframes_t sample_rate;
jack_nframes_t period_size;
unsigned long wait_time;
jack_time_t wait_last;
jack_time_t wait_next;
int wait_late;
jack_client_t *client;
int xrun_detected;
int xrun_count;
int process_count;
/* settings from the command line */
ffado_jack_settings_t settings;
/* the freebob virtual device */
ffado_device_t *dev;
JSList *capture_ports;
JSList *playback_ports;
JSList *monitor_ports;
unsigned long playback_nchannels;
unsigned long capture_nchannels;
unsigned long playback_nchannels_audio;
unsigned long capture_nchannels_audio;
JACK_DRIVER_NT_DECL;
jack_nframes_t sample_rate;
jack_nframes_t period_size;
unsigned long wait_time;
jack_time_t wait_last;
jack_time_t wait_next;
int wait_late;
jack_client_t *client;
int xrun_detected;
int xrun_count;
int process_count;
/* settings from the command line */
ffado_jack_settings_t settings;
/* the firewire virtual device */
ffado_device_t *dev;
channel_t playback_nchannels;
channel_t capture_nchannels;
ffado_playback_channel_t *playback_channels;
ffado_capture_channel_t *capture_channels;
ffado_sample_t *nullbuffer;
ffado_sample_t *scratchbuffer;
jack_nframes_t playback_frame_latency; jack_nframes_t playback_frame_latency;
jack_nframes_t capture_frame_latency;
jack_nframes_t capture_frame_latency;
ffado_device_info_t device_info;
ffado_options_t device_options;


ffado_device_info_t device_info;
ffado_options_t device_options;

#ifdef FFADO_DRIVER_WITH_MIDI
ffado_driver_midi_handle_t *midi_handle;
#endif
}; };


#endif /* __JACK_FFADO_DRIVER_H__ */ #endif /* __JACK_FFADO_DRIVER_H__ */


Loading…
Cancel
Save