xref: /haiku/src/bin/desklink/MixerControl.cpp (revision b31cb92f29fe89eaca84d173d0f70d38bf0c6a3d)
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 		fGainMediaNode = media_node::null;
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