Change the output device for AVAudioPlayer on OSX - macos

I need to play audio from AVAudioPlayer to a particular audio device such as a USB headset. By default the audio will get played out to the system default device setting. With QTKit, I was able to use SetMovieAudioContext() to do such a task but do not see equivalent in AVFoundation. How is it possible to change this on OSX?

Use NSSound instead:
Get list of audio devices with CoreAudio functions. Then get the devices' unique identifiers:
//...
address.mSelector = kAudioDevicePropertyDeviceUID;
CFStringRef uid = NULL;
UInt32 size = sizeof(uid);
AudioObjectGetPropertyData(deviceId, &address, 0, NULL, &size, &uid);
//...
Initialize sound item, set playbackDeviceIdentifier property value.

Opened a DTS case with Apple and they said it was not possible (as i need to support 10.8). If you only need to support 10.9 and above AVPlayerAudioDeviceSupport should work.

Related

AppleScriptingBridge for Music app not returning sources

With the advent of Catalina OSX, iTunes has been removed from OSX, instead a Music app has been introduced, apparently similar but exclusively for music content with podcast etc.
Following code written in Objective C does not return any sources from the music, iTunes object.
Similar code worked for iTunes. but is not working for new Music app of apple.
Please advise, any experts.
MusicApplication* music = [SBApplication applicationWithBundleIdentifier:#"com.apple.music"];
NSArray *sources = [music sources];
// sources are empty, zero length array always
for (MusicSource *source in sources)
{
SBElementArray *userPlaylists = [source userPlaylists];
for(MusicUserPlaylist* playList in userPlaylists)
{ }
}

How to ignore changing audio-output from System Preference? (macOS)

I made my app can select audio-output. (like 'system default' or 'user's DAC')
but when user choose a output from system preferences panel - sound, my app's output follows the output user seleced.
I searched a lot and add some listener so I can change immediatly my app's output to previously user selected if system output has been changed.
BUT it makes very anonying few milliseconds swiching delay.
I guess it is because I switch my app's output after it's already changed to system default.
So I wonder If I can know BEFORE system default output's changing.
(Like viewWillAppear api from cocoa)
Thank you.
listener that I used for knowing chaninging of system default audio out is from the article below.
How to get notification if System Preferences Default Sound changed
thanks
more details
I used AudioUnitSetProperty(audioOut, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Output, 0, &deviceID, (UInt32)sizeof(deviceID)) for selecting output device. apple document
and add this listener
func addListenerBlock(listenerBlock: #escaping AudioObjectPropertyListenerBlock, onAudioObjectID: AudioObjectID, forPropertyAddress: inout AudioObjectPropertyAddress) {
if (kAudioHardwareNoError != AudioObjectAddPropertyListenerBlock(onAudioObjectID, &forPropertyAddress, nil, listenerBlock)) {
LOG("Error calling: AudioObjectAddPropertyListenerBlock") }
}
func add() {
var propertyAddress = AudioObjectPropertyAddress(mSelector: kAudioHardwarePropertyDefaultOutputDevice,
mScope: kAudioObjectPropertyScopeGlobal,
mElement: kAudioObjectPropertyElementMaster)
self.addListenerBlock(listenerBlock: audioObjectPropertyListenerBlock,
onAudioObjectID: AudioObjectID(bitPattern: kAudioObjectSystemObject),
forPropertyAddress: &propertyAddress)
}
kAudioUnitSubType_DefaultOutput tracks the current output device selected by the user in the Sound Preferences. To play to a specific device use kAudioUnitSubType_HALOutput. The comments in AUComponent.h are helpful:
#enum Apple input/output audio unit sub types (OS X)
#constant kAudioUnitSubType_HALOutput
- desktop only
The audio unit that interfaces to any audio device. The user specifies which
audio device to track. The audio unit can do input from the device as well as
output to the device. Bus 0 is used for the output side, bus 1 is used
to get audio input from the device.
#constant kAudioUnitSubType_DefaultOutput
- desktop only
A specialisation of AUHAL that is used to track the user's selection of the
default device as set in the Sound Prefs
#constant kAudioUnitSubType_SystemOutput
- desktop only
A specialisation of AUHAL that is used to track the user's selection of the
device to use for sound effects, alerts
and other UI sounds.
You didn't specify how you're setting up your output (AUGraph?) so the way to use kAudioUnitSubType_HALOutput varies.

How to detect when an Audio Device is disconnected in CoreAudio?

Is there a way to set up a listener for any Audio Device to detect if it's been removed or unplugged? I found this post which helps if you only care about built-in audio related devices:
How to get notifications when the headphones are plugged in/out? Mac
But I'm looking for a more universal solution (i.e. all devices, USB, HDMI, etc.). And it's OSX specific.
Any ideas on how to do this?
I figured it out! One just needs to add a listener to the appropriate AudioDeviceID (the device you wish to monitor):
// add listener for detecting when a device is removed
const AudioObjectPropertyAddress alive_address =
{
kAudioDevicePropertyDeviceIsAlive,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};
AudioObjectAddPropertyListener(current_device_id_, &alive_address, deviceIsAliveCallback, &player_);
And then write the corresponding callback:
OSStatus deviceIsAliveCallback(AudioObjectID inObjectID,
UInt32 inNumberAddresses,
const AudioObjectPropertyAddress inAddresses[],
void* inClientData)
{
// your code here
}
Hope this helps someone!

How to automatically pair camera and microphone in QTKit

I am programming a video capture application using QTKit. It is set up so that users must select a webcam from the list obtained with [QTCaptureDevice inputDevicesWithMediaType: QTMediaTypeVideo]. I want the user to be able to choose a camera, and have the corresponding microphone automatically selected, but I don't see a way to accomplish this within QTKit.
My application needs to run on OSX 10.6 to 10.8, so I can't use AVFoundation, which arrived in 10.7. QuickTime is deprecated at this point.
So the question is: On Mac OS 10.6 to 10.8, how can I automatically match a webcam camera with it's embedded microphone.
Thanks
The documented way of doing this is found in the QTCaptureDevice Class Reference,
using method attributeForKey with a key of QTCaptureDeviceLinkeDevicesAttribute, which may be called like so.
QTCaptureDevice* device = [QTCaptureDevice deviceWithUniqueID:deviceUniqueID];
QTCaptureDevice* sibling = Nil;
NSArray* linkedDevices = [device attributeForKey: QTCaptureDeviceLinkeDevicesAttribute
NSUInteger linkedCount = [linkedDevices count];
for (NSUInteger i = 0; i < linkedCount; i++)
{
sibling = [linkedDevicesobjectAtIndex: i];
.
.
.
}
However, I have not seen this work, the returned array is always Nil. Additionally This Apple Mailing List Archive suggests that it may only work for Apple iSight devices :(.
Finally, An additional sample may be found here: Apple QTRecorder Sample

Programmatically switch audio devices on Windows 7

On my Windows 7 PC, I've got a set of speakers, some wireless headphones and a USB web cam. This means that I have two possible audio output devices and 2 possible audio input devices.
I find myself having to switch between them fairly frequently. At the moment this is a manual process: right-click on the speaker icon, choose one of "Playback devices" or "Recording devices", choose the correct device in the list (and there's some "dead" ones in there, too) and then hit "Set Default".
I've looked around, and all I can find are people scripting SendKeys to automate this.
That sucks.
Is there anyway to programmatically switch audio input/output devices, so that I can write a simple tray app/hotkey app to make this easier?
Allegedly undocumented COM-interface IPolicyConfig (kudos to #author EreTIk) allows to do that.
This is a sample implementation.
HRESULT SetDefaultAudioPlaybackDevice(LPCWSTR devID)
{
IPolicyConfigVista *pPolicyConfig;
ERole reserved = eConsole;
HRESULT hr = CoCreateInstance(
__uuidof(CPolicyConfigVistaClient),
NULL,
CLSCTX_ALL,
__uuidof(IPolicyConfigVista),
(LPVOID *)&pPolicyConfig);
if (SUCCEEDED(hr))
{
hr = pPolicyConfig->SetDefaultEndpoint(devID, reserved);
pPolicyConfig->Release();
}
return hr;
}
A string of Device ID needs to be passed to this function. An example of a device id
{0.0.1.00000000}.{d915c7bb-d5d7-4c92-80d9-1a0ee5d954f1}
This device id can be obtained through audio device enumeration.
If you are looking into changing default devices programmatically, then this is impossible by design.
Programatically setting the default playback device (and recording device)
How to change default sound playback device programatically?

Resources