/[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 1513 by capela, Fri Nov 23 09:32:06 2007 UTC revision 3849 by capela, Thu Jan 7 16:18:02 2021 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-2021, 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    #pragma GCC diagnostic push
78    #pragma GCC diagnostic ignored "-Wunused-parameter"
79  #include <gig.h>  #include <gig.h>
80    #pragma GCC diagnostic pop
81  #endif  #endif
82    
83  // Needed for lroundf()  // Deprecated QTextStreamFunctions/Qt namespaces workaround.
84  #include <math.h>  #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
85    #define endl    Qt::endl
86    #endif
87    
88  #ifndef CONFIG_ROUND  // Needed for lroundf()
89    #ifdef CONFIG_ROUND
90    #include <cmath>
91    #else
92  static inline long lroundf ( float x )  static inline long lroundf ( float x )
93  {  {
94          if (x >= 0.0f)          if (x >= 0.0f)
# Line 77  static inline long lroundf ( float x ) Line 98  static inline long lroundf ( float x )
98  }  }
99  #endif  #endif
100    
101    
102    // All winsock apps needs this.
103    #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
104    static WSADATA _wsaData;
105    #undef HAVE_SIGNAL_H
106    #endif
107    
108    
109    //-------------------------------------------------------------------------
110    // LADISH Level 1 support stuff.
111    
112    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
113    
114    #include <QSocketNotifier>
115    
116    #include <unistd.h>
117    #include <sys/types.h>
118    #include <sys/socket.h>
119    #include <signal.h>
120    
121    // File descriptor for SIGUSR1 notifier.
122    static int g_fdSigusr1[2] = { -1, -1 };
123    
124    // Unix SIGUSR1 signal handler.
125    static void qsampler_sigusr1_handler ( int /* signo */ )
126    {
127            char c = 1;
128    
129            (::write(g_fdSigusr1[0], &c, sizeof(c)) > 0);
130    }
131    
132    // File descriptor for SIGTERM notifier.
133    static int g_fdSigterm[2] = { -1, -1 };
134    
135    // Unix SIGTERM signal handler.
136    static void qsampler_sigterm_handler ( int /* signo */ )
137    {
138            char c = 1;
139    
140            (::write(g_fdSigterm[0], &c, sizeof(c)) > 0);
141    }
142    
143    #endif  // HAVE_SIGNAL_H
144    
145    
146    //-------------------------------------------------------------------------
147    // QSampler -- namespace
148    
149    
150    namespace QSampler {
151    
152  // Timer constant stuff.  // Timer constant stuff.
153  #define QSAMPLER_TIMER_MSECS    200  #define QSAMPLER_TIMER_MSECS    200
154    
# Line 87  static inline long lroundf ( float x ) Line 159  static inline long lroundf ( float x )
159  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.
160    
161    
162  // All winsock apps needs this.  // Specialties for thread-callback comunication.
163  #if defined(WIN32)  #define QSAMPLER_LSCP_EVENT   QEvent::Type(QEvent::User + 1)
 static WSADATA _wsaData;  
 #endif  
164    
165    
166  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
167  // qsamplerCustomEvent -- specialty for callback comunication.  // QSampler::LscpEvent -- specialty for LSCP callback comunication.
   
 #define QSAMPLER_CUSTOM_EVENT   QEvent::Type(QEvent::User + 0)  
168    
169  class qsamplerCustomEvent : public QEvent  class LscpEvent : public QEvent
170  {  {
171  public:  public:
172    
173          // Constructor.          // Constructor.
174          qsamplerCustomEvent(lscp_event_t event, const char *pchData, int cchData)          LscpEvent(lscp_event_t event, const char *pchData, int cchData)
175                  : QEvent(QSAMPLER_CUSTOM_EVENT)                  : QEvent(QSAMPLER_LSCP_EVENT)
176          {          {
177                  m_event = event;                  m_event = event;
178                  m_data  = QString::fromUtf8(pchData, cchData);                  m_data  = QString::fromUtf8(pchData, cchData);
179          }          }
180    
181          // Accessors.          // Accessors.
182          lscp_event_t event() { return m_event; }          lscp_event_t  event() { return m_event; }
183          QString&     data()  { return m_data;  }          const QString& data() { return m_data;  }
184    
185  private:  private:
186    
# Line 124  private: Line 192  private:
192    
193    
194  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
195  // qsamplerMainForm -- Main window form implementation.  // QSampler::Workspace -- Main window workspace (MDI Area) decl.
196    
197  namespace QSampler {  class Workspace : public QMdiArea
198    {
199    public:
200    
201            Workspace(MainForm *pMainForm) : QMdiArea(pMainForm) {}
202    
203    protected:
204    
205            void resizeEvent(QResizeEvent *)
206            {
207                    MainForm *pMainForm = static_cast<MainForm *> (parentWidget());
208                    if (pMainForm)
209                            pMainForm->channelsArrangeAuto();
210            }
211    };
212    
213    
214    //-------------------------------------------------------------------------
215    // QSampler::MainForm -- Main window form implementation.
216    
217  // Kind of singleton reference.  // Kind of singleton reference.
218  MainForm* MainForm::g_pMainForm = NULL;  MainForm *MainForm::g_pMainForm = nullptr;
219    
220  MainForm::MainForm ( QWidget *pParent )  MainForm::MainForm ( QWidget *pParent )
221          : QMainWindow(pParent)          : QMainWindow(pParent)
# Line 140  MainForm::MainForm ( QWidget *pParent ) Line 226  MainForm::MainForm ( QWidget *pParent )
226          g_pMainForm = this;          g_pMainForm = this;
227    
228          // Initialize some pointer references.          // Initialize some pointer references.
229          m_pOptions = NULL;          m_pOptions = nullptr;
230    
231          // All child forms are to be created later, not earlier than setup.          // All child forms are to be created later, not earlier than setup.
232          m_pMessages = NULL;          m_pMessages = nullptr;
233          m_pInstrumentListForm = NULL;          m_pInstrumentListForm = nullptr;
234          m_pDeviceForm = NULL;          m_pDeviceForm = nullptr;
235    
236          // We'll start clean.          // We'll start clean.
237          m_iUntitled   = 0;          m_iUntitled   = 0;
238            m_iDirtySetup = 0;
239          m_iDirtyCount = 0;          m_iDirtyCount = 0;
240    
241          m_pServer = NULL;          m_pServer = nullptr;
242          m_pClient = NULL;          m_pClient = nullptr;
243    
244          m_iStartDelay = 0;          m_iStartDelay = 0;
245          m_iTimerDelay = 0;          m_iTimerDelay = 0;
246    
247          m_iTimerSlot = 0;          m_iTimerSlot = 0;
248    
249  #ifdef HAVE_SIGNAL_H  #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
250    
251          // Set to ignore any fatal "Broken pipe" signals.          // Set to ignore any fatal "Broken pipe" signals.
252          ::signal(SIGPIPE, SIG_IGN);          ::signal(SIGPIPE, SIG_IGN);
253  #endif  
254            // LADISH Level 1 suport.
255    
256            // Initialize file descriptors for SIGUSR1 socket notifier.
257            ::socketpair(AF_UNIX, SOCK_STREAM, 0, g_fdSigusr1);
258            m_pSigusr1Notifier
259                    = new QSocketNotifier(g_fdSigusr1[1], QSocketNotifier::Read, this);
260    
261            QObject::connect(m_pSigusr1Notifier,
262                    SIGNAL(activated(int)),
263                    SLOT(handle_sigusr1()));
264    
265            // Install SIGUSR1 signal handler.
266            struct sigaction sigusr1;
267            sigusr1.sa_handler = qsampler_sigusr1_handler;
268            sigemptyset(&sigusr1.sa_mask);
269            sigusr1.sa_flags = 0;
270            sigusr1.sa_flags |= SA_RESTART;
271            ::sigaction(SIGUSR1, &sigusr1, nullptr);
272    
273            // Initialize file descriptors for SIGTERM socket notifier.
274            ::socketpair(AF_UNIX, SOCK_STREAM, 0, g_fdSigterm);
275            m_pSigtermNotifier
276                    = new QSocketNotifier(g_fdSigterm[1], QSocketNotifier::Read, this);
277    
278            QObject::connect(m_pSigtermNotifier,
279                    SIGNAL(activated(int)),
280                    SLOT(handle_sigterm()));
281    
282            // Install SIGTERM signal handler.
283            struct sigaction sigterm;
284            sigterm.sa_handler = qsampler_sigterm_handler;
285            sigemptyset(&sigterm.sa_mask);
286            sigterm.sa_flags = 0;
287            sigterm.sa_flags |= SA_RESTART;
288            ::sigaction(SIGTERM, &sigterm, nullptr);
289            ::sigaction(SIGQUIT, &sigterm, nullptr);
290    
291            // Ignore SIGHUP/SIGINT signals.
292            ::signal(SIGHUP, SIG_IGN);
293            ::signal(SIGINT, SIG_IGN);
294    
295    #else   // HAVE_SIGNAL_H
296    
297            m_pSigusr1Notifier = nullptr;
298            m_pSigtermNotifier = nullptr;
299            
300    #endif  // !HAVE_SIGNAL_H
301    
302  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
303          // Make some extras into the toolbar...          // Make some extras into the toolbar...
# Line 171  MainForm::MainForm ( QWidget *pParent ) Line 306  MainForm::MainForm ( QWidget *pParent )
306          // Volume slider...          // Volume slider...
307          m_ui.channelsToolbar->addSeparator();          m_ui.channelsToolbar->addSeparator();
308          m_pVolumeSlider = new QSlider(Qt::Horizontal, m_ui.channelsToolbar);          m_pVolumeSlider = new QSlider(Qt::Horizontal, m_ui.channelsToolbar);
309          m_pVolumeSlider->setTickPosition(QSlider::TicksBelow);          m_pVolumeSlider->setTickPosition(QSlider::TicksBothSides);
310          m_pVolumeSlider->setTickInterval(10);          m_pVolumeSlider->setTickInterval(10);
311          m_pVolumeSlider->setPageStep(10);          m_pVolumeSlider->setPageStep(10);
312          m_pVolumeSlider->setSingleStep(10);          m_pVolumeSlider->setSingleStep(10);
# Line 183  MainForm::MainForm ( QWidget *pParent ) Line 318  MainForm::MainForm ( QWidget *pParent )
318          QObject::connect(m_pVolumeSlider,          QObject::connect(m_pVolumeSlider,
319                  SIGNAL(valueChanged(int)),                  SIGNAL(valueChanged(int)),
320                  SLOT(volumeChanged(int)));                  SLOT(volumeChanged(int)));
         //m_ui.channelsToolbar->setHorizontallyStretchable(true);  
         //m_ui.channelsToolbar->setStretchableWidget(m_pVolumeSlider);  
321          m_ui.channelsToolbar->addWidget(m_pVolumeSlider);          m_ui.channelsToolbar->addWidget(m_pVolumeSlider);
322          // Volume spin-box          // Volume spin-box
323          m_ui.channelsToolbar->addSeparator();          m_ui.channelsToolbar->addSeparator();
# Line 200  MainForm::MainForm ( QWidget *pParent ) Line 333  MainForm::MainForm ( QWidget *pParent )
333  #endif  #endif
334    
335          // Make it an MDI workspace.          // Make it an MDI workspace.
336          m_pWorkspace = new QWorkspace(this);          m_pWorkspace = new Workspace(this);
337          m_pWorkspace->setScrollBarsEnabled(true);          m_pWorkspace->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
338            m_pWorkspace->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
339          // Set the activation connection.          // Set the activation connection.
340          QObject::connect(m_pWorkspace,          QObject::connect(m_pWorkspace,
341                  SIGNAL(windowActivated(QWidget *)),                  SIGNAL(subWindowActivated(QMdiSubWindow *)),
342                  SLOT(stabilizeForm()));                  SLOT(activateStrip(QMdiSubWindow *)));
343          // Make it shine :-)          // Make it shine :-)
344          setCentralWidget(m_pWorkspace);          setCentralWidget(m_pWorkspace);
345    
# Line 234  MainForm::MainForm ( QWidget *pParent ) Line 368  MainForm::MainForm ( QWidget *pParent )
368          m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;          m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;
369          statusBar()->addWidget(pLabel);          statusBar()->addWidget(pLabel);
370    
371  #if defined(WIN32)  #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
372          WSAStartup(MAKEWORD(1, 1), &_wsaData);          WSAStartup(MAKEWORD(1, 1), &_wsaData);
373  #endif  #endif
374    
# Line 322  MainForm::MainForm ( QWidget *pParent ) Line 456  MainForm::MainForm ( QWidget *pParent )
456          QObject::connect(m_ui.channelsMenu,          QObject::connect(m_ui.channelsMenu,
457                  SIGNAL(aboutToShow()),                  SIGNAL(aboutToShow()),
458                  SLOT(channelsMenuAboutToShow()));                  SLOT(channelsMenuAboutToShow()));
459    #ifdef CONFIG_VOLUME
460            QObject::connect(m_ui.channelsToolbar,
461                    SIGNAL(orientationChanged(Qt::Orientation)),
462                    SLOT(channelsToolbarOrientation(Qt::Orientation)));
463    #endif
464  }  }
465    
466  // Destructor.  // Destructor.
# Line 330  MainForm::~MainForm() Line 469  MainForm::~MainForm()
469          // Do final processing anyway.          // Do final processing anyway.
470          processServerExit();          processServerExit();
471    
472  #if defined(WIN32)  #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
473          WSACleanup();          WSACleanup();
474  #endif  #endif
475    
476    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
477            if (m_pSigusr1Notifier)
478                    delete m_pSigusr1Notifier;
479            if (m_pSigtermNotifier)
480                    delete m_pSigtermNotifier;
481    #endif
482    
483          // Finally drop any widgets around...          // Finally drop any widgets around...
484          if (m_pDeviceForm)          if (m_pDeviceForm)
485                  delete m_pDeviceForm;                  delete m_pDeviceForm;
# Line 360  MainForm::~MainForm() Line 506  MainForm::~MainForm()
506  #endif  #endif
507    
508          // Pseudo-singleton reference shut-down.          // Pseudo-singleton reference shut-down.
509          g_pMainForm = NULL;          g_pMainForm = nullptr;
510  }  }
511    
512    
513  // Make and set a proper setup options step.  // Make and set a proper setup options step.
514  void MainForm::setup ( qsamplerOptions *pOptions )  void MainForm::setup ( Options *pOptions )
515  {  {
516          // We got options?          // We got options?
517          m_pOptions = pOptions;          m_pOptions = pOptions;
518    
519          // What style do we create these forms?          // What style do we create these forms?
520          Qt::WindowFlags wflags = Qt::Window          Qt::WindowFlags wflags = Qt::Window
 #if QT_VERSION >= 0x040200  
521                  | Qt::CustomizeWindowHint                  | Qt::CustomizeWindowHint
 #endif  
522                  | Qt::WindowTitleHint                  | Qt::WindowTitleHint
523                  | Qt::WindowSystemMenuHint                  | Qt::WindowSystemMenuHint
524                  | Qt::WindowMinMaxButtonsHint;                  | Qt::WindowMinMaxButtonsHint
525                    | Qt::WindowCloseButtonHint;
526          if (m_pOptions->bKeepOnTop)          if (m_pOptions->bKeepOnTop)
527                  wflags |= Qt::Tool;                  wflags |= Qt::Tool;
528    
529          // Some child forms are to be created right now.          // Some child forms are to be created right now.
530          m_pMessages = new qsamplerMessages(this);          m_pMessages = new Messages(this);
531          m_pDeviceForm = new DeviceForm(this, wflags);          m_pDeviceForm = new DeviceForm(this, wflags);
532  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
533          m_pInstrumentListForm = new InstrumentListForm(this, wflags);          m_pInstrumentListForm = new InstrumentListForm(this, wflags);
534  #else  #else
535          viewInstrumentsAction->setEnabled(false);          m_ui.viewInstrumentsAction->setEnabled(false);
536  #endif  #endif
537    
538            // Setup messages logging appropriately...
539            m_pMessages->setLogging(
540                    m_pOptions->bMessagesLog,
541                    m_pOptions->sMessagesLogPath);
542    
543          // Set message defaults...          // Set message defaults...
544          updateMessagesFont();          updateMessagesFont();
545          updateMessagesLimit();          updateMessagesLimit();
546          updateMessagesCapture();          updateMessagesCapture();
547    
548          // Set the visibility signal.          // Set the visibility signal.
549          QObject::connect(m_pMessages,          QObject::connect(m_pMessages,
550                  SIGNAL(visibilityChanged(bool)),                  SIGNAL(visibilityChanged(bool)),
# Line 418  void MainForm::setup ( qsamplerOptions * Line 571  void MainForm::setup ( qsamplerOptions *
571          }          }
572    
573          // Try to restore old window positioning and initial visibility.          // Try to restore old window positioning and initial visibility.
574          m_pOptions->loadWidgetGeometry(this);          m_pOptions->loadWidgetGeometry(this, true);
575          m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);          m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);
576          m_pOptions->loadWidgetGeometry(m_pDeviceForm);          m_pOptions->loadWidgetGeometry(m_pDeviceForm);
577    
# Line 457  bool MainForm::queryClose (void) Line 610  bool MainForm::queryClose (void)
610                                  || m_ui.channelsToolbar->isVisible());                                  || m_ui.channelsToolbar->isVisible());
611                          m_pOptions->bStatusbar = statusBar()->isVisible();                          m_pOptions->bStatusbar = statusBar()->isVisible();
612                          // Save the dock windows state.                          // Save the dock windows state.
                         const QString sDockables = saveState().toBase64().data();  
613                          m_pOptions->settings().setValue("/Layout/DockWindows", saveState());                          m_pOptions->settings().setValue("/Layout/DockWindows", saveState());
614                          // And the children, and the main windows state,.                          // And the children, and the main windows state,.
615                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);
616                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);
617                          m_pOptions->saveWidgetGeometry(this);                          m_pOptions->saveWidgetGeometry(this, true);
618                          // Close popup widgets.                          // Close popup widgets.
619                          if (m_pInstrumentListForm)                          if (m_pInstrumentListForm)
620                                  m_pInstrumentListForm->close();                                  m_pInstrumentListForm->close();
621                          if (m_pDeviceForm)                          if (m_pDeviceForm)
622                                  m_pDeviceForm->close();                                  m_pDeviceForm->close();
623                          // Stop client and/or server, gracefully.                          // Stop client and/or server, gracefully.
624                          stopServer();                          stopServer(true /*interactive*/);
625                  }                  }
626          }          }
627    
# Line 479  bool MainForm::queryClose (void) Line 631  bool MainForm::queryClose (void)
631    
632  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )
633  {  {
634          if (queryClose())          if (queryClose()) {
635                    DeviceStatusForm::deleteAllInstances();
636                  pCloseEvent->accept();                  pCloseEvent->accept();
637          else          } else
638                  pCloseEvent->ignore();                  pCloseEvent->ignore();
639  }  }
640    
# Line 490  void MainForm::closeEvent ( QCloseEvent Line 643  void MainForm::closeEvent ( QCloseEvent
643  void MainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )  void MainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )
644  {  {
645          // Accept external drags only...          // Accept external drags only...
646          if (pDragEnterEvent->source() == NULL          if (pDragEnterEvent->source() == nullptr
647                  && pDragEnterEvent->mimeData()->hasUrls()) {                  && pDragEnterEvent->mimeData()->hasUrls()) {
648                  pDragEnterEvent->accept();                  pDragEnterEvent->accept();
649          } else {          } else {
# Line 499  void MainForm::dragEnterEvent ( QDragEnt Line 652  void MainForm::dragEnterEvent ( QDragEnt
652  }  }
653    
654    
655  void MainForm::dropEvent ( QDropEvent* pDropEvent )  void MainForm::dropEvent ( QDropEvent *pDropEvent )
656  {  {
657          // Accept externally originated drops only...          // Accept externally originated drops only...
658          if (pDropEvent->source())          if (pDropEvent->source())
# Line 510  void MainForm::dropEvent ( QDropEvent* p Line 663  void MainForm::dropEvent ( QDropEvent* p
663                  QListIterator<QUrl> iter(pMimeData->urls());                  QListIterator<QUrl> iter(pMimeData->urls());
664                  while (iter.hasNext()) {                  while (iter.hasNext()) {
665                          const QString& sPath = iter.next().toLocalFile();                          const QString& sPath = iter.next().toLocalFile();
666                          if (qsamplerChannel::isInstrumentFile(sPath)) {                  //      if (Channel::isDlsInstrumentFile(sPath)) {
667                            if (QFileInfo(sPath).exists()) {
668                                  // Try to create a new channel from instrument file...                                  // Try to create a new channel from instrument file...
669                                  qsamplerChannel *pChannel = new qsamplerChannel();                                  Channel *pChannel = new Channel();
670                                  if (pChannel == NULL)                                  if (pChannel == nullptr)
671                                          return;                                          return;
672                                  // Start setting the instrument filename...                                  // Start setting the instrument filename...
673                                  pChannel->setInstrument(sPath, 0);                                  pChannel->setInstrument(sPath, 0);
# Line 544  void MainForm::dropEvent ( QDropEvent* p Line 698  void MainForm::dropEvent ( QDropEvent* p
698    
699    
700  // Custome event handler.  // Custome event handler.
701  void MainForm::customEvent(QEvent* pCustomEvent)  void MainForm::customEvent ( QEvent* pEvent )
702  {  {
703          // For the time being, just pump it to messages.          // For the time being, just pump it to messages.
704          if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {          if (pEvent->type() == QSAMPLER_LSCP_EVENT) {
705                  qsamplerCustomEvent *pEvent = (qsamplerCustomEvent *) pCustomEvent;                  LscpEvent *pLscpEvent = static_cast<LscpEvent *> (pEvent);
706                  if (pEvent->event() == LSCP_EVENT_CHANNEL_INFO) {                  switch (pLscpEvent->event()) {
707                          int iChannelID = pEvent->data().toInt();                          case LSCP_EVENT_CHANNEL_COUNT:
708                          ChannelStrip *pChannelStrip = channelStrip(iChannelID);                                  updateAllChannelStrips(true);
709                          if (pChannelStrip)                                  break;
710                                  channelStripChanged(pChannelStrip);                          case LSCP_EVENT_CHANNEL_INFO: {
711                  } else {                                  const int iChannelID = pLscpEvent->data().toInt();
712                          appendMessagesColor(tr("Notify event: %1 data: %2")                                  ChannelStrip *pChannelStrip = channelStrip(iChannelID);
713                                  .arg(::lscp_event_to_text(pEvent->event()))                                  if (pChannelStrip)
714                                  .arg(pEvent->data()), "#996699");                                          channelStripChanged(pChannelStrip);
715                                    break;
716                            }
717                            case LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT:
718                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
719                                    DeviceStatusForm::onDevicesChanged();
720                                    updateViewMidiDeviceStatusMenu();
721                                    break;
722                            case LSCP_EVENT_MIDI_INPUT_DEVICE_INFO: {
723                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
724                                    const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt();
725                                    DeviceStatusForm::onDeviceChanged(iDeviceID);
726                                    break;
727                            }
728                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT:
729                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
730                                    break;
731                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO:
732                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
733                                    break;
734                    #if CONFIG_EVENT_CHANNEL_MIDI
735                            case LSCP_EVENT_CHANNEL_MIDI: {
736                                    const int iChannelID = pLscpEvent->data().section(' ', 0, 0).toInt();
737                                    ChannelStrip *pChannelStrip = channelStrip(iChannelID);
738                                    if (pChannelStrip)
739                                            pChannelStrip->midiActivityLedOn();
740                                    break;
741                            }
742                    #endif
743                    #if CONFIG_EVENT_DEVICE_MIDI
744                            case LSCP_EVENT_DEVICE_MIDI: {
745                                    const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt();
746                                    const int iPortID   = pLscpEvent->data().section(' ', 1, 1).toInt();
747                                    DeviceStatusForm *pDeviceStatusForm
748                                            = DeviceStatusForm::getInstance(iDeviceID);
749                                    if (pDeviceStatusForm)
750                                            pDeviceStatusForm->midiArrived(iPortID);
751                                    break;
752                            }
753                    #endif
754                            default:
755                                    appendMessagesColor(tr("LSCP Event: %1 data: %2")
756                                            .arg(::lscp_event_to_text(pLscpEvent->event()))
757                                            .arg(pLscpEvent->data()), "#996699");
758                  }                  }
759          }          }
760  }  }
761    
762    
763    // LADISH Level 1 -- SIGUSR1 signal handler.
764    void MainForm::handle_sigusr1 (void)
765    {
766    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
767    
768            char c;
769    
770            if (::read(g_fdSigusr1[1], &c, sizeof(c)) > 0)
771                    saveSession(false);
772    
773    #endif
774    }
775    
776    
777    void MainForm::handle_sigterm (void)
778    {
779    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
780    
781            char c;
782    
783            if (::read(g_fdSigterm[1], &c, sizeof(c)) > 0)
784                    close();
785    
786    #endif
787    }
788    
789    
790    void MainForm::updateViewMidiDeviceStatusMenu (void)
791    {
792            m_ui.viewMidiDeviceStatusMenu->clear();
793            const std::map<int, DeviceStatusForm *> statusForms
794                    = DeviceStatusForm::getInstances();
795            std::map<int, DeviceStatusForm *>::const_iterator iter
796                    = statusForms.begin();
797            for ( ; iter != statusForms.end(); ++iter) {
798                    DeviceStatusForm *pStatusForm = iter->second;
799                    m_ui.viewMidiDeviceStatusMenu->addAction(
800                            pStatusForm->visibleAction());
801            }
802    }
803    
804    
805  // Context menu event handler.  // Context menu event handler.
806  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )
807  {  {
# Line 572  void MainForm::contextMenuEvent( QContex Line 812  void MainForm::contextMenuEvent( QContex
812    
813    
814  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
815  // qsamplerMainForm -- Brainless public property accessors.  // QSampler::MainForm -- Brainless public property accessors.
816    
817  // The global options settings property.  // The global options settings property.
818  qsamplerOptions *MainForm::options (void) const  Options *MainForm::options (void) const
819  {  {
820          return m_pOptions;          return m_pOptions;
821  }  }
# Line 596  MainForm *MainForm::getInstance (void) Line 836  MainForm *MainForm::getInstance (void)
836    
837    
838  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
839  // qsamplerMainForm -- Session file stuff.  // QSampler::MainForm -- Session file stuff.
840    
841  // Format the displayable session filename.  // Format the displayable session filename.
842  QString MainForm::sessionName ( const QString& sFilename )  QString MainForm::sessionName ( const QString& sFilename )
843  {  {
844          bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);          const bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);
845          QString sSessionName = sFilename;          QString sSessionName = sFilename;
846          if (sSessionName.isEmpty())          if (sSessionName.isEmpty())
847                  sSessionName = tr("Untitled") + QString::number(m_iUntitled);                  sSessionName = tr("Untitled") + QString::number(m_iUntitled);
# Line 625  bool MainForm::newSession (void) Line 865  bool MainForm::newSession (void)
865          m_iUntitled++;          m_iUntitled++;
866    
867          // Stabilize form.          // Stabilize form.
868          m_sFilename = QString::null;          m_sFilename = QString();
869          m_iDirtyCount = 0;          m_iDirtyCount = 0;
870          appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));          appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));
871          stabilizeForm();          stabilizeForm();
# Line 637  bool MainForm::newSession (void) Line 877  bool MainForm::newSession (void)
877  // Open an existing sampler session.  // Open an existing sampler session.
878  bool MainForm::openSession (void)  bool MainForm::openSession (void)
879  {  {
880          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
881                  return false;                  return false;
882    
883          // Ask for the filename to open...          // Ask for the filename to open...
884          QString sFilename = QFileDialog::getOpenFileName(this,          QString sFilename = QFileDialog::getOpenFileName(this,
885                  QSAMPLER_TITLE ": " + tr("Open Session"), // Caption.                  tr("Open Session"),                       // Caption.
886                  m_pOptions->sSessionDir,                  // Start here.                  m_pOptions->sSessionDir,                  // Start here.
887                  tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)                  tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
888          );          );
# Line 663  bool MainForm::openSession (void) Line 903  bool MainForm::openSession (void)
903  // Save current sampler session with another name.  // Save current sampler session with another name.
904  bool MainForm::saveSession ( bool bPrompt )  bool MainForm::saveSession ( bool bPrompt )
905  {  {
906          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
907                  return false;                  return false;
908    
909          QString sFilename = m_sFilename;          QString sFilename = m_sFilename;
# Line 675  bool MainForm::saveSession ( bool bPromp Line 915  bool MainForm::saveSession ( bool bPromp
915                          sFilename = m_pOptions->sSessionDir;                          sFilename = m_pOptions->sSessionDir;
916                  // Prompt the guy...                  // Prompt the guy...
917                  sFilename = QFileDialog::getSaveFileName(this,                  sFilename = QFileDialog::getSaveFileName(this,
918                          QSAMPLER_TITLE ": " + tr("Save Session"), // Caption.                          tr("Save Session"),                       // Caption.
919                          sFilename,                                // Start here.                          sFilename,                                // Start here.
920                          tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)                          tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
921                  );                  );
# Line 685  bool MainForm::saveSession ( bool bPromp Line 925  bool MainForm::saveSession ( bool bPromp
925                  // Enforce .lscp extension...                  // Enforce .lscp extension...
926                  if (QFileInfo(sFilename).suffix().isEmpty())                  if (QFileInfo(sFilename).suffix().isEmpty())
927                          sFilename += ".lscp";                          sFilename += ".lscp";
928            #if 0
929                  // Check if already exists...                  // Check if already exists...
930                  if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {                  if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {
931                          if (QMessageBox::warning(this,                          if (QMessageBox::warning(this,
932                                  QSAMPLER_TITLE ": " + tr("Warning"),                                  tr("Warning"),
933                                  tr("The file already exists:\n\n"                                  tr("The file already exists:\n\n"
934                                  "\"%1\"\n\n"                                  "\"%1\"\n\n"
935                                  "Do you want to replace it?")                                  "Do you want to replace it?")
936                                  .arg(sFilename),                                  .arg(sFilename),
937                                  tr("Replace"), tr("Cancel")) > 0)                                  QMessageBox::Yes | QMessageBox::No)
938                                    == QMessageBox::No)
939                                  return false;                                  return false;
940                  }                  }
941            #endif
942          }          }
943    
944          // Save it right away.          // Save it right away.
# Line 711  bool MainForm::closeSession ( bool bForc Line 954  bool MainForm::closeSession ( bool bForc
954          // Are we dirty enough to prompt it?          // Are we dirty enough to prompt it?
955          if (m_iDirtyCount > 0) {          if (m_iDirtyCount > 0) {
956                  switch (QMessageBox::warning(this,                  switch (QMessageBox::warning(this,
957                          QSAMPLER_TITLE ": " + tr("Warning"),                          tr("Warning"),
958                          tr("The current session has been changed:\n\n"                          tr("The current session has been changed:\n\n"
959                          "\"%1\"\n\n"                          "\"%1\"\n\n"
960                          "Do you want to save the changes?")                          "Do you want to save the changes?")
961                          .arg(sessionName(m_sFilename)),                          .arg(sessionName(m_sFilename)),
962                          tr("Save"), tr("Discard"), tr("Cancel"))) {                          QMessageBox::Save |
963                  case 0:     // Save...                          QMessageBox::Discard |
964                            QMessageBox::Cancel)) {
965                    case QMessageBox::Save:
966                          bClose = saveSession(false);                          bClose = saveSession(false);
967                          // Fall thru....                          // Fall thru....
968                  case 1:     // Discard                  case QMessageBox::Discard:
969                          break;                          break;
970                  default:    // Cancel.                  default:    // Cancel.
971                          bClose = false;                          bClose = false;
# Line 732  bool MainForm::closeSession ( bool bForc Line 977  bool MainForm::closeSession ( bool bForc
977          if (bClose) {          if (bClose) {
978                  // Remove all channel strips from sight...                  // Remove all channel strips from sight...
979                  m_pWorkspace->setUpdatesEnabled(false);                  m_pWorkspace->setUpdatesEnabled(false);
980                  QWidgetList wlist = m_pWorkspace->windowList();                  const QList<QMdiSubWindow *>& wlist
981                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                          = m_pWorkspace->subWindowList();
982                          ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
983                            ChannelStrip *pChannelStrip
984                                    = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
985                          if (pChannelStrip) {                          if (pChannelStrip) {
986                                  qsamplerChannel *pChannel = pChannelStrip->channel();                                  Channel *pChannel = pChannelStrip->channel();
987                                  if (bForce && pChannel)                                  if (bForce && pChannel)
988                                          pChannel->removeChannel();                                          pChannel->removeChannel();
989                                  delete pChannelStrip;                                  delete pChannelStrip;
990                          }                          }
991                            delete pMdiSubWindow;
992                  }                  }
993                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
994                  // We're now clean, for sure.                  // We're now clean, for sure.
# Line 754  bool MainForm::closeSession ( bool bForc Line 1002  bool MainForm::closeSession ( bool bForc
1002  // Load a session from specific file path.  // Load a session from specific file path.
1003  bool MainForm::loadSessionFile ( const QString& sFilename )  bool MainForm::loadSessionFile ( const QString& sFilename )
1004  {  {
1005          if (m_pClient == NULL)          if (m_pClient == nullptr)
1006                  return false;                  return false;
1007    
1008          // Open and read from real file.          // Open and read from real file.
# Line 830  bool MainForm::loadSessionFile ( const Q Line 1078  bool MainForm::loadSessionFile ( const Q
1078  // Save current session to specific file path.  // Save current session to specific file path.
1079  bool MainForm::saveSessionFile ( const QString& sFilename )  bool MainForm::saveSessionFile ( const QString& sFilename )
1080  {  {
1081          if (m_pClient == NULL)          if (m_pClient == nullptr)
1082                  return false;                  return false;
1083    
1084          // Check whether server is apparently OK...          // Check whether server is apparently OK...
# Line 852  bool MainForm::saveSessionFile ( const Q Line 1100  bool MainForm::saveSessionFile ( const Q
1100          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1101    
1102          // Write the file.          // Write the file.
1103          int  iErrors = 0;          int iErrors = 0;
1104          QTextStream ts(&file);          QTextStream ts(&file);
1105          ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;          ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;
1106          ts << "# " << tr("Version")          ts << "# " << tr("Version") << ": " CONFIG_BUILD_VERSION << endl;
1107          << ": " QSAMPLER_VERSION << endl;  //      ts << "# " << tr("Build") << ": " CONFIG_BUILD_DATE << endl;
         ts << "# " << tr("Build")  
         << ": " __DATE__ " " __TIME__ << endl;  
1108          ts << "#"  << endl;          ts << "#"  << endl;
1109          ts << "# " << tr("File")          ts << "# " << tr("File")
1110          << ": " << QFileInfo(sFilename).fileName() << endl;          << ": " << QFileInfo(sFilename).fileName() << endl;
# Line 871  bool MainForm::saveSessionFile ( const Q Line 1117  bool MainForm::saveSessionFile ( const Q
1117          // It is assumed that this new kind of device+session file          // It is assumed that this new kind of device+session file
1118          // will be loaded from a complete initialized server...          // will be loaded from a complete initialized server...
1119          int *piDeviceIDs;          int *piDeviceIDs;
1120          int  iDevice;          int  i, iDevice;
1121          ts << "RESET" << endl;          ts << "RESET" << endl;
1122    
1123          // Audio device mapping.          // Audio device mapping.
1124          QMap<int, int> audioDeviceMap;          QMap<int, int> audioDeviceMap; iDevice = 0;
1125          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Audio);          piDeviceIDs = Device::getDevices(m_pClient, Device::Audio);
1126          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (i = 0; piDeviceIDs && piDeviceIDs[i] >= 0; ++i) {
1127                  ts << endl;                  Device device(Device::Audio, piDeviceIDs[i]);
1128                  qsamplerDevice device(qsamplerDevice::Audio, piDeviceIDs[iDevice]);                  // Avoid plug-in driver devices...
1129                    if (device.driverName().toUpper() == "PLUGIN")
1130                            continue;
1131                  // Audio device specification...                  // Audio device specification...
1132                    ts << endl;
1133                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1134                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1135                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();
1136                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
1137                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
1138                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
1139                                          ++deviceParam) {                                          ++deviceParam) {
1140                          const qsamplerDeviceParam& param = deviceParam.value();                          const DeviceParam& param = deviceParam.value();
1141                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
1142                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
1143                  }                  }
1144                  ts << endl;                  ts << endl;
1145                  // Audio channel parameters...                  // Audio channel parameters...
1146                  int iPort = 0;                  int iPort = 0;
1147                  QListIterator<qsamplerDevicePort *> iter(device.ports());                  QListIterator<DevicePort *> iter(device.ports());
1148                  while (iter.hasNext()) {                  while (iter.hasNext()) {
1149                          qsamplerDevicePort *pPort = iter.next();                          DevicePort *pPort = iter.next();
1150                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1151                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1152                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1153                                                  ++portParam) {                                                  ++portParam) {
1154                                  const qsamplerDeviceParam& param = portParam.value();                                  const DeviceParam& param = portParam.value();
1155                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1156                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice
1157                                          << " " << iPort << " " << portParam.key()                                          << " " << iPort << " " << portParam.key()
# Line 911  bool MainForm::saveSessionFile ( const Q Line 1160  bool MainForm::saveSessionFile ( const Q
1160                          iPort++;                          iPort++;
1161                  }                  }
1162                  // Audio device index/id mapping.                  // Audio device index/id mapping.
1163                  audioDeviceMap[device.deviceID()] = iDevice;                  audioDeviceMap.insert(device.deviceID(), iDevice++);
1164                  // Try to keep it snappy :)                  // Try to keep it snappy :)
1165                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1166          }          }
1167    
1168          // MIDI device mapping.          // MIDI device mapping.
1169          QMap<int, int> midiDeviceMap;          QMap<int, int> midiDeviceMap; iDevice = 0;
1170          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Midi);          piDeviceIDs = Device::getDevices(m_pClient, Device::Midi);
1171          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (i = 0; piDeviceIDs && piDeviceIDs[i] >= 0; ++i) {
1172                  ts << endl;                  Device device(Device::Midi, piDeviceIDs[i]);
1173                  qsamplerDevice device(qsamplerDevice::Midi, piDeviceIDs[iDevice]);                  // Avoid plug-in driver devices...
1174                    if (device.driverName().toUpper() == "PLUGIN")
1175                            continue;
1176                  // MIDI device specification...                  // MIDI device specification...
1177                    ts << endl;
1178                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1179                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1180                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();
1181                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
1182                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
1183                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
1184                                          ++deviceParam) {                                          ++deviceParam) {
1185                          const qsamplerDeviceParam& param = deviceParam.value();                          const DeviceParam& param = deviceParam.value();
1186                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
1187                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
1188                  }                  }
1189                  ts << endl;                  ts << endl;
1190                  // MIDI port parameters...                  // MIDI port parameters...
1191                  int iPort = 0;                  int iPort = 0;
1192                  QListIterator<qsamplerDevicePort *> iter(device.ports());                  QListIterator<DevicePort *> iter(device.ports());
1193                  while (iter.hasNext()) {                  while (iter.hasNext()) {
1194                          qsamplerDevicePort *pPort = iter.next();                          DevicePort *pPort = iter.next();
1195                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1196                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1197                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1198                                                  ++portParam) {                                                  ++portParam) {
1199                                  const qsamplerDeviceParam& param = portParam.value();                                  const DeviceParam& param = portParam.value();
1200                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1201                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice
1202                                  << " " << iPort << " " << portParam.key()                                  << " " << iPort << " " << portParam.key()
# Line 953  bool MainForm::saveSessionFile ( const Q Line 1205  bool MainForm::saveSessionFile ( const Q
1205                          iPort++;                          iPort++;
1206                  }                  }
1207                  // MIDI device index/id mapping.                  // MIDI device index/id mapping.
1208                  midiDeviceMap[device.deviceID()] = iDevice;                  midiDeviceMap.insert(device.deviceID(), iDevice++);
1209                  // Try to keep it snappy :)                  // Try to keep it snappy :)
1210                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1211          }          }
# Line 964  bool MainForm::saveSessionFile ( const Q Line 1216  bool MainForm::saveSessionFile ( const Q
1216          QMap<int, int> midiInstrumentMap;          QMap<int, int> midiInstrumentMap;
1217          int *piMaps = ::lscp_list_midi_instrument_maps(m_pClient);          int *piMaps = ::lscp_list_midi_instrument_maps(m_pClient);
1218          for (int iMap = 0; piMaps && piMaps[iMap] >= 0; iMap++) {          for (int iMap = 0; piMaps && piMaps[iMap] >= 0; iMap++) {
1219                  int iMidiMap = piMaps[iMap];                  const int iMidiMap = piMaps[iMap];
1220                  const char *pszMapName                  const char *pszMapName
1221                          = ::lscp_get_midi_instrument_map_name(m_pClient, iMidiMap);                          = ::lscp_get_midi_instrument_map_name(m_pClient, iMidiMap);
1222                  ts << "# " << tr("MIDI instrument map") << " " << iMap;                  ts << "# " << tr("MIDI instrument map") << " " << iMap;
# Line 1016  bool MainForm::saveSessionFile ( const Q Line 1268  bool MainForm::saveSessionFile ( const Q
1268                  }                  }
1269                  ts << endl;                  ts << endl;
1270                  // Check for errors...                  // Check for errors...
1271                  if (pInstrs == NULL && ::lscp_client_get_errno(m_pClient)) {                  if (pInstrs == nullptr && ::lscp_client_get_errno(m_pClient)) {
1272                          appendMessagesClient("lscp_list_midi_instruments");                          appendMessagesClient("lscp_list_midi_instruments");
1273                          iErrors++;                          iErrors++;
1274                  }                  }
1275                  // MIDI strument index/id mapping.                  // MIDI strument index/id mapping.
1276                  midiInstrumentMap[iMidiMap] = iMap;                  midiInstrumentMap.insert(iMidiMap, iMap);
1277          }          }
1278          // Check for errors...          // Check for errors...
1279          if (piMaps == NULL && ::lscp_client_get_errno(m_pClient)) {          if (piMaps == nullptr && ::lscp_client_get_errno(m_pClient)) {
1280                  appendMessagesClient("lscp_list_midi_instrument_maps");                  appendMessagesClient("lscp_list_midi_instrument_maps");
1281                  iErrors++;                  iErrors++;
1282          }          }
1283  #endif  // CONFIG_MIDI_INSTRUMENT  #endif  // CONFIG_MIDI_INSTRUMENT
1284    
1285          // Sampler channel mapping.          // Sampler channel mapping...
1286          QWidgetList wlist = m_pWorkspace->windowList();          int iChannelID = 0;
1287          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          const QList<QMdiSubWindow *>& wlist
1288                  ChannelStrip* pChannelStrip                  = m_pWorkspace->subWindowList();
1289                          = static_cast<ChannelStrip *> (wlist.at(iChannel));          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
1290                    ChannelStrip *pChannelStrip
1291                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
1292                  if (pChannelStrip) {                  if (pChannelStrip) {
1293                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
1294                          if (pChannel) {                          if (pChannel) {
1295                                  ts << "# " << tr("Channel") << " " << iChannel << endl;                                  // Avoid "artifial" plug-in devices...
1296                                    const int iAudioDevice = pChannel->audioDevice();
1297                                    if (!audioDeviceMap.contains(iAudioDevice))
1298                                            continue;
1299                                    const int iMidiDevice = pChannel->midiDevice();
1300                                    if (!midiDeviceMap.contains(iMidiDevice))
1301                                            continue;
1302                                    // Go for regular, canonical devices...
1303                                    ts << "# " << tr("Channel") << " " << iChannelID << endl;
1304                                  ts << "ADD CHANNEL" << endl;                                  ts << "ADD CHANNEL" << endl;
1305                                  if (audioDeviceMap.isEmpty()) {                                  if (audioDeviceMap.isEmpty()) {
1306                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannelID
1307                                                  << " " << pChannel->audioDriver() << endl;                                                  << " " << pChannel->audioDriver() << endl;
1308                                  } else {                                  } else {
1309                                          ts << "SET CHANNEL AUDIO_OUTPUT_DEVICE " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_DEVICE " << iChannelID
1310                                                  << " " << audioDeviceMap[pChannel->audioDevice()] << endl;                                                  << " " << audioDeviceMap.value(iAudioDevice) << endl;
1311                                  }                                  }
1312                                  if (midiDeviceMap.isEmpty()) {                                  if (midiDeviceMap.isEmpty()) {
1313                                          ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannel                                          ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannelID
1314                                                  << " " << pChannel->midiDriver() << endl;                                                  << " " << pChannel->midiDriver() << endl;
1315                                  } else {                                  } else {
1316                                          ts << "SET CHANNEL MIDI_INPUT_DEVICE " << iChannel                                          ts << "SET CHANNEL MIDI_INPUT_DEVICE " << iChannelID
1317                                                  << " " << midiDeviceMap[pChannel->midiDevice()] << endl;                                                  << " " << midiDeviceMap.value(iMidiDevice) << endl;
1318                                  }                                  }
1319                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannelID
1320                                          << " " << pChannel->midiPort() << endl;                                          << " " << pChannel->midiPort() << endl;
1321                                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";                                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannelID << " ";
1322                                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)                                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
1323                                          ts << "ALL";                                          ts << "ALL";
1324                                  else                                  else
1325                                          ts << pChannel->midiChannel();                                          ts << pChannel->midiChannel();
1326                                  ts << endl;                                  ts << endl;
1327                                  ts << "LOAD ENGINE " << pChannel->engineName()                                  ts << "LOAD ENGINE " << pChannel->engineName()
1328                                          << " " << iChannel << endl;                                          << " " << iChannelID << endl;
1329                                  if (pChannel->instrumentStatus() < 100) ts << "# ";                                  if (pChannel->instrumentStatus() < 100) ts << "# ";
1330                                  ts << "LOAD INSTRUMENT NON_MODAL '"                                  ts << "LOAD INSTRUMENT NON_MODAL '"
1331                                          << pChannel->instrumentFile() << "' "                                          << pChannel->instrumentFile() << "' "
1332                                          << pChannel->instrumentNr() << " " << iChannel << endl;                                          << pChannel->instrumentNr() << " " << iChannelID << endl;
1333                                  qsamplerChannelRoutingMap::ConstIterator audioRoute;                                  ChannelRoutingMap::ConstIterator audioRoute;
1334                                  for (audioRoute = pChannel->audioRouting().begin();                                  for (audioRoute = pChannel->audioRouting().begin();
1335                                                  audioRoute != pChannel->audioRouting().end();                                                  audioRoute != pChannel->audioRouting().end();
1336                                                          ++audioRoute) {                                                          ++audioRoute) {
1337                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannelID
1338                                                  << " " << audioRoute.key()                                                  << " " << audioRoute.key()
1339                                                  << " " << audioRoute.value() << endl;                                                  << " " << audioRoute.value() << endl;
1340                                  }                                  }
1341                                  ts << "SET CHANNEL VOLUME " << iChannel                                  ts << "SET CHANNEL VOLUME " << iChannelID
1342                                          << " " << pChannel->volume() << endl;                                          << " " << pChannel->volume() << endl;
1343                                  if (pChannel->channelMute())                                  if (pChannel->channelMute())
1344                                          ts << "SET CHANNEL MUTE " << iChannel << " 1" << endl;                                          ts << "SET CHANNEL MUTE " << iChannelID << " 1" << endl;
1345                                  if (pChannel->channelSolo())                                  if (pChannel->channelSolo())
1346                                          ts << "SET CHANNEL SOLO " << iChannel << " 1" << endl;                                          ts << "SET CHANNEL SOLO " << iChannelID << " 1" << endl;
1347  #ifdef CONFIG_MIDI_INSTRUMENT                          #ifdef CONFIG_MIDI_INSTRUMENT
1348                                  if (pChannel->midiMap() >= 0) {                                  const int iMidiMap = pChannel->midiMap();
1349                                          ts << "SET CHANNEL MIDI_INSTRUMENT_MAP " << iChannel                                  if (midiInstrumentMap.contains(iMidiMap)) {
1350                                                  << " " << midiInstrumentMap[pChannel->midiMap()] << endl;                                          ts << "SET CHANNEL MIDI_INSTRUMENT_MAP " << iChannelID
1351                                                    << " " << midiInstrumentMap.value(iMidiMap) << endl;
1352                                  }                                  }
1353  #endif                          #endif
1354  #ifdef CONFIG_FXSEND                          #ifdef CONFIG_FXSEND
                                 int iChannelID = pChannel->channelID();  
1355                                  int *piFxSends = ::lscp_list_fxsends(m_pClient, iChannelID);                                  int *piFxSends = ::lscp_list_fxsends(m_pClient, iChannelID);
1356                                  for (int iFxSend = 0;                                  for (int iFxSend = 0;
1357                                                  piFxSends && piFxSends[iFxSend] >= 0;                                                  piFxSends && piFxSends[iFxSend] >= 0;
# Line 1097  bool MainForm::saveSessionFile ( const Q Line 1359  bool MainForm::saveSessionFile ( const Q
1359                                          lscp_fxsend_info_t *pFxSendInfo = ::lscp_get_fxsend_info(                                          lscp_fxsend_info_t *pFxSendInfo = ::lscp_get_fxsend_info(
1360                                                  m_pClient, iChannelID, piFxSends[iFxSend]);                                                  m_pClient, iChannelID, piFxSends[iFxSend]);
1361                                          if (pFxSendInfo) {                                          if (pFxSendInfo) {
1362                                                  ts << "CREATE FX_SEND " << iChannel                                                  ts << "CREATE FX_SEND " << iChannelID
1363                                                          << " " << pFxSendInfo->midi_controller;                                                          << " " << pFxSendInfo->midi_controller;
1364                                                  if (pFxSendInfo->name)                                                  if (pFxSendInfo->name)
1365                                                          ts << " '" << pFxSendInfo->name << "'";                                                          ts << " '" << pFxSendInfo->name << "'";
# Line 1107  bool MainForm::saveSessionFile ( const Q Line 1369  bool MainForm::saveSessionFile ( const Q
1369                                                                  piRouting && piRouting[iAudioSrc] >= 0;                                                                  piRouting && piRouting[iAudioSrc] >= 0;
1370                                                                          iAudioSrc++) {                                                                          iAudioSrc++) {
1371                                                          ts << "SET FX_SEND AUDIO_OUTPUT_CHANNEL "                                                          ts << "SET FX_SEND AUDIO_OUTPUT_CHANNEL "
1372                                                                  << iChannel                                                                  << iChannelID
1373                                                                  << " " << iFxSend                                                                  << " " << iFxSend
1374                                                                  << " " << iAudioSrc                                                                  << " " << iAudioSrc
1375                                                                  << " " << piRouting[iAudioSrc] << endl;                                                                  << " " << piRouting[iAudioSrc] << endl;
1376                                                  }                                                  }
1377  #ifdef CONFIG_FXSEND_LEVEL                                          #ifdef CONFIG_FXSEND_LEVEL
1378                                                  ts << "SET FX_SEND LEVEL " << iChannel                                                  ts << "SET FX_SEND LEVEL " << iChannelID
1379                                                          << " " << iFxSend                                                          << " " << iFxSend
1380                                                          << " " << pFxSendInfo->level << endl;                                                          << " " << pFxSendInfo->level << endl;
1381  #endif                                          #endif
1382                                          }       // Check for errors...                                          }       // Check for errors...
1383                                          else if (::lscp_client_get_errno(m_pClient)) {                                          else if (::lscp_client_get_errno(m_pClient)) {
1384                                                  appendMessagesClient("lscp_get_fxsend_info");                                                  appendMessagesClient("lscp_get_fxsend_info");
1385                                                  iErrors++;                                                  iErrors++;
1386                                          }                                          }
1387                                  }                                  }
1388  #endif                          #endif
1389                                  ts << endl;                                  ts << endl;
1390                                    // Go for next channel...
1391                                    ++iChannelID;
1392                          }                          }
1393                  }                  }
1394                  // Try to keep it snappy :)                  // Try to keep it snappy :)
# Line 1176  void MainForm::sessionDirty (void) Line 1440  void MainForm::sessionDirty (void)
1440    
1441    
1442  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1443  // qsamplerMainForm -- File Action slots.  // QSampler::MainForm -- File Action slots.
1444    
1445  // Create a new sampler session.  // Create a new sampler session.
1446  void MainForm::fileNew (void)  void MainForm::fileNew (void)
# Line 1200  void MainForm::fileOpenRecent (void) Line 1464  void MainForm::fileOpenRecent (void)
1464          // Retrive filename index from action data...          // Retrive filename index from action data...
1465          QAction *pAction = qobject_cast<QAction *> (sender());          QAction *pAction = qobject_cast<QAction *> (sender());
1466          if (pAction && m_pOptions) {          if (pAction && m_pOptions) {
1467                  int iIndex = pAction->data().toInt();                  const int iIndex = pAction->data().toInt();
1468                  if (iIndex >= 0 && iIndex < m_pOptions->recentFiles.count()) {                  if (iIndex >= 0 && iIndex < m_pOptions->recentFiles.count()) {
1469                          QString sFilename = m_pOptions->recentFiles[iIndex];                          QString sFilename = m_pOptions->recentFiles[iIndex];
1470                          // Check if we can safely close the current session...                          // Check if we can safely close the current session...
# Line 1230  void MainForm::fileSaveAs (void) Line 1494  void MainForm::fileSaveAs (void)
1494  // Reset the sampler instance.  // Reset the sampler instance.
1495  void MainForm::fileReset (void)  void MainForm::fileReset (void)
1496  {  {
1497          if (m_pClient == NULL)          if (m_pClient == nullptr)
1498                  return;                  return;
1499    
1500          // Ask user whether he/she want's an internal sampler reset...          // Ask user whether he/she want's an internal sampler reset...
1501          if (QMessageBox::warning(this,          if (m_pOptions && m_pOptions->bConfirmReset) {
1502                  QSAMPLER_TITLE ": " + tr("Warning"),                  const QString& sTitle = tr("Warning");
1503                  tr("Resetting the sampler instance will close\n"                  const QString& sText = tr(
1504                  "all device and channel configurations.\n\n"                          "Resetting the sampler instance will close\n"
1505                  "Please note that this operation may cause\n"                          "all device and channel configurations.\n\n"
1506                  "temporary MIDI and Audio disruption.\n\n"                          "Please note that this operation may cause\n"
1507                  "Do you want to reset the sampler engine now?"),                          "temporary MIDI and Audio disruption.\n\n"
1508                  tr("Reset"), tr("Cancel")) > 0)                          "Do you want to reset the sampler engine now?");
1509                  return;          #if 0
1510                    if (QMessageBox::warning(this, sTitle, sText,
1511                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1512                            return;
1513            #else
1514                    QMessageBox mbox(this);
1515                    mbox.setIcon(QMessageBox::Warning);
1516                    mbox.setWindowTitle(sTitle);
1517                    mbox.setText(sText);
1518                    mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1519                    QCheckBox cbox(tr("Don't ask this again"));
1520                    cbox.setChecked(false);
1521                    cbox.blockSignals(true);
1522                    mbox.addButton(&cbox, QMessageBox::ActionRole);
1523                    if (mbox.exec() == QMessageBox::Cancel)
1524                            return;
1525                    if (cbox.isChecked())
1526                            m_pOptions->bConfirmReset = false;
1527            #endif
1528            }
1529    
1530          // Trye closing the current session, first...          // Trye closing the current session, first...
1531          if (!closeSession(true))          if (!closeSession(true))
# Line 1267  void MainForm::fileReset (void) Line 1550  void MainForm::fileReset (void)
1550  // Restart the client/server instance.  // Restart the client/server instance.
1551  void MainForm::fileRestart (void)  void MainForm::fileRestart (void)
1552  {  {
1553          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
1554                  return;                  return;
1555    
1556          bool bRestart = true;          bool bRestart = true;
1557    
1558          // Ask user whether he/she want's a complete restart...          // Ask user whether he/she want's a complete restart...
1559          // (if we're currently up and running)          // (if we're currently up and running)
1560          if (bRestart && m_pClient) {          if (m_pOptions && m_pOptions->bConfirmRestart) {
1561                  bRestart = (QMessageBox::warning(this,                  const QString& sTitle = tr("Warning");
1562                          QSAMPLER_TITLE ": " + tr("Warning"),                  const QString& sText = tr(
1563                          tr("New settings will be effective after\n"                          "New settings will be effective after\n"
1564                          "restarting the client/server connection.\n\n"                          "restarting the client/server connection.\n\n"
1565                          "Please note that this operation may cause\n"                          "Please note that this operation may cause\n"
1566                          "temporary MIDI and Audio disruption.\n\n"                          "temporary MIDI and Audio disruption.\n\n"
1567                          "Do you want to restart the connection now?"),                          "Do you want to restart the connection now?");
1568                          tr("Restart"), tr("Cancel")) == 0);          #if 0
1569                    if (QMessageBox::warning(this, sTitle, sText,
1570                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1571                            bRestart = false;
1572            #else
1573                    QMessageBox mbox(this);
1574                    mbox.setIcon(QMessageBox::Warning);
1575                    mbox.setWindowTitle(sTitle);
1576                    mbox.setText(sText);
1577                    mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1578                    QCheckBox cbox(tr("Don't ask this again"));
1579                    cbox.setChecked(false);
1580                    cbox.blockSignals(true);
1581                    mbox.addButton(&cbox, QMessageBox::ActionRole);
1582                    if (mbox.exec() == QMessageBox::Cancel)
1583                            bRestart = false;
1584                    else
1585                    if (cbox.isChecked())
1586                            m_pOptions->bConfirmRestart = false;
1587            #endif
1588          }          }
1589    
1590          // Are we still for it?          // Are we still for it?
# Line 1304  void MainForm::fileExit (void) Line 1606  void MainForm::fileExit (void)
1606    
1607    
1608  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1609  // qsamplerMainForm -- Edit Action slots.  // QSampler::MainForm -- Edit Action slots.
1610    
1611  // Add a new sampler channel.  // Add a new sampler channel.
1612  void MainForm::editAddChannel (void)  void MainForm::editAddChannel (void)
1613  {  {
1614          if (m_pClient == NULL)          ++m_iDirtySetup;
1615            addChannelStrip();
1616            --m_iDirtySetup;
1617    }
1618    
1619    void MainForm::addChannelStrip (void)
1620    {
1621            if (m_pClient == nullptr)
1622                  return;                  return;
1623    
1624          // Just create the channel instance...          // Just create the channel instance...
1625          qsamplerChannel *pChannel = new qsamplerChannel();          Channel *pChannel = new Channel();
1626          if (pChannel == NULL)          if (pChannel == nullptr)
1627                  return;                  return;
1628    
1629          // Before we show it up, may be we'll          // Before we show it up, may be we'll
# Line 1331  void MainForm::editAddChannel (void) Line 1640  void MainForm::editAddChannel (void)
1640                  return;                  return;
1641          }          }
1642    
1643            // Do we auto-arrange?
1644            channelsArrangeAuto();
1645    
1646          // Make that an overall update.          // Make that an overall update.
1647          m_iDirtyCount++;          m_iDirtyCount++;
1648          stabilizeForm();          stabilizeForm();
# Line 1340  void MainForm::editAddChannel (void) Line 1652  void MainForm::editAddChannel (void)
1652  // Remove current sampler channel.  // Remove current sampler channel.
1653  void MainForm::editRemoveChannel (void)  void MainForm::editRemoveChannel (void)
1654  {  {
1655          if (m_pClient == NULL)          ++m_iDirtySetup;
1656            removeChannelStrip();
1657            --m_iDirtySetup;
1658    }
1659    
1660    void MainForm::removeChannelStrip (void)
1661    {
1662            if (m_pClient == nullptr)
1663                  return;                  return;
1664    
1665          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1666          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
1667                  return;                  return;
1668    
1669          qsamplerChannel *pChannel = pChannelStrip->channel();          Channel *pChannel = pChannelStrip->channel();
1670          if (pChannel == NULL)          if (pChannel == nullptr)
1671                  return;                  return;
1672    
1673          // Prompt user if he/she's sure about this...          // Prompt user if he/she's sure about this...
1674          if (m_pOptions && m_pOptions->bConfirmRemove) {          if (m_pOptions && m_pOptions->bConfirmRemove) {
1675                  if (QMessageBox::warning(this,                  const QString& sTitle = tr("Warning");
1676                          QSAMPLER_TITLE ": " + tr("Warning"),                  const QString& sText = tr(
1677                          tr("About to remove channel:\n\n"                          "About to remove channel:\n\n"
1678                          "%1\n\n"                          "%1\n\n"
1679                          "Are you sure?")                          "Are you sure?")
1680                          .arg(pChannelStrip->windowTitle()),                          .arg(pChannelStrip->windowTitle());
1681                          tr("OK"), tr("Cancel")) > 0)          #if 0
1682                    if (QMessageBox::warning(this, sTitle, sText,
1683                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1684                          return;                          return;
1685            #else
1686                    QMessageBox mbox(this);
1687                    mbox.setIcon(QMessageBox::Warning);
1688                    mbox.setWindowTitle(sTitle);
1689                    mbox.setText(sText);
1690                    mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1691                    QCheckBox cbox(tr("Don't ask this again"));
1692                    cbox.setChecked(false);
1693                    cbox.blockSignals(true);
1694                    mbox.addButton(&cbox, QMessageBox::ActionRole);
1695                    if (mbox.exec() == QMessageBox::Cancel)
1696                            return;
1697                    if (cbox.isChecked())
1698                            m_pOptions->bConfirmRemove = false;
1699            #endif
1700          }          }
1701    
1702          // Remove the existing sampler channel.          // Remove the existing sampler channel.
# Line 1368  void MainForm::editRemoveChannel (void) Line 1704  void MainForm::editRemoveChannel (void)
1704                  return;                  return;
1705    
1706          // Just delete the channel strip.          // Just delete the channel strip.
1707          delete pChannelStrip;          destroyChannelStrip(pChannelStrip);
   
         // Do we auto-arrange?  
         if (m_pOptions && m_pOptions->bAutoArrange)  
                 channelsArrange();  
1708    
1709          // We'll be dirty, for sure...          // We'll be dirty, for sure...
1710          m_iDirtyCount++;          m_iDirtyCount++;
# Line 1383  void MainForm::editRemoveChannel (void) Line 1715  void MainForm::editRemoveChannel (void)
1715  // Setup current sampler channel.  // Setup current sampler channel.
1716  void MainForm::editSetupChannel (void)  void MainForm::editSetupChannel (void)
1717  {  {
1718          if (m_pClient == NULL)          if (m_pClient == nullptr)
1719                  return;                  return;
1720    
1721          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1722          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
1723                  return;                  return;
1724    
1725          // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
# Line 1398  void MainForm::editSetupChannel (void) Line 1730  void MainForm::editSetupChannel (void)
1730  // Edit current sampler channel.  // Edit current sampler channel.
1731  void MainForm::editEditChannel (void)  void MainForm::editEditChannel (void)
1732  {  {
1733          if (m_pClient == NULL)          if (m_pClient == nullptr)
1734                  return;                  return;
1735    
1736          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1737          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
1738                  return;                  return;
1739    
1740          // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
# Line 1413  void MainForm::editEditChannel (void) Line 1745  void MainForm::editEditChannel (void)
1745  // Reset current sampler channel.  // Reset current sampler channel.
1746  void MainForm::editResetChannel (void)  void MainForm::editResetChannel (void)
1747  {  {
1748          if (m_pClient == NULL)          if (m_pClient == nullptr)
1749                  return;                  return;
1750    
1751          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1752          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
1753                  return;                  return;
1754    
1755          // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
# Line 1428  void MainForm::editResetChannel (void) Line 1760  void MainForm::editResetChannel (void)
1760  // Reset all sampler channels.  // Reset all sampler channels.
1761  void MainForm::editResetAllChannels (void)  void MainForm::editResetAllChannels (void)
1762  {  {
1763          if (m_pClient == NULL)          if (m_pClient == nullptr)
1764                  return;                  return;
1765    
1766          // Invoque the channel strip procedure,          // Invoque the channel strip procedure,
1767          // for all channels out there...          // for all channels out there...
1768          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
1769          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
1770          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  = m_pWorkspace->subWindowList();
1771                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
1772                    ChannelStrip *pChannelStrip
1773                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
1774                  if (pChannelStrip)                  if (pChannelStrip)
1775                          pChannelStrip->channelReset();                          pChannelStrip->channelReset();
1776          }          }
# Line 1445  void MainForm::editResetAllChannels (voi Line 1779  void MainForm::editResetAllChannels (voi
1779    
1780    
1781  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1782  // qsamplerMainForm -- View Action slots.  // QSampler::MainForm -- View Action slots.
1783    
1784  // Show/hide the main program window menubar.  // Show/hide the main program window menubar.
1785  void MainForm::viewMenubar ( bool bOn )  void MainForm::viewMenubar ( bool bOn )
# Line 1495  void MainForm::viewMessages ( bool bOn ) Line 1829  void MainForm::viewMessages ( bool bOn )
1829  // Show/hide the MIDI instrument list-view form.  // Show/hide the MIDI instrument list-view form.
1830  void MainForm::viewInstruments (void)  void MainForm::viewInstruments (void)
1831  {  {
1832          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
1833                  return;                  return;
1834    
1835          if (m_pInstrumentListForm) {          if (m_pInstrumentListForm) {
# Line 1514  void MainForm::viewInstruments (void) Line 1848  void MainForm::viewInstruments (void)
1848  // Show/hide the device configurator form.  // Show/hide the device configurator form.
1849  void MainForm::viewDevices (void)  void MainForm::viewDevices (void)
1850  {  {
1851          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
1852                  return;                  return;
1853    
1854          if (m_pDeviceForm) {          if (m_pDeviceForm) {
# Line 1533  void MainForm::viewDevices (void) Line 1867  void MainForm::viewDevices (void)
1867  // Show options dialog.  // Show options dialog.
1868  void MainForm::viewOptions (void)  void MainForm::viewOptions (void)
1869  {  {
1870          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
1871                  return;                  return;
1872    
1873          OptionsForm* pOptionsForm = new OptionsForm(this);          OptionsForm* pOptionsForm = new OptionsForm(this);
1874          if (pOptionsForm) {          if (pOptionsForm) {
1875                  // Check out some initial nullities(tm)...                  // Check out some initial nullities(tm)...
1876                  ChannelStrip* pChannelStrip = activeChannelStrip();                  ChannelStrip *pChannelStrip = activeChannelStrip();
1877                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)
1878                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();
1879                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)
1880                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
1881                  // To track down deferred or immediate changes.                  // To track down deferred or immediate changes.
1882                  QString sOldServerHost      = m_pOptions->sServerHost;                  const QString sOldServerHost       = m_pOptions->sServerHost;
1883                  int     iOldServerPort      = m_pOptions->iServerPort;                  const int     iOldServerPort       = m_pOptions->iServerPort;
1884                  int     iOldServerTimeout   = m_pOptions->iServerTimeout;                  const int     iOldServerTimeout    = m_pOptions->iServerTimeout;
1885                  bool    bOldServerStart     = m_pOptions->bServerStart;                  const bool    bOldServerStart      = m_pOptions->bServerStart;
1886                  QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;                  const QString sOldServerCmdLine    = m_pOptions->sServerCmdLine;
1887                  QString sOldDisplayFont     = m_pOptions->sDisplayFont;                  const bool    bOldMessagesLog      = m_pOptions->bMessagesLog;
1888                  bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;                  const QString sOldMessagesLogPath  = m_pOptions->sMessagesLogPath;
1889                  int     iOldMaxVolume       = m_pOptions->iMaxVolume;                  const QString sOldDisplayFont      = m_pOptions->sDisplayFont;
1890                  QString sOldMessagesFont    = m_pOptions->sMessagesFont;                  const bool    bOldDisplayEffect    = m_pOptions->bDisplayEffect;
1891                  bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;                  const int     iOldMaxVolume        = m_pOptions->iMaxVolume;
1892                  bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;                  const QString sOldMessagesFont     = m_pOptions->sMessagesFont;
1893                  int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;                  const bool    bOldKeepOnTop        = m_pOptions->bKeepOnTop;
1894                  int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;                  const bool    bOldStdoutCapture    = m_pOptions->bStdoutCapture;
1895                  bool    bOldCompletePath    = m_pOptions->bCompletePath;                  const int     bOldMessagesLimit    = m_pOptions->bMessagesLimit;
1896                  bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;                  const int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;
1897                  int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;                  const bool    bOldCompletePath     = m_pOptions->bCompletePath;
1898                    const bool    bOldInstrumentNames  = m_pOptions->bInstrumentNames;
1899                    const int     iOldMaxRecentFiles   = m_pOptions->iMaxRecentFiles;
1900                    const int     iOldBaseFontSize     = m_pOptions->iBaseFontSize;
1901                    const QString sOldCustomStyleTheme = m_pOptions->sCustomStyleTheme;
1902                    const QString sOldCustomColorTheme = m_pOptions->sCustomColorTheme;
1903                  // Load the current setup settings.                  // Load the current setup settings.
1904                  pOptionsForm->setup(m_pOptions);                  pOptionsForm->setup(m_pOptions);
1905                  // Show the setup dialog...                  // Show the setup dialog...
1906                  if (pOptionsForm->exec()) {                  if (pOptionsForm->exec()) {
1907                          // Warn if something will be only effective on next run.                          // Warn if something will be only effective on next run.
1908                            int iNeedRestart = 0;
1909                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1910                                  (!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"));  
1911                                  updateMessagesCapture();                                  updateMessagesCapture();
1912                                    ++iNeedRestart;
1913                            }
1914                            if (( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||
1915                                    (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)     ||
1916                                    (iOldBaseFontSize   !=  m_pOptions->iBaseFontSize)) {
1917                                    ++iNeedRestart;
1918                            }
1919                            // Check whether restart is needed or whether
1920                            // custom options maybe set up immediately...
1921                            if (m_pOptions->sCustomStyleTheme != sOldCustomStyleTheme) {
1922                                    if (m_pOptions->sCustomStyleTheme.isEmpty()) {
1923                                            ++iNeedRestart;
1924                                    } else {
1925                                            QApplication::setStyle(
1926                                                    QStyleFactory::create(m_pOptions->sCustomStyleTheme));
1927                                    }
1928                            }
1929                            if (m_pOptions->sCustomColorTheme != sOldCustomColorTheme) {
1930                                    if (m_pOptions->sCustomColorTheme.isEmpty()) {
1931                                            ++iNeedRestart;
1932                                    } else {
1933                                            QPalette pal;
1934                                            if (PaletteForm::namedPalette(
1935                                                            &m_pOptions->settings(), m_pOptions->sCustomColorTheme, pal))
1936                                                    QApplication::setPalette(pal);
1937                                    }
1938                          }                          }
1939                          // Check wheather something immediate has changed.                          // Check wheather something immediate has changed.
1940                            if (( bOldMessagesLog && !m_pOptions->bMessagesLog) ||
1941                                    (!bOldMessagesLog &&  m_pOptions->bMessagesLog) ||
1942                                    (sOldMessagesLogPath != m_pOptions->sMessagesLogPath))
1943                                    m_pMessages->setLogging(
1944                                            m_pOptions->bMessagesLog, m_pOptions->sMessagesLogPath);
1945                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||
1946                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||
1947                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
# Line 1597  void MainForm::viewOptions (void) Line 1962  void MainForm::viewOptions (void)
1962                                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||                                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||
1963                                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))                                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))
1964                                  updateMessagesLimit();                                  updateMessagesLimit();
1965                            // Show restart needed message...
1966                            if (iNeedRestart > 0) {
1967                                    QMessageBox::information(this,
1968                                            tr("Information"),
1969                                            tr("Some settings may be only effective\n"
1970                                            "next time you start this program."));
1971                            }
1972                          // And now the main thing, whether we'll do client/server recycling?                          // And now the main thing, whether we'll do client/server recycling?
1973                          if ((sOldServerHost != m_pOptions->sServerHost) ||                          if ((sOldServerHost != m_pOptions->sServerHost) ||
1974                                  (iOldServerPort != m_pOptions->iServerPort) ||                                  (iOldServerPort != m_pOptions->iServerPort) ||
# Line 1617  void MainForm::viewOptions (void) Line 1989  void MainForm::viewOptions (void)
1989    
1990    
1991  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1992  // qsamplerMainForm -- Channels action slots.  // QSampler::MainForm -- Channels action slots.
1993    
1994  // Arrange channel strips.  // Arrange channel strips.
1995  void MainForm::channelsArrange (void)  void MainForm::channelsArrange (void)
1996  {  {
1997          // Full width vertical tiling          // Full width vertical tiling
1998          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
1999                    = m_pWorkspace->subWindowList();
2000          if (wlist.isEmpty())          if (wlist.isEmpty())
2001                  return;                  return;
2002    
2003          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2004          int y = 0;          int y = 0;
2005          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2006                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  pMdiSubWindow->adjustSize();
2007          /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {                  const QRect& frameRect
2008                          // Prevent flicker...                          = pMdiSubWindow->frameGeometry();
2009                          pChannelStrip->hide();                  int w = m_pWorkspace->width();
2010                          pChannelStrip->showNormal();                  if (w < frameRect.width())
2011                  }   */                          w = frameRect.width();
2012                  pChannelStrip->adjustSize();                  const int h = frameRect.height();
2013                  int iWidth  = m_pWorkspace->width();                  pMdiSubWindow->setGeometry(0, y, w, h);
2014                  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;  
2015          }          }
2016          m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2017    
# Line 1655  void MainForm::channelsArrange (void) Line 2022  void MainForm::channelsArrange (void)
2022  // Auto-arrange channel strips.  // Auto-arrange channel strips.
2023  void MainForm::channelsAutoArrange ( bool bOn )  void MainForm::channelsAutoArrange ( bool bOn )
2024  {  {
2025          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2026                  return;                  return;
2027    
2028          // Toggle the auto-arrange flag.          // Toggle the auto-arrange flag.
2029          m_pOptions->bAutoArrange = bOn;          m_pOptions->bAutoArrange = bOn;
2030    
2031          // If on, update whole workspace...          // If on, update whole workspace...
2032          if (m_pOptions->bAutoArrange)          channelsArrangeAuto();
2033    }
2034    
2035    
2036    void MainForm::channelsArrangeAuto (void)
2037    {
2038            if (m_pOptions && m_pOptions->bAutoArrange)
2039                  channelsArrange();                  channelsArrange();
2040  }  }
2041    
2042    
2043  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2044  // qsamplerMainForm -- Help Action slots.  // QSampler::MainForm -- Help Action slots.
2045    
2046  // Show information about the Qt toolkit.  // Show information about the Qt toolkit.
2047  void MainForm::helpAboutQt (void)  void MainForm::helpAboutQt (void)
# Line 1680  void MainForm::helpAboutQt (void) Line 2053  void MainForm::helpAboutQt (void)
2053  // Show information about application program.  // Show information about application program.
2054  void MainForm::helpAbout (void)  void MainForm::helpAbout (void)
2055  {  {
2056          // 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";  
2057  #ifdef CONFIG_DEBUG  #ifdef CONFIG_DEBUG
2058          sText += "<small><font color=\"red\">";          list << tr("Debugging option enabled.");
         sText += tr("Debugging option enabled.");  
         sText += "</font></small><br />";  
2059  #endif  #endif
2060  #ifndef CONFIG_LIBGIG  #ifndef CONFIG_LIBGIG
2061          sText += "<small><font color=\"red\">";          list << tr("GIG (libgig) file support disabled.");
         sText += tr("GIG (libgig) file support disabled.");  
         sText += "</font></small><br />";  
2062  #endif  #endif
2063  #ifndef CONFIG_INSTRUMENT_NAME  #ifndef CONFIG_INSTRUMENT_NAME
2064          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 />";  
2065  #endif  #endif
2066  #ifndef CONFIG_MUTE_SOLO  #ifndef CONFIG_MUTE_SOLO
2067          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 />";  
2068  #endif  #endif
2069  #ifndef CONFIG_AUDIO_ROUTING  #ifndef CONFIG_AUDIO_ROUTING
2070          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 />";  
2071  #endif  #endif
2072  #ifndef CONFIG_FXSEND  #ifndef CONFIG_FXSEND
2073          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 />";  
2074  #endif  #endif
2075  #ifndef CONFIG_VOLUME  #ifndef CONFIG_VOLUME
2076          sText += "<small><font color=\"red\">";          list << tr("Global volume support disabled.");
         sText += tr("Global volume support disabled.");  
         sText += "</font></small><br />";  
2077  #endif  #endif
2078  #ifndef CONFIG_MIDI_INSTRUMENT  #ifndef CONFIG_MIDI_INSTRUMENT
2079          sText += "<small><font color=\"red\">";          list << tr("MIDI instrument mapping support disabled.");
         sText += tr("MIDI instrument mapping support disabled.");  
         sText += "</font></small><br />";  
2080  #endif  #endif
2081  #ifndef CONFIG_EDIT_INSTRUMENT  #ifndef CONFIG_EDIT_INSTRUMENT
2082          sText += "<small><font color=\"red\">";          list << tr("Instrument editing support disabled.");
         sText += tr("Instrument editing support disabled.");  
         sText += "</font></small><br />";  
2083  #endif  #endif
2084    #ifndef CONFIG_EVENT_CHANNEL_MIDI
2085            list << tr("Channel MIDI event support disabled.");
2086    #endif
2087    #ifndef CONFIG_EVENT_DEVICE_MIDI
2088            list << tr("Device MIDI event support disabled.");
2089    #endif
2090    #ifndef CONFIG_MAX_VOICES
2091            list << tr("Runtime max. voices / disk streams support disabled.");
2092    #endif
2093    
2094            // Stuff the about box text...
2095            QString sText = "<p>\n";
2096            sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";
2097            sText += "<br />\n";
2098            sText += tr("Version") + ": <b>" CONFIG_BUILD_VERSION "</b><br />\n";
2099    //      sText += "<small>" + tr("Build") + ": " CONFIG_BUILD_DATE "</small><br />\n";
2100            if (!list.isEmpty()) {
2101                    sText += "<small><font color=\"red\">";
2102                    sText += list.join("<br />\n");
2103                    sText += "</font></small>";
2104            }
2105          sText += "<br />\n";          sText += "<br />\n";
2106          sText += tr("Using") + ": ";          sText += tr("Using: Qt %1").arg(qVersion());
2107    #if defined(QT_STATIC)
2108            sText += "-static";
2109    #endif
2110            sText += ", ";
2111          sText += ::lscp_client_package();          sText += ::lscp_client_package();
2112          sText += " ";          sText += " ";
2113          sText += ::lscp_client_version();          sText += ::lscp_client_version();
# Line 1755  void MainForm::helpAbout (void) Line 2130  void MainForm::helpAbout (void)
2130          sText += "</small>";          sText += "</small>";
2131          sText += "</p>\n";          sText += "</p>\n";
2132    
2133          QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);          QMessageBox::about(this, tr("About"), sText);
2134  }  }
2135    
2136    
2137  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2138  // qsamplerMainForm -- Main window stabilization.  // QSampler::MainForm -- Main window stabilization.
2139    
2140  void MainForm::stabilizeForm (void)  void MainForm::stabilizeForm (void)
2141  {  {
# Line 1768  void MainForm::stabilizeForm (void) Line 2143  void MainForm::stabilizeForm (void)
2143          QString sSessionName = sessionName(m_sFilename);          QString sSessionName = sessionName(m_sFilename);
2144          if (m_iDirtyCount > 0)          if (m_iDirtyCount > 0)
2145                  sSessionName += " *";                  sSessionName += " *";
2146          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));          setWindowTitle(sSessionName);
2147    
2148          // Update the main menu state...          // Update the main menu state...
2149          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
2150          bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);          const QList<QMdiSubWindow *>& wlist = m_pWorkspace->subWindowList();
2151          bool bHasChannel = (bHasClient && pChannelStrip != NULL);          const bool bHasClient = (m_pOptions != nullptr && m_pClient != nullptr);
2152            const bool bHasChannel = (bHasClient && pChannelStrip != nullptr);
2153            const bool bHasChannels = (bHasClient && wlist.count() > 0);
2154          m_ui.fileNewAction->setEnabled(bHasClient);          m_ui.fileNewAction->setEnabled(bHasClient);
2155          m_ui.fileOpenAction->setEnabled(bHasClient);          m_ui.fileOpenAction->setEnabled(bHasClient);
2156          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
2157          m_ui.fileSaveAsAction->setEnabled(bHasClient);          m_ui.fileSaveAsAction->setEnabled(bHasClient);
2158          m_ui.fileResetAction->setEnabled(bHasClient);          m_ui.fileResetAction->setEnabled(bHasClient);
2159          m_ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);          m_ui.fileRestartAction->setEnabled(bHasClient || m_pServer == nullptr);
2160          m_ui.editAddChannelAction->setEnabled(bHasClient);          m_ui.editAddChannelAction->setEnabled(bHasClient);
2161          m_ui.editRemoveChannelAction->setEnabled(bHasChannel);          m_ui.editRemoveChannelAction->setEnabled(bHasChannel);
2162          m_ui.editSetupChannelAction->setEnabled(bHasChannel);          m_ui.editSetupChannelAction->setEnabled(bHasChannel);
# Line 1789  void MainForm::stabilizeForm (void) Line 2166  void MainForm::stabilizeForm (void)
2166          m_ui.editEditChannelAction->setEnabled(false);          m_ui.editEditChannelAction->setEnabled(false);
2167  #endif  #endif
2168          m_ui.editResetChannelAction->setEnabled(bHasChannel);          m_ui.editResetChannelAction->setEnabled(bHasChannel);
2169          m_ui.editResetAllChannelsAction->setEnabled(bHasChannel);          m_ui.editResetAllChannelsAction->setEnabled(bHasChannels);
2170          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());
2171  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
2172          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm
# Line 1801  void MainForm::stabilizeForm (void) Line 2178  void MainForm::stabilizeForm (void)
2178          m_ui.viewDevicesAction->setChecked(m_pDeviceForm          m_ui.viewDevicesAction->setChecked(m_pDeviceForm
2179                  && m_pDeviceForm->isVisible());                  && m_pDeviceForm->isVisible());
2180          m_ui.viewDevicesAction->setEnabled(bHasClient);          m_ui.viewDevicesAction->setEnabled(bHasClient);
2181          m_ui.channelsArrangeAction->setEnabled(bHasChannel);          m_ui.viewMidiDeviceStatusMenu->setEnabled(
2182                    DeviceStatusForm::getInstances().size() > 0);
2183            m_ui.channelsArrangeAction->setEnabled(bHasChannels);
2184    
2185  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2186          // Toolbar widgets are also affected...          // Toolbar widgets are also affected...
# Line 1851  void MainForm::volumeChanged ( int iVolu Line 2230  void MainForm::volumeChanged ( int iVolu
2230                  m_pVolumeSpinBox->setValue(iVolume);                  m_pVolumeSpinBox->setValue(iVolume);
2231    
2232          // Do it as commanded...          // Do it as commanded...
2233          float fVolume = 0.01f * float(iVolume);          const float fVolume = 0.01f * float(iVolume);
2234          if (::lscp_set_volume(m_pClient, fVolume) == LSCP_OK)          if (::lscp_set_volume(m_pClient, fVolume) == LSCP_OK)
2235                  appendMessages(QObject::tr("Volume: %1.").arg(fVolume));                  appendMessages(QObject::tr("Volume: %1.").arg(fVolume));
2236          else          else
# Line 1867  void MainForm::volumeChanged ( int iVolu Line 2246  void MainForm::volumeChanged ( int iVolu
2246    
2247    
2248  // Channel change receiver slot.  // Channel change receiver slot.
2249  void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)  void MainForm::channelStripChanged ( ChannelStrip *pChannelStrip )
2250  {  {
2251          // Add this strip to the changed list...          // Add this strip to the changed list...
2252          if (!m_changedStrips.contains(pChannelStrip)) {          if (!m_changedStrips.contains(pChannelStrip)) {
# Line 1886  void MainForm::channelStripChanged(Chann Line 2265  void MainForm::channelStripChanged(Chann
2265  void MainForm::updateSession (void)  void MainForm::updateSession (void)
2266  {  {
2267  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2268          int iVolume = ::lroundf(100.0f * ::lscp_get_volume(m_pClient));          const int iVolume = ::lroundf(100.0f * ::lscp_get_volume(m_pClient));
2269          m_iVolumeChanging++;          m_iVolumeChanging++;
2270          m_pVolumeSlider->setValue(iVolume);          m_pVolumeSlider->setValue(iVolume);
2271          m_pVolumeSpinBox->setValue(iVolume);          m_pVolumeSpinBox->setValue(iVolume);
# Line 1894  void MainForm::updateSession (void) Line 2273  void MainForm::updateSession (void)
2273  #endif  #endif
2274  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
2275          // FIXME: Make some room for default instrument maps...          // FIXME: Make some room for default instrument maps...
2276          int iMaps = ::lscp_get_midi_instrument_maps(m_pClient);          const int iMaps = ::lscp_get_midi_instrument_maps(m_pClient);
2277          if (iMaps < 0)          if (iMaps < 0)
2278                  appendMessagesClient("lscp_get_midi_instrument_maps");                  appendMessagesClient("lscp_get_midi_instrument_maps");
2279          else if (iMaps < 1) {          else if (iMaps < 1) {
# Line 1905  void MainForm::updateSession (void) Line 2284  void MainForm::updateSession (void)
2284          }          }
2285  #endif  #endif
2286    
2287            updateAllChannelStrips(false);
2288    
2289            // Do we auto-arrange?
2290            channelsArrangeAuto();
2291    
2292            // Remember to refresh devices and instruments...
2293            if (m_pInstrumentListForm)
2294                    m_pInstrumentListForm->refreshInstruments();
2295            if (m_pDeviceForm)
2296                    m_pDeviceForm->refreshDevices();
2297    }
2298    
2299    
2300    void MainForm::updateAllChannelStrips ( bool bRemoveDeadStrips )
2301    {
2302            // Skip if setting up a new channel strip...
2303            if (m_iDirtySetup > 0)
2304                    return;
2305    
2306          // Retrieve the current channel list.          // Retrieve the current channel list.
2307          int *piChannelIDs = ::lscp_list_channels(m_pClient);          int *piChannelIDs = ::lscp_list_channels(m_pClient);
2308          if (piChannelIDs == NULL) {          if (piChannelIDs == nullptr) {
2309                  if (::lscp_client_get_errno(m_pClient)) {                  if (::lscp_client_get_errno(m_pClient)) {
2310                          appendMessagesClient("lscp_list_channels");                          appendMessagesClient("lscp_list_channels");
2311                          appendMessagesError(                          appendMessagesError(
# Line 1916  void MainForm::updateSession (void) Line 2314  void MainForm::updateSession (void)
2314          } else {          } else {
2315                  // Try to (re)create each channel.                  // Try to (re)create each channel.
2316                  m_pWorkspace->setUpdatesEnabled(false);                  m_pWorkspace->setUpdatesEnabled(false);
2317                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; ++iChannel) {
2318                          // Check if theres already a channel strip for this one...                          // Check if theres already a channel strip for this one...
2319                          if (!channelStrip(piChannelIDs[iChannel]))                          if (!channelStrip(piChannelIDs[iChannel]))
2320                                  createChannelStrip(new qsamplerChannel(piChannelIDs[iChannel]));                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));
2321                    }
2322                    // Do we auto-arrange?
2323                    channelsArrangeAuto();
2324                    // remove dead channel strips
2325                    if (bRemoveDeadStrips) {
2326                            const QList<QMdiSubWindow *>& wlist
2327                                    = m_pWorkspace->subWindowList();
2328                            foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2329                                    ChannelStrip *pChannelStrip
2330                                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2331                                    if (pChannelStrip) {
2332                                            bool bExists = false;
2333                                            for (int iChannel = 0; piChannelIDs[iChannel] >= 0; ++iChannel) {
2334                                                    Channel *pChannel = pChannelStrip->channel();
2335                                                    if (pChannel == nullptr)
2336                                                            break;
2337                                                    if (piChannelIDs[iChannel] == pChannel->channelID()) {
2338                                                            // strip exists, don't touch it
2339                                                            bExists = true;
2340                                                            break;
2341                                                    }
2342                                            }
2343                                            if (!bExists)
2344                                                    destroyChannelStrip(pChannelStrip);
2345                                    }
2346                            }
2347                  }                  }
2348                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
2349          }          }
2350    
2351          // 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();  
2352  }  }
2353    
2354    
2355  // Update the recent files list and menu.  // Update the recent files list and menu.
2356  void MainForm::updateRecentFiles ( const QString& sFilename )  void MainForm::updateRecentFiles ( const QString& sFilename )
2357  {  {
2358          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2359                  return;                  return;
2360    
2361          // Remove from list if already there (avoid duplicates)          // Remove from list if already there (avoid duplicates)
2362          int iIndex = m_pOptions->recentFiles.indexOf(sFilename);          const int iIndex = m_pOptions->recentFiles.indexOf(sFilename);
2363          if (iIndex >= 0)          if (iIndex >= 0)
2364                  m_pOptions->recentFiles.removeAt(iIndex);                  m_pOptions->recentFiles.removeAt(iIndex);
2365          // Put it to front...          // Put it to front...
# Line 1954  void MainForm::updateRecentFiles ( const Line 2370  void MainForm::updateRecentFiles ( const
2370  // Update the recent files list and menu.  // Update the recent files list and menu.
2371  void MainForm::updateRecentFilesMenu (void)  void MainForm::updateRecentFilesMenu (void)
2372  {  {
2373          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2374                  return;                  return;
2375    
2376          // Time to keep the list under limits.          // Time to keep the list under limits.
# Line 1982  void MainForm::updateRecentFilesMenu (vo Line 2398  void MainForm::updateRecentFilesMenu (vo
2398  void MainForm::updateInstrumentNames (void)  void MainForm::updateInstrumentNames (void)
2399  {  {
2400          // Full channel list update...          // Full channel list update...
2401          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2402                    = m_pWorkspace->subWindowList();
2403          if (wlist.isEmpty())          if (wlist.isEmpty())
2404                  return;                  return;
2405    
2406          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2407          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2408                  ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);                  ChannelStrip *pChannelStrip
2409                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2410                  if (pChannelStrip)                  if (pChannelStrip)
2411                          pChannelStrip->updateInstrumentName(true);                          pChannelStrip->updateInstrumentName(true);
2412          }          }
# Line 1999  void MainForm::updateInstrumentNames (vo Line 2417  void MainForm::updateInstrumentNames (vo
2417  // Force update of the channels display font.  // Force update of the channels display font.
2418  void MainForm::updateDisplayFont (void)  void MainForm::updateDisplayFont (void)
2419  {  {
2420          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2421                  return;                  return;
2422    
2423          // Check if display font is legal.          // Check if display font is legal.
2424          if (m_pOptions->sDisplayFont.isEmpty())          if (m_pOptions->sDisplayFont.isEmpty())
2425                  return;                  return;
2426    
2427          // Realize it.          // Realize it.
2428          QFont font;          QFont font;
2429          if (!font.fromString(m_pOptions->sDisplayFont))          if (!font.fromString(m_pOptions->sDisplayFont))
2430                  return;                  return;
2431    
2432          // Full channel list update...          // Full channel list update...
2433          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2434                    = m_pWorkspace->subWindowList();
2435          if (wlist.isEmpty())          if (wlist.isEmpty())
2436                  return;                  return;
2437    
2438          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2439          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2440                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip *pChannelStrip
2441                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2442                  if (pChannelStrip)                  if (pChannelStrip)
2443                          pChannelStrip->setDisplayFont(font);                          pChannelStrip->setDisplayFont(font);
2444          }          }
# Line 2029  void MainForm::updateDisplayFont (void) Line 2450  void MainForm::updateDisplayFont (void)
2450  void MainForm::updateDisplayEffect (void)  void MainForm::updateDisplayEffect (void)
2451  {  {
2452          // Full channel list update...          // Full channel list update...
2453          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2454                    = m_pWorkspace->subWindowList();
2455          if (wlist.isEmpty())          if (wlist.isEmpty())
2456                  return;                  return;
2457    
2458          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2459          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2460                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip *pChannelStrip
2461                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2462                  if (pChannelStrip)                  if (pChannelStrip)
2463                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2464          }          }
# Line 2046  void MainForm::updateDisplayEffect (void Line 2469  void MainForm::updateDisplayEffect (void
2469  // Force update of the channels maximum volume setting.  // Force update of the channels maximum volume setting.
2470  void MainForm::updateMaxVolume (void)  void MainForm::updateMaxVolume (void)
2471  {  {
2472          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2473                  return;                  return;
2474    
2475  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
# Line 2057  void MainForm::updateMaxVolume (void) Line 2480  void MainForm::updateMaxVolume (void)
2480  #endif  #endif
2481    
2482          // Full channel list update...          // Full channel list update...
2483          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2484                    = m_pWorkspace->subWindowList();
2485          if (wlist.isEmpty())          if (wlist.isEmpty())
2486                  return;                  return;
2487    
2488          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2489          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2490                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip *pChannelStrip
2491                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2492                  if (pChannelStrip)                  if (pChannelStrip)
2493                          pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                          pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2494          }          }
# Line 2072  void MainForm::updateMaxVolume (void) Line 2497  void MainForm::updateMaxVolume (void)
2497    
2498    
2499  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2500  // qsamplerMainForm -- Messages window form handlers.  // QSampler::MainForm -- Messages window form handlers.
2501    
2502  // Messages output methods.  // Messages output methods.
2503  void MainForm::appendMessages( const QString& s )  void MainForm::appendMessages ( const QString& s )
2504  {  {
2505          if (m_pMessages)          if (m_pMessages)
2506                  m_pMessages->appendMessages(s);                  m_pMessages->appendMessages(s);
# Line 2083  void MainForm::appendMessages( const QSt Line 2508  void MainForm::appendMessages( const QSt
2508          statusBar()->showMessage(s, 3000);          statusBar()->showMessage(s, 3000);
2509  }  }
2510    
2511  void MainForm::appendMessagesColor( const QString& s, const QString& c )  void MainForm::appendMessagesColor ( const QString& s, const QColor& rgb )
2512  {  {
2513          if (m_pMessages)          if (m_pMessages)
2514                  m_pMessages->appendMessagesColor(s, c);                  m_pMessages->appendMessagesColor(s, rgb);
2515    
2516          statusBar()->showMessage(s, 3000);          statusBar()->showMessage(s, 3000);
2517  }  }
2518    
2519  void MainForm::appendMessagesText( const QString& s )  void MainForm::appendMessagesText ( const QString& s )
2520  {  {
2521          if (m_pMessages)          if (m_pMessages)
2522                  m_pMessages->appendMessagesText(s);                  m_pMessages->appendMessagesText(s);
2523  }  }
2524    
2525  void MainForm::appendMessagesError( const QString& s )  void MainForm::appendMessagesError ( const QString& s )
2526  {  {
2527          if (m_pMessages)          if (m_pMessages)
2528                  m_pMessages->show();                  m_pMessages->show();
2529    
2530          appendMessagesColor(s.simplified(), "#ff0000");          appendMessagesColor(s.simplified(), Qt::red);
2531    
2532          // Make it look responsive...:)          // Make it look responsive...:)
2533          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2534    
2535          QMessageBox::critical(this,          if (m_pOptions && m_pOptions->bConfirmError) {
2536                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));                  const QString& sTitle = tr("Error");
2537            #if 0
2538                    QMessageBox::critical(this, sTitle, sText, QMessageBox::Cancel);
2539            #else
2540                    QMessageBox mbox(this);
2541                    mbox.setIcon(QMessageBox::Critical);
2542                    mbox.setWindowTitle(sTitle);
2543                    mbox.setText(s);
2544                    mbox.setStandardButtons(QMessageBox::Cancel);
2545                    QCheckBox cbox(tr("Don't show this again"));
2546                    cbox.setChecked(false);
2547                    cbox.blockSignals(true);
2548                    mbox.addButton(&cbox, QMessageBox::ActionRole);
2549                    if (mbox.exec() && cbox.isChecked())
2550                            m_pOptions->bConfirmError = false;
2551            #endif
2552            }
2553  }  }
2554    
2555    
2556  // This is a special message format, just for client results.  // This is a special message format, just for client results.
2557  void MainForm::appendMessagesClient( const QString& s )  void MainForm::appendMessagesClient( const QString& s )
2558  {  {
2559          if (m_pClient == NULL)          if (m_pClient == nullptr)
2560                  return;                  return;
2561    
2562          appendMessagesColor(s + QString(": %1 (errno=%2)")          appendMessagesColor(s + QString(": %1 (errno=%2)")
# Line 2130  void MainForm::appendMessagesClient( con Line 2571  void MainForm::appendMessagesClient( con
2571  // Force update of the messages font.  // Force update of the messages font.
2572  void MainForm::updateMessagesFont (void)  void MainForm::updateMessagesFont (void)
2573  {  {
2574          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2575                  return;                  return;
2576    
2577          if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {          if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {
# Line 2144  void MainForm::updateMessagesFont (void) Line 2585  void MainForm::updateMessagesFont (void)
2585  // Update messages window line limit.  // Update messages window line limit.
2586  void MainForm::updateMessagesLimit (void)  void MainForm::updateMessagesLimit (void)
2587  {  {
2588          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2589                  return;                  return;
2590    
2591          if (m_pMessages) {          if (m_pMessages) {
# Line 2159  void MainForm::updateMessagesLimit (void Line 2600  void MainForm::updateMessagesLimit (void
2600  // Enablement of the messages capture feature.  // Enablement of the messages capture feature.
2601  void MainForm::updateMessagesCapture (void)  void MainForm::updateMessagesCapture (void)
2602  {  {
2603          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2604                  return;                  return;
2605    
2606          if (m_pMessages)          if (m_pMessages)
# Line 2168  void MainForm::updateMessagesCapture (vo Line 2609  void MainForm::updateMessagesCapture (vo
2609    
2610    
2611  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2612  // qsamplerMainForm -- MDI channel strip management.  // QSampler::MainForm -- MDI channel strip management.
2613    
2614  // The channel strip creation executive.  // The channel strip creation executive.
2615  ChannelStrip* MainForm::createChannelStrip(qsamplerChannel* pChannel)  ChannelStrip *MainForm::createChannelStrip ( Channel *pChannel )
2616  {  {
2617          if (m_pClient == NULL || pChannel == NULL)          if (m_pClient == nullptr || pChannel == nullptr)
2618                  return NULL;                  return nullptr;
   
         // Prepare for auto-arrange?  
         ChannelStrip* pChannelStrip = NULL;  
         int y = 0;  
         if (m_pOptions && m_pOptions->bAutoArrange) {  
                 QWidgetList wlist = m_pWorkspace->windowList();  
                 for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {  
                         pChannelStrip = static_cast<ChannelStrip *> (wlist.at(iChannel));  
                         if (pChannelStrip) {  
                         //  y += pChannelStrip->height()  
                         //              + pChannelStrip->parentWidget()->baseSize().height();  
                                 y += pChannelStrip->parentWidget()->frameGeometry().height();  
                         }  
                 }  
         }  
2619    
2620          // Add a new channel itema...          // Add a new channel itema...
2621          pChannelStrip = new ChannelStrip();          ChannelStrip *pChannelStrip = new ChannelStrip();
2622          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
2623                  return NULL;                  return nullptr;
   
         m_pWorkspace->addWindow(pChannelStrip, Qt::FramelessWindowHint);  
2624    
2625          // Actual channel strip setup...          // Set some initial channel strip options...
         pChannelStrip->setup(pChannel);  
         QObject::connect(pChannelStrip,  
                 SIGNAL(channelChanged(ChannelStrip*)),  
                 SLOT(channelStripChanged(ChannelStrip*)));  
         // Set some initial aesthetic options...  
2626          if (m_pOptions) {          if (m_pOptions) {
2627                  // Background display effect...                  // Background display effect...
2628                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2629                  // We'll need a display font.                  // We'll need a display font.
2630                  QFont font;                  QFont font;
2631                  if (font.fromString(m_pOptions->sDisplayFont))                  if (!m_pOptions->sDisplayFont.isEmpty() &&
2632                            font.fromString(m_pOptions->sDisplayFont))
2633                          pChannelStrip->setDisplayFont(font);                          pChannelStrip->setDisplayFont(font);
2634                  // Maximum allowed volume setting.                  // Maximum allowed volume setting.
2635                  pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                  pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2636          }          }
2637    
2638            // Add it to workspace...
2639            QMdiSubWindow *pMdiSubWindow
2640                    = m_pWorkspace->addSubWindow(pChannelStrip,
2641                            Qt::SubWindow | Qt::FramelessWindowHint);
2642            pMdiSubWindow->setAttribute(Qt::WA_DeleteOnClose);
2643    
2644            // Actual channel strip setup...
2645            pChannelStrip->setup(pChannel);
2646    
2647            QObject::connect(pChannelStrip,
2648                    SIGNAL(channelChanged(ChannelStrip *)),
2649                    SLOT(channelStripChanged(ChannelStrip *)));
2650    
2651          // Now we show up us to the world.          // Now we show up us to the world.
2652          pChannelStrip->show();          pChannelStrip->show();
         // Only then, we'll auto-arrange...  
         if (m_pOptions && m_pOptions->bAutoArrange) {  
                 int iWidth  = m_pWorkspace->width();  
         //  int iHeight = pChannel->height()  
         //              + pChannel->parentWidget()->baseSize().height();  
                 int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();  
                 pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);  
         }  
2653    
2654          // This is pretty new, so we'll watch for it closely.          // This is pretty new, so we'll watch for it closely.
2655          channelStripChanged(pChannelStrip);          channelStripChanged(pChannelStrip);
# Line 2234  ChannelStrip* MainForm::createChannelStr Line 2659  ChannelStrip* MainForm::createChannelStr
2659  }  }
2660    
2661    
2662    void MainForm::destroyChannelStrip ( ChannelStrip *pChannelStrip )
2663    {
2664            QMdiSubWindow *pMdiSubWindow
2665                    = static_cast<QMdiSubWindow *> (pChannelStrip->parentWidget());
2666            if (pMdiSubWindow == nullptr)
2667                    return;
2668    
2669            // Just delete the channel strip.
2670            delete pChannelStrip;
2671            delete pMdiSubWindow;
2672    
2673            // Do we auto-arrange?
2674            channelsArrangeAuto();
2675    }
2676    
2677    
2678  // Retrieve the active channel strip.  // Retrieve the active channel strip.
2679  ChannelStrip* MainForm::activeChannelStrip (void)  ChannelStrip *MainForm::activeChannelStrip (void)
2680  {  {
2681          return static_cast<ChannelStrip *> (m_pWorkspace->activeWindow());          QMdiSubWindow *pMdiSubWindow = m_pWorkspace->activeSubWindow();
2682            if (pMdiSubWindow)
2683                    return static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2684            else
2685                    return nullptr;
2686  }  }
2687    
2688    
2689  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
2690  ChannelStrip* MainForm::channelStripAt ( int iChannel )  ChannelStrip *MainForm::channelStripAt ( int iStrip )
2691  {  {
2692          QWidgetList wlist = m_pWorkspace->windowList();          if (!m_pWorkspace) return nullptr;
2693    
2694            const QList<QMdiSubWindow *>& wlist
2695                    = m_pWorkspace->subWindowList();
2696          if (wlist.isEmpty())          if (wlist.isEmpty())
2697                  return NULL;                  return nullptr;
2698    
2699            if (iStrip < 0 || iStrip >= wlist.count())
2700                    return nullptr;
2701    
2702          return static_cast<ChannelStrip *> (wlist.at(iChannel));          QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2703            if (pMdiSubWindow)
2704                    return static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2705            else
2706                    return nullptr;
2707  }  }
2708    
2709    
2710  // Retrieve a channel strip by sampler channel id.  // Retrieve a channel strip by sampler channel id.
2711  ChannelStrip* MainForm::channelStrip ( int iChannelID )  ChannelStrip *MainForm::channelStrip ( int iChannelID )
2712  {  {
2713          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2714                    = m_pWorkspace->subWindowList();
2715          if (wlist.isEmpty())          if (wlist.isEmpty())
2716                  return NULL;                  return nullptr;
2717    
2718          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2719                  ChannelStrip* pChannelStrip                  ChannelStrip *pChannelStrip
2720                          = static_cast<ChannelStrip*> (wlist.at(iChannel));                          = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2721                  if (pChannelStrip) {                  if (pChannelStrip) {
2722                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
2723                          if (pChannel && pChannel->channelID() == iChannelID)                          if (pChannel && pChannel->channelID() == iChannelID)
2724                                  return pChannelStrip;                                  return pChannelStrip;
2725                  }                  }
2726          }          }
2727    
2728          // Not found.          // Not found.
2729          return NULL;          return nullptr;
2730  }  }
2731    
2732    
# Line 2281  void MainForm::channelsMenuAboutToShow ( Line 2737  void MainForm::channelsMenuAboutToShow (
2737          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);
2738          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);
2739    
2740          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2741                    = m_pWorkspace->subWindowList();
2742          if (!wlist.isEmpty()) {          if (!wlist.isEmpty()) {
2743                  m_ui.channelsMenu->addSeparator();                  m_ui.channelsMenu->addSeparator();
2744                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  int iStrip = 0;
2745                          ChannelStrip* pChannelStrip                  foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2746                                  = static_cast<ChannelStrip*> (wlist.at(iChannel));                          ChannelStrip *pChannelStrip
2747                                    = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2748                          if (pChannelStrip) {                          if (pChannelStrip) {
2749                                  QAction *pAction = m_ui.channelsMenu->addAction(                                  QAction *pAction = m_ui.channelsMenu->addAction(
2750                                          pChannelStrip->windowTitle(),                                          pChannelStrip->windowTitle(),
2751                                          this, SLOT(channelsMenuActivated()));                                          this, SLOT(channelsMenuActivated()));
2752                                  pAction->setCheckable(true);                                  pAction->setCheckable(true);
2753                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);
2754                                  pAction->setData(iChannel);                                  pAction->setData(iStrip);
2755                          }                          }
2756                            ++iStrip;
2757                  }                  }
2758          }          }
2759  }  }
# Line 2305  void MainForm::channelsMenuActivated (vo Line 2764  void MainForm::channelsMenuActivated (vo
2764  {  {
2765          // Retrive channel index from action data...          // Retrive channel index from action data...
2766          QAction *pAction = qobject_cast<QAction *> (sender());          QAction *pAction = qobject_cast<QAction *> (sender());
2767          if (pAction == NULL)          if (pAction == nullptr)
2768                  return;                  return;
2769    
2770          ChannelStrip* pChannelStrip = channelStripAt(pAction->data().toInt());          ChannelStrip *pChannelStrip = channelStripAt(pAction->data().toInt());
2771          if (pChannelStrip) {          if (pChannelStrip) {
2772                  pChannelStrip->showNormal();                  pChannelStrip->showNormal();
2773                  pChannelStrip->setFocus();                  pChannelStrip->setFocus();
# Line 2317  void MainForm::channelsMenuActivated (vo Line 2776  void MainForm::channelsMenuActivated (vo
2776    
2777    
2778  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2779  // qsamplerMainForm -- Timer stuff.  // QSampler::MainForm -- Timer stuff.
2780    
2781  // Set the pseudo-timer delay schedule.  // Set the pseudo-timer delay schedule.
2782  void MainForm::startSchedule ( int iStartDelay )  void MainForm::startSchedule ( int iStartDelay )
# Line 2336  void MainForm::stopSchedule (void) Line 2795  void MainForm::stopSchedule (void)
2795  // Timer slot funtion.  // Timer slot funtion.
2796  void MainForm::timerSlot (void)  void MainForm::timerSlot (void)
2797  {  {
2798          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2799                  return;                  return;
2800    
2801          // 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 2358  void MainForm::timerSlot (void) Line 2817  void MainForm::timerSlot (void)
2817                          ChannelStrip *pChannelStrip = iter.next();                          ChannelStrip *pChannelStrip = iter.next();
2818                          // If successfull, remove from pending list...                          // If successfull, remove from pending list...
2819                          if (pChannelStrip->updateChannelInfo()) {                          if (pChannelStrip->updateChannelInfo()) {
2820                                  int iChannelStrip = m_changedStrips.indexOf(pChannelStrip);                                  const int iChannelStrip = m_changedStrips.indexOf(pChannelStrip);
2821                                  if (iChannelStrip >= 0)                                  if (iChannelStrip >= 0)
2822                                          m_changedStrips.removeAt(iChannelStrip);                                          m_changedStrips.removeAt(iChannelStrip);
2823                          }                          }
# Line 2369  void MainForm::timerSlot (void) Line 2828  void MainForm::timerSlot (void)
2828                          if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime)  {                          if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime)  {
2829                                  m_iTimerSlot = 0;                                  m_iTimerSlot = 0;
2830                                  // Update the channel stream usage for each strip...                                  // Update the channel stream usage for each strip...
2831                                  QWidgetList wlist = m_pWorkspace->windowList();                                  const QList<QMdiSubWindow *>& wlist
2832                                  for (int iChannel = 0;                                          = m_pWorkspace->subWindowList();
2833                                                  iChannel < (int) wlist.count(); iChannel++) {                                  foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2834                                          ChannelStrip* pChannelStrip                                          ChannelStrip *pChannelStrip
2835                                                  = (ChannelStrip*) wlist.at(iChannel);                                                  = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2836                                          if (pChannelStrip && pChannelStrip->isVisible())                                          if (pChannelStrip && pChannelStrip->isVisible())
2837                                                  pChannelStrip->updateChannelUsage();                                                  pChannelStrip->updateChannelUsage();
2838                                  }                                  }
2839                          }                          }
2840                  }                  }
2841    
2842            #if CONFIG_LSCP_CLIENT_CONNECTION_LOST
2843                    // If we lost connection to server: Try to automatically reconnect if we
2844                    // did not start the server.
2845                    //
2846                    // TODO: If we started the server, then we might inform the user that
2847                    // the server probably crashed and asking user ONCE whether we should
2848                    // restart the server.
2849                    if (lscp_client_connection_lost(m_pClient) && !m_pServer)
2850                            startAutoReconnectClient();
2851            #endif // CONFIG_LSCP_CLIENT_CONNECTION_LOST
2852          }          }
2853    
2854          // Register the next timer slot.          // Register the next timer slot.
# Line 2387  void MainForm::timerSlot (void) Line 2857  void MainForm::timerSlot (void)
2857    
2858    
2859  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2860  // qsamplerMainForm -- Server stuff.  // QSampler::MainForm -- Server stuff.
2861    
2862  // Start linuxsampler server...  // Start linuxsampler server...
2863  void MainForm::startServer (void)  void MainForm::startServer (void)
2864  {  {
2865          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2866                  return;                  return;
2867    
2868          // Aren't already a client, are we?          // Aren't already a client, are we?
# Line 2401  void MainForm::startServer (void) Line 2871  void MainForm::startServer (void)
2871    
2872          // Is the server process instance still here?          // Is the server process instance still here?
2873          if (m_pServer) {          if (m_pServer) {
2874                  switch (QMessageBox::warning(this,                  if (QMessageBox::warning(this,
2875                          QSAMPLER_TITLE ": " + tr("Warning"),                          tr("Warning"),
2876                          tr("Could not start the LinuxSampler server.\n\n"                          tr("Could not start the LinuxSampler server.\n\n"
2877                          "Maybe it ss already started."),                          "Maybe it is already started."),
2878                          tr("Stop"), tr("Kill"), tr("Cancel"))) {                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
                 case 0:  
2879                          m_pServer->terminate();                          m_pServer->terminate();
                         break;  
                 case 1:  
2880                          m_pServer->kill();                          m_pServer->kill();
                         break;  
2881                  }                  }
2882                  return;                  return;
2883          }          }
# Line 2424  void MainForm::startServer (void) Line 2890  void MainForm::startServer (void)
2890                  return;                  return;
2891    
2892          // OK. Let's build the startup process...          // OK. Let's build the startup process...
2893          m_pServer = new QProcess(this);          m_pServer = new QProcess();
2894            m_bForceServerStop = true;
2895    
2896          // Setup stdout/stderr capture...          // Setup stdout/stderr capture...
2897  //      if (m_pOptions->bStdoutCapture) {          m_pServer->setProcessChannelMode(QProcess::ForwardedChannels);
2898                  //m_pServer->setProcessChannelMode(          QObject::connect(m_pServer,
2899                  //      QProcess::StandardOutput);                  SIGNAL(readyReadStandardOutput()),
2900                  QObject::connect(m_pServer,                  SLOT(readServerStdout()));
2901                          SIGNAL(readyReadStandardOutput()),          QObject::connect(m_pServer,
2902                          SLOT(readServerStdout()));                  SIGNAL(readyReadStandardError()),
2903                  QObject::connect(m_pServer,                  SLOT(readServerStdout()));
                         SIGNAL(readyReadStandardError()),  
                         SLOT(readServerStdout()));  
 //      }  
2904    
2905          // The unforgiveable signal communication...          // The unforgiveable signal communication...
2906          QObject::connect(m_pServer,          QObject::connect(m_pServer,
2907                  SIGNAL(finished(int,QProcess::ExitStatus)),                  SIGNAL(finished(int, QProcess::ExitStatus)),
2908                  SLOT(processServerExit()));                  SLOT(processServerExit()));
2909    
2910          // Build process arguments...          // Build process arguments...
# Line 2461  void MainForm::startServer (void) Line 2925  void MainForm::startServer (void)
2925    
2926          // Show startup results...          // Show startup results...
2927          appendMessages(          appendMessages(
2928                  tr("Server was started with PID=%1.").arg((long) m_pServer->pid()));                  tr("Server was started with PID=%1.")
2929                    #if QT_VERSION < QT_VERSION_CHECK(5, 3, 0)
2930                            .arg(quint64(m_pServer->pid())));
2931                    #else
2932                            .arg(quint64(m_pServer->processId())));
2933                    #endif
2934    
2935          // Reset (yet again) the timer counters,          // Reset (yet again) the timer counters,
2936          // but this time is deferred as the user opted.          // but this time is deferred as the user opted.
# Line 2471  void MainForm::startServer (void) Line 2940  void MainForm::startServer (void)
2940    
2941    
2942  // Stop linuxsampler server...  // Stop linuxsampler server...
2943  void MainForm::stopServer (void)  void MainForm::stopServer ( bool bInteractive )
2944  {  {
2945          // Stop client code.          // Stop client code.
2946          stopClient();          stopClient();
2947    
2948            if (m_pServer && bInteractive) {
2949                    if (QMessageBox::question(this,
2950                            tr("The backend's fate ..."),
2951                            tr("You have the option to keep the sampler backend (LinuxSampler)\n"
2952                            "running in the background. The sampler would continue to work\n"
2953                            "according to your current sampler session and you could alter the\n"
2954                            "sampler session at any time by relaunching QSampler.\n\n"
2955                            "Do you want LinuxSampler to stop?"),
2956                            QMessageBox::Yes | QMessageBox::No,
2957                            QMessageBox::Yes) == QMessageBox::No) {
2958                            m_bForceServerStop = false;
2959                    }
2960            }
2961    
2962            bool bGraceWait = true;
2963    
2964          // And try to stop server.          // And try to stop server.
2965          if (m_pServer) {          if (m_pServer && m_bForceServerStop) {
2966                  appendMessages(tr("Server is stopping..."));                  appendMessages(tr("Server is stopping..."));
2967                  if (m_pServer->state() == QProcess::Running)                  if (m_pServer->state() == QProcess::Running) {
2968                    #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
2969                            // Try harder...
2970                            m_pServer->kill();
2971                    #else
2972                            // Try softly...
2973                          m_pServer->terminate();                          m_pServer->terminate();
2974          }                          bool bFinished = m_pServer->waitForFinished(QSAMPLER_TIMER_MSECS * 1000);
2975                            if (bFinished) bGraceWait = false;
2976                    #endif
2977                    }
2978            }       // Do final processing anyway.
2979            else processServerExit();
2980    
2981          // Give it some time to terminate gracefully and stabilize...          // Give it some time to terminate gracefully and stabilize...
2982          QTime t;          if (bGraceWait) {
2983          t.start();                  QElapsedTimer timer;
2984          while (t.elapsed() < QSAMPLER_TIMER_MSECS)                  timer.start();
2985                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  while (timer.elapsed() < QSAMPLER_TIMER_MSECS)
2986                            QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2987          // Do final processing anyway.          }
         processServerExit();  
2988  }  }
2989    
2990    
# Line 2512  void MainForm::processServerExit (void) Line 3006  void MainForm::processServerExit (void)
3006          if (m_pMessages)          if (m_pMessages)
3007                  m_pMessages->flushStdoutBuffer();                  m_pMessages->flushStdoutBuffer();
3008    
3009          if (m_pServer) {          if (m_pServer && m_bForceServerStop) {
3010                    if (m_pServer->state() != QProcess::NotRunning) {
3011                            appendMessages(tr("Server is being forced..."));
3012                            // Force final server shutdown...
3013                            m_pServer->kill();
3014                            // Give it some time to terminate gracefully and stabilize...
3015                            QElapsedTimer timer;
3016                            timer.start();
3017                            while (timer.elapsed() < QSAMPLER_TIMER_MSECS)
3018                                    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
3019                    }
3020                  // Force final server shutdown...                  // Force final server shutdown...
3021                  appendMessages(                  appendMessages(
3022                          tr("Server was stopped with exit status %1.")                          tr("Server was stopped with exit status %1.")
3023                          .arg(m_pServer->exitStatus()));                          .arg(m_pServer->exitStatus()));
                 m_pServer->terminate();  
                 if (!m_pServer->waitForFinished(2000))  
                         m_pServer->kill();  
                 // Destroy it.  
3024                  delete m_pServer;                  delete m_pServer;
3025                  m_pServer = NULL;                  m_pServer = nullptr;
3026          }          }
3027    
3028          // Again, make status visible stable.          // Again, make status visible stable.
# Line 2531  void MainForm::processServerExit (void) Line 3031  void MainForm::processServerExit (void)
3031    
3032    
3033  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
3034  // qsamplerMainForm -- Client stuff.  // QSampler::MainForm -- Client stuff.
3035    
3036  // The LSCP client callback procedure.  // The LSCP client callback procedure.
3037  lscp_status_t qsampler_client_callback ( lscp_client_t */*pClient*/,  lscp_status_t qsampler_client_callback ( lscp_client_t */*pClient*/,
3038          lscp_event_t event, const char *pchData, int cchData, void *pvData )          lscp_event_t event, const char *pchData, int cchData, void *pvData )
3039  {  {
3040          MainForm* pMainForm = (MainForm *) pvData;          MainForm* pMainForm = (MainForm *) pvData;
3041          if (pMainForm == NULL)          if (pMainForm == nullptr)
3042                  return LSCP_FAILED;                  return LSCP_FAILED;
3043    
3044          // ATTN: DO NOT EVER call any GUI code here,          // ATTN: DO NOT EVER call any GUI code here,
3045          // as this is run under some other thread context.          // as this is run under some other thread context.
3046          // A custom event must be posted here...          // A custom event must be posted here...
3047          QApplication::postEvent(pMainForm,          QApplication::postEvent(pMainForm,
3048                  new qsamplerCustomEvent(event, pchData, cchData));                  new LscpEvent(event, pchData, cchData));
3049    
3050          return LSCP_OK;          return LSCP_OK;
3051  }  }
3052    
3053    
3054  // Start our almighty client...  // Start our almighty client...
3055  bool MainForm::startClient (void)  bool MainForm::startClient (bool bReconnectOnly)
3056  {  {
3057          // Have it a setup?          // Have it a setup?
3058          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
3059                  return false;                  return false;
3060    
3061          // Aren't we already started, are we?          // Aren't we already started, are we?
# Line 2569  bool MainForm::startClient (void) Line 3069  bool MainForm::startClient (void)
3069          m_pClient = ::lscp_client_create(          m_pClient = ::lscp_client_create(
3070                  m_pOptions->sServerHost.toUtf8().constData(),                  m_pOptions->sServerHost.toUtf8().constData(),
3071                  m_pOptions->iServerPort, qsampler_client_callback, this);                  m_pOptions->iServerPort, qsampler_client_callback, this);
3072          if (m_pClient == NULL) {          if (m_pClient == nullptr) {
3073                  // Is this the first try?                  // Is this the first try?
3074                  // maybe we need to start a local server...                  // maybe we need to start a local server...
3075                  if ((m_pServer && m_pServer->state() == QProcess::Running)                  if ((m_pServer && m_pServer->state() == QProcess::Running)
3076                          || !m_pOptions->bServerStart) {                          || !m_pOptions->bServerStart || bReconnectOnly)
3077                          appendMessagesError(                  {
3078                                  tr("Could not connect to server as client.\n\nSorry."));                          // if this method is called from autoReconnectClient()
3079                            // then don't bother user with an error message...
3080                            if (!bReconnectOnly) {
3081                                    appendMessagesError(
3082                                            tr("Could not connect to server as client.\n\nSorry.")
3083                                    );
3084                            }
3085                  } else {                  } else {
3086                          startServer();                          startServer();
3087                  }                  }
# Line 2583  bool MainForm::startClient (void) Line 3089  bool MainForm::startClient (void)
3089                  stabilizeForm();                  stabilizeForm();
3090                  return false;                  return false;
3091          }          }
3092    
3093          // Just set receive timeout value, blindly.          // Just set receive timeout value, blindly.
3094          ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);          ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);
3095          appendMessages(          appendMessages(
# Line 2590  bool MainForm::startClient (void) Line 3097  bool MainForm::startClient (void)
3097                  .arg(::lscp_client_get_timeout(m_pClient)));                  .arg(::lscp_client_get_timeout(m_pClient)));
3098    
3099          // Subscribe to channel info change notifications...          // Subscribe to channel info change notifications...
3100            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT) != LSCP_OK)
3101                    appendMessagesClient("lscp_client_subscribe(CHANNEL_COUNT)");
3102          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)
3103                  appendMessagesClient("lscp_client_subscribe");                  appendMessagesClient("lscp_client_subscribe(CHANNEL_INFO)");
3104    
3105            DeviceStatusForm::onDevicesChanged(); // initialize
3106            updateViewMidiDeviceStatusMenu();
3107            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT) != LSCP_OK)
3108                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_COUNT)");
3109            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO) != LSCP_OK)
3110                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_INFO)");
3111            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT) != LSCP_OK)
3112                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_COUNT)");
3113            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO) != LSCP_OK)
3114                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_INFO)");
3115    
3116    #if CONFIG_EVENT_CHANNEL_MIDI
3117            // Subscribe to channel MIDI data notifications...
3118            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI) != LSCP_OK)
3119                    appendMessagesClient("lscp_client_subscribe(CHANNEL_MIDI)");
3120    #endif
3121    
3122    #if CONFIG_EVENT_DEVICE_MIDI
3123            // Subscribe to channel MIDI data notifications...
3124            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI) != LSCP_OK)
3125                    appendMessagesClient("lscp_client_subscribe(DEVICE_MIDI)");
3126    #endif
3127    
3128          // We may stop scheduling around.          // We may stop scheduling around.
3129          stopSchedule();          stopSchedule();
# Line 2613  bool MainForm::startClient (void) Line 3145  bool MainForm::startClient (void)
3145          if (!m_pOptions->sSessionFile.isEmpty()) {          if (!m_pOptions->sSessionFile.isEmpty()) {
3146                  // Just load the prabably startup session...                  // Just load the prabably startup session...
3147                  if (loadSessionFile(m_pOptions->sSessionFile)) {                  if (loadSessionFile(m_pOptions->sSessionFile)) {
3148                          m_pOptions->sSessionFile = QString::null;                          m_pOptions->sSessionFile = QString();
3149                          return true;                          return true;
3150                  }                  }
3151          }          }
3152    
3153            // send the current / loaded fine tuning settings to the sampler
3154            m_pOptions->sendFineTuningSettings();
3155    
3156          // Make a new session          // Make a new session
3157          return newSession();          return newSession();
3158  }  }
# Line 2626  bool MainForm::startClient (void) Line 3161  bool MainForm::startClient (void)
3161  // Stop client...  // Stop client...
3162  void MainForm::stopClient (void)  void MainForm::stopClient (void)
3163  {  {
3164          if (m_pClient == NULL)          if (m_pClient == nullptr)
3165                  return;                  return;
3166    
3167          // Log prepare here.          // Log prepare here.
# Line 2645  void MainForm::stopClient (void) Line 3180  void MainForm::stopClient (void)
3180          closeSession(false);          closeSession(false);
3181    
3182          // Close us as a client...          // Close us as a client...
3183    #if CONFIG_EVENT_DEVICE_MIDI
3184            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI);
3185    #endif
3186    #if CONFIG_EVENT_CHANNEL_MIDI
3187            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI);
3188    #endif
3189            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
3190            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
3191            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
3192            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
3193          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
3194            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT);
3195          ::lscp_client_destroy(m_pClient);          ::lscp_client_destroy(m_pClient);
3196          m_pClient = NULL;          m_pClient = nullptr;
3197    
3198          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
3199          // if visible, that we're running out...          // if visible, that we're running out...
# Line 2663  void MainForm::stopClient (void) Line 3209  void MainForm::stopClient (void)
3209          stabilizeForm();          stabilizeForm();
3210  }  }
3211    
3212    
3213    void MainForm::startAutoReconnectClient (void)
3214    {
3215            stopClient();
3216            appendMessages(tr("Trying to reconnect..."));
3217            QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(autoReconnectClient()));
3218    }
3219    
3220    
3221    void MainForm::autoReconnectClient (void)
3222    {
3223            const bool bSuccess = startClient(true);
3224            if (!bSuccess)
3225                    QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(autoReconnectClient()));
3226    }
3227    
3228    
3229    // Channel strip activation/selection.
3230    void MainForm::activateStrip ( QMdiSubWindow *pMdiSubWindow )
3231    {
3232            ChannelStrip *pChannelStrip = nullptr;
3233            if (pMdiSubWindow)
3234                    pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
3235            if (pChannelStrip)
3236                    pChannelStrip->setSelected(true);
3237    
3238            stabilizeForm();
3239    }
3240    
3241    
3242    // Channel toolbar orientation change.
3243    void MainForm::channelsToolbarOrientation ( Qt::Orientation orientation )
3244    {
3245    #ifdef CONFIG_VOLUME
3246            m_pVolumeSlider->setOrientation(orientation);
3247            if (orientation == Qt::Horizontal) {
3248                    m_pVolumeSlider->setMinimumHeight(24);
3249                    m_pVolumeSlider->setMaximumHeight(32);
3250                    m_pVolumeSlider->setMinimumWidth(120);
3251                    m_pVolumeSlider->setMaximumWidth(640);
3252                    m_pVolumeSpinBox->setMaximumWidth(64);
3253                    m_pVolumeSpinBox->setButtonSymbols(QSpinBox::UpDownArrows);
3254            } else {
3255                    m_pVolumeSlider->setMinimumHeight(120);
3256                    m_pVolumeSlider->setMaximumHeight(480);
3257                    m_pVolumeSlider->setMinimumWidth(24);
3258                    m_pVolumeSlider->setMaximumWidth(32);
3259                    m_pVolumeSpinBox->setMaximumWidth(32);
3260                    m_pVolumeSpinBox->setButtonSymbols(QSpinBox::NoButtons);
3261            }
3262    #endif
3263    }
3264    
3265    
3266  } // namespace QSampler  } // namespace QSampler
3267    
3268    

Legend:
Removed from v.1513  
changed lines
  Added in v.3849

  ViewVC Help
Powered by ViewVC