/* * 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 #include #include 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) { // Finding the Mixer slider in the audio output ParameterWeb int32 numParams = fParameterWeb->CountParameters(); BParameter* p = NULL; bool foundMixerLabel = false; for (int i = 0; i < numParams; i++) { p = fParameterWeb->ParameterAt(i); // assume the mute preceeding master gain control 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) { /* not all cards use the same name, and * they don't seem to use Kind() == B_MASTER_GAIN */ if (!strcmp(p->Kind(), B_MASTER_GAIN)) break; PRINT(("not MASTER_GAIN \n")); /* some audio card */ if (!strcmp(p->Name(), "Master")) break; PRINT(("not 'Master' \n")); /* some Ensonic card have all controls names 'Volume', so * 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->Name(), "Master")) { 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(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; }