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