ConfigDefaultOutput.c
/* Copyright © 2007 Apple Inc. All Rights Reserved. |
Disclaimer: IMPORTANT: This Apple software is supplied to you by |
Apple Inc. ("Apple") in consideration of your agreement to the |
following terms, and your use, installation, modification or |
redistribution of this Apple software constitutes acceptance of these |
terms. If you do not agree with these terms, please do not use, |
install, modify or redistribute this Apple software. |
In consideration of your agreement to abide by the following terms, and |
subject to these terms, Apple grants you a personal, non-exclusive |
license, under Apple's copyrights in this original Apple software (the |
"Apple Software"), to use, reproduce, modify and redistribute the Apple |
Software, with or without modifications, in source and/or binary forms; |
provided that if you redistribute the Apple Software in its entirety and |
without modifications, you must retain this notice and the following |
text and disclaimers in all such redistributions of the Apple Software. |
Neither the name, trademarks, service marks or logos of Apple Inc. |
may be used to endorse or promote products derived from the Apple |
Software without specific prior written permission from Apple. Except |
as expressly stated in this notice, no other rights or licenses, express |
or implied, are granted by Apple herein, including but not limited to |
any patent rights that may be infringed by your derivative works or by |
other works in which the Apple Software may be incorporated. |
The Apple Software is provided by Apple on an "AS IS" basis. APPLE |
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION |
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS |
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND |
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. |
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL |
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, |
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED |
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), |
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE |
POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <stdio.h> |
#include <CoreAudio/CoreAudio.h> |
static void usage() |
{ |
fprintf(stderr, |
"Usage:\n" |
"%s [option...] input_file output_file\n\n" |
"Options: (may appear before or after arguments)\n" |
" {-a | --all}\n" |
" {-d | --device} DEVICE\n" |
" set DEVICE as the default output device\n" |
" print all known devices on the system\n" |
" {-v | --volume} VOLUME\n" |
" set the volume for the default output device\n" |
" {-m | --mute} MUTE\n" |
" set mute on (1) or off (0) for the default output device\n" |
" {-h | --help}\n" |
" print help\n" |
, "ConfigDefaultOutput"); |
exit(1); |
} |
void MissingArgument() |
{ |
fprintf(stderr, "Missing argument\n"); |
usage(); |
} |
int main (int argc, const char * argv[]) |
{ |
OSStatus result = noErr; |
Float32 theVolume = 0.0; |
UInt32 theMute = 0; |
Boolean doSetMute = false, doPrintDeviceList = false; |
const char* theNewDefaultDeviceString = NULL; |
Boolean didFindNewDevice = false; |
CFStringRef theNewDefaultDeviceName = 0; |
for (int i = 1; i < argc; ++i) { |
const char *arg = argv[i]; |
if (arg[0] != '-') { |
usage(); |
} else { |
arg += 1; |
if (arg[0] == 'v' || !strcmp(arg, "-volume")) { |
if (++i == argc) |
MissingArgument(); |
arg = argv[i]; |
sscanf(arg, "%f", &theVolume); |
} else if (arg[0] == 'm' || !strcmp(arg, "-mute")) { |
if (++i == argc) |
MissingArgument(); |
arg = argv[i]; |
doSetMute = true; |
sscanf(arg, "%d", &theMute); |
} else if (arg[0] == 'd' || !strcmp(arg, "-device")) { |
if (++i == argc) |
MissingArgument(); |
theNewDefaultDeviceString = argv[i]; |
theNewDefaultDeviceName = CFStringCreateWithCString(kCFAllocatorDefault, theNewDefaultDeviceString, CFStringGetSystemEncoding()); |
} else if (arg[0] == 'a' || !strcmp(arg, "-all")) { |
doPrintDeviceList = true; |
} else if (arg[0] == 'h' || !strcmp(arg, "-help")) { |
usage(); |
} else { |
fprintf(stderr, "unknown argument: %s\n\n", arg - 1); |
usage(); |
} |
} |
} |
UInt32 thePropSize; |
AudioDeviceID *theDeviceList = NULL; |
UInt32 theNumDevices = 0; |
if (doPrintDeviceList || theNewDefaultDeviceString) |
{ |
// get the device list |
AudioObjectPropertyAddress thePropertyAddress = { kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; |
result = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &thePropertyAddress, 0, NULL, &thePropSize); |
if (result) { printf("Error in AudioObjectGetPropertyDataSize: %d\n", result); goto end; } |
// Find out how many devices are on the system |
theNumDevices = thePropSize / sizeof(AudioDeviceID); |
theDeviceList = (AudioDeviceID*)calloc(theNumDevices, sizeof(AudioDeviceID)); |
result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &thePropertyAddress, 0, NULL, &thePropSize, theDeviceList); |
if (result) { printf("Error in AudioObjectGetPropertyData: %d\n", result); goto end; } |
CFStringRef theDeviceName; |
for (UInt32 i=0; i < theNumDevices; i++) |
{ |
// get the device name |
thePropSize = sizeof(CFStringRef); |
thePropertyAddress.mSelector = kAudioObjectPropertyName; |
thePropertyAddress.mScope = kAudioObjectPropertyScopeGlobal; |
thePropertyAddress.mElement = kAudioObjectPropertyElementMaster; |
result = AudioObjectGetPropertyData(theDeviceList[i], &thePropertyAddress, 0, NULL, &thePropSize, &theDeviceName); |
if (result) { printf("Error in AudioObjectGetPropertyData: %d\n", result); goto end; } |
if (doPrintDeviceList) |
CFShow(theDeviceName); |
if (theNewDefaultDeviceString) |
{ |
if (CFStringCompare(theDeviceName, theNewDefaultDeviceName, 0) == kCFCompareEqualTo) |
{ |
// we found the device, now it as the default output device |
thePropertyAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice; |
thePropertyAddress.mScope = kAudioObjectPropertyScopeGlobal; |
thePropertyAddress.mElement = kAudioObjectPropertyElementMaster; |
result = AudioObjectSetPropertyData(kAudioObjectSystemObject, &thePropertyAddress, 0, NULL, sizeof(AudioDeviceID), &theDeviceList[i]); |
if (result) { printf("Error in AudioObjectSetPropertyData: kAudioHardwarePropertyDefaultOutputDevice: %d\n", result); goto end; } |
else |
{ |
didFindNewDevice = true; |
printf("\tSuccessfully changed default output device to %s\n", theNewDefaultDeviceString); |
if (!doPrintDeviceList) break; |
} |
} |
} |
CFRelease(theDeviceName); |
} |
if (theNewDefaultDeviceString) |
{ |
if (!didFindNewDevice) |
printf("Error! Could not find specified device %s. Using current default output device\n", theNewDefaultDeviceString); |
CFRelease(theNewDefaultDeviceName); |
} |
} |
if (doSetMute || theVolume > 0.) |
{ |
AudioDeviceID theDefaultOutputDeviceID; |
thePropSize = sizeof(theDefaultOutputDeviceID); |
CFStringRef theDefaultOutputDeviceName; |
AudioObjectPropertyAddress thePropertyAddress = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; |
// get the ID of the default output device |
result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &thePropertyAddress, 0, NULL, &thePropSize, &theDefaultOutputDeviceID); |
if (result) { printf("Error in AudioObjectGetPropertyData: %d\n", result); goto end; } |
thePropSize = sizeof(CFStringRef); |
thePropertyAddress.mSelector = kAudioObjectPropertyName; |
thePropertyAddress.mScope = kAudioObjectPropertyScopeGlobal; |
thePropertyAddress.mElement = kAudioObjectPropertyElementMaster; |
// get the name of the default output device |
result = AudioObjectGetPropertyData(theDefaultOutputDeviceID, &thePropertyAddress, 0, NULL, &thePropSize, &theDefaultOutputDeviceName); |
if (result) { printf("Error in AudioObjectGetPropertyData: %d\n", result); goto end; } |
const char* theDefaultOutputDeviceString = CFStringGetCStringPtr(theDefaultOutputDeviceName, CFStringGetSystemEncoding()); |
if (doSetMute) |
{ |
thePropSize = sizeof(theMute); |
thePropertyAddress.mSelector = kAudioDevicePropertyMute; |
thePropertyAddress.mScope = kAudioDevicePropertyScopeOutput; |
thePropertyAddress.mElement = kAudioObjectPropertyElementMaster; |
// check if the device supports setting mute |
if (AudioObjectHasProperty(theDefaultOutputDeviceID, &thePropertyAddress)) |
{ |
printf("\tSetting %s mute %s\n", theDefaultOutputDeviceString, (theMute) ? "on" : "off"); |
// if so then set it |
result = AudioObjectSetPropertyData(theDefaultOutputDeviceID, &thePropertyAddress, 0, NULL, thePropSize, &theMute); |
if (result) { printf("Error in AudioObjectSetPropertyData: %d\n", result); goto end; } |
} |
else |
{ |
// if the device does not support master mute control, do nothing |
printf("Error: the default output device does not support mute control\n"); |
} |
} |
if (theVolume > 0.) |
{ |
thePropSize = sizeof(theVolume); |
thePropertyAddress.mSelector = kAudioDevicePropertyVolumeScalar; |
thePropertyAddress.mScope = kAudioDevicePropertyScopeOutput; |
thePropertyAddress.mElement = kAudioObjectPropertyElementMaster; |
// see if the device supports volume control, if so, then set the user specified volume |
if (AudioObjectHasProperty(theDefaultOutputDeviceID, &thePropertyAddress)) |
{ |
printf("\tSetting %s volume to %g\n", theDefaultOutputDeviceString, theVolume); |
result = AudioObjectSetPropertyData(theDefaultOutputDeviceID, &thePropertyAddress, 0, NULL, thePropSize, &theVolume); |
if (result) { printf("Error in AudioObjectSetPropertyData: %d\n", result); goto end; } |
} |
else |
{ |
// if the device does not support master volume control, do nothing |
printf("Error: the default output device does not support volume control\n"); |
} |
} |
CFRelease(theDefaultOutputDeviceName); |
} |
end: |
if (theDeviceList) |
free(theDeviceList); |
return result; |
} |
Copyright © 2009 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2009-04-15