/[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 1514 by capela, Fri Nov 23 10:51:37 2007 UTC revision 3759 by capela, Sat Mar 28 00:28:13 2020 UTC
# Line 1  Line 1 
1  // qsamplerMainForm.cpp  // qsamplerMainForm.cpp
2  //  //
3  /****************************************************************************  /****************************************************************************
4     Copyright (C) 2004-2007, rncbc aka Rui Nuno Capela. All rights reserved.     Copyright (C) 2004-2020, rncbc aka Rui Nuno Capela. All rights reserved.
5     Copyright (C) 2007, Christian Schoenebeck     Copyright (C) 2007-2019 Christian Schoenebeck
6    
7     This program is free software; you can redistribute it and/or     This program is free software; you can redistribute it and/or
8     modify it under the terms of the GNU General Public License     modify it under the terms of the GNU General Public License
# Line 33  Line 33 
33  #include "qsamplerInstrumentListForm.h"  #include "qsamplerInstrumentListForm.h"
34  #include "qsamplerDeviceForm.h"  #include "qsamplerDeviceForm.h"
35  #include "qsamplerOptionsForm.h"  #include "qsamplerOptionsForm.h"
36    #include "qsamplerDeviceStatusForm.h"
37    
38    #include <QMdiArea>
39    #include <QMdiSubWindow>
40    
41  #include <QApplication>  #include <QApplication>
 #include <QWorkspace>  
42  #include <QProcess>  #include <QProcess>
43  #include <QMessageBox>  #include <QMessageBox>
44    
# Line 55  Line 58 
58  #include <QTimer>  #include <QTimer>
59  #include <QDateTime>  #include <QDateTime>
60    
61    #include <QElapsedTimer>
62    
63  #ifdef HAVE_SIGNAL_H  #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
64  #include <signal.h>  #include <QMimeData>
65    #endif
66    
67    #if QT_VERSION < QT_VERSION_CHECK(4, 5, 0)
68    namespace Qt {
69    const WindowFlags WindowCloseButtonHint = WindowFlags(0x08000000);
70    }
71  #endif  #endif
72    
73    // Deprecated QTextStreamFunctions/Qt namespaces workaround.
74    #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
75    #define endl    Qt::endl
76    #endif
77    
78    
79  #ifdef CONFIG_LIBGIG  #ifdef CONFIG_LIBGIG
80  #include <gig.h>  #include <gig.h>
81  #endif  #endif
# Line 77  static inline long lroundf ( float x ) Line 93  static inline long lroundf ( float x )
93  }  }
94  #endif  #endif
95    
96    
97    // All winsock apps needs this.
98    #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
99    static WSADATA _wsaData;
100    #undef HAVE_SIGNAL_H
101    #endif
102    
103    
104    //-------------------------------------------------------------------------
105    // LADISH Level 1 support stuff.
106    
107    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
108    
109    #include <QSocketNotifier>
110    
111    #include <unistd.h>
112    #include <sys/types.h>
113    #include <sys/socket.h>
114    #include <signal.h>
115    
116    // File descriptor for SIGUSR1 notifier.
117    static int g_fdSigusr1[2] = { -1, -1 };
118    
119    // Unix SIGUSR1 signal handler.
120    static void qsampler_sigusr1_handler ( int /* signo */ )
121    {
122            char c = 1;
123    
124            (::write(g_fdSigusr1[0], &c, sizeof(c)) > 0);
125    }
126    
127    // File descriptor for SIGTERM notifier.
128    static int g_fdSigterm[2] = { -1, -1 };
129    
130    // Unix SIGTERM signal handler.
131    static void qsampler_sigterm_handler ( int /* signo */ )
132    {
133            char c = 1;
134    
135            (::write(g_fdSigterm[0], &c, sizeof(c)) > 0);
136    }
137    
138    #endif  // HAVE_SIGNAL_H
139    
140    
141    //-------------------------------------------------------------------------
142    // QSampler -- namespace
143    
144    
145    namespace QSampler {
146    
147  // Timer constant stuff.  // Timer constant stuff.
148  #define QSAMPLER_TIMER_MSECS    200  #define QSAMPLER_TIMER_MSECS    200
149    
# Line 87  static inline long lroundf ( float x ) Line 154  static inline long lroundf ( float x )
154  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.
155    
156    
157  // All winsock apps needs this.  // Specialties for thread-callback comunication.
158  #if defined(WIN32)  #define QSAMPLER_LSCP_EVENT   QEvent::Type(QEvent::User + 1)
 static WSADATA _wsaData;  
 #endif  
159    
160    
161  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
162  // qsamplerCustomEvent -- specialty for callback comunication.  // QSampler::LscpEvent -- specialty for LSCP callback comunication.
163    
164  #define QSAMPLER_CUSTOM_EVENT   QEvent::Type(QEvent::User + 0)  class LscpEvent : public QEvent
   
 class qsamplerCustomEvent : public QEvent  
165  {  {
166  public:  public:
167    
168          // Constructor.          // Constructor.
169          qsamplerCustomEvent(lscp_event_t event, const char *pchData, int cchData)          LscpEvent(lscp_event_t event, const char *pchData, int cchData)
170                  : QEvent(QSAMPLER_CUSTOM_EVENT)                  : QEvent(QSAMPLER_LSCP_EVENT)
171          {          {
172                  m_event = event;                  m_event = event;
173                  m_data  = QString::fromUtf8(pchData, cchData);                  m_data  = QString::fromUtf8(pchData, cchData);
174          }          }
175    
176          // Accessors.          // Accessors.
177          lscp_event_t event() { return m_event; }          lscp_event_t  event() { return m_event; }
178          QString&     data()  { return m_data;  }          const QString& data() { return m_data;  }
179    
180  private:  private:
181    
# Line 124  private: Line 187  private:
187    
188    
189  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
190  // qsamplerMainForm -- Main window form implementation.  // QSampler::Workspace -- Main window workspace (MDI Area) decl.
191    
192  namespace QSampler {  class Workspace : public QMdiArea
193    {
194    public:
195    
196            Workspace(MainForm *pMainForm) : QMdiArea(pMainForm) {}
197    
198    protected:
199    
200            void resizeEvent(QResizeEvent *)
201            {
202                    MainForm *pMainForm = static_cast<MainForm *> (parentWidget());
203                    if (pMainForm)
204                            pMainForm->channelsArrangeAuto();
205            }
206    };
207    
208    
209    //-------------------------------------------------------------------------
210    // QSampler::MainForm -- Main window form implementation.
211    
212  // Kind of singleton reference.  // Kind of singleton reference.
213  MainForm* MainForm::g_pMainForm = NULL;  MainForm *MainForm::g_pMainForm = nullptr;
214    
215  MainForm::MainForm ( QWidget *pParent )  MainForm::MainForm ( QWidget *pParent )
216          : QMainWindow(pParent)          : QMainWindow(pParent)
# Line 140  MainForm::MainForm ( QWidget *pParent ) Line 221  MainForm::MainForm ( QWidget *pParent )
221          g_pMainForm = this;          g_pMainForm = this;
222    
223          // Initialize some pointer references.          // Initialize some pointer references.
224          m_pOptions = NULL;          m_pOptions = nullptr;
225    
226          // All child forms are to be created later, not earlier than setup.          // All child forms are to be created later, not earlier than setup.
227          m_pMessages = NULL;          m_pMessages = nullptr;
228          m_pInstrumentListForm = NULL;          m_pInstrumentListForm = nullptr;
229          m_pDeviceForm = NULL;          m_pDeviceForm = nullptr;
230    
231          // We'll start clean.          // We'll start clean.
232          m_iUntitled   = 0;          m_iUntitled   = 0;
233            m_iDirtySetup = 0;
234          m_iDirtyCount = 0;          m_iDirtyCount = 0;
235    
236          m_pServer = NULL;          m_pServer = nullptr;
237          m_pClient = NULL;          m_pClient = nullptr;
238    
239          m_iStartDelay = 0;          m_iStartDelay = 0;
240          m_iTimerDelay = 0;          m_iTimerDelay = 0;
241    
242          m_iTimerSlot = 0;          m_iTimerSlot = 0;
243    
244  #ifdef HAVE_SIGNAL_H  #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
245    
246          // Set to ignore any fatal "Broken pipe" signals.          // Set to ignore any fatal "Broken pipe" signals.
247          ::signal(SIGPIPE, SIG_IGN);          ::signal(SIGPIPE, SIG_IGN);
248  #endif  
249            // LADISH Level 1 suport.
250    
251            // Initialize file descriptors for SIGUSR1 socket notifier.
252            ::socketpair(AF_UNIX, SOCK_STREAM, 0, g_fdSigusr1);
253            m_pSigusr1Notifier
254                    = new QSocketNotifier(g_fdSigusr1[1], QSocketNotifier::Read, this);
255    
256            QObject::connect(m_pSigusr1Notifier,
257                    SIGNAL(activated(int)),
258                    SLOT(handle_sigusr1()));
259    
260            // Install SIGUSR1 signal handler.
261            struct sigaction sigusr1;
262            sigusr1.sa_handler = qsampler_sigusr1_handler;
263            sigemptyset(&sigusr1.sa_mask);
264            sigusr1.sa_flags = 0;
265            sigusr1.sa_flags |= SA_RESTART;
266            ::sigaction(SIGUSR1, &sigusr1, nullptr);
267    
268            // Initialize file descriptors for SIGTERM socket notifier.
269            ::socketpair(AF_UNIX, SOCK_STREAM, 0, g_fdSigterm);
270            m_pSigtermNotifier
271                    = new QSocketNotifier(g_fdSigterm[1], QSocketNotifier::Read, this);
272    
273            QObject::connect(m_pSigtermNotifier,
274                    SIGNAL(activated(int)),
275                    SLOT(handle_sigterm()));
276    
277            // Install SIGTERM signal handler.
278            struct sigaction sigterm;
279            sigterm.sa_handler = qsampler_sigterm_handler;
280            sigemptyset(&sigterm.sa_mask);
281            sigterm.sa_flags = 0;
282            sigterm.sa_flags |= SA_RESTART;
283            ::sigaction(SIGTERM, &sigterm, nullptr);
284            ::sigaction(SIGQUIT, &sigterm, nullptr);
285    
286            // Ignore SIGHUP/SIGINT signals.
287            ::signal(SIGHUP, SIG_IGN);
288            ::signal(SIGINT, SIG_IGN);
289    
290    #else   // HAVE_SIGNAL_H
291    
292            m_pSigusr1Notifier = nullptr;
293            m_pSigtermNotifier = nullptr;
294            
295    #endif  // !HAVE_SIGNAL_H
296    
297  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
298          // Make some extras into the toolbar...          // Make some extras into the toolbar...
# Line 171  MainForm::MainForm ( QWidget *pParent ) Line 301  MainForm::MainForm ( QWidget *pParent )
301          // Volume slider...          // Volume slider...
302          m_ui.channelsToolbar->addSeparator();          m_ui.channelsToolbar->addSeparator();
303          m_pVolumeSlider = new QSlider(Qt::Horizontal, m_ui.channelsToolbar);          m_pVolumeSlider = new QSlider(Qt::Horizontal, m_ui.channelsToolbar);
304          m_pVolumeSlider->setTickPosition(QSlider::TicksBelow);          m_pVolumeSlider->setTickPosition(QSlider::TicksBothSides);
305          m_pVolumeSlider->setTickInterval(10);          m_pVolumeSlider->setTickInterval(10);
306          m_pVolumeSlider->setPageStep(10);          m_pVolumeSlider->setPageStep(10);
307          m_pVolumeSlider->setSingleStep(10);          m_pVolumeSlider->setSingleStep(10);
# Line 183  MainForm::MainForm ( QWidget *pParent ) Line 313  MainForm::MainForm ( QWidget *pParent )
313          QObject::connect(m_pVolumeSlider,          QObject::connect(m_pVolumeSlider,
314                  SIGNAL(valueChanged(int)),                  SIGNAL(valueChanged(int)),
315                  SLOT(volumeChanged(int)));                  SLOT(volumeChanged(int)));
         //m_ui.channelsToolbar->setHorizontallyStretchable(true);  
         //m_ui.channelsToolbar->setStretchableWidget(m_pVolumeSlider);  
316          m_ui.channelsToolbar->addWidget(m_pVolumeSlider);          m_ui.channelsToolbar->addWidget(m_pVolumeSlider);
317          // Volume spin-box          // Volume spin-box
318          m_ui.channelsToolbar->addSeparator();          m_ui.channelsToolbar->addSeparator();
# Line 200  MainForm::MainForm ( QWidget *pParent ) Line 328  MainForm::MainForm ( QWidget *pParent )
328  #endif  #endif
329    
330          // Make it an MDI workspace.          // Make it an MDI workspace.
331          m_pWorkspace = new QWorkspace(this);          m_pWorkspace = new Workspace(this);
332          m_pWorkspace->setScrollBarsEnabled(true);          m_pWorkspace->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
333            m_pWorkspace->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
334          // Set the activation connection.          // Set the activation connection.
335          QObject::connect(m_pWorkspace,          QObject::connect(m_pWorkspace,
336                  SIGNAL(windowActivated(QWidget *)),                  SIGNAL(subWindowActivated(QMdiSubWindow *)),
337                  SLOT(activateStrip(QWidget *)));                  SLOT(activateStrip(QMdiSubWindow *)));
338          // Make it shine :-)          // Make it shine :-)
339          setCentralWidget(m_pWorkspace);          setCentralWidget(m_pWorkspace);
340    
# Line 234  MainForm::MainForm ( QWidget *pParent ) Line 363  MainForm::MainForm ( QWidget *pParent )
363          m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;          m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;
364          statusBar()->addWidget(pLabel);          statusBar()->addWidget(pLabel);
365    
366  #if defined(WIN32)  #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
367          WSAStartup(MAKEWORD(1, 1), &_wsaData);          WSAStartup(MAKEWORD(1, 1), &_wsaData);
368  #endif  #endif
369    
# Line 322  MainForm::MainForm ( QWidget *pParent ) Line 451  MainForm::MainForm ( QWidget *pParent )
451          QObject::connect(m_ui.channelsMenu,          QObject::connect(m_ui.channelsMenu,
452                  SIGNAL(aboutToShow()),                  SIGNAL(aboutToShow()),
453                  SLOT(channelsMenuAboutToShow()));                  SLOT(channelsMenuAboutToShow()));
454    #ifdef CONFIG_VOLUME
455            QObject::connect(m_ui.channelsToolbar,
456                    SIGNAL(orientationChanged(Qt::Orientation)),
457                    SLOT(channelsToolbarOrientation(Qt::Orientation)));
458    #endif
459  }  }
460    
461  // Destructor.  // Destructor.
# Line 330  MainForm::~MainForm() Line 464  MainForm::~MainForm()
464          // Do final processing anyway.          // Do final processing anyway.
465          processServerExit();          processServerExit();
466    
467  #if defined(WIN32)  #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
468          WSACleanup();          WSACleanup();
469  #endif  #endif
470    
471    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
472            if (m_pSigusr1Notifier)
473                    delete m_pSigusr1Notifier;
474            if (m_pSigtermNotifier)
475                    delete m_pSigtermNotifier;
476    #endif
477    
478          // Finally drop any widgets around...          // Finally drop any widgets around...
479          if (m_pDeviceForm)          if (m_pDeviceForm)
480                  delete m_pDeviceForm;                  delete m_pDeviceForm;
# Line 360  MainForm::~MainForm() Line 501  MainForm::~MainForm()
501  #endif  #endif
502    
503          // Pseudo-singleton reference shut-down.          // Pseudo-singleton reference shut-down.
504          g_pMainForm = NULL;          g_pMainForm = nullptr;
505  }  }
506    
507    
508  // Make and set a proper setup options step.  // Make and set a proper setup options step.
509  void MainForm::setup ( qsamplerOptions *pOptions )  void MainForm::setup ( Options *pOptions )
510  {  {
511          // We got options?          // We got options?
512          m_pOptions = pOptions;          m_pOptions = pOptions;
513    
514          // What style do we create these forms?          // What style do we create these forms?
515          Qt::WindowFlags wflags = Qt::Window          Qt::WindowFlags wflags = Qt::Window
 #if QT_VERSION >= 0x040200  
516                  | Qt::CustomizeWindowHint                  | Qt::CustomizeWindowHint
 #endif  
517                  | Qt::WindowTitleHint                  | Qt::WindowTitleHint
518                  | Qt::WindowSystemMenuHint                  | Qt::WindowSystemMenuHint
519                  | Qt::WindowMinMaxButtonsHint;                  | Qt::WindowMinMaxButtonsHint
520                    | Qt::WindowCloseButtonHint;
521          if (m_pOptions->bKeepOnTop)          if (m_pOptions->bKeepOnTop)
522                  wflags |= Qt::Tool;                  wflags |= Qt::Tool;
523    
524          // Some child forms are to be created right now.          // Some child forms are to be created right now.
525          m_pMessages = new qsamplerMessages(this);          m_pMessages = new Messages(this);
526          m_pDeviceForm = new DeviceForm(this, wflags);          m_pDeviceForm = new DeviceForm(this, wflags);
527  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
528          m_pInstrumentListForm = new InstrumentListForm(this, wflags);          m_pInstrumentListForm = new InstrumentListForm(this, wflags);
529  #else  #else
530          viewInstrumentsAction->setEnabled(false);          m_ui.viewInstrumentsAction->setEnabled(false);
531  #endif  #endif
532    
533            // Setup messages logging appropriately...
534            m_pMessages->setLogging(
535                    m_pOptions->bMessagesLog,
536                    m_pOptions->sMessagesLogPath);
537    
538          // Set message defaults...          // Set message defaults...
539          updateMessagesFont();          updateMessagesFont();
540          updateMessagesLimit();          updateMessagesLimit();
541          updateMessagesCapture();          updateMessagesCapture();
542    
543          // Set the visibility signal.          // Set the visibility signal.
544          QObject::connect(m_pMessages,          QObject::connect(m_pMessages,
545                  SIGNAL(visibilityChanged(bool)),                  SIGNAL(visibilityChanged(bool)),
# Line 418  void MainForm::setup ( qsamplerOptions * Line 566  void MainForm::setup ( qsamplerOptions *
566          }          }
567    
568          // Try to restore old window positioning and initial visibility.          // Try to restore old window positioning and initial visibility.
569          m_pOptions->loadWidgetGeometry(this);          m_pOptions->loadWidgetGeometry(this, true);
570          m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);          m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);
571          m_pOptions->loadWidgetGeometry(m_pDeviceForm);          m_pOptions->loadWidgetGeometry(m_pDeviceForm);
572    
# Line 457  bool MainForm::queryClose (void) Line 605  bool MainForm::queryClose (void)
605                                  || m_ui.channelsToolbar->isVisible());                                  || m_ui.channelsToolbar->isVisible());
606                          m_pOptions->bStatusbar = statusBar()->isVisible();                          m_pOptions->bStatusbar = statusBar()->isVisible();
607                          // Save the dock windows state.                          // Save the dock windows state.
                         const QString sDockables = saveState().toBase64().data();  
608                          m_pOptions->settings().setValue("/Layout/DockWindows", saveState());                          m_pOptions->settings().setValue("/Layout/DockWindows", saveState());
609                          // And the children, and the main windows state,.                          // And the children, and the main windows state,.
610                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);
611                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);
612                          m_pOptions->saveWidgetGeometry(this);                          m_pOptions->saveWidgetGeometry(this, true);
613                          // Close popup widgets.                          // Close popup widgets.
614                          if (m_pInstrumentListForm)                          if (m_pInstrumentListForm)
615                                  m_pInstrumentListForm->close();                                  m_pInstrumentListForm->close();
616                          if (m_pDeviceForm)                          if (m_pDeviceForm)
617                                  m_pDeviceForm->close();                                  m_pDeviceForm->close();
618                          // Stop client and/or server, gracefully.                          // Stop client and/or server, gracefully.
619                          stopServer();                          stopServer(true /*interactive*/);
620                  }                  }
621          }          }
622    
# Line 479  bool MainForm::queryClose (void) Line 626  bool MainForm::queryClose (void)
626    
627  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )
628  {  {
629          if (queryClose())          if (queryClose()) {
630                    DeviceStatusForm::deleteAllInstances();
631                  pCloseEvent->accept();                  pCloseEvent->accept();
632          else          } else
633                  pCloseEvent->ignore();                  pCloseEvent->ignore();
634  }  }
635    
# Line 490  void MainForm::closeEvent ( QCloseEvent Line 638  void MainForm::closeEvent ( QCloseEvent
638  void MainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )  void MainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )
639  {  {
640          // Accept external drags only...          // Accept external drags only...
641          if (pDragEnterEvent->source() == NULL          if (pDragEnterEvent->source() == nullptr
642                  && pDragEnterEvent->mimeData()->hasUrls()) {                  && pDragEnterEvent->mimeData()->hasUrls()) {
643                  pDragEnterEvent->accept();                  pDragEnterEvent->accept();
644          } else {          } else {
# Line 499  void MainForm::dragEnterEvent ( QDragEnt Line 647  void MainForm::dragEnterEvent ( QDragEnt
647  }  }
648    
649    
650  void MainForm::dropEvent ( QDropEvent* pDropEvent )  void MainForm::dropEvent ( QDropEvent *pDropEvent )
651  {  {
652          // Accept externally originated drops only...          // Accept externally originated drops only...
653          if (pDropEvent->source())          if (pDropEvent->source())
# Line 510  void MainForm::dropEvent ( QDropEvent* p Line 658  void MainForm::dropEvent ( QDropEvent* p
658                  QListIterator<QUrl> iter(pMimeData->urls());                  QListIterator<QUrl> iter(pMimeData->urls());
659                  while (iter.hasNext()) {                  while (iter.hasNext()) {
660                          const QString& sPath = iter.next().toLocalFile();                          const QString& sPath = iter.next().toLocalFile();
661                          if (qsamplerChannel::isInstrumentFile(sPath)) {                  //      if (Channel::isDlsInstrumentFile(sPath)) {
662                            if (QFileInfo(sPath).exists()) {
663                                  // Try to create a new channel from instrument file...                                  // Try to create a new channel from instrument file...
664                                  qsamplerChannel *pChannel = new qsamplerChannel();                                  Channel *pChannel = new Channel();
665                                  if (pChannel == NULL)                                  if (pChannel == nullptr)
666                                          return;                                          return;
667                                  // Start setting the instrument filename...                                  // Start setting the instrument filename...
668                                  pChannel->setInstrument(sPath, 0);                                  pChannel->setInstrument(sPath, 0);
# Line 544  void MainForm::dropEvent ( QDropEvent* p Line 693  void MainForm::dropEvent ( QDropEvent* p
693    
694    
695  // Custome event handler.  // Custome event handler.
696  void MainForm::customEvent(QEvent* pCustomEvent)  void MainForm::customEvent ( QEvent* pEvent )
697  {  {
698          // For the time being, just pump it to messages.          // For the time being, just pump it to messages.
699          if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {          if (pEvent->type() == QSAMPLER_LSCP_EVENT) {
700                  qsamplerCustomEvent *pEvent = (qsamplerCustomEvent *) pCustomEvent;                  LscpEvent *pLscpEvent = static_cast<LscpEvent *> (pEvent);
701                  if (pEvent->event() == LSCP_EVENT_CHANNEL_INFO) {                  switch (pLscpEvent->event()) {
702                          int iChannelID = pEvent->data().toInt();                          case LSCP_EVENT_CHANNEL_COUNT:
703                          ChannelStrip *pChannelStrip = channelStrip(iChannelID);                                  updateAllChannelStrips(true);
704                          if (pChannelStrip)                                  break;
705                                  channelStripChanged(pChannelStrip);                          case LSCP_EVENT_CHANNEL_INFO: {
706                  } else {                                  const int iChannelID = pLscpEvent->data().toInt();
707                          appendMessagesColor(tr("Notify event: %1 data: %2")                                  ChannelStrip *pChannelStrip = channelStrip(iChannelID);
708                                  .arg(::lscp_event_to_text(pEvent->event()))                                  if (pChannelStrip)
709                                  .arg(pEvent->data()), "#996699");                                          channelStripChanged(pChannelStrip);
710                                    break;
711                            }
712                            case LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT:
713                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
714                                    DeviceStatusForm::onDevicesChanged();
715                                    updateViewMidiDeviceStatusMenu();
716                                    break;
717                            case LSCP_EVENT_MIDI_INPUT_DEVICE_INFO: {
718                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
719                                    const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt();
720                                    DeviceStatusForm::onDeviceChanged(iDeviceID);
721                                    break;
722                            }
723                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT:
724                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
725                                    break;
726                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO:
727                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
728                                    break;
729                    #if CONFIG_EVENT_CHANNEL_MIDI
730                            case LSCP_EVENT_CHANNEL_MIDI: {
731                                    const int iChannelID = pLscpEvent->data().section(' ', 0, 0).toInt();
732                                    ChannelStrip *pChannelStrip = channelStrip(iChannelID);
733                                    if (pChannelStrip)
734                                            pChannelStrip->midiActivityLedOn();
735                                    break;
736                            }
737                    #endif
738                    #if CONFIG_EVENT_DEVICE_MIDI
739                            case LSCP_EVENT_DEVICE_MIDI: {
740                                    const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt();
741                                    const int iPortID   = pLscpEvent->data().section(' ', 1, 1).toInt();
742                                    DeviceStatusForm *pDeviceStatusForm
743                                            = DeviceStatusForm::getInstance(iDeviceID);
744                                    if (pDeviceStatusForm)
745                                            pDeviceStatusForm->midiArrived(iPortID);
746                                    break;
747                            }
748                    #endif
749                            default:
750                                    appendMessagesColor(tr("LSCP Event: %1 data: %2")
751                                            .arg(::lscp_event_to_text(pLscpEvent->event()))
752                                            .arg(pLscpEvent->data()), "#996699");
753                  }                  }
754          }          }
755  }  }
756    
757    
758    // LADISH Level 1 -- SIGUSR1 signal handler.
759    void MainForm::handle_sigusr1 (void)
760    {
761    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
762    
763            char c;
764    
765            if (::read(g_fdSigusr1[1], &c, sizeof(c)) > 0)
766                    saveSession(false);
767    
768    #endif
769    }
770    
771    
772    void MainForm::handle_sigterm (void)
773    {
774    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
775    
776            char c;
777    
778            if (::read(g_fdSigterm[1], &c, sizeof(c)) > 0)
779                    close();
780    
781    #endif
782    }
783    
784    
785    void MainForm::updateViewMidiDeviceStatusMenu (void)
786    {
787            m_ui.viewMidiDeviceStatusMenu->clear();
788            const std::map<int, DeviceStatusForm *> statusForms
789                    = DeviceStatusForm::getInstances();
790            std::map<int, DeviceStatusForm *>::const_iterator iter
791                    = statusForms.begin();
792            for ( ; iter != statusForms.end(); ++iter) {
793                    DeviceStatusForm *pStatusForm = iter->second;
794                    m_ui.viewMidiDeviceStatusMenu->addAction(
795                            pStatusForm->visibleAction());
796            }
797    }
798    
799    
800  // Context menu event handler.  // Context menu event handler.
801  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )
802  {  {
# Line 572  void MainForm::contextMenuEvent( QContex Line 807  void MainForm::contextMenuEvent( QContex
807    
808    
809  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
810  // qsamplerMainForm -- Brainless public property accessors.  // QSampler::MainForm -- Brainless public property accessors.
811    
812  // The global options settings property.  // The global options settings property.
813  qsamplerOptions *MainForm::options (void) const  Options *MainForm::options (void) const
814  {  {
815          return m_pOptions;          return m_pOptions;
816  }  }
# Line 596  MainForm *MainForm::getInstance (void) Line 831  MainForm *MainForm::getInstance (void)
831    
832    
833  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
834  // qsamplerMainForm -- Session file stuff.  // QSampler::MainForm -- Session file stuff.
835    
836  // Format the displayable session filename.  // Format the displayable session filename.
837  QString MainForm::sessionName ( const QString& sFilename )  QString MainForm::sessionName ( const QString& sFilename )
838  {  {
839          bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);          const bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);
840          QString sSessionName = sFilename;          QString sSessionName = sFilename;
841          if (sSessionName.isEmpty())          if (sSessionName.isEmpty())
842                  sSessionName = tr("Untitled") + QString::number(m_iUntitled);                  sSessionName = tr("Untitled") + QString::number(m_iUntitled);
# Line 625  bool MainForm::newSession (void) Line 860  bool MainForm::newSession (void)
860          m_iUntitled++;          m_iUntitled++;
861    
862          // Stabilize form.          // Stabilize form.
863          m_sFilename = QString::null;          m_sFilename = QString();
864          m_iDirtyCount = 0;          m_iDirtyCount = 0;
865          appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));          appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));
866          stabilizeForm();          stabilizeForm();
# Line 637  bool MainForm::newSession (void) Line 872  bool MainForm::newSession (void)
872  // Open an existing sampler session.  // Open an existing sampler session.
873  bool MainForm::openSession (void)  bool MainForm::openSession (void)
874  {  {
875          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
876                  return false;                  return false;
877    
878          // Ask for the filename to open...          // Ask for the filename to open...
879          QString sFilename = QFileDialog::getOpenFileName(this,          QString sFilename = QFileDialog::getOpenFileName(this,
880                  QSAMPLER_TITLE ": " + tr("Open Session"), // Caption.                  tr("Open Session"),                       // Caption.
881                  m_pOptions->sSessionDir,                  // Start here.                  m_pOptions->sSessionDir,                  // Start here.
882                  tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)                  tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
883          );          );
# Line 663  bool MainForm::openSession (void) Line 898  bool MainForm::openSession (void)
898  // Save current sampler session with another name.  // Save current sampler session with another name.
899  bool MainForm::saveSession ( bool bPrompt )  bool MainForm::saveSession ( bool bPrompt )
900  {  {
901          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
902                  return false;                  return false;
903    
904          QString sFilename = m_sFilename;          QString sFilename = m_sFilename;
# Line 675  bool MainForm::saveSession ( bool bPromp Line 910  bool MainForm::saveSession ( bool bPromp
910                          sFilename = m_pOptions->sSessionDir;                          sFilename = m_pOptions->sSessionDir;
911                  // Prompt the guy...                  // Prompt the guy...
912                  sFilename = QFileDialog::getSaveFileName(this,                  sFilename = QFileDialog::getSaveFileName(this,
913                          QSAMPLER_TITLE ": " + tr("Save Session"), // Caption.                          tr("Save Session"),                       // Caption.
914                          sFilename,                                // Start here.                          sFilename,                                // Start here.
915                          tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)                          tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
916                  );                  );
# Line 685  bool MainForm::saveSession ( bool bPromp Line 920  bool MainForm::saveSession ( bool bPromp
920                  // Enforce .lscp extension...                  // Enforce .lscp extension...
921                  if (QFileInfo(sFilename).suffix().isEmpty())                  if (QFileInfo(sFilename).suffix().isEmpty())
922                          sFilename += ".lscp";                          sFilename += ".lscp";
923            #if 0
924                  // Check if already exists...                  // Check if already exists...
925                  if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {                  if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {
926                          if (QMessageBox::warning(this,                          if (QMessageBox::warning(this,
927                                  QSAMPLER_TITLE ": " + tr("Warning"),                                  tr("Warning"),
928                                  tr("The file already exists:\n\n"                                  tr("The file already exists:\n\n"
929                                  "\"%1\"\n\n"                                  "\"%1\"\n\n"
930                                  "Do you want to replace it?")                                  "Do you want to replace it?")
931                                  .arg(sFilename),                                  .arg(sFilename),
932                                  tr("Replace"), tr("Cancel")) > 0)                                  QMessageBox::Yes | QMessageBox::No)
933                                    == QMessageBox::No)
934                                  return false;                                  return false;
935                  }                  }
936            #endif
937          }          }
938    
939          // Save it right away.          // Save it right away.
# Line 711  bool MainForm::closeSession ( bool bForc Line 949  bool MainForm::closeSession ( bool bForc
949          // Are we dirty enough to prompt it?          // Are we dirty enough to prompt it?
950          if (m_iDirtyCount > 0) {          if (m_iDirtyCount > 0) {
951                  switch (QMessageBox::warning(this,                  switch (QMessageBox::warning(this,
952                          QSAMPLER_TITLE ": " + tr("Warning"),                          tr("Warning"),
953                          tr("The current session has been changed:\n\n"                          tr("The current session has been changed:\n\n"
954                          "\"%1\"\n\n"                          "\"%1\"\n\n"
955                          "Do you want to save the changes?")                          "Do you want to save the changes?")
956                          .arg(sessionName(m_sFilename)),                          .arg(sessionName(m_sFilename)),
957                          tr("Save"), tr("Discard"), tr("Cancel"))) {                          QMessageBox::Save |
958                  case 0:     // Save...                          QMessageBox::Discard |
959                            QMessageBox::Cancel)) {
960                    case QMessageBox::Save:
961                          bClose = saveSession(false);                          bClose = saveSession(false);
962                          // Fall thru....                          // Fall thru....
963                  case 1:     // Discard                  case QMessageBox::Discard:
964                          break;                          break;
965                  default:    // Cancel.                  default:    // Cancel.
966                          bClose = false;                          bClose = false;
# Line 732  bool MainForm::closeSession ( bool bForc Line 972  bool MainForm::closeSession ( bool bForc
972          if (bClose) {          if (bClose) {
973                  // Remove all channel strips from sight...                  // Remove all channel strips from sight...
974                  m_pWorkspace->setUpdatesEnabled(false);                  m_pWorkspace->setUpdatesEnabled(false);
975                  QWidgetList wlist = m_pWorkspace->windowList();                  const QList<QMdiSubWindow *>& wlist
976                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                          = m_pWorkspace->subWindowList();
977                          ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
978                            ChannelStrip *pChannelStrip
979                                    = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
980                          if (pChannelStrip) {                          if (pChannelStrip) {
981                                  qsamplerChannel *pChannel = pChannelStrip->channel();                                  Channel *pChannel = pChannelStrip->channel();
982                                  if (bForce && pChannel)                                  if (bForce && pChannel)
983                                          pChannel->removeChannel();                                          pChannel->removeChannel();
984                                  delete pChannelStrip;                                  delete pChannelStrip;
985                          }                          }
986                            delete pMdiSubWindow;
987                  }                  }
988                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
989                  // We're now clean, for sure.                  // We're now clean, for sure.
# Line 754  bool MainForm::closeSession ( bool bForc Line 997  bool MainForm::closeSession ( bool bForc
997  // Load a session from specific file path.  // Load a session from specific file path.
998  bool MainForm::loadSessionFile ( const QString& sFilename )  bool MainForm::loadSessionFile ( const QString& sFilename )
999  {  {
1000          if (m_pClient == NULL)          if (m_pClient == nullptr)
1001                  return false;                  return false;
1002    
1003          // Open and read from real file.          // Open and read from real file.
# Line 830  bool MainForm::loadSessionFile ( const Q Line 1073  bool MainForm::loadSessionFile ( const Q
1073  // Save current session to specific file path.  // Save current session to specific file path.
1074  bool MainForm::saveSessionFile ( const QString& sFilename )  bool MainForm::saveSessionFile ( const QString& sFilename )
1075  {  {
1076          if (m_pClient == NULL)          if (m_pClient == nullptr)
1077                  return false;                  return false;
1078    
1079          // Check whether server is apparently OK...          // Check whether server is apparently OK...
# Line 852  bool MainForm::saveSessionFile ( const Q Line 1095  bool MainForm::saveSessionFile ( const Q
1095          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1096    
1097          // Write the file.          // Write the file.
1098          int  iErrors = 0;          int iErrors = 0;
1099          QTextStream ts(&file);          QTextStream ts(&file);
1100          ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;          ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;
1101          ts << "# " << tr("Version")          ts << "# " << tr("Version") << ": " CONFIG_BUILD_VERSION << endl;
1102          << ": " QSAMPLER_VERSION << endl;  //      ts << "# " << tr("Build") << ": " CONFIG_BUILD_DATE << endl;
         ts << "# " << tr("Build")  
         << ": " __DATE__ " " __TIME__ << endl;  
1103          ts << "#"  << endl;          ts << "#"  << endl;
1104          ts << "# " << tr("File")          ts << "# " << tr("File")
1105          << ": " << QFileInfo(sFilename).fileName() << endl;          << ": " << QFileInfo(sFilename).fileName() << endl;
# Line 871  bool MainForm::saveSessionFile ( const Q Line 1112  bool MainForm::saveSessionFile ( const Q
1112          // It is assumed that this new kind of device+session file          // It is assumed that this new kind of device+session file
1113          // will be loaded from a complete initialized server...          // will be loaded from a complete initialized server...
1114          int *piDeviceIDs;          int *piDeviceIDs;
1115          int  iDevice;          int  i, iDevice;
1116          ts << "RESET" << endl;          ts << "RESET" << endl;
1117    
1118          // Audio device mapping.          // Audio device mapping.
1119          QMap<int, int> audioDeviceMap;          QMap<int, int> audioDeviceMap; iDevice = 0;
1120          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Audio);          piDeviceIDs = Device::getDevices(m_pClient, Device::Audio);
1121          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (i = 0; piDeviceIDs && piDeviceIDs[i] >= 0; ++i) {
1122                  ts << endl;                  Device device(Device::Audio, piDeviceIDs[i]);
1123                  qsamplerDevice device(qsamplerDevice::Audio, piDeviceIDs[iDevice]);                  // Avoid plug-in driver devices...
1124                    if (device.driverName().toUpper() == "PLUGIN")
1125                            continue;
1126                  // Audio device specification...                  // Audio device specification...
1127                    ts << endl;
1128                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1129                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1130                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();
1131                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
1132                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
1133                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
1134                                          ++deviceParam) {                                          ++deviceParam) {
1135                          const qsamplerDeviceParam& param = deviceParam.value();                          const DeviceParam& param = deviceParam.value();
1136                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
1137                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
1138                  }                  }
1139                  ts << endl;                  ts << endl;
1140                  // Audio channel parameters...                  // Audio channel parameters...
1141                  int iPort = 0;                  int iPort = 0;
1142                  QListIterator<qsamplerDevicePort *> iter(device.ports());                  QListIterator<DevicePort *> iter(device.ports());
1143                  while (iter.hasNext()) {                  while (iter.hasNext()) {
1144                          qsamplerDevicePort *pPort = iter.next();                          DevicePort *pPort = iter.next();
1145                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1146                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1147                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1148                                                  ++portParam) {                                                  ++portParam) {
1149                                  const qsamplerDeviceParam& param = portParam.value();                                  const DeviceParam& param = portParam.value();
1150                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1151                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice
1152                                          << " " << iPort << " " << portParam.key()                                          << " " << iPort << " " << portParam.key()
# Line 911  bool MainForm::saveSessionFile ( const Q Line 1155  bool MainForm::saveSessionFile ( const Q
1155                          iPort++;                          iPort++;
1156                  }                  }
1157                  // Audio device index/id mapping.                  // Audio device index/id mapping.
1158                  audioDeviceMap[device.deviceID()] = iDevice;                  audioDeviceMap.insert(device.deviceID(), iDevice++);
1159                  // Try to keep it snappy :)                  // Try to keep it snappy :)
1160                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1161          }          }
1162    
1163          // MIDI device mapping.          // MIDI device mapping.
1164          QMap<int, int> midiDeviceMap;          QMap<int, int> midiDeviceMap; iDevice = 0;
1165          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Midi);          piDeviceIDs = Device::getDevices(m_pClient, Device::Midi);
1166          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (i = 0; piDeviceIDs && piDeviceIDs[i] >= 0; ++i) {
1167                  ts << endl;                  Device device(Device::Midi, piDeviceIDs[i]);
1168                  qsamplerDevice device(qsamplerDevice::Midi, piDeviceIDs[iDevice]);                  // Avoid plug-in driver devices...
1169                    if (device.driverName().toUpper() == "PLUGIN")
1170                            continue;
1171                  // MIDI device specification...                  // MIDI device specification...
1172                    ts << endl;
1173                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1174                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1175                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();
1176                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
1177                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
1178                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
1179                                          ++deviceParam) {                                          ++deviceParam) {
1180                          const qsamplerDeviceParam& param = deviceParam.value();                          const DeviceParam& param = deviceParam.value();
1181                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
1182                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
1183                  }                  }
1184                  ts << endl;                  ts << endl;
1185                  // MIDI port parameters...                  // MIDI port parameters...
1186                  int iPort = 0;                  int iPort = 0;
1187                  QListIterator<qsamplerDevicePort *> iter(device.ports());                  QListIterator<DevicePort *> iter(device.ports());
1188                  while (iter.hasNext()) {                  while (iter.hasNext()) {
1189                          qsamplerDevicePort *pPort = iter.next();                          DevicePort *pPort = iter.next();
1190                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1191                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1192                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1193                                                  ++portParam) {                                                  ++portParam) {
1194                                  const qsamplerDeviceParam& param = portParam.value();                                  const DeviceParam& param = portParam.value();
1195                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1196                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice
1197                                  << " " << iPort << " " << portParam.key()                                  << " " << iPort << " " << portParam.key()
# Line 953  bool MainForm::saveSessionFile ( const Q Line 1200  bool MainForm::saveSessionFile ( const Q
1200                          iPort++;                          iPort++;
1201                  }                  }
1202                  // MIDI device index/id mapping.                  // MIDI device index/id mapping.
1203                  midiDeviceMap[device.deviceID()] = iDevice;                  midiDeviceMap.insert(device.deviceID(), iDevice++);
1204                  // Try to keep it snappy :)                  // Try to keep it snappy :)
1205                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1206          }          }
# Line 964  bool MainForm::saveSessionFile ( const Q Line 1211  bool MainForm::saveSessionFile ( const Q
1211          QMap<int, int> midiInstrumentMap;          QMap<int, int> midiInstrumentMap;
1212          int *piMaps = ::lscp_list_midi_instrument_maps(m_pClient);          int *piMaps = ::lscp_list_midi_instrument_maps(m_pClient);
1213          for (int iMap = 0; piMaps && piMaps[iMap] >= 0; iMap++) {          for (int iMap = 0; piMaps && piMaps[iMap] >= 0; iMap++) {
1214                  int iMidiMap = piMaps[iMap];                  const int iMidiMap = piMaps[iMap];
1215                  const char *pszMapName                  const char *pszMapName
1216                          = ::lscp_get_midi_instrument_map_name(m_pClient, iMidiMap);                          = ::lscp_get_midi_instrument_map_name(m_pClient, iMidiMap);
1217                  ts << "# " << tr("MIDI instrument map") << " " << iMap;                  ts << "# " << tr("MIDI instrument map") << " " << iMap;
# Line 1016  bool MainForm::saveSessionFile ( const Q Line 1263  bool MainForm::saveSessionFile ( const Q
1263                  }                  }
1264                  ts << endl;                  ts << endl;
1265                  // Check for errors...                  // Check for errors...
1266                  if (pInstrs == NULL && ::lscp_client_get_errno(m_pClient)) {                  if (pInstrs == nullptr && ::lscp_client_get_errno(m_pClient)) {
1267                          appendMessagesClient("lscp_list_midi_instruments");                          appendMessagesClient("lscp_list_midi_instruments");
1268                          iErrors++;                          iErrors++;
1269                  }                  }
1270                  // MIDI strument index/id mapping.                  // MIDI strument index/id mapping.
1271                  midiInstrumentMap[iMidiMap] = iMap;                  midiInstrumentMap.insert(iMidiMap, iMap);
1272          }          }
1273          // Check for errors...          // Check for errors...
1274          if (piMaps == NULL && ::lscp_client_get_errno(m_pClient)) {          if (piMaps == nullptr && ::lscp_client_get_errno(m_pClient)) {
1275                  appendMessagesClient("lscp_list_midi_instrument_maps");                  appendMessagesClient("lscp_list_midi_instrument_maps");
1276                  iErrors++;                  iErrors++;
1277          }          }
1278  #endif  // CONFIG_MIDI_INSTRUMENT  #endif  // CONFIG_MIDI_INSTRUMENT
1279    
1280          // Sampler channel mapping.          // Sampler channel mapping...
1281          QWidgetList wlist = m_pWorkspace->windowList();          int iChannelID = 0;
1282          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          const QList<QMdiSubWindow *>& wlist
1283                  ChannelStrip* pChannelStrip                  = m_pWorkspace->subWindowList();
1284                          = static_cast<ChannelStrip *> (wlist.at(iChannel));          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
1285                    ChannelStrip *pChannelStrip
1286                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
1287                  if (pChannelStrip) {                  if (pChannelStrip) {
1288                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
1289                          if (pChannel) {                          if (pChannel) {
1290                                  ts << "# " << tr("Channel") << " " << iChannel << endl;                                  // Avoid "artifial" plug-in devices...
1291                                    const int iAudioDevice = pChannel->audioDevice();
1292                                    if (!audioDeviceMap.contains(iAudioDevice))
1293                                            continue;
1294                                    const int iMidiDevice = pChannel->midiDevice();
1295                                    if (!midiDeviceMap.contains(iMidiDevice))
1296                                            continue;
1297                                    // Go for regular, canonical devices...
1298                                    ts << "# " << tr("Channel") << " " << iChannelID << endl;
1299                                  ts << "ADD CHANNEL" << endl;                                  ts << "ADD CHANNEL" << endl;
1300                                  if (audioDeviceMap.isEmpty()) {                                  if (audioDeviceMap.isEmpty()) {
1301                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannelID
1302                                                  << " " << pChannel->audioDriver() << endl;                                                  << " " << pChannel->audioDriver() << endl;
1303                                  } else {                                  } else {
1304                                          ts << "SET CHANNEL AUDIO_OUTPUT_DEVICE " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_DEVICE " << iChannelID
1305                                                  << " " << audioDeviceMap[pChannel->audioDevice()] << endl;                                                  << " " << audioDeviceMap.value(iAudioDevice) << endl;
1306                                  }                                  }
1307                                  if (midiDeviceMap.isEmpty()) {                                  if (midiDeviceMap.isEmpty()) {
1308                                          ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannel                                          ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannelID
1309                                                  << " " << pChannel->midiDriver() << endl;                                                  << " " << pChannel->midiDriver() << endl;
1310                                  } else {                                  } else {
1311                                          ts << "SET CHANNEL MIDI_INPUT_DEVICE " << iChannel                                          ts << "SET CHANNEL MIDI_INPUT_DEVICE " << iChannelID
1312                                                  << " " << midiDeviceMap[pChannel->midiDevice()] << endl;                                                  << " " << midiDeviceMap.value(iMidiDevice) << endl;
1313                                  }                                  }
1314                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannelID
1315                                          << " " << pChannel->midiPort() << endl;                                          << " " << pChannel->midiPort() << endl;
1316                                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";                                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannelID << " ";
1317                                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)                                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
1318                                          ts << "ALL";                                          ts << "ALL";
1319                                  else                                  else
1320                                          ts << pChannel->midiChannel();                                          ts << pChannel->midiChannel();
1321                                  ts << endl;                                  ts << endl;
1322                                  ts << "LOAD ENGINE " << pChannel->engineName()                                  ts << "LOAD ENGINE " << pChannel->engineName()
1323                                          << " " << iChannel << endl;                                          << " " << iChannelID << endl;
1324                                  if (pChannel->instrumentStatus() < 100) ts << "# ";                                  if (pChannel->instrumentStatus() < 100) ts << "# ";
1325                                  ts << "LOAD INSTRUMENT NON_MODAL '"                                  ts << "LOAD INSTRUMENT NON_MODAL '"
1326                                          << pChannel->instrumentFile() << "' "                                          << pChannel->instrumentFile() << "' "
1327                                          << pChannel->instrumentNr() << " " << iChannel << endl;                                          << pChannel->instrumentNr() << " " << iChannelID << endl;
1328                                  qsamplerChannelRoutingMap::ConstIterator audioRoute;                                  ChannelRoutingMap::ConstIterator audioRoute;
1329                                  for (audioRoute = pChannel->audioRouting().begin();                                  for (audioRoute = pChannel->audioRouting().begin();
1330                                                  audioRoute != pChannel->audioRouting().end();                                                  audioRoute != pChannel->audioRouting().end();
1331                                                          ++audioRoute) {                                                          ++audioRoute) {
1332                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannelID
1333                                                  << " " << audioRoute.key()                                                  << " " << audioRoute.key()
1334                                                  << " " << audioRoute.value() << endl;                                                  << " " << audioRoute.value() << endl;
1335                                  }                                  }
1336                                  ts << "SET CHANNEL VOLUME " << iChannel                                  ts << "SET CHANNEL VOLUME " << iChannelID
1337                                          << " " << pChannel->volume() << endl;                                          << " " << pChannel->volume() << endl;
1338                                  if (pChannel->channelMute())                                  if (pChannel->channelMute())
1339                                          ts << "SET CHANNEL MUTE " << iChannel << " 1" << endl;                                          ts << "SET CHANNEL MUTE " << iChannelID << " 1" << endl;
1340                                  if (pChannel->channelSolo())                                  if (pChannel->channelSolo())
1341                                          ts << "SET CHANNEL SOLO " << iChannel << " 1" << endl;                                          ts << "SET CHANNEL SOLO " << iChannelID << " 1" << endl;
1342  #ifdef CONFIG_MIDI_INSTRUMENT                          #ifdef CONFIG_MIDI_INSTRUMENT
1343                                  if (pChannel->midiMap() >= 0) {                                  const int iMidiMap = pChannel->midiMap();
1344                                          ts << "SET CHANNEL MIDI_INSTRUMENT_MAP " << iChannel                                  if (midiInstrumentMap.contains(iMidiMap)) {
1345                                                  << " " << midiInstrumentMap[pChannel->midiMap()] << endl;                                          ts << "SET CHANNEL MIDI_INSTRUMENT_MAP " << iChannelID
1346                                                    << " " << midiInstrumentMap.value(iMidiMap) << endl;
1347                                  }                                  }
1348  #endif                          #endif
1349  #ifdef CONFIG_FXSEND                          #ifdef CONFIG_FXSEND
                                 int iChannelID = pChannel->channelID();  
1350                                  int *piFxSends = ::lscp_list_fxsends(m_pClient, iChannelID);                                  int *piFxSends = ::lscp_list_fxsends(m_pClient, iChannelID);
1351                                  for (int iFxSend = 0;                                  for (int iFxSend = 0;
1352                                                  piFxSends && piFxSends[iFxSend] >= 0;                                                  piFxSends && piFxSends[iFxSend] >= 0;
# Line 1097  bool MainForm::saveSessionFile ( const Q Line 1354  bool MainForm::saveSessionFile ( const Q
1354                                          lscp_fxsend_info_t *pFxSendInfo = ::lscp_get_fxsend_info(                                          lscp_fxsend_info_t *pFxSendInfo = ::lscp_get_fxsend_info(
1355                                                  m_pClient, iChannelID, piFxSends[iFxSend]);                                                  m_pClient, iChannelID, piFxSends[iFxSend]);
1356                                          if (pFxSendInfo) {                                          if (pFxSendInfo) {
1357                                                  ts << "CREATE FX_SEND " << iChannel                                                  ts << "CREATE FX_SEND " << iChannelID
1358                                                          << " " << pFxSendInfo->midi_controller;                                                          << " " << pFxSendInfo->midi_controller;
1359                                                  if (pFxSendInfo->name)                                                  if (pFxSendInfo->name)
1360                                                          ts << " '" << pFxSendInfo->name << "'";                                                          ts << " '" << pFxSendInfo->name << "'";
# Line 1107  bool MainForm::saveSessionFile ( const Q Line 1364  bool MainForm::saveSessionFile ( const Q
1364                                                                  piRouting && piRouting[iAudioSrc] >= 0;                                                                  piRouting && piRouting[iAudioSrc] >= 0;
1365                                                                          iAudioSrc++) {                                                                          iAudioSrc++) {
1366                                                          ts << "SET FX_SEND AUDIO_OUTPUT_CHANNEL "                                                          ts << "SET FX_SEND AUDIO_OUTPUT_CHANNEL "
1367                                                                  << iChannel                                                                  << iChannelID
1368                                                                  << " " << iFxSend                                                                  << " " << iFxSend
1369                                                                  << " " << iAudioSrc                                                                  << " " << iAudioSrc
1370                                                                  << " " << piRouting[iAudioSrc] << endl;                                                                  << " " << piRouting[iAudioSrc] << endl;
1371                                                  }                                                  }
1372  #ifdef CONFIG_FXSEND_LEVEL                                          #ifdef CONFIG_FXSEND_LEVEL
1373                                                  ts << "SET FX_SEND LEVEL " << iChannel                                                  ts << "SET FX_SEND LEVEL " << iChannelID
1374                                                          << " " << iFxSend                                                          << " " << iFxSend
1375                                                          << " " << pFxSendInfo->level << endl;                                                          << " " << pFxSendInfo->level << endl;
1376  #endif                                          #endif
1377                                          }       // Check for errors...                                          }       // Check for errors...
1378                                          else if (::lscp_client_get_errno(m_pClient)) {                                          else if (::lscp_client_get_errno(m_pClient)) {
1379                                                  appendMessagesClient("lscp_get_fxsend_info");                                                  appendMessagesClient("lscp_get_fxsend_info");
1380                                                  iErrors++;                                                  iErrors++;
1381                                          }                                          }
1382                                  }                                  }
1383  #endif                          #endif
1384                                  ts << endl;                                  ts << endl;
1385                                    // Go for next channel...
1386                                    ++iChannelID;
1387                          }                          }
1388                  }                  }
1389                  // Try to keep it snappy :)                  // Try to keep it snappy :)
# Line 1176  void MainForm::sessionDirty (void) Line 1435  void MainForm::sessionDirty (void)
1435    
1436    
1437  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1438  // qsamplerMainForm -- File Action slots.  // QSampler::MainForm -- File Action slots.
1439    
1440  // Create a new sampler session.  // Create a new sampler session.
1441  void MainForm::fileNew (void)  void MainForm::fileNew (void)
# Line 1200  void MainForm::fileOpenRecent (void) Line 1459  void MainForm::fileOpenRecent (void)
1459          // Retrive filename index from action data...          // Retrive filename index from action data...
1460          QAction *pAction = qobject_cast<QAction *> (sender());          QAction *pAction = qobject_cast<QAction *> (sender());
1461          if (pAction && m_pOptions) {          if (pAction && m_pOptions) {
1462                  int iIndex = pAction->data().toInt();                  const int iIndex = pAction->data().toInt();
1463                  if (iIndex >= 0 && iIndex < m_pOptions->recentFiles.count()) {                  if (iIndex >= 0 && iIndex < m_pOptions->recentFiles.count()) {
1464                          QString sFilename = m_pOptions->recentFiles[iIndex];                          QString sFilename = m_pOptions->recentFiles[iIndex];
1465                          // Check if we can safely close the current session...                          // Check if we can safely close the current session...
# Line 1230  void MainForm::fileSaveAs (void) Line 1489  void MainForm::fileSaveAs (void)
1489  // Reset the sampler instance.  // Reset the sampler instance.
1490  void MainForm::fileReset (void)  void MainForm::fileReset (void)
1491  {  {
1492          if (m_pClient == NULL)          if (m_pClient == nullptr)
1493                  return;                  return;
1494    
1495          // Ask user whether he/she want's an internal sampler reset...          // Ask user whether he/she want's an internal sampler reset...
1496          if (QMessageBox::warning(this,          if (m_pOptions && m_pOptions->bConfirmReset) {
1497                  QSAMPLER_TITLE ": " + tr("Warning"),                  const QString& sTitle = tr("Warning");
1498                  tr("Resetting the sampler instance will close\n"                  const QString& sText = tr(
1499                  "all device and channel configurations.\n\n"                          "Resetting the sampler instance will close\n"
1500                  "Please note that this operation may cause\n"                          "all device and channel configurations.\n\n"
1501                  "temporary MIDI and Audio disruption.\n\n"                          "Please note that this operation may cause\n"
1502                  "Do you want to reset the sampler engine now?"),                          "temporary MIDI and Audio disruption.\n\n"
1503                  tr("Reset"), tr("Cancel")) > 0)                          "Do you want to reset the sampler engine now?");
1504                  return;          #if 0
1505                    if (QMessageBox::warning(this, sTitle, sText,
1506                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1507                            return;
1508            #else
1509                    QMessageBox mbox(this);
1510                    mbox.setIcon(QMessageBox::Warning);
1511                    mbox.setWindowTitle(sTitle);
1512                    mbox.setText(sText);
1513                    mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1514                    QCheckBox cbox(tr("Don't ask this again"));
1515                    cbox.setChecked(false);
1516                    cbox.blockSignals(true);
1517                    mbox.addButton(&cbox, QMessageBox::ActionRole);
1518                    if (mbox.exec() == QMessageBox::Cancel)
1519                            return;
1520                    if (cbox.isChecked())
1521                            m_pOptions->bConfirmReset = false;
1522            #endif
1523            }
1524    
1525          // Trye closing the current session, first...          // Trye closing the current session, first...
1526          if (!closeSession(true))          if (!closeSession(true))
# Line 1267  void MainForm::fileReset (void) Line 1545  void MainForm::fileReset (void)
1545  // Restart the client/server instance.  // Restart the client/server instance.
1546  void MainForm::fileRestart (void)  void MainForm::fileRestart (void)
1547  {  {
1548          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
1549                  return;                  return;
1550    
1551          bool bRestart = true;          bool bRestart = true;
1552    
1553          // Ask user whether he/she want's a complete restart...          // Ask user whether he/she want's a complete restart...
1554          // (if we're currently up and running)          // (if we're currently up and running)
1555          if (bRestart && m_pClient) {          if (m_pOptions && m_pOptions->bConfirmRestart) {
1556                  bRestart = (QMessageBox::warning(this,                  const QString& sTitle = tr("Warning");
1557                          QSAMPLER_TITLE ": " + tr("Warning"),                  const QString& sText = tr(
1558                          tr("New settings will be effective after\n"                          "New settings will be effective after\n"
1559                          "restarting the client/server connection.\n\n"                          "restarting the client/server connection.\n\n"
1560                          "Please note that this operation may cause\n"                          "Please note that this operation may cause\n"
1561                          "temporary MIDI and Audio disruption.\n\n"                          "temporary MIDI and Audio disruption.\n\n"
1562                          "Do you want to restart the connection now?"),                          "Do you want to restart the connection now?");
1563                          tr("Restart"), tr("Cancel")) == 0);          #if 0
1564                    if (QMessageBox::warning(this, sTitle, sText,
1565                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1566                            bRestart = false;
1567            #else
1568                    QMessageBox mbox(this);
1569                    mbox.setIcon(QMessageBox::Warning);
1570                    mbox.setWindowTitle(sTitle);
1571                    mbox.setText(sText);
1572                    mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1573                    QCheckBox cbox(tr("Don't ask this again"));
1574                    cbox.setChecked(false);
1575                    cbox.blockSignals(true);
1576                    mbox.addButton(&cbox, QMessageBox::ActionRole);
1577                    if (mbox.exec() == QMessageBox::Cancel)
1578                            bRestart = false;
1579                    else
1580                    if (cbox.isChecked())
1581                            m_pOptions->bConfirmRestart = false;
1582            #endif
1583          }          }
1584    
1585          // Are we still for it?          // Are we still for it?
# Line 1304  void MainForm::fileExit (void) Line 1601  void MainForm::fileExit (void)
1601    
1602    
1603  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1604  // qsamplerMainForm -- Edit Action slots.  // QSampler::MainForm -- Edit Action slots.
1605    
1606  // Add a new sampler channel.  // Add a new sampler channel.
1607  void MainForm::editAddChannel (void)  void MainForm::editAddChannel (void)
1608  {  {
1609          if (m_pClient == NULL)          ++m_iDirtySetup;
1610            addChannelStrip();
1611            --m_iDirtySetup;
1612    }
1613    
1614    void MainForm::addChannelStrip (void)
1615    {
1616            if (m_pClient == nullptr)
1617                  return;                  return;
1618    
1619          // Just create the channel instance...          // Just create the channel instance...
1620          qsamplerChannel *pChannel = new qsamplerChannel();          Channel *pChannel = new Channel();
1621          if (pChannel == NULL)          if (pChannel == nullptr)
1622                  return;                  return;
1623    
1624          // Before we show it up, may be we'll          // Before we show it up, may be we'll
# Line 1331  void MainForm::editAddChannel (void) Line 1635  void MainForm::editAddChannel (void)
1635                  return;                  return;
1636          }          }
1637    
1638            // Do we auto-arrange?
1639            channelsArrangeAuto();
1640    
1641          // Make that an overall update.          // Make that an overall update.
1642          m_iDirtyCount++;          m_iDirtyCount++;
1643          stabilizeForm();          stabilizeForm();
# Line 1340  void MainForm::editAddChannel (void) Line 1647  void MainForm::editAddChannel (void)
1647  // Remove current sampler channel.  // Remove current sampler channel.
1648  void MainForm::editRemoveChannel (void)  void MainForm::editRemoveChannel (void)
1649  {  {
1650          if (m_pClient == NULL)          ++m_iDirtySetup;
1651            removeChannelStrip();
1652            --m_iDirtySetup;
1653    }
1654    
1655    void MainForm::removeChannelStrip (void)
1656    {
1657            if (m_pClient == nullptr)
1658                  return;                  return;
1659    
1660          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1661          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
1662                  return;                  return;
1663    
1664          qsamplerChannel *pChannel = pChannelStrip->channel();          Channel *pChannel = pChannelStrip->channel();
1665          if (pChannel == NULL)          if (pChannel == nullptr)
1666                  return;                  return;
1667    
1668          // Prompt user if he/she's sure about this...          // Prompt user if he/she's sure about this...
1669          if (m_pOptions && m_pOptions->bConfirmRemove) {          if (m_pOptions && m_pOptions->bConfirmRemove) {
1670                  if (QMessageBox::warning(this,                  const QString& sTitle = tr("Warning");
1671                          QSAMPLER_TITLE ": " + tr("Warning"),                  const QString& sText = tr(
1672                          tr("About to remove channel:\n\n"                          "About to remove channel:\n\n"
1673                          "%1\n\n"                          "%1\n\n"
1674                          "Are you sure?")                          "Are you sure?")
1675                          .arg(pChannelStrip->windowTitle()),                          .arg(pChannelStrip->windowTitle());
1676                          tr("OK"), tr("Cancel")) > 0)          #if 0
1677                    if (QMessageBox::warning(this, sTitle, sText,
1678                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1679                          return;                          return;
1680            #else
1681                    QMessageBox mbox(this);
1682                    mbox.setIcon(QMessageBox::Warning);
1683                    mbox.setWindowTitle(sTitle);
1684                    mbox.setText(sText);
1685                    mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1686                    QCheckBox cbox(tr("Don't ask this again"));
1687                    cbox.setChecked(false);
1688                    cbox.blockSignals(true);
1689                    mbox.addButton(&cbox, QMessageBox::ActionRole);
1690                    if (mbox.exec() == QMessageBox::Cancel)
1691                            return;
1692                    if (cbox.isChecked())
1693                            m_pOptions->bConfirmRemove = false;
1694            #endif
1695          }          }
1696    
1697          // Remove the existing sampler channel.          // Remove the existing sampler channel.
# Line 1368  void MainForm::editRemoveChannel (void) Line 1699  void MainForm::editRemoveChannel (void)
1699                  return;                  return;
1700    
1701          // Just delete the channel strip.          // Just delete the channel strip.
1702          delete pChannelStrip;          destroyChannelStrip(pChannelStrip);
   
         // Do we auto-arrange?  
         if (m_pOptions && m_pOptions->bAutoArrange)  
                 channelsArrange();  
1703    
1704          // We'll be dirty, for sure...          // We'll be dirty, for sure...
1705          m_iDirtyCount++;          m_iDirtyCount++;
# Line 1383  void MainForm::editRemoveChannel (void) Line 1710  void MainForm::editRemoveChannel (void)
1710  // Setup current sampler channel.  // Setup current sampler channel.
1711  void MainForm::editSetupChannel (void)  void MainForm::editSetupChannel (void)
1712  {  {
1713          if (m_pClient == NULL)          if (m_pClient == nullptr)
1714                  return;                  return;
1715    
1716          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1717          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
1718                  return;                  return;
1719    
1720          // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
# Line 1398  void MainForm::editSetupChannel (void) Line 1725  void MainForm::editSetupChannel (void)
1725  // Edit current sampler channel.  // Edit current sampler channel.
1726  void MainForm::editEditChannel (void)  void MainForm::editEditChannel (void)
1727  {  {
1728          if (m_pClient == NULL)          if (m_pClient == nullptr)
1729                  return;                  return;
1730    
1731          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1732          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
1733                  return;                  return;
1734    
1735          // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
# Line 1413  void MainForm::editEditChannel (void) Line 1740  void MainForm::editEditChannel (void)
1740  // Reset current sampler channel.  // Reset current sampler channel.
1741  void MainForm::editResetChannel (void)  void MainForm::editResetChannel (void)
1742  {  {
1743          if (m_pClient == NULL)          if (m_pClient == nullptr)
1744                  return;                  return;
1745    
1746          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1747          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
1748                  return;                  return;
1749    
1750          // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
# Line 1428  void MainForm::editResetChannel (void) Line 1755  void MainForm::editResetChannel (void)
1755  // Reset all sampler channels.  // Reset all sampler channels.
1756  void MainForm::editResetAllChannels (void)  void MainForm::editResetAllChannels (void)
1757  {  {
1758          if (m_pClient == NULL)          if (m_pClient == nullptr)
1759                  return;                  return;
1760    
1761          // Invoque the channel strip procedure,          // Invoque the channel strip procedure,
1762          // for all channels out there...          // for all channels out there...
1763          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
1764          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
1765          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  = m_pWorkspace->subWindowList();
1766                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
1767                    ChannelStrip *pChannelStrip
1768                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
1769                  if (pChannelStrip)                  if (pChannelStrip)
1770                          pChannelStrip->channelReset();                          pChannelStrip->channelReset();
1771          }          }
# Line 1445  void MainForm::editResetAllChannels (voi Line 1774  void MainForm::editResetAllChannels (voi
1774    
1775    
1776  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1777  // qsamplerMainForm -- View Action slots.  // QSampler::MainForm -- View Action slots.
1778    
1779  // Show/hide the main program window menubar.  // Show/hide the main program window menubar.
1780  void MainForm::viewMenubar ( bool bOn )  void MainForm::viewMenubar ( bool bOn )
# Line 1495  void MainForm::viewMessages ( bool bOn ) Line 1824  void MainForm::viewMessages ( bool bOn )
1824  // Show/hide the MIDI instrument list-view form.  // Show/hide the MIDI instrument list-view form.
1825  void MainForm::viewInstruments (void)  void MainForm::viewInstruments (void)
1826  {  {
1827          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
1828                  return;                  return;
1829    
1830          if (m_pInstrumentListForm) {          if (m_pInstrumentListForm) {
# Line 1514  void MainForm::viewInstruments (void) Line 1843  void MainForm::viewInstruments (void)
1843  // Show/hide the device configurator form.  // Show/hide the device configurator form.
1844  void MainForm::viewDevices (void)  void MainForm::viewDevices (void)
1845  {  {
1846          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
1847                  return;                  return;
1848    
1849          if (m_pDeviceForm) {          if (m_pDeviceForm) {
# Line 1533  void MainForm::viewDevices (void) Line 1862  void MainForm::viewDevices (void)
1862  // Show options dialog.  // Show options dialog.
1863  void MainForm::viewOptions (void)  void MainForm::viewOptions (void)
1864  {  {
1865          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
1866                  return;                  return;
1867    
1868          OptionsForm* pOptionsForm = new OptionsForm(this);          OptionsForm* pOptionsForm = new OptionsForm(this);
1869          if (pOptionsForm) {          if (pOptionsForm) {
1870                  // Check out some initial nullities(tm)...                  // Check out some initial nullities(tm)...
1871                  ChannelStrip* pChannelStrip = activeChannelStrip();                  ChannelStrip *pChannelStrip = activeChannelStrip();
1872                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)
1873                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();
1874                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)
1875                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
1876                  // To track down deferred or immediate changes.                  // To track down deferred or immediate changes.
1877                  QString sOldServerHost      = m_pOptions->sServerHost;                  const QString sOldServerHost      = m_pOptions->sServerHost;
1878                  int     iOldServerPort      = m_pOptions->iServerPort;                  const int     iOldServerPort      = m_pOptions->iServerPort;
1879                  int     iOldServerTimeout   = m_pOptions->iServerTimeout;                  const int     iOldServerTimeout   = m_pOptions->iServerTimeout;
1880                  bool    bOldServerStart     = m_pOptions->bServerStart;                  const bool    bOldServerStart     = m_pOptions->bServerStart;
1881                  QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;                  const QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;
1882                  QString sOldDisplayFont     = m_pOptions->sDisplayFont;                  const bool    bOldMessagesLog     = m_pOptions->bMessagesLog;
1883                  bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;                  const QString sOldMessagesLogPath = m_pOptions->sMessagesLogPath;
1884                  int     iOldMaxVolume       = m_pOptions->iMaxVolume;                  const QString sOldDisplayFont     = m_pOptions->sDisplayFont;
1885                  QString sOldMessagesFont    = m_pOptions->sMessagesFont;                  const bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;
1886                  bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;                  const int     iOldMaxVolume       = m_pOptions->iMaxVolume;
1887                  bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;                  const QString sOldMessagesFont    = m_pOptions->sMessagesFont;
1888                  int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;                  const bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;
1889                  int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;                  const bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;
1890                  bool    bOldCompletePath    = m_pOptions->bCompletePath;                  const int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;
1891                  bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;                  const int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;
1892                  int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;                  const bool    bOldCompletePath    = m_pOptions->bCompletePath;
1893                    const bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;
1894                    const int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;
1895                    const int     iOldBaseFontSize    = m_pOptions->iBaseFontSize;
1896                  // Load the current setup settings.                  // Load the current setup settings.
1897                  pOptionsForm->setup(m_pOptions);                  pOptionsForm->setup(m_pOptions);
1898                  // Show the setup dialog...                  // Show the setup dialog...
# Line 1569  void MainForm::viewOptions (void) Line 1901  void MainForm::viewOptions (void)
1901                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1902                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||
1903                                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||                                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||
1904                                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {                                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)     ||
1905                                    (iOldBaseFontSize   !=  m_pOptions->iBaseFontSize)) {
1906                                  QMessageBox::information(this,                                  QMessageBox::information(this,
1907                                          QSAMPLER_TITLE ": " + tr("Information"),                                          tr("Information"),
1908                                          tr("Some settings may be only effective\n"                                          tr("Some settings may be only effective\n"
1909                                          "next time you start this program."), tr("OK"));                                          "next time you start this program."));
1910                                  updateMessagesCapture();                                  updateMessagesCapture();
1911                          }                          }
1912                          // Check wheather something immediate has changed.                          // Check wheather something immediate has changed.
1913                            if (( bOldMessagesLog && !m_pOptions->bMessagesLog) ||
1914                                    (!bOldMessagesLog &&  m_pOptions->bMessagesLog) ||
1915                                    (sOldMessagesLogPath != m_pOptions->sMessagesLogPath))
1916                                    m_pMessages->setLogging(
1917                                            m_pOptions->bMessagesLog, m_pOptions->sMessagesLogPath);
1918                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||
1919                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||
1920                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
# Line 1617  void MainForm::viewOptions (void) Line 1955  void MainForm::viewOptions (void)
1955    
1956    
1957  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1958  // qsamplerMainForm -- Channels action slots.  // QSampler::MainForm -- Channels action slots.
1959    
1960  // Arrange channel strips.  // Arrange channel strips.
1961  void MainForm::channelsArrange (void)  void MainForm::channelsArrange (void)
1962  {  {
1963          // Full width vertical tiling          // Full width vertical tiling
1964          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
1965                    = m_pWorkspace->subWindowList();
1966          if (wlist.isEmpty())          if (wlist.isEmpty())
1967                  return;                  return;
1968    
1969          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
1970          int y = 0;          int y = 0;
1971          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
1972                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  pMdiSubWindow->adjustSize();
1973          /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {                  const QRect& frameRect
1974                          // Prevent flicker...                          = pMdiSubWindow->frameGeometry();
1975                          pChannelStrip->hide();                  int w = m_pWorkspace->width();
1976                          pChannelStrip->showNormal();                  if (w < frameRect.width())
1977                  }   */                          w = frameRect.width();
1978                  pChannelStrip->adjustSize();                  const int h = frameRect.height();
1979                  int iWidth  = m_pWorkspace->width();                  pMdiSubWindow->setGeometry(0, y, w, h);
1980                  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;  
1981          }          }
1982          m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
1983    
# Line 1655  void MainForm::channelsArrange (void) Line 1988  void MainForm::channelsArrange (void)
1988  // Auto-arrange channel strips.  // Auto-arrange channel strips.
1989  void MainForm::channelsAutoArrange ( bool bOn )  void MainForm::channelsAutoArrange ( bool bOn )
1990  {  {
1991          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
1992                  return;                  return;
1993    
1994          // Toggle the auto-arrange flag.          // Toggle the auto-arrange flag.
1995          m_pOptions->bAutoArrange = bOn;          m_pOptions->bAutoArrange = bOn;
1996    
1997          // If on, update whole workspace...          // If on, update whole workspace...
1998          if (m_pOptions->bAutoArrange)          channelsArrangeAuto();
1999    }
2000    
2001    
2002    void MainForm::channelsArrangeAuto (void)
2003    {
2004            if (m_pOptions && m_pOptions->bAutoArrange)
2005                  channelsArrange();                  channelsArrange();
2006  }  }
2007    
2008    
2009  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2010  // qsamplerMainForm -- Help Action slots.  // QSampler::MainForm -- Help Action slots.
2011    
2012  // Show information about the Qt toolkit.  // Show information about the Qt toolkit.
2013  void MainForm::helpAboutQt (void)  void MainForm::helpAboutQt (void)
# Line 1680  void MainForm::helpAboutQt (void) Line 2019  void MainForm::helpAboutQt (void)
2019  // Show information about application program.  // Show information about application program.
2020  void MainForm::helpAbout (void)  void MainForm::helpAbout (void)
2021  {  {
2022          // 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";  
2023  #ifdef CONFIG_DEBUG  #ifdef CONFIG_DEBUG
2024          sText += "<small><font color=\"red\">";          list << tr("Debugging option enabled.");
         sText += tr("Debugging option enabled.");  
         sText += "</font></small><br />";  
2025  #endif  #endif
2026  #ifndef CONFIG_LIBGIG  #ifndef CONFIG_LIBGIG
2027          sText += "<small><font color=\"red\">";          list << tr("GIG (libgig) file support disabled.");
         sText += tr("GIG (libgig) file support disabled.");  
         sText += "</font></small><br />";  
2028  #endif  #endif
2029  #ifndef CONFIG_INSTRUMENT_NAME  #ifndef CONFIG_INSTRUMENT_NAME
2030          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 />";  
2031  #endif  #endif
2032  #ifndef CONFIG_MUTE_SOLO  #ifndef CONFIG_MUTE_SOLO
2033          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 />";  
2034  #endif  #endif
2035  #ifndef CONFIG_AUDIO_ROUTING  #ifndef CONFIG_AUDIO_ROUTING
2036          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 />";  
2037  #endif  #endif
2038  #ifndef CONFIG_FXSEND  #ifndef CONFIG_FXSEND
2039          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 />";  
2040  #endif  #endif
2041  #ifndef CONFIG_VOLUME  #ifndef CONFIG_VOLUME
2042          sText += "<small><font color=\"red\">";          list << tr("Global volume support disabled.");
         sText += tr("Global volume support disabled.");  
         sText += "</font></small><br />";  
2043  #endif  #endif
2044  #ifndef CONFIG_MIDI_INSTRUMENT  #ifndef CONFIG_MIDI_INSTRUMENT
2045          sText += "<small><font color=\"red\">";          list << tr("MIDI instrument mapping support disabled.");
         sText += tr("MIDI instrument mapping support disabled.");  
         sText += "</font></small><br />";  
2046  #endif  #endif
2047  #ifndef CONFIG_EDIT_INSTRUMENT  #ifndef CONFIG_EDIT_INSTRUMENT
2048          sText += "<small><font color=\"red\">";          list << tr("Instrument editing support disabled.");
2049          sText += tr("Instrument editing support disabled.");  #endif
2050          sText += "</font></small><br />";  #ifndef CONFIG_EVENT_CHANNEL_MIDI
2051            list << tr("Channel MIDI event support disabled.");
2052    #endif
2053    #ifndef CONFIG_EVENT_DEVICE_MIDI
2054            list << tr("Device MIDI event support disabled.");
2055  #endif  #endif
2056    #ifndef CONFIG_MAX_VOICES
2057            list << tr("Runtime max. voices / disk streams support disabled.");
2058    #endif
2059    
2060            // Stuff the about box text...
2061            QString sText = "<p>\n";
2062            sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";
2063            sText += "<br />\n";
2064            sText += tr("Version") + ": <b>" CONFIG_BUILD_VERSION "</b><br />\n";
2065    //      sText += "<small>" + tr("Build") + ": " CONFIG_BUILD_DATE "</small><br />\n";
2066            if (!list.isEmpty()) {
2067                    sText += "<small><font color=\"red\">";
2068                    sText += list.join("<br />\n");
2069                    sText += "</font></small>";
2070            }
2071          sText += "<br />\n";          sText += "<br />\n";
2072          sText += tr("Using") + ": ";          sText += tr("Using") + ": ";
2073          sText += ::lscp_client_package();          sText += ::lscp_client_package();
# Line 1755  void MainForm::helpAbout (void) Line 2092  void MainForm::helpAbout (void)
2092          sText += "</small>";          sText += "</small>";
2093          sText += "</p>\n";          sText += "</p>\n";
2094    
2095          QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);          QMessageBox::about(this, tr("About"), sText);
2096  }  }
2097    
2098    
2099  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2100  // qsamplerMainForm -- Main window stabilization.  // QSampler::MainForm -- Main window stabilization.
2101    
2102  void MainForm::stabilizeForm (void)  void MainForm::stabilizeForm (void)
2103  {  {
# Line 1768  void MainForm::stabilizeForm (void) Line 2105  void MainForm::stabilizeForm (void)
2105          QString sSessionName = sessionName(m_sFilename);          QString sSessionName = sessionName(m_sFilename);
2106          if (m_iDirtyCount > 0)          if (m_iDirtyCount > 0)
2107                  sSessionName += " *";                  sSessionName += " *";
2108          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));          setWindowTitle(sSessionName);
2109    
2110          // Update the main menu state...          // Update the main menu state...
2111          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
2112          bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);          const QList<QMdiSubWindow *>& wlist = m_pWorkspace->subWindowList();
2113          bool bHasChannel = (bHasClient && pChannelStrip != NULL);          const bool bHasClient = (m_pOptions != nullptr && m_pClient != nullptr);
2114            const bool bHasChannel = (bHasClient && pChannelStrip != nullptr);
2115            const bool bHasChannels = (bHasClient && wlist.count() > 0);
2116          m_ui.fileNewAction->setEnabled(bHasClient);          m_ui.fileNewAction->setEnabled(bHasClient);
2117          m_ui.fileOpenAction->setEnabled(bHasClient);          m_ui.fileOpenAction->setEnabled(bHasClient);
2118          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
2119          m_ui.fileSaveAsAction->setEnabled(bHasClient);          m_ui.fileSaveAsAction->setEnabled(bHasClient);
2120          m_ui.fileResetAction->setEnabled(bHasClient);          m_ui.fileResetAction->setEnabled(bHasClient);
2121          m_ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);          m_ui.fileRestartAction->setEnabled(bHasClient || m_pServer == nullptr);
2122          m_ui.editAddChannelAction->setEnabled(bHasClient);          m_ui.editAddChannelAction->setEnabled(bHasClient);
2123          m_ui.editRemoveChannelAction->setEnabled(bHasChannel);          m_ui.editRemoveChannelAction->setEnabled(bHasChannel);
2124          m_ui.editSetupChannelAction->setEnabled(bHasChannel);          m_ui.editSetupChannelAction->setEnabled(bHasChannel);
# Line 1789  void MainForm::stabilizeForm (void) Line 2128  void MainForm::stabilizeForm (void)
2128          m_ui.editEditChannelAction->setEnabled(false);          m_ui.editEditChannelAction->setEnabled(false);
2129  #endif  #endif
2130          m_ui.editResetChannelAction->setEnabled(bHasChannel);          m_ui.editResetChannelAction->setEnabled(bHasChannel);
2131          m_ui.editResetAllChannelsAction->setEnabled(bHasChannel);          m_ui.editResetAllChannelsAction->setEnabled(bHasChannels);
2132          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());
2133  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
2134          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm
# Line 1801  void MainForm::stabilizeForm (void) Line 2140  void MainForm::stabilizeForm (void)
2140          m_ui.viewDevicesAction->setChecked(m_pDeviceForm          m_ui.viewDevicesAction->setChecked(m_pDeviceForm
2141                  && m_pDeviceForm->isVisible());                  && m_pDeviceForm->isVisible());
2142          m_ui.viewDevicesAction->setEnabled(bHasClient);          m_ui.viewDevicesAction->setEnabled(bHasClient);
2143          m_ui.channelsArrangeAction->setEnabled(bHasChannel);          m_ui.viewMidiDeviceStatusMenu->setEnabled(
2144                    DeviceStatusForm::getInstances().size() > 0);
2145            m_ui.channelsArrangeAction->setEnabled(bHasChannels);
2146    
2147  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2148          // Toolbar widgets are also affected...          // Toolbar widgets are also affected...
# Line 1851  void MainForm::volumeChanged ( int iVolu Line 2192  void MainForm::volumeChanged ( int iVolu
2192                  m_pVolumeSpinBox->setValue(iVolume);                  m_pVolumeSpinBox->setValue(iVolume);
2193    
2194          // Do it as commanded...          // Do it as commanded...
2195          float fVolume = 0.01f * float(iVolume);          const float fVolume = 0.01f * float(iVolume);
2196          if (::lscp_set_volume(m_pClient, fVolume) == LSCP_OK)          if (::lscp_set_volume(m_pClient, fVolume) == LSCP_OK)
2197                  appendMessages(QObject::tr("Volume: %1.").arg(fVolume));                  appendMessages(QObject::tr("Volume: %1.").arg(fVolume));
2198          else          else
# Line 1867  void MainForm::volumeChanged ( int iVolu Line 2208  void MainForm::volumeChanged ( int iVolu
2208    
2209    
2210  // Channel change receiver slot.  // Channel change receiver slot.
2211  void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)  void MainForm::channelStripChanged ( ChannelStrip *pChannelStrip )
2212  {  {
2213          // Add this strip to the changed list...          // Add this strip to the changed list...
2214          if (!m_changedStrips.contains(pChannelStrip)) {          if (!m_changedStrips.contains(pChannelStrip)) {
# Line 1886  void MainForm::channelStripChanged(Chann Line 2227  void MainForm::channelStripChanged(Chann
2227  void MainForm::updateSession (void)  void MainForm::updateSession (void)
2228  {  {
2229  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2230          int iVolume = ::lroundf(100.0f * ::lscp_get_volume(m_pClient));          const int iVolume = ::lroundf(100.0f * ::lscp_get_volume(m_pClient));
2231          m_iVolumeChanging++;          m_iVolumeChanging++;
2232          m_pVolumeSlider->setValue(iVolume);          m_pVolumeSlider->setValue(iVolume);
2233          m_pVolumeSpinBox->setValue(iVolume);          m_pVolumeSpinBox->setValue(iVolume);
# Line 1894  void MainForm::updateSession (void) Line 2235  void MainForm::updateSession (void)
2235  #endif  #endif
2236  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
2237          // FIXME: Make some room for default instrument maps...          // FIXME: Make some room for default instrument maps...
2238          int iMaps = ::lscp_get_midi_instrument_maps(m_pClient);          const int iMaps = ::lscp_get_midi_instrument_maps(m_pClient);
2239          if (iMaps < 0)          if (iMaps < 0)
2240                  appendMessagesClient("lscp_get_midi_instrument_maps");                  appendMessagesClient("lscp_get_midi_instrument_maps");
2241          else if (iMaps < 1) {          else if (iMaps < 1) {
# Line 1905  void MainForm::updateSession (void) Line 2246  void MainForm::updateSession (void)
2246          }          }
2247  #endif  #endif
2248    
2249            updateAllChannelStrips(false);
2250    
2251            // Do we auto-arrange?
2252            channelsArrangeAuto();
2253    
2254            // Remember to refresh devices and instruments...
2255            if (m_pInstrumentListForm)
2256                    m_pInstrumentListForm->refreshInstruments();
2257            if (m_pDeviceForm)
2258                    m_pDeviceForm->refreshDevices();
2259    }
2260    
2261    
2262    void MainForm::updateAllChannelStrips ( bool bRemoveDeadStrips )
2263    {
2264            // Skip if setting up a new channel strip...
2265            if (m_iDirtySetup > 0)
2266                    return;
2267    
2268          // Retrieve the current channel list.          // Retrieve the current channel list.
2269          int *piChannelIDs = ::lscp_list_channels(m_pClient);          int *piChannelIDs = ::lscp_list_channels(m_pClient);
2270          if (piChannelIDs == NULL) {          if (piChannelIDs == nullptr) {
2271                  if (::lscp_client_get_errno(m_pClient)) {                  if (::lscp_client_get_errno(m_pClient)) {
2272                          appendMessagesClient("lscp_list_channels");                          appendMessagesClient("lscp_list_channels");
2273                          appendMessagesError(                          appendMessagesError(
# Line 1916  void MainForm::updateSession (void) Line 2276  void MainForm::updateSession (void)
2276          } else {          } else {
2277                  // Try to (re)create each channel.                  // Try to (re)create each channel.
2278                  m_pWorkspace->setUpdatesEnabled(false);                  m_pWorkspace->setUpdatesEnabled(false);
2279                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; ++iChannel) {
2280                          // Check if theres already a channel strip for this one...                          // Check if theres already a channel strip for this one...
2281                          if (!channelStrip(piChannelIDs[iChannel]))                          if (!channelStrip(piChannelIDs[iChannel]))
2282                                  createChannelStrip(new qsamplerChannel(piChannelIDs[iChannel]));                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));
2283                    }
2284                    // Do we auto-arrange?
2285                    channelsArrangeAuto();
2286                    // remove dead channel strips
2287                    if (bRemoveDeadStrips) {
2288                            const QList<QMdiSubWindow *>& wlist
2289                                    = m_pWorkspace->subWindowList();
2290                            foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2291                                    ChannelStrip *pChannelStrip
2292                                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2293                                    if (pChannelStrip) {
2294                                            bool bExists = false;
2295                                            for (int iChannel = 0; piChannelIDs[iChannel] >= 0; ++iChannel) {
2296                                                    Channel *pChannel = pChannelStrip->channel();
2297                                                    if (pChannel == nullptr)
2298                                                            break;
2299                                                    if (piChannelIDs[iChannel] == pChannel->channelID()) {
2300                                                            // strip exists, don't touch it
2301                                                            bExists = true;
2302                                                            break;
2303                                                    }
2304                                            }
2305                                            if (!bExists)
2306                                                    destroyChannelStrip(pChannelStrip);
2307                                    }
2308                            }
2309                  }                  }
2310                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
2311          }          }
2312    
2313          // 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();  
2314  }  }
2315    
2316    
2317  // Update the recent files list and menu.  // Update the recent files list and menu.
2318  void MainForm::updateRecentFiles ( const QString& sFilename )  void MainForm::updateRecentFiles ( const QString& sFilename )
2319  {  {
2320          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2321                  return;                  return;
2322    
2323          // Remove from list if already there (avoid duplicates)          // Remove from list if already there (avoid duplicates)
2324          int iIndex = m_pOptions->recentFiles.indexOf(sFilename);          const int iIndex = m_pOptions->recentFiles.indexOf(sFilename);
2325          if (iIndex >= 0)          if (iIndex >= 0)
2326                  m_pOptions->recentFiles.removeAt(iIndex);                  m_pOptions->recentFiles.removeAt(iIndex);
2327          // Put it to front...          // Put it to front...
# Line 1954  void MainForm::updateRecentFiles ( const Line 2332  void MainForm::updateRecentFiles ( const
2332  // Update the recent files list and menu.  // Update the recent files list and menu.
2333  void MainForm::updateRecentFilesMenu (void)  void MainForm::updateRecentFilesMenu (void)
2334  {  {
2335          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2336                  return;                  return;
2337    
2338          // Time to keep the list under limits.          // Time to keep the list under limits.
# Line 1982  void MainForm::updateRecentFilesMenu (vo Line 2360  void MainForm::updateRecentFilesMenu (vo
2360  void MainForm::updateInstrumentNames (void)  void MainForm::updateInstrumentNames (void)
2361  {  {
2362          // Full channel list update...          // Full channel list update...
2363          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2364                    = m_pWorkspace->subWindowList();
2365          if (wlist.isEmpty())          if (wlist.isEmpty())
2366                  return;                  return;
2367    
2368          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2369          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2370                  ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);                  ChannelStrip *pChannelStrip
2371                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2372                  if (pChannelStrip)                  if (pChannelStrip)
2373                          pChannelStrip->updateInstrumentName(true);                          pChannelStrip->updateInstrumentName(true);
2374          }          }
# Line 1999  void MainForm::updateInstrumentNames (vo Line 2379  void MainForm::updateInstrumentNames (vo
2379  // Force update of the channels display font.  // Force update of the channels display font.
2380  void MainForm::updateDisplayFont (void)  void MainForm::updateDisplayFont (void)
2381  {  {
2382          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2383                  return;                  return;
2384    
2385          // Check if display font is legal.          // Check if display font is legal.
2386          if (m_pOptions->sDisplayFont.isEmpty())          if (m_pOptions->sDisplayFont.isEmpty())
2387                  return;                  return;
2388    
2389          // Realize it.          // Realize it.
2390          QFont font;          QFont font;
2391          if (!font.fromString(m_pOptions->sDisplayFont))          if (!font.fromString(m_pOptions->sDisplayFont))
2392                  return;                  return;
2393    
2394          // Full channel list update...          // Full channel list update...
2395          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2396                    = m_pWorkspace->subWindowList();
2397          if (wlist.isEmpty())          if (wlist.isEmpty())
2398                  return;                  return;
2399    
2400          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2401          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2402                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip *pChannelStrip
2403                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2404                  if (pChannelStrip)                  if (pChannelStrip)
2405                          pChannelStrip->setDisplayFont(font);                          pChannelStrip->setDisplayFont(font);
2406          }          }
# Line 2029  void MainForm::updateDisplayFont (void) Line 2412  void MainForm::updateDisplayFont (void)
2412  void MainForm::updateDisplayEffect (void)  void MainForm::updateDisplayEffect (void)
2413  {  {
2414          // Full channel list update...          // Full channel list update...
2415          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2416                    = m_pWorkspace->subWindowList();
2417          if (wlist.isEmpty())          if (wlist.isEmpty())
2418                  return;                  return;
2419    
2420          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2421          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2422                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip *pChannelStrip
2423                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2424                  if (pChannelStrip)                  if (pChannelStrip)
2425                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2426          }          }
# Line 2046  void MainForm::updateDisplayEffect (void Line 2431  void MainForm::updateDisplayEffect (void
2431  // Force update of the channels maximum volume setting.  // Force update of the channels maximum volume setting.
2432  void MainForm::updateMaxVolume (void)  void MainForm::updateMaxVolume (void)
2433  {  {
2434          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2435                  return;                  return;
2436    
2437  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
# Line 2057  void MainForm::updateMaxVolume (void) Line 2442  void MainForm::updateMaxVolume (void)
2442  #endif  #endif
2443    
2444          // Full channel list update...          // Full channel list update...
2445          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2446                    = m_pWorkspace->subWindowList();
2447          if (wlist.isEmpty())          if (wlist.isEmpty())
2448                  return;                  return;
2449    
2450          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2451          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2452                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip *pChannelStrip
2453                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2454                  if (pChannelStrip)                  if (pChannelStrip)
2455                          pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                          pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2456          }          }
# Line 2072  void MainForm::updateMaxVolume (void) Line 2459  void MainForm::updateMaxVolume (void)
2459    
2460    
2461  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2462  // qsamplerMainForm -- Messages window form handlers.  // QSampler::MainForm -- Messages window form handlers.
2463    
2464  // Messages output methods.  // Messages output methods.
2465  void MainForm::appendMessages( const QString& s )  void MainForm::appendMessages( const QString& s )
# Line 2097  void MainForm::appendMessagesText( const Line 2484  void MainForm::appendMessagesText( const
2484                  m_pMessages->appendMessagesText(s);                  m_pMessages->appendMessagesText(s);
2485  }  }
2486    
2487  void MainForm::appendMessagesError( const QString& s )  void MainForm::appendMessagesError( const QString& sText )
2488  {  {
2489          if (m_pMessages)          if (m_pMessages)
2490                  m_pMessages->show();                  m_pMessages->show();
2491    
2492          appendMessagesColor(s.simplified(), "#ff0000");          appendMessagesColor(sText.simplified(), "#ff0000");
2493    
2494          // Make it look responsive...:)          // Make it look responsive...:)
2495          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2496    
2497          QMessageBox::critical(this,          if (m_pOptions && m_pOptions->bConfirmError) {
2498                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));                  const QString& sTitle = tr("Error");
2499            #if 0
2500                    QMessageBox::critical(this, sTitle, sText, QMessageBox::Cancel);
2501            #else
2502                    QMessageBox mbox(this);
2503                    mbox.setIcon(QMessageBox::Critical);
2504                    mbox.setWindowTitle(sTitle);
2505                    mbox.setText(sText);
2506                    mbox.setStandardButtons(QMessageBox::Cancel);
2507                    QCheckBox cbox(tr("Don't show this again"));
2508                    cbox.setChecked(false);
2509                    cbox.blockSignals(true);
2510                    mbox.addButton(&cbox, QMessageBox::ActionRole);
2511                    if (mbox.exec() && cbox.isChecked())
2512                            m_pOptions->bConfirmError = false;
2513            #endif
2514            }
2515  }  }
2516    
2517    
2518  // This is a special message format, just for client results.  // This is a special message format, just for client results.
2519  void MainForm::appendMessagesClient( const QString& s )  void MainForm::appendMessagesClient( const QString& s )
2520  {  {
2521          if (m_pClient == NULL)          if (m_pClient == nullptr)
2522                  return;                  return;
2523    
2524          appendMessagesColor(s + QString(": %1 (errno=%2)")          appendMessagesColor(s + QString(": %1 (errno=%2)")
# Line 2130  void MainForm::appendMessagesClient( con Line 2533  void MainForm::appendMessagesClient( con
2533  // Force update of the messages font.  // Force update of the messages font.
2534  void MainForm::updateMessagesFont (void)  void MainForm::updateMessagesFont (void)
2535  {  {
2536          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2537                  return;                  return;
2538    
2539          if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {          if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {
# Line 2144  void MainForm::updateMessagesFont (void) Line 2547  void MainForm::updateMessagesFont (void)
2547  // Update messages window line limit.  // Update messages window line limit.
2548  void MainForm::updateMessagesLimit (void)  void MainForm::updateMessagesLimit (void)
2549  {  {
2550          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2551                  return;                  return;
2552    
2553          if (m_pMessages) {          if (m_pMessages) {
# Line 2159  void MainForm::updateMessagesLimit (void Line 2562  void MainForm::updateMessagesLimit (void
2562  // Enablement of the messages capture feature.  // Enablement of the messages capture feature.
2563  void MainForm::updateMessagesCapture (void)  void MainForm::updateMessagesCapture (void)
2564  {  {
2565          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2566                  return;                  return;
2567    
2568          if (m_pMessages)          if (m_pMessages)
# Line 2168  void MainForm::updateMessagesCapture (vo Line 2571  void MainForm::updateMessagesCapture (vo
2571    
2572    
2573  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2574  // qsamplerMainForm -- MDI channel strip management.  // QSampler::MainForm -- MDI channel strip management.
2575    
2576  // The channel strip creation executive.  // The channel strip creation executive.
2577  ChannelStrip* MainForm::createChannelStrip(qsamplerChannel* pChannel)  ChannelStrip *MainForm::createChannelStrip ( Channel *pChannel )
2578  {  {
2579          if (m_pClient == NULL || pChannel == NULL)          if (m_pClient == nullptr || pChannel == nullptr)
2580                  return NULL;                  return nullptr;
   
         // Prepare for auto-arrange?  
         ChannelStrip* pChannelStrip = NULL;  
         int y = 0;  
         if (m_pOptions && m_pOptions->bAutoArrange) {  
                 QWidgetList wlist = m_pWorkspace->windowList();  
                 for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {  
                         pChannelStrip = static_cast<ChannelStrip *> (wlist.at(iChannel));  
                         if (pChannelStrip) {  
                         //  y += pChannelStrip->height()  
                         //              + pChannelStrip->parentWidget()->baseSize().height();  
                                 y += pChannelStrip->parentWidget()->frameGeometry().height();  
                         }  
                 }  
         }  
2581    
2582          // Add a new channel itema...          // Add a new channel itema...
2583          pChannelStrip = new ChannelStrip();          ChannelStrip *pChannelStrip = new ChannelStrip();
2584          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
2585                  return NULL;                  return nullptr;
   
         m_pWorkspace->addWindow(pChannelStrip, Qt::FramelessWindowHint);  
2586    
2587          // Actual channel strip setup...          // Set some initial channel strip options...
         pChannelStrip->setup(pChannel);  
         QObject::connect(pChannelStrip,  
                 SIGNAL(channelChanged(ChannelStrip*)),  
                 SLOT(channelStripChanged(ChannelStrip*)));  
         // Set some initial aesthetic options...  
2588          if (m_pOptions) {          if (m_pOptions) {
2589                  // Background display effect...                  // Background display effect...
2590                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2591                  // We'll need a display font.                  // We'll need a display font.
2592                  QFont font;                  QFont font;
2593                  if (font.fromString(m_pOptions->sDisplayFont))                  if (!m_pOptions->sDisplayFont.isEmpty() &&
2594                            font.fromString(m_pOptions->sDisplayFont))
2595                          pChannelStrip->setDisplayFont(font);                          pChannelStrip->setDisplayFont(font);
2596                  // Maximum allowed volume setting.                  // Maximum allowed volume setting.
2597                  pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                  pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2598          }          }
2599    
2600            // Add it to workspace...
2601            QMdiSubWindow *pMdiSubWindow
2602                    = m_pWorkspace->addSubWindow(pChannelStrip,
2603                            Qt::SubWindow | Qt::FramelessWindowHint);
2604            pMdiSubWindow->setAttribute(Qt::WA_DeleteOnClose);
2605    
2606            // Actual channel strip setup...
2607            pChannelStrip->setup(pChannel);
2608    
2609            QObject::connect(pChannelStrip,
2610                    SIGNAL(channelChanged(ChannelStrip *)),
2611                    SLOT(channelStripChanged(ChannelStrip *)));
2612    
2613          // Now we show up us to the world.          // Now we show up us to the world.
2614          pChannelStrip->show();          pChannelStrip->show();
         // Only then, we'll auto-arrange...  
         if (m_pOptions && m_pOptions->bAutoArrange) {  
                 int iWidth  = m_pWorkspace->width();  
         //  int iHeight = pChannel->height()  
         //              + pChannel->parentWidget()->baseSize().height();  
                 int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();  
                 pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);  
         }  
2615    
2616          // This is pretty new, so we'll watch for it closely.          // This is pretty new, so we'll watch for it closely.
2617          channelStripChanged(pChannelStrip);          channelStripChanged(pChannelStrip);
# Line 2234  ChannelStrip* MainForm::createChannelStr Line 2621  ChannelStrip* MainForm::createChannelStr
2621  }  }
2622    
2623    
2624    void MainForm::destroyChannelStrip ( ChannelStrip *pChannelStrip )
2625    {
2626            QMdiSubWindow *pMdiSubWindow
2627                    = static_cast<QMdiSubWindow *> (pChannelStrip->parentWidget());
2628            if (pMdiSubWindow == nullptr)
2629                    return;
2630    
2631            // Just delete the channel strip.
2632            delete pChannelStrip;
2633            delete pMdiSubWindow;
2634    
2635            // Do we auto-arrange?
2636            channelsArrangeAuto();
2637    }
2638    
2639    
2640  // Retrieve the active channel strip.  // Retrieve the active channel strip.
2641  ChannelStrip* MainForm::activeChannelStrip (void)  ChannelStrip *MainForm::activeChannelStrip (void)
2642  {  {
2643          return static_cast<ChannelStrip *> (m_pWorkspace->activeWindow());          QMdiSubWindow *pMdiSubWindow = m_pWorkspace->activeSubWindow();
2644            if (pMdiSubWindow)
2645                    return static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2646            else
2647                    return nullptr;
2648  }  }
2649    
2650    
2651  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
2652  ChannelStrip* MainForm::channelStripAt ( int iChannel )  ChannelStrip *MainForm::channelStripAt ( int iStrip )
2653  {  {
2654          QWidgetList wlist = m_pWorkspace->windowList();          if (!m_pWorkspace) return nullptr;
2655    
2656            const QList<QMdiSubWindow *>& wlist
2657                    = m_pWorkspace->subWindowList();
2658          if (wlist.isEmpty())          if (wlist.isEmpty())
2659                  return NULL;                  return nullptr;
2660    
2661            if (iStrip < 0 || iStrip >= wlist.count())
2662                    return nullptr;
2663    
2664          return static_cast<ChannelStrip *> (wlist.at(iChannel));          QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2665            if (pMdiSubWindow)
2666                    return static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2667            else
2668                    return nullptr;
2669  }  }
2670    
2671    
2672  // Retrieve a channel strip by sampler channel id.  // Retrieve a channel strip by sampler channel id.
2673  ChannelStrip* MainForm::channelStrip ( int iChannelID )  ChannelStrip *MainForm::channelStrip ( int iChannelID )
2674  {  {
2675          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2676                    = m_pWorkspace->subWindowList();
2677          if (wlist.isEmpty())          if (wlist.isEmpty())
2678                  return NULL;                  return nullptr;
2679    
2680          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2681                  ChannelStrip* pChannelStrip                  ChannelStrip *pChannelStrip
2682                          = static_cast<ChannelStrip*> (wlist.at(iChannel));                          = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2683                  if (pChannelStrip) {                  if (pChannelStrip) {
2684                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
2685                          if (pChannel && pChannel->channelID() == iChannelID)                          if (pChannel && pChannel->channelID() == iChannelID)
2686                                  return pChannelStrip;                                  return pChannelStrip;
2687                  }                  }
2688          }          }
2689    
2690          // Not found.          // Not found.
2691          return NULL;          return nullptr;
2692  }  }
2693    
2694    
# Line 2281  void MainForm::channelsMenuAboutToShow ( Line 2699  void MainForm::channelsMenuAboutToShow (
2699          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);
2700          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);
2701    
2702          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2703                    = m_pWorkspace->subWindowList();
2704          if (!wlist.isEmpty()) {          if (!wlist.isEmpty()) {
2705                  m_ui.channelsMenu->addSeparator();                  m_ui.channelsMenu->addSeparator();
2706                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  int iStrip = 0;
2707                          ChannelStrip* pChannelStrip                  foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2708                                  = static_cast<ChannelStrip*> (wlist.at(iChannel));                          ChannelStrip *pChannelStrip
2709                                    = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2710                          if (pChannelStrip) {                          if (pChannelStrip) {
2711                                  QAction *pAction = m_ui.channelsMenu->addAction(                                  QAction *pAction = m_ui.channelsMenu->addAction(
2712                                          pChannelStrip->windowTitle(),                                          pChannelStrip->windowTitle(),
2713                                          this, SLOT(channelsMenuActivated()));                                          this, SLOT(channelsMenuActivated()));
2714                                  pAction->setCheckable(true);                                  pAction->setCheckable(true);
2715                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);
2716                                  pAction->setData(iChannel);                                  pAction->setData(iStrip);
2717                          }                          }
2718                            ++iStrip;
2719                  }                  }
2720          }          }
2721  }  }
# Line 2305  void MainForm::channelsMenuActivated (vo Line 2726  void MainForm::channelsMenuActivated (vo
2726  {  {
2727          // Retrive channel index from action data...          // Retrive channel index from action data...
2728          QAction *pAction = qobject_cast<QAction *> (sender());          QAction *pAction = qobject_cast<QAction *> (sender());
2729          if (pAction == NULL)          if (pAction == nullptr)
2730                  return;                  return;
2731    
2732          ChannelStrip* pChannelStrip = channelStripAt(pAction->data().toInt());          ChannelStrip *pChannelStrip = channelStripAt(pAction->data().toInt());
2733          if (pChannelStrip) {          if (pChannelStrip) {
2734                  pChannelStrip->showNormal();                  pChannelStrip->showNormal();
2735                  pChannelStrip->setFocus();                  pChannelStrip->setFocus();
# Line 2317  void MainForm::channelsMenuActivated (vo Line 2738  void MainForm::channelsMenuActivated (vo
2738    
2739    
2740  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2741  // qsamplerMainForm -- Timer stuff.  // QSampler::MainForm -- Timer stuff.
2742    
2743  // Set the pseudo-timer delay schedule.  // Set the pseudo-timer delay schedule.
2744  void MainForm::startSchedule ( int iStartDelay )  void MainForm::startSchedule ( int iStartDelay )
# Line 2336  void MainForm::stopSchedule (void) Line 2757  void MainForm::stopSchedule (void)
2757  // Timer slot funtion.  // Timer slot funtion.
2758  void MainForm::timerSlot (void)  void MainForm::timerSlot (void)
2759  {  {
2760          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2761                  return;                  return;
2762    
2763          // Is it the first shot on server start after a few delay?          // Is it the first shot on server start after a few delay?
# Line 2358  void MainForm::timerSlot (void) Line 2779  void MainForm::timerSlot (void)
2779                          ChannelStrip *pChannelStrip = iter.next();                          ChannelStrip *pChannelStrip = iter.next();
2780                          // If successfull, remove from pending list...                          // If successfull, remove from pending list...
2781                          if (pChannelStrip->updateChannelInfo()) {                          if (pChannelStrip->updateChannelInfo()) {
2782                                  int iChannelStrip = m_changedStrips.indexOf(pChannelStrip);                                  const int iChannelStrip = m_changedStrips.indexOf(pChannelStrip);
2783                                  if (iChannelStrip >= 0)                                  if (iChannelStrip >= 0)
2784                                          m_changedStrips.removeAt(iChannelStrip);                                          m_changedStrips.removeAt(iChannelStrip);
2785                          }                          }
# Line 2369  void MainForm::timerSlot (void) Line 2790  void MainForm::timerSlot (void)
2790                          if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime)  {                          if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime)  {
2791                                  m_iTimerSlot = 0;                                  m_iTimerSlot = 0;
2792                                  // Update the channel stream usage for each strip...                                  // Update the channel stream usage for each strip...
2793                                  QWidgetList wlist = m_pWorkspace->windowList();                                  const QList<QMdiSubWindow *>& wlist
2794                                  for (int iChannel = 0;                                          = m_pWorkspace->subWindowList();
2795                                                  iChannel < (int) wlist.count(); iChannel++) {                                  foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2796                                          ChannelStrip* pChannelStrip                                          ChannelStrip *pChannelStrip
2797                                                  = (ChannelStrip*) wlist.at(iChannel);                                                  = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2798                                          if (pChannelStrip && pChannelStrip->isVisible())                                          if (pChannelStrip && pChannelStrip->isVisible())
2799                                                  pChannelStrip->updateChannelUsage();                                                  pChannelStrip->updateChannelUsage();
2800                                  }                                  }
2801                          }                          }
2802                  }                  }
2803    
2804            #if CONFIG_LSCP_CLIENT_CONNECTION_LOST
2805                    // If we lost connection to server: Try to automatically reconnect if we
2806                    // did not start the server.
2807                    //
2808                    // TODO: If we started the server, then we might inform the user that
2809                    // the server probably crashed and asking user ONCE whether we should
2810                    // restart the server.
2811                    if (lscp_client_connection_lost(m_pClient) && !m_pServer)
2812                            startAutoReconnectClient();
2813            #endif // CONFIG_LSCP_CLIENT_CONNECTION_LOST
2814          }          }
2815    
2816          // Register the next timer slot.          // Register the next timer slot.
# Line 2387  void MainForm::timerSlot (void) Line 2819  void MainForm::timerSlot (void)
2819    
2820    
2821  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2822  // qsamplerMainForm -- Server stuff.  // QSampler::MainForm -- Server stuff.
2823    
2824  // Start linuxsampler server...  // Start linuxsampler server...
2825  void MainForm::startServer (void)  void MainForm::startServer (void)
2826  {  {
2827          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2828                  return;                  return;
2829    
2830          // Aren't already a client, are we?          // Aren't already a client, are we?
# Line 2401  void MainForm::startServer (void) Line 2833  void MainForm::startServer (void)
2833    
2834          // Is the server process instance still here?          // Is the server process instance still here?
2835          if (m_pServer) {          if (m_pServer) {
2836                  switch (QMessageBox::warning(this,                  if (QMessageBox::warning(this,
2837                          QSAMPLER_TITLE ": " + tr("Warning"),                          tr("Warning"),
2838                          tr("Could not start the LinuxSampler server.\n\n"                          tr("Could not start the LinuxSampler server.\n\n"
2839                          "Maybe it ss already started."),                          "Maybe it is already started."),
2840                          tr("Stop"), tr("Kill"), tr("Cancel"))) {                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
                 case 0:  
2841                          m_pServer->terminate();                          m_pServer->terminate();
                         break;  
                 case 1:  
2842                          m_pServer->kill();                          m_pServer->kill();
                         break;  
2843                  }                  }
2844                  return;                  return;
2845          }          }
# Line 2424  void MainForm::startServer (void) Line 2852  void MainForm::startServer (void)
2852                  return;                  return;
2853    
2854          // OK. Let's build the startup process...          // OK. Let's build the startup process...
2855          m_pServer = new QProcess(this);          m_pServer = new QProcess();
2856            m_bForceServerStop = true;
2857    
2858          // Setup stdout/stderr capture...          // Setup stdout/stderr capture...
2859  //      if (m_pOptions->bStdoutCapture) {          m_pServer->setProcessChannelMode(QProcess::ForwardedChannels);
2860                  //m_pServer->setProcessChannelMode(          QObject::connect(m_pServer,
2861                  //      QProcess::StandardOutput);                  SIGNAL(readyReadStandardOutput()),
2862                  QObject::connect(m_pServer,                  SLOT(readServerStdout()));
2863                          SIGNAL(readyReadStandardOutput()),          QObject::connect(m_pServer,
2864                          SLOT(readServerStdout()));                  SIGNAL(readyReadStandardError()),
2865                  QObject::connect(m_pServer,                  SLOT(readServerStdout()));
                         SIGNAL(readyReadStandardError()),  
                         SLOT(readServerStdout()));  
 //      }  
2866    
2867          // The unforgiveable signal communication...          // The unforgiveable signal communication...
2868          QObject::connect(m_pServer,          QObject::connect(m_pServer,
2869                  SIGNAL(finished(int,QProcess::ExitStatus)),                  SIGNAL(finished(int, QProcess::ExitStatus)),
2870                  SLOT(processServerExit()));                  SLOT(processServerExit()));
2871    
2872          // Build process arguments...          // Build process arguments...
# Line 2471  void MainForm::startServer (void) Line 2897  void MainForm::startServer (void)
2897    
2898    
2899  // Stop linuxsampler server...  // Stop linuxsampler server...
2900  void MainForm::stopServer (void)  void MainForm::stopServer ( bool bInteractive )
2901  {  {
2902          // Stop client code.          // Stop client code.
2903          stopClient();          stopClient();
2904    
2905            if (m_pServer && bInteractive) {
2906                    if (QMessageBox::question(this,
2907                            tr("The backend's fate ..."),
2908                            tr("You have the option to keep the sampler backend (LinuxSampler)\n"
2909                            "running in the background. The sampler would continue to work\n"
2910                            "according to your current sampler session and you could alter the\n"
2911                            "sampler session at any time by relaunching QSampler.\n\n"
2912                            "Do you want LinuxSampler to stop?"),
2913                            QMessageBox::Yes | QMessageBox::No,
2914                            QMessageBox::Yes) == QMessageBox::No) {
2915                            m_bForceServerStop = false;
2916                    }
2917            }
2918    
2919            bool bGraceWait = true;
2920    
2921          // And try to stop server.          // And try to stop server.
2922          if (m_pServer) {          if (m_pServer && m_bForceServerStop) {
2923                  appendMessages(tr("Server is stopping..."));                  appendMessages(tr("Server is stopping..."));
2924                  if (m_pServer->state() == QProcess::Running)                  if (m_pServer->state() == QProcess::Running) {
2925                    #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
2926                            // Try harder...
2927                            m_pServer->kill();
2928                    #else
2929                            // Try softly...
2930                          m_pServer->terminate();                          m_pServer->terminate();
2931          }                          bool bFinished = m_pServer->waitForFinished(QSAMPLER_TIMER_MSECS * 1000);
2932                            if (bFinished) bGraceWait = false;
2933                    #endif
2934                    }
2935            }       // Do final processing anyway.
2936            else processServerExit();
2937    
2938          // Give it some time to terminate gracefully and stabilize...          // Give it some time to terminate gracefully and stabilize...
2939          QTime t;          if (bGraceWait) {
2940          t.start();                  QElapsedTimer timer;
2941          while (t.elapsed() < QSAMPLER_TIMER_MSECS)                  timer.start();
2942                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  while (timer.elapsed() < QSAMPLER_TIMER_MSECS)
2943                            QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2944          // Do final processing anyway.          }
         processServerExit();  
2945  }  }
2946    
2947    
# Line 2512  void MainForm::processServerExit (void) Line 2963  void MainForm::processServerExit (void)
2963          if (m_pMessages)          if (m_pMessages)
2964                  m_pMessages->flushStdoutBuffer();                  m_pMessages->flushStdoutBuffer();
2965    
2966          if (m_pServer) {          if (m_pServer && m_bForceServerStop) {
2967                    if (m_pServer->state() != QProcess::NotRunning) {
2968                            appendMessages(tr("Server is being forced..."));
2969                            // Force final server shutdown...
2970                            m_pServer->kill();
2971                            // Give it some time to terminate gracefully and stabilize...
2972                            QElapsedTimer timer;
2973                            timer.start();
2974                            while (timer.elapsed() < QSAMPLER_TIMER_MSECS)
2975                                    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2976                    }
2977                  // Force final server shutdown...                  // Force final server shutdown...
2978                  appendMessages(                  appendMessages(
2979                          tr("Server was stopped with exit status %1.")                          tr("Server was stopped with exit status %1.")
2980                          .arg(m_pServer->exitStatus()));                          .arg(m_pServer->exitStatus()));
                 m_pServer->terminate();  
                 if (!m_pServer->waitForFinished(2000))  
                         m_pServer->kill();  
                 // Destroy it.  
2981                  delete m_pServer;                  delete m_pServer;
2982                  m_pServer = NULL;                  m_pServer = nullptr;
2983          }          }
2984    
2985          // Again, make status visible stable.          // Again, make status visible stable.
# Line 2531  void MainForm::processServerExit (void) Line 2988  void MainForm::processServerExit (void)
2988    
2989    
2990  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2991  // qsamplerMainForm -- Client stuff.  // QSampler::MainForm -- Client stuff.
2992    
2993  // The LSCP client callback procedure.  // The LSCP client callback procedure.
2994  lscp_status_t qsampler_client_callback ( lscp_client_t */*pClient*/,  lscp_status_t qsampler_client_callback ( lscp_client_t */*pClient*/,
2995          lscp_event_t event, const char *pchData, int cchData, void *pvData )          lscp_event_t event, const char *pchData, int cchData, void *pvData )
2996  {  {
2997          MainForm* pMainForm = (MainForm *) pvData;          MainForm* pMainForm = (MainForm *) pvData;
2998          if (pMainForm == NULL)          if (pMainForm == nullptr)
2999                  return LSCP_FAILED;                  return LSCP_FAILED;
3000    
3001          // ATTN: DO NOT EVER call any GUI code here,          // ATTN: DO NOT EVER call any GUI code here,
3002          // as this is run under some other thread context.          // as this is run under some other thread context.
3003          // A custom event must be posted here...          // A custom event must be posted here...
3004          QApplication::postEvent(pMainForm,          QApplication::postEvent(pMainForm,
3005                  new qsamplerCustomEvent(event, pchData, cchData));                  new LscpEvent(event, pchData, cchData));
3006    
3007          return LSCP_OK;          return LSCP_OK;
3008  }  }
3009    
3010    
3011  // Start our almighty client...  // Start our almighty client...
3012  bool MainForm::startClient (void)  bool MainForm::startClient (bool bReconnectOnly)
3013  {  {
3014          // Have it a setup?          // Have it a setup?
3015          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
3016                  return false;                  return false;
3017    
3018          // Aren't we already started, are we?          // Aren't we already started, are we?
# Line 2569  bool MainForm::startClient (void) Line 3026  bool MainForm::startClient (void)
3026          m_pClient = ::lscp_client_create(          m_pClient = ::lscp_client_create(
3027                  m_pOptions->sServerHost.toUtf8().constData(),                  m_pOptions->sServerHost.toUtf8().constData(),
3028                  m_pOptions->iServerPort, qsampler_client_callback, this);                  m_pOptions->iServerPort, qsampler_client_callback, this);
3029          if (m_pClient == NULL) {          if (m_pClient == nullptr) {
3030                  // Is this the first try?                  // Is this the first try?
3031                  // maybe we need to start a local server...                  // maybe we need to start a local server...
3032                  if ((m_pServer && m_pServer->state() == QProcess::Running)                  if ((m_pServer && m_pServer->state() == QProcess::Running)
3033                          || !m_pOptions->bServerStart) {                          || !m_pOptions->bServerStart || bReconnectOnly)
3034                          appendMessagesError(                  {
3035                                  tr("Could not connect to server as client.\n\nSorry."));                          // if this method is called from autoReconnectClient()
3036                            // then don't bother user with an error message...
3037                            if (!bReconnectOnly) {
3038                                    appendMessagesError(
3039                                            tr("Could not connect to server as client.\n\nSorry.")
3040                                    );
3041                            }
3042                  } else {                  } else {
3043                          startServer();                          startServer();
3044                  }                  }
# Line 2583  bool MainForm::startClient (void) Line 3046  bool MainForm::startClient (void)
3046                  stabilizeForm();                  stabilizeForm();
3047                  return false;                  return false;
3048          }          }
3049    
3050          // Just set receive timeout value, blindly.          // Just set receive timeout value, blindly.
3051          ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);          ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);
3052          appendMessages(          appendMessages(
# Line 2590  bool MainForm::startClient (void) Line 3054  bool MainForm::startClient (void)
3054                  .arg(::lscp_client_get_timeout(m_pClient)));                  .arg(::lscp_client_get_timeout(m_pClient)));
3055    
3056          // Subscribe to channel info change notifications...          // Subscribe to channel info change notifications...
3057            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT) != LSCP_OK)
3058                    appendMessagesClient("lscp_client_subscribe(CHANNEL_COUNT)");
3059          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)
3060                  appendMessagesClient("lscp_client_subscribe");                  appendMessagesClient("lscp_client_subscribe(CHANNEL_INFO)");
3061    
3062            DeviceStatusForm::onDevicesChanged(); // initialize
3063            updateViewMidiDeviceStatusMenu();
3064            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT) != LSCP_OK)
3065                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_COUNT)");
3066            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO) != LSCP_OK)
3067                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_INFO)");
3068            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT) != LSCP_OK)
3069                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_COUNT)");
3070            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO) != LSCP_OK)
3071                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_INFO)");
3072    
3073    #if CONFIG_EVENT_CHANNEL_MIDI
3074            // Subscribe to channel MIDI data notifications...
3075            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI) != LSCP_OK)
3076                    appendMessagesClient("lscp_client_subscribe(CHANNEL_MIDI)");
3077    #endif
3078    
3079    #if CONFIG_EVENT_DEVICE_MIDI
3080            // Subscribe to channel MIDI data notifications...
3081            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI) != LSCP_OK)
3082                    appendMessagesClient("lscp_client_subscribe(DEVICE_MIDI)");
3083    #endif
3084    
3085          // We may stop scheduling around.          // We may stop scheduling around.
3086          stopSchedule();          stopSchedule();
# Line 2613  bool MainForm::startClient (void) Line 3102  bool MainForm::startClient (void)
3102          if (!m_pOptions->sSessionFile.isEmpty()) {          if (!m_pOptions->sSessionFile.isEmpty()) {
3103                  // Just load the prabably startup session...                  // Just load the prabably startup session...
3104                  if (loadSessionFile(m_pOptions->sSessionFile)) {                  if (loadSessionFile(m_pOptions->sSessionFile)) {
3105                          m_pOptions->sSessionFile = QString::null;                          m_pOptions->sSessionFile = QString();
3106                          return true;                          return true;
3107                  }                  }
3108          }          }
3109    
3110            // send the current / loaded fine tuning settings to the sampler
3111            m_pOptions->sendFineTuningSettings();
3112    
3113          // Make a new session          // Make a new session
3114          return newSession();          return newSession();
3115  }  }
# Line 2626  bool MainForm::startClient (void) Line 3118  bool MainForm::startClient (void)
3118  // Stop client...  // Stop client...
3119  void MainForm::stopClient (void)  void MainForm::stopClient (void)
3120  {  {
3121          if (m_pClient == NULL)          if (m_pClient == nullptr)
3122                  return;                  return;
3123    
3124          // Log prepare here.          // Log prepare here.
# Line 2645  void MainForm::stopClient (void) Line 3137  void MainForm::stopClient (void)
3137          closeSession(false);          closeSession(false);
3138    
3139          // Close us as a client...          // Close us as a client...
3140    #if CONFIG_EVENT_DEVICE_MIDI
3141            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI);
3142    #endif
3143    #if CONFIG_EVENT_CHANNEL_MIDI
3144            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI);
3145    #endif
3146            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
3147            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
3148            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
3149            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
3150          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
3151            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT);
3152          ::lscp_client_destroy(m_pClient);          ::lscp_client_destroy(m_pClient);
3153          m_pClient = NULL;          m_pClient = nullptr;
3154    
3155          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
3156          // if visible, that we're running out...          // if visible, that we're running out...
# Line 2664  void MainForm::stopClient (void) Line 3167  void MainForm::stopClient (void)
3167  }  }
3168    
3169    
3170    void MainForm::startAutoReconnectClient (void)
3171    {
3172            stopClient();
3173            appendMessages(tr("Trying to reconnect..."));
3174            QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(autoReconnectClient()));
3175    }
3176    
3177    
3178    void MainForm::autoReconnectClient (void)
3179    {
3180            const bool bSuccess = startClient(true);
3181            if (!bSuccess)
3182                    QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(autoReconnectClient()));
3183    }
3184    
3185    
3186  // Channel strip activation/selection.  // Channel strip activation/selection.
3187  void MainForm::activateStrip ( QWidget *pWidget )  void MainForm::activateStrip ( QMdiSubWindow *pMdiSubWindow )
3188  {  {
3189          ChannelStrip *pChannelStrip          ChannelStrip *pChannelStrip = nullptr;
3190                  = static_cast<ChannelStrip *> (pWidget);          if (pMdiSubWindow)
3191                    pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
3192          if (pChannelStrip)          if (pChannelStrip)
3193                  pChannelStrip->setSelected(true);                  pChannelStrip->setSelected(true);
3194    
# Line 2676  void MainForm::activateStrip ( QWidget * Line 3196  void MainForm::activateStrip ( QWidget *
3196  }  }
3197    
3198    
3199    // Channel toolbar orientation change.
3200    void MainForm::channelsToolbarOrientation ( Qt::Orientation orientation )
3201    {
3202    #ifdef CONFIG_VOLUME
3203            m_pVolumeSlider->setOrientation(orientation);
3204            if (orientation == Qt::Horizontal) {
3205                    m_pVolumeSlider->setMinimumHeight(24);
3206                    m_pVolumeSlider->setMaximumHeight(32);
3207                    m_pVolumeSlider->setMinimumWidth(120);
3208                    m_pVolumeSlider->setMaximumWidth(640);
3209                    m_pVolumeSpinBox->setMaximumWidth(64);
3210                    m_pVolumeSpinBox->setButtonSymbols(QSpinBox::UpDownArrows);
3211            } else {
3212                    m_pVolumeSlider->setMinimumHeight(120);
3213                    m_pVolumeSlider->setMaximumHeight(480);
3214                    m_pVolumeSlider->setMinimumWidth(24);
3215                    m_pVolumeSlider->setMaximumWidth(32);
3216                    m_pVolumeSpinBox->setMaximumWidth(32);
3217                    m_pVolumeSpinBox->setButtonSymbols(QSpinBox::NoButtons);
3218            }
3219    #endif
3220    }
3221    
3222    
3223  } // namespace QSampler  } // namespace QSampler
3224    
3225    

Legend:
Removed from v.1514  
changed lines
  Added in v.3759

  ViewVC Help
Powered by ViewVC