diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | e2de64d6f1beb9e492daf5b886e19933c1fa41dd (patch) | |
tree | 9047cf9e6b5c43878d5bf82660adae77ceee097a /kmix/mixer_sun.cpp | |
download | tdemultimedia-e2de64d6f1beb9e492daf5b886e19933c1fa41dd.tar.gz tdemultimedia-e2de64d6f1beb9e492daf5b886e19933c1fa41dd.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdemultimedia@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kmix/mixer_sun.cpp')
-rw-r--r-- | kmix/mixer_sun.cpp | 473 |
1 files changed, 473 insertions, 0 deletions
diff --git a/kmix/mixer_sun.cpp b/kmix/mixer_sun.cpp new file mode 100644 index 00000000..542fdcc8 --- /dev/null +++ b/kmix/mixer_sun.cpp @@ -0,0 +1,473 @@ +/* + * KMix -- KDE's full featured mini mixer + * + * + * Copyright (C) 1996-2000 Christian Esken <esken@kde.org> + * 2000 Brian Hanson <bhanson@hotmail.com> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/file.h> +#include <sys/audioio.h> +#include <errno.h> +#include <unistd.h> +#include <stdlib.h> + +#include "mixer_sun.h" + + +//====================================================================== +// CONSTANT/ENUM DEFINITIONS +//====================================================================== + +// +// Mixer Device Numbers +// +// Note: We can't just use the Sun port #defines because : +// 1) Some logical devices don't correspond to ports (master&recmon) +// 2) The play and record port definitions reuse the same values +// +enum MixerDevs +{ + MIXERDEV_MASTER_VOLUME, + MIXERDEV_INTERNAL_SPEAKER, + MIXERDEV_HEADPHONE, + MIXERDEV_LINE_OUT, + MIXERDEV_RECORD_MONITOR, + MIXERDEV_MICROPHONE, + MIXERDEV_LINE_IN, + MIXERDEV_CD, + // Insert new devices before this marker + MIXERDEV_END_MARKER +}; +const int numDevs = MIXERDEV_END_MARKER; + +// +// Device name strings +// +const char* MixerDevNames[] = +{ + I18N_NOOP("Master Volume"), + I18N_NOOP("Internal Speaker"), + I18N_NOOP("Headphone"), + I18N_NOOP("Line Out"), + I18N_NOOP("Record Monitor"), + I18N_NOOP("Microphone"), + I18N_NOOP("Line In"), + I18N_NOOP("CD") +}; + +// +// Channel types (this specifies which icon to display) +// +const MixDevice::ChannelType MixerChannelTypes[] = +{ + MixDevice::VOLUME, // MASTER_VOLUME + MixDevice::AUDIO, // INTERNAL_SPEAKER + MixDevice::EXTERNAL, // HEADPHONE (we really need an icon for this) + MixDevice::EXTERNAL, // LINE_OUT + MixDevice::RECMONITOR, // RECORD_MONITOR + MixDevice::MICROPHONE, // MICROPHONE + MixDevice::EXTERNAL, // LINE_IN + MixDevice::CD // CD +}; + +// +// Mapping from device numbers to Sun port mask values +// +const uint_t MixerSunPortMasks[] = +{ + 0, // MASTER_VOLUME - no associated port + AUDIO_SPEAKER, + AUDIO_HEADPHONE, + AUDIO_LINE_OUT, + 0, // RECORD_MONITOR - no associated port + AUDIO_MICROPHONE, + AUDIO_LINE_IN, + AUDIO_CD +}; + + +//====================================================================== +// FUNCTION/METHOD DEFINITIONS +//====================================================================== + + +//====================================================================== +// FUNCTION : SUN_getMixer +// DESCRIPTION : Creates and returns a new mixer object. +//====================================================================== +Mixer_Backend* SUN_getMixer( int devnum ) +{ + Mixer_Backend *l_mixer; + l_mixer = new Mixer_SUN( devnum ); + return l_mixer; +} + + +//====================================================================== +// FUNCTION : Mixer::Mixer +// DESCRIPTION : Class constructor. +//====================================================================== +Mixer_SUN::Mixer_SUN(int devnum) : Mixer_Backend(devnum) +{ + if ( devnum == -1 ) + m_devnum = 0; +} + +//====================================================================== +// FUNCTION : Mixer::Mixer +// DESCRIPTION : Class destructor. +//====================================================================== +Mixer_SUN::~Mixer_SUN() +{ + close(); +} + +//====================================================================== +// FUNCTION : Mixer::open +// DESCRIPTION : Initialize the mixer and open the hardware driver. +//====================================================================== +int Mixer_SUN::open() +{ + // + // We don't support multiple devices + // + if ( m_devnum !=0 ) + return Mixer::ERR_OPEN; + + // + // Open the mixer hardware driver + // + QCString audiodev(getenv("AUDIODEV")); + if(audiodev.isNull()) + audiodev = "/dev/audio"; + audiodev += "ctl"; + if ( ( fd = ::open( audiodev.data(), O_RDWR ) ) < 0 ) + { + if ( errno == EACCES ) + return Mixer::ERR_PERM; + else + return Mixer::ERR_OPEN; + } + else + { + // + // Mixer is open. Now define all of the mix devices. + // + + if( m_mixDevices.isEmpty() ) + { + for ( int idx = 0; idx < numDevs; idx++ ) + { + Volume vol( 2, AUDIO_MAX_GAIN ); + readVolumeFromHW( idx, vol ); + MixDevice* md = new MixDevice( idx, vol, false, true, + QString(MixerDevNames[idx]), MixerChannelTypes[idx]); + md->setRecSource( isRecsrcHW( idx ) ); + m_mixDevices.append( md ); + } + } + else + { + for( unsigned int idx = 0; idx < m_mixDevices.count(); idx++ ) + { + MixDevice* md = m_mixDevices.at( idx ); + if( !md ) + return Mixer::ERR_INCOMPATIBLESET; + writeVolumeToHW( idx, md->getVolume() ); + } + } + + m_mixerName = "SUN Audio Mixer"; + m_isOpen = true; + + return 0; + } +} + +//====================================================================== +// FUNCTION : Mixer::close +// DESCRIPTION : Close the hardware driver. +//====================================================================== +int Mixer_SUN::close() +{ + m_isOpen = false; + int l_i_ret = ::close( fd ); + m_mixDevices.clear(); + return l_i_ret; +} + +//====================================================================== +// FUNCTION : Mixer::errorText +// DESCRIPTION : Convert an error code enum to a text string. +//====================================================================== +QString Mixer_SUN::errorText( int mixer_error ) +{ + QString errmsg; + switch (mixer_error) + { + case Mixer::ERR_PERM: + errmsg = i18n( + "kmix: You do not have permission to access the mixer device.\n" + "Ask your system administrator to fix /dev/audioctl to allow access." + ); + break; + default: + errmsg = Mixer_Backend::errorText( mixer_error ); + } + return errmsg; +} + + +//====================================================================== +// FUNCTION : Mixer::readVolumeFrmoHW +// DESCRIPTION : Read the audio information from the driver. +//====================================================================== +int Mixer_SUN::readVolumeFromHW( int devnum, Volume& volume ) +{ + audio_info_t audioinfo; + uint_t devMask = MixerSunPortMasks[devnum]; + + // + // Read the current audio information from the driver + // + if ( ioctl( fd, AUDIO_GETINFO, &audioinfo ) < 0 ) + { + return( Mixer::ERR_READ ); + } + else + { + // + // Extract the appropriate fields based on the requested device + // + switch ( devnum ) + { + case MIXERDEV_MASTER_VOLUME : + volume.setMuted( audioinfo.output_muted ); + GainBalanceToVolume( audioinfo.play.gain, + audioinfo.play.balance, + volume ); + break; + + case MIXERDEV_RECORD_MONITOR : + volume.setMuted(FALSE); + volume.setAllVolumes( audioinfo.monitor_gain ); + break; + + case MIXERDEV_INTERNAL_SPEAKER : + case MIXERDEV_HEADPHONE : + case MIXERDEV_LINE_OUT : + volume.setMuted( (audioinfo.play.port & devMask) ? FALSE : TRUE ); + GainBalanceToVolume( audioinfo.play.gain, + audioinfo.play.balance, + volume ); + break; + + case MIXERDEV_MICROPHONE : + case MIXERDEV_LINE_IN : + case MIXERDEV_CD : + volume.setMuted( (audioinfo.record.port & devMask) ? FALSE : TRUE ); + GainBalanceToVolume( audioinfo.record.gain, + audioinfo.record.balance, + volume ); + break; + + default : + return Mixer::ERR_NODEV; + } + return 0; + } +} + +//====================================================================== +// FUNCTION : Mixer::writeVolumeToHW +// DESCRIPTION : Write the specified audio settings to the hardware. +//====================================================================== +int Mixer_SUN::writeVolumeToHW( int devnum, Volume &volume ) +{ + uint_t gain; + uchar_t balance; + uchar_t mute; + + // + // Convert the Volume(left vol, right vol) to the Gain/Balance Sun uses + // + VolumeToGainBalance( volume, gain, balance ); + mute = volume.isMuted() ? 1 : 0; + + // + // Read the current audio settings from the hardware + // + audio_info_t audioinfo; + if ( ioctl( fd, AUDIO_GETINFO, &audioinfo ) < 0 ) + { + return( Mixer::ERR_READ ); + } + + // + // Now, based on the devnum that we are writing to, update the appropriate + // volume field and twiddle the appropriate bitmask to enable/mute the + // device as necessary. + // + switch ( devnum ) + { + case MIXERDEV_MASTER_VOLUME : + audioinfo.play.gain = gain; + audioinfo.play.balance = balance; + audioinfo.output_muted = mute; + break; + + case MIXERDEV_RECORD_MONITOR : + audioinfo.monitor_gain = gain; + // no mute or balance for record monitor + break; + + case MIXERDEV_INTERNAL_SPEAKER : + case MIXERDEV_HEADPHONE : + case MIXERDEV_LINE_OUT : + audioinfo.play.gain = gain; + audioinfo.play.balance = balance; + if ( mute ) + audioinfo.play.port &= ~MixerSunPortMasks[devnum]; + else + audioinfo.play.port |= MixerSunPortMasks[devnum]; + break; + + case MIXERDEV_MICROPHONE : + case MIXERDEV_LINE_IN : + case MIXERDEV_CD : + audioinfo.record.gain = gain; + audioinfo.record.balance = balance; + if ( mute ) + audioinfo.record.port &= ~MixerSunPortMasks[devnum]; + else + audioinfo.record.port |= MixerSunPortMasks[devnum]; + break; + + default : + return Mixer::ERR_NODEV; + } + + // + // Now that we've updated the audioinfo struct, write it back to the hardware + // + if ( ioctl( fd, AUDIO_SETINFO, &audioinfo ) < 0 ) + { + return( Mixer::ERR_WRITE ); + } + else + { + return 0; + } +} + +//====================================================================== +// FUNCTION : Mixer::setRecsrcHW +// DESCRIPTION : +//====================================================================== +bool Mixer_SUN::setRecsrcHW( int /* devnum */, bool /* on */ ) +{ + return FALSE; +} + +//====================================================================== +// FUNCTION : Mixer::isRecsrcHW +// DESCRIPTION : Returns true if the specified device is a record source. +//====================================================================== +bool Mixer_SUN::isRecsrcHW( int devnum ) +{ + switch ( devnum ) + { + case MIXERDEV_MICROPHONE : + case MIXERDEV_LINE_IN : + case MIXERDEV_CD : + return TRUE; + + default : + return FALSE; + } +} + +//====================================================================== +// FUNCTION : Mixer::VolumeToGainBalance +// DESCRIPTION : Converts a Volume(left vol + right vol) into the +// Gain/Balance values used by Sun. +//====================================================================== +void Mixer_SUN::VolumeToGainBalance( Volume& volume, uint_t& gain, uchar_t& balance ) +{ + if ( ( volume.count() == 1 ) || + ( volume[Volume::LEFT] == volume[Volume::RIGHT] ) ) + { + gain = volume[Volume::LEFT]; + balance = AUDIO_MID_BALANCE; + } + else + { + if ( volume[Volume::LEFT] > volume[Volume::RIGHT] ) + { + gain = volume[Volume::LEFT]; + balance = AUDIO_LEFT_BALANCE + + ( AUDIO_MID_BALANCE - AUDIO_LEFT_BALANCE ) * + volume[Volume::RIGHT] / volume[Volume::LEFT]; + } + else + { + gain = volume[Volume::RIGHT]; + balance = AUDIO_RIGHT_BALANCE - + ( AUDIO_RIGHT_BALANCE - AUDIO_MID_BALANCE ) * + volume[Volume::LEFT] / volume[Volume::RIGHT]; + } + } +} + +//====================================================================== +// FUNCTION : Mixer::GainBalanceToVolume +// DESCRIPTION : Converts Gain/Balance returned by Sun driver to the +// Volume(left vol + right vol) format used by kmix. +//====================================================================== +void Mixer_SUN::GainBalanceToVolume( uint_t& gain, uchar_t& balance, Volume& volume ) +{ + if ( volume.count() == 1 ) + { + volume.setVolume( Volume::LEFT, gain ); + } + else + { + if ( balance <= AUDIO_MID_BALANCE ) + { + volume.setVolume( Volume::LEFT, gain ); + volume.setVolume( Volume::RIGHT, gain * + ( balance - AUDIO_LEFT_BALANCE ) / + ( AUDIO_MID_BALANCE - AUDIO_LEFT_BALANCE ) ); + } + else + { + volume.setVolume( Volume::RIGHT, gain ); + volume.setVolume( Volume::LEFT, gain * + ( AUDIO_RIGHT_BALANCE - balance ) / + ( AUDIO_RIGHT_BALANCE - AUDIO_MID_BALANCE ) ); + } + } +} + +QString SUN_getDriverName() { + return "SUNAudio"; +} + |