Browse Source

Enable explicit channel mapping in CoreAudio driver.

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@4515 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/1.9.8
sletz 14 years ago
parent
commit
4e0a70b5d2
6 changed files with 242 additions and 114 deletions
  1. +4
    -0
      ChangeLog
  2. +15
    -32
      common/JackDriverLoader.cpp
  3. +17
    -19
      common/jack/net.h
  4. +1
    -1
      example-clients/netslave.c
  5. +197
    -60
      macosx/coreaudio/JackCoreAudioDriver.cpp
  6. +8
    -2
      macosx/coreaudio/JackCoreAudioDriver.h

+ 4
- 0
ChangeLog View File

@@ -35,6 +35,10 @@ Chris Caudle
Jackdmp changes log
---------------------------

2011-07-29 Stephane Letz <letz@grame.fr>

* Enable explicit channel mapping in CoreAudio driver.

2011-07-25 Stephane Letz <letz@grame.fr>

* NetJack2: no more timeout, correct JackWaitThreadedDriver::Execute.


+ 15
- 32
common/JackDriverLoader.cpp View File

@@ -173,10 +173,10 @@ jack_parse_driver_params(jack_driver_desc_t * desc, int argc, char* argv[], JSLi
if (optarg) {
switch (desc->params[param_index].type) {
case JackDriverParamInt:
driver_param->value.i = atoi (optarg);
driver_param->value.i = atoi(optarg);
break;
case JackDriverParamUInt:
driver_param->value.ui = strtoul (optarg, NULL, 10);
driver_param->value.ui = strtoul(optarg, NULL, 10);
break;
case JackDriverParamChar:
driver_param->value.c = optarg[0];
@@ -185,20 +185,11 @@ jack_parse_driver_params(jack_driver_desc_t * desc, int argc, char* argv[], JSLi
strncpy (driver_param->value.str, optarg, JACK_DRIVER_PARAM_STRING_MAX);
break;
case JackDriverParamBool:

/*
if (strcasecmp ("false", optarg) == 0 ||
strcasecmp ("off", optarg) == 0 ||
strcasecmp ("no", optarg) == 0 ||
strcasecmp ("0", optarg) == 0 ||
strcasecmp ("(null)", optarg) == 0 ) {
*/
// steph
if (strcmp ("false", optarg) == 0 ||
strcmp ("off", optarg) == 0 ||
strcmp ("no", optarg) == 0 ||
strcmp ("0", optarg) == 0 ||
strcmp ("(null)", optarg) == 0 ) {
if (strcasecmp("false", optarg) == 0 ||
strcasecmp("off", optarg) == 0 ||
strcasecmp("no", optarg) == 0 ||
strcasecmp("0", optarg) == 0 ||
strcasecmp("(null)", optarg) == 0 ) {
driver_param->value.i = false;

} else {
@@ -317,11 +308,11 @@ jackctl_parse_driver_params(jackctl_driver *driver_ptr, int argc, char* argv[])
if (optarg) {
switch (jackctl_parameter_get_type(param)) {
case JackDriverParamInt:
value.i = atoi (optarg);
value.i = atoi(optarg);
jackctl_parameter_set_value(param, &value);
break;
case JackDriverParamUInt:
value.ui = strtoul (optarg, NULL, 10);
value.ui = strtoul(optarg, NULL, 10);
jackctl_parameter_set_value(param, &value);
break;
case JackDriverParamChar:
@@ -329,23 +320,15 @@ jackctl_parse_driver_params(jackctl_driver *driver_ptr, int argc, char* argv[])
jackctl_parameter_set_value(param, &value);
break;
case JackDriverParamString:
strncpy (value.str, optarg, JACK_DRIVER_PARAM_STRING_MAX);
strncpy(value.str, optarg, JACK_DRIVER_PARAM_STRING_MAX);
jackctl_parameter_set_value(param, &value);
break;
case JackDriverParamBool:
/*
if (strcasecmp ("false", optarg) == 0 ||
strcasecmp ("off", optarg) == 0 ||
strcasecmp ("no", optarg) == 0 ||
strcasecmp ("0", optarg) == 0 ||
strcasecmp ("(null)", optarg) == 0 ) {
*/
// steph
if (strcmp ("false", optarg) == 0 ||
strcmp ("off", optarg) == 0 ||
strcmp ("no", optarg) == 0 ||
strcmp ("0", optarg) == 0 ||
strcmp ("(null)", optarg) == 0 ) {
if (strcasecmp("false", optarg) == 0 ||
strcasecmp("off", optarg) == 0 ||
strcasecmp("no", optarg) == 0 ||
strcasecmp("0", optarg) == 0 ||
strcasecmp("(null)", optarg) == 0 ) {
value.i = false;
} else {
value.i = true;


+ 17
- 19
common/jack/net.h View File

@@ -28,18 +28,18 @@ extern "C"
#include <jack/systemdeps.h>
#include <jack/types.h>

#define DEFAULT_MULTICAST_IP "225.3.19.154"
#define DEFAULT_PORT 19000
#define DEFAULT_MTU 1500
#define MASTER_NAME_SIZE 256
#define DEFAULT_MULTICAST_IP "225.3.19.154"
#define DEFAULT_PORT 19000
#define DEFAULT_MTU 1500
#define MASTER_NAME_SIZE 256

#define SOCKET_ERROR -1

enum JackNetEncoder {

JackFloatEncoder = 0, // Samples are transmitted as float
JackIntEncoder = 1, // Samples are transmitted as 16 bits integer
JackCeltEncoder = 2, // Samples are transmitted using CELT codec (http://www.celt-codec.org/)
JackFloatEncoder = 0, // samples are transmitted as float
JackIntEncoder = 1, // samples are transmitted as 16 bits integer
JackCeltEncoder = 2, // samples are transmitted using CELT codec (http://www.celt-codec.org/)
};

typedef struct {
@@ -50,7 +50,7 @@ typedef struct {
int midi_output; // to master or from slave (-1 for get master MIDI physical inputs)
int mtu; // network Maximum Transmission Unit
int time_out; // in second, -1 means in infinite
int encoder; // Encoder type (one of JackNetEncoder)
int encoder; // encoder type (one of JackNetEncoder)
int kbps; // KB per second for CELT encoder
int latency; // network latency

@@ -104,7 +104,7 @@ int jack_net_slave_close(jack_net_slave_t* net);
* @param audio_output_buffer an array of audio output buffers (to master)
* @param midi_output number of MIDI outputs
* @param midi_output_buffer an array of MIDI output buffers (to master)
* @param arg pointer to a client supplied structure supplied by jack_set_net_process_callback().
* @param arg pointer to a client supplied structure supplied by jack_set_net_process_callback()
*
* @return zero on success, non-zero on error
*/
@@ -148,7 +148,7 @@ int jack_net_slave_deactivate(jack_net_slave_t* net);
/**
* Prototype for BufferSize callback.
* @param nframes buffer size
* @param arg pointer to a client supplied structure supplied by jack_set_net_buffer_size_callback().
* @param arg pointer to a client supplied structure supplied by jack_set_net_buffer_size_callback()
*
* @return zero on success, non-zero on error
*/
@@ -157,7 +157,7 @@ typedef int (*JackNetSlaveBufferSizeCallback)(jack_nframes_t nframes, void *arg)
/**
* Prototype for SampleRate callback.
* @param nframes sample rate
* @param arg pointer to a client supplied structure supplied by jack_set_net_sample_rate_callback().
* @param arg pointer to a client supplied structure supplied by jack_set_net_sample_rate_callback()
*
* @return zero on success, non-zero on error
*/
@@ -185,7 +185,7 @@ int jack_set_net_slave_sample_rate_callback(jack_net_slave_t *net, JackNetSlaveS

/**
* Prototype for server Shutdown callback (if not set, the client will just restart, waiting for an available master again).
* @param arg pointer to a client supplied structure supplied by jack_set_net_shutdown_callback().
* @param arg pointer to a client supplied structure supplied by jack_set_net_shutdown_callback()
*/
typedef void (*JackNetSlaveShutdownCallback)(void* data);

@@ -200,8 +200,7 @@ typedef void (*JackNetSlaveShutdownCallback)(void* data);
int jack_set_net_slave_shutdown_callback(jack_net_slave_t *net, JackNetSlaveShutdownCallback shutdown_callback, void *arg);

/**
* jack_net_master_t is an opaque type.
* You may only access it using the API provided.
* jack_net_master_t is an opaque type, you may only access it using the API provided.
*/
typedef struct _jack_net_master jack_net_master_t;

@@ -237,7 +236,7 @@ int jack_net_master_close(jack_net_master_t* net);
int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer);

/**
* Send sync and data to the network
* Send sync and data to the network.
* @param net the network connection
* @param audio_output number of audio outputs
* @param audio_output_buffer an array of audio output buffers
@@ -251,8 +250,7 @@ int jack_net_master_send(jack_net_master_t* net, int audio_output, float** audio
// Experimental Adapter API

/**
* jack_adapter_t is an opaque type. You may only access it using the
* API provided.
* jack_adapter_t is an opaque type, you may only access it using the API provided.
*/
typedef struct _jack_adapter jack_adapter_t;

@@ -290,7 +288,7 @@ int jack_destroy_adapter(jack_adapter_t* adapter);
void jack_flush_adapter(jack_adapter_t* adapter);

/**
* Push input to and pull output from adapter ringbuffer
* Push input to and pull output from adapter ringbuffer.
* @param adapter the adapter
* @param input an array of audio input buffers
* @param output an array of audio ouput buffers
@@ -301,7 +299,7 @@ void jack_flush_adapter(jack_adapter_t* adapter);
int jack_adapter_push_and_pull(jack_adapter_t* adapter, float** input, float** output, unsigned int frames);

/**
* Pull input to and push output from adapter ringbuffer
* Pull input to and push output from adapter ringbuffer.
* @param adapter the adapter
* @param input an array of audio input buffers
* @param output an array of audio ouput buffers


+ 1
- 1
example-clients/netslave.c View File

@@ -130,7 +130,7 @@ main (int argc, char *argv[])
return 1;
}

printf("Slave is found and running...\n");
printf("Master is found and running...\n");

jack_set_net_slave_process_callback(net, net_process, NULL);
jack_set_net_slave_shutdown_callback(net, net_shutdown, NULL);


+ 197
- 60
macosx/coreaudio/JackCoreAudioDriver.cpp View File

@@ -29,6 +29,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "JackCompilerDeps.h"
#include "JackLockedEngine.h"

#include <sstream>
#include <iostream>
#include <CoreServices/CoreServices.h>
#include <CoreFoundation/CFNumber.h>
@@ -137,15 +138,17 @@ static OSStatus DisplayDeviceNames()
CFStringRef UIname;

err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
if (err != noErr)
if (err != noErr) {
return err;
}

deviceNum = size / sizeof(AudioDeviceID);
AudioDeviceID devices[deviceNum];

err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
if (err != noErr)
if (err != noErr) {
return err;
}

for (i = 0; i < deviceNum; i++) {
char device_name[256];
@@ -162,8 +165,9 @@ static OSStatus DisplayDeviceNames()

size = 256;
err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name);
if (err != noErr)
if (err != noErr) {
return err;
}

jack_info("Device name = \'%s\', internal name = \'%s\' (to be used as -C, -P, or -d parameter)", device_name, internal_name);
}
@@ -171,8 +175,9 @@ static OSStatus DisplayDeviceNames()
return noErr;

error:
if (UIname != NULL)
if (UIname != NULL) {
CFRelease(UIname);
}
return err;
}

@@ -184,6 +189,20 @@ static CFStringRef GetDeviceName(AudioDeviceID id)
return (err == noErr) ? UIname : NULL;
}

void JackCoreAudioDriver::ParseChannelList(const string& list, vector<int>& result)
{
stringstream ss(list);
string token;
int chan;

while (ss >> token) {
istringstream ins;
ins.str(token);
ins >> chan;
result.push_back(chan);
}
}

OSStatus JackCoreAudioDriver::Render(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
@@ -241,8 +260,9 @@ int JackCoreAudioDriver::Write()
int size = sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize;
memcpy((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, buffer, size);
// Monitor ports
if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0)
if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0) {
memcpy(GetMonitorBuffer(i), buffer, size);
}
} else {
memset((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, 0, sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize);
}
@@ -349,8 +369,9 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice,
Float64 sample_rate = 0;
UInt32 outsize = sizeof(Float64);
OSStatus err = AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sample_rate);
if (err != noErr)
if (err != noErr) {
return kAudioHardwareUnsupportedOperationError;
}

char device_name[256];
const char* digidesign_name = "Digidesign";
@@ -420,11 +441,13 @@ OSStatus JackCoreAudioDriver::GetDefaultDevice(AudioDeviceID* id)
AudioDeviceID inDefault;
AudioDeviceID outDefault;

if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr)
if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) {
return res;
}

if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr)
if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) {
return res;
}

jack_log("GetDefaultDevice: input = %ld output = %ld", inDefault, outDefault);

@@ -447,8 +470,9 @@ OSStatus JackCoreAudioDriver::GetDefaultInputDevice(AudioDeviceID* id)
UInt32 theSize = sizeof(UInt32);
AudioDeviceID inDefault;

if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr)
if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) {
return res;
}

if (inDefault == 0) {
jack_error("Error : input device is 0, please select a correct one !!");
@@ -465,8 +489,9 @@ OSStatus JackCoreAudioDriver::GetDefaultOutputDevice(AudioDeviceID* id)
UInt32 theSize = sizeof(UInt32);
AudioDeviceID outDefault;

if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr)
if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) {
return res;
}

if (outDefault == 0) {
jack_error("Error : output device is 0, please select a correct one !!");
@@ -495,8 +520,9 @@ OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device, int& channe
AudioBufferList bufferList[outSize];
err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList);
if (err == noErr) {
for (unsigned int i = 0; i < bufferList->mNumberBuffers; i++)
for (unsigned int i = 0; i < bufferList->mNumberBuffers; i++) {
channelCount += bufferList->mBuffers[i].mNumberChannels;
}
}
}
return err;
@@ -526,7 +552,7 @@ OSStatus JackCoreAudioDriver::DestroyAggregateDevice()
pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
UInt32 outDataSize;

if (fPluginID > 0) {
if (fPluginID > 0) {

osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
if (osErr != noErr) {
@@ -771,8 +797,9 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap
vector<CFStringRef> captureDeviceUID;
for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
CFStringRef ref = GetDeviceName(captureDeviceID[i]);
if (ref == NULL)
if (ref == NULL) {
return -1;
}
captureDeviceUID.push_back(ref);
// input sub-devices in this example, so append the sub-device's UID to the CFArray
CFArrayAppendValue(subDevicesArray, ref);
@@ -781,8 +808,9 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap
vector<CFStringRef> playbackDeviceUID;
for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
CFStringRef ref = GetDeviceName(playbackDeviceID[i]);
if (ref == NULL)
if (ref == NULL) {
return -1;
}
playbackDeviceUID.push_back(ref);
// output sub-devices in this example, so append the sub-device's UID to the CFArray
CFArrayAppendValue(subDevicesArray, ref);
@@ -908,8 +936,9 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap
CFRelease(aggDeviceDict);
CFRelease(subDevicesArray);

if (subDevicesArrayClock)
if (subDevicesArrayClock) {
CFRelease(subDevicesArrayClock);
}

// release the device UID
for (UInt32 i = 0; i < captureDeviceUID.size(); i++) {
@@ -977,8 +1006,9 @@ int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid,
}
}

if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr)
if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) {
return -1;
}
}

// Capture only
@@ -1036,8 +1066,9 @@ int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid,
}
}

if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr)
if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) {
return -1;
}
}
}

@@ -1081,14 +1112,16 @@ int JackCoreAudioDriver::SetupChannels(bool capturing, bool playing, int& inchan

if (inchannels > in_nChannels) {
jack_error("This device hasn't required input channels inchannels = %d in_nChannels = %d", inchannels, in_nChannels);
if (strict)
if (strict) {
return -1;
}
}

if (outchannels > out_nChannels) {
jack_error("This device hasn't required output channels outchannels = %d out_nChannels = %d", outchannels, out_nChannels);
if (strict)
if (strict) {
return -1;
}
}

if (inchannels == -1) {
@@ -1261,6 +1294,8 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing,
int outchannels,
int in_nChannels,
int out_nChannels,
const vector<int>& chan_in_list,
const vector<int>& chan_out_list,
jack_nframes_t buffer_size,
jack_nframes_t sample_rate)
{
@@ -1270,7 +1305,8 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing,
AudioDeviceID currAudioDeviceID;
UInt32 size;

jack_log("OpenAUHAL capturing = %d playing = %d inchannels = %d outchannels = %d in_nChannels = %d out_nChannels = %d", capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels);
jack_log("OpenAUHAL capturing = %d playing = %d inchannels = %d outchannels = %d in_nChannels = %d out_nChannels = %d chan_in_list = %d chan_out_list = %d",
capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, chan_in_list.size(), chan_out_list.size());

if (inchannels == 0 && outchannels == 0) {
jack_error("No input and output channels...");
@@ -1363,34 +1399,61 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing,
}
}

// Setup channel map
if (capturing && inchannels > 0 && inchannels < in_nChannels) {
SInt32 chanArr[in_nChannels];
// Setup input channel map
if (capturing && inchannels > 0 && inchannels <= in_nChannels) {
UInt32 chanArr[in_nChannels];
for (int i = 0; i < in_nChannels; i++) {
chanArr[i] = -1;
}
for (int i = 0; i < inchannels; i++) {
chanArr[i] = i;
// Explicit mapping
if (chan_in_list.size() > 0) {
for (uint i = 0; i < chan_in_list.size(); i++) {
int chan = chan_in_list[i];
if (chan < out_nChannels) {
chanArr[i] = chan;
} else {
jack_info("Error input channel number is incorrect : %d", chan);
goto error;
}
}
} else {
for (int i = 0; i < inchannels; i++) {
chanArr[i] = i;
}
}
AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels);
AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(UInt32) * in_nChannels);
if (err1 != noErr) {
jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1");
jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap for input");
printError(err1);
goto error;
}
}

if (playing && outchannels > 0 && outchannels < out_nChannels) {
SInt32 chanArr[out_nChannels];
// Setup output channel map
if (playing && outchannels > 0 && outchannels <= out_nChannels) {
UInt32 chanArr[out_nChannels];
for (int i = 0; i < out_nChannels; i++) {
chanArr[i] = -1;
}
for (int i = 0; i < outchannels; i++) {
chanArr[i] = i;
// Explicit mapping
if (chan_out_list.size() > 0) {
for (uint i = 0; i < chan_out_list.size(); i++) {
int chan = chan_out_list[i];
if (chan < out_nChannels) {
chanArr[i] = chan;
} else {
jack_info("Error output channel number is incorrect : %d", chan);
goto error;
}
}
} else {
for (int i = 0; i < outchannels; i++) {
chanArr[i] = i;
}
}
err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels);
err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(UInt32) * out_nChannels);
if (err1 != noErr) {
jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0");
jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap for output");
printError(err1);
goto error;
}
@@ -1588,6 +1651,8 @@ int JackCoreAudioDriver::Open(jack_nframes_t buffer_size,
bool playing,
int inchannels,
int outchannels,
const char* chan_in_list,
const char* chan_out_list,
bool monitor,
const char* capture_driver_uid,
const char* playback_driver_uid,
@@ -1618,6 +1683,21 @@ int JackCoreAudioDriver::Open(jack_nframes_t buffer_size,
Gestalt(gestaltSystemVersionMajor, &major);
Gestalt(gestaltSystemVersionMinor, &minor);

vector<int> parsed_chan_in_list;
vector<int> parsed_chan_out_list;

ParseChannelList(chan_in_list, parsed_chan_in_list);
if (parsed_chan_in_list.size() > 0) {
jack_info("Explicit input channel list size = %d", parsed_chan_in_list.size());
inchannels = parsed_chan_in_list.size();
}

ParseChannelList(chan_out_list, parsed_chan_out_list);
if (parsed_chan_out_list.size() > 0) {
jack_info("Explicit output channel list size = %d", parsed_chan_out_list.size());
outchannels = parsed_chan_out_list.size();
}

// Starting with 10.6 systems, the HAL notification thread is created internally
if (major == 10 && minor >= 6) {
CFRunLoopRef theRunLoop = NULL;
@@ -1629,31 +1709,47 @@ int JackCoreAudioDriver::Open(jack_nframes_t buffer_size,
}
}

if (SetupDevices(capture_driver_uid, playback_driver_uid, capture_driver_name, playback_driver_name, sample_rate) < 0)
if (SetupDevices(capture_driver_uid, playback_driver_uid, capture_driver_name, playback_driver_name, sample_rate) < 0) {
goto error;
}

// Generic JackAudioDriver Open
if (JackAudioDriver::Open(buffer_size, sample_rate, capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency) != 0)
if (JackAudioDriver::Open(buffer_size, sample_rate,
capturing, playing,
inchannels, outchannels,
monitor,
capture_driver_name,
playback_driver_name,
capture_latency,
playback_latency) != 0) {
goto error;
}

if (SetupChannels(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, true) < 0)
if (SetupChannels(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, true) < 0) {
goto error;
}

if (SetupBufferSize(buffer_size) < 0)
if (SetupBufferSize(buffer_size) < 0) {
goto error;
}

if (SetupSampleRate(sample_rate) < 0)
if (SetupSampleRate(sample_rate) < 0) {
goto error;
}

if (OpenAUHAL(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, buffer_size, sample_rate) < 0)
if (OpenAUHAL(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, parsed_chan_in_list, parsed_chan_out_list, buffer_size, sample_rate) < 0) {
goto error;
}

if (capturing && inchannels > 0)
if (SetupBuffers(inchannels) < 0)
if (capturing && inchannels > 0) {
if (SetupBuffers(inchannels) < 0) {
goto error;
}
}

if (AddListeners() < 0)
if (AddListeners() < 0) {
goto error;
}

// Core driver may have changed the in/out values
fCaptureChannels = inchannels;
@@ -1692,11 +1788,13 @@ void JackCoreAudioDriver::UpdateLatencies()
UInt32 value1 = 0;
UInt32 value2 = 0;
err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertyLatency, &size, &value1);
if (err != noErr)
if (err != noErr) {
jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error");
}
err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertySafetyOffset, &size, &value2);
if (err != noErr)
if (err != noErr) {
jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error");
}

range.min = range.max = fEngineControl->fBufferSize + value1 + value2 + fCaptureLatency;
fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &range);
@@ -1707,11 +1805,13 @@ void JackCoreAudioDriver::UpdateLatencies()
UInt32 value1 = 0;
UInt32 value2 = 0;
err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertyLatency, &size, &value1);
if (err != noErr)
if (err != noErr) {
jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error");
}
err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertySafetyOffset, &size, &value2);
if (err != noErr)
if (err != noErr) {
jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error");
}

// Add more latency if "async" mode is used...
range.min = range.max
@@ -1742,12 +1842,14 @@ int JackCoreAudioDriver::Attach()
for (int i = 0; i < fCaptureChannels; i++) {

err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, &isWritable);
if (err != noErr)
if (err != noErr) {
jack_log("AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error");
}
if (err == noErr && size > 0) {
err = AudioDeviceGetProperty(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, channel_name);
if (err != noErr)
if (err != noErr) {
jack_log("AudioDeviceGetProperty kAudioDevicePropertyChannelName error");
}
snprintf(alias, sizeof(alias) - 1, "%s:%s:out_%s%u", fAliasName, fCaptureDriverName, channel_name, i + 1);
} else {
snprintf(alias, sizeof(alias) - 1, "%s:%s:out%u", fAliasName, fCaptureDriverName, i + 1);
@@ -1768,12 +1870,14 @@ int JackCoreAudioDriver::Attach()
for (int i = 0; i < fPlaybackChannels; i++) {

err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, &isWritable);
if (err != noErr)
if (err != noErr) {
jack_log("AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error");
}
if (err == noErr && size > 0) {
err = AudioDeviceGetProperty(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, channel_name);
if (err != noErr)
if (err != noErr) {
jack_log("AudioDeviceGetProperty kAudioDevicePropertyChannelName error");
}
snprintf(alias, sizeof(alias) - 1, "%s:%s:in_%s%u", fAliasName, fPlaybackDriverName, channel_name, i + 1);
} else {
snprintf(alias, sizeof(alias) - 1, "%s:%s:in%u", fAliasName, fPlaybackDriverName, i + 1);
@@ -1854,8 +1958,9 @@ int JackCoreAudioDriver::Stop()

int JackCoreAudioDriver::SetBufferSize(jack_nframes_t buffer_size)
{
if (SetupBufferSize(buffer_size) < 0)
if (SetupBufferSize(buffer_size) < 0) {
return -1;
}

JackAudioDriver::SetBufferSize(buffer_size); // Generic change, never fails

@@ -1950,8 +2055,12 @@ extern "C"

value.i = -1;
jack_driver_descriptor_add_parameter(desc, &filler, "channels", 'c', JackDriverParamInt, &value, NULL, "Maximum number of channels", "Maximum number of channels. If -1, max possible number of channels will be used");
jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamInt, &value, NULL, "Maximum number of input channels", "Maximum number of input channels. If -1, max possible number of input channels will be used");
jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamInt, &value, NULL, "Maximum number of output channels", "Maximum number of output channels. If -1, max possible number of output channels will be used");
jack_driver_descriptor_add_parameter(desc, &filler, "in-channels", 'i', JackDriverParamInt, &value, NULL, "Maximum number of input channels", "Maximum number of input channels. If -1, max possible number of input channels will be used");
jack_driver_descriptor_add_parameter(desc, &filler, "out-channels", 'o', JackDriverParamInt, &value, NULL, "Maximum number of output channels", "Maximum number of output channels. If -1, max possible number of output channels will be used");

value.str[0] = 0;
jack_driver_descriptor_add_parameter(desc, &filler, "input-list", 'n', JackDriverParamString, &value, NULL, "Input channel list", "List of input channel number to be opened");
jack_driver_descriptor_add_parameter(desc, &filler, "output-list", 'N', JackDriverParamString, &value, NULL, "Output channel list", "List of output channel number to be opened");

value.str[0] = 0;
jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Input CoreAudio device name", NULL);
@@ -1966,7 +2075,7 @@ extern "C"
value.ui = 44100U;
jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);

value.ui = 128U;
value.ui = 256U;
jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);

value.str[0] = 0;
@@ -1997,11 +2106,13 @@ extern "C"
SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
{
jack_nframes_t srate = 44100;
jack_nframes_t frames_per_interrupt = 128;
jack_nframes_t frames_per_interrupt = 256;
bool capture = false;
bool playback = false;
int chan_in = -1; // Default: if not explicitely set, then max possible will be used...
int chan_out = -1; // Default: if not explicitely set, then max possible will be used...
const char* chan_in_list = "";
const char* chan_out_list = "";
bool monitor = false;
const char* capture_driver_uid = "";
const char* playback_driver_uid = "";
@@ -2030,15 +2141,23 @@ extern "C"
break;

case 'c':
chan_in = chan_out = (int)param->value.ui;
chan_in = chan_out = param->value.i;
break;

case 'i':
chan_in = (int)param->value.ui;
chan_in = param->value.i;
break;

case 'o':
chan_out = (int)param->value.ui;
chan_out = param->value.i;
break;

case 'n':
chan_in_list = param->value.str;
break;

case 'N':
chan_out_list = param->value.str;
break;

case 'C':
@@ -2103,9 +2222,27 @@ extern "C"
playback = true;
}

if (strcmp(chan_in_list, "") != 0 && chan_in >= 0) {
printf("Input channel list and in channels are both specified, input channel list will take over...\n");
}

if (strcmp(chan_out_list, "") != 0 && chan_out >= 0) {
printf("Output channel list and out channels are both specified, output channel list will take over...\n");
}

Jack::JackCoreAudioDriver* driver = new Jack::JackCoreAudioDriver("system", "coreaudio", engine, table);
if (driver->Open(frames_per_interrupt, srate, capture, playback, chan_in, chan_out, monitor, capture_driver_uid,
playback_driver_uid, systemic_input_latency, systemic_output_latency, async_output_latency, computation_grain, hogged, clock_drift) == 0) {
if (driver->Open(frames_per_interrupt,
srate, capture,
playback, chan_in,
chan_out, chan_in_list,
chan_out_list, monitor,
capture_driver_uid,
playback_driver_uid,
systemic_input_latency,
systemic_output_latency,
async_output_latency,
computation_grain,
hogged, clock_drift) == 0) {
return driver;
} else {
delete driver;


+ 8
- 2
macosx/coreaudio/JackCoreAudioDriver.h View File

@@ -141,6 +141,8 @@ class JackCoreAudioDriver : public JackAudioDriver
int outchannels,
int in_nChannels,
int out_nChannels,
const vector<int>& chan_in_list,
const vector<int>& chan_out_list,
jack_nframes_t nframes,
jack_nframes_t samplerate);
void CloseAUHAL();
@@ -153,6 +155,8 @@ class JackCoreAudioDriver : public JackAudioDriver

void UpdateLatencies();

void ParseChannelList(const string& list, vector<int>& result);

public:

JackCoreAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table);
@@ -162,8 +166,10 @@ class JackCoreAudioDriver : public JackAudioDriver
jack_nframes_t samplerate,
bool capturing,
bool playing,
int chan_in,
int chan_out,
int inchannels,
int outchannels,
const char* chan_in_list,
const char* chan_out_list,
bool monitor,
const char* capture_driver_name,
const char* playback_driver_name,


Loading…
Cancel
Save