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

Legend:
Removed from v.1559  
changed lines
  Added in v.3685

  ViewVC Help
Powered by ViewVC