/* * KMix -- KDE's full featured mini mixer * * * Copyright (C) 1996-2004 Christian Esken <esken@kde.org> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // for operator<<() #include <iostream> #include <kdebug.h> #include "volume.h" int Volume::_channelMaskEnum[10] = { MLEFT, MRIGHT, MCENTER, MREARLEFT, MREARRIGHT, MWOOFER, MLEFTREC , MRIGHTREC , MCUSTOM1, MCUSTOM2 }; Volume::Volume( ChannelMask chmask, long maxVolume, long minVolume, bool isCapture ) { init(chmask, maxVolume, minVolume, isCapture); } // @ compatiblity constructor Volume::Volume( int channels, long maxVolume ) { if (channels == 1 ) { init(Volume::MLEFT, maxVolume, 0, false); } else if (channels == 2) { init(ChannelMask(Volume::MLEFT|Volume::MRIGHT), maxVolume, 0, false ); } else { init(ChannelMask(Volume::MLEFT|Volume::MRIGHT), maxVolume, 0, false ); kdError(67100) << "Warning: Multi-channel Volume object created with old constructor - this will not work fully\n"; } } Volume::Volume( const Volume &v ) { _chmask = v._chmask; _maxVolume = v._maxVolume; _minVolume = v._minVolume; _muted = v._muted; _isCapture = v._isCapture; setVolume(v, (ChannelMask)v._chmask); // kdDebug(67100) << "Volume::copy-constructor initialized " << v << "\n"; } void Volume::init( ChannelMask chmask, long maxVolume, long minVolume, bool isCapture ) { for ( int i=0; i<= Volume::CHIDMAX; i++ ) { _volumes[i] = 0; } _chmask = chmask; _maxVolume = maxVolume; _minVolume = minVolume; _isCapture = isCapture; _muted = false; } // @ compatibility void Volume::setAllVolumes(long vol) { for ( int i=0; i<= Volume::CHIDMAX; i++ ) { if ( (_channelMaskEnum[i]) & _chmask ) { // we are supposed to set it _volumes[i] = volrange(vol); } } } // @ compatibility void Volume::setVolume( ChannelID chid, long vol) { if ( chid>=0 && chid<=Volume::CHIDMAX ) { // accepted. we don't care if we support the channel, // because there is NO good action we could take. // Anyway: getVolume() on an unsupported channel will return 0 all the time _volumes[chid] = volrange(vol); } } /** * Copy the volume elements contained in v to this Volume object. * Only those elments are copied, that are supported in BOTH Volume objects. */ void Volume::setVolume(const Volume &v) { setVolume(v, (ChannelMask)(v._chmask&_chmask) ); } /** * Copy the volume elements contained in v to this Volume object. * Only those elments are copied, that are supported in BOTH Volume objects * and match the ChannelMask given by chmask. */ void Volume::setVolume(const Volume &v, ChannelMask chmask) { for ( int i=0; i<= Volume::CHIDMAX; i++ ) { if ( _channelMaskEnum[i] & _chmask & (int)chmask ) { // we are supposed to copy it _volumes[i] = volrange(v._volumes[i]); } else { // Safety first! Lets play safe here and put sane values in _volumes[i] = 0; } } } long Volume::maxVolume() { return _maxVolume; } long Volume::minVolume() { return _minVolume; } // @ compatibility long Volume::operator[](int id) { return getVolume( (Volume::ChannelID) id ); } long Volume::getVolume(ChannelID chid) { long vol = 0; if ( chid < 0 || chid > (Volume::CHIDMAX) ) { // should throw exception here. I will return 0 instead } else { // check if channel is supported int chmask = _channelMaskEnum[chid]; if ( (chmask & _chmask) != 0 ) { // channel is supported vol = _volumes[chid]; } else { // should throw exception here. I will return 0 instead } } return vol; } long Volume::getAvgVolume(ChannelMask chmask) { int avgVolumeCounter = 0; long long sumOfActiveVolumes = 0; for ( int i=0; i<= Volume::CHIDMAX; i++ ) { if ( (_channelMaskEnum[i] & _chmask) & (int)chmask ) { avgVolumeCounter++; sumOfActiveVolumes += _volumes[i]; } } if (avgVolumeCounter != 0) { sumOfActiveVolumes /= avgVolumeCounter; } else { // just return 0; } return (long)sumOfActiveVolumes; } long Volume::getTopStereoVolume(ChannelMask chmask) { long long topVolumeCount = 0; for ( int i=0; i<= Volume::CHIDMAX; i++ ) { if ( (_channelMaskEnum[i] & _chmask) & (int)chmask ) { if ( topVolumeCount < _volumes[i] ) topVolumeCount = _volumes[i]; } } return (long)topVolumeCount; } int Volume::count() { int counter = 0; for ( int i=0; i<= Volume::CHIDMAX; i++ ) { if ( _channelMaskEnum[i] & _chmask ) { counter++; } } return counter; } /** * returns a "sane" volume level. This means, it is a volume level inside the * valid bounds */ long Volume::volrange( int vol ) { if ( vol < _minVolume ) { return _minVolume; } else if ( vol < _maxVolume ) { return vol; } else { return _maxVolume; } } std::ostream& operator<<(std::ostream& os, const Volume& vol) { os << "("; for ( int i=0; i<= Volume::CHIDMAX; i++ ) { if ( i != 0 ) { os << ","; } if ( Volume::_channelMaskEnum[i] & vol._chmask ) { // supported channel: Print Volume os << vol._volumes[i]; } else { // unsupported channel: Print "x" os << "x"; } } // all channels os << ")"; os << " [" << vol._minVolume << "-" << vol._maxVolume; if ( vol._muted ) { os << " : muted ]"; } else { os << " : playing ]"; } return os; } kdbgstream& operator<<(kdbgstream &os, const Volume& vol) { os << "("; for ( int i=0; i<= Volume::CHIDMAX; i++ ) { if ( i != 0 ) { os << ","; } if ( Volume::_channelMaskEnum[i] & vol._chmask ) { // supported channel: Print Volume os << vol._volumes[i]; } else { // unsupported channel: Print "x" os << "x"; } } // all channels os << ")"; os << " [" << vol._minVolume << "-" << vol._maxVolume; if ( vol._muted ) { os << " : muted ]"; } else { os << " : playing ]"; } return os; }