summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xdrivers/coreaudio/coreaudio_driver.c705
-rwxr-xr-xdrivers/coreaudio/coreaudio_driver.h4
2 files changed, 430 insertions, 279 deletions
diff --git a/drivers/coreaudio/coreaudio_driver.c b/drivers/coreaudio/coreaudio_driver.c
index 46671f4..177590c 100755
--- a/drivers/coreaudio/coreaudio_driver.c
+++ b/drivers/coreaudio/coreaudio_driver.c
@@ -41,6 +41,7 @@
Aug 16, 2005: S.Letz: Remove get_device_id_from_num, use get_default_device instead. If the -n option is not used or the device name cannot
be found, the default device is used. Note: the default device can be used only if both default input and default output are the same.
Dec 19, 2005: S.Letz: Add -d option (display_device_names).
+ Apri 7, 2006: S.Letz: Synchronization with the jackdmp coreaudio driver version: improve half-duplex management.
*/
@@ -64,7 +65,7 @@ static void JCALog(char *fmt, ...)
#endif
}
-static void printError1(OSStatus err)
+static void printError(OSStatus err)
{
#ifdef DEBUG
switch (err) {
@@ -152,10 +153,86 @@ static OSStatus get_default_device(AudioDeviceID * id)
*id = inDefault;
return noErr;
} else {
+ jack_error("Default input and output devices are not the same !!");
return kAudioHardwareBadDeviceError;
}
}
+static OSStatus get_default_input_device(AudioDeviceID* id)
+{
+ OSStatus res;
+ UInt32 theSize = sizeof(UInt32);
+ AudioDeviceID inDefault;
+
+ if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice,
+ &theSize, &inDefault)) != noErr)
+ return res;
+
+ JCALog("get_default_input_device: input = %ld \n", inDefault);
+ *id = inDefault;
+ return noErr;
+}
+
+static OSStatus get_default_output_device(AudioDeviceID* id)
+{
+ OSStatus res;
+ UInt32 theSize = sizeof(UInt32);
+ AudioDeviceID outDefault;
+
+ if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice,
+ &theSize, &outDefault)) != noErr)
+ return res;
+
+ JCALog("get_default_output_device: output = %ld\n", outDefault);
+ *id = outDefault;
+ return noErr;
+}
+
+OSStatus get_total_channels(AudioDeviceID device, int* channelCount, bool isInput)
+{
+ OSStatus err = noErr;
+ UInt32 outSize;
+ Boolean outWritable;
+ AudioBufferList* bufferList = 0;
+ AudioStreamID* streamList = 0;
+ int i, numStream;
+
+ err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreams, &outSize, &outWritable);
+ if (err == noErr) {
+ streamList = (AudioStreamID*)malloc(outSize);
+ numStream = outSize/sizeof(AudioStreamID);
+ JCALog("get_total_channels device stream number = %ld numStream = %ld\n", device, numStream);
+ err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreams, &outSize, streamList);
+ if (err == noErr) {
+ AudioStreamBasicDescription streamDesc;
+ outSize = sizeof(AudioStreamBasicDescription);
+ for (i = 0; i < numStream; i++) {
+ err = AudioStreamGetProperty(streamList[i], 0, kAudioDevicePropertyStreamFormat, &outSize, &streamDesc);
+ JCALog("get_total_channels streamDesc mFormatFlags = %ld mChannelsPerFrame = %ld\n", streamDesc.mFormatFlags, streamDesc.mChannelsPerFrame);
+ }
+ }
+ }
+
+ *channelCount = 0;
+ err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable);
+ if (err == noErr) {
+ bufferList = (AudioBufferList*)malloc(outSize);
+ err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList);
+ if (err == noErr) {
+ for (i = 0; i < bufferList->mNumberBuffers; i++)
+ *channelCount += bufferList->mBuffers[i].mNumberChannels;
+ }
+ }
+
+ if (streamList)
+ free(streamList);
+ if (bufferList)
+ free(bufferList);
+
+ return err;
+}
+
+
static OSStatus display_device_names()
{
UInt32 size;
@@ -205,11 +282,11 @@ error:
}
static OSStatus render(void *inRefCon,
- AudioUnitRenderActionFlags *ioActionFlags,
- const AudioTimeStamp *inTimeStamp,
- UInt32 inBusNumber,
- UInt32 inNumberFrames,
- AudioBufferList *ioData)
+ AudioUnitRenderActionFlags *ioActionFlags,
+ const AudioTimeStamp *inTimeStamp,
+ UInt32 inBusNumber,
+ UInt32 inNumberFrames,
+ AudioBufferList *ioData)
{
int res, i;
@@ -248,11 +325,11 @@ static OSStatus render(void *inRefCon,
}
static OSStatus render_input(void *inRefCon,
- AudioUnitRenderActionFlags *ioActionFlags,
- const AudioTimeStamp *inTimeStamp,
- UInt32 inBusNumber,
- UInt32 inNumberFrames,
- AudioBufferList *ioData)
+ AudioUnitRenderActionFlags *ioActionFlags,
+ const AudioTimeStamp *inTimeStamp,
+ UInt32 inBusNumber,
+ UInt32 inNumberFrames,
+ AudioBufferList *ioData)
{
coreaudio_driver_t* ca_driver = (coreaudio_driver_t*)inRefCon;
@@ -273,10 +350,10 @@ static OSStatus render_input(void *inRefCon,
}
static OSStatus notification(AudioDeviceID inDevice,
- UInt32 inChannel,
- Boolean isInput,
- AudioDevicePropertyID inPropertyID,
- void* inClientData)
+ UInt32 inChannel,
+ Boolean isInput,
+ AudioDevicePropertyID inPropertyID,
+ void* inClientData)
{
coreaudio_driver_t* ca_driver = (coreaudio_driver_t*)inClientData;
if (inPropertyID == kAudioDeviceProcessorOverload) {
@@ -286,8 +363,7 @@ static OSStatus notification(AudioDeviceID inDevice,
}
static int
-coreaudio_driver_attach(coreaudio_driver_t * driver,
- jack_engine_t * engine)
+coreaudio_driver_attach(coreaudio_driver_t * driver, jack_engine_t * engine)
{
jack_port_t *port;
JSList *node;
@@ -319,9 +395,9 @@ coreaudio_driver_attach(coreaudio_driver_t * driver,
err = AudioDeviceGetProperty(driver->device_id, chn + 1, true, kAudioDevicePropertyChannelName, &size, channel_name);
if (err != noErr)
JCALog("AudioDeviceGetProperty kAudioDevicePropertyChannelName error \n");
- snprintf(buf, sizeof(buf) - 1, "%s:out_%s%lu", driver->driver_name, channel_name, chn + 1);
+ snprintf(buf, sizeof(buf) - 1, "%s:out_%s%lu", driver->capture_driver_name, channel_name, chn + 1);
} else {
- snprintf(buf, sizeof(buf) - 1, "%s:out%lu", driver->driver_name, chn + 1);
+ snprintf(buf, sizeof(buf) - 1, "%s:out%lu", driver->capture_driver_name, chn + 1);
}
if ((port = jack_port_register(driver->client, buf,
@@ -353,9 +429,9 @@ coreaudio_driver_attach(coreaudio_driver_t * driver,
err = AudioDeviceGetProperty(driver->device_id, chn + 1, false, kAudioDevicePropertyChannelName, &size, channel_name);
if (err != noErr)
JCALog("AudioDeviceGetProperty kAudioDevicePropertyChannelName error \n");
- snprintf(buf, sizeof(buf) - 1, "%s:in_%s%lu", driver->driver_name, channel_name, chn + 1);
+ snprintf(buf, sizeof(buf) - 1, "%s:in_%s%lu", driver->playback_driver_name, channel_name, chn + 1);
} else {
- snprintf(buf, sizeof(buf) - 1, "%s:in%lu", driver->driver_name, chn + 1);
+ snprintf(buf, sizeof(buf) - 1, "%s:in%lu", driver->playback_driver_name, chn + 1);
}
if ((port = jack_port_register(driver->client, buf,
@@ -390,8 +466,7 @@ coreaudio_driver_attach(coreaudio_driver_t * driver,
}
static int
-coreaudio_driver_detach(coreaudio_driver_t * driver,
- jack_engine_t * engine)
+coreaudio_driver_detach(coreaudio_driver_t * driver, jack_engine_t * engine)
{
JSList *node;
@@ -418,8 +493,7 @@ coreaudio_driver_detach(coreaudio_driver_t * driver,
}
static int
-coreaudio_driver_null_cycle(coreaudio_driver_t * driver,
- jack_nframes_t nframes)
+coreaudio_driver_null_cycle(coreaudio_driver_t * driver, jack_nframes_t nframes)
{
driver->null_cycle_occured = 1;
return 0;
@@ -464,37 +538,39 @@ coreaudio_driver_bufsize(coreaudio_driver_t * driver,
/** create a new driver instance
*/
static jack_driver_t *coreaudio_driver_new(char* name,
- jack_client_t* client,
- jack_nframes_t frames_per_cycle,
- jack_nframes_t rate,
- int capturing,
- int playing,
- int chan_in,
- int chan_out,
- char* driver_uid,
- jack_nframes_t capture_latency,
- jack_nframes_t playback_latency)
+ jack_client_t* client,
+ jack_nframes_t nframes,
+ jack_nframes_t samplerate,
+ int capturing,
+ int playing,
+ int inchannels,
+ int outchannels,
+ char* capture_driver_uid,
+ char* playback_driver_uid,
+ jack_nframes_t capture_latency,
+ jack_nframes_t playback_latency)
{
coreaudio_driver_t *driver;
OSStatus err = noErr;
ComponentResult err1;
UInt32 outSize;
- Boolean isWritable;
- AudioStreamBasicDescription srcFormat, dstFormat;
- int in_nChannels, out_nChannels, i;
- Float64 nominalSampleRate;
-
+ UInt32 enableIO;
+ AudioStreamBasicDescription srcFormat, dstFormat, sampleRate;
+ int in_nChannels = 0;
+ int out_nChannels = 0;
+ int i;
+
driver = (coreaudio_driver_t *) calloc(1, sizeof(coreaudio_driver_t));
jack_driver_init((jack_driver_t *) driver);
- if (!jack_power_of_two(frames_per_cycle)) {
+ if (!jack_power_of_two(nframes)) {
fprintf(stderr, "CA: -p must be a power of two.\n");
goto error;
}
- driver->frames_per_cycle = frames_per_cycle;
- driver->frame_rate = rate;
+ driver->frames_per_cycle = nframes;
+ driver->frame_rate = samplerate;
driver->capturing = capturing;
driver->playing = playing;
driver->xrun_detected = 0;
@@ -511,263 +587,330 @@ static jack_driver_t *coreaudio_driver_new(char* name,
driver->stop = (JackDriverStopFunction) coreaudio_driver_audio_stop;
driver->capture_frame_latency = capture_latency;
driver->playback_frame_latency = playback_latency;
-
- if (driver_uid) {
- if (get_device_id_from_uid(driver_uid, &driver->device_id) != noErr) {
- if (get_default_device(&driver->device_id) != noErr)
+
+ // Duplex
+ if (capture_driver_uid != NULL && playback_driver_uid != NULL) {
+ JCALog("Open duplex \n");
+ if (get_device_id_from_uid(playback_driver_uid, &driver->device_id) != noErr) {
+ if (get_default_device(&driver->device_id) != noErr) {
+ jack_error("Cannot open default device");
goto error;
+ }
+ }
+ if (get_device_name_from_id(driver->device_id, driver->capture_driver_name) != noErr || get_device_name_from_id(driver->device_id, driver->playback_driver_name) != noErr) {
+ jack_error("Cannot get device name from device ID");
+ goto error;
+ }
+
+ // Capture only
+ } else if (capture_driver_uid != NULL) {
+ JCALog("Open capture only \n");
+ if (get_device_id_from_uid(capture_driver_uid, &driver->device_id) != noErr) {
+ if (get_default_input_device(&driver->device_id) != noErr) {
+ jack_error("Cannot open default device");
+ goto error;
+ }
+ }
+ if (get_device_name_from_id(driver->device_id, driver->capture_driver_name) != noErr) {
+ jack_error("Cannot get device name from device ID");
+ goto error;
+ }
+
+ // Playback only
+ } else if (playback_driver_uid != NULL) {
+ JCALog("Open playback only \n");
+ if (get_device_id_from_uid(playback_driver_uid, &driver->device_id) != noErr) {
+ if (get_default_output_device(&driver->device_id) != noErr) {
+ jack_error("Cannot open default device");
+ goto error;
+ }
+ }
+ if (get_device_name_from_id(driver->device_id, driver->playback_driver_name) != noErr) {
+ jack_error("Cannot get device name from device ID");
+ goto error;
}
+
+ // Use default driver in duplex mode
} else {
- if (get_default_device(&driver->device_id) != noErr)
+ JCALog("Open default driver \n");
+ if (get_default_device(&driver->device_id) != noErr) {
+ jack_error("Cannot open default device");
+ goto error;
+ }
+ if (get_device_name_from_id(driver->device_id, driver->capture_driver_name) != noErr || get_device_name_from_id(driver->device_id, driver->playback_driver_name) != noErr) {
+ jack_error("Cannot get device name from device ID");
goto error;
+ }
}
-
- if (get_device_name_from_id(driver->device_id, driver->driver_name) != noErr)
- goto error;
-
+
driver->client = client;
driver->period_usecs =
(((float) driver->frames_per_cycle) / driver->frame_rate) *
1000000.0f;
-
- driver->playback_nchannels = chan_out;
- driver->capture_nchannels = chan_in;
- // Setting buffer size
- outSize = sizeof(UInt32);
- err = AudioDeviceSetProperty(driver->device_id, NULL, 0, false,
- kAudioDevicePropertyBufferFrameSize, outSize, &frames_per_cycle);
- if (err != noErr) {
- JCALog("Cannot set buffer size %ld\n", frames_per_cycle);
- printError1(err);
+ if (capturing) {
+ err = get_total_channels(driver->device_id, &in_nChannels, true);
+ if (err != noErr) {
+ jack_error("Cannot get input channel number");
+ printError(err);
+ goto error;
+ }
+ }
+
+ if (playing) {
+ err = get_total_channels(driver->device_id, &out_nChannels, false);
+ if (err != noErr) {
+ jack_error("Cannot get output channel number");
+ printError(err);
+ goto error;
+ }
+ }
+
+ if (inchannels > in_nChannels) {
+ jack_error("This device hasn't required input channels inchannels = %ld in_nChannels = %ld", inchannels, in_nChannels);
goto error;
}
- outSize = sizeof(Float64);
- err = AudioDeviceGetProperty(driver->device_id, 0, false,
- kAudioDevicePropertyNominalSampleRate, &outSize, &nominalSampleRate);
- if (err != noErr) {
- JCALog("Cannot get sample rate\n");
- printError1(err);
+ if (outchannels > out_nChannels) {
+ jack_error("This device hasn't required output channels outchannels = %ld out_nChannels = %ld", outchannels, out_nChannels);
goto error;
- } else {
- JCALog("Read nominalSampleRate %f\n", nominalSampleRate);
+ }
+
+ if (inchannels == 0) {
+ JCALog("Setup max in channels = %ld\n", in_nChannels);
+ inchannels = in_nChannels;
+ }
+
+ if (outchannels == 0) {
+ JCALog("Setup max out channels = %ld\n", out_nChannels);
+ outchannels = out_nChannels;
}
- if (rate != (jack_nframes_t)nominalSampleRate) {
- nominalSampleRate = (Float64)rate;
- err = AudioDeviceSetProperty(driver->device_id, NULL, 0,
- false, kAudioDevicePropertyNominalSampleRate, outSize, &nominalSampleRate);
- if (err != noErr) {
- JCALog("Cannot set sample rate %ld\n", rate);
- printError1(err);
- goto error;
- }
+ // Setting buffer size
+ outSize = sizeof(UInt32);
+ err = AudioDeviceSetProperty(driver->device_id, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &nframes);
+ if (err != noErr) {
+ jack_error("Cannot set buffer size %ld", nframes);
+ printError(err);
+ goto error;
}
+
+ // Set sample rate
+ if (capturing && inchannels > 0) {
+ outSize = sizeof(AudioStreamBasicDescription);
+ err = AudioDeviceGetProperty(driver->device_id, 0, true, kAudioDevicePropertyStreamFormat, &outSize, &sampleRate);
+ if (err != noErr) {
+ jack_error("Cannot get current sample rate");
+ printError(err);
+ goto error;
+ }
+
+ if (samplerate != (unsigned long)sampleRate.mSampleRate) {
+ sampleRate.mSampleRate = (Float64)samplerate;
+ err = AudioDeviceSetProperty(driver->device_id, NULL, 0, true, kAudioDevicePropertyStreamFormat, outSize, &sampleRate);
+ if (err != noErr) {
+ jack_error("Cannot set sample rate = %ld", samplerate);
+ printError(err);
+ goto error;
+ }
+ }
+ }
- err = AudioDeviceGetProperty(driver->device_id, 0, false,
- kAudioDevicePropertyNominalSampleRate, &outSize, &nominalSampleRate);
- if (err != noErr) {
- JCALog("Cannot get sample rate\n");
- printError1(err);
- goto error;
- } else {
- JCALog("Read again nominalSampleRate %f\n", nominalSampleRate);
+ if (playing && outchannels > 0) {
+ outSize = sizeof(AudioStreamBasicDescription);
+ err = AudioDeviceGetProperty(driver->device_id, 0, false, kAudioDevicePropertyStreamFormat, &outSize, &sampleRate);
+ if (err != noErr) {
+ jack_error("Cannot get current sample rate");
+ printError(err);
+ goto error;
+ }
+
+ if (samplerate != (unsigned long)sampleRate.mSampleRate) {
+ sampleRate.mSampleRate = (Float64)samplerate;
+ err = AudioDeviceSetProperty(driver->device_id, NULL, 0, false, kAudioDevicePropertyStreamFormat, outSize, &sampleRate);
+ if (err != noErr) {
+ jack_error("Cannot set sample rate = %ld", samplerate);
+ printError(err);
+ goto error;
+ }
+ }
}
- // AUHAL
- ComponentDescription cd = {kAudioUnitType_Output,
- kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
- Component HALOutput = FindNextComponent(NULL, &cd);
-
- err1 = OpenAComponent(HALOutput, &driver->au_hal);
- if (err1 != noErr)
- goto error;
+ // AUHAL
+ ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
+ Component HALOutput = FindNextComponent(NULL, &cd);
- err1 = AudioUnitInitialize(driver->au_hal);
- if (err1 != noErr) {
- printError1(err1);
+ err1 = OpenAComponent(HALOutput, &driver->au_hal);
+ if (err1 != noErr) {
+ jack_error("Error calling OpenAComponent");
+ printError(err1);
goto error;
}
-
- outSize = 1;
- err1 = AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_EnableIO,
- kAudioUnitScope_Output, 0, &outSize, sizeof(outSize));
- if (err1 != noErr) {
- JCALog("error: calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output\n");
- printError1(err1);
- goto error;
+
+ err1 = AudioUnitInitialize(driver->au_hal);
+ if (err1 != noErr) {
+ jack_error("Cannot initialize AUHAL unit");
+ printError(err1);
+ goto error;
}
+
+ // Start I/O
+ enableIO = 1;
+ if (capturing && inchannels > 0) {
+ JCALog("Setup AUHAL input\n");
+ err1 = AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO));
+ if (err1 != noErr) {
+ jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input");
+ printError(err1);
+ goto error;
+ }
+ }
- if (chan_in > 0) {
- outSize = 1;
- err1 = AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_EnableIO,
- kAudioUnitScope_Input, 1, &outSize, sizeof(outSize));
- if (err1 != noErr) {
- JCALog("error: calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Input\n");
- printError1(err1);
- goto error;
+ if (playing && outchannels > 0) {
+ JCALog("Setup AUHAL output\n");
+ err1 = AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO));
+ if (err1 != noErr) {
+ jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output");
+ printError(err1);
+ goto error;
}
}
- err1 = AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_CurrentDevice,
- kAudioUnitScope_Global, 0, &driver->device_id, sizeof(AudioDeviceID));
- if (err1 != noErr) {
- JCALog("error: calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice\n");
- printError1(err1);
+ // Setup up choosen device, in both input and output cases
+ err1 = AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &driver->device_id, sizeof(AudioDeviceID));
+ if (err1 != noErr) {
+ jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice");
+ printError(err1);
goto error;
}
-
- err1 = AudioUnitSetProperty(driver->au_hal, kAudioUnitProperty_MaximumFramesPerSlice,
- kAudioUnitScope_Global, 0, (UInt32*)&frames_per_cycle, sizeof(UInt32));
- if (err1 != noErr) {
- JCALog("error: calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n");
- printError1(err1);
- goto error;
- }
- err1 = AudioUnitGetPropertyInfo(driver->au_hal, kAudioOutputUnitProperty_ChannelMap,
- kAudioUnitScope_Input, 1, &outSize, &isWritable);
- if (err1 != noErr) {
- JCALog("error: calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap-INFO 1\n");
- printError1(err1);
+ // Set buffer size
+ if (capturing && inchannels > 0) {
+ err1 = AudioUnitSetProperty(driver->au_hal, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&nframes, sizeof(UInt32));
+ if (err1 != noErr) {
+ jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
+ printError(err1);
+ goto error;
+ }
}
- in_nChannels = outSize / sizeof(SInt32);
-
- err1 = AudioUnitGetPropertyInfo(driver->au_hal, kAudioOutputUnitProperty_ChannelMap,
- kAudioUnitScope_Output, 0, &outSize, &isWritable);
- if (err1 != noErr) {
- JCALog("error: calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap-INFO 0\n");
- printError1(err1);
+ if (playing && outchannels > 0) {
+ err1 = AudioUnitSetProperty(driver->au_hal, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&nframes, sizeof(UInt32));
+ if (err1 != noErr) {
+ jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
+ printError(err1);
+ goto error;
+ }
}
- out_nChannels = outSize / sizeof(SInt32);
-
- if (chan_out > out_nChannels) {
- JCALog("This device hasn't required output channels.\n");
- goto error;
- }
- if (chan_in > in_nChannels) {
- JCALog("This device hasn't required input channels.\n");
- goto error;
- }
+ // Setup channel map
+ if (capturing && inchannels > 0 && inchannels < in_nChannels) {
+ SInt32 chanArr[in_nChannels];
+ for (i = 0; i < in_nChannels; i++) {
+ chanArr[i] = -1;
+ }
+ for (i = 0; i < inchannels; i++) {
+ chanArr[i] = i;
+ }
+ AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels);
+ if (err1 != noErr) {
+ jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1");
+ printError(err1);
+ }
+ }
- if (chan_out < out_nChannels) {
- SInt32 chanArr[out_nChannels];
- for (i = 0;i < out_nChannels; i++) {
- chanArr[i] = -1;
- }
- for (i = 0; i < chan_out; i++) {
- chanArr[i] = i;
- }
- err1 = AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_ChannelMap,
- kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels);
+ if (playing && outchannels > 0 && outchannels < out_nChannels) {
+ SInt32 chanArr[out_nChannels];
+ for (i = 0; i < out_nChannels; i++) {
+ chanArr[i] = -1;
+ }
+ for (i = 0; i < outchannels; i++) {
+ chanArr[i] = i;
+ }
+ err1 = AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels);
+ if (err1 != noErr) {
+ jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0");
+ printError(err1);
+ }
+ }
+
+ // Setup stream converters
+ if (capturing && inchannels > 0) {
+ srcFormat.mSampleRate = samplerate;
+ srcFormat.mFormatID = kAudioFormatLinearPCM;
+ srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
+ srcFormat.mBytesPerPacket = sizeof(float);
+ srcFormat.mFramesPerPacket = 1;
+ srcFormat.mBytesPerFrame = sizeof(float);
+ srcFormat.mChannelsPerFrame = outchannels;
+ srcFormat.mBitsPerChannel = 32;
+
+ err1 = AudioUnitSetProperty(driver->au_hal, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, sizeof(AudioStreamBasicDescription));
if (err1 != noErr) {
- JCALog("error: calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0\n");
- printError1(err1);
+ jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
+ printError(err1);
}
}
-
- if (chan_in < in_nChannels) {
- SInt32 chanArr[in_nChannels];
- for (i = 0; i < in_nChannels; i++) {
- chanArr[i] = -1;
- }
- for(i = 0;i < chan_in; i++) {
- chanArr[i] = i;
- }
- AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_ChannelMap,
- kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels);
+
+ if (playing && outchannels > 0) {
+ dstFormat.mSampleRate = samplerate;
+ dstFormat.mFormatID = kAudioFormatLinearPCM;
+ dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
+ dstFormat.mBytesPerPacket = sizeof(float);
+ dstFormat.mFramesPerPacket = 1;
+ dstFormat.mBytesPerFrame = sizeof(float);
+ dstFormat.mChannelsPerFrame = inchannels;
+ dstFormat.mBitsPerChannel = 32;
+
+ err1 = AudioUnitSetProperty(driver->au_hal, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &dstFormat, sizeof(AudioStreamBasicDescription));
if (err1 != noErr) {
- JCALog("error: calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1\n");
- printError1(err1);
+ jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
+ printError(err1);
}
}
- srcFormat.mSampleRate = rate;
- srcFormat.mFormatID = kAudioFormatLinearPCM;
- srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked |
- kLinearPCMFormatFlagIsNonInterleaved;
- srcFormat.mBytesPerPacket = sizeof(float);
- srcFormat.mFramesPerPacket = 1;
- srcFormat.mBytesPerFrame = sizeof(float);
- srcFormat.mChannelsPerFrame = chan_out;
- srcFormat.mBitsPerChannel = 32;
-
- err1 = AudioUnitSetProperty(driver->au_hal, kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Input, 0, &srcFormat, sizeof(AudioStreamBasicDescription));
- if (err1 != noErr) {
- JCALog("error: calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input\n");
- printError1(err1);
- }
+ // Setup callbacks
+ if (inchannels > 0 && outchannels == 0) {
+ AURenderCallbackStruct output;
+ output.inputProc = render_input;
+ output.inputProcRefCon = driver;
+ err1 = AudioUnitSetProperty(driver->au_hal, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output));
+ if (err1 != noErr) {
+ jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1");
+ printError(err1);
+ goto error;
+ }
+ } else {
+ AURenderCallbackStruct output;
+ output.inputProc = render;
+ output.inputProcRefCon = driver;
+ err1 = AudioUnitSetProperty(driver->au_hal, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output));
+ if (err1 != noErr) {
+ jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0");
+ printError(err1);
+ goto error;
+ }
+ }
+
+ if (capturing && inchannels > 0) {
+ driver->input_list = (AudioBufferList*)malloc(sizeof(UInt32) + inchannels * sizeof(AudioBuffer));
+ if (driver->input_list == 0)
+ goto error;
+ driver->input_list->mNumberBuffers = inchannels;
- dstFormat.mSampleRate = rate;
- dstFormat.mFormatID = kAudioFormatLinearPCM;
- dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked |
- kLinearPCMFormatFlagIsNonInterleaved;
- dstFormat.mBytesPerPacket = sizeof(float);
- dstFormat.mFramesPerPacket = 1;
- dstFormat.mBytesPerFrame = sizeof(float);
- dstFormat.mChannelsPerFrame = chan_in;
- dstFormat.mBitsPerChannel = 32;
-
- err1 = AudioUnitSetProperty(driver->au_hal, kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Output, 1, &dstFormat, sizeof(AudioStreamBasicDescription));
- if (err1 != noErr) {
- JCALog("error: calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n");
- printError1(err1);
- }
-
- if (chan_in > 0 && chan_out== 0) {
- AURenderCallbackStruct output;
- output.inputProc = render_input;
- output.inputProcRefCon = driver;
- err1 = AudioUnitSetProperty(driver->au_hal, kAudioUnitProperty_SetRenderCallback,
- kAudioUnitScope_Output, 1, &output, sizeof(output));
- if (err1 != noErr) {
- JCALog("AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1\n");
- printError1(err1);
- goto error;
- }
- } else {
- AURenderCallbackStruct output;
- output.inputProc = render;
- output.inputProcRefCon = driver;
- err1 = AudioUnitSetProperty(driver->au_hal, kAudioUnitProperty_SetRenderCallback,
- kAudioUnitScope_Input, 0, &output, sizeof(output));
- if (err1 != noErr) {
- JCALog("AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0\n");
- printError1(err1);
- goto error;
+ // Prepare buffers
+ for (i = 0; i < driver->capture_nchannels; i++) {
+ driver->input_list->mBuffers[i].mNumberChannels = 1;
+ driver->input_list->mBuffers[i].mDataByteSize = nframes * sizeof(float);
}
}
-
- driver->input_list = (AudioBufferList*)malloc(sizeof(UInt32) + chan_in * sizeof(AudioBuffer));
- if (driver->input_list == 0)
- goto error;
- driver->input_list->mNumberBuffers = chan_in;
- driver->output_list = (AudioBufferList*)malloc(sizeof(UInt32) + chan_out * sizeof(AudioBuffer));
- if (driver->output_list == 0)
- goto error;
- driver->output_list->mNumberBuffers = chan_out;
-
err = AudioDeviceAddPropertyListener(driver->device_id, 0, true, kAudioDeviceProcessorOverload, notification, driver);
if (err != noErr)
goto error;
- // Prepare buffers
- for (i = 0; i < driver->capture_nchannels; i++) {
- driver->input_list->mBuffers[i].mNumberChannels = 1;
- driver->input_list->mBuffers[i].mDataByteSize = frames_per_cycle * sizeof(float);
- }
-
- for (i = 0; i < driver->playback_nchannels; i++) {
- driver->output_list->mBuffers[i].mNumberChannels = 1;
- driver->output_list->mBuffers[i].mDataByteSize = frames_per_cycle * sizeof(float);
- }
-
+ driver->playback_nchannels = outchannels;
+ driver->capture_nchannels = inchannels;
return ((jack_driver_t *) driver);
error:
@@ -784,8 +927,7 @@ static void coreaudio_driver_delete(coreaudio_driver_t * driver)
{
AudioDeviceRemovePropertyListener(driver->device_id, 0, true, kAudioDeviceProcessorOverload, notification);
free(driver->input_list);
- free(driver->output_list);
- AudioUnitUninitialize(driver->au_hal);
+ AudioUnitUninitialize(driver->au_hal);
CloseComponent(driver->au_hal);
free(driver);
}
@@ -831,20 +973,20 @@ jack_driver_desc_t *driver_get_descriptor()
strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
i++;
- strcpy(desc->params[i].name, "capture");
- desc->params[i].character = 'C';
- desc->params[i].type = JackDriverParamBool;
- desc->params[i].value.i = TRUE;
- strcpy(desc->params[i].short_desc, "Whether or not to capture");
- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+ strcpy(desc->params[i].name, "capture");
+ desc->params[i].character = 'C';
+ desc->params[i].type = JackDriverParamString;
+ strcpy(desc->params[i].value.str, "will take default CoreAudio input device");
+ strcpy(desc->params[i].short_desc, "Provide capture ports. Optionally set CoreAudio device name");
+ strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
- i++;
- strcpy(desc->params[i].name, "playback");
- desc->params[i].character = 'P';
- desc->params[i].type = JackDriverParamBool;
- desc->params[i].value.i = TRUE;
- strcpy(desc->params[i].short_desc, "Whether or not to playback");
- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+ i++;
+ strcpy(desc->params[i].name, "playback");
+ desc->params[i].character = 'P';
+ desc->params[i].type = JackDriverParamString;
+ strcpy(desc->params[i].value.str, "will take default CoreAudio output device");
+ strcpy(desc->params[i].short_desc, "Provide playback ports. Optionally set CoreAudio device name");
+ strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
i++;
strcpy(desc->params[i].name, "duplex");
@@ -871,12 +1013,13 @@ jack_driver_desc_t *driver_get_descriptor()
strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
i++;
- strcpy(desc->params[i].name, "name");
- desc->params[i].character = 'n';
- desc->params[i].type = JackDriverParamString;
- desc->params[i].value.ui = 128U;
- strcpy(desc->params[i].short_desc, "Driver name");
- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+ strcpy(desc->params[i].name, "name");
+ desc->params[i].character = 'n';
+ desc->params[i].type = JackDriverParamString;
+ desc->params[i].value.ui = 128U;
+ strcpy(desc->params[i].value.str, "will take default CoreAudio device name");
+ strcpy(desc->params[i].short_desc, "CoreAudio device name");
+ strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
i++;
strcpy(desc->params[i].name, "input-latency");
@@ -912,9 +1055,10 @@ jack_driver_t *driver_initialize(jack_client_t * client,
jack_nframes_t frames_per_interrupt = 128;
int capture = FALSE;
int playback = FALSE;
- int chan_in = 2;
- int chan_out = 2;
- char *name = NULL;
+ int chan_in = 0;
+ int chan_out = 0;
+ char* capture_pcm_name = NULL;
+ char* playback_pcm_name = NULL;
const JSList *node;
const jack_driver_param_t *param;
jack_nframes_t systemic_input_latency = 0;
@@ -926,7 +1070,8 @@ jack_driver_t *driver_initialize(jack_client_t * client,
switch (param->character) {
case 'n':
- name = (char *) param->value.str;
+ capture_pcm_name = strdup(param->value.str);
+ playback_pcm_name = strdup(param->value.str);
break;
case 'D':
@@ -947,11 +1092,17 @@ jack_driver_t *driver_initialize(jack_client_t * client,
break;
case 'C':
- capture = param->value.i;
+ capture = TRUE;
+ if (strcmp(param->value.str, "none") != 0) {
+ capture_pcm_name = strdup(param->value.str);
+ }
break;
case 'P':
- playback = param->value.i;
+ playback = TRUE;
+ if (strcmp(param->value.str, "none") != 0) {
+ playback_pcm_name = strdup(param->value.str);
+ }
break;
case 'r':
@@ -984,7 +1135,7 @@ jack_driver_t *driver_initialize(jack_client_t * client,
return coreaudio_driver_new("coreaudio", client, frames_per_interrupt,
srate, capture, playback, chan_in,
- chan_out, name, systemic_input_latency, systemic_output_latency);
+ chan_out, capture_pcm_name, playback_pcm_name, systemic_input_latency, systemic_output_latency);
}
void driver_finish(jack_driver_t * driver)
diff --git a/drivers/coreaudio/coreaudio_driver.h b/drivers/coreaudio/coreaudio_driver.h
index 99eabf6..b6a60ab 100755
--- a/drivers/coreaudio/coreaudio_driver.h
+++ b/drivers/coreaudio/coreaudio_driver.h
@@ -55,11 +55,11 @@ typedef struct {
JSList *capture_ports;
JSList *playback_ports;
- char driver_name[256];
+ char capture_driver_name[256];
+ char playback_driver_name[256];
AudioUnit au_hal;
AudioBufferList* input_list;
- AudioBufferList* output_list;
AudioDeviceID device_id;
jack_nframes_t capture_frame_latency;