Core Audio output: Fix so it stops properly
parent
91c3feac2e
commit
557e0bd399
|
@ -60,7 +60,7 @@
|
||||||
n = [super readData:ptr amount:amount];
|
n = [super readData:ptr amount:amount];
|
||||||
amountPlayed += n;
|
amountPlayed += n;
|
||||||
|
|
||||||
if (endOfStream == YES)
|
if (endOfStream == YES && !n)
|
||||||
{
|
{
|
||||||
amountPlayed = 0;
|
amountPlayed = 0;
|
||||||
[controller endOfInputPlayed]; //Updates shouldContinue appropriately?
|
[controller endOfInputPlayed]; //Updates shouldContinue appropriately?
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#import <AssertMacros.h>
|
#import <AssertMacros.h>
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#import <dispatch/dispatch.h>
|
||||||
|
|
||||||
#import <CoreAudio/AudioHardware.h>
|
#import <CoreAudio/AudioHardware.h>
|
||||||
#import <AudioToolbox/AudioToolbox.h>
|
#import <AudioToolbox/AudioToolbox.h>
|
||||||
|
@ -19,12 +20,9 @@
|
||||||
@interface OutputCoreAudio : NSObject {
|
@interface OutputCoreAudio : NSObject {
|
||||||
OutputNode * outputController;
|
OutputNode * outputController;
|
||||||
|
|
||||||
BOOL running;
|
|
||||||
BOOL stopping;
|
BOOL stopping;
|
||||||
BOOL stopped;
|
BOOL stopped;
|
||||||
|
|
||||||
size_t outputSilenceBlocks;
|
|
||||||
|
|
||||||
BOOL listenerapplied;
|
BOOL listenerapplied;
|
||||||
|
|
||||||
float volume;
|
float volume;
|
||||||
|
@ -34,6 +32,8 @@
|
||||||
|
|
||||||
AUAudioUnit *_au;
|
AUAudioUnit *_au;
|
||||||
size_t _bufferSize;
|
size_t _bufferSize;
|
||||||
|
|
||||||
|
dispatch_semaphore_t sem;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithController:(OutputNode *)c;
|
- (id)initWithController:(OutputNode *)c;
|
||||||
|
|
|
@ -26,7 +26,6 @@ extern void scale_by_volume(float * buffer, size_t count, float volume);
|
||||||
volume = 1.0;
|
volume = 1.0;
|
||||||
outputDeviceID = -1;
|
outputDeviceID = -1;
|
||||||
listenerapplied = NO;
|
listenerapplied = NO;
|
||||||
outputSilenceBlocks = 0;
|
|
||||||
|
|
||||||
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.outputDevice" options:0 context:NULL];
|
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.outputDevice" options:0 context:NULL];
|
||||||
}
|
}
|
||||||
|
@ -51,6 +50,13 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)threadEntry:(id)arg
|
||||||
|
{
|
||||||
|
while (!stopping) {
|
||||||
|
dispatch_semaphore_wait(sem, 500 * USEC_PER_SEC);
|
||||||
|
}
|
||||||
|
[self stop];
|
||||||
|
}
|
||||||
|
|
||||||
- (OSStatus)setOutputDeviceByID:(AudioDeviceID)deviceID
|
- (OSStatus)setOutputDeviceByID:(AudioDeviceID)deviceID
|
||||||
{
|
{
|
||||||
|
@ -224,9 +230,7 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
|
||||||
[self stop];
|
[self stop];
|
||||||
|
|
||||||
stopping = NO;
|
stopping = NO;
|
||||||
stopped = NO;
|
|
||||||
outputDeviceID = -1;
|
outputDeviceID = -1;
|
||||||
outputSilenceBlocks = 0;
|
|
||||||
|
|
||||||
AVAudioFormat *format, *renderFormat;
|
AVAudioFormat *format, *renderFormat;
|
||||||
AudioComponentDescription desc;
|
AudioComponentDescription desc;
|
||||||
|
@ -320,21 +324,12 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
|
||||||
|
|
||||||
amountToRead = framesToRead * (self->deviceFormat.mBytesPerPacket);
|
amountToRead = framesToRead * (self->deviceFormat.mBytesPerPacket);
|
||||||
|
|
||||||
if (self->outputSilenceBlocks || self->stopping == YES)
|
if (self->stopping == YES || [self->outputController shouldContinue] == NO)
|
||||||
{
|
{
|
||||||
memset(readPointer, 0, amountToRead);
|
memset(readPointer, 0, amountToRead);
|
||||||
inputData->mBuffers[0].mDataByteSize = amountToRead;
|
inputData->mBuffers[0].mDataByteSize = amountToRead;
|
||||||
if (self->outputSilenceBlocks &&
|
self->stopping = YES;
|
||||||
--self->outputSilenceBlocks == 0)
|
dispatch_semaphore_signal(weakSelf->sem);
|
||||||
[weakSelf stop];
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ([self->outputController shouldContinue] == NO)
|
|
||||||
{
|
|
||||||
memset(readPointer, 0, amountToRead);
|
|
||||||
inputData->mBuffers[0].mDataByteSize = amountToRead;
|
|
||||||
self->outputSilenceBlocks = 48;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,6 +361,9 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
|
||||||
|
|
||||||
[_au allocateRenderResourcesAndReturnError:&err];
|
[_au allocateRenderResourcesAndReturnError:&err];
|
||||||
|
|
||||||
|
sem = dispatch_semaphore_create(0);
|
||||||
|
[NSThread detachNewThreadSelector:@selector(threadEntry:) toTarget:self withObject:nil];
|
||||||
|
|
||||||
[outputController setFormat:&deviceFormat];
|
[outputController setFormat:&deviceFormat];
|
||||||
|
|
||||||
return (err == nil);
|
return (err == nil);
|
||||||
|
@ -380,12 +378,10 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
|
||||||
{
|
{
|
||||||
NSError *err;
|
NSError *err;
|
||||||
[_au startHardwareAndReturnError:&err];
|
[_au startHardwareAndReturnError:&err];
|
||||||
running = YES;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)stop
|
- (void)stop
|
||||||
{
|
{
|
||||||
stopping = YES;
|
|
||||||
if (listenerapplied) {
|
if (listenerapplied) {
|
||||||
AudioObjectPropertyAddress theAddress = {
|
AudioObjectPropertyAddress theAddress = {
|
||||||
.mSelector = kAudioHardwarePropertyDefaultOutputDevice,
|
.mSelector = kAudioHardwarePropertyDefaultOutputDevice,
|
||||||
|
@ -397,8 +393,9 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
|
||||||
}
|
}
|
||||||
if (_au) {
|
if (_au) {
|
||||||
[_au stopHardware];
|
[_au stopHardware];
|
||||||
running = NO;
|
|
||||||
_au = nil;
|
_au = nil;
|
||||||
|
stopping = YES;
|
||||||
|
dispatch_semaphore_signal(sem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,14 +409,12 @@ default_device_changed(AudioObjectID inObjectID, UInt32 inNumberAddresses, const
|
||||||
- (void)pause
|
- (void)pause
|
||||||
{
|
{
|
||||||
[_au stopHardware];
|
[_au stopHardware];
|
||||||
running = NO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)resume
|
- (void)resume
|
||||||
{
|
{
|
||||||
NSError *err;
|
NSError *err;
|
||||||
[_au startHardwareAndReturnError:&err];
|
[_au startHardwareAndReturnError:&err];
|
||||||
running = YES;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
Loading…
Reference in New Issue