/* * 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. */ #include <tdelocale.h> #include <kled.h> #include <kiconloader.h> #include <tdeconfig.h> #include <tdeaction.h> #include <tdepopupmenu.h> #include <kglobalaccel.h> #include <kkeydialog.h> #include <kdebug.h> #include <tqobject.h> #include <tqcursor.h> #include <tqslider.h> #include <tqlabel.h> #include <tqlayout.h> #include <tqpixmap.h> #include <tqtooltip.h> #include <tqwmatrix.h> #include "mdwslider.h" #include "mixer.h" #include "viewbase.h" #include "kledbutton.h" #include "ksmallslider.h" #include "verticaltext.h" /** * MixDeviceWidget that represents a single mix device, inlcuding PopUp, muteLED, ... * * Used in KMix main window and DockWidget and PanelApplet. * It can be configured to include or exclude the recordLED and the muteLED. * The direction (horizontal, vertical) can be configured and whether it should * be "small" (uses KSmallSlider instead of TQSlider then). * * Due to the many options, this is the most complicated MixDeviceWidget subclass. */ MDWSlider::MDWSlider(Mixer *mixer, MixDevice* md, bool showMuteLED, bool showRecordLED, bool small, Qt::Orientation orientation, TQWidget* parent, ViewBase* mw, const char* name) : MixDeviceWidget(mixer,md,small,orientation,parent,mw,name), m_linked(true), m_valueStyle( NNONE), m_iconLabel( 0 ), m_muteLED( 0 ), m_recordLED( 0 ), m_label( 0 ), _layout(0) { // create actions (on _mdwActions, see MixDeviceWidget) new TDEToggleAction( i18n("&Split Channels"), 0, TQT_TQOBJECT(this), TQT_SLOT(toggleStereoLinked()), _mdwActions, "stereo" ); new TDEToggleAction( i18n("&Hide"), 0, TQT_TQOBJECT(this), TQT_SLOT(setDisabled()), _mdwActions, "hide" ); TDEToggleAction *a = new TDEToggleAction(i18n("&Muted"), 0, 0, 0, _mdwActions, "mute" ); connect( a, TQT_SIGNAL(toggled(bool)), TQT_SLOT(toggleMuted()) ); if( m_mixdevice->isRecordable() ) { a = new TDEToggleAction( i18n("Set &Record Source"), 0, 0, 0, _mdwActions, "recsrc" ); connect( a, TQT_SIGNAL(toggled(bool)), TQT_SLOT( toggleRecsrc()) ); } new TDEAction( i18n("C&onfigure Global Shortcuts..."), 0, TQT_TQOBJECT(this), TQT_SLOT(defineKeys()), _mdwActions, "keys" ); // create widgets createWidgets( showMuteLED, showRecordLED ); m_keys->insert( "Increase volume", i18n( "Increase Volume of '%1'" ).arg(m_mixdevice->name().utf8().data()), TQString(), TDEShortcut(), TDEShortcut(), TQT_TQOBJECT(this), TQT_SLOT( increaseVolume() ) ); m_keys->insert( "Decrease volume", i18n( "Decrease Volume of '%1'" ).arg(m_mixdevice->name().utf8().data()), TQString(), TDEShortcut(), TDEShortcut(), TQT_TQOBJECT(this), TQT_SLOT( decreaseVolume() ) ); m_keys->insert( "Toggle mute", i18n( "Toggle Mute of '%1'" ).arg(m_mixdevice->name().utf8().data()), TQString(), TDEShortcut(), TDEShortcut(), TQT_TQOBJECT(this), TQT_SLOT( toggleMuted() ) ); installEventFilter( this ); // filter for popup update(); } TQSizePolicy MDWSlider::sizePolicy() const { if ( _orientation == Qt::Vertical ) { return TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Expanding ); } else { return TQSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::Fixed ); } } /** * Creates up to 4 widgets - Icon, Mute-Button, Slider and Record-Button. * * Those widgets are placed into */ void MDWSlider::createWidgets( bool showMuteLED, bool showRecordLED ) { if ( _orientation == Qt::Vertical ) { _layout = new TQVBoxLayout( this ); _layout->setAlignment(TQt::AlignCenter); } else { _layout = new TQHBoxLayout( this ); _layout->setAlignment(TQt::AlignCenter); } // -- MAIN SLIDERS LAYOUT --- TQBoxLayout *slidersLayout; if ( _orientation == Qt::Vertical ) { slidersLayout = new TQHBoxLayout( _layout ); slidersLayout->setAlignment(TQt::AlignVCenter); } else { slidersLayout = new TQVBoxLayout( _layout ); slidersLayout->setAlignment(TQt::AlignHCenter); } /* cesken: This is inconsistent. Why should vertical and horizontal layout differ? * Also it eats too much space - especially when you don't show sliders at all. * Even more on the vertical panel applet (see Bug #97667) if ( _orientation == Qt::Horizontal ) slidersLayout->addSpacing( 10 ); */ // -- LABEL LAYOUT TO POSITION TQBoxLayout *labelLayout; if ( _orientation == Qt::Vertical ) { labelLayout = new TQVBoxLayout( slidersLayout ); labelLayout->setAlignment(TQt::AlignHCenter); } else { labelLayout = new TQHBoxLayout( slidersLayout ); labelLayout->setAlignment(TQt::AlignVCenter); } if ( _orientation == Qt::Vertical ) { m_label = new VerticalText( this, m_mixdevice->name().utf8().data() ); TQToolTip::add( m_label, m_mixdevice->name() ); } else { m_label = new TQLabel(this); static_cast<TQLabel*>(m_label) ->setText(m_mixdevice->name()); TQToolTip::add( m_label, m_mixdevice->name() ); } m_label->hide(); /* This addSpacing() looks VERY bizarre => removing it (cesken, 21.2.2006). Also horizontal and vertical spacing differs. This doesn't look sensible. if ( _orientation == Qt::Horizontal ) labelLayout->addSpacing( 36 ); */ labelLayout->addWidget( m_label ); m_label->installEventFilter( this ); /* This addSpacing() looks VERY bizarre => removing it (cesken, 21.2.2006) Also horizontal and vertical spacing differs. This doesn't look sensible. if ( _orientation == Qt::Vertical ) { labelLayout->addSpacing( 18 ); } */ // -- SLIDERS, LEDS AND ICON TQBoxLayout *sliLayout; if ( _orientation == Qt::Vertical ) { sliLayout = new TQVBoxLayout( slidersLayout ); sliLayout->setAlignment(TQt::AlignHCenter); } else { sliLayout = new TQHBoxLayout( slidersLayout ); sliLayout->setAlignment(TQt::AlignVCenter); } // --- ICON ---------------------------- TQBoxLayout *iconLayout; if ( _orientation == Qt::Vertical ) { iconLayout = new TQHBoxLayout( sliLayout ); iconLayout->setAlignment(TQt::AlignVCenter); } else { iconLayout = new TQVBoxLayout( sliLayout ); iconLayout->setAlignment(TQt::AlignHCenter); } m_iconLabel = 0L; setIcon( m_mixdevice->type() ); iconLayout->addStretch(); iconLayout->addWidget( m_iconLabel ); iconLayout->addStretch(); m_iconLabel->installEventFilter( this ); sliLayout->addSpacing( 5 ); // --- MUTE LED if ( showMuteLED ) { TQBoxLayout *ledlayout; if ( _orientation == Qt::Vertical ) { ledlayout = new TQHBoxLayout( sliLayout ); ledlayout->setAlignment(TQt::AlignVCenter); } else { ledlayout = new TQVBoxLayout( sliLayout ); ledlayout->setAlignment(TQt::AlignHCenter); } if( m_mixdevice->hasMute() ) { ledlayout->addStretch(); // create mute LED m_muteLED = new KLedButton( TQt::green, KLed::On, KLed::Sunken, KLed::Circular, this, "MuteLED" ); m_muteLED->setFixedSize( TQSize(16, 16) ); m_muteLED->resize( TQSize(16, 16) ); ledlayout->addWidget( m_muteLED ); TQToolTip::add( m_muteLED, i18n( "Mute" ) ); connect( m_muteLED, TQT_SIGNAL(stateChanged(bool)), this, TQT_SLOT(toggleMuted()) ); m_muteLED->installEventFilter( this ); ledlayout->addStretch(); } // has Mute LED else { // we don't have a MUTE LED. We create a dummy widget // !! possibly not neccesary any more (we are layouted) TQWidget *qw = new TQWidget(this, "Spacer"); qw->setFixedSize( TQSize(16, 16) ); ledlayout->addWidget(qw); qw->installEventFilter( this ); } // has no Mute LED sliLayout->addSpacing( 3 ); } // showMuteLED // --- SLIDERS --------------------------- TQBoxLayout *volLayout; if ( _orientation == Qt::Vertical ) { volLayout = new TQHBoxLayout( sliLayout ); volLayout->setAlignment(TQt::AlignVCenter); } else { volLayout = new TQVBoxLayout( sliLayout ); volLayout->setAlignment(TQt::AlignHCenter); } // Sliders and volume number indication TQBoxLayout *slinumLayout; for( int i = 0; i < m_mixdevice->getVolume().count(); i++ ) { Volume::ChannelID chid = Volume::ChannelID(i); // @todo !! Normally the mixdevicewidget SHOULD know, which slider represents which channel. // We should look up the mapping here, but for now, we simply assume "chid == i". int maxvol = m_mixdevice->getVolume().maxVolume(); int minvol = m_mixdevice->getVolume().minVolume(); if ( _orientation == Qt::Vertical ) { slinumLayout = new TQVBoxLayout( volLayout ); slinumLayout->setAlignment(TQt::AlignHCenter); } else { slinumLayout = new TQHBoxLayout( volLayout ); slinumLayout->setAlignment(TQt::AlignVCenter); } // create labels to hold volume values (taken from qamix/kamix) TQLabel *number = new TQLabel( "100", this ); slinumLayout->addWidget( number ); number->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); number->setLineWidth( 2 ); number->setMinimumWidth( number->sizeHint().width() ); number->setPaletteBackgroundColor( TQColor(190, 250, 190) ); // don't show the value by default number->hide(); updateValue( number, chid ); _numbers.append( number ); TQWidget* slider; if ( m_small ) { slider = new KSmallSlider( minvol, maxvol, maxvol/10, m_mixdevice->getVolume( chid ), _orientation, this, m_mixdevice->name().ascii() ); } else { slider = new TQSlider( 0, maxvol, maxvol/10, maxvol - m_mixdevice->getVolume( chid ), _orientation, this, m_mixdevice->name().ascii() ); slider->setMinimumSize( slider->sizeHint() ); } slider->setBackgroundOrigin(AncestorOrigin); slider->installEventFilter( this ); TQToolTip::add( slider, m_mixdevice->name() ); if( i>0 && isStereoLinked() ) { // show only one (the first) slider, when the user wants it so slider->hide(); number->hide(); } slinumLayout->addWidget( slider ); // add to layout m_sliders.append ( slider ); // add to list _slidersChids.append(chid); // Remember slider-chid association connect( slider, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(volumeChange(int)) ); } // for all channels of this device // --- RECORD SOURCE LED -------------------------- if ( showRecordLED ) { sliLayout->addSpacing( 5 ); // --- LED LAYOUT TO CENTER --- TQBoxLayout *reclayout; if ( _orientation == Qt::Vertical ) { reclayout = new TQHBoxLayout( sliLayout ); reclayout->setAlignment(TQt::AlignVCenter); } else { reclayout = new TQVBoxLayout( sliLayout ); reclayout->setAlignment(TQt::AlignHCenter); } if( m_mixdevice->isRecordable() ) { reclayout->addStretch(); m_recordLED = new KLedButton( TQt::red, m_mixdevice->isRecSource()?KLed::On:KLed::Off, KLed::Sunken, KLed::Circular, this, "RecordLED" ); m_recordLED->setFixedSize( TQSize(16, 16) ); reclayout->addWidget( m_recordLED ); connect(m_recordLED, TQT_SIGNAL(stateChanged(bool)), this, TQT_SLOT(setRecsrc(bool))); m_recordLED->installEventFilter( this ); TQToolTip::add( m_recordLED, i18n( "Record" ) ); reclayout->addStretch(); } else { // we don't have a RECORD LED. We create a dummy widget // !! possibly not neccesary any more (we are layouted) TQWidget *qw = new TQWidget(this, "Spacer"); qw->setFixedSize( TQSize(16, 16) ); reclayout->addWidget(qw); qw->installEventFilter( this ); } // has no Record LED } // showRecordLED layout()->activate(); } TQPixmap MDWSlider::icon( int icontype ) { TQPixmap miniDevPM; switch (icontype) { case MixDevice::AUDIO: miniDevPM = UserIcon("mix_audio"); break; case MixDevice::BASS: case MixDevice::SURROUND_LFE: // "LFE" SHOULD have an own icon miniDevPM = UserIcon("mix_bass"); break; case MixDevice::CD: miniDevPM = UserIcon("mix_cd"); break; case MixDevice::EXTERNAL: miniDevPM = UserIcon("mix_ext"); break; case MixDevice::MICROPHONE: miniDevPM = UserIcon("mix_microphone");break; case MixDevice::MIDI: miniDevPM = UserIcon("mix_midi"); break; case MixDevice::RECMONITOR: miniDevPM = UserIcon("mix_recmon"); break; case MixDevice::TREBLE: miniDevPM = UserIcon("mix_treble"); break; case MixDevice::UNKNOWN: miniDevPM = UserIcon("mix_unknown"); break; case MixDevice::VOLUME: miniDevPM = UserIcon("mix_volume"); break; case MixDevice::VIDEO: miniDevPM = UserIcon("mix_video"); break; case MixDevice::SURROUND: case MixDevice::SURROUND_BACK: case MixDevice::SURROUND_CENTERFRONT: case MixDevice::SURROUND_CENTERBACK: miniDevPM = UserIcon("mix_surround"); break; case MixDevice::HEADPHONE: miniDevPM = UserIcon( "mix_headphone" ); break; case MixDevice::DIGITAL: miniDevPM = UserIcon( "mix_digital" ); break; case MixDevice::AC97: miniDevPM = UserIcon( "mix_ac97" ); break; default: miniDevPM = UserIcon("mix_unknown"); break; } return miniDevPM; } void MDWSlider::setIcon( int icontype ) { if( !m_iconLabel ) { m_iconLabel = new TQLabel(this); m_iconLabel->setBackgroundOrigin(AncestorOrigin); installEventFilter( m_iconLabel ); } TQPixmap miniDevPM = icon( icontype ); if ( !miniDevPM.isNull() ) { if ( m_small ) { // scale icon TQWMatrix t; t = t.scale( 10.0/miniDevPM.width(), 10.0/miniDevPM.height() ); m_iconLabel->setPixmap( miniDevPM.xForm( t ) ); m_iconLabel->resize( 10, 10 ); } else m_iconLabel->setPixmap( miniDevPM ); m_iconLabel->setAlignment( TQt::AlignCenter ); } else { kdError(67100) << "Pixmap missing." << endl; } layout()->activate(); } bool MDWSlider::isLabeled() const { if ( m_label == 0 ) return false; else return !m_label->isHidden(); } void MDWSlider::toggleStereoLinked() { setStereoLinked( !isStereoLinked() ); } void MDWSlider::setStereoLinked(bool value) { m_linked = value; TQWidget *slider = m_sliders.first(); TQLabel *number = _numbers.first(); TQString qs = number->text(); /*********************************************************** Remember value of first slider, so that it can be copied to the other sliders. ***********************************************************/ int firstSliderValue = 0; bool firstSliderValueValid = false; if (slider->isA(TQSLIDER_OBJECT_NAME_STRING) ) { TQSlider *sld = static_cast<TQSlider*>(slider); firstSliderValue = sld->value(); firstSliderValueValid = true; } else if ( slider->isA("KSmallSlider") ) { KSmallSlider *sld = static_cast<KSmallSlider*>(slider); firstSliderValue = sld->value(); firstSliderValueValid = true; } for( slider=m_sliders.next(), number=_numbers.next(); slider!=0 && number!=0; slider=m_sliders.next(), number=_numbers.next() ) { if ( m_linked ) { slider->hide(); number->hide(); } else { // When splitting, make the next sliders show the same value as the first. // This might not be entirely true, but better than showing the random value // that was used to be shown before hot-fixing this. !! must be revised if ( firstSliderValueValid ) { // Remark: firstSlider== 0 could happen, if the static_cast<TQRangeControl*> above fails. // It's a safety measure, if we got other Slider types in the future. if (slider->isA(TQSLIDER_OBJECT_NAME_STRING) ) { TQSlider *sld = static_cast<TQSlider*>(slider); sld->setValue( firstSliderValue ); } if (slider->isA("KSmallSlider") ) { KSmallSlider *sld = static_cast<KSmallSlider*>(slider); sld->setValue( firstSliderValue ); } } slider->show(); number->setText(qs); if (m_valueStyle != NNONE) number->show(); } } slider = m_sliders.last(); if( slider && static_cast<TQSlider *>(slider)->tickmarks() ) setTicks( true ); layout()->activate(); } void MDWSlider::setLabeled(bool value) { if ( m_label == 0 ) return; if (value ) m_label->show(); else m_label->hide(); layout()->activate(); } void MDWSlider::setTicks( bool ticks ) { TQWidget* slider; slider = m_sliders.first(); if ( slider->inherits( TQSLIDER_OBJECT_NAME_STRING ) ) { if( ticks ) if( isStereoLinked() ) static_cast<TQSlider *>(slider)->setTickmarks( TQSlider::Right ); else { static_cast<TQSlider *>(slider)->setTickmarks( TQSlider::NoMarks ); slider = m_sliders.last(); static_cast<TQSlider *>(slider)->setTickmarks( TQSlider::Left ); } else { static_cast<TQSlider *>(slider)->setTickmarks( TQSlider::NoMarks ); slider = m_sliders.last(); static_cast<TQSlider *>(slider)->setTickmarks( TQSlider::NoMarks ); } } layout()->activate(); } void MDWSlider::setValueStyle( ValueStyle valueStyle ) { m_valueStyle = valueStyle; int i = 0; TQValueList<Volume::ChannelID>::Iterator it = _slidersChids.begin(); for(TQLabel *number = _numbers.first(); number!=0; number = _numbers.next(), ++i, ++it) { Volume::ChannelID chid = *it; switch ( m_valueStyle ) { case NNONE: number->hide(); break; default: if ( !isStereoLinked() || (i == 0)) { updateValue( number, chid ); number->show(); } } } layout()->activate(); } void MDWSlider::setIcons(bool value) { if ( m_iconLabel != 0 ) { if ( ( !m_iconLabel->isHidden()) !=value ) { if (value) m_iconLabel->show(); else m_iconLabel->hide(); layout()->activate(); } } // if it has an icon } void MDWSlider::setColors( TQColor high, TQColor low, TQColor back ) { for( TQWidget *slider=m_sliders.first(); slider!=0; slider=m_sliders.next() ) { KSmallSlider *smallSlider = dynamic_cast<KSmallSlider*>(slider); if ( smallSlider ) smallSlider->setColors( high, low, back ); } } void MDWSlider::setMutedColors( TQColor high, TQColor low, TQColor back ) { for( TQWidget *slider=m_sliders.first(); slider!=0; slider=m_sliders.next() ) { KSmallSlider *smallSlider = dynamic_cast<KSmallSlider*>(slider); if ( smallSlider ) smallSlider->setGrayColors( high, low, back ); } } void MDWSlider::updateValue( TQLabel *value, Volume::ChannelID chid ) { TQString qs; Volume& vol = m_mixdevice->getVolume(); if (m_valueStyle == NABSOLUTE ) qs.sprintf("%3d", (int) vol.getVolume( chid ) ); else qs.sprintf("%3d", (int)( vol.getVolume( chid ) / (double)vol.maxVolume() * 100 ) ); value->setText(qs); } /** This slot is called, when a user has changed the volume via the KMix Slider */ void MDWSlider::volumeChange( int ) { // --- Step 1: Get a REFERENCE of the volume Object --- Volume& vol = m_mixdevice->getVolume(); // --- Step 2: Change the volumes directly in the Volume object to reflect the Sliders --- if ( isStereoLinked() ) { TQWidget *slider = m_sliders.first(); Volume::ChannelID chid = _slidersChids.first(); int sliderValue = 0; if ( slider->inherits( "KSmallSlider" ) ) { KSmallSlider *slider = dynamic_cast<KSmallSlider *>(m_sliders.first()); if (slider) { sliderValue= slider->value(); } } else { TQSlider *slider = dynamic_cast<TQSlider *>(m_sliders.first()); if (slider) { if ( _orientation == Qt::Vertical ) sliderValue= slider->maxValue() - slider->value(); else sliderValue= slider->value(); } } // With balance proper working, we must change relative volumes, // not absolute, which leads a make some difference calc related // to new sliders position against the top volume on channels long volumeDif = sliderValue - vol.getTopStereoVolume( Volume::MMAIN ); if ( chid == Volume::LEFT ) { vol.setVolume( Volume::LEFT , vol.getVolume( Volume::LEFT ) + volumeDif ); vol.setVolume( Volume::RIGHT, vol.getVolume( Volume::RIGHT ) + volumeDif ); } else { kdDebug(67100) << "MDWSlider::volumeChange(), unknown chid " << chid << endl; } updateValue( _numbers.first(), Volume::LEFT ); } // joined else { int n = 0; TQValueList<Volume::ChannelID>::Iterator it = _slidersChids.begin(); TQLabel *number = _numbers.first(); for( TQWidget *slider=m_sliders.first(); slider!=0 && number!=0; slider=m_sliders.next(), number=_numbers.next(), ++it ) { Volume::ChannelID chid = *it; if ( slider->inherits( "KSmallSlider" ) ) { KSmallSlider *smallSlider = dynamic_cast<KSmallSlider *>(slider); if (smallSlider) vol.setVolume( chid, smallSlider->value() ); } else { TQSlider *bigSlider = dynamic_cast<TQSlider *>(slider); if (bigSlider) if ( _orientation == Qt::Vertical ) vol.setVolume( chid, bigSlider->maxValue() - bigSlider->value() ); else vol.setVolume( chid, bigSlider->value() ); } updateValue( number, chid ); n++; } } // --- Step 3: Write back the new volumes to the HW --- m_mixer->commitVolumeChange(m_mixdevice); } /** This slot is called, when a user has clicked the recsrc button. Also it is called by any other associated TDEAction like the context menu. */ void MDWSlider::toggleRecsrc() { setRecsrc( !m_mixdevice->isRecSource() ); } void MDWSlider::setRecsrc(bool value ) { if ( m_mixdevice->isRecordable() ) { m_mixer->setRecordSource( m_mixdevice->num(), value ); } } /** This slot is called, when a user has clicked the mute button. Also it is called by any other associated TDEAction like the context menu. */ void MDWSlider::toggleMuted() { setMuted( !m_mixdevice->isMuted() ); } void MDWSlider::setMuted(bool value) { if ( m_mixdevice->hasMute() ) { m_mixdevice->setMuted( value ); m_mixer->commitVolumeChange(m_mixdevice); } } void MDWSlider::setDisabled() { setDisabled( true ); } void MDWSlider::setDisabled( bool value ) { if ( m_disabled!=value) { value ? hide() : show(); m_disabled = value; } } /** This slot is called on a MouseWheel event. Also it is called by any other associated TDEAction like the context menu. */ void MDWSlider::increaseVolume() { Volume vol = m_mixdevice->getVolume(); long inc = vol.maxVolume() / 20; if ( inc == 0 ) inc = 1; for ( int i = 0; i < vol.count(); i++ ) { long newVal = (vol[i]) + inc; m_mixdevice->setVolume( i, newVal < vol.maxVolume() ? newVal : vol.maxVolume() ); } m_mixer->commitVolumeChange(m_mixdevice); } /** This slot is called on a MouseWheel event. Also it is called by any other associated TDEAction like the context menu. */ void MDWSlider::decreaseVolume() { Volume vol = m_mixdevice->getVolume(); long inc = vol.maxVolume() / 20; if ( inc == 0 ) inc = 1; for ( int i = 0; i < vol.count(); i++ ) { long newVal = (vol[i]) - inc; m_mixdevice->setVolume( i, newVal > 0 ? newVal : 0 ); } m_mixer->commitVolumeChange(m_mixdevice); } /** This is called whenever there are volume updates pending from the hardware for this MDW. At the moment it is called regulary via a TQTimer (implicitely). */ void MDWSlider::update() { // update volumes Volume vol = m_mixdevice->getVolume(); if( isStereoLinked() ) { TQValueList<Volume::ChannelID>::Iterator it = _slidersChids.begin(); long avgVol = vol.getAvgVolume( Volume::MMAIN ); TQWidget *slider = m_sliders.first(); if ( slider == 0 ) { return; // !!! Development version, check this !!! } slider->blockSignals( true ); if ( slider->inherits( "KSmallSlider" ) ) { KSmallSlider *smallSlider = dynamic_cast<KSmallSlider *>(slider); if (smallSlider) { smallSlider->setValue( avgVol ); // !! inverted ?!? smallSlider->setGray( m_mixdevice->isMuted() ); } } // small slider else { TQSlider *bigSlider = dynamic_cast<TQSlider *>(slider); if (bigSlider) { // In case of stereo linked and single slider, slider must // show the top of both volumes, and not strangely low down // the main volume by half if ( _orientation == Qt::Vertical ) bigSlider->setValue( vol.maxVolume() - vol.getTopStereoVolume( Volume::MMAIN ) ); else bigSlider->setValue( vol.getTopStereoVolume( Volume::MMAIN ) ); } } // big slider updateValue( _numbers.first(), Volume::LEFT ); slider->blockSignals( false ); } // only 1 slider (stereo-linked) else { TQValueList<Volume::ChannelID>::Iterator it = _slidersChids.begin(); for( int i=0; i<vol.count(); i++, ++it ) { TQWidget *slider = m_sliders.at( i ); Volume::ChannelID chid = *it; if (slider == 0) { // !!! not implemented !!! // not implemented: happens if there are record and playback // sliders in the same device. Or if you only show // the right slider (or any other fancy occasion) continue; } slider->blockSignals( true ); if ( slider->inherits( "KSmallSlider" ) ) { KSmallSlider *smallSlider = dynamic_cast<KSmallSlider *>(slider); if (smallSlider) { smallSlider->setValue( vol[chid] ); smallSlider->setGray( m_mixdevice->isMuted() ); } } else { TQSlider *bigSlider = dynamic_cast<TQSlider *>(slider); if (bigSlider) if ( _orientation == Qt::Vertical ) { bigSlider->setValue( vol.maxVolume() - vol[i] ); } else { bigSlider->setValue( vol[i] ); } } updateValue( _numbers.at ( i ), chid ); slider->blockSignals( false ); } // for all sliders } // more than 1 slider // update mute led if ( m_muteLED ) { m_muteLED->blockSignals( true ); m_muteLED->setState( m_mixdevice->isMuted() ? KLed::Off : KLed::On ); m_muteLED->blockSignals( false ); } // update recsrc if( m_recordLED ) { m_recordLED->blockSignals( true ); m_recordLED->setState( m_mixdevice->isRecSource() ? KLed::On : KLed::Off ); m_recordLED->blockSignals( false ); } } void MDWSlider::showContextMenu() { if( m_mixerwidget == NULL ) return; TDEPopupMenu *menu = m_mixerwidget->getPopup(); menu->insertTitle( SmallIcon( "kmix" ), m_mixdevice->name() ); if ( m_sliders.count()>1 ) { TDEToggleAction *stereo = (TDEToggleAction *)_mdwActions->action( "stereo" ); if ( stereo ) { stereo->setChecked( !isStereoLinked() ); stereo->plug( menu ); } } TDEToggleAction *ta = (TDEToggleAction *)_mdwActions->action( "recsrc" ); if ( ta ) { ta->setChecked( m_mixdevice->isRecSource() ); ta->plug( menu ); } if ( m_mixdevice->hasMute() ) { ta = ( TDEToggleAction* )_mdwActions->action( "mute" ); if ( ta ) { ta->setChecked( m_mixdevice->isMuted() ); ta->plug( menu ); } } TDEAction *a = _mdwActions->action( "hide" ); if ( a ) a->plug( menu ); a = _mdwActions->action( "keys" ); if ( a && m_keys ) { TDEActionSeparator sep( TQT_TQOBJECT(this) ); sep.plug( menu ); a->plug( menu ); } TQPoint pos = TQCursor::pos(); menu->popup( pos ); } TQSize MDWSlider::sizeHint() const { if ( _layout != 0 ) { return _layout->sizeHint(); } else { // layout not (yet) created return TQWidget::sizeHint(); } } /** * An event filter for the various TQWidgets. We watch for Mouse press Events, so * that we can popup the context menu. */ bool MDWSlider::eventFilter( TQObject* obj, TQEvent* e ) { if (e->type() == TQEvent::MouseButtonPress) { TQMouseEvent *qme = TQT_TQMOUSEEVENT(e); if (qme->button() == Qt::RightButton) { showContextMenu(); return true; } } // Attention: We don't filter WheelEvents for KSmallSlider, because it handles WheelEvents itself else if ( (e->type() == TQEvent::Wheel) && !obj->isA("KSmallSlider") ) { TQWheelEvent *qwe = TQT_TQWHEELEVENT(e); if (qwe->delta() > 0) { increaseVolume(); } else { decreaseVolume(); } return true; } return TQWidget::eventFilter(obj,e); } #include "mdwslider.moc"