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

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

  ViewVC Help
Powered by ViewVC