/[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 1515 by capela, Fri Nov 23 18:15:33 2007 UTC revision 2441 by capela, Wed Apr 10 09:11:37 2013 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-2013, rncbc aka Rui Nuno Capela. All rights reserved.
5     Copyright (C) 2007, Christian Schoenebeck     Copyright (C) 2007, 2008 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    #if QT_VERSION >= 0x050000
62    #include <QMimeData>
63    #endif
64    
65    #if QT_VERSION < 0x040500
66    namespace Qt {
67    const WindowFlags WindowCloseButtonHint = WindowFlags(0x08000000);
68    #if QT_VERSION < 0x040200
69    const WindowFlags CustomizeWindowHint   = WindowFlags(0x02000000);
70    #endif
71    }
72    #endif
73    
74  #ifdef HAVE_SIGNAL_H  #ifdef HAVE_SIGNAL_H
75  #include <signal.h>  #include <signal.h>
# Line 77  static inline long lroundf ( float x ) Line 92  static inline long lroundf ( float x )
92  }  }
93  #endif  #endif
94    
95    
96    // All winsock apps needs this.
97    #if defined(WIN32)
98    static WSADATA _wsaData;
99    #endif
100    
101    
102    //-------------------------------------------------------------------------
103    // LADISH Level 1 support stuff.
104    
105    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
106    
107    #include <QSocketNotifier>
108    
109    #include <sys/types.h>
110    #include <sys/socket.h>
111    
112    #include <signal.h>
113    
114    // File descriptor for SIGUSR1 notifier.
115    static int g_fdUsr1[2];
116    
117    // Unix SIGUSR1 signal handler.
118    static void qsampler_sigusr1_handler ( int /* signo */ )
119    {
120            char c = 1;
121    
122            (::write(g_fdUsr1[0], &c, sizeof(c)) > 0);
123    }
124    
125    #endif  // HAVE_SIGNAL_H
126    
127    
128    //-------------------------------------------------------------------------
129    // qsampler -- namespace
130    
131    
132    namespace QSampler {
133    
134  // Timer constant stuff.  // Timer constant stuff.
135  #define QSAMPLER_TIMER_MSECS    200  #define QSAMPLER_TIMER_MSECS    200
136    
# Line 87  static inline long lroundf ( float x ) Line 141  static inline long lroundf ( float x )
141  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.
142    
143    
144  // All winsock apps needs this.  // Specialties for thread-callback comunication.
145  #if defined(WIN32)  #define QSAMPLER_LSCP_EVENT   QEvent::Type(QEvent::User + 1)
 static WSADATA _wsaData;  
 #endif  
146    
147    
148  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
149  // qsamplerCustomEvent -- specialty for callback comunication.  // LscpEvent -- specialty for LSCP callback comunication.
150    
 #define QSAMPLER_CUSTOM_EVENT   QEvent::Type(QEvent::User + 0)  
151    
152  class qsamplerCustomEvent : public QEvent  class LscpEvent : public QEvent
153  {  {
154  public:  public:
155    
156          // Constructor.          // Constructor.
157          qsamplerCustomEvent(lscp_event_t event, const char *pchData, int cchData)          LscpEvent(lscp_event_t event, const char *pchData, int cchData)
158                  : QEvent(QSAMPLER_CUSTOM_EVENT)                  : QEvent(QSAMPLER_LSCP_EVENT)
159          {          {
160                  m_event = event;                  m_event = event;
161                  m_data  = QString::fromUtf8(pchData, cchData);                  m_data  = QString::fromUtf8(pchData, cchData);
# Line 126  private: Line 177  private:
177  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
178  // qsamplerMainForm -- Main window form implementation.  // qsamplerMainForm -- Main window form implementation.
179    
 namespace QSampler {  
   
180  // Kind of singleton reference.  // Kind of singleton reference.
181  MainForm* MainForm::g_pMainForm = NULL;  MainForm* MainForm::g_pMainForm = NULL;
182    
# Line 159  MainForm::MainForm ( QWidget *pParent ) Line 208  MainForm::MainForm ( QWidget *pParent )
208    
209          m_iTimerSlot = 0;          m_iTimerSlot = 0;
210    
211  #ifdef HAVE_SIGNAL_H  #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
212    
213          // Set to ignore any fatal "Broken pipe" signals.          // Set to ignore any fatal "Broken pipe" signals.
214          ::signal(SIGPIPE, SIG_IGN);          ::signal(SIGPIPE, SIG_IGN);
215  #endif  
216            // LADISH Level 1 suport.
217    
218            // Initialize file descriptors for SIGUSR1 socket notifier.
219            ::socketpair(AF_UNIX, SOCK_STREAM, 0, g_fdUsr1);
220            m_pUsr1Notifier
221                    = new QSocketNotifier(g_fdUsr1[1], QSocketNotifier::Read, this);
222    
223            QObject::connect(m_pUsr1Notifier,
224                    SIGNAL(activated(int)),
225                    SLOT(handle_sigusr1()));
226    
227            // Install SIGUSR1 signal handler.
228        struct sigaction usr1;
229        usr1.sa_handler = qsampler_sigusr1_handler;
230        sigemptyset(&usr1.sa_mask);
231        usr1.sa_flags = 0;
232        usr1.sa_flags |= SA_RESTART;
233        ::sigaction(SIGUSR1, &usr1, NULL);
234    
235    #else   // HAVE_SIGNAL_H
236    
237            m_pUsr1Notifier = NULL;
238            
239    #endif  // !HAVE_SIGNAL_H
240    
241  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
242          // Make some extras into the toolbar...          // Make some extras into the toolbar...
# Line 201  MainForm::MainForm ( QWidget *pParent ) Line 275  MainForm::MainForm ( QWidget *pParent )
275  #endif  #endif
276    
277          // Make it an MDI workspace.          // Make it an MDI workspace.
278          m_pWorkspace = new QWorkspace(this);          m_pWorkspace = new QMdiArea(this);
279          m_pWorkspace->setScrollBarsEnabled(true);          m_pWorkspace->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
280            m_pWorkspace->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
281          // Set the activation connection.          // Set the activation connection.
282          QObject::connect(m_pWorkspace,          QObject::connect(m_pWorkspace,
283                  SIGNAL(windowActivated(QWidget *)),                  SIGNAL(subWindowActivated(QMdiSubWindow *)),
284                  SLOT(activateStrip(QWidget *)));                  SLOT(activateStrip(QMdiSubWindow *)));
285          // Make it shine :-)          // Make it shine :-)
286          setCentralWidget(m_pWorkspace);          setCentralWidget(m_pWorkspace);
287    
# Line 335  MainForm::~MainForm() Line 410  MainForm::~MainForm()
410          WSACleanup();          WSACleanup();
411  #endif  #endif
412    
413    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
414            if (m_pUsr1Notifier)
415                    delete m_pUsr1Notifier;
416    #endif
417    
418          // Finally drop any widgets around...          // Finally drop any widgets around...
419          if (m_pDeviceForm)          if (m_pDeviceForm)
420                  delete m_pDeviceForm;                  delete m_pDeviceForm;
# Line 366  MainForm::~MainForm() Line 446  MainForm::~MainForm()
446    
447    
448  // Make and set a proper setup options step.  // Make and set a proper setup options step.
449  void MainForm::setup ( qsamplerOptions *pOptions )  void MainForm::setup ( Options *pOptions )
450  {  {
451          // We got options?          // We got options?
452          m_pOptions = pOptions;          m_pOptions = pOptions;
453    
454          // What style do we create these forms?          // What style do we create these forms?
455          Qt::WindowFlags wflags = Qt::Window          Qt::WindowFlags wflags = Qt::Window
 #if QT_VERSION >= 0x040200  
456                  | Qt::CustomizeWindowHint                  | Qt::CustomizeWindowHint
 #endif  
457                  | Qt::WindowTitleHint                  | Qt::WindowTitleHint
458                  | Qt::WindowSystemMenuHint                  | Qt::WindowSystemMenuHint
459                  | Qt::WindowMinMaxButtonsHint;                  | Qt::WindowMinMaxButtonsHint
460                    | Qt::WindowCloseButtonHint;
461          if (m_pOptions->bKeepOnTop)          if (m_pOptions->bKeepOnTop)
462                  wflags |= Qt::Tool;                  wflags |= Qt::Tool;
463    
464          // Some child forms are to be created right now.          // Some child forms are to be created right now.
465          m_pMessages = new qsamplerMessages(this);          m_pMessages = new Messages(this);
466          m_pDeviceForm = new DeviceForm(this, wflags);          m_pDeviceForm = new DeviceForm(this, wflags);
467  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
468          m_pInstrumentListForm = new InstrumentListForm(this, wflags);          m_pInstrumentListForm = new InstrumentListForm(this, wflags);
469  #else  #else
470          viewInstrumentsAction->setEnabled(false);          m_ui.viewInstrumentsAction->setEnabled(false);
471  #endif  #endif
472    
473            // Setup messages logging appropriately...
474            m_pMessages->setLogging(
475                    m_pOptions->bMessagesLog,
476                    m_pOptions->sMessagesLogPath);
477    
478          // Set message defaults...          // Set message defaults...
479          updateMessagesFont();          updateMessagesFont();
480          updateMessagesLimit();          updateMessagesLimit();
# Line 419  void MainForm::setup ( qsamplerOptions * Line 505  void MainForm::setup ( qsamplerOptions *
505          }          }
506    
507          // Try to restore old window positioning and initial visibility.          // Try to restore old window positioning and initial visibility.
508          m_pOptions->loadWidgetGeometry(this);          m_pOptions->loadWidgetGeometry(this, true);
509          m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);          m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);
510          m_pOptions->loadWidgetGeometry(m_pDeviceForm);          m_pOptions->loadWidgetGeometry(m_pDeviceForm);
511    
# Line 463  bool MainForm::queryClose (void) Line 549  bool MainForm::queryClose (void)
549                          // And the children, and the main windows state,.                          // And the children, and the main windows state,.
550                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);
551                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);
552                          m_pOptions->saveWidgetGeometry(this);                          m_pOptions->saveWidgetGeometry(this, true);
553                          // Close popup widgets.                          // Close popup widgets.
554                          if (m_pInstrumentListForm)                          if (m_pInstrumentListForm)
555                                  m_pInstrumentListForm->close();                                  m_pInstrumentListForm->close();
556                          if (m_pDeviceForm)                          if (m_pDeviceForm)
557                                  m_pDeviceForm->close();                                  m_pDeviceForm->close();
558                          // Stop client and/or server, gracefully.                          // Stop client and/or server, gracefully.
559                          stopServer();                          stopServer(true /*interactive*/);
560                  }                  }
561          }          }
562    
# Line 480  bool MainForm::queryClose (void) Line 566  bool MainForm::queryClose (void)
566    
567  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )
568  {  {
569          if (queryClose())          if (queryClose()) {
570                    DeviceStatusForm::deleteAllInstances();
571                  pCloseEvent->accept();                  pCloseEvent->accept();
572          else          } else
573                  pCloseEvent->ignore();                  pCloseEvent->ignore();
574  }  }
575    
# Line 511  void MainForm::dropEvent ( QDropEvent* p Line 598  void MainForm::dropEvent ( QDropEvent* p
598                  QListIterator<QUrl> iter(pMimeData->urls());                  QListIterator<QUrl> iter(pMimeData->urls());
599                  while (iter.hasNext()) {                  while (iter.hasNext()) {
600                          const QString& sPath = iter.next().toLocalFile();                          const QString& sPath = iter.next().toLocalFile();
601                          if (qsamplerChannel::isInstrumentFile(sPath)) {                  //      if (Channel::isDlsInstrumentFile(sPath)) {
602                            if (QFileInfo(sPath).exists()) {
603                                  // Try to create a new channel from instrument file...                                  // Try to create a new channel from instrument file...
604                                  qsamplerChannel *pChannel = new qsamplerChannel();                                  Channel *pChannel = new Channel();
605                                  if (pChannel == NULL)                                  if (pChannel == NULL)
606                                          return;                                          return;
607                                  // Start setting the instrument filename...                                  // Start setting the instrument filename...
# Line 545  void MainForm::dropEvent ( QDropEvent* p Line 633  void MainForm::dropEvent ( QDropEvent* p
633    
634    
635  // Custome event handler.  // Custome event handler.
636  void MainForm::customEvent(QEvent* pCustomEvent)  void MainForm::customEvent ( QEvent* pEvent )
637  {  {
638          // For the time being, just pump it to messages.          // For the time being, just pump it to messages.
639          if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {          if (pEvent->type() == QSAMPLER_LSCP_EVENT) {
640                  qsamplerCustomEvent *pEvent = (qsamplerCustomEvent *) pCustomEvent;                  LscpEvent *pLscpEvent = static_cast<LscpEvent *> (pEvent);
641                  if (pEvent->event() == LSCP_EVENT_CHANNEL_INFO) {                  switch (pLscpEvent->event()) {
642                          int iChannelID = pEvent->data().toInt();                          case LSCP_EVENT_CHANNEL_COUNT:
643                          ChannelStrip *pChannelStrip = channelStrip(iChannelID);                                  updateAllChannelStrips(true);
644                          if (pChannelStrip)                                  break;
645                                  channelStripChanged(pChannelStrip);                          case LSCP_EVENT_CHANNEL_INFO: {
646                  } else {                                  int iChannelID = pLscpEvent->data().toInt();
647                          appendMessagesColor(tr("Notify event: %1 data: %2")                                  ChannelStrip *pChannelStrip = channelStrip(iChannelID);
648                                  .arg(::lscp_event_to_text(pEvent->event()))                                  if (pChannelStrip)
649                                  .arg(pEvent->data()), "#996699");                                          channelStripChanged(pChannelStrip);
650                                    break;
651                            }
652                            case LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT:
653                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
654                                    DeviceStatusForm::onDevicesChanged();
655                                    updateViewMidiDeviceStatusMenu();
656                                    break;
657                            case LSCP_EVENT_MIDI_INPUT_DEVICE_INFO: {
658                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
659                                    const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt();
660                                    DeviceStatusForm::onDeviceChanged(iDeviceID);
661                                    break;
662                            }
663                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT:
664                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
665                                    break;
666                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO:
667                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
668                                    break;
669                    #if CONFIG_EVENT_CHANNEL_MIDI
670                            case LSCP_EVENT_CHANNEL_MIDI: {
671                                    const int iChannelID = pLscpEvent->data().section(' ', 0, 0).toInt();
672                                    ChannelStrip *pChannelStrip = channelStrip(iChannelID);
673                                    if (pChannelStrip)
674                                            pChannelStrip->midiActivityLedOn();
675                                    break;
676                            }
677                    #endif
678                    #if CONFIG_EVENT_DEVICE_MIDI
679                            case LSCP_EVENT_DEVICE_MIDI: {
680                                    const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt();
681                                    const int iPortID   = pLscpEvent->data().section(' ', 1, 1).toInt();
682                                    DeviceStatusForm *pDeviceStatusForm
683                                            = DeviceStatusForm::getInstance(iDeviceID);
684                                    if (pDeviceStatusForm)
685                                            pDeviceStatusForm->midiArrived(iPortID);
686                                    break;
687                            }
688                    #endif
689                            default:
690                                    appendMessagesColor(tr("LSCP Event: %1 data: %2")
691                                            .arg(::lscp_event_to_text(pLscpEvent->event()))
692                                            .arg(pLscpEvent->data()), "#996699");
693                  }                  }
694          }          }
695  }  }
696    
697    
698    // LADISH Level 1 -- SIGUSR1 signal handler.
699    void MainForm::handle_sigusr1 (void)
700    {
701    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
702    
703            char c;
704    
705            if (::read(g_fdUsr1[1], &c, sizeof(c)) > 0)
706                    saveSession(false);
707    
708    #endif
709    }
710    
711    
712    void MainForm::updateViewMidiDeviceStatusMenu (void)
713    {
714            m_ui.viewMidiDeviceStatusMenu->clear();
715            const std::map<int, DeviceStatusForm *> statusForms
716                    = DeviceStatusForm::getInstances();
717            std::map<int, DeviceStatusForm *>::const_iterator iter
718                    = statusForms.begin();
719            for ( ; iter != statusForms.end(); ++iter) {
720                    DeviceStatusForm *pStatusForm = iter->second;
721                    m_ui.viewMidiDeviceStatusMenu->addAction(
722                            pStatusForm->visibleAction());
723            }
724    }
725    
726    
727  // Context menu event handler.  // Context menu event handler.
728  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )
729  {  {
# Line 576  void MainForm::contextMenuEvent( QContex Line 737  void MainForm::contextMenuEvent( QContex
737  // qsamplerMainForm -- Brainless public property accessors.  // qsamplerMainForm -- Brainless public property accessors.
738    
739  // The global options settings property.  // The global options settings property.
740  qsamplerOptions *MainForm::options (void) const  Options *MainForm::options (void) const
741  {  {
742          return m_pOptions;          return m_pOptions;
743  }  }
# Line 694  bool MainForm::saveSession ( bool bPromp Line 855  bool MainForm::saveSession ( bool bPromp
855                                  "\"%1\"\n\n"                                  "\"%1\"\n\n"
856                                  "Do you want to replace it?")                                  "Do you want to replace it?")
857                                  .arg(sFilename),                                  .arg(sFilename),
858                                  tr("Replace"), tr("Cancel")) > 0)                                  QMessageBox::Yes | QMessageBox::No)
859                                    == QMessageBox::No)
860                                  return false;                                  return false;
861                  }                  }
862          }          }
# Line 717  bool MainForm::closeSession ( bool bForc Line 879  bool MainForm::closeSession ( bool bForc
879                          "\"%1\"\n\n"                          "\"%1\"\n\n"
880                          "Do you want to save the changes?")                          "Do you want to save the changes?")
881                          .arg(sessionName(m_sFilename)),                          .arg(sessionName(m_sFilename)),
882                          tr("Save"), tr("Discard"), tr("Cancel"))) {                          QMessageBox::Save |
883                  case 0:     // Save...                          QMessageBox::Discard |
884                            QMessageBox::Cancel)) {
885                    case QMessageBox::Save:
886                          bClose = saveSession(false);                          bClose = saveSession(false);
887                          // Fall thru....                          // Fall thru....
888                  case 1:     // Discard                  case QMessageBox::Discard:
889                          break;                          break;
890                  default:    // Cancel.                  default:    // Cancel.
891                          bClose = false;                          bClose = false;
# Line 733  bool MainForm::closeSession ( bool bForc Line 897  bool MainForm::closeSession ( bool bForc
897          if (bClose) {          if (bClose) {
898                  // Remove all channel strips from sight...                  // Remove all channel strips from sight...
899                  m_pWorkspace->setUpdatesEnabled(false);                  m_pWorkspace->setUpdatesEnabled(false);
900                  QWidgetList wlist = m_pWorkspace->windowList();                  QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
901                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
902                          ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                          ChannelStrip *pChannelStrip = NULL;
903                            QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
904                            if (pMdiSubWindow)
905                                    pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
906                          if (pChannelStrip) {                          if (pChannelStrip) {
907                                  qsamplerChannel *pChannel = pChannelStrip->channel();                                  Channel *pChannel = pChannelStrip->channel();
908                                  if (bForce && pChannel)                                  if (bForce && pChannel)
909                                          pChannel->removeChannel();                                          pChannel->removeChannel();
910                                  delete pChannelStrip;                                  delete pChannelStrip;
911                          }                          }
912                            if (pMdiSubWindow)
913                                    delete pMdiSubWindow;
914                  }                  }
915                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
916                  // We're now clean, for sure.                  // We're now clean, for sure.
# Line 877  bool MainForm::saveSessionFile ( const Q Line 1046  bool MainForm::saveSessionFile ( const Q
1046    
1047          // Audio device mapping.          // Audio device mapping.
1048          QMap<int, int> audioDeviceMap;          QMap<int, int> audioDeviceMap;
1049          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Audio);          piDeviceIDs = Device::getDevices(m_pClient, Device::Audio);
1050          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
1051                  ts << endl;                  ts << endl;
1052                  qsamplerDevice device(qsamplerDevice::Audio, piDeviceIDs[iDevice]);                  Device device(Device::Audio, piDeviceIDs[iDevice]);
1053                  // Audio device specification...                  // Audio device specification...
1054                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1055                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1056                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();
1057                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
1058                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
1059                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
1060                                          ++deviceParam) {                                          ++deviceParam) {
1061                          const qsamplerDeviceParam& param = deviceParam.value();                          const DeviceParam& param = deviceParam.value();
1062                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
1063                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
1064                  }                  }
1065                  ts << endl;                  ts << endl;
1066                  // Audio channel parameters...                  // Audio channel parameters...
1067                  int iPort = 0;                  int iPort = 0;
1068                  QListIterator<qsamplerDevicePort *> iter(device.ports());                  QListIterator<DevicePort *> iter(device.ports());
1069                  while (iter.hasNext()) {                  while (iter.hasNext()) {
1070                          qsamplerDevicePort *pPort = iter.next();                          DevicePort *pPort = iter.next();
1071                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1072                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1073                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1074                                                  ++portParam) {                                                  ++portParam) {
1075                                  const qsamplerDeviceParam& param = portParam.value();                                  const DeviceParam& param = portParam.value();
1076                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1077                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice
1078                                          << " " << iPort << " " << portParam.key()                                          << " " << iPort << " " << portParam.key()
# Line 919  bool MainForm::saveSessionFile ( const Q Line 1088  bool MainForm::saveSessionFile ( const Q
1088    
1089          // MIDI device mapping.          // MIDI device mapping.
1090          QMap<int, int> midiDeviceMap;          QMap<int, int> midiDeviceMap;
1091          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Midi);          piDeviceIDs = Device::getDevices(m_pClient, Device::Midi);
1092          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
1093                  ts << endl;                  ts << endl;
1094                  qsamplerDevice device(qsamplerDevice::Midi, piDeviceIDs[iDevice]);                  Device device(Device::Midi, piDeviceIDs[iDevice]);
1095                  // MIDI device specification...                  // MIDI device specification...
1096                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1097                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1098                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();
1099                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
1100                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
1101                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
1102                                          ++deviceParam) {                                          ++deviceParam) {
1103                          const qsamplerDeviceParam& param = deviceParam.value();                          const DeviceParam& param = deviceParam.value();
1104                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
1105                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
1106                  }                  }
1107                  ts << endl;                  ts << endl;
1108                  // MIDI port parameters...                  // MIDI port parameters...
1109                  int iPort = 0;                  int iPort = 0;
1110                  QListIterator<qsamplerDevicePort *> iter(device.ports());                  QListIterator<DevicePort *> iter(device.ports());
1111                  while (iter.hasNext()) {                  while (iter.hasNext()) {
1112                          qsamplerDevicePort *pPort = iter.next();                          DevicePort *pPort = iter.next();
1113                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1114                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1115                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1116                                                  ++portParam) {                                                  ++portParam) {
1117                                  const qsamplerDeviceParam& param = portParam.value();                                  const DeviceParam& param = portParam.value();
1118                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1119                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice
1120                                  << " " << iPort << " " << portParam.key()                                  << " " << iPort << " " << portParam.key()
# Line 1032  bool MainForm::saveSessionFile ( const Q Line 1201  bool MainForm::saveSessionFile ( const Q
1201  #endif  // CONFIG_MIDI_INSTRUMENT  #endif  // CONFIG_MIDI_INSTRUMENT
1202    
1203          // Sampler channel mapping.          // Sampler channel mapping.
1204          QWidgetList wlist = m_pWorkspace->windowList();          QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
1205          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
1206                  ChannelStrip* pChannelStrip                  ChannelStrip *pChannelStrip = NULL;
1207                          = static_cast<ChannelStrip *> (wlist.at(iChannel));                  QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
1208                    if (pMdiSubWindow)
1209                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
1210                  if (pChannelStrip) {                  if (pChannelStrip) {
1211                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
1212                          if (pChannel) {                          if (pChannel) {
1213                                  ts << "# " << tr("Channel") << " " << iChannel << endl;                                  ts << "# " << tr("Channel") << " " << iChannel << endl;
1214                                  ts << "ADD CHANNEL" << endl;                                  ts << "ADD CHANNEL" << endl;
# Line 1069  bool MainForm::saveSessionFile ( const Q Line 1240  bool MainForm::saveSessionFile ( const Q
1240                                  ts << "LOAD INSTRUMENT NON_MODAL '"                                  ts << "LOAD INSTRUMENT NON_MODAL '"
1241                                          << pChannel->instrumentFile() << "' "                                          << pChannel->instrumentFile() << "' "
1242                                          << pChannel->instrumentNr() << " " << iChannel << endl;                                          << pChannel->instrumentNr() << " " << iChannel << endl;
1243                                  qsamplerChannelRoutingMap::ConstIterator audioRoute;                                  ChannelRoutingMap::ConstIterator audioRoute;
1244                                  for (audioRoute = pChannel->audioRouting().begin();                                  for (audioRoute = pChannel->audioRouting().begin();
1245                                                  audioRoute != pChannel->audioRouting().end();                                                  audioRoute != pChannel->audioRouting().end();
1246                                                          ++audioRoute) {                                                          ++audioRoute) {
# Line 1083  bool MainForm::saveSessionFile ( const Q Line 1254  bool MainForm::saveSessionFile ( const Q
1254                                          ts << "SET CHANNEL MUTE " << iChannel << " 1" << endl;                                          ts << "SET CHANNEL MUTE " << iChannel << " 1" << endl;
1255                                  if (pChannel->channelSolo())                                  if (pChannel->channelSolo())
1256                                          ts << "SET CHANNEL SOLO " << iChannel << " 1" << endl;                                          ts << "SET CHANNEL SOLO " << iChannel << " 1" << endl;
1257  #ifdef CONFIG_MIDI_INSTRUMENT                          #ifdef CONFIG_MIDI_INSTRUMENT
1258                                  if (pChannel->midiMap() >= 0) {                                  if (pChannel->midiMap() >= 0) {
1259                                          ts << "SET CHANNEL MIDI_INSTRUMENT_MAP " << iChannel                                          ts << "SET CHANNEL MIDI_INSTRUMENT_MAP " << iChannel
1260                                                  << " " << midiInstrumentMap[pChannel->midiMap()] << endl;                                                  << " " << midiInstrumentMap[pChannel->midiMap()] << endl;
1261                                  }                                  }
1262  #endif                          #endif
1263  #ifdef CONFIG_FXSEND                          #ifdef CONFIG_FXSEND
1264                                  int iChannelID = pChannel->channelID();                                  int iChannelID = pChannel->channelID();
1265                                  int *piFxSends = ::lscp_list_fxsends(m_pClient, iChannelID);                                  int *piFxSends = ::lscp_list_fxsends(m_pClient, iChannelID);
1266                                  for (int iFxSend = 0;                                  for (int iFxSend = 0;
# Line 1113  bool MainForm::saveSessionFile ( const Q Line 1284  bool MainForm::saveSessionFile ( const Q
1284                                                                  << " " << iAudioSrc                                                                  << " " << iAudioSrc
1285                                                                  << " " << piRouting[iAudioSrc] << endl;                                                                  << " " << piRouting[iAudioSrc] << endl;
1286                                                  }                                                  }
1287  #ifdef CONFIG_FXSEND_LEVEL                                          #ifdef CONFIG_FXSEND_LEVEL
1288                                                  ts << "SET FX_SEND LEVEL " << iChannel                                                  ts << "SET FX_SEND LEVEL " << iChannel
1289                                                          << " " << iFxSend                                                          << " " << iFxSend
1290                                                          << " " << pFxSendInfo->level << endl;                                                          << " " << pFxSendInfo->level << endl;
1291  #endif                                          #endif
1292                                          }       // Check for errors...                                          }       // Check for errors...
1293                                          else if (::lscp_client_get_errno(m_pClient)) {                                          else if (::lscp_client_get_errno(m_pClient)) {
1294                                                  appendMessagesClient("lscp_get_fxsend_info");                                                  appendMessagesClient("lscp_get_fxsend_info");
1295                                                  iErrors++;                                                  iErrors++;
1296                                          }                                          }
1297                                  }                                  }
1298  #endif                          #endif
1299                                  ts << endl;                                  ts << endl;
1300                          }                          }
1301                  }                  }
# Line 1242  void MainForm::fileReset (void) Line 1413  void MainForm::fileReset (void)
1413                  "Please note that this operation may cause\n"                  "Please note that this operation may cause\n"
1414                  "temporary MIDI and Audio disruption.\n\n"                  "temporary MIDI and Audio disruption.\n\n"
1415                  "Do you want to reset the sampler engine now?"),                  "Do you want to reset the sampler engine now?"),
1416                  tr("Reset"), tr("Cancel")) > 0)                  QMessageBox::Ok | QMessageBox::Cancel)
1417                    == QMessageBox::Cancel)
1418                  return;                  return;
1419    
1420          // Trye closing the current session, first...          // Trye closing the current session, first...
# Line 1283  void MainForm::fileRestart (void) Line 1455  void MainForm::fileRestart (void)
1455                          "Please note that this operation may cause\n"                          "Please note that this operation may cause\n"
1456                          "temporary MIDI and Audio disruption.\n\n"                          "temporary MIDI and Audio disruption.\n\n"
1457                          "Do you want to restart the connection now?"),                          "Do you want to restart the connection now?"),
1458                          tr("Restart"), tr("Cancel")) == 0);                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok);
1459          }          }
1460    
1461          // Are we still for it?          // Are we still for it?
# Line 1314  void MainForm::editAddChannel (void) Line 1486  void MainForm::editAddChannel (void)
1486                  return;                  return;
1487    
1488          // Just create the channel instance...          // Just create the channel instance...
1489          qsamplerChannel *pChannel = new qsamplerChannel();          Channel *pChannel = new Channel();
1490          if (pChannel == NULL)          if (pChannel == NULL)
1491                  return;                  return;
1492    
# Line 1348  void MainForm::editRemoveChannel (void) Line 1520  void MainForm::editRemoveChannel (void)
1520          if (m_pClient == NULL)          if (m_pClient == NULL)
1521                  return;                  return;
1522    
1523          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1524          if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1525                  return;                  return;
1526    
1527          qsamplerChannel *pChannel = pChannelStrip->channel();          Channel *pChannel = pChannelStrip->channel();
1528          if (pChannel == NULL)          if (pChannel == NULL)
1529                  return;                  return;
1530    
# Line 1364  void MainForm::editRemoveChannel (void) Line 1536  void MainForm::editRemoveChannel (void)
1536                          "%1\n\n"                          "%1\n\n"
1537                          "Are you sure?")                          "Are you sure?")
1538                          .arg(pChannelStrip->windowTitle()),                          .arg(pChannelStrip->windowTitle()),
1539                          tr("OK"), tr("Cancel")) > 0)                          QMessageBox::Ok | QMessageBox::Cancel)
1540                            == QMessageBox::Cancel)
1541                          return;                          return;
1542          }          }
1543    
# Line 1372  void MainForm::editRemoveChannel (void) Line 1545  void MainForm::editRemoveChannel (void)
1545          if (!pChannel->removeChannel())          if (!pChannel->removeChannel())
1546                  return;                  return;
1547    
         // Just delete the channel strip.  
         delete pChannelStrip;  
   
         // Do we auto-arrange?  
         if (m_pOptions && m_pOptions->bAutoArrange)  
                 channelsArrange();  
   
1548          // We'll be dirty, for sure...          // We'll be dirty, for sure...
1549          m_iDirtyCount++;          m_iDirtyCount++;
1550          stabilizeForm();  
1551            // Just delete the channel strip.
1552            destroyChannelStrip(pChannelStrip);
1553  }  }
1554    
1555    
# Line 1391  void MainForm::editSetupChannel (void) Line 1559  void MainForm::editSetupChannel (void)
1559          if (m_pClient == NULL)          if (m_pClient == NULL)
1560                  return;                  return;
1561    
1562          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1563          if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1564                  return;                  return;
1565    
# Line 1406  void MainForm::editEditChannel (void) Line 1574  void MainForm::editEditChannel (void)
1574          if (m_pClient == NULL)          if (m_pClient == NULL)
1575                  return;                  return;
1576    
1577          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1578          if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1579                  return;                  return;
1580    
# Line 1421  void MainForm::editResetChannel (void) Line 1589  void MainForm::editResetChannel (void)
1589          if (m_pClient == NULL)          if (m_pClient == NULL)
1590                  return;                  return;
1591    
1592          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1593          if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1594                  return;                  return;
1595    
# Line 1439  void MainForm::editResetAllChannels (voi Line 1607  void MainForm::editResetAllChannels (voi
1607          // Invoque the channel strip procedure,          // Invoque the channel strip procedure,
1608          // for all channels out there...          // for all channels out there...
1609          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
1610          QWidgetList wlist = m_pWorkspace->windowList();          QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
1611          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
1612                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip *pChannelStrip = NULL;
1613                    QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
1614                    if (pMdiSubWindow)
1615                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
1616                  if (pChannelStrip)                  if (pChannelStrip)
1617                          pChannelStrip->channelReset();                          pChannelStrip->channelReset();
1618          }          }
# Line 1544  void MainForm::viewOptions (void) Line 1715  void MainForm::viewOptions (void)
1715          OptionsForm* pOptionsForm = new OptionsForm(this);          OptionsForm* pOptionsForm = new OptionsForm(this);
1716          if (pOptionsForm) {          if (pOptionsForm) {
1717                  // Check out some initial nullities(tm)...                  // Check out some initial nullities(tm)...
1718                  ChannelStrip* pChannelStrip = activeChannelStrip();                  ChannelStrip *pChannelStrip = activeChannelStrip();
1719                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)
1720                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();
1721                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)
# Line 1555  void MainForm::viewOptions (void) Line 1726  void MainForm::viewOptions (void)
1726                  int     iOldServerTimeout   = m_pOptions->iServerTimeout;                  int     iOldServerTimeout   = m_pOptions->iServerTimeout;
1727                  bool    bOldServerStart     = m_pOptions->bServerStart;                  bool    bOldServerStart     = m_pOptions->bServerStart;
1728                  QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;                  QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;
1729                    bool    bOldMessagesLog     = m_pOptions->bMessagesLog;
1730                    QString sOldMessagesLogPath = m_pOptions->sMessagesLogPath;
1731                  QString sOldDisplayFont     = m_pOptions->sDisplayFont;                  QString sOldDisplayFont     = m_pOptions->sDisplayFont;
1732                  bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;                  bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;
1733                  int     iOldMaxVolume       = m_pOptions->iMaxVolume;                  int     iOldMaxVolume       = m_pOptions->iMaxVolume;
# Line 1566  void MainForm::viewOptions (void) Line 1739  void MainForm::viewOptions (void)
1739                  bool    bOldCompletePath    = m_pOptions->bCompletePath;                  bool    bOldCompletePath    = m_pOptions->bCompletePath;
1740                  bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;                  bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;
1741                  int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;                  int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;
1742                    int     iOldBaseFontSize    = m_pOptions->iBaseFontSize;
1743                  // Load the current setup settings.                  // Load the current setup settings.
1744                  pOptionsForm->setup(m_pOptions);                  pOptionsForm->setup(m_pOptions);
1745                  // Show the setup dialog...                  // Show the setup dialog...
# Line 1574  void MainForm::viewOptions (void) Line 1748  void MainForm::viewOptions (void)
1748                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1749                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||
1750                                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||                                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||
1751                                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {                                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)     ||
1752                                    (iOldBaseFontSize   !=  m_pOptions->iBaseFontSize)) {
1753                                  QMessageBox::information(this,                                  QMessageBox::information(this,
1754                                          QSAMPLER_TITLE ": " + tr("Information"),                                          QSAMPLER_TITLE ": " + tr("Information"),
1755                                          tr("Some settings may be only effective\n"                                          tr("Some settings may be only effective\n"
1756                                          "next time you start this program."), tr("OK"));                                          "next time you start this program."));
1757                                  updateMessagesCapture();                                  updateMessagesCapture();
1758                          }                          }
1759                          // Check wheather something immediate has changed.                          // Check wheather something immediate has changed.
1760                            if (( bOldMessagesLog && !m_pOptions->bMessagesLog) ||
1761                                    (!bOldMessagesLog &&  m_pOptions->bMessagesLog) ||
1762                                    (sOldMessagesLogPath != m_pOptions->sMessagesLogPath))
1763                                    m_pMessages->setLogging(
1764                                            m_pOptions->bMessagesLog, m_pOptions->sMessagesLogPath);
1765                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||
1766                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||
1767                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
# Line 1628  void MainForm::viewOptions (void) Line 1808  void MainForm::viewOptions (void)
1808  void MainForm::channelsArrange (void)  void MainForm::channelsArrange (void)
1809  {  {
1810          // Full width vertical tiling          // Full width vertical tiling
1811          QWidgetList wlist = m_pWorkspace->windowList();          QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
1812          if (wlist.isEmpty())          if (wlist.isEmpty())
1813                  return;                  return;
1814    
1815          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
1816          int y = 0;          int y = 0;
1817          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
1818                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip *pChannelStrip = NULL;
1819          /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {                  QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
1820                          // Prevent flicker...                  if (pMdiSubWindow)
1821                          pChannelStrip->hide();                          pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
1822                          pChannelStrip->showNormal();                  if (pChannelStrip) {
1823                  }   */                  /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {
1824                  pChannelStrip->adjustSize();                                  // Prevent flicker...
1825                  int iWidth  = m_pWorkspace->width();                                  pChannelStrip->hide();
1826                  if (iWidth < pChannelStrip->width())                                  pChannelStrip->showNormal();
1827                          iWidth = pChannelStrip->width();                          }   */
1828          //  int iHeight = pChannelStrip->height()                          pChannelStrip->adjustSize();
1829          //              + pChannelStrip->parentWidget()->baseSize().height();                          int iWidth  = m_pWorkspace->width();
1830                  int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();                          if (iWidth < pChannelStrip->width())
1831                  pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);                                  iWidth = pChannelStrip->width();
1832                  y += iHeight;                  //  int iHeight = pChannelStrip->height()
1833                    //              + pChannelStrip->parentWidget()->baseSize().height();
1834                            int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();
1835                            pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);
1836                            y += iHeight;
1837                    }
1838          }          }
1839          m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
1840    
# Line 1736  void MainForm::helpAbout (void) Line 1921  void MainForm::helpAbout (void)
1921          sText += tr("Instrument editing support disabled.");          sText += tr("Instrument editing support disabled.");
1922          sText += "</font></small><br />";          sText += "</font></small><br />";
1923  #endif  #endif
1924    #ifndef CONFIG_EVENT_CHANNEL_MIDI
1925            sText += "<small><font color=\"red\">";
1926            sText += tr("Channel MIDI event support disabled.");
1927            sText += "</font></small><br />";
1928    #endif
1929    #ifndef CONFIG_EVENT_DEVICE_MIDI
1930            sText += "<small><font color=\"red\">";
1931            sText += tr("Device MIDI event support disabled.");
1932            sText += "</font></small><br />";
1933    #endif
1934    #ifndef CONFIG_MAX_VOICES
1935            sText += "<small><font color=\"red\">";
1936            sText += tr("Runtime max. voices / disk streams support disabled.");
1937            sText += "</font></small><br />";
1938    #endif
1939          sText += "<br />\n";          sText += "<br />\n";
1940          sText += tr("Using") + ": ";          sText += tr("Using") + ": ";
1941          sText += ::lscp_client_package();          sText += ::lscp_client_package();
# Line 1776  void MainForm::stabilizeForm (void) Line 1976  void MainForm::stabilizeForm (void)
1976          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));
1977    
1978          // Update the main menu state...          // Update the main menu state...
1979          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1980          bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);          bool bHasClient = (m_pOptions != NULL && m_pClient != NULL);
1981          bool bHasChannel = (bHasClient && pChannelStrip != NULL);          bool bHasChannel = (bHasClient && pChannelStrip != NULL);
1982            bool bHasChannels = (bHasClient && m_pWorkspace->subWindowList().count() > 0);
1983          m_ui.fileNewAction->setEnabled(bHasClient);          m_ui.fileNewAction->setEnabled(bHasClient);
1984          m_ui.fileOpenAction->setEnabled(bHasClient);          m_ui.fileOpenAction->setEnabled(bHasClient);
1985          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
# Line 1794  void MainForm::stabilizeForm (void) Line 1995  void MainForm::stabilizeForm (void)
1995          m_ui.editEditChannelAction->setEnabled(false);          m_ui.editEditChannelAction->setEnabled(false);
1996  #endif  #endif
1997          m_ui.editResetChannelAction->setEnabled(bHasChannel);          m_ui.editResetChannelAction->setEnabled(bHasChannel);
1998          m_ui.editResetAllChannelsAction->setEnabled(bHasChannel);          m_ui.editResetAllChannelsAction->setEnabled(bHasChannels);
1999          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());
2000  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
2001          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm
# Line 1806  void MainForm::stabilizeForm (void) Line 2007  void MainForm::stabilizeForm (void)
2007          m_ui.viewDevicesAction->setChecked(m_pDeviceForm          m_ui.viewDevicesAction->setChecked(m_pDeviceForm
2008                  && m_pDeviceForm->isVisible());                  && m_pDeviceForm->isVisible());
2009          m_ui.viewDevicesAction->setEnabled(bHasClient);          m_ui.viewDevicesAction->setEnabled(bHasClient);
2010          m_ui.channelsArrangeAction->setEnabled(bHasChannel);          m_ui.viewMidiDeviceStatusMenu->setEnabled(
2011                    DeviceStatusForm::getInstances().size() > 0);
2012            m_ui.channelsArrangeAction->setEnabled(bHasChannels);
2013    
2014  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2015          // Toolbar widgets are also affected...          // Toolbar widgets are also affected...
# Line 1872  void MainForm::volumeChanged ( int iVolu Line 2075  void MainForm::volumeChanged ( int iVolu
2075    
2076    
2077  // Channel change receiver slot.  // Channel change receiver slot.
2078  void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)  void MainForm::channelStripChanged ( ChannelStrip *pChannelStrip )
2079  {  {
2080          // Add this strip to the changed list...          // Add this strip to the changed list...
2081          if (!m_changedStrips.contains(pChannelStrip)) {          if (!m_changedStrips.contains(pChannelStrip)) {
# Line 1910  void MainForm::updateSession (void) Line 2113  void MainForm::updateSession (void)
2113          }          }
2114  #endif  #endif
2115    
2116            updateAllChannelStrips(false);
2117    
2118            // Do we auto-arrange?
2119            if (m_pOptions && m_pOptions->bAutoArrange)
2120                    channelsArrange();
2121    
2122            // Remember to refresh devices and instruments...
2123            if (m_pInstrumentListForm)
2124                    m_pInstrumentListForm->refreshInstruments();
2125            if (m_pDeviceForm)
2126                    m_pDeviceForm->refreshDevices();
2127    }
2128    
2129    
2130    void MainForm::updateAllChannelStrips ( bool bRemoveDeadStrips )
2131    {
2132          // Retrieve the current channel list.          // Retrieve the current channel list.
2133          int *piChannelIDs = ::lscp_list_channels(m_pClient);          int *piChannelIDs = ::lscp_list_channels(m_pClient);
2134          if (piChannelIDs == NULL) {          if (piChannelIDs == NULL) {
# Line 1921  void MainForm::updateSession (void) Line 2140  void MainForm::updateSession (void)
2140          } else {          } else {
2141                  // Try to (re)create each channel.                  // Try to (re)create each channel.
2142                  m_pWorkspace->setUpdatesEnabled(false);                  m_pWorkspace->setUpdatesEnabled(false);
2143                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; ++iChannel) {
2144                          // Check if theres already a channel strip for this one...                          // Check if theres already a channel strip for this one...
2145                          if (!channelStrip(piChannelIDs[iChannel]))                          if (!channelStrip(piChannelIDs[iChannel]))
2146                                  createChannelStrip(new qsamplerChannel(piChannelIDs[iChannel]));                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));
2147                    }
2148                    // Do we auto-arrange?
2149                    if (m_pOptions && m_pOptions->bAutoArrange)
2150                            channelsArrange();
2151                    // remove dead channel strips
2152                    if (bRemoveDeadStrips) {
2153                            QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
2154                            for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
2155                                    ChannelStrip *pChannelStrip = NULL;
2156                                    QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
2157                                    if (pMdiSubWindow)
2158                                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2159                                    if (pChannelStrip) {
2160                                            bool bExists = false;
2161                                            for (int j = 0; piChannelIDs[j] >= 0; ++j) {
2162                                                    if (!pChannelStrip->channel())
2163                                                            break;
2164                                                    if (piChannelIDs[j] == pChannelStrip->channel()->channelID()) {
2165                                                            // strip exists, don't touch it
2166                                                            bExists = true;
2167                                                            break;
2168                                                    }
2169                                            }
2170                                            if (!bExists)
2171                                                    destroyChannelStrip(pChannelStrip);
2172                                    }
2173                            }
2174                  }                  }
2175                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
2176          }          }
2177    
2178          // 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();  
2179  }  }
2180    
2181    
# Line 1987  void MainForm::updateRecentFilesMenu (vo Line 2225  void MainForm::updateRecentFilesMenu (vo
2225  void MainForm::updateInstrumentNames (void)  void MainForm::updateInstrumentNames (void)
2226  {  {
2227          // Full channel list update...          // Full channel list update...
2228          QWidgetList wlist = m_pWorkspace->windowList();          QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
2229          if (wlist.isEmpty())          if (wlist.isEmpty())
2230                  return;                  return;
2231    
2232          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2233          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
2234                  ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);                  ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);
2235                  if (pChannelStrip)                  if (pChannelStrip)
2236                          pChannelStrip->updateInstrumentName(true);                          pChannelStrip->updateInstrumentName(true);
# Line 2016  void MainForm::updateDisplayFont (void) Line 2254  void MainForm::updateDisplayFont (void)
2254                  return;                  return;
2255    
2256          // Full channel list update...          // Full channel list update...
2257          QWidgetList wlist = m_pWorkspace->windowList();          QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
2258          if (wlist.isEmpty())          if (wlist.isEmpty())
2259                  return;                  return;
2260    
2261          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2262          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
2263                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip *pChannelStrip = NULL;
2264                    QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
2265                    if (pMdiSubWindow)
2266                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2267                  if (pChannelStrip)                  if (pChannelStrip)
2268                          pChannelStrip->setDisplayFont(font);                          pChannelStrip->setDisplayFont(font);
2269          }          }
# Line 2034  void MainForm::updateDisplayFont (void) Line 2275  void MainForm::updateDisplayFont (void)
2275  void MainForm::updateDisplayEffect (void)  void MainForm::updateDisplayEffect (void)
2276  {  {
2277          // Full channel list update...          // Full channel list update...
2278          QWidgetList wlist = m_pWorkspace->windowList();          QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
2279          if (wlist.isEmpty())          if (wlist.isEmpty())
2280                  return;                  return;
2281    
2282          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2283          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
2284                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip *pChannelStrip = NULL;
2285                    QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
2286                    if (pMdiSubWindow)
2287                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2288                  if (pChannelStrip)                  if (pChannelStrip)
2289                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2290          }          }
# Line 2062  void MainForm::updateMaxVolume (void) Line 2306  void MainForm::updateMaxVolume (void)
2306  #endif  #endif
2307    
2308          // Full channel list update...          // Full channel list update...
2309          QWidgetList wlist = m_pWorkspace->windowList();          QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
2310          if (wlist.isEmpty())          if (wlist.isEmpty())
2311                  return;                  return;
2312    
2313          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2314          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
2315                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip *pChannelStrip = NULL;
2316                    QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
2317                    if (pMdiSubWindow)
2318                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2319                  if (pChannelStrip)                  if (pChannelStrip)
2320                          pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                          pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2321          }          }
# Line 2113  void MainForm::appendMessagesError( cons Line 2360  void MainForm::appendMessagesError( cons
2360          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2361    
2362          QMessageBox::critical(this,          QMessageBox::critical(this,
2363                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));                  QSAMPLER_TITLE ": " + tr("Error"), s, QMessageBox::Cancel);
2364  }  }
2365    
2366    
# Line 2176  void MainForm::updateMessagesCapture (vo Line 2423  void MainForm::updateMessagesCapture (vo
2423  // qsamplerMainForm -- MDI channel strip management.  // qsamplerMainForm -- MDI channel strip management.
2424    
2425  // The channel strip creation executive.  // The channel strip creation executive.
2426  ChannelStrip* MainForm::createChannelStrip ( qsamplerChannel *pChannel )  ChannelStrip *MainForm::createChannelStrip ( Channel *pChannel )
2427  {  {
2428          if (m_pClient == NULL || pChannel == NULL)          if (m_pClient == NULL || pChannel == NULL)
2429                  return NULL;                  return NULL;
# Line 2199  ChannelStrip* MainForm::createChannelStr Line 2446  ChannelStrip* MainForm::createChannelStr
2446          }          }
2447    
2448          // Add it to workspace...          // Add it to workspace...
2449          m_pWorkspace->addWindow(pChannelStrip, Qt::FramelessWindowHint);          m_pWorkspace->addSubWindow(pChannelStrip,
2450                    Qt::SubWindow | Qt::FramelessWindowHint);
2451    
2452          // Actual channel strip setup...          // Actual channel strip setup...
2453          pChannelStrip->setup(pChannel);          pChannelStrip->setup(pChannel);
2454    
2455          QObject::connect(pChannelStrip,          QObject::connect(pChannelStrip,
2456                  SIGNAL(channelChanged(ChannelStrip*)),                  SIGNAL(channelChanged(ChannelStrip *)),
2457                  SLOT(channelStripChanged(ChannelStrip*)));                  SLOT(channelStripChanged(ChannelStrip *)));
2458    
2459          // Now we show up us to the world.          // Now we show up us to the world.
2460          pChannelStrip->show();          pChannelStrip->show();
# Line 2219  ChannelStrip* MainForm::createChannelStr Line 2467  ChannelStrip* MainForm::createChannelStr
2467  }  }
2468    
2469    
2470    void MainForm::destroyChannelStrip ( ChannelStrip *pChannelStrip )
2471    {
2472            QMdiSubWindow *pMdiSubWindow
2473                    = static_cast<QMdiSubWindow *> (pChannelStrip->parentWidget());
2474            if (pMdiSubWindow == NULL)
2475                    return;
2476    
2477            // Just delete the channel strip.
2478            delete pChannelStrip;
2479            delete pMdiSubWindow;
2480    
2481            // Do we auto-arrange?
2482            if (m_pOptions && m_pOptions->bAutoArrange)
2483                    channelsArrange();
2484    
2485            stabilizeForm();
2486    }
2487    
2488    
2489  // Retrieve the active channel strip.  // Retrieve the active channel strip.
2490  ChannelStrip* MainForm::activeChannelStrip (void)  ChannelStrip *MainForm::activeChannelStrip (void)
2491  {  {
2492          return static_cast<ChannelStrip *> (m_pWorkspace->activeWindow());          QMdiSubWindow *pMdiSubWindow = m_pWorkspace->activeSubWindow();
2493            if (pMdiSubWindow)
2494                    return static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2495            else
2496                    return NULL;
2497  }  }
2498    
2499    
2500  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
2501  ChannelStrip* MainForm::channelStripAt ( int iChannel )  ChannelStrip *MainForm::channelStripAt ( int iChannel )
2502  {  {
2503          QWidgetList wlist = m_pWorkspace->windowList();          if (!m_pWorkspace) return NULL;
2504    
2505            QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
2506          if (wlist.isEmpty())          if (wlist.isEmpty())
2507                  return NULL;                  return NULL;
2508    
2509          return static_cast<ChannelStrip *> (wlist.at(iChannel));          if (iChannel < 0 || iChannel >= wlist.size())
2510                    return NULL;
2511    
2512            QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
2513            if (pMdiSubWindow)
2514                    return static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2515            else
2516                    return NULL;
2517  }  }
2518    
2519    
2520  // Retrieve a channel strip by sampler channel id.  // Retrieve a channel strip by sampler channel id.
2521  ChannelStrip* MainForm::channelStrip ( int iChannelID )  ChannelStrip *MainForm::channelStrip ( int iChannelID )
2522  {  {
2523          QWidgetList wlist = m_pWorkspace->windowList();          QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
2524          if (wlist.isEmpty())          if (wlist.isEmpty())
2525                  return NULL;                  return NULL;
2526    
2527          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
2528                  ChannelStrip* pChannelStrip                  ChannelStrip *pChannelStrip = NULL;
2529                          = static_cast<ChannelStrip*> (wlist.at(iChannel));                  QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
2530                    if (pMdiSubWindow)
2531                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2532                  if (pChannelStrip) {                  if (pChannelStrip) {
2533                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
2534                          if (pChannel && pChannel->channelID() == iChannelID)                          if (pChannel && pChannel->channelID() == iChannelID)
2535                                  return pChannelStrip;                                  return pChannelStrip;
2536                  }                  }
# Line 2266  void MainForm::channelsMenuAboutToShow ( Line 2548  void MainForm::channelsMenuAboutToShow (
2548          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);
2549          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);
2550    
2551          QWidgetList wlist = m_pWorkspace->windowList();          QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
2552          if (!wlist.isEmpty()) {          if (!wlist.isEmpty()) {
2553                  m_ui.channelsMenu->addSeparator();                  m_ui.channelsMenu->addSeparator();
2554                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
2555                          ChannelStrip* pChannelStrip                          ChannelStrip *pChannelStrip = NULL;
2556                                  = static_cast<ChannelStrip*> (wlist.at(iChannel));                          QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
2557                            if (pMdiSubWindow)
2558                                    pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2559                          if (pChannelStrip) {                          if (pChannelStrip) {
2560                                  QAction *pAction = m_ui.channelsMenu->addAction(                                  QAction *pAction = m_ui.channelsMenu->addAction(
2561                                          pChannelStrip->windowTitle(),                                          pChannelStrip->windowTitle(),
# Line 2293  void MainForm::channelsMenuActivated (vo Line 2577  void MainForm::channelsMenuActivated (vo
2577          if (pAction == NULL)          if (pAction == NULL)
2578                  return;                  return;
2579    
2580          ChannelStrip* pChannelStrip = channelStripAt(pAction->data().toInt());          ChannelStrip *pChannelStrip = channelStripAt(pAction->data().toInt());
2581          if (pChannelStrip) {          if (pChannelStrip) {
2582                  pChannelStrip->showNormal();                  pChannelStrip->showNormal();
2583                  pChannelStrip->setFocus();                  pChannelStrip->setFocus();
# Line 2354  void MainForm::timerSlot (void) Line 2638  void MainForm::timerSlot (void)
2638                          if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime)  {                          if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime)  {
2639                                  m_iTimerSlot = 0;                                  m_iTimerSlot = 0;
2640                                  // Update the channel stream usage for each strip...                                  // Update the channel stream usage for each strip...
2641                                  QWidgetList wlist = m_pWorkspace->windowList();                                  QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
2642                                  for (int iChannel = 0;                                  for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
2643                                                  iChannel < (int) wlist.count(); iChannel++) {                                          ChannelStrip *pChannelStrip = NULL;
2644                                          ChannelStrip* pChannelStrip                                          QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
2645                                                  = (ChannelStrip*) wlist.at(iChannel);                                          if (pMdiSubWindow)
2646                                                    pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2647                                          if (pChannelStrip && pChannelStrip->isVisible())                                          if (pChannelStrip && pChannelStrip->isVisible())
2648                                                  pChannelStrip->updateChannelUsage();                                                  pChannelStrip->updateChannelUsage();
2649                                  }                                  }
# Line 2386  void MainForm::startServer (void) Line 2671  void MainForm::startServer (void)
2671    
2672          // Is the server process instance still here?          // Is the server process instance still here?
2673          if (m_pServer) {          if (m_pServer) {
2674                  switch (QMessageBox::warning(this,                  if (QMessageBox::warning(this,
2675                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
2676                          tr("Could not start the LinuxSampler server.\n\n"                          tr("Could not start the LinuxSampler server.\n\n"
2677                          "Maybe it ss already started."),                          "Maybe it is already started."),
2678                          tr("Stop"), tr("Kill"), tr("Cancel"))) {                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
                 case 0:  
2679                          m_pServer->terminate();                          m_pServer->terminate();
                         break;  
                 case 1:  
2680                          m_pServer->kill();                          m_pServer->kill();
                         break;  
2681                  }                  }
2682                  return;                  return;
2683          }          }
# Line 2409  void MainForm::startServer (void) Line 2690  void MainForm::startServer (void)
2690                  return;                  return;
2691    
2692          // OK. Let's build the startup process...          // OK. Let's build the startup process...
2693          m_pServer = new QProcess(this);          m_pServer = new QProcess();
2694            bForceServerStop = true;
2695    
2696          // Setup stdout/stderr capture...          // Setup stdout/stderr capture...
2697  //      if (m_pOptions->bStdoutCapture) {  //      if (m_pOptions->bStdoutCapture) {
2698                  //m_pServer->setProcessChannelMode(          #if QT_VERSION >= 0x040200
2699                  //      QProcess::StandardOutput);                  m_pServer->setProcessChannelMode(QProcess::ForwardedChannels);
2700            #endif
2701                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2702                          SIGNAL(readyReadStandardOutput()),                          SIGNAL(readyReadStandardOutput()),
2703                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
# Line 2425  void MainForm::startServer (void) Line 2708  void MainForm::startServer (void)
2708    
2709          // The unforgiveable signal communication...          // The unforgiveable signal communication...
2710          QObject::connect(m_pServer,          QObject::connect(m_pServer,
2711                  SIGNAL(finished(int,QProcess::ExitStatus)),                  SIGNAL(finished(int, QProcess::ExitStatus)),
2712                  SLOT(processServerExit()));                  SLOT(processServerExit()));
2713    
2714          // Build process arguments...          // Build process arguments...
# Line 2456  void MainForm::startServer (void) Line 2739  void MainForm::startServer (void)
2739    
2740    
2741  // Stop linuxsampler server...  // Stop linuxsampler server...
2742  void MainForm::stopServer (void)  void MainForm::stopServer (bool bInteractive)
2743  {  {
2744          // Stop client code.          // Stop client code.
2745          stopClient();          stopClient();
2746    
2747            if (m_pServer && bInteractive) {
2748                    if (QMessageBox::question(this,
2749                            QSAMPLER_TITLE ": " + tr("The backend's fate ..."),
2750                            tr("You have the option to keep the sampler backend (LinuxSampler)\n"
2751                            "running in the background. The sampler would continue to work\n"
2752                            "according to your current sampler session and you could alter the\n"
2753                            "sampler session at any time by relaunching QSampler.\n\n"
2754                            "Do you want LinuxSampler to stop?"),
2755                            QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
2756                    {
2757                            bForceServerStop = false;
2758                    }
2759            }
2760    
2761          // And try to stop server.          // And try to stop server.
2762          if (m_pServer) {          if (m_pServer && bForceServerStop) {
2763                  appendMessages(tr("Server is stopping..."));                  appendMessages(tr("Server is stopping..."));
2764                  if (m_pServer->state() == QProcess::Running)                  if (m_pServer->state() == QProcess::Running) {
2765                    #if defined(WIN32)
2766                            // Try harder...
2767                            m_pServer->kill();
2768                    #else
2769                            // Try softly...
2770                          m_pServer->terminate();                          m_pServer->terminate();
2771          }                  #endif
2772                    }
2773            }       // Do final processing anyway.
2774            else processServerExit();
2775    
2776          // Give it some time to terminate gracefully and stabilize...          // Give it some time to terminate gracefully and stabilize...
2777          QTime t;          QTime t;
2778          t.start();          t.start();
2779          while (t.elapsed() < QSAMPLER_TIMER_MSECS)          while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2780                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
   
         // Do final processing anyway.  
         processServerExit();  
2781  }  }
2782    
2783    
# Line 2497  void MainForm::processServerExit (void) Line 2799  void MainForm::processServerExit (void)
2799          if (m_pMessages)          if (m_pMessages)
2800                  m_pMessages->flushStdoutBuffer();                  m_pMessages->flushStdoutBuffer();
2801    
2802          if (m_pServer) {          if (m_pServer && bForceServerStop) {
2803                    if (m_pServer->state() != QProcess::NotRunning) {
2804                            appendMessages(tr("Server is being forced..."));
2805                            // Force final server shutdown...
2806                            m_pServer->kill();
2807                            // Give it some time to terminate gracefully and stabilize...
2808                            QTime t;
2809                            t.start();
2810                            while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2811                                    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2812                    }
2813                  // Force final server shutdown...                  // Force final server shutdown...
2814                  appendMessages(                  appendMessages(
2815                          tr("Server was stopped with exit status %1.")                          tr("Server was stopped with exit status %1.")
2816                          .arg(m_pServer->exitStatus()));                          .arg(m_pServer->exitStatus()));
                 m_pServer->terminate();  
                 if (!m_pServer->waitForFinished(2000))  
                         m_pServer->kill();  
                 // Destroy it.  
2817                  delete m_pServer;                  delete m_pServer;
2818                  m_pServer = NULL;                  m_pServer = NULL;
2819          }          }
# Line 2530  lscp_status_t qsampler_client_callback ( Line 2838  lscp_status_t qsampler_client_callback (
2838          // as this is run under some other thread context.          // as this is run under some other thread context.
2839          // A custom event must be posted here...          // A custom event must be posted here...
2840          QApplication::postEvent(pMainForm,          QApplication::postEvent(pMainForm,
2841                  new qsamplerCustomEvent(event, pchData, cchData));                  new LscpEvent(event, pchData, cchData));
2842    
2843          return LSCP_OK;          return LSCP_OK;
2844  }  }
# Line 2575  bool MainForm::startClient (void) Line 2883  bool MainForm::startClient (void)
2883                  .arg(::lscp_client_get_timeout(m_pClient)));                  .arg(::lscp_client_get_timeout(m_pClient)));
2884    
2885          // Subscribe to channel info change notifications...          // Subscribe to channel info change notifications...
2886            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT) != LSCP_OK)
2887                    appendMessagesClient("lscp_client_subscribe(CHANNEL_COUNT)");
2888          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)
2889                  appendMessagesClient("lscp_client_subscribe");                  appendMessagesClient("lscp_client_subscribe(CHANNEL_INFO)");
2890    
2891            DeviceStatusForm::onDevicesChanged(); // initialize
2892            updateViewMidiDeviceStatusMenu();
2893            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT) != LSCP_OK)
2894                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_COUNT)");
2895            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO) != LSCP_OK)
2896                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_INFO)");
2897            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT) != LSCP_OK)
2898                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_COUNT)");
2899            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO) != LSCP_OK)
2900                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_INFO)");
2901    
2902    #if CONFIG_EVENT_CHANNEL_MIDI
2903            // Subscribe to channel MIDI data notifications...
2904            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI) != LSCP_OK)
2905                    appendMessagesClient("lscp_client_subscribe(CHANNEL_MIDI)");
2906    #endif
2907    
2908    #if CONFIG_EVENT_DEVICE_MIDI
2909            // Subscribe to channel MIDI data notifications...
2910            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI) != LSCP_OK)
2911                    appendMessagesClient("lscp_client_subscribe(DEVICE_MIDI)");
2912    #endif
2913    
2914          // We may stop scheduling around.          // We may stop scheduling around.
2915          stopSchedule();          stopSchedule();
# Line 2603  bool MainForm::startClient (void) Line 2936  bool MainForm::startClient (void)
2936                  }                  }
2937          }          }
2938    
2939            // send the current / loaded fine tuning settings to the sampler
2940            m_pOptions->sendFineTuningSettings();
2941    
2942          // Make a new session          // Make a new session
2943          return newSession();          return newSession();
2944  }  }
# Line 2630  void MainForm::stopClient (void) Line 2966  void MainForm::stopClient (void)
2966          closeSession(false);          closeSession(false);
2967    
2968          // Close us as a client...          // Close us as a client...
2969    #if CONFIG_EVENT_DEVICE_MIDI
2970            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI);
2971    #endif
2972    #if CONFIG_EVENT_CHANNEL_MIDI
2973            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI);
2974    #endif
2975            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
2976            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
2977            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
2978            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
2979          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
2980            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT);
2981          ::lscp_client_destroy(m_pClient);          ::lscp_client_destroy(m_pClient);
2982          m_pClient = NULL;          m_pClient = NULL;
2983    
# Line 2650  void MainForm::stopClient (void) Line 2997  void MainForm::stopClient (void)
2997    
2998    
2999  // Channel strip activation/selection.  // Channel strip activation/selection.
3000  void MainForm::activateStrip ( QWidget *pWidget )  void MainForm::activateStrip ( QMdiSubWindow *pMdiSubWindow )
3001  {  {
3002          ChannelStrip *pChannelStrip          ChannelStrip *pChannelStrip = NULL;
3003                  = static_cast<ChannelStrip *> (pWidget);          if (pMdiSubWindow)
3004                    pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
3005          if (pChannelStrip)          if (pChannelStrip)
3006                  pChannelStrip->setSelected(true);                  pChannelStrip->setSelected(true);
3007    

Legend:
Removed from v.1515  
changed lines
  Added in v.2441

  ViewVC Help
Powered by ViewVC