vfs: check userland buffers before reading them.
[haiku.git] / src / bin / desklink / MixerControl.cpp
blobcdc6d3ffa754c0de443728e7580c0d631fb319f6
1 /*
2 * Copyright 2003-2013, Haiku, Inc.
3 * Distributed under the terms of the MIT license.
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
14 #include "MixerControl.h"
16 #include <string.h>
18 #include <Debug.h>
19 #include <ParameterWeb.h>
22 MixerControl::MixerControl(int32 volumeWhich)
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)
35 fRoster = BMediaRoster::Roster();
39 MixerControl::~MixerControl()
41 _Disconnect();
45 bool
46 MixerControl::Connect(int32 volumeWhich, float* _value, const char** _error)
48 fVolumeWhich = volumeWhich;
50 _Disconnect();
52 status_t status = B_OK;
53 const char* errorString = NULL;
54 if (fRoster == NULL)
55 fRoster = BMediaRoster::Roster(&status);
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;
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);
77 // assume the mute preceeding master gain control
78 if (!strcmp(p->Kind(), B_MUTE)) {
79 fMuteParameter = p;
80 fMuteMediaNode = fMuteParameter->Web()->Node();
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
91 if (!strcmp(p->Kind(), B_MASTER_GAIN))
92 break;
93 PRINT(("not MASTER_GAIN \n"));
95 /* some audio card
97 if (!strcmp(p->Name(), "Master"))
98 break;
99 PRINT(("not 'Master' \n"));
101 /* some Ensonic card have all controls names 'Volume', so
102 * need to fint the one that has the 'Mixer' text label
104 if (foundMixerLabel && !strcmp(p->Name(), "Volume"))
105 break;
106 if (!strcmp(p->Name(), "Mixer"))
107 foundMixerLabel = true;
108 PRINT(("not 'Mixer' \n"));
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;
120 break;
121 } else
122 p = NULL;
123 #endif
124 p = NULL;
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();
138 if (_value != NULL) {
139 float volume;
140 bigtime_t lastChange;
141 size_t size = sizeof(float);
142 fMixerParameter->GetValue(&volume, &size, &lastChange);
144 *_value = volume;
147 } else {
148 errorString = "No parameter web";
149 fParameterWeb = NULL;
151 } else
152 errorString = volumeWhich ? "No Audio output" : "No Mixer";
154 } else
155 errorString = "Media services not running";
157 if (status != B_OK) {
158 fGainMediaNode = media_node::null;
159 fMuteMediaNode = media_node::null;
162 if (errorString) {
163 fprintf(stderr, "MixerControl: %s.\n", errorString);
164 if (_error)
165 *_error = errorString;
167 if (fMixerParameter == NULL && _value != NULL)
168 *_value = 0;
170 return errorString == NULL;
174 bool
175 MixerControl::Connected()
177 return fGainMediaNode != media_node::null;
181 int32
182 MixerControl::VolumeWhich() const
184 return fVolumeWhich;
188 void
189 MixerControl::SetMute(bool muted)
191 if (fMuteParameter == NULL)
192 return;
194 int32 mute = muted ? 1 : 0;
195 fMuteParameter->SetValue(&mute, sizeof(int32), system_time());
199 bool
200 MixerControl::Mute()
202 if (fMuteParameter == NULL)
203 return false;
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;
213 float
214 MixerControl::Volume() const
216 if (fMixerParameter == NULL)
217 return 0.0f;
219 float volume = 0;
220 bigtime_t lastChange;
221 size_t size = sizeof(float);
222 fMixerParameter->GetValue(&volume, &size, &lastChange);
224 return volume;
228 void
229 MixerControl::SetVolume(float volume)
231 if (fMixerParameter == NULL)
232 return;
234 if (volume < fMin)
235 volume = fMin;
236 else if (volume > fMax)
237 volume = fMax;
239 if (volume != Volume())
240 fMixerParameter->SetValue(&volume, sizeof(float), system_time());
244 void
245 MixerControl::ChangeVolumeBy(float value)
247 if (fMixerParameter == NULL || value == 0.0f)
248 return;
250 float volume = Volume();
251 SetVolume(volume + value);
255 void
256 MixerControl::_Disconnect()
258 delete fParameterWeb;
259 fParameterWeb = NULL;
260 fMixerParameter = NULL;
262 if (fRoster == NULL)
263 fRoster = BMediaRoster::Roster();
265 if (fRoster != NULL && fGainMediaNode != media_node::null)
266 fRoster->ReleaseNode(fGainMediaNode);
268 fGainMediaNode = media_node::null;