macOS: Move NSSound category to its own file
[vlc.git] / modules / gui / macosx / NSSound+VLCAdditions.m
1 /*****************************************************************************
2  * NSSound+VLCAdditions.m: Category that adds system volume control
3  *****************************************************************************
4  * Copyright (C) 2003-2014 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8  *          Felix Paul K├╝hne <fkuehne at videolan dot org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #import "NSSound+VLCAdditions.h"
26 #import "VLCMain.h"
27
28 #import <CoreAudio/CoreAudio.h>
29
30 @implementation NSSound (VLCAdditions)
31
32 + (float)systemVolumeForChannel:(int)channel
33 {
34     AudioDeviceID i_device;
35     float f_volume;
36     OSStatus err;
37     UInt32 i_size;
38
39     i_size = sizeof( i_device );
40     AudioObjectPropertyAddress deviceAddress = { kAudioHardwarePropertyDefaultOutputDevice, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster };
41     err = AudioObjectGetPropertyData( kAudioObjectSystemObject, &deviceAddress, 0, NULL, &i_size, &i_device );
42     if (err != noErr) {
43         msg_Warn( getIntf(), "couldn't get main audio output device" );
44         return .0;
45     }
46
47     AudioObjectPropertyAddress propertyAddress = { kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeOutput, channel };
48     i_size = sizeof( f_volume );
49     err = AudioObjectGetPropertyData(i_device, &propertyAddress, 0, NULL, &i_size, &f_volume);
50     if (err != noErr) {
51         msg_Warn( getIntf(), "couldn't get volume value" );
52         return .0;
53     }
54
55     return f_volume;
56 }
57
58 + (bool)setSystemVolume:(float)f_volume forChannel:(int)i_channel
59 {
60     /* the following code will fail on S/PDIF devices. there is an easy work-around, but we'd like to match the OS behavior */
61
62     AudioDeviceID i_device;
63     OSStatus err;
64     UInt32 i_size;
65     Boolean b_writeable;
66
67     i_size = sizeof( i_device );
68     AudioObjectPropertyAddress deviceAddress = { kAudioHardwarePropertyDefaultOutputDevice, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster };
69     err = AudioObjectGetPropertyData( kAudioObjectSystemObject, &deviceAddress, 0, NULL, &i_size, &i_device );
70     if (err != noErr) {
71         msg_Warn( getIntf(), "couldn't get main audio output device" );
72         return NO;
73     }
74
75     AudioObjectPropertyAddress propertyAddress = { kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeOutput, i_channel };
76     i_size = sizeof( f_volume );
77     err = AudioObjectIsPropertySettable( i_device, &propertyAddress, &b_writeable );
78     if (err != noErr || !b_writeable ) {
79         msg_Warn( getIntf(), "we can't set the main audio devices' volume" );
80         return NO;
81     }
82     err = AudioObjectSetPropertyData(i_device, &propertyAddress, 0, NULL, i_size, &f_volume);
83
84     return YES;
85 }
86
87 + (void)increaseSystemVolume
88 {
89     float f_volume = [NSSound systemVolumeForChannel:1]; // we trust that mono is always available and that all channels got the same volume
90     f_volume += .0625; // 1/16 to match the OS
91     bool b_returned = YES;
92
93     /* 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 */
94     for (NSUInteger x = 1; b_returned ; x++)
95         b_returned = [NSSound setSystemVolume: f_volume forChannel:x];
96 }
97
98 + (void)decreaseSystemVolume
99 {
100     float f_volume = [NSSound systemVolumeForChannel:1]; // we trust that mono is always available and that all channels got the same volume
101     f_volume -= .0625; // 1/16 to match the OS
102     bool b_returned = YES;
103
104     /* 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 */
105     for (NSUInteger x = 1; b_returned ; x++)
106         b_returned = [NSSound setSystemVolume: f_volume forChannel:x];
107 }
108
109 @end