// qsynthChannelsForm.cpp // /**************************************************************************** Copyright (C) 2003-2007, rncbc aka Rui Nuno Capela. All rights reserved. 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; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qsynthAbout.h" #include "qsynthChannelsForm.h" #include "qsynthChannels.h" #include "qsynthEngine.h" #include "qsynthMainForm.h" #include "qsynthPresetForm.h" #include #include #include #include #include #include #include #include //---------------------------------------------------------------------------- // qsynthChannelsForm -- UI wrapper form. // Constructor. qsynthChannelsForm::qsynthChannelsForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QWidget(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); m_iChannels = 0; m_ppChannels = NULL; // No setup synth references initially (the caller will set them). m_pOptions = NULL; m_pEngine = NULL; m_pSynth = NULL; // Initialize dirty control state. m_iDirtySetup = 0; m_iDirtyCount = 0; // Our activity leds (same of main form :). m_pXpmLedOn = new QPixmap(":/icons/ledon1.png"); m_pXpmLedOff = new QPixmap(":/icons/ledoff1.png"); // Set validators... m_ui.PresetComboBox->setValidator( new QRegExpValidator(QRegExp("[\\w-]+"), m_ui.PresetComboBox)); // Soundfonts list view... QHeaderView *pHeader = m_ui.ChannelsListView->header(); // pHeader->setResizeMode(QHeaderView::Custom); pHeader->setDefaultAlignment(Qt::AlignLeft); // pHeader->setDefaultSectionSize(320); pHeader->setMovable(false); pHeader->setStretchLastSection(true); pHeader->resizeSection(0, 24); // In. m_ui.ChannelsListView->resizeColumnToContents(1); // Ch. m_ui.ChannelsListView->resizeColumnToContents(2); // Bank. m_ui.ChannelsListView->resizeColumnToContents(3); // Prog. pHeader->resizeSection(4, 320); // Name. m_ui.ChannelsListView->resizeColumnToContents(5); // SFID. m_ui.ChannelsListView->resizeColumnToContents(6); // Soundfont. // Initial sort order... m_ui.ChannelsListView->sortItems(1, Qt::AscendingOrder); // UI connections... QObject::connect(m_ui.PresetComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(changePreset(const QString&))); QObject::connect(m_ui.PresetSavePushButton, SIGNAL(clicked()), SLOT(savePreset())); QObject::connect(m_ui.PresetDeletePushButton, SIGNAL(clicked()), SLOT(deletePreset())); QObject::connect(m_ui.ChannelsListView, SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(contextMenuRequested(const QPoint&))); QObject::connect(m_ui.ChannelsListView, SIGNAL(itemActivated(QTreeWidgetItem*,int)), SLOT(itemActivated(QTreeWidgetItem*,int))); } // Destructor. qsynthChannelsForm::~qsynthChannelsForm (void) { // Nullify references. setup(NULL, NULL, false); // Delete pixmaps. delete m_pXpmLedOn; delete m_pXpmLedOff; } // Notify our parent that we're emerging. void qsynthChannelsForm::showEvent ( QShowEvent *pShowEvent ) { qsynthMainForm *pMainForm = qsynthMainForm::getInstance(); if (pMainForm) pMainForm->stabilizeForm(); QWidget::showEvent(pShowEvent); } // Notify our parent that we're closing. void qsynthChannelsForm::hideEvent ( QHideEvent *pHideEvent ) { QWidget::hideEvent(pHideEvent); qsynthMainForm *pMainForm = qsynthMainForm::getInstance(); if (pMainForm) pMainForm->stabilizeForm(); } // Populate (setup) synth settings descriptors. void qsynthChannelsForm::setup ( qsynthOptions *pOptions, qsynthEngine *pEngine, bool bPreset ) { // Set the proper descriptors. m_pOptions = pOptions; m_pEngine = pEngine; m_pSynth = pEngine ? pEngine->pSynth : NULL; // Update caption. QString sTitle = QSYNTH_TITLE ": " + tr("Channels"); if (pEngine) sTitle += " [" + pEngine->name() + "]"; setWindowTitle(sTitle); // Free up current channel list view. if (m_ppChannels) { delete [] m_ppChannels; m_ppChannels = NULL; m_iChannels = 0; } // Allocate a new channel list view... m_ui.ChannelsListView->clear(); if (m_pSynth && m_ppChannels == NULL) { m_iChannels = ::fluid_synth_count_midi_channels(m_pSynth); if (m_iChannels > 0) m_ppChannels = new qsynthChannelsItemPtr [m_iChannels]; if (m_ppChannels) { for (int iChan = 0; iChan < m_iChannels; iChan++) { qsynthChannelsItem *pItem = new qsynthChannelsItem( m_ui.ChannelsListView); if (pItem) { pItem->setIcon(QSYNTH_CHANNELS_IN, *m_pXpmLedOff); pItem->setText(QSYNTH_CHANNELS_CHAN, QString::number(iChan + 1)); } m_ppChannels[iChan] = pItem; } } // Load preset list... m_iDirtySetup++; resetPresets(); m_ui.PresetComboBox->setEditText((m_pEngine->setup())->sDefPreset); m_iDirtySetup--; // Load default preset and update/refresh the whole thing... resetAllChannels(bPreset); } } // Channel item update. void qsynthChannelsForm::updateChannel ( int iChan ) { if (m_pSynth == NULL || m_ppChannels == NULL) return; if (iChan < 0 || iChan >= m_iChannels) return; qsynthChannelsItem *pItem = m_ppChannels[iChan]; fluid_preset_t *pPreset = ::fluid_synth_get_channel_preset(m_pSynth, iChan); if (pPreset) { int iBank = pPreset->get_banknum(pPreset); #ifdef CONFIG_FLUID_BANK_OFFSET iBank += ::fluid_synth_get_bank_offset(m_pSynth, (pPreset->sfont)->id); #endif pItem->setText(QSYNTH_CHANNELS_BANK, QString::number(iBank)); pItem->setText(QSYNTH_CHANNELS_PROG, QString::number(pPreset->get_num(pPreset))); pItem->setText(QSYNTH_CHANNELS_NAME, pPreset->get_name(pPreset)); pItem->setText(QSYNTH_CHANNELS_SFID, QString::number((pPreset->sfont)->id)); pItem->setText(QSYNTH_CHANNELS_SFNAME, QFileInfo((pPreset->sfont)->get_name(pPreset->sfont)).baseName()); // Make this a dirty-operation. m_iDirtyCount++; } else { QString n = "-"; pItem->setText(QSYNTH_CHANNELS_BANK, n); pItem->setText(QSYNTH_CHANNELS_PROG, n); pItem->setText(QSYNTH_CHANNELS_NAME, n); pItem->setText(QSYNTH_CHANNELS_SFID, n); pItem->setText(QSYNTH_CHANNELS_SFNAME, n); } } // All channels update. void qsynthChannelsForm::updateAllChannels (void) { for (int iChan = 0; iChan < m_iChannels; iChan++) updateChannel(iChan); stabilizeForm(); } // All channels reset update. void qsynthChannelsForm::resetAllChannels ( bool bPreset ) { if (m_pEngine == NULL) return; qsynthSetup *pSetup = m_pEngine->setup(); if (pSetup == NULL) return; if (bPreset) changePreset(pSetup->sDefPreset); else updateAllChannels(); } // Update channel activity status LED. void qsynthChannelsForm::setChannelOn ( int iChan, bool bOn ) { if (m_ppChannels == NULL) return; if (iChan < 0 || iChan >= m_iChannels) return; m_ppChannels[iChan]->setIcon(QSYNTH_CHANNELS_IN, (bOn ? *m_pXpmLedOn : *m_pXpmLedOff)); } // Channel view context menu handler. void qsynthChannelsForm::contextMenuRequested ( const QPoint& pos ) { QTreeWidgetItem *pItem = m_ui.ChannelsListView->itemAt(pos); // Build the channel context menu... QMenu menu(this); QAction *pAction; bool bEnabled = (m_pSynth && pItem); pAction = menu.addAction( QIcon(":/icons/edit1.png"), tr("Edit") + "...", this, SLOT(editSelectedChannel())); pAction->setEnabled(bEnabled); menu.addSeparator(); pAction = menu.addAction( tr("Refresh"), this, SLOT(updateAllChannels())); pAction->setEnabled(bEnabled); menu.exec((m_ui.ChannelsListView->viewport())->mapToGlobal(pos)); } // Edit detail dialog. void qsynthChannelsForm::editSelectedChannel (void) { itemActivated(m_ui.ChannelsListView->currentItem(), 0); } // Show detail dialog. void qsynthChannelsForm::itemActivated ( QTreeWidgetItem *pItem, int ) { if (pItem == NULL) return; if (m_ppChannels == NULL) return; if (m_pOptions == NULL || m_pEngine == NULL || m_pSynth == NULL) return; int iChan = (pItem->text(QSYNTH_CHANNELS_CHAN).toInt() - 1); if (iChan < 0 || iChan >= m_iChannels) return; qsynthPresetForm *pPresetForm = new qsynthPresetForm(this); if (pPresetForm) { // The the proper context. pPresetForm->setup(m_pOptions, m_pSynth, iChan); // Show the channel preset dialog... if (pPresetForm->exec()) updateChannel(iChan); // Done. delete pPresetForm; } stabilizeForm(); } // Channels preset naming slots. void qsynthChannelsForm::changePreset ( const QString& sPreset ) { if (m_pOptions == NULL || m_pEngine == NULL || m_pSynth == NULL) return; if (m_iDirtySetup > 0) return; // Force this is pseudo-dirty procedure... m_iDirtyCount++; // Load presets and update/refresh the whole thing. if (m_pOptions->loadPreset(m_pEngine, sPreset)) { updateAllChannels(); // Very special, make this the new default preset. (m_pEngine->setup())->sDefPreset = sPreset; // This is clean now, for sure. m_iDirtyCount = 0; } stabilizeForm(); } void qsynthChannelsForm::savePreset (void) { if (m_pOptions == NULL || m_pEngine == NULL || m_pSynth == NULL) return; QString sPreset = m_ui.PresetComboBox->currentText(); if (sPreset.isEmpty()) return; // Unload presets (from synth). if (m_pOptions->savePreset(m_pEngine, sPreset)) { m_iDirtySetup++; resetPresets(); m_ui.PresetComboBox->setEditText(sPreset); m_iDirtySetup--; // Again special, force this the default preset. (m_pEngine->setup())->sDefPreset = sPreset; // Not dirty anymore, by definition. m_iDirtyCount = 0; } stabilizeForm(); } void qsynthChannelsForm::deletePreset (void) { if (m_pOptions == NULL || m_pEngine == NULL || m_pSynth == NULL) return; QString sPreset = m_ui.PresetComboBox->currentText(); if (sPreset.isEmpty()) return; // Try to prompt user if he/she really wants this... if (QMessageBox::warning(this, QSYNTH_TITLE ": " + tr("Warning"), tr("Delete preset:") + "\n\n" + sPreset + "\n\n" + tr("Are you sure?"), tr("OK"), tr("Cancel")) > 0) return; // Remove current preset item... m_iDirtySetup++; int iItem = m_ui.PresetComboBox->currentIndex(); m_pOptions->deletePreset(m_pEngine, sPreset); resetPresets(); m_ui.PresetComboBox->setCurrentIndex(iItem); m_iDirtySetup--; // Load a new preset... changePreset(m_ui.PresetComboBox->currentText()); } void qsynthChannelsForm::resetPresets (void) { if (m_pEngine == NULL) return; qsynthSetup *pSetup = m_pEngine->setup(); if (pSetup == NULL) return; m_ui.PresetComboBox->clear(); m_ui.PresetComboBox->addItems(pSetup->presets); m_ui.PresetComboBox->addItem(pSetup->sDefPresetName); } // Stabilize current form state. void qsynthChannelsForm::stabilizeForm (void) { if (m_pEngine == NULL) return; qsynthSetup *pSetup = m_pEngine->setup(); if (pSetup == NULL) return; QString sPreset = m_ui.PresetComboBox->currentText(); if (m_pSynth && !sPreset.isEmpty()) { bool bPreset = pSetup->presets.contains(sPreset); m_ui.PresetSavePushButton->setEnabled(m_iDirtyCount > 0 || (!bPreset && sPreset != pSetup->sDefPresetName)); m_ui.PresetDeletePushButton->setEnabled(bPreset); } else { m_ui.PresetSavePushButton->setEnabled(false); m_ui.PresetDeletePushButton->setEnabled(false); } } // end of qsynthChannelsForm.cpp