+#import "CoreInteraction.h"
+#import <CoreAudio/CoreAudio.h>
+#import <vlc_keys.h>
+
+
+/*****************************************************************************
+ * NSSound (VLCAdditions)
+ *
+ * added code to change the system volume, needed for the apple remote code
+ * this is simplified code, which won't let you set the exact volume
+ * (that's what the audio output is for after all), but just the system volume
+ * in steps of 1/16 (matching the default AR or volume key implementation).
+ *****************************************************************************/
+
+@implementation NSSound (VLCAdditions)
+
++ (float)systemVolumeForChannel:(int)channel
+{
+ AudioDeviceID i_device;
+ float f_volume;
+ OSStatus err;
+ UInt32 i_size;
+
+ i_size = sizeof( i_device );
+ AudioObjectPropertyAddress deviceAddress = { kAudioHardwarePropertyDefaultOutputDevice, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster };
+ err = AudioObjectGetPropertyData( kAudioObjectSystemObject, &deviceAddress, 0, NULL, &i_size, &i_device );
+ if (err != noErr) {
+ msg_Warn( VLCIntf, "couldn't get main audio output device" );
+ return .0;
+ }
+
+ AudioObjectPropertyAddress propertyAddress = { kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeOutput, channel };
+ i_size = sizeof( f_volume );
+ err = AudioObjectGetPropertyData(i_device, &propertyAddress, 0, NULL, &i_size, &f_volume);
+ if (err != noErr) {
+ msg_Warn( VLCIntf, "couldn't get volume value" );
+ return .0;
+ }
+
+ return f_volume;
+}
+
++ (bool)setSystemVolume:(float)f_volume forChannel:(int)i_channel
+{
+ /* the following code will fail on S/PDIF devices. there is an easy work-around, but we'd like to match the OS behavior */
+
+ AudioDeviceID i_device;
+ OSStatus err;
+ UInt32 i_size;
+ Boolean b_writeable;
+
+ i_size = sizeof( i_device );
+ AudioObjectPropertyAddress deviceAddress = { kAudioHardwarePropertyDefaultOutputDevice, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster };
+ err = AudioObjectGetPropertyData( kAudioObjectSystemObject, &deviceAddress, 0, NULL, &i_size, &i_device );
+ if (err != noErr) {
+ msg_Warn( VLCIntf, "couldn't get main audio output device" );
+ return NO;
+ }
+
+ AudioObjectPropertyAddress propertyAddress = { kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeOutput, i_channel };
+ i_size = sizeof( f_volume );
+ err = AudioObjectIsPropertySettable( i_device, &propertyAddress, &b_writeable );
+ if (err != noErr || !b_writeable ) {
+ msg_Warn( VLCIntf, "we can't set the main audio devices' volume" );
+ return NO;
+ }
+ err = AudioObjectSetPropertyData(i_device, &propertyAddress, 0, NULL, i_size, &f_volume);
+
+ return YES;
+}
+
++ (void)increaseSystemVolume
+{
+ float f_volume = [NSSound systemVolumeForChannel:1]; // we trust that mono is always available and that all channels got the same volume
+ f_volume += .0625; // 1/16 to match the OS
+ bool b_returned = YES;
+
+ /* since core audio doesn't provide a reasonable way to see how many channels we got, let's see how long we can do this */
+ for (NSUInteger x = 1; b_returned ; x++)
+ b_returned = [NSSound setSystemVolume: f_volume forChannel:x];
+}
+
++ (void)decreaseSystemVolume
+{
+ float f_volume = [NSSound systemVolumeForChannel:1]; // we trust that mono is always available and that all channels got the same volume
+ f_volume -= .0625; // 1/16 to match the OS
+ bool b_returned = YES;
+
+ /* since core audio doesn't provide a reasonable way to see how many channels we got, let's see how long we can do this */
+ for (NSUInteger x = 1; b_returned ; x++)
+ b_returned = [NSSound setSystemVolume: f_volume forChannel:x];
+}
+
+@end