/* * FxMixerView.cpp - effect-mixer-view for LMMS * * Copyright (c) 2008-2009 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU 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 * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program (see COPYING); if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. * */ #include #include #include #include #include #include #include #include #include #include "FxMixerView.h" #include "fader.h" #include "EffectRackView.h" #include "engine.h" #include "embed.h" #include "MainWindow.h" #include "lcd_spinbox.h" #include "gui_templates.h" #include "tooltip.h" #include "pixmap_button.h" class FxLine : public QWidget { public: FxLine( QWidget * _parent, FxMixerView * _mv, QString & _name ) : QWidget( _parent ), m_mv( _mv ), m_name( _name ) { setFixedSize( 32, 232 ); setAttribute( Qt::WA_OpaquePaintEvent, true ); setCursor( QCursor( embed::getIconPixmap( "hand" ), 0, 0 ) ); } virtual void paintEvent( QPaintEvent * ) { QPainter p( this ); p.fillRect( rect(), QColor( 72, 76, 88 ) ); p.setPen( QColor( 40, 42, 48 ) ); p.drawRect( 0, 0, width()-2, height()-2 ); p.setPen( QColor( 108, 114, 132 ) ); p.drawRect( 1, 1, width()-2, height()-2 ); p.setPen( QColor( 20, 24, 32 ) ); p.drawRect( 0, 0, width()-1, height()-1 ); p.rotate( -90 ); p.setPen( m_mv->currentFxLine() == this ? QColor( 0, 255, 0 ) : Qt::white ); p.setFont( pointSizeF( font(), 7.5f ) ); p.drawText( -90, 20, m_name ); } virtual void mousePressEvent( QMouseEvent * ) { m_mv->setCurrentFxLine( this ); } virtual void mouseDoubleClickEvent( QMouseEvent * ) { bool ok; QString new_name = QInputDialog::getText( this, FxMixerView::tr( "Rename FX channel" ), FxMixerView::tr( "Enter the new name for this " "FX channel" ), QLineEdit::Normal, m_name, &ok ); if( ok && !new_name.isEmpty() ) { m_name = new_name; update(); } } private: FxMixerView * m_mv; QString & m_name; } ; FxMixerView::FxMixerView() : QWidget(), ModelView( NULL, this ), SerializingObjectHook() { FxMixer * m = engine::fxMixer(); m->setHook( this ); QPalette pal = palette(); pal.setColor( QPalette::Background, QColor( 72, 76, 88 ) ); setPalette( pal ); setAutoFillBackground( true ); setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum ); setWindowTitle( tr( "FX-Mixer" ) ); setWindowIcon( embed::getIconPixmap( "fx_mixer" ) ); m_fxLineBanks = new QStackedLayout; m_fxLineBanks->setSpacing( 0 ); m_fxLineBanks->setMargin( 1 ); m_fxRacksLayout = new QStackedLayout; m_fxRacksLayout->setSpacing( 0 ); m_fxRacksLayout->setMargin( 0 ); // main-layout QHBoxLayout * ml = new QHBoxLayout; ml->setMargin( 0 ); ml->setSpacing( 0 ); ml->addSpacing( 6 ); QHBoxLayout * banks[NumFxChannels/16]; for( int i = 0; i < NumFxChannels/16; ++i ) { QWidget * w = new QWidget( this ); banks[i] = new QHBoxLayout( w ); banks[i]->setMargin( 5 ); banks[i]->setSpacing( 1 ); m_fxLineBanks->addWidget( w ); } for( int i = 0; i < NumFxChannels+1; ++i ) { FxChannelView * cv = &m_fxChannelViews[i]; if( i == 0 ) { cv->m_fxLine = new FxLine( NULL, this, m->m_fxChannels[i]->m_name ); ml->addWidget( cv->m_fxLine ); ml->addSpacing( 10 ); } else { const int bank = (i-1) / 16; cv->m_fxLine = new FxLine( NULL, this, m->m_fxChannels[i]->m_name ); banks[bank]->addWidget( cv->m_fxLine ); } lcdSpinBox * l = new lcdSpinBox( 2, cv->m_fxLine ); l->model()->setRange( i, i ); l->model()->setValue( i ); l->move( 2, 4 ); l->setMarginWidth( 1 ); cv->m_fader = new fader( &m->m_fxChannels[i]->m_volumeModel, tr( "FX Fader %1" ).arg( i ), cv->m_fxLine ); cv->m_fader->move( 15-cv->m_fader->width()/2, cv->m_fxLine->height()- cv->m_fader->height()-5 ); cv->m_muteBtn = new pixmapButton( cv->m_fxLine, tr( "Mute" ) ); cv->m_muteBtn->setModel( &m->m_fxChannels[i]->m_muteModel ); cv->m_muteBtn->setActiveGraphic( embed::getIconPixmap( "led_off" ) ); cv->m_muteBtn->setInactiveGraphic( embed::getIconPixmap( "led_green" ) ); cv->m_muteBtn->setCheckable( true ); cv->m_muteBtn->move( 9, cv->m_fader->y()-16); toolTip::add( cv->m_muteBtn, tr( "Mute this FX channel" ) ); cv->m_rackView = new EffectRackView( &m->m_fxChannels[i]->m_fxChain, this ); m_fxRacksLayout->addWidget( cv->m_rackView ); if( i == 0 ) { QVBoxLayout * l = new QVBoxLayout; l->addSpacing( 10 ); QButtonGroup * g = new QButtonGroup( this ); m_bankButtons = g; g->setExclusive( true ); for( int j = 0; j < 4; ++j ) { QToolButton * btn = new QToolButton; btn->setText( QString( 'A'+j ) ); btn->setCheckable( true ); btn->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Expanding ); l->addWidget( btn ); g->addButton( btn, j ); btn->setChecked( j == 0); } l->addSpacing( 10 ); ml->addLayout( l ); connect( g, SIGNAL( buttonClicked( int ) ), m_fxLineBanks, SLOT( setCurrentIndex( int ) ) ); } } ml->addLayout( m_fxLineBanks ); ml->addLayout( m_fxRacksLayout ); setLayout( ml ); updateGeometry(); m_fxLineBanks->setCurrentIndex( 0 ); setCurrentFxLine( m_fxChannelViews[0].m_fxLine ); // timer for updating faders connect( engine::mainWindow(), SIGNAL( periodicUpdate() ), this, SLOT( updateFaders() ) ); // add ourself to workspace QMdiSubWindow * subWin = engine::mainWindow()->workspace()->addSubWindow( this ); Qt::WindowFlags flags = subWin->windowFlags(); flags |= Qt::MSWindowsFixedSizeDialogHint; flags &= ~Qt::WindowMaximizeButtonHint; subWin->setWindowFlags( flags ); subWin->layout()->setSizeConstraint(QLayout::SetFixedSize); parentWidget()->setAttribute( Qt::WA_DeleteOnClose, false ); parentWidget()->move( 5, 310 ); // we want to receive dataChanged-signals in order to update setModel( m ); } FxMixerView::~FxMixerView() { } void FxMixerView::saveSettings( QDomDocument & _doc, QDomElement & _this ) { MainWindow::saveWidgetState( this, _this ); } void FxMixerView::loadSettings( const QDomElement & _this ) { MainWindow::restoreWidgetState( this, _this ); } void FxMixerView::setCurrentFxLine( FxLine * _line ) { m_currentFxLine = _line; for( int i = 0; i < NumFxChannels+1; ++i ) { if( m_fxChannelViews[i].m_fxLine == _line ) { m_fxRacksLayout->setCurrentIndex( i ); } m_fxChannelViews[i].m_fxLine->update(); } } void FxMixerView::setCurrentFxLine( int _line ) { if ( _line >= 0 && _line < NumFxChannels+1 ) { setCurrentFxLine( m_fxChannelViews[_line].m_fxLine ); m_bankButtons->button( (_line-1) / 16 )->click(); } } void FxMixerView::clear() { for( int i = 0; i <= NumFxChannels; ++i ) { m_fxChannelViews[i].m_rackView->clearViews(); } } void FxMixerView::updateFaders() { FxMixer * m = engine::fxMixer(); for( int i = 0; i < NumFxChannels+1; ++i ) { const float opl = m_fxChannelViews[i].m_fader->getPeak_L(); const float opr = m_fxChannelViews[i].m_fader->getPeak_R(); const float fall_off = 1.2; if( m->m_fxChannels[i]->m_peakLeft > opl ) { m_fxChannelViews[i].m_fader->setPeak_L( m->m_fxChannels[i]->m_peakLeft ); } else { m_fxChannelViews[i].m_fader->setPeak_L( opl/fall_off ); } if( m->m_fxChannels[i]->m_peakRight > opr ) { m_fxChannelViews[i].m_fader->setPeak_R( m->m_fxChannels[i]->m_peakRight ); } else { m_fxChannelViews[i].m_fader->setPeak_R( opr/fall_off ); } } } #include "moc_FxMixerView.cxx"