/[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 1815 by capela, Mon Dec 22 10:04:59 2008 UTC revision 3613 by capela, Tue Oct 1 08:35:49 2019 UTC
# Line 1  Line 1 
1  // qsamplerMainForm.cpp  // qsamplerMainForm.cpp
2  //  //
3  /****************************************************************************  /****************************************************************************
4     Copyright (C) 2004-2008, rncbc aka Rui Nuno Capela. All rights reserved.     Copyright (C) 2004-2019, rncbc aka Rui Nuno Capela. All rights reserved.
5     Copyright (C) 2007, 2008 Christian Schoenebeck     Copyright (C) 2007,2008,2015 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 35  Line 35 
35  #include "qsamplerOptionsForm.h"  #include "qsamplerOptionsForm.h"
36  #include "qsamplerDeviceStatusForm.h"  #include "qsamplerDeviceStatusForm.h"
37    
38    #include <QMdiArea>
39    #include <QMdiSubWindow>
40    
41  #include <QApplication>  #include <QApplication>
 #include <QWorkspace>  
42  #include <QProcess>  #include <QProcess>
43  #include <QMessageBox>  #include <QMessageBox>
44    
# Line 56  Line 58 
58  #include <QTimer>  #include <QTimer>
59  #include <QDateTime>  #include <QDateTime>
60    
61    #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
62    #include <QMimeData>
63    #endif
64    
65  #ifdef HAVE_SIGNAL_H  #if QT_VERSION < QT_VERSION_CHECK(4, 5, 0)
66  #include <signal.h>  namespace Qt {
67    const WindowFlags WindowCloseButtonHint = WindowFlags(0x08000000);
68    }
69  #endif  #endif
70    
71  #ifdef CONFIG_LIBGIG  #ifdef CONFIG_LIBGIG
# Line 80  static inline long lroundf ( float x ) Line 87  static inline long lroundf ( float x )
87    
88    
89  // All winsock apps needs this.  // All winsock apps needs this.
90  #if defined(WIN32)  #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
91  static WSADATA _wsaData;  static WSADATA _wsaData;
92    #undef HAVE_SIGNAL_H
93  #endif  #endif
94    
95    
96    //-------------------------------------------------------------------------
97    // LADISH Level 1 support stuff.
98    
99    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
100    
101    #include <QSocketNotifier>
102    
103    #include <unistd.h>
104    #include <sys/types.h>
105    #include <sys/socket.h>
106    #include <signal.h>
107    
108    // File descriptor for SIGUSR1 notifier.
109    static int g_fdSigusr1[2] = { -1, -1 };
110    
111    // Unix SIGUSR1 signal handler.
112    static void qsampler_sigusr1_handler ( int /* signo */ )
113    {
114            char c = 1;
115    
116            (::write(g_fdSigusr1[0], &c, sizeof(c)) > 0);
117    }
118    
119    // File descriptor for SIGTERM notifier.
120    static int g_fdSigterm[2] = { -1, -1 };
121    
122    // Unix SIGTERM signal handler.
123    static void qsampler_sigterm_handler ( int /* signo */ )
124    {
125            char c = 1;
126    
127            (::write(g_fdSigterm[0], &c, sizeof(c)) > 0);
128    }
129    
130    #endif  // HAVE_SIGNAL_H
131    
132    
133    //-------------------------------------------------------------------------
134    // QSampler -- namespace
135    
136    
137  namespace QSampler {  namespace QSampler {
138    
139  // Timer constant stuff.  // Timer constant stuff.
# Line 97  namespace QSampler { Line 146  namespace QSampler {
146  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.
147    
148    
149  //-------------------------------------------------------------------------  // Specialties for thread-callback comunication.
150  // CustomEvent -- specialty for callback comunication.  #define QSAMPLER_LSCP_EVENT   QEvent::Type(QEvent::User + 1)
151    
152    
153  #define QSAMPLER_CUSTOM_EVENT   QEvent::Type(QEvent::User + 0)  //-------------------------------------------------------------------------
154    // QSampler::LscpEvent -- specialty for LSCP callback comunication.
155    
156  class CustomEvent : public QEvent  class LscpEvent : public QEvent
157  {  {
158  public:  public:
159    
160          // Constructor.          // Constructor.
161          CustomEvent(lscp_event_t event, const char *pchData, int cchData)          LscpEvent(lscp_event_t event, const char *pchData, int cchData)
162                  : QEvent(QSAMPLER_CUSTOM_EVENT)                  : QEvent(QSAMPLER_LSCP_EVENT)
163          {          {
164                  m_event = event;                  m_event = event;
165                  m_data  = QString::fromUtf8(pchData, cchData);                  m_data  = QString::fromUtf8(pchData, cchData);
166          }          }
167    
168          // Accessors.          // Accessors.
169          lscp_event_t event() { return m_event; }          lscp_event_t  event() { return m_event; }
170          QString&     data()  { return m_data;  }          const QString& data() { return m_data;  }
171    
172  private:  private:
173    
# Line 128  private: Line 179  private:
179    
180    
181  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
182  // qsamplerMainForm -- Main window form implementation.  // QSampler::Workspace -- Main window workspace (MDI Area) decl.
183    
184    class Workspace : public QMdiArea
185    {
186    public:
187    
188            Workspace(MainForm *pMainForm) : QMdiArea(pMainForm) {}
189    
190    protected:
191    
192            void resizeEvent(QResizeEvent *)
193            {
194                    MainForm *pMainForm = static_cast<MainForm *> (parentWidget());
195                    if (pMainForm)
196                            pMainForm->channelsArrangeAuto();
197            }
198    };
199    
200    
201    //-------------------------------------------------------------------------
202    // QSampler::MainForm -- Main window form implementation.
203    
204  // Kind of singleton reference.  // Kind of singleton reference.
205  MainForm* MainForm::g_pMainForm = NULL;  MainForm *MainForm::g_pMainForm = nullptr;
206    
207  MainForm::MainForm ( QWidget *pParent )  MainForm::MainForm ( QWidget *pParent )
208          : QMainWindow(pParent)          : QMainWindow(pParent)
# Line 142  MainForm::MainForm ( QWidget *pParent ) Line 213  MainForm::MainForm ( QWidget *pParent )
213          g_pMainForm = this;          g_pMainForm = this;
214    
215          // Initialize some pointer references.          // Initialize some pointer references.
216          m_pOptions = NULL;          m_pOptions = nullptr;
217    
218          // All child forms are to be created later, not earlier than setup.          // All child forms are to be created later, not earlier than setup.
219          m_pMessages = NULL;          m_pMessages = nullptr;
220          m_pInstrumentListForm = NULL;          m_pInstrumentListForm = nullptr;
221          m_pDeviceForm = NULL;          m_pDeviceForm = nullptr;
222    
223          // We'll start clean.          // We'll start clean.
224          m_iUntitled   = 0;          m_iUntitled   = 0;
225            m_iDirtySetup = 0;
226          m_iDirtyCount = 0;          m_iDirtyCount = 0;
227    
228          m_pServer = NULL;          m_pServer = nullptr;
229          m_pClient = NULL;          m_pClient = nullptr;
230    
231          m_iStartDelay = 0;          m_iStartDelay = 0;
232          m_iTimerDelay = 0;          m_iTimerDelay = 0;
233    
234          m_iTimerSlot = 0;          m_iTimerSlot = 0;
235    
236  #ifdef HAVE_SIGNAL_H  #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
237    
238          // Set to ignore any fatal "Broken pipe" signals.          // Set to ignore any fatal "Broken pipe" signals.
239          ::signal(SIGPIPE, SIG_IGN);          ::signal(SIGPIPE, SIG_IGN);
240  #endif  
241            // LADISH Level 1 suport.
242    
243            // Initialize file descriptors for SIGUSR1 socket notifier.
244            ::socketpair(AF_UNIX, SOCK_STREAM, 0, g_fdSigusr1);
245            m_pSigusr1Notifier
246                    = new QSocketNotifier(g_fdSigusr1[1], QSocketNotifier::Read, this);
247    
248            QObject::connect(m_pSigusr1Notifier,
249                    SIGNAL(activated(int)),
250                    SLOT(handle_sigusr1()));
251    
252            // Install SIGUSR1 signal handler.
253            struct sigaction sigusr1;
254            sigusr1.sa_handler = qsampler_sigusr1_handler;
255            sigemptyset(&sigusr1.sa_mask);
256            sigusr1.sa_flags = 0;
257            sigusr1.sa_flags |= SA_RESTART;
258            ::sigaction(SIGUSR1, &sigusr1, nullptr);
259    
260            // Initialize file descriptors for SIGTERM socket notifier.
261            ::socketpair(AF_UNIX, SOCK_STREAM, 0, g_fdSigterm);
262            m_pSigtermNotifier
263                    = new QSocketNotifier(g_fdSigterm[1], QSocketNotifier::Read, this);
264    
265            QObject::connect(m_pSigtermNotifier,
266                    SIGNAL(activated(int)),
267                    SLOT(handle_sigterm()));
268    
269            // Install SIGTERM signal handler.
270            struct sigaction sigterm;
271            sigterm.sa_handler = qsampler_sigterm_handler;
272            sigemptyset(&sigterm.sa_mask);
273            sigterm.sa_flags = 0;
274            sigterm.sa_flags |= SA_RESTART;
275            ::sigaction(SIGTERM, &sigterm, nullptr);
276            ::sigaction(SIGQUIT, &sigterm, nullptr);
277    
278            // Ignore SIGHUP/SIGINT signals.
279            ::signal(SIGHUP, SIG_IGN);
280            ::signal(SIGINT, SIG_IGN);
281    
282    #else   // HAVE_SIGNAL_H
283    
284            m_pSigusr1Notifier = nullptr;
285            m_pSigtermNotifier = nullptr;
286            
287    #endif  // !HAVE_SIGNAL_H
288    
289  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
290          // Make some extras into the toolbar...          // Make some extras into the toolbar...
# Line 185  MainForm::MainForm ( QWidget *pParent ) Line 305  MainForm::MainForm ( QWidget *pParent )
305          QObject::connect(m_pVolumeSlider,          QObject::connect(m_pVolumeSlider,
306                  SIGNAL(valueChanged(int)),                  SIGNAL(valueChanged(int)),
307                  SLOT(volumeChanged(int)));                  SLOT(volumeChanged(int)));
         //m_ui.channelsToolbar->setHorizontallyStretchable(true);  
         //m_ui.channelsToolbar->setStretchableWidget(m_pVolumeSlider);  
308          m_ui.channelsToolbar->addWidget(m_pVolumeSlider);          m_ui.channelsToolbar->addWidget(m_pVolumeSlider);
309          // Volume spin-box          // Volume spin-box
310          m_ui.channelsToolbar->addSeparator();          m_ui.channelsToolbar->addSeparator();
311          m_pVolumeSpinBox = new QSpinBox(m_ui.channelsToolbar);          m_pVolumeSpinBox = new QSpinBox(m_ui.channelsToolbar);
         m_pVolumeSpinBox->setMaximumHeight(24);  
312          m_pVolumeSpinBox->setSuffix(" %");          m_pVolumeSpinBox->setSuffix(" %");
313          m_pVolumeSpinBox->setMinimum(0);          m_pVolumeSpinBox->setMinimum(0);
314          m_pVolumeSpinBox->setMaximum(100);          m_pVolumeSpinBox->setMaximum(100);
# Line 203  MainForm::MainForm ( QWidget *pParent ) Line 320  MainForm::MainForm ( QWidget *pParent )
320  #endif  #endif
321    
322          // Make it an MDI workspace.          // Make it an MDI workspace.
323          m_pWorkspace = new QWorkspace(this);          m_pWorkspace = new Workspace(this);
324          m_pWorkspace->setScrollBarsEnabled(true);          m_pWorkspace->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
325            m_pWorkspace->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
326          // Set the activation connection.          // Set the activation connection.
327          QObject::connect(m_pWorkspace,          QObject::connect(m_pWorkspace,
328                  SIGNAL(windowActivated(QWidget *)),                  SIGNAL(subWindowActivated(QMdiSubWindow *)),
329                  SLOT(activateStrip(QWidget *)));                  SLOT(activateStrip(QMdiSubWindow *)));
330          // Make it shine :-)          // Make it shine :-)
331          setCentralWidget(m_pWorkspace);          setCentralWidget(m_pWorkspace);
332    
# Line 237  MainForm::MainForm ( QWidget *pParent ) Line 355  MainForm::MainForm ( QWidget *pParent )
355          m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;          m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;
356          statusBar()->addWidget(pLabel);          statusBar()->addWidget(pLabel);
357    
358  #if defined(WIN32)  #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
359          WSAStartup(MAKEWORD(1, 1), &_wsaData);          WSAStartup(MAKEWORD(1, 1), &_wsaData);
360  #endif  #endif
361    
# Line 325  MainForm::MainForm ( QWidget *pParent ) Line 443  MainForm::MainForm ( QWidget *pParent )
443          QObject::connect(m_ui.channelsMenu,          QObject::connect(m_ui.channelsMenu,
444                  SIGNAL(aboutToShow()),                  SIGNAL(aboutToShow()),
445                  SLOT(channelsMenuAboutToShow()));                  SLOT(channelsMenuAboutToShow()));
446    #ifdef CONFIG_VOLUME
447            QObject::connect(m_ui.channelsToolbar,
448                    SIGNAL(orientationChanged(Qt::Orientation)),
449                    SLOT(channelsToolbarOrientation(Qt::Orientation)));
450    #endif
451  }  }
452    
453  // Destructor.  // Destructor.
# Line 333  MainForm::~MainForm() Line 456  MainForm::~MainForm()
456          // Do final processing anyway.          // Do final processing anyway.
457          processServerExit();          processServerExit();
458    
459  #if defined(WIN32)  #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
460          WSACleanup();          WSACleanup();
461  #endif  #endif
462    
463    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
464            if (m_pSigusr1Notifier)
465                    delete m_pSigusr1Notifier;
466            if (m_pSigtermNotifier)
467                    delete m_pSigtermNotifier;
468    #endif
469    
470          // Finally drop any widgets around...          // Finally drop any widgets around...
471          if (m_pDeviceForm)          if (m_pDeviceForm)
472                  delete m_pDeviceForm;                  delete m_pDeviceForm;
# Line 363  MainForm::~MainForm() Line 493  MainForm::~MainForm()
493  #endif  #endif
494    
495          // Pseudo-singleton reference shut-down.          // Pseudo-singleton reference shut-down.
496          g_pMainForm = NULL;          g_pMainForm = nullptr;
497  }  }
498    
499    
# Line 375  void MainForm::setup ( Options *pOptions Line 505  void MainForm::setup ( Options *pOptions
505    
506          // What style do we create these forms?          // What style do we create these forms?
507          Qt::WindowFlags wflags = Qt::Window          Qt::WindowFlags wflags = Qt::Window
 #if QT_VERSION >= 0x040200  
508                  | Qt::CustomizeWindowHint                  | Qt::CustomizeWindowHint
 #endif  
509                  | Qt::WindowTitleHint                  | Qt::WindowTitleHint
510                  | Qt::WindowSystemMenuHint                  | Qt::WindowSystemMenuHint
511                  | Qt::WindowMinMaxButtonsHint;                  | Qt::WindowMinMaxButtonsHint
512                    | Qt::WindowCloseButtonHint;
513          if (m_pOptions->bKeepOnTop)          if (m_pOptions->bKeepOnTop)
514                  wflags |= Qt::Tool;                  wflags |= Qt::Tool;
515    
516          // Some child forms are to be created right now.          // Some child forms are to be created right now.
517          m_pMessages = new Messages(this);          m_pMessages = new Messages(this);
518          m_pDeviceForm = new DeviceForm(this, wflags);          m_pDeviceForm = new DeviceForm(this, wflags);
519  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
520          m_pInstrumentListForm = new InstrumentListForm(this, wflags);          m_pInstrumentListForm = new InstrumentListForm(this, wflags);
521  #else  #else
522          viewInstrumentsAction->setEnabled(false);          m_ui.viewInstrumentsAction->setEnabled(false);
523  #endif  #endif
524    
525          // Setup messages logging appropriately...          // Setup messages logging appropriately...
526          m_pMessages->setLogging(          m_pMessages->setLogging(
527                  m_pOptions->bMessagesLog,                  m_pOptions->bMessagesLog,
528                  m_pOptions->sMessagesLogPath);                  m_pOptions->sMessagesLogPath);
529    
530          // Set message defaults...          // Set message defaults...
531          updateMessagesFont();          updateMessagesFont();
532          updateMessagesLimit();          updateMessagesLimit();
533          updateMessagesCapture();          updateMessagesCapture();
534    
535          // Set the visibility signal.          // Set the visibility signal.
536          QObject::connect(m_pMessages,          QObject::connect(m_pMessages,
537                  SIGNAL(visibilityChanged(bool)),                  SIGNAL(visibilityChanged(bool)),
# Line 425  void MainForm::setup ( Options *pOptions Line 558  void MainForm::setup ( Options *pOptions
558          }          }
559    
560          // Try to restore old window positioning and initial visibility.          // Try to restore old window positioning and initial visibility.
561          m_pOptions->loadWidgetGeometry(this);          m_pOptions->loadWidgetGeometry(this, true);
562          m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);          m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);
563          m_pOptions->loadWidgetGeometry(m_pDeviceForm);          m_pOptions->loadWidgetGeometry(m_pDeviceForm);
564    
# Line 464  bool MainForm::queryClose (void) Line 597  bool MainForm::queryClose (void)
597                                  || m_ui.channelsToolbar->isVisible());                                  || m_ui.channelsToolbar->isVisible());
598                          m_pOptions->bStatusbar = statusBar()->isVisible();                          m_pOptions->bStatusbar = statusBar()->isVisible();
599                          // Save the dock windows state.                          // Save the dock windows state.
                         const QString sDockables = saveState().toBase64().data();  
600                          m_pOptions->settings().setValue("/Layout/DockWindows", saveState());                          m_pOptions->settings().setValue("/Layout/DockWindows", saveState());
601                          // And the children, and the main windows state,.                          // And the children, and the main windows state,.
602                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);
603                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);
604                          m_pOptions->saveWidgetGeometry(this);                          m_pOptions->saveWidgetGeometry(this, true);
605                          // Close popup widgets.                          // Close popup widgets.
606                          if (m_pInstrumentListForm)                          if (m_pInstrumentListForm)
607                                  m_pInstrumentListForm->close();                                  m_pInstrumentListForm->close();
# Line 498  void MainForm::closeEvent ( QCloseEvent Line 630  void MainForm::closeEvent ( QCloseEvent
630  void MainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )  void MainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )
631  {  {
632          // Accept external drags only...          // Accept external drags only...
633          if (pDragEnterEvent->source() == NULL          if (pDragEnterEvent->source() == nullptr
634                  && pDragEnterEvent->mimeData()->hasUrls()) {                  && pDragEnterEvent->mimeData()->hasUrls()) {
635                  pDragEnterEvent->accept();                  pDragEnterEvent->accept();
636          } else {          } else {
# Line 507  void MainForm::dragEnterEvent ( QDragEnt Line 639  void MainForm::dragEnterEvent ( QDragEnt
639  }  }
640    
641    
642  void MainForm::dropEvent ( QDropEvent* pDropEvent )  void MainForm::dropEvent ( QDropEvent *pDropEvent )
643  {  {
644          // Accept externally originated drops only...          // Accept externally originated drops only...
645          if (pDropEvent->source())          if (pDropEvent->source())
# Line 518  void MainForm::dropEvent ( QDropEvent* p Line 650  void MainForm::dropEvent ( QDropEvent* p
650                  QListIterator<QUrl> iter(pMimeData->urls());                  QListIterator<QUrl> iter(pMimeData->urls());
651                  while (iter.hasNext()) {                  while (iter.hasNext()) {
652                          const QString& sPath = iter.next().toLocalFile();                          const QString& sPath = iter.next().toLocalFile();
653                          if (Channel::isInstrumentFile(sPath)) {                  //      if (Channel::isDlsInstrumentFile(sPath)) {
654                            if (QFileInfo(sPath).exists()) {
655                                  // Try to create a new channel from instrument file...                                  // Try to create a new channel from instrument file...
656                                  Channel *pChannel = new Channel();                                  Channel *pChannel = new Channel();
657                                  if (pChannel == NULL)                                  if (pChannel == nullptr)
658                                          return;                                          return;
659                                  // Start setting the instrument filename...                                  // Start setting the instrument filename...
660                                  pChannel->setInstrument(sPath, 0);                                  pChannel->setInstrument(sPath, 0);
# Line 552  void MainForm::dropEvent ( QDropEvent* p Line 685  void MainForm::dropEvent ( QDropEvent* p
685    
686    
687  // Custome event handler.  // Custome event handler.
688  void MainForm::customEvent(QEvent* pCustomEvent)  void MainForm::customEvent ( QEvent* pEvent )
689  {  {
690          // For the time being, just pump it to messages.          // For the time being, just pump it to messages.
691          if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {          if (pEvent->type() == QSAMPLER_LSCP_EVENT) {
692                  CustomEvent *pEvent = static_cast<CustomEvent *> (pCustomEvent);                  LscpEvent *pLscpEvent = static_cast<LscpEvent *> (pEvent);
693                  switch (pEvent->event()) {                  switch (pLscpEvent->event()) {
694                          case LSCP_EVENT_CHANNEL_COUNT:                          case LSCP_EVENT_CHANNEL_COUNT:
695                                  updateAllChannelStrips(true);                                  updateAllChannelStrips(true);
696                                  break;                                  break;
697                          case LSCP_EVENT_CHANNEL_INFO: {                          case LSCP_EVENT_CHANNEL_INFO: {
698                                  int iChannelID = pEvent->data().toInt();                                  const int iChannelID = pLscpEvent->data().toInt();
699                                  ChannelStrip *pChannelStrip = channelStrip(iChannelID);                                  ChannelStrip *pChannelStrip = channelStrip(iChannelID);
700                                  if (pChannelStrip)                                  if (pChannelStrip)
701                                          channelStripChanged(pChannelStrip);                                          channelStripChanged(pChannelStrip);
# Line 575  void MainForm::customEvent(QEvent* pCust Line 708  void MainForm::customEvent(QEvent* pCust
708                                  break;                                  break;
709                          case LSCP_EVENT_MIDI_INPUT_DEVICE_INFO: {                          case LSCP_EVENT_MIDI_INPUT_DEVICE_INFO: {
710                                  if (m_pDeviceForm) m_pDeviceForm->refreshDevices();                                  if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
711                                  const int iDeviceID = pEvent->data().section(' ', 0, 0).toInt();                                  const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt();
712                                  DeviceStatusForm::onDeviceChanged(iDeviceID);                                  DeviceStatusForm::onDeviceChanged(iDeviceID);
713                                  break;                                  break;
714                          }                          }
# Line 585  void MainForm::customEvent(QEvent* pCust Line 718  void MainForm::customEvent(QEvent* pCust
718                          case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO:                          case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO:
719                                  if (m_pDeviceForm) m_pDeviceForm->refreshDevices();                                  if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
720                                  break;                                  break;
721  #if CONFIG_EVENT_CHANNEL_MIDI                  #if CONFIG_EVENT_CHANNEL_MIDI
722                          case LSCP_EVENT_CHANNEL_MIDI: {                          case LSCP_EVENT_CHANNEL_MIDI: {
723                                  const int iChannelID = pEvent->data().section(' ', 0, 0).toInt();                                  const int iChannelID = pLscpEvent->data().section(' ', 0, 0).toInt();
724                                  ChannelStrip *pChannelStrip = channelStrip(iChannelID);                                  ChannelStrip *pChannelStrip = channelStrip(iChannelID);
725                                  if (pChannelStrip)                                  if (pChannelStrip)
726                                          pChannelStrip->midiArrived();                                          pChannelStrip->midiActivityLedOn();
727                                  break;                                  break;
728                          }                          }
729  #endif                  #endif
730  #if CONFIG_EVENT_DEVICE_MIDI                  #if CONFIG_EVENT_DEVICE_MIDI
731                          case LSCP_EVENT_DEVICE_MIDI: {                          case LSCP_EVENT_DEVICE_MIDI: {
732                                  const int iDeviceID = pEvent->data().section(' ', 0, 0).toInt();                                  const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt();
733                                  const int iPortID   = pEvent->data().section(' ', 1, 1).toInt();                                  const int iPortID   = pLscpEvent->data().section(' ', 1, 1).toInt();
734                                  DeviceStatusForm* pDeviceStatusForm =                                  DeviceStatusForm *pDeviceStatusForm
735                                          DeviceStatusForm::getInstance(iDeviceID);                                          = DeviceStatusForm::getInstance(iDeviceID);
736                                  if (pDeviceStatusForm)                                  if (pDeviceStatusForm)
737                                          pDeviceStatusForm->midiArrived(iPortID);                                          pDeviceStatusForm->midiArrived(iPortID);
738                                  break;                                  break;
739                          }                          }
740  #endif                  #endif
741                          default:                          default:
742                                  appendMessagesColor(tr("Notify event: %1 data: %2")                                  appendMessagesColor(tr("LSCP Event: %1 data: %2")
743                                          .arg(::lscp_event_to_text(pEvent->event()))                                          .arg(::lscp_event_to_text(pLscpEvent->event()))
744                                          .arg(pEvent->data()), "#996699");                                          .arg(pLscpEvent->data()), "#996699");
745                  }                  }
746          }          }
747  }  }
748    
749  void MainForm::updateViewMidiDeviceStatusMenu() {  
750    // LADISH Level 1 -- SIGUSR1 signal handler.
751    void MainForm::handle_sigusr1 (void)
752    {
753    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
754    
755            char c;
756    
757            if (::read(g_fdSigusr1[1], &c, sizeof(c)) > 0)
758                    saveSession(false);
759    
760    #endif
761    }
762    
763    
764    void MainForm::handle_sigterm (void)
765    {
766    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
767    
768            char c;
769    
770            if (::read(g_fdSigterm[1], &c, sizeof(c)) > 0)
771                    close();
772    
773    #endif
774    }
775    
776    
777    void MainForm::updateViewMidiDeviceStatusMenu (void)
778    {
779          m_ui.viewMidiDeviceStatusMenu->clear();          m_ui.viewMidiDeviceStatusMenu->clear();
780          const std::map<int, DeviceStatusForm*> statusForms =          const std::map<int, DeviceStatusForm *> statusForms
781                  DeviceStatusForm::getInstances();                  = DeviceStatusForm::getInstances();
782          for (          std::map<int, DeviceStatusForm *>::const_iterator iter
783                  std::map<int, DeviceStatusForm*>::const_iterator iter = statusForms.begin();                  = statusForms.begin();
784                  iter != statusForms.end(); ++iter          for ( ; iter != statusForms.end(); ++iter) {
785          ) {                  DeviceStatusForm *pStatusForm = iter->second;
                 DeviceStatusForm* pForm = iter->second;  
786                  m_ui.viewMidiDeviceStatusMenu->addAction(                  m_ui.viewMidiDeviceStatusMenu->addAction(
787                          pForm->visibleAction()                          pStatusForm->visibleAction());
                 );  
788          }          }
789  }  }
790    
791    
792  // Context menu event handler.  // Context menu event handler.
793  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )
794  {  {
# Line 638  void MainForm::contextMenuEvent( QContex Line 799  void MainForm::contextMenuEvent( QContex
799    
800    
801  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
802  // qsamplerMainForm -- Brainless public property accessors.  // QSampler::MainForm -- Brainless public property accessors.
803    
804  // The global options settings property.  // The global options settings property.
805  Options *MainForm::options (void) const  Options *MainForm::options (void) const
# Line 662  MainForm *MainForm::getInstance (void) Line 823  MainForm *MainForm::getInstance (void)
823    
824    
825  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
826  // qsamplerMainForm -- Session file stuff.  // QSampler::MainForm -- Session file stuff.
827    
828  // Format the displayable session filename.  // Format the displayable session filename.
829  QString MainForm::sessionName ( const QString& sFilename )  QString MainForm::sessionName ( const QString& sFilename )
830  {  {
831          bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);          const bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);
832          QString sSessionName = sFilename;          QString sSessionName = sFilename;
833          if (sSessionName.isEmpty())          if (sSessionName.isEmpty())
834                  sSessionName = tr("Untitled") + QString::number(m_iUntitled);                  sSessionName = tr("Untitled") + QString::number(m_iUntitled);
# Line 691  bool MainForm::newSession (void) Line 852  bool MainForm::newSession (void)
852          m_iUntitled++;          m_iUntitled++;
853    
854          // Stabilize form.          // Stabilize form.
855          m_sFilename = QString::null;          m_sFilename = QString();
856          m_iDirtyCount = 0;          m_iDirtyCount = 0;
857          appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));          appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));
858          stabilizeForm();          stabilizeForm();
# Line 703  bool MainForm::newSession (void) Line 864  bool MainForm::newSession (void)
864  // Open an existing sampler session.  // Open an existing sampler session.
865  bool MainForm::openSession (void)  bool MainForm::openSession (void)
866  {  {
867          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
868                  return false;                  return false;
869    
870          // Ask for the filename to open...          // Ask for the filename to open...
871          QString sFilename = QFileDialog::getOpenFileName(this,          QString sFilename = QFileDialog::getOpenFileName(this,
872                  QSAMPLER_TITLE ": " + tr("Open Session"), // Caption.                  tr("Open Session"),                       // Caption.
873                  m_pOptions->sSessionDir,                  // Start here.                  m_pOptions->sSessionDir,                  // Start here.
874                  tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)                  tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
875          );          );
# Line 729  bool MainForm::openSession (void) Line 890  bool MainForm::openSession (void)
890  // Save current sampler session with another name.  // Save current sampler session with another name.
891  bool MainForm::saveSession ( bool bPrompt )  bool MainForm::saveSession ( bool bPrompt )
892  {  {
893          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
894                  return false;                  return false;
895    
896          QString sFilename = m_sFilename;          QString sFilename = m_sFilename;
# Line 741  bool MainForm::saveSession ( bool bPromp Line 902  bool MainForm::saveSession ( bool bPromp
902                          sFilename = m_pOptions->sSessionDir;                          sFilename = m_pOptions->sSessionDir;
903                  // Prompt the guy...                  // Prompt the guy...
904                  sFilename = QFileDialog::getSaveFileName(this,                  sFilename = QFileDialog::getSaveFileName(this,
905                          QSAMPLER_TITLE ": " + tr("Save Session"), // Caption.                          tr("Save Session"),                       // Caption.
906                          sFilename,                                // Start here.                          sFilename,                                // Start here.
907                          tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)                          tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
908                  );                  );
# Line 751  bool MainForm::saveSession ( bool bPromp Line 912  bool MainForm::saveSession ( bool bPromp
912                  // Enforce .lscp extension...                  // Enforce .lscp extension...
913                  if (QFileInfo(sFilename).suffix().isEmpty())                  if (QFileInfo(sFilename).suffix().isEmpty())
914                          sFilename += ".lscp";                          sFilename += ".lscp";
915            #if 0
916                  // Check if already exists...                  // Check if already exists...
917                  if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {                  if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {
918                          if (QMessageBox::warning(this,                          if (QMessageBox::warning(this,
919                                  QSAMPLER_TITLE ": " + tr("Warning"),                                  tr("Warning"),
920                                  tr("The file already exists:\n\n"                                  tr("The file already exists:\n\n"
921                                  "\"%1\"\n\n"                                  "\"%1\"\n\n"
922                                  "Do you want to replace it?")                                  "Do you want to replace it?")
923                                  .arg(sFilename),                                  .arg(sFilename),
924                                  tr("Replace"), tr("Cancel")) > 0)                                  QMessageBox::Yes | QMessageBox::No)
925                                    == QMessageBox::No)
926                                  return false;                                  return false;
927                  }                  }
928            #endif
929          }          }
930    
931          // Save it right away.          // Save it right away.
# Line 777  bool MainForm::closeSession ( bool bForc Line 941  bool MainForm::closeSession ( bool bForc
941          // Are we dirty enough to prompt it?          // Are we dirty enough to prompt it?
942          if (m_iDirtyCount > 0) {          if (m_iDirtyCount > 0) {
943                  switch (QMessageBox::warning(this,                  switch (QMessageBox::warning(this,
944                          QSAMPLER_TITLE ": " + tr("Warning"),                          tr("Warning"),
945                          tr("The current session has been changed:\n\n"                          tr("The current session has been changed:\n\n"
946                          "\"%1\"\n\n"                          "\"%1\"\n\n"
947                          "Do you want to save the changes?")                          "Do you want to save the changes?")
948                          .arg(sessionName(m_sFilename)),                          .arg(sessionName(m_sFilename)),
949                          tr("Save"), tr("Discard"), tr("Cancel"))) {                          QMessageBox::Save |
950                  case 0:     // Save...                          QMessageBox::Discard |
951                            QMessageBox::Cancel)) {
952                    case QMessageBox::Save:
953                          bClose = saveSession(false);                          bClose = saveSession(false);
954                          // Fall thru....                          // Fall thru....
955                  case 1:     // Discard                  case QMessageBox::Discard:
956                          break;                          break;
957                  default:    // Cancel.                  default:    // Cancel.
958                          bClose = false;                          bClose = false;
# Line 798  bool MainForm::closeSession ( bool bForc Line 964  bool MainForm::closeSession ( bool bForc
964          if (bClose) {          if (bClose) {
965                  // Remove all channel strips from sight...                  // Remove all channel strips from sight...
966                  m_pWorkspace->setUpdatesEnabled(false);                  m_pWorkspace->setUpdatesEnabled(false);
967                  QWidgetList wlist = m_pWorkspace->windowList();                  const QList<QMdiSubWindow *>& wlist
968                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                          = m_pWorkspace->subWindowList();
969                          ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
970                            ChannelStrip *pChannelStrip
971                                    = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
972                          if (pChannelStrip) {                          if (pChannelStrip) {
973                                  Channel *pChannel = pChannelStrip->channel();                                  Channel *pChannel = pChannelStrip->channel();
974                                  if (bForce && pChannel)                                  if (bForce && pChannel)
975                                          pChannel->removeChannel();                                          pChannel->removeChannel();
976                                  delete pChannelStrip;                                  delete pChannelStrip;
977                          }                          }
978                            delete pMdiSubWindow;
979                  }                  }
980                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
981                  // We're now clean, for sure.                  // We're now clean, for sure.
# Line 820  bool MainForm::closeSession ( bool bForc Line 989  bool MainForm::closeSession ( bool bForc
989  // Load a session from specific file path.  // Load a session from specific file path.
990  bool MainForm::loadSessionFile ( const QString& sFilename )  bool MainForm::loadSessionFile ( const QString& sFilename )
991  {  {
992          if (m_pClient == NULL)          if (m_pClient == nullptr)
993                  return false;                  return false;
994    
995          // Open and read from real file.          // Open and read from real file.
# Line 896  bool MainForm::loadSessionFile ( const Q Line 1065  bool MainForm::loadSessionFile ( const Q
1065  // Save current session to specific file path.  // Save current session to specific file path.
1066  bool MainForm::saveSessionFile ( const QString& sFilename )  bool MainForm::saveSessionFile ( const QString& sFilename )
1067  {  {
1068          if (m_pClient == NULL)          if (m_pClient == nullptr)
1069                  return false;                  return false;
1070    
1071          // Check whether server is apparently OK...          // Check whether server is apparently OK...
# Line 918  bool MainForm::saveSessionFile ( const Q Line 1087  bool MainForm::saveSessionFile ( const Q
1087          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1088    
1089          // Write the file.          // Write the file.
1090          int  iErrors = 0;          int iErrors = 0;
1091          QTextStream ts(&file);          QTextStream ts(&file);
1092          ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;          ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;
1093          ts << "# " << tr("Version")          ts << "# " << tr("Version") << ": " CONFIG_BUILD_VERSION << endl;
1094          << ": " QSAMPLER_VERSION << endl;  //      ts << "# " << tr("Build") << ": " CONFIG_BUILD_DATE << endl;
         ts << "# " << tr("Build")  
         << ": " __DATE__ " " __TIME__ << endl;  
1095          ts << "#"  << endl;          ts << "#"  << endl;
1096          ts << "# " << tr("File")          ts << "# " << tr("File")
1097          << ": " << QFileInfo(sFilename).fileName() << endl;          << ": " << QFileInfo(sFilename).fileName() << endl;
# Line 937  bool MainForm::saveSessionFile ( const Q Line 1104  bool MainForm::saveSessionFile ( const Q
1104          // It is assumed that this new kind of device+session file          // It is assumed that this new kind of device+session file
1105          // will be loaded from a complete initialized server...          // will be loaded from a complete initialized server...
1106          int *piDeviceIDs;          int *piDeviceIDs;
1107          int  iDevice;          int  i, iDevice;
1108          ts << "RESET" << endl;          ts << "RESET" << endl;
1109    
1110          // Audio device mapping.          // Audio device mapping.
1111          QMap<int, int> audioDeviceMap;          QMap<int, int> audioDeviceMap; iDevice = 0;
1112          piDeviceIDs = Device::getDevices(m_pClient, Device::Audio);          piDeviceIDs = Device::getDevices(m_pClient, Device::Audio);
1113          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (i = 0; piDeviceIDs && piDeviceIDs[i] >= 0; ++i) {
1114                  ts << endl;                  Device device(Device::Audio, piDeviceIDs[i]);
1115                  Device device(Device::Audio, piDeviceIDs[iDevice]);                  // Avoid plug-in driver devices...
1116                    if (device.driverName().toUpper() == "PLUGIN")
1117                            continue;
1118                  // Audio device specification...                  // Audio device specification...
1119                    ts << endl;
1120                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1121                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1122                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();
# Line 977  bool MainForm::saveSessionFile ( const Q Line 1147  bool MainForm::saveSessionFile ( const Q
1147                          iPort++;                          iPort++;
1148                  }                  }
1149                  // Audio device index/id mapping.                  // Audio device index/id mapping.
1150                  audioDeviceMap[device.deviceID()] = iDevice;                  audioDeviceMap.insert(device.deviceID(), iDevice++);
1151                  // Try to keep it snappy :)                  // Try to keep it snappy :)
1152                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1153          }          }
1154    
1155          // MIDI device mapping.          // MIDI device mapping.
1156          QMap<int, int> midiDeviceMap;          QMap<int, int> midiDeviceMap; iDevice = 0;
1157          piDeviceIDs = Device::getDevices(m_pClient, Device::Midi);          piDeviceIDs = Device::getDevices(m_pClient, Device::Midi);
1158          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (i = 0; piDeviceIDs && piDeviceIDs[i] >= 0; ++i) {
1159                  ts << endl;                  Device device(Device::Midi, piDeviceIDs[i]);
1160                  Device device(Device::Midi, piDeviceIDs[iDevice]);                  // Avoid plug-in driver devices...
1161                    if (device.driverName().toUpper() == "PLUGIN")
1162                            continue;
1163                  // MIDI device specification...                  // MIDI device specification...
1164                    ts << endl;
1165                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1166                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1167                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();
# Line 1019  bool MainForm::saveSessionFile ( const Q Line 1192  bool MainForm::saveSessionFile ( const Q
1192                          iPort++;                          iPort++;
1193                  }                  }
1194                  // MIDI device index/id mapping.                  // MIDI device index/id mapping.
1195                  midiDeviceMap[device.deviceID()] = iDevice;                  midiDeviceMap.insert(device.deviceID(), iDevice++);
1196                  // Try to keep it snappy :)                  // Try to keep it snappy :)
1197                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1198          }          }
# Line 1030  bool MainForm::saveSessionFile ( const Q Line 1203  bool MainForm::saveSessionFile ( const Q
1203          QMap<int, int> midiInstrumentMap;          QMap<int, int> midiInstrumentMap;
1204          int *piMaps = ::lscp_list_midi_instrument_maps(m_pClient);          int *piMaps = ::lscp_list_midi_instrument_maps(m_pClient);
1205          for (int iMap = 0; piMaps && piMaps[iMap] >= 0; iMap++) {          for (int iMap = 0; piMaps && piMaps[iMap] >= 0; iMap++) {
1206                  int iMidiMap = piMaps[iMap];                  const int iMidiMap = piMaps[iMap];
1207                  const char *pszMapName                  const char *pszMapName
1208                          = ::lscp_get_midi_instrument_map_name(m_pClient, iMidiMap);                          = ::lscp_get_midi_instrument_map_name(m_pClient, iMidiMap);
1209                  ts << "# " << tr("MIDI instrument map") << " " << iMap;                  ts << "# " << tr("MIDI instrument map") << " " << iMap;
# Line 1082  bool MainForm::saveSessionFile ( const Q Line 1255  bool MainForm::saveSessionFile ( const Q
1255                  }                  }
1256                  ts << endl;                  ts << endl;
1257                  // Check for errors...                  // Check for errors...
1258                  if (pInstrs == NULL && ::lscp_client_get_errno(m_pClient)) {                  if (pInstrs == nullptr && ::lscp_client_get_errno(m_pClient)) {
1259                          appendMessagesClient("lscp_list_midi_instruments");                          appendMessagesClient("lscp_list_midi_instruments");
1260                          iErrors++;                          iErrors++;
1261                  }                  }
1262                  // MIDI strument index/id mapping.                  // MIDI strument index/id mapping.
1263                  midiInstrumentMap[iMidiMap] = iMap;                  midiInstrumentMap.insert(iMidiMap, iMap);
1264          }          }
1265          // Check for errors...          // Check for errors...
1266          if (piMaps == NULL && ::lscp_client_get_errno(m_pClient)) {          if (piMaps == nullptr && ::lscp_client_get_errno(m_pClient)) {
1267                  appendMessagesClient("lscp_list_midi_instrument_maps");                  appendMessagesClient("lscp_list_midi_instrument_maps");
1268                  iErrors++;                  iErrors++;
1269          }          }
1270  #endif  // CONFIG_MIDI_INSTRUMENT  #endif  // CONFIG_MIDI_INSTRUMENT
1271    
1272          // Sampler channel mapping.          // Sampler channel mapping...
1273          QWidgetList wlist = m_pWorkspace->windowList();          int iChannelID = 0;
1274          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          const QList<QMdiSubWindow *>& wlist
1275                  ChannelStrip* pChannelStrip                  = m_pWorkspace->subWindowList();
1276                          = static_cast<ChannelStrip *> (wlist.at(iChannel));          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
1277                    ChannelStrip *pChannelStrip
1278                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
1279                  if (pChannelStrip) {                  if (pChannelStrip) {
1280                          Channel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
1281                          if (pChannel) {                          if (pChannel) {
1282                                  ts << "# " << tr("Channel") << " " << iChannel << endl;                                  // Avoid "artifial" plug-in devices...
1283                                    const int iAudioDevice = pChannel->audioDevice();
1284                                    if (!audioDeviceMap.contains(iAudioDevice))
1285                                            continue;
1286                                    const int iMidiDevice = pChannel->midiDevice();
1287                                    if (!midiDeviceMap.contains(iMidiDevice))
1288                                            continue;
1289                                    // Go for regular, canonical devices...
1290                                    ts << "# " << tr("Channel") << " " << iChannelID << endl;
1291                                  ts << "ADD CHANNEL" << endl;                                  ts << "ADD CHANNEL" << endl;
1292                                  if (audioDeviceMap.isEmpty()) {                                  if (audioDeviceMap.isEmpty()) {
1293                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannelID
1294                                                  << " " << pChannel->audioDriver() << endl;                                                  << " " << pChannel->audioDriver() << endl;
1295                                  } else {                                  } else {
1296                                          ts << "SET CHANNEL AUDIO_OUTPUT_DEVICE " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_DEVICE " << iChannelID
1297                                                  << " " << audioDeviceMap[pChannel->audioDevice()] << endl;                                                  << " " << audioDeviceMap.value(iAudioDevice) << endl;
1298                                  }                                  }
1299                                  if (midiDeviceMap.isEmpty()) {                                  if (midiDeviceMap.isEmpty()) {
1300                                          ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannel                                          ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannelID
1301                                                  << " " << pChannel->midiDriver() << endl;                                                  << " " << pChannel->midiDriver() << endl;
1302                                  } else {                                  } else {
1303                                          ts << "SET CHANNEL MIDI_INPUT_DEVICE " << iChannel                                          ts << "SET CHANNEL MIDI_INPUT_DEVICE " << iChannelID
1304                                                  << " " << midiDeviceMap[pChannel->midiDevice()] << endl;                                                  << " " << midiDeviceMap.value(iMidiDevice) << endl;
1305                                  }                                  }
1306                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannelID
1307                                          << " " << pChannel->midiPort() << endl;                                          << " " << pChannel->midiPort() << endl;
1308                                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";                                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannelID << " ";
1309                                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)                                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
1310                                          ts << "ALL";                                          ts << "ALL";
1311                                  else                                  else
1312                                          ts << pChannel->midiChannel();                                          ts << pChannel->midiChannel();
1313                                  ts << endl;                                  ts << endl;
1314                                  ts << "LOAD ENGINE " << pChannel->engineName()                                  ts << "LOAD ENGINE " << pChannel->engineName()
1315                                          << " " << iChannel << endl;                                          << " " << iChannelID << endl;
1316                                  if (pChannel->instrumentStatus() < 100) ts << "# ";                                  if (pChannel->instrumentStatus() < 100) ts << "# ";
1317                                  ts << "LOAD INSTRUMENT NON_MODAL '"                                  ts << "LOAD INSTRUMENT NON_MODAL '"
1318                                          << pChannel->instrumentFile() << "' "                                          << pChannel->instrumentFile() << "' "
1319                                          << pChannel->instrumentNr() << " " << iChannel << endl;                                          << pChannel->instrumentNr() << " " << iChannelID << endl;
1320                                  ChannelRoutingMap::ConstIterator audioRoute;                                  ChannelRoutingMap::ConstIterator audioRoute;
1321                                  for (audioRoute = pChannel->audioRouting().begin();                                  for (audioRoute = pChannel->audioRouting().begin();
1322                                                  audioRoute != pChannel->audioRouting().end();                                                  audioRoute != pChannel->audioRouting().end();
1323                                                          ++audioRoute) {                                                          ++audioRoute) {
1324                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannelID
1325                                                  << " " << audioRoute.key()                                                  << " " << audioRoute.key()
1326                                                  << " " << audioRoute.value() << endl;                                                  << " " << audioRoute.value() << endl;
1327                                  }                                  }
1328                                  ts << "SET CHANNEL VOLUME " << iChannel                                  ts << "SET CHANNEL VOLUME " << iChannelID
1329                                          << " " << pChannel->volume() << endl;                                          << " " << pChannel->volume() << endl;
1330                                  if (pChannel->channelMute())                                  if (pChannel->channelMute())
1331                                          ts << "SET CHANNEL MUTE " << iChannel << " 1" << endl;                                          ts << "SET CHANNEL MUTE " << iChannelID << " 1" << endl;
1332                                  if (pChannel->channelSolo())                                  if (pChannel->channelSolo())
1333                                          ts << "SET CHANNEL SOLO " << iChannel << " 1" << endl;                                          ts << "SET CHANNEL SOLO " << iChannelID << " 1" << endl;
1334  #ifdef CONFIG_MIDI_INSTRUMENT                          #ifdef CONFIG_MIDI_INSTRUMENT
1335                                  if (pChannel->midiMap() >= 0) {                                  const int iMidiMap = pChannel->midiMap();
1336                                          ts << "SET CHANNEL MIDI_INSTRUMENT_MAP " << iChannel                                  if (midiInstrumentMap.contains(iMidiMap)) {
1337                                                  << " " << midiInstrumentMap[pChannel->midiMap()] << endl;                                          ts << "SET CHANNEL MIDI_INSTRUMENT_MAP " << iChannelID
1338                                                    << " " << midiInstrumentMap.value(iMidiMap) << endl;
1339                                  }                                  }
1340  #endif                          #endif
1341  #ifdef CONFIG_FXSEND                          #ifdef CONFIG_FXSEND
                                 int iChannelID = pChannel->channelID();  
1342                                  int *piFxSends = ::lscp_list_fxsends(m_pClient, iChannelID);                                  int *piFxSends = ::lscp_list_fxsends(m_pClient, iChannelID);
1343                                  for (int iFxSend = 0;                                  for (int iFxSend = 0;
1344                                                  piFxSends && piFxSends[iFxSend] >= 0;                                                  piFxSends && piFxSends[iFxSend] >= 0;
# Line 1163  bool MainForm::saveSessionFile ( const Q Line 1346  bool MainForm::saveSessionFile ( const Q
1346                                          lscp_fxsend_info_t *pFxSendInfo = ::lscp_get_fxsend_info(                                          lscp_fxsend_info_t *pFxSendInfo = ::lscp_get_fxsend_info(
1347                                                  m_pClient, iChannelID, piFxSends[iFxSend]);                                                  m_pClient, iChannelID, piFxSends[iFxSend]);
1348                                          if (pFxSendInfo) {                                          if (pFxSendInfo) {
1349                                                  ts << "CREATE FX_SEND " << iChannel                                                  ts << "CREATE FX_SEND " << iChannelID
1350                                                          << " " << pFxSendInfo->midi_controller;                                                          << " " << pFxSendInfo->midi_controller;
1351                                                  if (pFxSendInfo->name)                                                  if (pFxSendInfo->name)
1352                                                          ts << " '" << pFxSendInfo->name << "'";                                                          ts << " '" << pFxSendInfo->name << "'";
# Line 1173  bool MainForm::saveSessionFile ( const Q Line 1356  bool MainForm::saveSessionFile ( const Q
1356                                                                  piRouting && piRouting[iAudioSrc] >= 0;                                                                  piRouting && piRouting[iAudioSrc] >= 0;
1357                                                                          iAudioSrc++) {                                                                          iAudioSrc++) {
1358                                                          ts << "SET FX_SEND AUDIO_OUTPUT_CHANNEL "                                                          ts << "SET FX_SEND AUDIO_OUTPUT_CHANNEL "
1359                                                                  << iChannel                                                                  << iChannelID
1360                                                                  << " " << iFxSend                                                                  << " " << iFxSend
1361                                                                  << " " << iAudioSrc                                                                  << " " << iAudioSrc
1362                                                                  << " " << piRouting[iAudioSrc] << endl;                                                                  << " " << piRouting[iAudioSrc] << endl;
1363                                                  }                                                  }
1364  #ifdef CONFIG_FXSEND_LEVEL                                          #ifdef CONFIG_FXSEND_LEVEL
1365                                                  ts << "SET FX_SEND LEVEL " << iChannel                                                  ts << "SET FX_SEND LEVEL " << iChannelID
1366                                                          << " " << iFxSend                                                          << " " << iFxSend
1367                                                          << " " << pFxSendInfo->level << endl;                                                          << " " << pFxSendInfo->level << endl;
1368  #endif                                          #endif
1369                                          }       // Check for errors...                                          }       // Check for errors...
1370                                          else if (::lscp_client_get_errno(m_pClient)) {                                          else if (::lscp_client_get_errno(m_pClient)) {
1371                                                  appendMessagesClient("lscp_get_fxsend_info");                                                  appendMessagesClient("lscp_get_fxsend_info");
1372                                                  iErrors++;                                                  iErrors++;
1373                                          }                                          }
1374                                  }                                  }
1375  #endif                          #endif
1376                                  ts << endl;                                  ts << endl;
1377                                    // Go for next channel...
1378                                    ++iChannelID;
1379                          }                          }
1380                  }                  }
1381                  // Try to keep it snappy :)                  // Try to keep it snappy :)
# Line 1242  void MainForm::sessionDirty (void) Line 1427  void MainForm::sessionDirty (void)
1427    
1428    
1429  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1430  // qsamplerMainForm -- File Action slots.  // QSampler::MainForm -- File Action slots.
1431    
1432  // Create a new sampler session.  // Create a new sampler session.
1433  void MainForm::fileNew (void)  void MainForm::fileNew (void)
# Line 1266  void MainForm::fileOpenRecent (void) Line 1451  void MainForm::fileOpenRecent (void)
1451          // Retrive filename index from action data...          // Retrive filename index from action data...
1452          QAction *pAction = qobject_cast<QAction *> (sender());          QAction *pAction = qobject_cast<QAction *> (sender());
1453          if (pAction && m_pOptions) {          if (pAction && m_pOptions) {
1454                  int iIndex = pAction->data().toInt();                  const int iIndex = pAction->data().toInt();
1455                  if (iIndex >= 0 && iIndex < m_pOptions->recentFiles.count()) {                  if (iIndex >= 0 && iIndex < m_pOptions->recentFiles.count()) {
1456                          QString sFilename = m_pOptions->recentFiles[iIndex];                          QString sFilename = m_pOptions->recentFiles[iIndex];
1457                          // Check if we can safely close the current session...                          // Check if we can safely close the current session...
# Line 1296  void MainForm::fileSaveAs (void) Line 1481  void MainForm::fileSaveAs (void)
1481  // Reset the sampler instance.  // Reset the sampler instance.
1482  void MainForm::fileReset (void)  void MainForm::fileReset (void)
1483  {  {
1484          if (m_pClient == NULL)          if (m_pClient == nullptr)
1485                  return;                  return;
1486    
1487          // Ask user whether he/she want's an internal sampler reset...          // Ask user whether he/she want's an internal sampler reset...
1488          if (QMessageBox::warning(this,          if (m_pOptions && m_pOptions->bConfirmReset) {
1489                  QSAMPLER_TITLE ": " + tr("Warning"),                  const QString& sTitle = tr("Warning");
1490                  tr("Resetting the sampler instance will close\n"                  const QString& sText = tr(
1491                  "all device and channel configurations.\n\n"                          "Resetting the sampler instance will close\n"
1492                  "Please note that this operation may cause\n"                          "all device and channel configurations.\n\n"
1493                  "temporary MIDI and Audio disruption.\n\n"                          "Please note that this operation may cause\n"
1494                  "Do you want to reset the sampler engine now?"),                          "temporary MIDI and Audio disruption.\n\n"
1495                  tr("Reset"), tr("Cancel")) > 0)                          "Do you want to reset the sampler engine now?");
1496                  return;          #if 0
1497                    if (QMessageBox::warning(this, sTitle, sText,
1498                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1499                            return;
1500            #else
1501                    QMessageBox mbox(this);
1502                    mbox.setIcon(QMessageBox::Warning);
1503                    mbox.setWindowTitle(sTitle);
1504                    mbox.setText(sText);
1505                    mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1506                    QCheckBox cbox(tr("Don't ask this again"));
1507                    cbox.setChecked(false);
1508                    cbox.blockSignals(true);
1509                    mbox.addButton(&cbox, QMessageBox::ActionRole);
1510                    if (mbox.exec() == QMessageBox::Cancel)
1511                            return;
1512                    if (cbox.isChecked())
1513                            m_pOptions->bConfirmReset = false;
1514            #endif
1515            }
1516    
1517          // Trye closing the current session, first...          // Trye closing the current session, first...
1518          if (!closeSession(true))          if (!closeSession(true))
# Line 1333  void MainForm::fileReset (void) Line 1537  void MainForm::fileReset (void)
1537  // Restart the client/server instance.  // Restart the client/server instance.
1538  void MainForm::fileRestart (void)  void MainForm::fileRestart (void)
1539  {  {
1540          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
1541                  return;                  return;
1542    
1543          bool bRestart = true;          bool bRestart = true;
1544    
1545          // Ask user whether he/she want's a complete restart...          // Ask user whether he/she want's a complete restart...
1546          // (if we're currently up and running)          // (if we're currently up and running)
1547          if (bRestart && m_pClient) {          if (m_pOptions && m_pOptions->bConfirmRestart) {
1548                  bRestart = (QMessageBox::warning(this,                  const QString& sTitle = tr("Warning");
1549                          QSAMPLER_TITLE ": " + tr("Warning"),                  const QString& sText = tr(
1550                          tr("New settings will be effective after\n"                          "New settings will be effective after\n"
1551                          "restarting the client/server connection.\n\n"                          "restarting the client/server connection.\n\n"
1552                          "Please note that this operation may cause\n"                          "Please note that this operation may cause\n"
1553                          "temporary MIDI and Audio disruption.\n\n"                          "temporary MIDI and Audio disruption.\n\n"
1554                          "Do you want to restart the connection now?"),                          "Do you want to restart the connection now?");
1555                          tr("Restart"), tr("Cancel")) == 0);          #if 0
1556                    if (QMessageBox::warning(this, sTitle, sText,
1557                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1558                            bRestart = false;
1559            #else
1560                    QMessageBox mbox(this);
1561                    mbox.setIcon(QMessageBox::Warning);
1562                    mbox.setWindowTitle(sTitle);
1563                    mbox.setText(sText);
1564                    mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1565                    QCheckBox cbox(tr("Don't ask this again"));
1566                    cbox.setChecked(false);
1567                    cbox.blockSignals(true);
1568                    mbox.addButton(&cbox, QMessageBox::ActionRole);
1569                    if (mbox.exec() == QMessageBox::Cancel)
1570                            bRestart = false;
1571                    else
1572                    if (cbox.isChecked())
1573                            m_pOptions->bConfirmRestart = false;
1574            #endif
1575          }          }
1576    
1577          // Are we still for it?          // Are we still for it?
# Line 1370  void MainForm::fileExit (void) Line 1593  void MainForm::fileExit (void)
1593    
1594    
1595  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1596  // qsamplerMainForm -- Edit Action slots.  // QSampler::MainForm -- Edit Action slots.
1597    
1598  // Add a new sampler channel.  // Add a new sampler channel.
1599  void MainForm::editAddChannel (void)  void MainForm::editAddChannel (void)
1600  {  {
1601          if (m_pClient == NULL)          ++m_iDirtySetup;
1602            addChannelStrip();
1603            --m_iDirtySetup;
1604    }
1605    
1606    void MainForm::addChannelStrip (void)
1607    {
1608            if (m_pClient == nullptr)
1609                  return;                  return;
1610    
1611          // Just create the channel instance...          // Just create the channel instance...
1612          Channel *pChannel = new Channel();          Channel *pChannel = new Channel();
1613          if (pChannel == NULL)          if (pChannel == nullptr)
1614                  return;                  return;
1615    
1616          // Before we show it up, may be we'll          // Before we show it up, may be we'll
# Line 1398  void MainForm::editAddChannel (void) Line 1628  void MainForm::editAddChannel (void)
1628          }          }
1629    
1630          // Do we auto-arrange?          // Do we auto-arrange?
1631          if (m_pOptions && m_pOptions->bAutoArrange)          channelsArrangeAuto();
                 channelsArrange();  
1632    
1633          // Make that an overall update.          // Make that an overall update.
1634          m_iDirtyCount++;          m_iDirtyCount++;
# Line 1410  void MainForm::editAddChannel (void) Line 1639  void MainForm::editAddChannel (void)
1639  // Remove current sampler channel.  // Remove current sampler channel.
1640  void MainForm::editRemoveChannel (void)  void MainForm::editRemoveChannel (void)
1641  {  {
1642          if (m_pClient == NULL)          ++m_iDirtySetup;
1643            removeChannelStrip();
1644            --m_iDirtySetup;
1645    }
1646    
1647    void MainForm::removeChannelStrip (void)
1648    {
1649            if (m_pClient == nullptr)
1650                  return;                  return;
1651    
1652          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1653          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
1654                  return;                  return;
1655    
1656          Channel *pChannel = pChannelStrip->channel();          Channel *pChannel = pChannelStrip->channel();
1657          if (pChannel == NULL)          if (pChannel == nullptr)
1658                  return;                  return;
1659    
1660          // Prompt user if he/she's sure about this...          // Prompt user if he/she's sure about this...
1661          if (m_pOptions && m_pOptions->bConfirmRemove) {          if (m_pOptions && m_pOptions->bConfirmRemove) {
1662                  if (QMessageBox::warning(this,                  const QString& sTitle = tr("Warning");
1663                          QSAMPLER_TITLE ": " + tr("Warning"),                  const QString& sText = tr(
1664                          tr("About to remove channel:\n\n"                          "About to remove channel:\n\n"
1665                          "%1\n\n"                          "%1\n\n"
1666                          "Are you sure?")                          "Are you sure?")
1667                          .arg(pChannelStrip->windowTitle()),                          .arg(pChannelStrip->windowTitle());
1668                          tr("OK"), tr("Cancel")) > 0)          #if 0
1669                    if (QMessageBox::warning(this, sTitle, sText,
1670                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1671                            return;
1672            #else
1673                    QMessageBox mbox(this);
1674                    mbox.setIcon(QMessageBox::Warning);
1675                    mbox.setWindowTitle(sTitle);
1676                    mbox.setText(sText);
1677                    mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1678                    QCheckBox cbox(tr("Don't ask this again"));
1679                    cbox.setChecked(false);
1680                    cbox.blockSignals(true);
1681                    mbox.addButton(&cbox, QMessageBox::ActionRole);
1682                    if (mbox.exec() == QMessageBox::Cancel)
1683                          return;                          return;
1684                    if (cbox.isChecked())
1685                            m_pOptions->bConfirmRemove = false;
1686            #endif
1687          }          }
1688    
1689          // Remove the existing sampler channel.          // Remove the existing sampler channel.
# Line 1438  void MainForm::editRemoveChannel (void) Line 1691  void MainForm::editRemoveChannel (void)
1691                  return;                  return;
1692    
1693          // Just delete the channel strip.          // Just delete the channel strip.
1694          delete pChannelStrip;          destroyChannelStrip(pChannelStrip);
   
         // Do we auto-arrange?  
         if (m_pOptions && m_pOptions->bAutoArrange)  
                 channelsArrange();  
1695    
1696          // We'll be dirty, for sure...          // We'll be dirty, for sure...
1697          m_iDirtyCount++;          m_iDirtyCount++;
# Line 1453  void MainForm::editRemoveChannel (void) Line 1702  void MainForm::editRemoveChannel (void)
1702  // Setup current sampler channel.  // Setup current sampler channel.
1703  void MainForm::editSetupChannel (void)  void MainForm::editSetupChannel (void)
1704  {  {
1705          if (m_pClient == NULL)          if (m_pClient == nullptr)
1706                  return;                  return;
1707    
1708          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1709          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
1710                  return;                  return;
1711    
1712          // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
# Line 1468  void MainForm::editSetupChannel (void) Line 1717  void MainForm::editSetupChannel (void)
1717  // Edit current sampler channel.  // Edit current sampler channel.
1718  void MainForm::editEditChannel (void)  void MainForm::editEditChannel (void)
1719  {  {
1720          if (m_pClient == NULL)          if (m_pClient == nullptr)
1721                  return;                  return;
1722    
1723          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1724          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
1725                  return;                  return;
1726    
1727          // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
# Line 1483  void MainForm::editEditChannel (void) Line 1732  void MainForm::editEditChannel (void)
1732  // Reset current sampler channel.  // Reset current sampler channel.
1733  void MainForm::editResetChannel (void)  void MainForm::editResetChannel (void)
1734  {  {
1735          if (m_pClient == NULL)          if (m_pClient == nullptr)
1736                  return;                  return;
1737    
1738          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1739          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
1740                  return;                  return;
1741    
1742          // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
# Line 1498  void MainForm::editResetChannel (void) Line 1747  void MainForm::editResetChannel (void)
1747  // Reset all sampler channels.  // Reset all sampler channels.
1748  void MainForm::editResetAllChannels (void)  void MainForm::editResetAllChannels (void)
1749  {  {
1750          if (m_pClient == NULL)          if (m_pClient == nullptr)
1751                  return;                  return;
1752    
1753          // Invoque the channel strip procedure,          // Invoque the channel strip procedure,
1754          // for all channels out there...          // for all channels out there...
1755          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
1756          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
1757          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  = m_pWorkspace->subWindowList();
1758                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
1759                    ChannelStrip *pChannelStrip
1760                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
1761                  if (pChannelStrip)                  if (pChannelStrip)
1762                          pChannelStrip->channelReset();                          pChannelStrip->channelReset();
1763          }          }
# Line 1515  void MainForm::editResetAllChannels (voi Line 1766  void MainForm::editResetAllChannels (voi
1766    
1767    
1768  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1769  // qsamplerMainForm -- View Action slots.  // QSampler::MainForm -- View Action slots.
1770    
1771  // Show/hide the main program window menubar.  // Show/hide the main program window menubar.
1772  void MainForm::viewMenubar ( bool bOn )  void MainForm::viewMenubar ( bool bOn )
# Line 1565  void MainForm::viewMessages ( bool bOn ) Line 1816  void MainForm::viewMessages ( bool bOn )
1816  // Show/hide the MIDI instrument list-view form.  // Show/hide the MIDI instrument list-view form.
1817  void MainForm::viewInstruments (void)  void MainForm::viewInstruments (void)
1818  {  {
1819          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
1820                  return;                  return;
1821    
1822          if (m_pInstrumentListForm) {          if (m_pInstrumentListForm) {
# Line 1584  void MainForm::viewInstruments (void) Line 1835  void MainForm::viewInstruments (void)
1835  // Show/hide the device configurator form.  // Show/hide the device configurator form.
1836  void MainForm::viewDevices (void)  void MainForm::viewDevices (void)
1837  {  {
1838          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
1839                  return;                  return;
1840    
1841          if (m_pDeviceForm) {          if (m_pDeviceForm) {
# Line 1603  void MainForm::viewDevices (void) Line 1854  void MainForm::viewDevices (void)
1854  // Show options dialog.  // Show options dialog.
1855  void MainForm::viewOptions (void)  void MainForm::viewOptions (void)
1856  {  {
1857          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
1858                  return;                  return;
1859    
1860          OptionsForm* pOptionsForm = new OptionsForm(this);          OptionsForm* pOptionsForm = new OptionsForm(this);
1861          if (pOptionsForm) {          if (pOptionsForm) {
1862                  // Check out some initial nullities(tm)...                  // Check out some initial nullities(tm)...
1863                  ChannelStrip* pChannelStrip = activeChannelStrip();                  ChannelStrip *pChannelStrip = activeChannelStrip();
1864                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)
1865                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();
1866                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)
1867                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
1868                  // To track down deferred or immediate changes.                  // To track down deferred or immediate changes.
1869                  QString sOldServerHost      = m_pOptions->sServerHost;                  const QString sOldServerHost      = m_pOptions->sServerHost;
1870                  int     iOldServerPort      = m_pOptions->iServerPort;                  const int     iOldServerPort      = m_pOptions->iServerPort;
1871                  int     iOldServerTimeout   = m_pOptions->iServerTimeout;                  const int     iOldServerTimeout   = m_pOptions->iServerTimeout;
1872                  bool    bOldServerStart     = m_pOptions->bServerStart;                  const bool    bOldServerStart     = m_pOptions->bServerStart;
1873                  QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;                  const QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;
1874                  bool    bOldMessagesLog     = m_pOptions->bMessagesLog;                  const bool    bOldMessagesLog     = m_pOptions->bMessagesLog;
1875                  QString sOldMessagesLogPath = m_pOptions->sMessagesLogPath;                  const QString sOldMessagesLogPath = m_pOptions->sMessagesLogPath;
1876                  QString sOldDisplayFont     = m_pOptions->sDisplayFont;                  const QString sOldDisplayFont     = m_pOptions->sDisplayFont;
1877                  bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;                  const bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;
1878                  int     iOldMaxVolume       = m_pOptions->iMaxVolume;                  const int     iOldMaxVolume       = m_pOptions->iMaxVolume;
1879                  QString sOldMessagesFont    = m_pOptions->sMessagesFont;                  const QString sOldMessagesFont    = m_pOptions->sMessagesFont;
1880                  bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;                  const bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;
1881                  bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;                  const bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;
1882                  int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;                  const int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;
1883                  int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;                  const int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;
1884                  bool    bOldCompletePath    = m_pOptions->bCompletePath;                  const bool    bOldCompletePath    = m_pOptions->bCompletePath;
1885                  bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;                  const bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;
1886                  int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;                  const int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;
1887                  int     iOldBaseFontSize    = m_pOptions->iBaseFontSize;                  const int     iOldBaseFontSize    = m_pOptions->iBaseFontSize;
1888                  // Load the current setup settings.                  // Load the current setup settings.
1889                  pOptionsForm->setup(m_pOptions);                  pOptionsForm->setup(m_pOptions);
1890                  // Show the setup dialog...                  // Show the setup dialog...
# Line 1645  void MainForm::viewOptions (void) Line 1896  void MainForm::viewOptions (void)
1896                                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)     ||                                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)     ||
1897                                  (iOldBaseFontSize   !=  m_pOptions->iBaseFontSize)) {                                  (iOldBaseFontSize   !=  m_pOptions->iBaseFontSize)) {
1898                                  QMessageBox::information(this,                                  QMessageBox::information(this,
1899                                          QSAMPLER_TITLE ": " + tr("Information"),                                          tr("Information"),
1900                                          tr("Some settings may be only effective\n"                                          tr("Some settings may be only effective\n"
1901                                          "next time you start this program."), tr("OK"));                                          "next time you start this program."));
1902                                  updateMessagesCapture();                                  updateMessagesCapture();
1903                          }                          }
1904                          // Check wheather something immediate has changed.                          // Check wheather something immediate has changed.
# Line 1696  void MainForm::viewOptions (void) Line 1947  void MainForm::viewOptions (void)
1947    
1948    
1949  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1950  // qsamplerMainForm -- Channels action slots.  // QSampler::MainForm -- Channels action slots.
1951    
1952  // Arrange channel strips.  // Arrange channel strips.
1953  void MainForm::channelsArrange (void)  void MainForm::channelsArrange (void)
1954  {  {
1955          // Full width vertical tiling          // Full width vertical tiling
1956          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
1957                    = m_pWorkspace->subWindowList();
1958          if (wlist.isEmpty())          if (wlist.isEmpty())
1959                  return;                  return;
1960    
1961          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
1962          int y = 0;          int y = 0;
1963          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
1964                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  pMdiSubWindow->adjustSize();
1965          /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {                  const QRect& frameRect
1966                          // Prevent flicker...                          = pMdiSubWindow->frameGeometry();
1967                          pChannelStrip->hide();                  int w = m_pWorkspace->width();
1968                          pChannelStrip->showNormal();                  if (w < frameRect.width())
1969                  }   */                          w = frameRect.width();
1970                  pChannelStrip->adjustSize();                  const int h = frameRect.height();
1971                  int iWidth  = m_pWorkspace->width();                  pMdiSubWindow->setGeometry(0, y, w, h);
1972                  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;  
1973          }          }
1974          m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
1975    
# Line 1734  void MainForm::channelsArrange (void) Line 1980  void MainForm::channelsArrange (void)
1980  // Auto-arrange channel strips.  // Auto-arrange channel strips.
1981  void MainForm::channelsAutoArrange ( bool bOn )  void MainForm::channelsAutoArrange ( bool bOn )
1982  {  {
1983          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
1984                  return;                  return;
1985    
1986          // Toggle the auto-arrange flag.          // Toggle the auto-arrange flag.
1987          m_pOptions->bAutoArrange = bOn;          m_pOptions->bAutoArrange = bOn;
1988    
1989          // If on, update whole workspace...          // If on, update whole workspace...
1990          if (m_pOptions->bAutoArrange)          channelsArrangeAuto();
1991    }
1992    
1993    
1994    void MainForm::channelsArrangeAuto (void)
1995    {
1996            if (m_pOptions && m_pOptions->bAutoArrange)
1997                  channelsArrange();                  channelsArrange();
1998  }  }
1999    
2000    
2001  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2002  // qsamplerMainForm -- Help Action slots.  // QSampler::MainForm -- Help Action slots.
2003    
2004  // Show information about the Qt toolkit.  // Show information about the Qt toolkit.
2005  void MainForm::helpAboutQt (void)  void MainForm::helpAboutQt (void)
# Line 1759  void MainForm::helpAboutQt (void) Line 2011  void MainForm::helpAboutQt (void)
2011  // Show information about application program.  // Show information about application program.
2012  void MainForm::helpAbout (void)  void MainForm::helpAbout (void)
2013  {  {
2014          // 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";  
2015  #ifdef CONFIG_DEBUG  #ifdef CONFIG_DEBUG
2016          sText += "<small><font color=\"red\">";          list << tr("Debugging option enabled.");
         sText += tr("Debugging option enabled.");  
         sText += "</font></small><br />";  
2017  #endif  #endif
2018  #ifndef CONFIG_LIBGIG  #ifndef CONFIG_LIBGIG
2019          sText += "<small><font color=\"red\">";          list << tr("GIG (libgig) file support disabled.");
         sText += tr("GIG (libgig) file support disabled.");  
         sText += "</font></small><br />";  
2020  #endif  #endif
2021  #ifndef CONFIG_INSTRUMENT_NAME  #ifndef CONFIG_INSTRUMENT_NAME
2022          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 />";  
2023  #endif  #endif
2024  #ifndef CONFIG_MUTE_SOLO  #ifndef CONFIG_MUTE_SOLO
2025          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 />";  
2026  #endif  #endif
2027  #ifndef CONFIG_AUDIO_ROUTING  #ifndef CONFIG_AUDIO_ROUTING
2028          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 />";  
2029  #endif  #endif
2030  #ifndef CONFIG_FXSEND  #ifndef CONFIG_FXSEND
2031          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 />";  
2032  #endif  #endif
2033  #ifndef CONFIG_VOLUME  #ifndef CONFIG_VOLUME
2034          sText += "<small><font color=\"red\">";          list << tr("Global volume support disabled.");
         sText += tr("Global volume support disabled.");  
         sText += "</font></small><br />";  
2035  #endif  #endif
2036  #ifndef CONFIG_MIDI_INSTRUMENT  #ifndef CONFIG_MIDI_INSTRUMENT
2037          sText += "<small><font color=\"red\">";          list << tr("MIDI instrument mapping support disabled.");
         sText += tr("MIDI instrument mapping support disabled.");  
         sText += "</font></small><br />";  
2038  #endif  #endif
2039  #ifndef CONFIG_EDIT_INSTRUMENT  #ifndef CONFIG_EDIT_INSTRUMENT
2040          sText += "<small><font color=\"red\">";          list << tr("Instrument editing support disabled.");
         sText += tr("Instrument editing support disabled.");  
         sText += "</font></small><br />";  
2041  #endif  #endif
2042  #ifndef CONFIG_EVENT_CHANNEL_MIDI  #ifndef CONFIG_EVENT_CHANNEL_MIDI
2043          sText += "<small><font color=\"red\">";          list << tr("Channel MIDI event support disabled.");
         sText += tr("Channel MIDI event support disabled.");  
         sText += "</font></small><br />";  
2044  #endif  #endif
2045  #ifndef CONFIG_EVENT_DEVICE_MIDI  #ifndef CONFIG_EVENT_DEVICE_MIDI
2046          sText += "<small><font color=\"red\">";          list << tr("Device MIDI event support disabled.");
         sText += tr("Device MIDI event support disabled.");  
         sText += "</font></small><br />";  
2047  #endif  #endif
2048  #ifndef CONFIG_MAX_VOICES  #ifndef CONFIG_MAX_VOICES
2049          sText += "<small><font color=\"red\">";          list << tr("Runtime max. voices / disk streams support disabled.");
         sText += tr("Runtime max. voices / disk streams support disabled.");  
         sText += "</font></small><br />";  
2050  #endif  #endif
2051    
2052            // Stuff the about box text...
2053            QString sText = "<p>\n";
2054            sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";
2055            sText += "<br />\n";
2056            sText += tr("Version") + ": <b>" CONFIG_BUILD_VERSION "</b><br />\n";
2057    //      sText += "<small>" + tr("Build") + ": " CONFIG_BUILD_DATE "</small><br />\n";
2058            if (!list.isEmpty()) {
2059                    sText += "<small><font color=\"red\">";
2060                    sText += list.join("<br />\n");
2061                    sText += "</font></small>";
2062            }
2063          sText += "<br />\n";          sText += "<br />\n";
2064          sText += tr("Using") + ": ";          sText += tr("Using") + ": ";
2065          sText += ::lscp_client_package();          sText += ::lscp_client_package();
# Line 1849  void MainForm::helpAbout (void) Line 2084  void MainForm::helpAbout (void)
2084          sText += "</small>";          sText += "</small>";
2085          sText += "</p>\n";          sText += "</p>\n";
2086    
2087          QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);          QMessageBox::about(this, tr("About"), sText);
2088  }  }
2089    
2090    
2091  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2092  // qsamplerMainForm -- Main window stabilization.  // QSampler::MainForm -- Main window stabilization.
2093    
2094  void MainForm::stabilizeForm (void)  void MainForm::stabilizeForm (void)
2095  {  {
# Line 1862  void MainForm::stabilizeForm (void) Line 2097  void MainForm::stabilizeForm (void)
2097          QString sSessionName = sessionName(m_sFilename);          QString sSessionName = sessionName(m_sFilename);
2098          if (m_iDirtyCount > 0)          if (m_iDirtyCount > 0)
2099                  sSessionName += " *";                  sSessionName += " *";
2100          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));          setWindowTitle(sSessionName);
2101    
2102          // Update the main menu state...          // Update the main menu state...
2103          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
2104          bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);          const QList<QMdiSubWindow *>& wlist = m_pWorkspace->subWindowList();
2105          bool bHasChannel = (bHasClient && pChannelStrip != NULL);          const bool bHasClient = (m_pOptions != nullptr && m_pClient != nullptr);
2106            const bool bHasChannel = (bHasClient && pChannelStrip != nullptr);
2107            const bool bHasChannels = (bHasClient && wlist.count() > 0);
2108          m_ui.fileNewAction->setEnabled(bHasClient);          m_ui.fileNewAction->setEnabled(bHasClient);
2109          m_ui.fileOpenAction->setEnabled(bHasClient);          m_ui.fileOpenAction->setEnabled(bHasClient);
2110          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
2111          m_ui.fileSaveAsAction->setEnabled(bHasClient);          m_ui.fileSaveAsAction->setEnabled(bHasClient);
2112          m_ui.fileResetAction->setEnabled(bHasClient);          m_ui.fileResetAction->setEnabled(bHasClient);
2113          m_ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);          m_ui.fileRestartAction->setEnabled(bHasClient || m_pServer == nullptr);
2114          m_ui.editAddChannelAction->setEnabled(bHasClient);          m_ui.editAddChannelAction->setEnabled(bHasClient);
2115          m_ui.editRemoveChannelAction->setEnabled(bHasChannel);          m_ui.editRemoveChannelAction->setEnabled(bHasChannel);
2116          m_ui.editSetupChannelAction->setEnabled(bHasChannel);          m_ui.editSetupChannelAction->setEnabled(bHasChannel);
# Line 1883  void MainForm::stabilizeForm (void) Line 2120  void MainForm::stabilizeForm (void)
2120          m_ui.editEditChannelAction->setEnabled(false);          m_ui.editEditChannelAction->setEnabled(false);
2121  #endif  #endif
2122          m_ui.editResetChannelAction->setEnabled(bHasChannel);          m_ui.editResetChannelAction->setEnabled(bHasChannel);
2123          m_ui.editResetAllChannelsAction->setEnabled(bHasChannel);          m_ui.editResetAllChannelsAction->setEnabled(bHasChannels);
2124          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());
2125  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
2126          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm
# Line 1895  void MainForm::stabilizeForm (void) Line 2132  void MainForm::stabilizeForm (void)
2132          m_ui.viewDevicesAction->setChecked(m_pDeviceForm          m_ui.viewDevicesAction->setChecked(m_pDeviceForm
2133                  && m_pDeviceForm->isVisible());                  && m_pDeviceForm->isVisible());
2134          m_ui.viewDevicesAction->setEnabled(bHasClient);          m_ui.viewDevicesAction->setEnabled(bHasClient);
2135          m_ui.channelsArrangeAction->setEnabled(bHasChannel);          m_ui.viewMidiDeviceStatusMenu->setEnabled(
2136                    DeviceStatusForm::getInstances().size() > 0);
2137            m_ui.channelsArrangeAction->setEnabled(bHasChannels);
2138    
2139  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2140          // Toolbar widgets are also affected...          // Toolbar widgets are also affected...
# Line 1945  void MainForm::volumeChanged ( int iVolu Line 2184  void MainForm::volumeChanged ( int iVolu
2184                  m_pVolumeSpinBox->setValue(iVolume);                  m_pVolumeSpinBox->setValue(iVolume);
2185    
2186          // Do it as commanded...          // Do it as commanded...
2187          float fVolume = 0.01f * float(iVolume);          const float fVolume = 0.01f * float(iVolume);
2188          if (::lscp_set_volume(m_pClient, fVolume) == LSCP_OK)          if (::lscp_set_volume(m_pClient, fVolume) == LSCP_OK)
2189                  appendMessages(QObject::tr("Volume: %1.").arg(fVolume));                  appendMessages(QObject::tr("Volume: %1.").arg(fVolume));
2190          else          else
# Line 1961  void MainForm::volumeChanged ( int iVolu Line 2200  void MainForm::volumeChanged ( int iVolu
2200    
2201    
2202  // Channel change receiver slot.  // Channel change receiver slot.
2203  void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)  void MainForm::channelStripChanged ( ChannelStrip *pChannelStrip )
2204  {  {
2205          // Add this strip to the changed list...          // Add this strip to the changed list...
2206          if (!m_changedStrips.contains(pChannelStrip)) {          if (!m_changedStrips.contains(pChannelStrip)) {
# Line 1980  void MainForm::channelStripChanged(Chann Line 2219  void MainForm::channelStripChanged(Chann
2219  void MainForm::updateSession (void)  void MainForm::updateSession (void)
2220  {  {
2221  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2222          int iVolume = ::lroundf(100.0f * ::lscp_get_volume(m_pClient));          const int iVolume = ::lroundf(100.0f * ::lscp_get_volume(m_pClient));
2223          m_iVolumeChanging++;          m_iVolumeChanging++;
2224          m_pVolumeSlider->setValue(iVolume);          m_pVolumeSlider->setValue(iVolume);
2225          m_pVolumeSpinBox->setValue(iVolume);          m_pVolumeSpinBox->setValue(iVolume);
# Line 1988  void MainForm::updateSession (void) Line 2227  void MainForm::updateSession (void)
2227  #endif  #endif
2228  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
2229          // FIXME: Make some room for default instrument maps...          // FIXME: Make some room for default instrument maps...
2230          int iMaps = ::lscp_get_midi_instrument_maps(m_pClient);          const int iMaps = ::lscp_get_midi_instrument_maps(m_pClient);
2231          if (iMaps < 0)          if (iMaps < 0)
2232                  appendMessagesClient("lscp_get_midi_instrument_maps");                  appendMessagesClient("lscp_get_midi_instrument_maps");
2233          else if (iMaps < 1) {          else if (iMaps < 1) {
# Line 2002  void MainForm::updateSession (void) Line 2241  void MainForm::updateSession (void)
2241          updateAllChannelStrips(false);          updateAllChannelStrips(false);
2242    
2243          // Do we auto-arrange?          // Do we auto-arrange?
2244          if (m_pOptions && m_pOptions->bAutoArrange)          channelsArrangeAuto();
                 channelsArrange();  
2245    
2246          // Remember to refresh devices and instruments...          // Remember to refresh devices and instruments...
2247          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
# Line 2012  void MainForm::updateSession (void) Line 2250  void MainForm::updateSession (void)
2250                  m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
2251  }  }
2252    
2253  void MainForm::updateAllChannelStrips(bool bRemoveDeadStrips) {  
2254    void MainForm::updateAllChannelStrips ( bool bRemoveDeadStrips )
2255    {
2256            // Skip if setting up a new channel strip...
2257            if (m_iDirtySetup > 0)
2258                    return;
2259    
2260          // Retrieve the current channel list.          // Retrieve the current channel list.
2261          int *piChannelIDs = ::lscp_list_channels(m_pClient);          int *piChannelIDs = ::lscp_list_channels(m_pClient);
2262          if (piChannelIDs == NULL) {          if (piChannelIDs == nullptr) {
2263                  if (::lscp_client_get_errno(m_pClient)) {                  if (::lscp_client_get_errno(m_pClient)) {
2264                          appendMessagesClient("lscp_list_channels");                          appendMessagesClient("lscp_list_channels");
2265                          appendMessagesError(                          appendMessagesError(
# Line 2024  void MainForm::updateAllChannelStrips(bo Line 2268  void MainForm::updateAllChannelStrips(bo
2268          } else {          } else {
2269                  // Try to (re)create each channel.                  // Try to (re)create each channel.
2270                  m_pWorkspace->setUpdatesEnabled(false);                  m_pWorkspace->setUpdatesEnabled(false);
2271                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; ++iChannel) {
2272                          // Check if theres already a channel strip for this one...                          // Check if theres already a channel strip for this one...
2273                          if (!channelStrip(piChannelIDs[iChannel]))                          if (!channelStrip(piChannelIDs[iChannel]))
2274                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));
2275                  }                  }
   
2276                  // Do we auto-arrange?                  // Do we auto-arrange?
2277                  if (m_pOptions && m_pOptions->bAutoArrange)                  channelsArrangeAuto();
                         channelsArrange();  
   
                 stabilizeForm();  
   
2278                  // remove dead channel strips                  // remove dead channel strips
2279                  if (bRemoveDeadStrips) {                  if (bRemoveDeadStrips) {
2280                          for (int i = 0; channelStripAt(i); ++i) {                          const QList<QMdiSubWindow *>& wlist
2281                                  ChannelStrip* pChannelStrip = channelStripAt(i);                                  = m_pWorkspace->subWindowList();
2282                                  bool bExists = false;                          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2283                                  for (int j = 0; piChannelIDs[j] >= 0; ++j) {                                  ChannelStrip *pChannelStrip
2284                                          if (!pChannelStrip->channel()) break;                                          = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2285                                          if (piChannelIDs[j] == pChannelStrip->channel()->channelID()) {                                  if (pChannelStrip) {
2286                                                  // strip exists, don't touch it                                          bool bExists = false;
2287                                                  bExists = true;                                          for (int iChannel = 0; piChannelIDs[iChannel] >= 0; ++iChannel) {
2288                                                  break;                                                  Channel *pChannel = pChannelStrip->channel();
2289                                                    if (pChannel == nullptr)
2290                                                            break;
2291                                                    if (piChannelIDs[iChannel] == pChannel->channelID()) {
2292                                                            // strip exists, don't touch it
2293                                                            bExists = true;
2294                                                            break;
2295                                                    }
2296                                          }                                          }
2297                                            if (!bExists)
2298                                                    destroyChannelStrip(pChannelStrip);
2299                                  }                                  }
                                 if (!bExists) destroyChannelStrip(pChannelStrip);  
2300                          }                          }
2301                  }                  }
2302                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
2303          }          }
2304    
2305            stabilizeForm();
2306  }  }
2307    
2308    
2309  // Update the recent files list and menu.  // Update the recent files list and menu.
2310  void MainForm::updateRecentFiles ( const QString& sFilename )  void MainForm::updateRecentFiles ( const QString& sFilename )
2311  {  {
2312          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2313                  return;                  return;
2314    
2315          // Remove from list if already there (avoid duplicates)          // Remove from list if already there (avoid duplicates)
2316          int iIndex = m_pOptions->recentFiles.indexOf(sFilename);          const int iIndex = m_pOptions->recentFiles.indexOf(sFilename);
2317          if (iIndex >= 0)          if (iIndex >= 0)
2318                  m_pOptions->recentFiles.removeAt(iIndex);                  m_pOptions->recentFiles.removeAt(iIndex);
2319          // Put it to front...          // Put it to front...
# Line 2074  void MainForm::updateRecentFiles ( const Line 2324  void MainForm::updateRecentFiles ( const
2324  // Update the recent files list and menu.  // Update the recent files list and menu.
2325  void MainForm::updateRecentFilesMenu (void)  void MainForm::updateRecentFilesMenu (void)
2326  {  {
2327          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2328                  return;                  return;
2329    
2330          // Time to keep the list under limits.          // Time to keep the list under limits.
# Line 2102  void MainForm::updateRecentFilesMenu (vo Line 2352  void MainForm::updateRecentFilesMenu (vo
2352  void MainForm::updateInstrumentNames (void)  void MainForm::updateInstrumentNames (void)
2353  {  {
2354          // Full channel list update...          // Full channel list update...
2355          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2356                    = m_pWorkspace->subWindowList();
2357          if (wlist.isEmpty())          if (wlist.isEmpty())
2358                  return;                  return;
2359    
2360          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2361          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2362                  ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);                  ChannelStrip *pChannelStrip
2363                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2364                  if (pChannelStrip)                  if (pChannelStrip)
2365                          pChannelStrip->updateInstrumentName(true);                          pChannelStrip->updateInstrumentName(true);
2366          }          }
# Line 2119  void MainForm::updateInstrumentNames (vo Line 2371  void MainForm::updateInstrumentNames (vo
2371  // Force update of the channels display font.  // Force update of the channels display font.
2372  void MainForm::updateDisplayFont (void)  void MainForm::updateDisplayFont (void)
2373  {  {
2374          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2375                  return;                  return;
2376    
2377          // Check if display font is legal.          // Check if display font is legal.
2378          if (m_pOptions->sDisplayFont.isEmpty())          if (m_pOptions->sDisplayFont.isEmpty())
2379                  return;                  return;
2380    
2381          // Realize it.          // Realize it.
2382          QFont font;          QFont font;
2383          if (!font.fromString(m_pOptions->sDisplayFont))          if (!font.fromString(m_pOptions->sDisplayFont))
2384                  return;                  return;
2385    
2386          // Full channel list update...          // Full channel list update...
2387          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2388                    = m_pWorkspace->subWindowList();
2389          if (wlist.isEmpty())          if (wlist.isEmpty())
2390                  return;                  return;
2391    
2392          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2393          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2394                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip *pChannelStrip
2395                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2396                  if (pChannelStrip)                  if (pChannelStrip)
2397                          pChannelStrip->setDisplayFont(font);                          pChannelStrip->setDisplayFont(font);
2398          }          }
# Line 2149  void MainForm::updateDisplayFont (void) Line 2404  void MainForm::updateDisplayFont (void)
2404  void MainForm::updateDisplayEffect (void)  void MainForm::updateDisplayEffect (void)
2405  {  {
2406          // Full channel list update...          // Full channel list update...
2407          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2408                    = m_pWorkspace->subWindowList();
2409          if (wlist.isEmpty())          if (wlist.isEmpty())
2410                  return;                  return;
2411    
2412          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2413          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2414                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip *pChannelStrip
2415                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2416                  if (pChannelStrip)                  if (pChannelStrip)
2417                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2418          }          }
# Line 2166  void MainForm::updateDisplayEffect (void Line 2423  void MainForm::updateDisplayEffect (void
2423  // Force update of the channels maximum volume setting.  // Force update of the channels maximum volume setting.
2424  void MainForm::updateMaxVolume (void)  void MainForm::updateMaxVolume (void)
2425  {  {
2426          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2427                  return;                  return;
2428    
2429  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
# Line 2177  void MainForm::updateMaxVolume (void) Line 2434  void MainForm::updateMaxVolume (void)
2434  #endif  #endif
2435    
2436          // Full channel list update...          // Full channel list update...
2437          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2438                    = m_pWorkspace->subWindowList();
2439          if (wlist.isEmpty())          if (wlist.isEmpty())
2440                  return;                  return;
2441    
2442          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2443          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2444                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip *pChannelStrip
2445                            = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2446                  if (pChannelStrip)                  if (pChannelStrip)
2447                          pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                          pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2448          }          }
# Line 2192  void MainForm::updateMaxVolume (void) Line 2451  void MainForm::updateMaxVolume (void)
2451    
2452    
2453  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2454  // qsamplerMainForm -- Messages window form handlers.  // QSampler::MainForm -- Messages window form handlers.
2455    
2456  // Messages output methods.  // Messages output methods.
2457  void MainForm::appendMessages( const QString& s )  void MainForm::appendMessages( const QString& s )
# Line 2217  void MainForm::appendMessagesText( const Line 2476  void MainForm::appendMessagesText( const
2476                  m_pMessages->appendMessagesText(s);                  m_pMessages->appendMessagesText(s);
2477  }  }
2478    
2479  void MainForm::appendMessagesError( const QString& s )  void MainForm::appendMessagesError( const QString& sText )
2480  {  {
2481          if (m_pMessages)          if (m_pMessages)
2482                  m_pMessages->show();                  m_pMessages->show();
2483    
2484          appendMessagesColor(s.simplified(), "#ff0000");          appendMessagesColor(sText.simplified(), "#ff0000");
2485    
2486          // Make it look responsive...:)          // Make it look responsive...:)
2487          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2488    
2489          QMessageBox::critical(this,          if (m_pOptions && m_pOptions->bConfirmError) {
2490                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));                  const QString& sTitle = tr("Error");
2491            #if 0
2492                    QMessageBox::critical(this, sTitle, sText, QMessageBox::Cancel);
2493            #else
2494                    QMessageBox mbox(this);
2495                    mbox.setIcon(QMessageBox::Critical);
2496                    mbox.setWindowTitle(sTitle);
2497                    mbox.setText(sText);
2498                    mbox.setStandardButtons(QMessageBox::Cancel);
2499                    QCheckBox cbox(tr("Don't show this again"));
2500                    cbox.setChecked(false);
2501                    cbox.blockSignals(true);
2502                    mbox.addButton(&cbox, QMessageBox::ActionRole);
2503                    if (mbox.exec() && cbox.isChecked())
2504                            m_pOptions->bConfirmError = false;
2505            #endif
2506            }
2507  }  }
2508    
2509    
2510  // This is a special message format, just for client results.  // This is a special message format, just for client results.
2511  void MainForm::appendMessagesClient( const QString& s )  void MainForm::appendMessagesClient( const QString& s )
2512  {  {
2513          if (m_pClient == NULL)          if (m_pClient == nullptr)
2514                  return;                  return;
2515    
2516          appendMessagesColor(s + QString(": %1 (errno=%2)")          appendMessagesColor(s + QString(": %1 (errno=%2)")
# Line 2250  void MainForm::appendMessagesClient( con Line 2525  void MainForm::appendMessagesClient( con
2525  // Force update of the messages font.  // Force update of the messages font.
2526  void MainForm::updateMessagesFont (void)  void MainForm::updateMessagesFont (void)
2527  {  {
2528          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2529                  return;                  return;
2530    
2531          if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {          if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {
# Line 2264  void MainForm::updateMessagesFont (void) Line 2539  void MainForm::updateMessagesFont (void)
2539  // Update messages window line limit.  // Update messages window line limit.
2540  void MainForm::updateMessagesLimit (void)  void MainForm::updateMessagesLimit (void)
2541  {  {
2542          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2543                  return;                  return;
2544    
2545          if (m_pMessages) {          if (m_pMessages) {
# Line 2279  void MainForm::updateMessagesLimit (void Line 2554  void MainForm::updateMessagesLimit (void
2554  // Enablement of the messages capture feature.  // Enablement of the messages capture feature.
2555  void MainForm::updateMessagesCapture (void)  void MainForm::updateMessagesCapture (void)
2556  {  {
2557          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2558                  return;                  return;
2559    
2560          if (m_pMessages)          if (m_pMessages)
# Line 2288  void MainForm::updateMessagesCapture (vo Line 2563  void MainForm::updateMessagesCapture (vo
2563    
2564    
2565  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2566  // qsamplerMainForm -- MDI channel strip management.  // QSampler::MainForm -- MDI channel strip management.
2567    
2568  // The channel strip creation executive.  // The channel strip creation executive.
2569  ChannelStrip* MainForm::createChannelStrip ( Channel *pChannel )  ChannelStrip *MainForm::createChannelStrip ( Channel *pChannel )
2570  {  {
2571          if (m_pClient == NULL || pChannel == NULL)          if (m_pClient == nullptr || pChannel == nullptr)
2572                  return NULL;                  return nullptr;
2573    
2574          // Add a new channel itema...          // Add a new channel itema...
2575          ChannelStrip *pChannelStrip = new ChannelStrip();          ChannelStrip *pChannelStrip = new ChannelStrip();
2576          if (pChannelStrip == NULL)          if (pChannelStrip == nullptr)
2577                  return NULL;                  return nullptr;
2578    
2579          // Set some initial channel strip options...          // Set some initial channel strip options...
2580          if (m_pOptions) {          if (m_pOptions) {
# Line 2307  ChannelStrip* MainForm::createChannelStr Line 2582  ChannelStrip* MainForm::createChannelStr
2582                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2583                  // We'll need a display font.                  // We'll need a display font.
2584                  QFont font;                  QFont font;
2585                  if (font.fromString(m_pOptions->sDisplayFont))                  if (!m_pOptions->sDisplayFont.isEmpty() &&
2586                            font.fromString(m_pOptions->sDisplayFont))
2587                          pChannelStrip->setDisplayFont(font);                          pChannelStrip->setDisplayFont(font);
2588                  // Maximum allowed volume setting.                  // Maximum allowed volume setting.
2589                  pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                  pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2590          }          }
2591    
2592          // Add it to workspace...          // Add it to workspace...
2593          m_pWorkspace->addWindow(pChannelStrip, Qt::FramelessWindowHint);          QMdiSubWindow *pMdiSubWindow
2594                    = m_pWorkspace->addSubWindow(pChannelStrip,
2595                            Qt::SubWindow | Qt::FramelessWindowHint);
2596            pMdiSubWindow->setAttribute(Qt::WA_DeleteOnClose);
2597    
2598          // Actual channel strip setup...          // Actual channel strip setup...
2599          pChannelStrip->setup(pChannel);          pChannelStrip->setup(pChannel);
2600    
2601          QObject::connect(pChannelStrip,          QObject::connect(pChannelStrip,
2602                  SIGNAL(channelChanged(ChannelStrip*)),                  SIGNAL(channelChanged(ChannelStrip *)),
2603                  SLOT(channelStripChanged(ChannelStrip*)));                  SLOT(channelStripChanged(ChannelStrip *)));
2604    
2605          // Now we show up us to the world.          // Now we show up us to the world.
2606          pChannelStrip->show();          pChannelStrip->show();
# Line 2333  ChannelStrip* MainForm::createChannelStr Line 2612  ChannelStrip* MainForm::createChannelStr
2612          return pChannelStrip;          return pChannelStrip;
2613  }  }
2614    
2615  void MainForm::destroyChannelStrip(ChannelStrip* pChannelStrip) {  
2616    void MainForm::destroyChannelStrip ( ChannelStrip *pChannelStrip )
2617    {
2618            QMdiSubWindow *pMdiSubWindow
2619                    = static_cast<QMdiSubWindow *> (pChannelStrip->parentWidget());
2620            if (pMdiSubWindow == nullptr)
2621                    return;
2622    
2623          // Just delete the channel strip.          // Just delete the channel strip.
2624          delete pChannelStrip;          delete pChannelStrip;
2625            delete pMdiSubWindow;
2626    
2627          // Do we auto-arrange?          // Do we auto-arrange?
2628          if (m_pOptions && m_pOptions->bAutoArrange)          channelsArrangeAuto();
                 channelsArrange();  
   
         stabilizeForm();  
2629  }  }
2630    
2631    
2632  // Retrieve the active channel strip.  // Retrieve the active channel strip.
2633  ChannelStrip* MainForm::activeChannelStrip (void)  ChannelStrip *MainForm::activeChannelStrip (void)
2634  {  {
2635          return static_cast<ChannelStrip *> (m_pWorkspace->activeWindow());          QMdiSubWindow *pMdiSubWindow = m_pWorkspace->activeSubWindow();
2636            if (pMdiSubWindow)
2637                    return static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2638            else
2639                    return nullptr;
2640  }  }
2641    
2642    
2643  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
2644  ChannelStrip* MainForm::channelStripAt ( int iChannel )  ChannelStrip *MainForm::channelStripAt ( int iStrip )
2645  {  {
2646          if (!m_pWorkspace) return NULL;          if (!m_pWorkspace) return nullptr;
2647    
2648          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2649                    = m_pWorkspace->subWindowList();
2650          if (wlist.isEmpty())          if (wlist.isEmpty())
2651                  return NULL;                  return nullptr;
2652    
2653          if (iChannel < 0 || iChannel >= wlist.size())          if (iStrip < 0 || iStrip >= wlist.count())
2654                  return NULL;                  return nullptr;
2655    
2656          return dynamic_cast<ChannelStrip *> (wlist.at(iChannel));          QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2657            if (pMdiSubWindow)
2658                    return static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2659            else
2660                    return nullptr;
2661  }  }
2662    
2663    
2664  // Retrieve a channel strip by sampler channel id.  // Retrieve a channel strip by sampler channel id.
2665  ChannelStrip* MainForm::channelStrip ( int iChannelID )  ChannelStrip *MainForm::channelStrip ( int iChannelID )
2666  {  {
2667          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2668                    = m_pWorkspace->subWindowList();
2669          if (wlist.isEmpty())          if (wlist.isEmpty())
2670                  return NULL;                  return nullptr;
2671    
2672          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2673                  ChannelStrip* pChannelStrip                  ChannelStrip *pChannelStrip
2674                          = static_cast<ChannelStrip*> (wlist.at(iChannel));                          = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2675                  if (pChannelStrip) {                  if (pChannelStrip) {
2676                          Channel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
2677                          if (pChannel && pChannel->channelID() == iChannelID)                          if (pChannel && pChannel->channelID() == iChannelID)
# Line 2385  ChannelStrip* MainForm::channelStrip ( i Line 2680  ChannelStrip* MainForm::channelStrip ( i
2680          }          }
2681    
2682          // Not found.          // Not found.
2683          return NULL;          return nullptr;
2684  }  }
2685    
2686    
# Line 2396  void MainForm::channelsMenuAboutToShow ( Line 2691  void MainForm::channelsMenuAboutToShow (
2691          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);
2692          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);
2693    
2694          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2695                    = m_pWorkspace->subWindowList();
2696          if (!wlist.isEmpty()) {          if (!wlist.isEmpty()) {
2697                  m_ui.channelsMenu->addSeparator();                  m_ui.channelsMenu->addSeparator();
2698                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  int iStrip = 0;
2699                          ChannelStrip* pChannelStrip                  foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2700                                  = static_cast<ChannelStrip*> (wlist.at(iChannel));                          ChannelStrip *pChannelStrip
2701                                    = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2702                          if (pChannelStrip) {                          if (pChannelStrip) {
2703                                  QAction *pAction = m_ui.channelsMenu->addAction(                                  QAction *pAction = m_ui.channelsMenu->addAction(
2704                                          pChannelStrip->windowTitle(),                                          pChannelStrip->windowTitle(),
2705                                          this, SLOT(channelsMenuActivated()));                                          this, SLOT(channelsMenuActivated()));
2706                                  pAction->setCheckable(true);                                  pAction->setCheckable(true);
2707                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);
2708                                  pAction->setData(iChannel);                                  pAction->setData(iStrip);
2709                          }                          }
2710                            ++iStrip;
2711                  }                  }
2712          }          }
2713  }  }
# Line 2420  void MainForm::channelsMenuActivated (vo Line 2718  void MainForm::channelsMenuActivated (vo
2718  {  {
2719          // Retrive channel index from action data...          // Retrive channel index from action data...
2720          QAction *pAction = qobject_cast<QAction *> (sender());          QAction *pAction = qobject_cast<QAction *> (sender());
2721          if (pAction == NULL)          if (pAction == nullptr)
2722                  return;                  return;
2723    
2724          ChannelStrip* pChannelStrip = channelStripAt(pAction->data().toInt());          ChannelStrip *pChannelStrip = channelStripAt(pAction->data().toInt());
2725          if (pChannelStrip) {          if (pChannelStrip) {
2726                  pChannelStrip->showNormal();                  pChannelStrip->showNormal();
2727                  pChannelStrip->setFocus();                  pChannelStrip->setFocus();
# Line 2432  void MainForm::channelsMenuActivated (vo Line 2730  void MainForm::channelsMenuActivated (vo
2730    
2731    
2732  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2733  // qsamplerMainForm -- Timer stuff.  // QSampler::MainForm -- Timer stuff.
2734    
2735  // Set the pseudo-timer delay schedule.  // Set the pseudo-timer delay schedule.
2736  void MainForm::startSchedule ( int iStartDelay )  void MainForm::startSchedule ( int iStartDelay )
# Line 2451  void MainForm::stopSchedule (void) Line 2749  void MainForm::stopSchedule (void)
2749  // Timer slot funtion.  // Timer slot funtion.
2750  void MainForm::timerSlot (void)  void MainForm::timerSlot (void)
2751  {  {
2752          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2753                  return;                  return;
2754    
2755          // 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 2473  void MainForm::timerSlot (void) Line 2771  void MainForm::timerSlot (void)
2771                          ChannelStrip *pChannelStrip = iter.next();                          ChannelStrip *pChannelStrip = iter.next();
2772                          // If successfull, remove from pending list...                          // If successfull, remove from pending list...
2773                          if (pChannelStrip->updateChannelInfo()) {                          if (pChannelStrip->updateChannelInfo()) {
2774                                  int iChannelStrip = m_changedStrips.indexOf(pChannelStrip);                                  const int iChannelStrip = m_changedStrips.indexOf(pChannelStrip);
2775                                  if (iChannelStrip >= 0)                                  if (iChannelStrip >= 0)
2776                                          m_changedStrips.removeAt(iChannelStrip);                                          m_changedStrips.removeAt(iChannelStrip);
2777                          }                          }
# Line 2484  void MainForm::timerSlot (void) Line 2782  void MainForm::timerSlot (void)
2782                          if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime)  {                          if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime)  {
2783                                  m_iTimerSlot = 0;                                  m_iTimerSlot = 0;
2784                                  // Update the channel stream usage for each strip...                                  // Update the channel stream usage for each strip...
2785                                  QWidgetList wlist = m_pWorkspace->windowList();                                  const QList<QMdiSubWindow *>& wlist
2786                                  for (int iChannel = 0;                                          = m_pWorkspace->subWindowList();
2787                                                  iChannel < (int) wlist.count(); iChannel++) {                                  foreach (QMdiSubWindow *pMdiSubWindow, wlist) {
2788                                          ChannelStrip* pChannelStrip                                          ChannelStrip *pChannelStrip
2789                                                  = (ChannelStrip*) wlist.at(iChannel);                                                  = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2790                                          if (pChannelStrip && pChannelStrip->isVisible())                                          if (pChannelStrip && pChannelStrip->isVisible())
2791                                                  pChannelStrip->updateChannelUsage();                                                  pChannelStrip->updateChannelUsage();
2792                                  }                                  }
# Line 2502  void MainForm::timerSlot (void) Line 2800  void MainForm::timerSlot (void)
2800    
2801    
2802  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2803  // qsamplerMainForm -- Server stuff.  // QSampler::MainForm -- Server stuff.
2804    
2805  // Start linuxsampler server...  // Start linuxsampler server...
2806  void MainForm::startServer (void)  void MainForm::startServer (void)
2807  {  {
2808          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2809                  return;                  return;
2810    
2811          // Aren't already a client, are we?          // Aren't already a client, are we?
# Line 2516  void MainForm::startServer (void) Line 2814  void MainForm::startServer (void)
2814    
2815          // Is the server process instance still here?          // Is the server process instance still here?
2816          if (m_pServer) {          if (m_pServer) {
2817                  switch (QMessageBox::warning(this,                  if (QMessageBox::warning(this,
2818                          QSAMPLER_TITLE ": " + tr("Warning"),                          tr("Warning"),
2819                          tr("Could not start the LinuxSampler server.\n\n"                          tr("Could not start the LinuxSampler server.\n\n"
2820                          "Maybe it is already started."),                          "Maybe it is already started."),
2821                          tr("Stop"), tr("Kill"), tr("Cancel"))) {                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
                 case 0:  
2822                          m_pServer->terminate();                          m_pServer->terminate();
                         break;  
                 case 1:  
2823                          m_pServer->kill();                          m_pServer->kill();
                         break;  
2824                  }                  }
2825                  return;                  return;
2826          }          }
# Line 2540  void MainForm::startServer (void) Line 2834  void MainForm::startServer (void)
2834    
2835          // OK. Let's build the startup process...          // OK. Let's build the startup process...
2836          m_pServer = new QProcess();          m_pServer = new QProcess();
2837          bForceServerStop = true;          m_bForceServerStop = true;
2838    
2839          // Setup stdout/stderr capture...          // Setup stdout/stderr capture...
2840  //      if (m_pOptions->bStdoutCapture) {          m_pServer->setProcessChannelMode(QProcess::ForwardedChannels);
2841  #if QT_VERSION >= 0x040200          QObject::connect(m_pServer,
2842                  m_pServer->setProcessChannelMode(QProcess::ForwardedChannels);                  SIGNAL(readyReadStandardOutput()),
2843  #endif                  SLOT(readServerStdout()));
2844                  QObject::connect(m_pServer,          QObject::connect(m_pServer,
2845                          SIGNAL(readyReadStandardOutput()),                  SIGNAL(readyReadStandardError()),
2846                          SLOT(readServerStdout()));                  SLOT(readServerStdout()));
                 QObject::connect(m_pServer,  
                         SIGNAL(readyReadStandardError()),  
                         SLOT(readServerStdout()));  
 //      }  
2847    
2848          // The unforgiveable signal communication...          // The unforgiveable signal communication...
2849          QObject::connect(m_pServer,          QObject::connect(m_pServer,
# Line 2588  void MainForm::startServer (void) Line 2878  void MainForm::startServer (void)
2878    
2879    
2880  // Stop linuxsampler server...  // Stop linuxsampler server...
2881  void MainForm::stopServer (bool bInteractive)  void MainForm::stopServer ( bool bInteractive )
2882  {  {
2883          // Stop client code.          // Stop client code.
2884          stopClient();          stopClient();
2885    
2886          if (m_pServer && bInteractive) {          if (m_pServer && bInteractive) {
2887                  if (QMessageBox::question(this,                  if (QMessageBox::question(this,
2888                          QSAMPLER_TITLE ": " + tr("The backend's fate ..."),                          tr("The backend's fate ..."),
2889                          tr("You have the option to keep the sampler backend (LinuxSampler)\n"                          tr("You have the option to keep the sampler backend (LinuxSampler)\n"
2890                          "running in the background. The sampler would continue to work\n"                          "running in the background. The sampler would continue to work\n"
2891                          "according to your current sampler session and you could alter the\n"                          "according to your current sampler session and you could alter the\n"
2892                          "sampler session at any time by relaunching QSampler.\n\n"                          "sampler session at any time by relaunching QSampler.\n\n"
2893                          "Do you want LinuxSampler to stop or to keep running in\n"                          "Do you want LinuxSampler to stop?"),
2894                          "the background?"),                          QMessageBox::Yes | QMessageBox::No,
2895                          tr("Stop"), tr("Keep Running")) == 1)                          QMessageBox::Yes) == QMessageBox::No) {
2896                  {                          m_bForceServerStop = false;
                         bForceServerStop = false;  
2897                  }                  }
2898          }          }
2899    
2900            bool bGraceWait = true;
2901    
2902          // And try to stop server.          // And try to stop server.
2903          if (m_pServer && bForceServerStop) {          if (m_pServer && m_bForceServerStop) {
2904                  appendMessages(tr("Server is stopping..."));                  appendMessages(tr("Server is stopping..."));
2905                  if (m_pServer->state() == QProcess::Running) {                  if (m_pServer->state() == QProcess::Running) {
2906  #if defined(WIN32)                  #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
2907                          // Try harder...                          // Try harder...
2908                          m_pServer->kill();                          m_pServer->kill();
2909  #else                  #else
2910                          // Try softly...                          // Try softly...
2911                          m_pServer->terminate();                          m_pServer->terminate();
2912  #endif                          bool bFinished = m_pServer->waitForFinished(QSAMPLER_TIMER_MSECS * 1000);
2913                            if (bFinished) bGraceWait = false;
2914                    #endif
2915                  }                  }
2916          }       // Do final processing anyway.          }       // Do final processing anyway.
2917          else processServerExit();          else processServerExit();
2918    
2919          // Give it some time to terminate gracefully and stabilize...          // Give it some time to terminate gracefully and stabilize...
2920          QTime t;          if (bGraceWait) {
2921          t.start();                  QTime t;
2922          while (t.elapsed() < QSAMPLER_TIMER_MSECS)                  t.start();
2923                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2924                            QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2925            }
2926  }  }
2927    
2928    
# Line 2649  void MainForm::processServerExit (void) Line 2944  void MainForm::processServerExit (void)
2944          if (m_pMessages)          if (m_pMessages)
2945                  m_pMessages->flushStdoutBuffer();                  m_pMessages->flushStdoutBuffer();
2946    
2947          if (m_pServer && bForceServerStop) {          if (m_pServer && m_bForceServerStop) {
2948                  if (m_pServer->state() != QProcess::NotRunning) {                  if (m_pServer->state() != QProcess::NotRunning) {
2949                          appendMessages(tr("Server is being forced..."));                          appendMessages(tr("Server is being forced..."));
2950                          // Force final server shutdown...                          // Force final server shutdown...
# Line 2665  void MainForm::processServerExit (void) Line 2960  void MainForm::processServerExit (void)
2960                          tr("Server was stopped with exit status %1.")                          tr("Server was stopped with exit status %1.")
2961                          .arg(m_pServer->exitStatus()));                          .arg(m_pServer->exitStatus()));
2962                  delete m_pServer;                  delete m_pServer;
2963                  m_pServer = NULL;                  m_pServer = nullptr;
2964          }          }
2965    
2966          // Again, make status visible stable.          // Again, make status visible stable.
# Line 2674  void MainForm::processServerExit (void) Line 2969  void MainForm::processServerExit (void)
2969    
2970    
2971  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2972  // qsamplerMainForm -- Client stuff.  // QSampler::MainForm -- Client stuff.
2973    
2974  // The LSCP client callback procedure.  // The LSCP client callback procedure.
2975  lscp_status_t qsampler_client_callback ( lscp_client_t */*pClient*/,  lscp_status_t qsampler_client_callback ( lscp_client_t */*pClient*/,
2976          lscp_event_t event, const char *pchData, int cchData, void *pvData )          lscp_event_t event, const char *pchData, int cchData, void *pvData )
2977  {  {
2978          MainForm* pMainForm = (MainForm *) pvData;          MainForm* pMainForm = (MainForm *) pvData;
2979          if (pMainForm == NULL)          if (pMainForm == nullptr)
2980                  return LSCP_FAILED;                  return LSCP_FAILED;
2981    
2982          // ATTN: DO NOT EVER call any GUI code here,          // ATTN: DO NOT EVER call any GUI code here,
2983          // as this is run under some other thread context.          // as this is run under some other thread context.
2984          // A custom event must be posted here...          // A custom event must be posted here...
2985          QApplication::postEvent(pMainForm,          QApplication::postEvent(pMainForm,
2986                  new CustomEvent(event, pchData, cchData));                  new LscpEvent(event, pchData, cchData));
2987    
2988          return LSCP_OK;          return LSCP_OK;
2989  }  }
# Line 2698  lscp_status_t qsampler_client_callback ( Line 2993  lscp_status_t qsampler_client_callback (
2993  bool MainForm::startClient (void)  bool MainForm::startClient (void)
2994  {  {
2995          // Have it a setup?          // Have it a setup?
2996          if (m_pOptions == NULL)          if (m_pOptions == nullptr)
2997                  return false;                  return false;
2998    
2999          // Aren't we already started, are we?          // Aren't we already started, are we?
# Line 2712  bool MainForm::startClient (void) Line 3007  bool MainForm::startClient (void)
3007          m_pClient = ::lscp_client_create(          m_pClient = ::lscp_client_create(
3008                  m_pOptions->sServerHost.toUtf8().constData(),                  m_pOptions->sServerHost.toUtf8().constData(),
3009                  m_pOptions->iServerPort, qsampler_client_callback, this);                  m_pOptions->iServerPort, qsampler_client_callback, this);
3010          if (m_pClient == NULL) {          if (m_pClient == nullptr) {
3011                  // Is this the first try?                  // Is this the first try?
3012                  // maybe we need to start a local server...                  // maybe we need to start a local server...
3013                  if ((m_pServer && m_pServer->state() == QProcess::Running)                  if ((m_pServer && m_pServer->state() == QProcess::Running)
# Line 2726  bool MainForm::startClient (void) Line 3021  bool MainForm::startClient (void)
3021                  stabilizeForm();                  stabilizeForm();
3022                  return false;                  return false;
3023          }          }
3024    
3025          // Just set receive timeout value, blindly.          // Just set receive timeout value, blindly.
3026          ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);          ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);
3027          appendMessages(          appendMessages(
# Line 2781  bool MainForm::startClient (void) Line 3077  bool MainForm::startClient (void)
3077          if (!m_pOptions->sSessionFile.isEmpty()) {          if (!m_pOptions->sSessionFile.isEmpty()) {
3078                  // Just load the prabably startup session...                  // Just load the prabably startup session...
3079                  if (loadSessionFile(m_pOptions->sSessionFile)) {                  if (loadSessionFile(m_pOptions->sSessionFile)) {
3080                          m_pOptions->sSessionFile = QString::null;                          m_pOptions->sSessionFile = QString();
3081                          return true;                          return true;
3082                  }                  }
3083          }          }
# Line 2797  bool MainForm::startClient (void) Line 3093  bool MainForm::startClient (void)
3093  // Stop client...  // Stop client...
3094  void MainForm::stopClient (void)  void MainForm::stopClient (void)
3095  {  {
3096          if (m_pClient == NULL)          if (m_pClient == nullptr)
3097                  return;                  return;
3098    
3099          // Log prepare here.          // Log prepare here.
# Line 2829  void MainForm::stopClient (void) Line 3125  void MainForm::stopClient (void)
3125          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
3126          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT);
3127          ::lscp_client_destroy(m_pClient);          ::lscp_client_destroy(m_pClient);
3128          m_pClient = NULL;          m_pClient = nullptr;
3129    
3130          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
3131          // if visible, that we're running out...          // if visible, that we're running out...
# Line 2847  void MainForm::stopClient (void) Line 3143  void MainForm::stopClient (void)
3143    
3144    
3145  // Channel strip activation/selection.  // Channel strip activation/selection.
3146  void MainForm::activateStrip ( QWidget *pWidget )  void MainForm::activateStrip ( QMdiSubWindow *pMdiSubWindow )
3147  {  {
3148          ChannelStrip *pChannelStrip          ChannelStrip *pChannelStrip = nullptr;
3149                  = static_cast<ChannelStrip *> (pWidget);          if (pMdiSubWindow)
3150                    pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
3151          if (pChannelStrip)          if (pChannelStrip)
3152                  pChannelStrip->setSelected(true);                  pChannelStrip->setSelected(true);
3153    
# Line 2858  void MainForm::activateStrip ( QWidget * Line 3155  void MainForm::activateStrip ( QWidget *
3155  }  }
3156    
3157    
3158    // Channel toolbar orientation change.
3159    void MainForm::channelsToolbarOrientation ( Qt::Orientation orientation )
3160    {
3161    #ifdef CONFIG_VOLUME
3162            m_pVolumeSlider->setOrientation(orientation);
3163            if (orientation == Qt::Horizontal) {
3164                    m_pVolumeSlider->setMinimumHeight(24);
3165                    m_pVolumeSlider->setMaximumHeight(32);
3166                    m_pVolumeSlider->setMinimumWidth(120);
3167                    m_pVolumeSlider->setMaximumWidth(640);
3168                    m_pVolumeSpinBox->setMaximumWidth(64);
3169                    m_pVolumeSpinBox->setButtonSymbols(QSpinBox::UpDownArrows);
3170            } else {
3171                    m_pVolumeSlider->setMinimumHeight(120);
3172                    m_pVolumeSlider->setMaximumHeight(480);
3173                    m_pVolumeSlider->setMinimumWidth(24);
3174                    m_pVolumeSlider->setMaximumWidth(32);
3175                    m_pVolumeSpinBox->setMaximumWidth(32);
3176                    m_pVolumeSpinBox->setButtonSymbols(QSpinBox::NoButtons);
3177            }
3178    #endif
3179    }
3180    
3181    
3182  } // namespace QSampler  } // namespace QSampler
3183    
3184    

Legend:
Removed from v.1815  
changed lines
  Added in v.3613

  ViewVC Help
Powered by ViewVC