Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display UID and allow setting by a substring of UID #1

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@ switchaudio-osx requires command line tools to be installed from OS X. To instal
Usage
-----

SwitchAudioSource [-a] [-c] [-t type] [-n] -s device\_name | -i device\_id
SwitchAudioSource [-a] [-c] [-t type] [-n] -s device\_name | -i device\_id | -u device\_uid

- **-a** : shows all devices
- **-c** : shows current device
- **-t** _type_ : device type (input/output/system). Defaults to output.
- **-n** : cycles the audio device to the next one
- **-i** _device_id_ : sets the audio device to the given device by id
- **-u** _device_uid_ : sets the audio device to the given device by uid or a substring of the uid
- **-s** _device_name_ : sets the audio device to the given device by name


Expand Down
84 changes: 80 additions & 4 deletions audio_switch.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,28 @@ OTHER DEALINGS IN THE SOFTWARE.


void showUsage(const char * appName) {
printf("Usage: %s [-a] [-c] [-t type] [-n] -s device_name | -i device_id\n"
printf("Usage: %s [-a] [-c] [-t type] [-n] -s device_name | -i device_id | -u device_uid\n"
" -a : shows all devices\n"
" -c : shows current device\n\n"

" -t type : device type (input/output/system). Defaults to output.\n"
" -n : cycles the audio device to the next one\n"
" -i device_id : sets the audio device to the given device by id\n"
" -u device_uid : sets the audio device to the given device by uid or a substring of the uid\n"
" -s device_name : sets the audio device to the given device by name\n\n",appName);
}

int runAudioSwitch(int argc, const char * argv[]) {
char requestedDeviceName[256];
char printableDeviceName[256];
int requestedDeviceID;
char requestedDeviceUID[256];
AudioDeviceID chosenDeviceID = kAudioDeviceUnknown;
ASDeviceType typeRequested = kAudioTypeUnknown;
int function = 0;

int c;
while ((c = getopt(argc, (char **)argv, "hacnt:i:s:")) != -1) {
while ((c = getopt(argc, (char **)argv, "hacnt:i:s:u:")) != -1) {
switch (c) {
case 'a':
// show all
Expand All @@ -77,6 +79,12 @@ int runAudioSwitch(int argc, const char * argv[]) {
requestedDeviceID = atoi(optarg);
break;

case 'u':
// set the requestedDeviceUID
function = kFunctionSetDeviceByUID;
strcpy(requestedDeviceUID, optarg);
break;

case 's':
// set the requestedDeviceName
function = kFunctionSetDeviceByName;
Expand Down Expand Up @@ -165,6 +173,16 @@ int runAudioSwitch(int argc, const char * argv[]) {
strcpy(printableDeviceName, requestedDeviceName);
}

if (function == kFunctionSetDeviceByUID) {
// find the id of the requested device
chosenDeviceID = getRequestedDeviceIDFromUIDSubstring(requestedDeviceUID, typeRequested);
if (chosenDeviceID == kAudioDeviceUnknown) {
printf("Could not find an audio device with UID \"%s\" of type %s. Nothing was changed.\n", requestedDeviceUID, deviceTypeName(typeRequested));
return 1;
}
sprintf(printableDeviceName, "Device with UID: %s", getDeviceUID(chosenDeviceID));
}

if (!chosenDeviceID) {
printf("Please specify audio device.\n");
showUsage(argv[0]);
Expand All @@ -178,6 +196,64 @@ int runAudioSwitch(int argc, const char * argv[]) {
return 0;
}

char * getDeviceUID(AudioDeviceID deviceID) {
CFStringRef deviceUID = NULL;
UInt32 dataSize = sizeof(deviceUID);
AudioObjectPropertyAddress propertyAddress = {
kAudioHardwarePropertyDevices,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};

propertyAddress.mSelector = kAudioDevicePropertyDeviceUID;

AudioObjectGetPropertyData(deviceID, &propertyAddress, 0, NULL, &dataSize, &deviceUID);

char * deviceUID_string = CFStringGetCStringPtr(deviceUID, kCFStringEncodingASCII);

CFRelease(deviceUID);

return deviceUID_string;
}


AudioDeviceID getRequestedDeviceIDFromUIDSubstring(char * requestedDeviceUID, ASDeviceType typeRequested) {
UInt32 propertySize;
AudioDeviceID dev_array[64];
int numberOfDevices = 0;

AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &propertySize, NULL);
// printf("propertySize=%d\n",propertySize);

AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &propertySize, dev_array);
numberOfDevices = (propertySize / sizeof(AudioDeviceID));
// printf("numberOfDevices=%d\n",numberOfDevices);

for(int i = 0; i < numberOfDevices; ++i) {
switch(typeRequested) {
case kAudioTypeInput:
if (!isAnInputDevice(dev_array[i])) continue;
break;

case kAudioTypeOutput:
if (!isAnOutputDevice(dev_array[i])) continue;
break;

case kAudioTypeSystemOutput:
if (getDeviceType(dev_array[i]) != kAudioTypeOutput) continue;
break;
default: break;
}

char * deviceUID = getDeviceUID(dev_array[i]);

if (strstr(deviceUID, requestedDeviceUID) != NULL) {
return dev_array[i];
}
}

return kAudioDeviceUnknown;
}

AudioDeviceID getCurrentlySelectedDeviceID(ASDeviceType typeRequested) {
UInt32 propertySize;
Expand Down Expand Up @@ -259,7 +335,7 @@ void showCurrentlySelectedDeviceID(ASDeviceType typeRequested) {

currentDeviceID = getCurrentlySelectedDeviceID(typeRequested);
getDeviceName(currentDeviceID, currentDeviceName);
printf("%s\n",currentDeviceName);
printf("%s (ID: %u) (UID: %s)\n", currentDeviceName, currentDeviceID, getDeviceUID(currentDeviceID));
}


Expand Down Expand Up @@ -397,6 +473,6 @@ void showAllDevices(ASDeviceType typeRequested) {
}

getDeviceName(dev_array[i], deviceName);
printf("\"%s\" (ID: %u) (%s)\n", deviceName, dev_array[i], deviceTypeName(device_type));
printf("\"%s\" (ID: %u) (UID: %s) (%s)\n", deviceName, dev_array[i], getDeviceUID(dev_array[i]), deviceTypeName(device_type));
}
}
5 changes: 4 additions & 1 deletion audio_switch.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,16 @@ enum {
kFunctionShowAll = 3,
kFunctionShowCurrent = 4,
kFunctionCycleNext = 5,
kFunctionSetDeviceByID = 6
kFunctionSetDeviceByID = 6,
kFunctionSetDeviceByUID = 7
};



void showUsage(const char * appName);
int runAudioSwitch(int argc, const char * argv[]);
char * getDeviceUID(AudioDeviceID deviceID);
AudioDeviceID getRequestedDeviceIDFromUIDSubstring(char * requestedDeviceUID, ASDeviceType typeRequested);
AudioDeviceID getCurrentlySelectedDeviceID(ASDeviceType typeRequested);
void getDeviceName(AudioDeviceID deviceID, char * deviceName);
ASDeviceType getDeviceType(AudioDeviceID deviceID);
Expand Down