Cocoa Port:

- Fix some UI bugs with mic level checks where the mic status icon wasn't showing the correct color under certain conditions.
- Fix UI bug where the mic mute control wasn't being respected under certain conditions.
- The mic status icon now includes a tooltip that reports the name and sample rate of the current input device.
- Handle mic hardware state changes more gracefully when the input device is changed externally.
This commit is contained in:
rogerman 2015-03-09 21:49:22 +00:00
parent 381324ca09
commit d0ec648952
10 changed files with 433 additions and 735 deletions

View File

@ -23,6 +23,7 @@
#import "cocoa_util.h"
@class CocoaDSCore;
@class CocoaDSController;
@class CocoaDSFirmware;
@class CocoaDSGPU;
@ -32,8 +33,7 @@ typedef void *gdbstub_handle_t;
typedef struct
{
void *cdsCore;
void *cdsController;
CocoaDSCore *cdsCore;
int state;
bool isFrameSkipEnabled;
size_t frameCount;

View File

@ -178,7 +178,6 @@ volatile bool execute = true;
_slot1R4Path = "";
threadParam.cdsCore = self;
threadParam.cdsController = cdsController;
threadParam.state = CORESTATE_PAUSE;
threadParam.isFrameSkipEnabled = true;
threadParam.frameCount = 0;
@ -289,7 +288,6 @@ volatile bool execute = true;
pthread_mutex_lock(&threadParam.mutexThreadExecute);
[cdsController release];
cdsController = theController;
threadParam.cdsController = theController;
pthread_mutex_unlock(&threadParam.mutexThreadExecute);
OSSpinLockUnlock(&spinlockCdsController);
@ -1093,13 +1091,14 @@ static void* RunCoreThread(void *arg)
timeBudget = param->timeBudgetMachAbsTime;
}
CocoaDSController *cdsController = [cdsCore cdsController];
if (param->state != CORESTATE_FRAMEJUMP)
{
[(CocoaDSController *)param->cdsController flush];
[cdsController flush];
}
else
{
[(CocoaDSController *)param->cdsController flushEmpty];
[cdsController flushEmpty];
}
NDS_beginProcessingInput();
@ -1127,6 +1126,18 @@ static void* RunCoreThread(void *arg)
param->frameCount++;
}
// Make sure that the mic level is updated at least once per frame, regardless
// of whether the NDS actually reads the mic or not.
if (![cdsController isHardwareMicReadThisFrame])
{
[cdsController updateHardwareMicLevelWithSample:MIC_NULL_SAMPLE_VALUE];
[[cdsController delegate] doMicSamplesReadFromController:cdsController inSample:MIC_NULL_SAMPLE_VALUE];
}
else
{
[cdsController setIsHardwareMicReadThisFrame:NO];
}
pthread_mutex_lock(&param->mutexOutputList);
switch (param->state)

View File

@ -249,9 +249,9 @@
#define MIC_SAMPLE_SIZE ((MIC_SAMPLE_RESOLUTION / 8) * MIC_NUMBER_CHANNELS) // Bytes per sample, multiplied by the number of channels
#define MIC_MAX_BUFFER_SAMPLES ((MIC_SAMPLE_RATE / DS_FRAMES_PER_SECOND) * MIC_SAMPLE_SIZE)
#define MIC_CAPTURE_FRAMES 192 // The number of audio frames that the NDS microphone should pull. The lower this value, the lower the latency. Ensure that this value is not too low, or else audio frames may be lost.
#define MIC_CLIP_FRAME_THRESHOLD 15 // When the number of clipped mic samples exceeds this amount, the UI will reflect that the mic is clipping.
#define MIC_CLIP_FRAME_THRESHOLD 15 // When the number of clipped mic samples reaches this amount, the UI will reflect that the mic is clipping.
#define MIC_CLIP_FRAME_MAX_COUNT 60 // When counting clipped mic samples, don't count past this number. This is to prevent the mic clip state from persisting too long after the mic has stopped clipping.
#define MIC_NULL_FRAME_THRESHOLD 12 // When the number of null mic samples exceeds this amount, the UI will reflect that the mic is null.
#define MIC_NULL_FRAME_THRESHOLD 12 // When the number of null mic samples reaches this amount, the UI will reflect that the mic is null.
#define MIC_NULL_FRAME_MAX_COUNT 24 // When counting null mic samples, don't count past this number. This is to prevent the mic null state from persisting too long after the mic has read some samples.
#define MIC_NULL_SAMPLE_VALUE 64

View File

@ -21,6 +21,7 @@
@class CocoaDSController;
class CoreAudioInput;
struct CoreAudioInputDeviceInfo;
class AudioGenerator;
class AudioSampleBlockGenerator;
@ -80,6 +81,11 @@ typedef struct
- (uint8_t) doMicSamplesReadFromController:(CocoaDSController *)cdsController inSample:(uint8_t)sampleValue;
@optional
- (void) doMicHardwareStateChangedFromController:(CocoaDSController *)cdsController
isEnabled:(BOOL)isHardwareEnabled
isLocked:(BOOL)isHardwareLocked
isMuted:(BOOL)isHardwareMuted;
- (void) doMicHardwareGainChangedFromController:(CocoaDSController *)cdsController gain:(float)gainValue;
@end
@ -87,10 +93,13 @@ typedef struct
@interface CocoaDSController : NSObject
{
id <CocoaDSControllerDelegate> delegate;
BOOL isHardwareMicReadThisFrame;
BOOL autohold;
BOOL isAutoholdCleared;
BOOL _useHardwareMic;
size_t _availableMicSamples;
uint32_t _hwMicNumberIdleFrames;
uint32_t _hwMicNumberClippedFrames;
NSInteger micMode;
NSPoint touchLocation;
@ -99,6 +108,7 @@ typedef struct
CoreAudioInput *CAInputDevice;
AudioGenerator *softwareMicSampleGenerator;
NSInteger paddleAdjust;
NSString *hardwareMicInfoString;
OSSpinLock spinlockControllerState;
}
@ -106,6 +116,9 @@ typedef struct
@property (retain) id <CocoaDSControllerDelegate> delegate;
@property (assign) BOOL autohold;
@property (readonly) BOOL isHardwareMicAvailable;
@property (assign) BOOL isHardwareMicIdle;
@property (assign) BOOL isHardwareMicInClip;
@property (assign) BOOL isHardwareMicReadThisFrame;
@property (assign) BOOL hardwareMicEnabled;
@property (readonly) BOOL hardwareMicLocked;
@property (assign) float hardwareMicGain;
@ -118,6 +131,7 @@ typedef struct
@property (readonly) AudioGenerator *softwareMicSampleGenerator;
@property (assign) AudioSampleBlockGenerator *selectedAudioFileGenerator;
@property (assign) NSInteger paddleAdjust;
@property (retain) NSString *hardwareMicInfoString;
- (void) setControllerState:(BOOL)theState controlID:(const NSUInteger)controlID;
- (void) setControllerState:(BOOL)theState controlID:(const NSUInteger)controlID turbo:(const BOOL)isTurboEnabled;
@ -126,7 +140,12 @@ typedef struct
- (void) clearAutohold;
- (void) flush;
- (void) flushEmpty;
- (void) updateHardwareMicLevelWithSample:(uint8_t)inSample;
- (uint8_t) handleMicSampleRead:(CoreAudioInput *)caInput softwareMic:(AudioGenerator *)sampleGenerator;
- (void) handleMicHardwareStateChanged:(CoreAudioInputDeviceInfo *)deviceInfo
isEnabled:(BOOL)isHardwareEnabled
isLocked:(BOOL)isHardwareLocked
isMuted:(BOOL)isHardwareMuted;
- (void) handleMicHardwareGainChanged:(float)gainValue;
@end
@ -138,6 +157,12 @@ extern "C"
void CAResetCallback(void *inParam1, void *inParam2);
uint8_t CASampleReadCallback(void *inParam1, void *inParam2);
void CAHardwareStateChangedCallback(CoreAudioInputDeviceInfo *deviceInfo,
const bool isHardwareEnabled,
const bool isHardwareLocked,
const bool isHardwareMuted,
void *inParam1,
void *inParam2);
void CAHardwareGainChangedCallback(float normalizedGain, void *inParam1, void *inParam2);
#ifdef __cplusplus

View File

@ -36,6 +36,9 @@ SineWaveGenerator sineWaveGenerator(250.0, MIC_SAMPLE_RATE);
@synthesize delegate;
@dynamic isHardwareMicAvailable;
@dynamic isHardwareMicIdle;
@dynamic isHardwareMicInClip;
@synthesize isHardwareMicReadThisFrame;
@dynamic hardwareMicEnabled;
@dynamic hardwareMicLocked;
@dynamic hardwareMicGain;
@ -49,6 +52,7 @@ SineWaveGenerator sineWaveGenerator(250.0, MIC_SAMPLE_RATE);
@synthesize softwareMicSampleGenerator;
@synthesize selectedAudioFileGenerator;
@synthesize paddleAdjust;
@synthesize hardwareMicInfoString;
- (id)init
{
@ -70,16 +74,21 @@ SineWaveGenerator sineWaveGenerator(250.0, MIC_SAMPLE_RATE);
spinlockControllerState = OS_SPINLOCK_INIT;
autohold = NO;
isAutoholdCleared = YES;
isHardwareMicReadThisFrame = NO;
_useHardwareMic = NO;
_availableMicSamples = 0;
_hwMicNumberIdleFrames = MIC_NULL_FRAME_THRESHOLD;
_hwMicNumberClippedFrames = 0;
micMode = MICMODE_NONE;
selectedAudioFileGenerator = NULL;
CAInputDevice = new CoreAudioInput;
CAInputDevice->SetCallbackHardwareStateChanged(&CAHardwareStateChangedCallback, self, NULL);
CAInputDevice->SetCallbackHardwareGainChanged(&CAHardwareGainChangedCallback, self, NULL);
softwareMicSampleGenerator = &nullSampleGenerator;
touchLocation = NSMakePoint(0.0f, 0.0f);
paddleAdjust = 0;
hardwareMicInfoString = @"No hardware input detected.";
Mic_SetResetCallback(&CAResetCallback, self, NULL);
Mic_SetSampleReadCallback(&CASampleReadCallback, self, NULL);
@ -100,6 +109,42 @@ SineWaveGenerator sineWaveGenerator(250.0, MIC_SAMPLE_RATE);
!CAInputDevice->GetPauseState() ) ? YES : NO;
}
- (void) setIsHardwareMicIdle:(BOOL)theState
{
if (theState)
{
_hwMicNumberIdleFrames = MIC_NULL_FRAME_THRESHOLD;
_hwMicNumberClippedFrames = 0;
}
else
{
_hwMicNumberIdleFrames = 0;
}
}
- (BOOL) isHardwareMicIdle
{
return (_hwMicNumberIdleFrames >= MIC_NULL_FRAME_THRESHOLD);
}
- (void) setIsHardwareMicInClip:(BOOL)theState
{
if (theState)
{
_hwMicNumberIdleFrames = 0;
_hwMicNumberClippedFrames = MIC_CLIP_FRAME_THRESHOLD;
}
else
{
_hwMicNumberClippedFrames = 0;
}
}
- (BOOL) isHardwareMicInClip
{
return (_hwMicNumberClippedFrames >= MIC_CLIP_FRAME_THRESHOLD);
}
- (void) setHardwareMicEnabled:(BOOL)micEnabled
{
if (micEnabled)
@ -140,20 +185,18 @@ SineWaveGenerator sineWaveGenerator(250.0, MIC_SAMPLE_RATE);
- (BOOL) hardwareMicMute
{
BOOL isMicMuted = (CAInputDevice->GetMuteState()) ? YES : NO;
return isMicMuted;
return (CAInputDevice->GetMuteState()) ? YES : NO;
}
- (void) setHardwareMicPause:(BOOL)isMicPaused
{
bool pauseState = (isMicPaused) ? true : false;
CAInputDevice->SetMuteState(pauseState);
CAInputDevice->SetPauseState(pauseState);
}
- (BOOL) hardwareMicPause
{
BOOL isMicPaused = (CAInputDevice->GetPauseState()) ? YES : NO;
return isMicPaused;
return (CAInputDevice->GetPauseState()) ? YES : NO;
}
- (void) setSoftwareMicState:(BOOL)theState
@ -483,6 +526,45 @@ SineWaveGenerator sineWaveGenerator(250.0, MIC_SAMPLE_RATE);
NDS_setMic(false);
}
- (void) updateHardwareMicLevelWithSample:(uint8_t)inSample
{
switch (inSample)
{
case MIC_NULL_SAMPLE_VALUE:
{
if (_hwMicNumberIdleFrames < MIC_NULL_FRAME_MAX_COUNT)
{
_hwMicNumberIdleFrames++;
}
break;
}
case 0:
case 127:
{
if (_hwMicNumberClippedFrames < MIC_CLIP_FRAME_MAX_COUNT)
{
_hwMicNumberClippedFrames++;
}
break;
}
default:
{
if (_hwMicNumberIdleFrames > 0)
{
_hwMicNumberIdleFrames--;
}
if (_hwMicNumberClippedFrames > 0)
{
_hwMicNumberClippedFrames--;
}
break;
}
}
}
- (uint8_t) handleMicSampleRead:(CoreAudioInput *)caInput softwareMic:(AudioGenerator *)sampleGenerator
{
uint8_t theSample = MIC_NULL_SAMPLE_VALUE;
@ -503,6 +585,9 @@ SineWaveGenerator sineWaveGenerator(250.0, MIC_SAMPLE_RATE);
caInput->_samplesConverted->read(&theSample, 1);
theSample >>= 1; // Samples from CoreAudio are 8-bit, so we need to convert the sample to 7-bit
_availableMicSamples--;
[self updateHardwareMicLevelWithSample:theSample];
[self setIsHardwareMicReadThisFrame:YES];
}
}
else
@ -513,14 +598,42 @@ SineWaveGenerator sineWaveGenerator(250.0, MIC_SAMPLE_RATE);
return [[self delegate] doMicSamplesReadFromController:self inSample:theSample];
}
- (void) handleMicHardwareGainChanged:(float)gainValue
- (void) handleMicHardwareStateChanged:(CoreAudioInputDeviceInfo *)deviceInfo
isEnabled:(BOOL)isHardwareEnabled
isLocked:(BOOL)isHardwareLocked
isMuted:(BOOL)isHardwareMuted
{
if (delegate == nil || ![delegate respondsToSelector:@selector(doMicHardwareGainChangedFromController:gain:)])
NSString *newHWMicInfoString;
if (deviceInfo->objectID == kAudioObjectUnknown)
{
return;
newHWMicInfoString = @"No hardware input detected.";
}
else
{
newHWMicInfoString = [NSString stringWithFormat:@"%@\nSample Rate: %1.1f Hz",
(NSString *)deviceInfo->name,
(double)deviceInfo->sampleRate];
}
[[self delegate] doMicHardwareGainChangedFromController:self gain:gainValue];
[self setHardwareMicInfoString:newHWMicInfoString];
[self setIsHardwareMicIdle:YES];
[self setIsHardwareMicInClip:NO];
if (delegate != nil && [delegate respondsToSelector:@selector(doMicHardwareStateChangedFromController:isEnabled:isLocked:isMuted:)])
{
[[self delegate] doMicHardwareStateChangedFromController:self
isEnabled:isHardwareEnabled
isLocked:isHardwareLocked
isMuted:isHardwareMuted];
}
}
- (void) handleMicHardwareGainChanged:(float)gainValue
{
if (delegate != nil && [delegate respondsToSelector:@selector(doMicHardwareGainChangedFromController:gain:)])
{
[[self delegate] doMicHardwareGainChangedFromController:self gain:gainValue];
}
}
@end
@ -537,6 +650,20 @@ uint8_t CASampleReadCallback(void *inParam1, void *inParam2)
return [cdsController handleMicSampleRead:[cdsController CAInputDevice] softwareMic:[cdsController softwareMicSampleGenerator]];
}
void CAHardwareStateChangedCallback(CoreAudioInputDeviceInfo *deviceInfo,
const bool isHardwareEnabled,
const bool isHardwareLocked,
const bool isHardwareMuted,
void *inParam1,
void *inParam2)
{
CocoaDSController *cdsController = (CocoaDSController *)inParam1;
[cdsController handleMicHardwareStateChanged:(CoreAudioInputDeviceInfo *)deviceInfo
isEnabled:((isHardwareEnabled) ? YES : NO)
isLocked:((isHardwareLocked) ? YES : NO)
isMuted:((isHardwareMuted) ? YES : NO)];
}
void CAHardwareGainChangedCallback(float normalizedGain, void *inParam1, void *inParam2)
{
CocoaDSController *cdsController = (CocoaDSController *)inParam1;

View File

@ -29,6 +29,10 @@ CoreAudioInput::CoreAudioInput()
_spinlockAUHAL = (OSSpinLock *)malloc(sizeof(OSSpinLock));
*_spinlockAUHAL = OS_SPINLOCK_INIT;
_hwStateChangedCallbackFunc = &CoreAudioInputDefaultHardwareStateChangedCallback;
_hwStateChangedCallbackParam1 = NULL;
_hwStateChangedCallbackParam2 = NULL;
_hwGainChangedCallbackFunc = &CoreAudioInputDefaultHardwareGainChangedCallback;
_hwGainChangedCallbackParam1 = NULL;
_hwGainChangedCallbackParam2 = NULL;
@ -37,6 +41,12 @@ CoreAudioInput::CoreAudioInput()
_inputElement = 0;
_isMuted = false;
_hwDeviceInfo.objectID = kAudioObjectUnknown;
_hwDeviceInfo.name = CFSTR("Unknown Device");
_hwDeviceInfo.manufacturer = CFSTR("Unknown Manufacturer");
_hwDeviceInfo.deviceUID = CFSTR("");
_hwDeviceInfo.modelUID = CFSTR("");
_hwDeviceInfo.sampleRate = 0.0;
_isPaused = false;
_isHardwareEnabled = false;
_isHardwareLocked = true;
@ -269,6 +279,11 @@ CoreAudioInput::~CoreAudioInput()
free(_spinlockAUHAL);
_spinlockAUHAL = NULL;
CFRelease(this->_hwDeviceInfo.name);
CFRelease(this->_hwDeviceInfo.manufacturer);
CFRelease(this->_hwDeviceInfo.deviceUID);
CFRelease(this->_hwDeviceInfo.modelUID);
}
OSStatus CoreAudioInput::InitInputAUHAL(UInt32 deviceID)
@ -277,6 +292,7 @@ OSStatus CoreAudioInput::InitInputAUHAL(UInt32 deviceID)
static const AudioUnitScope inputBus = 1;
UInt32 propertySize = 0;
this->_hwDeviceInfo.objectID = kAudioObjectUnknown;
if (deviceID == kAudioObjectUnknown)
{
error = kAudioHardwareUnspecifiedError;
@ -286,47 +302,47 @@ OSStatus CoreAudioInput::InitInputAUHAL(UInt32 deviceID)
// Get some information about the device before attempting to attach it to the AUHAL.
// Currently, this information is only available in debug mode. However, if there is
// a need to actually do something with this information, then we've already got it.
CFStringRef devicePropertyString;
AudioObjectPropertyAddress deviceProperty;
UInt32 dataSize = 0;
deviceProperty.mScope = kAudioObjectPropertyScopeGlobal;
deviceProperty.mElement = kAudioObjectPropertyElementMaster;
printf("\nInput Device Information:\n");
printf(" Object ID: %d\n", deviceID);
deviceProperty.mSelector = kAudioObjectPropertyName;
error = AudioObjectGetPropertyDataSize(deviceID, &deviceProperty, 0, NULL, &dataSize);
if (error == noErr)
{
error = AudioObjectGetPropertyData(deviceID, &deviceProperty, 0, NULL, &dataSize, &devicePropertyString);
printf(" Name: %s\n", CFStringGetCStringPtr(devicePropertyString, kCFStringEncodingUTF8));
CFRelease(devicePropertyString);
CFRelease(this->_hwDeviceInfo.name);
error = AudioObjectGetPropertyData(deviceID, &deviceProperty, 0, NULL, &dataSize, &this->_hwDeviceInfo.name);
printf(" Name: %s\n", CFStringGetCStringPtr(this->_hwDeviceInfo.name, kCFStringEncodingUTF8));
}
deviceProperty.mSelector = kAudioObjectPropertyManufacturer;
error = AudioObjectGetPropertyDataSize(deviceID, &deviceProperty, 0, NULL, &dataSize);
if (error == noErr)
{
error = AudioObjectGetPropertyData(deviceID, &deviceProperty, 0, NULL, &dataSize, &devicePropertyString);
printf(" Manufacturer: %s\n", CFStringGetCStringPtr(devicePropertyString, kCFStringEncodingUTF8));
CFRelease(devicePropertyString);
CFRelease(this->_hwDeviceInfo.manufacturer);
error = AudioObjectGetPropertyData(deviceID, &deviceProperty, 0, NULL, &dataSize, &this->_hwDeviceInfo.manufacturer);
printf(" Manufacturer: %s\n", CFStringGetCStringPtr(this->_hwDeviceInfo.manufacturer, kCFStringEncodingUTF8));
}
deviceProperty.mSelector = kAudioDevicePropertyDeviceUID;
error = AudioObjectGetPropertyDataSize(deviceID, &deviceProperty, 0, NULL, &dataSize);
if (error == noErr)
{
error = AudioObjectGetPropertyData(deviceID, &deviceProperty, 0, NULL, &dataSize, &devicePropertyString);
printf(" Device UID: %s\n", CFStringGetCStringPtr(devicePropertyString, kCFStringEncodingUTF8));
CFRelease(devicePropertyString);
CFRelease(this->_hwDeviceInfo.deviceUID);
error = AudioObjectGetPropertyData(deviceID, &deviceProperty, 0, NULL, &dataSize, &this->_hwDeviceInfo.deviceUID);
printf(" Device UID: %s\n", CFStringGetCStringPtr(this->_hwDeviceInfo.deviceUID, kCFStringEncodingUTF8));
}
deviceProperty.mSelector = kAudioDevicePropertyModelUID;
error = AudioObjectGetPropertyDataSize(deviceID, &deviceProperty, 0, NULL, &dataSize);
if (error == noErr)
{
error = AudioObjectGetPropertyData(deviceID, &deviceProperty, 0, NULL, &dataSize, &devicePropertyString);
printf(" Model UID: %s\n", CFStringGetCStringPtr(devicePropertyString, kCFStringEncodingUTF8));
CFRelease(devicePropertyString);
CFRelease(this->_hwDeviceInfo.modelUID);
error = AudioObjectGetPropertyData(deviceID, &deviceProperty, 0, NULL, &dataSize, &this->_hwDeviceInfo.modelUID);
printf(" Model UID: %s\n", CFStringGetCStringPtr(this->_hwDeviceInfo.modelUID, kCFStringEncodingUTF8));
}
deviceProperty.mSelector = kAudioDevicePropertyNominalSampleRate;
@ -334,9 +350,8 @@ OSStatus CoreAudioInput::InitInputAUHAL(UInt32 deviceID)
error = AudioObjectGetPropertyDataSize(deviceID, &deviceProperty, 0, NULL, &dataSize);
if (error == noErr)
{
Float64 deviceSampleRate = 0.0;
error = AudioObjectGetPropertyData(deviceID, &deviceProperty, 0, NULL, &dataSize, &deviceSampleRate);
printf(" Sample Rate: %1.1f\n\n", deviceSampleRate);
error = AudioObjectGetPropertyData(deviceID, &deviceProperty, 0, NULL, &dataSize, &this->_hwDeviceInfo.sampleRate);
printf(" Sample Rate: %1.1f\n\n", this->_hwDeviceInfo.sampleRate);
}
// Before attaching the HAL input device, stop everything first.
@ -444,6 +459,8 @@ OSStatus CoreAudioInput::InitInputAUHAL(UInt32 deviceID)
return error;
}
this->_hwDeviceInfo.objectID = deviceID;
return error;
}
@ -489,8 +506,7 @@ void CoreAudioInput::Start()
if (error == noErr)
{
this->_inputElement = elementNumber;
this->SetGain_ValueOnly(theGain);
this->RunHardwareGainChangedCallback(theGain);
this->UpdateHardwareGain(theGain);
break;
}
}
@ -505,7 +521,7 @@ void CoreAudioInput::Start()
this->_isHardwareEnabled = false;
}
if (this->_isHardwareEnabled && !this->IsHardwareLocked() && !this->_isPaused)
if (this->IsHardwareEnabled() && !this->IsHardwareLocked() && !this->GetPauseState())
{
error = AudioOutputUnitStart(this->_auHALInputDevice);
}
@ -513,13 +529,19 @@ void CoreAudioInput::Start()
OSSpinLockUnlock(this->_spinlockAUHAL);
error = AUGraphInitialize(_auGraph);
if (!this->_isPaused)
if (!this->GetPauseState())
{
error = AUGraphStart(this->_auGraph);
}
this->_samplesCaptured->clear();
this->_samplesConverted->clear();
this->_hwStateChangedCallbackFunc(&this->_hwDeviceInfo,
this->IsHardwareEnabled(),
this->IsHardwareLocked(),
this->_isMuted,
this->_hwStateChangedCallbackParam1,
this->_hwStateChangedCallbackParam2);
}
void CoreAudioInput::Stop()
@ -569,8 +591,14 @@ bool CoreAudioInput::GetMuteState() const
void CoreAudioInput::SetMuteState(bool muteState)
{
this->SetPauseState(muteState);
this->_isMuted = muteState;
this->SetPauseState(muteState);
this->_hwStateChangedCallbackFunc(&this->_hwDeviceInfo,
this->IsHardwareEnabled(),
this->IsHardwareLocked(),
this->_isMuted,
this->_hwStateChangedCallbackParam1,
this->_hwStateChangedCallbackParam2);
}
bool CoreAudioInput::GetPauseState() const
@ -580,14 +608,14 @@ bool CoreAudioInput::GetPauseState() const
void CoreAudioInput::SetPauseState(bool pauseState)
{
if (pauseState && !this->_isPaused)
if (pauseState && !this->GetPauseState())
{
OSSpinLockLock(this->_spinlockAUHAL);
AudioOutputUnitStop(this->_auHALInputDevice);
OSSpinLockUnlock(this->_spinlockAUHAL);
AUGraphStop(this->_auGraph);
}
else if (!pauseState && this->_isPaused && !this->IsHardwareLocked())
else if (!pauseState && this->GetPauseState() && !this->IsHardwareLocked() && !this->GetMuteState())
{
OSSpinLockLock(this->_spinlockAUHAL);
AudioOutputUnitStart(this->_auHALInputDevice);
@ -595,7 +623,7 @@ void CoreAudioInput::SetPauseState(bool pauseState)
AUGraphStart(this->_auGraph);
}
this->_isPaused = pauseState;
this->_isPaused = (this->IsHardwareLocked() || this->GetMuteState()) ? true : pauseState;
}
float CoreAudioInput::GetGain() const
@ -619,9 +647,10 @@ void CoreAudioInput::SetGain(float normalizedGain)
OSSpinLockUnlock(this->_spinlockAUHAL);
}
void CoreAudioInput::SetGain_ValueOnly(float normalizedGain)
void CoreAudioInput::UpdateHardwareGain(float normalizedGain)
{
this->_inputGainNormalized = normalizedGain;
this->_hwGainChangedCallbackFunc(this->_inputGainNormalized, this->_hwGainChangedCallbackParam1, this->_hwGainChangedCallbackParam2);
}
void CoreAudioInput::UpdateHardwareLock()
@ -629,65 +658,78 @@ void CoreAudioInput::UpdateHardwareLock()
OSStatus error = noErr;
bool hardwareLocked = false;
if (!this->IsHardwareEnabled())
if (this->IsHardwareEnabled())
{
// Check if another application has exclusive access to the hardware.
pid_t hogMode = 0;
UInt32 propertySize = sizeof(hogMode);
error = AudioUnitGetProperty(this->_auHALInputDevice,
kAudioDevicePropertyHogMode,
kAudioUnitScope_Input,
1,
&hogMode,
&propertySize);
if (error == noErr)
{
if (hogMode != -1)
{
hardwareLocked = true;
}
}
else
{
// If this property is not supported, then always assume that
// the hardware device is shared.
hogMode = -1;
}
// Check if the hardware device is plugged in.
UInt32 isJackConnected = 0;
propertySize = sizeof(isJackConnected);
error = AudioUnitGetProperty(this->_auHALInputDevice,
kAudioDevicePropertyJackIsConnected,
kAudioUnitScope_Input,
1,
&hogMode,
&propertySize);
if (error == noErr)
{
if (isJackConnected == 0)
{
hardwareLocked = true;
}
}
else
{
// If this property is not supported, then always assume that
// the hardware device is always plugged in.
isJackConnected = 1;
}
}
else
{
hardwareLocked = true;
this->_isHardwareLocked = hardwareLocked;
return;
}
// Check if another application has exclusive access to the hardware.
pid_t hogMode = 0;
UInt32 propertySize = sizeof(hogMode);
error = AudioUnitGetProperty(this->_auHALInputDevice,
kAudioDevicePropertyHogMode,
kAudioUnitScope_Input,
1,
&hogMode,
&propertySize);
if (error == noErr)
{
if (hogMode != -1)
{
hardwareLocked = true;
}
}
else
{
// If this property is not supported, then always assume that
// the hardware device is shared.
hogMode = -1;
}
// Check if the hardware device is plugged in.
UInt32 isJackConnected = 0;
propertySize = sizeof(isJackConnected);
error = AudioUnitGetProperty(this->_auHALInputDevice,
kAudioDevicePropertyJackIsConnected,
kAudioUnitScope_Input,
1,
&hogMode,
&propertySize);
if (error == noErr)
{
if (isJackConnected == 0)
{
hardwareLocked = true;
}
}
else
{
// If this property is not supported, then always assume that
// the hardware device is always plugged in.
isJackConnected = 1;
}
if (hardwareLocked && !this->GetPauseState())
this->_isHardwareLocked = hardwareLocked;
if (this->_isHardwareLocked && !this->GetPauseState())
{
this->SetPauseState(true);
}
this->_isHardwareLocked = hardwareLocked;
this->_hwStateChangedCallbackFunc(&this->_hwDeviceInfo,
this->IsHardwareEnabled(),
this->IsHardwareLocked(),
this->_isMuted,
this->_hwStateChangedCallbackParam1,
this->_hwStateChangedCallbackParam2);
}
void CoreAudioInput::SetCallbackHardwareStateChanged(CoreAudioInputHardwareStateChangedCallback callbackFunc, void *inParam1, void *inParam2)
{
this->_hwStateChangedCallbackFunc = callbackFunc;
this->_hwStateChangedCallbackParam1 = inParam1;
this->_hwStateChangedCallbackParam2 = inParam2;
}
void CoreAudioInput::SetCallbackHardwareGainChanged(CoreAudioInputHardwareGainChangedCallback callbackFunc, void *inParam1, void *inParam2)
@ -697,11 +739,6 @@ void CoreAudioInput::SetCallbackHardwareGainChanged(CoreAudioInputHardwareGainCh
this->_hwGainChangedCallbackParam2 = inParam2;
}
void CoreAudioInput::RunHardwareGainChangedCallback(float normalizedGain)
{
this->_hwGainChangedCallbackFunc(normalizedGain, this->_hwGainChangedCallbackParam1, this->_hwGainChangedCallbackParam2);
}
OSStatus CoreAudioInputCaptureCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
@ -808,28 +845,33 @@ void CoreAudioInputAUHALChanged(void *inRefCon,
inElement,
&gainValue,
&propertySize);
if (error == noErr)
{
caInput->SetGain_ValueOnly(gainValue);
caInput->RunHardwareGainChangedCallback(gainValue);
caInput->UpdateHardwareGain(gainValue);
}
break;
}
case kAudioDevicePropertyHogMode:
case kAudioDevicePropertyJackIsConnected:
{
caInput->UpdateHardwareLock();
break;
}
default:
break;
}
}
void CoreAudioInputDefaultHardwareStateChangedCallback(CoreAudioInputDeviceInfo *deviceInfo,
const bool isHardwareEnabled,
const bool isHardwareLocked,
const bool isHardwareMuted,
void *inParam1,
void *inParam2)
{
// Do nothing.
}
void CoreAudioInputDefaultHardwareGainChangedCallback(float normalizedGain, void *inParam1, void *inParam2)
{
// Do nothing.

View File

@ -25,6 +25,24 @@
#include "ringbuffer.h"
struct CoreAudioInputDeviceInfo
{
AudioObjectID objectID;
CFStringRef name;
CFStringRef manufacturer;
CFStringRef deviceUID;
CFStringRef modelUID;
Float64 sampleRate;
};
typedef CoreAudioInputDeviceInfo CoreAudioInputDeviceInfo;
typedef void (*CoreAudioInputHardwareStateChangedCallback)(CoreAudioInputDeviceInfo *deviceInfo,
const bool isHardwareEnabled,
const bool isHardwareLocked,
const bool isHardwareMuted,
void *inParam1,
void *inParam2);
typedef void (*CoreAudioInputHardwareGainChangedCallback)(float normalizedGain, void *inParam1, void *inParam2);
class CoreAudioInput
@ -32,6 +50,10 @@ class CoreAudioInput
private:
OSSpinLock *_spinlockAUHAL;
CoreAudioInputHardwareStateChangedCallback _hwStateChangedCallbackFunc;
void *_hwStateChangedCallbackParam1;
void *_hwStateChangedCallbackParam2;
CoreAudioInputHardwareGainChangedCallback _hwGainChangedCallbackFunc;
void *_hwGainChangedCallbackParam1;
void *_hwGainChangedCallbackParam2;
@ -39,26 +61,26 @@ private:
AUGraph _auGraph;
AUNode _auFormatConverterNode;
AUNode _auOutputNode;
AudioUnit _auFormatConverterUnit;
AudioUnit _auOutputUnit;
AudioBufferList *_convertBufferList;
UInt32 _captureFrames;
float _inputGainNormalized;
AudioUnitElement _inputElement;
bool _isMuted;
bool _isPaused;
CoreAudioInputDeviceInfo _hwDeviceInfo;
bool _isHardwareEnabled;
bool _isHardwareLocked;
bool _isMuted;
OSStatus InitInputAUHAL(UInt32 deviceID);
public:
AudioUnit _auHALInputDevice;
AudioUnit _auOutputUnit;
AudioTimeStamp _timeStamp;
AudioBufferList *_captureBufferList;
AudioBufferList *_convertBufferList;
UInt32 _captureFrames;
RingBuffer *_samplesCaptured;
RingBuffer *_samplesConverted;
@ -68,6 +90,7 @@ public:
void Start();
void Stop();
size_t Pull();
bool IsHardwareEnabled() const;
bool IsHardwareLocked() const;
bool GetMuteState() const;
@ -76,10 +99,11 @@ public:
void SetPauseState(bool pauseState);
float GetGain() const;
void SetGain(float normalizedGain);
void SetGain_ValueOnly(float normalizedGain);
void UpdateHardwareGain(float normalizedGain);
void UpdateHardwareLock();
void SetCallbackHardwareStateChanged(CoreAudioInputHardwareStateChangedCallback callbackFunc, void *inParam1, void *inParam2);
void SetCallbackHardwareGainChanged(CoreAudioInputHardwareGainChangedCallback callbackFunc, void *inParam1, void *inParam2);
void RunHardwareGainChangedCallback(float normalizedGain);
};
class CoreAudioOutput
@ -146,6 +170,13 @@ OSStatus CoreAudioOutputRenderCallback(void *inRefCon,
UInt32 inNumberFrames,
AudioBufferList *ioData);
void CoreAudioInputDefaultHardwareStateChangedCallback(CoreAudioInputDeviceInfo *deviceInfo,
const bool isHardwareEnabled,
const bool isHardwareLocked,
const bool isHardwareMuted,
void *inParam1,
void *inParam2);
void CoreAudioInputDefaultHardwareGainChangedCallback(float normalizedGain, void *inParam1, void *inParam2);
bool CreateAudioUnitInstance(AudioUnit *au, ComponentDescription *auDescription);

View File

@ -301,6 +301,7 @@
<int key="NSvFlags">294</int>
<string key="NSFrame">{{17, 5}, {137, 14}}</string>
<reference key="NSSuperview" ref="1027645320"/>
<reference key="NSNextKeyView" ref="154157914"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="644649254">
<int key="NSCellFlags">68157504</int>
@ -420,6 +421,7 @@
<int key="NSvFlags">289</int>
<string key="NSFrame">{{152, -1}, {40, 26}}</string>
<reference key="NSSuperview" ref="1027645320"/>
<reference key="NSNextKeyView" ref="347607109"/>
<string key="NSReuseIdentifierKey">_NS:791</string>
<bool key="NSEnabled">YES</bool>
<object class="NSPopUpButtonCell" key="NSCell" id="480563989">
@ -611,7 +613,7 @@
<string key="NSClassName">NSView</string>
</object>
<object class="NSCustomView" id="545736283">
<reference key="NSNextResponder"/>
<nil key="NSNextResponder"/>
<int key="NSvFlags">268</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="NSButton" id="208921964">
@ -619,8 +621,6 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{2, 0}, {49, 18}}</string>
<reference key="NSSuperview" ref="545736283"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<string key="NSReuseIdentifierKey">_NS:682</string>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="169016076">
@ -651,7 +651,6 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{-4, 20}, {66, 11}}</string>
<reference key="NSSuperview" ref="545736283"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="208921964"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="30057499">
@ -729,12 +728,11 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{17, 31}, {21, 105}}</string>
<reference key="NSSuperview" ref="545736283"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="261027162"/>
<string key="NSReuseIdentifierKey">_NS:768</string>
<bool key="NSEnabled">YES</bool>
<object class="NSSliderCell" key="NSCell" id="893365979">
<int key="NSCellFlags">67371264</int>
<int key="NSCellFlags">604242176</int>
<int key="NSCellFlags2">0</int>
<string key="NSContents"/>
<string key="NSCellIdentifier">_NS:768</string>
@ -752,14 +750,12 @@
</object>
</array>
<string key="NSFrameSize">{55, 139}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="738109744"/>
<string key="NSReuseIdentifierKey">_NS:1109</string>
<string key="NSClassName">NSView</string>
</object>
<object class="NSCustomView" id="552471306">
<reference key="NSNextResponder"/>
<nil key="NSNextResponder"/>
<int key="NSvFlags">268</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="NSTextField" id="1023402314">
@ -767,8 +763,6 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{-1, 6}, {51, 11}}</string>
<reference key="NSSuperview" ref="552471306"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="999175719">
<int key="NSCellFlags">68157504</int>
@ -829,7 +823,6 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{12, 17}, {21, 105}}</string>
<reference key="NSSuperview" ref="552471306"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="1023402314"/>
<string key="NSReuseIdentifierKey">_NS:768</string>
<bool key="NSEnabled">YES</bool>
@ -852,8 +845,6 @@
</object>
</array>
<string key="NSFrameSize">{45, 125}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="782084649"/>
<string key="NSReuseIdentifierKey">_NS:1109</string>
<string key="NSClassName">NSView</string>
@ -1154,6 +1145,22 @@
</object>
<int key="connectionID">133</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">toolTip: emuControl.cdsCoreController.content.cdsController.hardwareMicInfoString</string>
<reference key="source" ref="154157914"/>
<reference key="destination" ref="1001"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="154157914"/>
<reference key="NSDestination" ref="1001"/>
<string key="NSLabel">toolTip: emuControl.cdsCoreController.content.cdsController.hardwareMicInfoString</string>
<string key="NSBinding">toolTip</string>
<string key="NSKeyPath">emuControl.cdsCoreController.content.cdsController.hardwareMicInfoString</string>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">226</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">image: emuControl.currentMicStatusIcon</string>
@ -1186,6 +1193,22 @@
</object>
<int key="connectionID">138</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">enabled: emuControl.isHardwareMicAvailable</string>
<reference key="source" ref="738109744"/>
<reference key="destination" ref="1001"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="738109744"/>
<reference key="NSDestination" ref="1001"/>
<string key="NSLabel">enabled: emuControl.isHardwareMicAvailable</string>
<string key="NSBinding">enabled</string>
<string key="NSKeyPath">emuControl.isHardwareMicAvailable</string>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">218</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">value: emuControl.currentMicGainValue</string>
@ -1200,7 +1223,7 @@
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">200</int>
<int key="connectionID">230</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
@ -1262,6 +1285,22 @@
</object>
<int key="connectionID">167</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">enabled: emuControl.isHardwareMicAvailable</string>
<reference key="source" ref="261027162"/>
<reference key="destination" ref="1001"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="261027162"/>
<reference key="NSDestination" ref="1001"/>
<string key="NSLabel">enabled: emuControl.isHardwareMicAvailable</string>
<string key="NSBinding">enabled</string>
<string key="NSKeyPath">emuControl.isHardwareMicAvailable</string>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">220</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">value: emuControl.currentMicGainValue</string>
@ -1280,23 +1319,23 @@
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">205</int>
<int key="connectionID">232</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">value: emuControl.isHardwareMicMuted</string>
<string key="label">value: emuControl.cdsCoreController.content.cdsController.hardwareMicMute</string>
<reference key="source" ref="208921964"/>
<reference key="destination" ref="1001"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="208921964"/>
<reference key="NSDestination" ref="1001"/>
<string key="NSLabel">value: emuControl.isHardwareMicMuted</string>
<string key="NSLabel">value: emuControl.cdsCoreController.content.cdsController.hardwareMicMute</string>
<string key="NSBinding">value</string>
<string key="NSKeyPath">emuControl.isHardwareMicMuted</string>
<string key="NSKeyPath">emuControl.cdsCoreController.content.cdsController.hardwareMicMute</string>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">199</int>
<int key="connectionID">224</int>
</object>
</array>
<object class="IBMutableOrderedSet" key="objectRecords">
@ -1750,539 +1789,9 @@
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">216</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
<object class="IBPartialClassDescription">
<string key="className">DisplayView</string>
<string key="superclassName">NSView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier" id="1035067465">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">../userinterface/DisplayWindowController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">DisplayWindowController</string>
<string key="superclassName">NSWindowController</string>
<dictionary class="NSMutableDictionary" key="actions">
<string key="changeCoreSpeed:">id</string>
<string key="changeDisplayGap:">id</string>
<string key="changeDisplayMode:">id</string>
<string key="changeDisplayOrder:">id</string>
<string key="changeDisplayOrientation:">id</string>
<string key="changeHardwareMicGain:">id</string>
<string key="changeRotation:">id</string>
<string key="changeRotationRelative:">id</string>
<string key="changeScale:">id</string>
<string key="changeVideoOutputFilter:">id</string>
<string key="changeVideoPixelScaler:">id</string>
<string key="changeVolume:">id</string>
<string key="copy:">id</string>
<string key="openRom:">id</string>
<string key="reset:">id</string>
<string key="saveScreenshotAs:">id</string>
<string key="toggleExecutePause:">id</string>
<string key="toggleFullScreenDisplay:">id</string>
<string key="toggleKeepMinDisplaySizeAtNormal:">id</string>
<string key="toggleStatusBar:">id</string>
<string key="toggleVideoSourceDeposterize:">id</string>
<string key="writeDefaultsDisplayGap:">id</string>
<string key="writeDefaultsDisplayRotation:">id</string>
<string key="writeDefaultsDisplayVideoSettings:">id</string>
<string key="writeDefaultsHUDSettings:">id</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="actionInfosByName">
<object class="IBActionInfo" key="changeCoreSpeed:">
<string key="name">changeCoreSpeed:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="changeDisplayGap:">
<string key="name">changeDisplayGap:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="changeDisplayMode:">
<string key="name">changeDisplayMode:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="changeDisplayOrder:">
<string key="name">changeDisplayOrder:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="changeDisplayOrientation:">
<string key="name">changeDisplayOrientation:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="changeHardwareMicGain:">
<string key="name">changeHardwareMicGain:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="changeRotation:">
<string key="name">changeRotation:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="changeRotationRelative:">
<string key="name">changeRotationRelative:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="changeScale:">
<string key="name">changeScale:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="changeVideoOutputFilter:">
<string key="name">changeVideoOutputFilter:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="changeVideoPixelScaler:">
<string key="name">changeVideoPixelScaler:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="changeVolume:">
<string key="name">changeVolume:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="copy:">
<string key="name">copy:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="openRom:">
<string key="name">openRom:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="reset:">
<string key="name">reset:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="saveScreenshotAs:">
<string key="name">saveScreenshotAs:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="toggleExecutePause:">
<string key="name">toggleExecutePause:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="toggleFullScreenDisplay:">
<string key="name">toggleFullScreenDisplay:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="toggleKeepMinDisplaySizeAtNormal:">
<string key="name">toggleKeepMinDisplaySizeAtNormal:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="toggleStatusBar:">
<string key="name">toggleStatusBar:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="toggleVideoSourceDeposterize:">
<string key="name">toggleVideoSourceDeposterize:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="writeDefaultsDisplayGap:">
<string key="name">writeDefaultsDisplayGap:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="writeDefaultsDisplayRotation:">
<string key="name">writeDefaultsDisplayRotation:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="writeDefaultsDisplayVideoSettings:">
<string key="name">writeDefaultsDisplayVideoSettings:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="writeDefaultsHUDSettings:">
<string key="name">writeDefaultsHUDSettings:</string>
<string key="candidateClassName">id</string>
</object>
</dictionary>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="microphoneGainControlView">NSView</string>
<string key="microphoneGainMenuItem">NSMenuItem</string>
<string key="microphoneGainSlider">NSSlider</string>
<string key="microphoneMuteButton">NSButton</string>
<string key="outputVolumeControlView">NSView</string>
<string key="outputVolumeMenuItem">NSMenuItem</string>
<string key="saveScreenshotPanelAccessoryView">NSView</string>
<string key="view">DisplayView</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="microphoneGainControlView">
<string key="name">microphoneGainControlView</string>
<string key="candidateClassName">NSView</string>
</object>
<object class="IBToOneOutletInfo" key="microphoneGainMenuItem">
<string key="name">microphoneGainMenuItem</string>
<string key="candidateClassName">NSMenuItem</string>
</object>
<object class="IBToOneOutletInfo" key="microphoneGainSlider">
<string key="name">microphoneGainSlider</string>
<string key="candidateClassName">NSSlider</string>
</object>
<object class="IBToOneOutletInfo" key="microphoneMuteButton">
<string key="name">microphoneMuteButton</string>
<string key="candidateClassName">NSButton</string>
</object>
<object class="IBToOneOutletInfo" key="outputVolumeControlView">
<string key="name">outputVolumeControlView</string>
<string key="candidateClassName">NSView</string>
</object>
<object class="IBToOneOutletInfo" key="outputVolumeMenuItem">
<string key="name">outputVolumeMenuItem</string>
<string key="candidateClassName">NSMenuItem</string>
</object>
<object class="IBToOneOutletInfo" key="saveScreenshotPanelAccessoryView">
<string key="name">saveScreenshotPanelAccessoryView</string>
<string key="candidateClassName">NSView</string>
</object>
<object class="IBToOneOutletInfo" key="view">
<string key="name">view</string>
<string key="candidateClassName">DisplayView</string>
</object>
</dictionary>
<reference key="sourceIdentifier" ref="1035067465"/>
</object>
<object class="IBPartialClassDescription">
<string key="className">DisplayWindowController</string>
<dictionary class="NSMutableDictionary" key="actions">
<string key="changeCoreSpeed:">id</string>
<string key="changeDisplayGap:">id</string>
<string key="changeDisplayMode:">id</string>
<string key="changeDisplayOrder:">id</string>
<string key="changeDisplayOrientation:">id</string>
<string key="changeHardwareMicGain:">id</string>
<string key="changeRotation:">id</string>
<string key="changeRotationRelative:">id</string>
<string key="changeScale:">id</string>
<string key="changeVideoOutputFilter:">id</string>
<string key="changeVideoPixelScaler:">id</string>
<string key="changeVolume:">id</string>
<string key="copy:">id</string>
<string key="openRom:">id</string>
<string key="reset:">id</string>
<string key="saveScreenshotAs:">id</string>
<string key="toggleExecutePause:">id</string>
<string key="toggleFullScreenDisplay:">id</string>
<string key="toggleKeepMinDisplaySizeAtNormal:">id</string>
<string key="toggleStatusBar:">id</string>
<string key="toggleVideoSourceDeposterize:">id</string>
<string key="writeDefaultsDisplayGap:">id</string>
<string key="writeDefaultsDisplayRotation:">id</string>
<string key="writeDefaultsDisplayVideoSettings:">id</string>
<string key="writeDefaultsHUDSettings:">id</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="actionInfosByName">
<object class="IBActionInfo" key="changeCoreSpeed:">
<string key="name">changeCoreSpeed:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="changeDisplayGap:">
<string key="name">changeDisplayGap:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="changeDisplayMode:">
<string key="name">changeDisplayMode:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="changeDisplayOrder:">
<string key="name">changeDisplayOrder:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="changeDisplayOrientation:">
<string key="name">changeDisplayOrientation:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="changeHardwareMicGain:">
<string key="name">changeHardwareMicGain:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="changeRotation:">
<string key="name">changeRotation:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="changeRotationRelative:">
<string key="name">changeRotationRelative:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="changeScale:">
<string key="name">changeScale:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="changeVideoOutputFilter:">
<string key="name">changeVideoOutputFilter:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="changeVideoPixelScaler:">
<string key="name">changeVideoPixelScaler:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="changeVolume:">
<string key="name">changeVolume:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="copy:">
<string key="name">copy:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="openRom:">
<string key="name">openRom:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="reset:">
<string key="name">reset:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="saveScreenshotAs:">
<string key="name">saveScreenshotAs:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="toggleExecutePause:">
<string key="name">toggleExecutePause:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="toggleFullScreenDisplay:">
<string key="name">toggleFullScreenDisplay:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="toggleKeepMinDisplaySizeAtNormal:">
<string key="name">toggleKeepMinDisplaySizeAtNormal:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="toggleStatusBar:">
<string key="name">toggleStatusBar:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="toggleVideoSourceDeposterize:">
<string key="name">toggleVideoSourceDeposterize:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="writeDefaultsDisplayGap:">
<string key="name">writeDefaultsDisplayGap:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="writeDefaultsDisplayRotation:">
<string key="name">writeDefaultsDisplayRotation:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="writeDefaultsDisplayVideoSettings:">
<string key="name">writeDefaultsDisplayVideoSettings:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="writeDefaultsHUDSettings:">
<string key="name">writeDefaultsHUDSettings:</string>
<string key="candidateClassName">id</string>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">../userinterface/DisplayWindowController.mm</string>
</object>
</object>
</array>
<array class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
<object class="IBPartialClassDescription">
<string key="className">NSActionCell</string>
<string key="superclassName">NSCell</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSActionCell.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSApplication</string>
<string key="superclassName">NSResponder</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSApplication.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSButton</string>
<string key="superclassName">NSControl</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSButton.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSButtonCell</string>
<string key="superclassName">NSActionCell</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSButtonCell.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSCell</string>
<string key="superclassName">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSCell.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSControl</string>
<string key="superclassName">NSView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSControl.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSFormatter</string>
<string key="superclassName">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSFormatter.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSMenu</string>
<string key="superclassName">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSMenu.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSMenuItem</string>
<string key="superclassName">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSMenuItem.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSMenuItemCell</string>
<string key="superclassName">NSButtonCell</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSMenuItemCell.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSNumberFormatter</string>
<string key="superclassName">NSFormatter</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSNumberFormatter.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSPopUpButton</string>
<string key="superclassName">NSButton</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSPopUpButton.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSPopUpButtonCell</string>
<string key="superclassName">NSMenuItemCell</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSPopUpButtonCell.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSProgressIndicator</string>
<string key="superclassName">NSView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSProgressIndicator.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSResponder</string>
<string key="superclassName">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSResponder.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSSlider</string>
<string key="superclassName">NSControl</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSSlider.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSSliderCell</string>
<string key="superclassName">NSActionCell</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSSliderCell.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSTextField</string>
<string key="superclassName">NSControl</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSTextField.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSTextFieldCell</string>
<string key="superclassName">NSActionCell</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSTextFieldCell.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSToolbar</string>
<string key="superclassName">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSToolbar.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSToolbarItem</string>
<string key="superclassName">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSToolbarItem.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSView</string>
<string key="superclassName">NSResponder</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSWindow</string>
<string key="superclassName">NSResponder</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSWindow.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSWindowController</string>
<string key="superclassName">NSResponder</string>
<object class="NSMutableDictionary" key="actions">
<string key="NS.key.0">showWindow:</string>
<string key="NS.object.0">id</string>
</object>
<object class="NSMutableDictionary" key="actionInfosByName">
<string key="NS.key.0">showWindow:</string>
<object class="IBActionInfo" key="NS.object.0">
<string key="name">showWindow:</string>
<string key="candidateClassName">id</string>
</object>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSWindowController.h</string>
</object>
</object>
</array>
<int key="maxID">232</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes"/>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
<bool key="IBDocument.previouslyAttemptedUpgradeToXcode5">NO</bool>

View File

@ -75,9 +75,8 @@ class AudioSampleBlockGenerator;
NSInteger frameJumpToFrame;
CGFloat lastSetSpeedScalar;
uint32_t hwMicNumberIdleFrames;
uint32_t hwMicNumberClippedFrames;
BOOL isSoftwareMicActive;
BOOL isHardwareMicAvailable;
BOOL isHardwareMicIdle;
BOOL isHardwareMicInClip;
float currentMicGainValue;
@ -142,7 +141,7 @@ class AudioSampleBlockGenerator;
@property (assign) BOOL isRomLoading;
@property (assign) NSString *statusText;
@property (assign) BOOL isSoftwareMicActive;
@property (assign) BOOL isHardwareMicMuted;
@property (assign) BOOL isHardwareMicAvailable;
@property (assign) BOOL isHardwareMicIdle;
@property (assign) BOOL isHardwareMicInClip;
@property (assign) float currentMicGainValue;
@ -261,8 +260,6 @@ class AudioSampleBlockGenerator;
- (void) pauseCore;
- (void) restoreCoreState;
- (void) updateMicStatusIcon;
- (BOOL) isMicSampleIdle:(uint8_t)sampleValue;
- (BOOL) isMicSampleCausingClip:(uint8_t)sampleValue;
- (AudioSampleBlockGenerator *) selectedAudioFileGenerator;
- (void) setSelectedAudioFileGenerator:(AudioSampleBlockGenerator *)theGenerator;

View File

@ -72,7 +72,7 @@
@synthesize isRomLoading;
@synthesize statusText;
@synthesize isSoftwareMicActive;
@dynamic isHardwareMicMuted;
@synthesize isHardwareMicAvailable;
@synthesize isHardwareMicIdle;
@synthesize isHardwareMicInClip;
@synthesize currentMicGainValue;
@ -127,12 +127,11 @@
frameJumpToFrame = 0;
lastSetSpeedScalar = 1.0f;
hwMicNumberIdleFrames = 0;
hwMicNumberClippedFrames = 0;
isSoftwareMicActive = NO;
isHardwareMicAvailable = NO;
isHardwareMicIdle = YES;
isHardwareMicInClip = NO;
currentMicGainValue = 0.5f;
currentMicGainValue = 0.0f;
isSoundMuted = NO;
lastSetVolumeValue = MAX_VOLUME;
@ -292,19 +291,6 @@
return [cdsCore speedScalar];
}
- (void) setIsHardwareMicMuted:(BOOL)theState
{
CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content];
[[cdsCore cdsController] setHardwareMicMute:theState];
[self updateMicStatusIcon];
}
- (BOOL) isHardwareMicMuted
{
CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content];
return [[cdsCore cdsController] hardwareMicMute];
}
- (void) setCurrentVolumeValue:(float)vol
{
currentVolumeValue = vol;
@ -1960,46 +1946,6 @@
[self performSelectorOnMainThread:@selector(setCurrentMicStatusIcon:) withObject:micIcon waitUntilDone:NO];
}
- (BOOL) isMicSampleIdle:(uint8_t)sampleValue
{
if (sampleValue == MIC_NULL_SAMPLE_VALUE)
{
if (hwMicNumberIdleFrames < MIC_NULL_FRAME_MAX_COUNT)
{
hwMicNumberIdleFrames++;
}
}
else
{
if (hwMicNumberIdleFrames > 0)
{
hwMicNumberIdleFrames--;
}
}
return (hwMicNumberIdleFrames >= MIC_NULL_FRAME_THRESHOLD);
}
- (BOOL) isMicSampleCausingClip:(uint8_t)sampleValue
{
if (sampleValue == 0 || sampleValue == 127)
{
if (hwMicNumberClippedFrames < MIC_CLIP_FRAME_MAX_COUNT)
{
hwMicNumberClippedFrames++;
}
}
else
{
if (hwMicNumberClippedFrames > 0)
{
hwMicNumberClippedFrames--;
}
}
return (hwMicNumberClippedFrames >= MIC_CLIP_FRAME_THRESHOLD);
}
- (AudioSampleBlockGenerator *) selectedAudioFileGenerator
{
CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content];
@ -2494,21 +2440,21 @@
// sure to check the mic's level state.
if (!controllerSoftwareMicState)
{
const BOOL isSampleIdle = [self isMicSampleIdle:sampleValue];
const BOOL isIdle = [self isHardwareMicIdle];
if (( isSampleIdle && !isIdle) ||
(!isSampleIdle && isIdle))
const BOOL isIdleHardware = [cdsController isHardwareMicIdle];
const BOOL isIdleEmuControl = [self isHardwareMicIdle];
if (( isIdleHardware && !isIdleEmuControl) ||
(!isIdleHardware && isIdleEmuControl))
{
[self setIsHardwareMicIdle:isSampleIdle];
[self setIsHardwareMicIdle:isIdleHardware];
needsUpdate = YES;
}
const BOOL isCausingClip = [self isMicSampleCausingClip:sampleValue];
const BOOL isInClip = [self isHardwareMicInClip];
if (( isCausingClip && !isInClip) ||
(!isCausingClip && isInClip))
const BOOL isClipHardware = [cdsController isHardwareMicInClip];
const BOOL isClipEmuControl = [self isHardwareMicInClip];
if (( isClipHardware && !isClipEmuControl) ||
(!isClipHardware && isClipEmuControl))
{
[self setIsHardwareMicInClip:isCausingClip];
[self setIsHardwareMicInClip:isClipHardware];
needsUpdate = YES;
}
}
@ -2521,6 +2467,16 @@
return sampleValue;
}
- (void) doMicHardwareStateChangedFromController:(CocoaDSController *)cdsController
isEnabled:(BOOL)isHardwareEnabled
isLocked:(BOOL)isHardwareLocked
isMuted:(BOOL)isHardwareMuted
{
const BOOL hwMicAvailable = (isHardwareEnabled && !isHardwareLocked);
[self setIsHardwareMicAvailable:hwMicAvailable];
[self updateMicStatusIcon];
}
- (void) doMicHardwareGainChangedFromController:(CocoaDSController *)cdsController gain:(float)gainValue
{
[self setCurrentMicGainValue:gainValue];