/* * KMix -- KDE's full featured mini mixer * * Copyright (C) 2000 Stefan Schimanski * Copyright (C) 2001 Preston Brown * Copyright (C) 2003 Sven Leiber * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H #include #endif // include files for QT #include #include #include #include #include #include #include #include // include files for KDE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // application specific includes #include "mixertoolbox.h" #include "kmix.h" #include "kmixerwidget.h" #include "kmixdockwidget.h" #include "kmixtoolbox.h" #include "kmixsettings.h" #include "behaviorconfig.h" #include "appearanceconfig.h" #ifdef WITH_KMIX_EXPERIMENTAL #include "experimental.h" #endif /** * Constructs a mixer window (KMix main window) */ KMixWindow::KMixWindow() : DCOPObject("kmix"), TDEMainWindow(0, 0, 0, 0), m_dockWidget( 0L ) { m_visibilityUpdateAllowed = true; m_mixerWidgets.setAutoDelete(true); #ifdef WITH_KMIX_EXPERIMENTAL MixerToolBox::initMixer(Mixer::mixers(), KMixSettings::multiDriver(), m_hwInfoString); #else MixerToolBox::initMixer(Mixer::mixers(), false, m_hwInfoString); #endif loadConfig(); initActions(); initWidgets(); initMixerWidgets(); updateDocking(); if ( KMixSettings::visible() ) { show(); } else { hide(); } connect( kapp, TQT_SIGNAL( aboutToQuit()), TQT_SLOT( saveSettings()) ); } KMixWindow::~KMixWindow() { MixerToolBox::deinitMixer(); } void KMixWindow::initActions() { // file menu KStdAction::quit( TQT_TQOBJECT(this), TQT_SLOT(quit()), actionCollection()); // settings menu KStdAction::showMenubar( TQT_TQOBJECT(this), TQT_SLOT(toggleMenuBar()), actionCollection()); KStdAction::preferences( TQT_TQOBJECT(this), TQT_SLOT(showSettings()), actionCollection()); new TDEAction( i18n( "Configure &Global Shortcuts..." ), "configure_shortcuts", 0, TQT_TQOBJECT(this), TQT_SLOT( configureGlobalShortcuts() ), actionCollection(), "settings_global" ); KStdAction::keyBindings( guiFactory(), TQT_SLOT(configureShortcuts()), actionCollection()); (void) new TDEAction( i18n( "Hardware &Information" ), 0, TQT_TQOBJECT(this), TQT_SLOT( slotHWInfo() ), actionCollection(), "hwinfo" ); (void) new TDEAction( i18n( "Hide Mixer Window" ), Key_Escape, TQT_TQOBJECT(this), TQT_SLOT(hide()), actionCollection(), "hide_kmixwindow" ); m_globalAccel = new TDEGlobalAccel(this, "KMix"); m_globalAccel->insert( "Increase volume", i18n( "Increase Volume of Master Channel"), TQString(), TDEShortcut(), TDEShortcut(), TQT_TQOBJECT(this), TQT_SLOT( slotIncreaseVolume() ) ); m_globalAccel->insert( "Decrease volume", i18n( "Decrease Volume of Master Channel"), TQString(), TDEShortcut(), TDEShortcut(), TQT_TQOBJECT(this), TQT_SLOT( slotDecreaseVolume() ) ); m_globalAccel->insert( "Toggle mute", i18n( "Toggle Mute of Master Channel"), TQString(), TDEShortcut(), TDEShortcut(), TQT_TQOBJECT(this), TQT_SLOT( slotToggleMuted() ) ); m_globalAccel->readSettings(); m_globalAccel->updateConnections(); createGUI( "kmixui.rc" ); } void KMixWindow::initWidgets() { // Main widget and layout setCentralWidget( new TQWidget( this, "qt_central_widget" ) ); // Widgets layout widgetsLayout = new TQVBoxLayout( centralWidget(), 0, 0, "widgetsLayout" ); widgetsLayout->setResizeMode(TQLayout::Minimum); // works fine // Mixer widget line mixerNameLayout = new TQHBox( centralWidget(), "mixerNameLayout" ); widgetsLayout->setStretchFactor( mixerNameLayout, 0 ); TQSizePolicy qsp( TQSizePolicy::Ignored, TQSizePolicy::Maximum); mixerNameLayout->setSizePolicy(qsp); mixerNameLayout->setSpacing(KDialog::spacingHint()); TQLabel *qlbl = new TQLabel( i18n("Current mixer:"), mixerNameLayout ); qlbl->setFixedHeight(qlbl->sizeHint().height()); m_cMixer = new KComboBox( FALSE, mixerNameLayout, "mixerCombo" ); m_cMixer->setFixedHeight(m_cMixer->sizeHint().height()); connect( m_cMixer, TQT_SIGNAL( activated( int ) ), TQT_TQOBJECT(this), TQT_SLOT( showSelectedMixer( int ) ) ); TQToolTip::add( m_cMixer, i18n("Current mixer" ) ); // Add first layout to widgets widgetsLayout->addWidget( mixerNameLayout ); m_wsMixers = new TQWidgetStack( centralWidget(), "MixerWidgetStack" ); widgetsLayout->setStretchFactor( m_wsMixers, 10 ); widgetsLayout->addWidget( m_wsMixers ); if ( KMixSettings::menubar() ) menuBar()->show(); else menuBar()->hide(); widgetsLayout->activate(); } void KMixWindow::updateDocking() { // delete old dock widget if (m_dockWidget) { delete m_dockWidget; m_dockWidget = 0L; } if ( KMixSettings::allowDocking() ) { // create dock widget m_dockWidget = new KMixDockWidget( Mixer::mixers().first(), this, "mainDockWidget", KMixSettings::trayVolumeControl(), KMixSettings::dockIconMuting() ); m_dockWidget->show(); } } void KMixWindow::saveSettings() { saveConfig(); saveVolumes(); } void KMixWindow::saveConfig() { // make sure we don't start without any UI (in case the tray icon is disabled) bool startVisible = KMixSettings::visible(); if ( !KMixSettings::allowDocking() ) { startVisible = true; } KMixSettings::setSize(size()); KMixSettings::setPosition(pos()); KMixSettings::setVisible(startVisible); Mixer* mixerMasterCard = Mixer::masterCard(); if ( mixerMasterCard != 0 ) { KMixSettings::setMasterMixer(mixerMasterCard->id()); } MixDevice* mdMaster = Mixer::masterCardDevice(); if ( mdMaster != 0 ) { KMixSettings::setMasterMixerDevice(mdMaster->getPK()); } // save mixer widgets for ( KMixerWidget *mw = m_mixerWidgets.first(); mw != 0; mw = m_mixerWidgets.next() ) { if ( mw->mixer()->isOpen() ) { // protect from unplugged devices (better do *not* save them) TQString grp; grp.sprintf( "%i", mw->id() ); mw->saveConfig( TDESharedConfig::openConfig("kmixrc"), grp ); } } KMixSettings::writeConfig(); } void KMixWindow::loadConfig() { if (!KMixSettings::useDefaultMaster()) { Mixer::setMasterCard(KMixSettings::masterMixer()); Mixer::setMasterCardDevice(KMixSettings::masterMixerDevice()); } m_toplevelOrientation = static_cast(KMixSettings::orientation()); TDEToggleAction *a = static_cast(actionCollection()->action("options_show_menubar")); if (a) a->setChecked( KMixSettings::menubar() ); // restore window size and position if ( !kapp->isRestored() ) // done by the session manager otherwise { TQSize size = KMixSettings::size(); if(!size.isEmpty()) { resize(size); } move(KMixSettings::position()); } } void KMixWindow::initMixerWidgets() { m_mixerWidgets.clear(); int id=0; Mixer *mixer; // Attention!! If Mixer::mixers() is empty, we behave stupid. We don't show nothing and there // is not even a context menu. for ( mixer=Mixer::mixers().first(),id=0; mixer!=0; mixer=Mixer::mixers().next(),id++ ) { //kdDebug(67100) << "Mixer number: " << id << " Name: " << mixer->mixerName() << endl ; ViewBase::ViewFlags vflags = ViewBase::HasMenuBar; if (KMixSettings::menubar()) { vflags |= ViewBase::MenuBarVisible; } #ifdef WITH_KMIX_EXPERIMENTAL if (KMixSettings::experimental_ViewSurround()) { vflags |= ViewBase::Experimental_SurroundView; } if (KMixSettings::experimental_ViewGrid()) { vflags |= ViewBase::Experimental_GridView; } #endif if ( m_toplevelOrientation == TQt::Vertical ) { vflags |= ViewBase::Vertical; } else { vflags |= ViewBase::Horizontal; } KMixerWidget *mw = new KMixerWidget( id, mixer, mixer->mixerName(), MixDevice::ALL, this, "KMixerWidget", vflags ); m_mixerWidgets.append( mw ); // Add to Combo and Stack m_cMixer->insertItem( mixer->mixerName() ); m_wsMixers->addWidget( mw, id ); TQString grp; grp.sprintf( "%i", mw->id() ); mw->loadConfig( TDESharedConfig::openConfig("kmixrc"), grp ); mw->setTicks(KMixSettings::tickmarks()); mw->setLabels(KMixSettings::labels()); mw->setValueStyle(KMixSettings::valueStyle()); // !! I am still not sure whether this works 100% reliably - chris mw->show(); } if (id == 1) { // don't show the Current Mixer bit unless we have multiple mixers mixerNameLayout->hide(); } } bool KMixWindow::queryClose ( ) { if ( KMixSettings::allowDocking() && !kapp->sessionSaving() ) { hide(); return false; } return true; } void KMixWindow::quit() { kapp->quit(); } void KMixWindow::showSettings() { if (TDEConfigDialog::showDialog("KMixConfigDialog")) { return; } TDEConfigDialog *cfg = new TDEConfigDialog(this, "KMixConfigDialog", KMixSettings::self()); KMixBehaviorConfig *cfgb = new KMixBehaviorConfig(0, "Behavior"); cfg->addPage(cfgb, i18n("Behavior"), "configure"); KMixAppearanceConfig *cfga = new KMixAppearanceConfig(0, "Appearance"); cfg->addPage(cfga, i18n("Appearance"), "kmix"); #ifdef WITH_KMIX_EXPERIMENTAL KMixExperimental *cfgx = new KMixExperimental(0, "Experimental"); cfg->addPage(cfgx, i18n("Experimental"), "bug"); #endif connect(cfg, TQT_SIGNAL(settingsChanged()), this, TQT_SLOT(applyPrefs())); cfg->show(); } void KMixWindow::showHelp() { actionCollection()->action( "help_contents" )->activate(); } void KMixWindow::showAbout() { actionCollection()->action( "help_about_app" )->activate(); } /** * Loads the volumes of all mixers from kmixctrlrc. * In other words: * Restores the default voumes as stored via saveVolumes() or the * execution of "kmixctrl --save" */ /* Currently this is not in use void KMixWindow::loadVolumes() { TDEConfig *cfg = new TDEConfig( "kmixctrlrc", true ); for (Mixer *mixer=Mixer::mixers().first(); mixer!=0; mixer=Mixer::mixers().next()) { mixer->volumeLoad( cfg ); } delete cfg; } */ /** * Stores the volumes of all mixers Can be restored via loadVolumes() or * the kmixctrl application. */ void KMixWindow::saveVolumes() { TDEConfig *cfg = new TDEConfig( "kmixctrlrc", false ); for (Mixer *mixer=Mixer::mixers().first(); mixer!=0; mixer=Mixer::mixers().next()) { //kdDebug(67100) << "KMixWindow::saveConfig()" << endl; if ( mixer->isOpen() ) { // protect from unplugged devices (better do *not* save them) mixer->volumeSave( cfg ); } } delete cfg; } void KMixWindow::applyPrefs() { auto old = static_cast(KMixSettings::orientation()); if (m_toplevelOrientation != old) { TQString msg = i18n("The change of orientation will be adopted on the next start of KMix."); KMessageBox::information(0, msg); } this->setUpdatesEnabled(false); updateDocking(); for (KMixerWidget *mw=m_mixerWidgets.first(); mw!=0; mw=m_mixerWidgets.next()) { mw->setTicks( KMixSettings::tickmarks() ); mw->setLabels( KMixSettings::labels() ); mw->setValueStyle( KMixSettings::valueStyle() ); mw->mixer()->readSetFromHWforceUpdate(); // needed, as updateDocking() has reconstructed the DockWidget } this->setUpdatesEnabled(true); this->repaint(); // make KMix look fast (saveConfig() often uses several seconds) kapp->processEvents(); saveConfig(); } void KMixWindow::toggleMenuBar() { if( menuBar()->isShown() ) { menuBar()->hide(); } else { menuBar()->show(); } } void KMixWindow::showEvent( TQShowEvent * ) { if ( m_visibilityUpdateAllowed ) m_isVisible = isVisible(); // !! could possibly start polling now (idea: use someting like ref() and unref() on Mixer instance } void KMixWindow::hideEvent( TQHideEvent * ) { if ( m_visibilityUpdateAllowed ) { m_isVisible = isVisible(); } // !! could possibly stop polling now (idea: use someting like ref() and unref() on Mixer instance // Update: This is a stupid idea, because now the views are responsible for updating. So it will be done in the Views. // But the dock icon is currently no View, so that must be done first. } void KMixWindow::stopVisibilityUpdates() { m_visibilityUpdateAllowed = false; } void KMixWindow::slotHWInfo() { KMessageBox::information( 0, m_hwInfoString, i18n("Mixer Hardware Information") ); } void KMixWindow::showSelectedMixer( int mixer ) { m_wsMixers->raiseWidget( mixer ); } void KMixWindow::configureGlobalShortcuts() { KKeyDialog::configure( m_globalAccel, 0, false ) ; m_globalAccel->writeSettings(); m_globalAccel->updateConnections(); } // KMixIface DCOP interface methods void KMixWindow::setVolume(int percentage) { Mixer *mixerMaster = Mixer::masterCard(); if (mixerMaster) { mixerMaster->setMasterVolume(percentage); } } void KMixWindow::increaseVolume(int percentage) { Mixer *mixerMaster = Mixer::masterCard(); if (mixerMaster) { MixDevice *md = mixerMaster->masterDevice(); if (md) { mixerMaster->increaseVolume(md->num(), percentage); } } } void KMixWindow::decreaseVolume(int percentage) { Mixer *mixerMaster = Mixer::masterCard(); if (mixerMaster) { MixDevice *md = mixerMaster->masterDevice(); if (md) { mixerMaster->decreaseVolume(md->num(), percentage); } } } int KMixWindow::volume() { Mixer *mixerMaster = Mixer::masterCard(); if (mixerMaster) { return mixerMaster->masterVolume(); } return -1; } void KMixWindow::setAbsoluteVolume(long absoluteVolume) { Mixer *mixerMaster = Mixer::masterCard(); if (mixerMaster) { MixDevice *md = mixerMaster->masterDevice(); if (md) { return mixerMaster->setAbsoluteVolume(md->num(), absoluteVolume); } } } long KMixWindow::absoluteVolume() { Mixer *mixerMaster = Mixer::masterCard(); if (mixerMaster) { MixDevice *md = mixerMaster->masterDevice(); if (md) { return mixerMaster->absoluteVolume(md->num()); } } return -1L; } long KMixWindow::absoluteVolumeMin() { Mixer *mixerMaster = Mixer::masterCard(); if (mixerMaster) { MixDevice *md = mixerMaster->masterDevice(); if (md) { return mixerMaster->absoluteVolumeMin(md->num()); } } return -1L; } long KMixWindow::absoluteVolumeMax() { Mixer *mixerMaster = Mixer::masterCard(); if (mixerMaster) { MixDevice *md = mixerMaster->masterDevice(); if (md) { return mixerMaster->absoluteVolumeMax(md->num()); } } return -1L; } void KMixWindow::setMute(bool on) { Mixer *mixerMaster = Mixer::masterCard(); if (mixerMaster) { mixerMaster->setMasterMute(on); } } void KMixWindow::toggleMute() { Mixer *mixerMaster = Mixer::masterCard(); if (mixerMaster) { mixerMaster->toggleMasterMute(); } } bool KMixWindow::mute() { Mixer *mixerMaster = Mixer::masterCard(); if (mixerMaster) { return mixerMaster->masterMute(); } return true; } TQString KMixWindow::mixerName() { Mixer *mixerMaster = Mixer::masterCard(); if (mixerMaster) { return mixerMaster->mixerName(); } return TQString::null; } int KMixWindow::deviceIndex() { Mixer *mixerMaster = Mixer::masterCard(); if (mixerMaster) { return mixerMaster->masterDeviceIndex(); } return -1; } void KMixWindow::setBalance(int balance) { Mixer *mixerMaster = Mixer::masterCard(); if (mixerMaster) { mixerMaster->setBalance(balance); } } #include "kmix.moc"