/[svn]/qsampler/trunk/src/qsamplerMainForm.cpp
ViewVC logotype

Diff of /qsampler/trunk/src/qsamplerMainForm.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1558 by capela, Thu Dec 6 09:35:33 2007 UTC revision 4038 by capela, Sun May 15 18:43:41 2022 UTC
# Line 1  Line 1 
1  // qsamplerMainForm.cpp  // qsamplerMainForm.cpp
2  //  //
3  /****************************************************************************  /****************************************************************************
4     Copyright (C) 2004-2007, rncbc aka Rui Nuno Capela. All rights reserved.     Copyright (C) 2004-2022, rncbc aka Rui Nuno Capela. All rights reserved.
5     Copyright (C) 2007, Christian Schoenebeck     Copyright (C) 2007-2019 Christian Schoenebeck
6    
7     This program is free software; you can redistribute it and/or     This program is free software; you can redistribute it and/or
8     modify it under the terms of the GNU General Public License     modify it under the terms of the GNU General Public License
# Line 33  Line 33 
33  #include "qsamplerInstrumentListForm.h"  #include "qsamplerInstrumentListForm.h"
34  #include "qsamplerDeviceForm.h"  #include "qsamplerDeviceForm.h"
35  #include "qsamplerOptionsForm.h"  #include "qsamplerOptionsForm.h"
36    #include "qsamplerDeviceStatusForm.h"
37    
38    #include "qsamplerPaletteForm.h"
39    
40    #include <QStyleFactory>
41    
42    #include <QMdiArea>
43    #include <QMdiSubWindow>
44    
45  #include <QApplication>  #include <QApplication>
 #include <QWorkspace>  
46  #include <QProcess>  #include <QProcess>
47  #include <QMessageBox>  #include <QMessageBox>
48    
 #include <QRegExp>  
49  #include <QTextStream>  #include <QTextStream>
50  #include <QFileDialog>  #include <QFileDialog>
51  #include <QFileInfo>  #include <QFileInfo>
# Line 55  Line 61 
61  #include <QTimer>  #include <QTimer>
62  #include <QDateTime>  #include <QDateTime>
63    
64    #include <QElapsedTimer>
65    
66  #ifdef HAVE_SIGNAL_H  #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
67  #include <signal.h>  #include <QMimeData>
68    #endif
69    
70    #if QT_VERSION < QT_VERSION_CHECK(4, 5, 0)
71    namespace Qt {
72    const WindowFlags WindowCloseButtonHint = WindowFlags(0x08000000);
73    }
74  #endif  #endif
75    
76  #ifdef CONFIG_LIBGIG  #ifdef CONFIG_LIBGIG
77    #if defined(Q_CC_GNU) || defined(Q_CC_MINGW)
78    #pragma GCC diagnostic push
79    #pragma GCC diagnostic ignored "-Wunused-parameter"
80    #endif
81  #include <gig.h>  #include <gig.h>
82    #if defined(Q_CC_GNU) || defined(Q_CC_MINGW)
83    #pragma GCC diagnostic pop
84    #endif
85  #endif  #endif
86    
87  // Needed for lroundf()  // Deprecated QTextStreamFunctions/Qt namespaces workaround.
88  #include <math.h>  #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
89    #define endl    Qt::endl
90    #endif
91    
92  #ifndef CONFIG_ROUND  // Needed for lroundf()
93    #ifdef CONFIG_ROUND
94    #include <cmath>
95    #else
96  static inline long lroundf ( float x )  static inline long lroundf ( float x )
97  {  {
98          if (x >= 0.0f)          if (x >= 0.0f)
# Line 79  static inline long lroundf ( float x ) Line 104  static inline long lroundf ( float x )
104    
105    
106  // All winsock apps needs this.  // All winsock apps needs this.
107  #if defined(WIN32)  #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
108  static WSADATA _wsaData;  static WSADATA _wsaData;
109    #undef HAVE_SIGNAL_H
110  #endif  #endif
111    
112    
113    //-------------------------------------------------------------------------
114    // LADISH Level 1 support stuff.
115    
116    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
117    
118    #include <QSocketNotifier>
119    
120    #include <unistd.h>
121    #include <sys/types.h>
122    #include <sys/socket.h>
123    #include <signal.h>
124    
125    // File descriptor for SIGUSR1 notifier.
126    static int g_fdSigusr1[2] = { -1, -1 };
127    
128    // Unix SIGUSR1 signal handler.
129    static void qsampler_sigusr1_handler ( int /* signo */ )
130    {
131            char c = 1;
132    
133            (void) (::write(g_fdSigusr1[0], &c, sizeof(c)) > 0);
134    }
135    
136    // File descriptor for SIGTERM notifier.
137    static int g_fdSigterm[2] = { -1, -1 };
138    
139    // Unix SIGTERM signal handler.
140    static void qsampler_sigterm_handler ( int /* signo */ )
141    {
142            char c = 1;
143    
144            (void) (::write(g_fdSigterm[0], &c, sizeof(c)) > 0);
145    }
146    
147    #endif  // HAVE_SIGNAL_H
148    
149    
150    //-------------------------------------------------------------------------
151    // QSampler -- namespace
152    
153    
154  namespace QSampler {  namespace QSampler {
155    
156  // Timer constant stuff.  // Timer constant stuff.
# Line 96  namespace QSampler { Line 163  namespace QSampler {
163  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.
164    
165    
166  //-------------------------------------------------------------------------  // Specialties for thread-callback comunication.
167  // CustomEvent -- specialty for callback comunication.  #define QSAMPLER_LSCP_EVENT   QEvent::Type(QEvent::User + 1)
168    
 #define QSAMPLER_CUSTOM_EVENT   QEvent::Type(QEvent::User + 0)  
169    
170  class CustomEvent : public QEvent  //-------------------------------------------------------------------------
171    // QSampler::LscpEvent -- specialty for LSCP callback comunication.
172    
173    class LscpEvent : public QEvent
174  {  {
175  public:  public:
176    
177          // Constructor.          // Constructor.
178          CustomEvent(lscp_event_t event, const char *pchData, int cchData)          LscpEvent(lscp_event_t event, const char *pchData, int cchData)
179                  : QEvent(QSAMPLER_CUSTOM_EVENT)                  : QEvent(QSAMPLER_LSCP_EVENT)
180          {          {
181                  m_event = event;                  m_event = event;
182                  m_data  = QString::fromUtf8(pchData, cchData);                  m_data  = QString::fromUtf8(pchData, cchData);
183          }          }
184    
185          // Accessors.          // Accessors.
186          lscp_event_t event() { return m_event; }          lscp_event_t  event() { return m_event; }
187          QString&     data()  { return m_data;  }          const QString& data() { return m_data;  }
188    
189  private:  private:
190    
# Line 127  private: Line 196  private:
196    
197    
198  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
199  // qsamplerMainForm -- Main window form implementation.  // QSampler::Workspace -- Main window workspace (MDI Area) decl.
200    
201    class Workspace : public QMdiArea
202    {
203    public:
204    
205            Workspace(MainForm *pMainForm) : QMdiArea(pMainForm) {}
206    
207    protected:
208    
209            void resizeEvent(QResizeEvent *)
210            {
211                    MainForm *pMainForm = static_cast<MainForm *> (parentWidget());
212                    if (pMainForm)
213                            pMainForm->channelsArrangeAuto();
214            }
215    };
216    
217    
218    //-------------------------------------------------------------------------
219    // QSampler::MainForm -- Main window form implementation.
220    
221  // Kind of singleton reference.  // Kind of singleton reference.
222  MainForm* MainForm::g_pMainForm = NULL;  MainForm *MainForm::g_pMainForm = nullptr;
223    
224  MainForm::MainForm ( QWidget *pParent )  MainForm::MainForm ( QWidget *pParent )
225          : QMainWindow(pParent)          : QMainWindow(pParent)
226  {  {
227          m_ui.setupUi(this);          m_ui.setupUi(this);
228    #if QT_VERSION < QT_VERSION_CHECK(6, 1, 0)
229            QMainWindow::setWindowIcon(QIcon(":/images/qsampler.png"));
230    #endif
231          // Pseudo-singleton reference setup.          // Pseudo-singleton reference setup.
232          g_pMainForm = this;          g_pMainForm = this;
233    
234          // Initialize some pointer references.          // Initialize some pointer references.
235          m_pOptions = NULL;          m_pOptions = nullptr;
236    
237          // All child forms are to be created later, not earlier than setup.          // All child forms are to be created later, not earlier than setup.
238          m_pMessages = NULL;          m_pMessages = nullptr;
239          m_pInstrumentListForm = NULL;          m_pInstrumentListForm = nullptr;
240          m_pDeviceForm = NULL;          m_pDeviceForm = nullptr;
241    
242          // We'll start clean.          // We'll start clean.
243          m_iUntitled   = 0;          m_iUntitled   = 0;
244            m_iDirtySetup = 0;
245          m_iDirtyCount = 0;          m_iDirtyCount = 0;
246    
247          m_pServer = NULL;          m_pServer = nullptr;
248          m_pClient = NULL;          m_pClient = nullptr;
249    
250          m_iStartDelay = 0;          m_iStartDelay = 0;
251          m_iTimerDelay = 0;          m_iTimerDelay = 0;
252    
253          m_iTimerSlot = 0;          m_iTimerSlot = 0;
254    
255  #ifdef HAVE_SIGNAL_H  #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
256    
257          // Set to ignore any fatal "Broken pipe" signals.          // Set to ignore any fatal "Broken pipe" signals.
258          ::signal(SIGPIPE, SIG_IGN);          ::signal(SIGPIPE, SIG_IGN);
259  #endif  
260            // LADISH Level 1 suport.
261    
262            // Initialize file descriptors for SIGUSR1 socket notifier.
263            ::socketpair(AF_UNIX, SOCK_STREAM, 0, g_fdSigusr1);
264            m_pSigusr1Notifier
265                    = new QSocketNotifier(g_fdSigusr1[1], QSocketNotifier::Read, this);
266    
267            QObject::connect(m_pSigusr1Notifier,
268                    SIGNAL(activated(int)),
269                    SLOT(handle_sigusr1()));
270    
271            // Install SIGUSR1 signal handler.
272            struct sigaction sigusr1;
273            sigusr1.sa_handler = qsampler_sigusr1_handler;
274            sigemptyset(&sigusr1.sa_mask);
275            sigusr1.sa_flags = 0;
276            sigusr1.sa_flags |= SA_RESTART;
277            ::sigaction(SIGUSR1, &sigusr1, nullptr);
278    
279            // Initialize file descriptors for SIGTERM socket notifier.
280            ::socketpair(AF_UNIX, SOCK_STREAM, 0, g_fdSigterm);
281            m_pSigtermNotifier
282                    = new QSocketNotifier(g_fdSigterm[1], QSocketNotifier::Read, this);
283    
284            QObject::connect(m_pSigtermNotifier,
285                    SIGNAL(activated(int)),
286                    SLOT(handle_sigterm()));
287    
288            // Install SIGTERM signal handler.
289            struct sigaction sigterm;
290            sigterm.sa_handler = qsampler_sigterm_handler;
291            sigemptyset(&sigterm.sa_mask);
292            sigterm.sa_flags = 0;
293            sigterm.sa_flags |= SA_RESTART;
294            ::sigaction(SIGTERM, &sigterm, nullptr);
295            ::sigaction(SIGQUIT, &sigterm, nullptr);
296    
297            // Ignore SIGHUP/SIGINT signals.
298            ::signal(SIGHUP, SIG_IGN);
299            ::signal(SIGINT, SIG_IGN);
300    
301    #else   // HAVE_SIGNAL_H
302    
303            m_pSigusr1Notifier = nullptr;
304            m_pSigtermNotifier = nullptr;
305            
306    #endif  // !HAVE_SIGNAL_H
307    
308  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
309          // Make some extras into the toolbar...          // Make some extras into the toolbar...
# Line 184  MainForm::MainForm ( QWidget *pParent ) Line 324  MainForm::MainForm ( QWidget *pParent )
324          QObject::connect(m_pVolumeSlider,          QObject::connect(m_pVolumeSlider,
325                  SIGNAL(valueChanged(int)),                  SIGNAL(valueChanged(int)),
326                  SLOT(volumeChanged(int)));                  SLOT(volumeChanged(int)));
         //m_ui.channelsToolbar->setHorizontallyStretchable(true);  
         //m_ui.channelsToolbar->setStretchableWidget(m_pVolumeSlider);  
327          m_ui.channelsToolbar->addWidget(m_pVolumeSlider);          m_ui.channelsToolbar->addWidget(m_pVolumeSlider);
328          // Volume spin-box          // Volume spin-box
329          m_ui.channelsToolbar->addSeparator();          m_ui.channelsToolbar->addSeparator();
330          m_pVolumeSpinBox = new QSpinBox(m_ui.channelsToolbar);          m_pVolumeSpinBox = new QSpinBox(m_ui.channelsToolbar);
         m_pVolumeSpinBox->setMaximumHeight(24);  
331          m_pVolumeSpinBox->setSuffix(" %");          m_pVolumeSpinBox->setSuffix(" %");
332          m_pVolumeSpinBox->setMinimum(0);          m_pVolumeSpinBox->setMinimum(0);
333          m_pVolumeSpinBox->setMaximum(100);          m_pVolumeSpinBox->setMaximum(100);
# Line 202  MainForm::MainForm ( QWidget *pParent ) Line 339  MainForm::MainForm ( QWidget *pParent )
339  #endif  #endif
340    
341          // Make it an MDI workspace.          // Make it an MDI workspace.
342          m_pWorkspace = new QWorkspace(this);          m_pWorkspace = new Workspace(this);
343          m_pWorkspace->setScrollBarsEnabled(true);          m_pWorkspace->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
344            m_pWorkspace->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
345          // Set the activation connection.          // Set the activation connection.
346          QObject::connect(m_pWorkspace,          QObject::connect(m_pWorkspace,
347                  SIGNAL(windowActivated(QWidget *)),                  SIGNAL(subWindowActivated(QMdiSubWindow *)),
348                  SLOT(activateStrip(QWidget *)));                  SLOT(activateStrip(QMdiSubWindow *)));
349          // Make it shine :-)          // Make it shine :-)
350          setCentralWidget(m_pWorkspace);          setCentralWidget(m_pWorkspace);
351    
# Line 236  MainForm::MainForm ( QWidget *pParent ) Line 374  MainForm::MainForm ( QWidget *pParent )
374          m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;          m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;
375          statusBar()->addWidget(pLabel);          statusBar()->addWidget(pLabel);
376    
377  #if defined(WIN32)  #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
378          WSAStartup(MAKEWORD(1, 1), &_wsaData);          WSAStartup(MAKEWORD(1, 1), &_wsaData);
379  #endif  #endif
380    
# Line 324  MainForm::MainForm ( QWidget *pParent ) Line 462  MainForm::MainForm ( QWidget *pParent )
462          QObject::connect(m_ui.channelsMenu,          QObject::connect(m_ui.channelsMenu,
463                  SIGNAL(aboutToShow()),                  SIGNAL(aboutToShow()),
464                  SLOT(channelsMenuAboutToShow()));                  SLOT(channelsMenuAboutToShow()));
465    #ifdef CONFIG_VOLUME
466            QObject::connect(m_ui.channelsToolbar,
467                    SIGNAL(orientationChanged(Qt::Orientation)),
468                    SLOT(channelsToolbarOrientation(Qt::Orientation)));
469    #endif
470  }  }
471    
472  // Destructor.  // Destructor.
# Line 332  MainForm::~MainForm() Line 475  MainForm::~MainForm()
475          // Do final processing anyway.          // Do final processing anyway.
476          processServerExit();          processServerExit();
477    
478  #if defined(WIN32)  #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
479          WSACleanup();          WSACleanup();
480  #endif  #endif
481    
482    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
483            if (m_pSigusr1Notifier)
484                    delete m_pSigusr1Notifier;
485            if (m_pSigtermNotifier)
486                    delete m_pSigtermNotifier;
487    #endif
488    
489          // Finally drop any widgets around...          // Finally drop any widgets around...
490          if (m_pDeviceForm)          if (m_pDeviceForm)
491                  delete m_pDeviceForm;                  delete m_pDeviceForm;
# Line 362  MainForm::~MainForm() Line 512  MainForm::~MainForm()
512  #endif  #endif
513    
514          // Pseudo-singleton reference shut-down.          // Pseudo-singleton reference shut-down.
515          g_pMainForm = NULL;          g_pMainForm = nullptr;
516  }  }
517    
518    
# Line 374  void MainForm::setup ( Options *pOptions Line 524  void MainForm::setup ( Options *pOptions
524    
525          // What style do we create these forms?          // What style do we create these forms?
526          Qt::WindowFlags wflags = Qt::Window          Qt::WindowFlags wflags = Qt::Window
 #if QT_VERSION >= 0x040200  
527                  | Qt::CustomizeWindowHint                  | Qt::CustomizeWindowHint
 #endif  
528                  | Qt::WindowTitleHint                  | Qt::WindowTitleHint
529                  | Qt::WindowSystemMenuHint                  | Qt::WindowSystemMenuHint
530                  | Qt::WindowMinMaxButtonsHint;                  | Qt::WindowMinMaxButtonsHint
531                    | Qt::WindowCloseButtonHint;
532          if (m_pOptions->bKeepOnTop)          if (m_pOptions->bKeepOnTop)
533                  wflags |= Qt::Tool;                  wflags |= Qt::Tool;
534    
535          // Some child forms are to be created right now.          // Some child forms are to be created right now.
536          m_pMessages = new Messages(this);          m_pMessages = new Messages(this);
537          m_pDeviceForm = new DeviceForm(this, wflags);          m_pDeviceForm = new DeviceForm(this, wflags);
538  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
539          m_pInstrumentListForm = new InstrumentListForm(this, wflags);          m_pInstrumentListForm = new InstrumentListForm(this, wflags);
540  #else  #else
541          viewInstrumentsAction->setEnabled(false);          m_ui.viewInstrumentsAction->setEnabled(false);
542  #endif  #endif
543    
544            // Setup messages logging appropriately...
545            m_pMessages->setLogging(
546                    m_pOptions->bMessagesLog,
547                    m_pOptions->sMessagesLogPath);
548    
549          // Set message defaults...          // Set message defaults...
550          updateMessagesFont();          updateMessagesFont();
551          updateMessagesLimit();          updateMessagesLimit();
552          updateMessagesCapture();          updateMessagesCapture();
553    
554          // Set the visibility signal.          // Set the visibility signal.
555          QObject::connect(m_pMessages,          QObject::connect(m_pMessages,
556                  SIGNAL(visibilityChanged(bool)),                  SIGNAL(visibilityChanged(bool)),
# Line 420  void MainForm::setup ( Options *pOptions Line 577  void MainForm::setup ( Options *pOptions
577          }          }
578    
579          // Try to restore old window positioning and initial visibility.          // Try to restore old window positioning and initial visibility.
580          m_pOptions->loadWidgetGeometry(this);          m_pOptions->loadWidgetGeometry(this, true);
581          m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);          m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);
582          m_pOptions->loadWidgetGeometry(m_pDeviceForm);          m_pOptions->loadWidgetGeometry(m_pDeviceForm);
583    
# Line 459  bool MainForm::queryClose (void) Line 616  bool MainForm::queryClose (void)
616                                  || m_ui.channelsToolbar->isVisible());                                  || m_ui.channelsToolbar->isVisible());
617                          m_pOptions->bStatusbar = statusBar()->isVisible();                          m_pOptions->bStatusbar = statusBar()->isVisible();
618                          // Save the dock windows state.                          // Save the dock windows state.
                         const QString sDockables = saveState().toBase64().data();  
619                          m_pOptions->settings().setValue("/Layout/DockWindows", saveState());                          m_pOptions->settings().setValue("/Layout/DockWindows", saveState());
620                          // And the children, and the main windows state,.                          // And the children, and the main windows state,.
621                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);
622                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);
623                          m_pOptions->saveWidgetGeometry(this);                          m_pOptions->saveWidgetGeometry(this, true);
624                          // Close popup widgets.                          // Close popup widgets.
625                          if (m_pInstrumentListForm)                          if (m_pInstrumentListForm)
626                                  m_pInstrumentListForm->close();                                  m_pInstrumentListForm->close();
627                          if (m_pDeviceForm)                          if (m_pDeviceForm)
628                                  m_pDeviceForm->close();                                  m_pDeviceForm->close();
629                          // Stop client and/or server, gracefully.                          // Stop client and/or server, gracefully.
630                          stopServer();                          stopServer(true /*interactive*/);
631                  }                  }
632          }          }
633    
# Line 481  bool MainForm::queryClose (void) Line 637  bool MainForm::queryClose (void)
637    
638  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )
639  {  {
640          if (queryClose())          if (queryClose()) {
641                    DeviceStatusForm::deleteAllInstances();
642                  pCloseEvent->accept();                  pCloseEvent->accept();
643          else          } else
644                  pCloseEvent->ignore();                  pCloseEvent->ignore();
645  }  }
646    
# Line 492  void MainForm::closeEvent ( QCloseEvent Line 649  void MainForm::closeEvent ( QCloseEvent
649  void MainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )  void MainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )
650  {  {
651          // Accept external drags only...          // Accept external drags only...
652          if (pDragEnterEvent->source() == NULL          if (pDragEnterEvent->source() == nullptr
653                  && pDragEnterEvent->mimeData()->hasUrls()) {                  && pDragEnterEvent->mimeData()->hasUrls()) {
654                  pDragEnterEvent->accept();                  pDragEnterEvent->accept();
655          } else {          } else {
# Line 501  void MainForm::dragEnterEvent ( QDragEnt Line 658  void MainForm::dragEnterEvent ( QDragEnt
658  }  }
659    
660    
661  void MainForm::dropEvent ( QDropEvent* pDropEvent )  void MainForm::dropEvent ( QDropEvent *pDropEvent )
662  {  {
663          // Accept externally originated drops only...          // Accept externally originated drops only...
664          if (pDropEvent->source())          if (pDropEvent->source())
# Line 512  void MainForm::dropEvent ( QDropEvent* p Line 669  void MainForm::dropEvent ( QDropEvent* p
669                  QListIterator<QUrl> iter(pMimeData->urls());                  QListIterator<QUrl> iter(pMimeData->urls());
670                  while (iter.hasNext()) {                  while (iter.hasNext()) {
671                          const QString& sPath = iter.next().toLocalFile();                          const QString& sPath = iter.next().toLocalFile();
672                          if (Channel::isInstrumentFile(sPath)) {                  //      if (Channel::isDlsInstrumentFile(sPath)) {
673                            if (QFileInfo(sPath).exists()) {
674                                  // Try to create a new channel from instrument file...                                  // Try to create a new channel from instrument file...
675                                  Channel *pChannel = new Channel();                                  Channel *pChannel = new Channel();
676                                  if (pChannel == NULL)                                  if (pChannel == nullptr)
677                                          return;                                          return;
678                                  // Start setting the instrument filename...                                  // Start setting the instrument filename...
679                                  pChannel->setInstrument(sPath, 0);                                  pChannel->setInstrument(sPath, 0);
# Line 546  void MainForm::dropEvent ( QDropEvent* p Line 704  void MainForm::dropEvent ( QDropEvent* p
704    
705    
706  // Custome event handler.  // Custome event handler.
707  void MainForm::customEvent(QEvent* pCustomEvent)  void MainForm::customEvent ( QEvent* pEvent )
708  {  {
709          // For the time being, just pump it to messages.          // For the time being, just pump it to messages.
710          if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {          if (pEvent->type() == QSAMPLER_LSCP_EVENT) {
711                  CustomEvent *pEvent = static_cast<CustomEvent *> (pCustomEvent);                  LscpEvent *pLscpEvent = static_cast<LscpEvent *> (pEvent);
712                  if (pEvent->event() == LSCP_EVENT_CHANNEL_INFO) {                  switch (pLscpEvent->event()) {
713                          int iChannelID = pEvent->data().toInt();                          case LSCP_EVENT_CHANNEL_COUNT:
714                          ChannelStrip *pChannelStrip = channelStrip(iChannelID);                                  updateAllChannelStrips(true);
715                          if (pChannelStrip)                                  break;
716                                  channelStripChanged(pChannelStrip);                          case LSCP_EVENT_CHANNEL_INFO: {
717                  } else {                                  const int iChannelID = pLscpEvent->data().toInt();
718                          appendMessagesColor(tr("Notify event: %1 data: %2")                                  ChannelStrip *pChannelStrip = channelStrip(iChannelID);
719                                  .arg(::lscp_event_to_text(pEvent->event()))                                  if (pChannelStrip)
720                                  .arg(pEvent->data()), "#996699");                                          channelStripChanged(pChannelStrip);
721                                    break;
722                            }
723                            case LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT:
724                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
725                                    DeviceStatusForm::onDevicesChanged();
726                                    updateViewMidiDeviceStatusMenu();
727                                    break;
728                            case LSCP_EVENT_MIDI_INPUT_DEVICE_INFO: {
729                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
730                                    const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt();
731                                    DeviceStatusForm::onDeviceChanged(iDeviceID);
732                                    break;
733                            }
734                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT:
735                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
736                                    break;
737                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO:
738                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
739                                    break;
740                    #if CONFIG_EVENT_CHANNEL_MIDI
741                            case LSCP_EVENT_CHANNEL_MIDI: {
742                                    const int iChannelID = pLscpEvent->data().section(' ', 0, 0).toInt();
743                                    ChannelStrip *pChannelStrip = channelStrip(iChannelID);
744                                    if (pChannelStrip)
745                                            pChannelStrip->midiActivityLedOn();
746                                    break;
747                            }
748                    #endif
749                    #if CONFIG_EVENT_DEVICE_MIDI
750                            case LSCP_EVENT_DEVICE_MIDI: {
751                                    const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt();
752                                    const int iPortID   = pLscpEvent->data().section(' ', 1, 1).toInt();
753                                    DeviceStatusForm *pDeviceStatusForm
754                                            = DeviceStatusForm::getInstance(iDeviceID);
755                                    if (pDeviceStatusForm)
756                                            pDeviceStatusForm->midiArrived(iPortID);
757                                    break;
758                            }
759                    #endif
760                            default:
761                                    appendMessagesColor(tr("LSCP Event: %1 data: %2")
762                                            .arg(::lscp_event_to_text(pLscpEvent->event()))
763                                            .arg(pLscpEvent->data()), "#996699");
764                  }                  }
765          }          }
766  }  }
767    
768    
769    // LADISH Level 1 -- SIGUSR1 signal handler.
770    void MainForm::handle_sigusr1 (void)
771    {
772    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
773    
774            char c;
775    
776            if (::read(g_fdSigusr1[1], &c, sizeof(c)) > 0)
777                    saveSession(false);
778    
779    #endif
780    }
781    
782    
783    void MainForm::handle_sigterm (void)
784    {
785    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
786    
787            char c;
788    
789            if (::read(g_fdSigterm[1], &c, sizeof(c)) > 0)
790                    close();
791    
792    #endif
793    }
794    
795    
796    void MainForm::updateViewMidiDeviceStatusMenu (void)
797    {
798            m_ui.viewMidiDeviceStatusMenu->clear();
799            const std::map<int, DeviceStatusForm *> statusForms
800                    = DeviceStatusForm::getInstances();
801            std::map<int, DeviceStatusForm *>::const_iterator iter
802                    = statusForms.begin();
803            for ( ; iter != statusForms.end(); ++iter) {
804                    DeviceStatusForm *pStatusForm = iter->second;
805                    m_ui.viewMidiDeviceStatusMenu->addAction(
806                            pStatusForm->visibleAction());
807            }
808    }
809    
810    
811  // Context menu event handler.  // Context menu event handler.
812  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )
813  {  {
# Line 574  void MainForm::contextMenuEvent( QContex Line 818  void MainForm::contextMenuEvent( QContex
818    
819    
820  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
821  // qsamplerMainForm -- Brainless public property accessors.  // QSampler::MainForm -- Brainless public property accessors.
822    
823  // The global options settings property.  // The global options settings property.
824  Options *MainForm::options (void) const  Options *MainForm::options (void) const
# Line 598  MainForm *MainForm::getInstance (void) Line 842  MainForm *MainForm::getInstance (void)
842    
843    
844  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
845  // qsamplerMainForm -- Session file stuff.  // QSampler::MainForm -- Session file stuff.
846    
847  // Format the displayable session filename.  // Format the displayable session filename.
848  QString MainForm::sessionName ( const QString& sFilename )  QString MainForm::sessionName ( const QString& sFilename )
849  {  {
850          bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);          const bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);
851          QString sSessionName = sFilename;          QString sSessionName = sFilename;
852          if (sSessionName.isEmpty())          if (sSessionName.isEmpty())
853                  sSessionName = tr("Untitled") + QString::number(m_iUntitled);                  sSessionName = tr("Untitled") + QString::number(m_iUntitled);
# Line 627  bool MainForm::newSession (void) Line 871  bool MainForm::newSession (void)
871          m_iUntitled++;          m_iUntitled++;
872    
873          // Stabilize form.          // Stabilize form.
874          m_sFilename = QString::null;          m_sFilename = QString();
875          m_iDirtyCount = 0;          m_iDirtyCount = 0;
876          appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));          appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));
877          stabilizeForm();          stabilizeForm();
# Line 639  bool MainForm::newSession (void) Line 883  bool MainForm::newSession (void)
883  // Open an existing sampler session.  // Open an existing sampler session.
884  bool MainForm::openSession (void)  bool MainForm::openSession (void)
885  {  {
886          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
887                  return false;                  return false;
888    
889          // Ask for the filename to open...          // Ask for the filename to open...
890          QString sFilename = QFileDialog::getOpenFileName(this,          QString sFilename = QFileDialog::getOpenFileName(this,
891                  QSAMPLER_TITLE ": " + tr("Open Session"), // Caption.                  tr("Open Session"),                       // Caption.
892                  m_pOptions->sSessionDir,                  // Start here.                  m_pOptions->sSessionDir,                  // Start here.
893                  tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)                  tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
894          );          );
# Line 665  bool MainForm::openSession (void) Line 909  bool MainForm::openSession (void)
909  // Save current sampler session with another name.  // Save current sampler session with another name.
910  bool MainForm::saveSession ( bool bPrompt )  bool MainForm::saveSession ( bool bPrompt )
911  {  {
912          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
913                  return false;                  return false;
914    
915          QString sFilename = m_sFilename;          QString sFilename = m_sFilename;
# Line 677  bool MainForm::saveSession ( bool bPromp Line 921  bool MainForm::saveSession ( bool bPromp
921                          sFilename = m_pOptions->sSessionDir;                          sFilename = m_pOptions->sSessionDir;
922                  // Prompt the guy...                  // Prompt the guy...
923                  sFilename = QFileDialog::getSaveFileName(this,                  sFilename = QFileDialog::getSaveFileName(this,
924                          QSAMPLER_TITLE ": " + tr("Save Session"), // Caption.                          tr("Save Session"),                       // Caption.
925                          sFilename,                                // Start here.                          sFilename,                                // Start here.
926                          tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)                          tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
927                  );                  );
# Line 687  bool MainForm::saveSession ( bool bPromp Line 931  bool MainForm::saveSession ( bool bPromp
931                  // Enforce .lscp extension...                  // Enforce .lscp extension...
932                  if (QFileInfo(sFilename).suffix().isEmpty())                  if (QFileInfo(sFilename).suffix().isEmpty())
933                          sFilename += ".lscp";                          sFilename += ".lscp";
934            #if 0
935                  // Check if already exists...                  // Check if already exists...
936                  if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {                  if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {
937                          if (QMessageBox::warning(this,                          if (QMessageBox::warning(this,
938                                  QSAMPLER_TITLE ": " + tr("Warning"),                                  tr("Warning"),
939                                  tr("The file already exists:\n\n"                                  tr("The file already exists:\n\n"
940                                  "\"%1\"\n\n"                                  "\"%1\"\n\n"
941                                  "Do you want to replace it?")                                  "Do you want to replace it?")
942                                  .arg(sFilename),                                  .arg(sFilename),
943                                  tr("Replace"), tr("Cancel")) > 0)                                  QMessageBox::Yes | QMessageBox::No)
944                                    == QMessageBox::No)
945                                  return false;                                  return false;
946                  }                  }
947            #endif
948          }          }
949    
950          // Save it right away.          // Save it right away.
# Line 713  bool MainForm::closeSession ( bool bForc Line 960  bool MainForm::closeSession ( bool bForc
960          // Are we dirty enough to prompt it?          // Are we dirty enough to prompt it?
961          if (m_iDirtyCount > 0) {          if (m_iDirtyCount > 0) {
962                  switch (QMessageBox::warning(this,                  switch (QMessageBox::warning(this,
963                          QSAMPLER_TITLE ": " + tr("Warning"),                          tr("Warning"),
964                          tr("The current session has been changed:\n\n"                          tr("The current session has been changed:\n\n"
965                          "\"%1\"\n\n"                          "\"%1\"\n\n"
966                          "Do you want to save the changes?")                          "Do you want to save the changes?")
967                          .arg(sessionName(m_sFilename)),                          .arg(sessionName(m_sFilename)),
968                          tr("Save"), tr("Discard"), tr("Cancel"))) {                          QMessageBox::Save |
969                  case 0:     // Save...                          QMessageBox::Discard |
970                            QMessageBox::Cancel)) {
971                    case QMessageBox::Save:
972                          bClose = saveSession(false);                          bClose = saveSession(false);
973                          // Fall thru....                          // Fall thru....
974                  case 1:     // Discard                  case QMessageBox::Discard:
975                          break;                          break;
976                  default:    // Cancel.                  default:    // Cancel.
977                          bClose = false;                          bClose = false;
# Line 734  bool MainForm::closeSession ( bool bForc Line 983  bool MainForm::closeSession ( bool bForc
983          if (bClose) {          if (bClose) {
984                  // Remove all channel strips from sight...                  // Remove all channel strips from sight...
985                  m_pWorkspace->setUpdatesEnabled(false);                  m_pWorkspace->setUpdatesEnabled(false);
986                  QWidgetList wlist = m_pWorkspace->windowList();                  const QList<QMdiSubWindow *>& wlist
987                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                          = m_pWorkspace->subWindowList();
988                          ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
989                            ChannelStrip *pChannelStrip
990                                    = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
991                          if (pChannelStrip) {                          if (pChannelStrip) {
992                                  Channel *pChannel = pChannelStrip->channel();                                  Channel *pChannel = pChannelStrip->channel();
993                                  if (bForce && pChannel)                                  if (bForce && pChannel)
994                                          pChannel->removeChannel();                                          pChannel->removeChannel();
995                                  delete pChannelStrip;                                  delete pChannelStrip;
996                          }                          }
997                            delete pMdiSubWindow;
998                  }                  }
999                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
1000                  // We're now clean, for sure.                  // We're now clean, for sure.
# Line 756  bool MainForm::closeSession ( bool bForc Line 1008  bool MainForm::closeSession ( bool bForc
1008  // Load a session from specific file path.  // Load a session from specific file path.
1009  bool MainForm::loadSessionFile ( const QString& sFilename )  bool MainForm::loadSessionFile ( const QString& sFilename )
1010  {  {
1011          if (m_pClient == NULL)          if (m_pClient == nullptr)
1012                  return false;                  return false;
1013    
1014          // Open and read from real file.          // Open and read from real file.
# Line 832  bool MainForm::loadSessionFile ( const Q Line 1084  bool MainForm::loadSessionFile ( const Q
1084  // Save current session to specific file path.  // Save current session to specific file path.
1085  bool MainForm::saveSessionFile ( const QString& sFilename )  bool MainForm::saveSessionFile ( const QString& sFilename )
1086  {  {
1087          if (m_pClient == NULL)          if (m_pClient == nullptr)
1088                  return false;                  return false;
1089    
1090          // Check whether server is apparently OK...          // Check whether server is apparently OK...
# Line 854  bool MainForm::saveSessionFile ( const Q Line 1106  bool MainForm::saveSessionFile ( const Q
1106          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1107    
1108          // Write the file.          // Write the file.
1109          int  iErrors = 0;          int iErrors = 0;
1110          QTextStream ts(&file);          QTextStream ts(&file);
1111          ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;          ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;
1112          ts << "# " << tr("Version")          ts << "# " << tr("Version") << ": " CONFIG_BUILD_VERSION << endl;
1113          << ": " QSAMPLER_VERSION << endl;  //      ts << "# " << tr("Build") << ": " CONFIG_BUILD_DATE << endl;
         ts << "# " << tr("Build")  
         << ": " __DATE__ " " __TIME__ << endl;  
1114          ts << "#"  << endl;          ts << "#"  << endl;
1115          ts << "# " << tr("File")          ts << "# " << tr("File")
1116          << ": " << QFileInfo(sFilename).fileName() << endl;          << ": " << QFileInfo(sFilename).fileName() << endl;
# Line 873  bool MainForm::saveSessionFile ( const Q Line 1123  bool MainForm::saveSessionFile ( const Q
1123          // It is assumed that this new kind of device+session file          // It is assumed that this new kind of device+session file
1124          // will be loaded from a complete initialized server...          // will be loaded from a complete initialized server...
1125          int *piDeviceIDs;          int *piDeviceIDs;
1126          int  iDevice;          int  i, iDevice;
1127          ts << "RESET" << endl;          ts << "RESET" << endl;
1128    
1129          // Audio device mapping.          // Audio device mapping.
1130          QMap<int, int> audioDeviceMap;          QMap<int, int> audioDeviceMap; iDevice = 0;
1131          piDeviceIDs = Device::getDevices(m_pClient, Device::Audio);          piDeviceIDs = Device::getDevices(m_pClient, Device::Audio);
1132          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (i = 0; piDeviceIDs && piDeviceIDs[i] >= 0; ++i) {
1133                  ts << endl;                  Device device(Device::Audio, piDeviceIDs[i]);
1134                  Device device(Device::Audio, piDeviceIDs[iDevice]);                  // Avoid plug-in driver devices...
1135                    if (device.driverName().toUpper() == "PLUGIN")
1136                            continue;
1137                  // Audio device specification...                  // Audio device specification...
1138                    ts << endl;
1139                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1140                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1141                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();
# Line 913  bool MainForm::saveSessionFile ( const Q Line 1166  bool MainForm::saveSessionFile ( const Q
1166                          iPort++;                          iPort++;
1167                  }                  }
1168                  // Audio device index/id mapping.                  // Audio device index/id mapping.
1169                  audioDeviceMap[device.deviceID()] = iDevice;                  audioDeviceMap.insert(device.deviceID(), iDevice++);
1170                  // Try to keep it snappy :)                  // Try to keep it snappy :)
1171                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1172          }          }
1173    
1174          // MIDI device mapping.          // MIDI device mapping.
1175          QMap<int, int> midiDeviceMap;          QMap<int, int> midiDeviceMap; iDevice = 0;
1176          piDeviceIDs = Device::getDevices(m_pClient, Device::Midi);          piDeviceIDs = Device::getDevices(m_pClient, Device::Midi);
1177          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (i = 0; piDeviceIDs && piDeviceIDs[i] >= 0; ++i) {
1178                  ts << endl;                  Device device(Device::Midi, piDeviceIDs[i]);
1179                  Device device(Device::Midi, piDeviceIDs[iDevice]);                  // Avoid plug-in driver devices...
1180                    if (device.driverName().toUpper() == "PLUGIN")
1181                            continue;
1182                  // MIDI device specification...                  // MIDI device specification...
1183                    ts << endl;
1184                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1185                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1186                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();
# Line 955  bool MainForm::saveSessionFile ( const Q Line 1211  bool MainForm::saveSessionFile ( const Q
1211                          iPort++;                          iPort++;
1212                  }                  }
1213                  // MIDI device index/id mapping.                  // MIDI device index/id mapping.
1214                  midiDeviceMap[device.deviceID()] = iDevice;                  midiDeviceMap.insert(device.deviceID(), iDevice++);
1215                  // Try to keep it snappy :)                  // Try to keep it snappy :)
1216                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1217          }          }
# Line 966  bool MainForm::saveSessionFile ( const Q Line 1222  bool MainForm::saveSessionFile ( const Q
1222          QMap<int, int> midiInstrumentMap;          QMap<int, int> midiInstrumentMap;
1223          int *piMaps = ::lscp_list_midi_instrument_maps(m_pClient);          int *piMaps = ::lscp_list_midi_instrument_maps(m_pClient);
1224          for (int iMap = 0; piMaps && piMaps[iMap] >= 0; iMap++) {          for (int iMap = 0; piMaps && piMaps[iMap] >= 0; iMap++) {
1225                  int iMidiMap = piMaps[iMap];                  const int iMidiMap = piMaps[iMap];
1226                  const char *pszMapName                  const char *pszMapName
1227                          = ::lscp_get_midi_instrument_map_name(m_pClient, iMidiMap);                          = ::lscp_get_midi_instrument_map_name(m_pClient, iMidiMap);
1228                  ts << "# " << tr("MIDI instrument map") << " " << iMap;                  ts << "# " << tr("MIDI instrument map") << " " << iMap;
# Line 1018  bool MainForm::saveSessionFile ( const Q Line 1274  bool MainForm::saveSessionFile ( const Q
1274                  }                  }
1275                  ts << endl;                  ts << endl;
1276                  // Check for errors...                  // Check for errors...
1277                  if (pInstrs == NULL && ::lscp_client_get_errno(m_pClient)) {                  if (pInstrs == nullptr && ::lscp_client_get_errno(m_pClient)) {
1278                          appendMessagesClient("lscp_list_midi_instruments");                          appendMessagesClient("lscp_list_midi_instruments");
1279                          iErrors++;                          iErrors++;
1280                  }                  }
1281                  // MIDI strument index/id mapping.                  // MIDI strument index/id mapping.
1282                  midiInstrumentMap[iMidiMap] = iMap;                  midiInstrumentMap.insert(iMidiMap, iMap);
1283          }          }
1284          // Check for errors...          // Check for errors...
1285          if (piMaps == NULL && ::lscp_client_get_errno(m_pClient)) {          if (piMaps == nullptr && ::lscp_client_get_errno(m_pClient)) {
1286                  appendMessagesClient("lscp_list_midi_instrument_maps");                  appendMessagesClient("lscp_list_midi_instrument_maps");
1287                  iErrors++;                  iErrors++;
1288          }          }
1289  #endif  // CONFIG_MIDI_INSTRUMENT  #endif  // CONFIG_MIDI_INSTRUMENT
1290    
1291          // Sampler channel mapping.          // Sampler channel mapping...
1292          QWidgetList wlist = m_pWorkspace->windowList();          int iChannelID = 0;
1293          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          const QList<QMdiSubWindow *>& wlist
1294                  ChannelStrip* pChannelStrip                  = m_pWorkspace->subWindowList();
1295                          = static_cast<ChannelStrip *> (wlist.at(iChannel));          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
1296                    ChannelStrip *pChannelStrip
1297                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
1298                  if (pChannelStrip) {                  if (pChannelStrip) {
1299                          Channel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
1300                          if (pChannel) {                          if (pChannel) {
1301                                  ts << "# " << tr("Channel") << " " << iChannel << endl;                                  // Avoid "artifial" plug-in devices...
1302                                    const int iAudioDevice = pChannel->audioDevice();
1303                                    if (!audioDeviceMap.contains(iAudioDevice))
1304                                            continue;
1305                                    const int iMidiDevice = pChannel->midiDevice();
1306                                    if (!midiDeviceMap.contains(iMidiDevice))
1307                                            continue;
1308                                    // Go for regular, canonical devices...
1309                                    ts << "# " << tr("Channel") << " " << iChannelID << endl;
1310                                  ts << "ADD CHANNEL" << endl;                                  ts << "ADD CHANNEL" << endl;
1311                                  if (audioDeviceMap.isEmpty()) {                                  if (audioDeviceMap.isEmpty()) {
1312                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannelID
1313                                                  << " " << pChannel->audioDriver() << endl;                                                  << " " << pChannel->audioDriver() << endl;
1314                                  } else {                                  } else {
1315                                          ts << "SET CHANNEL AUDIO_OUTPUT_DEVICE " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_DEVICE " << iChannelID
1316                                                  << " " << audioDeviceMap[pChannel->audioDevice()] << endl;                                                  << " " << audioDeviceMap.value(iAudioDevice) << endl;
1317                                  }                                  }
1318                                  if (midiDeviceMap.isEmpty()) {                                  if (midiDeviceMap.isEmpty()) {
1319                                          ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannel                                          ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannelID
1320                                                  << " " << pChannel->midiDriver() << endl;                                                  << " " << pChannel->midiDriver() << endl;
1321                                  } else {                                  } else {
1322                                          ts << "SET CHANNEL MIDI_INPUT_DEVICE " << iChannel                                          ts << "SET CHANNEL MIDI_INPUT_DEVICE " << iChannelID
1323                                                  << " " << midiDeviceMap[pChannel->midiDevice()] << endl;                                                  << " " << midiDeviceMap.value(iMidiDevice) << endl;
1324                                  }                                  }
1325                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannelID
1326                                          << " " << pChannel->midiPort() << endl;                                          << " " << pChannel->midiPort() << endl;
1327                                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";                                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannelID << " ";
1328                                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)                                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
1329                                          ts << "ALL";                                          ts << "ALL";
1330                                  else                                  else
1331                                          ts << pChannel->midiChannel();                                          ts << pChannel->midiChannel();
1332                                  ts << endl;                                  ts << endl;
1333                                  ts << "LOAD ENGINE " << pChannel->engineName()                                  ts << "LOAD ENGINE " << pChannel->engineName()
1334                                          << " " << iChannel << endl;                                          << " " << iChannelID << endl;
1335                                  if (pChannel->instrumentStatus() < 100) ts << "# ";                                  if (pChannel->instrumentStatus() < 100) ts << "# ";
1336                                  ts << "LOAD INSTRUMENT NON_MODAL '"                                  ts << "LOAD INSTRUMENT NON_MODAL '"
1337                                          << pChannel->instrumentFile() << "' "                                          << pChannel->instrumentFile() << "' "
1338                                          << pChannel->instrumentNr() << " " << iChannel << endl;                                          << pChannel->instrumentNr() << " " << iChannelID << endl;
1339                                  ChannelRoutingMap::ConstIterator audioRoute;                                  ChannelRoutingMap::ConstIterator audioRoute;
1340                                  for (audioRoute = pChannel->audioRouting().begin();                                  for (audioRoute = pChannel->audioRouting().begin();
1341                                                  audioRoute != pChannel->audioRouting().end();                                                  audioRoute != pChannel->audioRouting().end();
1342                                                          ++audioRoute) {                                                          ++audioRoute) {
1343                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannelID
1344                                                  << " " << audioRoute.key()                                                  << " " << audioRoute.key()
1345                                                  << " " << audioRoute.value() << endl;                                                  << " " << audioRoute.value() << endl;
1346                                  }                                  }
1347                                  ts << "SET CHANNEL VOLUME " << iChannel                                  ts << "SET CHANNEL VOLUME " << iChannelID
1348                                          << " " << pChannel->volume() << endl;                                          << " " << pChannel->volume() << endl;
1349                                  if (pChannel->channelMute())                                  if (pChannel->channelMute())
1350                                          ts << "SET CHANNEL MUTE " << iChannel << " 1" << endl;                                          ts << "SET CHANNEL MUTE " << iChannelID << " 1" << endl;
1351                                  if (pChannel->channelSolo())                                  if (pChannel->channelSolo())
1352                                          ts << "SET CHANNEL SOLO " << iChannel << " 1" << endl;                                          ts << "SET CHANNEL SOLO " << iChannelID << " 1" << endl;
1353  #ifdef CONFIG_MIDI_INSTRUMENT                          #ifdef CONFIG_MIDI_INSTRUMENT
1354                                  if (pChannel->midiMap() >= 0) {                                  const int iMidiMap = pChannel->midiMap();
1355                                          ts << "SET CHANNEL MIDI_INSTRUMENT_MAP " << iChannel                                  if (midiInstrumentMap.contains(iMidiMap)) {
1356                                                  << " " << midiInstrumentMap[pChannel->midiMap()] << endl;                                          ts << "SET CHANNEL MIDI_INSTRUMENT_MAP " << iChannelID
1357                                                    << " " << midiInstrumentMap.value(iMidiMap) << endl;
1358                                  }                                  }
1359  #endif                          #endif
1360  #ifdef CONFIG_FXSEND                          #ifdef CONFIG_FXSEND
                                 int iChannelID = pChannel->channelID();  
1361                                  int *piFxSends = ::lscp_list_fxsends(m_pClient, iChannelID);                                  int *piFxSends = ::lscp_list_fxsends(m_pClient, iChannelID);
1362                                  for (int iFxSend = 0;                                  for (int iFxSend = 0;
1363                                                  piFxSends && piFxSends[iFxSend] >= 0;                                                  piFxSends && piFxSends[iFxSend] >= 0;
# Line 1099  bool MainForm::saveSessionFile ( const Q Line 1365  bool MainForm::saveSessionFile ( const Q
1365                                          lscp_fxsend_info_t *pFxSendInfo = ::lscp_get_fxsend_info(                                          lscp_fxsend_info_t *pFxSendInfo = ::lscp_get_fxsend_info(
1366                                                  m_pClient, iChannelID, piFxSends[iFxSend]);                                                  m_pClient, iChannelID, piFxSends[iFxSend]);
1367                                          if (pFxSendInfo) {                                          if (pFxSendInfo) {
1368                                                  ts << "CREATE FX_SEND " << iChannel                                                  ts << "CREATE FX_SEND " << iChannelID
1369                                                          << " " << pFxSendInfo->midi_controller;                                                          << " " << pFxSendInfo->midi_controller;
1370                                                  if (pFxSendInfo->name)                                                  if (pFxSendInfo->name)
1371                                                          ts << " '" << pFxSendInfo->name << "'";                                                          ts << " '" << pFxSendInfo->name << "'";
# Line 1109  bool MainForm::saveSessionFile ( const Q Line 1375  bool MainForm::saveSessionFile ( const Q
1375                                                                  piRouting && piRouting[iAudioSrc] >= 0;                                                                  piRouting && piRouting[iAudioSrc] >= 0;
1376                                                                          iAudioSrc++) {                                                                          iAudioSrc++) {
1377                                                          ts << "SET FX_SEND AUDIO_OUTPUT_CHANNEL "                                                          ts << "SET FX_SEND AUDIO_OUTPUT_CHANNEL "
1378                                                                  << iChannel                                                                  << iChannelID
1379                                                                  << " " << iFxSend                                                                  << " " << iFxSend
1380                                                                  << " " << iAudioSrc                                                                  << " " << iAudioSrc
1381                                                                  << " " << piRouting[iAudioSrc] << endl;                                                                  << " " << piRouting[iAudioSrc] << endl;
1382                                                  }                                                  }
1383  #ifdef CONFIG_FXSEND_LEVEL                                          #ifdef CONFIG_FXSEND_LEVEL
1384                                                  ts << "SET FX_SEND LEVEL " << iChannel                                                  ts << "SET FX_SEND LEVEL " << iChannelID
1385                                                          << " " << iFxSend                                                          << " " << iFxSend
1386                                                          << " " << pFxSendInfo->level << endl;                                                          << " " << pFxSendInfo->level << endl;
1387  #endif                                          #endif
1388                                          }       // Check for errors...                                          }       // Check for errors...
1389                                          else if (::lscp_client_get_errno(m_pClient)) {                                          else if (::lscp_client_get_errno(m_pClient)) {
1390                                                  appendMessagesClient("lscp_get_fxsend_info");                                                  appendMessagesClient("lscp_get_fxsend_info");
1391                                                  iErrors++;                                                  iErrors++;
1392                                          }                                          }
1393                                  }                                  }
1394  #endif                          #endif
1395                                  ts << endl;                                  ts << endl;
1396                                    // Go for next channel...
1397                                    ++iChannelID;
1398                          }                          }
1399                  }                  }
1400                  // Try to keep it snappy :)                  // Try to keep it snappy :)
# Line 1178  void MainForm::sessionDirty (void) Line 1446  void MainForm::sessionDirty (void)
1446    
1447    
1448  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1449  // qsamplerMainForm -- File Action slots.  // QSampler::MainForm -- File Action slots.
1450    
1451  // Create a new sampler session.  // Create a new sampler session.
1452  void MainForm::fileNew (void)  void MainForm::fileNew (void)
# Line 1202  void MainForm::fileOpenRecent (void) Line 1470  void MainForm::fileOpenRecent (void)
1470          // Retrive filename index from action data...          // Retrive filename index from action data...
1471          QAction *pAction = qobject_cast<QAction *> (sender());          QAction *pAction = qobject_cast<QAction *> (sender());
1472          if (pAction && m_pOptions) {          if (pAction && m_pOptions) {
1473                  int iIndex = pAction->data().toInt();                  const int iIndex = pAction->data().toInt();
1474                  if (iIndex >= 0 && iIndex < m_pOptions->recentFiles.count()) {                  if (iIndex >= 0 && iIndex < m_pOptions->recentFiles.count()) {
1475                          QString sFilename = m_pOptions->recentFiles[iIndex];                          QString sFilename = m_pOptions->recentFiles[iIndex];
1476                          // Check if we can safely close the current session...                          // Check if we can safely close the current session...
# Line 1232  void MainForm::fileSaveAs (void) Line 1500  void MainForm::fileSaveAs (void)
1500  // Reset the sampler instance.  // Reset the sampler instance.
1501  void MainForm::fileReset (void)  void MainForm::fileReset (void)
1502  {  {
1503          if (m_pClient == NULL)          if (m_pClient == nullptr)
1504                  return;                  return;
1505    
1506          // Ask user whether he/she want's an internal sampler reset...          // Ask user whether he/she want's an internal sampler reset...
1507          if (QMessageBox::warning(this,          if (m_pOptions && m_pOptions->bConfirmReset) {
1508                  QSAMPLER_TITLE ": " + tr("Warning"),                  const QString& sTitle = tr("Warning");
1509                  tr("Resetting the sampler instance will close\n"                  const QString& sText = tr(
1510                  "all device and channel configurations.\n\n"                          "Resetting the sampler instance will close\n"
1511                  "Please note that this operation may cause\n"                          "all device and channel configurations.\n\n"
1512                  "temporary MIDI and Audio disruption.\n\n"                          "Please note that this operation may cause\n"
1513                  "Do you want to reset the sampler engine now?"),                          "temporary MIDI and Audio disruption.\n\n"
1514                  tr("Reset"), tr("Cancel")) > 0)                          "Do you want to reset the sampler engine now?");
1515                  return;          #if 0
1516                    if (QMessageBox::warning(this, sTitle, sText,
1517                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1518                            return;
1519            #else
1520                    QMessageBox mbox(this);
1521                    mbox.setIcon(QMessageBox::Warning);
1522                    mbox.setWindowTitle(sTitle);
1523                    mbox.setText(sText);
1524                    mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1525                    QCheckBox cbox(tr("Don't ask this again"));
1526                    cbox.setChecked(false);
1527                    cbox.blockSignals(true);
1528                    mbox.addButton(&cbox, QMessageBox::ActionRole);
1529                    if (mbox.exec() == QMessageBox::Cancel)
1530                            return;
1531                    if (cbox.isChecked())
1532                            m_pOptions->bConfirmReset = false;
1533            #endif
1534            }
1535    
1536          // Trye closing the current session, first...          // Trye closing the current session, first...
1537          if (!closeSession(true))          if (!closeSession(true))
# Line 1269  void MainForm::fileReset (void) Line 1556  void MainForm::fileReset (void)
1556  // Restart the client/server instance.  // Restart the client/server instance.
1557  void MainForm::fileRestart (void)  void MainForm::fileRestart (void)
1558  {  {
1559          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
1560                  return;                  return;
1561    
1562          bool bRestart = true;          bool bRestart = true;
1563    
1564          // Ask user whether he/she want's a complete restart...          // Ask user whether he/she want's a complete restart...
1565          // (if we're currently up and running)          // (if we're currently up and running)
1566          if (bRestart && m_pClient) {          if (m_pOptions && m_pOptions->bConfirmRestart) {
1567                  bRestart = (QMessageBox::warning(this,                  const QString& sTitle = tr("Warning");
1568                          QSAMPLER_TITLE ": " + tr("Warning"),                  const QString& sText = tr(
1569                          tr("New settings will be effective after\n"                          "New settings will be effective after\n"
1570                          "restarting the client/server connection.\n\n"                          "restarting the client/server connection.\n\n"
1571                          "Please note that this operation may cause\n"                          "Please note that this operation may cause\n"
1572                          "temporary MIDI and Audio disruption.\n\n"                          "temporary MIDI and Audio disruption.\n\n"
1573                          "Do you want to restart the connection now?"),                          "Do you want to restart the connection now?");
1574                          tr("Restart"), tr("Cancel")) == 0);          #if 0
1575                    if (QMessageBox::warning(this, sTitle, sText,
1576                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1577                            bRestart = false;
1578            #else
1579                    QMessageBox mbox(this);
1580                    mbox.setIcon(QMessageBox::Warning);
1581                    mbox.setWindowTitle(sTitle);
1582                    mbox.setText(sText);
1583                    mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1584                    QCheckBox cbox(tr("Don't ask this again"));
1585                    cbox.setChecked(false);
1586                    cbox.blockSignals(true);
1587                    mbox.addButton(&cbox, QMessageBox::ActionRole);
1588                    if (mbox.exec() == QMessageBox::Cancel)
1589                            bRestart = false;
1590                    else
1591                    if (cbox.isChecked())
1592                            m_pOptions->bConfirmRestart = false;
1593            #endif
1594          }          }
1595    
1596          // Are we still for it?          // Are we still for it?
# Line 1306  void MainForm::fileExit (void) Line 1612  void MainForm::fileExit (void)
1612    
1613    
1614  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1615  // qsamplerMainForm -- Edit Action slots.  // QSampler::MainForm -- Edit Action slots.
1616    
1617  // Add a new sampler channel.  // Add a new sampler channel.
1618  void MainForm::editAddChannel (void)  void MainForm::editAddChannel (void)
1619  {  {
1620          if (m_pClient == NULL)          ++m_iDirtySetup;
1621            addChannelStrip();
1622            --m_iDirtySetup;
1623    }
1624    
1625    void MainForm::addChannelStrip (void)
1626    {
1627            if (m_pClient == nullptr)
1628                  return;                  return;
1629    
1630          // Just create the channel instance...          // Just create the channel instance...
1631          Channel *pChannel = new Channel();          Channel *pChannel = new Channel();
1632          if (pChannel == NULL)          if (pChannel == nullptr)
1633                  return;                  return;
1634    
1635          // Before we show it up, may be we'll          // Before we show it up, may be we'll
# Line 1334  void MainForm::editAddChannel (void) Line 1647  void MainForm::editAddChannel (void)
1647          }          }
1648    
1649          // Do we auto-arrange?          // Do we auto-arrange?
1650          if (m_pOptions && m_pOptions->bAutoArrange)          channelsArrangeAuto();
                 channelsArrange();  
1651    
1652          // Make that an overall update.          // Make that an overall update.
1653          m_iDirtyCount++;          m_iDirtyCount++;
# Line 1346  void MainForm::editAddChannel (void) Line 1658  void MainForm::editAddChannel (void)
1658  // Remove current sampler channel.  // Remove current sampler channel.
1659  void MainForm::editRemoveChannel (void)  void MainForm::editRemoveChannel (void)
1660  {  {
1661          if (m_pClient == NULL)          ++m_iDirtySetup;
1662            removeChannelStrip();
1663            --m_iDirtySetup;
1664    }
1665    
1666    void MainForm::removeChannelStrip (void)
1667    {
1668            if (m_pClient == nullptr)
1669                  return;                  return;
1670    
1671          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1672          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
1673                  return;                  return;
1674    
1675          Channel *pChannel = pChannelStrip->channel();          Channel *pChannel = pChannelStrip->channel();
1676          if (pChannel == NULL)          if (pChannel == nullptr)
1677                  return;                  return;
1678    
1679          // Prompt user if he/she's sure about this...          // Prompt user if he/she's sure about this...
1680          if (m_pOptions && m_pOptions->bConfirmRemove) {          if (m_pOptions && m_pOptions->bConfirmRemove) {
1681                  if (QMessageBox::warning(this,                  const QString& sTitle = tr("Warning");
1682                          QSAMPLER_TITLE ": " + tr("Warning"),                  const QString& sText = tr(
1683                          tr("About to remove channel:\n\n"                          "About to remove channel:\n\n"
1684                          "%1\n\n"                          "%1\n\n"
1685                          "Are you sure?")                          "Are you sure?")
1686                          .arg(pChannelStrip->windowTitle()),                          .arg(pChannelStrip->windowTitle());
1687                          tr("OK"), tr("Cancel")) > 0)          #if 0
1688                    if (QMessageBox::warning(this, sTitle, sText,
1689                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1690                          return;                          return;
1691            #else
1692                    QMessageBox mbox(this);
1693                    mbox.setIcon(QMessageBox::Warning);
1694                    mbox.setWindowTitle(sTitle);
1695                    mbox.setText(sText);
1696                    mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1697                    QCheckBox cbox(tr("Don't ask this again"));
1698                    cbox.setChecked(false);
1699                    cbox.blockSignals(true);
1700                    mbox.addButton(&cbox, QMessageBox::ActionRole);
1701                    if (mbox.exec() == QMessageBox::Cancel)
1702                            return;
1703                    if (cbox.isChecked())
1704                            m_pOptions->bConfirmRemove = false;
1705            #endif
1706          }          }
1707    
1708          // Remove the existing sampler channel.          // Remove the existing sampler channel.
# Line 1374  void MainForm::editRemoveChannel (void) Line 1710  void MainForm::editRemoveChannel (void)
1710                  return;                  return;
1711    
1712          // Just delete the channel strip.          // Just delete the channel strip.
1713          delete pChannelStrip;          destroyChannelStrip(pChannelStrip);
   
         // Do we auto-arrange?  
         if (m_pOptions && m_pOptions->bAutoArrange)  
                 channelsArrange();  
1714    
1715          // We'll be dirty, for sure...          // We'll be dirty, for sure...
1716          m_iDirtyCount++;          m_iDirtyCount++;
# Line 1389  void MainForm::editRemoveChannel (void) Line 1721  void MainForm::editRemoveChannel (void)
1721  // Setup current sampler channel.  // Setup current sampler channel.
1722  void MainForm::editSetupChannel (void)  void MainForm::editSetupChannel (void)
1723  {  {
1724          if (m_pClient == NULL)          if (m_pClient == nullptr)
1725                  return;                  return;
1726    
1727          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1728          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
1729                  return;                  return;
1730    
1731          // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
# Line 1404  void MainForm::editSetupChannel (void) Line 1736  void MainForm::editSetupChannel (void)
1736  // Edit current sampler channel.  // Edit current sampler channel.
1737  void MainForm::editEditChannel (void)  void MainForm::editEditChannel (void)
1738  {  {
1739          if (m_pClient == NULL)          if (m_pClient == nullptr)
1740                  return;                  return;
1741    
1742          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1743          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
1744                  return;                  return;
1745    
1746          // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
# Line 1419  void MainForm::editEditChannel (void) Line 1751  void MainForm::editEditChannel (void)
1751  // Reset current sampler channel.  // Reset current sampler channel.
1752  void MainForm::editResetChannel (void)  void MainForm::editResetChannel (void)
1753  {  {
1754          if (m_pClient == NULL)          if (m_pClient == nullptr)
1755                  return;                  return;
1756    
1757          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1758          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
1759                  return;                  return;
1760    
1761          // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
# Line 1434  void MainForm::editResetChannel (void) Line 1766  void MainForm::editResetChannel (void)
1766  // Reset all sampler channels.  // Reset all sampler channels.
1767  void MainForm::editResetAllChannels (void)  void MainForm::editResetAllChannels (void)
1768  {  {
1769          if (m_pClient == NULL)          if (m_pClient == nullptr)
1770                  return;                  return;
1771    
1772          // Invoque the channel strip procedure,          // Invoque the channel strip procedure,
1773          // for all channels out there...          // for all channels out there...
1774          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
1775          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
1776          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  = m_pWorkspace->subWindowList();
1777                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
1778                    ChannelStrip *pChannelStrip
1779                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
1780                  if (pChannelStrip)                  if (pChannelStrip)
1781                          pChannelStrip->channelReset();                          pChannelStrip->channelReset();
1782          }          }
# Line 1451  void MainForm::editResetAllChannels (voi Line 1785  void MainForm::editResetAllChannels (voi
1785    
1786    
1787  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1788  // qsamplerMainForm -- View Action slots.  // QSampler::MainForm -- View Action slots.
1789    
1790  // Show/hide the main program window menubar.  // Show/hide the main program window menubar.
1791  void MainForm::viewMenubar ( bool bOn )  void MainForm::viewMenubar ( bool bOn )
# Line 1501  void MainForm::viewMessages ( bool bOn ) Line 1835  void MainForm::viewMessages ( bool bOn )
1835  // Show/hide the MIDI instrument list-view form.  // Show/hide the MIDI instrument list-view form.
1836  void MainForm::viewInstruments (void)  void MainForm::viewInstruments (void)
1837  {  {
1838          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
1839                  return;                  return;
1840    
1841          if (m_pInstrumentListForm) {          if (m_pInstrumentListForm) {
# Line 1520  void MainForm::viewInstruments (void) Line 1854  void MainForm::viewInstruments (void)
1854  // Show/hide the device configurator form.  // Show/hide the device configurator form.
1855  void MainForm::viewDevices (void)  void MainForm::viewDevices (void)
1856  {  {
1857          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
1858                  return;                  return;
1859    
1860          if (m_pDeviceForm) {          if (m_pDeviceForm) {
# Line 1539  void MainForm::viewDevices (void) Line 1873  void MainForm::viewDevices (void)
1873  // Show options dialog.  // Show options dialog.
1874  void MainForm::viewOptions (void)  void MainForm::viewOptions (void)
1875  {  {
1876          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
1877                  return;                  return;
1878    
1879          OptionsForm* pOptionsForm = new OptionsForm(this);          OptionsForm* pOptionsForm = new OptionsForm(this);
1880          if (pOptionsForm) {          if (pOptionsForm) {
1881                  // Check out some initial nullities(tm)...                  // Check out some initial nullities(tm)...
1882                  ChannelStrip* pChannelStrip = activeChannelStrip();                  ChannelStrip *pChannelStrip = activeChannelStrip();
1883                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)
1884                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();
1885                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)
1886                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
1887                  // To track down deferred or immediate changes.                  // To track down deferred or immediate changes.
1888                  QString sOldServerHost      = m_pOptions->sServerHost;                  const QString sOldServerHost       = m_pOptions->sServerHost;
1889                  int     iOldServerPort      = m_pOptions->iServerPort;                  const int     iOldServerPort       = m_pOptions->iServerPort;
1890                  int     iOldServerTimeout   = m_pOptions->iServerTimeout;                  const int     iOldServerTimeout    = m_pOptions->iServerTimeout;
1891                  bool    bOldServerStart     = m_pOptions->bServerStart;                  const bool    bOldServerStart      = m_pOptions->bServerStart;
1892                  QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;                  const QString sOldServerCmdLine    = m_pOptions->sServerCmdLine;
1893                  QString sOldDisplayFont     = m_pOptions->sDisplayFont;                  const bool    bOldMessagesLog      = m_pOptions->bMessagesLog;
1894                  bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;                  const QString sOldMessagesLogPath  = m_pOptions->sMessagesLogPath;
1895                  int     iOldMaxVolume       = m_pOptions->iMaxVolume;                  const QString sOldDisplayFont      = m_pOptions->sDisplayFont;
1896                  QString sOldMessagesFont    = m_pOptions->sMessagesFont;                  const bool    bOldDisplayEffect    = m_pOptions->bDisplayEffect;
1897                  bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;                  const int     iOldMaxVolume        = m_pOptions->iMaxVolume;
1898                  bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;                  const QString sOldMessagesFont     = m_pOptions->sMessagesFont;
1899                  int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;                  const bool    bOldKeepOnTop        = m_pOptions->bKeepOnTop;
1900                  int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;                  const bool    bOldStdoutCapture    = m_pOptions->bStdoutCapture;
1901                  bool    bOldCompletePath    = m_pOptions->bCompletePath;                  const int     bOldMessagesLimit    = m_pOptions->bMessagesLimit;
1902                  bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;                  const int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;
1903                  int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;                  const bool    bOldCompletePath     = m_pOptions->bCompletePath;
1904                    const bool    bOldInstrumentNames  = m_pOptions->bInstrumentNames;
1905                    const int     iOldMaxRecentFiles   = m_pOptions->iMaxRecentFiles;
1906                    const int     iOldBaseFontSize     = m_pOptions->iBaseFontSize;
1907                    const QString sOldCustomStyleTheme = m_pOptions->sCustomStyleTheme;
1908                    const QString sOldCustomColorTheme = m_pOptions->sCustomColorTheme;
1909                  // Load the current setup settings.                  // Load the current setup settings.
1910                  pOptionsForm->setup(m_pOptions);                  pOptionsForm->setup(m_pOptions);
1911                  // Show the setup dialog...                  // Show the setup dialog...
1912                  if (pOptionsForm->exec()) {                  if (pOptionsForm->exec()) {
1913                          // Warn if something will be only effective on next run.                          // Warn if something will be only effective on next run.
1914                            int iNeedRestart = 0;
1915                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1916                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture)) {
                                 ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||  
                                 (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {  
                                 QMessageBox::information(this,  
                                         QSAMPLER_TITLE ": " + tr("Information"),  
                                         tr("Some settings may be only effective\n"  
                                         "next time you start this program."), tr("OK"));  
1917                                  updateMessagesCapture();                                  updateMessagesCapture();
1918                                    ++iNeedRestart;
1919                            }
1920                            if (( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||
1921                                    (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)     ||
1922                                    (iOldBaseFontSize   !=  m_pOptions->iBaseFontSize)) {
1923                                    ++iNeedRestart;
1924                            }
1925                            // Check whether restart is needed or whether
1926                            // custom options maybe set up immediately...
1927                            if (m_pOptions->sCustomStyleTheme != sOldCustomStyleTheme) {
1928                                    if (m_pOptions->sCustomStyleTheme.isEmpty()) {
1929                                            ++iNeedRestart;
1930                                    } else {
1931                                            QApplication::setStyle(
1932                                                    QStyleFactory::create(m_pOptions->sCustomStyleTheme));
1933                                    }
1934                            }
1935                            if (m_pOptions->sCustomColorTheme != sOldCustomColorTheme) {
1936                                    if (m_pOptions->sCustomColorTheme.isEmpty()) {
1937                                            ++iNeedRestart;
1938                                    } else {
1939                                            QPalette pal;
1940                                            if (PaletteForm::namedPalette(
1941                                                            &m_pOptions->settings(), m_pOptions->sCustomColorTheme, pal))
1942                                                    QApplication::setPalette(pal);
1943                                    }
1944                          }                          }
1945                          // Check wheather something immediate has changed.                          // Check wheather something immediate has changed.
1946                            if (( bOldMessagesLog && !m_pOptions->bMessagesLog) ||
1947                                    (!bOldMessagesLog &&  m_pOptions->bMessagesLog) ||
1948                                    (sOldMessagesLogPath != m_pOptions->sMessagesLogPath))
1949                                    m_pMessages->setLogging(
1950                                            m_pOptions->bMessagesLog, m_pOptions->sMessagesLogPath);
1951                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||
1952                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||
1953                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
# Line 1603  void MainForm::viewOptions (void) Line 1968  void MainForm::viewOptions (void)
1968                                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||                                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||
1969                                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))                                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))
1970                                  updateMessagesLimit();                                  updateMessagesLimit();
1971                            // Show restart needed message...
1972                            if (iNeedRestart > 0) {
1973                                    QMessageBox::information(this,
1974                                            tr("Information"),
1975                                            tr("Some settings may be only effective\n"
1976                                            "next time you start this program."));
1977                            }
1978                          // And now the main thing, whether we'll do client/server recycling?                          // And now the main thing, whether we'll do client/server recycling?
1979                          if ((sOldServerHost != m_pOptions->sServerHost) ||                          if ((sOldServerHost != m_pOptions->sServerHost) ||
1980                                  (iOldServerPort != m_pOptions->iServerPort) ||                                  (iOldServerPort != m_pOptions->iServerPort) ||
# Line 1623  void MainForm::viewOptions (void) Line 1995  void MainForm::viewOptions (void)
1995    
1996    
1997  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1998  // qsamplerMainForm -- Channels action slots.  // QSampler::MainForm -- Channels action slots.
1999    
2000  // Arrange channel strips.  // Arrange channel strips.
2001  void MainForm::channelsArrange (void)  void MainForm::channelsArrange (void)
2002  {  {
2003          // Full width vertical tiling          // Full width vertical tiling
2004          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2005                    = m_pWorkspace->subWindowList();
2006          if (wlist.isEmpty())          if (wlist.isEmpty())
2007                  return;                  return;
2008    
2009          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2010          int y = 0;          int y = 0;
2011          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2012                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  pMdiSubWindow->adjustSize();
2013          /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {                  const QRect& frameRect
2014                          // Prevent flicker...                          = pMdiSubWindow->frameGeometry();
2015                          pChannelStrip->hide();                  int w = m_pWorkspace->width();
2016                          pChannelStrip->showNormal();                  if (w < frameRect.width())
2017                  }   */                          w = frameRect.width();
2018                  pChannelStrip->adjustSize();                  const int h = frameRect.height();
2019                  int iWidth  = m_pWorkspace->width();                  pMdiSubWindow->setGeometry(0, y, w, h);
2020                  if (iWidth < pChannelStrip->width())                  y += h;
                         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;  
2021          }          }
2022          m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2023    
# Line 1661  void MainForm::channelsArrange (void) Line 2028  void MainForm::channelsArrange (void)
2028  // Auto-arrange channel strips.  // Auto-arrange channel strips.
2029  void MainForm::channelsAutoArrange ( bool bOn )  void MainForm::channelsAutoArrange ( bool bOn )
2030  {  {
2031          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2032                  return;                  return;
2033    
2034          // Toggle the auto-arrange flag.          // Toggle the auto-arrange flag.
2035          m_pOptions->bAutoArrange = bOn;          m_pOptions->bAutoArrange = bOn;
2036    
2037          // If on, update whole workspace...          // If on, update whole workspace...
2038          if (m_pOptions->bAutoArrange)          channelsArrangeAuto();
2039    }
2040    
2041    
2042    void MainForm::channelsArrangeAuto (void)
2043    {
2044            if (m_pOptions && m_pOptions->bAutoArrange)
2045                  channelsArrange();                  channelsArrange();
2046  }  }
2047    
2048    
2049  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2050  // qsamplerMainForm -- Help Action slots.  // QSampler::MainForm -- Help Action slots.
2051    
2052  // Show information about the Qt toolkit.  // Show information about the Qt toolkit.
2053  void MainForm::helpAboutQt (void)  void MainForm::helpAboutQt (void)
# Line 1686  void MainForm::helpAboutQt (void) Line 2059  void MainForm::helpAboutQt (void)
2059  // Show information about application program.  // Show information about application program.
2060  void MainForm::helpAbout (void)  void MainForm::helpAbout (void)
2061  {  {
2062          // Stuff the about box text...          QStringList list;
         QString sText = "<p>\n";  
         sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";  
         sText += "<br />\n";  
         sText += tr("Version") + ": <b>" QSAMPLER_VERSION "</b><br />\n";  
         sText += "<small>" + tr("Build") + ": " __DATE__ " " __TIME__ "</small><br />\n";  
2063  #ifdef CONFIG_DEBUG  #ifdef CONFIG_DEBUG
2064          sText += "<small><font color=\"red\">";          list << tr("Debugging option enabled.");
         sText += tr("Debugging option enabled.");  
         sText += "</font></small><br />";  
2065  #endif  #endif
2066  #ifndef CONFIG_LIBGIG  #ifndef CONFIG_LIBGIG
2067          sText += "<small><font color=\"red\">";          list << tr("GIG (libgig) file support disabled.");
         sText += tr("GIG (libgig) file support disabled.");  
         sText += "</font></small><br />";  
2068  #endif  #endif
2069  #ifndef CONFIG_INSTRUMENT_NAME  #ifndef CONFIG_INSTRUMENT_NAME
2070          sText += "<small><font color=\"red\">";          list << tr("LSCP (liblscp) instrument_name support disabled.");
         sText += tr("LSCP (liblscp) instrument_name support disabled.");  
         sText += "</font></small><br />";  
2071  #endif  #endif
2072  #ifndef CONFIG_MUTE_SOLO  #ifndef CONFIG_MUTE_SOLO
2073          sText += "<small><font color=\"red\">";          list << tr("Sampler channel Mute/Solo support disabled.");
         sText += tr("Sampler channel Mute/Solo support disabled.");  
         sText += "</font></small><br />";  
2074  #endif  #endif
2075  #ifndef CONFIG_AUDIO_ROUTING  #ifndef CONFIG_AUDIO_ROUTING
2076          sText += "<small><font color=\"red\">";          list << tr("LSCP (liblscp) audio_routing support disabled.");
         sText += tr("LSCP (liblscp) audio_routing support disabled.");  
         sText += "</font></small><br />";  
2077  #endif  #endif
2078  #ifndef CONFIG_FXSEND  #ifndef CONFIG_FXSEND
2079          sText += "<small><font color=\"red\">";          list << tr("Sampler channel Effect Sends support disabled.");
         sText += tr("Sampler channel Effect Sends support disabled.");  
         sText += "</font></small><br />";  
2080  #endif  #endif
2081  #ifndef CONFIG_VOLUME  #ifndef CONFIG_VOLUME
2082          sText += "<small><font color=\"red\">";          list << tr("Global volume support disabled.");
         sText += tr("Global volume support disabled.");  
         sText += "</font></small><br />";  
2083  #endif  #endif
2084  #ifndef CONFIG_MIDI_INSTRUMENT  #ifndef CONFIG_MIDI_INSTRUMENT
2085          sText += "<small><font color=\"red\">";          list << tr("MIDI instrument mapping support disabled.");
         sText += tr("MIDI instrument mapping support disabled.");  
         sText += "</font></small><br />";  
2086  #endif  #endif
2087  #ifndef CONFIG_EDIT_INSTRUMENT  #ifndef CONFIG_EDIT_INSTRUMENT
2088          sText += "<small><font color=\"red\">";          list << tr("Instrument editing support disabled.");
2089          sText += tr("Instrument editing support disabled.");  #endif
2090          sText += "</font></small><br />";  #ifndef CONFIG_EVENT_CHANNEL_MIDI
2091            list << tr("Channel MIDI event support disabled.");
2092    #endif
2093    #ifndef CONFIG_EVENT_DEVICE_MIDI
2094            list << tr("Device MIDI event support disabled.");
2095  #endif  #endif
2096    #ifndef CONFIG_MAX_VOICES
2097            list << tr("Runtime max. voices / disk streams support disabled.");
2098    #endif
2099    
2100            // Stuff the about box text...
2101            QString sText = "<p>\n";
2102            sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";
2103            sText += "<br />\n";
2104            sText += tr("Version") + ": <b>" CONFIG_BUILD_VERSION "</b><br />\n";
2105    //      sText += "<small>" + tr("Build") + ": " CONFIG_BUILD_DATE "</small><br />\n";
2106            if (!list.isEmpty()) {
2107                    sText += "<small><font color=\"red\">";
2108                    sText += list.join("<br />\n");
2109                    sText += "</font></small>";
2110            }
2111          sText += "<br />\n";          sText += "<br />\n";
2112          sText += tr("Using") + ": ";          sText += tr("Using: Qt %1").arg(qVersion());
2113    #if defined(QT_STATIC)
2114            sText += "-static";
2115    #endif
2116            sText += ", ";
2117          sText += ::lscp_client_package();          sText += ::lscp_client_package();
2118          sText += " ";          sText += " ";
2119          sText += ::lscp_client_version();          sText += ::lscp_client_version();
# Line 1761  void MainForm::helpAbout (void) Line 2136  void MainForm::helpAbout (void)
2136          sText += "</small>";          sText += "</small>";
2137          sText += "</p>\n";          sText += "</p>\n";
2138    
2139          QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);          QMessageBox::about(this, tr("About"), sText);
2140  }  }
2141    
2142    
2143  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2144  // qsamplerMainForm -- Main window stabilization.  // QSampler::MainForm -- Main window stabilization.
2145    
2146  void MainForm::stabilizeForm (void)  void MainForm::stabilizeForm (void)
2147  {  {
# Line 1774  void MainForm::stabilizeForm (void) Line 2149  void MainForm::stabilizeForm (void)
2149          QString sSessionName = sessionName(m_sFilename);          QString sSessionName = sessionName(m_sFilename);
2150          if (m_iDirtyCount > 0)          if (m_iDirtyCount > 0)
2151                  sSessionName += " *";                  sSessionName += " *";
2152          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));          setWindowTitle(sSessionName);
2153    
2154          // Update the main menu state...          // Update the main menu state...
2155          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
2156          bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);          const QList<QMdiSubWindow *>& wlist = m_pWorkspace->subWindowList();
2157          bool bHasChannel = (bHasClient && pChannelStrip != NULL);          const bool bHasClient = (m_pOptions != nullptr && m_pClient != nullptr);
2158            const bool bHasChannel = (bHasClient && pChannelStrip != nullptr);
2159            const bool bHasChannels = (bHasClient && wlist.count() > 0);
2160          m_ui.fileNewAction->setEnabled(bHasClient);          m_ui.fileNewAction->setEnabled(bHasClient);
2161          m_ui.fileOpenAction->setEnabled(bHasClient);          m_ui.fileOpenAction->setEnabled(bHasClient);
2162          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
2163          m_ui.fileSaveAsAction->setEnabled(bHasClient);          m_ui.fileSaveAsAction->setEnabled(bHasClient);
2164          m_ui.fileResetAction->setEnabled(bHasClient);          m_ui.fileResetAction->setEnabled(bHasClient);
2165          m_ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);          m_ui.fileRestartAction->setEnabled(bHasClient || m_pServer == nullptr);
2166          m_ui.editAddChannelAction->setEnabled(bHasClient);          m_ui.editAddChannelAction->setEnabled(bHasClient);
2167          m_ui.editRemoveChannelAction->setEnabled(bHasChannel);          m_ui.editRemoveChannelAction->setEnabled(bHasChannel);
2168          m_ui.editSetupChannelAction->setEnabled(bHasChannel);          m_ui.editSetupChannelAction->setEnabled(bHasChannel);
# Line 1795  void MainForm::stabilizeForm (void) Line 2172  void MainForm::stabilizeForm (void)
2172          m_ui.editEditChannelAction->setEnabled(false);          m_ui.editEditChannelAction->setEnabled(false);
2173  #endif  #endif
2174          m_ui.editResetChannelAction->setEnabled(bHasChannel);          m_ui.editResetChannelAction->setEnabled(bHasChannel);
2175          m_ui.editResetAllChannelsAction->setEnabled(bHasChannel);          m_ui.editResetAllChannelsAction->setEnabled(bHasChannels);
2176          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());
2177  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
2178          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm
# Line 1807  void MainForm::stabilizeForm (void) Line 2184  void MainForm::stabilizeForm (void)
2184          m_ui.viewDevicesAction->setChecked(m_pDeviceForm          m_ui.viewDevicesAction->setChecked(m_pDeviceForm
2185                  && m_pDeviceForm->isVisible());                  && m_pDeviceForm->isVisible());
2186          m_ui.viewDevicesAction->setEnabled(bHasClient);          m_ui.viewDevicesAction->setEnabled(bHasClient);
2187          m_ui.channelsArrangeAction->setEnabled(bHasChannel);          m_ui.viewMidiDeviceStatusMenu->setEnabled(
2188                    DeviceStatusForm::getInstances().size() > 0);
2189            m_ui.channelsArrangeAction->setEnabled(bHasChannels);
2190    
2191  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2192          // Toolbar widgets are also affected...          // Toolbar widgets are also affected...
# Line 1857  void MainForm::volumeChanged ( int iVolu Line 2236  void MainForm::volumeChanged ( int iVolu
2236                  m_pVolumeSpinBox->setValue(iVolume);                  m_pVolumeSpinBox->setValue(iVolume);
2237    
2238          // Do it as commanded...          // Do it as commanded...
2239          float fVolume = 0.01f * float(iVolume);          const float fVolume = 0.01f * float(iVolume);
2240          if (::lscp_set_volume(m_pClient, fVolume) == LSCP_OK)          if (::lscp_set_volume(m_pClient, fVolume) == LSCP_OK)
2241                  appendMessages(QObject::tr("Volume: %1.").arg(fVolume));                  appendMessages(QObject::tr("Volume: %1.").arg(fVolume));
2242          else          else
# Line 1873  void MainForm::volumeChanged ( int iVolu Line 2252  void MainForm::volumeChanged ( int iVolu
2252    
2253    
2254  // Channel change receiver slot.  // Channel change receiver slot.
2255  void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)  void MainForm::channelStripChanged ( ChannelStrip *pChannelStrip )
2256  {  {
2257          // Add this strip to the changed list...          // Add this strip to the changed list...
2258          if (!m_changedStrips.contains(pChannelStrip)) {          if (!m_changedStrips.contains(pChannelStrip)) {
# Line 1892  void MainForm::channelStripChanged(Chann Line 2271  void MainForm::channelStripChanged(Chann
2271  void MainForm::updateSession (void)  void MainForm::updateSession (void)
2272  {  {
2273  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2274          int iVolume = ::lroundf(100.0f * ::lscp_get_volume(m_pClient));          const int iVolume = ::lroundf(100.0f * ::lscp_get_volume(m_pClient));
2275          m_iVolumeChanging++;          m_iVolumeChanging++;
2276          m_pVolumeSlider->setValue(iVolume);          m_pVolumeSlider->setValue(iVolume);
2277          m_pVolumeSpinBox->setValue(iVolume);          m_pVolumeSpinBox->setValue(iVolume);
# Line 1900  void MainForm::updateSession (void) Line 2279  void MainForm::updateSession (void)
2279  #endif  #endif
2280  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
2281          // FIXME: Make some room for default instrument maps...          // FIXME: Make some room for default instrument maps...
2282          int iMaps = ::lscp_get_midi_instrument_maps(m_pClient);          const int iMaps = ::lscp_get_midi_instrument_maps(m_pClient);
2283          if (iMaps < 0)          if (iMaps < 0)
2284                  appendMessagesClient("lscp_get_midi_instrument_maps");                  appendMessagesClient("lscp_get_midi_instrument_maps");
2285          else if (iMaps < 1) {          else if (iMaps < 1) {
# Line 1911  void MainForm::updateSession (void) Line 2290  void MainForm::updateSession (void)
2290          }          }
2291  #endif  #endif
2292    
2293            updateAllChannelStrips(false);
2294    
2295            // Do we auto-arrange?
2296            channelsArrangeAuto();
2297    
2298            // Remember to refresh devices and instruments...
2299            if (m_pInstrumentListForm)
2300                    m_pInstrumentListForm->refreshInstruments();
2301            if (m_pDeviceForm)
2302                    m_pDeviceForm->refreshDevices();
2303    }
2304    
2305    
2306    void MainForm::updateAllChannelStrips ( bool bRemoveDeadStrips )
2307    {
2308            // Skip if setting up a new channel strip...
2309            if (m_iDirtySetup > 0)
2310                    return;
2311    
2312          // Retrieve the current channel list.          // Retrieve the current channel list.
2313          int *piChannelIDs = ::lscp_list_channels(m_pClient);          int *piChannelIDs = ::lscp_list_channels(m_pClient);
2314          if (piChannelIDs == NULL) {          if (piChannelIDs == nullptr) {
2315                  if (::lscp_client_get_errno(m_pClient)) {                  if (::lscp_client_get_errno(m_pClient)) {
2316                          appendMessagesClient("lscp_list_channels");                          appendMessagesClient("lscp_list_channels");
2317                          appendMessagesError(                          appendMessagesError(
# Line 1922  void MainForm::updateSession (void) Line 2320  void MainForm::updateSession (void)
2320          } else {          } else {
2321                  // Try to (re)create each channel.                  // Try to (re)create each channel.
2322                  m_pWorkspace->setUpdatesEnabled(false);                  m_pWorkspace->setUpdatesEnabled(false);
2323                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; ++iChannel) {
2324                          // Check if theres already a channel strip for this one...                          // Check if theres already a channel strip for this one...
2325                          if (!channelStrip(piChannelIDs[iChannel]))                          if (!channelStrip(piChannelIDs[iChannel]))
2326                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));
2327                  }                  }
2328                    // Do we auto-arrange?
2329                    channelsArrangeAuto();
2330                    // remove dead channel strips
2331                    if (bRemoveDeadStrips) {
2332                            const QList<QMdiSubWindow *>& wlist
2333                                    = m_pWorkspace->subWindowList();
2334                            foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2335                                    ChannelStrip *pChannelStrip
2336                                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2337                                    if (pChannelStrip) {
2338                                            bool bExists = false;
2339                                            for (int iChannel = 0; piChannelIDs[iChannel] >= 0; ++iChannel) {
2340                                                    Channel *pChannel = pChannelStrip->channel();
2341                                                    if (pChannel == nullptr)
2342                                                            break;
2343                                                    if (piChannelIDs[iChannel] == pChannel->channelID()) {
2344                                                            // strip exists, don't touch it
2345                                                            bExists = true;
2346                                                            break;
2347                                                    }
2348                                            }
2349                                            if (!bExists)
2350                                                    destroyChannelStrip(pChannelStrip);
2351                                    }
2352                            }
2353                    }
2354                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
2355          }          }
2356    
2357          // Do we auto-arrange?          stabilizeForm();
         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();  
2358  }  }
2359    
2360    
2361  // Update the recent files list and menu.  // Update the recent files list and menu.
2362  void MainForm::updateRecentFiles ( const QString& sFilename )  void MainForm::updateRecentFiles ( const QString& sFilename )
2363  {  {
2364          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2365                  return;                  return;
2366    
2367          // Remove from list if already there (avoid duplicates)          // Remove from list if already there (avoid duplicates)
2368          int iIndex = m_pOptions->recentFiles.indexOf(sFilename);          const int iIndex = m_pOptions->recentFiles.indexOf(sFilename);
2369          if (iIndex >= 0)          if (iIndex >= 0)
2370                  m_pOptions->recentFiles.removeAt(iIndex);                  m_pOptions->recentFiles.removeAt(iIndex);
2371          // Put it to front...          // Put it to front...
# Line 1960  void MainForm::updateRecentFiles ( const Line 2376  void MainForm::updateRecentFiles ( const
2376  // Update the recent files list and menu.  // Update the recent files list and menu.
2377  void MainForm::updateRecentFilesMenu (void)  void MainForm::updateRecentFilesMenu (void)
2378  {  {
2379          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2380                  return;                  return;
2381    
2382          // Time to keep the list under limits.          // Time to keep the list under limits.
# Line 1988  void MainForm::updateRecentFilesMenu (vo Line 2404  void MainForm::updateRecentFilesMenu (vo
2404  void MainForm::updateInstrumentNames (void)  void MainForm::updateInstrumentNames (void)
2405  {  {
2406          // Full channel list update...          // Full channel list update...
2407          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2408                    = m_pWorkspace->subWindowList();
2409          if (wlist.isEmpty())          if (wlist.isEmpty())
2410                  return;                  return;
2411    
2412          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2413          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2414                  ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);                  ChannelStrip *pChannelStrip
2415                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2416                  if (pChannelStrip)                  if (pChannelStrip)
2417                          pChannelStrip->updateInstrumentName(true);                          pChannelStrip->updateInstrumentName(true);
2418          }          }
# Line 2005  void MainForm::updateInstrumentNames (vo Line 2423  void MainForm::updateInstrumentNames (vo
2423  // Force update of the channels display font.  // Force update of the channels display font.
2424  void MainForm::updateDisplayFont (void)  void MainForm::updateDisplayFont (void)
2425  {  {
2426          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2427                  return;                  return;
2428    
2429          // Check if display font is legal.          // Check if display font is legal.
2430          if (m_pOptions->sDisplayFont.isEmpty())          if (m_pOptions->sDisplayFont.isEmpty())
2431                  return;                  return;
2432    
2433          // Realize it.          // Realize it.
2434          QFont font;          QFont font;
2435          if (!font.fromString(m_pOptions->sDisplayFont))          if (!font.fromString(m_pOptions->sDisplayFont))
2436                  return;                  return;
2437    
2438          // Full channel list update...          // Full channel list update...
2439          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2440                    = m_pWorkspace->subWindowList();
2441          if (wlist.isEmpty())          if (wlist.isEmpty())
2442                  return;                  return;
2443    
2444          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2445          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2446                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip *pChannelStrip
2447                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2448                  if (pChannelStrip)                  if (pChannelStrip)
2449                          pChannelStrip->setDisplayFont(font);                          pChannelStrip->setDisplayFont(font);
2450          }          }
# Line 2035  void MainForm::updateDisplayFont (void) Line 2456  void MainForm::updateDisplayFont (void)
2456  void MainForm::updateDisplayEffect (void)  void MainForm::updateDisplayEffect (void)
2457  {  {
2458          // Full channel list update...          // Full channel list update...
2459          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2460                    = m_pWorkspace->subWindowList();
2461          if (wlist.isEmpty())          if (wlist.isEmpty())
2462                  return;                  return;
2463    
2464          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2465          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2466                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip *pChannelStrip
2467                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2468                  if (pChannelStrip)                  if (pChannelStrip)
2469                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2470          }          }
# Line 2052  void MainForm::updateDisplayEffect (void Line 2475  void MainForm::updateDisplayEffect (void
2475  // Force update of the channels maximum volume setting.  // Force update of the channels maximum volume setting.
2476  void MainForm::updateMaxVolume (void)  void MainForm::updateMaxVolume (void)
2477  {  {
2478          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2479                  return;                  return;
2480    
2481  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
# Line 2063  void MainForm::updateMaxVolume (void) Line 2486  void MainForm::updateMaxVolume (void)
2486  #endif  #endif
2487    
2488          // Full channel list update...          // Full channel list update...
2489          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2490                    = m_pWorkspace->subWindowList();
2491          if (wlist.isEmpty())          if (wlist.isEmpty())
2492                  return;                  return;
2493    
2494          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2495          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2496                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip *pChannelStrip
2497                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2498                  if (pChannelStrip)                  if (pChannelStrip)
2499                          pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                          pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2500          }          }
# Line 2078  void MainForm::updateMaxVolume (void) Line 2503  void MainForm::updateMaxVolume (void)
2503    
2504    
2505  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2506  // qsamplerMainForm -- Messages window form handlers.  // QSampler::MainForm -- Messages window form handlers.
2507    
2508  // Messages output methods.  // Messages output methods.
2509  void MainForm::appendMessages( const QString& s )  void MainForm::appendMessages ( const QString& s )
2510  {  {
2511          if (m_pMessages)          if (m_pMessages)
2512                  m_pMessages->appendMessages(s);                  m_pMessages->appendMessages(s);
# Line 2089  void MainForm::appendMessages( const QSt Line 2514  void MainForm::appendMessages( const QSt
2514          statusBar()->showMessage(s, 3000);          statusBar()->showMessage(s, 3000);
2515  }  }
2516    
2517  void MainForm::appendMessagesColor( const QString& s, const QString& c )  void MainForm::appendMessagesColor ( const QString& s, const QColor& rgb )
2518  {  {
2519          if (m_pMessages)          if (m_pMessages)
2520                  m_pMessages->appendMessagesColor(s, c);                  m_pMessages->appendMessagesColor(s, rgb);
2521    
2522          statusBar()->showMessage(s, 3000);          statusBar()->showMessage(s, 3000);
2523  }  }
2524    
2525  void MainForm::appendMessagesText( const QString& s )  void MainForm::appendMessagesText ( const QString& s )
2526  {  {
2527          if (m_pMessages)          if (m_pMessages)
2528                  m_pMessages->appendMessagesText(s);                  m_pMessages->appendMessagesText(s);
2529  }  }
2530    
2531  void MainForm::appendMessagesError( const QString& s )  void MainForm::appendMessagesError ( const QString& s )
2532  {  {
2533          if (m_pMessages)          if (m_pMessages)
2534                  m_pMessages->show();                  m_pMessages->show();
2535    
2536          appendMessagesColor(s.simplified(), "#ff0000");          appendMessagesColor(s.simplified(), Qt::red);
2537    
2538          // Make it look responsive...:)          // Make it look responsive...:)
2539          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2540    
2541          QMessageBox::critical(this,          if (m_pOptions && m_pOptions->bConfirmError) {
2542                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));                  const QString& sTitle = tr("Error");
2543            #if 0
2544                    QMessageBox::critical(this, sTitle, sText, QMessageBox::Cancel);
2545            #else
2546                    QMessageBox mbox(this);
2547                    mbox.setIcon(QMessageBox::Critical);
2548                    mbox.setWindowTitle(sTitle);
2549                    mbox.setText(s);
2550                    mbox.setStandardButtons(QMessageBox::Cancel);
2551                    QCheckBox cbox(tr("Don't show this again"));
2552                    cbox.setChecked(false);
2553                    cbox.blockSignals(true);
2554                    mbox.addButton(&cbox, QMessageBox::ActionRole);
2555                    if (mbox.exec() && cbox.isChecked())
2556                            m_pOptions->bConfirmError = false;
2557            #endif
2558            }
2559  }  }
2560    
2561    
2562  // This is a special message format, just for client results.  // This is a special message format, just for client results.
2563  void MainForm::appendMessagesClient( const QString& s )  void MainForm::appendMessagesClient( const QString& s )
2564  {  {
2565          if (m_pClient == NULL)          if (m_pClient == nullptr)
2566                  return;                  return;
2567    
2568          appendMessagesColor(s + QString(": %1 (errno=%2)")          appendMessagesColor(s + QString(": %1 (errno=%2)")
# Line 2136  void MainForm::appendMessagesClient( con Line 2577  void MainForm::appendMessagesClient( con
2577  // Force update of the messages font.  // Force update of the messages font.
2578  void MainForm::updateMessagesFont (void)  void MainForm::updateMessagesFont (void)
2579  {  {
2580          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2581                  return;                  return;
2582    
2583          if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {          if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {
# Line 2150  void MainForm::updateMessagesFont (void) Line 2591  void MainForm::updateMessagesFont (void)
2591  // Update messages window line limit.  // Update messages window line limit.
2592  void MainForm::updateMessagesLimit (void)  void MainForm::updateMessagesLimit (void)
2593  {  {
2594          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2595                  return;                  return;
2596    
2597          if (m_pMessages) {          if (m_pMessages) {
# Line 2165  void MainForm::updateMessagesLimit (void Line 2606  void MainForm::updateMessagesLimit (void
2606  // Enablement of the messages capture feature.  // Enablement of the messages capture feature.
2607  void MainForm::updateMessagesCapture (void)  void MainForm::updateMessagesCapture (void)
2608  {  {
2609          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2610                  return;                  return;
2611    
2612          if (m_pMessages)          if (m_pMessages)
# Line 2174  void MainForm::updateMessagesCapture (vo Line 2615  void MainForm::updateMessagesCapture (vo
2615    
2616    
2617  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2618  // qsamplerMainForm -- MDI channel strip management.  // QSampler::MainForm -- MDI channel strip management.
2619    
2620  // The channel strip creation executive.  // The channel strip creation executive.
2621  ChannelStrip* MainForm::createChannelStrip ( Channel *pChannel )  ChannelStrip *MainForm::createChannelStrip ( Channel *pChannel )
2622  {  {
2623          if (m_pClient == NULL || pChannel == NULL)          if (m_pClient == nullptr || pChannel == nullptr)
2624                  return NULL;                  return nullptr;
2625    
2626          // Add a new channel itema...          // Add a new channel itema...
2627          ChannelStrip *pChannelStrip = new ChannelStrip();          ChannelStrip *pChannelStrip = new ChannelStrip();
2628          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
2629                  return NULL;                  return nullptr;
2630    
2631          // Set some initial channel strip options...          // Set some initial channel strip options...
2632          if (m_pOptions) {          if (m_pOptions) {
# Line 2193  ChannelStrip* MainForm::createChannelStr Line 2634  ChannelStrip* MainForm::createChannelStr
2634                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2635                  // We'll need a display font.                  // We'll need a display font.
2636                  QFont font;                  QFont font;
2637                  if (font.fromString(m_pOptions->sDisplayFont))                  if (!m_pOptions->sDisplayFont.isEmpty() &&
2638                            font.fromString(m_pOptions->sDisplayFont))
2639                          pChannelStrip->setDisplayFont(font);                          pChannelStrip->setDisplayFont(font);
2640                  // Maximum allowed volume setting.                  // Maximum allowed volume setting.
2641                  pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                  pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2642          }          }
2643    
2644          // Add it to workspace...          // Add it to workspace...
2645          m_pWorkspace->addWindow(pChannelStrip, Qt::FramelessWindowHint);          QMdiSubWindow *pMdiSubWindow
2646                    = m_pWorkspace->addSubWindow(pChannelStrip,
2647                            Qt::SubWindow | Qt::FramelessWindowHint);
2648            pMdiSubWindow->setAttribute(Qt::WA_DeleteOnClose);
2649    
2650          // Actual channel strip setup...          // Actual channel strip setup...
2651          pChannelStrip->setup(pChannel);          pChannelStrip->setup(pChannel);
2652    
2653          QObject::connect(pChannelStrip,          QObject::connect(pChannelStrip,
2654                  SIGNAL(channelChanged(ChannelStrip*)),                  SIGNAL(channelChanged(ChannelStrip *)),
2655                  SLOT(channelStripChanged(ChannelStrip*)));                  SLOT(channelStripChanged(ChannelStrip *)));
2656    
2657          // Now we show up us to the world.          // Now we show up us to the world.
2658          pChannelStrip->show();          pChannelStrip->show();
# Line 2220  ChannelStrip* MainForm::createChannelStr Line 2665  ChannelStrip* MainForm::createChannelStr
2665  }  }
2666    
2667    
2668    void MainForm::destroyChannelStrip ( ChannelStrip *pChannelStrip )
2669    {
2670            QMdiSubWindow *pMdiSubWindow
2671                    = static_cast<QMdiSubWindow *> (pChannelStrip->parentWidget());
2672            if (pMdiSubWindow == nullptr)
2673                    return;
2674    
2675            // Just delete the channel strip.
2676            delete pChannelStrip;
2677            delete pMdiSubWindow;
2678    
2679            // Do we auto-arrange?
2680            channelsArrangeAuto();
2681    }
2682    
2683    
2684  // Retrieve the active channel strip.  // Retrieve the active channel strip.
2685  ChannelStrip* MainForm::activeChannelStrip (void)  ChannelStrip *MainForm::activeChannelStrip (void)
2686  {  {
2687          return static_cast<ChannelStrip *> (m_pWorkspace->activeWindow());          QMdiSubWindow *pMdiSubWindow = m_pWorkspace->activeSubWindow();
2688            if (pMdiSubWindow)
2689                    return static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2690            else
2691                    return nullptr;
2692  }  }
2693    
2694    
2695  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
2696  ChannelStrip* MainForm::channelStripAt ( int iChannel )  ChannelStrip *MainForm::channelStripAt ( int iStrip )
2697  {  {
2698          QWidgetList wlist = m_pWorkspace->windowList();          if (!m_pWorkspace) return nullptr;
2699    
2700            const QList<QMdiSubWindow *>& wlist
2701                    = m_pWorkspace->subWindowList();
2702          if (wlist.isEmpty())          if (wlist.isEmpty())
2703                  return NULL;                  return nullptr;
2704    
2705          return static_cast<ChannelStrip *> (wlist.at(iChannel));          if (iStrip < 0 || iStrip >= wlist.count())
2706                    return nullptr;
2707    
2708            QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2709            if (pMdiSubWindow)
2710                    return static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2711            else
2712                    return nullptr;
2713  }  }
2714    
2715    
2716  // Retrieve a channel strip by sampler channel id.  // Retrieve a channel strip by sampler channel id.
2717  ChannelStrip* MainForm::channelStrip ( int iChannelID )  ChannelStrip *MainForm::channelStrip ( int iChannelID )
2718  {  {
2719          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2720                    = m_pWorkspace->subWindowList();
2721          if (wlist.isEmpty())          if (wlist.isEmpty())
2722                  return NULL;                  return nullptr;
2723    
2724          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2725                  ChannelStrip* pChannelStrip                  ChannelStrip *pChannelStrip
2726                          = static_cast<ChannelStrip*> (wlist.at(iChannel));                          = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2727                  if (pChannelStrip) {                  if (pChannelStrip) {
2728                          Channel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
2729                          if (pChannel && pChannel->channelID() == iChannelID)                          if (pChannel && pChannel->channelID() == iChannelID)
# Line 2256  ChannelStrip* MainForm::channelStrip ( i Line 2732  ChannelStrip* MainForm::channelStrip ( i
2732          }          }
2733    
2734          // Not found.          // Not found.
2735          return NULL;          return nullptr;
2736  }  }
2737    
2738    
# Line 2267  void MainForm::channelsMenuAboutToShow ( Line 2743  void MainForm::channelsMenuAboutToShow (
2743          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);
2744          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);
2745    
2746          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2747                    = m_pWorkspace->subWindowList();
2748          if (!wlist.isEmpty()) {          if (!wlist.isEmpty()) {
2749                  m_ui.channelsMenu->addSeparator();                  m_ui.channelsMenu->addSeparator();
2750                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  int iStrip = 0;
2751                          ChannelStrip* pChannelStrip                  foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2752                                  = static_cast<ChannelStrip*> (wlist.at(iChannel));                          ChannelStrip *pChannelStrip
2753                                    = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2754                          if (pChannelStrip) {                          if (pChannelStrip) {
2755                                  QAction *pAction = m_ui.channelsMenu->addAction(                                  QAction *pAction = m_ui.channelsMenu->addAction(
2756                                          pChannelStrip->windowTitle(),                                          pChannelStrip->windowTitle(),
2757                                          this, SLOT(channelsMenuActivated()));                                          this, SLOT(channelsMenuActivated()));
2758                                  pAction->setCheckable(true);                                  pAction->setCheckable(true);
2759                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);
2760                                  pAction->setData(iChannel);                                  pAction->setData(iStrip);
2761                          }                          }
2762                            ++iStrip;
2763                  }                  }
2764          }          }
2765  }  }
# Line 2291  void MainForm::channelsMenuActivated (vo Line 2770  void MainForm::channelsMenuActivated (vo
2770  {  {
2771          // Retrive channel index from action data...          // Retrive channel index from action data...
2772          QAction *pAction = qobject_cast<QAction *> (sender());          QAction *pAction = qobject_cast<QAction *> (sender());
2773          if (pAction == NULL)          if (pAction == nullptr)
2774                  return;                  return;
2775    
2776          ChannelStrip* pChannelStrip = channelStripAt(pAction->data().toInt());          ChannelStrip *pChannelStrip = channelStripAt(pAction->data().toInt());
2777          if (pChannelStrip) {          if (pChannelStrip) {
2778                  pChannelStrip->showNormal();                  pChannelStrip->showNormal();
2779                  pChannelStrip->setFocus();                  pChannelStrip->setFocus();
# Line 2303  void MainForm::channelsMenuActivated (vo Line 2782  void MainForm::channelsMenuActivated (vo
2782    
2783    
2784  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2785  // qsamplerMainForm -- Timer stuff.  // QSampler::MainForm -- Timer stuff.
2786    
2787  // Set the pseudo-timer delay schedule.  // Set the pseudo-timer delay schedule.
2788  void MainForm::startSchedule ( int iStartDelay )  void MainForm::startSchedule ( int iStartDelay )
# Line 2322  void MainForm::stopSchedule (void) Line 2801  void MainForm::stopSchedule (void)
2801  // Timer slot funtion.  // Timer slot funtion.
2802  void MainForm::timerSlot (void)  void MainForm::timerSlot (void)
2803  {  {
2804          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2805                  return;                  return;
2806    
2807          // Is it the first shot on server start after a few delay?          // Is it the first shot on server start after a few delay?
# Line 2344  void MainForm::timerSlot (void) Line 2823  void MainForm::timerSlot (void)
2823                          ChannelStrip *pChannelStrip = iter.next();                          ChannelStrip *pChannelStrip = iter.next();
2824                          // If successfull, remove from pending list...                          // If successfull, remove from pending list...
2825                          if (pChannelStrip->updateChannelInfo()) {                          if (pChannelStrip->updateChannelInfo()) {
2826                                  int iChannelStrip = m_changedStrips.indexOf(pChannelStrip);                                  const int iChannelStrip = m_changedStrips.indexOf(pChannelStrip);
2827                                  if (iChannelStrip >= 0)                                  if (iChannelStrip >= 0)
2828                                          m_changedStrips.removeAt(iChannelStrip);                                          m_changedStrips.removeAt(iChannelStrip);
2829                          }                          }
# Line 2355  void MainForm::timerSlot (void) Line 2834  void MainForm::timerSlot (void)
2834                          if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime)  {                          if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime)  {
2835                                  m_iTimerSlot = 0;                                  m_iTimerSlot = 0;
2836                                  // Update the channel stream usage for each strip...                                  // Update the channel stream usage for each strip...
2837                                  QWidgetList wlist = m_pWorkspace->windowList();                                  const QList<QMdiSubWindow *>& wlist
2838                                  for (int iChannel = 0;                                          = m_pWorkspace->subWindowList();
2839                                                  iChannel < (int) wlist.count(); iChannel++) {                                  foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2840                                          ChannelStrip* pChannelStrip                                          ChannelStrip *pChannelStrip
2841                                                  = (ChannelStrip*) wlist.at(iChannel);                                                  = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2842                                          if (pChannelStrip && pChannelStrip->isVisible())                                          if (pChannelStrip && pChannelStrip->isVisible())
2843                                                  pChannelStrip->updateChannelUsage();                                                  pChannelStrip->updateChannelUsage();
2844                                  }                                  }
2845                          }                          }
2846                  }                  }
2847    
2848            #if CONFIG_LSCP_CLIENT_CONNECTION_LOST
2849                    // If we lost connection to server: Try to automatically reconnect if we
2850                    // did not start the server.
2851                    //
2852                    // TODO: If we started the server, then we might inform the user that
2853                    // the server probably crashed and asking user ONCE whether we should
2854                    // restart the server.
2855                    if (lscp_client_connection_lost(m_pClient) && !m_pServer)
2856                            startAutoReconnectClient();
2857            #endif // CONFIG_LSCP_CLIENT_CONNECTION_LOST
2858          }          }
2859    
2860          // Register the next timer slot.          // Register the next timer slot.
# Line 2373  void MainForm::timerSlot (void) Line 2863  void MainForm::timerSlot (void)
2863    
2864    
2865  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2866  // qsamplerMainForm -- Server stuff.  // QSampler::MainForm -- Server stuff.
2867    
2868  // Start linuxsampler server...  // Start linuxsampler server...
2869  void MainForm::startServer (void)  void MainForm::startServer (void)
2870  {  {
2871          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2872                  return;                  return;
2873    
2874          // Aren't already a client, are we?          // Aren't already a client, are we?
# Line 2387  void MainForm::startServer (void) Line 2877  void MainForm::startServer (void)
2877    
2878          // Is the server process instance still here?          // Is the server process instance still here?
2879          if (m_pServer) {          if (m_pServer) {
2880                  switch (QMessageBox::warning(this,                  if (QMessageBox::warning(this,
2881                          QSAMPLER_TITLE ": " + tr("Warning"),                          tr("Warning"),
2882                          tr("Could not start the LinuxSampler server.\n\n"                          tr("Could not start the LinuxSampler server.\n\n"
2883                          "Maybe it ss already started."),                          "Maybe it is already started."),
2884                          tr("Stop"), tr("Kill"), tr("Cancel"))) {                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
                 case 0:  
2885                          m_pServer->terminate();                          m_pServer->terminate();
                         break;  
                 case 1:  
2886                          m_pServer->kill();                          m_pServer->kill();
                         break;  
2887                  }                  }
2888                  return;                  return;
2889          }          }
# Line 2410  void MainForm::startServer (void) Line 2896  void MainForm::startServer (void)
2896                  return;                  return;
2897    
2898          // OK. Let's build the startup process...          // OK. Let's build the startup process...
2899          m_pServer = new QProcess(this);          m_pServer = new QProcess();
2900            m_bForceServerStop = true;
2901    
2902          // Setup stdout/stderr capture...          // Setup stdout/stderr capture...
2903  //      if (m_pOptions->bStdoutCapture) {          m_pServer->setProcessChannelMode(QProcess::ForwardedChannels);
2904                  //m_pServer->setProcessChannelMode(          QObject::connect(m_pServer,
2905                  //      QProcess::StandardOutput);                  SIGNAL(readyReadStandardOutput()),
2906                  QObject::connect(m_pServer,                  SLOT(readServerStdout()));
2907                          SIGNAL(readyReadStandardOutput()),          QObject::connect(m_pServer,
2908                          SLOT(readServerStdout()));                  SIGNAL(readyReadStandardError()),
2909                  QObject::connect(m_pServer,                  SLOT(readServerStdout()));
                         SIGNAL(readyReadStandardError()),  
                         SLOT(readServerStdout()));  
 //      }  
2910    
2911          // The unforgiveable signal communication...          // The unforgiveable signal communication...
2912          QObject::connect(m_pServer,          QObject::connect(m_pServer,
2913                  SIGNAL(finished(int,QProcess::ExitStatus)),                  SIGNAL(finished(int, QProcess::ExitStatus)),
2914                  SLOT(processServerExit()));                  SLOT(processServerExit()));
2915    
2916          // Build process arguments...          // Build process arguments...
# Line 2447  void MainForm::startServer (void) Line 2931  void MainForm::startServer (void)
2931    
2932          // Show startup results...          // Show startup results...
2933          appendMessages(          appendMessages(
2934                  tr("Server was started with PID=%1.").arg((long) m_pServer->pid()));                  tr("Server was started with PID=%1.")
2935                    #if QT_VERSION < QT_VERSION_CHECK(5, 3, 0)
2936                            .arg(quint64(m_pServer->pid())));
2937                    #else
2938                            .arg(quint64(m_pServer->processId())));
2939                    #endif
2940    
2941          // Reset (yet again) the timer counters,          // Reset (yet again) the timer counters,
2942          // but this time is deferred as the user opted.          // but this time is deferred as the user opted.
# Line 2457  void MainForm::startServer (void) Line 2946  void MainForm::startServer (void)
2946    
2947    
2948  // Stop linuxsampler server...  // Stop linuxsampler server...
2949  void MainForm::stopServer (void)  void MainForm::stopServer ( bool bInteractive )
2950  {  {
2951          // Stop client code.          // Stop client code.
2952          stopClient();          stopClient();
2953    
2954            if (m_pServer && bInteractive) {
2955                    if (QMessageBox::question(this,
2956                            tr("The backend's fate ..."),
2957                            tr("You have the option to keep the sampler backend (LinuxSampler)\n"
2958                            "running in the background. The sampler would continue to work\n"
2959                            "according to your current sampler session and you could alter the\n"
2960                            "sampler session at any time by relaunching QSampler.\n\n"
2961                            "Do you want LinuxSampler to stop?"),
2962                            QMessageBox::Yes | QMessageBox::No,
2963                            QMessageBox::Yes) == QMessageBox::No) {
2964                            m_bForceServerStop = false;
2965                    }
2966            }
2967    
2968            bool bGraceWait = true;
2969    
2970          // And try to stop server.          // And try to stop server.
2971          if (m_pServer) {          if (m_pServer && m_bForceServerStop) {
2972                  appendMessages(tr("Server is stopping..."));                  appendMessages(tr("Server is stopping..."));
2973                  if (m_pServer->state() == QProcess::Running)                  if (m_pServer->state() == QProcess::Running) {
2974                    #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
2975                            // Try harder...
2976                            m_pServer->kill();
2977                    #else
2978                            // Try softly...
2979                          m_pServer->terminate();                          m_pServer->terminate();
2980          }                          bool bFinished = m_pServer->waitForFinished(QSAMPLER_TIMER_MSECS * 1000);
2981                            if (bFinished) bGraceWait = false;
2982                    #endif
2983                    }
2984            }       // Do final processing anyway.
2985            else processServerExit();
2986    
2987          // Give it some time to terminate gracefully and stabilize...          // Give it some time to terminate gracefully and stabilize...
2988          QTime t;          if (bGraceWait) {
2989          t.start();                  QElapsedTimer timer;
2990          while (t.elapsed() < QSAMPLER_TIMER_MSECS)                  timer.start();
2991                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  while (timer.elapsed() < QSAMPLER_TIMER_MSECS)
2992                            QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2993          // Do final processing anyway.          }
         processServerExit();  
2994  }  }
2995    
2996    
# Line 2498  void MainForm::processServerExit (void) Line 3012  void MainForm::processServerExit (void)
3012          if (m_pMessages)          if (m_pMessages)
3013                  m_pMessages->flushStdoutBuffer();                  m_pMessages->flushStdoutBuffer();
3014    
3015          if (m_pServer) {          if (m_pServer && m_bForceServerStop) {
3016                    if (m_pServer->state() != QProcess::NotRunning) {
3017                            appendMessages(tr("Server is being forced..."));
3018                            // Force final server shutdown...
3019                            m_pServer->kill();
3020                            // Give it some time to terminate gracefully and stabilize...
3021                            QElapsedTimer timer;
3022                            timer.start();
3023                            while (timer.elapsed() < QSAMPLER_TIMER_MSECS)
3024                                    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
3025                    }
3026                  // Force final server shutdown...                  // Force final server shutdown...
3027                  appendMessages(                  appendMessages(
3028                          tr("Server was stopped with exit status %1.")                          tr("Server was stopped with exit status %1.")
3029                          .arg(m_pServer->exitStatus()));                          .arg(m_pServer->exitStatus()));
                 m_pServer->terminate();  
                 if (!m_pServer->waitForFinished(2000))  
                         m_pServer->kill();  
                 // Destroy it.  
3030                  delete m_pServer;                  delete m_pServer;
3031                  m_pServer = NULL;                  m_pServer = nullptr;
3032          }          }
3033    
3034          // Again, make status visible stable.          // Again, make status visible stable.
# Line 2517  void MainForm::processServerExit (void) Line 3037  void MainForm::processServerExit (void)
3037    
3038    
3039  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
3040  // qsamplerMainForm -- Client stuff.  // QSampler::MainForm -- Client stuff.
3041    
3042  // The LSCP client callback procedure.  // The LSCP client callback procedure.
3043  lscp_status_t qsampler_client_callback ( lscp_client_t */*pClient*/,  lscp_status_t qsampler_client_callback ( lscp_client_t */*pClient*/,
3044          lscp_event_t event, const char *pchData, int cchData, void *pvData )          lscp_event_t event, const char *pchData, int cchData, void *pvData )
3045  {  {
3046          MainForm* pMainForm = (MainForm *) pvData;          MainForm* pMainForm = (MainForm *) pvData;
3047          if (pMainForm == NULL)          if (pMainForm == nullptr)
3048                  return LSCP_FAILED;                  return LSCP_FAILED;
3049    
3050          // ATTN: DO NOT EVER call any GUI code here,          // ATTN: DO NOT EVER call any GUI code here,
3051          // as this is run under some other thread context.          // as this is run under some other thread context.
3052          // A custom event must be posted here...          // A custom event must be posted here...
3053          QApplication::postEvent(pMainForm,          QApplication::postEvent(pMainForm,
3054                  new CustomEvent(event, pchData, cchData));                  new LscpEvent(event, pchData, cchData));
3055    
3056          return LSCP_OK;          return LSCP_OK;
3057  }  }
3058    
3059    
3060  // Start our almighty client...  // Start our almighty client...
3061  bool MainForm::startClient (void)  bool MainForm::startClient (bool bReconnectOnly)
3062  {  {
3063          // Have it a setup?          // Have it a setup?
3064          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
3065                  return false;                  return false;
3066    
3067          // Aren't we already started, are we?          // Aren't we already started, are we?
# Line 2555  bool MainForm::startClient (void) Line 3075  bool MainForm::startClient (void)
3075          m_pClient = ::lscp_client_create(          m_pClient = ::lscp_client_create(
3076                  m_pOptions->sServerHost.toUtf8().constData(),                  m_pOptions->sServerHost.toUtf8().constData(),
3077                  m_pOptions->iServerPort, qsampler_client_callback, this);                  m_pOptions->iServerPort, qsampler_client_callback, this);
3078          if (m_pClient == NULL) {          if (m_pClient == nullptr) {
3079                  // Is this the first try?                  // Is this the first try?
3080                  // maybe we need to start a local server...                  // maybe we need to start a local server...
3081                  if ((m_pServer && m_pServer->state() == QProcess::Running)                  if ((m_pServer && m_pServer->state() == QProcess::Running)
3082                          || !m_pOptions->bServerStart) {                          || !m_pOptions->bServerStart || bReconnectOnly)
3083                          appendMessagesError(                  {
3084                                  tr("Could not connect to server as client.\n\nSorry."));                          // if this method is called from autoReconnectClient()
3085                            // then don't bother user with an error message...
3086                            if (!bReconnectOnly) {
3087                                    appendMessagesError(
3088                                            tr("Could not connect to server as client.\n\nSorry.")
3089                                    );
3090                            }
3091                  } else {                  } else {
3092                          startServer();                          startServer();
3093                  }                  }
# Line 2569  bool MainForm::startClient (void) Line 3095  bool MainForm::startClient (void)
3095                  stabilizeForm();                  stabilizeForm();
3096                  return false;                  return false;
3097          }          }
3098    
3099          // Just set receive timeout value, blindly.          // Just set receive timeout value, blindly.
3100          ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);          ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);
3101          appendMessages(          appendMessages(
# Line 2576  bool MainForm::startClient (void) Line 3103  bool MainForm::startClient (void)
3103                  .arg(::lscp_client_get_timeout(m_pClient)));                  .arg(::lscp_client_get_timeout(m_pClient)));
3104    
3105          // Subscribe to channel info change notifications...          // Subscribe to channel info change notifications...
3106            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT) != LSCP_OK)
3107                    appendMessagesClient("lscp_client_subscribe(CHANNEL_COUNT)");
3108          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)
3109                  appendMessagesClient("lscp_client_subscribe");                  appendMessagesClient("lscp_client_subscribe(CHANNEL_INFO)");
3110    
3111            DeviceStatusForm::onDevicesChanged(); // initialize
3112            updateViewMidiDeviceStatusMenu();
3113            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT) != LSCP_OK)
3114                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_COUNT)");
3115            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO) != LSCP_OK)
3116                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_INFO)");
3117            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT) != LSCP_OK)
3118                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_COUNT)");
3119            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO) != LSCP_OK)
3120                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_INFO)");
3121    
3122    #if CONFIG_EVENT_CHANNEL_MIDI
3123            // Subscribe to channel MIDI data notifications...
3124            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI) != LSCP_OK)
3125                    appendMessagesClient("lscp_client_subscribe(CHANNEL_MIDI)");
3126    #endif
3127    
3128    #if CONFIG_EVENT_DEVICE_MIDI
3129            // Subscribe to channel MIDI data notifications...
3130            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI) != LSCP_OK)
3131                    appendMessagesClient("lscp_client_subscribe(DEVICE_MIDI)");
3132    #endif
3133    
3134          // We may stop scheduling around.          // We may stop scheduling around.
3135          stopSchedule();          stopSchedule();
# Line 2599  bool MainForm::startClient (void) Line 3151  bool MainForm::startClient (void)
3151          if (!m_pOptions->sSessionFile.isEmpty()) {          if (!m_pOptions->sSessionFile.isEmpty()) {
3152                  // Just load the prabably startup session...                  // Just load the prabably startup session...
3153                  if (loadSessionFile(m_pOptions->sSessionFile)) {                  if (loadSessionFile(m_pOptions->sSessionFile)) {
3154                          m_pOptions->sSessionFile = QString::null;                          m_pOptions->sSessionFile = QString();
3155                          return true;                          return true;
3156                  }                  }
3157          }          }
3158    
3159            // send the current / loaded fine tuning settings to the sampler
3160            m_pOptions->sendFineTuningSettings();
3161    
3162          // Make a new session          // Make a new session
3163          return newSession();          return newSession();
3164  }  }
# Line 2612  bool MainForm::startClient (void) Line 3167  bool MainForm::startClient (void)
3167  // Stop client...  // Stop client...
3168  void MainForm::stopClient (void)  void MainForm::stopClient (void)
3169  {  {
3170          if (m_pClient == NULL)          if (m_pClient == nullptr)
3171                  return;                  return;
3172    
3173          // Log prepare here.          // Log prepare here.
# Line 2631  void MainForm::stopClient (void) Line 3186  void MainForm::stopClient (void)
3186          closeSession(false);          closeSession(false);
3187    
3188          // Close us as a client...          // Close us as a client...
3189    #if CONFIG_EVENT_DEVICE_MIDI
3190            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI);
3191    #endif
3192    #if CONFIG_EVENT_CHANNEL_MIDI
3193            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI);
3194    #endif
3195            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
3196            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
3197            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
3198            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
3199          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
3200            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT);
3201          ::lscp_client_destroy(m_pClient);          ::lscp_client_destroy(m_pClient);
3202          m_pClient = NULL;          m_pClient = nullptr;
3203    
3204          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
3205          // if visible, that we're running out...          // if visible, that we're running out...
# Line 2650  void MainForm::stopClient (void) Line 3216  void MainForm::stopClient (void)
3216  }  }
3217    
3218    
3219    void MainForm::startAutoReconnectClient (void)
3220    {
3221            stopClient();
3222            appendMessages(tr("Trying to reconnect..."));
3223            QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(autoReconnectClient()));
3224    }
3225    
3226    
3227    void MainForm::autoReconnectClient (void)
3228    {
3229            const bool bSuccess = startClient(true);
3230            if (!bSuccess)
3231                    QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(autoReconnectClient()));
3232    }
3233    
3234    
3235  // Channel strip activation/selection.  // Channel strip activation/selection.
3236  void MainForm::activateStrip ( QWidget *pWidget )  void MainForm::activateStrip ( QMdiSubWindow *pMdiSubWindow )
3237  {  {
3238          ChannelStrip *pChannelStrip          ChannelStrip *pChannelStrip = nullptr;
3239                  = static_cast<ChannelStrip *> (pWidget);          if (pMdiSubWindow)
3240                    pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
3241          if (pChannelStrip)          if (pChannelStrip)
3242                  pChannelStrip->setSelected(true);                  pChannelStrip->setSelected(true);
3243    
# Line 2662  void MainForm::activateStrip ( QWidget * Line 3245  void MainForm::activateStrip ( QWidget *
3245  }  }
3246    
3247    
3248    // Channel toolbar orientation change.
3249    void MainForm::channelsToolbarOrientation ( Qt::Orientation orientation )
3250    {
3251    #ifdef CONFIG_VOLUME
3252            m_pVolumeSlider->setOrientation(orientation);
3253            if (orientation == Qt::Horizontal) {
3254                    m_pVolumeSlider->setMinimumHeight(24);
3255                    m_pVolumeSlider->setMaximumHeight(32);
3256                    m_pVolumeSlider->setMinimumWidth(120);
3257                    m_pVolumeSlider->setMaximumWidth(640);
3258                    m_pVolumeSpinBox->setMaximumWidth(64);
3259                    m_pVolumeSpinBox->setButtonSymbols(QSpinBox::UpDownArrows);
3260            } else {
3261                    m_pVolumeSlider->setMinimumHeight(120);
3262                    m_pVolumeSlider->setMaximumHeight(480);
3263                    m_pVolumeSlider->setMinimumWidth(24);
3264                    m_pVolumeSlider->setMaximumWidth(32);
3265                    m_pVolumeSpinBox->setMaximumWidth(32);
3266                    m_pVolumeSpinBox->setButtonSymbols(QSpinBox::NoButtons);
3267            }
3268    #endif
3269    }
3270    
3271    
3272  } // namespace QSampler  } // namespace QSampler
3273    
3274    

Legend:
Removed from v.1558  
changed lines
  Added in v.4038

  ViewVC Help
Powered by ViewVC