Core Audio output: Properly support switching output devices
parent
642945e80a
commit
d2e480ace5
|
@ -18,7 +18,10 @@
|
||||||
@interface OutputCoreAudio : NSObject {
|
@interface OutputCoreAudio : NSObject {
|
||||||
OutputNode * outputController;
|
OutputNode * outputController;
|
||||||
|
|
||||||
|
BOOL primed;
|
||||||
|
BOOL running;
|
||||||
BOOL stopping;
|
BOOL stopping;
|
||||||
|
BOOL stopped;
|
||||||
|
|
||||||
float volume;
|
float volume;
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
|
|
||||||
#import "Logging.h"
|
#import "Logging.h"
|
||||||
|
|
||||||
|
@interface OutputCoreAudio (Private)
|
||||||
|
- (void)prime;
|
||||||
|
@end
|
||||||
|
|
||||||
@implementation OutputCoreAudio
|
@implementation OutputCoreAudio
|
||||||
|
|
||||||
- (id)initWithController:(OutputNode *)c
|
- (id)initWithController:(OutputNode *)c
|
||||||
|
@ -44,6 +48,7 @@ static void Sound_Renderer(void *userData, AudioQueueRef queue, AudioQueueBuffer
|
||||||
|
|
||||||
if (output->stopping == YES)
|
if (output->stopping == YES)
|
||||||
{
|
{
|
||||||
|
output->stopped = YES;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +132,15 @@ static void Sound_Renderer(void *userData, AudioQueueRef queue, AudioQueueBuffer
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = AudioQueueStop(audioQueue, true);
|
||||||
|
if (err) {
|
||||||
|
DLog(@"Error stopping stream to set device");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
primed = NO;
|
||||||
err = AudioQueueSetProperty(audioQueue, kAudioQueueProperty_CurrentDevice, &theDeviceUID, sizeof(theDeviceUID));
|
err = AudioQueueSetProperty(audioQueue, kAudioQueueProperty_CurrentDevice, &theDeviceUID, sizeof(theDeviceUID));
|
||||||
|
if (running)
|
||||||
|
[self start];
|
||||||
}
|
}
|
||||||
else if (outputUnit) {
|
else if (outputUnit) {
|
||||||
err = AudioUnitSetProperty(outputUnit,
|
err = AudioUnitSetProperty(outputUnit,
|
||||||
|
@ -258,6 +271,7 @@ static void Sound_Renderer(void *userData, AudioQueueRef queue, AudioQueueBuffer
|
||||||
[self stop];
|
[self stop];
|
||||||
|
|
||||||
stopping = NO;
|
stopping = NO;
|
||||||
|
stopped = NO;
|
||||||
|
|
||||||
AudioComponentDescription desc;
|
AudioComponentDescription desc;
|
||||||
OSStatus err;
|
OSStatus err;
|
||||||
|
@ -332,6 +346,19 @@ static void Sound_Renderer(void *userData, AudioQueueRef queue, AudioQueueBuffer
|
||||||
if (err != noErr)
|
if (err != noErr)
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
|
if (device) {
|
||||||
|
BOOL ok = [self setOutputDeviceWithDeviceDict:device];
|
||||||
|
if (!ok) {
|
||||||
|
//Ruh roh.
|
||||||
|
[self setOutputDeviceWithDeviceDict:nil];
|
||||||
|
|
||||||
|
[[[NSUserDefaultsController sharedUserDefaultsController] defaults] removeObjectForKey:@"outputDevice"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
[self setOutputDeviceWithDeviceDict:nil];
|
||||||
|
}
|
||||||
|
|
||||||
numberOfBuffers = 4;
|
numberOfBuffers = 4;
|
||||||
bufferByteSize = deviceFormat.mBytesPerPacket * 512;
|
bufferByteSize = deviceFormat.mBytesPerPacket * 512;
|
||||||
|
|
||||||
|
@ -355,15 +382,22 @@ static void Sound_Renderer(void *userData, AudioQueueRef queue, AudioQueueBuffer
|
||||||
}
|
}
|
||||||
|
|
||||||
buffers[i]->mAudioDataByteSize = bufferByteSize;
|
buffers[i]->mAudioDataByteSize = bufferByteSize;
|
||||||
|
|
||||||
Sound_Renderer((__bridge void * _Nullable)(self), audioQueue, buffers[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[self prime];
|
||||||
|
|
||||||
[outputController setFormat:&deviceFormat];
|
[outputController setFormat:&deviceFormat];
|
||||||
|
|
||||||
return (err == noErr);
|
return (err == noErr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)prime
|
||||||
|
{
|
||||||
|
for (UInt32 i = 0; i < numberOfBuffers; ++i)
|
||||||
|
Sound_Renderer((__bridge void * _Nullable)(self), audioQueue, buffers[i]);
|
||||||
|
primed = YES;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setVolume:(double)v
|
- (void)setVolume:(double)v
|
||||||
{
|
{
|
||||||
volume = v * 0.01f;
|
volume = v * 0.01f;
|
||||||
|
@ -376,6 +410,9 @@ static void Sound_Renderer(void *userData, AudioQueueRef queue, AudioQueueBuffer
|
||||||
AudioQueueSetParameter(audioQueue, kAudioQueueParam_VolumeRampTime, 0);
|
AudioQueueSetParameter(audioQueue, kAudioQueueParam_VolumeRampTime, 0);
|
||||||
AudioQueueSetParameter(audioQueue, kAudioQueueParam_Volume, volume);
|
AudioQueueSetParameter(audioQueue, kAudioQueueParam_Volume, volume);
|
||||||
AudioQueueStart(audioQueue, NULL);
|
AudioQueueStart(audioQueue, NULL);
|
||||||
|
running = YES;
|
||||||
|
if (!primed)
|
||||||
|
[self prime];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)stop
|
- (void)stop
|
||||||
|
@ -391,6 +428,7 @@ static void Sound_Renderer(void *userData, AudioQueueRef queue, AudioQueueBuffer
|
||||||
{
|
{
|
||||||
AudioQueuePause(audioQueue);
|
AudioQueuePause(audioQueue);
|
||||||
AudioQueueStop(audioQueue, true);
|
AudioQueueStop(audioQueue, true);
|
||||||
|
running = NO;
|
||||||
|
|
||||||
for (UInt32 i = 0; i < numberOfBuffers; ++i)
|
for (UInt32 i = 0; i < numberOfBuffers; ++i)
|
||||||
{
|
{
|
||||||
|
@ -418,11 +456,15 @@ static void Sound_Renderer(void *userData, AudioQueueRef queue, AudioQueueBuffer
|
||||||
- (void)pause
|
- (void)pause
|
||||||
{
|
{
|
||||||
AudioQueuePause(audioQueue);
|
AudioQueuePause(audioQueue);
|
||||||
|
running = NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)resume
|
- (void)resume
|
||||||
{
|
{
|
||||||
AudioQueueStart(audioQueue, NULL);
|
AudioQueueStart(audioQueue, NULL);
|
||||||
|
running = YES;
|
||||||
|
if (!primed)
|
||||||
|
[self prime];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
Loading…
Reference in New Issue