How to programmatically sense the iPhone mute switch?
Thanks, JPM. Indeed, the link you provide leads to the correct answer (eventually. ;) For completeness (because S.O. should be a source of QUICK answers! )...
// "Ambient" makes it respect the mute switch// Must call this once to init sessionif (!gAudioSessionInited){ AudioSessionInterruptionListener inInterruptionListener = NULL; OSStatus error; if ((error = AudioSessionInitialize (NULL, NULL, inInterruptionListener, NULL))) { NSLog(@"*** Error *** error in AudioSessionInitialize: %d.", error); } else { gAudioSessionInited = YES; }}SInt32 ambient = kAudioSessionCategory_AmbientSound;if (AudioSessionSetProperty (kAudioSessionProperty_AudioCategory, sizeof (ambient), &ambient)){ NSLog(@"*** Error *** could not set Session property to ambient.");}
I answered a similar question here (link). The relevant code:
-(BOOL)silenced { #if TARGET_IPHONE_SIMULATOR // return NO in simulator. Code causes crashes for some reason. return NO; #endif CFStringRef state; UInt32 propertySize = sizeof(CFStringRef); AudioSessionInitialize(NULL, NULL, NULL, NULL); AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state); if(CFStringGetLength(state) > 0) return NO; else return YES; }
Some of the code in other answers (including the accepted answer) may not work if you aren't in the ambient mode, where the mute switch is respected.
I wrote the routine below to switch to ambient, read the switch, and then return to the settings I need in my app.
-(BOOL)muteSwitchEnabled {#if TARGET_IPHONE_SIMULATOR // set to NO in simulator. Code causes crashes for some reason. return NO;#endif// go back to Ambient to detect the switchAVAudioSession* sharedSession = [AVAudioSession sharedInstance];[sharedSession setCategory:AVAudioSessionCategoryAmbient error:nil];CFStringRef state;UInt32 propertySize = sizeof(CFStringRef);AudioSessionInitialize(NULL, NULL, NULL, NULL);AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);BOOL muteSwitch = (CFStringGetLength(state) <= 0);NSLog(@"Mute switch: %d",muteSwitch);// code below here is just restoring my own audio state, YMMV_hasMicrophone = [sharedSession inputIsAvailable];NSError* setCategoryError = nil;if (_hasMicrophone) { [sharedSession setCategory: AVAudioSessionCategoryPlayAndRecord error: &setCategoryError]; // By default PlayAndRecord plays out over the internal speaker. We want the external speakers, thanks. UInt32 ASRoute = kAudioSessionOverrideAudioRoute_Speaker; AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute, sizeof (ASRoute), &ASRoute );}else // Devices with no mike don't support PlayAndRecord - we don't get playback, so use just playback as we don't have a microphone anyway [sharedSession setCategory: AVAudioSessionCategoryPlayback error: &setCategoryError];if (setCategoryError) NSLog(@"Error setting audio category! %@", setCategoryError);return muteSwitch;}