~ubuntu-branches/ubuntu/natty/kdemultimedia/natty-proposed

« back to all changes in this revision

Viewing changes to kmix/kmix.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Debian Qt/KDE Maintainers
  • Date: 2011-05-26 02:41:36 UTC
  • mfrom: (0.2.3 upstream)
  • mto: This revision was merged to the branch mainline in revision 108.
  • Revision ID: james.westby@ubuntu.com-20110526024136-jjwsigfy402jhupm
Tags: upstream-4.6.3
ImportĀ upstreamĀ versionĀ 4.6.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
/*
3
 
 * KMix -- KDE's full featured mini mixer
4
 
 *
5
 
 * Copyright 1996-2000 Christian Esken <esken@kde.org>
6
 
 * Copyright 2000-2003 Christian Esken <esken@kde.org>, Stefan Schimanski <1Stein@gmx.de>
7
 
 * Copyright 2002-2007 Christian Esken <esken@kde.org>, Helio Chissini de Castro <helio@conectiva.com.br>
8
 
 *
9
 
 * This program is free software; you can redistribute it and/or
10
 
 * modify it under the terms of the GNU Library General Public
11
 
 * License as published by the Free Software Foundation; either
12
 
 * version 2 of the License, or (at your option) any later version.
13
 
 *
14
 
 * This program is distributed in the hope that it will be useful,
15
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 
 * Library General Public License for more details.
18
 
 *
19
 
 * You should have received a copy of the GNU Library General Public
20
 
 * License along with this program; if not, write to the Free
21
 
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
22
 
 */
23
 
 
24
 
 
25
 
// include files for QT
26
 
#include <QCheckBox>
27
 
#include <QLabel>
28
 
#include <QDesktopWidget>
29
 
#include <qradiobutton.h>
30
 
#include <QCursor>
31
 
#include <KTabWidget>
32
 
 
33
 
// include files for KDE
34
 
#include <kcombobox.h>
35
 
#include <kiconloader.h>
36
 
#include <kmessagebox.h>
37
 
#include <kmenubar.h>
38
 
#include <klocale.h>
39
 
#include <kconfig.h>
40
 
#include <kaction.h>
41
 
#include <kapplication.h>
42
 
#include <kstandardaction.h>
43
 
#include <kmenu.h>
44
 
#include <khelpmenu.h>
45
 
#include <kdebug.h>
46
 
#include <kxmlguifactory.h>
47
 
#include <kglobal.h>
48
 
#include <kactioncollection.h>
49
 
#include <ktoggleaction.h>
50
 
 
51
 
// KMix
52
 
#include "mixertoolbox.h"
53
 
#include "kmix.h"
54
 
#include "kmixdevicemanager.h"
55
 
#include "kmixerwidget.h"
56
 
#include "kmixprefdlg.h"
57
 
#include "kmixdockwidget.h"
58
 
#include "kmixtoolbox.h"
59
 
#include "version.h"
60
 
#include "viewdockareapopup.h"
61
 
#include "dialogselectmaster.h"
62
 
 
63
 
#include "osdwidget.h"
64
 
 
65
 
 
66
 
/* KMixWindow
67
 
 * Constructs a mixer window (KMix main window)
68
 
 */
69
 
KMixWindow::KMixWindow(bool invisible)
70
 
   : KXmlGuiWindow(0, Qt::WindowFlags( KDE_DEFAULT_WINDOWFLAGS | Qt::WindowContextHelpButtonHint) ),
71
 
   m_showTicks( true ),
72
 
//   m_isVisible (false),    // initialize, as we don't trigger a hideEvent()
73
 
//   m_visibilityUpdateAllowed( true ),
74
 
   m_multiDriverMode (false), // -<- I never-ever want the multi-drivermode to be activated by accident
75
 
   m_dockWidget(),
76
 
   m_dontSetDefaultCardOnStart (false),
77
 
   _dockAreaPopup(0)
78
 
{
79
 
    setObjectName("KMixWindow");
80
 
    // disable delete-on-close because KMix might just sit in the background waiting for cards to be plugged in
81
 
    setAttribute(Qt::WA_DeleteOnClose, false);
82
 
 
83
 
   initActions(); // init actions first, so we can use them in the loadConfig() already
84
 
   loadConfig(); // Load config before initMixer(), e.g. due to "MultiDriver" keyword
85
 
   KGlobal::locale()->insertCatalog("kmix-controls");
86
 
   initWidgets();
87
 
   initPrefDlg();
88
 
   MixerToolBox::instance()->initMixer(m_multiDriverMode, m_hwInfoString);
89
 
   KMixDeviceManager *theKMixDeviceManager = KMixDeviceManager::instance();
90
 
   recreateGUI(false);
91
 
   fixConfigAfterRead();
92
 
   theKMixDeviceManager->initHotplug();
93
 
   connect(theKMixDeviceManager, SIGNAL( plugged( const char*, const QString&, QString&)), SLOT (plugged( const char*, const QString&, QString&) ) );
94
 
   connect(theKMixDeviceManager, SIGNAL( unplugged( const QString&)), SLOT (unplugged( const QString&) ) );
95
 
   if ( m_startVisible && ! invisible)
96
 
      show(); // Started visible: We don't do "m_isVisible = true;", as the showEvent() already does it
97
 
 
98
 
   connect( kapp, SIGNAL( aboutToQuit()), SLOT( saveConfig()) );
99
 
}
100
 
 
101
 
 
102
 
KMixWindow::~KMixWindow()
103
 
{
104
 
   clearMixerWidgets();
105
 
   MixerToolBox::instance()->deinitMixer();
106
 
}
107
 
 
108
 
 
109
 
void KMixWindow::initActions()
110
 
{
111
 
   // file menu
112
 
   KStandardAction::quit( this, SLOT(quit()), actionCollection());
113
 
 
114
 
   // settings menu
115
 
   _actionShowMenubar = KStandardAction::showMenubar( this, SLOT(toggleMenuBar()), actionCollection());
116
 
   //actionCollection()->addAction( a->objectName(), a );
117
 
   KStandardAction::preferences( this, SLOT(showSettings()), actionCollection());
118
 
   KStandardAction::keyBindings( guiFactory(), SLOT(configureShortcuts()), actionCollection());
119
 
 
120
 
   KAction *action = actionCollection()->addAction( "hwinfo" );
121
 
   action->setText( i18n( "Hardware &Information" ) );
122
 
   connect(action, SIGNAL(triggered(bool) ), SLOT( slotHWInfo() ));
123
 
   action = actionCollection()->addAction( "hide_kmixwindow" );
124
 
   action->setText( i18n( "Hide Mixer Window" ) );
125
 
   connect(action, SIGNAL(triggered(bool) ), SLOT(hideOrClose()));
126
 
   action->setShortcut(QKeySequence(Qt::Key_Escape));
127
 
   action = actionCollection()->addAction("toggle_channels_currentview");
128
 
   action->setText(i18n("Configure &Channels..."));
129
 
   connect(action, SIGNAL(triggered(bool) ), SLOT(slotConfigureCurrentView()));
130
 
   action = actionCollection()->addAction( "select_master" );
131
 
   action->setText( i18n("Select Master Channel...") );
132
 
   connect(action, SIGNAL(triggered(bool) ), SLOT(slotSelectMaster()));
133
 
 
134
 
   KAction* globalAction = actionCollection()->addAction("increase_volume");
135
 
   globalAction->setText(i18n("Increase Volume"));
136
 
   globalAction->setGlobalShortcut(KShortcut(Qt::Key_VolumeUp));
137
 
   connect(globalAction, SIGNAL(triggered(bool) ), SLOT(slotIncreaseVolume()));
138
 
 
139
 
   globalAction = actionCollection()->addAction("decrease_volume");
140
 
   globalAction->setText(i18n("Decrease Volume"));
141
 
   globalAction->setGlobalShortcut(KShortcut(Qt::Key_VolumeDown));
142
 
   connect(globalAction, SIGNAL(triggered(bool) ), SLOT(slotDecreaseVolume()));
143
 
 
144
 
   globalAction = actionCollection()->addAction("mute");
145
 
   globalAction->setText(i18n("Mute"));
146
 
   globalAction->setGlobalShortcut(KShortcut(Qt::Key_VolumeMute));
147
 
   connect(globalAction, SIGNAL(triggered(bool) ), SLOT(slotMute()));
148
 
 
149
 
   osdWidget = new OSDWidget();
150
 
 
151
 
   createGUI( "kmixui.rc" );
152
 
}
153
 
 
154
 
 
155
 
void KMixWindow::initPrefDlg()
156
 
{
157
 
   m_prefDlg = new KMixPrefDlg( this );
158
 
   connect( m_prefDlg, SIGNAL(signalApplied(KMixPrefDlg *)), SLOT(applyPrefs(KMixPrefDlg *)) );
159
 
}
160
 
 
161
 
 
162
 
 
163
 
 
164
 
void KMixWindow::initWidgets()
165
 
{
166
 
   // Main widget and layout
167
 
   setCentralWidget( new QWidget( this ) );
168
 
 
169
 
   // Widgets layout
170
 
   m_widgetsLayout = new QVBoxLayout(   centralWidget()   );
171
 
   m_widgetsLayout->setObjectName(   "m_widgetsLayout"   );
172
 
   m_widgetsLayout->setSpacing(   0   );
173
 
   m_widgetsLayout->setMargin (   0   );
174
 
 
175
 
 
176
 
   m_wsMixers = new KTabWidget( centralWidget() );
177
 
   connect( m_wsMixers, SIGNAL( currentChanged ( int ) ), SLOT( newMixerShown(int)) );
178
 
 
179
 
   m_widgetsLayout->addWidget(m_wsMixers);
180
 
 
181
 
   // show menubar if the actions says so (or if the action does not exist)
182
 
   menuBar()->setVisible( (_actionShowMenubar==0) || _actionShowMenubar->isChecked());
183
 
 
184
 
   m_widgetsLayout->activate();
185
 
}
186
 
 
187
 
 
188
 
/**
189
 
 * Updates the docking icon by recreating it.
190
 
 * @returns Whether the docking succeeded. Failure usually means that there
191
 
 *    was no suitable mixer control selected.
192
 
 */
193
 
bool KMixWindow::updateDocking()
194
 
{
195
 
   // delete old dock widget
196
 
   if (m_dockWidget)
197
 
   {
198
 
      // If this is called during a master control change, the dock widget is currently active, so we use deleteLater().
199
 
      m_dockWidget->deleteLater();
200
 
      m_dockWidget = 0L;
201
 
   }
202
 
   if ( _dockAreaPopup ) {
203
 
      // If this is called during a master control change, we rather play safe by using deleteLater().
204
 
      _dockAreaPopup->deleteLater();
205
 
      _dockAreaPopup = 0L;
206
 
   }
207
 
 
208
 
   if ( m_showDockWidget == false || Mixer::mixers().count() == 0 ) {
209
 
      return false;
210
 
   }
211
 
 
212
 
   // create dock widget and the corresponding popup
213
 
   /* A GUIProfile does not make sense for the DockAreaPopup => Using (GUIProfile*)0 */
214
 
   QWidget* referenceWidgetForSystray = this;
215
 
   if ( m_volumeWidget ) {
216
 
      KMenu *volMenu = new KMenu(this);
217
 
      _dockAreaPopup = new ViewDockAreaPopup(volMenu, "dockArea", Mixer::getGlobalMasterMixer(), 0, (GUIProfile*)0, this);
218
 
      _dockAreaPopup->createDeviceWidgets();
219
 
 
220
 
      QWidgetAction *volWA = new QWidgetAction(volMenu);
221
 
      volWA->setDefaultWidget(_dockAreaPopup);
222
 
      volMenu->addAction(volWA);
223
 
      referenceWidgetForSystray = volMenu;
224
 
   }
225
 
   m_dockWidget = new KMixDockWidget( this, referenceWidgetForSystray, _dockAreaPopup );
226
 
   //m_dockWidget->show();
227
 
   connect(m_dockWidget, SIGNAL(newMasterSelected()), SLOT(saveConfig()) );
228
 
   return true;
229
 
}
230
 
 
231
 
void KMixWindow::saveConfig()
232
 
{
233
 
   saveBaseConfig();
234
 
   saveViewConfig();
235
 
   saveVolumes();
236
 
#ifdef __GNUC_
237
 
#warn We must Sync here, or we will lose configuration data. The reson for that is unknown.
238
 
#endif
239
 
   KGlobal::config()->sync();
240
 
}
241
 
 
242
 
void KMixWindow::saveBaseConfig()
243
 
{
244
 
   KConfigGroup config(KGlobal::config(), "Global");
245
 
 
246
 
   config.writeEntry( "Size", size() );
247
 
   config.writeEntry( "Position", pos() );
248
 
   // Cannot use isVisible() here, as in the "aboutToQuit()" case this widget is already hidden.
249
 
   // (Please note that the problem was only there when quitting via Systray - esken).
250
 
   // Using it again, as internal behaviour has changed with KDE4
251
 
   config.writeEntry( "Visible", isVisible() );
252
 
   config.writeEntry( "Menubar", _actionShowMenubar->isChecked() );
253
 
   config.writeEntry( "AllowDocking", m_showDockWidget );
254
 
   config.writeEntry( "TrayVolumeControl", m_volumeWidget );
255
 
   config.writeEntry( "Tickmarks", m_showTicks );
256
 
   config.writeEntry( "Labels", m_showLabels );
257
 
   config.writeEntry( "startkdeRestore", m_onLogin );
258
 
   config.writeEntry( "DefaultCardOnStart", m_defaultCardOnStart );
259
 
   config.writeEntry( "ConfigVersion", KMIX_CONFIG_VERSION );
260
 
   Mixer* mixerMasterCard = Mixer::getGlobalMasterMixer();
261
 
   if ( mixerMasterCard != 0 ) {
262
 
      config.writeEntry( "MasterMixer", mixerMasterCard->id() );
263
 
   }
264
 
   MixDevice* mdMaster = Mixer::getGlobalMasterMD();
265
 
   if ( mdMaster != 0 ) {
266
 
      config.writeEntry( "MasterMixerDevice", mdMaster->id() );
267
 
   }
268
 
   QString mixerIgnoreExpression = MixerToolBox::instance()->mixerIgnoreExpression();
269
 
   config.writeEntry( "MixerIgnoreExpression", mixerIgnoreExpression );
270
 
 
271
 
   // @todo basically this should be moved in the views later (e.g. KDE4.2 ?)
272
 
   if ( m_toplevelOrientation  == Qt::Horizontal )
273
 
      config.writeEntry( "Orientation","Horizontal" );
274
 
   else
275
 
      config.writeEntry( "Orientation","Vertical" );
276
 
}
277
 
 
278
 
void KMixWindow::saveViewConfig()
279
 
{
280
 
    // Save Views
281
 
    for ( int i=0; i<m_wsMixers->count() ; ++i )
282
 
    {
283
 
        QWidget *w = m_wsMixers->widget(i);
284
 
        if ( w->inherits("KMixerWidget") ) {
285
 
            KMixerWidget* mw = (KMixerWidget*)w;
286
 
            // Here also Views are saved. even for Mixers that are closed. This is necessary when unplugging cards.
287
 
            // Otherwise the user will be confused afer re-plugging the card (as the config was not saved).
288
 
            mw->saveConfig( KGlobal::config().data() );
289
 
        }
290
 
    }
291
 
}
292
 
 
293
 
 
294
 
/**
295
 
 * Stores the volumes of all mixers  Can be restored via loadVolumes() or
296
 
 * the kmixctrl application.
297
 
 */
298
 
void KMixWindow::saveVolumes()
299
 
{
300
 
   KConfig *cfg = new KConfig( "kmixctrlrc" );
301
 
   for ( int i=0; i<Mixer::mixers().count(); ++i)
302
 
   {
303
 
      Mixer *mixer = (Mixer::mixers())[i];
304
 
      if ( mixer->isOpen() ) { // protect from unplugged devices (better do *not* save them)
305
 
          mixer->volumeSave( cfg );
306
 
      }
307
 
   }
308
 
   delete cfg;
309
 
}
310
 
 
311
 
 
312
 
 
313
 
void KMixWindow::loadConfig()
314
 
{
315
 
   loadBaseConfig();
316
 
   //loadViewConfig(); // mw->loadConfig() explicitly called always after creating mw.
317
 
   //loadVolumes(); // not in use
318
 
}
319
 
 
320
 
void KMixWindow::loadBaseConfig()
321
 
{
322
 
    KConfigGroup config(KGlobal::config(), "Global");
323
 
 
324
 
   m_showDockWidget = config.readEntry("AllowDocking", true);
325
 
   m_volumeWidget = config.readEntry("TrayVolumeControl", true);
326
 
   m_showTicks = config.readEntry("Tickmarks", true);
327
 
   m_showLabels = config.readEntry("Labels", true);
328
 
   m_onLogin = config.readEntry("startkdeRestore", true );
329
 
   m_startVisible = config.readEntry("Visible", false);
330
 
   m_multiDriverMode = config.readEntry("MultiDriver", false);
331
 
   const QString& orientationString = config.readEntry("Orientation", "Vertical");
332
 
   m_defaultCardOnStart = config.readEntry( "DefaultCardOnStart", "" );
333
 
   m_configVersion = config.readEntry( "ConfigVersion", 0 );
334
 
   // WARNING Don't overwrite m_configVersion with the "correct" value, before having it
335
 
   // evaluated. Better only write that in saveBaseConfig()
336
 
   QString mixerMasterCard = config.readEntry( "MasterMixer", "" );
337
 
   QString masterDev = config.readEntry( "MasterMixerDevice", "" );
338
 
   //if ( ! mixerMasterCard.isEmpty() && ! masterDev.isEmpty() ) {
339
 
      Mixer::setGlobalMaster(mixerMasterCard, masterDev);
340
 
   //}
341
 
   QString mixerIgnoreExpression = config.readEntry( "MixerIgnoreExpression", "Modem" );
342
 
   MixerToolBox::instance()->setMixerIgnoreExpression(mixerIgnoreExpression);
343
 
 
344
 
   if ( orientationString == "Horizontal" )
345
 
       m_toplevelOrientation  = Qt::Horizontal;
346
 
   else
347
 
       m_toplevelOrientation = Qt::Vertical;
348
 
 
349
 
   // show/hide menu bar
350
 
   bool showMenubar = config.readEntry("Menubar", true);
351
 
 
352
 
   if (_actionShowMenubar) _actionShowMenubar->setChecked( showMenubar );
353
 
 
354
 
   // restore window size and position
355
 
   if ( !kapp->isSessionRestored() ) // done by the session manager otherwise
356
 
   {
357
 
      QSize defSize( minimumWidth(), height() );
358
 
      QSize size = config.readEntry("Size", defSize );
359
 
      if(!size.isEmpty()) resize(size);
360
 
 
361
 
      QPoint defPos = pos();
362
 
      QPoint pos = config.readEntry("Position", defPos);
363
 
      move(pos);
364
 
   }
365
 
}
366
 
 
367
 
/**
368
 
 * Loads the volumes of all mixers from kmixctrlrc.
369
 
 * In other words:
370
 
 * Restores the default voumes as stored via saveVolumes() or the
371
 
 * execution of "kmixctrl --save"
372
 
 */
373
 
/* Currently this is not in use
374
 
void
375
 
KMixWindow::loadVolumes()
376
 
{
377
 
    KConfig *cfg = new KConfig( "kmixctrlrc", true );
378
 
    for ( int i=0; i<Mixer::mixers().count(); ++i)
379
 
    {
380
 
        Mixer *mixer = (Mixer::mixers())[i];
381
 
        mixer->volumeLoad( cfg );
382
 
    }
383
 
    delete cfg;
384
 
}
385
 
*/
386
 
 
387
 
 
388
 
 
389
 
 
390
 
void KMixWindow::recreateGUIwithoutSavingView()
391
 
{
392
 
        recreateGUI(false);
393
 
}
394
 
 
395
 
 
396
 
/**
397
 
 * Create or recreate the Mixer GUI elements
398
 
 */
399
 
void KMixWindow::recreateGUI(bool saveConfig)
400
 
{
401
 
   saveViewConfig();  // save the state before recreating
402
 
   clearMixerWidgets();
403
 
   if ( Mixer::mixers().count() > 0 ) {
404
 
      for (int i=0; i<Mixer::mixers().count(); ++i) {
405
 
         Mixer *mixer = (Mixer::mixers())[i];
406
 
         addMixerWidget(mixer->id());
407
 
      }
408
 
      bool dockingSucceded = updateDocking();
409
 
      if( !dockingSucceded && Mixer::mixers().count() > 0 )
410
 
         show(); // avoid invisible and unaccessible main window
411
 
   }
412
 
   else {
413
 
      // No soundcard found. Do not complain, but sit in the background, and wait for newly plugged soundcards.
414
 
       updateDocking();  // -<- removes the DockIcon
415
 
       hide();
416
 
   }
417
 
}
418
 
 
419
 
 
420
 
void KMixWindow::fixConfigAfterRead()
421
 
{
422
 
   KConfigGroup grp(KGlobal::config(), "Global");
423
 
   unsigned int configVersion = grp.readEntry( "ConfigVersion", 0 );
424
 
   if ( configVersion < 3 ) {
425
 
       // Fix the "double Base" bug, by deleting all groups starting with "View.Base.Base.".
426
 
       // The group has been copied over by KMixToolBox::loadView() for all soundcards, so
427
 
       // we should be fine now
428
 
       QStringList cfgGroups = KGlobal::config()->groupList();
429
 
       QStringListIterator it(cfgGroups);
430
 
       while ( it.hasNext() ) {
431
 
          QString groupName = it.next();
432
 
          if ( groupName.indexOf("View.Base.Base" ) == 0 ) {
433
 
               kDebug(67100) << "Fixing group " << groupName;
434
 
               KConfigGroup buggyDevgrpCG = KGlobal::config()->group( groupName );
435
 
               buggyDevgrpCG.deleteGroup();
436
 
          } // remove buggy group
437
 
       } // for all groups
438
 
   } // if config version < 3
439
 
}
440
 
 
441
 
void KMixWindow::plugged( const char* driverName, const QString& /*udi*/, QString& dev)
442
 
{
443
 
//     kDebug(67100) << "Plugged: dev=" << dev << "(" << driverName << ") udi=" << udi << "\n";
444
 
    QString driverNameString;
445
 
    driverNameString = driverName;
446
 
    int devNum = dev.toInt();
447
 
    Mixer *mixer = new Mixer( driverNameString, devNum );
448
 
    if ( mixer != 0 ) {
449
 
        kDebug(67100) << "Plugged: dev=" << dev << "\n";
450
 
        MixerToolBox::instance()->possiblyAddMixer(mixer);
451
 
        recreateGUI(true);
452
 
    }
453
 
 
454
 
// Test code for OSD. But OSD is postponed to KDE4.1
455
 
//    OSDWidget* osd = new OSDWidget(0);
456
 
//    osd->volChanged(70, true);
457
 
 
458
 
}
459
 
 
460
 
void KMixWindow::unplugged( const QString& udi)
461
 
{
462
 
//     kDebug(67100) << "Unplugged: udi=" <<udi << "\n";
463
 
    for (int i=0; i<Mixer::mixers().count(); ++i) {
464
 
        Mixer *mixer = (Mixer::mixers())[i];
465
 
//         kDebug(67100) << "Try Match with:" << mixer->udi() << "\n";
466
 
        if (mixer->udi() == udi ) {
467
 
            kDebug(67100) << "Unplugged Match: Removing udi=" <<udi << "\n";
468
 
            //KMixToolBox::notification("MasterFallback", "aaa");
469
 
            bool globalMasterMixerDestroyed = ( mixer == Mixer::getGlobalMasterMixer() );
470
 
            // Part 1) Remove Tab
471
 
            for ( int i=0; i<m_wsMixers->count() ; ++i )
472
 
            {
473
 
                QWidget *w = m_wsMixers->widget(i);
474
 
                KMixerWidget* kmw = ::qobject_cast<KMixerWidget*>(w);
475
 
                if ( kmw && kmw->mixer() ==  mixer ) {
476
 
                    kmw->saveConfig( KGlobal::config().data() );
477
 
                    m_wsMixers->removeTab(i);
478
 
                    delete kmw;
479
 
                    i= -1; // Restart loop from scratch (indices are most likeliy invalidated at removeTab() )
480
 
                }
481
 
            }
482
 
            MixerToolBox::instance()->removeMixer(mixer);
483
 
            // Check whether the Global Master disappeared, and select a new one if necessary
484
 
            MixDevice* md = Mixer::getGlobalMasterMD();
485
 
            if ( globalMasterMixerDestroyed || md == 0 ) {
486
 
                // We don't know what the global master should be now.
487
 
                // So lets play stupid, and just select the recommendended master of the first device
488
 
                if ( Mixer::mixers().count() > 0 ) {
489
 
                    QString localMaster = ((Mixer::mixers())[0])->getLocalMasterMD()->id();
490
 
                    Mixer::setGlobalMaster( ((Mixer::mixers())[0])->id(), localMaster);
491
 
                    
492
 
                    QString text;
493
 
                    text = i18n("The soundcard containing the master device was unplugged. Changing to control %1 on card %2.", 
494
 
                            ((Mixer::mixers())[0])->getLocalMasterMD()->readableName(),
495
 
                            ((Mixer::mixers())[0])->readableName()
496
 
                                );
497
 
                    KMixToolBox::notification("MasterFallback", text);
498
 
                }
499
 
            }
500
 
            if ( Mixer::mixers().count() == 0 ) {
501
 
                QString text;
502
 
                text = i18n("The last soundcard was unplugged.");
503
 
                KMixToolBox::notification("MasterFallback", text);
504
 
            }
505
 
            recreateGUI(true);
506
 
            break;
507
 
        }
508
 
    }
509
 
 
510
 
}
511
 
 
512
 
 
513
 
/**
514
 
 * Create a widget with an error message
515
 
 * This widget shows an error message like "no mixers detected.
516
 
void KMixWindow::setErrorMixerWidget()
517
 
{
518
 
   QString s = i18n("Please plug in your soundcard.No soundcard found. Probably you have not set it up or are missing soundcard drivers. Please check your operating system manual for installing your soundcard."); // !! better text
519
 
   m_errorLabel = new QLabel( s,this  );
520
 
   m_errorLabel->setAlignment( Qt::AlignCenter );
521
 
   m_errorLabel->setWordWrap(true);
522
 
   m_errorLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
523
 
   m_wsMixers->addTab( m_errorLabel, i18n("No soundcard found") );
524
 
}
525
 
 */
526
 
 
527
 
void KMixWindow::clearMixerWidgets()
528
 
{
529
 
   while ( m_wsMixers->count() != 0 )
530
 
   {
531
 
      QWidget *mw = m_wsMixers->widget(0);
532
 
      m_wsMixers->removeTab(0);
533
 
      delete mw;
534
 
   }
535
 
}
536
 
 
537
 
 
538
 
 
539
 
void KMixWindow::addMixerWidget(const QString& mixer_ID)
540
 
{
541
 
//    kDebug(67100) << "KMixWindow::addMixerWidget() " << mixer_ID;
542
 
   Mixer *mixer = MixerToolBox::instance()->find(mixer_ID);
543
 
   if ( mixer != 0 )
544
 
   {
545
 
//       kDebug(67100) << "KMixWindow::addMixerWidget() " << mixer_ID << " is being added";
546
 
      ViewBase::ViewFlags vflags = ViewBase::HasMenuBar;
547
 
      if ( (_actionShowMenubar==0) || _actionShowMenubar->isChecked() ) {
548
 
            vflags |= ViewBase::MenuBarVisible;
549
 
      }
550
 
      if ( m_toplevelOrientation == Qt::Vertical ) {
551
 
            vflags |= ViewBase::Horizontal;
552
 
      }
553
 
      else {
554
 
            vflags |= ViewBase::Vertical;
555
 
      }
556
 
 
557
 
 
558
 
      KMixerWidget *kmw = new KMixerWidget( mixer, this, "KMixerWidget", vflags, actionCollection() );
559
 
 
560
 
      /* A newly added mixer will automatically added at the top
561
 
      * and thus the window title is also set appropriately */
562
 
      bool isFirstTab = m_wsMixers->count() == 0;
563
 
      m_wsMixers->addTab( kmw, kmw->mixer()->readableName() );
564
 
      if (isFirstTab || kmw->mixer()->id() == m_defaultCardOnStart ) {
565
 
         m_dontSetDefaultCardOnStart = true; // inhipbit implicit stting of m_defaultCardOnStart
566
 
         m_wsMixers->setCurrentWidget(kmw);
567
 
         m_dontSetDefaultCardOnStart = false;
568
 
         if ( m_defaultCardOnStart.isEmpty() )
569
 
            m_defaultCardOnStart = kmw->mixer()->id(); // If there was noc configuration file entry
570
 
      }
571
 
 
572
 
      kmw->loadConfig( KGlobal::config().data() );
573
 
 
574
 
      kmw->setTicks( m_showTicks );
575
 
      kmw->setLabels( m_showLabels );
576
 
      kmw->mixer()->readSetFromHWforceUpdate();
577
 
   } // given mixer exist really
578
 
}
579
 
 
580
 
 
581
 
 
582
 
bool KMixWindow::queryClose ( )
583
 
{
584
 
//     kDebug(67100) << "queryClose ";
585
 
    if ( m_showDockWidget && !kapp->sessionSaving() )
586
 
    {
587
 
//         kDebug(67100) << "don't close";
588
 
        // Hide (don't close and destroy), if docking is enabled. Except when session saving (shutdown) is in process.
589
 
        hide();
590
 
        return false;
591
 
    }
592
 
    else {
593
 
        // Accept the close, if:
594
 
        //     The user has disabled docking
595
 
        // or  SessionSaving() is running
596
 
//         kDebug(67100) << "close";
597
 
        return true;
598
 
    }
599
 
}
600
 
 
601
 
void KMixWindow::hideOrClose ( )
602
 
{
603
 
    if ( m_showDockWidget  && m_dockWidget != 0) {
604
 
        // we can hide if there is a dock widget
605
 
        hide();
606
 
    }
607
 
    else {
608
 
        //  if there is no dock widget, we will quit
609
 
        quit();
610
 
    }
611
 
}
612
 
 
613
 
// internal helper to prevent code duplication in slotIncreaseVolume and slotDecreaseVolume
614
 
void KMixWindow::increaseOrDecreaseVolume(bool increase)
615
 
{
616
 
  Mixer* mixer = Mixer::getGlobalMasterMixer(); // only needed for the awkward construct below
617
 
  if ( mixer == 0 ) return; // e.g. when no soundcard is available
618
 
  MixDevice *md = Mixer::getGlobalMasterMD();
619
 
  if ( md == 0 ) return; // shouldn't happen, but lets play safe
620
 
  md->setMuted(false);
621
 
  if (increase)
622
 
    mixer->increaseVolume(md->id());    // this is awkward. Better move the increaseVolume impl to the Volume class.
623
 
  else
624
 
    mixer->decreaseVolume(md->id());
625
 
  // md->playbackVolume().increase(); // not yet implemented
626
 
  showVolumeDisplay();
627
 
}
628
 
 
629
 
void KMixWindow::slotIncreaseVolume()
630
 
{
631
 
  increaseOrDecreaseVolume(true);
632
 
}
633
 
 
634
 
void KMixWindow::slotDecreaseVolume()
635
 
{
636
 
  increaseOrDecreaseVolume(false);
637
 
}
638
 
 
639
 
void KMixWindow::showVolumeDisplay()
640
 
{
641
 
  Mixer* mixer = Mixer::getGlobalMasterMixer();
642
 
  if ( mixer == 0 ) return; // e.g. when no soundcard is available
643
 
  MixDevice *md = Mixer::getGlobalMasterMD();
644
 
  if ( md == 0 ) return; // shouldn't happen, but lets play safe
645
 
  int currentVolume = mixer->volume(md->id());
646
 
  
647
 
  osdWidget->setCurrentVolume(currentVolume, md->isMuted());
648
 
  osdWidget->show();
649
 
  osdWidget->activateOSD(); //Enable the hide timer
650
 
 
651
 
  //Center the OSD
652
 
  QRect rect = KApplication::kApplication()->desktop()->screenGeometry(QCursor::pos());
653
 
  QSize size = osdWidget->sizeHint();
654
 
  int posX = rect.x() + (rect.width() - size.width()) / 2;
655
 
  int posY = rect.y() + 4 * rect.height() / 5;
656
 
  osdWidget->setGeometry(posX, posY, size.width(), size.height());
657
 
}
658
 
 
659
 
void KMixWindow::slotMute()
660
 
{
661
 
  Mixer* mixer = Mixer::getGlobalMasterMixer();
662
 
  if ( mixer == 0 ) return; // e.g. when no soundcard is available
663
 
  MixDevice *md = Mixer::getGlobalMasterMD();
664
 
  if ( md == 0 ) return; // shouldn't happen, but lets play safe
665
 
  mixer->toggleMute(md->id()); 
666
 
  showVolumeDisplay();
667
 
}
668
 
 
669
 
void KMixWindow::quit()
670
 
{
671
 
//     kDebug(67100) << "quit";
672
 
    kapp->quit();
673
 
}
674
 
 
675
 
 
676
 
void KMixWindow::showSettings()
677
 
{
678
 
   if (!m_prefDlg->isVisible())
679
 
   {
680
 
      // copy actual values to dialog
681
 
      m_prefDlg->m_dockingChk->setChecked( m_showDockWidget );
682
 
      m_prefDlg->m_volumeChk->setChecked(m_volumeWidget);
683
 
      m_prefDlg->m_volumeChk->setEnabled( m_showDockWidget );
684
 
      m_prefDlg->m_onLogin->setChecked( m_onLogin );
685
 
 
686
 
      m_prefDlg->m_showTicks->setChecked( m_showTicks );
687
 
      m_prefDlg->m_showLabels->setChecked( m_showLabels );
688
 
      m_prefDlg->_rbVertical  ->setChecked( m_toplevelOrientation == Qt::Vertical );
689
 
      m_prefDlg->_rbHorizontal->setChecked( m_toplevelOrientation == Qt::Horizontal );
690
 
 
691
 
      // show dialog
692
 
      m_prefDlg->show();
693
 
   }
694
 
}
695
 
 
696
 
 
697
 
void KMixWindow::showHelp()
698
 
{
699
 
   actionCollection()->action( "help_contents" )->trigger();
700
 
}
701
 
 
702
 
 
703
 
void
704
 
KMixWindow::showAbout()
705
 
{
706
 
   actionCollection()->action( "help_about_app" )->trigger();
707
 
}
708
 
 
709
 
 
710
 
 
711
 
void KMixWindow::applyPrefs( KMixPrefDlg *prefDlg )
712
 
{
713
 
   bool labelsHasChanged = m_showLabels ^ prefDlg->m_showLabels->isChecked();
714
 
   bool ticksHasChanged = m_showTicks ^ prefDlg->m_showTicks->isChecked();
715
 
   bool dockwidgetHasChanged = m_showDockWidget ^ prefDlg->m_dockingChk->isChecked();
716
 
   bool systrayPopupHasChanged = m_volumeWidget ^ prefDlg->m_volumeChk->isChecked();
717
 
   bool toplevelOrientationHasChanged =
718
 
        ( prefDlg->_rbVertical->isChecked()   && m_toplevelOrientation == Qt::Horizontal )
719
 
     || ( prefDlg->_rbHorizontal->isChecked() && m_toplevelOrientation == Qt::Vertical   );
720
 
 
721
 
   m_showLabels = prefDlg->m_showLabels->isChecked();
722
 
   m_showTicks = prefDlg->m_showTicks->isChecked();
723
 
   m_showDockWidget = prefDlg->m_dockingChk->isChecked();
724
 
   m_volumeWidget = prefDlg->m_volumeChk->isChecked();
725
 
   m_onLogin = prefDlg->m_onLogin->isChecked();
726
 
   if ( prefDlg->_rbVertical->isChecked() ) {
727
 
      m_toplevelOrientation = Qt::Vertical;
728
 
   }
729
 
   else if ( prefDlg->_rbHorizontal->isChecked() ) {
730
 
      m_toplevelOrientation = Qt::Horizontal;
731
 
   }
732
 
 
733
 
   if ( labelsHasChanged || ticksHasChanged || dockwidgetHasChanged || toplevelOrientationHasChanged || systrayPopupHasChanged) {
734
 
      recreateGUI(true);
735
 
   }
736
 
 
737
 
   this->repaint(); // make KMix look fast (saveConfig() often uses several seconds)
738
 
   kapp->processEvents();
739
 
   saveConfig();
740
 
}
741
 
 
742
 
 
743
 
void KMixWindow::toggleMenuBar()
744
 
{
745
 
   menuBar()->setVisible(_actionShowMenubar->isChecked());
746
 
}
747
 
 
748
 
/*
749
 
void KMixWindow::showEvent( QShowEvent * )
750
 
{
751
 
   if ( m_visibilityUpdateAllowed )
752
 
      m_isVisible = isVisible();
753
 
}
754
 
 
755
 
void KMixWindow::hideEvent( QHideEvent * )
756
 
{
757
 
   if ( m_visibilityUpdateAllowed )
758
 
   {
759
 
      m_isVisible = isVisible();
760
 
   }
761
 
}
762
 
 
763
 
void KMixWindow::stopVisibilityUpdates()
764
 
{
765
 
   m_visibilityUpdateAllowed = false;
766
 
}
767
 
*/
768
 
 
769
 
void KMixWindow::slotHWInfo()
770
 
{
771
 
   KMessageBox::information( 0, m_hwInfoString, i18n("Mixer Hardware Information") );
772
 
}
773
 
 
774
 
void KMixWindow::slotConfigureCurrentView()
775
 
{
776
 
    KMixerWidget* mw = (KMixerWidget*)m_wsMixers->currentWidget();
777
 
    ViewBase* view = 0;
778
 
    if (mw) view = mw->currentView();
779
 
    if (view) view->configureView();
780
 
}
781
 
 
782
 
void KMixWindow::slotSelectMaster()
783
 
{
784
 
   DialogSelectMaster* dsm = new DialogSelectMaster(Mixer::getGlobalMasterMixer());
785
 
   if (dsm) dsm->show();
786
 
}
787
 
 
788
 
void KMixWindow::newMixerShown(int /*tabIndex*/ ) {
789
 
   KMixerWidget* mw = (KMixerWidget*)m_wsMixers->currentWidget();
790
 
   if (mw) {
791
 
       setWindowTitle( mw->mixer()->readableName() );
792
 
       if ( ! m_dontSetDefaultCardOnStart )
793
 
           m_defaultCardOnStart = mw->mixer()->id();
794
 
       // As switching the tab does NOT mean switching the master card, we do not need to update dock icon here.
795
 
       // It would lead to unnecesary flickering of the (complete) dock area.
796
 
   }
797
 
}
798
 
 
799
 
 
800
 
 
801
 
#include "kmix.moc"