* Copyright 2003-2013, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Authors:
* JΓ©rΓ΄me Duval
* FranΓ§ois Revol
* Axel DΓΆrfler, axeld@pinc-software.de.
* Puck Meerburg, puck@puckipedia.nl
* Dario Casalinuovo, b.vitruvio@gmail.com
*/
#include "MixerControl.h"
#include <string.h>
#include <Debug.h>
#include <ParameterWeb.h>
MixerControl::MixerControl(int32 volumeWhich)
:
fVolumeWhich(volumeWhich),
fGainMediaNode(media_node::null),
fMuteMediaNode(media_node::null),
fParameterWeb(NULL),
fMixerParameter(NULL),
fMuteParameter(NULL),
fMin(0.0f),
fMax(0.0f),
fStep(0.0f),
fRoster(NULL)
{
fRoster = BMediaRoster::Roster();
}
MixerControl::~MixerControl()
{
_Disconnect();
}
bool
MixerControl::Connect(int32 volumeWhich, float* _value, const char** _error)
{
fVolumeWhich = volumeWhich;
_Disconnect();
status_t status = B_OK;
const char* errorString = NULL;
if (fRoster == NULL)
fRoster = BMediaRoster::Roster(&status);
if (BMediaRoster::IsRunning() && fRoster != NULL
&& status == B_OK) {
switch (volumeWhich) {
case VOLUME_USE_MIXER:
status = fRoster->GetAudioMixer(&fGainMediaNode);
break;
case VOLUME_USE_PHYS_OUTPUT:
status = fRoster->GetAudioOutput(&fGainMediaNode);
break;
}
if (status == B_OK) {
status = fRoster->GetParameterWebFor(fGainMediaNode, &fParameterWeb);
if (status == B_OK) {
int32 numParams = fParameterWeb->CountParameters();
BParameter* p = NULL;
bool foundMixerLabel = false;
for (int i = 0; i < numParams; i++) {
p = fParameterWeb->ParameterAt(i);
if (!strcmp(p->Kind(), B_MUTE)) {
fMuteParameter = p;
fMuteMediaNode = fMuteParameter->Web()->Node();
}
PRINT(("BParameter[%i]: %s\n", i, p->Name()));
if (volumeWhich == VOLUME_USE_MIXER) {
if (!strcmp(p->Kind(), B_MASTER_GAIN))
break;
} else if (volumeWhich == VOLUME_USE_PHYS_OUTPUT) {
* they don't seem to use Kind() == B_MASTER_GAIN
*/
if (!strcmp(p->Kind(), B_MASTER_GAIN))
break;
PRINT(("not MASTER_GAIN \n"));
*/
if (!strcmp(p->Name(), "Master"))
break;
PRINT(("not 'Master' \n"));
* need to fint the one that has the 'Mixer' text label
*/
if (foundMixerLabel && !strcmp(p->Name(), "Volume"))
break;
if (!strcmp(p->Name(), "Mixer"))
foundMixerLabel = true;
PRINT(("not 'Mixer' \n"));
}
#if 0
if (!strcmp(p->Kind(), B_MASTER_GAIN)) {
for (; i < numParams; i++) {
p = fParamWeb->ParameterAt(i);
if (strcmp(p->Kind(), B_MASTER_GAIN))
p = NULL;
else
break;
}
break;
} else
p = NULL;
#endif
p = NULL;
}
if (p == NULL) {
errorString = volumeWhich ? "Could not find the soundcard"
: "Could not find the mixer";
} else if (p->Type() != BParameter::B_CONTINUOUS_PARAMETER) {
errorString = volumeWhich ? "Soundcard control unknown"
: "Mixer control unknown";
} else {
fMixerParameter = static_cast<BContinuousParameter*>(p);
fMin = fMixerParameter->MinValue();
fMax = fMixerParameter->MaxValue();
fStep = fMixerParameter->ValueStep();
if (_value != NULL) {
float volume;
bigtime_t lastChange;
size_t size = sizeof(float);
fMixerParameter->GetValue(&volume, &size, &lastChange);
*_value = volume;
}
}
} else {
errorString = "No parameter web";
fParameterWeb = NULL;
}
} else
errorString = volumeWhich ? "No Audio output" : "No Mixer";
} else
errorString = "Media services not running";
if (status != B_OK) {
_Disconnect();
fMuteMediaNode = media_node::null;
}
if (errorString) {
fprintf(stderr, "MixerControl: %s.\n", errorString);
if (_error)
*_error = errorString;
}
if (fMixerParameter == NULL && _value != NULL)
*_value = 0;
return errorString == NULL;
}
bool
MixerControl::Connected()
{
return fGainMediaNode != media_node::null;
}
int32
MixerControl::VolumeWhich() const
{
return fVolumeWhich;
}
void
MixerControl::SetMute(bool muted)
{
if (fMuteParameter == NULL)
return;
int32 mute = muted ? 1 : 0;
fMuteParameter->SetValue(&mute, sizeof(int32), system_time());
}
bool
MixerControl::Mute()
{
if (fMuteParameter == NULL)
return false;
int32 mute = 0;
bigtime_t lastChange = 0;
size_t size = sizeof(int32);
fMuteParameter->GetValue(&mute, &size, &lastChange);
return mute != 0;
}
float
MixerControl::Volume() const
{
if (fMixerParameter == NULL)
return 0.0f;
float volume = 0;
bigtime_t lastChange;
size_t size = sizeof(float);
fMixerParameter->GetValue(&volume, &size, &lastChange);
return volume;
}
void
MixerControl::SetVolume(float volume)
{
if (fMixerParameter == NULL)
return;
if (volume < fMin)
volume = fMin;
else if (volume > fMax)
volume = fMax;
if (volume != Volume())
fMixerParameter->SetValue(&volume, sizeof(float), system_time());
}
void
MixerControl::ChangeVolumeBy(float value)
{
if (fMixerParameter == NULL || value == 0.0f)
return;
float volume = Volume();
SetVolume(volume + value);
}
void
MixerControl::_Disconnect()
{
delete fParameterWeb;
fParameterWeb = NULL;
fMixerParameter = NULL;
if (fRoster == NULL)
fRoster = BMediaRoster::Roster();
if (fRoster != NULL && fGainMediaNode != media_node::null)
fRoster->ReleaseNode(fGainMediaNode);
fGainMediaNode = media_node::null;
}