diff options
| author | Christian Esken <esken@kde.org> | 2012-09-22 21:29:12 (GMT) |
|---|---|---|
| committer | Christian Esken <esken@kde.org> | 2012-09-22 21:29:12 (GMT) |
| commit | 5c57272add398124256cd4f8240b219db3e5128d (patch) | |
| tree | 2080dd3a4bb04e4b02b4f0400004efb3019c00f9 | |
| parent | c8b2da514d0b88be53f4c4efdae7769255bab19c (diff) | |
Moving towards a fully dynamic tray popup, with multiple controls
| -rw-r--r-- | apps/kmix.cpp | 1878 | ||||
| -rw-r--r-- | apps/kmix.h | 5 | ||||
| -rw-r--r-- | backends/mixer_pulse.cpp | 7 | ||||
| -rw-r--r-- | gui/kmixdockwidget.cpp | 9 | ||||
| -rw-r--r-- | gui/kmixdockwidget.h | 3 | ||||
| -rw-r--r-- | gui/viewbase.cpp | 74 | ||||
| -rw-r--r-- | gui/viewbase.h | 10 | ||||
| -rw-r--r-- | gui/viewdockareapopup.cpp | 69 | ||||
| -rw-r--r-- | gui/viewdockareapopup.h | 4 | ||||
| -rw-r--r-- | gui/viewsliders.cpp | 39 |
10 files changed, 1131 insertions, 967 deletions
diff --git a/apps/kmix.cpp b/apps/kmix.cpp index 4ea83ea..5319be6 100644 --- a/apps/kmix.cpp +++ b/apps/kmix.cpp @@ -31,7 +31,6 @@ #include <QCursor> #include <QString> - // include files for KDE #include <kcombobox.h> #include <kiconloader.h> @@ -68,243 +67,256 @@ #include "dbus/dbusmixsetwrapper.h" #include "gui/osdwidget.h" - /* KMixWindow * Constructs a mixer window (KMix main window) */ -KMixWindow::KMixWindow(bool invisible) -: KXmlGuiWindow(0, Qt::WindowFlags( KDE_DEFAULT_WINDOWFLAGS | Qt::WindowContextHelpButtonHint) ), - m_showTicks( true ), - m_multiDriverMode (false), // -<- I never-ever want the multi-drivermode to be activated by accident - m_dockWidget(), - m_dontSetDefaultCardOnStart (false) +KMixWindow::KMixWindow(bool invisible) : + KXmlGuiWindow(0, + Qt::WindowFlags( + KDE_DEFAULT_WINDOWFLAGS | Qt::WindowContextHelpButtonHint)), m_showTicks( + true), m_multiDriverMode(false), // -<- I never-ever want the multi-drivermode to be activated by accident + m_dockWidget(), m_dontSetDefaultCardOnStart(false) { - setObjectName( QLatin1String("KMixWindow" )); - // disable delete-on-close because KMix might just sit in the background waiting for cards to be plugged in - setAttribute(Qt::WA_DeleteOnClose, false); - - kDebug() << "Hello Randa 2012"; - initActions(); // init actions first, so we can use them in the loadConfig() already - loadConfig(); // Load config before initMixer(), e.g. due to "MultiDriver" keyword - initActionsLate(); // init actions that require a loaded config - KGlobal::locale()->insertCatalog( QLatin1String( "kmix-controls" )); - initWidgets(); - initPrefDlg(); - MixerToolBox::instance()->initMixer(m_multiDriverMode, m_backendFilter, m_hwInfoString); - KMixDeviceManager *theKMixDeviceManager = KMixDeviceManager::instance(); - initActionsAfterInitMixer(); // init actions that require initialized mixer backend(s). - - recreateGUI(false); - if ( m_wsMixers->count() < 1 ) + setObjectName(QLatin1String("KMixWindow")); + // disable delete-on-close because KMix might just sit in the background waiting for cards to be plugged in + setAttribute(Qt::WA_DeleteOnClose, false); + + kDebug() + << "Hello Randa 2012"; + initActions(); // init actions first, so we can use them in the loadConfig() already + loadConfig(); // Load config before initMixer(), e.g. due to "MultiDriver" keyword + initActionsLate(); // init actions that require a loaded config + KGlobal::locale()->insertCatalog(QLatin1String("kmix-controls")); + initWidgets(); + initPrefDlg(); + MixerToolBox::instance()->initMixer(m_multiDriverMode, m_backendFilter, + m_hwInfoString); + KMixDeviceManager *theKMixDeviceManager = KMixDeviceManager::instance(); + initActionsAfterInitMixer(); // init actions that require initialized mixer backend(s). + + recreateGUI(false); + if (m_wsMixers->count() < 1) { - // Something is wrong. Perhaps a hardware or driver or backend change. Let KMix search harder - recreateGUI(false, QString(), true); + // Something is wrong. Perhaps a hardware or driver or backend change. Let KMix search harder + recreateGUI(false, QString(), true); } - if ( !kapp->isSessionRestored() ) // done by the session manager otherwise - setInitialSize(); - - fixConfigAfterRead(); - theKMixDeviceManager->initHotplug(); - connect(theKMixDeviceManager, SIGNAL(plugged(const char*,QString,QString&)), SLOT (plugged(const char*,QString,QString&)) ); - connect(theKMixDeviceManager, SIGNAL(unplugged(QString)), SLOT (unplugged(QString)) ); - if ( m_startVisible && ! invisible) - show(); // Started visible - - connect( kapp, SIGNAL(aboutToQuit()), SLOT(saveConfig()) ); - - // Creating a dbus interface - DBusMixSetWrapper *wrapper = new DBusMixSetWrapper( this, "/Mixers" ); - // these signals should be emitted right after the mixer device is added - connect( theKMixDeviceManager, SIGNAL(plugged(const char*,QString,QString&)), - wrapper, SLOT(devicePlugged(const char*,QString,QString&)) ); - connect( theKMixDeviceManager, SIGNAL(unplugged(QString)), - wrapper, SLOT(deviceUnplugged(QString)) ); + if (!kapp->isSessionRestored() ) // done by the session manager otherwise + setInitialSize(); + + fixConfigAfterRead(); + theKMixDeviceManager->initHotplug(); + connect(theKMixDeviceManager, SIGNAL(plugged(const char*,QString,QString&)), + SLOT (plugged(const char*,QString,QString&))); + connect(theKMixDeviceManager, SIGNAL(unplugged(QString)), + SLOT (unplugged(QString))); + if (m_startVisible && !invisible) + show(); // Started visible + + connect(kapp, SIGNAL(aboutToQuit()), SLOT(saveConfig()) ); + + // Creating a dbus interface + DBusMixSetWrapper *wrapper = new DBusMixSetWrapper(this, "/Mixers"); + // these signals should be emitted right after the mixer device is added + connect(theKMixDeviceManager, SIGNAL(plugged(const char*,QString,QString&)), + wrapper, SLOT(devicePlugged(const char*,QString,QString&))); + connect(theKMixDeviceManager, SIGNAL(unplugged(QString)), wrapper, + SLOT(deviceUnplugged(QString))); } - KMixWindow::~KMixWindow() { - // -1- Cleanup Memory: clearMixerWidgets - while ( m_wsMixers->count() != 0 ) + // -1- Cleanup Memory: clearMixerWidgets + while (m_wsMixers->count() != 0) { - QWidget *mw = m_wsMixers->widget(0); - m_wsMixers->removeTab(0); - delete mw; + QWidget *mw = m_wsMixers->widget(0); + m_wsMixers->removeTab(0); + delete mw; } - // -2- Mixer HW - MixerToolBox::instance()->deinitMixer(); + // -2- Mixer HW + MixerToolBox::instance()->deinitMixer(); } - -void KMixWindow::initActions() +void +KMixWindow::initActions() { - // file menu - KStandardAction::quit( this, SLOT(quit()), actionCollection()); - - // settings menu - _actionShowMenubar = KStandardAction::showMenubar( this, SLOT(toggleMenuBar()), actionCollection()); - //actionCollection()->addAction( a->objectName(), a ); - KStandardAction::preferences( this, SLOT(showSettings()), actionCollection()); - KStandardAction::keyBindings( guiFactory(), SLOT(configureShortcuts()), actionCollection()); - KAction* action = actionCollection()->addAction( "launch_kdesoundsetup" ); - action->setText( i18n( "Audio Setup" ) ); - connect(action, SIGNAL(triggered(bool)), SLOT(slotKdeAudioSetupExec())); - - action = actionCollection()->addAction( "hwinfo" ); - action->setText( i18n( "Hardware &Information" ) ); - connect(action, SIGNAL(triggered(bool)), SLOT(slotHWInfo())); - action = actionCollection()->addAction( "hide_kmixwindow" ); - action->setText( i18n( "Hide Mixer Window" ) ); - connect(action, SIGNAL(triggered(bool)), SLOT(hideOrClose())); - action->setShortcut(QKeySequence(Qt::Key_Escape)); - action = actionCollection()->addAction("toggle_channels_currentview"); - action->setText(i18n("Configure &Channels...")); - connect(action, SIGNAL(triggered(bool)), SLOT(slotConfigureCurrentView())); - action = actionCollection()->addAction( "select_master" ); - action->setText( i18n("Select Master Channel...") ); - connect(action, SIGNAL(triggered(bool)), SLOT(slotSelectMaster())); - - action = actionCollection()->addAction( "save_1" ); - action->setShortcut(KShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_1)); - action->setText( i18n("Save volume profile 1") ); - connect(action, SIGNAL(triggered(bool)), SLOT(saveVolumes1())); - - action = actionCollection()->addAction( "save_2" ); - action->setShortcut(KShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_2)); - action->setText( i18n("Save volume profile 2") ); - connect(action, SIGNAL(triggered(bool)), SLOT(saveVolumes2())); - - action = actionCollection()->addAction( "save_3" ); - action->setShortcut(KShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_3)); - action->setText( i18n("Save volume profile 3") ); - connect(action, SIGNAL(triggered(bool)), SLOT(saveVolumes3())); - - action = actionCollection()->addAction( "save_4" ); - action->setShortcut(KShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_4)); - action->setText( i18n("Save volume profile 4") ); - connect(action, SIGNAL(triggered(bool)), SLOT(saveVolumes4())); - - action = actionCollection()->addAction( "load_1" ); - action->setShortcut(KShortcut(Qt::CTRL + Qt::Key_1)); - action->setText( i18n("Load volume profile 1") ); - connect(action, SIGNAL(triggered(bool)), SLOT(loadVolumes1())); - - action = actionCollection()->addAction( "load_2" ); - action->setShortcut(KShortcut(Qt::CTRL + Qt::Key_2)); - action->setText( i18n("Load volume profile 2") ); - connect(action, SIGNAL(triggered(bool)), SLOT(loadVolumes2())); - - action = actionCollection()->addAction( "load_3" ); - action->setShortcut(KShortcut(Qt::CTRL + Qt::Key_3)); - action->setText( i18n("Load volume profile 3") ); - connect(action, SIGNAL(triggered(bool)), SLOT(loadVolumes3())); - - action = actionCollection()->addAction( "load_4" ); - action->setShortcut(KShortcut(Qt::CTRL + Qt::Key_4)); - action->setText( i18n("Load volume profile 4") ); - connect(action, SIGNAL(triggered(bool)), SLOT(loadVolumes4())); - - osdWidget = new OSDWidget(); - - createGUI( QLatin1String( "kmixui.rc" ) ); + // file menu + KStandardAction::quit(this, SLOT(quit()), actionCollection()); + + // settings menu + _actionShowMenubar = KStandardAction::showMenubar(this, SLOT(toggleMenuBar()), + actionCollection()); + //actionCollection()->addAction( a->objectName(), a ); + KStandardAction::preferences(this, SLOT(showSettings()), actionCollection()); + KStandardAction::keyBindings(guiFactory(), SLOT(configureShortcuts()), + actionCollection()); + KAction* action = actionCollection()->addAction("launch_kdesoundsetup"); + action->setText(i18n("Audio Setup")); + connect(action, SIGNAL(triggered(bool)), SLOT(slotKdeAudioSetupExec())); + + action = actionCollection()->addAction("hwinfo"); + action->setText(i18n("Hardware &Information")); + connect(action, SIGNAL(triggered(bool)), SLOT(slotHWInfo())); + action = actionCollection()->addAction("hide_kmixwindow"); + action->setText(i18n("Hide Mixer Window")); + connect(action, SIGNAL(triggered(bool)), SLOT(hideOrClose())); + action->setShortcut(QKeySequence(Qt::Key_Escape)); + action = actionCollection()->addAction("toggle_channels_currentview"); + action->setText(i18n("Configure &Channels...")); + connect(action, SIGNAL(triggered(bool)), SLOT(slotConfigureCurrentView())); + action = actionCollection()->addAction("select_master"); + action->setText(i18n("Select Master Channel...")); + connect(action, SIGNAL(triggered(bool)), SLOT(slotSelectMaster())); + + action = actionCollection()->addAction("save_1"); + action->setShortcut(KShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_1)); + action->setText(i18n("Save volume profile 1")); + connect(action, SIGNAL(triggered(bool)), SLOT(saveVolumes1())); + + action = actionCollection()->addAction("save_2"); + action->setShortcut(KShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_2)); + action->setText(i18n("Save volume profile 2")); + connect(action, SIGNAL(triggered(bool)), SLOT(saveVolumes2())); + + action = actionCollection()->addAction("save_3"); + action->setShortcut(KShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_3)); + action->setText(i18n("Save volume profile 3")); + connect(action, SIGNAL(triggered(bool)), SLOT(saveVolumes3())); + + action = actionCollection()->addAction("save_4"); + action->setShortcut(KShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_4)); + action->setText(i18n("Save volume profile 4")); + connect(action, SIGNAL(triggered(bool)), SLOT(saveVolumes4())); + + action = actionCollection()->addAction("load_1"); + action->setShortcut(KShortcut(Qt::CTRL + Qt::Key_1)); + action->setText(i18n("Load volume profile 1")); + connect(action, SIGNAL(triggered(bool)), SLOT(loadVolumes1())); + + action = actionCollection()->addAction("load_2"); + action->setShortcut(KShortcut(Qt::CTRL + Qt::Key_2)); + action->setText(i18n("Load volume profile 2")); + connect(action, SIGNAL(triggered(bool)), SLOT(loadVolumes2())); + + action = actionCollection()->addAction("load_3"); + action->setShortcut(KShortcut(Qt::CTRL + Qt::Key_3)); + action->setText(i18n("Load volume profile 3")); + connect(action, SIGNAL(triggered(bool)), SLOT(loadVolumes3())); + + action = actionCollection()->addAction("load_4"); + action->setShortcut(KShortcut(Qt::CTRL + Qt::Key_4)); + action->setText(i18n("Load volume profile 4")); + connect(action, SIGNAL(triggered(bool)), SLOT(loadVolumes4())); + + osdWidget = new OSDWidget(); + + createGUI(QLatin1String("kmixui.rc")); } -void KMixWindow::initActionsLate() +void +KMixWindow::initActionsLate() { - if ( m_autouseMultimediaKeys ) { - KAction* globalAction = actionCollection()->addAction("increase_volume"); - globalAction->setText(i18n("Increase Volume")); - globalAction->setGlobalShortcut(KShortcut(Qt::Key_VolumeUp)); - connect(globalAction, SIGNAL(triggered(bool)), SLOT(slotIncreaseVolume())); - - globalAction = actionCollection()->addAction("decrease_volume"); - globalAction->setText(i18n("Decrease Volume")); - globalAction->setGlobalShortcut(KShortcut(Qt::Key_VolumeDown)); - connect(globalAction, SIGNAL(triggered(bool)), SLOT(slotDecreaseVolume())); - - globalAction = actionCollection()->addAction("mute"); - globalAction->setText(i18n("Mute")); - globalAction->setGlobalShortcut(KShortcut(Qt::Key_VolumeMute)); - connect(globalAction, SIGNAL(triggered(bool)), SLOT(slotMute())); + if (m_autouseMultimediaKeys) + { + KAction* globalAction = actionCollection()->addAction("increase_volume"); + globalAction->setText(i18n("Increase Volume")); + globalAction->setGlobalShortcut(KShortcut(Qt::Key_VolumeUp)); + connect(globalAction, SIGNAL(triggered(bool)), + SLOT(slotIncreaseVolume())); + + globalAction = actionCollection()->addAction("decrease_volume"); + globalAction->setText(i18n("Decrease Volume")); + globalAction->setGlobalShortcut(KShortcut(Qt::Key_VolumeDown)); + connect(globalAction, SIGNAL(triggered(bool)), + SLOT(slotDecreaseVolume())); + + globalAction = actionCollection()->addAction("mute"); + globalAction->setText(i18n("Mute")); + globalAction->setGlobalShortcut(KShortcut(Qt::Key_VolumeMute)); + connect(globalAction, SIGNAL(triggered(bool)), SLOT(slotMute())); } } -void KMixWindow::initActionsAfterInitMixer() +void +KMixWindow::initActionsAfterInitMixer() { - // Only show the new tab widget if some of the mixers are not Dynamic. - // The GUI that then pops up could then make a new mixer from a dynamic one, - // if mixed dynamic and non-dynamic mixers were allowed, but this is generally not the case. - bool allDynamic = true; - foreach( Mixer* mixer, Mixer::mixers() ) + // Only show the new tab widget if some of the mixers are not Dynamic. + // The GUI that then pops up could then make a new mixer from a dynamic one, + // if mixed dynamic and non-dynamic mixers were allowed, but this is generally not the case. + bool allDynamic = true; + foreach( Mixer* mixer, Mixer::mixers() ){ + if ( !mixer->isDynamic() ) { - if ( !mixer->isDynamic() ) - { - allDynamic = false; - break; - } + allDynamic = false; + break; } +} - if (! allDynamic ) + if (!allDynamic) { - QPixmap cornerNewPM = KIconLoader::global()->loadIcon( "tab-new", KIconLoader::Toolbar, KIconLoader::SizeSmall ); - QPushButton* _cornerLabelNew = new QPushButton(); - _cornerLabelNew->setIcon(cornerNewPM); - //cornerLabelNew->setSizePolicy(QSizePolicy()); - m_wsMixers->setCornerWidget(_cornerLabelNew, Qt::TopLeftCorner); - connect ( _cornerLabelNew, SIGNAL(clicked()), SLOT (newView()) ); + QPixmap cornerNewPM = KIconLoader::global()->loadIcon("tab-new", + KIconLoader::Toolbar, KIconLoader::SizeSmall); + QPushButton* _cornerLabelNew = new QPushButton(); + _cornerLabelNew->setIcon(cornerNewPM); + //cornerLabelNew->setSizePolicy(QSizePolicy()); + m_wsMixers->setCornerWidget(_cornerLabelNew, Qt::TopLeftCorner); + connect(_cornerLabelNew, SIGNAL(clicked()), SLOT (newView())); } } -void KMixWindow::initPrefDlg() +void +KMixWindow::initPrefDlg() { - m_prefDlg = new KMixPrefDlg( this ); - connect( m_prefDlg, SIGNAL(signalApplied(KMixPrefDlg*)), SLOT(applyPrefs(KMixPrefDlg*)) ); + m_prefDlg = new KMixPrefDlg(this); + connect(m_prefDlg, SIGNAL(signalApplied(KMixPrefDlg*)), + SLOT(applyPrefs(KMixPrefDlg*))); } - - - -void KMixWindow::initWidgets() +void +KMixWindow::initWidgets() { - m_wsMixers = new KTabWidget(); - m_wsMixers->setDocumentMode(true); - setCentralWidget(m_wsMixers); - m_wsMixers->setTabsClosable(false); - connect (m_wsMixers, SIGNAL(tabCloseRequested(int)), SLOT(saveAndCloseView(int)) ); + m_wsMixers = new KTabWidget(); + m_wsMixers->setDocumentMode(true); + setCentralWidget(m_wsMixers); + m_wsMixers->setTabsClosable(false); + connect(m_wsMixers, SIGNAL(tabCloseRequested(int)), + SLOT(saveAndCloseView(int))); - QPixmap cornerNewPM = KIconLoader::global()->loadIcon( "tab-new", KIconLoader::Toolbar, KIconLoader::SizeSmall ); + QPixmap cornerNewPM = KIconLoader::global()->loadIcon("tab-new", + KIconLoader::Toolbar, KIconLoader::SizeSmall); - connect( m_wsMixers, SIGNAL(currentChanged(int)), SLOT(newMixerShown(int)) ); + connect(m_wsMixers, SIGNAL(currentChanged(int)), SLOT(newMixerShown(int))); - // show menubar if the actions says so (or if the action does not exist) - menuBar()->setVisible( (_actionShowMenubar==0) || _actionShowMenubar->isChecked()); + // show menubar if the actions says so (or if the action does not exist) + menuBar()->setVisible( + (_actionShowMenubar == 0) || _actionShowMenubar->isChecked()); } - -void KMixWindow::setInitialSize() +void +KMixWindow::setInitialSize() { - KConfigGroup config(KGlobal::config(), "Global"); - - // HACK: QTabWidget will bound its sizeHint to 200x200 unless scrollbuttons - // are disabled, so we disable them, get a decent sizehint and enable them - // back - m_wsMixers->setUsesScrollButtons(false); - QSize defSize = sizeHint(); - m_wsMixers->setUsesScrollButtons(true); - QSize size = config.readEntry("Size", defSize ); - if(!size.isEmpty()) resize(size); - - QPoint defPos = pos(); - QPoint pos = config.readEntry("Position", defPos); - move(pos); + KConfigGroup config(KGlobal::config(), "Global"); + + // HACK: QTabWidget will bound its sizeHint to 200x200 unless scrollbuttons + // are disabled, so we disable them, get a decent sizehint and enable them + // back + m_wsMixers->setUsesScrollButtons(false); + QSize defSize = sizeHint(); + m_wsMixers->setUsesScrollButtons(true); + QSize size = config.readEntry("Size", defSize); + if (!size.isEmpty()) + resize(size); + + QPoint defPos = pos(); + QPoint pos = config.readEntry("Position", defPos); + move(pos); } - -void KMixWindow::recreateDockWidget() +void +KMixWindow::recreateDockWidget() { // kDebug() << "recreate dock urgently requested"; - updateDocking(); + updateDocking(); } /** @@ -312,222 +324,252 @@ void KMixWindow::recreateDockWidget() * @returns Whether the docking succeeded. Failure usually means that there * was no suitable mixer control selected. */ -bool KMixWindow::updateDocking() +bool +KMixWindow::updateDocking() { - kDebug(); + kDebug(); - if ( m_showDockWidget == false || Mixer::mixers().count() == 0 ) { - if (m_dockWidget) { // Config update: we are not supposed to have one, but we have one. - m_dockWidget->deleteLater(); - m_dockWidget = 0; + if (m_showDockWidget == false || Mixer::mixers().count() == 0) + { + if (m_dockWidget) + { // Config update: we are not supposed to have one, but we have one. + m_dockWidget->deleteLater(); + m_dockWidget = 0; } - return false; + return false; } - if (!m_dockWidget) { - m_dockWidget = new KMixDockWidget( this, m_volumeWidget ); // Could be optimized, by refreshing instead of recreating. - connect(m_dockWidget, SIGNAL(newMasterSelected()), SLOT(saveConfig()) ); - } else { - m_dockWidget->update(); + if (!m_dockWidget) + { + m_dockWidget = new KMixDockWidget(this, m_volumeWidget); // Could be optimized, by refreshing instead of recreating. + connect(m_dockWidget, SIGNAL(newMasterSelected()), SLOT(saveConfig())); + } + else + { + m_dockWidget->update(); } - return true; + return true; } -void KMixWindow::saveConfig() +void +KMixWindow::saveConfig() { - kDebug() << "About to save config"; - saveBaseConfig(); - saveViewConfig(); - saveVolumes(); + kDebug() + << "About to save config"; + saveBaseConfig(); + saveViewConfig(); + saveVolumes(); #ifdef __GNUC_ #warn We must Sync here, or we will lose configuration data. The reson for that is unknown. #endif - // TODO cesken The reason for not writing might be that we have multiple cascaded KConfig objects. I must migrate to KSharedConfig !!! - kDebug() << "Saved config ... now syncing explicitely"; - KGlobal::config()->sync(); - kDebug() << "Saved config ... sync finished"; + // TODO cesken The reason for not writing might be that we have multiple cascaded KConfig objects. I must migrate to KSharedConfig !!! + kDebug() + << "Saved config ... now syncing explicitely"; + KGlobal::config()->sync(); + kDebug() + << "Saved config ... sync finished"; } -void KMixWindow::saveBaseConfig() +void +KMixWindow::saveBaseConfig() { - kDebug() << "About to save config (Base)"; - KConfigGroup config(KGlobal::config(), "Global"); - - config.writeEntry( "Size", size() ); - config.writeEntry( "Position", pos() ); - // Cannot use isVisible() here, as in the "aboutToQuit()" case this widget is already hidden. - // (Please note that the problem was only there when quitting via Systray - esken). - // Using it again, as internal behaviour has changed with KDE4 - config.writeEntry( "Visible", isVisible() ); - config.writeEntry( "Menubar", _actionShowMenubar->isChecked() ); - config.writeEntry( "AllowDocking", m_showDockWidget ); - config.writeEntry( "TrayVolumeControl", m_volumeWidget ); - config.writeEntry( "Tickmarks", m_showTicks ); - config.writeEntry( "Labels", m_showLabels ); - config.writeEntry( "startkdeRestore", m_onLogin ); - config.writeEntry( "AutoStart", allowAutostart ); - config.writeEntry( "VolumeFeedback", m_beepOnVolumeChange ); - config.writeEntry( "DefaultCardOnStart", m_defaultCardOnStart ); - config.writeEntry( "ConfigVersion", KMIX_CONFIG_VERSION ); - config.writeEntry( "AutoUseMultimediaKeys", m_autouseMultimediaKeys ); - - MasterControl& master = Mixer::getGlobalMasterPreferred(); - if ( master.isValid()) { - config.writeEntry( "MasterMixer", master.getCard() ); - config.writeEntry( "MasterMixerDevice", master.getControl() ); + kDebug() + << "About to save config (Base)"; + KConfigGroup config(KGlobal::config(), "Global"); + + config.writeEntry("Size", size()); + config.writeEntry("Position", pos()); + // Cannot use isVisible() here, as in the "aboutToQuit()" case this widget is already hidden. + // (Please note that the problem was only there when quitting via Systray - esken). + // Using it again, as internal behaviour has changed with KDE4 + config.writeEntry("Visible", isVisible()); + config.writeEntry("Menubar", _actionShowMenubar->isChecked()); + config.writeEntry("AllowDocking", m_showDockWidget); + config.writeEntry("TrayVolumeControl", m_volumeWidget); + config.writeEntry("Tickmarks", m_showTicks); + config.writeEntry("Labels", m_showLabels); + config.writeEntry("startkdeRestore", m_onLogin); + config.writeEntry("AutoStart", allowAutostart); + config.writeEntry("VolumeFeedback", m_beepOnVolumeChange); + config.writeEntry("DefaultCardOnStart", m_defaultCardOnStart); + config.writeEntry("ConfigVersion", KMIX_CONFIG_VERSION); + config.writeEntry("AutoUseMultimediaKeys", m_autouseMultimediaKeys); + + MasterControl& master = Mixer::getGlobalMasterPreferred(); + if (master.isValid()) + { + config.writeEntry("MasterMixer", master.getCard()); + config.writeEntry("MasterMixerDevice", master.getControl()); } - QString mixerIgnoreExpression = MixerToolBox::instance()->mixerIgnoreExpression(); - config.writeEntry( "MixerIgnoreExpression", mixerIgnoreExpression ); + QString mixerIgnoreExpression = + MixerToolBox::instance()->mixerIgnoreExpression(); + config.writeEntry("MixerIgnoreExpression", mixerIgnoreExpression); - if ( m_toplevelOrientation == Qt::Horizontal ) - config.writeEntry( "Orientation","Horizontal" ); - else - config.writeEntry( "Orientation","Vertical" ); + if (m_toplevelOrientation == Qt::Horizontal) + config.writeEntry("Orientation", "Horizontal"); + else + config.writeEntry("Orientation", "Vertical"); - kDebug() << "Config (Base) saving done"; + kDebug() + << "Config (Base) saving done"; } -void KMixWindow::saveViewConfig() +void +KMixWindow::saveViewConfig() { - kDebug() << "About to save config (View)"; - // Save Views - - QMap<QString, QStringList> mixerViews; - - // The following loop is necessary for the case that the user has hidden all views for a Mixer instance. - // Otherwise we would not save the Meta information (step -2- below for that mixer. - // We also do not save dynamic mixers (e.g. PulseAudio) - foreach ( Mixer* mixer, Mixer::mixers() ) { - if ( !mixer->isDynamic() ) - mixerViews[mixer->id()]; // just insert a map entry - } + kDebug() + << "About to save config (View)"; + // Save Views + + QMap<QString, QStringList> mixerViews; + + // The following loop is necessary for the case that the user has hidden all views for a Mixer instance. + // Otherwise we would not save the Meta information (step -2- below for that mixer. + // We also do not save dynamic mixers (e.g. PulseAudio) + foreach ( Mixer* mixer, Mixer::mixers() ){ + if ( !mixer->isDynamic() ) + mixerViews[mixer->id()]; // just insert a map entry +} - // -1- Save the views themselves - for ( int i=0; i<m_wsMixers->count() ; ++i ) { - QWidget *w = m_wsMixers->widget(i); - if ( w->inherits("KMixerWidget") ) { - KMixerWidget* mw = (KMixerWidget*)w; - // Here also Views are saved. even for Mixers that are closed. This is necessary when unplugging cards. - // Otherwise the user will be confused afer re-plugging the card (as the config was not saved). - mw->saveConfig( KGlobal::config().data() ); - // add the view to the corresponding mixer list, so we can save a views-per-mixer list below - if ( !mw->mixer()->isDynamic() ) { - QStringList& qsl = mixerViews[mw->mixer()->id()]; - qsl.append(mw->getGuiprof()->getId()); +// -1- Save the views themselves + for (int i = 0; i < m_wsMixers->count(); ++i) + { + QWidget *w = m_wsMixers->widget(i); + if (w->inherits("KMixerWidget")) + { + KMixerWidget* mw = (KMixerWidget*) w; + // Here also Views are saved. even for Mixers that are closed. This is necessary when unplugging cards. + // Otherwise the user will be confused afer re-plugging the card (as the config was not saved). + mw->saveConfig(KGlobal::config().data()); + // add the view to the corresponding mixer list, so we can save a views-per-mixer list below + if (!mw->mixer()->isDynamic()) + { + QStringList& qsl = mixerViews[mw->mixer()->id()]; + qsl.append(mw->getGuiprof()->getId()); } } } - // -2- Save Meta-Information (which views, and in which order). views-per-mixer list - KConfigGroup pconfig(KGlobal::config(), "Profiles"); - QMap<QString, QStringList>::const_iterator itEnd = mixerViews.constEnd(); - for ( QMap<QString, QStringList>::const_iterator it=mixerViews.constBegin(); it != itEnd; ++it ) + // -2- Save Meta-Information (which views, and in which order). views-per-mixer list + KConfigGroup pconfig(KGlobal::config(), "Profiles"); + QMap<QString, QStringList>::const_iterator itEnd = mixerViews.constEnd(); + for (QMap<QString, QStringList>::const_iterator it = mixerViews.constBegin(); + it != itEnd; ++it) { - const QString& mixerProfileKey = it.key(); // this is actually some mixer->id() - const QStringList& qslProfiles = it.value(); - pconfig.writeEntry( mixerProfileKey, qslProfiles ); - kDebug() << "Save Profile List for " << mixerProfileKey << ", number of views is " << qslProfiles.count(); + const QString& mixerProfileKey = it.key(); // this is actually some mixer->id() + const QStringList& qslProfiles = it.value(); + pconfig.writeEntry(mixerProfileKey, qslProfiles); + kDebug() + << "Save Profile List for " << mixerProfileKey << ", number of views is " << qslProfiles.count(); } - kDebug() << "Config (View) saving done"; + kDebug() + << "Config (View) saving done"; } - /** * Stores the volumes of all mixers Can be restored via loadVolumes() or * the kmixctrl application. */ -void KMixWindow::saveVolumes() +void +KMixWindow::saveVolumes() { - saveVolumes(QString()); + saveVolumes(QString()); } -void KMixWindow::saveVolumes(QString postfix) +void +KMixWindow::saveVolumes(QString postfix) { - kDebug() << "About to save config (Volume)"; - const QString& kmixctrlRcFilename = getKmixctrlRcFilename(postfix); - KConfig *cfg = new KConfig( kmixctrlRcFilename ); - for ( int i=0; i<Mixer::mixers().count(); ++i) + kDebug() + << "About to save config (Volume)"; + const QString& kmixctrlRcFilename = getKmixctrlRcFilename(postfix); + KConfig *cfg = new KConfig(kmixctrlRcFilename); + for (int i = 0; i < Mixer::mixers().count(); ++i) { - Mixer *mixer = (Mixer::mixers())[i]; - if ( mixer->isOpen() ) { // protect from unplugged devices (better do *not* save them) - mixer->volumeSave( cfg ); + Mixer *mixer = (Mixer::mixers())[i]; + if (mixer->isOpen()) + { // protect from unplugged devices (better do *not* save them) + mixer->volumeSave(cfg); } } - cfg->sync(); - delete cfg; - kDebug() << "Config (Volume) saving done"; + cfg->sync(); + delete cfg; + kDebug() + << "Config (Volume) saving done"; } -QString KMixWindow::getKmixctrlRcFilename(QString postfix) +QString +KMixWindow::getKmixctrlRcFilename(QString postfix) { - QString kmixctrlRcFilename("kmixctrlrc"); - if ( !postfix.isEmpty() ) - { - kmixctrlRcFilename.append(".").append(postfix); - } - return kmixctrlRcFilename; + QString kmixctrlRcFilename("kmixctrlrc"); + if (!postfix.isEmpty()) + { + kmixctrlRcFilename.append(".").append(postfix); + } + return kmixctrlRcFilename; } - - -void KMixWindow::loadConfig() +void +KMixWindow::loadConfig() { - loadBaseConfig(); - //loadViewConfig(); // mw->loadConfig() explicitly called always after creating mw. - //loadVolumes(); // not in use + loadBaseConfig(); + //loadViewConfig(); // mw->loadConfig() explicitly called always after creating mw. + //loadVolumes(); // not in use } -void KMixWindow::loadBaseConfig() +void +KMixWindow::loadBaseConfig() { - KConfigGroup config(KGlobal::config(), "Global"); - - m_showDockWidget = config.readEntry("AllowDocking", true); - m_volumeWidget = config.readEntry("TrayVolumeControl", true); - m_showTicks = config.readEntry("Tickmarks", true); - m_showLabels = config.readEntry("Labels", true); - m_onLogin = config.readEntry("startkdeRestore", true ); - allowAutostart = config.readEntry( "AutoStart", true ); - - setBeepOnVolumeChange(config.readEntry("VolumeFeedback", false )); - m_startVisible = config.readEntry("Visible", false); - m_multiDriverMode = config.readEntry("MultiDriver", false); - const QString& orientationString = config.readEntry("Orientation", "Vertical"); - m_defaultCardOnStart = config.readEntry( "DefaultCardOnStart", "" ); - m_configVersion = config.readEntry( "ConfigVersion", 0 ); - // WARNING Don't overwrite m_configVersion with the "correct" value, before having it - // evaluated. Better only write that in saveBaseConfig() - m_autouseMultimediaKeys = config.readEntry( "AutoUseMultimediaKeys", true ); - QString mixerMasterCard = config.readEntry( "MasterMixer", "" ); - QString masterDev = config.readEntry( "MasterMixerDevice", "" ); - //if ( ! mixerMasterCard.isEmpty() && ! masterDev.isEmpty() ) { - Mixer::setGlobalMaster(mixerMasterCard, masterDev, true); - //} - QString mixerIgnoreExpression = config.readEntry( "MixerIgnoreExpression", "Modem" ); - MixerToolBox::instance()->setMixerIgnoreExpression(mixerIgnoreExpression); - - QString volumePercentageStepString = config.readEntry( "VolumePercentageStep" ); - if ( ! volumePercentageStepString.isNull()) + KConfigGroup config(KGlobal::config(), "Global"); + + m_showDockWidget = config.readEntry("AllowDocking", true); + m_volumeWidget = config.readEntry("TrayVolumeControl", true); + m_showTicks = config.readEntry("Tickmarks", true); + m_showLabels = config.readEntry("Labels", true); + m_onLogin = config.readEntry("startkdeRestore", true); + allowAutostart = config.readEntry("AutoStart", true); + + setBeepOnVolumeChange(config.readEntry("VolumeFeedback", false)); + m_startVisible = config.readEntry("Visible", false); + m_multiDriverMode = config.readEntry("MultiDriver", false); + const QString& orientationString = config.readEntry("Orientation", + "Vertical"); + m_defaultCardOnStart = config.readEntry("DefaultCardOnStart", ""); + m_configVersion = config.readEntry("ConfigVersion", 0); + // WARNING Don't overwrite m_configVersion with the "correct" value, before having it + // evaluated. Better only write that in saveBaseConfig() + m_autouseMultimediaKeys = config.readEntry("AutoUseMultimediaKeys", true); + QString mixerMasterCard = config.readEntry("MasterMixer", ""); + QString masterDev = config.readEntry("MasterMixerDevice", ""); + Mixer::setGlobalMaster(mixerMasterCard, masterDev, true); + QString mixerIgnoreExpression = config.readEntry("MixerIgnoreExpression", + "Modem"); + MixerToolBox::instance()->setMixerIgnoreExpression(mixerIgnoreExpression); + + QString volumePercentageStepString = config.readEntry("VolumePercentageStep"); + if (!volumePercentageStepString.isNull()) { - float volumePercentageStep = volumePercentageStepString.toFloat(); - if ( volumePercentageStep > 0 && volumePercentageStep <= 100) - Mixer::VOLUME_STEP_DIVISOR = (100 / volumePercentageStep); + float volumePercentageStep = volumePercentageStepString.toFloat(); + if (volumePercentageStep > 0 && volumePercentageStep <= 100) + Mixer::VOLUME_STEP_DIVISOR = (100 / volumePercentageStep); } - m_backendFilter = config.readEntry<>( "Backends", QList<QString>() ); - kDebug() << "Backends: " << m_backendFilter; + m_backendFilter = config.readEntry<>("Backends", QList<QString>()); + kDebug() + << "Backends: " << m_backendFilter; - if ( orientationString == "Horizontal" ) - m_toplevelOrientation = Qt::Horizontal; - else - m_toplevelOrientation = Qt::Vertical; + if (orientationString == "Horizontal") + m_toplevelOrientation = Qt::Horizontal; + else + m_toplevelOrientation = Qt::Vertical; - // show/hide menu bar - bool showMenubar = config.readEntry("Menubar", true); + // show/hide menu bar + bool showMenubar = config.readEntry("Menubar", true); - if (_actionShowMenubar) _actionShowMenubar->setChecked( showMenubar ); + if (_actionShowMenubar) + _actionShowMenubar->setChecked(showMenubar); } /** @@ -537,44 +579,44 @@ void KMixWindow::loadBaseConfig() * execution of "kmixctrl --save" */ - -void KMixWindow::loadVolumes() +void +KMixWindow::loadVolumes() { - loadVolumes(QString()); + loadVolumes(QString()); } -void KMixWindow::loadVolumes(QString postfix) +void +KMixWindow::loadVolumes(QString postfix) { - kDebug() << "About to load config (Volume)"; - const QString& kmixctrlRcFilename = getKmixctrlRcFilename(postfix); + kDebug() + << "About to load config (Volume)"; + const QString& kmixctrlRcFilename = getKmixctrlRcFilename(postfix); - KConfig *cfg = new KConfig( kmixctrlRcFilename ); - for ( int i=0; i<Mixer::mixers().count(); ++i) + KConfig *cfg = new KConfig(kmixctrlRcFilename); + for (int i = 0; i < Mixer::mixers().count(); ++i) { - Mixer *mixer = (Mixer::mixers())[i]; - mixer->volumeLoad( cfg ); + Mixer *mixer = (Mixer::mixers())[i]; + mixer->volumeLoad(cfg); } - delete cfg; + delete cfg; } - - - - -void KMixWindow::recreateGUIwithoutSavingView() +void +KMixWindow::recreateGUIwithoutSavingView() { - recreateGUI(false); + recreateGUI(false); } - -void KMixWindow::recreateGUIwithSavingView() +void +KMixWindow::recreateGUIwithSavingView() { - recreateGUI(true); + recreateGUI(true); } -void KMixWindow::recreateGUI(bool saveConfig) +void +KMixWindow::recreateGUI(bool saveConfig) { - recreateGUI(saveConfig, QString(), false); + recreateGUI(saveConfig, QString(), false); } /** @@ -584,198 +626,219 @@ void KMixWindow::recreateGUI(bool saveConfig) * @param forceNewTab To enforce opening a new tab, even when the profileList in the kmixrc is empty. * It should only be set to "true" in case of a Hotplug (because then the user definitely expects a new Tab to show). */ -void KMixWindow::recreateGUI(bool saveConfig, const QString& mixerId, bool forceNewTab) -{ - // -1- Find out which of the tabs is currently selected for restoration - int current_tab = -1; - if (m_wsMixers) - current_tab = m_wsMixers->currentIndex(); - - if (saveConfig) - saveViewConfig(); // save the state before recreating +void +KMixWindow::recreateGUI(bool saveConfig, const QString& mixerId, + bool forceNewTab) +{ + // -1- Remember which of the tabs is currently selected for restoration for re-insertion + int oldTabPosition = m_wsMixers->currentIndex(); + if (saveConfig) + saveViewConfig(); // save the state before recreating - // -2- RECREATE THE ALREADY EXISTING TABS ********************************** - QMap<Mixer*, bool> mixerHasProfile; + // -2- RECREATE THE ALREADY EXISTING TABS ********************************** + QMap<Mixer*, bool> mixerHasProfile; - // -2a- Build a list of all active profiles in the main window (that means: from all tabs) - QList<GUIProfile*> activeGuiProfiles; - for (int i=0; i< m_wsMixers->count(); ++i) + // -2a- Build a list of all active profiles in the main window (that means: from all tabs) + QList<GUIProfile*> activeGuiProfiles; + for (int i = 0; i < m_wsMixers->count(); ++i) { - KMixerWidget* kmw = dynamic_cast<KMixerWidget*>(m_wsMixers->widget(i)); - if ( kmw ) { - activeGuiProfiles.append(kmw->getGuiprof()); + KMixerWidget* kmw = dynamic_cast<KMixerWidget*>(m_wsMixers->widget(i)); + if (kmw) + { + activeGuiProfiles.append(kmw->getGuiprof()); } } - // TODO The following loop is a bit buggy, as it iterates over all cached Profiles. But that is wrong for Tabs that got closed. - // I need to loop over something else, e.g. a profile list built from the currently open Tabs. - // Or (if it that is easier) I might discard the Profile from the cache on "close-tab" (but that must also include unplug actions). - foreach( GUIProfile* guiprof, activeGuiProfiles) + // TODO The following loop is a bit buggy, as it iterates over all cached Profiles. But that is wrong for Tabs that got closed. + // I need to loop over something else, e.g. a profile list built from the currently open Tabs. + // Or (if it that is easier) I might discard the Profile from the cache on "close-tab" (but that must also include unplug actions). + foreach( GUIProfile* guiprof, activeGuiProfiles){ + KMixerWidget* kmw = findKMWforTab(guiprof->getId()); + Mixer *mixer = Mixer::findMixer( guiprof->getMixerId() ); + if ( mixer == 0 ) { - KMixerWidget* kmw = findKMWforTab(guiprof->getId()); - Mixer *mixer = Mixer::findMixer( guiprof->getMixerId() ); - if ( mixer == 0 ) { - kError() << "MixerToolBox::find() hasn't found the Mixer for the profile " << guiprof->getId(); - continue; - } - mixerHasProfile[mixer] = true; - if ( kmw == 0 ) { - // does not yet exist => create - addMixerWidget(mixer->id(), guiprof, -1); - } - else { - // did exist => remove and insert new guiprof at old position - int indexOfTab = m_wsMixers->indexOf(kmw); - if ( indexOfTab != -1 ) m_wsMixers->removeTab(indexOfTab); - delete kmw; - addMixerWidget(mixer->id(), guiprof, indexOfTab); - } - } // Loop over all GUIProfile's - + kError() << "MixerToolBox::find() hasn't found the Mixer for the profile " << guiprof->getId(); + continue; + } + mixerHasProfile[mixer] = true; + if ( kmw == 0 ) + { + // does not yet exist => create + addMixerWidget(mixer->id(), guiprof, -1); + } + else + { + // did exist => remove and insert new guiprof at old position + int indexOfTab = m_wsMixers->indexOf(kmw); + if ( indexOfTab != -1 ) m_wsMixers->removeTab(indexOfTab); + delete kmw; + addMixerWidget(mixer->id(), guiprof, indexOfTab); + } +} // Loop over all GUIProfile's - // -3- ADD TABS FOR Mixer instances that have no tab yet ********************************** - KConfigGroup pconfig(KGlobal::config(), "Profiles"); - foreach ( Mixer *mixer, Mixer::mixers()) +// -3- ADD TABS FOR Mixer instances that have no tab yet ********************************** + KConfigGroup pconfig(KGlobal::config(), "Profiles"); + foreach ( Mixer *mixer, Mixer::mixers()){ + if ( mixerHasProfile.contains(mixer)) { - if ( mixerHasProfile.contains(mixer)) { - continue; // OK, this mixer already has a profile => skip it - } - // No TAB YET => This should mean KMix is just started, or the user has just plugged in a card - bool profileListHasKey = false; - QStringList profileList; - bool aProfileWasAddedSucesufully = false; + continue; // OK, this mixer already has a profile => skip it + } + // No TAB YET => This should mean KMix is just started, or the user has just plugged in a card + bool profileListHasKey = false; + QStringList profileList; + bool aProfileWasAddedSucesufully = false; - if ( !mixer->isDynamic() ) { - // We do not support save profiles for dynamic mixers (i.e. PulseAudio) + if ( !mixer->isDynamic() ) + { + // We do not support save profiles for dynamic mixers (i.e. PulseAudio) - profileListHasKey = pconfig.hasKey( mixer->id() ); // <<< SHOULD be before the following line - profileList = pconfig.readEntry( mixer->id(), QStringList() ); + profileListHasKey = pconfig.hasKey( mixer->id() );// <<< SHOULD be before the following line + profileList = pconfig.readEntry( mixer->id(), QStringList() ); - foreach ( QString profileId, profileList) + foreach ( QString profileId, profileList) + { + // This handles the profileList form the kmixrc + kDebug() << "Now searching for profile: " << profileId; + GUIProfile* guiprof = GUIProfile::find(mixer, profileId, true, false);// ### Card specific profile ### + if ( guiprof != 0 ) { - // This handles the profileList form the kmixrc - kDebug() << "Now searching for profile: " << profileId ; - GUIProfile* guiprof = GUIProfile::find(mixer, profileId, true, false); // ### Card specific profile ### - if ( guiprof != 0 ) { - addMixerWidget(mixer->id(), guiprof, -1); - aProfileWasAddedSucesufully = true; - } - else { - kError() << "Cannot load profile " << profileId << " . It was removed by the user, or the KMix config file is defective."; - } + addMixerWidget(mixer->id(), guiprof, -1); + aProfileWasAddedSucesufully = true; + } + else + { + kError() << "Cannot load profile " << profileId << " . It was removed by the user, or the KMix config file is defective."; } } + } - // The we_need_a_fallback case is a bit tricky. Please ask the author (cesken) before even considering to change the code. - bool we_need_a_fallback = !aProfileWasAddedSucesufully; // we *possibly* want a fallback, if we couldn't add one - bool thisMixerShouldBeForced = forceNewTab && ( mixerId.isEmpty() || (mixer->id() == mixerId) ); - we_need_a_fallback = we_need_a_fallback && ( thisMixerShouldBeForced || !profileListHasKey ); // Additional requirement: "forced-tab-for-this-mixer" OR "no key stored in kmixrc yet" - if ( we_need_a_fallback ) - { - // The profileList was empty or nothing could be loaded - // (Hint: This means the user cannot hide a device completely - - // Lets try a bunch of fallback strategies: - GUIProfile* guiprof = 0; - if ( !mixer->isDynamic() ) { - // We know that GUIProfile::find() will return 0 if the mixer is dynamic, so don't bother checking. - kDebug() << "Attempting to find a card-specific GUI Profile for the mixer " << mixer->id(); - guiprof = GUIProfile::find(mixer, QString("default"), false, false); // ### Card specific profile ### - if ( guiprof == 0 ) { - kDebug() << "Not found. Attempting to find a generic GUI Profile for the mixer " << mixer->id(); - guiprof = GUIProfile::find(mixer, QString("default"), false, true); // ### Card unspecific profile ### - } - } - if ( guiprof == 0) { - kDebug() << "Using fallback GUI Profile for the mixer " << mixer->id(); - // This means there is neither card specific nor card unspecific profile - // This is the case for some backends (as they don't ship profiles). - guiprof = GUIProfile::fallbackProfile(mixer); - } + // The we_need_a_fallback case is a bit tricky. Please ask the author (cesken) before even considering to change the code. + bool we_need_a_fallback = !aProfileWasAddedSucesufully;// we *possibly* want a fallback, if we couldn't add one + bool thisMixerShouldBeForced = forceNewTab && ( mixerId.isEmpty() || (mixer->id() == mixerId) ); + we_need_a_fallback = we_need_a_fallback && ( thisMixerShouldBeForced || !profileListHasKey );// Additional requirement: "forced-tab-for-this-mixer" OR "no key stored in kmixrc yet" + if ( we_need_a_fallback ) + { + // The profileList was empty or nothing could be loaded + // (Hint: This means the user cannot hide a device completely - if ( guiprof != 0 ) { - guiprof->setDirty(); // All fallback => dirty - addMixerWidget(mixer->id(), guiprof, -1); - } - else { - kError() << "Cannot use ANY profile (including Fallback) for mixer " << mixer->id() << " . This is impossible, and thus this mixer can NOT be used."; + // Lets try a bunch of fallback strategies: + GUIProfile* guiprof = 0; + if ( !mixer->isDynamic() ) + { + // We know that GUIProfile::find() will return 0 if the mixer is dynamic, so don't bother checking. + kDebug() << "Attempting to find a card-specific GUI Profile for the mixer " << mixer->id(); + guiprof = GUIProfile::find(mixer, QString("default"), false, false);// ### Card specific profile ### + if ( guiprof == 0 ) + { + kDebug() << "Not found. Attempting to find a generic GUI Profile for the mixer " << mixer->id(); + guiprof = GUIProfile::find(mixer, QString("default"), false, true); // ### Card unspecific profile ### } + } + if ( guiprof == 0) + { + kDebug() << "Using fallback GUI Profile for the mixer " << mixer->id(); + // This means there is neither card specific nor card unspecific profile + // This is the case for some backends (as they don't ship profiles). + guiprof = GUIProfile::fallbackProfile(mixer); + } + if ( guiprof != 0 ) + { + guiprof->setDirty(); // All fallback => dirty + addMixerWidget(mixer->id(), guiprof, -1); + } + else + { + kError() << "Cannot use ANY profile (including Fallback) for mixer " << mixer->id() << " . This is impossible, and thus this mixer can NOT be used."; } - } - mixerHasProfile.clear(); + } +} + mixerHasProfile.clear(); - // -4- FINALIZE ********************************** - if (m_wsMixers->count() > 0) { - if (current_tab >= 0) { - m_wsMixers->setCurrentIndex(current_tab); + // -4- FINALIZE ********************************** + if (m_wsMixers->count() > 0) + { + if (oldTabPosition >= 0) + { + m_wsMixers->setCurrentIndex(oldTabPosition); } - bool dockingSucceded = updateDocking(); - if ( !dockingSucceded && !Mixer::mixers().empty() ) + bool dockingSucceded = updateDocking(); + if (!dockingSucceded && !Mixer::mixers().empty()) { - show(); // avoid invisible and unaccessible main window + show(); // avoid invisible and unaccessible main window } } - else { - // No soundcard found. Do not complain, but sit in the background, and wait for newly plugged soundcards. - updateDocking(); // -<- removes the DockIcon - hide(); + else + { + // No soundcard found. Do not complain, but sit in the background, and wait for newly plugged soundcards. + updateDocking(); // -<- removes the DockIcon + hide(); } } -KMixerWidget* KMixWindow::findKMWforTab( const QString& kmwId ) +KMixerWidget* +KMixWindow::findKMWforTab(const QString& kmwId) { - for (int i=0; i< m_wsMixers->count(); ++i) + for (int i = 0; i < m_wsMixers->count(); ++i) { - KMixerWidget* kmw = (KMixerWidget*)m_wsMixers->widget(i); - if ( kmw->getGuiprof()->getId() == kmwId ) { - return kmw; + KMixerWidget* kmw = (KMixerWidget*) m_wsMixers->widget(i); + if (kmw->getGuiprof()->getId() == kmwId) + { + return kmw; } } - return 0; + return 0; } - -void KMixWindow::newView() +void +KMixWindow::newView() { - if ( Mixer::mixers().empty() ) { - kError() << "Trying to create a View, but no Mixer exists"; - return; // should never happen + if (Mixer::mixers().empty()) + { + kError() << "Trying to create a View, but no Mixer exists"; + return; // should never happen } - Mixer *mixer = Mixer::mixers()[0]; - QPointer<DialogAddView> dav = new DialogAddView(this, mixer); - int ret = dav->exec(); - - if ( QDialog::Accepted == ret ) { - QString profileName = dav->getresultViewName(); - QString mixerId = dav->getresultMixerId(); - mixer = Mixer::findMixer(mixerId); - kDebug() << ">>> mixer = " << mixerId << " -> " << mixer; - - GUIProfile*guiprof = GUIProfile::find(mixer, profileName, false, false); - if ( guiprof == 0 ) { - guiprof = GUIProfile::find(mixer, profileName, false, true); - } - - if ( guiprof == 0 ) { - static const QString msg (i18n("Cannot add view - GUIProfile is invalid.")); - errorPopup(msg); - } - else { - bool ret = addMixerWidget(mixer->id(), guiprof, -1); - if ( ret == false ) { - errorPopup(i18n("View already exists. Cannot add View.")); - } - } - - delete dav; + Mixer *mixer = Mixer::mixers()[0]; + QPointer<DialogAddView> dav = new DialogAddView(this, mixer); + int ret = dav->exec(); + + if (QDialog::Accepted == ret) + { + QString profileName = dav->getresultViewName(); + QString mixerId = dav->getresultMixerId(); + mixer = Mixer::findMixer(mixerId); + kDebug() + << ">>> mixer = " << mixerId << " -> " << mixer; + + GUIProfile*guiprof = GUIProfile::find(mixer, profileName, false, false); + if (guiprof == 0) + { + guiprof = GUIProfile::find(mixer, profileName, false, true); + } + + if (guiprof == 0) + { + static const QString msg( + i18n("Cannot add view - GUIProfile is invalid.")); + errorPopup(msg); + } + else + { + bool ret = addMixerWidget(mixer->id(), guiprof, -1); + if (ret == false) + { + errorPopup(i18n("View already exists. Cannot add View.")); + } + } + + delete dav; } - //kDebug() << "Exit"; + //kDebug() << "Exit"; } /** @@ -783,405 +846,442 @@ void KMixWindow::newView() * * @arg idx The index in the TabWidget */ -void KMixWindow::saveAndCloseView(int idx) +void +KMixWindow::saveAndCloseView(int idx) { - kDebug() << "Enter"; - QWidget *w = m_wsMixers->widget(idx); - KMixerWidget* kmw = ::qobject_cast<KMixerWidget*>(w); - if ( kmw ) { - kmw->saveConfig( KGlobal::config().data() ); // -<- This alone is not enough, as I need to save the META information as well. Thus use saveViewConfig() below - m_wsMixers->removeTab(idx); - m_wsMixers->setTabsClosable(!kmw->mixer()->isDynamic() && m_wsMixers->count() > 1); // This does not work properly in (experimental) multi-driver-mode + kDebug() + << "Enter"; + QWidget *w = m_wsMixers->widget(idx); + KMixerWidget* kmw = ::qobject_cast<KMixerWidget*>(w); + if (kmw) + { + kmw->saveConfig(KGlobal::config().data()); // -<- This alone is not enough, as I need to save the META information as well. Thus use saveViewConfig() below + m_wsMixers->removeTab(idx); + m_wsMixers->setTabsClosable( + !kmw->mixer()->isDynamic() && m_wsMixers->count() > 1); // This does not work properly in (experimental) multi-driver-mode - saveViewConfig(); + saveViewConfig(); - delete kmw; + delete kmw; } - kDebug() << "Exit"; + kDebug() + << "Exit"; } - /** * Create or recreate the Mixer GUI elements */ -void KMixWindow::redrawMixer( const QString& mixer_ID ) +void +KMixWindow::redrawMixer(const QString& mixer_ID) { - for ( int i=0; i<m_wsMixers->count() ; ++i ) + for (int i = 0; i < m_wsMixers->count(); ++i) { - QWidget *w = m_wsMixers->widget(i); - if ( w->inherits("KMixerWidget") ) + QWidget *w = m_wsMixers->widget(i); + if (w->inherits("KMixerWidget")) { - KMixerWidget* kmw = (KMixerWidget*)w; - if ( kmw->mixer()->id() == mixer_ID ) + KMixerWidget* kmw = (KMixerWidget*) w; + if (kmw->mixer()->id() == mixer_ID) { - kDebug(67100) << "KMixWindow::redrawMixer() " << mixer_ID << " is being redrawn"; - kmw->loadConfig( KGlobal::config().data() ); + kDebug(67100) + << "KMixWindow::redrawMixer() " << mixer_ID << " is being redrawn"; + kmw->loadConfig(KGlobal::config().data()); - // Is the below needed? It is done on startup so copied it here... - kmw->setTicks( m_showTicks ); - kmw->setLabels( m_showLabels ); + // Is the below needed? It is done on startup so copied it here... + kmw->setTicks(m_showTicks); + kmw->setLabels(m_showLabels); - return; + return; } } } - kWarning(67100) << "KMixWindow::redrawMixer() Requested to redraw " << mixer_ID << " but I cannot find it :s"; + kWarning(67100)<< "KMixWindow::redrawMixer() Requested to redraw " << mixer_ID << " but I cannot find it :s"; } - -void KMixWindow::fixConfigAfterRead() +void +KMixWindow::fixConfigAfterRead() { - KConfigGroup grp(KGlobal::config(), "Global"); - unsigned int configVersion = grp.readEntry( "ConfigVersion", 0 ); - if ( configVersion < 3 ) { - // Fix the "double Base" bug, by deleting all groups starting with "View.Base.Base.". - // The group has been copied over by KMixToolBox::loadView() for all soundcards, so - // we should be fine now - QStringList cfgGroups = KGlobal::config()->groupList(); - QStringListIterator it(cfgGroups); - while ( it.hasNext() ) { - QString groupName = it.next(); - if ( groupName.indexOf("View.Base.Base" ) == 0 ) { - kDebug(67100) << "Fixing group " << groupName; - KConfigGroup buggyDevgrpCG = KGlobal::config()->group( groupName ); - buggyDevgrpCG.deleteGroup(); + KConfigGroup grp(KGlobal::config(), "Global"); + unsigned int configVersion = grp.readEntry("ConfigVersion", 0); + if (configVersion < 3) + { + // Fix the "double Base" bug, by deleting all groups starting with "View.Base.Base.". + // The group has been copied over by KMixToolBox::loadView() for all soundcards, so + // we should be fine now + QStringList cfgGroups = KGlobal::config()->groupList(); + QStringListIterator it(cfgGroups); + while (it.hasNext()) + { + QString groupName = it.next(); + if (groupName.indexOf("View.Base.Base") == 0) + { + kDebug(67100) + << "Fixing group " << groupName; + KConfigGroup buggyDevgrpCG = KGlobal::config()->group(groupName); + buggyDevgrpCG.deleteGroup(); } // remove buggy group } // for all groups } // if config version < 3 } -void KMixWindow::plugged( const char* driverName, const QString& udi, QString& dev) +void +KMixWindow::plugged(const char* driverName, const QString& udi, QString& dev) { - kDebug() << "Plugged: dev=" << dev << "(" << driverName << ") udi=" << udi << "\n"; - QString driverNameString; - driverNameString = driverName; - int devNum = dev.toInt(); - Mixer *mixer = new Mixer( driverNameString, devNum ); - if ( mixer != 0 ) { - kDebug() << "Plugged: dev=" << dev << "\n"; - MixerToolBox::instance()->possiblyAddMixer(mixer); - recreateGUI(true, mixer->id(), true); + kDebug() + << "Plugged: dev=" << dev << "(" << driverName << ") udi=" << udi << "\n"; + QString driverNameString; + driverNameString = driverName; + int devNum = dev.toInt(); + Mixer *mixer = new Mixer(driverNameString, devNum); + if (mixer != 0) + { + kDebug() + << "Plugged: dev=" << dev << "\n"; + MixerToolBox::instance()->possiblyAddMixer(mixer); + recreateGUI(true, mixer->id(), true); } - // Test code for OSD. But OSD is postponed to KDE4.1 - // OSDWidget* osd = new OSDWidget(0); - // osd->volChanged(70, true); + // Test code for OSD. But OSD is postponed to KDE4.1 + // OSDWidget* osd = new OSDWidget(0); + // osd->volChanged(70, true); } -void KMixWindow::unplugged( const QString& udi) +void +KMixWindow::unplugged(const QString& udi) { - kDebug() << "Unplugged: udi=" <<udi << "\n"; - for (int i=0; i<Mixer::mixers().count(); ++i) { - Mixer *mixer = (Mixer::mixers())[i]; - // kDebug(67100) << "Try Match with:" << mixer->udi() << "\n"; - if (mixer->udi() == udi ) { - kDebug() << "Unplugged Match: Removing udi=" <<udi << "\n"; - //KMixToolBox::notification("MasterFallback", "aaa"); - bool globalMasterMixerDestroyed = ( mixer == Mixer::getGlobalMasterMixer() ); - // Part 1) Remove Tab - for ( int i=0; i<m_wsMixers->count() ; ++i ) + kDebug() + << "Unplugged: udi=" << udi << "\n"; + for (int i = 0; i < Mixer::mixers().count(); ++i) + { + Mixer *mixer = (Mixer::mixers())[i]; + // kDebug(67100) << "Try Match with:" << mixer->udi() << "\n"; + if (mixer->udi() == udi) + { + kDebug() << "Unplugged Match: Removing udi=" << udi << "\n"; + //KMixToolBox::notification("MasterFallback", "aaa"); + bool globalMasterMixerDestroyed = (mixer == Mixer::getGlobalMasterMixer()); + // Part 1) Remove Tab + for (int i = 0; i < m_wsMixers->count(); ++i) { - QWidget *w = m_wsMixers->widget(i); - KMixerWidget* kmw = ::qobject_cast<KMixerWidget*>(w); - if ( kmw && kmw->mixer() == mixer ) { - saveAndCloseView(i); - i= -1; // Restart loop from scratch (indices are most likely invalidated at removeTab() ) + QWidget *w = m_wsMixers->widget(i); + KMixerWidget* kmw = ::qobject_cast<KMixerWidget*>(w); + if (kmw && kmw->mixer() == mixer) + { + saveAndCloseView(i); + i = -1; // Restart loop from scratch (indices are most likely invalidated at removeTab() ) } } - MixerToolBox::instance()->removeMixer(mixer); - // Check whether the Global Master disappeared, and select a new one if necessary - shared_ptr<MixDevice> md = Mixer::getGlobalMasterMD(); - if ( globalMasterMixerDestroyed || md.get() == 0 ) { - // We don't know what the global master should be now. - // So lets play stupid, and just select the recommended master of the first device - if ( Mixer::mixers().count() > 0 ) { - shared_ptr<MixDevice> master = ((Mixer::mixers())[0])->getLocalMasterMD(); - if ( master.get() != 0 ) { - QString localMaster = master->id(); - Mixer::setGlobalMaster( ((Mixer::mixers())[0])->id(), localMaster, false); - - QString text; - text = i18n("The soundcard containing the master device was unplugged. Changing to control %1 on card %2.", - master->readableName(), - ((Mixer::mixers())[0])->readableName() - ); - KMixToolBox::notification("MasterFallback", text); + MixerToolBox::instance()->removeMixer(mixer); + // Check whether the Global Master disappeared, and select a new one if necessary + shared_ptr<MixDevice> md = Mixer::getGlobalMasterMD(); + if (globalMasterMixerDestroyed || md.get() == 0) + { + // We don't know what the global master should be now. + // So lets play stupid, and just select the recommended master of the first device + if (Mixer::mixers().count() > 0) + { + shared_ptr<MixDevice> master = + ((Mixer::mixers())[0])->getLocalMasterMD(); + if (master.get() != 0) + { + QString localMaster = master->id(); + Mixer::setGlobalMaster(((Mixer::mixers())[0])->id(), localMaster, false); + + QString text; + text = + i18n( + "The soundcard containing the master device was unplugged. Changing to control %1 on card %2.", + master->readableName(), + ((Mixer::mixers())[0])->readableName()); + KMixToolBox::notification("MasterFallback", text); } } } - if ( Mixer::mixers().count() == 0 ) { - QString text; - text = i18n("The last soundcard was unplugged."); - KMixToolBox::notification("MasterFallback", text); + if (Mixer::mixers().count() == 0) + { + QString text; + text = i18n("The last soundcard was unplugged."); + KMixToolBox::notification("MasterFallback", text); } - recreateGUI(true); - break; + recreateGUI(true); + break; } } } - /** * Create a widget with an error message * This widget shows an error message like "no mixers detected. -void KMixWindow::setErrorMixerWidget() -{ - 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 - m_errorLabel = new QLabel( s,this ); - m_errorLabel->setAlignment( Qt::AlignCenter ); - m_errorLabel->setWordWrap(true); - m_errorLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); - m_wsMixers->addTab( m_errorLabel, i18n("No soundcard found") ); -} + void KMixWindow::setErrorMixerWidget() + { + 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 + m_errorLabel = new QLabel( s,this ); + m_errorLabel->setAlignment( Qt::AlignCenter ); + m_errorLabel->setWordWrap(true); + m_errorLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + m_wsMixers->addTab( m_errorLabel, i18n("No soundcard found") ); + } */ -bool KMixWindow::addMixerWidget(const QString& mixer_ID, GUIProfile *guiprof, int insertPosition) +/** + * + */ +bool +KMixWindow::profileExists(GUIProfile* guiprof) { - bool ret = true; - // First check whether we already have this profile - for ( int i=0; i<m_wsMixers->count() ; ++i ) { - KMixerWidget *kmw = dynamic_cast<KMixerWidget*> (m_wsMixers->widget(i) ); - if ( kmw ) { - if ( kmw->getGuiprof()->getId() == guiprof->getId() ) - { - return false; // There is already a tab for this Profile => Cannot add. - } - } - + for (int i = 0; i < m_wsMixers->count(); ++i) + { + KMixerWidget* kmw = dynamic_cast<KMixerWidget*>(m_wsMixers->widget(i)); + if (kmw && kmw->getGuiprof()->getId() == guiprof->getId()) + return true; } + return false; +} - - // kDebug(67100) << "KMixWindow::addMixerWidget() " << mixer_ID; - Mixer *mixer = Mixer::findMixer(mixer_ID); - if ( mixer != 0 ) +bool +KMixWindow::addMixerWidget(const QString& mixer_ID, GUIProfile *guiprof, + int insertPosition) +{ + if (profileExists(guiprof)) + return false; // already present => don't add again + Mixer *mixer = Mixer::findMixer(mixer_ID); + if (mixer == 0) + return false; // no such Mixer + + // kDebug(67100) << "KMixWindow::addMixerWidget() " << mixer_ID << " is being added"; + ViewBase::ViewFlags vflags = ViewBase::HasMenuBar; + if ((_actionShowMenubar == 0) || _actionShowMenubar->isChecked()) + vflags |= ViewBase::MenuBarVisible; + if (m_toplevelOrientation == Qt::Vertical) + vflags |= ViewBase::Horizontal; + else + vflags |= ViewBase::Vertical; + + KMixerWidget *kmw = new KMixerWidget(mixer, this, vflags, guiprof, + actionCollection()); + /* A newly added mixer will automatically added at the top + * and thus the window title is also set appropriately */ + + QString tabLabel = guiprof->getName(); + if (tabLabel.isEmpty()) + tabLabel = kmw->mixer()->readableName(); + + m_dontSetDefaultCardOnStart = true; // inhibit implicit setting of m_defaultCardOnStart + + if (insertPosition == -1) + m_wsMixers->addTab(kmw, tabLabel); + else + m_wsMixers->insertTab(insertPosition, kmw, tabLabel); + + if (kmw->getGuiprof()->getId() == m_defaultCardOnStart) { - // kDebug(67100) << "KMixWindow::addMixerWidget() " << mixer_ID << " is being added"; - ViewBase::ViewFlags vflags = ViewBase::HasMenuBar; - if ( (_actionShowMenubar==0) || _actionShowMenubar->isChecked() ) { - vflags |= ViewBase::MenuBarVisible; - } - if ( m_toplevelOrientation == Qt::Vertical ) { - vflags |= ViewBase::Horizontal; - } - else { - vflags |= ViewBase::Vertical; - } - - - KMixerWidget *kmw = new KMixerWidget( mixer, this, vflags, guiprof, actionCollection() ); - /* A newly added mixer will automatically added at the top - * and thus the window title is also set appropriately */ - - QString tabLabel; - if ( ! guiprof->getName().isEmpty() ) { - tabLabel = guiprof->getName(); - } - else { - tabLabel = kmw->mixer()->readableName(); - } - - m_dontSetDefaultCardOnStart = true; // inhibit implicit setting of m_defaultCardOnStart - - if ( insertPosition == -1 ) - m_wsMixers->addTab( kmw, tabLabel ); - else - m_wsMixers->insertTab( insertPosition, kmw, tabLabel ); - - if ( kmw->getGuiprof()->getId() == m_defaultCardOnStart ) { - m_wsMixers->setCurrentWidget(kmw); - } - - m_wsMixers->setTabsClosable(!mixer->isDynamic() && m_wsMixers->count() > 1); - m_dontSetDefaultCardOnStart = false; - + m_wsMixers->setCurrentWidget(kmw); + } - kmw->loadConfig( KGlobal::config().data() ); + m_wsMixers->setTabsClosable(!mixer->isDynamic() && m_wsMixers->count() > 1); + m_dontSetDefaultCardOnStart = false; - kmw->setTicks( m_showTicks ); - kmw->setLabels( m_showLabels ); - kmw->mixer()->readSetFromHWforceUpdate(); - } // given mixer exist really + kmw->loadConfig(KGlobal::config().data()); - return ret; + kmw->setTicks(m_showTicks); + kmw->setLabels(m_showLabels); + kmw->mixer()->readSetFromHWforceUpdate(); + return true; } - - -bool KMixWindow::queryClose ( ) +bool +KMixWindow::queryClose() { - // kDebug(67100) << "queryClose "; - if ( m_showDockWidget && !kapp->sessionSaving() ) + // kDebug(67100) << "queryClose "; + if (m_showDockWidget && !kapp->sessionSaving() ) { - // kDebug(67100) << "don't close"; - // Hide (don't close and destroy), if docking is enabled. Except when session saving (shutdown) is in process. - hide(); - return false; + // kDebug(67100) << "don't close"; + // Hide (don't close and destroy), if docking is enabled. Except when session saving (shutdown) is in process. + hide(); + return false; } - else { - // Accept the close, if: - // The user has disabled docking - // or SessionSaving() is running - // kDebug(67100) << "close"; - return true; + else + { + // Accept the close, if: + // The user has disabled docking + // or SessionSaving() is running + // kDebug(67100) << "close"; + return true; } } -void KMixWindow::hideOrClose ( ) +void +KMixWindow::hideOrClose() { - if ( m_showDockWidget && m_dockWidget != 0) { - // we can hide if there is a dock widget - hide(); + if (m_showDockWidget && m_dockWidget != 0) + { + // we can hide if there is a dock widget + hide(); } - else { - // if there is no dock widget, we will quit - quit(); + else + { + // if there is no dock widget, we will quit + quit(); } } // internal helper to prevent code duplication in slotIncreaseVolume and slotDecreaseVolume -void KMixWindow::increaseOrDecreaseVolume(bool increase) +void +KMixWindow::increaseOrDecreaseVolume(bool increase) { - Mixer* mixer = Mixer::getGlobalMasterMixer(); // only needed for the awkward construct below - if ( mixer == 0 ) - return; // e.g. when no soundcard is available - shared_ptr<MixDevice> md = Mixer::getGlobalMasterMD(); - if ( md.get() == 0 ) - return; // shouldn't happen, but lets play safe - - md->setMuted(false); - if (increase) - mixer->increaseVolume(md->id()); // this is awkward. Better move the increaseVolume impl to the Volume class. - else - mixer->decreaseVolume(md->id()); - // md->playbackVolume().increase(); // not yet implemented - showVolumeDisplay(); + Mixer* mixer = Mixer::getGlobalMasterMixer(); // only needed for the awkward construct below + if (mixer == 0) + return; // e.g. when no soundcard is available + shared_ptr<MixDevice> md = Mixer::getGlobalMasterMD(); + if (md.get() == 0) + return; // shouldn't happen, but lets play safe + + md->setMuted(false); + if (increase) + mixer->increaseVolume(md->id()); // this is awkward. Better move the increaseVolume impl to the Volume class. + else + mixer->decreaseVolume(md->id()); + // md->playbackVolume().increase(); // not yet implemented + showVolumeDisplay(); } -void KMixWindow::slotIncreaseVolume() +void +KMixWindow::slotIncreaseVolume() { - increaseOrDecreaseVolume(true); + increaseOrDecreaseVolume(true); } -void KMixWindow::slotDecreaseVolume() +void +KMixWindow::slotDecreaseVolume() { - increaseOrDecreaseVolume(false); + increaseOrDecreaseVolume(false); } -void KMixWindow::showVolumeDisplay() +void +KMixWindow::showVolumeDisplay() { - Mixer* mixer = Mixer::getGlobalMasterMixer(); - if ( mixer == 0 ) - return; // e.g. when no soundcard is available - shared_ptr<MixDevice> md = Mixer::getGlobalMasterMD(); - if ( md.get() == 0 ) - return; // shouldn't happen, but lets play safe - // Current volume - Volume& vol = md->playbackVolume(); - - osdWidget->setCurrentVolume(vol.getAvgVolumePercent(Volume::MALL), md->isMuted()); - osdWidget->show(); - osdWidget->activateOSD(); //Enable the hide timer - - //Center the OSD - QRect rect = KApplication::kApplication()->desktop()->screenGeometry(QCursor::pos()); - QSize size = osdWidget->sizeHint(); - int posX = rect.x() + (rect.width() - size.width()) / 2; - int posY = rect.y() + 4 * rect.height() / 5; - osdWidget->setGeometry(posX, posY, size.width(), size.height()); + Mixer* mixer = Mixer::getGlobalMasterMixer(); + if (mixer == 0) + return; // e.g. when no soundcard is available + shared_ptr<MixDevice> md = Mixer::getGlobalMasterMD(); + if (md.get() == 0) + return; // shouldn't happen, but lets play safe + // Current volume + Volume& vol = md->playbackVolume(); + + osdWidget->setCurrentVolume(vol.getAvgVolumePercent(Volume::MALL), + md->isMuted()); + osdWidget->show(); + osdWidget->activateOSD(); //Enable the hide timer + + //Center the OSD + QRect rect = KApplication::kApplication()->desktop()->screenGeometry( + QCursor::pos()); + QSize size = osdWidget->sizeHint(); + int posX = rect.x() + (rect.width() - size.width()) / 2; + int posY = rect.y() + 4 * rect.height() / 5; + osdWidget->setGeometry(posX, posY, size.width(), size.height()); } -void KMixWindow::slotMute() +void +KMixWindow::slotMute() { - Mixer* mixer = Mixer::getGlobalMasterMixer(); - if ( mixer == 0 ) - return; // e.g. when no soundcard is available - shared_ptr<MixDevice> md = Mixer::getGlobalMasterMD(); - if ( md.get() == 0 ) - return; // shouldn't happen, but lets play safe - md->toggleMute(); - mixer->commitVolumeChange( md ); - showVolumeDisplay(); + Mixer* mixer = Mixer::getGlobalMasterMixer(); + if (mixer == 0) + return; // e.g. when no soundcard is available + shared_ptr<MixDevice> md = Mixer::getGlobalMasterMD(); + if (md.get() == 0) + return; // shouldn't happen, but lets play safe + md->toggleMute(); + mixer->commitVolumeChange(md); + showVolumeDisplay(); } -void KMixWindow::quit() +void +KMixWindow::quit() { - // kDebug(67100) << "quit"; - kapp->quit(); + // kDebug(67100) << "quit"; + kapp->quit(); } - -void KMixWindow::showSettings() +void +KMixWindow::showSettings() { - if (!m_prefDlg->isVisible()) + if (!m_prefDlg->isVisible()) { - // copy actual values to dialog - m_prefDlg->m_dockingChk->setChecked( m_showDockWidget ); - m_prefDlg->m_volumeChk->setChecked(m_volumeWidget); - m_prefDlg->m_volumeChk->setEnabled( m_showDockWidget ); - m_prefDlg->m_onLogin->setChecked( m_onLogin ); - m_prefDlg->allowAutostart->setChecked( allowAutostart ); - m_prefDlg->m_beepOnVolumeChange->setChecked( m_beepOnVolumeChange ); - - m_prefDlg->m_showTicks->setChecked( m_showTicks ); - m_prefDlg->m_showLabels->setChecked( m_showLabels ); - m_prefDlg->_rbVertical ->setChecked( m_toplevelOrientation == Qt::Vertical ); - m_prefDlg->_rbHorizontal->setChecked( m_toplevelOrientation == Qt::Horizontal ); - - // show dialog - m_prefDlg->show(); + // copy actual values to dialog + m_prefDlg->m_dockingChk->setChecked(m_showDockWidget); + m_prefDlg->m_volumeChk->setChecked(m_volumeWidget); + m_prefDlg->m_volumeChk->setEnabled(m_showDockWidget); + m_prefDlg->m_onLogin->setChecked(m_onLogin); + m_prefDlg->allowAutostart->setChecked(allowAutostart); + m_prefDlg->m_beepOnVolumeChange->setChecked(m_beepOnVolumeChange); + + m_prefDlg->m_showTicks->setChecked(m_showTicks); + m_prefDlg->m_showLabels->setChecked(m_showLabels); + m_prefDlg->_rbVertical->setChecked(m_toplevelOrientation == Qt::Vertical); + m_prefDlg->_rbHorizontal->setChecked( + m_toplevelOrientation == Qt::Horizontal); + + // show dialog + m_prefDlg->show(); } } - -void KMixWindow::showHelp() +void +KMixWindow::showHelp() { - actionCollection()->action( "help_contents" )->trigger(); + actionCollection()->action("help_contents")->trigger(); } - void KMixWindow::showAbout() { - actionCollection()->action( "help_about_app" )->trigger(); + actionCollection()->action("help_about_app")->trigger(); } - - -void KMixWindow::applyPrefs( KMixPrefDlg *prefDlg ) +void +KMixWindow::applyPrefs(KMixPrefDlg *prefDlg) { - bool labelsHasChanged = m_showLabels ^ prefDlg->m_showLabels->isChecked(); - bool ticksHasChanged = m_showTicks ^ prefDlg->m_showTicks->isChecked(); - bool dockwidgetHasChanged = m_showDockWidget ^ prefDlg->m_dockingChk->isChecked(); - bool systrayPopupHasChanged = m_volumeWidget ^ prefDlg->m_volumeChk->isChecked(); - bool toplevelOrientationHasChanged = - ( prefDlg->_rbVertical->isChecked() && m_toplevelOrientation == Qt::Horizontal ) - || ( prefDlg->_rbHorizontal->isChecked() && m_toplevelOrientation == Qt::Vertical ); - - m_showLabels = prefDlg->m_showLabels->isChecked(); - m_showTicks = prefDlg->m_showTicks->isChecked(); - m_showDockWidget = prefDlg->m_dockingChk->isChecked(); - m_volumeWidget = prefDlg->m_volumeChk->isChecked(); - m_onLogin = prefDlg->m_onLogin->isChecked(); - allowAutostart = m_prefDlg->allowAutostart->isChecked(); - setBeepOnVolumeChange(prefDlg->m_beepOnVolumeChange->isChecked()); - - if ( prefDlg->_rbVertical->isChecked() ) { - m_toplevelOrientation = Qt::Vertical; + bool labelsHasChanged = m_showLabels ^ prefDlg->m_showLabels->isChecked(); + bool ticksHasChanged = m_showTicks ^ prefDlg->m_showTicks->isChecked(); + bool dockwidgetHasChanged = m_showDockWidget + ^ prefDlg->m_dockingChk->isChecked(); + bool systrayPopupHasChanged = m_volumeWidget + ^ prefDlg->m_volumeChk->isChecked(); + bool toplevelOrientationHasChanged = (prefDlg->_rbVertical->isChecked() + && m_toplevelOrientation == Qt::Horizontal) + || (prefDlg->_rbHorizontal->isChecked() + && m_toplevelOrientation == Qt::Vertical); + + m_showLabels = prefDlg->m_showLabels->isChecked(); + m_showTicks = prefDlg->m_showTicks->isChecked(); + m_showDockWidget = prefDlg->m_dockingChk->isChecked(); + m_volumeWidget = prefDlg->m_volumeChk->isChecked(); + m_onLogin = prefDlg->m_onLogin->isChecked(); + allowAutostart = m_prefDlg->allowAutostart->isChecked(); + setBeepOnVolumeChange(prefDlg->m_beepOnVolumeChange->isChecked()); + + if (prefDlg->_rbVertical->isChecked()) + { + m_toplevelOrientation = Qt::Vertical; } - else if ( prefDlg->_rbHorizontal->isChecked() ) { - m_toplevelOrientation = Qt::Horizontal; + else if (prefDlg->_rbHorizontal->isChecked()) + { + m_toplevelOrientation = Qt::Horizontal; } - if ( labelsHasChanged || ticksHasChanged || dockwidgetHasChanged || toplevelOrientationHasChanged || systrayPopupHasChanged) { - recreateGUI(true); + if (labelsHasChanged || ticksHasChanged || dockwidgetHasChanged + || toplevelOrientationHasChanged || systrayPopupHasChanged) + { + recreateGUI(true); } - this->repaint(); // make KMix look fast (saveConfig() often uses several seconds) - kapp->processEvents(); - saveConfig(); + this->repaint(); // make KMix look fast (saveConfig() often uses several seconds) + kapp->processEvents(); + saveConfig(); } /** @@ -1191,102 +1291,118 @@ void KMixWindow::applyPrefs( KMixPrefDlg *prefDlg ) * * @param beep true, if a beep should be changed */ -void KMixWindow::setBeepOnVolumeChange(bool beep) +void +KMixWindow::setBeepOnVolumeChange(bool beep) { - m_beepOnVolumeChange = beep; - Mixer::setBeepOnVolumeChange(m_beepOnVolumeChange); + m_beepOnVolumeChange = beep; + Mixer::setBeepOnVolumeChange(m_beepOnVolumeChange); } -void KMixWindow::toggleMenuBar() +void +KMixWindow::toggleMenuBar() { - menuBar()->setVisible(_actionShowMenubar->isChecked()); + menuBar()->setVisible(_actionShowMenubar->isChecked()); } - -void KMixWindow::slotHWInfo() +void +KMixWindow::slotHWInfo() { - KMessageBox::information( 0, m_hwInfoString, i18n("Mixer Hardware Information") ); + KMessageBox::information(0, m_hwInfoString, + i18n("Mixer Hardware Information")); } -void KMixWindow::slotKdeAudioSetupExec() +void +KMixWindow::slotKdeAudioSetupExec() { - QStringList args; - args << "kcmshell4" << "kcm_phonon"; - forkExec(args); + QStringList args; + args << "kcmshell4" << "kcm_phonon"; + forkExec(args); } -void KMixWindow::forkExec(const QStringList& args) +void +KMixWindow::forkExec(const QStringList& args) { - int pid = KProcess::startDetached(args); - if ( pid == 0 ) { - static const QString startErrorMessage (i18n("The helper application is either not installed or not working.")); - QString msg; - msg += startErrorMessage; - msg += "\n("; - msg += args.join( QLatin1String( " " )); - msg += ')'; - errorPopup(msg); + int pid = KProcess::startDetached(args); + if (pid == 0) + { + static const QString startErrorMessage( + i18n( + "The helper application is either not installed or not working.")); + QString msg; + msg += startErrorMessage; + msg += "\n("; + msg += args.join(QLatin1String(" ")); + msg += ')'; + errorPopup(msg); } } -void KMixWindow::errorPopup(const QString& msg) +void +KMixWindow::errorPopup(const QString& msg) { - QPointer<KDialog> dialog = new KDialog(this); - dialog->setButtons(KDialog::Ok); - dialog->setCaption(i18n("Error")); - QLabel* qlbl = new QLabel(msg); - dialog->setMainWidget(qlbl); - dialog->exec(); - delete dialog; - kWarning() << msg; + QPointer<KDialog> dialog = new KDialog(this); + dialog->setButtons(KDialog::Ok); + dialog->setCaption(i18n("Error")); + QLabel* qlbl = new QLabel(msg); + dialog->setMainWidget(qlbl); + dialog->exec(); + delete dialog; + kWarning() << msg; } -void KMixWindow::slotConfigureCurrentView() +void +KMixWindow::slotConfigureCurrentView() { - KMixerWidget* mw = (KMixerWidget*)m_wsMixers->currentWidget(); - ViewBase* view = 0; - if (mw) view = mw->currentView(); - if (view) view->configureView(); + KMixerWidget* mw = (KMixerWidget*) m_wsMixers->currentWidget(); + ViewBase* view = 0; + if (mw) + view = mw->currentView(); + if (view) + view->configureView(); } -void KMixWindow::slotSelectMaster() +void +KMixWindow::slotSelectMaster() { - Mixer *mixer = Mixer::getGlobalMasterMixer(); - if ( mixer != 0) - { - QPointer<DialogSelectMaster> dsm = new DialogSelectMaster(Mixer::getGlobalMasterMixer()); - dsm->setAttribute(Qt::WA_DeleteOnClose, true); - dsm->show(); - } - else - { - - KMessageBox::error(0, i18n("No sound card is installed or currently plugged in.")); - } + Mixer *mixer = Mixer::getGlobalMasterMixer(); + if (mixer != 0) + { + QPointer<DialogSelectMaster> dsm = new DialogSelectMaster( + Mixer::getGlobalMasterMixer()); + dsm->setAttribute(Qt::WA_DeleteOnClose, true); + dsm->show(); + } + else + { + + KMessageBox::error(0, + i18n("No sound card is installed or currently plugged in.")); + } } -void KMixWindow::newMixerShown(int /*tabIndex*/ ) { - KMixerWidget* kmw = (KMixerWidget*)m_wsMixers->currentWidget(); - if (kmw) +void +KMixWindow::newMixerShown(int /*tabIndex*/) +{ + KMixerWidget* kmw = (KMixerWidget*) m_wsMixers->currentWidget(); + if (kmw) { - // I am using the app name as a PREFIX, as KMix is a single window app, and it is - // more helpful to the user to see "KDE Mixer" in a window list than a possibly cryptic - // soundcard name like "HDA ATI SB" - setWindowTitle( i18n("KDE Mixer") + " - " + kmw->mixer()->readableName() ); - if ( ! m_dontSetDefaultCardOnStart ) - m_defaultCardOnStart = kmw->getGuiprof()->getId(); - // As switching the tab does NOT mean switching the master card, we do not need to update dock icon here. - // It would lead to unnecesary flickering of the (complete) dock area. - - // We only show the "Configure Channels..." menu item if the mixer is not dynamic - ViewBase* view = kmw->currentView(); - QAction* action = actionCollection()->action( "toggle_channels_currentview" ); - if (view && action) - action->setVisible( !view->isDynamic() ); + // I am using the app name as a PREFIX, as KMix is a single window app, and it is + // more helpful to the user to see "KDE Mixer" in a window list than a possibly cryptic + // soundcard name like "HDA ATI SB" + setWindowTitle(i18n("KDE Mixer") + " - " + kmw->mixer()->readableName()); + if (!m_dontSetDefaultCardOnStart) + m_defaultCardOnStart = kmw->getGuiprof()->getId(); + // As switching the tab does NOT mean switching the master card, we do not need to update dock icon here. + // It would lead to unnecesary flickering of the (complete) dock area. + + // We only show the "Configure Channels..." menu item if the mixer is not dynamic + ViewBase* view = kmw->currentView(); + QAction* action = actionCollection()->action( + "toggle_channels_currentview"); + if (view && action) + action->setVisible(!view->isDynamic()); } } - - #include "kmix.moc" diff --git a/apps/kmix.h b/apps/kmix.h index 74f8948..91ba0f1 100644 --- a/apps/kmix.h +++ b/apps/kmix.h @@ -169,7 +169,10 @@ KMixWindow : public KXmlGuiWindow void saveVolumes2() { saveVolumes(QString("2")); } void saveVolumes3() { saveVolumes(QString("3")); } void saveVolumes4() { saveVolumes(QString("4")); } -; + + bool profileExists(GUIProfile* guiprof); + + ; }; #endif // KMIX_H diff --git a/backends/mixer_pulse.cpp b/backends/mixer_pulse.cpp index 9272408..e5ef166 100644 --- a/backends/mixer_pulse.cpp +++ b/backends/mixer_pulse.cpp @@ -835,6 +835,7 @@ void Mixer_PULSE::addDevice(devinfo& dev, bool isAppStream) { if (dev.chanMask != Volume::MNONE) { MixSet *ms = 0; + bool isCapture = (m_devnum == KMIXPA_CAPTURE || m_devnum == KMIXPA_APP_CAPTURE); if (m_devnum == KMIXPA_APP_PLAYBACK && s_mixers.contains(KMIXPA_PLAYBACK)) ms = s_mixers[KMIXPA_PLAYBACK]->getMixSet(); else if (m_devnum == KMIXPA_APP_CAPTURE && s_mixers.contains(KMIXPA_CAPTURE)) @@ -847,7 +848,11 @@ void Mixer_PULSE::addDevice(devinfo& dev, bool isAppStream) if (isAppStream) md->setApplicationStream(true); - md->addPlaybackVolume(v); + kDebug() << "Adding Pulse volume " << dev.name << ", isCapture= " << isCapture << ", devnum=" << m_devnum; + if ( isCapture ) + md->addCaptureVolume(v); // TODO cesken Check with Colin + else + md->addPlaybackVolume(v); md->setMuted(dev.mute); m_mixDevices.append(md->addToPool()); } diff --git a/gui/kmixdockwidget.cpp b/gui/kmixdockwidget.cpp index 22a753e..4e87b1e 100644 --- a/gui/kmixdockwidget.cpp +++ b/gui/kmixdockwidget.cpp @@ -80,7 +80,7 @@ KMixDockWidget::KMixDockWidget(KMixWindow* parent, bool volumePopup) if (_volumePopup) { kDebug() << "Construct the ViewDockAreaPopup and actions"; _referenceWidget = new KMenu(parent); - ViewDockAreaPopup* _referenceWidget2 = new ViewDockAreaPopup(_referenceWidget, "dockArea", Mixer::getGlobalMasterMixer(), 0, (GUIProfile*)0, parent); + _referenceWidget2 = new ViewDockAreaPopup(_referenceWidget, "dockArea", 0, (GUIProfile*)0, parent); _referenceWidget2->createDeviceWidgets(); connect(_referenceWidget2, SIGNAL(recreateMe()), _kmixMainWindow, SLOT(recreateDockWidget())); @@ -156,6 +156,7 @@ void KMixDockWidget::createMasterVolWidget() */ connect( &m_metaMixer, SIGNAL(controlChanged()), this, SLOT(setVolumeTip()) ); connect( &m_metaMixer, SIGNAL(controlChanged()), this, SLOT(updatePixmap()) ); + connect( &m_metaMixer, SIGNAL(controlChanged()), this, SLOT(updateDockPopup()) ); } void KMixDockWidget::selectMaster() @@ -229,6 +230,12 @@ KMixDockWidget::setVolumeTip() _oldToolTipValue = virtualToolTipValue; } +void KMixDockWidget::updateDockPopup() +{ +// _referenceWidget2->setMixSet(); +// _referenceWidget2->constructionFinished(); +} + void KMixDockWidget::updatePixmap() { diff --git a/gui/kmixdockwidget.h b/gui/kmixdockwidget.h index 8323722..082817d 100644 --- a/gui/kmixdockwidget.h +++ b/gui/kmixdockwidget.h @@ -83,6 +83,7 @@ class KMixDockWidget : public KStatusNotifierItem public slots: void setVolumeTip(); void updatePixmap(); + void updateDockPopup(); void activate(const QPoint &pos); protected: @@ -92,7 +93,7 @@ class KMixDockWidget : public KStatusNotifierItem void toggleMinimizeRestore(); private: - //ViewDockAreaPopup *_referenceWidget; + ViewDockAreaPopup *_referenceWidget2; KMenu *_referenceWidget; QWidgetAction *_volWA; bool _ignoreNextEvent; diff --git a/gui/viewbase.cpp b/gui/viewbase.cpp index 7979ba8..854b4bf 100644 --- a/gui/viewbase.cpp +++ b/gui/viewbase.cpp @@ -43,17 +43,11 @@ #include "core/mixertoolbox.h" -ViewBase::ViewBase(QWidget* parent, const char* id, Mixer* mixer, Qt::WFlags f, ViewBase::ViewFlags vflags, GUIProfile *guiprof, KActionCollection *actionColletion) +ViewBase::ViewBase(QWidget* parent, const char* id, Qt::WFlags f, ViewBase::ViewFlags vflags, GUIProfile *guiprof, KActionCollection *actionColletion) : QWidget(parent, f), _popMenu(NULL), _actions(actionColletion), _vflags(vflags), _guiprof(guiprof) { setObjectName(id); m_viewId = id; - _mixer = mixer; - - // This must be populated now otherwise bad things happen (circular dependancies etc - // This is due to the fact that setMixSet() calls isDynamic() which in turn needs a populated - // _mixers array to ensure that this is the case.... - _mixers.insert(_mixer); if ( _actions == 0 ) { // We create our own action collection, if the actionColletion was 0. @@ -78,11 +72,6 @@ ViewBase::ViewBase(QWidget* parent, const char* id, Mixer* mixer, Qt::WFlags f, } } } - if ( !isDynamic() ) { - QAction *action = _localActionColletion->addAction("toggle_channels"); - action->setText(i18n("&Channels")); - connect(action, SIGNAL(triggered(bool)), SLOT(configureView())); - } /* connect ( _mixer, SIGNAL(controlChanged()), this, SLOT(refreshVolumeLevels()) ); connect ( _mixer, SIGNAL(controlsReconfigured(QString)), this, SLOT(controlsReconfigured(QString)) );*/ } @@ -92,6 +81,11 @@ ViewBase::~ViewBase() { } +void ViewBase::addMixer(Mixer *mixer) +{ + _mixers.append(mixer); +} + void ViewBase::configurationUpdate() { } @@ -122,8 +116,16 @@ void ViewBase::createDeviceWidgets() QWidget* mdw = add(md); // a) Let the View implementation do its work _mdws.append(mdw); // b) Add it to the local list } - // allow view to "polish" itself - constructionFinished(); + + if ( !isDynamic() ) + { + QAction *action = _localActionColletion->addAction("toggle_channels"); + action->setText(i18n("&Channels")); + connect(action, SIGNAL(triggered(bool)), SLOT(configureView())); + } + + // allow view to "polish" itself + constructionFinished(); } /** @@ -182,27 +184,23 @@ void ViewBase::showContextMenu() _popMenu->popup( pos ); } -void ViewBase::controlsReconfigured( const QString& mixer_ID ) +void ViewBase::controlsReconfigured( const QString& mixerId ) { - // TODO Search _mixers for the correct Mixer*. After that, remove _mixer instance variable - bool isRelevantMixer = (_mixer->id() == mixer_ID ); - // if (!isRelevantMixer) - // { - // foreach ( Mixer* mixer , _mixers) - // { - // if ( mixer->id() == mixer_ID ) - // { - // isRelevantMixer = true; - // break; - // } - // } - // } + bool isRelevantMixer = false; + foreach ( Mixer* mixer , _mixers) + { + if ( mixer->id() == mixerId ) + { + isRelevantMixer = true; + break; + } + } if (isRelevantMixer) { - kDebug(67100) << "ViewBase::controlsReconfigured() " << mixer_ID << " is being redrawn (mixset contains: " << _mixSet.count() << ")"; + kDebug(67100) << "ViewBase::controlsReconfigured() " << mixerId << " is being redrawn (mixset contains: " << _mixSet.count() << ")"; setMixSet(); - kDebug(67100) << "ViewBase::controlsReconfigured() " << mixer_ID << ": Recreating widgets (mixset contains: " << _mixSet.count() << ")"; + kDebug(67100) << "ViewBase::controlsReconfigured() " << mixerId << ": Recreating widgets (mixset contains: " << _mixSet.count() << ")"; createDeviceWidgets(); } } @@ -239,14 +237,14 @@ void ViewBase::setMixSet() } _setMixSet(); - _mixers.clear(); - _mixers.insert(_mixer); - foreach ( shared_ptr<MixDevice> md, _mixSet ) - { -// kDebug() << "VVV Add to " << md->mixer()->id(); -// MixDeviceWidget* mdw = qobject_cast<MixDeviceWidget*>(qw); - _mixers.insert(md->mixer()); - } +// _mixers.clear(); +// _mixers.insert(mixer); +// foreach ( shared_ptr<MixDevice> md, _mixSet ) +// { +// // kDebug() << "VVV Add to " << md->mixer()->id(); +// // MixDeviceWidget* mdw = qobject_cast<MixDeviceWidget*>(qw); +// _mixers.insert(md->mixer()); +// } } int ViewBase::visibleControls() diff --git a/gui/viewbase.h b/gui/viewbase.h index a143408..fa35751 100644 --- a/gui/viewbase.h +++ b/gui/viewbase.h @@ -22,7 +22,6 @@ #define ViewBase_h // QT -#include <QSet> #include <QWidget> #include <QList> @@ -58,9 +57,11 @@ public: Vertical = 0x0008 }; - ViewBase(QWidget* parent, const char* id, Mixer* mixer, Qt::WFlags=0, ViewFlags vflags=0, GUIProfile *guiprof=0, KActionCollection* actionCollection = 0); + ViewBase(QWidget* parent, const char* id, Qt::WFlags=0, ViewFlags vflags=0, GUIProfile *guiprof=0, KActionCollection* actionCollection = 0); virtual ~ViewBase(); + void addMixer(Mixer *mixer); + QString id() const; // This method is called by ViewBase at the end of createDeviceWidgets(). The default @@ -115,7 +116,7 @@ public: GUIProfile* guiProfile() { return _guiprof; }; KActionCollection* actionCollection() { return _actions; }; - QSet<Mixer*>& getMixers() { return _mixers; }; + QList<Mixer*>& getMixers() { return _mixers; }; /** * Contains the widgets for the _mixSet. There is a 1:1 relationship, which means: @@ -132,8 +133,7 @@ signals: protected: MixSet _mixSet; - Mixer *_mixer; - QSet<Mixer*> _mixers; // this might deprecate _mixer in the future. Currently only in use by ViewDockAreaPopup + QList<Mixer*> _mixers; // this might deprecate _mixer in the future. Currently only in use by ViewDockAreaPopup KMenu *_popMenu; KActionCollection* _actions; // -<- applciations wide action collection diff --git a/gui/viewdockareapopup.cpp b/gui/viewdockareapopup.cpp index fa01c8c..4d44b7c 100644 --- a/gui/viewdockareapopup.cpp +++ b/gui/viewdockareapopup.cpp @@ -41,9 +41,14 @@ #include "apps/kmix.h" -ViewDockAreaPopup::ViewDockAreaPopup(QWidget* parent, const char* name, Mixer* mixer, ViewBase::ViewFlags vflags, GUIProfile *guiprof, KMixWindow *dockW ) - : ViewBase(parent, name, mixer, /*Qt::FramelessWindowHint | Qt::MSWindowsFixedSizeDialogHint*/0, vflags, guiprof), _dock(dockW) +ViewDockAreaPopup::ViewDockAreaPopup(QWidget* parent, const char* name, ViewBase::ViewFlags vflags, GUIProfile *guiprof, KMixWindow *dockW ) + : ViewBase(parent, name, /*Qt::FramelessWindowHint | Qt::MSWindowsFixedSizeDialogHint*/0, vflags, guiprof), _dock(dockW) { + foreach ( Mixer* mixer, Mixer::mixers() ) + { + // Adding all mixers, as we potentially want to show all master controls + addMixer(mixer); + } //_layoutControls = new QHBoxLayout(this); _layoutMDW = new QGridLayout( this ); _layoutMDW->setSpacing( KDialog::spacingHint() ); @@ -53,26 +58,27 @@ ViewDockAreaPopup::ViewDockAreaPopup(QWidget* parent, const char* name, Mixer* m setMixSet(); } -ViewDockAreaPopup::~ViewDockAreaPopup() { +ViewDockAreaPopup::~ViewDockAreaPopup() +{ + delete _layoutMDW; } -void ViewDockAreaPopup::wheelEvent ( QWheelEvent * e ) { +void ViewDockAreaPopup::wheelEvent ( QWheelEvent * e ) +{ + if ( _mdws.isEmpty() ) + return; + // Pass wheel event from "border widget" to child - QWidget* mdw = 0; - if ( !_mdws.isEmpty() ) - mdw = _mdws.first(); - - if ( mdw != 0 ) - QApplication::sendEvent( mdw, e); + QApplication::sendEvent( _mdws.first(), e); } -void ViewDockAreaPopup::showContextMenu() -{ - // no right-button-menu on "dock area popup" - return; -} +// void ViewDockAreaPopup::showContextMenu() +// { +// // no right-button-menu on "dock area popup" +// return; +// } void ViewDockAreaPopup::_setMixSet() @@ -80,24 +86,33 @@ void ViewDockAreaPopup::_setMixSet() // kDebug(67100) << "ViewDockAreaPopup::setMixSet()\n"; // -- remove controls - if ( _mixer->isDynamic() ) { + if ( isDynamic() ) { // Our _layoutMDW now should only contain spacer widgets from the QSpacerItem's in add() below. // We need to trash those too otherwise all sliders gradually migrate away from the edge :p QLayoutItem *li; while ( ( li = _layoutMDW->takeAt(0) ) ) delete li; } + _mixSet.clear(); - shared_ptr<MixDevice>dockMD = Mixer::getGlobalMasterMD(); - if ( dockMD == 0 ) { + foreach ( Mixer* mixer, _mixers ) + { + shared_ptr<MixDevice>dockMD = mixer->getLocalMasterMD(); + if ( dockMD == 0 && mixer->size() > 0 ) + { // If we have no dock device yet, we will take the first available mixer device - if ( _mixer->size() > 0) { - dockMD = (*_mixer)[0]; - } + dockMD = (*mixer)[0]; } - if ( dockMD != 0 ) { + if ( dockMD != 0 ) + { + if ( !dockMD->isApplicationStream() && dockMD->playbackVolume().hasVolume()) + { + // don't add application streams here. They are handled below, so + // we make sure to not add them twice _mixSet.append(dockMD); } + } + } // loop over all cards foreach ( Mixer* mixer2 , Mixer::mixers() ) { @@ -129,18 +144,18 @@ QWidget* ViewDockAreaPopup::add(shared_ptr<MixDevice> md) ProfControl *pctl = new ProfControl( dummyMatchAll, matchAllPlaybackAndTheCswitch); MixDeviceWidget *mdw = new MDWSlider( md, // only 1 device. - true, // Show Mute LED + true, // Show Mute LE true, // Show Record LED false, // Small _dock->toplevelOrientation(), // Direction: only 1 device, so doesn't matter this, // parent - 0 // Is "NULL", so that there is no RMB-popup + this // NOT ANYMORE!!! -> Is "NULL", so that there is no RMB-popup , pctl ); int sliderColumn = _layoutMDW->rowCount(); - if (sliderColumn == 1 ) sliderColumn =0; + //if (sliderColumn == 1 ) sliderColumn =0; _layoutMDW->addItem( new QSpacerItem( 5, 20 ), sliderColumn,0 ); - _layoutMDW->addWidget( mdw, sliderColumn+1,0 ); + _layoutMDW->addWidget( mdw, 0, sliderColumn+1 ); //kDebug(67100) << "ADDED " << md->id() << " at column " << sliderColumn; return mdw; @@ -150,7 +165,7 @@ void ViewDockAreaPopup::constructionFinished() { // kDebug(67100) << "ViewDockAreaPopup::constructionFinished()\n"; int sliderColumn = _layoutMDW->rowCount(); - _layoutMDW->addItem( new QSpacerItem( 5, 20 ), sliderColumn, 0 ); // TODO add this on "polish()" + _layoutMDW->addItem( new QSpacerItem( 5, 20 ), 0, sliderColumn ); // TODO add this on "polish()" QPushButton *pb = new QPushButton( i18n("Mixer"), this ); pb->setObjectName( QLatin1String("MixerPanel" )); connect ( pb, SIGNAL(clicked()), SLOT(showPanelSlot()) ); diff --git a/gui/viewdockareapopup.h b/gui/viewdockareapopup.h index 303ec61..01beda1 100644 --- a/gui/viewdockareapopup.h +++ b/gui/viewdockareapopup.h @@ -34,13 +34,13 @@ class ViewDockAreaPopup : public ViewBase { Q_OBJECT public: - ViewDockAreaPopup(QWidget* parent, const char* name, Mixer* mixer, ViewBase::ViewFlags vflags, GUIProfile *guiprof, KMixWindow *dockW); + ViewDockAreaPopup(QWidget* parent, const char* name, ViewBase::ViewFlags vflags, GUIProfile *guiprof, KMixWindow *dockW); virtual ~ViewDockAreaPopup(); virtual QWidget* add(shared_ptr<MixDevice> md); virtual void constructionFinished(); virtual void refreshVolumeLevels(); - virtual void showContextMenu(); +// virtual void showContextMenu(); protected: KMixWindow *_dock; diff --git a/gui/viewsliders.cpp b/gui/viewsliders.cpp index d893b8e..25f5779 100644 --- a/gui/viewsliders.cpp +++ b/gui/viewsliders.cpp @@ -44,10 +44,13 @@ // KDE #include <kdebug.h> +#include <KIcon> #include <KLocale> // Qt +#include <QPushButton> #include <QLabel> +#include <QLayoutItem> #include <QWidget> #include <QVBoxLayout> #include <QHBoxLayout> @@ -60,10 +63,12 @@ * the class name suggests). * TODO change "const char*" parameter to QString */ -ViewSliders::ViewSliders(QWidget* parent, const char* name, Mixer* mixer, ViewBase::ViewFlags vflags, GUIProfile *guiprof, KActionCollection *actColl) - : ViewBase(parent, name, mixer, Qt::FramelessWindowHint, vflags, guiprof, actColl) +ViewSliders::ViewSliders(QWidget* parent, const char* id, Mixer* mixer, ViewBase::ViewFlags vflags, GUIProfile *guiprof, KActionCollection *actColl) + : ViewBase(parent, id, Qt::FramelessWindowHint, vflags, guiprof, actColl) , _layoutEnum(0) { + addMixer(mixer); + if ( _vflags & ViewBase::Vertical ) { _layoutMDW = new QVBoxLayout(this); _layoutMDW->setAlignment(Qt::AlignLeft|Qt::AlignTop); @@ -84,12 +89,9 @@ ViewSliders::ViewSliders(QWidget* parent, const char* name, Mixer* mixer, ViewBa _layoutMDW->setSpacing(0); _layoutMDW->addItem( _layoutSliders ); - QString driverName = _mixer->getDriverName(); - - // Hint: This text comparison is not a clean solution, but one that will work for quite a while. // TODO cesken Revise this "text comparison" thingy when I change the View constructor to take an "id" and a "readableName" - QString viewName(name); + QString viewName(id); if (viewName.contains(".Capture_Streams.")) emptyStreamHint = new QLabel(i18n("Nothing is capturing audio.")); else if (viewName.contains(".Playback_Streams.")) @@ -172,9 +174,7 @@ QWidget* ViewSliders::add(shared_ptr<MixDevice> md) void ViewSliders::_setMixSet() { - const MixSet& mixset = _mixer->getMixSet(); - - if ( _mixer->isDynamic() ) { + if ( isDynamic() ) { // We will be recreating our sliders, so make sure we trash all the separators too. qDeleteAll(_separators); _separators.clear(); @@ -193,7 +193,11 @@ void ViewSliders::_setMixSet() // This method iterates the controls from the Profile // Each control is checked, whether it is also contained in the mixset, and // applicable for this kind of View. If yes, the control is accepted and inserted. - + + foreach (Mixer* mixer , _mixers ) + { + const MixSet& mixset = mixer->getMixSet(); + foreach ( ProfControl* control, _guiprof->getControls() ) { //ProfControl* control = *it; @@ -248,6 +252,8 @@ void ViewSliders::_setMixSet() //kDebug(67100) << "ViewSliders::setMixSet(): No such control '" << control->id << "'in the mixer . Please check the GUIProfile\n"; } } // iteration over all controls from the Profile + + } // Iteration over all Mixers emptyStreamHint->setVisible( _mixSet.isEmpty() && isDynamic() ); // show a hint why a tab is empty (dynamic controls!!!) // visibleControls() == 0 could be used for the !isDynamic() case @@ -271,6 +277,19 @@ void ViewSliders::_setMixSet() void ViewSliders::constructionFinished() { configurationUpdate(); // TODO Add a "show more" / "configure this view" button + const KIcon& icon = KIcon( QLatin1String( "audio-volume-muted" )); + QPushButton* configureViewButton = new QPushButton(icon, "configure view", this); + _layoutSliders->addWidget(configureViewButton); + QPushButton* profileButton = new QPushButton("1", this); + profileButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + _layoutSliders->addWidget(profileButton); + profileButton = new QPushButton("2", this); + _layoutSliders->addWidget(profileButton); + profileButton = new QPushButton("3", this); + _layoutSliders->addWidget(profileButton); + profileButton = new QPushButton("4", this); + _layoutSliders->addWidget(profileButton); + } |
