views:

100

answers:

1

Hi,

I've spent the last week on an unplanned excursion into the depths of the Macintosh sound system after NSSound proved to be unequal to the task.. I finally got my file playing with Audio Queue Services and now there's only one little thing left to do: switch output devices.

Unfortunately, it seems that I'm either doing something wrong or the device UID CFStringRef that you're supposed to pass is not the one that Core Audio gives out..

The piece of code below retrieves the standard output device (to which the Audio Queue will be playing by default anyway, but it refuses to change devices:

UInt32 thePropSize;
AudioDeviceID defaultAudioDevice;

OSStatus result = noErr;

// get the device list  
AudioObjectPropertyAddress thePropertyAddress = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, 
    kAudioObjectPropertyElementMaster };

result = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &thePropertyAddress, 0, NULL, &thePropSize);

result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &thePropertyAddress, 0, NULL, &thePropSize, &defaultAudioDevice);

CFStringRef theDeviceName;      

// get the device name
thePropSize = sizeof(CFStringRef);
thePropertyAddress.mSelector = kAudioObjectPropertyName;
thePropertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
thePropertyAddress.mElement = kAudioObjectPropertyElementMaster;

// get the name of the device
result = AudioObjectGetPropertyData( (AudioObjectID)defaultAudioDevice, 
                                    &thePropertyAddress, 0, NULL, &thePropSize, &theDeviceName);

// get the uid of the device
CFStringRef theDeviceUID;
thePropertyAddress.mSelector = kAudioDevicePropertyDeviceUID;
result = AudioObjectGetPropertyData( (AudioObjectID)defaultAudioDevice, 
                                    &thePropertyAddress, 0, NULL, &thePropSize, &theDeviceUID);


result = AudioQueueSetProperty( playerState.mQueue,
                                        kAudioQueueProperty_CurrentDevice,
                                        &theDeviceUID,
                                        sizeof(theDeviceUID));

If the queue is playing, I get an error kAudioQueueErr_InvalidRunState, telling me that you can't set this property while the queue is playing. If the queue is not playing, I get the -50 parameter error.

I'm I doing something wrong with the pointers? or is there a different device uid somewhere!?

Any help would be greatly appreciated.

A: 

I've figured out a solution and I'm posting it here for the archives:

Apple Developer Services tested my code in a separate project and it ran just great for them straight away.. the difference was that they set the device uid without all the tedious audio buffers and volume setup, etc.. I moved the device uid change from the end of the queue setup to immediately after the queue is created and bingo! it works just fine.

I'm not 100% certain but I think you just can't change the device after you set the gain for the queue due to some hardware driver restrictions. "parameter error" doesn't seem to quite point in that direction but I think a "too late to change device" error would be more appropriate.

Frank R.