1 /* 2 * Copyright 2003-2013, Haiku, Inc. 3 * Distributed under the terms of the MIT license. 4 * 5 * Authors: 6 * Jérôme Duval 7 * François Revol 8 * Axel Dörfler, axeld@pinc-software.de. 9 * Puck Meerburg, puck@puckipedia.nl 10 * Dario Casalinuovo, b.vitruvio@gmail.com 11 */ 12 13 14 #include "MixerControl.h" 15 16 #include <string.h> 17 18 #include <Debug.h> 19 #include <ParameterWeb.h> 20 21 22 MixerControl::MixerControl(int32 volumeWhich) 23 : 24 fVolumeWhich(volumeWhich), 25 fGainMediaNode(media_node::null), 26 fParameterWeb(NULL), 27 fMixerParameter(NULL), 28 fMuteParameter(NULL), 29 fMin(0.0f), 30 fMax(0.0f), 31 fStep(0.0f), 32 fRoster(NULL) 33 { 34 fRoster = BMediaRoster::Roster(); 35 } 36 37 38 MixerControl::~MixerControl() 39 { 40 _Disconnect(); 41 } 42 43 44 bool 45 MixerControl::Connect(int32 volumeWhich, float* _value, const char** _error) 46 { 47 fVolumeWhich = volumeWhich; 48 49 _Disconnect(); 50 51 status_t status = B_OK; 52 const char* errorString = NULL; 53 if (fRoster == NULL) 54 fRoster = BMediaRoster::Roster(&status); 55 56 if (BMediaRoster::IsRunning() && fRoster != NULL 57 && status == B_OK) { 58 switch (volumeWhich) { 59 case VOLUME_USE_MIXER: 60 status = fRoster->GetAudioMixer(&fGainMediaNode); 61 break; 62 case VOLUME_USE_PHYS_OUTPUT: 63 status = fRoster->GetAudioOutput(&fGainMediaNode); 64 break; 65 } 66 if (status == B_OK) { 67 status = fRoster->GetParameterWebFor(fGainMediaNode, &fParameterWeb); 68 if (status == B_OK) { 69 // Finding the Mixer slider in the audio output ParameterWeb 70 int32 numParams = fParameterWeb->CountParameters(); 71 BParameter* p = NULL; 72 bool foundMixerLabel = false; 73 for (int i = 0; i < numParams; i++) { 74 p = fParameterWeb->ParameterAt(i); 75 76 // assume the mute preceeding master gain control 77 if (!strcmp(p->Kind(), B_MUTE)) 78 fMuteParameter = p; 79 80 PRINT(("BParameter[%i]: %s\n", i, p->Name())); 81 if (volumeWhich == VOLUME_USE_MIXER) { 82 if (!strcmp(p->Kind(), B_MASTER_GAIN)) 83 break; 84 } else if (volumeWhich == VOLUME_USE_PHYS_OUTPUT) { 85 /* not all cards use the same name, and 86 * they don't seem to use Kind() == B_MASTER_GAIN 87 */ 88 if (!strcmp(p->Kind(), B_MASTER_GAIN)) 89 break; 90 PRINT(("not MASTER_GAIN \n")); 91 92 /* some audio card 93 */ 94 if (!strcmp(p->Name(), "Master")) 95 break; 96 PRINT(("not 'Master' \n")); 97 98 /* some Ensonic card have all controls names 'Volume', so 99 * need to fint the one that has the 'Mixer' text label 100 */ 101 if (foundMixerLabel && !strcmp(p->Name(), "Volume")) 102 break; 103 if (!strcmp(p->Name(), "Mixer")) 104 foundMixerLabel = true; 105 PRINT(("not 'Mixer' \n")); 106 } 107 #if 0 108 //if (!strcmp(p->Name(), "Master")) { 109 if (!strcmp(p->Kind(), B_MASTER_GAIN)) { 110 for (; i < numParams; i++) { 111 p = fParamWeb->ParameterAt(i); 112 if (strcmp(p->Kind(), B_MASTER_GAIN)) 113 p = NULL; 114 else 115 break; 116 } 117 break; 118 } else 119 p = NULL; 120 #endif 121 p = NULL; 122 } 123 if (p == NULL) { 124 errorString = volumeWhich ? "Could not find the soundcard" 125 : "Could not find the mixer"; 126 } else if (p->Type() != BParameter::B_CONTINUOUS_PARAMETER) { 127 errorString = volumeWhich ? "Soundcard control unknown" 128 : "Mixer control unknown"; 129 } else { 130 fMixerParameter = static_cast<BContinuousParameter*>(p); 131 fMin = fMixerParameter->MinValue(); 132 fMax = fMixerParameter->MaxValue(); 133 fStep = fMixerParameter->ValueStep(); 134 135 if (_value != NULL) { 136 float volume; 137 bigtime_t lastChange; 138 size_t size = sizeof(float); 139 fMixerParameter->GetValue(&volume, &size, &lastChange); 140 141 *_value = volume; 142 } 143 } 144 } else { 145 errorString = "No parameter web"; 146 fParameterWeb = NULL; 147 } 148 } else 149 errorString = volumeWhich ? "No Audio output" : "No Mixer"; 150 151 } else 152 errorString = "Media services not running"; 153 154 if (status != B_OK) 155 fGainMediaNode = media_node::null; 156 157 if (errorString) { 158 fprintf(stderr, "MixerControl: %s.\n", errorString); 159 if (_error) 160 *_error = errorString; 161 } 162 if (fMixerParameter == NULL && _value != NULL) 163 *_value = 0; 164 165 return errorString == NULL; 166 } 167 168 169 bool 170 MixerControl::Connected() 171 { 172 return fGainMediaNode != media_node::null; 173 } 174 175 176 int32 177 MixerControl::VolumeWhich() const 178 { 179 return fVolumeWhich; 180 } 181 182 183 void 184 MixerControl::SetMute(bool muted) 185 { 186 if (fMuteParameter == NULL) 187 return; 188 189 int32 mute = muted ? 1 : 0; 190 fMuteParameter->SetValue(&mute, sizeof(int32), system_time()); 191 } 192 193 194 bool 195 MixerControl::Mute() 196 { 197 if (fMuteParameter == NULL) 198 return false; 199 200 int32 mute = 0; 201 bigtime_t lastChange = 0; 202 size_t size = sizeof(int32); 203 fMuteParameter->GetValue(&mute, &size, &lastChange); 204 return mute != 0; 205 } 206 207 208 float 209 MixerControl::Volume() const 210 { 211 if (fMixerParameter == NULL) 212 return 0.0f; 213 214 float volume = 0; 215 bigtime_t lastChange; 216 size_t size = sizeof(float); 217 fMixerParameter->GetValue(&volume, &size, &lastChange); 218 219 return volume; 220 } 221 222 223 void 224 MixerControl::SetVolume(float volume) 225 { 226 if (fMixerParameter == NULL) 227 return; 228 229 if (volume < fMin) 230 volume = fMin; 231 else if (volume > fMax) 232 volume = fMax; 233 234 if (volume != Volume()) 235 fMixerParameter->SetValue(&volume, sizeof(float), system_time()); 236 } 237 238 239 void 240 MixerControl::ChangeVolumeBy(float value) 241 { 242 if (fMixerParameter == NULL || value == 0.0f) 243 return; 244 245 float volume = Volume(); 246 SetVolume(volume + value); 247 } 248 249 250 void 251 MixerControl::_Disconnect() 252 { 253 delete fParameterWeb; 254 fParameterWeb = NULL; 255 fMixerParameter = NULL; 256 257 if (fRoster == NULL) 258 fRoster = BMediaRoster::Roster(); 259 260 if (fRoster != NULL && fGainMediaNode != media_node::null) 261 fRoster->ReleaseNode(fGainMediaNode); 262 263 fGainMediaNode = media_node::null; 264 } 265