pjv
pjv

Reputation: 566

Cannot get output volume from any audio devices from cocoa objective-c

i'm trying to implement a volume control in a mac os x application. when i run code that loops over the audio devices installed in my macbook pro and queries their master volume (or individual channel volumes -- i've tried that too), i cannot get any results.

here is the code i am running:

- (NSArray*)getAudioDevices
{
  AudioObjectPropertyAddress propertyAddress = { 
    kAudioHardwarePropertyDevices, 
    kAudioObjectPropertyScopeGlobal, 
    kAudioObjectPropertyElementMaster 
  };

  UInt32 dataSize = 0;
  OSStatus status = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize);
  if(kAudioHardwareNoError != status)
  {
    NSLog(@"Unable to get number of audio devices. Error: %d",status);
    return NULL;
  }

  UInt32 deviceCount = dataSize / sizeof(AudioDeviceID);

  AudioDeviceID *audioDevices = malloc(dataSize);

  status = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize, audioDevices);
  if(kAudioHardwareNoError != status) 
  {
    NSLog(@"AudioObjectGetPropertyData failed when getting device IDs. Error: %d",status);
    free(audioDevices), audioDevices = NULL;
    return NULL;
  }

  NSMutableArray* devices = [NSMutableArray array];

  for(UInt32 i = 0; i < deviceCount; i++)
  {    

    // Query device name
    CFStringRef deviceName = NULL;
    dataSize = sizeof(deviceName);
    propertyAddress.mSelector = kAudioDevicePropertyDeviceNameCFString;
    status = AudioObjectGetPropertyData(audioDevices[i], &propertyAddress, 0, NULL, &dataSize, &deviceName);
    if(kAudioHardwareNoError != status) {
      fprintf(stderr, "AudioObjectGetPropertyData (kAudioDevicePropertyDeviceNameCFString) failed: %i\n", status);
      continue;
    }

    // Query device output volume
    Float32 volume;
    propertyAddress.mSelector = kAudioHardwareServiceDeviceProperty_VirtualMasterVolume;
    status = AudioHardwareServiceHasProperty(audioDevices[i], &propertyAddress);
    if(status) {
      fprintf(stderr, "AudioObjectGetPropertyData (kAudioHardwareServiceDeviceProperty_VirtualMasterVolume) failed: %i\n", status);
    } else {
      dataSize = sizeof(volume);
      status = AudioObjectGetPropertyData(audioDevices[i], &propertyAddress, 0, NULL, &dataSize, &volume);
      if (status) {
        // handle error
      }
    }

    NSLog(@"device found: %d - %@ || Vol: %f || status %i",audioDevices[i], deviceName, volume, status);  

    [devices addObject:[NSNumber numberWithInt:audioDevices[i]]];
  }

  free(audioDevices);

  return [NSArray arrayWithArray:devices];
}

and the output that i get from the log:

device found: 58 - Built-in Microphone || Vol: 0.000000 || status 2003332927
device found: 78 - Built-in Input || Vol: 0.000000 || status 2003332927
device found: 68 - Built-in Output || Vol: 0.000000 || status 2003332927
device found: 54 - Microsoft LifeCam VX-5000 || Vol: 0.000000 || status 2003332927
device found: 87 - Microsoft LifeChat LX-3000  || Vol: 0.000000 || status 2003332927

i'm running OS X 10.7.3 / Xcode 4.3.2

the volumes on the devices are not actually set at zero. can anyone tell me why i can't get any values?

Upvotes: 2

Views: 1751

Answers (1)

Nick
Nick

Reputation: 9860

I'm not sure your propertyAddress is formed correctly just by changing the mSelector. Try creating a new propertyAddress with these values:

AudioObjectPropertyAddress propertyAddress = { 
    kAudioDevicePropertyVolumeScalar, 
    kAudioDevicePropertyScopeOutput,
    1 
};

And use that in your final AudioObjectGetPropertyData call.

Upvotes: 2

Related Questions