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

Legend:
Removed from v.1693  
changed lines
  Added in v.3855

  ViewVC Help
Powered by ViewVC