Added hardware mute via core audio

This commit is contained in:
Diogo Tridapalli
2015-10-05 23:06:47 -03:00
parent e1f3538d4a
commit 5d82c5e170
4 changed files with 286 additions and 29 deletions

View File

@@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
D9A9F66F1BC35EDC004395E8 /* AudioMixer.c in Sources */ = {isa = PBXBuildFile; fileRef = D9A9F66D1BC35EDC004395E8 /* AudioMixer.c */; settings = {ASSET_TAGS = (); }; };
ECF208BE1BAF2DE6000D3C2C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = ECF208BD1BAF2DE6000D3C2C /* AppDelegate.m */; };
ECF208C11BAF2DE6000D3C2C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = ECF208C01BAF2DE6000D3C2C /* main.m */; };
ECF208C31BAF2DE6000D3C2C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = ECF208C21BAF2DE6000D3C2C /* Assets.xcassets */; };
@@ -14,6 +15,8 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
D9A9F66D1BC35EDC004395E8 /* AudioMixer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = AudioMixer.c; path = MuteUnmuteMic/AudioMixer.c; sourceTree = "<group>"; };
D9A9F66E1BC35EDC004395E8 /* AudioMixer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioMixer.h; path = MuteUnmuteMic/AudioMixer.h; sourceTree = "<group>"; };
ECF208B91BAF2DE6000D3C2C /* MuteUnmuteMic.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MuteUnmuteMic.app; sourceTree = BUILT_PRODUCTS_DIR; };
ECF208BC1BAF2DE6000D3C2C /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
ECF208BD1BAF2DE6000D3C2C /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
@@ -39,6 +42,8 @@
children = (
ECF208BB1BAF2DE6000D3C2C /* MuteUnmuteMic */,
ECF208BA1BAF2DE6000D3C2C /* Products */,
D9A9F66D1BC35EDC004395E8 /* AudioMixer.c */,
D9A9F66E1BC35EDC004395E8 /* AudioMixer.h */,
);
sourceTree = "<group>";
};
@@ -142,6 +147,7 @@
files = (
ECF208C11BAF2DE6000D3C2C /* main.m in Sources */,
ECF208BE1BAF2DE6000D3C2C /* AppDelegate.m in Sources */,
D9A9F66F1BC35EDC004395E8 /* AudioMixer.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@@ -1,32 +1,37 @@
#import "AppDelegate.h"
#import "AudioMixer.h"
#define MAX_VOLUME 70
static NSInteger const kDefaultVolume = 70;
@interface AppDelegate ()
{
NSStatusItem *menuItem;
BOOL muted;
int inputVolumeToUnmute;
}
@property (nonatomic) NSStatusItem *menuItem;
@property (nonatomic) BOOL muted;
@property (nonatomic) NSInteger inputVolumeToUnmute;
@end
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[self initDefaults];
[self configureStatusBar];
[self updateInputVolume];
}
- (void)initDefaults {
muted = NO;
inputVolumeToUnmute = MAX_VOLUME;
- (void)initDefaults
{
_muted = IsHardwareMuted();
_inputVolumeToUnmute = kDefaultVolume;
}
- (void)configureStatusBar {
- (void)configureStatusBar
{
NSStatusBar *statusBar = [NSStatusBar systemStatusBar];
menuItem = [statusBar statusItemWithLength:NSVariableStatusItemLength];
NSStatusItem *menuItem =
[statusBar statusItemWithLength:NSVariableStatusItemLength];
[menuItem setToolTip:@"MuteUnmuteMic by CocoaHeads Brazil"];
[menuItem setImage:[NSImage imageNamed:@"mic_on"]];
[menuItem setHighlightMode:YES];
@@ -34,9 +39,12 @@
[menuItem setTarget:self];
[menuItem setAction:@selector(menuItemClicked:)];
[menuItem.button sendActionOn:NSLeftMouseUpMask|NSRightMouseUpMask];
self.menuItem = menuItem;
}
- (void)menuItemClicked:(id)sender {
- (void)menuItemClicked:(id)sender
{
NSEvent *event = [[NSApplication sharedApplication] currentEvent];
if ((event.modifierFlags & NSControlKeyMask) || (event.type == NSRightMouseUp)) {
@@ -44,39 +52,59 @@
} else {
[self toggleMute];
}
}
- (void)toggleMute {
muted = !muted;
- (void)toggleMute
{
self.muted = !self.muted;
[self updateInputVolume];
}
- (void)updateInputVolume {
int volume = muted ? 0 : inputVolumeToUnmute;
NSString *source = [NSString stringWithFormat:@"set volume input volume %d", volume];
- (void)updateInputVolume
{
BOOL muted = self.muted;
NSInteger volume;
NSString *imageName;
if (muted) {
volume = 0;
imageName = @"mic_off";
} else {
volume = self.inputVolumeToUnmute;
imageName = @"mic_on";
}
// set volume
NSString *source =
[NSString stringWithFormat:@"set volume input volume %ld", (long)volume];
NSAppleScript *script = [[NSAppleScript alloc] initWithSource:source];
NSDictionary *errorInfo = nil;
[script executeAndReturnError:&errorInfo];
[script executeAndReturnError:nil];
if (errorInfo) {
NSLog(@"Error on script %@", errorInfo);
}
NSString *imageName = muted ? @"mic_off" : @"mic_on";
menuItem.image = [NSImage imageNamed:imageName];
// set hardware mute
SetHardwareMute(muted);
// set image
self.menuItem.image = [NSImage imageNamed:imageName];
}
- (void)showMenu {
[menuItem popUpStatusItemMenu:self.menu];
- (void)showMenu
{
[self.menuItem popUpStatusItemMenu:self.menu];
}
- (IBAction)didSetVolumeInput:(NSMenuItem *)sender {
- (IBAction)didSetVolumeInput:(NSMenuItem *)sender
{
for (NSMenuItem *item in sender.menu.itemArray) {
item.state = 0;
}
sender.state = 1;
inputVolumeToUnmute = [sender.title intValue];
self.inputVolumeToUnmute = [sender.title integerValue];
[self updateInputVolume];
}

154
MuteUnmuteMic/AudioMixer.c Normal file
View File

@@ -0,0 +1,154 @@
//
// AudioMixer.c
// MuteUnmuteMic
//
// Created by Diogo Tridapalli on 10/5/15.
// Copyright © 2015 Gustavo Barbosa. All rights reserved.
//
#include "AudioMixer.h"
Boolean GetDefaultInputAudioDevice(AudioDeviceID *defaultInputDeviceID)
{
UInt32 thePropSize = sizeof(AudioDeviceID);
AudioObjectPropertyAddress thePropertyAddress =
{ kAudioHardwarePropertyDefaultInputDevice,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster };
OSStatus errorCode =
AudioObjectGetPropertyData(kAudioObjectSystemObject,
&thePropertyAddress,
0,
NULL,
&thePropSize,
defaultInputDeviceID);
if (errorCode) {
printf("Error in GetDefaultInputAudioDevice: %d\n", errorCode);
}
return errorCode == 0;
}
Boolean GetAudioDeviceName(const AudioDeviceID deviceID,
CFStringRef *deviceName)
{
UInt32 thePropSize = sizeof(CFStringRef);
AudioObjectPropertyAddress thePropertyAddress =
{ kAudioObjectPropertyName,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster };
OSStatus errorCode =
AudioObjectGetPropertyData(deviceID,
&thePropertyAddress,
0,
NULL,
&thePropSize,
deviceName);
if (errorCode) {
printf("Error in GetAudioDeviceName: %d\n", errorCode);
}
return errorCode == 0;
}
Boolean GetMuteOnInputAudioDevice(const AudioDeviceID inputDeviceID,
Boolean *isMuted)
{
AudioObjectPropertyAddress thePropertyAddress =
{ kAudioDevicePropertyMute,
kAudioDevicePropertyScopeInput,
kAudioObjectPropertyElementMaster };
UInt32 mute = 0;
UInt32 thePropSize = sizeof(mute);
OSStatus errorCode;
if (AudioObjectHasProperty(inputDeviceID, &thePropertyAddress)) {
errorCode = AudioObjectGetPropertyData(inputDeviceID,
&thePropertyAddress,
0,
NULL,
&thePropSize,
&mute);
if (errorCode) {
printf("Error in GetMuteOnInputAudioDevice: %d\n", errorCode);
}
*isMuted = mute > 0;
return errorCode == 0;
} else {
printf("Error in GetMuteOnInputAudioDevice: mute not supported\n");
return false;
}
}
Boolean SetMuteOnInputAudioDevice(const AudioDeviceID inputDeviceID,
const Boolean mute)
{
AudioObjectPropertyAddress thePropertyAddress =
{ kAudioDevicePropertyMute,
kAudioDevicePropertyScopeInput,
kAudioObjectPropertyElementMaster };
UInt32 theMute = mute;
UInt32 thePropSize = sizeof(theMute);
const char *inputDeviceString;
CFStringRef inputDeviceName;
if (GetAudioDeviceName(inputDeviceID, &inputDeviceName)) {
inputDeviceString =
CFStringGetCStringPtr(inputDeviceName, CFStringGetSystemEncoding());
CFRelease(inputDeviceName);
} else {
inputDeviceString = "<Unamed device>";
}
Boolean setMute = true;
if (AudioObjectHasProperty(inputDeviceID, &thePropertyAddress)) {
printf("\tSetting %s mute %s\n", inputDeviceString, (theMute) ? "on" : "off");
OSStatus errorCode = AudioObjectSetPropertyData(inputDeviceID,
&thePropertyAddress,
0,
NULL,
thePropSize,
&theMute);
if (errorCode) {
printf("Error in SetMuteOnInputAudioDevice: %d\n", errorCode);
setMute = false;
}
} else {
printf("Error in SetMuteOnInputAudioDevice: mute not supported\n");
setMute = false;
}
return setMute;
}
Boolean IsHardwareMuted()
{
AudioDeviceID theDefaultInputDeviceID;
Boolean isMuted = false;
if (GetDefaultInputAudioDevice(&theDefaultInputDeviceID)) {
GetMuteOnInputAudioDevice(theDefaultInputDeviceID, &isMuted);
}
return isMuted;
}
void SetHardwareMute(Boolean theMute)
{
AudioDeviceID theDefaultInputDeviceID;
if (GetDefaultInputAudioDevice(&theDefaultInputDeviceID)) {
SetMuteOnInputAudioDevice(theDefaultInputDeviceID, theMute);
}
}

View File

@@ -0,0 +1,69 @@
//
// AudioMixer.h
// MuteUnmuteMic
//
// Created by Diogo Tridapalli on 10/5/15.
// Copyright © 2015 Gustavo Barbosa. All rights reserved.
//
#ifndef AudioMixer_h
#define AudioMixer_h
#import <CoreAudio/CoreAudio.h>
/**
* Get device id for the default input device
*
* @param defaultInputDeviceID AudioDeviceID pointer
*
* @return @a true if success @a false otherwise
*/
extern Boolean GetDefaultInputAudioDevice(AudioDeviceID *defaultInputDeviceID);
/**
* Get the name of an audio device
*
* @param deviceID AudioDeviceID
* @param deviceName CFStringRef reference, must be release after use
*
* @return @a true if success @a false otherwise
*/
extern Boolean GetAudioDeviceName(const AudioDeviceID deviceID,
CFStringRef *deviceName);
/**
* Get mute state on input device
*
* @param inputDeviceID AudioDeviceID
* @param isMuted @a true if device is muted @a false otherwise
*
* @return @a true if success @a false otherwise
*/
extern Boolean GetMuteOnInputAudioDevice(const AudioDeviceID inputDeviceID,
Boolean *isMuted);
/**
* Mute or unmute an inpute device
*
* @param inputDeviceID AudioDeviceID
* @param mute @a true if device should be muted @a false otherwise
*
* @return @a true if success @a false otherwise
*/
extern Boolean SetMuteOnInputAudioDevice(const AudioDeviceID inputDeviceID,
const Boolean mute);
/**
* Get the mute state of default input via HAL
*
* @return @a true if is muted @a false otherwise
*/
extern Boolean IsHardwareMuted();
/**
* Set the mute state of default input via HAL
*
* @param theMute @a true if should be muted @a false otherwise
*/
extern void SetHardwareMute(Boolean theMute);
#endif /* AudioMixer_h */