--- qsampler/trunk/src/qsamplerMainForm.cpp 2015/03/03 17:41:04 2722 +++ qsampler/trunk/src/qsamplerMainForm.cpp 2019/06/30 16:58:30 3518 @@ -1,7 +1,7 @@ // qsamplerMainForm.cpp // /**************************************************************************** - Copyright (C) 2004-2015, rncbc aka Rui Nuno Capela. All rights reserved. + Copyright (C) 2004-2019, rncbc aka Rui Nuno Capela. All rights reserved. Copyright (C) 2007,2008,2015 Christian Schoenebeck This program is free software; you can redistribute it and/or @@ -68,10 +68,6 @@ } #endif -#ifdef HAVE_SIGNAL_H -#include -#endif - #ifdef CONFIG_LIBGIG #include #endif @@ -91,8 +87,9 @@ // All winsock apps needs this. -#if defined(WIN32) +#if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) static WSADATA _wsaData; +#undef HAVE_SIGNAL_H #endif @@ -103,27 +100,38 @@ #include +#include #include #include - #include // File descriptor for SIGUSR1 notifier. -static int g_fdUsr1[2]; +static int g_fdSigusr1[2] = { -1, -1 }; // Unix SIGUSR1 signal handler. static void qsampler_sigusr1_handler ( int /* signo */ ) { char c = 1; - (::write(g_fdUsr1[0], &c, sizeof(c)) > 0); + (::write(g_fdSigusr1[0], &c, sizeof(c)) > 0); +} + +// File descriptor for SIGTERM notifier. +static int g_fdSigterm[2] = { -1, -1 }; + +// Unix SIGTERM signal handler. +static void qsampler_sigterm_handler ( int /* signo */ ) +{ + char c = 1; + + (::write(g_fdSigterm[0], &c, sizeof(c)) > 0); } #endif // HAVE_SIGNAL_H //------------------------------------------------------------------------- -// qsampler -- namespace +// QSampler -- namespace namespace QSampler { @@ -143,8 +151,7 @@ //------------------------------------------------------------------------- -// LscpEvent -- specialty for LSCP callback comunication. - +// QSampler::LscpEvent -- specialty for LSCP callback comunication. class LscpEvent : public QEvent { @@ -159,8 +166,8 @@ } // Accessors. - lscp_event_t event() { return m_event; } - QString& data() { return m_data; } + lscp_event_t event() { return m_event; } + const QString& data() { return m_data; } private: @@ -172,10 +179,30 @@ //------------------------------------------------------------------------- -// qsamplerMainForm -- Main window form implementation. +// QSampler::Workspace -- Main window workspace (MDI Area) decl. + +class Workspace : public QMdiArea +{ +public: + + Workspace(MainForm *pMainForm) : QMdiArea(pMainForm) {} + +protected: + + void resizeEvent(QResizeEvent *) + { + MainForm *pMainForm = static_cast (parentWidget()); + if (pMainForm) + pMainForm->channelsArrangeAuto(); + } +}; + + +//------------------------------------------------------------------------- +// QSampler::MainForm -- Main window form implementation. // Kind of singleton reference. -MainForm* MainForm::g_pMainForm = NULL; +MainForm *MainForm::g_pMainForm = NULL; MainForm::MainForm ( QWidget *pParent ) : QMainWindow(pParent) @@ -195,6 +222,7 @@ // We'll start clean. m_iUntitled = 0; + m_iDirtySetup = 0; m_iDirtyCount = 0; m_pServer = NULL; @@ -213,25 +241,48 @@ // LADISH Level 1 suport. // Initialize file descriptors for SIGUSR1 socket notifier. - ::socketpair(AF_UNIX, SOCK_STREAM, 0, g_fdUsr1); - m_pUsr1Notifier - = new QSocketNotifier(g_fdUsr1[1], QSocketNotifier::Read, this); + ::socketpair(AF_UNIX, SOCK_STREAM, 0, g_fdSigusr1); + m_pSigusr1Notifier + = new QSocketNotifier(g_fdSigusr1[1], QSocketNotifier::Read, this); - QObject::connect(m_pUsr1Notifier, + QObject::connect(m_pSigusr1Notifier, SIGNAL(activated(int)), SLOT(handle_sigusr1())); // Install SIGUSR1 signal handler. - struct sigaction usr1; - usr1.sa_handler = qsampler_sigusr1_handler; - sigemptyset(&usr1.sa_mask); - usr1.sa_flags = 0; - usr1.sa_flags |= SA_RESTART; - ::sigaction(SIGUSR1, &usr1, NULL); + struct sigaction sigusr1; + sigusr1.sa_handler = qsampler_sigusr1_handler; + sigemptyset(&sigusr1.sa_mask); + sigusr1.sa_flags = 0; + sigusr1.sa_flags |= SA_RESTART; + ::sigaction(SIGUSR1, &sigusr1, NULL); + + // Initialize file descriptors for SIGTERM socket notifier. + ::socketpair(AF_UNIX, SOCK_STREAM, 0, g_fdSigterm); + m_pSigtermNotifier + = new QSocketNotifier(g_fdSigterm[1], QSocketNotifier::Read, this); + + QObject::connect(m_pSigtermNotifier, + SIGNAL(activated(int)), + SLOT(handle_sigterm())); + + // Install SIGTERM signal handler. + struct sigaction sigterm; + sigterm.sa_handler = qsampler_sigterm_handler; + ::sigemptyset(&sigterm.sa_mask); + sigterm.sa_flags = 0; + sigterm.sa_flags |= SA_RESTART; + ::sigaction(SIGTERM, &sigterm, NULL); + ::sigaction(SIGQUIT, &sigterm, NULL); + + // Ignore SIGHUP/SIGINT signals. + ::signal(SIGHUP, SIG_IGN); + ::signal(SIGINT, SIG_IGN); #else // HAVE_SIGNAL_H - m_pUsr1Notifier = NULL; + m_pSigusr1Notifier = NULL; + m_pSigtermNotifier = NULL; #endif // !HAVE_SIGNAL_H @@ -269,7 +320,7 @@ #endif // Make it an MDI workspace. - m_pWorkspace = new QMdiArea(this); + m_pWorkspace = new Workspace(this); m_pWorkspace->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); m_pWorkspace->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); // Set the activation connection. @@ -304,7 +355,7 @@ m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel; statusBar()->addWidget(pLabel); -#if defined(WIN32) +#if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) WSAStartup(MAKEWORD(1, 1), &_wsaData); #endif @@ -405,13 +456,15 @@ // Do final processing anyway. processServerExit(); -#if defined(WIN32) +#if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) WSACleanup(); #endif #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H) - if (m_pUsr1Notifier) - delete m_pUsr1Notifier; + if (m_pSigusr1Notifier) + delete m_pSigusr1Notifier; + if (m_pSigtermNotifier) + delete m_pSigtermNotifier; #endif // Finally drop any widgets around... @@ -478,6 +531,7 @@ updateMessagesFont(); updateMessagesLimit(); updateMessagesCapture(); + // Set the visibility signal. QObject::connect(m_pMessages, SIGNAL(visibilityChanged(bool)), @@ -543,7 +597,6 @@ || 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); @@ -586,7 +639,7 @@ } -void MainForm::dropEvent ( QDropEvent* pDropEvent ) +void MainForm::dropEvent ( QDropEvent *pDropEvent ) { // Accept externally originated drops only... if (pDropEvent->source()) @@ -642,7 +695,7 @@ updateAllChannelStrips(true); break; case LSCP_EVENT_CHANNEL_INFO: { - int iChannelID = pLscpEvent->data().toInt(); + const int iChannelID = pLscpEvent->data().toInt(); ChannelStrip *pChannelStrip = channelStrip(iChannelID); if (pChannelStrip) channelStripChanged(pChannelStrip); @@ -701,13 +754,26 @@ char c; - if (::read(g_fdUsr1[1], &c, sizeof(c)) > 0) + if (::read(g_fdSigusr1[1], &c, sizeof(c)) > 0) saveSession(false); #endif } +void MainForm::handle_sigterm (void) +{ +#if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H) + + char c; + + if (::read(g_fdSigterm[1], &c, sizeof(c)) > 0) + close(); + +#endif +} + + void MainForm::updateViewMidiDeviceStatusMenu (void) { m_ui.viewMidiDeviceStatusMenu->clear(); @@ -733,7 +799,7 @@ //------------------------------------------------------------------------- -// qsamplerMainForm -- Brainless public property accessors. +// QSampler::MainForm -- Brainless public property accessors. // The global options settings property. Options *MainForm::options (void) const @@ -757,12 +823,12 @@ //------------------------------------------------------------------------- -// qsamplerMainForm -- Session file stuff. +// QSampler::MainForm -- Session file stuff. // Format the displayable session filename. QString MainForm::sessionName ( const QString& sFilename ) { - bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath); + const bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath); QString sSessionName = sFilename; if (sSessionName.isEmpty()) sSessionName = tr("Untitled") + QString::number(m_iUntitled); @@ -786,7 +852,7 @@ m_iUntitled++; // Stabilize form. - m_sFilename = QString::null; + m_sFilename = QString(); m_iDirtyCount = 0; appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename))); stabilizeForm(); @@ -846,6 +912,7 @@ // Enforce .lscp extension... if (QFileInfo(sFilename).suffix().isEmpty()) sFilename += ".lscp"; + #if 0 // Check if already exists... if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) { if (QMessageBox::warning(this, @@ -858,6 +925,7 @@ == QMessageBox::No) return false; } + #endif } // Save it right away. @@ -896,10 +964,12 @@ if (bClose) { // Remove all channel strips from sight... m_pWorkspace->setUpdatesEnabled(false); - QList wlist = m_pWorkspace->subWindowList(); - for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) { + const QList& wlist + = m_pWorkspace->subWindowList(); + const int iStripCount = wlist.count(); + for (int iStrip = 0; iStrip < iStripCount; ++iStrip) { ChannelStrip *pChannelStrip = NULL; - QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel); + QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip); if (pMdiSubWindow) pChannelStrip = static_cast (pMdiSubWindow->widget()); if (pChannelStrip) { @@ -1021,13 +1091,11 @@ QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); // Write the file. - int iErrors = 0; + 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 << "# " << tr("Version") << ": " CONFIG_BUILD_VERSION << endl; +// ts << "# " << tr("Build") << ": " CONFIG_BUILD_DATE << endl; ts << "#" << endl; ts << "# " << tr("File") << ": " << QFileInfo(sFilename).fileName() << endl; @@ -1040,16 +1108,19 @@ // It is assumed that this new kind of device+session file // will be loaded from a complete initialized server... int *piDeviceIDs; - int iDevice; + int i, iDevice; ts << "RESET" << endl; // Audio device mapping. - QMap audioDeviceMap; + QMap audioDeviceMap; iDevice = 0; piDeviceIDs = Device::getDevices(m_pClient, Device::Audio); - for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) { - ts << endl; - Device device(Device::Audio, piDeviceIDs[iDevice]); + for (i = 0; piDeviceIDs && piDeviceIDs[i] >= 0; ++i) { + Device device(Device::Audio, piDeviceIDs[i]); + // Avoid plug-in driver devices... + if (device.driverName().toUpper() == "PLUGIN") + continue; // Audio device specification... + ts << endl; ts << "# " << device.deviceTypeName() << " " << device.driverName() << " " << tr("Device") << " " << iDevice << endl; ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName(); @@ -1080,18 +1151,21 @@ iPort++; } // Audio device index/id mapping. - audioDeviceMap[device.deviceID()] = iDevice; + audioDeviceMap.insert(device.deviceID(), iDevice++); // Try to keep it snappy :) QApplication::processEvents(QEventLoop::ExcludeUserInputEvents); } // MIDI device mapping. - QMap midiDeviceMap; + QMap midiDeviceMap; iDevice = 0; piDeviceIDs = Device::getDevices(m_pClient, Device::Midi); - for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) { - ts << endl; - Device device(Device::Midi, piDeviceIDs[iDevice]); + for (i = 0; piDeviceIDs && piDeviceIDs[i] >= 0; ++i) { + Device device(Device::Midi, piDeviceIDs[i]); + // Avoid plug-in driver devices... + if (device.driverName().toUpper() == "PLUGIN") + continue; // MIDI device specification... + ts << endl; ts << "# " << device.deviceTypeName() << " " << device.driverName() << " " << tr("Device") << " " << iDevice << endl; ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName(); @@ -1122,7 +1196,7 @@ iPort++; } // MIDI device index/id mapping. - midiDeviceMap[device.deviceID()] = iDevice; + midiDeviceMap.insert(device.deviceID(), iDevice++); // Try to keep it snappy :) QApplication::processEvents(QEventLoop::ExcludeUserInputEvents); } @@ -1133,7 +1207,7 @@ QMap midiInstrumentMap; int *piMaps = ::lscp_list_midi_instrument_maps(m_pClient); for (int iMap = 0; piMaps && piMaps[iMap] >= 0; iMap++) { - int iMidiMap = piMaps[iMap]; + const int iMidiMap = piMaps[iMap]; const char *pszMapName = ::lscp_get_midi_instrument_map_name(m_pClient, iMidiMap); ts << "# " << tr("MIDI instrument map") << " " << iMap; @@ -1190,7 +1264,7 @@ iErrors++; } // MIDI strument index/id mapping. - midiInstrumentMap[iMidiMap] = iMap; + midiInstrumentMap.insert(iMidiMap, iMap); } // Check for errors... if (piMaps == NULL && ::lscp_client_get_errno(m_pClient)) { @@ -1199,68 +1273,79 @@ } #endif // CONFIG_MIDI_INSTRUMENT - // Sampler channel mapping. - QList wlist = m_pWorkspace->subWindowList(); - for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) { + // Sampler channel mapping... + int iChannelID = 0; + const QList& wlist + = m_pWorkspace->subWindowList(); + const int iStripCount = wlist.count(); + for (int iStrip = 0; iStrip < iStripCount; ++iStrip) { ChannelStrip *pChannelStrip = NULL; - QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel); + QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip); if (pMdiSubWindow) pChannelStrip = static_cast (pMdiSubWindow->widget()); if (pChannelStrip) { Channel *pChannel = pChannelStrip->channel(); if (pChannel) { - ts << "# " << tr("Channel") << " " << iChannel << endl; + // Avoid "artifial" plug-in devices... + const int iAudioDevice = pChannel->audioDevice(); + if (!audioDeviceMap.contains(iAudioDevice)) + continue; + const int iMidiDevice = pChannel->midiDevice(); + if (!midiDeviceMap.contains(iMidiDevice)) + continue; + // Go for regular, canonical devices... + ts << "# " << tr("Channel") << " " << iChannelID << endl; ts << "ADD CHANNEL" << endl; if (audioDeviceMap.isEmpty()) { - ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel + ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannelID << " " << pChannel->audioDriver() << endl; } else { - ts << "SET CHANNEL AUDIO_OUTPUT_DEVICE " << iChannel - << " " << audioDeviceMap[pChannel->audioDevice()] << endl; + ts << "SET CHANNEL AUDIO_OUTPUT_DEVICE " << iChannelID + << " " << audioDeviceMap.value(iAudioDevice) << endl; } if (midiDeviceMap.isEmpty()) { - ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannel + ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannelID << " " << pChannel->midiDriver() << endl; } else { - ts << "SET CHANNEL MIDI_INPUT_DEVICE " << iChannel - << " " << midiDeviceMap[pChannel->midiDevice()] << endl; + ts << "SET CHANNEL MIDI_INPUT_DEVICE " << iChannelID + << " " << midiDeviceMap.value(iMidiDevice) << endl; } - ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel + ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannelID << " " << pChannel->midiPort() << endl; - ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " "; + ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannelID << " "; if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL) ts << "ALL"; else ts << pChannel->midiChannel(); ts << endl; ts << "LOAD ENGINE " << pChannel->engineName() - << " " << iChannel << endl; + << " " << iChannelID << endl; if (pChannel->instrumentStatus() < 100) ts << "# "; ts << "LOAD INSTRUMENT NON_MODAL '" << pChannel->instrumentFile() << "' " - << pChannel->instrumentNr() << " " << iChannel << endl; + << pChannel->instrumentNr() << " " << iChannelID << endl; ChannelRoutingMap::ConstIterator audioRoute; for (audioRoute = pChannel->audioRouting().begin(); audioRoute != pChannel->audioRouting().end(); ++audioRoute) { - ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannel + ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannelID << " " << audioRoute.key() << " " << audioRoute.value() << endl; } - ts << "SET CHANNEL VOLUME " << iChannel + ts << "SET CHANNEL VOLUME " << iChannelID << " " << pChannel->volume() << endl; if (pChannel->channelMute()) - ts << "SET CHANNEL MUTE " << iChannel << " 1" << endl; + ts << "SET CHANNEL MUTE " << iChannelID << " 1" << endl; if (pChannel->channelSolo()) - ts << "SET CHANNEL SOLO " << iChannel << " 1" << endl; + ts << "SET CHANNEL SOLO " << iChannelID << " 1" << endl; #ifdef CONFIG_MIDI_INSTRUMENT - if (pChannel->midiMap() >= 0) { - ts << "SET CHANNEL MIDI_INSTRUMENT_MAP " << iChannel - << " " << midiInstrumentMap[pChannel->midiMap()] << endl; + const int iMidiMap = pChannel->midiMap(); + if (midiInstrumentMap.contains(iMidiMap)) { + ts << "SET CHANNEL MIDI_INSTRUMENT_MAP " << iChannelID + << " " << midiInstrumentMap.value(iMidiMap) << endl; } #endif #ifdef CONFIG_FXSEND - int iChannelID = pChannel->channelID(); int *piFxSends = ::lscp_list_fxsends(m_pClient, iChannelID); for (int iFxSend = 0; piFxSends && piFxSends[iFxSend] >= 0; @@ -1268,7 +1353,7 @@ lscp_fxsend_info_t *pFxSendInfo = ::lscp_get_fxsend_info( m_pClient, iChannelID, piFxSends[iFxSend]); if (pFxSendInfo) { - ts << "CREATE FX_SEND " << iChannel + ts << "CREATE FX_SEND " << iChannelID << " " << pFxSendInfo->midi_controller; if (pFxSendInfo->name) ts << " '" << pFxSendInfo->name << "'"; @@ -1278,13 +1363,13 @@ piRouting && piRouting[iAudioSrc] >= 0; iAudioSrc++) { ts << "SET FX_SEND AUDIO_OUTPUT_CHANNEL " - << iChannel + << iChannelID << " " << iFxSend << " " << iAudioSrc << " " << piRouting[iAudioSrc] << endl; } #ifdef CONFIG_FXSEND_LEVEL - ts << "SET FX_SEND LEVEL " << iChannel + ts << "SET FX_SEND LEVEL " << iChannelID << " " << iFxSend << " " << pFxSendInfo->level << endl; #endif @@ -1296,6 +1381,8 @@ } #endif ts << endl; + // Go for next channel... + ++iChannelID; } } // Try to keep it snappy :) @@ -1347,7 +1434,7 @@ //------------------------------------------------------------------------- -// qsamplerMainForm -- File Action slots. +// QSampler::MainForm -- File Action slots. // Create a new sampler session. void MainForm::fileNew (void) @@ -1371,7 +1458,7 @@ // Retrive filename index from action data... QAction *pAction = qobject_cast (sender()); if (pAction && m_pOptions) { - int iIndex = pAction->data().toInt(); + const 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... @@ -1513,11 +1600,18 @@ //------------------------------------------------------------------------- -// qsamplerMainForm -- Edit Action slots. +// QSampler::MainForm -- Edit Action slots. // Add a new sampler channel. void MainForm::editAddChannel (void) { + ++m_iDirtySetup; + addChannelStrip(); + --m_iDirtySetup; +} + +void MainForm::addChannelStrip (void) +{ if (m_pClient == NULL) return; @@ -1541,8 +1635,7 @@ } // Do we auto-arrange? - if (m_pOptions && m_pOptions->bAutoArrange) - channelsArrange(); + channelsArrangeAuto(); // Make that an overall update. m_iDirtyCount++; @@ -1553,6 +1646,13 @@ // Remove current sampler channel. void MainForm::editRemoveChannel (void) { + ++m_iDirtySetup; + removeChannelStrip(); + --m_iDirtySetup; +} + +void MainForm::removeChannelStrip (void) +{ if (m_pClient == NULL) return; @@ -1597,11 +1697,12 @@ if (!pChannel->removeChannel()) return; - // We'll be dirty, for sure... - m_iDirtyCount++; - // Just delete the channel strip. destroyChannelStrip(pChannelStrip); + + // We'll be dirty, for sure... + m_iDirtyCount++; + stabilizeForm(); } @@ -1659,10 +1760,12 @@ // Invoque the channel strip procedure, // for all channels out there... m_pWorkspace->setUpdatesEnabled(false); - QList wlist = m_pWorkspace->subWindowList(); - for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) { + const QList& wlist + = m_pWorkspace->subWindowList(); + const int iStripCount = wlist.count(); + for (int iStrip = 0; iStrip < iStripCount; ++iStrip) { ChannelStrip *pChannelStrip = NULL; - QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel); + QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip); if (pMdiSubWindow) pChannelStrip = static_cast (pMdiSubWindow->widget()); if (pChannelStrip) @@ -1673,7 +1776,7 @@ //------------------------------------------------------------------------- -// qsamplerMainForm -- View Action slots. +// QSampler::MainForm -- View Action slots. // Show/hide the main program window menubar. void MainForm::viewMenubar ( bool bOn ) @@ -1773,25 +1876,25 @@ 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; + const QString sOldServerHost = m_pOptions->sServerHost; + const int iOldServerPort = m_pOptions->iServerPort; + const int iOldServerTimeout = m_pOptions->iServerTimeout; + const bool bOldServerStart = m_pOptions->bServerStart; + const QString sOldServerCmdLine = m_pOptions->sServerCmdLine; + const bool bOldMessagesLog = m_pOptions->bMessagesLog; + const QString sOldMessagesLogPath = m_pOptions->sMessagesLogPath; + const QString sOldDisplayFont = m_pOptions->sDisplayFont; + const bool bOldDisplayEffect = m_pOptions->bDisplayEffect; + const int iOldMaxVolume = m_pOptions->iMaxVolume; + const QString sOldMessagesFont = m_pOptions->sMessagesFont; + const bool bOldKeepOnTop = m_pOptions->bKeepOnTop; + const bool bOldStdoutCapture = m_pOptions->bStdoutCapture; + const int bOldMessagesLimit = m_pOptions->bMessagesLimit; + const int iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines; + const bool bOldCompletePath = m_pOptions->bCompletePath; + const bool bOldInstrumentNames = m_pOptions->bInstrumentNames; + const int iOldMaxRecentFiles = m_pOptions->iMaxRecentFiles; + const int iOldBaseFontSize = m_pOptions->iBaseFontSize; // Load the current setup settings. pOptionsForm->setup(m_pOptions); // Show the setup dialog... @@ -1854,37 +1957,29 @@ //------------------------------------------------------------------------- -// qsamplerMainForm -- Channels action slots. +// QSampler::MainForm -- Channels action slots. // Arrange channel strips. void MainForm::channelsArrange (void) { // Full width vertical tiling - QList wlist = m_pWorkspace->subWindowList(); + const QList& wlist + = m_pWorkspace->subWindowList(); if (wlist.isEmpty()) return; m_pWorkspace->setUpdatesEnabled(false); int y = 0; - for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) { - ChannelStrip *pChannelStrip = NULL; - QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel); - if (pMdiSubWindow) - pChannelStrip = static_cast (pMdiSubWindow->widget()); - if (pChannelStrip) { - /* 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); + const int iStripCount = wlist.count(); + for (int iStrip = 0; iStrip < iStripCount; ++iStrip) { + QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip); + if (pMdiSubWindow) { + pMdiSubWindow->adjustSize(); + int iWidth = m_pWorkspace->width(); + if (iWidth < pMdiSubWindow->width()) + iWidth = pMdiSubWindow->width(); + const int iHeight = pMdiSubWindow->frameGeometry().height(); + pMdiSubWindow->setGeometry(0, y, iWidth, iHeight); y += iHeight; } } @@ -1904,13 +1999,19 @@ m_pOptions->bAutoArrange = bOn; // If on, update whole workspace... - if (m_pOptions->bAutoArrange) + channelsArrangeAuto(); +} + + +void MainForm::channelsArrangeAuto (void) +{ + if (m_pOptions && m_pOptions->bAutoArrange) channelsArrange(); } //------------------------------------------------------------------------- -// qsamplerMainForm -- Help Action slots. +// QSampler::MainForm -- Help Action slots. // Show information about the Qt toolkit. void MainForm::helpAboutQt (void) @@ -1922,72 +2023,55 @@ // 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"; + QStringList list; #ifdef CONFIG_DEBUG - sText += ""; - sText += tr("Debugging option enabled."); - sText += "
"; + list << tr("Debugging option enabled."); #endif #ifndef CONFIG_LIBGIG - sText += ""; - sText += tr("GIG (libgig) file support disabled."); - sText += "
"; + list << tr("GIG (libgig) file support disabled."); #endif #ifndef CONFIG_INSTRUMENT_NAME - sText += ""; - sText += tr("LSCP (liblscp) instrument_name support disabled."); - sText += "
"; + list << tr("LSCP (liblscp) instrument_name support disabled."); #endif #ifndef CONFIG_MUTE_SOLO - sText += ""; - sText += tr("Sampler channel Mute/Solo support disabled."); - sText += "
"; + list << tr("Sampler channel Mute/Solo support disabled."); #endif #ifndef CONFIG_AUDIO_ROUTING - sText += ""; - sText += tr("LSCP (liblscp) audio_routing support disabled."); - sText += "
"; + list << tr("LSCP (liblscp) audio_routing support disabled."); #endif #ifndef CONFIG_FXSEND - sText += ""; - sText += tr("Sampler channel Effect Sends support disabled."); - sText += "
"; + list << tr("Sampler channel Effect Sends support disabled."); #endif #ifndef CONFIG_VOLUME - sText += ""; - sText += tr("Global volume support disabled."); - sText += "
"; + list << tr("Global volume support disabled."); #endif #ifndef CONFIG_MIDI_INSTRUMENT - sText += ""; - sText += tr("MIDI instrument mapping support disabled."); - sText += "
"; + list << tr("MIDI instrument mapping support disabled."); #endif #ifndef CONFIG_EDIT_INSTRUMENT - sText += ""; - sText += tr("Instrument editing support disabled."); - sText += "
"; + list << tr("Instrument editing support disabled."); #endif #ifndef CONFIG_EVENT_CHANNEL_MIDI - sText += ""; - sText += tr("Channel MIDI event support disabled."); - sText += "
"; + list << tr("Channel MIDI event support disabled."); #endif #ifndef CONFIG_EVENT_DEVICE_MIDI - sText += ""; - sText += tr("Device MIDI event support disabled."); - sText += "
"; + list << tr("Device MIDI event support disabled."); #endif #ifndef CONFIG_MAX_VOICES - sText += ""; - sText += tr("Runtime max. voices / disk streams support disabled."); - sText += "
"; + list << tr("Runtime max. voices / disk streams support disabled."); #endif + + // Stuff the about box text... + QString sText = "

\n"; + sText += "" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "
\n"; + sText += "
\n"; + sText += tr("Version") + ": " CONFIG_BUILD_VERSION "
\n"; +// sText += "" + tr("Build") + ": " CONFIG_BUILD_DATE "
\n"; + if (!list.isEmpty()) { + sText += ""; + sText += list.join("
\n"); + sText += "
"; + } sText += "
\n"; sText += tr("Using") + ": "; sText += ::lscp_client_package(); @@ -2017,7 +2101,7 @@ //------------------------------------------------------------------------- -// qsamplerMainForm -- Main window stabilization. +// QSampler::MainForm -- Main window stabilization. void MainForm::stabilizeForm (void) { @@ -2029,9 +2113,10 @@ // Update the main menu state... ChannelStrip *pChannelStrip = activeChannelStrip(); - bool bHasClient = (m_pOptions != NULL && m_pClient != NULL); - bool bHasChannel = (bHasClient && pChannelStrip != NULL); - bool bHasChannels = (bHasClient && m_pWorkspace->subWindowList().count() > 0); + const QList& wlist = m_pWorkspace->subWindowList(); + const bool bHasClient = (m_pOptions != NULL && m_pClient != NULL); + const bool bHasChannel = (bHasClient && pChannelStrip != NULL); + const bool bHasChannels = (bHasClient && wlist.count() > 0); m_ui.fileNewAction->setEnabled(bHasClient); m_ui.fileOpenAction->setEnabled(bHasClient); m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0); @@ -2111,7 +2196,7 @@ m_pVolumeSpinBox->setValue(iVolume); // Do it as commanded... - float fVolume = 0.01f * float(iVolume); + const float fVolume = 0.01f * float(iVolume); if (::lscp_set_volume(m_pClient, fVolume) == LSCP_OK) appendMessages(QObject::tr("Volume: %1.").arg(fVolume)); else @@ -2146,7 +2231,7 @@ void MainForm::updateSession (void) { #ifdef CONFIG_VOLUME - int iVolume = ::lroundf(100.0f * ::lscp_get_volume(m_pClient)); + const int iVolume = ::lroundf(100.0f * ::lscp_get_volume(m_pClient)); m_iVolumeChanging++; m_pVolumeSlider->setValue(iVolume); m_pVolumeSpinBox->setValue(iVolume); @@ -2154,7 +2239,7 @@ #endif #ifdef CONFIG_MIDI_INSTRUMENT // FIXME: Make some room for default instrument maps... - int iMaps = ::lscp_get_midi_instrument_maps(m_pClient); + const int iMaps = ::lscp_get_midi_instrument_maps(m_pClient); if (iMaps < 0) appendMessagesClient("lscp_get_midi_instrument_maps"); else if (iMaps < 1) { @@ -2168,8 +2253,7 @@ updateAllChannelStrips(false); // Do we auto-arrange? - if (m_pOptions && m_pOptions->bAutoArrange) - channelsArrange(); + channelsArrangeAuto(); // Remember to refresh devices and instruments... if (m_pInstrumentListForm) @@ -2181,6 +2265,10 @@ void MainForm::updateAllChannelStrips ( bool bRemoveDeadStrips ) { + // Skip if setting up a new channel strip... + if (m_iDirtySetup > 0) + return; + // Retrieve the current channel list. int *piChannelIDs = ::lscp_list_channels(m_pClient); if (piChannelIDs == NULL) { @@ -2198,22 +2286,24 @@ createChannelStrip(new Channel(piChannelIDs[iChannel])); } // Do we auto-arrange? - if (m_pOptions && m_pOptions->bAutoArrange) - channelsArrange(); + channelsArrangeAuto(); // remove dead channel strips if (bRemoveDeadStrips) { - QList wlist = m_pWorkspace->subWindowList(); - for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) { + const QList& wlist + = m_pWorkspace->subWindowList(); + const int iStripCount = wlist.count(); + for (int iStrip = 0; iStrip < iStripCount; ++iStrip) { ChannelStrip *pChannelStrip = NULL; - QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel); + QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip); if (pMdiSubWindow) pChannelStrip = static_cast (pMdiSubWindow->widget()); if (pChannelStrip) { bool bExists = false; - for (int j = 0; piChannelIDs[j] >= 0; ++j) { - if (!pChannelStrip->channel()) + for (int iChannel = 0; piChannelIDs[iChannel] >= 0; ++iChannel) { + Channel *pChannel = pChannelStrip->channel(); + if (pChannel == NULL) break; - if (piChannelIDs[j] == pChannelStrip->channel()->channelID()) { + if (piChannelIDs[iChannel] == pChannel->channelID()) { // strip exists, don't touch it bExists = true; break; @@ -2238,7 +2328,7 @@ return; // Remove from list if already there (avoid duplicates) - int iIndex = m_pOptions->recentFiles.indexOf(sFilename); + const int iIndex = m_pOptions->recentFiles.indexOf(sFilename); if (iIndex >= 0) m_pOptions->recentFiles.removeAt(iIndex); // Put it to front... @@ -2277,13 +2367,18 @@ void MainForm::updateInstrumentNames (void) { // Full channel list update... - QList wlist = m_pWorkspace->subWindowList(); + const QList& wlist + = m_pWorkspace->subWindowList(); if (wlist.isEmpty()) return; m_pWorkspace->setUpdatesEnabled(false); - for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) { - ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel); + const int iStripCount = wlist.count(); + for (int iStrip = 0; iStrip < iStripCount; ++iStrip) { + ChannelStrip *pChannelStrip = NULL; + QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip); + if (pMdiSubWindow) + pChannelStrip = static_cast (pMdiSubWindow->widget()); if (pChannelStrip) pChannelStrip->updateInstrumentName(true); } @@ -2300,20 +2395,23 @@ // 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... - QList wlist = m_pWorkspace->subWindowList(); + const QList& wlist + = m_pWorkspace->subWindowList(); if (wlist.isEmpty()) return; m_pWorkspace->setUpdatesEnabled(false); - for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) { + const int iStripCount = wlist.count(); + for (int iStrip = 0; iStrip < iStripCount; ++iStrip) { ChannelStrip *pChannelStrip = NULL; - QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel); + QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip); if (pMdiSubWindow) pChannelStrip = static_cast (pMdiSubWindow->widget()); if (pChannelStrip) @@ -2327,14 +2425,16 @@ void MainForm::updateDisplayEffect (void) { // Full channel list update... - QList wlist = m_pWorkspace->subWindowList(); + const QList& wlist + = m_pWorkspace->subWindowList(); if (wlist.isEmpty()) return; m_pWorkspace->setUpdatesEnabled(false); - for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) { + const int iStripCount = wlist.count(); + for (int iStrip = 0; iStrip < iStripCount; ++iStrip) { ChannelStrip *pChannelStrip = NULL; - QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel); + QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip); if (pMdiSubWindow) pChannelStrip = static_cast (pMdiSubWindow->widget()); if (pChannelStrip) @@ -2358,14 +2458,16 @@ #endif // Full channel list update... - QList wlist = m_pWorkspace->subWindowList(); + const QList& wlist + = m_pWorkspace->subWindowList(); if (wlist.isEmpty()) return; m_pWorkspace->setUpdatesEnabled(false); - for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) { + const int iStripCount = wlist.count(); + for (int iStrip = 0; iStrip < iStripCount; ++iStrip) { ChannelStrip *pChannelStrip = NULL; - QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel); + QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip); if (pMdiSubWindow) pChannelStrip = static_cast (pMdiSubWindow->widget()); if (pChannelStrip) @@ -2376,7 +2478,7 @@ //------------------------------------------------------------------------- -// qsamplerMainForm -- Messages window form handlers. +// QSampler::MainForm -- Messages window form handlers. // Messages output methods. void MainForm::appendMessages( const QString& s ) @@ -2488,7 +2590,7 @@ //------------------------------------------------------------------------- -// qsamplerMainForm -- MDI channel strip management. +// QSampler::MainForm -- MDI channel strip management. // The channel strip creation executive. ChannelStrip *MainForm::createChannelStrip ( Channel *pChannel ) @@ -2507,7 +2609,8 @@ pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect); // We'll need a display font. QFont font; - if (font.fromString(m_pOptions->sDisplayFont)) + if (!m_pOptions->sDisplayFont.isEmpty() && + font.fromString(m_pOptions->sDisplayFont)) pChannelStrip->setDisplayFont(font); // Maximum allowed volume setting. pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume); @@ -2547,10 +2650,7 @@ delete pMdiSubWindow; // Do we auto-arrange? - if (m_pOptions && m_pOptions->bAutoArrange) - channelsArrange(); - - stabilizeForm(); + channelsArrangeAuto(); } @@ -2566,18 +2666,19 @@ // Retrieve a channel strip by index. -ChannelStrip *MainForm::channelStripAt ( int iChannel ) +ChannelStrip *MainForm::channelStripAt ( int iStrip ) { if (!m_pWorkspace) return NULL; - QList wlist = m_pWorkspace->subWindowList(); + const QList& wlist + = m_pWorkspace->subWindowList(); if (wlist.isEmpty()) return NULL; - if (iChannel < 0 || iChannel >= wlist.size()) + if (iStrip < 0 || iStrip >= wlist.count()) return NULL; - QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel); + QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip); if (pMdiSubWindow) return static_cast (pMdiSubWindow->widget()); else @@ -2588,13 +2689,15 @@ // Retrieve a channel strip by sampler channel id. ChannelStrip *MainForm::channelStrip ( int iChannelID ) { - QList wlist = m_pWorkspace->subWindowList(); + const QList& wlist + = m_pWorkspace->subWindowList(); if (wlist.isEmpty()) return NULL; - for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) { + const int iStripCount = wlist.count(); + for (int iStrip = 0; iStrip < iStripCount; ++iStrip) { ChannelStrip *pChannelStrip = NULL; - QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel); + QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip); if (pMdiSubWindow) pChannelStrip = static_cast (pMdiSubWindow->widget()); if (pChannelStrip) { @@ -2616,12 +2719,14 @@ m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction); m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction); - QList wlist = m_pWorkspace->subWindowList(); + const QList& wlist + = m_pWorkspace->subWindowList(); if (!wlist.isEmpty()) { m_ui.channelsMenu->addSeparator(); - for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) { + const int iStripCount = wlist.count(); + for (int iStrip = 0; iStrip < iStripCount; ++iStrip) { ChannelStrip *pChannelStrip = NULL; - QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel); + QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip); if (pMdiSubWindow) pChannelStrip = static_cast (pMdiSubWindow->widget()); if (pChannelStrip) { @@ -2630,7 +2735,7 @@ this, SLOT(channelsMenuActivated())); pAction->setCheckable(true); pAction->setChecked(activeChannelStrip() == pChannelStrip); - pAction->setData(iChannel); + pAction->setData(iStrip); } } } @@ -2654,7 +2759,7 @@ //------------------------------------------------------------------------- -// qsamplerMainForm -- Timer stuff. +// QSampler::MainForm -- Timer stuff. // Set the pseudo-timer delay schedule. void MainForm::startSchedule ( int iStartDelay ) @@ -2695,7 +2800,7 @@ ChannelStrip *pChannelStrip = iter.next(); // If successfull, remove from pending list... if (pChannelStrip->updateChannelInfo()) { - int iChannelStrip = m_changedStrips.indexOf(pChannelStrip); + const int iChannelStrip = m_changedStrips.indexOf(pChannelStrip); if (iChannelStrip >= 0) m_changedStrips.removeAt(iChannelStrip); } @@ -2706,10 +2811,12 @@ if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime) { m_iTimerSlot = 0; // Update the channel stream usage for each strip... - QList wlist = m_pWorkspace->subWindowList(); - for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) { + const QList& wlist + = m_pWorkspace->subWindowList(); + const int iStripCount = wlist.count(); + for (int iStrip = 0; iStrip < iStripCount; ++iStrip) { ChannelStrip *pChannelStrip = NULL; - QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel); + QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip); if (pMdiSubWindow) pChannelStrip = static_cast (pMdiSubWindow->widget()); if (pChannelStrip && pChannelStrip->isVisible()) @@ -2725,7 +2832,7 @@ //------------------------------------------------------------------------- -// qsamplerMainForm -- Server stuff. +// QSampler::MainForm -- Server stuff. // Start linuxsampler server... void MainForm::startServer (void) @@ -2759,18 +2866,16 @@ // OK. Let's build the startup process... m_pServer = new QProcess(); - bForceServerStop = true; + m_bForceServerStop = true; // Setup stdout/stderr capture... -// if (m_pOptions->bStdoutCapture) { - m_pServer->setProcessChannelMode(QProcess::ForwardedChannels); - QObject::connect(m_pServer, - SIGNAL(readyReadStandardOutput()), - SLOT(readServerStdout())); - QObject::connect(m_pServer, - SIGNAL(readyReadStandardError()), - SLOT(readServerStdout())); -// } + m_pServer->setProcessChannelMode(QProcess::ForwardedChannels); + QObject::connect(m_pServer, + SIGNAL(readyReadStandardOutput()), + SLOT(readServerStdout())); + QObject::connect(m_pServer, + SIGNAL(readyReadStandardError()), + SLOT(readServerStdout())); // The unforgiveable signal communication... QObject::connect(m_pServer, @@ -2805,7 +2910,7 @@ // Stop linuxsampler server... -void MainForm::stopServer (bool bInteractive) +void MainForm::stopServer ( bool bInteractive ) { // Stop client code. stopClient(); @@ -2819,32 +2924,37 @@ "sampler session at any time by relaunching QSampler.\n\n" "Do you want LinuxSampler to stop?"), QMessageBox::Yes | QMessageBox::No, - QMessageBox::Yes) == QMessageBox::No) - { - bForceServerStop = false; + QMessageBox::Yes) == QMessageBox::No) { + m_bForceServerStop = false; } } + bool bGraceWait = true; + // And try to stop server. - if (m_pServer && bForceServerStop) { + if (m_pServer && m_bForceServerStop) { appendMessages(tr("Server is stopping...")); if (m_pServer->state() == QProcess::Running) { - #if defined(WIN32) + #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) // Try harder... m_pServer->kill(); #else // Try softly... m_pServer->terminate(); + bool bFinished = m_pServer->waitForFinished(QSAMPLER_TIMER_MSECS * 1000); + if (bFinished) bGraceWait = false; #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); + if (bGraceWait) { + QTime t; + t.start(); + while (t.elapsed() < QSAMPLER_TIMER_MSECS) + QApplication::processEvents(QEventLoop::ExcludeUserInputEvents); + } } @@ -2866,7 +2976,7 @@ if (m_pMessages) m_pMessages->flushStdoutBuffer(); - if (m_pServer && bForceServerStop) { + if (m_pServer && m_bForceServerStop) { if (m_pServer->state() != QProcess::NotRunning) { appendMessages(tr("Server is being forced...")); // Force final server shutdown... @@ -2891,7 +3001,7 @@ //------------------------------------------------------------------------- -// qsamplerMainForm -- Client stuff. +// QSampler::MainForm -- Client stuff. // The LSCP client callback procedure. lscp_status_t qsampler_client_callback ( lscp_client_t */*pClient*/, @@ -2943,6 +3053,7 @@ stabilizeForm(); return false; } + // Just set receive timeout value, blindly. ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout); appendMessages( @@ -2998,7 +3109,7 @@ if (!m_pOptions->sSessionFile.isEmpty()) { // Just load the prabably startup session... if (loadSessionFile(m_pOptions->sSessionFile)) { - m_pOptions->sSessionFile = QString::null; + m_pOptions->sSessionFile = QString(); return true; } }