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

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

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

revision 1558 by capela, Thu Dec 6 09:35:33 2007 UTC revision 3820 by capela, Tue Sep 1 10:55:24 2020 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-2020, 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  #include <gig.h>  #include <gig.h>
78  #endif  #endif
79    
80    // Deprecated QTextStreamFunctions/Qt namespaces workaround.
81    #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
82    #define endl    Qt::endl
83    #endif
84    
85  // Needed for lroundf()  // Needed for lroundf()
86  #include <math.h>  #include <math.h>
87    
# Line 79  static inline long lroundf ( float x ) Line 97  static inline long lroundf ( float x )
97    
98    
99  // All winsock apps needs this.  // All winsock apps needs this.
100  #if defined(WIN32)  #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
101  static WSADATA _wsaData;  static WSADATA _wsaData;
102    #undef HAVE_SIGNAL_H
103  #endif  #endif
104    
105    
106    //-------------------------------------------------------------------------
107    // LADISH Level 1 support stuff.
108    
109    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
110    
111    #include <QSocketNotifier>
112    
113    #include <unistd.h>
114    #include <sys/types.h>
115    #include <sys/socket.h>
116    #include <signal.h>
117    
118    // File descriptor for SIGUSR1 notifier.
119    static int g_fdSigusr1[2] = { -1, -1 };
120    
121    // Unix SIGUSR1 signal handler.
122    static void qsampler_sigusr1_handler ( int /* signo */ )
123    {
124            char c = 1;
125    
126            (::write(g_fdSigusr1[0], &c, sizeof(c)) > 0);
127    }
128    
129    // File descriptor for SIGTERM notifier.
130    static int g_fdSigterm[2] = { -1, -1 };
131    
132    // Unix SIGTERM signal handler.
133    static void qsampler_sigterm_handler ( int /* signo */ )
134    {
135            char c = 1;
136    
137            (::write(g_fdSigterm[0], &c, sizeof(c)) > 0);
138    }
139    
140    #endif  // HAVE_SIGNAL_H
141    
142    
143    //-------------------------------------------------------------------------
144    // QSampler -- namespace
145    
146    
147  namespace QSampler {  namespace QSampler {
148    
149  // Timer constant stuff.  // Timer constant stuff.
# Line 96  namespace QSampler { Line 156  namespace QSampler {
156  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.
157    
158    
159  //-------------------------------------------------------------------------  // Specialties for thread-callback comunication.
160  // CustomEvent -- specialty for callback comunication.  #define QSAMPLER_LSCP_EVENT   QEvent::Type(QEvent::User + 1)
161    
 #define QSAMPLER_CUSTOM_EVENT   QEvent::Type(QEvent::User + 0)  
162    
163  class CustomEvent : public QEvent  //-------------------------------------------------------------------------
164    // QSampler::LscpEvent -- specialty for LSCP callback comunication.
165    
166    class LscpEvent : public QEvent
167  {  {
168  public:  public:
169    
170          // Constructor.          // Constructor.
171          CustomEvent(lscp_event_t event, const char *pchData, int cchData)          LscpEvent(lscp_event_t event, const char *pchData, int cchData)
172                  : QEvent(QSAMPLER_CUSTOM_EVENT)                  : QEvent(QSAMPLER_LSCP_EVENT)
173          {          {
174                  m_event = event;                  m_event = event;
175                  m_data  = QString::fromUtf8(pchData, cchData);                  m_data  = QString::fromUtf8(pchData, cchData);
176          }          }
177    
178          // Accessors.          // Accessors.
179          lscp_event_t event() { return m_event; }          lscp_event_t  event() { return m_event; }
180          QString&     data()  { return m_data;  }          const QString& data() { return m_data;  }
181    
182  private:  private:
183    
# Line 127  private: Line 189  private:
189    
190    
191  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
192  // qsamplerMainForm -- Main window form implementation.  // QSampler::Workspace -- Main window workspace (MDI Area) decl.
193    
194    class Workspace : public QMdiArea
195    {
196    public:
197    
198            Workspace(MainForm *pMainForm) : QMdiArea(pMainForm) {}
199    
200    protected:
201    
202            void resizeEvent(QResizeEvent *)
203            {
204                    MainForm *pMainForm = static_cast<MainForm *> (parentWidget());
205                    if (pMainForm)
206                            pMainForm->channelsArrangeAuto();
207            }
208    };
209    
210    
211    //-------------------------------------------------------------------------
212    // QSampler::MainForm -- Main window form implementation.
213    
214  // Kind of singleton reference.  // Kind of singleton reference.
215  MainForm* MainForm::g_pMainForm = NULL;  MainForm *MainForm::g_pMainForm = nullptr;
216    
217  MainForm::MainForm ( QWidget *pParent )  MainForm::MainForm ( QWidget *pParent )
218          : QMainWindow(pParent)          : QMainWindow(pParent)
# Line 141  MainForm::MainForm ( QWidget *pParent ) Line 223  MainForm::MainForm ( QWidget *pParent )
223          g_pMainForm = this;          g_pMainForm = this;
224    
225          // Initialize some pointer references.          // Initialize some pointer references.
226          m_pOptions = NULL;          m_pOptions = nullptr;
227    
228          // All child forms are to be created later, not earlier than setup.          // All child forms are to be created later, not earlier than setup.
229          m_pMessages = NULL;          m_pMessages = nullptr;
230          m_pInstrumentListForm = NULL;          m_pInstrumentListForm = nullptr;
231          m_pDeviceForm = NULL;          m_pDeviceForm = nullptr;
232    
233          // We'll start clean.          // We'll start clean.
234          m_iUntitled   = 0;          m_iUntitled   = 0;
235            m_iDirtySetup = 0;
236          m_iDirtyCount = 0;          m_iDirtyCount = 0;
237    
238          m_pServer = NULL;          m_pServer = nullptr;
239          m_pClient = NULL;          m_pClient = nullptr;
240    
241          m_iStartDelay = 0;          m_iStartDelay = 0;
242          m_iTimerDelay = 0;          m_iTimerDelay = 0;
243    
244          m_iTimerSlot = 0;          m_iTimerSlot = 0;
245    
246  #ifdef HAVE_SIGNAL_H  #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
247    
248          // Set to ignore any fatal "Broken pipe" signals.          // Set to ignore any fatal "Broken pipe" signals.
249          ::signal(SIGPIPE, SIG_IGN);          ::signal(SIGPIPE, SIG_IGN);
250  #endif  
251            // LADISH Level 1 suport.
252    
253            // Initialize file descriptors for SIGUSR1 socket notifier.
254            ::socketpair(AF_UNIX, SOCK_STREAM, 0, g_fdSigusr1);
255            m_pSigusr1Notifier
256                    = new QSocketNotifier(g_fdSigusr1[1], QSocketNotifier::Read, this);
257    
258            QObject::connect(m_pSigusr1Notifier,
259                    SIGNAL(activated(int)),
260                    SLOT(handle_sigusr1()));
261    
262            // Install SIGUSR1 signal handler.
263            struct sigaction sigusr1;
264            sigusr1.sa_handler = qsampler_sigusr1_handler;
265            sigemptyset(&sigusr1.sa_mask);
266            sigusr1.sa_flags = 0;
267            sigusr1.sa_flags |= SA_RESTART;
268            ::sigaction(SIGUSR1, &sigusr1, nullptr);
269    
270            // Initialize file descriptors for SIGTERM socket notifier.
271            ::socketpair(AF_UNIX, SOCK_STREAM, 0, g_fdSigterm);
272            m_pSigtermNotifier
273                    = new QSocketNotifier(g_fdSigterm[1], QSocketNotifier::Read, this);
274    
275            QObject::connect(m_pSigtermNotifier,
276                    SIGNAL(activated(int)),
277                    SLOT(handle_sigterm()));
278    
279            // Install SIGTERM signal handler.
280            struct sigaction sigterm;
281            sigterm.sa_handler = qsampler_sigterm_handler;
282            sigemptyset(&sigterm.sa_mask);
283            sigterm.sa_flags = 0;
284            sigterm.sa_flags |= SA_RESTART;
285            ::sigaction(SIGTERM, &sigterm, nullptr);
286            ::sigaction(SIGQUIT, &sigterm, nullptr);
287    
288            // Ignore SIGHUP/SIGINT signals.
289            ::signal(SIGHUP, SIG_IGN);
290            ::signal(SIGINT, SIG_IGN);
291    
292    #else   // HAVE_SIGNAL_H
293    
294            m_pSigusr1Notifier = nullptr;
295            m_pSigtermNotifier = nullptr;
296            
297    #endif  // !HAVE_SIGNAL_H
298    
299  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
300          // Make some extras into the toolbar...          // Make some extras into the toolbar...
# Line 184  MainForm::MainForm ( QWidget *pParent ) Line 315  MainForm::MainForm ( QWidget *pParent )
315          QObject::connect(m_pVolumeSlider,          QObject::connect(m_pVolumeSlider,
316                  SIGNAL(valueChanged(int)),                  SIGNAL(valueChanged(int)),
317                  SLOT(volumeChanged(int)));                  SLOT(volumeChanged(int)));
         //m_ui.channelsToolbar->setHorizontallyStretchable(true);  
         //m_ui.channelsToolbar->setStretchableWidget(m_pVolumeSlider);  
318          m_ui.channelsToolbar->addWidget(m_pVolumeSlider);          m_ui.channelsToolbar->addWidget(m_pVolumeSlider);
319          // Volume spin-box          // Volume spin-box
320          m_ui.channelsToolbar->addSeparator();          m_ui.channelsToolbar->addSeparator();
321          m_pVolumeSpinBox = new QSpinBox(m_ui.channelsToolbar);          m_pVolumeSpinBox = new QSpinBox(m_ui.channelsToolbar);
         m_pVolumeSpinBox->setMaximumHeight(24);  
322          m_pVolumeSpinBox->setSuffix(" %");          m_pVolumeSpinBox->setSuffix(" %");
323          m_pVolumeSpinBox->setMinimum(0);          m_pVolumeSpinBox->setMinimum(0);
324          m_pVolumeSpinBox->setMaximum(100);          m_pVolumeSpinBox->setMaximum(100);
# Line 202  MainForm::MainForm ( QWidget *pParent ) Line 330  MainForm::MainForm ( QWidget *pParent )
330  #endif  #endif
331    
332          // Make it an MDI workspace.          // Make it an MDI workspace.
333          m_pWorkspace = new QWorkspace(this);          m_pWorkspace = new Workspace(this);
334          m_pWorkspace->setScrollBarsEnabled(true);          m_pWorkspace->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
335            m_pWorkspace->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
336          // Set the activation connection.          // Set the activation connection.
337          QObject::connect(m_pWorkspace,          QObject::connect(m_pWorkspace,
338                  SIGNAL(windowActivated(QWidget *)),                  SIGNAL(subWindowActivated(QMdiSubWindow *)),
339                  SLOT(activateStrip(QWidget *)));                  SLOT(activateStrip(QMdiSubWindow *)));
340          // Make it shine :-)          // Make it shine :-)
341          setCentralWidget(m_pWorkspace);          setCentralWidget(m_pWorkspace);
342    
# Line 236  MainForm::MainForm ( QWidget *pParent ) Line 365  MainForm::MainForm ( QWidget *pParent )
365          m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;          m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;
366          statusBar()->addWidget(pLabel);          statusBar()->addWidget(pLabel);
367    
368  #if defined(WIN32)  #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
369          WSAStartup(MAKEWORD(1, 1), &_wsaData);          WSAStartup(MAKEWORD(1, 1), &_wsaData);
370  #endif  #endif
371    
# Line 324  MainForm::MainForm ( QWidget *pParent ) Line 453  MainForm::MainForm ( QWidget *pParent )
453          QObject::connect(m_ui.channelsMenu,          QObject::connect(m_ui.channelsMenu,
454                  SIGNAL(aboutToShow()),                  SIGNAL(aboutToShow()),
455                  SLOT(channelsMenuAboutToShow()));                  SLOT(channelsMenuAboutToShow()));
456    #ifdef CONFIG_VOLUME
457            QObject::connect(m_ui.channelsToolbar,
458                    SIGNAL(orientationChanged(Qt::Orientation)),
459                    SLOT(channelsToolbarOrientation(Qt::Orientation)));
460    #endif
461  }  }
462    
463  // Destructor.  // Destructor.
# Line 332  MainForm::~MainForm() Line 466  MainForm::~MainForm()
466          // Do final processing anyway.          // Do final processing anyway.
467          processServerExit();          processServerExit();
468    
469  #if defined(WIN32)  #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
470          WSACleanup();          WSACleanup();
471  #endif  #endif
472    
473    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
474            if (m_pSigusr1Notifier)
475                    delete m_pSigusr1Notifier;
476            if (m_pSigtermNotifier)
477                    delete m_pSigtermNotifier;
478    #endif
479    
480          // Finally drop any widgets around...          // Finally drop any widgets around...
481          if (m_pDeviceForm)          if (m_pDeviceForm)
482                  delete m_pDeviceForm;                  delete m_pDeviceForm;
# Line 362  MainForm::~MainForm() Line 503  MainForm::~MainForm()
503  #endif  #endif
504    
505          // Pseudo-singleton reference shut-down.          // Pseudo-singleton reference shut-down.
506          g_pMainForm = NULL;          g_pMainForm = nullptr;
507  }  }
508    
509    
# Line 374  void MainForm::setup ( Options *pOptions Line 515  void MainForm::setup ( Options *pOptions
515    
516          // What style do we create these forms?          // What style do we create these forms?
517          Qt::WindowFlags wflags = Qt::Window          Qt::WindowFlags wflags = Qt::Window
 #if QT_VERSION >= 0x040200  
518                  | Qt::CustomizeWindowHint                  | Qt::CustomizeWindowHint
 #endif  
519                  | Qt::WindowTitleHint                  | Qt::WindowTitleHint
520                  | Qt::WindowSystemMenuHint                  | Qt::WindowSystemMenuHint
521                  | Qt::WindowMinMaxButtonsHint;                  | Qt::WindowMinMaxButtonsHint
522                    | Qt::WindowCloseButtonHint;
523          if (m_pOptions->bKeepOnTop)          if (m_pOptions->bKeepOnTop)
524                  wflags |= Qt::Tool;                  wflags |= Qt::Tool;
525    
526          // Some child forms are to be created right now.          // Some child forms are to be created right now.
527          m_pMessages = new Messages(this);          m_pMessages = new Messages(this);
528          m_pDeviceForm = new DeviceForm(this, wflags);          m_pDeviceForm = new DeviceForm(this, wflags);
529  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
530          m_pInstrumentListForm = new InstrumentListForm(this, wflags);          m_pInstrumentListForm = new InstrumentListForm(this, wflags);
531  #else  #else
532          viewInstrumentsAction->setEnabled(false);          m_ui.viewInstrumentsAction->setEnabled(false);
533  #endif  #endif
534    
535            // Setup messages logging appropriately...
536            m_pMessages->setLogging(
537                    m_pOptions->bMessagesLog,
538                    m_pOptions->sMessagesLogPath);
539    
540          // Set message defaults...          // Set message defaults...
541          updateMessagesFont();          updateMessagesFont();
542          updateMessagesLimit();          updateMessagesLimit();
543          updateMessagesCapture();          updateMessagesCapture();
544    
545          // Set the visibility signal.          // Set the visibility signal.
546          QObject::connect(m_pMessages,          QObject::connect(m_pMessages,
547                  SIGNAL(visibilityChanged(bool)),                  SIGNAL(visibilityChanged(bool)),
# Line 420  void MainForm::setup ( Options *pOptions Line 568  void MainForm::setup ( Options *pOptions
568          }          }
569    
570          // Try to restore old window positioning and initial visibility.          // Try to restore old window positioning and initial visibility.
571          m_pOptions->loadWidgetGeometry(this);          m_pOptions->loadWidgetGeometry(this, true);
572          m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);          m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);
573          m_pOptions->loadWidgetGeometry(m_pDeviceForm);          m_pOptions->loadWidgetGeometry(m_pDeviceForm);
574    
# Line 459  bool MainForm::queryClose (void) Line 607  bool MainForm::queryClose (void)
607                                  || m_ui.channelsToolbar->isVisible());                                  || m_ui.channelsToolbar->isVisible());
608                          m_pOptions->bStatusbar = statusBar()->isVisible();                          m_pOptions->bStatusbar = statusBar()->isVisible();
609                          // Save the dock windows state.                          // Save the dock windows state.
                         const QString sDockables = saveState().toBase64().data();  
610                          m_pOptions->settings().setValue("/Layout/DockWindows", saveState());                          m_pOptions->settings().setValue("/Layout/DockWindows", saveState());
611                          // And the children, and the main windows state,.                          // And the children, and the main windows state,.
612                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);
613                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);
614                          m_pOptions->saveWidgetGeometry(this);                          m_pOptions->saveWidgetGeometry(this, true);
615                          // Close popup widgets.                          // Close popup widgets.
616                          if (m_pInstrumentListForm)                          if (m_pInstrumentListForm)
617                                  m_pInstrumentListForm->close();                                  m_pInstrumentListForm->close();
618                          if (m_pDeviceForm)                          if (m_pDeviceForm)
619                                  m_pDeviceForm->close();                                  m_pDeviceForm->close();
620                          // Stop client and/or server, gracefully.                          // Stop client and/or server, gracefully.
621                          stopServer();                          stopServer(true /*interactive*/);
622                  }                  }
623          }          }
624    
# Line 481  bool MainForm::queryClose (void) Line 628  bool MainForm::queryClose (void)
628    
629  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )
630  {  {
631          if (queryClose())          if (queryClose()) {
632                    DeviceStatusForm::deleteAllInstances();
633                  pCloseEvent->accept();                  pCloseEvent->accept();
634          else          } else
635                  pCloseEvent->ignore();                  pCloseEvent->ignore();
636  }  }
637    
# Line 492  void MainForm::closeEvent ( QCloseEvent Line 640  void MainForm::closeEvent ( QCloseEvent
640  void MainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )  void MainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )
641  {  {
642          // Accept external drags only...          // Accept external drags only...
643          if (pDragEnterEvent->source() == NULL          if (pDragEnterEvent->source() == nullptr
644                  && pDragEnterEvent->mimeData()->hasUrls()) {                  && pDragEnterEvent->mimeData()->hasUrls()) {
645                  pDragEnterEvent->accept();                  pDragEnterEvent->accept();
646          } else {          } else {
# Line 501  void MainForm::dragEnterEvent ( QDragEnt Line 649  void MainForm::dragEnterEvent ( QDragEnt
649  }  }
650    
651    
652  void MainForm::dropEvent ( QDropEvent* pDropEvent )  void MainForm::dropEvent ( QDropEvent *pDropEvent )
653  {  {
654          // Accept externally originated drops only...          // Accept externally originated drops only...
655          if (pDropEvent->source())          if (pDropEvent->source())
# Line 512  void MainForm::dropEvent ( QDropEvent* p Line 660  void MainForm::dropEvent ( QDropEvent* p
660                  QListIterator<QUrl> iter(pMimeData->urls());                  QListIterator<QUrl> iter(pMimeData->urls());
661                  while (iter.hasNext()) {                  while (iter.hasNext()) {
662                          const QString& sPath = iter.next().toLocalFile();                          const QString& sPath = iter.next().toLocalFile();
663                          if (Channel::isInstrumentFile(sPath)) {                  //      if (Channel::isDlsInstrumentFile(sPath)) {
664                            if (QFileInfo(sPath).exists()) {
665                                  // Try to create a new channel from instrument file...                                  // Try to create a new channel from instrument file...
666                                  Channel *pChannel = new Channel();                                  Channel *pChannel = new Channel();
667                                  if (pChannel == NULL)                                  if (pChannel == nullptr)
668                                          return;                                          return;
669                                  // Start setting the instrument filename...                                  // Start setting the instrument filename...
670                                  pChannel->setInstrument(sPath, 0);                                  pChannel->setInstrument(sPath, 0);
# Line 546  void MainForm::dropEvent ( QDropEvent* p Line 695  void MainForm::dropEvent ( QDropEvent* p
695    
696    
697  // Custome event handler.  // Custome event handler.
698  void MainForm::customEvent(QEvent* pCustomEvent)  void MainForm::customEvent ( QEvent* pEvent )
699  {  {
700          // For the time being, just pump it to messages.          // For the time being, just pump it to messages.
701          if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {          if (pEvent->type() == QSAMPLER_LSCP_EVENT) {
702                  CustomEvent *pEvent = static_cast<CustomEvent *> (pCustomEvent);                  LscpEvent *pLscpEvent = static_cast<LscpEvent *> (pEvent);
703                  if (pEvent->event() == LSCP_EVENT_CHANNEL_INFO) {                  switch (pLscpEvent->event()) {
704                          int iChannelID = pEvent->data().toInt();                          case LSCP_EVENT_CHANNEL_COUNT:
705                          ChannelStrip *pChannelStrip = channelStrip(iChannelID);                                  updateAllChannelStrips(true);
706                          if (pChannelStrip)                                  break;
707                                  channelStripChanged(pChannelStrip);                          case LSCP_EVENT_CHANNEL_INFO: {
708                  } else {                                  const int iChannelID = pLscpEvent->data().toInt();
709                          appendMessagesColor(tr("Notify event: %1 data: %2")                                  ChannelStrip *pChannelStrip = channelStrip(iChannelID);
710                                  .arg(::lscp_event_to_text(pEvent->event()))                                  if (pChannelStrip)
711                                  .arg(pEvent->data()), "#996699");                                          channelStripChanged(pChannelStrip);
712                                    break;
713                            }
714                            case LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT:
715                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
716                                    DeviceStatusForm::onDevicesChanged();
717                                    updateViewMidiDeviceStatusMenu();
718                                    break;
719                            case LSCP_EVENT_MIDI_INPUT_DEVICE_INFO: {
720                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
721                                    const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt();
722                                    DeviceStatusForm::onDeviceChanged(iDeviceID);
723                                    break;
724                            }
725                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT:
726                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
727                                    break;
728                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO:
729                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
730                                    break;
731                    #if CONFIG_EVENT_CHANNEL_MIDI
732                            case LSCP_EVENT_CHANNEL_MIDI: {
733                                    const int iChannelID = pLscpEvent->data().section(' ', 0, 0).toInt();
734                                    ChannelStrip *pChannelStrip = channelStrip(iChannelID);
735                                    if (pChannelStrip)
736                                            pChannelStrip->midiActivityLedOn();
737                                    break;
738                            }
739                    #endif
740                    #if CONFIG_EVENT_DEVICE_MIDI
741                            case LSCP_EVENT_DEVICE_MIDI: {
742                                    const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt();
743                                    const int iPortID   = pLscpEvent->data().section(' ', 1, 1).toInt();
744                                    DeviceStatusForm *pDeviceStatusForm
745                                            = DeviceStatusForm::getInstance(iDeviceID);
746                                    if (pDeviceStatusForm)
747                                            pDeviceStatusForm->midiArrived(iPortID);
748                                    break;
749                            }
750                    #endif
751                            default:
752                                    appendMessagesColor(tr("LSCP Event: %1 data: %2")
753                                            .arg(::lscp_event_to_text(pLscpEvent->event()))
754                                            .arg(pLscpEvent->data()), "#996699");
755                  }                  }
756          }          }
757  }  }
758    
759    
760    // LADISH Level 1 -- SIGUSR1 signal handler.
761    void MainForm::handle_sigusr1 (void)
762    {
763    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
764    
765            char c;
766    
767            if (::read(g_fdSigusr1[1], &c, sizeof(c)) > 0)
768                    saveSession(false);
769    
770    #endif
771    }
772    
773    
774    void MainForm::handle_sigterm (void)
775    {
776    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
777    
778            char c;
779    
780            if (::read(g_fdSigterm[1], &c, sizeof(c)) > 0)
781                    close();
782    
783    #endif
784    }
785    
786    
787    void MainForm::updateViewMidiDeviceStatusMenu (void)
788    {
789            m_ui.viewMidiDeviceStatusMenu->clear();
790            const std::map<int, DeviceStatusForm *> statusForms
791                    = DeviceStatusForm::getInstances();
792            std::map<int, DeviceStatusForm *>::const_iterator iter
793                    = statusForms.begin();
794            for ( ; iter != statusForms.end(); ++iter) {
795                    DeviceStatusForm *pStatusForm = iter->second;
796                    m_ui.viewMidiDeviceStatusMenu->addAction(
797                            pStatusForm->visibleAction());
798            }
799    }
800    
801    
802  // Context menu event handler.  // Context menu event handler.
803  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )
804  {  {
# Line 574  void MainForm::contextMenuEvent( QContex Line 809  void MainForm::contextMenuEvent( QContex
809    
810    
811  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
812  // qsamplerMainForm -- Brainless public property accessors.  // QSampler::MainForm -- Brainless public property accessors.
813    
814  // The global options settings property.  // The global options settings property.
815  Options *MainForm::options (void) const  Options *MainForm::options (void) const
# Line 598  MainForm *MainForm::getInstance (void) Line 833  MainForm *MainForm::getInstance (void)
833    
834    
835  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
836  // qsamplerMainForm -- Session file stuff.  // QSampler::MainForm -- Session file stuff.
837    
838  // Format the displayable session filename.  // Format the displayable session filename.
839  QString MainForm::sessionName ( const QString& sFilename )  QString MainForm::sessionName ( const QString& sFilename )
840  {  {
841          bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);          const bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);
842          QString sSessionName = sFilename;          QString sSessionName = sFilename;
843          if (sSessionName.isEmpty())          if (sSessionName.isEmpty())
844                  sSessionName = tr("Untitled") + QString::number(m_iUntitled);                  sSessionName = tr("Untitled") + QString::number(m_iUntitled);
# Line 627  bool MainForm::newSession (void) Line 862  bool MainForm::newSession (void)
862          m_iUntitled++;          m_iUntitled++;
863    
864          // Stabilize form.          // Stabilize form.
865          m_sFilename = QString::null;          m_sFilename = QString();
866          m_iDirtyCount = 0;          m_iDirtyCount = 0;
867          appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));          appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));
868          stabilizeForm();          stabilizeForm();
# Line 639  bool MainForm::newSession (void) Line 874  bool MainForm::newSession (void)
874  // Open an existing sampler session.  // Open an existing sampler session.
875  bool MainForm::openSession (void)  bool MainForm::openSession (void)
876  {  {
877          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
878                  return false;                  return false;
879    
880          // Ask for the filename to open...          // Ask for the filename to open...
881          QString sFilename = QFileDialog::getOpenFileName(this,          QString sFilename = QFileDialog::getOpenFileName(this,
882                  QSAMPLER_TITLE ": " + tr("Open Session"), // Caption.                  tr("Open Session"),                       // Caption.
883                  m_pOptions->sSessionDir,                  // Start here.                  m_pOptions->sSessionDir,                  // Start here.
884                  tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)                  tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
885          );          );
# Line 665  bool MainForm::openSession (void) Line 900  bool MainForm::openSession (void)
900  // Save current sampler session with another name.  // Save current sampler session with another name.
901  bool MainForm::saveSession ( bool bPrompt )  bool MainForm::saveSession ( bool bPrompt )
902  {  {
903          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
904                  return false;                  return false;
905    
906          QString sFilename = m_sFilename;          QString sFilename = m_sFilename;
# Line 677  bool MainForm::saveSession ( bool bPromp Line 912  bool MainForm::saveSession ( bool bPromp
912                          sFilename = m_pOptions->sSessionDir;                          sFilename = m_pOptions->sSessionDir;
913                  // Prompt the guy...                  // Prompt the guy...
914                  sFilename = QFileDialog::getSaveFileName(this,                  sFilename = QFileDialog::getSaveFileName(this,
915                          QSAMPLER_TITLE ": " + tr("Save Session"), // Caption.                          tr("Save Session"),                       // Caption.
916                          sFilename,                                // Start here.                          sFilename,                                // Start here.
917                          tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)                          tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
918                  );                  );
# Line 687  bool MainForm::saveSession ( bool bPromp Line 922  bool MainForm::saveSession ( bool bPromp
922                  // Enforce .lscp extension...                  // Enforce .lscp extension...
923                  if (QFileInfo(sFilename).suffix().isEmpty())                  if (QFileInfo(sFilename).suffix().isEmpty())
924                          sFilename += ".lscp";                          sFilename += ".lscp";
925            #if 0
926                  // Check if already exists...                  // Check if already exists...
927                  if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {                  if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {
928                          if (QMessageBox::warning(this,                          if (QMessageBox::warning(this,
929                                  QSAMPLER_TITLE ": " + tr("Warning"),                                  tr("Warning"),
930                                  tr("The file already exists:\n\n"                                  tr("The file already exists:\n\n"
931                                  "\"%1\"\n\n"                                  "\"%1\"\n\n"
932                                  "Do you want to replace it?")                                  "Do you want to replace it?")
933                                  .arg(sFilename),                                  .arg(sFilename),
934                                  tr("Replace"), tr("Cancel")) > 0)                                  QMessageBox::Yes | QMessageBox::No)
935                                    == QMessageBox::No)
936                                  return false;                                  return false;
937                  }                  }
938            #endif
939          }          }
940    
941          // Save it right away.          // Save it right away.
# Line 713  bool MainForm::closeSession ( bool bForc Line 951  bool MainForm::closeSession ( bool bForc
951          // Are we dirty enough to prompt it?          // Are we dirty enough to prompt it?
952          if (m_iDirtyCount > 0) {          if (m_iDirtyCount > 0) {
953                  switch (QMessageBox::warning(this,                  switch (QMessageBox::warning(this,
954                          QSAMPLER_TITLE ": " + tr("Warning"),                          tr("Warning"),
955                          tr("The current session has been changed:\n\n"                          tr("The current session has been changed:\n\n"
956                          "\"%1\"\n\n"                          "\"%1\"\n\n"
957                          "Do you want to save the changes?")                          "Do you want to save the changes?")
958                          .arg(sessionName(m_sFilename)),                          .arg(sessionName(m_sFilename)),
959                          tr("Save"), tr("Discard"), tr("Cancel"))) {                          QMessageBox::Save |
960                  case 0:     // Save...                          QMessageBox::Discard |
961                            QMessageBox::Cancel)) {
962                    case QMessageBox::Save:
963                          bClose = saveSession(false);                          bClose = saveSession(false);
964                          // Fall thru....                          // Fall thru....
965                  case 1:     // Discard                  case QMessageBox::Discard:
966                          break;                          break;
967                  default:    // Cancel.                  default:    // Cancel.
968                          bClose = false;                          bClose = false;
# Line 734  bool MainForm::closeSession ( bool bForc Line 974  bool MainForm::closeSession ( bool bForc
974          if (bClose) {          if (bClose) {
975                  // Remove all channel strips from sight...                  // Remove all channel strips from sight...
976                  m_pWorkspace->setUpdatesEnabled(false);                  m_pWorkspace->setUpdatesEnabled(false);
977                  QWidgetList wlist = m_pWorkspace->windowList();                  const QList<QMdiSubWindow *>& wlist
978                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                          = m_pWorkspace->subWindowList();
979                          ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
980                            ChannelStrip *pChannelStrip
981                                    = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
982                          if (pChannelStrip) {                          if (pChannelStrip) {
983                                  Channel *pChannel = pChannelStrip->channel();                                  Channel *pChannel = pChannelStrip->channel();
984                                  if (bForce && pChannel)                                  if (bForce && pChannel)
985                                          pChannel->removeChannel();                                          pChannel->removeChannel();
986                                  delete pChannelStrip;                                  delete pChannelStrip;
987                          }                          }
988                            delete pMdiSubWindow;
989                  }                  }
990                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
991                  // We're now clean, for sure.                  // We're now clean, for sure.
# Line 756  bool MainForm::closeSession ( bool bForc Line 999  bool MainForm::closeSession ( bool bForc
999  // Load a session from specific file path.  // Load a session from specific file path.
1000  bool MainForm::loadSessionFile ( const QString& sFilename )  bool MainForm::loadSessionFile ( const QString& sFilename )
1001  {  {
1002          if (m_pClient == NULL)          if (m_pClient == nullptr)
1003                  return false;                  return false;
1004    
1005          // Open and read from real file.          // Open and read from real file.
# Line 832  bool MainForm::loadSessionFile ( const Q Line 1075  bool MainForm::loadSessionFile ( const Q
1075  // Save current session to specific file path.  // Save current session to specific file path.
1076  bool MainForm::saveSessionFile ( const QString& sFilename )  bool MainForm::saveSessionFile ( const QString& sFilename )
1077  {  {
1078          if (m_pClient == NULL)          if (m_pClient == nullptr)
1079                  return false;                  return false;
1080    
1081          // Check whether server is apparently OK...          // Check whether server is apparently OK...
# Line 854  bool MainForm::saveSessionFile ( const Q Line 1097  bool MainForm::saveSessionFile ( const Q
1097          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1098    
1099          // Write the file.          // Write the file.
1100          int  iErrors = 0;          int iErrors = 0;
1101          QTextStream ts(&file);          QTextStream ts(&file);
1102          ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;          ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;
1103          ts << "# " << tr("Version")          ts << "# " << tr("Version") << ": " CONFIG_BUILD_VERSION << endl;
1104          << ": " QSAMPLER_VERSION << endl;  //      ts << "# " << tr("Build") << ": " CONFIG_BUILD_DATE << endl;
         ts << "# " << tr("Build")  
         << ": " __DATE__ " " __TIME__ << endl;  
1105          ts << "#"  << endl;          ts << "#"  << endl;
1106          ts << "# " << tr("File")          ts << "# " << tr("File")
1107          << ": " << QFileInfo(sFilename).fileName() << endl;          << ": " << QFileInfo(sFilename).fileName() << endl;
# Line 873  bool MainForm::saveSessionFile ( const Q Line 1114  bool MainForm::saveSessionFile ( const Q
1114          // It is assumed that this new kind of device+session file          // It is assumed that this new kind of device+session file
1115          // will be loaded from a complete initialized server...          // will be loaded from a complete initialized server...
1116          int *piDeviceIDs;          int *piDeviceIDs;
1117          int  iDevice;          int  i, iDevice;
1118          ts << "RESET" << endl;          ts << "RESET" << endl;
1119    
1120          // Audio device mapping.          // Audio device mapping.
1121          QMap<int, int> audioDeviceMap;          QMap<int, int> audioDeviceMap; iDevice = 0;
1122          piDeviceIDs = Device::getDevices(m_pClient, Device::Audio);          piDeviceIDs = Device::getDevices(m_pClient, Device::Audio);
1123          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (i = 0; piDeviceIDs && piDeviceIDs[i] >= 0; ++i) {
1124                  ts << endl;                  Device device(Device::Audio, piDeviceIDs[i]);
1125                  Device device(Device::Audio, piDeviceIDs[iDevice]);                  // Avoid plug-in driver devices...
1126                    if (device.driverName().toUpper() == "PLUGIN")
1127                            continue;
1128                  // Audio device specification...                  // Audio device specification...
1129                    ts << endl;
1130                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1131                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1132                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();
# Line 913  bool MainForm::saveSessionFile ( const Q Line 1157  bool MainForm::saveSessionFile ( const Q
1157                          iPort++;                          iPort++;
1158                  }                  }
1159                  // Audio device index/id mapping.                  // Audio device index/id mapping.
1160                  audioDeviceMap[device.deviceID()] = iDevice;                  audioDeviceMap.insert(device.deviceID(), iDevice++);
1161                  // Try to keep it snappy :)                  // Try to keep it snappy :)
1162                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1163          }          }
1164    
1165          // MIDI device mapping.          // MIDI device mapping.
1166          QMap<int, int> midiDeviceMap;          QMap<int, int> midiDeviceMap; iDevice = 0;
1167          piDeviceIDs = Device::getDevices(m_pClient, Device::Midi);          piDeviceIDs = Device::getDevices(m_pClient, Device::Midi);
1168          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (i = 0; piDeviceIDs && piDeviceIDs[i] >= 0; ++i) {
1169                  ts << endl;                  Device device(Device::Midi, piDeviceIDs[i]);
1170                  Device device(Device::Midi, piDeviceIDs[iDevice]);                  // Avoid plug-in driver devices...
1171                    if (device.driverName().toUpper() == "PLUGIN")
1172                            continue;
1173                  // MIDI device specification...                  // MIDI device specification...
1174                    ts << endl;
1175                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1176                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1177                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();
# Line 955  bool MainForm::saveSessionFile ( const Q Line 1202  bool MainForm::saveSessionFile ( const Q
1202                          iPort++;                          iPort++;
1203                  }                  }
1204                  // MIDI device index/id mapping.                  // MIDI device index/id mapping.
1205                  midiDeviceMap[device.deviceID()] = iDevice;                  midiDeviceMap.insert(device.deviceID(), iDevice++);
1206                  // Try to keep it snappy :)                  // Try to keep it snappy :)
1207                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1208          }          }
# Line 966  bool MainForm::saveSessionFile ( const Q Line 1213  bool MainForm::saveSessionFile ( const Q
1213          QMap<int, int> midiInstrumentMap;          QMap<int, int> midiInstrumentMap;
1214          int *piMaps = ::lscp_list_midi_instrument_maps(m_pClient);          int *piMaps = ::lscp_list_midi_instrument_maps(m_pClient);
1215          for (int iMap = 0; piMaps && piMaps[iMap] >= 0; iMap++) {          for (int iMap = 0; piMaps && piMaps[iMap] >= 0; iMap++) {
1216                  int iMidiMap = piMaps[iMap];                  const int iMidiMap = piMaps[iMap];
1217                  const char *pszMapName                  const char *pszMapName
1218                          = ::lscp_get_midi_instrument_map_name(m_pClient, iMidiMap);                          = ::lscp_get_midi_instrument_map_name(m_pClient, iMidiMap);
1219                  ts << "# " << tr("MIDI instrument map") << " " << iMap;                  ts << "# " << tr("MIDI instrument map") << " " << iMap;
# Line 1018  bool MainForm::saveSessionFile ( const Q Line 1265  bool MainForm::saveSessionFile ( const Q
1265                  }                  }
1266                  ts << endl;                  ts << endl;
1267                  // Check for errors...                  // Check for errors...
1268                  if (pInstrs == NULL && ::lscp_client_get_errno(m_pClient)) {                  if (pInstrs == nullptr && ::lscp_client_get_errno(m_pClient)) {
1269                          appendMessagesClient("lscp_list_midi_instruments");                          appendMessagesClient("lscp_list_midi_instruments");
1270                          iErrors++;                          iErrors++;
1271                  }                  }
1272                  // MIDI strument index/id mapping.                  // MIDI strument index/id mapping.
1273                  midiInstrumentMap[iMidiMap] = iMap;                  midiInstrumentMap.insert(iMidiMap, iMap);
1274          }          }
1275          // Check for errors...          // Check for errors...
1276          if (piMaps == NULL && ::lscp_client_get_errno(m_pClient)) {          if (piMaps == nullptr && ::lscp_client_get_errno(m_pClient)) {
1277                  appendMessagesClient("lscp_list_midi_instrument_maps");                  appendMessagesClient("lscp_list_midi_instrument_maps");
1278                  iErrors++;                  iErrors++;
1279          }          }
1280  #endif  // CONFIG_MIDI_INSTRUMENT  #endif  // CONFIG_MIDI_INSTRUMENT
1281    
1282          // Sampler channel mapping.          // Sampler channel mapping...
1283          QWidgetList wlist = m_pWorkspace->windowList();          int iChannelID = 0;
1284          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          const QList<QMdiSubWindow *>& wlist
1285                  ChannelStrip* pChannelStrip                  = m_pWorkspace->subWindowList();
1286                          = static_cast<ChannelStrip *> (wlist.at(iChannel));          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
1287                    ChannelStrip *pChannelStrip
1288                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
1289                  if (pChannelStrip) {                  if (pChannelStrip) {
1290                          Channel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
1291                          if (pChannel) {                          if (pChannel) {
1292                                  ts << "# " << tr("Channel") << " " << iChannel << endl;                                  // Avoid "artifial" plug-in devices...
1293                                    const int iAudioDevice = pChannel->audioDevice();
1294                                    if (!audioDeviceMap.contains(iAudioDevice))
1295                                            continue;
1296                                    const int iMidiDevice = pChannel->midiDevice();
1297                                    if (!midiDeviceMap.contains(iMidiDevice))
1298                                            continue;
1299                                    // Go for regular, canonical devices...
1300                                    ts << "# " << tr("Channel") << " " << iChannelID << endl;
1301                                  ts << "ADD CHANNEL" << endl;                                  ts << "ADD CHANNEL" << endl;
1302                                  if (audioDeviceMap.isEmpty()) {                                  if (audioDeviceMap.isEmpty()) {
1303                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannelID
1304                                                  << " " << pChannel->audioDriver() << endl;                                                  << " " << pChannel->audioDriver() << endl;
1305                                  } else {                                  } else {
1306                                          ts << "SET CHANNEL AUDIO_OUTPUT_DEVICE " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_DEVICE " << iChannelID
1307                                                  << " " << audioDeviceMap[pChannel->audioDevice()] << endl;                                                  << " " << audioDeviceMap.value(iAudioDevice) << endl;
1308                                  }                                  }
1309                                  if (midiDeviceMap.isEmpty()) {                                  if (midiDeviceMap.isEmpty()) {
1310                                          ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannel                                          ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannelID
1311                                                  << " " << pChannel->midiDriver() << endl;                                                  << " " << pChannel->midiDriver() << endl;
1312                                  } else {                                  } else {
1313                                          ts << "SET CHANNEL MIDI_INPUT_DEVICE " << iChannel                                          ts << "SET CHANNEL MIDI_INPUT_DEVICE " << iChannelID
1314                                                  << " " << midiDeviceMap[pChannel->midiDevice()] << endl;                                                  << " " << midiDeviceMap.value(iMidiDevice) << endl;
1315                                  }                                  }
1316                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannelID
1317                                          << " " << pChannel->midiPort() << endl;                                          << " " << pChannel->midiPort() << endl;
1318                                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";                                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannelID << " ";
1319                                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)                                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
1320                                          ts << "ALL";                                          ts << "ALL";
1321                                  else                                  else
1322                                          ts << pChannel->midiChannel();                                          ts << pChannel->midiChannel();
1323                                  ts << endl;                                  ts << endl;
1324                                  ts << "LOAD ENGINE " << pChannel->engineName()                                  ts << "LOAD ENGINE " << pChannel->engineName()
1325                                          << " " << iChannel << endl;                                          << " " << iChannelID << endl;
1326                                  if (pChannel->instrumentStatus() < 100) ts << "# ";                                  if (pChannel->instrumentStatus() < 100) ts << "# ";
1327                                  ts << "LOAD INSTRUMENT NON_MODAL '"                                  ts << "LOAD INSTRUMENT NON_MODAL '"
1328                                          << pChannel->instrumentFile() << "' "                                          << pChannel->instrumentFile() << "' "
1329                                          << pChannel->instrumentNr() << " " << iChannel << endl;                                          << pChannel->instrumentNr() << " " << iChannelID << endl;
1330                                  ChannelRoutingMap::ConstIterator audioRoute;                                  ChannelRoutingMap::ConstIterator audioRoute;
1331                                  for (audioRoute = pChannel->audioRouting().begin();                                  for (audioRoute = pChannel->audioRouting().begin();
1332                                                  audioRoute != pChannel->audioRouting().end();                                                  audioRoute != pChannel->audioRouting().end();
1333                                                          ++audioRoute) {                                                          ++audioRoute) {
1334                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannelID
1335                                                  << " " << audioRoute.key()                                                  << " " << audioRoute.key()
1336                                                  << " " << audioRoute.value() << endl;                                                  << " " << audioRoute.value() << endl;
1337                                  }                                  }
1338                                  ts << "SET CHANNEL VOLUME " << iChannel                                  ts << "SET CHANNEL VOLUME " << iChannelID
1339                                          << " " << pChannel->volume() << endl;                                          << " " << pChannel->volume() << endl;
1340                                  if (pChannel->channelMute())                                  if (pChannel->channelMute())
1341                                          ts << "SET CHANNEL MUTE " << iChannel << " 1" << endl;                                          ts << "SET CHANNEL MUTE " << iChannelID << " 1" << endl;
1342                                  if (pChannel->channelSolo())                                  if (pChannel->channelSolo())
1343                                          ts << "SET CHANNEL SOLO " << iChannel << " 1" << endl;                                          ts << "SET CHANNEL SOLO " << iChannelID << " 1" << endl;
1344  #ifdef CONFIG_MIDI_INSTRUMENT                          #ifdef CONFIG_MIDI_INSTRUMENT
1345                                  if (pChannel->midiMap() >= 0) {                                  const int iMidiMap = pChannel->midiMap();
1346                                          ts << "SET CHANNEL MIDI_INSTRUMENT_MAP " << iChannel                                  if (midiInstrumentMap.contains(iMidiMap)) {
1347                                                  << " " << midiInstrumentMap[pChannel->midiMap()] << endl;                                          ts << "SET CHANNEL MIDI_INSTRUMENT_MAP " << iChannelID
1348                                                    << " " << midiInstrumentMap.value(iMidiMap) << endl;
1349                                  }                                  }
1350  #endif                          #endif
1351  #ifdef CONFIG_FXSEND                          #ifdef CONFIG_FXSEND
                                 int iChannelID = pChannel->channelID();  
1352                                  int *piFxSends = ::lscp_list_fxsends(m_pClient, iChannelID);                                  int *piFxSends = ::lscp_list_fxsends(m_pClient, iChannelID);
1353                                  for (int iFxSend = 0;                                  for (int iFxSend = 0;
1354                                                  piFxSends && piFxSends[iFxSend] >= 0;                                                  piFxSends && piFxSends[iFxSend] >= 0;
# Line 1099  bool MainForm::saveSessionFile ( const Q Line 1356  bool MainForm::saveSessionFile ( const Q
1356                                          lscp_fxsend_info_t *pFxSendInfo = ::lscp_get_fxsend_info(                                          lscp_fxsend_info_t *pFxSendInfo = ::lscp_get_fxsend_info(
1357                                                  m_pClient, iChannelID, piFxSends[iFxSend]);                                                  m_pClient, iChannelID, piFxSends[iFxSend]);
1358                                          if (pFxSendInfo) {                                          if (pFxSendInfo) {
1359                                                  ts << "CREATE FX_SEND " << iChannel                                                  ts << "CREATE FX_SEND " << iChannelID
1360                                                          << " " << pFxSendInfo->midi_controller;                                                          << " " << pFxSendInfo->midi_controller;
1361                                                  if (pFxSendInfo->name)                                                  if (pFxSendInfo->name)
1362                                                          ts << " '" << pFxSendInfo->name << "'";                                                          ts << " '" << pFxSendInfo->name << "'";
# Line 1109  bool MainForm::saveSessionFile ( const Q Line 1366  bool MainForm::saveSessionFile ( const Q
1366                                                                  piRouting && piRouting[iAudioSrc] >= 0;                                                                  piRouting && piRouting[iAudioSrc] >= 0;
1367                                                                          iAudioSrc++) {                                                                          iAudioSrc++) {
1368                                                          ts << "SET FX_SEND AUDIO_OUTPUT_CHANNEL "                                                          ts << "SET FX_SEND AUDIO_OUTPUT_CHANNEL "
1369                                                                  << iChannel                                                                  << iChannelID
1370                                                                  << " " << iFxSend                                                                  << " " << iFxSend
1371                                                                  << " " << iAudioSrc                                                                  << " " << iAudioSrc
1372                                                                  << " " << piRouting[iAudioSrc] << endl;                                                                  << " " << piRouting[iAudioSrc] << endl;
1373                                                  }                                                  }
1374  #ifdef CONFIG_FXSEND_LEVEL                                          #ifdef CONFIG_FXSEND_LEVEL
1375                                                  ts << "SET FX_SEND LEVEL " << iChannel                                                  ts << "SET FX_SEND LEVEL " << iChannelID
1376                                                          << " " << iFxSend                                                          << " " << iFxSend
1377                                                          << " " << pFxSendInfo->level << endl;                                                          << " " << pFxSendInfo->level << endl;
1378  #endif                                          #endif
1379                                          }       // Check for errors...                                          }       // Check for errors...
1380                                          else if (::lscp_client_get_errno(m_pClient)) {                                          else if (::lscp_client_get_errno(m_pClient)) {
1381                                                  appendMessagesClient("lscp_get_fxsend_info");                                                  appendMessagesClient("lscp_get_fxsend_info");
1382                                                  iErrors++;                                                  iErrors++;
1383                                          }                                          }
1384                                  }                                  }
1385  #endif                          #endif
1386                                  ts << endl;                                  ts << endl;
1387                                    // Go for next channel...
1388                                    ++iChannelID;
1389                          }                          }
1390                  }                  }
1391                  // Try to keep it snappy :)                  // Try to keep it snappy :)
# Line 1178  void MainForm::sessionDirty (void) Line 1437  void MainForm::sessionDirty (void)
1437    
1438    
1439  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1440  // qsamplerMainForm -- File Action slots.  // QSampler::MainForm -- File Action slots.
1441    
1442  // Create a new sampler session.  // Create a new sampler session.
1443  void MainForm::fileNew (void)  void MainForm::fileNew (void)
# Line 1202  void MainForm::fileOpenRecent (void) Line 1461  void MainForm::fileOpenRecent (void)
1461          // Retrive filename index from action data...          // Retrive filename index from action data...
1462          QAction *pAction = qobject_cast<QAction *> (sender());          QAction *pAction = qobject_cast<QAction *> (sender());
1463          if (pAction && m_pOptions) {          if (pAction && m_pOptions) {
1464                  int iIndex = pAction->data().toInt();                  const int iIndex = pAction->data().toInt();
1465                  if (iIndex >= 0 && iIndex < m_pOptions->recentFiles.count()) {                  if (iIndex >= 0 && iIndex < m_pOptions->recentFiles.count()) {
1466                          QString sFilename = m_pOptions->recentFiles[iIndex];                          QString sFilename = m_pOptions->recentFiles[iIndex];
1467                          // Check if we can safely close the current session...                          // Check if we can safely close the current session...
# Line 1232  void MainForm::fileSaveAs (void) Line 1491  void MainForm::fileSaveAs (void)
1491  // Reset the sampler instance.  // Reset the sampler instance.
1492  void MainForm::fileReset (void)  void MainForm::fileReset (void)
1493  {  {
1494          if (m_pClient == NULL)          if (m_pClient == nullptr)
1495                  return;                  return;
1496    
1497          // Ask user whether he/she want's an internal sampler reset...          // Ask user whether he/she want's an internal sampler reset...
1498          if (QMessageBox::warning(this,          if (m_pOptions && m_pOptions->bConfirmReset) {
1499                  QSAMPLER_TITLE ": " + tr("Warning"),                  const QString& sTitle = tr("Warning");
1500                  tr("Resetting the sampler instance will close\n"                  const QString& sText = tr(
1501                  "all device and channel configurations.\n\n"                          "Resetting the sampler instance will close\n"
1502                  "Please note that this operation may cause\n"                          "all device and channel configurations.\n\n"
1503                  "temporary MIDI and Audio disruption.\n\n"                          "Please note that this operation may cause\n"
1504                  "Do you want to reset the sampler engine now?"),                          "temporary MIDI and Audio disruption.\n\n"
1505                  tr("Reset"), tr("Cancel")) > 0)                          "Do you want to reset the sampler engine now?");
1506                  return;          #if 0
1507                    if (QMessageBox::warning(this, sTitle, sText,
1508                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1509                            return;
1510            #else
1511                    QMessageBox mbox(this);
1512                    mbox.setIcon(QMessageBox::Warning);
1513                    mbox.setWindowTitle(sTitle);
1514                    mbox.setText(sText);
1515                    mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1516                    QCheckBox cbox(tr("Don't ask this again"));
1517                    cbox.setChecked(false);
1518                    cbox.blockSignals(true);
1519                    mbox.addButton(&cbox, QMessageBox::ActionRole);
1520                    if (mbox.exec() == QMessageBox::Cancel)
1521                            return;
1522                    if (cbox.isChecked())
1523                            m_pOptions->bConfirmReset = false;
1524            #endif
1525            }
1526    
1527          // Trye closing the current session, first...          // Trye closing the current session, first...
1528          if (!closeSession(true))          if (!closeSession(true))
# Line 1269  void MainForm::fileReset (void) Line 1547  void MainForm::fileReset (void)
1547  // Restart the client/server instance.  // Restart the client/server instance.
1548  void MainForm::fileRestart (void)  void MainForm::fileRestart (void)
1549  {  {
1550          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
1551                  return;                  return;
1552    
1553          bool bRestart = true;          bool bRestart = true;
1554    
1555          // Ask user whether he/she want's a complete restart...          // Ask user whether he/she want's a complete restart...
1556          // (if we're currently up and running)          // (if we're currently up and running)
1557          if (bRestart && m_pClient) {          if (m_pOptions && m_pOptions->bConfirmRestart) {
1558                  bRestart = (QMessageBox::warning(this,                  const QString& sTitle = tr("Warning");
1559                          QSAMPLER_TITLE ": " + tr("Warning"),                  const QString& sText = tr(
1560                          tr("New settings will be effective after\n"                          "New settings will be effective after\n"
1561                          "restarting the client/server connection.\n\n"                          "restarting the client/server connection.\n\n"
1562                          "Please note that this operation may cause\n"                          "Please note that this operation may cause\n"
1563                          "temporary MIDI and Audio disruption.\n\n"                          "temporary MIDI and Audio disruption.\n\n"
1564                          "Do you want to restart the connection now?"),                          "Do you want to restart the connection now?");
1565                          tr("Restart"), tr("Cancel")) == 0);          #if 0
1566                    if (QMessageBox::warning(this, sTitle, sText,
1567                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1568                            bRestart = false;
1569            #else
1570                    QMessageBox mbox(this);
1571                    mbox.setIcon(QMessageBox::Warning);
1572                    mbox.setWindowTitle(sTitle);
1573                    mbox.setText(sText);
1574                    mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1575                    QCheckBox cbox(tr("Don't ask this again"));
1576                    cbox.setChecked(false);
1577                    cbox.blockSignals(true);
1578                    mbox.addButton(&cbox, QMessageBox::ActionRole);
1579                    if (mbox.exec() == QMessageBox::Cancel)
1580                            bRestart = false;
1581                    else
1582                    if (cbox.isChecked())
1583                            m_pOptions->bConfirmRestart = false;
1584            #endif
1585          }          }
1586    
1587          // Are we still for it?          // Are we still for it?
# Line 1306  void MainForm::fileExit (void) Line 1603  void MainForm::fileExit (void)
1603    
1604    
1605  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1606  // qsamplerMainForm -- Edit Action slots.  // QSampler::MainForm -- Edit Action slots.
1607    
1608  // Add a new sampler channel.  // Add a new sampler channel.
1609  void MainForm::editAddChannel (void)  void MainForm::editAddChannel (void)
1610  {  {
1611          if (m_pClient == NULL)          ++m_iDirtySetup;
1612            addChannelStrip();
1613            --m_iDirtySetup;
1614    }
1615    
1616    void MainForm::addChannelStrip (void)
1617    {
1618            if (m_pClient == nullptr)
1619                  return;                  return;
1620    
1621          // Just create the channel instance...          // Just create the channel instance...
1622          Channel *pChannel = new Channel();          Channel *pChannel = new Channel();
1623          if (pChannel == NULL)          if (pChannel == nullptr)
1624                  return;                  return;
1625    
1626          // Before we show it up, may be we'll          // Before we show it up, may be we'll
# Line 1334  void MainForm::editAddChannel (void) Line 1638  void MainForm::editAddChannel (void)
1638          }          }
1639    
1640          // Do we auto-arrange?          // Do we auto-arrange?
1641          if (m_pOptions && m_pOptions->bAutoArrange)          channelsArrangeAuto();
                 channelsArrange();  
1642    
1643          // Make that an overall update.          // Make that an overall update.
1644          m_iDirtyCount++;          m_iDirtyCount++;
# Line 1346  void MainForm::editAddChannel (void) Line 1649  void MainForm::editAddChannel (void)
1649  // Remove current sampler channel.  // Remove current sampler channel.
1650  void MainForm::editRemoveChannel (void)  void MainForm::editRemoveChannel (void)
1651  {  {
1652          if (m_pClient == NULL)          ++m_iDirtySetup;
1653            removeChannelStrip();
1654            --m_iDirtySetup;
1655    }
1656    
1657    void MainForm::removeChannelStrip (void)
1658    {
1659            if (m_pClient == nullptr)
1660                  return;                  return;
1661    
1662          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1663          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
1664                  return;                  return;
1665    
1666          Channel *pChannel = pChannelStrip->channel();          Channel *pChannel = pChannelStrip->channel();
1667          if (pChannel == NULL)          if (pChannel == nullptr)
1668                  return;                  return;
1669    
1670          // Prompt user if he/she's sure about this...          // Prompt user if he/she's sure about this...
1671          if (m_pOptions && m_pOptions->bConfirmRemove) {          if (m_pOptions && m_pOptions->bConfirmRemove) {
1672                  if (QMessageBox::warning(this,                  const QString& sTitle = tr("Warning");
1673                          QSAMPLER_TITLE ": " + tr("Warning"),                  const QString& sText = tr(
1674                          tr("About to remove channel:\n\n"                          "About to remove channel:\n\n"
1675                          "%1\n\n"                          "%1\n\n"
1676                          "Are you sure?")                          "Are you sure?")
1677                          .arg(pChannelStrip->windowTitle()),                          .arg(pChannelStrip->windowTitle());
1678                          tr("OK"), tr("Cancel")) > 0)          #if 0
1679                    if (QMessageBox::warning(this, sTitle, sText,
1680                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1681                            return;
1682            #else
1683                    QMessageBox mbox(this);
1684                    mbox.setIcon(QMessageBox::Warning);
1685                    mbox.setWindowTitle(sTitle);
1686                    mbox.setText(sText);
1687                    mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1688                    QCheckBox cbox(tr("Don't ask this again"));
1689                    cbox.setChecked(false);
1690                    cbox.blockSignals(true);
1691                    mbox.addButton(&cbox, QMessageBox::ActionRole);
1692                    if (mbox.exec() == QMessageBox::Cancel)
1693                          return;                          return;
1694                    if (cbox.isChecked())
1695                            m_pOptions->bConfirmRemove = false;
1696            #endif
1697          }          }
1698    
1699          // Remove the existing sampler channel.          // Remove the existing sampler channel.
# Line 1374  void MainForm::editRemoveChannel (void) Line 1701  void MainForm::editRemoveChannel (void)
1701                  return;                  return;
1702    
1703          // Just delete the channel strip.          // Just delete the channel strip.
1704          delete pChannelStrip;          destroyChannelStrip(pChannelStrip);
   
         // Do we auto-arrange?  
         if (m_pOptions && m_pOptions->bAutoArrange)  
                 channelsArrange();  
1705    
1706          // We'll be dirty, for sure...          // We'll be dirty, for sure...
1707          m_iDirtyCount++;          m_iDirtyCount++;
# Line 1389  void MainForm::editRemoveChannel (void) Line 1712  void MainForm::editRemoveChannel (void)
1712  // Setup current sampler channel.  // Setup current sampler channel.
1713  void MainForm::editSetupChannel (void)  void MainForm::editSetupChannel (void)
1714  {  {
1715          if (m_pClient == NULL)          if (m_pClient == nullptr)
1716                  return;                  return;
1717    
1718          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1719          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
1720                  return;                  return;
1721    
1722          // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
# Line 1404  void MainForm::editSetupChannel (void) Line 1727  void MainForm::editSetupChannel (void)
1727  // Edit current sampler channel.  // Edit current sampler channel.
1728  void MainForm::editEditChannel (void)  void MainForm::editEditChannel (void)
1729  {  {
1730          if (m_pClient == NULL)          if (m_pClient == nullptr)
1731                  return;                  return;
1732    
1733          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1734          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
1735                  return;                  return;
1736    
1737          // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
# Line 1419  void MainForm::editEditChannel (void) Line 1742  void MainForm::editEditChannel (void)
1742  // Reset current sampler channel.  // Reset current sampler channel.
1743  void MainForm::editResetChannel (void)  void MainForm::editResetChannel (void)
1744  {  {
1745          if (m_pClient == NULL)          if (m_pClient == nullptr)
1746                  return;                  return;
1747    
1748          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1749          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
1750                  return;                  return;
1751    
1752          // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
# Line 1434  void MainForm::editResetChannel (void) Line 1757  void MainForm::editResetChannel (void)
1757  // Reset all sampler channels.  // Reset all sampler channels.
1758  void MainForm::editResetAllChannels (void)  void MainForm::editResetAllChannels (void)
1759  {  {
1760          if (m_pClient == NULL)          if (m_pClient == nullptr)
1761                  return;                  return;
1762    
1763          // Invoque the channel strip procedure,          // Invoque the channel strip procedure,
1764          // for all channels out there...          // for all channels out there...
1765          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
1766          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
1767          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  = m_pWorkspace->subWindowList();
1768                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
1769                    ChannelStrip *pChannelStrip
1770                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
1771                  if (pChannelStrip)                  if (pChannelStrip)
1772                          pChannelStrip->channelReset();                          pChannelStrip->channelReset();
1773          }          }
# Line 1451  void MainForm::editResetAllChannels (voi Line 1776  void MainForm::editResetAllChannels (voi
1776    
1777    
1778  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1779  // qsamplerMainForm -- View Action slots.  // QSampler::MainForm -- View Action slots.
1780    
1781  // Show/hide the main program window menubar.  // Show/hide the main program window menubar.
1782  void MainForm::viewMenubar ( bool bOn )  void MainForm::viewMenubar ( bool bOn )
# Line 1501  void MainForm::viewMessages ( bool bOn ) Line 1826  void MainForm::viewMessages ( bool bOn )
1826  // Show/hide the MIDI instrument list-view form.  // Show/hide the MIDI instrument list-view form.
1827  void MainForm::viewInstruments (void)  void MainForm::viewInstruments (void)
1828  {  {
1829          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
1830                  return;                  return;
1831    
1832          if (m_pInstrumentListForm) {          if (m_pInstrumentListForm) {
# Line 1520  void MainForm::viewInstruments (void) Line 1845  void MainForm::viewInstruments (void)
1845  // Show/hide the device configurator form.  // Show/hide the device configurator form.
1846  void MainForm::viewDevices (void)  void MainForm::viewDevices (void)
1847  {  {
1848          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
1849                  return;                  return;
1850    
1851          if (m_pDeviceForm) {          if (m_pDeviceForm) {
# Line 1539  void MainForm::viewDevices (void) Line 1864  void MainForm::viewDevices (void)
1864  // Show options dialog.  // Show options dialog.
1865  void MainForm::viewOptions (void)  void MainForm::viewOptions (void)
1866  {  {
1867          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
1868                  return;                  return;
1869    
1870          OptionsForm* pOptionsForm = new OptionsForm(this);          OptionsForm* pOptionsForm = new OptionsForm(this);
1871          if (pOptionsForm) {          if (pOptionsForm) {
1872                  // Check out some initial nullities(tm)...                  // Check out some initial nullities(tm)...
1873                  ChannelStrip* pChannelStrip = activeChannelStrip();                  ChannelStrip *pChannelStrip = activeChannelStrip();
1874                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)
1875                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();
1876                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)
1877                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
1878                  // To track down deferred or immediate changes.                  // To track down deferred or immediate changes.
1879                  QString sOldServerHost      = m_pOptions->sServerHost;                  const QString sOldServerHost       = m_pOptions->sServerHost;
1880                  int     iOldServerPort      = m_pOptions->iServerPort;                  const int     iOldServerPort       = m_pOptions->iServerPort;
1881                  int     iOldServerTimeout   = m_pOptions->iServerTimeout;                  const int     iOldServerTimeout    = m_pOptions->iServerTimeout;
1882                  bool    bOldServerStart     = m_pOptions->bServerStart;                  const bool    bOldServerStart      = m_pOptions->bServerStart;
1883                  QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;                  const QString sOldServerCmdLine    = m_pOptions->sServerCmdLine;
1884                  QString sOldDisplayFont     = m_pOptions->sDisplayFont;                  const bool    bOldMessagesLog      = m_pOptions->bMessagesLog;
1885                  bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;                  const QString sOldMessagesLogPath  = m_pOptions->sMessagesLogPath;
1886                  int     iOldMaxVolume       = m_pOptions->iMaxVolume;                  const QString sOldDisplayFont      = m_pOptions->sDisplayFont;
1887                  QString sOldMessagesFont    = m_pOptions->sMessagesFont;                  const bool    bOldDisplayEffect    = m_pOptions->bDisplayEffect;
1888                  bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;                  const int     iOldMaxVolume        = m_pOptions->iMaxVolume;
1889                  bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;                  const QString sOldMessagesFont     = m_pOptions->sMessagesFont;
1890                  int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;                  const bool    bOldKeepOnTop        = m_pOptions->bKeepOnTop;
1891                  int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;                  const bool    bOldStdoutCapture    = m_pOptions->bStdoutCapture;
1892                  bool    bOldCompletePath    = m_pOptions->bCompletePath;                  const int     bOldMessagesLimit    = m_pOptions->bMessagesLimit;
1893                  bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;                  const int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;
1894                  int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;                  const bool    bOldCompletePath     = m_pOptions->bCompletePath;
1895                    const bool    bOldInstrumentNames  = m_pOptions->bInstrumentNames;
1896                    const int     iOldMaxRecentFiles   = m_pOptions->iMaxRecentFiles;
1897                    const int     iOldBaseFontSize     = m_pOptions->iBaseFontSize;
1898                    const QString sOldCustomStyleTheme = m_pOptions->sCustomStyleTheme;
1899                    const QString sOldCustomColorTheme = m_pOptions->sCustomColorTheme;
1900                  // Load the current setup settings.                  // Load the current setup settings.
1901                  pOptionsForm->setup(m_pOptions);                  pOptionsForm->setup(m_pOptions);
1902                  // Show the setup dialog...                  // Show the setup dialog...
1903                  if (pOptionsForm->exec()) {                  if (pOptionsForm->exec()) {
1904                          // Warn if something will be only effective on next run.                          // Warn if something will be only effective on next run.
1905                            int iNeedRestart = 0;
1906                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1907                                  (!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"));  
1908                                  updateMessagesCapture();                                  updateMessagesCapture();
1909                                    ++iNeedRestart;
1910                            }
1911                            if (( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||
1912                                    (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)     ||
1913                                    (iOldBaseFontSize   !=  m_pOptions->iBaseFontSize)) {
1914                                    ++iNeedRestart;
1915                            }
1916                            // Check whether restart is needed or whether
1917                            // custom options maybe set up immediately...
1918                            if (m_pOptions->sCustomStyleTheme != sOldCustomStyleTheme) {
1919                                    if (m_pOptions->sCustomStyleTheme.isEmpty()) {
1920                                            ++iNeedRestart;
1921                                    } else {
1922                                            QApplication::setStyle(
1923                                                    QStyleFactory::create(m_pOptions->sCustomStyleTheme));
1924                                    }
1925                            }
1926                            if (m_pOptions->sCustomColorTheme != sOldCustomColorTheme) {
1927                                    if (m_pOptions->sCustomColorTheme.isEmpty()) {
1928                                            ++iNeedRestart;
1929                                    } else {
1930                                            QPalette pal;
1931                                            if (PaletteForm::namedPalette(
1932                                                            &m_pOptions->settings(), m_pOptions->sCustomColorTheme, pal))
1933                                                    QApplication::setPalette(pal);
1934                                    }
1935                          }                          }
1936                          // Check wheather something immediate has changed.                          // Check wheather something immediate has changed.
1937                            if (( bOldMessagesLog && !m_pOptions->bMessagesLog) ||
1938                                    (!bOldMessagesLog &&  m_pOptions->bMessagesLog) ||
1939                                    (sOldMessagesLogPath != m_pOptions->sMessagesLogPath))
1940                                    m_pMessages->setLogging(
1941                                            m_pOptions->bMessagesLog, m_pOptions->sMessagesLogPath);
1942                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||
1943                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||
1944                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
# Line 1603  void MainForm::viewOptions (void) Line 1959  void MainForm::viewOptions (void)
1959                                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||                                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||
1960                                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))                                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))
1961                                  updateMessagesLimit();                                  updateMessagesLimit();
1962                            // Show restart needed message...
1963                            if (iNeedRestart > 0) {
1964                                    QMessageBox::information(this,
1965                                            tr("Information"),
1966                                            tr("Some settings may be only effective\n"
1967                                            "next time you start this program."));
1968                            }
1969                          // And now the main thing, whether we'll do client/server recycling?                          // And now the main thing, whether we'll do client/server recycling?
1970                          if ((sOldServerHost != m_pOptions->sServerHost) ||                          if ((sOldServerHost != m_pOptions->sServerHost) ||
1971                                  (iOldServerPort != m_pOptions->iServerPort) ||                                  (iOldServerPort != m_pOptions->iServerPort) ||
# Line 1623  void MainForm::viewOptions (void) Line 1986  void MainForm::viewOptions (void)
1986    
1987    
1988  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1989  // qsamplerMainForm -- Channels action slots.  // QSampler::MainForm -- Channels action slots.
1990    
1991  // Arrange channel strips.  // Arrange channel strips.
1992  void MainForm::channelsArrange (void)  void MainForm::channelsArrange (void)
1993  {  {
1994          // Full width vertical tiling          // Full width vertical tiling
1995          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
1996                    = m_pWorkspace->subWindowList();
1997          if (wlist.isEmpty())          if (wlist.isEmpty())
1998                  return;                  return;
1999    
2000          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2001          int y = 0;          int y = 0;
2002          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2003                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  pMdiSubWindow->adjustSize();
2004          /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {                  const QRect& frameRect
2005                          // Prevent flicker...                          = pMdiSubWindow->frameGeometry();
2006                          pChannelStrip->hide();                  int w = m_pWorkspace->width();
2007                          pChannelStrip->showNormal();                  if (w < frameRect.width())
2008                  }   */                          w = frameRect.width();
2009                  pChannelStrip->adjustSize();                  const int h = frameRect.height();
2010                  int iWidth  = m_pWorkspace->width();                  pMdiSubWindow->setGeometry(0, y, w, h);
2011                  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;  
2012          }          }
2013          m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2014    
# Line 1661  void MainForm::channelsArrange (void) Line 2019  void MainForm::channelsArrange (void)
2019  // Auto-arrange channel strips.  // Auto-arrange channel strips.
2020  void MainForm::channelsAutoArrange ( bool bOn )  void MainForm::channelsAutoArrange ( bool bOn )
2021  {  {
2022          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2023                  return;                  return;
2024    
2025          // Toggle the auto-arrange flag.          // Toggle the auto-arrange flag.
2026          m_pOptions->bAutoArrange = bOn;          m_pOptions->bAutoArrange = bOn;
2027    
2028          // If on, update whole workspace...          // If on, update whole workspace...
2029          if (m_pOptions->bAutoArrange)          channelsArrangeAuto();
2030    }
2031    
2032    
2033    void MainForm::channelsArrangeAuto (void)
2034    {
2035            if (m_pOptions && m_pOptions->bAutoArrange)
2036                  channelsArrange();                  channelsArrange();
2037  }  }
2038    
2039    
2040  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2041  // qsamplerMainForm -- Help Action slots.  // QSampler::MainForm -- Help Action slots.
2042    
2043  // Show information about the Qt toolkit.  // Show information about the Qt toolkit.
2044  void MainForm::helpAboutQt (void)  void MainForm::helpAboutQt (void)
# Line 1686  void MainForm::helpAboutQt (void) Line 2050  void MainForm::helpAboutQt (void)
2050  // Show information about application program.  // Show information about application program.
2051  void MainForm::helpAbout (void)  void MainForm::helpAbout (void)
2052  {  {
2053          // 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";  
2054  #ifdef CONFIG_DEBUG  #ifdef CONFIG_DEBUG
2055          sText += "<small><font color=\"red\">";          list << tr("Debugging option enabled.");
         sText += tr("Debugging option enabled.");  
         sText += "</font></small><br />";  
2056  #endif  #endif
2057  #ifndef CONFIG_LIBGIG  #ifndef CONFIG_LIBGIG
2058          sText += "<small><font color=\"red\">";          list << tr("GIG (libgig) file support disabled.");
         sText += tr("GIG (libgig) file support disabled.");  
         sText += "</font></small><br />";  
2059  #endif  #endif
2060  #ifndef CONFIG_INSTRUMENT_NAME  #ifndef CONFIG_INSTRUMENT_NAME
2061          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 />";  
2062  #endif  #endif
2063  #ifndef CONFIG_MUTE_SOLO  #ifndef CONFIG_MUTE_SOLO
2064          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 />";  
2065  #endif  #endif
2066  #ifndef CONFIG_AUDIO_ROUTING  #ifndef CONFIG_AUDIO_ROUTING
2067          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 />";  
2068  #endif  #endif
2069  #ifndef CONFIG_FXSEND  #ifndef CONFIG_FXSEND
2070          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 />";  
2071  #endif  #endif
2072  #ifndef CONFIG_VOLUME  #ifndef CONFIG_VOLUME
2073          sText += "<small><font color=\"red\">";          list << tr("Global volume support disabled.");
         sText += tr("Global volume support disabled.");  
         sText += "</font></small><br />";  
2074  #endif  #endif
2075  #ifndef CONFIG_MIDI_INSTRUMENT  #ifndef CONFIG_MIDI_INSTRUMENT
2076          sText += "<small><font color=\"red\">";          list << tr("MIDI instrument mapping support disabled.");
         sText += tr("MIDI instrument mapping support disabled.");  
         sText += "</font></small><br />";  
2077  #endif  #endif
2078  #ifndef CONFIG_EDIT_INSTRUMENT  #ifndef CONFIG_EDIT_INSTRUMENT
2079          sText += "<small><font color=\"red\">";          list << tr("Instrument editing support disabled.");
2080          sText += tr("Instrument editing support disabled.");  #endif
2081          sText += "</font></small><br />";  #ifndef CONFIG_EVENT_CHANNEL_MIDI
2082            list << tr("Channel MIDI event support disabled.");
2083    #endif
2084    #ifndef CONFIG_EVENT_DEVICE_MIDI
2085            list << tr("Device MIDI event support disabled.");
2086    #endif
2087    #ifndef CONFIG_MAX_VOICES
2088            list << tr("Runtime max. voices / disk streams support disabled.");
2089  #endif  #endif
2090    
2091            // Stuff the about box text...
2092            QString sText = "<p>\n";
2093            sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";
2094            sText += "<br />\n";
2095            sText += tr("Version") + ": <b>" CONFIG_BUILD_VERSION "</b><br />\n";
2096    //      sText += "<small>" + tr("Build") + ": " CONFIG_BUILD_DATE "</small><br />\n";
2097            if (!list.isEmpty()) {
2098                    sText += "<small><font color=\"red\">";
2099                    sText += list.join("<br />\n");
2100                    sText += "</font></small>";
2101            }
2102          sText += "<br />\n";          sText += "<br />\n";
2103          sText += tr("Using") + ": ";          sText += tr("Using") + ": ";
2104          sText += ::lscp_client_package();          sText += ::lscp_client_package();
# Line 1761  void MainForm::helpAbout (void) Line 2123  void MainForm::helpAbout (void)
2123          sText += "</small>";          sText += "</small>";
2124          sText += "</p>\n";          sText += "</p>\n";
2125    
2126          QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);          QMessageBox::about(this, tr("About"), sText);
2127  }  }
2128    
2129    
2130  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2131  // qsamplerMainForm -- Main window stabilization.  // QSampler::MainForm -- Main window stabilization.
2132    
2133  void MainForm::stabilizeForm (void)  void MainForm::stabilizeForm (void)
2134  {  {
# Line 1774  void MainForm::stabilizeForm (void) Line 2136  void MainForm::stabilizeForm (void)
2136          QString sSessionName = sessionName(m_sFilename);          QString sSessionName = sessionName(m_sFilename);
2137          if (m_iDirtyCount > 0)          if (m_iDirtyCount > 0)
2138                  sSessionName += " *";                  sSessionName += " *";
2139          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));          setWindowTitle(sSessionName);
2140    
2141          // Update the main menu state...          // Update the main menu state...
2142          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
2143          bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);          const QList<QMdiSubWindow *>& wlist = m_pWorkspace->subWindowList();
2144          bool bHasChannel = (bHasClient && pChannelStrip != NULL);          const bool bHasClient = (m_pOptions != nullptr && m_pClient != nullptr);
2145            const bool bHasChannel = (bHasClient && pChannelStrip != nullptr);
2146            const bool bHasChannels = (bHasClient && wlist.count() > 0);
2147          m_ui.fileNewAction->setEnabled(bHasClient);          m_ui.fileNewAction->setEnabled(bHasClient);
2148          m_ui.fileOpenAction->setEnabled(bHasClient);          m_ui.fileOpenAction->setEnabled(bHasClient);
2149          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
2150          m_ui.fileSaveAsAction->setEnabled(bHasClient);          m_ui.fileSaveAsAction->setEnabled(bHasClient);
2151          m_ui.fileResetAction->setEnabled(bHasClient);          m_ui.fileResetAction->setEnabled(bHasClient);
2152          m_ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);          m_ui.fileRestartAction->setEnabled(bHasClient || m_pServer == nullptr);
2153          m_ui.editAddChannelAction->setEnabled(bHasClient);          m_ui.editAddChannelAction->setEnabled(bHasClient);
2154          m_ui.editRemoveChannelAction->setEnabled(bHasChannel);          m_ui.editRemoveChannelAction->setEnabled(bHasChannel);
2155          m_ui.editSetupChannelAction->setEnabled(bHasChannel);          m_ui.editSetupChannelAction->setEnabled(bHasChannel);
# Line 1795  void MainForm::stabilizeForm (void) Line 2159  void MainForm::stabilizeForm (void)
2159          m_ui.editEditChannelAction->setEnabled(false);          m_ui.editEditChannelAction->setEnabled(false);
2160  #endif  #endif
2161          m_ui.editResetChannelAction->setEnabled(bHasChannel);          m_ui.editResetChannelAction->setEnabled(bHasChannel);
2162          m_ui.editResetAllChannelsAction->setEnabled(bHasChannel);          m_ui.editResetAllChannelsAction->setEnabled(bHasChannels);
2163          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());
2164  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
2165          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm
# Line 1807  void MainForm::stabilizeForm (void) Line 2171  void MainForm::stabilizeForm (void)
2171          m_ui.viewDevicesAction->setChecked(m_pDeviceForm          m_ui.viewDevicesAction->setChecked(m_pDeviceForm
2172                  && m_pDeviceForm->isVisible());                  && m_pDeviceForm->isVisible());
2173          m_ui.viewDevicesAction->setEnabled(bHasClient);          m_ui.viewDevicesAction->setEnabled(bHasClient);
2174          m_ui.channelsArrangeAction->setEnabled(bHasChannel);          m_ui.viewMidiDeviceStatusMenu->setEnabled(
2175                    DeviceStatusForm::getInstances().size() > 0);
2176            m_ui.channelsArrangeAction->setEnabled(bHasChannels);
2177    
2178  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2179          // Toolbar widgets are also affected...          // Toolbar widgets are also affected...
# Line 1857  void MainForm::volumeChanged ( int iVolu Line 2223  void MainForm::volumeChanged ( int iVolu
2223                  m_pVolumeSpinBox->setValue(iVolume);                  m_pVolumeSpinBox->setValue(iVolume);
2224    
2225          // Do it as commanded...          // Do it as commanded...
2226          float fVolume = 0.01f * float(iVolume);          const float fVolume = 0.01f * float(iVolume);
2227          if (::lscp_set_volume(m_pClient, fVolume) == LSCP_OK)          if (::lscp_set_volume(m_pClient, fVolume) == LSCP_OK)
2228                  appendMessages(QObject::tr("Volume: %1.").arg(fVolume));                  appendMessages(QObject::tr("Volume: %1.").arg(fVolume));
2229          else          else
# Line 1873  void MainForm::volumeChanged ( int iVolu Line 2239  void MainForm::volumeChanged ( int iVolu
2239    
2240    
2241  // Channel change receiver slot.  // Channel change receiver slot.
2242  void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)  void MainForm::channelStripChanged ( ChannelStrip *pChannelStrip )
2243  {  {
2244          // Add this strip to the changed list...          // Add this strip to the changed list...
2245          if (!m_changedStrips.contains(pChannelStrip)) {          if (!m_changedStrips.contains(pChannelStrip)) {
# Line 1892  void MainForm::channelStripChanged(Chann Line 2258  void MainForm::channelStripChanged(Chann
2258  void MainForm::updateSession (void)  void MainForm::updateSession (void)
2259  {  {
2260  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2261          int iVolume = ::lroundf(100.0f * ::lscp_get_volume(m_pClient));          const int iVolume = ::lroundf(100.0f * ::lscp_get_volume(m_pClient));
2262          m_iVolumeChanging++;          m_iVolumeChanging++;
2263          m_pVolumeSlider->setValue(iVolume);          m_pVolumeSlider->setValue(iVolume);
2264          m_pVolumeSpinBox->setValue(iVolume);          m_pVolumeSpinBox->setValue(iVolume);
# Line 1900  void MainForm::updateSession (void) Line 2266  void MainForm::updateSession (void)
2266  #endif  #endif
2267  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
2268          // FIXME: Make some room for default instrument maps...          // FIXME: Make some room for default instrument maps...
2269          int iMaps = ::lscp_get_midi_instrument_maps(m_pClient);          const int iMaps = ::lscp_get_midi_instrument_maps(m_pClient);
2270          if (iMaps < 0)          if (iMaps < 0)
2271                  appendMessagesClient("lscp_get_midi_instrument_maps");                  appendMessagesClient("lscp_get_midi_instrument_maps");
2272          else if (iMaps < 1) {          else if (iMaps < 1) {
# Line 1911  void MainForm::updateSession (void) Line 2277  void MainForm::updateSession (void)
2277          }          }
2278  #endif  #endif
2279    
2280            updateAllChannelStrips(false);
2281    
2282            // Do we auto-arrange?
2283            channelsArrangeAuto();
2284    
2285            // Remember to refresh devices and instruments...
2286            if (m_pInstrumentListForm)
2287                    m_pInstrumentListForm->refreshInstruments();
2288            if (m_pDeviceForm)
2289                    m_pDeviceForm->refreshDevices();
2290    }
2291    
2292    
2293    void MainForm::updateAllChannelStrips ( bool bRemoveDeadStrips )
2294    {
2295            // Skip if setting up a new channel strip...
2296            if (m_iDirtySetup > 0)
2297                    return;
2298    
2299          // Retrieve the current channel list.          // Retrieve the current channel list.
2300          int *piChannelIDs = ::lscp_list_channels(m_pClient);          int *piChannelIDs = ::lscp_list_channels(m_pClient);
2301          if (piChannelIDs == NULL) {          if (piChannelIDs == nullptr) {
2302                  if (::lscp_client_get_errno(m_pClient)) {                  if (::lscp_client_get_errno(m_pClient)) {
2303                          appendMessagesClient("lscp_list_channels");                          appendMessagesClient("lscp_list_channels");
2304                          appendMessagesError(                          appendMessagesError(
# Line 1922  void MainForm::updateSession (void) Line 2307  void MainForm::updateSession (void)
2307          } else {          } else {
2308                  // Try to (re)create each channel.                  // Try to (re)create each channel.
2309                  m_pWorkspace->setUpdatesEnabled(false);                  m_pWorkspace->setUpdatesEnabled(false);
2310                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; ++iChannel) {
2311                          // Check if theres already a channel strip for this one...                          // Check if theres already a channel strip for this one...
2312                          if (!channelStrip(piChannelIDs[iChannel]))                          if (!channelStrip(piChannelIDs[iChannel]))
2313                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));
2314                  }                  }
2315                    // Do we auto-arrange?
2316                    channelsArrangeAuto();
2317                    // remove dead channel strips
2318                    if (bRemoveDeadStrips) {
2319                            const QList<QMdiSubWindow *>& wlist
2320                                    = m_pWorkspace->subWindowList();
2321                            foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2322                                    ChannelStrip *pChannelStrip
2323                                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2324                                    if (pChannelStrip) {
2325                                            bool bExists = false;
2326                                            for (int iChannel = 0; piChannelIDs[iChannel] >= 0; ++iChannel) {
2327                                                    Channel *pChannel = pChannelStrip->channel();
2328                                                    if (pChannel == nullptr)
2329                                                            break;
2330                                                    if (piChannelIDs[iChannel] == pChannel->channelID()) {
2331                                                            // strip exists, don't touch it
2332                                                            bExists = true;
2333                                                            break;
2334                                                    }
2335                                            }
2336                                            if (!bExists)
2337                                                    destroyChannelStrip(pChannelStrip);
2338                                    }
2339                            }
2340                    }
2341                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
2342          }          }
2343    
2344          // 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();  
2345  }  }
2346    
2347    
2348  // Update the recent files list and menu.  // Update the recent files list and menu.
2349  void MainForm::updateRecentFiles ( const QString& sFilename )  void MainForm::updateRecentFiles ( const QString& sFilename )
2350  {  {
2351          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2352                  return;                  return;
2353    
2354          // Remove from list if already there (avoid duplicates)          // Remove from list if already there (avoid duplicates)
2355          int iIndex = m_pOptions->recentFiles.indexOf(sFilename);          const int iIndex = m_pOptions->recentFiles.indexOf(sFilename);
2356          if (iIndex >= 0)          if (iIndex >= 0)
2357                  m_pOptions->recentFiles.removeAt(iIndex);                  m_pOptions->recentFiles.removeAt(iIndex);
2358          // Put it to front...          // Put it to front...
# Line 1960  void MainForm::updateRecentFiles ( const Line 2363  void MainForm::updateRecentFiles ( const
2363  // Update the recent files list and menu.  // Update the recent files list and menu.
2364  void MainForm::updateRecentFilesMenu (void)  void MainForm::updateRecentFilesMenu (void)
2365  {  {
2366          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2367                  return;                  return;
2368    
2369          // Time to keep the list under limits.          // Time to keep the list under limits.
# Line 1988  void MainForm::updateRecentFilesMenu (vo Line 2391  void MainForm::updateRecentFilesMenu (vo
2391  void MainForm::updateInstrumentNames (void)  void MainForm::updateInstrumentNames (void)
2392  {  {
2393          // Full channel list update...          // Full channel list update...
2394          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2395                    = m_pWorkspace->subWindowList();
2396          if (wlist.isEmpty())          if (wlist.isEmpty())
2397                  return;                  return;
2398    
2399          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2400          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2401                  ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);                  ChannelStrip *pChannelStrip
2402                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2403                  if (pChannelStrip)                  if (pChannelStrip)
2404                          pChannelStrip->updateInstrumentName(true);                          pChannelStrip->updateInstrumentName(true);
2405          }          }
# Line 2005  void MainForm::updateInstrumentNames (vo Line 2410  void MainForm::updateInstrumentNames (vo
2410  // Force update of the channels display font.  // Force update of the channels display font.
2411  void MainForm::updateDisplayFont (void)  void MainForm::updateDisplayFont (void)
2412  {  {
2413          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2414                  return;                  return;
2415    
2416          // Check if display font is legal.          // Check if display font is legal.
2417          if (m_pOptions->sDisplayFont.isEmpty())          if (m_pOptions->sDisplayFont.isEmpty())
2418                  return;                  return;
2419    
2420          // Realize it.          // Realize it.
2421          QFont font;          QFont font;
2422          if (!font.fromString(m_pOptions->sDisplayFont))          if (!font.fromString(m_pOptions->sDisplayFont))
2423                  return;                  return;
2424    
2425          // Full channel list update...          // Full channel list update...
2426          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2427                    = m_pWorkspace->subWindowList();
2428          if (wlist.isEmpty())          if (wlist.isEmpty())
2429                  return;                  return;
2430    
2431          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2432          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2433                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip *pChannelStrip
2434                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2435                  if (pChannelStrip)                  if (pChannelStrip)
2436                          pChannelStrip->setDisplayFont(font);                          pChannelStrip->setDisplayFont(font);
2437          }          }
# Line 2035  void MainForm::updateDisplayFont (void) Line 2443  void MainForm::updateDisplayFont (void)
2443  void MainForm::updateDisplayEffect (void)  void MainForm::updateDisplayEffect (void)
2444  {  {
2445          // Full channel list update...          // Full channel list update...
2446          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2447                    = m_pWorkspace->subWindowList();
2448          if (wlist.isEmpty())          if (wlist.isEmpty())
2449                  return;                  return;
2450    
2451          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2452          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2453                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip *pChannelStrip
2454                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2455                  if (pChannelStrip)                  if (pChannelStrip)
2456                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2457          }          }
# Line 2052  void MainForm::updateDisplayEffect (void Line 2462  void MainForm::updateDisplayEffect (void
2462  // Force update of the channels maximum volume setting.  // Force update of the channels maximum volume setting.
2463  void MainForm::updateMaxVolume (void)  void MainForm::updateMaxVolume (void)
2464  {  {
2465          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2466                  return;                  return;
2467    
2468  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
# Line 2063  void MainForm::updateMaxVolume (void) Line 2473  void MainForm::updateMaxVolume (void)
2473  #endif  #endif
2474    
2475          // Full channel list update...          // Full channel list update...
2476          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2477                    = m_pWorkspace->subWindowList();
2478          if (wlist.isEmpty())          if (wlist.isEmpty())
2479                  return;                  return;
2480    
2481          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2482          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2483                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip *pChannelStrip
2484                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2485                  if (pChannelStrip)                  if (pChannelStrip)
2486                          pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                          pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2487          }          }
# Line 2078  void MainForm::updateMaxVolume (void) Line 2490  void MainForm::updateMaxVolume (void)
2490    
2491    
2492  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2493  // qsamplerMainForm -- Messages window form handlers.  // QSampler::MainForm -- Messages window form handlers.
2494    
2495  // Messages output methods.  // Messages output methods.
2496  void MainForm::appendMessages( const QString& s )  void MainForm::appendMessages ( const QString& s )
2497  {  {
2498          if (m_pMessages)          if (m_pMessages)
2499                  m_pMessages->appendMessages(s);                  m_pMessages->appendMessages(s);
# Line 2089  void MainForm::appendMessages( const QSt Line 2501  void MainForm::appendMessages( const QSt
2501          statusBar()->showMessage(s, 3000);          statusBar()->showMessage(s, 3000);
2502  }  }
2503    
2504  void MainForm::appendMessagesColor( const QString& s, const QString& c )  void MainForm::appendMessagesColor ( const QString& s, const QColor& rgb )
2505  {  {
2506          if (m_pMessages)          if (m_pMessages)
2507                  m_pMessages->appendMessagesColor(s, c);                  m_pMessages->appendMessagesColor(s, rgb);
2508    
2509          statusBar()->showMessage(s, 3000);          statusBar()->showMessage(s, 3000);
2510  }  }
2511    
2512  void MainForm::appendMessagesText( const QString& s )  void MainForm::appendMessagesText ( const QString& s )
2513  {  {
2514          if (m_pMessages)          if (m_pMessages)
2515                  m_pMessages->appendMessagesText(s);                  m_pMessages->appendMessagesText(s);
2516  }  }
2517    
2518  void MainForm::appendMessagesError( const QString& s )  void MainForm::appendMessagesError ( const QString& s )
2519  {  {
2520          if (m_pMessages)          if (m_pMessages)
2521                  m_pMessages->show();                  m_pMessages->show();
2522    
2523          appendMessagesColor(s.simplified(), "#ff0000");          appendMessagesColor(s.simplified(), Qt::red);
2524    
2525          // Make it look responsive...:)          // Make it look responsive...:)
2526          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2527    
2528          QMessageBox::critical(this,          if (m_pOptions && m_pOptions->bConfirmError) {
2529                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));                  const QString& sTitle = tr("Error");
2530            #if 0
2531                    QMessageBox::critical(this, sTitle, sText, QMessageBox::Cancel);
2532            #else
2533                    QMessageBox mbox(this);
2534                    mbox.setIcon(QMessageBox::Critical);
2535                    mbox.setWindowTitle(sTitle);
2536                    mbox.setText(s);
2537                    mbox.setStandardButtons(QMessageBox::Cancel);
2538                    QCheckBox cbox(tr("Don't show this again"));
2539                    cbox.setChecked(false);
2540                    cbox.blockSignals(true);
2541                    mbox.addButton(&cbox, QMessageBox::ActionRole);
2542                    if (mbox.exec() && cbox.isChecked())
2543                            m_pOptions->bConfirmError = false;
2544            #endif
2545            }
2546  }  }
2547    
2548    
2549  // This is a special message format, just for client results.  // This is a special message format, just for client results.
2550  void MainForm::appendMessagesClient( const QString& s )  void MainForm::appendMessagesClient( const QString& s )
2551  {  {
2552          if (m_pClient == NULL)          if (m_pClient == nullptr)
2553                  return;                  return;
2554    
2555          appendMessagesColor(s + QString(": %1 (errno=%2)")          appendMessagesColor(s + QString(": %1 (errno=%2)")
# Line 2136  void MainForm::appendMessagesClient( con Line 2564  void MainForm::appendMessagesClient( con
2564  // Force update of the messages font.  // Force update of the messages font.
2565  void MainForm::updateMessagesFont (void)  void MainForm::updateMessagesFont (void)
2566  {  {
2567          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2568                  return;                  return;
2569    
2570          if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {          if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {
# Line 2150  void MainForm::updateMessagesFont (void) Line 2578  void MainForm::updateMessagesFont (void)
2578  // Update messages window line limit.  // Update messages window line limit.
2579  void MainForm::updateMessagesLimit (void)  void MainForm::updateMessagesLimit (void)
2580  {  {
2581          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2582                  return;                  return;
2583    
2584          if (m_pMessages) {          if (m_pMessages) {
# Line 2165  void MainForm::updateMessagesLimit (void Line 2593  void MainForm::updateMessagesLimit (void
2593  // Enablement of the messages capture feature.  // Enablement of the messages capture feature.
2594  void MainForm::updateMessagesCapture (void)  void MainForm::updateMessagesCapture (void)
2595  {  {
2596          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2597                  return;                  return;
2598    
2599          if (m_pMessages)          if (m_pMessages)
# Line 2174  void MainForm::updateMessagesCapture (vo Line 2602  void MainForm::updateMessagesCapture (vo
2602    
2603    
2604  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2605  // qsamplerMainForm -- MDI channel strip management.  // QSampler::MainForm -- MDI channel strip management.
2606    
2607  // The channel strip creation executive.  // The channel strip creation executive.
2608  ChannelStrip* MainForm::createChannelStrip ( Channel *pChannel )  ChannelStrip *MainForm::createChannelStrip ( Channel *pChannel )
2609  {  {
2610          if (m_pClient == NULL || pChannel == NULL)          if (m_pClient == nullptr || pChannel == nullptr)
2611                  return NULL;                  return nullptr;
2612    
2613          // Add a new channel itema...          // Add a new channel itema...
2614          ChannelStrip *pChannelStrip = new ChannelStrip();          ChannelStrip *pChannelStrip = new ChannelStrip();
2615          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
2616                  return NULL;                  return nullptr;
2617    
2618          // Set some initial channel strip options...          // Set some initial channel strip options...
2619          if (m_pOptions) {          if (m_pOptions) {
# Line 2193  ChannelStrip* MainForm::createChannelStr Line 2621  ChannelStrip* MainForm::createChannelStr
2621                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2622                  // We'll need a display font.                  // We'll need a display font.
2623                  QFont font;                  QFont font;
2624                  if (font.fromString(m_pOptions->sDisplayFont))                  if (!m_pOptions->sDisplayFont.isEmpty() &&
2625                            font.fromString(m_pOptions->sDisplayFont))
2626                          pChannelStrip->setDisplayFont(font);                          pChannelStrip->setDisplayFont(font);
2627                  // Maximum allowed volume setting.                  // Maximum allowed volume setting.
2628                  pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                  pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2629          }          }
2630    
2631          // Add it to workspace...          // Add it to workspace...
2632          m_pWorkspace->addWindow(pChannelStrip, Qt::FramelessWindowHint);          QMdiSubWindow *pMdiSubWindow
2633                    = m_pWorkspace->addSubWindow(pChannelStrip,
2634                            Qt::SubWindow | Qt::FramelessWindowHint);
2635            pMdiSubWindow->setAttribute(Qt::WA_DeleteOnClose);
2636    
2637          // Actual channel strip setup...          // Actual channel strip setup...
2638          pChannelStrip->setup(pChannel);          pChannelStrip->setup(pChannel);
2639    
2640          QObject::connect(pChannelStrip,          QObject::connect(pChannelStrip,
2641                  SIGNAL(channelChanged(ChannelStrip*)),                  SIGNAL(channelChanged(ChannelStrip *)),
2642                  SLOT(channelStripChanged(ChannelStrip*)));                  SLOT(channelStripChanged(ChannelStrip *)));
2643    
2644          // Now we show up us to the world.          // Now we show up us to the world.
2645          pChannelStrip->show();          pChannelStrip->show();
# Line 2220  ChannelStrip* MainForm::createChannelStr Line 2652  ChannelStrip* MainForm::createChannelStr
2652  }  }
2653    
2654    
2655    void MainForm::destroyChannelStrip ( ChannelStrip *pChannelStrip )
2656    {
2657            QMdiSubWindow *pMdiSubWindow
2658                    = static_cast<QMdiSubWindow *> (pChannelStrip->parentWidget());
2659            if (pMdiSubWindow == nullptr)
2660                    return;
2661    
2662            // Just delete the channel strip.
2663            delete pChannelStrip;
2664            delete pMdiSubWindow;
2665    
2666            // Do we auto-arrange?
2667            channelsArrangeAuto();
2668    }
2669    
2670    
2671  // Retrieve the active channel strip.  // Retrieve the active channel strip.
2672  ChannelStrip* MainForm::activeChannelStrip (void)  ChannelStrip *MainForm::activeChannelStrip (void)
2673  {  {
2674          return static_cast<ChannelStrip *> (m_pWorkspace->activeWindow());          QMdiSubWindow *pMdiSubWindow = m_pWorkspace->activeSubWindow();
2675            if (pMdiSubWindow)
2676                    return static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2677            else
2678                    return nullptr;
2679  }  }
2680    
2681    
2682  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
2683  ChannelStrip* MainForm::channelStripAt ( int iChannel )  ChannelStrip *MainForm::channelStripAt ( int iStrip )
2684  {  {
2685          QWidgetList wlist = m_pWorkspace->windowList();          if (!m_pWorkspace) return nullptr;
2686    
2687            const QList<QMdiSubWindow *>& wlist
2688                    = m_pWorkspace->subWindowList();
2689          if (wlist.isEmpty())          if (wlist.isEmpty())
2690                  return NULL;                  return nullptr;
2691    
2692          return static_cast<ChannelStrip *> (wlist.at(iChannel));          if (iStrip < 0 || iStrip >= wlist.count())
2693                    return nullptr;
2694    
2695            QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2696            if (pMdiSubWindow)
2697                    return static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2698            else
2699                    return nullptr;
2700  }  }
2701    
2702    
2703  // Retrieve a channel strip by sampler channel id.  // Retrieve a channel strip by sampler channel id.
2704  ChannelStrip* MainForm::channelStrip ( int iChannelID )  ChannelStrip *MainForm::channelStrip ( int iChannelID )
2705  {  {
2706          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2707                    = m_pWorkspace->subWindowList();
2708          if (wlist.isEmpty())          if (wlist.isEmpty())
2709                  return NULL;                  return nullptr;
2710    
2711          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2712                  ChannelStrip* pChannelStrip                  ChannelStrip *pChannelStrip
2713                          = static_cast<ChannelStrip*> (wlist.at(iChannel));                          = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2714                  if (pChannelStrip) {                  if (pChannelStrip) {
2715                          Channel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
2716                          if (pChannel && pChannel->channelID() == iChannelID)                          if (pChannel && pChannel->channelID() == iChannelID)
# Line 2256  ChannelStrip* MainForm::channelStrip ( i Line 2719  ChannelStrip* MainForm::channelStrip ( i
2719          }          }
2720    
2721          // Not found.          // Not found.
2722          return NULL;          return nullptr;
2723  }  }
2724    
2725    
# Line 2267  void MainForm::channelsMenuAboutToShow ( Line 2730  void MainForm::channelsMenuAboutToShow (
2730          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);
2731          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);
2732    
2733          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2734                    = m_pWorkspace->subWindowList();
2735          if (!wlist.isEmpty()) {          if (!wlist.isEmpty()) {
2736                  m_ui.channelsMenu->addSeparator();                  m_ui.channelsMenu->addSeparator();
2737                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  int iStrip = 0;
2738                          ChannelStrip* pChannelStrip                  foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2739                                  = static_cast<ChannelStrip*> (wlist.at(iChannel));                          ChannelStrip *pChannelStrip
2740                                    = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2741                          if (pChannelStrip) {                          if (pChannelStrip) {
2742                                  QAction *pAction = m_ui.channelsMenu->addAction(                                  QAction *pAction = m_ui.channelsMenu->addAction(
2743                                          pChannelStrip->windowTitle(),                                          pChannelStrip->windowTitle(),
2744                                          this, SLOT(channelsMenuActivated()));                                          this, SLOT(channelsMenuActivated()));
2745                                  pAction->setCheckable(true);                                  pAction->setCheckable(true);
2746                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);
2747                                  pAction->setData(iChannel);                                  pAction->setData(iStrip);
2748                          }                          }
2749                            ++iStrip;
2750                  }                  }
2751          }          }
2752  }  }
# Line 2291  void MainForm::channelsMenuActivated (vo Line 2757  void MainForm::channelsMenuActivated (vo
2757  {  {
2758          // Retrive channel index from action data...          // Retrive channel index from action data...
2759          QAction *pAction = qobject_cast<QAction *> (sender());          QAction *pAction = qobject_cast<QAction *> (sender());
2760          if (pAction == NULL)          if (pAction == nullptr)
2761                  return;                  return;
2762    
2763          ChannelStrip* pChannelStrip = channelStripAt(pAction->data().toInt());          ChannelStrip *pChannelStrip = channelStripAt(pAction->data().toInt());
2764          if (pChannelStrip) {          if (pChannelStrip) {
2765                  pChannelStrip->showNormal();                  pChannelStrip->showNormal();
2766                  pChannelStrip->setFocus();                  pChannelStrip->setFocus();
# Line 2303  void MainForm::channelsMenuActivated (vo Line 2769  void MainForm::channelsMenuActivated (vo
2769    
2770    
2771  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2772  // qsamplerMainForm -- Timer stuff.  // QSampler::MainForm -- Timer stuff.
2773    
2774  // Set the pseudo-timer delay schedule.  // Set the pseudo-timer delay schedule.
2775  void MainForm::startSchedule ( int iStartDelay )  void MainForm::startSchedule ( int iStartDelay )
# Line 2322  void MainForm::stopSchedule (void) Line 2788  void MainForm::stopSchedule (void)
2788  // Timer slot funtion.  // Timer slot funtion.
2789  void MainForm::timerSlot (void)  void MainForm::timerSlot (void)
2790  {  {
2791          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2792                  return;                  return;
2793    
2794          // Is it the first shot on server start after a few delay?          // Is it the first shot on server start after a few delay?
# Line 2344  void MainForm::timerSlot (void) Line 2810  void MainForm::timerSlot (void)
2810                          ChannelStrip *pChannelStrip = iter.next();                          ChannelStrip *pChannelStrip = iter.next();
2811                          // If successfull, remove from pending list...                          // If successfull, remove from pending list...
2812                          if (pChannelStrip->updateChannelInfo()) {                          if (pChannelStrip->updateChannelInfo()) {
2813                                  int iChannelStrip = m_changedStrips.indexOf(pChannelStrip);                                  const int iChannelStrip = m_changedStrips.indexOf(pChannelStrip);
2814                                  if (iChannelStrip >= 0)                                  if (iChannelStrip >= 0)
2815                                          m_changedStrips.removeAt(iChannelStrip);                                          m_changedStrips.removeAt(iChannelStrip);
2816                          }                          }
# Line 2355  void MainForm::timerSlot (void) Line 2821  void MainForm::timerSlot (void)
2821                          if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime)  {                          if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime)  {
2822                                  m_iTimerSlot = 0;                                  m_iTimerSlot = 0;
2823                                  // Update the channel stream usage for each strip...                                  // Update the channel stream usage for each strip...
2824                                  QWidgetList wlist = m_pWorkspace->windowList();                                  const QList<QMdiSubWindow *>& wlist
2825                                  for (int iChannel = 0;                                          = m_pWorkspace->subWindowList();
2826                                                  iChannel < (int) wlist.count(); iChannel++) {                                  foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2827                                          ChannelStrip* pChannelStrip                                          ChannelStrip *pChannelStrip
2828                                                  = (ChannelStrip*) wlist.at(iChannel);                                                  = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2829                                          if (pChannelStrip && pChannelStrip->isVisible())                                          if (pChannelStrip && pChannelStrip->isVisible())
2830                                                  pChannelStrip->updateChannelUsage();                                                  pChannelStrip->updateChannelUsage();
2831                                  }                                  }
2832                          }                          }
2833                  }                  }
2834    
2835            #if CONFIG_LSCP_CLIENT_CONNECTION_LOST
2836                    // If we lost connection to server: Try to automatically reconnect if we
2837                    // did not start the server.
2838                    //
2839                    // TODO: If we started the server, then we might inform the user that
2840                    // the server probably crashed and asking user ONCE whether we should
2841                    // restart the server.
2842                    if (lscp_client_connection_lost(m_pClient) && !m_pServer)
2843                            startAutoReconnectClient();
2844            #endif // CONFIG_LSCP_CLIENT_CONNECTION_LOST
2845          }          }
2846    
2847          // Register the next timer slot.          // Register the next timer slot.
# Line 2373  void MainForm::timerSlot (void) Line 2850  void MainForm::timerSlot (void)
2850    
2851    
2852  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2853  // qsamplerMainForm -- Server stuff.  // QSampler::MainForm -- Server stuff.
2854    
2855  // Start linuxsampler server...  // Start linuxsampler server...
2856  void MainForm::startServer (void)  void MainForm::startServer (void)
2857  {  {
2858          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2859                  return;                  return;
2860    
2861          // Aren't already a client, are we?          // Aren't already a client, are we?
# Line 2387  void MainForm::startServer (void) Line 2864  void MainForm::startServer (void)
2864    
2865          // Is the server process instance still here?          // Is the server process instance still here?
2866          if (m_pServer) {          if (m_pServer) {
2867                  switch (QMessageBox::warning(this,                  if (QMessageBox::warning(this,
2868                          QSAMPLER_TITLE ": " + tr("Warning"),                          tr("Warning"),
2869                          tr("Could not start the LinuxSampler server.\n\n"                          tr("Could not start the LinuxSampler server.\n\n"
2870                          "Maybe it ss already started."),                          "Maybe it is already started."),
2871                          tr("Stop"), tr("Kill"), tr("Cancel"))) {                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
                 case 0:  
2872                          m_pServer->terminate();                          m_pServer->terminate();
                         break;  
                 case 1:  
2873                          m_pServer->kill();                          m_pServer->kill();
                         break;  
2874                  }                  }
2875                  return;                  return;
2876          }          }
# Line 2410  void MainForm::startServer (void) Line 2883  void MainForm::startServer (void)
2883                  return;                  return;
2884    
2885          // OK. Let's build the startup process...          // OK. Let's build the startup process...
2886          m_pServer = new QProcess(this);          m_pServer = new QProcess();
2887            m_bForceServerStop = true;
2888    
2889          // Setup stdout/stderr capture...          // Setup stdout/stderr capture...
2890  //      if (m_pOptions->bStdoutCapture) {          m_pServer->setProcessChannelMode(QProcess::ForwardedChannels);
2891                  //m_pServer->setProcessChannelMode(          QObject::connect(m_pServer,
2892                  //      QProcess::StandardOutput);                  SIGNAL(readyReadStandardOutput()),
2893                  QObject::connect(m_pServer,                  SLOT(readServerStdout()));
2894                          SIGNAL(readyReadStandardOutput()),          QObject::connect(m_pServer,
2895                          SLOT(readServerStdout()));                  SIGNAL(readyReadStandardError()),
2896                  QObject::connect(m_pServer,                  SLOT(readServerStdout()));
                         SIGNAL(readyReadStandardError()),  
                         SLOT(readServerStdout()));  
 //      }  
2897    
2898          // The unforgiveable signal communication...          // The unforgiveable signal communication...
2899          QObject::connect(m_pServer,          QObject::connect(m_pServer,
2900                  SIGNAL(finished(int,QProcess::ExitStatus)),                  SIGNAL(finished(int, QProcess::ExitStatus)),
2901                  SLOT(processServerExit()));                  SLOT(processServerExit()));
2902    
2903          // Build process arguments...          // Build process arguments...
# Line 2457  void MainForm::startServer (void) Line 2928  void MainForm::startServer (void)
2928    
2929    
2930  // Stop linuxsampler server...  // Stop linuxsampler server...
2931  void MainForm::stopServer (void)  void MainForm::stopServer ( bool bInteractive )
2932  {  {
2933          // Stop client code.          // Stop client code.
2934          stopClient();          stopClient();
2935    
2936            if (m_pServer && bInteractive) {
2937                    if (QMessageBox::question(this,
2938                            tr("The backend's fate ..."),
2939                            tr("You have the option to keep the sampler backend (LinuxSampler)\n"
2940                            "running in the background. The sampler would continue to work\n"
2941                            "according to your current sampler session and you could alter the\n"
2942                            "sampler session at any time by relaunching QSampler.\n\n"
2943                            "Do you want LinuxSampler to stop?"),
2944                            QMessageBox::Yes | QMessageBox::No,
2945                            QMessageBox::Yes) == QMessageBox::No) {
2946                            m_bForceServerStop = false;
2947                    }
2948            }
2949    
2950            bool bGraceWait = true;
2951    
2952          // And try to stop server.          // And try to stop server.
2953          if (m_pServer) {          if (m_pServer && m_bForceServerStop) {
2954                  appendMessages(tr("Server is stopping..."));                  appendMessages(tr("Server is stopping..."));
2955                  if (m_pServer->state() == QProcess::Running)                  if (m_pServer->state() == QProcess::Running) {
2956                    #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
2957                            // Try harder...
2958                            m_pServer->kill();
2959                    #else
2960                            // Try softly...
2961                          m_pServer->terminate();                          m_pServer->terminate();
2962          }                          bool bFinished = m_pServer->waitForFinished(QSAMPLER_TIMER_MSECS * 1000);
2963                            if (bFinished) bGraceWait = false;
2964                    #endif
2965                    }
2966            }       // Do final processing anyway.
2967            else processServerExit();
2968    
2969          // Give it some time to terminate gracefully and stabilize...          // Give it some time to terminate gracefully and stabilize...
2970          QTime t;          if (bGraceWait) {
2971          t.start();                  QElapsedTimer timer;
2972          while (t.elapsed() < QSAMPLER_TIMER_MSECS)                  timer.start();
2973                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  while (timer.elapsed() < QSAMPLER_TIMER_MSECS)
2974                            QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2975          // Do final processing anyway.          }
         processServerExit();  
2976  }  }
2977    
2978    
# Line 2498  void MainForm::processServerExit (void) Line 2994  void MainForm::processServerExit (void)
2994          if (m_pMessages)          if (m_pMessages)
2995                  m_pMessages->flushStdoutBuffer();                  m_pMessages->flushStdoutBuffer();
2996    
2997          if (m_pServer) {          if (m_pServer && m_bForceServerStop) {
2998                    if (m_pServer->state() != QProcess::NotRunning) {
2999                            appendMessages(tr("Server is being forced..."));
3000                            // Force final server shutdown...
3001                            m_pServer->kill();
3002                            // Give it some time to terminate gracefully and stabilize...
3003                            QElapsedTimer timer;
3004                            timer.start();
3005                            while (timer.elapsed() < QSAMPLER_TIMER_MSECS)
3006                                    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
3007                    }
3008                  // Force final server shutdown...                  // Force final server shutdown...
3009                  appendMessages(                  appendMessages(
3010                          tr("Server was stopped with exit status %1.")                          tr("Server was stopped with exit status %1.")
3011                          .arg(m_pServer->exitStatus()));                          .arg(m_pServer->exitStatus()));
                 m_pServer->terminate();  
                 if (!m_pServer->waitForFinished(2000))  
                         m_pServer->kill();  
                 // Destroy it.  
3012                  delete m_pServer;                  delete m_pServer;
3013                  m_pServer = NULL;                  m_pServer = nullptr;
3014          }          }
3015    
3016          // Again, make status visible stable.          // Again, make status visible stable.
# Line 2517  void MainForm::processServerExit (void) Line 3019  void MainForm::processServerExit (void)
3019    
3020    
3021  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
3022  // qsamplerMainForm -- Client stuff.  // QSampler::MainForm -- Client stuff.
3023    
3024  // The LSCP client callback procedure.  // The LSCP client callback procedure.
3025  lscp_status_t qsampler_client_callback ( lscp_client_t */*pClient*/,  lscp_status_t qsampler_client_callback ( lscp_client_t */*pClient*/,
3026          lscp_event_t event, const char *pchData, int cchData, void *pvData )          lscp_event_t event, const char *pchData, int cchData, void *pvData )
3027  {  {
3028          MainForm* pMainForm = (MainForm *) pvData;          MainForm* pMainForm = (MainForm *) pvData;
3029          if (pMainForm == NULL)          if (pMainForm == nullptr)
3030                  return LSCP_FAILED;                  return LSCP_FAILED;
3031    
3032          // ATTN: DO NOT EVER call any GUI code here,          // ATTN: DO NOT EVER call any GUI code here,
3033          // as this is run under some other thread context.          // as this is run under some other thread context.
3034          // A custom event must be posted here...          // A custom event must be posted here...
3035          QApplication::postEvent(pMainForm,          QApplication::postEvent(pMainForm,
3036                  new CustomEvent(event, pchData, cchData));                  new LscpEvent(event, pchData, cchData));
3037    
3038          return LSCP_OK;          return LSCP_OK;
3039  }  }
3040    
3041    
3042  // Start our almighty client...  // Start our almighty client...
3043  bool MainForm::startClient (void)  bool MainForm::startClient (bool bReconnectOnly)
3044  {  {
3045          // Have it a setup?          // Have it a setup?
3046          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
3047                  return false;                  return false;
3048    
3049          // Aren't we already started, are we?          // Aren't we already started, are we?
# Line 2555  bool MainForm::startClient (void) Line 3057  bool MainForm::startClient (void)
3057          m_pClient = ::lscp_client_create(          m_pClient = ::lscp_client_create(
3058                  m_pOptions->sServerHost.toUtf8().constData(),                  m_pOptions->sServerHost.toUtf8().constData(),
3059                  m_pOptions->iServerPort, qsampler_client_callback, this);                  m_pOptions->iServerPort, qsampler_client_callback, this);
3060          if (m_pClient == NULL) {          if (m_pClient == nullptr) {
3061                  // Is this the first try?                  // Is this the first try?
3062                  // maybe we need to start a local server...                  // maybe we need to start a local server...
3063                  if ((m_pServer && m_pServer->state() == QProcess::Running)                  if ((m_pServer && m_pServer->state() == QProcess::Running)
3064                          || !m_pOptions->bServerStart) {                          || !m_pOptions->bServerStart || bReconnectOnly)
3065                          appendMessagesError(                  {
3066                                  tr("Could not connect to server as client.\n\nSorry."));                          // if this method is called from autoReconnectClient()
3067                            // then don't bother user with an error message...
3068                            if (!bReconnectOnly) {
3069                                    appendMessagesError(
3070                                            tr("Could not connect to server as client.\n\nSorry.")
3071                                    );
3072                            }
3073                  } else {                  } else {
3074                          startServer();                          startServer();
3075                  }                  }
# Line 2569  bool MainForm::startClient (void) Line 3077  bool MainForm::startClient (void)
3077                  stabilizeForm();                  stabilizeForm();
3078                  return false;                  return false;
3079          }          }
3080    
3081          // Just set receive timeout value, blindly.          // Just set receive timeout value, blindly.
3082          ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);          ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);
3083          appendMessages(          appendMessages(
# Line 2576  bool MainForm::startClient (void) Line 3085  bool MainForm::startClient (void)
3085                  .arg(::lscp_client_get_timeout(m_pClient)));                  .arg(::lscp_client_get_timeout(m_pClient)));
3086    
3087          // Subscribe to channel info change notifications...          // Subscribe to channel info change notifications...
3088            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT) != LSCP_OK)
3089                    appendMessagesClient("lscp_client_subscribe(CHANNEL_COUNT)");
3090          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)
3091                  appendMessagesClient("lscp_client_subscribe");                  appendMessagesClient("lscp_client_subscribe(CHANNEL_INFO)");
3092    
3093            DeviceStatusForm::onDevicesChanged(); // initialize
3094            updateViewMidiDeviceStatusMenu();
3095            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT) != LSCP_OK)
3096                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_COUNT)");
3097            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO) != LSCP_OK)
3098                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_INFO)");
3099            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT) != LSCP_OK)
3100                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_COUNT)");
3101            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO) != LSCP_OK)
3102                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_INFO)");
3103    
3104    #if CONFIG_EVENT_CHANNEL_MIDI
3105            // Subscribe to channel MIDI data notifications...
3106            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI) != LSCP_OK)
3107                    appendMessagesClient("lscp_client_subscribe(CHANNEL_MIDI)");
3108    #endif
3109    
3110    #if CONFIG_EVENT_DEVICE_MIDI
3111            // Subscribe to channel MIDI data notifications...
3112            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI) != LSCP_OK)
3113                    appendMessagesClient("lscp_client_subscribe(DEVICE_MIDI)");
3114    #endif
3115    
3116          // We may stop scheduling around.          // We may stop scheduling around.
3117          stopSchedule();          stopSchedule();
# Line 2599  bool MainForm::startClient (void) Line 3133  bool MainForm::startClient (void)
3133          if (!m_pOptions->sSessionFile.isEmpty()) {          if (!m_pOptions->sSessionFile.isEmpty()) {
3134                  // Just load the prabably startup session...                  // Just load the prabably startup session...
3135                  if (loadSessionFile(m_pOptions->sSessionFile)) {                  if (loadSessionFile(m_pOptions->sSessionFile)) {
3136                          m_pOptions->sSessionFile = QString::null;                          m_pOptions->sSessionFile = QString();
3137                          return true;                          return true;
3138                  }                  }
3139          }          }
3140    
3141            // send the current / loaded fine tuning settings to the sampler
3142            m_pOptions->sendFineTuningSettings();
3143    
3144          // Make a new session          // Make a new session
3145          return newSession();          return newSession();
3146  }  }
# Line 2612  bool MainForm::startClient (void) Line 3149  bool MainForm::startClient (void)
3149  // Stop client...  // Stop client...
3150  void MainForm::stopClient (void)  void MainForm::stopClient (void)
3151  {  {
3152          if (m_pClient == NULL)          if (m_pClient == nullptr)
3153                  return;                  return;
3154    
3155          // Log prepare here.          // Log prepare here.
# Line 2631  void MainForm::stopClient (void) Line 3168  void MainForm::stopClient (void)
3168          closeSession(false);          closeSession(false);
3169    
3170          // Close us as a client...          // Close us as a client...
3171    #if CONFIG_EVENT_DEVICE_MIDI
3172            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI);
3173    #endif
3174    #if CONFIG_EVENT_CHANNEL_MIDI
3175            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI);
3176    #endif
3177            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
3178            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
3179            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
3180            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
3181          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
3182            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT);
3183          ::lscp_client_destroy(m_pClient);          ::lscp_client_destroy(m_pClient);
3184          m_pClient = NULL;          m_pClient = nullptr;
3185    
3186          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
3187          // if visible, that we're running out...          // if visible, that we're running out...
# Line 2650  void MainForm::stopClient (void) Line 3198  void MainForm::stopClient (void)
3198  }  }
3199    
3200    
3201    void MainForm::startAutoReconnectClient (void)
3202    {
3203            stopClient();
3204            appendMessages(tr("Trying to reconnect..."));
3205            QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(autoReconnectClient()));
3206    }
3207    
3208    
3209    void MainForm::autoReconnectClient (void)
3210    {
3211            const bool bSuccess = startClient(true);
3212            if (!bSuccess)
3213                    QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(autoReconnectClient()));
3214    }
3215    
3216    
3217  // Channel strip activation/selection.  // Channel strip activation/selection.
3218  void MainForm::activateStrip ( QWidget *pWidget )  void MainForm::activateStrip ( QMdiSubWindow *pMdiSubWindow )
3219  {  {
3220          ChannelStrip *pChannelStrip          ChannelStrip *pChannelStrip = nullptr;
3221                  = static_cast<ChannelStrip *> (pWidget);          if (pMdiSubWindow)
3222                    pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
3223          if (pChannelStrip)          if (pChannelStrip)
3224                  pChannelStrip->setSelected(true);                  pChannelStrip->setSelected(true);
3225    
# Line 2662  void MainForm::activateStrip ( QWidget * Line 3227  void MainForm::activateStrip ( QWidget *
3227  }  }
3228    
3229    
3230    // Channel toolbar orientation change.
3231    void MainForm::channelsToolbarOrientation ( Qt::Orientation orientation )
3232    {
3233    #ifdef CONFIG_VOLUME
3234            m_pVolumeSlider->setOrientation(orientation);
3235            if (orientation == Qt::Horizontal) {
3236                    m_pVolumeSlider->setMinimumHeight(24);
3237                    m_pVolumeSlider->setMaximumHeight(32);
3238                    m_pVolumeSlider->setMinimumWidth(120);
3239                    m_pVolumeSlider->setMaximumWidth(640);
3240                    m_pVolumeSpinBox->setMaximumWidth(64);
3241                    m_pVolumeSpinBox->setButtonSymbols(QSpinBox::UpDownArrows);
3242            } else {
3243                    m_pVolumeSlider->setMinimumHeight(120);
3244                    m_pVolumeSlider->setMaximumHeight(480);
3245                    m_pVolumeSlider->setMinimumWidth(24);
3246                    m_pVolumeSlider->setMaximumWidth(32);
3247                    m_pVolumeSpinBox->setMaximumWidth(32);
3248                    m_pVolumeSpinBox->setButtonSymbols(QSpinBox::NoButtons);
3249            }
3250    #endif
3251    }
3252    
3253    
3254  } // namespace QSampler  } // namespace QSampler
3255    
3256    

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

  ViewVC Help
Powered by ViewVC