--- qsampler/trunk/src/qsamplerChannelStrip.cpp 2008/02/14 22:31:26 1691 +++ qsampler/trunk/src/qsamplerChannelStrip.cpp 2019/07/01 10:53:41 3520 @@ -1,8 +1,8 @@ // qsamplerChannelStrip.cpp // /**************************************************************************** - Copyright (C) 2004-2007, rncbc aka Rui Nuno Capela. All rights reserved. - Copyright (C) 2007, 2008 Christian Schoenebeck + Copyright (C) 2004-2019, rncbc aka Rui Nuno Capela. All rights reserved. + Copyright (C) 2007, 2008, 2014 Christian Schoenebeck This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -29,10 +29,14 @@ #include #include +#include +#include #include +#include -#define MIDI_OFF_COLOR Qt::darkGreen -#define MIDI_ON_COLOR Qt::green +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) +#include +#endif // Channel status/usage usage limit control. #define QSAMPLER_ERROR_LIMIT 3 @@ -57,6 +61,11 @@ // QSampler::ChannelStrip -- Channel strip form implementation. // +// MIDI activity pixmap common resources. +int ChannelStrip::g_iMidiActivityRefCount = 0; +QPixmap *ChannelStrip::g_pMidiActivityLedOn = NULL; +QPixmap *ChannelStrip::g_pMidiActivityLedOff = NULL; + // Channel strip activation/selection. ChannelStrip *ChannelStrip::g_pSelectedStrip = NULL; @@ -69,6 +78,26 @@ m_pChannel = NULL; m_iDirtyChange = 0; m_iErrorCount = 0; + m_instrumentListPopupMenu = NULL; + + if (++g_iMidiActivityRefCount == 1) { + g_pMidiActivityLedOn = new QPixmap(":/images/ledon1.png"); + g_pMidiActivityLedOff = new QPixmap(":/images/ledoff1.png"); + } + + m_ui.MidiActivityLabel->setPixmap(*g_pMidiActivityLedOff); + +#ifndef CONFIG_EVENT_CHANNEL_MIDI + m_ui.MidiActivityLabel->setToolTip("MIDI activity (disabled)"); +#endif + + m_pMidiActivityTimer = new QTimer(this); + m_pMidiActivityTimer->setSingleShot(true); + + QObject::connect(m_pMidiActivityTimer, + SIGNAL(timeout()), + SLOT(midiActivityLedOff()) + ); // Try to restore normal window positioning. adjustSize(); @@ -82,34 +111,19 @@ QObject::connect(m_ui.ChannelSoloPushButton, SIGNAL(toggled(bool)), SLOT(channelSolo(bool))); - QObject::connect(m_ui.VolumeSlider, + QObject::connect(m_ui.ChannelVolumeSlider, SIGNAL(valueChanged(int)), SLOT(volumeChanged(int))); - QObject::connect(m_ui.VolumeSpinBox, + QObject::connect(m_ui.ChannelVolumeSpinBox, SIGNAL(valueChanged(int)), SLOT(volumeChanged(int))); QObject::connect(m_ui.ChannelEditPushButton, SIGNAL(clicked()), SLOT(channelEdit())); - QObject::connect(m_ui.FxPushButton, + QObject::connect(m_ui.ChannelFxPushButton, SIGNAL(clicked()), SLOT(channelFxEdit())); - pMidiActivityTimer = new QTimer(this); - pMidiActivityTimer->setSingleShot(true); - QObject::connect( - pMidiActivityTimer, SIGNAL(timeout()), - this, SLOT(midiDataCeased()) - ); - -#if CONFIG_LSCP_CHANNEL_MIDI - m_ui.MidiActivityLabel->setPalette(MIDI_OFF_COLOR); - m_ui.MidiActivityLabel->setAutoFillBackground(true); -#else - m_ui.MidiActivityLabel->setText("X"); - m_ui.MidiActivityLabel->setTooltip("MIDI Activity Disabled"); -#endif - setSelected(false); } @@ -122,6 +136,15 @@ if (m_pChannel) delete m_pChannel; m_pChannel = NULL; + + if (--g_iMidiActivityRefCount == 0) { + if (g_pMidiActivityLedOn) + delete g_pMidiActivityLedOn; + g_pMidiActivityLedOn = NULL; + if (g_pMidiActivityLedOff) + delete g_pMidiActivityLedOff; + g_pMidiActivityLedOff = NULL; + } } @@ -140,7 +163,8 @@ while (iter.hasNext()) { const QString& sFilename = iter.next().toLocalFile(); if (!sFilename.isEmpty()) { - bAccept = Channel::isInstrumentFile(sFilename); + // bAccept = Channel::isDlsInstrumentFile(sFilename); + bAccept = QFileInfo(sFilename).exists(); break; } } @@ -213,11 +237,12 @@ return m_ui.EngineNameTextLabel->font(); } + void ChannelStrip::setDisplayFont ( const QFont & font ) { m_ui.EngineNameTextLabel->setFont(font); m_ui.MidiPortChannelTextLabel->setFont(font); - m_ui.InstrumentNameTextLabel->setFont(font); + m_ui.InstrumentNamePushButton->setFont(font); m_ui.InstrumentStatusTextLabel->setFont(font); } @@ -227,17 +252,19 @@ { QPalette pal; pal.setColor(QPalette::Foreground, Qt::yellow); + pal.setColor(QPalette::ButtonText, Qt::yellow); m_ui.EngineNameTextLabel->setPalette(pal); m_ui.MidiPortChannelTextLabel->setPalette(pal); pal.setColor(QPalette::Foreground, Qt::green); + pal.setColor(QPalette::ButtonText, Qt::green); if (bDisplayEffect) { - QPixmap pm(":/icons/displaybg1.png"); + QPixmap pm(":/images/displaybg1.png"); pal.setBrush(QPalette::Background, QBrush(pm)); } else { pal.setColor(QPalette::Background, Qt::black); } m_ui.ChannelInfoFrame->setPalette(pal); - m_ui.InstrumentNameTextLabel->setPalette(pal); + m_ui.InstrumentNamePushButton->setPalette(pal); m_ui.StreamVoiceCountTextLabel->setPalette(pal); } @@ -246,8 +273,8 @@ void ChannelStrip::setMaxVolume ( int iMaxVolume ) { m_iDirtyChange++; - m_ui.VolumeSlider->setRange(0, iMaxVolume); - m_ui.VolumeSpinBox->setRange(0, iMaxVolume); + m_ui.ChannelVolumeSlider->setRange(0, iMaxVolume); + m_ui.ChannelVolumeSpinBox->setRange(0, iMaxVolume); m_iDirtyChange--; } @@ -259,7 +286,7 @@ return false; // Invoke the channel setup dialog. - bool bResult = m_pChannel->channelSetup(this); + const bool bResult = m_pChannel->channelSetup(this); // Notify that this channel has changed. if (bResult) emit channelChanged(this); @@ -275,7 +302,7 @@ return false; // Invoke the channel mute method. - bool bResult = m_pChannel->setChannelMute(bMute); + const bool bResult = m_pChannel->setChannelMute(bMute); // Notify that this channel has changed. if (bResult) emit channelChanged(this); @@ -291,7 +318,7 @@ return false; // Invoke the channel solo method. - bool bResult = m_pChannel->setChannelSolo(bSolo); + const bool bResult = m_pChannel->setChannelSolo(bSolo); // Notify that this channel has changed. if (bResult) emit channelChanged(this); @@ -337,6 +364,7 @@ return bResult; } + // Channel reset slot. bool ChannelStrip::channelReset (void) { @@ -344,7 +372,7 @@ return false; // Invoke the channel reset method. - bool bResult = m_pChannel->channelReset(); + const bool bResult = m_pChannel->channelReset(); // Notify that this channel has changed. if (bResult) emit channelChanged(this); @@ -366,21 +394,70 @@ // Instrument name... if (m_pChannel->instrumentName().isEmpty()) { if (m_pChannel->instrumentStatus() >= 0) { - m_ui.InstrumentNameTextLabel->setText( + m_ui.InstrumentNamePushButton->setText( ' ' + Channel::loadingInstrument()); } else { - m_ui.InstrumentNameTextLabel->setText( + m_ui.InstrumentNamePushButton->setText( ' ' + Channel::noInstrumentName()); } } else { - m_ui.InstrumentNameTextLabel->setText( + m_ui.InstrumentNamePushButton->setText( ' ' + m_pChannel->instrumentName()); } + + bool bShowInstrumentPopup = false; + + // Instrument list popup (for fast switching among sounds of the same file) + if (!m_pChannel->instrumentFile().isEmpty()) { + const QStringList instruments + = Channel::getInstrumentList(m_pChannel->instrumentFile(), true); + if (!instruments.isEmpty()) { + bShowInstrumentPopup = true; + if (!m_instrumentListPopupMenu) { + m_instrumentListPopupMenu + = new QMenu(m_ui.InstrumentNamePushButton); + m_instrumentListPopupMenu->setTitle(tr("Instruments")); + // for cosmetical reasons, should have at least + // the width of the instrument name label... + m_instrumentListPopupMenu->setMinimumWidth(120); + m_ui.InstrumentNamePushButton->setMenu(m_instrumentListPopupMenu); + QObject::connect(m_instrumentListPopupMenu, + SIGNAL(triggered(QAction*)), + SLOT(instrumentListPopupItemClicked(QAction *))); + } else { + m_instrumentListPopupMenu->clear(); + } + QAction *action; + for (int i = 0; i < instruments.size(); ++i) { + action = m_instrumentListPopupMenu->addAction(instruments.at(i)); + action->setData(i); + action->setCheckable(true); + action->setChecked(i == m_pChannel->instrumentNr()); + } + } + } + + if (!bShowInstrumentPopup && m_instrumentListPopupMenu) { + delete m_instrumentListPopupMenu; + m_instrumentListPopupMenu = NULL; + } return true; } +void ChannelStrip::instrumentListPopupItemClicked ( QAction *action ) +{ + if (!action) return; + + QVariant data = action->data(); + if (data.isValid() && !m_pChannel->instrumentFile().isEmpty()) { + m_pChannel->loadInstrument(m_pChannel->instrumentFile(), data.toInt()); + emit channelChanged(this); + } +} + + // Do the dirty volume change. bool ChannelStrip::updateChannelVolume (void) { @@ -395,8 +472,8 @@ // Flag it here, to avoid infinite recursion. m_iDirtyChange++; - m_ui.VolumeSlider->setValue(iVolume); - m_ui.VolumeSpinBox->setValue(iVolume); + m_ui.ChannelVolumeSlider->setValue(iVolume); + m_ui.ChannelVolumeSpinBox->setValue(iVolume); m_iDirtyChange--; return true; @@ -414,12 +491,12 @@ return true; // Update strip caption. - QString sText = m_pChannel->channelName(); + const QString& sText = m_pChannel->channelName(); setWindowTitle(sText); m_ui.ChannelSetupPushButton->setText('&' + sText); // Check if we're up and connected. - MainForm* pMainForm = MainForm::getInstance(); + MainForm *pMainForm = MainForm::getInstance(); if (pMainForm->client() == NULL) return false; @@ -451,7 +528,7 @@ const QColor& rgbFore = pal.color(QPalette::Foreground); // Instrument status... - int iInstrumentStatus = m_pChannel->instrumentStatus(); + const int iInstrumentStatus = m_pChannel->instrumentStatus(); if (iInstrumentStatus < 0) { pal.setColor(QPalette::Foreground, Qt::red); m_ui.InstrumentStatusTextLabel->setPalette(pal); @@ -460,6 +537,7 @@ m_iErrorCount++; return false; } + // All seems normal... pal.setColor(QPalette::Foreground, iInstrumentStatus < 100 ? Qt::yellow : Qt::green); @@ -470,14 +548,17 @@ #ifdef CONFIG_MUTE_SOLO // Mute/Solo button state coloring... - bool bMute = m_pChannel->channelMute(); + const bool bMute = m_pChannel->channelMute(); const QColor& rgbButton = pal.color(QPalette::Button); + const QColor& rgbButtonText = pal.color(QPalette::ButtonText); pal.setColor(QPalette::Foreground, rgbFore); pal.setColor(QPalette::Button, bMute ? Qt::yellow : rgbButton); + pal.setColor(QPalette::ButtonText, bMute ? Qt::darkYellow : rgbButtonText); m_ui.ChannelMutePushButton->setPalette(pal); m_ui.ChannelMutePushButton->setDown(bMute); - bool bSolo = m_pChannel->channelSolo(); + const bool bSolo = m_pChannel->channelSolo(); pal.setColor(QPalette::Button, bSolo ? Qt::cyan : rgbButton); + pal.setColor(QPalette::ButtonText, bSolo ? Qt::darkCyan : rgbButtonText); m_ui.ChannelSoloPushButton->setPalette(pal); m_ui.ChannelSoloPushButton->setDown(bSolo); #else @@ -506,16 +587,16 @@ return false; // Get current channel voice count. - int iVoiceCount = ::lscp_get_channel_voice_count( + const int iVoiceCount = ::lscp_get_channel_voice_count( pMainForm->client(), m_pChannel->channelID()); -// Get current stream count. - int iStreamCount = ::lscp_get_channel_stream_count( + // Get current stream count. + const int iStreamCount = ::lscp_get_channel_stream_count( pMainForm->client(), m_pChannel->channelID()); // Get current channel buffer fill usage. // As benno has suggested this is the percentage usage // of the least filled buffer stream... - int iStreamUsage = ::lscp_get_channel_stream_usage( - pMainForm->client(), m_pChannel->channelID());; + const int iStreamUsage = ::lscp_get_channel_stream_usage( + pMainForm->client(), m_pChannel->channelID()); // Update the GUI elements... m_ui.StreamUsageProgressBar->setValue(iStreamUsage); @@ -549,10 +630,6 @@ } } -void ChannelStrip::midiArrived() { - m_ui.MidiActivityLabel->setPalette(MIDI_ON_COLOR); - pMidiActivityTimer->start(50); -} // Context menu event handler. void ChannelStrip::contextMenuEvent( QContextMenuEvent *pEvent ) @@ -564,10 +641,20 @@ m_pChannel->contextMenuEvent(pEvent); } -void ChannelStrip::midiDataCeased() { - m_ui.MidiActivityLabel->setPalette(MIDI_OFF_COLOR); + +void ChannelStrip::midiActivityLedOn (void) +{ + m_ui.MidiActivityLabel->setPixmap(*g_pMidiActivityLedOn); + m_pMidiActivityTimer->start(100); } + +void ChannelStrip::midiActivityLedOff (void) +{ + m_ui.MidiActivityLabel->setPixmap(*g_pMidiActivityLedOff); +} + + // Error count hackish accessors. void ChannelStrip::resetErrorCount (void) { @@ -592,10 +679,13 @@ QPalette pal; if (bSelected) { const QColor& color = pal.midlight().color(); - pal.setColor(QPalette::Background, color.dark(150)); - pal.setColor(QPalette::Foreground, color.light(150)); + pal.setColor(QPalette::Background, color.darker(150)); + pal.setColor(QPalette::Foreground, color.lighter(150)); } - QWidget::setPalette(pal); + + QWidget *pParentWidget = QWidget::parentWidget(); + if (pParentWidget) + pParentWidget->setPalette(pal); }