/[svn]/qsampler/trunk/src/qsamplerMainForm.cpp
ViewVC logotype

Diff of /qsampler/trunk/src/qsamplerMainForm.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1514 by capela, Fri Nov 23 10:51:37 2007 UTC revision 2978 by capela, Mon Aug 15 19:10:16 2016 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-2016, rncbc aka Rui Nuno Capela. All rights reserved.
5     Copyright (C) 2007, Christian Schoenebeck     Copyright (C) 2007,2008,2015 Christian Schoenebeck
6    
7     This program is free software; you can redistribute it and/or     This program is free software; you can redistribute it and/or
8     modify it under the terms of the GNU General Public License     modify it under the terms of the GNU General Public License
# Line 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    }
69    #endif
70    
71  #ifdef HAVE_SIGNAL_H  #ifdef HAVE_SIGNAL_H
72  #include <signal.h>  #include <signal.h>
# Line 77  static inline long lroundf ( float x ) Line 89  static inline long lroundf ( float x )
89  }  }
90  #endif  #endif
91    
92    
93    // All winsock apps needs this.
94    #if defined(WIN32)
95    static WSADATA _wsaData;
96    #endif
97    
98    
99    //-------------------------------------------------------------------------
100    // LADISH Level 1 support stuff.
101    
102    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
103    
104    #include <QSocketNotifier>
105    
106    #include <sys/types.h>
107    #include <sys/socket.h>
108    
109    #include <signal.h>
110    
111    // File descriptor for SIGUSR1 notifier.
112    static int g_fdUsr1[2];
113    
114    // Unix SIGUSR1 signal handler.
115    static void qsampler_sigusr1_handler ( int /* signo */ )
116    {
117            char c = 1;
118    
119            (::write(g_fdUsr1[0], &c, sizeof(c)) > 0);
120    }
121    
122    #endif  // HAVE_SIGNAL_H
123    
124    
125    //-------------------------------------------------------------------------
126    // qsampler -- namespace
127    
128    
129    namespace QSampler {
130    
131  // Timer constant stuff.  // Timer constant stuff.
132  #define QSAMPLER_TIMER_MSECS    200  #define QSAMPLER_TIMER_MSECS    200
133    
# Line 87  static inline long lroundf ( float x ) Line 138  static inline long lroundf ( float x )
138  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.
139    
140    
141  // All winsock apps needs this.  // Specialties for thread-callback comunication.
142  #if defined(WIN32)  #define QSAMPLER_LSCP_EVENT   QEvent::Type(QEvent::User + 1)
 static WSADATA _wsaData;  
 #endif  
143    
144    
145  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
146  // qsamplerCustomEvent -- specialty for callback comunication.  // LscpEvent -- specialty for LSCP callback comunication.
147    
 #define QSAMPLER_CUSTOM_EVENT   QEvent::Type(QEvent::User + 0)  
148    
149  class qsamplerCustomEvent : public QEvent  class LscpEvent : public QEvent
150  {  {
151  public:  public:
152    
153          // Constructor.          // Constructor.
154          qsamplerCustomEvent(lscp_event_t event, const char *pchData, int cchData)          LscpEvent(lscp_event_t event, const char *pchData, int cchData)
155                  : QEvent(QSAMPLER_CUSTOM_EVENT)                  : QEvent(QSAMPLER_LSCP_EVENT)
156          {          {
157                  m_event = event;                  m_event = event;
158                  m_data  = QString::fromUtf8(pchData, cchData);                  m_data  = QString::fromUtf8(pchData, cchData);
# Line 126  private: Line 174  private:
174  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
175  // qsamplerMainForm -- Main window form implementation.  // qsamplerMainForm -- Main window form implementation.
176    
 namespace QSampler {  
   
177  // Kind of singleton reference.  // Kind of singleton reference.
178  MainForm* MainForm::g_pMainForm = NULL;  MainForm* MainForm::g_pMainForm = NULL;
179    
# Line 149  MainForm::MainForm ( QWidget *pParent ) Line 195  MainForm::MainForm ( QWidget *pParent )
195    
196          // We'll start clean.          // We'll start clean.
197          m_iUntitled   = 0;          m_iUntitled   = 0;
198            m_iDirtySetup = 0;
199          m_iDirtyCount = 0;          m_iDirtyCount = 0;
200    
201          m_pServer = NULL;          m_pServer = NULL;
# Line 159  MainForm::MainForm ( QWidget *pParent ) Line 206  MainForm::MainForm ( QWidget *pParent )
206    
207          m_iTimerSlot = 0;          m_iTimerSlot = 0;
208    
209  #ifdef HAVE_SIGNAL_H  #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
210    
211          // Set to ignore any fatal "Broken pipe" signals.          // Set to ignore any fatal "Broken pipe" signals.
212          ::signal(SIGPIPE, SIG_IGN);          ::signal(SIGPIPE, SIG_IGN);
213  #endif  
214            // LADISH Level 1 suport.
215    
216            // Initialize file descriptors for SIGUSR1 socket notifier.
217            ::socketpair(AF_UNIX, SOCK_STREAM, 0, g_fdUsr1);
218            m_pUsr1Notifier
219                    = new QSocketNotifier(g_fdUsr1[1], QSocketNotifier::Read, this);
220    
221            QObject::connect(m_pUsr1Notifier,
222                    SIGNAL(activated(int)),
223                    SLOT(handle_sigusr1()));
224    
225            // Install SIGUSR1 signal handler.
226        struct sigaction usr1;
227        usr1.sa_handler = qsampler_sigusr1_handler;
228        sigemptyset(&usr1.sa_mask);
229        usr1.sa_flags = 0;
230        usr1.sa_flags |= SA_RESTART;
231        ::sigaction(SIGUSR1, &usr1, NULL);
232    
233    #else   // HAVE_SIGNAL_H
234    
235            m_pUsr1Notifier = NULL;
236            
237    #endif  // !HAVE_SIGNAL_H
238    
239  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
240          // Make some extras into the toolbar...          // Make some extras into the toolbar...
# Line 171  MainForm::MainForm ( QWidget *pParent ) Line 243  MainForm::MainForm ( QWidget *pParent )
243          // Volume slider...          // Volume slider...
244          m_ui.channelsToolbar->addSeparator();          m_ui.channelsToolbar->addSeparator();
245          m_pVolumeSlider = new QSlider(Qt::Horizontal, m_ui.channelsToolbar);          m_pVolumeSlider = new QSlider(Qt::Horizontal, m_ui.channelsToolbar);
246          m_pVolumeSlider->setTickPosition(QSlider::TicksBelow);          m_pVolumeSlider->setTickPosition(QSlider::TicksBothSides);
247          m_pVolumeSlider->setTickInterval(10);          m_pVolumeSlider->setTickInterval(10);
248          m_pVolumeSlider->setPageStep(10);          m_pVolumeSlider->setPageStep(10);
249          m_pVolumeSlider->setSingleStep(10);          m_pVolumeSlider->setSingleStep(10);
# Line 183  MainForm::MainForm ( QWidget *pParent ) Line 255  MainForm::MainForm ( QWidget *pParent )
255          QObject::connect(m_pVolumeSlider,          QObject::connect(m_pVolumeSlider,
256                  SIGNAL(valueChanged(int)),                  SIGNAL(valueChanged(int)),
257                  SLOT(volumeChanged(int)));                  SLOT(volumeChanged(int)));
         //m_ui.channelsToolbar->setHorizontallyStretchable(true);  
         //m_ui.channelsToolbar->setStretchableWidget(m_pVolumeSlider);  
258          m_ui.channelsToolbar->addWidget(m_pVolumeSlider);          m_ui.channelsToolbar->addWidget(m_pVolumeSlider);
259          // Volume spin-box          // Volume spin-box
260          m_ui.channelsToolbar->addSeparator();          m_ui.channelsToolbar->addSeparator();
# Line 200  MainForm::MainForm ( QWidget *pParent ) Line 270  MainForm::MainForm ( QWidget *pParent )
270  #endif  #endif
271    
272          // Make it an MDI workspace.          // Make it an MDI workspace.
273          m_pWorkspace = new QWorkspace(this);          m_pWorkspace = new QMdiArea(this);
274          m_pWorkspace->setScrollBarsEnabled(true);          m_pWorkspace->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
275            m_pWorkspace->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
276          // Set the activation connection.          // Set the activation connection.
277          QObject::connect(m_pWorkspace,          QObject::connect(m_pWorkspace,
278                  SIGNAL(windowActivated(QWidget *)),                  SIGNAL(subWindowActivated(QMdiSubWindow *)),
279                  SLOT(activateStrip(QWidget *)));                  SLOT(activateStrip(QMdiSubWindow *)));
280          // Make it shine :-)          // Make it shine :-)
281          setCentralWidget(m_pWorkspace);          setCentralWidget(m_pWorkspace);
282    
# Line 322  MainForm::MainForm ( QWidget *pParent ) Line 393  MainForm::MainForm ( QWidget *pParent )
393          QObject::connect(m_ui.channelsMenu,          QObject::connect(m_ui.channelsMenu,
394                  SIGNAL(aboutToShow()),                  SIGNAL(aboutToShow()),
395                  SLOT(channelsMenuAboutToShow()));                  SLOT(channelsMenuAboutToShow()));
396    #ifdef CONFIG_VOLUME
397            QObject::connect(m_ui.channelsToolbar,
398                    SIGNAL(orientationChanged(Qt::Orientation)),
399                    SLOT(channelsToolbarOrientation(Qt::Orientation)));
400    #endif
401  }  }
402    
403  // Destructor.  // Destructor.
# Line 334  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 365  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();
481          updateMessagesCapture();          updateMessagesCapture();
482    
483          // Set the visibility signal.          // Set the visibility signal.
484          QObject::connect(m_pMessages,          QObject::connect(m_pMessages,
485                  SIGNAL(visibilityChanged(bool)),                  SIGNAL(visibilityChanged(bool)),
# Line 418  void MainForm::setup ( qsamplerOptions * Line 506  void MainForm::setup ( qsamplerOptions *
506          }          }
507    
508          // Try to restore old window positioning and initial visibility.          // Try to restore old window positioning and initial visibility.
509          m_pOptions->loadWidgetGeometry(this);          m_pOptions->loadWidgetGeometry(this, true);
510          m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);          m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);
511          m_pOptions->loadWidgetGeometry(m_pDeviceForm);          m_pOptions->loadWidgetGeometry(m_pDeviceForm);
512    
# Line 457  bool MainForm::queryClose (void) Line 545  bool MainForm::queryClose (void)
545                                  || m_ui.channelsToolbar->isVisible());                                  || m_ui.channelsToolbar->isVisible());
546                          m_pOptions->bStatusbar = statusBar()->isVisible();                          m_pOptions->bStatusbar = statusBar()->isVisible();
547                          // Save the dock windows state.                          // Save the dock windows state.
                         const QString sDockables = saveState().toBase64().data();  
548                          m_pOptions->settings().setValue("/Layout/DockWindows", saveState());                          m_pOptions->settings().setValue("/Layout/DockWindows", saveState());
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 479  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 499  void MainForm::dragEnterEvent ( QDragEnt Line 587  void MainForm::dragEnterEvent ( QDragEnt
587  }  }
588    
589    
590  void MainForm::dropEvent ( QDropEvent* pDropEvent )  void MainForm::dropEvent ( QDropEvent *pDropEvent )
591  {  {
592          // Accept externally originated drops only...          // Accept externally originated drops only...
593          if (pDropEvent->source())          if (pDropEvent->source())
# Line 510  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 544  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 {                                  const 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    // Window resize event handler.
699    void MainForm::resizeEvent ( QResizeEvent * )
700    {
701            if (m_pOptions->bAutoArrange)
702                    channelsArrange();
703    }
704    
705    
706    // LADISH Level 1 -- SIGUSR1 signal handler.
707    void MainForm::handle_sigusr1 (void)
708    {
709    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
710    
711            char c;
712    
713            if (::read(g_fdUsr1[1], &c, sizeof(c)) > 0)
714                    saveSession(false);
715    
716    #endif
717    }
718    
719    
720    void MainForm::updateViewMidiDeviceStatusMenu (void)
721    {
722            m_ui.viewMidiDeviceStatusMenu->clear();
723            const std::map<int, DeviceStatusForm *> statusForms
724                    = DeviceStatusForm::getInstances();
725            std::map<int, DeviceStatusForm *>::const_iterator iter
726                    = statusForms.begin();
727            for ( ; iter != statusForms.end(); ++iter) {
728                    DeviceStatusForm *pStatusForm = iter->second;
729                    m_ui.viewMidiDeviceStatusMenu->addAction(
730                            pStatusForm->visibleAction());
731            }
732    }
733    
734    
735  // Context menu event handler.  // Context menu event handler.
736  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )
737  {  {
# Line 575  void MainForm::contextMenuEvent( QContex Line 745  void MainForm::contextMenuEvent( QContex
745  // qsamplerMainForm -- Brainless public property accessors.  // qsamplerMainForm -- Brainless public property accessors.
746    
747  // The global options settings property.  // The global options settings property.
748  qsamplerOptions *MainForm::options (void) const  Options *MainForm::options (void) const
749  {  {
750          return m_pOptions;          return m_pOptions;
751  }  }
# Line 601  MainForm *MainForm::getInstance (void) Line 771  MainForm *MainForm::getInstance (void)
771  // Format the displayable session filename.  // Format the displayable session filename.
772  QString MainForm::sessionName ( const QString& sFilename )  QString MainForm::sessionName ( const QString& sFilename )
773  {  {
774          bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);          const bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);
775          QString sSessionName = sFilename;          QString sSessionName = sFilename;
776          if (sSessionName.isEmpty())          if (sSessionName.isEmpty())
777                  sSessionName = tr("Untitled") + QString::number(m_iUntitled);                  sSessionName = tr("Untitled") + QString::number(m_iUntitled);
# Line 693  bool MainForm::saveSession ( bool bPromp Line 863  bool MainForm::saveSession ( bool bPromp
863                                  "\"%1\"\n\n"                                  "\"%1\"\n\n"
864                                  "Do you want to replace it?")                                  "Do you want to replace it?")
865                                  .arg(sFilename),                                  .arg(sFilename),
866                                  tr("Replace"), tr("Cancel")) > 0)                                  QMessageBox::Yes | QMessageBox::No)
867                                    == QMessageBox::No)
868                                  return false;                                  return false;
869                  }                  }
870          }          }
# Line 716  bool MainForm::closeSession ( bool bForc Line 887  bool MainForm::closeSession ( bool bForc
887                          "\"%1\"\n\n"                          "\"%1\"\n\n"
888                          "Do you want to save the changes?")                          "Do you want to save the changes?")
889                          .arg(sessionName(m_sFilename)),                          .arg(sessionName(m_sFilename)),
890                          tr("Save"), tr("Discard"), tr("Cancel"))) {                          QMessageBox::Save |
891                  case 0:     // Save...                          QMessageBox::Discard |
892                            QMessageBox::Cancel)) {
893                    case QMessageBox::Save:
894                          bClose = saveSession(false);                          bClose = saveSession(false);
895                          // Fall thru....                          // Fall thru....
896                  case 1:     // Discard                  case QMessageBox::Discard:
897                          break;                          break;
898                  default:    // Cancel.                  default:    // Cancel.
899                          bClose = false;                          bClose = false;
# Line 732  bool MainForm::closeSession ( bool bForc Line 905  bool MainForm::closeSession ( bool bForc
905          if (bClose) {          if (bClose) {
906                  // Remove all channel strips from sight...                  // Remove all channel strips from sight...
907                  m_pWorkspace->setUpdatesEnabled(false);                  m_pWorkspace->setUpdatesEnabled(false);
908                  QWidgetList wlist = m_pWorkspace->windowList();                  const QList<QMdiSubWindow *>& wlist
909                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                          = m_pWorkspace->subWindowList();
910                          ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  const int iStripCount = wlist.count();
911                    for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
912                            ChannelStrip *pChannelStrip = NULL;
913                            QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
914                            if (pMdiSubWindow)
915                                    pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
916                          if (pChannelStrip) {                          if (pChannelStrip) {
917                                  qsamplerChannel *pChannel = pChannelStrip->channel();                                  Channel *pChannel = pChannelStrip->channel();
918                                  if (bForce && pChannel)                                  if (bForce && pChannel)
919                                          pChannel->removeChannel();                                          pChannel->removeChannel();
920                                  delete pChannelStrip;                                  delete pChannelStrip;
921                          }                          }
922                            if (pMdiSubWindow)
923                                    delete pMdiSubWindow;
924                  }                  }
925                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
926                  // We're now clean, for sure.                  // We're now clean, for sure.
# Line 852  bool MainForm::saveSessionFile ( const Q Line 1032  bool MainForm::saveSessionFile ( const Q
1032          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1033    
1034          // Write the file.          // Write the file.
1035          int  iErrors = 0;          int iErrors = 0;
1036          QTextStream ts(&file);          QTextStream ts(&file);
1037          ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;          ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;
1038          ts << "# " << tr("Version")          ts << "# " << tr("Version")
# Line 876  bool MainForm::saveSessionFile ( const Q Line 1056  bool MainForm::saveSessionFile ( const Q
1056    
1057          // Audio device mapping.          // Audio device mapping.
1058          QMap<int, int> audioDeviceMap;          QMap<int, int> audioDeviceMap;
1059          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Audio);          piDeviceIDs = Device::getDevices(m_pClient, Device::Audio);
1060          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
1061                  ts << endl;                  ts << endl;
1062                  qsamplerDevice device(qsamplerDevice::Audio, piDeviceIDs[iDevice]);                  Device device(Device::Audio, piDeviceIDs[iDevice]);
1063                  // Audio device specification...                  // Audio device specification...
1064                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1065                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1066                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();
1067                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
1068                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
1069                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
1070                                          ++deviceParam) {                                          ++deviceParam) {
1071                          const qsamplerDeviceParam& param = deviceParam.value();                          const DeviceParam& param = deviceParam.value();
1072                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
1073                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
1074                  }                  }
1075                  ts << endl;                  ts << endl;
1076                  // Audio channel parameters...                  // Audio channel parameters...
1077                  int iPort = 0;                  int iPort = 0;
1078                  QListIterator<qsamplerDevicePort *> iter(device.ports());                  QListIterator<DevicePort *> iter(device.ports());
1079                  while (iter.hasNext()) {                  while (iter.hasNext()) {
1080                          qsamplerDevicePort *pPort = iter.next();                          DevicePort *pPort = iter.next();
1081                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1082                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1083                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1084                                                  ++portParam) {                                                  ++portParam) {
1085                                  const qsamplerDeviceParam& param = portParam.value();                                  const DeviceParam& param = portParam.value();
1086                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1087                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice
1088                                          << " " << iPort << " " << portParam.key()                                          << " " << iPort << " " << portParam.key()
# Line 918  bool MainForm::saveSessionFile ( const Q Line 1098  bool MainForm::saveSessionFile ( const Q
1098    
1099          // MIDI device mapping.          // MIDI device mapping.
1100          QMap<int, int> midiDeviceMap;          QMap<int, int> midiDeviceMap;
1101          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Midi);          piDeviceIDs = Device::getDevices(m_pClient, Device::Midi);
1102          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
1103                  ts << endl;                  ts << endl;
1104                  qsamplerDevice device(qsamplerDevice::Midi, piDeviceIDs[iDevice]);                  Device device(Device::Midi, piDeviceIDs[iDevice]);
1105                  // MIDI device specification...                  // MIDI device specification...
1106                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1107                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1108                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();
1109                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
1110                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
1111                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
1112                                          ++deviceParam) {                                          ++deviceParam) {
1113                          const qsamplerDeviceParam& param = deviceParam.value();                          const DeviceParam& param = deviceParam.value();
1114                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
1115                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
1116                  }                  }
1117                  ts << endl;                  ts << endl;
1118                  // MIDI port parameters...                  // MIDI port parameters...
1119                  int iPort = 0;                  int iPort = 0;
1120                  QListIterator<qsamplerDevicePort *> iter(device.ports());                  QListIterator<DevicePort *> iter(device.ports());
1121                  while (iter.hasNext()) {                  while (iter.hasNext()) {
1122                          qsamplerDevicePort *pPort = iter.next();                          DevicePort *pPort = iter.next();
1123                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1124                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1125                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1126                                                  ++portParam) {                                                  ++portParam) {
1127                                  const qsamplerDeviceParam& param = portParam.value();                                  const DeviceParam& param = portParam.value();
1128                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1129                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice
1130                                  << " " << iPort << " " << portParam.key()                                  << " " << iPort << " " << portParam.key()
# Line 964  bool MainForm::saveSessionFile ( const Q Line 1144  bool MainForm::saveSessionFile ( const Q
1144          QMap<int, int> midiInstrumentMap;          QMap<int, int> midiInstrumentMap;
1145          int *piMaps = ::lscp_list_midi_instrument_maps(m_pClient);          int *piMaps = ::lscp_list_midi_instrument_maps(m_pClient);
1146          for (int iMap = 0; piMaps && piMaps[iMap] >= 0; iMap++) {          for (int iMap = 0; piMaps && piMaps[iMap] >= 0; iMap++) {
1147                  int iMidiMap = piMaps[iMap];                  const int iMidiMap = piMaps[iMap];
1148                  const char *pszMapName                  const char *pszMapName
1149                          = ::lscp_get_midi_instrument_map_name(m_pClient, iMidiMap);                          = ::lscp_get_midi_instrument_map_name(m_pClient, iMidiMap);
1150                  ts << "# " << tr("MIDI instrument map") << " " << iMap;                  ts << "# " << tr("MIDI instrument map") << " " << iMap;
# Line 1031  bool MainForm::saveSessionFile ( const Q Line 1211  bool MainForm::saveSessionFile ( const Q
1211  #endif  // CONFIG_MIDI_INSTRUMENT  #endif  // CONFIG_MIDI_INSTRUMENT
1212    
1213          // Sampler channel mapping.          // Sampler channel mapping.
1214          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
1215          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  = m_pWorkspace->subWindowList();
1216                  ChannelStrip* pChannelStrip          const int iStripCount = wlist.count();
1217                          = static_cast<ChannelStrip *> (wlist.at(iChannel));          for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
1218                    ChannelStrip *pChannelStrip = NULL;
1219                    QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
1220                    if (pMdiSubWindow)
1221                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
1222                  if (pChannelStrip) {                  if (pChannelStrip) {
1223                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
1224                          if (pChannel) {                          if (pChannel) {
1225                                  ts << "# " << tr("Channel") << " " << iChannel << endl;                                  const int iChannelID = pChannel->channelID();
1226                                    ts << "# " << tr("Channel") << " " << iChannelID << endl;
1227                                  ts << "ADD CHANNEL" << endl;                                  ts << "ADD CHANNEL" << endl;
1228                                  if (audioDeviceMap.isEmpty()) {                                  if (audioDeviceMap.isEmpty()) {
1229                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannelID
1230                                                  << " " << pChannel->audioDriver() << endl;                                                  << " " << pChannel->audioDriver() << endl;
1231                                  } else {                                  } else {
1232                                          ts << "SET CHANNEL AUDIO_OUTPUT_DEVICE " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_DEVICE " << iChannelID
1233                                                  << " " << audioDeviceMap[pChannel->audioDevice()] << endl;                                                  << " " << audioDeviceMap[pChannel->audioDevice()] << endl;
1234                                  }                                  }
1235                                  if (midiDeviceMap.isEmpty()) {                                  if (midiDeviceMap.isEmpty()) {
1236                                          ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannel                                          ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannelID
1237                                                  << " " << pChannel->midiDriver() << endl;                                                  << " " << pChannel->midiDriver() << endl;
1238                                  } else {                                  } else {
1239                                          ts << "SET CHANNEL MIDI_INPUT_DEVICE " << iChannel                                          ts << "SET CHANNEL MIDI_INPUT_DEVICE " << iChannelID
1240                                                  << " " << midiDeviceMap[pChannel->midiDevice()] << endl;                                                  << " " << midiDeviceMap[pChannel->midiDevice()] << endl;
1241                                  }                                  }
1242                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannelID
1243                                          << " " << pChannel->midiPort() << endl;                                          << " " << pChannel->midiPort() << endl;
1244                                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";                                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannelID << " ";
1245                                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)                                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
1246                                          ts << "ALL";                                          ts << "ALL";
1247                                  else                                  else
1248                                          ts << pChannel->midiChannel();                                          ts << pChannel->midiChannel();
1249                                  ts << endl;                                  ts << endl;
1250                                  ts << "LOAD ENGINE " << pChannel->engineName()                                  ts << "LOAD ENGINE " << pChannel->engineName()
1251                                          << " " << iChannel << endl;                                          << " " << iChannelID << endl;
1252                                  if (pChannel->instrumentStatus() < 100) ts << "# ";                                  if (pChannel->instrumentStatus() < 100) ts << "# ";
1253                                  ts << "LOAD INSTRUMENT NON_MODAL '"                                  ts << "LOAD INSTRUMENT NON_MODAL '"
1254                                          << pChannel->instrumentFile() << "' "                                          << pChannel->instrumentFile() << "' "
1255                                          << pChannel->instrumentNr() << " " << iChannel << endl;                                          << pChannel->instrumentNr() << " " << iChannelID << endl;
1256                                  qsamplerChannelRoutingMap::ConstIterator audioRoute;                                  ChannelRoutingMap::ConstIterator audioRoute;
1257                                  for (audioRoute = pChannel->audioRouting().begin();                                  for (audioRoute = pChannel->audioRouting().begin();
1258                                                  audioRoute != pChannel->audioRouting().end();                                                  audioRoute != pChannel->audioRouting().end();
1259                                                          ++audioRoute) {                                                          ++audioRoute) {
1260                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannelID
1261                                                  << " " << audioRoute.key()                                                  << " " << audioRoute.key()
1262                                                  << " " << audioRoute.value() << endl;                                                  << " " << audioRoute.value() << endl;
1263                                  }                                  }
1264                                  ts << "SET CHANNEL VOLUME " << iChannel                                  ts << "SET CHANNEL VOLUME " << iChannelID
1265                                          << " " << pChannel->volume() << endl;                                          << " " << pChannel->volume() << endl;
1266                                  if (pChannel->channelMute())                                  if (pChannel->channelMute())
1267                                          ts << "SET CHANNEL MUTE " << iChannel << " 1" << endl;                                          ts << "SET CHANNEL MUTE " << iChannelID << " 1" << endl;
1268                                  if (pChannel->channelSolo())                                  if (pChannel->channelSolo())
1269                                          ts << "SET CHANNEL SOLO " << iChannel << " 1" << endl;                                          ts << "SET CHANNEL SOLO " << iChannelID << " 1" << endl;
1270  #ifdef CONFIG_MIDI_INSTRUMENT                          #ifdef CONFIG_MIDI_INSTRUMENT
1271                                  if (pChannel->midiMap() >= 0) {                                  if (pChannel->midiMap() >= 0) {
1272                                          ts << "SET CHANNEL MIDI_INSTRUMENT_MAP " << iChannel                                          ts << "SET CHANNEL MIDI_INSTRUMENT_MAP " << iChannelID
1273                                                  << " " << midiInstrumentMap[pChannel->midiMap()] << endl;                                                  << " " << midiInstrumentMap[pChannel->midiMap()] << endl;
1274                                  }                                  }
1275  #endif                          #endif
1276  #ifdef CONFIG_FXSEND                          #ifdef CONFIG_FXSEND
                                 int iChannelID = pChannel->channelID();  
1277                                  int *piFxSends = ::lscp_list_fxsends(m_pClient, iChannelID);                                  int *piFxSends = ::lscp_list_fxsends(m_pClient, iChannelID);
1278                                  for (int iFxSend = 0;                                  for (int iFxSend = 0;
1279                                                  piFxSends && piFxSends[iFxSend] >= 0;                                                  piFxSends && piFxSends[iFxSend] >= 0;
# Line 1097  bool MainForm::saveSessionFile ( const Q Line 1281  bool MainForm::saveSessionFile ( const Q
1281                                          lscp_fxsend_info_t *pFxSendInfo = ::lscp_get_fxsend_info(                                          lscp_fxsend_info_t *pFxSendInfo = ::lscp_get_fxsend_info(
1282                                                  m_pClient, iChannelID, piFxSends[iFxSend]);                                                  m_pClient, iChannelID, piFxSends[iFxSend]);
1283                                          if (pFxSendInfo) {                                          if (pFxSendInfo) {
1284                                                  ts << "CREATE FX_SEND " << iChannel                                                  ts << "CREATE FX_SEND " << iChannelID
1285                                                          << " " << pFxSendInfo->midi_controller;                                                          << " " << pFxSendInfo->midi_controller;
1286                                                  if (pFxSendInfo->name)                                                  if (pFxSendInfo->name)
1287                                                          ts << " '" << pFxSendInfo->name << "'";                                                          ts << " '" << pFxSendInfo->name << "'";
# Line 1107  bool MainForm::saveSessionFile ( const Q Line 1291  bool MainForm::saveSessionFile ( const Q
1291                                                                  piRouting && piRouting[iAudioSrc] >= 0;                                                                  piRouting && piRouting[iAudioSrc] >= 0;
1292                                                                          iAudioSrc++) {                                                                          iAudioSrc++) {
1293                                                          ts << "SET FX_SEND AUDIO_OUTPUT_CHANNEL "                                                          ts << "SET FX_SEND AUDIO_OUTPUT_CHANNEL "
1294                                                                  << iChannel                                                                  << iChannelID
1295                                                                  << " " << iFxSend                                                                  << " " << iFxSend
1296                                                                  << " " << iAudioSrc                                                                  << " " << iAudioSrc
1297                                                                  << " " << piRouting[iAudioSrc] << endl;                                                                  << " " << piRouting[iAudioSrc] << endl;
1298                                                  }                                                  }
1299  #ifdef CONFIG_FXSEND_LEVEL                                          #ifdef CONFIG_FXSEND_LEVEL
1300                                                  ts << "SET FX_SEND LEVEL " << iChannel                                                  ts << "SET FX_SEND LEVEL " << iChannelID
1301                                                          << " " << iFxSend                                                          << " " << iFxSend
1302                                                          << " " << pFxSendInfo->level << endl;                                                          << " " << pFxSendInfo->level << endl;
1303  #endif                                          #endif
1304                                          }       // Check for errors...                                          }       // Check for errors...
1305                                          else if (::lscp_client_get_errno(m_pClient)) {                                          else if (::lscp_client_get_errno(m_pClient)) {
1306                                                  appendMessagesClient("lscp_get_fxsend_info");                                                  appendMessagesClient("lscp_get_fxsend_info");
1307                                                  iErrors++;                                                  iErrors++;
1308                                          }                                          }
1309                                  }                                  }
1310  #endif                          #endif
1311                                  ts << endl;                                  ts << endl;
1312                          }                          }
1313                  }                  }
# Line 1200  void MainForm::fileOpenRecent (void) Line 1384  void MainForm::fileOpenRecent (void)
1384          // Retrive filename index from action data...          // Retrive filename index from action data...
1385          QAction *pAction = qobject_cast<QAction *> (sender());          QAction *pAction = qobject_cast<QAction *> (sender());
1386          if (pAction && m_pOptions) {          if (pAction && m_pOptions) {
1387                  int iIndex = pAction->data().toInt();                  const int iIndex = pAction->data().toInt();
1388                  if (iIndex >= 0 && iIndex < m_pOptions->recentFiles.count()) {                  if (iIndex >= 0 && iIndex < m_pOptions->recentFiles.count()) {
1389                          QString sFilename = m_pOptions->recentFiles[iIndex];                          QString sFilename = m_pOptions->recentFiles[iIndex];
1390                          // Check if we can safely close the current session...                          // Check if we can safely close the current session...
# Line 1234  void MainForm::fileReset (void) Line 1418  void MainForm::fileReset (void)
1418                  return;                  return;
1419    
1420          // Ask user whether he/she want's an internal sampler reset...          // Ask user whether he/she want's an internal sampler reset...
1421          if (QMessageBox::warning(this,          if (m_pOptions && m_pOptions->bConfirmReset) {
1422                  QSAMPLER_TITLE ": " + tr("Warning"),                  const QString& sTitle = QSAMPLER_TITLE ": " + tr("Warning");
1423                  tr("Resetting the sampler instance will close\n"                  const QString& sText = tr(
1424                  "all device and channel configurations.\n\n"                          "Resetting the sampler instance will close\n"
1425                  "Please note that this operation may cause\n"                          "all device and channel configurations.\n\n"
1426                  "temporary MIDI and Audio disruption.\n\n"                          "Please note that this operation may cause\n"
1427                  "Do you want to reset the sampler engine now?"),                          "temporary MIDI and Audio disruption.\n\n"
1428                  tr("Reset"), tr("Cancel")) > 0)                          "Do you want to reset the sampler engine now?");
1429                  return;          #if 0
1430                    if (QMessageBox::warning(this, sTitle, sText,
1431                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1432                            return;
1433            #else
1434                    QMessageBox mbox(this);
1435                    mbox.setIcon(QMessageBox::Warning);
1436                    mbox.setWindowTitle(sTitle);
1437                    mbox.setText(sText);
1438                    mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1439                    QCheckBox cbox(tr("Don't ask this again"));
1440                    cbox.setChecked(false);
1441                    cbox.blockSignals(true);
1442                    mbox.addButton(&cbox, QMessageBox::ActionRole);
1443                    if (mbox.exec() == QMessageBox::Cancel)
1444                            return;
1445                    if (cbox.isChecked())
1446                            m_pOptions->bConfirmReset = false;
1447            #endif
1448            }
1449    
1450          // Trye closing the current session, first...          // Trye closing the current session, first...
1451          if (!closeSession(true))          if (!closeSession(true))
# Line 1274  void MainForm::fileRestart (void) Line 1477  void MainForm::fileRestart (void)
1477    
1478          // Ask user whether he/she want's a complete restart...          // Ask user whether he/she want's a complete restart...
1479          // (if we're currently up and running)          // (if we're currently up and running)
1480          if (bRestart && m_pClient) {          if (m_pOptions && m_pOptions->bConfirmRestart) {
1481                  bRestart = (QMessageBox::warning(this,                  const QString& sTitle = QSAMPLER_TITLE ": " + tr("Warning");
1482                          QSAMPLER_TITLE ": " + tr("Warning"),                  const QString& sText = tr(
1483                          tr("New settings will be effective after\n"                          "New settings will be effective after\n"
1484                          "restarting the client/server connection.\n\n"                          "restarting the client/server connection.\n\n"
1485                          "Please note that this operation may cause\n"                          "Please note that this operation may cause\n"
1486                          "temporary MIDI and Audio disruption.\n\n"                          "temporary MIDI and Audio disruption.\n\n"
1487                          "Do you want to restart the connection now?"),                          "Do you want to restart the connection now?");
1488                          tr("Restart"), tr("Cancel")) == 0);          #if 0
1489                    if (QMessageBox::warning(this, sTitle, sText,
1490                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1491                            bRestart = false;
1492            #else
1493                    QMessageBox mbox(this);
1494                    mbox.setIcon(QMessageBox::Warning);
1495                    mbox.setWindowTitle(sTitle);
1496                    mbox.setText(sText);
1497                    mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1498                    QCheckBox cbox(tr("Don't ask this again"));
1499                    cbox.setChecked(false);
1500                    cbox.blockSignals(true);
1501                    mbox.addButton(&cbox, QMessageBox::ActionRole);
1502                    if (mbox.exec() == QMessageBox::Cancel)
1503                            bRestart = false;
1504                    else
1505                    if (cbox.isChecked())
1506                            m_pOptions->bConfirmRestart = false;
1507            #endif
1508          }          }
1509    
1510          // Are we still for it?          // Are we still for it?
# Line 1309  void MainForm::fileExit (void) Line 1531  void MainForm::fileExit (void)
1531  // Add a new sampler channel.  // Add a new sampler channel.
1532  void MainForm::editAddChannel (void)  void MainForm::editAddChannel (void)
1533  {  {
1534            ++m_iDirtySetup;
1535            addChannelStrip();
1536            --m_iDirtySetup;
1537    }
1538    
1539    void MainForm::addChannelStrip (void)
1540    {
1541          if (m_pClient == NULL)          if (m_pClient == NULL)
1542                  return;                  return;
1543    
1544          // Just create the channel instance...          // Just create the channel instance...
1545          qsamplerChannel *pChannel = new qsamplerChannel();          Channel *pChannel = new Channel();
1546          if (pChannel == NULL)          if (pChannel == NULL)
1547                  return;                  return;
1548    
# Line 1331  void MainForm::editAddChannel (void) Line 1560  void MainForm::editAddChannel (void)
1560                  return;                  return;
1561          }          }
1562    
1563            // Do we auto-arrange?
1564            if (m_pOptions && m_pOptions->bAutoArrange)
1565                    channelsArrange();
1566    
1567          // Make that an overall update.          // Make that an overall update.
1568          m_iDirtyCount++;          m_iDirtyCount++;
1569          stabilizeForm();          stabilizeForm();
# Line 1340  void MainForm::editAddChannel (void) Line 1573  void MainForm::editAddChannel (void)
1573  // Remove current sampler channel.  // Remove current sampler channel.
1574  void MainForm::editRemoveChannel (void)  void MainForm::editRemoveChannel (void)
1575  {  {
1576            ++m_iDirtySetup;
1577            removeChannelStrip();
1578            --m_iDirtySetup;
1579    }
1580    
1581    void MainForm::removeChannelStrip (void)
1582    {
1583          if (m_pClient == NULL)          if (m_pClient == NULL)
1584                  return;                  return;
1585    
1586          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1587          if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1588                  return;                  return;
1589    
1590          qsamplerChannel *pChannel = pChannelStrip->channel();          Channel *pChannel = pChannelStrip->channel();
1591          if (pChannel == NULL)          if (pChannel == NULL)
1592                  return;                  return;
1593    
1594          // Prompt user if he/she's sure about this...          // Prompt user if he/she's sure about this...
1595          if (m_pOptions && m_pOptions->bConfirmRemove) {          if (m_pOptions && m_pOptions->bConfirmRemove) {
1596                  if (QMessageBox::warning(this,                  const QString& sTitle = QSAMPLER_TITLE ": " + tr("Warning");
1597                          QSAMPLER_TITLE ": " + tr("Warning"),                  const QString& sText = tr(
1598                          tr("About to remove channel:\n\n"                          "About to remove channel:\n\n"
1599                          "%1\n\n"                          "%1\n\n"
1600                          "Are you sure?")                          "Are you sure?")
1601                          .arg(pChannelStrip->windowTitle()),                          .arg(pChannelStrip->windowTitle());
1602                          tr("OK"), tr("Cancel")) > 0)          #if 0
1603                    if (QMessageBox::warning(this, sTitle, sText,
1604                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1605                            return;
1606            #else
1607                    QMessageBox mbox(this);
1608                    mbox.setIcon(QMessageBox::Warning);
1609                    mbox.setWindowTitle(sTitle);
1610                    mbox.setText(sText);
1611                    mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1612                    QCheckBox cbox(tr("Don't ask this again"));
1613                    cbox.setChecked(false);
1614                    cbox.blockSignals(true);
1615                    mbox.addButton(&cbox, QMessageBox::ActionRole);
1616                    if (mbox.exec() == QMessageBox::Cancel)
1617                          return;                          return;
1618                    if (cbox.isChecked())
1619                            m_pOptions->bConfirmRemove = false;
1620            #endif
1621          }          }
1622    
1623          // Remove the existing sampler channel.          // Remove the existing sampler channel.
# Line 1368  void MainForm::editRemoveChannel (void) Line 1625  void MainForm::editRemoveChannel (void)
1625                  return;                  return;
1626    
1627          // Just delete the channel strip.          // Just delete the channel strip.
1628          delete pChannelStrip;          destroyChannelStrip(pChannelStrip);
   
         // Do we auto-arrange?  
         if (m_pOptions && m_pOptions->bAutoArrange)  
                 channelsArrange();  
1629    
1630          // We'll be dirty, for sure...          // We'll be dirty, for sure...
1631          m_iDirtyCount++;          m_iDirtyCount++;
# Line 1386  void MainForm::editSetupChannel (void) Line 1639  void MainForm::editSetupChannel (void)
1639          if (m_pClient == NULL)          if (m_pClient == NULL)
1640                  return;                  return;
1641    
1642          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1643          if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1644                  return;                  return;
1645    
# Line 1401  void MainForm::editEditChannel (void) Line 1654  void MainForm::editEditChannel (void)
1654          if (m_pClient == NULL)          if (m_pClient == NULL)
1655                  return;                  return;
1656    
1657          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1658          if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1659                  return;                  return;
1660    
# Line 1416  void MainForm::editResetChannel (void) Line 1669  void MainForm::editResetChannel (void)
1669          if (m_pClient == NULL)          if (m_pClient == NULL)
1670                  return;                  return;
1671    
1672          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1673          if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1674                  return;                  return;
1675    
# Line 1434  void MainForm::editResetAllChannels (voi Line 1687  void MainForm::editResetAllChannels (voi
1687          // Invoque the channel strip procedure,          // Invoque the channel strip procedure,
1688          // for all channels out there...          // for all channels out there...
1689          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
1690          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
1691          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  = m_pWorkspace->subWindowList();
1692                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);          const int iStripCount = wlist.count();
1693            for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
1694                    ChannelStrip *pChannelStrip = NULL;
1695                    QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
1696                    if (pMdiSubWindow)
1697                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
1698                  if (pChannelStrip)                  if (pChannelStrip)
1699                          pChannelStrip->channelReset();                          pChannelStrip->channelReset();
1700          }          }
# Line 1539  void MainForm::viewOptions (void) Line 1797  void MainForm::viewOptions (void)
1797          OptionsForm* pOptionsForm = new OptionsForm(this);          OptionsForm* pOptionsForm = new OptionsForm(this);
1798          if (pOptionsForm) {          if (pOptionsForm) {
1799                  // Check out some initial nullities(tm)...                  // Check out some initial nullities(tm)...
1800                  ChannelStrip* pChannelStrip = activeChannelStrip();                  ChannelStrip *pChannelStrip = activeChannelStrip();
1801                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)
1802                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();
1803                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)
1804                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
1805                  // To track down deferred or immediate changes.                  // To track down deferred or immediate changes.
1806                  QString sOldServerHost      = m_pOptions->sServerHost;                  const QString sOldServerHost      = m_pOptions->sServerHost;
1807                  int     iOldServerPort      = m_pOptions->iServerPort;                  const int     iOldServerPort      = m_pOptions->iServerPort;
1808                  int     iOldServerTimeout   = m_pOptions->iServerTimeout;                  const int     iOldServerTimeout   = m_pOptions->iServerTimeout;
1809                  bool    bOldServerStart     = m_pOptions->bServerStart;                  const bool    bOldServerStart     = m_pOptions->bServerStart;
1810                  QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;                  const QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;
1811                  QString sOldDisplayFont     = m_pOptions->sDisplayFont;                  const bool    bOldMessagesLog     = m_pOptions->bMessagesLog;
1812                  bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;                  const QString sOldMessagesLogPath = m_pOptions->sMessagesLogPath;
1813                  int     iOldMaxVolume       = m_pOptions->iMaxVolume;                  const QString sOldDisplayFont     = m_pOptions->sDisplayFont;
1814                  QString sOldMessagesFont    = m_pOptions->sMessagesFont;                  const bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;
1815                  bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;                  const int     iOldMaxVolume       = m_pOptions->iMaxVolume;
1816                  bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;                  const QString sOldMessagesFont    = m_pOptions->sMessagesFont;
1817                  int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;                  const bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;
1818                  int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;                  const bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;
1819                  bool    bOldCompletePath    = m_pOptions->bCompletePath;                  const int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;
1820                  bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;                  const int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;
1821                  int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;                  const bool    bOldCompletePath    = m_pOptions->bCompletePath;
1822                    const bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;
1823                    const int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;
1824                    const int     iOldBaseFontSize    = m_pOptions->iBaseFontSize;
1825                  // Load the current setup settings.                  // Load the current setup settings.
1826                  pOptionsForm->setup(m_pOptions);                  pOptionsForm->setup(m_pOptions);
1827                  // Show the setup dialog...                  // Show the setup dialog...
# Line 1569  void MainForm::viewOptions (void) Line 1830  void MainForm::viewOptions (void)
1830                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1831                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||
1832                                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||                                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||
1833                                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {                                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)     ||
1834                                    (iOldBaseFontSize   !=  m_pOptions->iBaseFontSize)) {
1835                                  QMessageBox::information(this,                                  QMessageBox::information(this,
1836                                          QSAMPLER_TITLE ": " + tr("Information"),                                          QSAMPLER_TITLE ": " + tr("Information"),
1837                                          tr("Some settings may be only effective\n"                                          tr("Some settings may be only effective\n"
1838                                          "next time you start this program."), tr("OK"));                                          "next time you start this program."));
1839                                  updateMessagesCapture();                                  updateMessagesCapture();
1840                          }                          }
1841                          // Check wheather something immediate has changed.                          // Check wheather something immediate has changed.
1842                            if (( bOldMessagesLog && !m_pOptions->bMessagesLog) ||
1843                                    (!bOldMessagesLog &&  m_pOptions->bMessagesLog) ||
1844                                    (sOldMessagesLogPath != m_pOptions->sMessagesLogPath))
1845                                    m_pMessages->setLogging(
1846                                            m_pOptions->bMessagesLog, m_pOptions->sMessagesLogPath);
1847                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||
1848                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||
1849                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
# Line 1623  void MainForm::viewOptions (void) Line 1890  void MainForm::viewOptions (void)
1890  void MainForm::channelsArrange (void)  void MainForm::channelsArrange (void)
1891  {  {
1892          // Full width vertical tiling          // Full width vertical tiling
1893          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
1894                    = m_pWorkspace->subWindowList();
1895          if (wlist.isEmpty())          if (wlist.isEmpty())
1896                  return;                  return;
1897    
1898          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
1899          int y = 0;          int y = 0;
1900          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          const int iStripCount = wlist.count();
1901                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);          for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
1902          /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {                  QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
1903                          // Prevent flicker...                  if (pMdiSubWindow) {
1904                          pChannelStrip->hide();                          pMdiSubWindow->adjustSize();
1905                          pChannelStrip->showNormal();                          int iWidth = m_pWorkspace->width();
1906                  }   */                          if (iWidth < pMdiSubWindow->width())
1907                  pChannelStrip->adjustSize();                                  iWidth = pMdiSubWindow->width();
1908                  int iWidth  = m_pWorkspace->width();                          const int iHeight = pMdiSubWindow->frameGeometry().height();
1909                  if (iWidth < pChannelStrip->width())                          pMdiSubWindow->setGeometry(0, y, iWidth, iHeight);
1910                          iWidth = pChannelStrip->width();                          y += iHeight;
1911          //  int iHeight = pChannelStrip->height()                  }
         //              + pChannelStrip->parentWidget()->baseSize().height();  
                 int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();  
                 pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);  
                 y += iHeight;  
1912          }          }
1913          m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
1914    
# Line 1731  void MainForm::helpAbout (void) Line 1995  void MainForm::helpAbout (void)
1995          sText += tr("Instrument editing support disabled.");          sText += tr("Instrument editing support disabled.");
1996          sText += "</font></small><br />";          sText += "</font></small><br />";
1997  #endif  #endif
1998    #ifndef CONFIG_EVENT_CHANNEL_MIDI
1999            sText += "<small><font color=\"red\">";
2000            sText += tr("Channel MIDI event support disabled.");
2001            sText += "</font></small><br />";
2002    #endif
2003    #ifndef CONFIG_EVENT_DEVICE_MIDI
2004            sText += "<small><font color=\"red\">";
2005            sText += tr("Device MIDI event support disabled.");
2006            sText += "</font></small><br />";
2007    #endif
2008    #ifndef CONFIG_MAX_VOICES
2009            sText += "<small><font color=\"red\">";
2010            sText += tr("Runtime max. voices / disk streams support disabled.");
2011            sText += "</font></small><br />";
2012    #endif
2013          sText += "<br />\n";          sText += "<br />\n";
2014          sText += tr("Using") + ": ";          sText += tr("Using") + ": ";
2015          sText += ::lscp_client_package();          sText += ::lscp_client_package();
# Line 1771  void MainForm::stabilizeForm (void) Line 2050  void MainForm::stabilizeForm (void)
2050          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));
2051    
2052          // Update the main menu state...          // Update the main menu state...
2053          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
2054          bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);          const QList<QMdiSubWindow *>& wlist = m_pWorkspace->subWindowList();
2055          bool bHasChannel = (bHasClient && pChannelStrip != NULL);          const bool bHasClient = (m_pOptions != NULL && m_pClient != NULL);
2056            const bool bHasChannel = (bHasClient && pChannelStrip != NULL);
2057            const bool bHasChannels = (bHasClient && wlist.count() > 0);
2058          m_ui.fileNewAction->setEnabled(bHasClient);          m_ui.fileNewAction->setEnabled(bHasClient);
2059          m_ui.fileOpenAction->setEnabled(bHasClient);          m_ui.fileOpenAction->setEnabled(bHasClient);
2060          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
# Line 1789  void MainForm::stabilizeForm (void) Line 2070  void MainForm::stabilizeForm (void)
2070          m_ui.editEditChannelAction->setEnabled(false);          m_ui.editEditChannelAction->setEnabled(false);
2071  #endif  #endif
2072          m_ui.editResetChannelAction->setEnabled(bHasChannel);          m_ui.editResetChannelAction->setEnabled(bHasChannel);
2073          m_ui.editResetAllChannelsAction->setEnabled(bHasChannel);          m_ui.editResetAllChannelsAction->setEnabled(bHasChannels);
2074          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());
2075  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
2076          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm
# Line 1801  void MainForm::stabilizeForm (void) Line 2082  void MainForm::stabilizeForm (void)
2082          m_ui.viewDevicesAction->setChecked(m_pDeviceForm          m_ui.viewDevicesAction->setChecked(m_pDeviceForm
2083                  && m_pDeviceForm->isVisible());                  && m_pDeviceForm->isVisible());
2084          m_ui.viewDevicesAction->setEnabled(bHasClient);          m_ui.viewDevicesAction->setEnabled(bHasClient);
2085          m_ui.channelsArrangeAction->setEnabled(bHasChannel);          m_ui.viewMidiDeviceStatusMenu->setEnabled(
2086                    DeviceStatusForm::getInstances().size() > 0);
2087            m_ui.channelsArrangeAction->setEnabled(bHasChannels);
2088    
2089  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2090          // Toolbar widgets are also affected...          // Toolbar widgets are also affected...
# Line 1851  void MainForm::volumeChanged ( int iVolu Line 2134  void MainForm::volumeChanged ( int iVolu
2134                  m_pVolumeSpinBox->setValue(iVolume);                  m_pVolumeSpinBox->setValue(iVolume);
2135    
2136          // Do it as commanded...          // Do it as commanded...
2137          float fVolume = 0.01f * float(iVolume);          const float fVolume = 0.01f * float(iVolume);
2138          if (::lscp_set_volume(m_pClient, fVolume) == LSCP_OK)          if (::lscp_set_volume(m_pClient, fVolume) == LSCP_OK)
2139                  appendMessages(QObject::tr("Volume: %1.").arg(fVolume));                  appendMessages(QObject::tr("Volume: %1.").arg(fVolume));
2140          else          else
# Line 1867  void MainForm::volumeChanged ( int iVolu Line 2150  void MainForm::volumeChanged ( int iVolu
2150    
2151    
2152  // Channel change receiver slot.  // Channel change receiver slot.
2153  void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)  void MainForm::channelStripChanged ( ChannelStrip *pChannelStrip )
2154  {  {
2155          // Add this strip to the changed list...          // Add this strip to the changed list...
2156          if (!m_changedStrips.contains(pChannelStrip)) {          if (!m_changedStrips.contains(pChannelStrip)) {
# Line 1886  void MainForm::channelStripChanged(Chann Line 2169  void MainForm::channelStripChanged(Chann
2169  void MainForm::updateSession (void)  void MainForm::updateSession (void)
2170  {  {
2171  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2172          int iVolume = ::lroundf(100.0f * ::lscp_get_volume(m_pClient));          const int iVolume = ::lroundf(100.0f * ::lscp_get_volume(m_pClient));
2173          m_iVolumeChanging++;          m_iVolumeChanging++;
2174          m_pVolumeSlider->setValue(iVolume);          m_pVolumeSlider->setValue(iVolume);
2175          m_pVolumeSpinBox->setValue(iVolume);          m_pVolumeSpinBox->setValue(iVolume);
# Line 1894  void MainForm::updateSession (void) Line 2177  void MainForm::updateSession (void)
2177  #endif  #endif
2178  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
2179          // FIXME: Make some room for default instrument maps...          // FIXME: Make some room for default instrument maps...
2180          int iMaps = ::lscp_get_midi_instrument_maps(m_pClient);          const int iMaps = ::lscp_get_midi_instrument_maps(m_pClient);
2181          if (iMaps < 0)          if (iMaps < 0)
2182                  appendMessagesClient("lscp_get_midi_instrument_maps");                  appendMessagesClient("lscp_get_midi_instrument_maps");
2183          else if (iMaps < 1) {          else if (iMaps < 1) {
# Line 1905  void MainForm::updateSession (void) Line 2188  void MainForm::updateSession (void)
2188          }          }
2189  #endif  #endif
2190    
2191            updateAllChannelStrips(false);
2192    
2193            // Do we auto-arrange?
2194            if (m_pOptions && m_pOptions->bAutoArrange)
2195                    channelsArrange();
2196    
2197            // Remember to refresh devices and instruments...
2198            if (m_pInstrumentListForm)
2199                    m_pInstrumentListForm->refreshInstruments();
2200            if (m_pDeviceForm)
2201                    m_pDeviceForm->refreshDevices();
2202    }
2203    
2204    
2205    void MainForm::updateAllChannelStrips ( bool bRemoveDeadStrips )
2206    {
2207            // Skip if setting up a new channel strip...
2208            if (m_iDirtySetup > 0)
2209                    return;
2210    
2211          // Retrieve the current channel list.          // Retrieve the current channel list.
2212          int *piChannelIDs = ::lscp_list_channels(m_pClient);          int *piChannelIDs = ::lscp_list_channels(m_pClient);
2213          if (piChannelIDs == NULL) {          if (piChannelIDs == NULL) {
# Line 1916  void MainForm::updateSession (void) Line 2219  void MainForm::updateSession (void)
2219          } else {          } else {
2220                  // Try to (re)create each channel.                  // Try to (re)create each channel.
2221                  m_pWorkspace->setUpdatesEnabled(false);                  m_pWorkspace->setUpdatesEnabled(false);
2222                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; ++iChannel) {
2223                          // Check if theres already a channel strip for this one...                          // Check if theres already a channel strip for this one...
2224                          if (!channelStrip(piChannelIDs[iChannel]))                          if (!channelStrip(piChannelIDs[iChannel]))
2225                                  createChannelStrip(new qsamplerChannel(piChannelIDs[iChannel]));                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));
2226                    }
2227                    // Do we auto-arrange?
2228                    if (m_pOptions && m_pOptions->bAutoArrange)
2229                            channelsArrange();
2230                    // remove dead channel strips
2231                    if (bRemoveDeadStrips) {
2232                            const QList<QMdiSubWindow *>& wlist
2233                                    = m_pWorkspace->subWindowList();
2234                            const int iStripCount = wlist.count();
2235                            for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
2236                                    ChannelStrip *pChannelStrip = NULL;
2237                                    QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2238                                    if (pMdiSubWindow)
2239                                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2240                                    if (pChannelStrip) {
2241                                            bool bExists = false;
2242                                            for (int iChannel = 0; piChannelIDs[iChannel] >= 0; ++iChannel) {
2243                                                    Channel *pChannel = pChannelStrip->channel();
2244                                                    if (pChannel == NULL)
2245                                                            break;
2246                                                    if (piChannelIDs[iChannel] == pChannel->channelID()) {
2247                                                            // strip exists, don't touch it
2248                                                            bExists = true;
2249                                                            break;
2250                                                    }
2251                                            }
2252                                            if (!bExists)
2253                                                    destroyChannelStrip(pChannelStrip);
2254                                    }
2255                            }
2256                  }                  }
2257                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
2258          }          }
2259    
2260          // 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();  
2261  }  }
2262    
2263    
# Line 1943  void MainForm::updateRecentFiles ( const Line 2268  void MainForm::updateRecentFiles ( const
2268                  return;                  return;
2269    
2270          // Remove from list if already there (avoid duplicates)          // Remove from list if already there (avoid duplicates)
2271          int iIndex = m_pOptions->recentFiles.indexOf(sFilename);          const int iIndex = m_pOptions->recentFiles.indexOf(sFilename);
2272          if (iIndex >= 0)          if (iIndex >= 0)
2273                  m_pOptions->recentFiles.removeAt(iIndex);                  m_pOptions->recentFiles.removeAt(iIndex);
2274          // Put it to front...          // Put it to front...
# Line 1982  void MainForm::updateRecentFilesMenu (vo Line 2307  void MainForm::updateRecentFilesMenu (vo
2307  void MainForm::updateInstrumentNames (void)  void MainForm::updateInstrumentNames (void)
2308  {  {
2309          // Full channel list update...          // Full channel list update...
2310          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2311                    = m_pWorkspace->subWindowList();
2312          if (wlist.isEmpty())          if (wlist.isEmpty())
2313                  return;                  return;
2314    
2315          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2316          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          const int iStripCount = wlist.count();
2317                  ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);          for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
2318                    ChannelStrip *pChannelStrip = NULL;
2319                    QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2320                    if (pMdiSubWindow)
2321                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2322                  if (pChannelStrip)                  if (pChannelStrip)
2323                          pChannelStrip->updateInstrumentName(true);                          pChannelStrip->updateInstrumentName(true);
2324          }          }
# Line 2005  void MainForm::updateDisplayFont (void) Line 2335  void MainForm::updateDisplayFont (void)
2335          // Check if display font is legal.          // Check if display font is legal.
2336          if (m_pOptions->sDisplayFont.isEmpty())          if (m_pOptions->sDisplayFont.isEmpty())
2337                  return;                  return;
2338    
2339          // Realize it.          // Realize it.
2340          QFont font;          QFont font;
2341          if (!font.fromString(m_pOptions->sDisplayFont))          if (!font.fromString(m_pOptions->sDisplayFont))
2342                  return;                  return;
2343    
2344          // Full channel list update...          // Full channel list update...
2345          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2346                    = m_pWorkspace->subWindowList();
2347          if (wlist.isEmpty())          if (wlist.isEmpty())
2348                  return;                  return;
2349    
2350          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2351          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          const int iStripCount = wlist.count();
2352                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);          for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
2353                    ChannelStrip *pChannelStrip = NULL;
2354                    QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2355                    if (pMdiSubWindow)
2356                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2357                  if (pChannelStrip)                  if (pChannelStrip)
2358                          pChannelStrip->setDisplayFont(font);                          pChannelStrip->setDisplayFont(font);
2359          }          }
# Line 2029  void MainForm::updateDisplayFont (void) Line 2365  void MainForm::updateDisplayFont (void)
2365  void MainForm::updateDisplayEffect (void)  void MainForm::updateDisplayEffect (void)
2366  {  {
2367          // Full channel list update...          // Full channel list update...
2368          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2369                    = m_pWorkspace->subWindowList();
2370          if (wlist.isEmpty())          if (wlist.isEmpty())
2371                  return;                  return;
2372    
2373          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2374          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          const int iStripCount = wlist.count();
2375                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);          for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
2376                    ChannelStrip *pChannelStrip = NULL;
2377                    QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2378                    if (pMdiSubWindow)
2379                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2380                  if (pChannelStrip)                  if (pChannelStrip)
2381                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2382          }          }
# Line 2057  void MainForm::updateMaxVolume (void) Line 2398  void MainForm::updateMaxVolume (void)
2398  #endif  #endif
2399    
2400          // Full channel list update...          // Full channel list update...
2401          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2402                    = m_pWorkspace->subWindowList();
2403          if (wlist.isEmpty())          if (wlist.isEmpty())
2404                  return;                  return;
2405    
2406          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2407          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          const int iStripCount = wlist.count();
2408                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);          for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
2409                    ChannelStrip *pChannelStrip = NULL;
2410                    QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2411                    if (pMdiSubWindow)
2412                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2413                  if (pChannelStrip)                  if (pChannelStrip)
2414                          pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                          pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2415          }          }
# Line 2097  void MainForm::appendMessagesText( const Line 2443  void MainForm::appendMessagesText( const
2443                  m_pMessages->appendMessagesText(s);                  m_pMessages->appendMessagesText(s);
2444  }  }
2445    
2446  void MainForm::appendMessagesError( const QString& s )  void MainForm::appendMessagesError( const QString& sText )
2447  {  {
2448          if (m_pMessages)          if (m_pMessages)
2449                  m_pMessages->show();                  m_pMessages->show();
2450    
2451          appendMessagesColor(s.simplified(), "#ff0000");          appendMessagesColor(sText.simplified(), "#ff0000");
2452    
2453          // Make it look responsive...:)          // Make it look responsive...:)
2454          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2455    
2456          QMessageBox::critical(this,          if (m_pOptions && m_pOptions->bConfirmError) {
2457                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));                  const QString& sTitle = QSAMPLER_TITLE ": " + tr("Error");
2458            #if 0
2459                    QMessageBox::critical(this, sTitle, sText, QMessageBox::Cancel);
2460            #else
2461                    QMessageBox mbox(this);
2462                    mbox.setIcon(QMessageBox::Critical);
2463                    mbox.setWindowTitle(sTitle);
2464                    mbox.setText(sText);
2465                    mbox.setStandardButtons(QMessageBox::Cancel);
2466                    QCheckBox cbox(tr("Don't show this again"));
2467                    cbox.setChecked(false);
2468                    cbox.blockSignals(true);
2469                    mbox.addButton(&cbox, QMessageBox::ActionRole);
2470                    if (mbox.exec() && cbox.isChecked())
2471                            m_pOptions->bConfirmError = false;
2472            #endif
2473            }
2474  }  }
2475    
2476    
# Line 2171  void MainForm::updateMessagesCapture (vo Line 2533  void MainForm::updateMessagesCapture (vo
2533  // qsamplerMainForm -- MDI channel strip management.  // qsamplerMainForm -- MDI channel strip management.
2534    
2535  // The channel strip creation executive.  // The channel strip creation executive.
2536  ChannelStrip* MainForm::createChannelStrip(qsamplerChannel* pChannel)  ChannelStrip *MainForm::createChannelStrip ( Channel *pChannel )
2537  {  {
2538          if (m_pClient == NULL || pChannel == NULL)          if (m_pClient == NULL || pChannel == NULL)
2539                  return NULL;                  return NULL;
2540    
         // Prepare for auto-arrange?  
         ChannelStrip* pChannelStrip = NULL;  
         int y = 0;  
         if (m_pOptions && m_pOptions->bAutoArrange) {  
                 QWidgetList wlist = m_pWorkspace->windowList();  
                 for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {  
                         pChannelStrip = static_cast<ChannelStrip *> (wlist.at(iChannel));  
                         if (pChannelStrip) {  
                         //  y += pChannelStrip->height()  
                         //              + pChannelStrip->parentWidget()->baseSize().height();  
                                 y += pChannelStrip->parentWidget()->frameGeometry().height();  
                         }  
                 }  
         }  
   
2541          // Add a new channel itema...          // Add a new channel itema...
2542          pChannelStrip = new ChannelStrip();          ChannelStrip *pChannelStrip = new ChannelStrip();
2543          if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
2544                  return NULL;                  return NULL;
2545    
2546          m_pWorkspace->addWindow(pChannelStrip, Qt::FramelessWindowHint);          // Set some initial channel strip options...
   
         // Actual channel strip setup...  
         pChannelStrip->setup(pChannel);  
         QObject::connect(pChannelStrip,  
                 SIGNAL(channelChanged(ChannelStrip*)),  
                 SLOT(channelStripChanged(ChannelStrip*)));  
         // Set some initial aesthetic options...  
2547          if (m_pOptions) {          if (m_pOptions) {
2548                  // Background display effect...                  // Background display effect...
2549                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2550                  // We'll need a display font.                  // We'll need a display font.
2551                  QFont font;                  QFont font;
2552                  if (font.fromString(m_pOptions->sDisplayFont))                  if (!m_pOptions->sDisplayFont.isEmpty() &&
2553                            font.fromString(m_pOptions->sDisplayFont))
2554                          pChannelStrip->setDisplayFont(font);                          pChannelStrip->setDisplayFont(font);
2555                  // Maximum allowed volume setting.                  // Maximum allowed volume setting.
2556                  pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                  pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2557          }          }
2558    
2559            // Add it to workspace...
2560            m_pWorkspace->addSubWindow(pChannelStrip,
2561                    Qt::SubWindow | Qt::FramelessWindowHint);
2562    
2563            // Actual channel strip setup...
2564            pChannelStrip->setup(pChannel);
2565    
2566            QObject::connect(pChannelStrip,
2567                    SIGNAL(channelChanged(ChannelStrip *)),
2568                    SLOT(channelStripChanged(ChannelStrip *)));
2569    
2570          // Now we show up us to the world.          // Now we show up us to the world.
2571          pChannelStrip->show();          pChannelStrip->show();
         // Only then, we'll auto-arrange...  
         if (m_pOptions && m_pOptions->bAutoArrange) {  
                 int iWidth  = m_pWorkspace->width();  
         //  int iHeight = pChannel->height()  
         //              + pChannel->parentWidget()->baseSize().height();  
                 int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();  
                 pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);  
         }  
2572    
2573          // This is pretty new, so we'll watch for it closely.          // This is pretty new, so we'll watch for it closely.
2574          channelStripChanged(pChannelStrip);          channelStripChanged(pChannelStrip);
# Line 2234  ChannelStrip* MainForm::createChannelStr Line 2578  ChannelStrip* MainForm::createChannelStr
2578  }  }
2579    
2580    
2581    void MainForm::destroyChannelStrip ( ChannelStrip *pChannelStrip )
2582    {
2583            QMdiSubWindow *pMdiSubWindow
2584                    = static_cast<QMdiSubWindow *> (pChannelStrip->parentWidget());
2585            if (pMdiSubWindow == NULL)
2586                    return;
2587    
2588            // Just delete the channel strip.
2589            delete pChannelStrip;
2590            delete pMdiSubWindow;
2591    
2592            // Do we auto-arrange?
2593            if (m_pOptions && m_pOptions->bAutoArrange)
2594                    channelsArrange();
2595    }
2596    
2597    
2598  // Retrieve the active channel strip.  // Retrieve the active channel strip.
2599  ChannelStrip* MainForm::activeChannelStrip (void)  ChannelStrip *MainForm::activeChannelStrip (void)
2600  {  {
2601          return static_cast<ChannelStrip *> (m_pWorkspace->activeWindow());          QMdiSubWindow *pMdiSubWindow = m_pWorkspace->activeSubWindow();
2602            if (pMdiSubWindow)
2603                    return static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2604            else
2605                    return NULL;
2606  }  }
2607    
2608    
2609  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
2610  ChannelStrip* MainForm::channelStripAt ( int iChannel )  ChannelStrip *MainForm::channelStripAt ( int iStrip )
2611  {  {
2612          QWidgetList wlist = m_pWorkspace->windowList();          if (!m_pWorkspace) return NULL;
2613    
2614            const QList<QMdiSubWindow *>& wlist
2615                    = m_pWorkspace->subWindowList();
2616          if (wlist.isEmpty())          if (wlist.isEmpty())
2617                  return NULL;                  return NULL;
2618    
2619          return static_cast<ChannelStrip *> (wlist.at(iChannel));          if (iStrip < 0 || iStrip >= wlist.count())
2620                    return NULL;
2621    
2622            QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2623            if (pMdiSubWindow)
2624                    return static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2625            else
2626                    return NULL;
2627  }  }
2628    
2629    
2630  // Retrieve a channel strip by sampler channel id.  // Retrieve a channel strip by sampler channel id.
2631  ChannelStrip* MainForm::channelStrip ( int iChannelID )  ChannelStrip *MainForm::channelStrip ( int iChannelID )
2632  {  {
2633          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2634                    = m_pWorkspace->subWindowList();
2635          if (wlist.isEmpty())          if (wlist.isEmpty())
2636                  return NULL;                  return NULL;
2637    
2638          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          const int iStripCount = wlist.count();
2639                  ChannelStrip* pChannelStrip          for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
2640                          = static_cast<ChannelStrip*> (wlist.at(iChannel));                  ChannelStrip *pChannelStrip = NULL;
2641                    QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2642                    if (pMdiSubWindow)
2643                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2644                  if (pChannelStrip) {                  if (pChannelStrip) {
2645                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
2646                          if (pChannel && pChannel->channelID() == iChannelID)                          if (pChannel && pChannel->channelID() == iChannelID)
2647                                  return pChannelStrip;                                  return pChannelStrip;
2648                  }                  }
# Line 2281  void MainForm::channelsMenuAboutToShow ( Line 2660  void MainForm::channelsMenuAboutToShow (
2660          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);
2661          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);
2662    
2663          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2664                    = m_pWorkspace->subWindowList();
2665          if (!wlist.isEmpty()) {          if (!wlist.isEmpty()) {
2666                  m_ui.channelsMenu->addSeparator();                  m_ui.channelsMenu->addSeparator();
2667                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  const int iStripCount = wlist.count();
2668                          ChannelStrip* pChannelStrip                  for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
2669                                  = static_cast<ChannelStrip*> (wlist.at(iChannel));                          ChannelStrip *pChannelStrip = NULL;
2670                            QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2671                            if (pMdiSubWindow)
2672                                    pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2673                          if (pChannelStrip) {                          if (pChannelStrip) {
2674                                  QAction *pAction = m_ui.channelsMenu->addAction(                                  QAction *pAction = m_ui.channelsMenu->addAction(
2675                                          pChannelStrip->windowTitle(),                                          pChannelStrip->windowTitle(),
2676                                          this, SLOT(channelsMenuActivated()));                                          this, SLOT(channelsMenuActivated()));
2677                                  pAction->setCheckable(true);                                  pAction->setCheckable(true);
2678                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);
2679                                  pAction->setData(iChannel);                                  pAction->setData(iStrip);
2680                          }                          }
2681                  }                  }
2682          }          }
# Line 2308  void MainForm::channelsMenuActivated (vo Line 2691  void MainForm::channelsMenuActivated (vo
2691          if (pAction == NULL)          if (pAction == NULL)
2692                  return;                  return;
2693    
2694          ChannelStrip* pChannelStrip = channelStripAt(pAction->data().toInt());          ChannelStrip *pChannelStrip = channelStripAt(pAction->data().toInt());
2695          if (pChannelStrip) {          if (pChannelStrip) {
2696                  pChannelStrip->showNormal();                  pChannelStrip->showNormal();
2697                  pChannelStrip->setFocus();                  pChannelStrip->setFocus();
# Line 2358  void MainForm::timerSlot (void) Line 2741  void MainForm::timerSlot (void)
2741                          ChannelStrip *pChannelStrip = iter.next();                          ChannelStrip *pChannelStrip = iter.next();
2742                          // If successfull, remove from pending list...                          // If successfull, remove from pending list...
2743                          if (pChannelStrip->updateChannelInfo()) {                          if (pChannelStrip->updateChannelInfo()) {
2744                                  int iChannelStrip = m_changedStrips.indexOf(pChannelStrip);                                  const int iChannelStrip = m_changedStrips.indexOf(pChannelStrip);
2745                                  if (iChannelStrip >= 0)                                  if (iChannelStrip >= 0)
2746                                          m_changedStrips.removeAt(iChannelStrip);                                          m_changedStrips.removeAt(iChannelStrip);
2747                          }                          }
# Line 2369  void MainForm::timerSlot (void) Line 2752  void MainForm::timerSlot (void)
2752                          if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime)  {                          if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime)  {
2753                                  m_iTimerSlot = 0;                                  m_iTimerSlot = 0;
2754                                  // Update the channel stream usage for each strip...                                  // Update the channel stream usage for each strip...
2755                                  QWidgetList wlist = m_pWorkspace->windowList();                                  const QList<QMdiSubWindow *>& wlist
2756                                  for (int iChannel = 0;                                          = m_pWorkspace->subWindowList();
2757                                                  iChannel < (int) wlist.count(); iChannel++) {                                  const int iStripCount = wlist.count();
2758                                          ChannelStrip* pChannelStrip                                  for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
2759                                                  = (ChannelStrip*) wlist.at(iChannel);                                          ChannelStrip *pChannelStrip = NULL;
2760                                            QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2761                                            if (pMdiSubWindow)
2762                                                    pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2763                                          if (pChannelStrip && pChannelStrip->isVisible())                                          if (pChannelStrip && pChannelStrip->isVisible())
2764                                                  pChannelStrip->updateChannelUsage();                                                  pChannelStrip->updateChannelUsage();
2765                                  }                                  }
# Line 2401  void MainForm::startServer (void) Line 2787  void MainForm::startServer (void)
2787    
2788          // Is the server process instance still here?          // Is the server process instance still here?
2789          if (m_pServer) {          if (m_pServer) {
2790                  switch (QMessageBox::warning(this,                  if (QMessageBox::warning(this,
2791                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
2792                          tr("Could not start the LinuxSampler server.\n\n"                          tr("Could not start the LinuxSampler server.\n\n"
2793                          "Maybe it ss already started."),                          "Maybe it is already started."),
2794                          tr("Stop"), tr("Kill"), tr("Cancel"))) {                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
                 case 0:  
2795                          m_pServer->terminate();                          m_pServer->terminate();
                         break;  
                 case 1:  
2796                          m_pServer->kill();                          m_pServer->kill();
                         break;  
2797                  }                  }
2798                  return;                  return;
2799          }          }
# Line 2424  void MainForm::startServer (void) Line 2806  void MainForm::startServer (void)
2806                  return;                  return;
2807    
2808          // OK. Let's build the startup process...          // OK. Let's build the startup process...
2809          m_pServer = new QProcess(this);          m_pServer = new QProcess();
2810            bForceServerStop = true;
2811    
2812          // Setup stdout/stderr capture...          // Setup stdout/stderr capture...
2813  //      if (m_pOptions->bStdoutCapture) {          m_pServer->setProcessChannelMode(QProcess::ForwardedChannels);
2814                  //m_pServer->setProcessChannelMode(          QObject::connect(m_pServer,
2815                  //      QProcess::StandardOutput);                  SIGNAL(readyReadStandardOutput()),
2816                  QObject::connect(m_pServer,                  SLOT(readServerStdout()));
2817                          SIGNAL(readyReadStandardOutput()),          QObject::connect(m_pServer,
2818                          SLOT(readServerStdout()));                  SIGNAL(readyReadStandardError()),
2819                  QObject::connect(m_pServer,                  SLOT(readServerStdout()));
                         SIGNAL(readyReadStandardError()),  
                         SLOT(readServerStdout()));  
 //      }  
2820    
2821          // The unforgiveable signal communication...          // The unforgiveable signal communication...
2822          QObject::connect(m_pServer,          QObject::connect(m_pServer,
2823                  SIGNAL(finished(int,QProcess::ExitStatus)),                  SIGNAL(finished(int, QProcess::ExitStatus)),
2824                  SLOT(processServerExit()));                  SLOT(processServerExit()));
2825    
2826          // Build process arguments...          // Build process arguments...
# Line 2471  void MainForm::startServer (void) Line 2851  void MainForm::startServer (void)
2851    
2852    
2853  // Stop linuxsampler server...  // Stop linuxsampler server...
2854  void MainForm::stopServer (void)  void MainForm::stopServer (bool bInteractive)
2855  {  {
2856          // Stop client code.          // Stop client code.
2857          stopClient();          stopClient();
2858    
2859            if (m_pServer && bInteractive) {
2860                    if (QMessageBox::question(this,
2861                            QSAMPLER_TITLE ": " + tr("The backend's fate ..."),
2862                            tr("You have the option to keep the sampler backend (LinuxSampler)\n"
2863                            "running in the background. The sampler would continue to work\n"
2864                            "according to your current sampler session and you could alter the\n"
2865                            "sampler session at any time by relaunching QSampler.\n\n"
2866                            "Do you want LinuxSampler to stop?"),
2867                            QMessageBox::Yes | QMessageBox::No,
2868                            QMessageBox::Yes) == QMessageBox::No)
2869                    {
2870                            bForceServerStop = false;
2871                    }
2872            }
2873    
2874          // And try to stop server.          // And try to stop server.
2875          if (m_pServer) {          if (m_pServer && bForceServerStop) {
2876                  appendMessages(tr("Server is stopping..."));                  appendMessages(tr("Server is stopping..."));
2877                  if (m_pServer->state() == QProcess::Running)                  if (m_pServer->state() == QProcess::Running) {
2878                    #if defined(WIN32)
2879                            // Try harder...
2880                            m_pServer->kill();
2881                    #else
2882                            // Try softly...
2883                          m_pServer->terminate();                          m_pServer->terminate();
2884          }                  #endif
2885                    }
2886            }       // Do final processing anyway.
2887            else processServerExit();
2888    
2889          // Give it some time to terminate gracefully and stabilize...          // Give it some time to terminate gracefully and stabilize...
2890          QTime t;          QTime t;
2891          t.start();          t.start();
2892          while (t.elapsed() < QSAMPLER_TIMER_MSECS)          while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2893                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
   
         // Do final processing anyway.  
         processServerExit();  
2894  }  }
2895    
2896    
# Line 2512  void MainForm::processServerExit (void) Line 2912  void MainForm::processServerExit (void)
2912          if (m_pMessages)          if (m_pMessages)
2913                  m_pMessages->flushStdoutBuffer();                  m_pMessages->flushStdoutBuffer();
2914    
2915          if (m_pServer) {          if (m_pServer && bForceServerStop) {
2916                    if (m_pServer->state() != QProcess::NotRunning) {
2917                            appendMessages(tr("Server is being forced..."));
2918                            // Force final server shutdown...
2919                            m_pServer->kill();
2920                            // Give it some time to terminate gracefully and stabilize...
2921                            QTime t;
2922                            t.start();
2923                            while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2924                                    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2925                    }
2926                  // Force final server shutdown...                  // Force final server shutdown...
2927                  appendMessages(                  appendMessages(
2928                          tr("Server was stopped with exit status %1.")                          tr("Server was stopped with exit status %1.")
2929                          .arg(m_pServer->exitStatus()));                          .arg(m_pServer->exitStatus()));
                 m_pServer->terminate();  
                 if (!m_pServer->waitForFinished(2000))  
                         m_pServer->kill();  
                 // Destroy it.  
2930                  delete m_pServer;                  delete m_pServer;
2931                  m_pServer = NULL;                  m_pServer = NULL;
2932          }          }
# Line 2545  lscp_status_t qsampler_client_callback ( Line 2951  lscp_status_t qsampler_client_callback (
2951          // as this is run under some other thread context.          // as this is run under some other thread context.
2952          // A custom event must be posted here...          // A custom event must be posted here...
2953          QApplication::postEvent(pMainForm,          QApplication::postEvent(pMainForm,
2954                  new qsamplerCustomEvent(event, pchData, cchData));                  new LscpEvent(event, pchData, cchData));
2955    
2956          return LSCP_OK;          return LSCP_OK;
2957  }  }
# Line 2590  bool MainForm::startClient (void) Line 2996  bool MainForm::startClient (void)
2996                  .arg(::lscp_client_get_timeout(m_pClient)));                  .arg(::lscp_client_get_timeout(m_pClient)));
2997    
2998          // Subscribe to channel info change notifications...          // Subscribe to channel info change notifications...
2999            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT) != LSCP_OK)
3000                    appendMessagesClient("lscp_client_subscribe(CHANNEL_COUNT)");
3001          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)
3002                  appendMessagesClient("lscp_client_subscribe");                  appendMessagesClient("lscp_client_subscribe(CHANNEL_INFO)");
3003    
3004            DeviceStatusForm::onDevicesChanged(); // initialize
3005            updateViewMidiDeviceStatusMenu();
3006            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT) != LSCP_OK)
3007                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_COUNT)");
3008            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO) != LSCP_OK)
3009                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_INFO)");
3010            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT) != LSCP_OK)
3011                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_COUNT)");
3012            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO) != LSCP_OK)
3013                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_INFO)");
3014    
3015    #if CONFIG_EVENT_CHANNEL_MIDI
3016            // Subscribe to channel MIDI data notifications...
3017            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI) != LSCP_OK)
3018                    appendMessagesClient("lscp_client_subscribe(CHANNEL_MIDI)");
3019    #endif
3020    
3021    #if CONFIG_EVENT_DEVICE_MIDI
3022            // Subscribe to channel MIDI data notifications...
3023            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI) != LSCP_OK)
3024                    appendMessagesClient("lscp_client_subscribe(DEVICE_MIDI)");
3025    #endif
3026    
3027          // We may stop scheduling around.          // We may stop scheduling around.
3028          stopSchedule();          stopSchedule();
# Line 2618  bool MainForm::startClient (void) Line 3049  bool MainForm::startClient (void)
3049                  }                  }
3050          }          }
3051    
3052            // send the current / loaded fine tuning settings to the sampler
3053            m_pOptions->sendFineTuningSettings();
3054    
3055          // Make a new session          // Make a new session
3056          return newSession();          return newSession();
3057  }  }
# Line 2645  void MainForm::stopClient (void) Line 3079  void MainForm::stopClient (void)
3079          closeSession(false);          closeSession(false);
3080    
3081          // Close us as a client...          // Close us as a client...
3082    #if CONFIG_EVENT_DEVICE_MIDI
3083            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI);
3084    #endif
3085    #if CONFIG_EVENT_CHANNEL_MIDI
3086            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI);
3087    #endif
3088            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
3089            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
3090            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
3091            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
3092          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
3093            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT);
3094          ::lscp_client_destroy(m_pClient);          ::lscp_client_destroy(m_pClient);
3095          m_pClient = NULL;          m_pClient = NULL;
3096    
# Line 2665  void MainForm::stopClient (void) Line 3110  void MainForm::stopClient (void)
3110    
3111    
3112  // Channel strip activation/selection.  // Channel strip activation/selection.
3113  void MainForm::activateStrip ( QWidget *pWidget )  void MainForm::activateStrip ( QMdiSubWindow *pMdiSubWindow )
3114  {  {
3115          ChannelStrip *pChannelStrip          ChannelStrip *pChannelStrip = NULL;
3116                  = static_cast<ChannelStrip *> (pWidget);          if (pMdiSubWindow)
3117                    pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
3118          if (pChannelStrip)          if (pChannelStrip)
3119                  pChannelStrip->setSelected(true);                  pChannelStrip->setSelected(true);
3120    
# Line 2676  void MainForm::activateStrip ( QWidget * Line 3122  void MainForm::activateStrip ( QWidget *
3122  }  }
3123    
3124    
3125    // Channel toolbar orientation change.
3126    void MainForm::channelsToolbarOrientation ( Qt::Orientation orientation )
3127    {
3128    #ifdef CONFIG_VOLUME
3129            m_pVolumeSlider->setOrientation(orientation);
3130            if (orientation == Qt::Horizontal) {
3131                    m_pVolumeSlider->setMinimumHeight(24);
3132                    m_pVolumeSlider->setMaximumHeight(32);
3133                    m_pVolumeSlider->setMinimumWidth(120);
3134                    m_pVolumeSlider->setMaximumWidth(640);
3135                    m_pVolumeSpinBox->setMaximumWidth(64);
3136                    m_pVolumeSpinBox->setButtonSymbols(QSpinBox::UpDownArrows);
3137            } else {
3138                    m_pVolumeSlider->setMinimumHeight(120);
3139                    m_pVolumeSlider->setMaximumHeight(480);
3140                    m_pVolumeSlider->setMinimumWidth(24);
3141                    m_pVolumeSlider->setMaximumWidth(32);
3142                    m_pVolumeSpinBox->setMaximumWidth(32);
3143                    m_pVolumeSpinBox->setButtonSymbols(QSpinBox::NoButtons);
3144            }
3145    #endif
3146    }
3147    
3148    
3149  } // namespace QSampler  } // namespace QSampler
3150    
3151    

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

  ViewVC Help
Powered by ViewVC