--- qsampler/trunk/src/qsamplerMainForm.cpp 2007/10/28 23:30:36 1461
+++ qsampler/trunk/src/qsamplerMainForm.cpp 2009/02/19 11:44:57 1840
@@ -1,24 +1,28 @@
-#include "qsamplerMainForm.h"
+// qsamplerMainForm.cpp
+//
+/****************************************************************************
+ Copyright (C) 2004-2009, rncbc aka Rui Nuno Capela. All rights reserved.
+ Copyright (C) 2007, 2008 Christian Schoenebeck
+
+ 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
-#include
-#include
-#include
-#include
-//#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
+*****************************************************************************/
#include "qsamplerAbout.h"
+#include "qsamplerMainForm.h"
+
#include "qsamplerOptions.h"
#include "qsamplerChannel.h"
#include "qsamplerMessages.h"
@@ -29,6 +33,29 @@
#include "qsamplerInstrumentListForm.h"
#include "qsamplerDeviceForm.h"
#include "qsamplerOptionsForm.h"
+#include "qsamplerDeviceStatusForm.h"
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
#ifdef HAVE_SIGNAL_H
#include
@@ -51,6 +78,15 @@
}
#endif
+
+// All winsock apps needs this.
+#if defined(WIN32)
+static WSADATA _wsaData;
+#endif
+
+
+namespace QSampler {
+
// Timer constant stuff.
#define QSAMPLER_TIMER_MSECS 200
@@ -61,79 +97,69 @@
#define QSAMPLER_STATUS_SESSION 3 // Current session modification state.
-// All winsock apps needs this.
-#if defined(WIN32)
-static WSADATA _wsaData;
-#endif
-
-
//-------------------------------------------------------------------------
-// qsamplerCustomEvent -- specialty for callback comunication.
+// CustomEvent -- specialty for callback comunication.
#define QSAMPLER_CUSTOM_EVENT QEvent::Type(QEvent::User + 0)
-class qsamplerCustomEvent : public QEvent
+class CustomEvent : public QEvent
{
public:
- // Constructor.
- qsamplerCustomEvent(lscp_event_t event, const char *pchData, int cchData)
- : QEvent(QSAMPLER_CUSTOM_EVENT)
- {
- m_event = event;
- m_data.setLatin1(pchData, cchData);
- }
-
- // Accessors.
- lscp_event_t event() { return m_event; }
- QString& data() { return m_data; }
+ // Constructor.
+ CustomEvent(lscp_event_t event, const char *pchData, int cchData)
+ : QEvent(QSAMPLER_CUSTOM_EVENT)
+ {
+ m_event = event;
+ m_data = QString::fromUtf8(pchData, cchData);
+ }
+
+ // Accessors.
+ lscp_event_t event() { return m_event; }
+ QString& data() { return m_data; }
private:
- // The proper event type.
- lscp_event_t m_event;
- // The event data as a string.
- QString m_data;
+ // The proper event type.
+ lscp_event_t m_event;
+ // The event data as a string.
+ QString m_data;
};
//-------------------------------------------------------------------------
// qsamplerMainForm -- Main window form implementation.
-namespace QSampler {
-
// Kind of singleton reference.
MainForm* MainForm::g_pMainForm = NULL;
-MainForm::MainForm(QWidget* parent) : QMainWindow(parent) {
- ui.setupUi(this);
-
- fileToolbar = addToolBar(tr("File"));
- editToolbar = addToolBar(tr("Edit"));
- channelsToolbar = addToolBar(tr("Channels"));
+MainForm::MainForm ( QWidget *pParent )
+ : QMainWindow(pParent)
+{
+ m_ui.setupUi(this);
// Pseudo-singleton reference setup.
g_pMainForm = this;
- // Initialize some pointer references.
- m_pOptions = NULL;
+ // Initialize some pointer references.
+ m_pOptions = NULL;
- // All child forms are to be created later, not earlier than setup.
- m_pMessages = NULL;
- m_pInstrumentListForm = NULL;
- m_pDeviceForm = NULL;
+ // All child forms are to be created later, not earlier than setup.
+ m_pMessages = NULL;
+ m_pInstrumentListForm = NULL;
+ m_pDeviceForm = NULL;
- // We'll start clean.
- m_iUntitled = 0;
- m_iDirtyCount = 0;
+ // We'll start clean.
+ m_iUntitled = 0;
+ m_iDirtyCount = 0;
- m_pServer = NULL;
- m_pClient = NULL;
+ m_pServer = NULL;
+ m_pClient = NULL;
- m_iStartDelay = 0;
- m_iTimerDelay = 0;
+ m_iStartDelay = 0;
+ m_iTimerDelay = 0;
- m_iTimerSlot = 0;
+ m_iTimerSlot = 0;
#ifdef HAVE_SIGNAL_H
// Set to ignore any fatal "Broken pipe" signals.
@@ -141,219 +167,306 @@
#endif
#ifdef CONFIG_VOLUME
- // Make some extras into the toolbar...
+ // Make some extras into the toolbar...
const QString& sVolumeText = tr("Master volume");
m_iVolumeChanging = 0;
// Volume slider...
- channelsToolbar->addSeparator();
- m_pVolumeSlider = new QSlider(Qt::Horizontal, channelsToolbar);
- m_pVolumeSlider->setTickmarks(QSlider::Below);
+ m_ui.channelsToolbar->addSeparator();
+ m_pVolumeSlider = new QSlider(Qt::Horizontal, m_ui.channelsToolbar);
+ m_pVolumeSlider->setTickPosition(QSlider::TicksBothSides);
m_pVolumeSlider->setTickInterval(10);
m_pVolumeSlider->setPageStep(10);
- m_pVolumeSlider->setRange(0, 100);
- m_pVolumeSlider->setMaximumHeight(22);
+ m_pVolumeSlider->setSingleStep(10);
+ m_pVolumeSlider->setMinimum(0);
+ m_pVolumeSlider->setMaximum(100);
+ m_pVolumeSlider->setMaximumHeight(26);
m_pVolumeSlider->setMinimumWidth(160);
- QToolTip::add(m_pVolumeSlider, sVolumeText);
+ m_pVolumeSlider->setToolTip(sVolumeText);
QObject::connect(m_pVolumeSlider,
SIGNAL(valueChanged(int)),
SLOT(volumeChanged(int)));
- //channelsToolbar->setHorizontallyStretchable(true);
- //channelsToolbar->setStretchableWidget(m_pVolumeSlider);
- channelsToolbar->addWidget(m_pVolumeSlider);
+ //m_ui.channelsToolbar->setHorizontallyStretchable(true);
+ //m_ui.channelsToolbar->setStretchableWidget(m_pVolumeSlider);
+ m_ui.channelsToolbar->addWidget(m_pVolumeSlider);
// Volume spin-box
- channelsToolbar->addSeparator();
- m_pVolumeSpinBox = new QSpinBox(channelsToolbar);
+ m_ui.channelsToolbar->addSeparator();
+ m_pVolumeSpinBox = new QSpinBox(m_ui.channelsToolbar);
+ m_pVolumeSpinBox->setMaximumHeight(24);
m_pVolumeSpinBox->setSuffix(" %");
- m_pVolumeSpinBox->setRange(0, 100);
- QToolTip::add(m_pVolumeSpinBox, sVolumeText);
+ m_pVolumeSpinBox->setMinimum(0);
+ m_pVolumeSpinBox->setMaximum(100);
+ m_pVolumeSpinBox->setToolTip(sVolumeText);
QObject::connect(m_pVolumeSpinBox,
SIGNAL(valueChanged(int)),
SLOT(volumeChanged(int)));
+ m_ui.channelsToolbar->addWidget(m_pVolumeSpinBox);
#endif
- // Make it an MDI workspace.
- m_pWorkspace = new QWorkspace(this);
- m_pWorkspace->setScrollBarsEnabled(true);
+ // Make it an MDI workspace.
+ m_pWorkspace = new QWorkspace(this);
+ m_pWorkspace->setScrollBarsEnabled(true);
// Set the activation connection.
QObject::connect(m_pWorkspace,
SIGNAL(windowActivated(QWidget *)),
- SLOT(stabilizeForm()));
- // Make it shine :-)
- setCentralWidget(m_pWorkspace);
-
- // Create some statusbar labels...
- QLabel *pLabel;
- // Client status.
- pLabel = new QLabel(tr("Connected"), this);
- pLabel->setAlignment(Qt::AlignLeft);
- pLabel->setMinimumSize(pLabel->sizeHint());
- m_statusItem[QSAMPLER_STATUS_CLIENT] = pLabel;
- statusBar()->addWidget(pLabel);
- // Server address.
- pLabel = new QLabel(this);
- pLabel->setAlignment(Qt::AlignLeft);
- m_statusItem[QSAMPLER_STATUS_SERVER] = pLabel;
- statusBar()->addWidget(pLabel, 1);
- // Channel title.
- pLabel = new QLabel(this);
- pLabel->setAlignment(Qt::AlignLeft);
- m_statusItem[QSAMPLER_STATUS_CHANNEL] = pLabel;
- statusBar()->addWidget(pLabel, 2);
- // Session modification status.
- pLabel = new QLabel(tr("MOD"), this);
- pLabel->setAlignment(Qt::AlignHCenter);
- pLabel->setMinimumSize(pLabel->sizeHint());
- m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;
- statusBar()->addWidget(pLabel);
-
- // Create the recent files sub-menu.
- m_pRecentFilesMenu = new Q3PopupMenu(this);
- ui.fileMenu->insertSeparator(4);
- ui.fileMenu->insertItem(tr("Recent &Files"), m_pRecentFilesMenu, 0, 5);
+ SLOT(activateStrip(QWidget *)));
+ // Make it shine :-)
+ setCentralWidget(m_pWorkspace);
+
+ // Create some statusbar labels...
+ QLabel *pLabel;
+ // Client status.
+ pLabel = new QLabel(tr("Connected"), this);
+ pLabel->setAlignment(Qt::AlignLeft);
+ pLabel->setMinimumSize(pLabel->sizeHint());
+ m_statusItem[QSAMPLER_STATUS_CLIENT] = pLabel;
+ statusBar()->addWidget(pLabel);
+ // Server address.
+ pLabel = new QLabel(this);
+ pLabel->setAlignment(Qt::AlignLeft);
+ m_statusItem[QSAMPLER_STATUS_SERVER] = pLabel;
+ statusBar()->addWidget(pLabel, 1);
+ // Channel title.
+ pLabel = new QLabel(this);
+ pLabel->setAlignment(Qt::AlignLeft);
+ m_statusItem[QSAMPLER_STATUS_CHANNEL] = pLabel;
+ statusBar()->addWidget(pLabel, 2);
+ // Session modification status.
+ pLabel = new QLabel(tr("MOD"), this);
+ pLabel->setAlignment(Qt::AlignHCenter);
+ pLabel->setMinimumSize(pLabel->sizeHint());
+ m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;
+ statusBar()->addWidget(pLabel);
#if defined(WIN32)
- WSAStartup(MAKEWORD(1, 1), &_wsaData);
+ WSAStartup(MAKEWORD(1, 1), &_wsaData);
#endif
+
+ // Some actions surely need those
+ // shortcuts firmly attached...
+ addAction(m_ui.viewMenubarAction);
+ addAction(m_ui.viewToolbarAction);
+
+ QObject::connect(m_ui.fileNewAction,
+ SIGNAL(triggered()),
+ SLOT(fileNew()));
+ QObject::connect(m_ui.fileOpenAction,
+ SIGNAL(triggered()),
+ SLOT(fileOpen()));
+ QObject::connect(m_ui.fileSaveAction,
+ SIGNAL(triggered()),
+ SLOT(fileSave()));
+ QObject::connect(m_ui.fileSaveAsAction,
+ SIGNAL(triggered()),
+ SLOT(fileSaveAs()));
+ QObject::connect(m_ui.fileResetAction,
+ SIGNAL(triggered()),
+ SLOT(fileReset()));
+ QObject::connect(m_ui.fileRestartAction,
+ SIGNAL(triggered()),
+ SLOT(fileRestart()));
+ QObject::connect(m_ui.fileExitAction,
+ SIGNAL(triggered()),
+ SLOT(fileExit()));
+ QObject::connect(m_ui.editAddChannelAction,
+ SIGNAL(triggered()),
+ SLOT(editAddChannel()));
+ QObject::connect(m_ui.editRemoveChannelAction,
+ SIGNAL(triggered()),
+ SLOT(editRemoveChannel()));
+ QObject::connect(m_ui.editSetupChannelAction,
+ SIGNAL(triggered()),
+ SLOT(editSetupChannel()));
+ QObject::connect(m_ui.editEditChannelAction,
+ SIGNAL(triggered()),
+ SLOT(editEditChannel()));
+ QObject::connect(m_ui.editResetChannelAction,
+ SIGNAL(triggered()),
+ SLOT(editResetChannel()));
+ QObject::connect(m_ui.editResetAllChannelsAction,
+ SIGNAL(triggered()),
+ SLOT(editResetAllChannels()));
+ QObject::connect(m_ui.viewMenubarAction,
+ SIGNAL(toggled(bool)),
+ SLOT(viewMenubar(bool)));
+ QObject::connect(m_ui.viewToolbarAction,
+ SIGNAL(toggled(bool)),
+ SLOT(viewToolbar(bool)));
+ QObject::connect(m_ui.viewStatusbarAction,
+ SIGNAL(toggled(bool)),
+ SLOT(viewStatusbar(bool)));
+ QObject::connect(m_ui.viewMessagesAction,
+ SIGNAL(toggled(bool)),
+ SLOT(viewMessages(bool)));
+ QObject::connect(m_ui.viewInstrumentsAction,
+ SIGNAL(triggered()),
+ SLOT(viewInstruments()));
+ QObject::connect(m_ui.viewDevicesAction,
+ SIGNAL(triggered()),
+ SLOT(viewDevices()));
+ QObject::connect(m_ui.viewOptionsAction,
+ SIGNAL(triggered()),
+ SLOT(viewOptions()));
+ QObject::connect(m_ui.channelsArrangeAction,
+ SIGNAL(triggered()),
+ SLOT(channelsArrange()));
+ QObject::connect(m_ui.channelsAutoArrangeAction,
+ SIGNAL(toggled(bool)),
+ SLOT(channelsAutoArrange(bool)));
+ QObject::connect(m_ui.helpAboutAction,
+ SIGNAL(triggered()),
+ SLOT(helpAbout()));
+ QObject::connect(m_ui.helpAboutQtAction,
+ SIGNAL(triggered()),
+ SLOT(helpAboutQt()));
+
+ QObject::connect(m_ui.fileMenu,
+ SIGNAL(aboutToShow()),
+ SLOT(updateRecentFilesMenu()));
+ QObject::connect(m_ui.channelsMenu,
+ SIGNAL(aboutToShow()),
+ SLOT(channelsMenuAboutToShow()));
}
// Destructor.
MainForm::~MainForm()
{
- // Do final processing anyway.
- processServerExit();
+ // Do final processing anyway.
+ processServerExit();
#if defined(WIN32)
- WSACleanup();
+ WSACleanup();
#endif
- // Finally drop any widgets around...
- if (m_pDeviceForm)
- delete m_pDeviceForm;
- if (m_pInstrumentListForm)
- delete m_pInstrumentListForm;
- if (m_pMessages)
- delete m_pMessages;
- if (m_pWorkspace)
- delete m_pWorkspace;
-
- // Delete status item labels one by one.
- if (m_statusItem[QSAMPLER_STATUS_CLIENT])
- delete m_statusItem[QSAMPLER_STATUS_CLIENT];
- if (m_statusItem[QSAMPLER_STATUS_SERVER])
- delete m_statusItem[QSAMPLER_STATUS_SERVER];
- if (m_statusItem[QSAMPLER_STATUS_CHANNEL])
- delete m_statusItem[QSAMPLER_STATUS_CHANNEL];
- if (m_statusItem[QSAMPLER_STATUS_SESSION])
- delete m_statusItem[QSAMPLER_STATUS_SESSION];
+ // Finally drop any widgets around...
+ if (m_pDeviceForm)
+ delete m_pDeviceForm;
+ if (m_pInstrumentListForm)
+ delete m_pInstrumentListForm;
+ if (m_pMessages)
+ delete m_pMessages;
+ if (m_pWorkspace)
+ delete m_pWorkspace;
+
+ // Delete status item labels one by one.
+ if (m_statusItem[QSAMPLER_STATUS_CLIENT])
+ delete m_statusItem[QSAMPLER_STATUS_CLIENT];
+ if (m_statusItem[QSAMPLER_STATUS_SERVER])
+ delete m_statusItem[QSAMPLER_STATUS_SERVER];
+ if (m_statusItem[QSAMPLER_STATUS_CHANNEL])
+ delete m_statusItem[QSAMPLER_STATUS_CHANNEL];
+ if (m_statusItem[QSAMPLER_STATUS_SESSION])
+ delete m_statusItem[QSAMPLER_STATUS_SESSION];
#ifdef CONFIG_VOLUME
delete m_pVolumeSpinBox;
delete m_pVolumeSlider;
#endif
- // Delete recentfiles menu.
- if (m_pRecentFilesMenu)
- delete m_pRecentFilesMenu;
-
// Pseudo-singleton reference shut-down.
g_pMainForm = NULL;
}
// Make and set a proper setup options step.
-void MainForm::setup ( qsamplerOptions *pOptions )
+void MainForm::setup ( Options *pOptions )
{
- // We got options?
- m_pOptions = pOptions;
+ // We got options?
+ m_pOptions = pOptions;
- // What style do we create these forms?
- Qt::WFlags wflags = Qt::WStyle_Customize
- | Qt::WStyle_NormalBorder
- | Qt::WStyle_Title
- | Qt::WStyle_SysMenu
- | Qt::WStyle_MinMax
- | Qt::WType_TopLevel;
- if (m_pOptions->bKeepOnTop)
- wflags |= Qt::WStyle_Tool;
- // Some child forms are to be created right now.
- m_pMessages = new qsamplerMessages(this);
- m_pDeviceForm = new DeviceForm(this, wflags);
+ // What style do we create these forms?
+ Qt::WindowFlags wflags = Qt::Window
+#if QT_VERSION >= 0x040200
+ | Qt::CustomizeWindowHint
+#endif
+ | Qt::WindowTitleHint
+ | Qt::WindowSystemMenuHint
+ | Qt::WindowMinMaxButtonsHint;
+ if (m_pOptions->bKeepOnTop)
+ wflags |= Qt::Tool;
+ // Some child forms are to be created right now.
+ m_pMessages = new Messages(this);
+ m_pDeviceForm = new DeviceForm(this, wflags);
#ifdef CONFIG_MIDI_INSTRUMENT
- m_pInstrumentListForm = new InstrumentListForm(this, wflags);
- QObject::connect(&m_pInstrumentListForm->model,
- SIGNAL(instrumentsChanged()),
- SLOT(sessionDirty()));
+ m_pInstrumentListForm = new InstrumentListForm(this, wflags);
#else
viewInstrumentsAction->setEnabled(false);
#endif
- // Set message defaults...
- updateMessagesFont();
- updateMessagesLimit();
- updateMessagesCapture();
- // Set the visibility signal.
+ // Setup messages logging appropriately...
+ m_pMessages->setLogging(
+ m_pOptions->bMessagesLog,
+ m_pOptions->sMessagesLogPath);
+ // Set message defaults...
+ updateMessagesFont();
+ updateMessagesLimit();
+ updateMessagesCapture();
+ // Set the visibility signal.
QObject::connect(m_pMessages,
SIGNAL(visibilityChanged(bool)),
SLOT(stabilizeForm()));
- // Initial decorations toggle state.
- ui.viewMenubarAction->setOn(m_pOptions->bMenubar);
- ui.viewToolbarAction->setOn(m_pOptions->bToolbar);
- ui.viewStatusbarAction->setOn(m_pOptions->bStatusbar);
- ui.channelsAutoArrangeAction->setOn(m_pOptions->bAutoArrange);
-
- // Initial decorations visibility state.
- viewMenubar(m_pOptions->bMenubar);
- viewToolbar(m_pOptions->bToolbar);
- viewStatusbar(m_pOptions->bStatusbar);
-
- addDockWidget(Qt::BottomDockWidgetArea, m_pMessages);
-
- // Restore whole toolbar & dock windows states.
- QString sDockables = m_pOptions->settings().readEntry("/Layout/DockWindowsBase64" , QString::null);
- if (!sDockables.isEmpty()) {
- restoreState(QByteArray::fromBase64(sDockables.toAscii()));
- }
- // Try to restore old window positioning and initial visibility.
- m_pOptions->loadWidgetGeometry(this);
- m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);
- m_pOptions->loadWidgetGeometry(m_pDeviceForm);
-
- // Final startup stabilization...
- updateMaxVolume();
- updateRecentFilesMenu();
- stabilizeForm();
+ // Initial decorations toggle state.
+ m_ui.viewMenubarAction->setChecked(m_pOptions->bMenubar);
+ m_ui.viewToolbarAction->setChecked(m_pOptions->bToolbar);
+ m_ui.viewStatusbarAction->setChecked(m_pOptions->bStatusbar);
+ m_ui.channelsAutoArrangeAction->setChecked(m_pOptions->bAutoArrange);
+
+ // Initial decorations visibility state.
+ viewMenubar(m_pOptions->bMenubar);
+ viewToolbar(m_pOptions->bToolbar);
+ viewStatusbar(m_pOptions->bStatusbar);
+
+ addDockWidget(Qt::BottomDockWidgetArea, m_pMessages);
+
+ // Restore whole dock windows state.
+ QByteArray aDockables = m_pOptions->settings().value(
+ "/Layout/DockWindows").toByteArray();
+ if (!aDockables.isEmpty()) {
+ restoreState(aDockables);
+ }
+
+ // Try to restore old window positioning and initial visibility.
+ m_pOptions->loadWidgetGeometry(this);
+ m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);
+ m_pOptions->loadWidgetGeometry(m_pDeviceForm);
+
+ // Final startup stabilization...
+ updateMaxVolume();
+ updateRecentFilesMenu();
+ stabilizeForm();
- // Make it ready :-)
- statusBar()->message(tr("Ready"), 3000);
+ // Make it ready :-)
+ statusBar()->showMessage(tr("Ready"), 3000);
- // We'll try to start immediately...
- startSchedule(0);
+ // We'll try to start immediately...
+ startSchedule(0);
- // Register the first timer slot.
- QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
+ // Register the first timer slot.
+ QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
}
// Window close event handlers.
bool MainForm::queryClose (void)
{
- bool bQueryClose = closeSession(false);
+ bool bQueryClose = closeSession(false);
- // Try to save current general state...
- if (m_pOptions) {
- // Some windows default fonts is here on demand too.
- if (bQueryClose && m_pMessages)
- m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
- // Try to save current positioning.
- if (bQueryClose) {
- // Save decorations state.
- m_pOptions->bMenubar = ui.MenuBar->isVisible();
- m_pOptions->bToolbar = (fileToolbar->isVisible() || editToolbar->isVisible() || channelsToolbar->isVisible());
- m_pOptions->bStatusbar = statusBar()->isVisible();
- // Save the dock windows state.
- const QString sDockables = saveState().toBase64().data();
- m_pOptions->settings().writeEntry("/Layout/DockWindowsBase64", sDockables);
- // And the children, and the main windows state,.
+ // Try to save current general state...
+ if (m_pOptions) {
+ // Some windows default fonts is here on demand too.
+ if (bQueryClose && m_pMessages)
+ m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
+ // Try to save current positioning.
+ if (bQueryClose) {
+ // Save decorations state.
+ m_pOptions->bMenubar = m_ui.MenuBar->isVisible();
+ m_pOptions->bToolbar = (m_ui.fileToolbar->isVisible()
+ || m_ui.editToolbar->isVisible()
+ || m_ui.channelsToolbar->isVisible());
+ m_pOptions->bStatusbar = statusBar()->isVisible();
+ // Save the dock windows state.
+ const QString sDockables = saveState().toBase64().data();
+ m_pOptions->settings().setValue("/Layout/DockWindows", saveState());
+ // And the children, and the main windows state,.
m_pOptions->saveWidgetGeometry(m_pDeviceForm);
m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);
m_pOptions->saveWidgetGeometry(this);
@@ -362,116 +475,165 @@
m_pInstrumentListForm->close();
if (m_pDeviceForm)
m_pDeviceForm->close();
- // Stop client and/or server, gracefully.
- stopServer();
- }
- }
+ // Stop client and/or server, gracefully.
+ stopServer(true /*interactive*/);
+ }
+ }
- return bQueryClose;
+ return bQueryClose;
}
void MainForm::closeEvent ( QCloseEvent *pCloseEvent )
{
- if (queryClose())
- pCloseEvent->accept();
- else
- pCloseEvent->ignore();
-}
-
-
-// Drag'n'drop file handler.
-bool MainForm::decodeDragFiles ( const QMimeSource *pEvent, QStringList& files )
-{
- bool bDecode = false;
-
- if (Q3TextDrag::canDecode(pEvent)) {
- QString sText;
- bDecode = Q3TextDrag::decode(pEvent, sText);
- if (bDecode) {
- files = QStringList::split('\n', sText);
- for (QStringList::Iterator iter = files.begin(); iter != files.end(); iter++)
- *iter = QUrl((*iter).stripWhiteSpace().replace(QRegExp("^file:"), QString::null)).path();
- }
- }
-
- return bDecode;
+ if (queryClose()) {
+ DeviceStatusForm::deleteAllInstances();
+ pCloseEvent->accept();
+ } else
+ pCloseEvent->ignore();
}
// Window drag-n-drop event handlers.
void MainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )
{
- QStringList files;
- pDragEnterEvent->accept(decodeDragFiles(pDragEnterEvent, files));
+ // Accept external drags only...
+ if (pDragEnterEvent->source() == NULL
+ && pDragEnterEvent->mimeData()->hasUrls()) {
+ pDragEnterEvent->accept();
+ } else {
+ pDragEnterEvent->ignore();
+ }
}
void MainForm::dropEvent ( QDropEvent* pDropEvent )
{
- QStringList files;
-
- if (!decodeDragFiles(pDropEvent, files))
- return;
+ // Accept externally originated drops only...
+ if (pDropEvent->source())
+ return;
- for (QStringList::Iterator iter = files.begin(); iter != files.end(); iter++) {
- const QString& sPath = *iter;
- if (qsamplerChannel::isInstrumentFile(sPath)) {
- // Try to create a new channel from instrument file...
- qsamplerChannel *pChannel = new qsamplerChannel();
- if (pChannel == NULL)
- return;
- // Start setting the instrument filename...
- pChannel->setInstrument(sPath, 0);
- // Before we show it up, may be we'll
- // better ask for some initial values?
- if (!pChannel->channelSetup(this)) {
- delete pChannel;
- return;
- }
- // Finally, give it to a new channel strip...
- if (!createChannelStrip(pChannel)) {
- delete pChannel;
- return;
+ const QMimeData *pMimeData = pDropEvent->mimeData();
+ if (pMimeData->hasUrls()) {
+ QListIterator iter(pMimeData->urls());
+ while (iter.hasNext()) {
+ const QString& sPath = iter.next().toLocalFile();
+ if (Channel::isInstrumentFile(sPath)) {
+ // Try to create a new channel from instrument file...
+ Channel *pChannel = new Channel();
+ if (pChannel == NULL)
+ return;
+ // Start setting the instrument filename...
+ pChannel->setInstrument(sPath, 0);
+ // Before we show it up, may be we'll
+ // better ask for some initial values?
+ if (!pChannel->channelSetup(this)) {
+ delete pChannel;
+ return;
+ }
+ // Finally, give it to a new channel strip...
+ if (!createChannelStrip(pChannel)) {
+ delete pChannel;
+ return;
+ }
+ // Make that an overall update.
+ m_iDirtyCount++;
+ stabilizeForm();
+ } // Otherwise, load an usual session file (LSCP script)...
+ else if (closeSession(true)) {
+ loadSessionFile(sPath);
+ break;
}
- // Make that an overall update.
- m_iDirtyCount++;
- stabilizeForm();
- } // Otherwise, load an usual session file (LSCP script)...
- else if (closeSession(true)) {
- loadSessionFile(sPath);
- break;
}
// Make it look responsive...:)
- QApplication::processEvents(QEventLoop::ExcludeUserInput);
+ QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
}
}
+
// Custome event handler.
void MainForm::customEvent(QEvent* pCustomEvent)
{
- // For the time being, just pump it to messages.
- if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {
- qsamplerCustomEvent *pEvent = (qsamplerCustomEvent *) pCustomEvent;
- if (pEvent->event() == LSCP_EVENT_CHANNEL_INFO) {
- int iChannelID = pEvent->data().toInt();
- ChannelStrip *pChannelStrip = channelStrip(iChannelID);
- if (pChannelStrip)
- channelStripChanged(pChannelStrip);
- } else {
- appendMessagesColor(tr("Notify event: %1 data: %2")
- .arg(::lscp_event_to_text(pEvent->event()))
- .arg(pEvent->data()), "#996699");
+ // For the time being, just pump it to messages.
+ if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {
+ CustomEvent *pEvent = static_cast (pCustomEvent);
+ switch (pEvent->event()) {
+ case LSCP_EVENT_CHANNEL_COUNT:
+ updateAllChannelStrips(true);
+ break;
+ case LSCP_EVENT_CHANNEL_INFO: {
+ int iChannelID = pEvent->data().toInt();
+ ChannelStrip *pChannelStrip = channelStrip(iChannelID);
+ if (pChannelStrip)
+ channelStripChanged(pChannelStrip);
+ break;
+ }
+ case LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT:
+ if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
+ DeviceStatusForm::onDevicesChanged();
+ updateViewMidiDeviceStatusMenu();
+ break;
+ case LSCP_EVENT_MIDI_INPUT_DEVICE_INFO: {
+ if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
+ const int iDeviceID = pEvent->data().section(' ', 0, 0).toInt();
+ DeviceStatusForm::onDeviceChanged(iDeviceID);
+ break;
+ }
+ case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT:
+ if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
+ break;
+ case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO:
+ if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
+ break;
+#if CONFIG_EVENT_CHANNEL_MIDI
+ case LSCP_EVENT_CHANNEL_MIDI: {
+ const int iChannelID = pEvent->data().section(' ', 0, 0).toInt();
+ ChannelStrip *pChannelStrip = channelStrip(iChannelID);
+ if (pChannelStrip)
+ pChannelStrip->midiArrived();
+ break;
+ }
+#endif
+#if CONFIG_EVENT_DEVICE_MIDI
+ case LSCP_EVENT_DEVICE_MIDI: {
+ const int iDeviceID = pEvent->data().section(' ', 0, 0).toInt();
+ const int iPortID = pEvent->data().section(' ', 1, 1).toInt();
+ DeviceStatusForm* pDeviceStatusForm =
+ DeviceStatusForm::getInstance(iDeviceID);
+ if (pDeviceStatusForm)
+ pDeviceStatusForm->midiArrived(iPortID);
+ break;
+ }
+#endif
+ default:
+ appendMessagesColor(tr("Notify event: %1 data: %2")
+ .arg(::lscp_event_to_text(pEvent->event()))
+ .arg(pEvent->data()), "#996699");
}
- }
+ }
+}
+
+void MainForm::updateViewMidiDeviceStatusMenu() {
+ m_ui.viewMidiDeviceStatusMenu->clear();
+ const std::map statusForms =
+ DeviceStatusForm::getInstances();
+ for (
+ std::map::const_iterator iter = statusForms.begin();
+ iter != statusForms.end(); ++iter
+ ) {
+ DeviceStatusForm* pForm = iter->second;
+ m_ui.viewMidiDeviceStatusMenu->addAction(
+ pForm->visibleAction()
+ );
+ }
}
// Context menu event handler.
void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )
{
- stabilizeForm();
+ stabilizeForm();
- ui.editMenu->exec(pEvent->globalPos());
+ m_ui.editMenu->exec(pEvent->globalPos());
}
@@ -479,16 +641,16 @@
// qsamplerMainForm -- Brainless public property accessors.
// The global options settings property.
-qsamplerOptions *MainForm::options (void)
+Options *MainForm::options (void) const
{
- return m_pOptions;
+ return m_pOptions;
}
// The LSCP client descriptor property.
-lscp_client_t *MainForm::client (void)
+lscp_client_t *MainForm::client (void) const
{
- return m_pClient;
+ return m_pClient;
}
@@ -505,201 +667,205 @@
// Format the displayable session filename.
QString MainForm::sessionName ( const QString& sFilename )
{
- bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);
- QString sSessionName = sFilename;
- if (sSessionName.isEmpty())
- sSessionName = tr("Untitled") + QString::number(m_iUntitled);
- else if (!bCompletePath)
- sSessionName = QFileInfo(sSessionName).fileName();
- return sSessionName;
+ bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);
+ QString sSessionName = sFilename;
+ if (sSessionName.isEmpty())
+ sSessionName = tr("Untitled") + QString::number(m_iUntitled);
+ else if (!bCompletePath)
+ sSessionName = QFileInfo(sSessionName).fileName();
+ return sSessionName;
}
// Create a new session file from scratch.
bool MainForm::newSession (void)
{
- // Check if we can do it.
- if (!closeSession(true))
- return false;
+ // Check if we can do it.
+ if (!closeSession(true))
+ return false;
// Give us what the server has, right now...
updateSession();
- // Ok increment untitled count.
- m_iUntitled++;
+ // Ok increment untitled count.
+ m_iUntitled++;
- // Stabilize form.
- m_sFilename = QString::null;
- m_iDirtyCount = 0;
- appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));
- stabilizeForm();
+ // Stabilize form.
+ m_sFilename = QString::null;
+ m_iDirtyCount = 0;
+ appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));
+ stabilizeForm();
- return true;
+ return true;
}
// Open an existing sampler session.
bool MainForm::openSession (void)
{
- if (m_pOptions == NULL)
- return false;
+ if (m_pOptions == NULL)
+ return false;
- // Ask for the filename to open...
- QString sFilename = QFileDialog::getOpenFileName(
- m_pOptions->sSessionDir, // Start here.
- tr("LSCP Session files") + " (*.lscp)", // Filter (LSCP files)
- this, 0, // Parent and name (none)
- QSAMPLER_TITLE ": " + tr("Open Session") // Caption.
- );
-
- // Have we cancelled?
- if (sFilename.isEmpty())
- return false;
-
- // Check if we're going to discard safely the current one...
- if (!closeSession(true))
- return false;
+ // Ask for the filename to open...
+ QString sFilename = QFileDialog::getOpenFileName(this,
+ QSAMPLER_TITLE ": " + tr("Open Session"), // Caption.
+ m_pOptions->sSessionDir, // Start here.
+ tr("LSCP Session files") + " (*.lscp)" // Filter (LSCP files)
+ );
- // Load it right away.
- return loadSessionFile(sFilename);
+ // Have we cancelled?
+ if (sFilename.isEmpty())
+ return false;
+
+ // Check if we're going to discard safely the current one...
+ if (!closeSession(true))
+ return false;
+
+ // Load it right away.
+ return loadSessionFile(sFilename);
}
// Save current sampler session with another name.
bool MainForm::saveSession ( bool bPrompt )
{
- if (m_pOptions == NULL)
- return false;
+ if (m_pOptions == NULL)
+ return false;
- QString sFilename = m_sFilename;
+ QString sFilename = m_sFilename;
- // Ask for the file to save, if there's none...
- if (bPrompt || sFilename.isEmpty()) {
- // If none is given, assume default directory.
- if (sFilename.isEmpty())
- sFilename = m_pOptions->sSessionDir;
- // Prompt the guy...
- sFilename = QFileDialog::getSaveFileName(
- sFilename, // Start here.
- tr("LSCP Session files") + " (*.lscp)", // Filter (LSCP files)
- this, 0, // Parent and name (none)
- QSAMPLER_TITLE ": " + tr("Save Session") // Caption.
- );
- // Have we cancelled it?
- if (sFilename.isEmpty())
- return false;
- // Enforce .lscp extension...
- if (QFileInfo(sFilename).extension().isEmpty())
- sFilename += ".lscp";
- // Check if already exists...
- if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {
- if (QMessageBox::warning(this,
+ // Ask for the file to save, if there's none...
+ if (bPrompt || sFilename.isEmpty()) {
+ // If none is given, assume default directory.
+ if (sFilename.isEmpty())
+ sFilename = m_pOptions->sSessionDir;
+ // Prompt the guy...
+ sFilename = QFileDialog::getSaveFileName(this,
+ QSAMPLER_TITLE ": " + tr("Save Session"), // Caption.
+ sFilename, // Start here.
+ tr("LSCP Session files") + " (*.lscp)" // Filter (LSCP files)
+ );
+ // Have we cancelled it?
+ if (sFilename.isEmpty())
+ return false;
+ // Enforce .lscp extension...
+ if (QFileInfo(sFilename).suffix().isEmpty())
+ sFilename += ".lscp";
+ // Check if already exists...
+ if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {
+ if (QMessageBox::warning(this,
QSAMPLER_TITLE ": " + tr("Warning"),
- tr("The file already exists:\n\n"
- "\"%1\"\n\n"
- "Do you want to replace it?")
- .arg(sFilename),
- tr("Replace"), tr("Cancel")) > 0)
- return false;
- }
- }
+ tr("The file already exists:\n\n"
+ "\"%1\"\n\n"
+ "Do you want to replace it?")
+ .arg(sFilename),
+ QMessageBox::Yes | QMessageBox::No)
+ == QMessageBox::No)
+ return false;
+ }
+ }
- // Save it right away.
- return saveSessionFile(sFilename);
+ // Save it right away.
+ return saveSessionFile(sFilename);
}
// Close current session.
bool MainForm::closeSession ( bool bForce )
{
- bool bClose = true;
+ bool bClose = true;
- // Are we dirty enough to prompt it?
- if (m_iDirtyCount > 0) {
- switch (QMessageBox::warning(this,
+ // Are we dirty enough to prompt it?
+ if (m_iDirtyCount > 0) {
+ switch (QMessageBox::warning(this,
QSAMPLER_TITLE ": " + tr("Warning"),
- tr("The current session has been changed:\n\n"
- "\"%1\"\n\n"
- "Do you want to save the changes?")
- .arg(sessionName(m_sFilename)),
- tr("Save"), tr("Discard"), tr("Cancel"))) {
- case 0: // Save...
- bClose = saveSession(false);
- // Fall thru....
- case 1: // Discard
- break;
- default: // Cancel.
- bClose = false;
- break;
- }
- }
-
- // If we may close it, dot it.
- if (bClose) {
- // Remove all channel strips from sight...
- m_pWorkspace->setUpdatesEnabled(false);
- QWidgetList wlist = m_pWorkspace->windowList();
- for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
- ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
- if (pChannelStrip) {
- qsamplerChannel *pChannel = pChannelStrip->channel();
- if (bForce && pChannel)
- pChannel->removeChannel();
- delete pChannelStrip;
- }
- }
- m_pWorkspace->setUpdatesEnabled(true);
- // We're now clean, for sure.
- m_iDirtyCount = 0;
- }
+ tr("The current session has been changed:\n\n"
+ "\"%1\"\n\n"
+ "Do you want to save the changes?")
+ .arg(sessionName(m_sFilename)),
+ QMessageBox::Save |
+ QMessageBox::Discard |
+ QMessageBox::Cancel)) {
+ case QMessageBox::Save:
+ bClose = saveSession(false);
+ // Fall thru....
+ case QMessageBox::Discard:
+ break;
+ default: // Cancel.
+ bClose = false;
+ break;
+ }
+ }
- return bClose;
+ // If we may close it, dot it.
+ if (bClose) {
+ // Remove all channel strips from sight...
+ m_pWorkspace->setUpdatesEnabled(false);
+ QWidgetList wlist = m_pWorkspace->windowList();
+ for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
+ ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
+ if (pChannelStrip) {
+ Channel *pChannel = pChannelStrip->channel();
+ if (bForce && pChannel)
+ pChannel->removeChannel();
+ delete pChannelStrip;
+ }
+ }
+ m_pWorkspace->setUpdatesEnabled(true);
+ // We're now clean, for sure.
+ m_iDirtyCount = 0;
+ }
+
+ return bClose;
}
// Load a session from specific file path.
bool MainForm::loadSessionFile ( const QString& sFilename )
{
- if (m_pClient == NULL)
- return false;
+ if (m_pClient == NULL)
+ return false;
- // Open and read from real file.
- QFile file(sFilename);
- if (!file.open(IO_ReadOnly)) {
- appendMessagesError(tr("Could not open \"%1\" session file.\n\nSorry.").arg(sFilename));
- return false;
- }
+ // Open and read from real file.
+ QFile file(sFilename);
+ if (!file.open(QIODevice::ReadOnly)) {
+ appendMessagesError(
+ tr("Could not open \"%1\" session file.\n\nSorry.")
+ .arg(sFilename));
+ return false;
+ }
// Tell the world we'll take some time...
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
- // Read the file.
+ // Read the file.
int iLine = 0;
- int iErrors = 0;
- QTextStream ts(&file);
- while (!ts.atEnd()) {
- // Read the line.
- QString sCommand = ts.readLine().stripWhiteSpace();
+ int iErrors = 0;
+ QTextStream ts(&file);
+ while (!ts.atEnd()) {
+ // Read the line.
+ QString sCommand = ts.readLine().trimmed();
iLine++;
- // If not empty, nor a comment, call the server...
- if (!sCommand.isEmpty() && sCommand[0] != '#') {
+ // If not empty, nor a comment, call the server...
+ if (!sCommand.isEmpty() && sCommand[0] != '#') {
// Remember that, no matter what,
// all LSCP commands are CR/LF terminated.
sCommand += "\r\n";
- if (::lscp_client_query(m_pClient, sCommand.latin1()) != LSCP_OK) {
+ if (::lscp_client_query(m_pClient, sCommand.toUtf8().constData())
+ != LSCP_OK) {
appendMessagesColor(QString("%1(%2): %3")
.arg(QFileInfo(sFilename).fileName()).arg(iLine)
- .arg(sCommand.simplifyWhiteSpace()), "#996633");
+ .arg(sCommand.simplified()), "#996633");
appendMessagesClient("lscp_client_query");
iErrors++;
}
- }
- // Try to make it snappy :)
- QApplication::processEvents(QEventLoop::ExcludeUserInput);
- }
+ }
+ // Try to make it snappy :)
+ QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+ }
- // Ok. we've read it.
- file.close();
+ // Ok. we've read it.
+ file.close();
// Now we'll try to create (update) the whole GUI session.
updateSession();
@@ -708,22 +874,25 @@
QApplication::restoreOverrideCursor();
// Have we any errors?
- if (iErrors > 0)
- appendMessagesError(tr("Session loaded with errors\nfrom \"%1\".\n\nSorry.").arg(sFilename));
+ if (iErrors > 0) {
+ appendMessagesError(
+ tr("Session loaded with errors\nfrom \"%1\".\n\nSorry.")
+ .arg(sFilename));
+ }
- // Save as default session directory.
- if (m_pOptions)
- m_pOptions->sSessionDir = QFileInfo(sFilename).dirPath(true);
+ // Save as default session directory.
+ if (m_pOptions)
+ m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();
// We're not dirty anymore, if loaded without errors,
m_iDirtyCount = iErrors;
- // Stabilize form...
- m_sFilename = sFilename;
- updateRecentFiles(sFilename);
- appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));
-
- // Make that an overall update.
- stabilizeForm();
- return true;
+ // Stabilize form...
+ m_sFilename = sFilename;
+ updateRecentFiles(sFilename);
+ appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));
+
+ // Make that an overall update.
+ stabilizeForm();
+ return true;
}
@@ -739,32 +908,34 @@
return false;
}
- // Open and write into real file.
- QFile file(sFilename);
- if (!file.open(IO_WriteOnly | IO_Truncate)) {
- appendMessagesError(tr("Could not open \"%1\" session file.\n\nSorry.").arg(sFilename));
- return false;
- }
+ // Open and write into real file.
+ QFile file(sFilename);
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ appendMessagesError(
+ tr("Could not open \"%1\" session file.\n\nSorry.")
+ .arg(sFilename));
+ return false;
+ }
// Tell the world we'll take some time...
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
- // Write the file.
- int iErrors = 0;
- QTextStream ts(&file);
- ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;
- ts << "# " << tr("Version")
- << ": " QSAMPLER_VERSION << endl;
- ts << "# " << tr("Build")
- << ": " __DATE__ " " __TIME__ << endl;
- ts << "#" << endl;
- ts << "# " << tr("File")
- << ": " << QFileInfo(sFilename).fileName() << endl;
- ts << "# " << tr("Date")
- << ": " << QDate::currentDate().toString("MMM dd yyyy")
- << " " << QTime::currentTime().toString("hh:mm:ss") << endl;
- ts << "#" << endl;
- ts << endl;
+ // Write the file.
+ int iErrors = 0;
+ QTextStream ts(&file);
+ ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;
+ ts << "# " << tr("Version")
+ << ": " QSAMPLER_VERSION << endl;
+ ts << "# " << tr("Build")
+ << ": " __DATE__ " " __TIME__ << endl;
+ ts << "#" << endl;
+ ts << "# " << tr("File")
+ << ": " << QFileInfo(sFilename).fileName() << endl;
+ ts << "# " << tr("Date")
+ << ": " << QDate::currentDate().toString("MMM dd yyyy")
+ << " " << QTime::currentTime().toString("hh:mm:ss") << endl;
+ ts << "#" << endl;
+ ts << endl;
// It is assumed that this new kind of device+session file
// will be loaded from a complete initialized server...
@@ -774,84 +945,86 @@
// Audio device mapping.
QMap audioDeviceMap;
- piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Audio);
+ piDeviceIDs = Device::getDevices(m_pClient, Device::Audio);
for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
ts << endl;
- qsamplerDevice device(qsamplerDevice::Audio, piDeviceIDs[iDevice]);
+ Device device(Device::Audio, piDeviceIDs[iDevice]);
// Audio device specification...
ts << "# " << device.deviceTypeName() << " " << device.driverName()
<< " " << tr("Device") << " " << iDevice << endl;
ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();
- qsamplerDeviceParamMap::ConstIterator deviceParam;
+ DeviceParamMap::ConstIterator deviceParam;
for (deviceParam = device.params().begin();
deviceParam != device.params().end();
++deviceParam) {
- const qsamplerDeviceParam& param = deviceParam.data();
+ const DeviceParam& param = deviceParam.value();
if (param.value.isEmpty()) ts << "# ";
ts << " " << deviceParam.key() << "='" << param.value << "'";
}
ts << endl;
// Audio channel parameters...
int iPort = 0;
- for (qsamplerDevicePort *pPort = device.ports().first();
- pPort;
- pPort = device.ports().next(), ++iPort) {
- qsamplerDeviceParamMap::ConstIterator portParam;
+ QListIterator iter(device.ports());
+ while (iter.hasNext()) {
+ DevicePort *pPort = iter.next();
+ DeviceParamMap::ConstIterator portParam;
for (portParam = pPort->params().begin();
portParam != pPort->params().end();
++portParam) {
- const qsamplerDeviceParam& param = portParam.data();
+ const DeviceParam& param = portParam.value();
if (param.fix || param.value.isEmpty()) ts << "# ";
ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice
<< " " << iPort << " " << portParam.key()
<< "='" << param.value << "'" << endl;
}
+ iPort++;
}
// Audio device index/id mapping.
audioDeviceMap[device.deviceID()] = iDevice;
// Try to keep it snappy :)
- QApplication::processEvents(QEventLoop::ExcludeUserInput);
+ QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
}
// MIDI device mapping.
QMap midiDeviceMap;
- piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Midi);
+ piDeviceIDs = Device::getDevices(m_pClient, Device::Midi);
for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
ts << endl;
- qsamplerDevice device(qsamplerDevice::Midi, piDeviceIDs[iDevice]);
+ Device device(Device::Midi, piDeviceIDs[iDevice]);
// MIDI device specification...
ts << "# " << device.deviceTypeName() << " " << device.driverName()
<< " " << tr("Device") << " " << iDevice << endl;
ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();
- qsamplerDeviceParamMap::ConstIterator deviceParam;
+ DeviceParamMap::ConstIterator deviceParam;
for (deviceParam = device.params().begin();
deviceParam != device.params().end();
++deviceParam) {
- const qsamplerDeviceParam& param = deviceParam.data();
+ const DeviceParam& param = deviceParam.value();
if (param.value.isEmpty()) ts << "# ";
ts << " " << deviceParam.key() << "='" << param.value << "'";
}
ts << endl;
// MIDI port parameters...
int iPort = 0;
- for (qsamplerDevicePort *pPort = device.ports().first();
- pPort;
- pPort = device.ports().next(), ++iPort) {
- qsamplerDeviceParamMap::ConstIterator portParam;
+ QListIterator iter(device.ports());
+ while (iter.hasNext()) {
+ DevicePort *pPort = iter.next();
+ DeviceParamMap::ConstIterator portParam;
for (portParam = pPort->params().begin();
portParam != pPort->params().end();
++portParam) {
- const qsamplerDeviceParam& param = portParam.data();
+ const DeviceParam& param = portParam.value();
if (param.fix || param.value.isEmpty()) ts << "# ";
ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice
- << " " << iPort << " " << portParam.key()
- << "='" << param.value << "'" << endl;
+ << " " << iPort << " " << portParam.key()
+ << "='" << param.value << "'" << endl;
}
+ iPort++;
}
// MIDI device index/id mapping.
midiDeviceMap[device.deviceID()] = iDevice;
// Try to keep it snappy :)
- QApplication::processEvents(QEventLoop::ExcludeUserInput);
+ QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
}
ts << endl;
@@ -908,7 +1081,7 @@
iErrors++;
}
// Try to keep it snappy :)
- QApplication::processEvents(QEventLoop::ExcludeUserInput);
+ QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
}
ts << endl;
// Check for errors...
@@ -927,15 +1100,15 @@
#endif // CONFIG_MIDI_INSTRUMENT
// Sampler channel mapping.
- QWidgetList wlist = m_pWorkspace->windowList();
- for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
- ChannelStrip* pChannelStrip
+ QWidgetList wlist = m_pWorkspace->windowList();
+ for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
+ ChannelStrip* pChannelStrip
= static_cast (wlist.at(iChannel));
- if (pChannelStrip) {
- qsamplerChannel *pChannel = pChannelStrip->channel();
- if (pChannel) {
- ts << "# " << tr("Channel") << " " << iChannel << endl;
- ts << "ADD CHANNEL" << endl;
+ if (pChannelStrip) {
+ Channel *pChannel = pChannelStrip->channel();
+ if (pChannel) {
+ ts << "# " << tr("Channel") << " " << iChannel << endl;
+ ts << "ADD CHANNEL" << endl;
if (audioDeviceMap.isEmpty()) {
ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel
<< " " << pChannel->audioDriver() << endl;
@@ -952,23 +1125,25 @@
}
ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel
<< " " << pChannel->midiPort() << endl;
- ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";
- if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
- ts << "ALL";
- else
- ts << pChannel->midiChannel();
- ts << endl;
- ts << "LOAD ENGINE " << pChannel->engineName() << " " << iChannel << endl;
+ ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";
+ if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
+ ts << "ALL";
+ else
+ ts << pChannel->midiChannel();
+ ts << endl;
+ ts << "LOAD ENGINE " << pChannel->engineName()
+ << " " << iChannel << endl;
if (pChannel->instrumentStatus() < 100) ts << "# ";
- ts << "LOAD INSTRUMENT NON_MODAL '" << pChannel->instrumentFile() << "' "
+ ts << "LOAD INSTRUMENT NON_MODAL '"
+ << pChannel->instrumentFile() << "' "
<< pChannel->instrumentNr() << " " << iChannel << endl;
- qsamplerChannelRoutingMap::ConstIterator audioRoute;
+ ChannelRoutingMap::ConstIterator audioRoute;
for (audioRoute = pChannel->audioRouting().begin();
audioRoute != pChannel->audioRouting().end();
++audioRoute) {
ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannel
<< " " << audioRoute.key()
- << " " << audioRoute.data() << endl;
+ << " " << audioRoute.value() << endl;
}
ts << "SET CHANNEL VOLUME " << iChannel
<< " " << pChannel->volume() << endl;
@@ -1018,12 +1193,12 @@
}
}
#endif
- ts << endl;
- }
- }
- // Try to keep it snappy :)
- QApplication::processEvents(QEventLoop::ExcludeUserInput);
- }
+ ts << endl;
+ }
+ }
+ // Try to keep it snappy :)
+ QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+ }
#ifdef CONFIG_VOLUME
ts << "# " << tr("Global volume level") << endl;
@@ -1031,37 +1206,41 @@
ts << endl;
#endif
- // Ok. we've wrote it.
- file.close();
+ // Ok. we've wrote it.
+ file.close();
// We're fornerly done.
QApplication::restoreOverrideCursor();
- // Have we any errors?
- if (iErrors > 0)
- appendMessagesError(tr("Some settings could not be saved\nto \"%1\" session file.\n\nSorry.").arg(sFilename));
-
- // Save as default session directory.
- if (m_pOptions)
- m_pOptions->sSessionDir = QFileInfo(sFilename).dirPath(true);
- // We're not dirty anymore.
- m_iDirtyCount = 0;
- // Stabilize form...
- m_sFilename = sFilename;
- updateRecentFiles(sFilename);
- appendMessages(tr("Save session: \"%1\".").arg(sessionName(m_sFilename)));
- stabilizeForm();
- return true;
+ // Have we any errors?
+ if (iErrors > 0) {
+ appendMessagesError(
+ tr("Some settings could not be saved\n"
+ "to \"%1\" session file.\n\nSorry.")
+ .arg(sFilename));
+ }
+
+ // Save as default session directory.
+ if (m_pOptions)
+ m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();
+ // We're not dirty anymore.
+ m_iDirtyCount = 0;
+ // Stabilize form...
+ m_sFilename = sFilename;
+ updateRecentFiles(sFilename);
+ appendMessages(tr("Save session: \"%1\".").arg(sessionName(m_sFilename)));
+ stabilizeForm();
+ return true;
}
// Session change receiver slot.
void MainForm::sessionDirty (void)
{
- // Just mark the dirty form.
- m_iDirtyCount++;
- // and update the form status...
- stabilizeForm();
+ // Just mark the dirty form.
+ m_iDirtyCount++;
+ // and update the form status...
+ stabilizeForm();
}
@@ -1071,68 +1250,75 @@
// Create a new sampler session.
void MainForm::fileNew (void)
{
- // Of course we'll start clean new.
- newSession();
+ // Of course we'll start clean new.
+ newSession();
}
// Open an existing sampler session.
void MainForm::fileOpen (void)
{
- // Open it right away.
- openSession();
+ // Open it right away.
+ openSession();
}
// Open a recent file session.
-void MainForm::fileOpenRecent ( int iIndex )
+void MainForm::fileOpenRecent (void)
{
- // Check if we can safely close the current session...
- if (m_pOptions && closeSession(true)) {
- QString sFilename = m_pOptions->recentFiles[iIndex];
- loadSessionFile(sFilename);
- }
+ // Retrive filename index from action data...
+ QAction *pAction = qobject_cast (sender());
+ if (pAction && m_pOptions) {
+ int iIndex = pAction->data().toInt();
+ if (iIndex >= 0 && iIndex < m_pOptions->recentFiles.count()) {
+ QString sFilename = m_pOptions->recentFiles[iIndex];
+ // Check if we can safely close the current session...
+ if (!sFilename.isEmpty() && closeSession(true))
+ loadSessionFile(sFilename);
+ }
+ }
}
// Save current sampler session.
void MainForm::fileSave (void)
{
- // Save it right away.
- saveSession(false);
+ // Save it right away.
+ saveSession(false);
}
// Save current sampler session with another name.
void MainForm::fileSaveAs (void)
{
- // Save it right away, maybe with another name.
- saveSession(true);
+ // Save it right away, maybe with another name.
+ saveSession(true);
}
// Reset the sampler instance.
void MainForm::fileReset (void)
{
- if (m_pClient == NULL)
- return;
+ if (m_pClient == NULL)
+ return;
- // Ask user whether he/she want's an internal sampler reset...
- if (QMessageBox::warning(this,
+ // Ask user whether he/she want's an internal sampler reset...
+ if (QMessageBox::warning(this,
QSAMPLER_TITLE ": " + tr("Warning"),
- tr("Resetting the sampler instance will close\n"
- "all device and channel configurations.\n\n"
- "Please note that this operation may cause\n"
- "temporary MIDI and Audio disruption.\n\n"
- "Do you want to reset the sampler engine now?"),
- tr("Reset"), tr("Cancel")) > 0)
- return;
+ tr("Resetting the sampler instance will close\n"
+ "all device and channel configurations.\n\n"
+ "Please note that this operation may cause\n"
+ "temporary MIDI and Audio disruption.\n\n"
+ "Do you want to reset the sampler engine now?"),
+ QMessageBox::Ok | QMessageBox::Cancel)
+ == QMessageBox::Cancel)
+ return;
// Trye closing the current session, first...
if (!closeSession(true))
return;
- // Just do the reset, after closing down current session...
+ // Just do the reset, after closing down current session...
// Do the actual sampler reset...
if (::lscp_reset_sampler(m_pClient) != LSCP_OK) {
appendMessagesClient("lscp_reset_sampler");
@@ -1140,8 +1326,8 @@
return;
}
- // Log this.
- appendMessages(tr("Sampler reset."));
+ // Log this.
+ appendMessages(tr("Sampler reset."));
// Make it a new session...
newSession();
@@ -1151,39 +1337,39 @@
// Restart the client/server instance.
void MainForm::fileRestart (void)
{
- if (m_pOptions == NULL)
- return;
+ if (m_pOptions == NULL)
+ return;
- bool bRestart = true;
+ bool bRestart = true;
- // Ask user whether he/she want's a complete restart...
- // (if we're currently up and running)
- if (bRestart && m_pClient) {
- bRestart = (QMessageBox::warning(this,
+ // Ask user whether he/she want's a complete restart...
+ // (if we're currently up and running)
+ if (bRestart && m_pClient) {
+ bRestart = (QMessageBox::warning(this,
QSAMPLER_TITLE ": " + tr("Warning"),
- tr("New settings will be effective after\n"
- "restarting the client/server connection.\n\n"
- "Please note that this operation may cause\n"
- "temporary MIDI and Audio disruption.\n\n"
- "Do you want to restart the connection now?"),
- tr("Restart"), tr("Cancel")) == 0);
- }
-
- // Are we still for it?
- if (bRestart && closeSession(true)) {
- // Stop server, it will force the client too.
- stopServer();
- // Reschedule a restart...
- startSchedule(m_pOptions->iStartDelay);
- }
+ tr("New settings will be effective after\n"
+ "restarting the client/server connection.\n\n"
+ "Please note that this operation may cause\n"
+ "temporary MIDI and Audio disruption.\n\n"
+ "Do you want to restart the connection now?"),
+ QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok);
+ }
+
+ // Are we still for it?
+ if (bRestart && closeSession(true)) {
+ // Stop server, it will force the client too.
+ stopServer();
+ // Reschedule a restart...
+ startSchedule(m_pOptions->iStartDelay);
+ }
}
// Exit application program.
void MainForm::fileExit (void)
{
- // Go for close the whole thing.
- close();
+ // Go for close the whole thing.
+ close();
}
@@ -1193,118 +1379,124 @@
// Add a new sampler channel.
void MainForm::editAddChannel (void)
{
- if (m_pClient == NULL)
- return;
+ if (m_pClient == NULL)
+ return;
+
+ // Just create the channel instance...
+ Channel *pChannel = new Channel();
+ if (pChannel == NULL)
+ return;
+
+ // Before we show it up, may be we'll
+ // better ask for some initial values?
+ if (!pChannel->channelSetup(this)) {
+ delete pChannel;
+ return;
+ }
+
+ // And give it to the strip...
+ // (will own the channel instance, if successful).
+ if (!createChannelStrip(pChannel)) {
+ delete pChannel;
+ return;
+ }
+
+ // Do we auto-arrange?
+ if (m_pOptions && m_pOptions->bAutoArrange)
+ channelsArrange();
- // Just create the channel instance...
- qsamplerChannel *pChannel = new qsamplerChannel();
- if (pChannel == NULL)
- return;
-
- // Before we show it up, may be we'll
- // better ask for some initial values?
- if (!pChannel->channelSetup(this)) {
- delete pChannel;
- return;
- }
-
- // And give it to the strip (will own the channel instance, if successful).
- if (!createChannelStrip(pChannel)) {
- delete pChannel;
- return;
- }
-
- // Make that an overall update.
- m_iDirtyCount++;
- stabilizeForm();
+ // Make that an overall update.
+ m_iDirtyCount++;
+ stabilizeForm();
}
// Remove current sampler channel.
void MainForm::editRemoveChannel (void)
{
- if (m_pClient == NULL)
- return;
+ if (m_pClient == NULL)
+ return;
+
+ ChannelStrip* pChannelStrip = activeChannelStrip();
+ if (pChannelStrip == NULL)
+ return;
- ChannelStrip* pChannelStrip = activeChannelStrip();
- if (pChannelStrip == NULL)
- return;
-
- qsamplerChannel *pChannel = pChannelStrip->channel();
- if (pChannel == NULL)
- return;
-
- // Prompt user if he/she's sure about this...
- if (m_pOptions && m_pOptions->bConfirmRemove) {
- if (QMessageBox::warning(this,
+ Channel *pChannel = pChannelStrip->channel();
+ if (pChannel == NULL)
+ return;
+
+ // Prompt user if he/she's sure about this...
+ if (m_pOptions && m_pOptions->bConfirmRemove) {
+ if (QMessageBox::warning(this,
QSAMPLER_TITLE ": " + tr("Warning"),
- tr("About to remove channel:\n\n"
- "%1\n\n"
- "Are you sure?")
- .arg(pChannelStrip->caption()),
- tr("OK"), tr("Cancel")) > 0)
- return;
- }
-
- // Remove the existing sampler channel.
- if (!pChannel->removeChannel())
- return;
-
- // Just delete the channel strip.
- delete pChannelStrip;
-
- // Do we auto-arrange?
- if (m_pOptions && m_pOptions->bAutoArrange)
- channelsArrange();
-
- // We'll be dirty, for sure...
- m_iDirtyCount++;
- stabilizeForm();
+ tr("About to remove channel:\n\n"
+ "%1\n\n"
+ "Are you sure?")
+ .arg(pChannelStrip->windowTitle()),
+ QMessageBox::Ok | QMessageBox::Cancel)
+ == QMessageBox::Cancel)
+ return;
+ }
+
+ // Remove the existing sampler channel.
+ if (!pChannel->removeChannel())
+ return;
+
+ // Just delete the channel strip.
+ delete pChannelStrip;
+
+ // Do we auto-arrange?
+ if (m_pOptions && m_pOptions->bAutoArrange)
+ channelsArrange();
+
+ // We'll be dirty, for sure...
+ m_iDirtyCount++;
+ stabilizeForm();
}
// Setup current sampler channel.
void MainForm::editSetupChannel (void)
{
- if (m_pClient == NULL)
- return;
+ if (m_pClient == NULL)
+ return;
- ChannelStrip* pChannelStrip = activeChannelStrip();
- if (pChannelStrip == NULL)
- return;
+ ChannelStrip* pChannelStrip = activeChannelStrip();
+ if (pChannelStrip == NULL)
+ return;
- // Just invoque the channel strip procedure.
- pChannelStrip->channelSetup();
+ // Just invoque the channel strip procedure.
+ pChannelStrip->channelSetup();
}
// Edit current sampler channel.
void MainForm::editEditChannel (void)
{
- if (m_pClient == NULL)
- return;
+ if (m_pClient == NULL)
+ return;
- ChannelStrip* pChannelStrip = activeChannelStrip();
- if (pChannelStrip == NULL)
- return;
+ ChannelStrip* pChannelStrip = activeChannelStrip();
+ if (pChannelStrip == NULL)
+ return;
- // Just invoque the channel strip procedure.
- pChannelStrip->channelEdit();
+ // Just invoque the channel strip procedure.
+ pChannelStrip->channelEdit();
}
// Reset current sampler channel.
void MainForm::editResetChannel (void)
{
- if (m_pClient == NULL)
- return;
+ if (m_pClient == NULL)
+ return;
- ChannelStrip* pChannelStrip = activeChannelStrip();
- if (pChannelStrip == NULL)
- return;
+ ChannelStrip* pChannelStrip = activeChannelStrip();
+ if (pChannelStrip == NULL)
+ return;
- // Just invoque the channel strip procedure.
- pChannelStrip->channelReset();
+ // Just invoque the channel strip procedure.
+ pChannelStrip->channelReset();
}
@@ -1333,45 +1525,45 @@
// Show/hide the main program window menubar.
void MainForm::viewMenubar ( bool bOn )
{
- if (bOn)
- ui.MenuBar->show();
- else
- ui.MenuBar->hide();
+ if (bOn)
+ m_ui.MenuBar->show();
+ else
+ m_ui.MenuBar->hide();
}
// Show/hide the main program window toolbar.
void MainForm::viewToolbar ( bool bOn )
{
- if (bOn) {
- fileToolbar->show();
- editToolbar->show();
- channelsToolbar->show();
- } else {
- fileToolbar->hide();
- editToolbar->hide();
- channelsToolbar->hide();
- }
+ if (bOn) {
+ m_ui.fileToolbar->show();
+ m_ui.editToolbar->show();
+ m_ui.channelsToolbar->show();
+ } else {
+ m_ui.fileToolbar->hide();
+ m_ui.editToolbar->hide();
+ m_ui.channelsToolbar->hide();
+ }
}
// Show/hide the main program window statusbar.
void MainForm::viewStatusbar ( bool bOn )
{
- if (bOn)
- statusBar()->show();
- else
- statusBar()->hide();
+ if (bOn)
+ statusBar()->show();
+ else
+ statusBar()->hide();
}
// Show/hide the messages window logger.
void MainForm::viewMessages ( bool bOn )
{
- if (bOn)
- m_pMessages->show();
- else
- m_pMessages->hide();
+ if (bOn)
+ m_pMessages->show();
+ else
+ m_pMessages->hide();
}
@@ -1388,7 +1580,7 @@
} else {
m_pInstrumentListForm->show();
m_pInstrumentListForm->raise();
- m_pInstrumentListForm->setActiveWindow();
+ m_pInstrumentListForm->activateWindow();
}
}
}
@@ -1407,7 +1599,7 @@
} else {
m_pDeviceForm->show();
m_pDeviceForm->raise();
- m_pDeviceForm->setActiveWindow();
+ m_pDeviceForm->activateWindow();
}
}
}
@@ -1416,85 +1608,95 @@
// Show options dialog.
void MainForm::viewOptions (void)
{
- if (m_pOptions == NULL)
- return;
+ if (m_pOptions == NULL)
+ return;
- OptionsForm* pOptionsForm = new OptionsForm(this);
- if (pOptionsForm) {
- // Check out some initial nullities(tm)...
- ChannelStrip* pChannelStrip = activeChannelStrip();
- if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)
- m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();
- if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)
- m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
- // To track down deferred or immediate changes.
- QString sOldServerHost = m_pOptions->sServerHost;
- int iOldServerPort = m_pOptions->iServerPort;
- int iOldServerTimeout = m_pOptions->iServerTimeout;
- bool bOldServerStart = m_pOptions->bServerStart;
- QString sOldServerCmdLine = m_pOptions->sServerCmdLine;
- QString sOldDisplayFont = m_pOptions->sDisplayFont;
- bool bOldDisplayEffect = m_pOptions->bDisplayEffect;
- int iOldMaxVolume = m_pOptions->iMaxVolume;
- QString sOldMessagesFont = m_pOptions->sMessagesFont;
- bool bOldKeepOnTop = m_pOptions->bKeepOnTop;
- bool bOldStdoutCapture = m_pOptions->bStdoutCapture;
- int bOldMessagesLimit = m_pOptions->bMessagesLimit;
- int iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;
- bool bOldCompletePath = m_pOptions->bCompletePath;
- bool bOldInstrumentNames = m_pOptions->bInstrumentNames;
- int iOldMaxRecentFiles = m_pOptions->iMaxRecentFiles;
- // Load the current setup settings.
- pOptionsForm->setup(m_pOptions);
- // Show the setup dialog...
- if (pOptionsForm->exec()) {
- // Warn if something will be only effective on next run.
- if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
- (!bOldStdoutCapture && m_pOptions->bStdoutCapture) ||
- ( bOldKeepOnTop && !m_pOptions->bKeepOnTop) ||
- (!bOldKeepOnTop && m_pOptions->bKeepOnTop)) {
- QMessageBox::information(this,
+ OptionsForm* pOptionsForm = new OptionsForm(this);
+ if (pOptionsForm) {
+ // Check out some initial nullities(tm)...
+ ChannelStrip* pChannelStrip = activeChannelStrip();
+ if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)
+ m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();
+ if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)
+ m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
+ // To track down deferred or immediate changes.
+ QString sOldServerHost = m_pOptions->sServerHost;
+ int iOldServerPort = m_pOptions->iServerPort;
+ int iOldServerTimeout = m_pOptions->iServerTimeout;
+ bool bOldServerStart = m_pOptions->bServerStart;
+ QString sOldServerCmdLine = m_pOptions->sServerCmdLine;
+ bool bOldMessagesLog = m_pOptions->bMessagesLog;
+ QString sOldMessagesLogPath = m_pOptions->sMessagesLogPath;
+ QString sOldDisplayFont = m_pOptions->sDisplayFont;
+ bool bOldDisplayEffect = m_pOptions->bDisplayEffect;
+ int iOldMaxVolume = m_pOptions->iMaxVolume;
+ QString sOldMessagesFont = m_pOptions->sMessagesFont;
+ bool bOldKeepOnTop = m_pOptions->bKeepOnTop;
+ bool bOldStdoutCapture = m_pOptions->bStdoutCapture;
+ int bOldMessagesLimit = m_pOptions->bMessagesLimit;
+ int iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;
+ bool bOldCompletePath = m_pOptions->bCompletePath;
+ bool bOldInstrumentNames = m_pOptions->bInstrumentNames;
+ int iOldMaxRecentFiles = m_pOptions->iMaxRecentFiles;
+ int iOldBaseFontSize = m_pOptions->iBaseFontSize;
+ // Load the current setup settings.
+ pOptionsForm->setup(m_pOptions);
+ // Show the setup dialog...
+ if (pOptionsForm->exec()) {
+ // Warn if something will be only effective on next run.
+ if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
+ (!bOldStdoutCapture && m_pOptions->bStdoutCapture) ||
+ ( bOldKeepOnTop && !m_pOptions->bKeepOnTop) ||
+ (!bOldKeepOnTop && m_pOptions->bKeepOnTop) ||
+ (iOldBaseFontSize != m_pOptions->iBaseFontSize)) {
+ QMessageBox::information(this,
QSAMPLER_TITLE ": " + tr("Information"),
- tr("Some settings may be only effective\n"
- "next time you start this program."), tr("OK"));
- updateMessagesCapture();
- }
- // Check wheather something immediate has changed.
- if (( bOldCompletePath && !m_pOptions->bCompletePath) ||
- (!bOldCompletePath && m_pOptions->bCompletePath) ||
- (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
- updateRecentFilesMenu();
- if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||
- (!bOldInstrumentNames && m_pOptions->bInstrumentNames))
- updateInstrumentNames();
- if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||
- (!bOldDisplayEffect && m_pOptions->bDisplayEffect))
- updateDisplayEffect();
- if (sOldDisplayFont != m_pOptions->sDisplayFont)
- updateDisplayFont();
- if (iOldMaxVolume != m_pOptions->iMaxVolume)
- updateMaxVolume();
- if (sOldMessagesFont != m_pOptions->sMessagesFont)
- updateMessagesFont();
- if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||
- (!bOldMessagesLimit && m_pOptions->bMessagesLimit) ||
- (iOldMessagesLimitLines != m_pOptions->iMessagesLimitLines))
- updateMessagesLimit();
- // And now the main thing, whether we'll do client/server recycling?
- if ((sOldServerHost != m_pOptions->sServerHost) ||
- (iOldServerPort != m_pOptions->iServerPort) ||
- (iOldServerTimeout != m_pOptions->iServerTimeout) ||
- ( bOldServerStart && !m_pOptions->bServerStart) ||
- (!bOldServerStart && m_pOptions->bServerStart) ||
- (sOldServerCmdLine != m_pOptions->sServerCmdLine && m_pOptions->bServerStart))
- fileRestart();
- }
- // Done.
- delete pOptionsForm;
- }
+ tr("Some settings may be only effective\n"
+ "next time you start this program."));
+ updateMessagesCapture();
+ }
+ // Check wheather something immediate has changed.
+ if (( bOldMessagesLog && !m_pOptions->bMessagesLog) ||
+ (!bOldMessagesLog && m_pOptions->bMessagesLog) ||
+ (sOldMessagesLogPath != m_pOptions->sMessagesLogPath))
+ m_pMessages->setLogging(
+ m_pOptions->bMessagesLog, m_pOptions->sMessagesLogPath);
+ if (( bOldCompletePath && !m_pOptions->bCompletePath) ||
+ (!bOldCompletePath && m_pOptions->bCompletePath) ||
+ (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
+ updateRecentFilesMenu();
+ if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||
+ (!bOldInstrumentNames && m_pOptions->bInstrumentNames))
+ updateInstrumentNames();
+ if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||
+ (!bOldDisplayEffect && m_pOptions->bDisplayEffect))
+ updateDisplayEffect();
+ if (sOldDisplayFont != m_pOptions->sDisplayFont)
+ updateDisplayFont();
+ if (iOldMaxVolume != m_pOptions->iMaxVolume)
+ updateMaxVolume();
+ if (sOldMessagesFont != m_pOptions->sMessagesFont)
+ updateMessagesFont();
+ if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||
+ (!bOldMessagesLimit && m_pOptions->bMessagesLimit) ||
+ (iOldMessagesLimitLines != m_pOptions->iMessagesLimitLines))
+ updateMessagesLimit();
+ // And now the main thing, whether we'll do client/server recycling?
+ if ((sOldServerHost != m_pOptions->sServerHost) ||
+ (iOldServerPort != m_pOptions->iServerPort) ||
+ (iOldServerTimeout != m_pOptions->iServerTimeout) ||
+ ( bOldServerStart && !m_pOptions->bServerStart) ||
+ (!bOldServerStart && m_pOptions->bServerStart) ||
+ (sOldServerCmdLine != m_pOptions->sServerCmdLine
+ && m_pOptions->bServerStart))
+ fileRestart();
+ }
+ // Done.
+ delete pOptionsForm;
+ }
- // This makes it.
- stabilizeForm();
+ // This makes it.
+ stabilizeForm();
}
@@ -1504,47 +1706,48 @@
// Arrange channel strips.
void MainForm::channelsArrange (void)
{
- // Full width vertical tiling
- QWidgetList wlist = m_pWorkspace->windowList();
- if (wlist.isEmpty())
- return;
-
- m_pWorkspace->setUpdatesEnabled(false);
- int y = 0;
- for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
- ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
- /* if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {
- // Prevent flicker...
- pChannelStrip->hide();
- pChannelStrip->showNormal();
- } */
- pChannelStrip->adjustSize();
- int iWidth = m_pWorkspace->width();
- if (iWidth < pChannelStrip->width())
- iWidth = pChannelStrip->width();
- // int iHeight = pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();
- int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();
- pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);
- y += iHeight;
- }
- m_pWorkspace->setUpdatesEnabled(true);
+ // Full width vertical tiling
+ QWidgetList wlist = m_pWorkspace->windowList();
+ if (wlist.isEmpty())
+ return;
- stabilizeForm();
+ m_pWorkspace->setUpdatesEnabled(false);
+ int y = 0;
+ for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
+ ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
+ /* if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {
+ // Prevent flicker...
+ pChannelStrip->hide();
+ pChannelStrip->showNormal();
+ } */
+ pChannelStrip->adjustSize();
+ int iWidth = m_pWorkspace->width();
+ if (iWidth < pChannelStrip->width())
+ iWidth = pChannelStrip->width();
+ // int iHeight = pChannelStrip->height()
+ // + pChannelStrip->parentWidget()->baseSize().height();
+ int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();
+ pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);
+ y += iHeight;
+ }
+ m_pWorkspace->setUpdatesEnabled(true);
+
+ stabilizeForm();
}
// Auto-arrange channel strips.
void MainForm::channelsAutoArrange ( bool bOn )
{
- if (m_pOptions == NULL)
- return;
+ if (m_pOptions == NULL)
+ return;
- // Toggle the auto-arrange flag.
- m_pOptions->bAutoArrange = bOn;
+ // Toggle the auto-arrange flag.
+ m_pOptions->bAutoArrange = bOn;
- // If on, update whole workspace...
- if (m_pOptions->bAutoArrange)
- channelsArrange();
+ // If on, update whole workspace...
+ if (m_pOptions->bAutoArrange)
+ channelsArrange();
}
@@ -1554,88 +1757,104 @@
// Show information about the Qt toolkit.
void MainForm::helpAboutQt (void)
{
- QMessageBox::aboutQt(this);
+ QMessageBox::aboutQt(this);
}
// Show information about application program.
void MainForm::helpAbout (void)
{
- // Stuff the about box text...
- QString sText = "\n";
- sText += "" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "
\n";
- sText += "
\n";
- sText += tr("Version") + ": " QSAMPLER_VERSION "
\n";
- sText += "" + tr("Build") + ": " __DATE__ " " __TIME__ "
\n";
+ // Stuff the about box text...
+ QString sText = "
\n";
+ sText += "" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "
\n";
+ sText += "
\n";
+ sText += tr("Version") + ": " QSAMPLER_VERSION "
\n";
+ sText += "" + tr("Build") + ": " __DATE__ " " __TIME__ "
\n";
#ifdef CONFIG_DEBUG
- sText += "";
- sText += tr("Debugging option enabled.");
- sText += "
";
+ sText += "";
+ sText += tr("Debugging option enabled.");
+ sText += "
";
#endif
#ifndef CONFIG_LIBGIG
- sText += "";
- sText += tr("GIG (libgig) file support disabled.");
- sText += "
";
+ sText += "";
+ sText += tr("GIG (libgig) file support disabled.");
+ sText += "
";
#endif
#ifndef CONFIG_INSTRUMENT_NAME
- sText += "";
- sText += tr("LSCP (liblscp) instrument_name support disabled.");
- sText += "
";
+ sText += "";
+ sText += tr("LSCP (liblscp) instrument_name support disabled.");
+ sText += "
";
#endif
#ifndef CONFIG_MUTE_SOLO
- sText += "";
- sText += tr("Sampler channel Mute/Solo support disabled.");
- sText += "
";
+ sText += "";
+ sText += tr("Sampler channel Mute/Solo support disabled.");
+ sText += "
";
#endif
#ifndef CONFIG_AUDIO_ROUTING
- sText += "";
- sText += tr("LSCP (liblscp) audio_routing support disabled.");
- sText += "
";
+ sText += "";
+ sText += tr("LSCP (liblscp) audio_routing support disabled.");
+ sText += "
";
#endif
#ifndef CONFIG_FXSEND
- sText += "";
- sText += tr("Sampler channel Effect Sends support disabled.");
- sText += "
";
+ sText += "";
+ sText += tr("Sampler channel Effect Sends support disabled.");
+ sText += "
";
#endif
#ifndef CONFIG_VOLUME
- sText += "";
- sText += tr("Global volume support disabled.");
- sText += "
";
+ sText += "";
+ sText += tr("Global volume support disabled.");
+ sText += "
";
#endif
#ifndef CONFIG_MIDI_INSTRUMENT
- sText += "";
- sText += tr("MIDI instrument mapping support disabled.");
- sText += "
";
+ sText += "";
+ sText += tr("MIDI instrument mapping support disabled.");
+ sText += "
";
#endif
#ifndef CONFIG_EDIT_INSTRUMENT
- sText += "";
- sText += tr("Instrument editing support disabled.");
- sText += "
";
-#endif
- sText += "
\n";
- sText += tr("Using") + ": ";
- sText += ::lscp_client_package();
- sText += " ";
- sText += ::lscp_client_version();
+ sText += "";
+ sText += tr("Instrument editing support disabled.");
+ sText += "
";
+#endif
+#ifndef CONFIG_EVENT_CHANNEL_MIDI
+ sText += "";
+ sText += tr("Channel MIDI event support disabled.");
+ sText += "
";
+#endif
+#ifndef CONFIG_EVENT_DEVICE_MIDI
+ sText += "";
+ sText += tr("Device MIDI event support disabled.");
+ sText += "
";
+#endif
+#ifndef CONFIG_MAX_VOICES
+ sText += "";
+ sText += tr("Runtime max. voices / disk streams support disabled.");
+ sText += "
";
+#endif
+ sText += "
\n";
+ sText += tr("Using") + ": ";
+ sText += ::lscp_client_package();
+ sText += " ";
+ sText += ::lscp_client_version();
#ifdef CONFIG_LIBGIG
- sText += ", ";
- sText += gig::libraryName().c_str();
- sText += " ";
- sText += gig::libraryVersion().c_str();
-#endif
- sText += "
\n";
- sText += "
\n";
- sText += tr("Website") + ": " QSAMPLER_WEBSITE "
\n";
- sText += "
\n";
- sText += "";
- sText += QSAMPLER_COPYRIGHT "
\n";
- sText += "
\n";
- sText += tr("This program is free software; you can redistribute it and/or modify it") + "
\n";
- sText += tr("under the terms of the GNU General Public License version 2 or later.");
- sText += "";
- sText += "
\n";
+ sText += ", ";
+ sText += gig::libraryName().c_str();
+ sText += " ";
+ sText += gig::libraryVersion().c_str();
+#endif
+ sText += "
\n";
+ sText += "
\n";
+ sText += tr("Website") + ": " QSAMPLER_WEBSITE "
\n";
+ sText += "
\n";
+ sText += "";
+ sText += QSAMPLER_COPYRIGHT "
\n";
+ sText += QSAMPLER_COPYRIGHT2 "
\n";
+ sText += "
\n";
+ sText += tr("This program is free software; you can redistribute it and/or modify it") + "
\n";
+ sText += tr("under the terms of the GNU General Public License version 2 or later.");
+ sText += "";
+ sText += "
\n";
- QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);
+ QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);
}
@@ -1644,76 +1863,73 @@
void MainForm::stabilizeForm (void)
{
- // Update the main application caption...
- QString sSessionName = sessionName(m_sFilename);
- if (m_iDirtyCount > 0)
- sSessionName += " *";
- setCaption(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));
-
- // Update the main menu state...
- ChannelStrip* pChannelStrip = activeChannelStrip();
- bool bHasClient = (m_pOptions != NULL && m_pClient != NULL);
- bool bHasChannel = (bHasClient && pChannelStrip != NULL);
- ui.fileNewAction->setEnabled(bHasClient);
- ui.fileOpenAction->setEnabled(bHasClient);
- ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
- ui.fileSaveAsAction->setEnabled(bHasClient);
- ui.fileResetAction->setEnabled(bHasClient);
- ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);
- ui.editAddChannelAction->setEnabled(bHasClient);
- ui.editRemoveChannelAction->setEnabled(bHasChannel);
- ui.editSetupChannelAction->setEnabled(bHasChannel);
+ // Update the main application caption...
+ QString sSessionName = sessionName(m_sFilename);
+ if (m_iDirtyCount > 0)
+ sSessionName += " *";
+ setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));
+
+ // Update the main menu state...
+ ChannelStrip* pChannelStrip = activeChannelStrip();
+ bool bHasClient = (m_pOptions != NULL && m_pClient != NULL);
+ bool bHasChannel = (bHasClient && pChannelStrip != NULL);
+ m_ui.fileNewAction->setEnabled(bHasClient);
+ m_ui.fileOpenAction->setEnabled(bHasClient);
+ m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
+ m_ui.fileSaveAsAction->setEnabled(bHasClient);
+ m_ui.fileResetAction->setEnabled(bHasClient);
+ m_ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);
+ m_ui.editAddChannelAction->setEnabled(bHasClient);
+ m_ui.editRemoveChannelAction->setEnabled(bHasChannel);
+ m_ui.editSetupChannelAction->setEnabled(bHasChannel);
#ifdef CONFIG_EDIT_INSTRUMENT
- ui.editEditChannelAction->setEnabled(bHasChannel);
+ m_ui.editEditChannelAction->setEnabled(bHasChannel);
#else
- ui.editEditChannelAction->setEnabled(false);
+ m_ui.editEditChannelAction->setEnabled(false);
#endif
- ui.editResetChannelAction->setEnabled(bHasChannel);
- ui.editResetAllChannelsAction->setEnabled(bHasChannel);
- ui.viewMessagesAction->setOn(m_pMessages && m_pMessages->isVisible());
+ m_ui.editResetChannelAction->setEnabled(bHasChannel);
+ m_ui.editResetAllChannelsAction->setEnabled(bHasChannel);
+ m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());
#ifdef CONFIG_MIDI_INSTRUMENT
- ui.viewInstrumentsAction->setOn(m_pInstrumentListForm
+ m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm
&& m_pInstrumentListForm->isVisible());
- ui.viewInstrumentsAction->setEnabled(bHasClient);
+ m_ui.viewInstrumentsAction->setEnabled(bHasClient);
#else
- ui.viewInstrumentsAction->setEnabled(false);
+ m_ui.viewInstrumentsAction->setEnabled(false);
#endif
- ui.viewDevicesAction->setOn(m_pDeviceForm
+ m_ui.viewDevicesAction->setChecked(m_pDeviceForm
&& m_pDeviceForm->isVisible());
- ui.viewDevicesAction->setEnabled(bHasClient);
- ui.channelsArrangeAction->setEnabled(bHasChannel);
+ m_ui.viewDevicesAction->setEnabled(bHasClient);
+ m_ui.channelsArrangeAction->setEnabled(bHasChannel);
#ifdef CONFIG_VOLUME
// Toolbar widgets are also affected...
- m_pVolumeSlider->setEnabled(bHasClient);
- m_pVolumeSpinBox->setEnabled(bHasClient);
+ m_pVolumeSlider->setEnabled(bHasClient);
+ m_pVolumeSpinBox->setEnabled(bHasClient);
#endif
- // Client/Server status...
- if (bHasClient) {
- m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));
- m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost + ":" + QString::number(m_pOptions->iServerPort));
- } else {
- m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();
- m_statusItem[QSAMPLER_STATUS_SERVER]->clear();
- }
- // Channel status...
- if (bHasChannel)
- m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->caption());
- else
- m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();
- // Session status...
- if (m_iDirtyCount > 0)
- m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));
- else
- m_statusItem[QSAMPLER_STATUS_SESSION]->clear();
-
- // Recent files menu.
- m_pRecentFilesMenu->setEnabled(bHasClient && m_pOptions->recentFiles.count() > 0);
-
- // Always make the latest message visible.
- if (m_pMessages)
- m_pMessages->scrollToBottom();
+ // Client/Server status...
+ if (bHasClient) {
+ m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));
+ m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost
+ + ':' + QString::number(m_pOptions->iServerPort));
+ } else {
+ m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();
+ m_statusItem[QSAMPLER_STATUS_SERVER]->clear();
+ }
+ // Channel status...
+ if (bHasChannel)
+ m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->windowTitle());
+ else
+ m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();
+ // Session status...
+ if (m_iDirtyCount > 0)
+ m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));
+ else
+ m_statusItem[QSAMPLER_STATUS_SESSION]->clear();
+
+ // Recent files menu.
+ m_ui.fileOpenRecentMenu->setEnabled(m_pOptions->recentFiles.count() > 0);
}
@@ -1753,15 +1969,15 @@
void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)
{
// Add this strip to the changed list...
- if (m_changedStrips.containsRef(pChannelStrip) == 0) {
+ if (!m_changedStrips.contains(pChannelStrip)) {
m_changedStrips.append(pChannelStrip);
pChannelStrip->resetErrorCount();
}
- // Just mark the dirty form.
- m_iDirtyCount++;
- // and update the form status...
- stabilizeForm();
+ // Just mark the dirty form.
+ m_iDirtyCount++;
+ // and update the form status...
+ stabilizeForm();
}
@@ -1781,17 +1997,34 @@
if (iMaps < 0)
appendMessagesClient("lscp_get_midi_instrument_maps");
else if (iMaps < 1) {
- ::lscp_add_midi_instrument_map(m_pClient, tr("Chromatic").latin1());
- ::lscp_add_midi_instrument_map(m_pClient, tr("Drum Kits").latin1());
+ ::lscp_add_midi_instrument_map(m_pClient,
+ tr("Chromatic").toUtf8().constData());
+ ::lscp_add_midi_instrument_map(m_pClient,
+ tr("Drum Kits").toUtf8().constData());
}
#endif
+ updateAllChannelStrips(false);
+
+ // Do we auto-arrange?
+ if (m_pOptions && m_pOptions->bAutoArrange)
+ channelsArrange();
+
+ // Remember to refresh devices and instruments...
+ if (m_pInstrumentListForm)
+ m_pInstrumentListForm->refreshInstruments();
+ if (m_pDeviceForm)
+ m_pDeviceForm->refreshDevices();
+}
+
+void MainForm::updateAllChannelStrips(bool bRemoveDeadStrips) {
// Retrieve the current channel list.
int *piChannelIDs = ::lscp_list_channels(m_pClient);
if (piChannelIDs == NULL) {
if (::lscp_client_get_errno(m_pClient)) {
appendMessagesClient("lscp_list_channels");
- appendMessagesError(tr("Could not get current list of channels.\n\nSorry."));
+ appendMessagesError(
+ tr("Could not get current list of channels.\n\nSorry."));
}
} else {
// Try to (re)create each channel.
@@ -1799,161 +2032,167 @@
for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {
// Check if theres already a channel strip for this one...
if (!channelStrip(piChannelIDs[iChannel]))
- createChannelStrip(new qsamplerChannel(piChannelIDs[iChannel]));
+ createChannelStrip(new Channel(piChannelIDs[iChannel]));
+ }
+
+ // Do we auto-arrange?
+ if (m_pOptions && m_pOptions->bAutoArrange)
+ channelsArrange();
+
+ stabilizeForm();
+
+ // remove dead channel strips
+ if (bRemoveDeadStrips) {
+ for (int i = 0; channelStripAt(i); ++i) {
+ ChannelStrip* pChannelStrip = channelStripAt(i);
+ bool bExists = false;
+ for (int j = 0; piChannelIDs[j] >= 0; ++j) {
+ if (!pChannelStrip->channel()) break;
+ if (piChannelIDs[j] == pChannelStrip->channel()->channelID()) {
+ // strip exists, don't touch it
+ bExists = true;
+ break;
+ }
+ }
+ if (!bExists) destroyChannelStrip(pChannelStrip);
+ }
}
m_pWorkspace->setUpdatesEnabled(true);
}
-
- // Do we auto-arrange?
- if (m_pOptions && m_pOptions->bAutoArrange)
- channelsArrange();
-
- // Remember to refresh devices and instruments...
- if (m_pInstrumentListForm)
- m_pInstrumentListForm->refreshInstruments();
- if (m_pDeviceForm)
- m_pDeviceForm->refreshDevices();
}
-
// Update the recent files list and menu.
void MainForm::updateRecentFiles ( const QString& sFilename )
{
- if (m_pOptions == NULL)
- return;
-
- // Remove from list if already there (avoid duplicates)
- QStringList::Iterator iter = m_pOptions->recentFiles.find(sFilename);
- if (iter != m_pOptions->recentFiles.end())
- m_pOptions->recentFiles.remove(iter);
- // Put it to front...
- m_pOptions->recentFiles.push_front(sFilename);
+ if (m_pOptions == NULL)
+ return;
- // May update the menu.
- updateRecentFilesMenu();
+ // Remove from list if already there (avoid duplicates)
+ int iIndex = m_pOptions->recentFiles.indexOf(sFilename);
+ if (iIndex >= 0)
+ m_pOptions->recentFiles.removeAt(iIndex);
+ // Put it to front...
+ m_pOptions->recentFiles.push_front(sFilename);
}
// Update the recent files list and menu.
void MainForm::updateRecentFilesMenu (void)
{
- if (m_pOptions == NULL)
- return;
+ if (m_pOptions == NULL)
+ return;
+
+ // Time to keep the list under limits.
+ int iRecentFiles = m_pOptions->recentFiles.count();
+ while (iRecentFiles > m_pOptions->iMaxRecentFiles) {
+ m_pOptions->recentFiles.pop_back();
+ iRecentFiles--;
+ }
- // Time to keep the list under limits.
- int iRecentFiles = m_pOptions->recentFiles.count();
- while (iRecentFiles > m_pOptions->iMaxRecentFiles) {
- m_pOptions->recentFiles.pop_back();
- iRecentFiles--;
- }
-
- // rebuild the recent files menu...
- m_pRecentFilesMenu->clear();
- for (int i = 0; i < iRecentFiles; i++) {
- const QString& sFilename = m_pOptions->recentFiles[i];
- if (QFileInfo(sFilename).exists()) {
- m_pRecentFilesMenu->insertItem(QString("&%1 %2")
- .arg(i + 1).arg(sessionName(sFilename)),
- this, SLOT(fileOpenRecent(int)), 0, i);
- }
- }
+ // Rebuild the recent files menu...
+ m_ui.fileOpenRecentMenu->clear();
+ for (int i = 0; i < iRecentFiles; i++) {
+ const QString& sFilename = m_pOptions->recentFiles[i];
+ if (QFileInfo(sFilename).exists()) {
+ QAction *pAction = m_ui.fileOpenRecentMenu->addAction(
+ QString("&%1 %2").arg(i + 1).arg(sessionName(sFilename)),
+ this, SLOT(fileOpenRecent()));
+ pAction->setData(i);
+ }
+ }
}
// Force update of the channels instrument names mode.
void MainForm::updateInstrumentNames (void)
{
- // Full channel list update...
- QWidgetList wlist = m_pWorkspace->windowList();
- if (wlist.isEmpty())
- return;
-
- m_pWorkspace->setUpdatesEnabled(false);
- for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
- ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);
- if (pChannelStrip)
- pChannelStrip->updateInstrumentName(true);
- }
- m_pWorkspace->setUpdatesEnabled(true);
+ // Full channel list update...
+ QWidgetList wlist = m_pWorkspace->windowList();
+ if (wlist.isEmpty())
+ return;
+
+ m_pWorkspace->setUpdatesEnabled(false);
+ for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
+ ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);
+ if (pChannelStrip)
+ pChannelStrip->updateInstrumentName(true);
+ }
+ m_pWorkspace->setUpdatesEnabled(true);
}
// Force update of the channels display font.
void MainForm::updateDisplayFont (void)
{
- if (m_pOptions == NULL)
- return;
+ if (m_pOptions == NULL)
+ return;
+
+ // Check if display font is legal.
+ if (m_pOptions->sDisplayFont.isEmpty())
+ return;
+ // Realize it.
+ QFont font;
+ if (!font.fromString(m_pOptions->sDisplayFont))
+ return;
+
+ // Full channel list update...
+ QWidgetList wlist = m_pWorkspace->windowList();
+ if (wlist.isEmpty())
+ return;
- // Check if display font is legal.
- if (m_pOptions->sDisplayFont.isEmpty())
- return;
- // Realize it.
- QFont font;
- if (!font.fromString(m_pOptions->sDisplayFont))
- return;
-
- // Full channel list update...
- QWidgetList wlist = m_pWorkspace->windowList();
- if (wlist.isEmpty())
- return;
-
- m_pWorkspace->setUpdatesEnabled(false);
- for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
- ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
- if (pChannelStrip)
- pChannelStrip->setDisplayFont(font);
- }
- m_pWorkspace->setUpdatesEnabled(true);
+ m_pWorkspace->setUpdatesEnabled(false);
+ for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
+ ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
+ if (pChannelStrip)
+ pChannelStrip->setDisplayFont(font);
+ }
+ m_pWorkspace->setUpdatesEnabled(true);
}
// Update channel strips background effect.
void MainForm::updateDisplayEffect (void)
{
- QPixmap pm;
- if (m_pOptions->bDisplayEffect)
- pm = QPixmap(":/qsampler/pixmaps/displaybg1.png");
-
- // Full channel list update...
- QWidgetList wlist = m_pWorkspace->windowList();
- if (wlist.isEmpty())
- return;
-
- m_pWorkspace->setUpdatesEnabled(false);
- for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
- ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
- if (pChannelStrip)
- pChannelStrip->setDisplayBackground(pm);
- }
- m_pWorkspace->setUpdatesEnabled(true);
+ // Full channel list update...
+ QWidgetList wlist = m_pWorkspace->windowList();
+ if (wlist.isEmpty())
+ return;
+
+ m_pWorkspace->setUpdatesEnabled(false);
+ for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
+ ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
+ if (pChannelStrip)
+ pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
+ }
+ m_pWorkspace->setUpdatesEnabled(true);
}
// Force update of the channels maximum volume setting.
void MainForm::updateMaxVolume (void)
{
- if (m_pOptions == NULL)
- return;
+ if (m_pOptions == NULL)
+ return;
#ifdef CONFIG_VOLUME
m_iVolumeChanging++;
- m_pVolumeSlider->setMaxValue(m_pOptions->iMaxVolume);
- m_pVolumeSpinBox->setMaxValue(m_pOptions->iMaxVolume);
+ m_pVolumeSlider->setMaximum(m_pOptions->iMaxVolume);
+ m_pVolumeSpinBox->setMaximum(m_pOptions->iMaxVolume);
m_iVolumeChanging--;
#endif
- // Full channel list update...
- QWidgetList wlist = m_pWorkspace->windowList();
- if (wlist.isEmpty())
- return;
-
- m_pWorkspace->setUpdatesEnabled(false);
- for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
- ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
- if (pChannelStrip)
- pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
- }
- m_pWorkspace->setUpdatesEnabled(true);
+ // Full channel list update...
+ QWidgetList wlist = m_pWorkspace->windowList();
+ if (wlist.isEmpty())
+ return;
+
+ m_pWorkspace->setUpdatesEnabled(false);
+ for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
+ ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
+ if (pChannelStrip)
+ pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
+ }
+ m_pWorkspace->setUpdatesEnabled(true);
}
@@ -1963,93 +2202,93 @@
// Messages output methods.
void MainForm::appendMessages( const QString& s )
{
- if (m_pMessages)
- m_pMessages->appendMessages(s);
+ if (m_pMessages)
+ m_pMessages->appendMessages(s);
- statusBar()->message(s, 3000);
+ statusBar()->showMessage(s, 3000);
}
void MainForm::appendMessagesColor( const QString& s, const QString& c )
{
- if (m_pMessages)
- m_pMessages->appendMessagesColor(s, c);
+ if (m_pMessages)
+ m_pMessages->appendMessagesColor(s, c);
- statusBar()->message(s, 3000);
+ statusBar()->showMessage(s, 3000);
}
void MainForm::appendMessagesText( const QString& s )
{
- if (m_pMessages)
- m_pMessages->appendMessagesText(s);
+ if (m_pMessages)
+ m_pMessages->appendMessagesText(s);
}
void MainForm::appendMessagesError( const QString& s )
{
- if (m_pMessages)
- m_pMessages->show();
+ if (m_pMessages)
+ m_pMessages->show();
- appendMessagesColor(s.simplifyWhiteSpace(), "#ff0000");
+ appendMessagesColor(s.simplified(), "#ff0000");
// Make it look responsive...:)
- QApplication::processEvents(QEventLoop::ExcludeUserInput);
+ QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
- QMessageBox::critical(this,
- QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));
+ QMessageBox::critical(this,
+ QSAMPLER_TITLE ": " + tr("Error"), s, QMessageBox::Cancel);
}
// This is a special message format, just for client results.
void MainForm::appendMessagesClient( const QString& s )
{
- if (m_pClient == NULL)
- return;
+ if (m_pClient == NULL)
+ return;
- appendMessagesColor(s + QString(": %1 (errno=%2)")
- .arg(::lscp_client_get_result(m_pClient))
- .arg(::lscp_client_get_errno(m_pClient)), "#996666");
+ appendMessagesColor(s + QString(": %1 (errno=%2)")
+ .arg(::lscp_client_get_result(m_pClient))
+ .arg(::lscp_client_get_errno(m_pClient)), "#996666");
// Make it look responsive...:)
- QApplication::processEvents(QEventLoop::ExcludeUserInput);
+ QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
}
// Force update of the messages font.
void MainForm::updateMessagesFont (void)
{
- if (m_pOptions == NULL)
- return;
+ if (m_pOptions == NULL)
+ return;
- if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {
- QFont font;
- if (font.fromString(m_pOptions->sMessagesFont))
- m_pMessages->setMessagesFont(font);
- }
+ if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {
+ QFont font;
+ if (font.fromString(m_pOptions->sMessagesFont))
+ m_pMessages->setMessagesFont(font);
+ }
}
// Update messages window line limit.
void MainForm::updateMessagesLimit (void)
{
- if (m_pOptions == NULL)
- return;
+ if (m_pOptions == NULL)
+ return;
- if (m_pMessages) {
- if (m_pOptions->bMessagesLimit)
- m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);
- else
- m_pMessages->setMessagesLimit(-1);
- }
+ if (m_pMessages) {
+ if (m_pOptions->bMessagesLimit)
+ m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);
+ else
+ m_pMessages->setMessagesLimit(-1);
+ }
}
// Enablement of the messages capture feature.
void MainForm::updateMessagesCapture (void)
{
- if (m_pOptions == NULL)
- return;
+ if (m_pOptions == NULL)
+ return;
- if (m_pMessages)
- m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);
+ if (m_pMessages)
+ m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);
}
@@ -2057,80 +2296,79 @@
// qsamplerMainForm -- MDI channel strip management.
// The channel strip creation executive.
-ChannelStrip* MainForm::createChannelStrip(qsamplerChannel* pChannel)
+ChannelStrip* MainForm::createChannelStrip ( Channel *pChannel )
{
- if (m_pClient == NULL || pChannel == NULL)
- return NULL;
+ if (m_pClient == NULL || pChannel == NULL)
+ return NULL;
- // Prepare for auto-arrange?
- ChannelStrip* pChannelStrip = NULL;
- int y = 0;
- if (m_pOptions && m_pOptions->bAutoArrange) {
- QWidgetList wlist = m_pWorkspace->windowList();
- for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
- pChannelStrip = (ChannelStrip *) wlist.at(iChannel);
- if (pChannelStrip) {
- // y += pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();
- y += pChannelStrip->parentWidget()->frameGeometry().height();
- }
- }
- }
+ // Add a new channel itema...
+ ChannelStrip *pChannelStrip = new ChannelStrip();
+ if (pChannelStrip == NULL)
+ return NULL;
+
+ // Set some initial channel strip options...
+ if (m_pOptions) {
+ // Background display effect...
+ pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
+ // We'll need a display font.
+ QFont font;
+ if (font.fromString(m_pOptions->sDisplayFont))
+ pChannelStrip->setDisplayFont(font);
+ // Maximum allowed volume setting.
+ pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
+ }
+
+ // Add it to workspace...
+ m_pWorkspace->addWindow(pChannelStrip, Qt::FramelessWindowHint);
- // Add a new channel itema...
- Qt::WFlags wflags = Qt::WStyle_Customize | Qt::WStyle_Tool | Qt::WStyle_Title | Qt::WStyle_NoBorder;
- pChannelStrip = new ChannelStrip(m_pWorkspace, wflags);
- if (pChannelStrip == NULL)
- return NULL;
+ // Actual channel strip setup...
+ pChannelStrip->setup(pChannel);
- // Actual channel strip setup...
- pChannelStrip->setup(pChannel);
QObject::connect(pChannelStrip,
- SIGNAL(channelChanged(qsamplerChannelStrip *)),
- SLOT(channelStripChanged(qsamplerChannelStrip *)));
- // Set some initial aesthetic options...
- if (m_pOptions) {
- // Background display effect...
- pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
- // We'll need a display font.
- QFont font;
- if (font.fromString(m_pOptions->sDisplayFont))
- pChannelStrip->setDisplayFont(font);
- // Maximum allowed volume setting.
- pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
- }
-
- // Now we show up us to the world.
- pChannelStrip->show();
- // Only then, we'll auto-arrange...
- if (m_pOptions && m_pOptions->bAutoArrange) {
- int iWidth = m_pWorkspace->width();
- // int iHeight = pChannel->height() + pChannel->parentWidget()->baseSize().height();
- int iHeight = pChannelStrip->parentWidget()->frameGeometry().height(); pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);
- }
+ SIGNAL(channelChanged(ChannelStrip*)),
+ SLOT(channelStripChanged(ChannelStrip*)));
+
+ // Now we show up us to the world.
+ pChannelStrip->show();
// This is pretty new, so we'll watch for it closely.
channelStripChanged(pChannelStrip);
- // Return our successful reference...
- return pChannelStrip;
+ // Return our successful reference...
+ return pChannelStrip;
}
+void MainForm::destroyChannelStrip(ChannelStrip* pChannelStrip) {
+ // Just delete the channel strip.
+ delete pChannelStrip;
+
+ // Do we auto-arrange?
+ if (m_pOptions && m_pOptions->bAutoArrange)
+ channelsArrange();
+
+ stabilizeForm();
+}
// Retrieve the active channel strip.
ChannelStrip* MainForm::activeChannelStrip (void)
{
- return (ChannelStrip*) m_pWorkspace->activeWindow();
+ return static_cast (m_pWorkspace->activeWindow());
}
// Retrieve a channel strip by index.
ChannelStrip* MainForm::channelStripAt ( int iChannel )
{
- QWidgetList wlist = m_pWorkspace->windowList();
- if (wlist.isEmpty())
- return NULL;
+ if (!m_pWorkspace) return NULL;
+
+ QWidgetList wlist = m_pWorkspace->windowList();
+ if (wlist.isEmpty())
+ return NULL;
- return (ChannelStrip*) wlist.at(iChannel);
+ if (iChannel < 0 || iChannel >= wlist.size())
+ return NULL;
+
+ return dynamic_cast (wlist.at(iChannel));
}
@@ -2142,9 +2380,10 @@
return NULL;
for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
- ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
+ ChannelStrip* pChannelStrip
+ = static_cast (wlist.at(iChannel));
if (pChannelStrip) {
- qsamplerChannel *pChannel = pChannelStrip->channel();
+ Channel *pChannel = pChannelStrip->channel();
if (pChannel && pChannel->channelID() == iChannelID)
return pChannelStrip;
}
@@ -2158,32 +2397,42 @@
// Construct the windows menu.
void MainForm::channelsMenuAboutToShow (void)
{
- ui.channelsMenu->clear();
- ui.channelsArrangeAction->addTo(ui.channelsMenu);
- ui.channelsAutoArrangeAction->addTo(ui.channelsMenu);
-
- QWidgetList wlist = m_pWorkspace->windowList();
- if (!wlist.isEmpty()) {
- ui.channelsMenu->insertSeparator();
- for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
- ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
- if (pChannelStrip) {
- int iItemID = ui.channelsMenu->insertItem(pChannelStrip->caption(), this, SLOT(channelsMenuActivated(int)));
- ui.channelsMenu->setItemParameter(iItemID, iChannel);
- ui.channelsMenu->setItemChecked(iItemID, activeChannelStrip() == pChannelStrip);
- }
- }
- }
+ m_ui.channelsMenu->clear();
+ m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);
+ m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);
+
+ QWidgetList wlist = m_pWorkspace->windowList();
+ if (!wlist.isEmpty()) {
+ m_ui.channelsMenu->addSeparator();
+ for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
+ ChannelStrip* pChannelStrip
+ = static_cast (wlist.at(iChannel));
+ if (pChannelStrip) {
+ QAction *pAction = m_ui.channelsMenu->addAction(
+ pChannelStrip->windowTitle(),
+ this, SLOT(channelsMenuActivated()));
+ pAction->setCheckable(true);
+ pAction->setChecked(activeChannelStrip() == pChannelStrip);
+ pAction->setData(iChannel);
+ }
+ }
+ }
}
// Windows menu activation slot
-void MainForm::channelsMenuActivated ( int iChannel )
+void MainForm::channelsMenuActivated (void)
{
- ChannelStrip* pChannelStrip = channelStripAt(iChannel);
- if (pChannelStrip)
- pChannelStrip->showNormal();
- pChannelStrip->setFocus();
+ // Retrive channel index from action data...
+ QAction *pAction = qobject_cast (sender());
+ if (pAction == NULL)
+ return;
+
+ ChannelStrip* pChannelStrip = channelStripAt(pAction->data().toInt());
+ if (pChannelStrip) {
+ pChannelStrip->showNormal();
+ pChannelStrip->setFocus();
+ }
}
@@ -2193,43 +2442,45 @@
// Set the pseudo-timer delay schedule.
void MainForm::startSchedule ( int iStartDelay )
{
- m_iStartDelay = 1 + (iStartDelay * 1000);
- m_iTimerDelay = 0;
+ m_iStartDelay = 1 + (iStartDelay * 1000);
+ m_iTimerDelay = 0;
}
// Suspend the pseudo-timer delay schedule.
void MainForm::stopSchedule (void)
{
- m_iStartDelay = 0;
- m_iTimerDelay = 0;
+ m_iStartDelay = 0;
+ m_iTimerDelay = 0;
}
// Timer slot funtion.
void MainForm::timerSlot (void)
{
- if (m_pOptions == NULL)
- return;
+ if (m_pOptions == NULL)
+ return;
- // Is it the first shot on server start after a few delay?
- if (m_iTimerDelay < m_iStartDelay) {
- m_iTimerDelay += QSAMPLER_TIMER_MSECS;
- if (m_iTimerDelay >= m_iStartDelay) {
- // If we cannot start it now, maybe a lil'mo'later ;)
- if (!startClient()) {
- m_iStartDelay += m_iTimerDelay;
- m_iTimerDelay = 0;
- }
- }
- }
+ // Is it the first shot on server start after a few delay?
+ if (m_iTimerDelay < m_iStartDelay) {
+ m_iTimerDelay += QSAMPLER_TIMER_MSECS;
+ if (m_iTimerDelay >= m_iStartDelay) {
+ // If we cannot start it now, maybe a lil'mo'later ;)
+ if (!startClient()) {
+ m_iStartDelay += m_iTimerDelay;
+ m_iTimerDelay = 0;
+ }
+ }
+ }
if (m_pClient) {
// Update the channel information for each pending strip...
- if (m_changedStrips.count() > 0) {
- for (ChannelStrip* pChannelStrip = m_changedStrips.first();
- pChannelStrip; pChannelStrip = m_changedStrips.next()) {
- // If successfull, remove from pending list...
- if (pChannelStrip->updateChannelInfo())
- m_changedStrips.remove(pChannelStrip);
+ QListIterator iter(m_changedStrips);
+ while (iter.hasNext()) {
+ ChannelStrip *pChannelStrip = iter.next();
+ // If successfull, remove from pending list...
+ if (pChannelStrip->updateChannelInfo()) {
+ int iChannelStrip = m_changedStrips.indexOf(pChannelStrip);
+ if (iChannelStrip >= 0)
+ m_changedStrips.removeAt(iChannelStrip);
}
}
// Refresh each channel usage, on each period...
@@ -2250,8 +2501,8 @@
}
}
- // Register the next timer slot.
- QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
+ // Register the next timer slot.
+ QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
}
@@ -2261,136 +2512,165 @@
// Start linuxsampler server...
void MainForm::startServer (void)
{
- if (m_pOptions == NULL)
- return;
+ if (m_pOptions == NULL)
+ return;
+
+ // Aren't already a client, are we?
+ if (!m_pOptions->bServerStart || m_pClient)
+ return;
- // Aren't already a client, are we?
- if (!m_pOptions->bServerStart || m_pClient)
- return;
-
- // Is the server process instance still here?
- if (m_pServer) {
- switch (QMessageBox::warning(this,
+ // Is the server process instance still here?
+ if (m_pServer) {
+ if (QMessageBox::warning(this,
QSAMPLER_TITLE ": " + tr("Warning"),
- tr("Could not start the LinuxSampler server.\n\n"
- "Maybe it ss already started."),
- tr("Stop"), tr("Kill"), tr("Cancel"))) {
- case 0:
- m_pServer->terminate();
- break;
- case 1:
- m_pServer->kill();
- break;
- }
- return;
- }
-
- // Reset our timer counters...
- stopSchedule();
-
- // OK. Let's build the startup process...
- m_pServer = new QProcess(this);
-
- // Setup stdout/stderr capture...
- // if (m_pOptions->bStdoutCapture) {
- //m_pServer->setProcessChannelMode(
- // QProcess::StandardOutput);
+ tr("Could not start the LinuxSampler server.\n\n"
+ "Maybe it is already started."),
+ QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
+ m_pServer->terminate();
+ m_pServer->kill();
+ }
+ return;
+ }
+
+ // Reset our timer counters...
+ stopSchedule();
+
+ // Verify we have something to start with...
+ if (m_pOptions->sServerCmdLine.isEmpty())
+ return;
+
+ // OK. Let's build the startup process...
+ m_pServer = new QProcess();
+ bForceServerStop = true;
+
+ // Setup stdout/stderr capture...
+// if (m_pOptions->bStdoutCapture) {
+#if QT_VERSION >= 0x040200
+ m_pServer->setProcessChannelMode(QProcess::ForwardedChannels);
+#endif
QObject::connect(m_pServer,
- SIGNAL(readyReadStdout()),
+ SIGNAL(readyReadStandardOutput()),
SLOT(readServerStdout()));
QObject::connect(m_pServer,
- SIGNAL(readyReadStderr()),
+ SIGNAL(readyReadStandardError()),
SLOT(readServerStdout()));
- // }
+// }
+
// The unforgiveable signal communication...
QObject::connect(m_pServer,
- SIGNAL(processExited()),
+ SIGNAL(finished(int, QProcess::ExitStatus)),
SLOT(processServerExit()));
- // Build process arguments...
- QStringList serverCmdLine = QStringList::split(' ', m_pOptions->sServerCmdLine);
-
- appendMessages(tr("Server is starting..."));
- appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");
-
-
-
- const QString prog = (serverCmdLine.size() > 0) ? serverCmdLine[0] : QString();
- const QStringList args = serverCmdLine.mid(1);
-
- // Go jack, go...
- m_pServer->start(prog, args);
- if (!m_pServer->waitForStarted()) {
- appendMessagesError(tr("Could not start server.\n\nSorry."));
- processServerExit();
- return;
- }
-
- // Show startup results...
- appendMessages(tr("Server was started with PID=%1.").arg((long) m_pServer->pid()));
+ // Build process arguments...
+ QStringList args = m_pOptions->sServerCmdLine.split(' ');
+ QString sCommand = args[0];
+ args.removeAt(0);
+
+ appendMessages(tr("Server is starting..."));
+ appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");
+
+ // Go linuxsampler, go...
+ m_pServer->start(sCommand, args);
+ if (!m_pServer->waitForStarted()) {
+ appendMessagesError(tr("Could not start server.\n\nSorry."));
+ processServerExit();
+ return;
+ }
- // Reset (yet again) the timer counters,
- // but this time is deferred as the user opted.
- startSchedule(m_pOptions->iStartDelay);
- stabilizeForm();
+ // Show startup results...
+ appendMessages(
+ tr("Server was started with PID=%1.").arg((long) m_pServer->pid()));
+
+ // Reset (yet again) the timer counters,
+ // but this time is deferred as the user opted.
+ startSchedule(m_pOptions->iStartDelay);
+ stabilizeForm();
}
// Stop linuxsampler server...
-void MainForm::stopServer (void)
+void MainForm::stopServer (bool bInteractive)
{
- // Stop client code.
- stopClient();
+ // Stop client code.
+ stopClient();
- // And try to stop server.
- if (m_pServer) {
- appendMessages(tr("Server is stopping..."));
- if (m_pServer->state() == QProcess::Running)
- m_pServer->terminate();
- }
-
- // Give it some time to terminate gracefully and stabilize...
- QTime t;
- t.start();
- while (t.elapsed() < QSAMPLER_TIMER_MSECS)
- QApplication::processEvents(QEventLoop::ExcludeUserInput);
+ if (m_pServer && bInteractive) {
+ if (QMessageBox::question(this,
+ QSAMPLER_TITLE ": " + tr("The backend's fate ..."),
+ tr("You have the option to keep the sampler backend (LinuxSampler)\n"
+ "running in the background. The sampler would continue to work\n"
+ "according to your current sampler session and you could alter the\n"
+ "sampler session at any time by relaunching QSampler.\n\n"
+ "Do you want LinuxSampler to stop or to keep running in\n"
+ "the background?"),
+ QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ {
+ bForceServerStop = false;
+ }
+ }
- // Do final processing anyway.
- processServerExit();
+ // And try to stop server.
+ if (m_pServer && bForceServerStop) {
+ appendMessages(tr("Server is stopping..."));
+ if (m_pServer->state() == QProcess::Running) {
+#if defined(WIN32)
+ // Try harder...
+ m_pServer->kill();
+#else
+ // Try softly...
+ m_pServer->terminate();
+#endif
+ }
+ } // Do final processing anyway.
+ else processServerExit();
+
+ // Give it some time to terminate gracefully and stabilize...
+ QTime t;
+ t.start();
+ while (t.elapsed() < QSAMPLER_TIMER_MSECS)
+ QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
}
// Stdout handler...
void MainForm::readServerStdout (void)
{
- if (m_pMessages)
- m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());
+ if (m_pMessages)
+ m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());
}
// Linuxsampler server cleanup.
void MainForm::processServerExit (void)
{
- // Force client code cleanup.
- stopClient();
+ // Force client code cleanup.
+ stopClient();
- // Flush anything that maybe pending...
- if (m_pMessages)
- m_pMessages->flushStdoutBuffer();
-
- if (m_pServer) {
- // Force final server shutdown...
- appendMessages(tr("Server was stopped with exit status %1.").arg(m_pServer->exitStatus()));
- m_pServer->terminate();
- if (!m_pServer->waitForFinished(2000))
- m_pServer->kill();
- // Destroy it.
- delete m_pServer;
- m_pServer = NULL;
- }
+ // Flush anything that maybe pending...
+ if (m_pMessages)
+ m_pMessages->flushStdoutBuffer();
+
+ if (m_pServer && bForceServerStop) {
+ if (m_pServer->state() != QProcess::NotRunning) {
+ appendMessages(tr("Server is being forced..."));
+ // Force final server shutdown...
+ m_pServer->kill();
+ // Give it some time to terminate gracefully and stabilize...
+ QTime t;
+ t.start();
+ while (t.elapsed() < QSAMPLER_TIMER_MSECS)
+ QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+ }
+ // Force final server shutdown...
+ appendMessages(
+ tr("Server was stopped with exit status %1.")
+ .arg(m_pServer->exitStatus()));
+ delete m_pServer;
+ m_pServer = NULL;
+ }
- // Again, make status visible stable.
- stabilizeForm();
+ // Again, make status visible stable.
+ stabilizeForm();
}
@@ -2398,124 +2678,188 @@
// qsamplerMainForm -- Client stuff.
// The LSCP client callback procedure.
-lscp_status_t qsampler_client_callback ( lscp_client_t */*pClient*/, lscp_event_t event, const char *pchData, int cchData, void *pvData )
+lscp_status_t qsampler_client_callback ( lscp_client_t */*pClient*/,
+ lscp_event_t event, const char *pchData, int cchData, void *pvData )
{
- MainForm* pMainForm = (MainForm *) pvData;
- if (pMainForm == NULL)
- return LSCP_FAILED;
-
- // ATTN: DO NOT EVER call any GUI code here,
- // as this is run under some other thread context.
- // A custom event must be posted here...
- QApplication::postEvent(pMainForm, new qsamplerCustomEvent(event, pchData, cchData));
+ MainForm* pMainForm = (MainForm *) pvData;
+ if (pMainForm == NULL)
+ return LSCP_FAILED;
+
+ // ATTN: DO NOT EVER call any GUI code here,
+ // as this is run under some other thread context.
+ // A custom event must be posted here...
+ QApplication::postEvent(pMainForm,
+ new CustomEvent(event, pchData, cchData));
- return LSCP_OK;
+ return LSCP_OK;
}
// Start our almighty client...
bool MainForm::startClient (void)
{
- // Have it a setup?
- if (m_pOptions == NULL)
- return false;
-
- // Aren't we already started, are we?
- if (m_pClient)
- return true;
-
- // Log prepare here.
- appendMessages(tr("Client connecting..."));
-
- // Create the client handle...
- m_pClient = ::lscp_client_create(m_pOptions->sServerHost.latin1(), m_pOptions->iServerPort, qsampler_client_callback, this);
- if (m_pClient == NULL) {
- // Is this the first try?
- // maybe we need to start a local server...
- if ((m_pServer && m_pServer->state() == QProcess::Running) || !m_pOptions->bServerStart)
- appendMessagesError(tr("Could not connect to server as client.\n\nSorry."));
- else
- startServer();
- // This is always a failure.
- stabilizeForm();
- return false;
- }
- // Just set receive timeout value, blindly.
- ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);
- appendMessages(tr("Client receive timeout is set to %1 msec.").arg(::lscp_client_get_timeout(m_pClient)));
+ // Have it a setup?
+ if (m_pOptions == NULL)
+ return false;
+
+ // Aren't we already started, are we?
+ if (m_pClient)
+ return true;
+
+ // Log prepare here.
+ appendMessages(tr("Client connecting..."));
+
+ // Create the client handle...
+ m_pClient = ::lscp_client_create(
+ m_pOptions->sServerHost.toUtf8().constData(),
+ m_pOptions->iServerPort, qsampler_client_callback, this);
+ if (m_pClient == NULL) {
+ // Is this the first try?
+ // maybe we need to start a local server...
+ if ((m_pServer && m_pServer->state() == QProcess::Running)
+ || !m_pOptions->bServerStart) {
+ appendMessagesError(
+ tr("Could not connect to server as client.\n\nSorry."));
+ } else {
+ startServer();
+ }
+ // This is always a failure.
+ stabilizeForm();
+ return false;
+ }
+ // Just set receive timeout value, blindly.
+ ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);
+ appendMessages(
+ tr("Client receive timeout is set to %1 msec.")
+ .arg(::lscp_client_get_timeout(m_pClient)));
// Subscribe to channel info change notifications...
+ if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT) != LSCP_OK)
+ appendMessagesClient("lscp_client_subscribe(CHANNEL_COUNT)");
if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)
- appendMessagesClient("lscp_client_subscribe");
+ appendMessagesClient("lscp_client_subscribe(CHANNEL_INFO)");
+
+ DeviceStatusForm::onDevicesChanged(); // initialize
+ updateViewMidiDeviceStatusMenu();
+ if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT) != LSCP_OK)
+ appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_COUNT)");
+ if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO) != LSCP_OK)
+ appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_INFO)");
+ if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT) != LSCP_OK)
+ appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_COUNT)");
+ if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO) != LSCP_OK)
+ appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_INFO)");
+
+#if CONFIG_EVENT_CHANNEL_MIDI
+ // Subscribe to channel MIDI data notifications...
+ if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI) != LSCP_OK)
+ appendMessagesClient("lscp_client_subscribe(CHANNEL_MIDI)");
+#endif
+
+#if CONFIG_EVENT_DEVICE_MIDI
+ // Subscribe to channel MIDI data notifications...
+ if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI) != LSCP_OK)
+ appendMessagesClient("lscp_client_subscribe(DEVICE_MIDI)");
+#endif
- // We may stop scheduling around.
- stopSchedule();
+ // We may stop scheduling around.
+ stopSchedule();
- // We'll accept drops from now on...
- setAcceptDrops(true);
+ // We'll accept drops from now on...
+ setAcceptDrops(true);
- // Log success here.
- appendMessages(tr("Client connected."));
+ // Log success here.
+ appendMessages(tr("Client connected."));
// Hard-notify instrumnet and device configuration forms,
// if visible, that we're ready...
if (m_pInstrumentListForm)
- m_pInstrumentListForm->refreshInstruments();
+ m_pInstrumentListForm->refreshInstruments();
if (m_pDeviceForm)
- m_pDeviceForm->refreshDevices();
+ m_pDeviceForm->refreshDevices();
- // Is any session pending to be loaded?
- if (!m_pOptions->sSessionFile.isEmpty()) {
- // Just load the prabably startup session...
- if (loadSessionFile(m_pOptions->sSessionFile)) {
- m_pOptions->sSessionFile = QString::null;
- return true;
- }
- }
+ // Is any session pending to be loaded?
+ if (!m_pOptions->sSessionFile.isEmpty()) {
+ // Just load the prabably startup session...
+ if (loadSessionFile(m_pOptions->sSessionFile)) {
+ m_pOptions->sSessionFile = QString::null;
+ return true;
+ }
+ }
+
+ // send the current / loaded fine tuning settings to the sampler
+ m_pOptions->sendFineTuningSettings();
- // Make a new session
- return newSession();
+ // Make a new session
+ return newSession();
}
// Stop client...
void MainForm::stopClient (void)
{
- if (m_pClient == NULL)
- return;
-
- // Log prepare here.
- appendMessages(tr("Client disconnecting..."));
+ if (m_pClient == NULL)
+ return;
- // Clear timer counters...
- stopSchedule();
+ // Log prepare here.
+ appendMessages(tr("Client disconnecting..."));
- // We'll reject drops from now on...
- setAcceptDrops(false);
+ // Clear timer counters...
+ stopSchedule();
- // Force any channel strips around, but
- // but avoid removing the corresponding
- // channels from the back-end server.
- m_iDirtyCount = 0;
- closeSession(false);
+ // We'll reject drops from now on...
+ setAcceptDrops(false);
- // Close us as a client...
+ // Force any channel strips around, but
+ // but avoid removing the corresponding
+ // channels from the back-end server.
+ m_iDirtyCount = 0;
+ closeSession(false);
+
+ // Close us as a client...
+#if CONFIG_EVENT_DEVICE_MIDI
+ ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI);
+#endif
+#if CONFIG_EVENT_CHANNEL_MIDI
+ ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI);
+#endif
+ ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
+ ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
+ ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
+ ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
- ::lscp_client_destroy(m_pClient);
- m_pClient = NULL;
+ ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT);
+ ::lscp_client_destroy(m_pClient);
+ m_pClient = NULL;
// Hard-notify instrumnet and device configuration forms,
// if visible, that we're running out...
if (m_pInstrumentListForm)
- m_pInstrumentListForm->refreshInstruments();
+ m_pInstrumentListForm->refreshInstruments();
if (m_pDeviceForm)
- m_pDeviceForm->refreshDevices();
+ m_pDeviceForm->refreshDevices();
- // Log final here.
- appendMessages(tr("Client disconnected."));
+ // Log final here.
+ appendMessages(tr("Client disconnected."));
- // Make visible status.
- stabilizeForm();
+ // Make visible status.
+ stabilizeForm();
}
+
+// Channel strip activation/selection.
+void MainForm::activateStrip ( QWidget *pWidget )
+{
+ ChannelStrip *pChannelStrip
+ = static_cast (pWidget);
+ if (pChannelStrip)
+ pChannelStrip->setSelected(true);
+
+ stabilizeForm();
+}
+
+
} // namespace QSampler
+
+
+// end of qsamplerMainForm.cpp