2
* KMix -- KDE's full featured mini mixer
5
* Copyright (C) 1996-2007 Christian Esken <esken@kde.org>
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Library General Public
9
* License as published by the Free Software Foundation; either
10
* version 2 of the License, or (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Library General Public License for more details.
17
* You should have received a copy of the GNU Library General Public
18
* License along with this program; if not, write to the Free
19
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24
#include <kiconloader.h>
28
#include <kglobalaccel.h>
30
#include <kactioncollection.h>
31
#include <ktoggleaction.h>
34
#include <qtoolbutton.h>
38
#include <QMouseEvent>
45
#include "mdwslider.h"
48
#include "kledbutton.h"
49
#include "ksmallslider.h"
50
#include "verticaltext.h"
52
static const int MIN_SLIDER_SIZE = 50;
55
* MixDeviceWidget that represents a single mix device, inlcuding PopUp, muteLED, ...
57
* Used in KMix main window and DockWidget and PanelApplet.
58
* It can be configured to include or exclude the captureLED and the muteLED.
59
* The direction (horizontal, vertical) can be configured and whether it should
60
* be "small" (uses KSmallSlider instead of QSlider then).
62
* Due to the many options, this is the most complicated MixDeviceWidget subclass.
64
MDWSlider::MDWSlider(MixDevice* md,
65
bool showMuteLED, bool showCaptureLED,
66
bool small, Qt::Orientation orientation,
67
QWidget* parent, ViewBase* mw) :
68
MixDeviceWidget(md,small,orientation,parent,mw),
69
m_linked(true), m_defaultLabelSpacer(0), m_iconLabelSimple(0), m_qcb(0), m_muteText(0),
70
m_playbackSpacer(0), _layout(0), m_extraCaptureLabel( 0 ), m_label( 0 ),
71
m_captureLED( 0 ), m_captureText(0), m_captureSpacer(0)
73
// create actions (on _mdwActions, see MixDeviceWidget)
75
KToggleAction *action = _mdwActions->add<KToggleAction>( "stereo" );
76
action->setText( i18n("&Split Channels") );
77
connect(action, SIGNAL(triggered(bool) ), SLOT(toggleStereoLinked()));
78
action = _mdwActions->add<KToggleAction>( "hide" );
79
action->setText( i18n("&Hide") );
80
connect(action, SIGNAL(triggered(bool) ), SLOT(setDisabled()));
82
if( m_mixdevice->playbackVolume().hasSwitch() ) {
83
KToggleAction *a = _mdwActions->add<KToggleAction>( "mute" );
84
a->setText( i18n("&Muted") );
85
connect( a, SIGNAL(toggled(bool)), SLOT(toggleMuted()) );
88
if( m_mixdevice->captureVolume().hasSwitch() ) {
89
KToggleAction *a = _mdwActions->add<KToggleAction>( "recsrc" );
90
a->setText( i18n("Set &Record Source") );
91
connect( a, SIGNAL(toggled(bool)), SLOT( toggleRecsrc()) );
94
KAction *c = _mdwActions->addAction( "keys" );
95
c->setText( i18n("C&onfigure Shortcuts...") );
96
connect(c, SIGNAL(triggered(bool) ), SLOT(defineKeys()));
99
createWidgets( showMuteLED, showCaptureLED );
101
// The following actions are for the "Configure Shortcuts" dialog
102
/* PLEASE NOTE THAT global shortcuts are saved with the name as set with setName(), instead of their action name.
103
This is a bug according to the thread "Global shortcuts are saved with their text-name and not their action-name - Bug?" on kcd.
104
I work around this by using a text with setText() that is unique, but still readable to the user.
106
//QString actionSuffix = QString("%1@%2").arg(mixDevice()->id()).arg(mixDevice()->mixer()->id());
107
QString actionSuffix = QString(" - %1, %2").arg(mixDevice()->readableName()).arg(mixDevice()->mixer()->readableName());
110
b = _mdwPopupActions->addAction( QString("Increase volume %1").arg( actionSuffix ) );
111
QString increaseVolumeName = i18n( "Increase Volume" );
112
increaseVolumeName += " - " + mixDevice()->readableName() + ", " + mixDevice()->mixer()->readableName();
113
b->setText( increaseVolumeName );
115
#warning GLOBAL SHORTCUTS ARE NOW ASSIGNED TO ALL CONTROLS, as enableGlobalShortcut(), has not been committed
117
b->setGlobalShortcut(dummyShortcut); // -<- enableGlobalShortcut() is not there => use workaround
118
// b->enableGlobalShortcut();
119
connect(b, SIGNAL(triggered(bool) ), SLOT(increaseVolume()));
121
b = _mdwPopupActions->addAction( QString("Decrease volume %1").arg( actionSuffix ) );
122
QString decreaseVolumeName = i18n( "Decrease Volume" );
123
decreaseVolumeName += " - " + mixDevice()->readableName() + ", " + mixDevice()->mixer()->readableName();
124
b->setText( decreaseVolumeName );
126
#warning GLOBAL SHORTCUTS ARE NOW ASSIGNED TO ALL CONTROLS, as enableGlobalShortcut(), has not been committed
128
b->setGlobalShortcut(dummyShortcut); // -<- enableGlobalShortcut() is not there => use workaround
129
// b->enableGlobalShortcut();
130
connect(b, SIGNAL(triggered(bool) ), SLOT( decreaseVolume() ));
132
b = _mdwPopupActions->addAction( QString("Toggle mute %1").arg( actionSuffix ) );
133
QString muteVolumeName = i18n( "Toggle Mute" );
134
muteVolumeName += " - " + mixDevice()->readableName() + ", " + mixDevice()->mixer()->readableName();
135
b->setText( muteVolumeName );
137
#warning GLOBAL SHORTCUTS ARE NOW ASSIGNED TO ALL CONTROLS, as enableGlobalShortcut(), has not been committed
139
b->setGlobalShortcut(dummyShortcut); // -<- enableGlobalShortcut() is not there => use workaround
140
// b->enableGlobalShortcut();
142
connect(b, SIGNAL(triggered(bool) ), SLOT( toggleMuted() ));
143
if (mw) mw->actionCollection()->addAction( QString("Toggle mute %1").arg( actionSuffix ), b );
145
b = _mdwActions->addAction( "Set Record Source" );
146
b->setText( i18n( "Set Record Source" ) );
147
connect(b, SIGNAL(triggered(bool) ), SLOT( toggleRecsrc() ));
149
installEventFilter( this ); // filter for popup
155
QSizePolicy MDWSlider::sizePolicy() const
157
if ( _orientation == Qt::Vertical ) {
158
return QSizePolicy( QSizePolicy::Fixed, QSizePolicy::MinimumExpanding );
161
return QSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed );
165
/* This method is a helper for users of this class who would like to show multiple MDWSlider, and align the sliders.
166
* It returns the "height" (if Vertical) or width (of Horizontal) of the "playback portion" (e.g. Icon, Label, QCheckBox)
168
int MDWSlider::playbackExtentHint() const
170
int currentExtent = 0;
171
if ( _orientation == Qt::Vertical ) {
172
if ( m_qcb ) currentExtent += m_qcb->height();
173
if ( m_muteText ) currentExtent += m_muteText->height();
176
if ( m_qcb ) currentExtent += m_qcb->width();
177
if ( m_muteText ) currentExtent += m_muteText->width();
179
return currentExtent;
182
void MDWSlider::setPlaybackExtent(int extent) {
183
if ( playbackExtentHint() < extent ) {
184
if ( _orientation == Qt::Vertical )
185
if ( playbackExtentHint() < extent )
186
m_playbackSpacer->setFixedHeight(extent-playbackExtentHint());
188
m_playbackSpacer->setFixedHeight(0);
190
if ( playbackExtentHint() < extent )
191
m_playbackSpacer->setFixedWidth(extent-playbackExtentHint());
193
m_playbackSpacer->setFixedWidth(0);
197
/* This method is a helper for users of this class who would like to show multiple MDWSlider, and align the sliders.
198
* It returns the "height" (if Vertical) or width (of Horizontal) of the "capture portion" (e.g. Label, QCheckBox)
200
int MDWSlider::captureExtentHint() const
202
int currentExtent = 0;
203
if ( _orientation == Qt::Vertical ) {
204
if ( m_captureLED ) currentExtent += m_captureLED->height();
205
if ( m_captureText ) currentExtent += m_captureText->height();
208
if ( m_captureLED ) currentExtent += m_captureLED->width();
209
if ( m_captureText ) currentExtent += m_captureText->width();
211
return currentExtent;
214
void MDWSlider::setCaptureExtent(int extent) {
216
if ( _orientation == Qt::Vertical ) {
217
m_defaultLabelSpacer->setFixedHeight(extent);
218
if ( captureExtentHint() < extent )
219
m_captureSpacer->setFixedHeight(extent-captureExtentHint());
221
m_captureSpacer->setFixedHeight(0);
224
m_defaultLabelSpacer->setFixedWidth(extent);
225
if ( captureExtentHint() < extent )
226
m_captureSpacer->setFixedWidth(extent-captureExtentHint());
228
m_captureSpacer->setFixedWidth(0);
233
void MDWSlider::addDefaultLabel(QBoxLayout *layout, Qt::Orientation orientation)
235
QBoxLayout *labelLayout;
236
if ( orientation == Qt::Vertical ) {
237
labelLayout = new QVBoxLayout( );
238
labelLayout->setAlignment(Qt::AlignHCenter|Qt::AlignBottom);
239
m_label = new VerticalText( this, m_mixdevice->readableName() ); // .toUtf8().data()
242
labelLayout = new QHBoxLayout();
243
labelLayout->setAlignment(Qt::AlignVCenter|Qt::AlignLeft);
244
m_label = new QLabel(this);
245
static_cast<QLabel*>(m_label) ->setText(m_mixdevice->readableName());
247
//m_label->setToolTip( m_mixdevice->readableName() ); // @todo: Whatsthis, explaining the device
248
m_label->installEventFilter( this );
249
labelLayout->addWidget( m_label );
250
layout->addItem( labelLayout );
252
m_defaultLabelSpacer = new QWidget(this);
253
labelLayout->addWidget( m_defaultLabelSpacer );
254
m_defaultLabelSpacer->installEventFilter(this);
259
* Creates all widgets - Icon/Mute-Button, Slider(s) and capture-Button.
261
* Those widgets are placed into
263
void MDWSlider::createWidgets( bool showMuteLED, bool showCaptureLED )
265
// Base layout with two items: Left the Label, and Right the Sliders
266
if ( _orientation == Qt::Vertical ) {
267
_layout = new QHBoxLayout( this );
270
_layout = new QVBoxLayout( this );
272
_layout->setAlignment(Qt::AlignLeft|Qt::AlignTop);
273
_layout->setSpacing(0);
274
_layout->setMargin(0);
276
bool hasVolumeSliders = ( m_mixdevice->playbackVolume().count() + m_mixdevice->captureVolume().count() > 0 );
278
// --- LABEL -----------------------------------------------
279
if ( hasVolumeSliders ) {
280
// When we have volume sliders, we put the label left of them (in an own layout). Otherwise see below at "if ( ! hasVolumeSliders )"
281
addDefaultLabel( _layout, _orientation);
284
// The controlLayout holds three items: TopPart (Icon + MuteCheckBox + Label) ; MiddlePart (Sliders); Lower Part (CaptureCheckBox + Label)
285
QBoxLayout *controlLayout;
286
if ( _orientation == Qt::Vertical ) {
287
controlLayout = new QVBoxLayout();
288
controlLayout->setAlignment(Qt::AlignHCenter|Qt::AlignTop);
291
controlLayout = new QHBoxLayout();
292
controlLayout->setAlignment(Qt::AlignVCenter|Qt::AlignLeft);
294
_layout->addItem( controlLayout );
296
// --- ICON + Mute Switch ----------------------------
297
createWidgetsTopPart(controlLayout, showMuteLED);
299
controlLayout->addSpacing( 3 );
301
// --- SLIDERS ---------------------------
302
QBoxLayout *volLayout;
303
if ( _orientation == Qt::Vertical ) {
304
volLayout = new QHBoxLayout( );
305
// we use AlignBottom, so that Switches will be aligned with the bottom of the sliders
306
volLayout->setAlignment(Qt::AlignHCenter|Qt::AlignBottom);
309
volLayout = new QVBoxLayout( );
310
volLayout->setAlignment(Qt::AlignVCenter|Qt::AlignRight);
312
controlLayout->addItem( volLayout );
315
// -- SLIDERS, LEDS AND ICON
316
if ( ! hasVolumeSliders ) {
317
// When we don't have volume sliders, we but the label left of them (in an own layout). Otherwise see below
318
addDefaultLabel( volLayout, _orientation );
321
bool bothCaptureANDPlaybackExist = ( m_mixdevice->playbackVolume().count() > 0 && m_mixdevice->captureVolume().count() > 0 );
322
// --- SLIDERS -----------------------------------------------
323
if ( m_mixdevice->playbackVolume().count() > 0 )
324
addSliders( volLayout, 'p', false );
325
if ( m_mixdevice->captureVolume().count() > 0 )
326
addSliders( volLayout, 'c', bothCaptureANDPlaybackExist );
329
createWidgetsBottomPart(controlLayout, showCaptureLED);
331
layout()->activate(); // Activate it explicitly in KDE3 because of PanelApplet/kicker issues
335
/* Creates the top part: Icon, PlaybackSwitch (Switch + Text) */
336
void MDWSlider::createWidgetsTopPart(QBoxLayout *layout, bool showMuteLED)
338
QBoxLayout *m_iconLayout;
339
if ( _orientation == Qt::Vertical ) {
340
m_iconLayout = new QVBoxLayout( );
341
m_iconLayout->setAlignment(Qt::AlignHCenter|Qt::AlignTop);
344
m_iconLayout = new QHBoxLayout( );
345
m_iconLayout->setAlignment(Qt::AlignVCenter|Qt::AlignLeft);
347
layout->addItem(m_iconLayout);
349
m_iconLabelSimple = 0L;
351
//kDebug(67100) << ">>> MixDevice " << m_mixdevice->readableName() << " icon calculation:";
352
setIcon( m_mixdevice->type() );
353
m_iconLayout->addWidget( m_iconLabelSimple );
354
QString muteTip( m_mixdevice->readableName() );
355
m_iconLabelSimple->setToolTip( muteTip );
356
m_iconLayout->addSpacing( 3 );
357
if ( m_mixdevice->playbackVolume().hasSwitch() ) {
358
if ( m_mixdevice->playbackVolume().switchType() == Volume::OnSwitch ) {
359
m_muteText = new QLabel(i18n("On"), this);
361
else if ( m_mixdevice->playbackVolume().switchType() == Volume::OffSwitch ) {
362
m_muteText = new QLabel( i18n("Off"), this);
365
m_muteText = new QLabel(i18n( "Mute"), this);
367
m_iconLayout->addWidget( m_muteText );
368
m_muteText->installEventFilter(this);
370
m_qcb = new QCheckBox(this);
371
m_iconLayout->addWidget( m_qcb );
372
m_qcb->installEventFilter(this);
373
connect ( m_qcb, SIGNAL( toggled(bool) ), this, SLOT(toggleMuted() ) );
374
QString muteTip( i18n( "Mute/Unmute %1", m_mixdevice->readableName() ) );
375
m_qcb->setToolTip( muteTip );
378
m_playbackSpacer = new QWidget(this);
379
m_iconLayout->addWidget( m_playbackSpacer );
380
m_playbackSpacer->installEventFilter(this);
383
void MDWSlider::createWidgetsBottomPart(QBoxLayout *layout, bool showCaptureLED)
385
// --- capture SOURCE LED --------------------------
386
if ( showCaptureLED ) {
387
layout->addSpacing( 3 );
390
QBoxLayout *reclayout;
391
if ( _orientation == Qt::Vertical ) {
392
reclayout = new QVBoxLayout( );
393
reclayout->setAlignment(Qt::AlignHCenter|Qt::AlignBottom);
396
reclayout = new QHBoxLayout( );
397
reclayout->setAlignment(Qt::AlignVCenter|Qt::AlignRight);
399
layout->addItem( reclayout );
401
m_captureSpacer = new QWidget(this);
402
reclayout->addWidget( m_captureSpacer );
403
m_captureSpacer->installEventFilter(this);
405
if ( showCaptureLED && m_mixdevice->captureVolume().hasSwitch() )
407
m_captureLED = new QCheckBox(this);
408
reclayout->addWidget( m_captureLED );
409
m_captureLED->installEventFilter( this );
410
connect(m_captureLED, SIGNAL(toggled(bool)), this, SLOT(setRecsrc(bool)));
411
QString muteTip( i18n( "Capture/Uncapture %1", m_mixdevice->readableName() ) );
412
m_captureLED->setToolTip( muteTip ); // @todo: Whatsthis, explaining the device
414
m_captureText = new QLabel(i18n("Capture"), this);
415
reclayout->addWidget( m_captureText );
416
m_captureText->installEventFilter(this);
420
void MDWSlider::addSliders( QBoxLayout *volLayout, char type, bool addLabel)
423
QList<Volume::ChannelID>* ref_slidersChidsP;
424
QList<QWidget *>* ref_slidersP;
426
if ( type == 'c' ) { // capture
427
volP = & m_mixdevice->captureVolume();
428
ref_slidersChidsP = & _slidersChidsCapture;
429
ref_slidersP = & m_slidersCapture;
432
volP = & m_mixdevice->playbackVolume();
433
ref_slidersChidsP = & _slidersChidsPlayback;
434
ref_slidersP = & m_slidersPlayback;
438
QList<Volume::ChannelID>& ref_slidersChids = *ref_slidersChidsP;
439
QList<QWidget *>& ref_sliders = *ref_slidersP;
444
static QString capture = i18n("(capture)");
445
QString sliderDescription = m_mixdevice->readableName();
446
if ( type == 'c' ) { // capture
447
sliderDescription += ' ' + capture;
451
if ( _orientation == Qt::Vertical ) {
452
label = new VerticalText( this, sliderDescription );
455
label = new QLabel(this);
456
static_cast<QLabel*>(m_label)->setText(sliderDescription);
458
volLayout->addWidget( label );
459
label->installEventFilter( this );
460
if ( type == 'c' ) { // capture
461
m_extraCaptureLabel = label;
463
label->installEventFilter( this );
466
for ( int i=0; i<= Volume::CHIDMAX; i++ ) {
467
if ( vol._chmask & Volume::_channelMaskEnum[i] ) {
468
Volume::ChannelID chid = Volume::ChannelID(i);
470
long minvol = vol.minVolume();
471
long maxvol = vol.maxVolume();
475
slider = new KSmallSlider( minvol, maxvol, (maxvol-minvol)/10, // @todo !! User definable steps
476
vol.getVolume( chid ), _orientation, this );
479
QSlider* sliderBig = new QSlider( _orientation, this );
481
sliderBig->setMinimum(0);
482
sliderBig->setMaximum(maxvol);
483
sliderBig->setPageStep(maxvol/10);
484
sliderBig->setValue(maxvol - vol.getVolume( chid ));
486
if ( _orientation == Qt::Vertical ) {
487
sliderBig->setMinimumHeight( MIN_SLIDER_SIZE );
490
sliderBig->setMinimumWidth( MIN_SLIDER_SIZE );
494
slider->installEventFilter( this );
496
slider->setToolTip( m_mixdevice->readableName() );
499
QString captureTip( i18n( "%1 (capture)", m_mixdevice->readableName() ) );
500
slider->setToolTip( captureTip );
503
if( i>0 && isStereoLinked() ) {
504
// show only one (the first) slider, when the user wants it so
507
volLayout->addWidget( slider ); // add to layout
508
ref_sliders.append ( slider ); // add to list
509
ref_slidersChids.append(chid);
510
connect( slider, SIGNAL(valueChanged(int)), SLOT(volumeChange(int)) );
511
} //if channel is present
512
} // for all channels of this device
516
QPixmap MDWSlider::icon( int icontype )
521
case MixDevice::AUDIO:
522
miniDevPM = _iconName = "mixer-pcm"; break;
523
case MixDevice::BASS:
524
case MixDevice::SURROUND_LFE: // "LFE" SHOULD have an own icon
525
miniDevPM = _iconName ="mixer-lfe"; break;
527
miniDevPM = _iconName ="mixer-cd"; break;
528
case MixDevice::EXTERNAL:
529
miniDevPM = _iconName = "mixer-line"; break;
530
case MixDevice::MICROPHONE:
531
miniDevPM = _iconName ="mixer-microphone";break;
532
case MixDevice::MIDI:
533
miniDevPM = _iconName ="mixer-midi"; break;
534
case MixDevice::RECMONITOR:
535
miniDevPM = _iconName ="mixer-capture"; break;
536
case MixDevice::TREBLE:
537
miniDevPM = _iconName ="mixer-pcm-default"; break;
538
case MixDevice::UNKNOWN:
539
miniDevPM = _iconName ="mixer-front"; break;
540
case MixDevice::VOLUME:
541
miniDevPM = _iconName ="mixer-master"; break;
542
case MixDevice::VIDEO:
543
miniDevPM = _iconName ="mixer-video"; break;
544
case MixDevice::SURROUND:
545
case MixDevice::SURROUND_BACK:
546
miniDevPM = _iconName = "mixer-surround"; break;
547
case MixDevice::SURROUND_CENTERFRONT:
548
case MixDevice::SURROUND_CENTERBACK:
549
miniDevPM = _iconName ="mixer-surround-center"; break;
550
case MixDevice::HEADPHONE:
551
miniDevPM = _iconName = "mixer-headset"; break;
552
case MixDevice::DIGITAL:
553
miniDevPM = _iconName = "mixer-digital"; break;
554
case MixDevice::AC97:
555
miniDevPM = _iconName = "mixer-ac97"; break;
556
case MixDevice::SPEAKER:
557
miniDevPM = _iconName = "mixer-pc-speaker"; break;
558
case MixDevice::MICROPHONE_BOOST:
559
miniDevPM = _iconName = "mixer-microphone-boost"; break;
560
case MixDevice::MICROPHONE_FRONT_BOOST:
561
miniDevPM = _iconName = "mixer-microphone-front-boost"; break;
562
case MixDevice::MICROPHONE_FRONT:
563
miniDevPM = _iconName = "mixer-microphone-front"; break;
565
miniDevPM = _iconName ="mixer-front"; break;
568
miniDevPM = loadIcon(_iconName);
572
QPixmap MDWSlider::loadIcon( QString& filename )
574
return KIconLoader::global()->loadIcon( filename, KIconLoader::Small, KIconLoader::SizeSmallMedium );
578
MDWSlider::setIcon( int icontype )
580
if( !m_iconLabelSimple )
582
m_iconLabelSimple = new QLabel(this);
583
installEventFilter( m_iconLabelSimple );
586
QPixmap miniDevPM = icon( icontype );
587
if ( !miniDevPM.isNull() )
593
t = t.scale( 10.0/miniDevPM.width(), 10.0/miniDevPM.height() );
594
m_iconLabelSimple->setPixmap( miniDevPM.transformed( t ) );
595
m_iconLabelSimple->resize( 10, 10 );
599
m_iconLabelSimple->setPixmap( miniDevPM );
600
//kDebug(67100) << " > simple > icontype=" <<icontype<< "size=" << miniDevPM.size();
605
kError(67100) << "Pixmap missing." << endl;
608
layout()->activate();
613
MDWSlider::toggleStereoLinked()
615
setStereoLinked( !isStereoLinked() );
619
MDWSlider::setStereoLinked(bool value)
622
if (m_slidersPlayback.count() != 0) setStereoLinkedInternal(m_slidersPlayback);
623
if (m_slidersCapture.count() != 0) setStereoLinkedInternal(m_slidersCapture);
624
update(); // Call update(), so that the sliders can adjust EITHER to the individual values OR the average value.
628
MDWSlider::setStereoLinkedInternal(QList<QWidget *>& ref_sliders)
630
QWidget *slider = ref_sliders[0];
632
/***********************************************************
633
Remember value of first slider, so that it can be copied
634
to the other sliders.
635
***********************************************************/
636
int firstSliderValue = 0;
637
bool firstSliderValueValid = false;
638
if (::qobject_cast<QSlider*>(slider)) {
639
QSlider *sld = static_cast<QSlider*>(slider);
640
firstSliderValue = sld->value();
641
firstSliderValueValid = true;
643
else if ( ::qobject_cast<KSmallSlider*>(slider)) {
644
KSmallSlider *sld = static_cast<KSmallSlider*>(slider);
645
firstSliderValue = sld->value();
646
firstSliderValueValid = true;
649
for( int i=1; i<ref_sliders.count(); ++i ) {
650
slider = ref_sliders[i];
662
// Redo the tickmarks to last slider in the slider list.
663
// The implementation is not obvious, so lets explain:
664
// We ALWAYS have tickmarks on the LAST slider. Sometimes the slider is not shown, and then we just don't bother.
665
// a) So, if the last slider has tickmarks, we can always call setTicks( true ).
666
// b) if the last slider has NO tickmarks, there ae no tickmarks at all, and we don't need to redo the tickmarks.
667
slider = ref_sliders.last();
668
if( slider && ( static_cast<QSlider *>(slider)->tickPosition() != QSlider::NoTicks) )
675
MDWSlider::setLabeled(bool value)
677
if ( m_label == 0 && m_extraCaptureLabel == 0 )
681
if ( m_label != 0) m_label->show();
682
if ( m_extraCaptureLabel != 0) m_extraCaptureLabel->show();
683
if ( m_muteText != 0) m_muteText->show();
684
if ( m_captureText != 0) m_captureText->show();
687
if ( m_label != 0) m_label->hide();
688
if ( m_extraCaptureLabel != 0) m_extraCaptureLabel->hide();
689
if ( m_muteText != 0) m_muteText->hide();
690
if ( m_captureText != 0) m_captureText->hide();
692
layout()->activate();
696
MDWSlider::setTicks( bool value )
698
if (m_slidersPlayback.count() != 0) setTicksInternal(m_slidersPlayback, value);
699
if (m_slidersCapture.count() != 0) setTicksInternal(m_slidersCapture, value);
703
MDWSlider::setTicksInternal(QList<QWidget *>& ref_sliders, bool ticks)
705
QWidget* slider = ref_sliders[0];
707
if ( slider->inherits( "QSlider" ) )
710
if( isStereoLinked() )
711
static_cast<QSlider *>(slider)->setTickPosition( QSlider::TicksRight );
714
static_cast<QSlider *>(slider)->setTickPosition( QSlider::NoTicks );
715
slider = ref_sliders.last();
716
static_cast<QSlider *>(slider)->setTickPosition( QSlider::TicksLeft );
720
static_cast<QSlider *>(slider)->setTickPosition( QSlider::NoTicks );
721
slider = ref_sliders.last();
722
static_cast<QSlider *>(slider)->setTickPosition( QSlider::NoTicks );
728
MDWSlider::setIcons(bool value)
730
if ( m_iconLabelSimple != 0 ) {
731
if ( ( ! m_iconLabelSimple->isHidden()) !=value ) {
733
m_iconLabelSimple->show();
735
m_iconLabelSimple->hide();
737
layout()->activate();
739
} // if it has an icon
743
MDWSlider::setColors( QColor high, QColor low, QColor back )
745
for( int i=0; i<m_slidersPlayback.count(); ++i ) {
746
QWidget *slider = m_slidersPlayback[i];
747
KSmallSlider *smallSlider = dynamic_cast<KSmallSlider*>(slider);
748
if ( smallSlider ) smallSlider->setColors( high, low, back );
750
for( int i=0; i<m_slidersCapture.count(); ++i ) {
751
QWidget *slider = m_slidersCapture[i];
752
KSmallSlider *smallSlider = dynamic_cast<KSmallSlider*>(slider);
753
if ( smallSlider ) smallSlider->setColors( high, low, back );
758
MDWSlider::setMutedColors( QColor high, QColor low, QColor back )
760
for( int i=0; i<m_slidersPlayback.count(); ++i ) {
761
QWidget *slider = m_slidersPlayback[i];
762
KSmallSlider *smallSlider = dynamic_cast<KSmallSlider*>(slider);
763
if ( smallSlider ) smallSlider->setGrayColors( high, low, back );
765
for( int i=0; i<m_slidersCapture.count(); ++i ) {
766
QWidget *slider = m_slidersCapture[i];
767
KSmallSlider *smallSlider = dynamic_cast<KSmallSlider*>(slider);
768
if ( smallSlider ) smallSlider->setGrayColors( high, low, back );
773
/** This slot is called, when a user has changed the volume via the KMix Slider. */
774
void MDWSlider::volumeChange( int )
776
if (m_slidersPlayback.count() > 0) volumeChangeInternal(m_mixdevice->playbackVolume(), _slidersChidsPlayback, m_slidersPlayback);
777
if (m_slidersCapture.count() > 0) volumeChangeInternal(m_mixdevice->captureVolume() , _slidersChidsCapture, m_slidersCapture);
778
m_mixdevice->mixer()->commitVolumeChange(m_mixdevice);
781
void MDWSlider::volumeChangeInternal( Volume& vol, QList<Volume::ChannelID>& ref_slidersChids, QList<QWidget *>& ref_sliders )
784
// --- Step 2: Change the volumes directly in the Volume object to reflect the Sliders ---
785
if ( isStereoLinked() )
787
long firstVolume = 0;
788
if ( ref_sliders.first()->inherits( "KSmallSlider" ) )
790
KSmallSlider *slider = dynamic_cast<KSmallSlider *>(ref_sliders.first());
791
if (slider != 0 ) firstVolume = slider->value();
795
QSlider *slider = dynamic_cast<QSlider *>(ref_sliders.first());
796
if (slider != 0 ) firstVolume = slider->value();
798
vol.setAllVolumes(firstVolume);
802
QList<Volume::ChannelID>::Iterator it = ref_slidersChids.begin();
803
for( int i=0; i<ref_sliders.count(); i++, ++it ) {
804
Volume::ChannelID chid = *it;
805
QWidget *sliderWidget = ref_sliders[i];
807
if ( sliderWidget->inherits( "KSmallSlider" ) )
809
KSmallSlider *slider = dynamic_cast<KSmallSlider *>(sliderWidget);
810
if (slider) vol.setVolume( chid, slider->value() );
814
QSlider *slider = dynamic_cast<QSlider *>(sliderWidget);
815
if (slider) vol.setVolume( chid, slider->value() );
817
} // iterate over all sliders
820
// --- Step 3: Write back the new volumes to the HW ---
825
This slot is called, when a user has clicked the recsrc button. Also it is called by any other
826
associated KAction like the context menu.
828
void MDWSlider::toggleRecsrc() {
829
setRecsrc( m_mixdevice->isRecSource() );
832
void MDWSlider::setRecsrc(bool value )
834
if ( m_mixdevice->captureVolume().hasSwitch() ) {
835
m_mixdevice->setRecSource( value );
836
m_mixdevice->mixer()->commitVolumeChange( m_mixdevice );
842
This slot is called, when a user has clicked the mute button. Also it is called by any other
843
associated KAction like the context menu.
845
void MDWSlider::toggleMuted() {
846
setMuted( ! m_mixdevice->isMuted() );
849
void MDWSlider::setMuted(bool value)
851
if ( m_mixdevice->playbackVolume().hasSwitch() ) {
852
m_mixdevice->setMuted( value );
853
m_mixdevice->mixer()->commitVolumeChange(m_mixdevice);
858
void MDWSlider::setDisabled()
863
void MDWSlider::setDisabled( bool value )
865
if ( m_disabled!=value)
867
value ? hide() : show();
869
m_view->configurationUpdate();
875
This slot is called on a MouseWheel event. Also it is called by any other
876
associated KAction like the context menu.
878
void MDWSlider::increaseVolume()
880
Volume& volP = m_mixdevice->playbackVolume();
881
long inc = volP.maxVolume() / 20;
884
for ( int i = 0; i < volP.count(); i++ ) {
885
long newVal = (volP[i]) + inc;
886
volP.setVolume( (Volume::ChannelID)i, newVal < volP.maxVolume() ? newVal : volP.maxVolume() );
889
Volume& volC = m_mixdevice->captureVolume();
890
inc = volC.maxVolume() / 20;
893
for ( int i = 0; i < volC.count(); i++ ) {
894
long newVal = (volC[i]) + inc;
895
volC.setVolume( (Volume::ChannelID)i, newVal < volC.maxVolume() ? newVal : volC.maxVolume() );
897
m_mixdevice->mixer()->commitVolumeChange(m_mixdevice);
901
This slot is called on a MouseWheel event. Also it is called by any other
902
associated KAction like the context menu.
904
void MDWSlider::decreaseVolume()
906
Volume& volP = m_mixdevice->playbackVolume();
907
long inc = volP.maxVolume() / 20;
910
for ( int i = 0; i < volP.count(); i++ ) {
911
long newVal = (volP[i]) - inc;
912
volP.setVolume( (Volume::ChannelID)i, newVal > 0 ? newVal : 0 );
915
Volume& volC = m_mixdevice->captureVolume();
916
inc = volC.maxVolume() / 20;
919
for ( int i = 0; i < volC.count(); i++ ) {
920
long newVal = (volC[i]) - inc;
921
volC.setVolume( (Volume::ChannelID)i, newVal > 0 ? newVal : 0 );
923
m_mixdevice->mixer()->commitVolumeChange(m_mixdevice);
928
This is called whenever there are volume updates pending from the hardware for this MDW.
929
At the moment it is called regulary via a QTimer (implicitely).
931
void MDWSlider::update()
933
if (m_slidersPlayback.count() != 0 || m_mixdevice->playbackVolume().hasSwitch())
934
updateInternal(m_mixdevice->playbackVolume(), m_slidersPlayback, _slidersChidsPlayback);
935
if (m_slidersCapture.count() != 0 || m_mixdevice->captureVolume().hasSwitch())
936
updateInternal(m_mixdevice->captureVolume(), m_slidersCapture , _slidersChidsCapture );
939
void MDWSlider::updateInternal(Volume& vol, QList<QWidget *>& ref_sliders, QList<Volume::ChannelID>& ref_slidersChids)
942
long useVolume = vol.getAvgVolume( Volume::MMAIN );
945
QList<Volume::ChannelID>::Iterator it = ref_slidersChids.begin();
946
for( int i=0; i<ref_sliders.count(); i++, ++it ) {
947
if( ! isStereoLinked() ) {
948
Volume::ChannelID chid = *it;
949
useVolume = vol[chid];
951
QWidget *slider = ref_sliders.at( i );
953
slider->blockSignals( true );
955
if ( slider->inherits( "KSmallSlider" ) )
957
KSmallSlider *smallSlider = dynamic_cast<KSmallSlider *>(slider);
959
smallSlider->setValue( useVolume );
960
smallSlider->setGray( m_mixdevice->isMuted() );
965
QSlider *bigSlider = dynamic_cast<QSlider *>(slider);
967
bigSlider->setValue( useVolume );
970
slider->blockSignals( false );
978
m_iconLabelSimple->blockSignals( true );
979
m_iconLabelSimple->setChecked( !m_mixdevice->isMuted() );
980
m_iconLabelSimple->blockSignals( false );
982
m_qcb->blockSignals( true );
983
m_qcb->setChecked( m_mixdevice->isMuted() );
984
m_qcb->blockSignals( false );
989
m_captureLED->blockSignals( true );
990
m_captureLED->setChecked( m_mixdevice->isRecSource() );
991
// bool stateToShow = m_mixdevice->isRecSource();
992
// m_captureLED->setState( stateToShow ? KLed::On : KLed::Off );
993
m_captureLED->blockSignals( false );
997
void MDWSlider::showContextMenu()
1002
KMenu *menu = m_view->getPopup();
1003
menu->addTitle( SmallIcon( "kmix" ), m_mixdevice->readableName() );
1005
if ( m_slidersPlayback.count()>1 || m_slidersCapture.count()>1) {
1006
KToggleAction *stereo = (KToggleAction *)_mdwActions->action( "stereo" );
1008
stereo->setChecked( !isStereoLinked() );
1009
menu->addAction( stereo );
1013
if ( m_mixdevice->captureVolume().hasSwitch() ) {
1014
KToggleAction *ta = (KToggleAction *)_mdwActions->action( "recsrc" );
1016
ta->setChecked( m_mixdevice->isRecSource() );
1017
menu->addAction( ta );
1021
if ( m_mixdevice->playbackVolume().hasSwitch() ) {
1022
KToggleAction *ta = ( KToggleAction* )_mdwActions->action( "mute" );
1024
ta->setChecked( m_mixdevice->isMuted() );
1025
menu->addAction( ta );
1029
QAction *a = _mdwActions->action( "hide" );
1031
menu->addAction( a );
1033
QAction *b = _mdwActions->action( "keys" );
1035
// QAction sep( _mdwPopupActions );
1036
// sep.setSeparator( true );
1037
// menu->addAction( &sep );
1038
menu->addAction( b );
1041
QPoint pos = QCursor::pos();
1047
* An event filter for the various QWidgets. We watch for Mouse press Events, so
1048
* that we can popup the context menu.
1050
bool MDWSlider::eventFilter( QObject* obj, QEvent* e )
1052
if (e->type() == QEvent::MouseButtonPress) {
1053
QMouseEvent *qme = static_cast<QMouseEvent*>(e);
1054
if (qme->button() == Qt::RightButton) {
1059
// Attention: We don't filter WheelEvents for KSmallSlider, because it handles WheelEvents itself
1060
else if ( (e->type() == QEvent::Wheel)
1061
&& strcmp(obj->metaObject()->className(),"KSmallSlider") != 0) {
1062
QWheelEvent *qwe = static_cast<QWheelEvent*>(e);
1063
if (qwe->delta() > 0) {
1071
return QWidget::eventFilter(obj,e);
1074
#include "mdwslider.moc"