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

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

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

revision 1515 by capela, Fri Nov 23 18:15:33 2007 UTC revision 2144 by persson, Wed Oct 6 18:49:54 2010 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-2010, rncbc aka Rui Nuno Capela. All rights reserved.
5     Copyright (C) 2007, Christian Schoenebeck     Copyright (C) 2007, 2008 Christian Schoenebeck
6    
7     This program is free software; you can redistribute it and/or     This program is free software; you can redistribute it and/or
8     modify it under the terms of the GNU General Public License     modify it under the terms of the GNU General Public License
# Line 33  Line 33 
33  #include "qsamplerInstrumentListForm.h"  #include "qsamplerInstrumentListForm.h"
34  #include "qsamplerDeviceForm.h"  #include "qsamplerDeviceForm.h"
35  #include "qsamplerOptionsForm.h"  #include "qsamplerOptionsForm.h"
36    #include "qsamplerDeviceStatusForm.h"
37    
38  #include <QApplication>  #include <QApplication>
39  #include <QWorkspace>  #include <QWorkspace>
# Line 55  Line 56 
56  #include <QTimer>  #include <QTimer>
57  #include <QDateTime>  #include <QDateTime>
58    
59    #if QT_VERSION < 0x040500
60    namespace Qt {
61    const WindowFlags WindowCloseButtonHint = WindowFlags(0x08000000);
62    #if QT_VERSION < 0x040200
63    const WindowFlags CustomizeWindowHint   = WindowFlags(0x02000000);
64    #endif
65    }
66    #endif
67    
68  #ifdef HAVE_SIGNAL_H  #ifdef HAVE_SIGNAL_H
69  #include <signal.h>  #include <signal.h>
# Line 77  static inline long lroundf ( float x ) Line 86  static inline long lroundf ( float x )
86  }  }
87  #endif  #endif
88    
89    
90    // All winsock apps needs this.
91    #if defined(WIN32)
92    static WSADATA _wsaData;
93    #endif
94    
95    
96    //-------------------------------------------------------------------------
97    // LADISH Level 1 support stuff.
98    
99    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
100    
101    #include <QSocketNotifier>
102    
103    #include <sys/types.h>
104    #include <sys/socket.h>
105    
106    #include <signal.h>
107    
108    // File descriptor for SIGUSR1 notifier.
109    static int g_fdUsr1[2];
110    
111    // Unix SIGUSR1 signal handler.
112    static void qsampler_sigusr1_handler ( int /* signo */ )
113    {
114            char c = 1;
115    
116            (::write(g_fdUsr1[0], &c, sizeof(c)) > 0);
117    }
118    
119    #endif  // HAVE_SIGNAL_H
120    
121    
122    //-------------------------------------------------------------------------
123    // qsampler -- namespace
124    
125    
126    namespace QSampler {
127    
128  // Timer constant stuff.  // Timer constant stuff.
129  #define QSAMPLER_TIMER_MSECS    200  #define QSAMPLER_TIMER_MSECS    200
130    
# Line 87  static inline long lroundf ( float x ) Line 135  static inline long lroundf ( float x )
135  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.
136    
137    
138  // All winsock apps needs this.  // Specialties for thread-callback comunication.
139  #if defined(WIN32)  #define QSAMPLER_LSCP_EVENT   QEvent::Type(QEvent::User + 1)
 static WSADATA _wsaData;  
 #endif  
140    
141    
142  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
143  // qsamplerCustomEvent -- specialty for callback comunication.  // LscpEvent -- specialty for LSCP callback comunication.
144    
 #define QSAMPLER_CUSTOM_EVENT   QEvent::Type(QEvent::User + 0)  
145    
146  class qsamplerCustomEvent : public QEvent  class LscpEvent : public QEvent
147  {  {
148  public:  public:
149    
150          // Constructor.          // Constructor.
151          qsamplerCustomEvent(lscp_event_t event, const char *pchData, int cchData)          LscpEvent(lscp_event_t event, const char *pchData, int cchData)
152                  : QEvent(QSAMPLER_CUSTOM_EVENT)                  : QEvent(QSAMPLER_LSCP_EVENT)
153          {          {
154                  m_event = event;                  m_event = event;
155                  m_data  = QString::fromUtf8(pchData, cchData);                  m_data  = QString::fromUtf8(pchData, cchData);
# Line 126  private: Line 171  private:
171  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
172  // qsamplerMainForm -- Main window form implementation.  // qsamplerMainForm -- Main window form implementation.
173    
 namespace QSampler {  
   
174  // Kind of singleton reference.  // Kind of singleton reference.
175  MainForm* MainForm::g_pMainForm = NULL;  MainForm* MainForm::g_pMainForm = NULL;
176    
# Line 159  MainForm::MainForm ( QWidget *pParent ) Line 202  MainForm::MainForm ( QWidget *pParent )
202    
203          m_iTimerSlot = 0;          m_iTimerSlot = 0;
204    
205  #ifdef HAVE_SIGNAL_H  #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
206    
207          // Set to ignore any fatal "Broken pipe" signals.          // Set to ignore any fatal "Broken pipe" signals.
208          ::signal(SIGPIPE, SIG_IGN);          ::signal(SIGPIPE, SIG_IGN);
209  #endif  
210            // LADISH Level 1 suport.
211    
212            // Initialize file descriptors for SIGUSR1 socket notifier.
213            ::socketpair(AF_UNIX, SOCK_STREAM, 0, g_fdUsr1);
214            m_pUsr1Notifier
215                    = new QSocketNotifier(g_fdUsr1[1], QSocketNotifier::Read, this);
216    
217            QObject::connect(m_pUsr1Notifier,
218                    SIGNAL(activated(int)),
219                    SLOT(handle_sigusr1()));
220    
221            // Install SIGUSR1 signal handler.
222        struct sigaction usr1;
223        usr1.sa_handler = qsampler_sigusr1_handler;
224        ::sigemptyset(&usr1.sa_mask);
225        usr1.sa_flags = 0;
226        usr1.sa_flags |= SA_RESTART;
227        ::sigaction(SIGUSR1, &usr1, NULL);
228    
229    #else   // HAVE_SIGNAL_H
230    
231            m_pUsr1Notifier = NULL;
232            
233    #endif  // !HAVE_SIGNAL_H
234    
235  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
236          // Make some extras into the toolbar...          // Make some extras into the toolbar...
# Line 335  MainForm::~MainForm() Line 403  MainForm::~MainForm()
403          WSACleanup();          WSACleanup();
404  #endif  #endif
405    
406    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
407            if (m_pUsr1Notifier)
408                    delete m_pUsr1Notifier;
409    #endif
410    
411          // Finally drop any widgets around...          // Finally drop any widgets around...
412          if (m_pDeviceForm)          if (m_pDeviceForm)
413                  delete m_pDeviceForm;                  delete m_pDeviceForm;
# Line 366  MainForm::~MainForm() Line 439  MainForm::~MainForm()
439    
440    
441  // Make and set a proper setup options step.  // Make and set a proper setup options step.
442  void MainForm::setup ( qsamplerOptions *pOptions )  void MainForm::setup ( Options *pOptions )
443  {  {
444          // We got options?          // We got options?
445          m_pOptions = pOptions;          m_pOptions = pOptions;
446    
447          // What style do we create these forms?          // What style do we create these forms?
448          Qt::WindowFlags wflags = Qt::Window          Qt::WindowFlags wflags = Qt::Window
 #if QT_VERSION >= 0x040200  
449                  | Qt::CustomizeWindowHint                  | Qt::CustomizeWindowHint
 #endif  
450                  | Qt::WindowTitleHint                  | Qt::WindowTitleHint
451                  | Qt::WindowSystemMenuHint                  | Qt::WindowSystemMenuHint
452                  | Qt::WindowMinMaxButtonsHint;                  | Qt::WindowMinMaxButtonsHint
453                    | Qt::WindowCloseButtonHint;
454          if (m_pOptions->bKeepOnTop)          if (m_pOptions->bKeepOnTop)
455                  wflags |= Qt::Tool;                  wflags |= Qt::Tool;
456    
457          // Some child forms are to be created right now.          // Some child forms are to be created right now.
458          m_pMessages = new qsamplerMessages(this);          m_pMessages = new Messages(this);
459          m_pDeviceForm = new DeviceForm(this, wflags);          m_pDeviceForm = new DeviceForm(this, wflags);
460  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
461          m_pInstrumentListForm = new InstrumentListForm(this, wflags);          m_pInstrumentListForm = new InstrumentListForm(this, wflags);
462  #else  #else
463          viewInstrumentsAction->setEnabled(false);          m_ui.viewInstrumentsAction->setEnabled(false);
464  #endif  #endif
465    
466            // Setup messages logging appropriately...
467            m_pMessages->setLogging(
468                    m_pOptions->bMessagesLog,
469                    m_pOptions->sMessagesLogPath);
470    
471          // Set message defaults...          // Set message defaults...
472          updateMessagesFont();          updateMessagesFont();
473          updateMessagesLimit();          updateMessagesLimit();
# Line 419  void MainForm::setup ( qsamplerOptions * Line 498  void MainForm::setup ( qsamplerOptions *
498          }          }
499    
500          // Try to restore old window positioning and initial visibility.          // Try to restore old window positioning and initial visibility.
501          m_pOptions->loadWidgetGeometry(this);          m_pOptions->loadWidgetGeometry(this, true);
502          m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);          m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);
503          m_pOptions->loadWidgetGeometry(m_pDeviceForm);          m_pOptions->loadWidgetGeometry(m_pDeviceForm);
504    
# Line 463  bool MainForm::queryClose (void) Line 542  bool MainForm::queryClose (void)
542                          // And the children, and the main windows state,.                          // And the children, and the main windows state,.
543                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);
544                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);
545                          m_pOptions->saveWidgetGeometry(this);                          m_pOptions->saveWidgetGeometry(this, true);
546                          // Close popup widgets.                          // Close popup widgets.
547                          if (m_pInstrumentListForm)                          if (m_pInstrumentListForm)
548                                  m_pInstrumentListForm->close();                                  m_pInstrumentListForm->close();
549                          if (m_pDeviceForm)                          if (m_pDeviceForm)
550                                  m_pDeviceForm->close();                                  m_pDeviceForm->close();
551                          // Stop client and/or server, gracefully.                          // Stop client and/or server, gracefully.
552                          stopServer();                          stopServer(true /*interactive*/);
553                  }                  }
554          }          }
555    
# Line 480  bool MainForm::queryClose (void) Line 559  bool MainForm::queryClose (void)
559    
560  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )
561  {  {
562          if (queryClose())          if (queryClose()) {
563                    DeviceStatusForm::deleteAllInstances();
564                  pCloseEvent->accept();                  pCloseEvent->accept();
565          else          } else
566                  pCloseEvent->ignore();                  pCloseEvent->ignore();
567  }  }
568    
# Line 511  void MainForm::dropEvent ( QDropEvent* p Line 591  void MainForm::dropEvent ( QDropEvent* p
591                  QListIterator<QUrl> iter(pMimeData->urls());                  QListIterator<QUrl> iter(pMimeData->urls());
592                  while (iter.hasNext()) {                  while (iter.hasNext()) {
593                          const QString& sPath = iter.next().toLocalFile();                          const QString& sPath = iter.next().toLocalFile();
594                          if (qsamplerChannel::isInstrumentFile(sPath)) {                  //      if (Channel::isDlsInstrumentFile(sPath)) {
595                            if (QFileInfo(sPath).exists()) {
596                                  // Try to create a new channel from instrument file...                                  // Try to create a new channel from instrument file...
597                                  qsamplerChannel *pChannel = new qsamplerChannel();                                  Channel *pChannel = new Channel();
598                                  if (pChannel == NULL)                                  if (pChannel == NULL)
599                                          return;                                          return;
600                                  // Start setting the instrument filename...                                  // Start setting the instrument filename...
# Line 545  void MainForm::dropEvent ( QDropEvent* p Line 626  void MainForm::dropEvent ( QDropEvent* p
626    
627    
628  // Custome event handler.  // Custome event handler.
629  void MainForm::customEvent(QEvent* pCustomEvent)  void MainForm::customEvent ( QEvent* pEvent )
630  {  {
631          // For the time being, just pump it to messages.          // For the time being, just pump it to messages.
632          if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {          if (pEvent->type() == QSAMPLER_LSCP_EVENT) {
633                  qsamplerCustomEvent *pEvent = (qsamplerCustomEvent *) pCustomEvent;                  LscpEvent *pLscpEvent = static_cast<LscpEvent *> (pEvent);
634                  if (pEvent->event() == LSCP_EVENT_CHANNEL_INFO) {                  switch (pLscpEvent->event()) {
635                          int iChannelID = pEvent->data().toInt();                          case LSCP_EVENT_CHANNEL_COUNT:
636                          ChannelStrip *pChannelStrip = channelStrip(iChannelID);                                  updateAllChannelStrips(true);
637                          if (pChannelStrip)                                  break;
638                                  channelStripChanged(pChannelStrip);                          case LSCP_EVENT_CHANNEL_INFO: {
639                  } else {                                  int iChannelID = pLscpEvent->data().toInt();
640                          appendMessagesColor(tr("Notify event: %1 data: %2")                                  ChannelStrip *pChannelStrip = channelStrip(iChannelID);
641                                  .arg(::lscp_event_to_text(pEvent->event()))                                  if (pChannelStrip)
642                                  .arg(pEvent->data()), "#996699");                                          channelStripChanged(pChannelStrip);
643                                    break;
644                            }
645                            case LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT:
646                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
647                                    DeviceStatusForm::onDevicesChanged();
648                                    updateViewMidiDeviceStatusMenu();
649                                    break;
650                            case LSCP_EVENT_MIDI_INPUT_DEVICE_INFO: {
651                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
652                                    const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt();
653                                    DeviceStatusForm::onDeviceChanged(iDeviceID);
654                                    break;
655                            }
656                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT:
657                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
658                                    break;
659                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO:
660                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
661                                    break;
662                    #if CONFIG_EVENT_CHANNEL_MIDI
663                            case LSCP_EVENT_CHANNEL_MIDI: {
664                                    const int iChannelID = pLscpEvent->data().section(' ', 0, 0).toInt();
665                                    ChannelStrip *pChannelStrip = channelStrip(iChannelID);
666                                    if (pChannelStrip)
667                                            pChannelStrip->midiActivityLedOn();
668                                    break;
669                            }
670                    #endif
671                    #if CONFIG_EVENT_DEVICE_MIDI
672                            case LSCP_EVENT_DEVICE_MIDI: {
673                                    const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt();
674                                    const int iPortID   = pLscpEvent->data().section(' ', 1, 1).toInt();
675                                    DeviceStatusForm *pDeviceStatusForm
676                                            = DeviceStatusForm::getInstance(iDeviceID);
677                                    if (pDeviceStatusForm)
678                                            pDeviceStatusForm->midiArrived(iPortID);
679                                    break;
680                            }
681                    #endif
682                            default:
683                                    appendMessagesColor(tr("LSCP Event: %1 data: %2")
684                                            .arg(::lscp_event_to_text(pLscpEvent->event()))
685                                            .arg(pLscpEvent->data()), "#996699");
686                  }                  }
687          }          }
688  }  }
689    
690    
691    // LADISH Level 1 -- SIGUSR1 signal handler.
692    void MainForm::handle_sigusr1 (void)
693    {
694    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
695    
696            char c;
697    
698            if (::read(g_fdUsr1[1], &c, sizeof(c)) > 0)
699                    saveSession(false);
700    
701    #endif
702    }
703    
704    
705    void MainForm::updateViewMidiDeviceStatusMenu (void)
706    {
707            m_ui.viewMidiDeviceStatusMenu->clear();
708            const std::map<int, DeviceStatusForm *> statusForms
709                    = DeviceStatusForm::getInstances();
710            std::map<int, DeviceStatusForm *>::const_iterator iter
711                    = statusForms.begin();
712            for ( ; iter != statusForms.end(); ++iter) {
713                    DeviceStatusForm *pStatusForm = iter->second;
714                    m_ui.viewMidiDeviceStatusMenu->addAction(
715                            pStatusForm->visibleAction());
716            }
717    }
718    
719    
720  // Context menu event handler.  // Context menu event handler.
721  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )
722  {  {
# Line 576  void MainForm::contextMenuEvent( QContex Line 730  void MainForm::contextMenuEvent( QContex
730  // qsamplerMainForm -- Brainless public property accessors.  // qsamplerMainForm -- Brainless public property accessors.
731    
732  // The global options settings property.  // The global options settings property.
733  qsamplerOptions *MainForm::options (void) const  Options *MainForm::options (void) const
734  {  {
735          return m_pOptions;          return m_pOptions;
736  }  }
# Line 694  bool MainForm::saveSession ( bool bPromp Line 848  bool MainForm::saveSession ( bool bPromp
848                                  "\"%1\"\n\n"                                  "\"%1\"\n\n"
849                                  "Do you want to replace it?")                                  "Do you want to replace it?")
850                                  .arg(sFilename),                                  .arg(sFilename),
851                                  tr("Replace"), tr("Cancel")) > 0)                                  QMessageBox::Yes | QMessageBox::No)
852                                    == QMessageBox::No)
853                                  return false;                                  return false;
854                  }                  }
855          }          }
# Line 717  bool MainForm::closeSession ( bool bForc Line 872  bool MainForm::closeSession ( bool bForc
872                          "\"%1\"\n\n"                          "\"%1\"\n\n"
873                          "Do you want to save the changes?")                          "Do you want to save the changes?")
874                          .arg(sessionName(m_sFilename)),                          .arg(sessionName(m_sFilename)),
875                          tr("Save"), tr("Discard"), tr("Cancel"))) {                          QMessageBox::Save |
876                  case 0:     // Save...                          QMessageBox::Discard |
877                            QMessageBox::Cancel)) {
878                    case QMessageBox::Save:
879                          bClose = saveSession(false);                          bClose = saveSession(false);
880                          // Fall thru....                          // Fall thru....
881                  case 1:     // Discard                  case QMessageBox::Discard:
882                          break;                          break;
883                  default:    // Cancel.                  default:    // Cancel.
884                          bClose = false;                          bClose = false;
# Line 737  bool MainForm::closeSession ( bool bForc Line 894  bool MainForm::closeSession ( bool bForc
894                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
895                          ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                          ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
896                          if (pChannelStrip) {                          if (pChannelStrip) {
897                                  qsamplerChannel *pChannel = pChannelStrip->channel();                                  Channel *pChannel = pChannelStrip->channel();
898                                  if (bForce && pChannel)                                  if (bForce && pChannel)
899                                          pChannel->removeChannel();                                          pChannel->removeChannel();
900                                  delete pChannelStrip;                                  delete pChannelStrip;
# Line 877  bool MainForm::saveSessionFile ( const Q Line 1034  bool MainForm::saveSessionFile ( const Q
1034    
1035          // Audio device mapping.          // Audio device mapping.
1036          QMap<int, int> audioDeviceMap;          QMap<int, int> audioDeviceMap;
1037          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Audio);          piDeviceIDs = Device::getDevices(m_pClient, Device::Audio);
1038          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
1039                  ts << endl;                  ts << endl;
1040                  qsamplerDevice device(qsamplerDevice::Audio, piDeviceIDs[iDevice]);                  Device device(Device::Audio, piDeviceIDs[iDevice]);
1041                  // Audio device specification...                  // Audio device specification...
1042                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1043                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1044                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();
1045                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
1046                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
1047                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
1048                                          ++deviceParam) {                                          ++deviceParam) {
1049                          const qsamplerDeviceParam& param = deviceParam.value();                          const DeviceParam& param = deviceParam.value();
1050                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
1051                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
1052                  }                  }
1053                  ts << endl;                  ts << endl;
1054                  // Audio channel parameters...                  // Audio channel parameters...
1055                  int iPort = 0;                  int iPort = 0;
1056                  QListIterator<qsamplerDevicePort *> iter(device.ports());                  QListIterator<DevicePort *> iter(device.ports());
1057                  while (iter.hasNext()) {                  while (iter.hasNext()) {
1058                          qsamplerDevicePort *pPort = iter.next();                          DevicePort *pPort = iter.next();
1059                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1060                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1061                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1062                                                  ++portParam) {                                                  ++portParam) {
1063                                  const qsamplerDeviceParam& param = portParam.value();                                  const DeviceParam& param = portParam.value();
1064                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1065                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice
1066                                          << " " << iPort << " " << portParam.key()                                          << " " << iPort << " " << portParam.key()
# Line 919  bool MainForm::saveSessionFile ( const Q Line 1076  bool MainForm::saveSessionFile ( const Q
1076    
1077          // MIDI device mapping.          // MIDI device mapping.
1078          QMap<int, int> midiDeviceMap;          QMap<int, int> midiDeviceMap;
1079          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Midi);          piDeviceIDs = Device::getDevices(m_pClient, Device::Midi);
1080          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
1081                  ts << endl;                  ts << endl;
1082                  qsamplerDevice device(qsamplerDevice::Midi, piDeviceIDs[iDevice]);                  Device device(Device::Midi, piDeviceIDs[iDevice]);
1083                  // MIDI device specification...                  // MIDI device specification...
1084                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1085                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1086                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();
1087                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
1088                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
1089                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
1090                                          ++deviceParam) {                                          ++deviceParam) {
1091                          const qsamplerDeviceParam& param = deviceParam.value();                          const DeviceParam& param = deviceParam.value();
1092                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
1093                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
1094                  }                  }
1095                  ts << endl;                  ts << endl;
1096                  // MIDI port parameters...                  // MIDI port parameters...
1097                  int iPort = 0;                  int iPort = 0;
1098                  QListIterator<qsamplerDevicePort *> iter(device.ports());                  QListIterator<DevicePort *> iter(device.ports());
1099                  while (iter.hasNext()) {                  while (iter.hasNext()) {
1100                          qsamplerDevicePort *pPort = iter.next();                          DevicePort *pPort = iter.next();
1101                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1102                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1103                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1104                                                  ++portParam) {                                                  ++portParam) {
1105                                  const qsamplerDeviceParam& param = portParam.value();                                  const DeviceParam& param = portParam.value();
1106                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1107                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice
1108                                  << " " << iPort << " " << portParam.key()                                  << " " << iPort << " " << portParam.key()
# Line 1037  bool MainForm::saveSessionFile ( const Q Line 1194  bool MainForm::saveSessionFile ( const Q
1194                  ChannelStrip* pChannelStrip                  ChannelStrip* pChannelStrip
1195                          = static_cast<ChannelStrip *> (wlist.at(iChannel));                          = static_cast<ChannelStrip *> (wlist.at(iChannel));
1196                  if (pChannelStrip) {                  if (pChannelStrip) {
1197                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
1198                          if (pChannel) {                          if (pChannel) {
1199                                  ts << "# " << tr("Channel") << " " << iChannel << endl;                                  ts << "# " << tr("Channel") << " " << iChannel << endl;
1200                                  ts << "ADD CHANNEL" << endl;                                  ts << "ADD CHANNEL" << endl;
# Line 1069  bool MainForm::saveSessionFile ( const Q Line 1226  bool MainForm::saveSessionFile ( const Q
1226                                  ts << "LOAD INSTRUMENT NON_MODAL '"                                  ts << "LOAD INSTRUMENT NON_MODAL '"
1227                                          << pChannel->instrumentFile() << "' "                                          << pChannel->instrumentFile() << "' "
1228                                          << pChannel->instrumentNr() << " " << iChannel << endl;                                          << pChannel->instrumentNr() << " " << iChannel << endl;
1229                                  qsamplerChannelRoutingMap::ConstIterator audioRoute;                                  ChannelRoutingMap::ConstIterator audioRoute;
1230                                  for (audioRoute = pChannel->audioRouting().begin();                                  for (audioRoute = pChannel->audioRouting().begin();
1231                                                  audioRoute != pChannel->audioRouting().end();                                                  audioRoute != pChannel->audioRouting().end();
1232                                                          ++audioRoute) {                                                          ++audioRoute) {
# Line 1242  void MainForm::fileReset (void) Line 1399  void MainForm::fileReset (void)
1399                  "Please note that this operation may cause\n"                  "Please note that this operation may cause\n"
1400                  "temporary MIDI and Audio disruption.\n\n"                  "temporary MIDI and Audio disruption.\n\n"
1401                  "Do you want to reset the sampler engine now?"),                  "Do you want to reset the sampler engine now?"),
1402                  tr("Reset"), tr("Cancel")) > 0)                  QMessageBox::Ok | QMessageBox::Cancel)
1403                    == QMessageBox::Cancel)
1404                  return;                  return;
1405    
1406          // Trye closing the current session, first...          // Trye closing the current session, first...
# Line 1283  void MainForm::fileRestart (void) Line 1441  void MainForm::fileRestart (void)
1441                          "Please note that this operation may cause\n"                          "Please note that this operation may cause\n"
1442                          "temporary MIDI and Audio disruption.\n\n"                          "temporary MIDI and Audio disruption.\n\n"
1443                          "Do you want to restart the connection now?"),                          "Do you want to restart the connection now?"),
1444                          tr("Restart"), tr("Cancel")) == 0);                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok);
1445          }          }
1446    
1447          // Are we still for it?          // Are we still for it?
# Line 1314  void MainForm::editAddChannel (void) Line 1472  void MainForm::editAddChannel (void)
1472                  return;                  return;
1473    
1474          // Just create the channel instance...          // Just create the channel instance...
1475          qsamplerChannel *pChannel = new qsamplerChannel();          Channel *pChannel = new Channel();
1476          if (pChannel == NULL)          if (pChannel == NULL)
1477                  return;                  return;
1478    
# Line 1352  void MainForm::editRemoveChannel (void) Line 1510  void MainForm::editRemoveChannel (void)
1510          if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1511                  return;                  return;
1512    
1513          qsamplerChannel *pChannel = pChannelStrip->channel();          Channel *pChannel = pChannelStrip->channel();
1514          if (pChannel == NULL)          if (pChannel == NULL)
1515                  return;                  return;
1516    
# Line 1364  void MainForm::editRemoveChannel (void) Line 1522  void MainForm::editRemoveChannel (void)
1522                          "%1\n\n"                          "%1\n\n"
1523                          "Are you sure?")                          "Are you sure?")
1524                          .arg(pChannelStrip->windowTitle()),                          .arg(pChannelStrip->windowTitle()),
1525                          tr("OK"), tr("Cancel")) > 0)                          QMessageBox::Ok | QMessageBox::Cancel)
1526                            == QMessageBox::Cancel)
1527                          return;                          return;
1528          }          }
1529    
# Line 1555  void MainForm::viewOptions (void) Line 1714  void MainForm::viewOptions (void)
1714                  int     iOldServerTimeout   = m_pOptions->iServerTimeout;                  int     iOldServerTimeout   = m_pOptions->iServerTimeout;
1715                  bool    bOldServerStart     = m_pOptions->bServerStart;                  bool    bOldServerStart     = m_pOptions->bServerStart;
1716                  QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;                  QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;
1717                    bool    bOldMessagesLog     = m_pOptions->bMessagesLog;
1718                    QString sOldMessagesLogPath = m_pOptions->sMessagesLogPath;
1719                  QString sOldDisplayFont     = m_pOptions->sDisplayFont;                  QString sOldDisplayFont     = m_pOptions->sDisplayFont;
1720                  bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;                  bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;
1721                  int     iOldMaxVolume       = m_pOptions->iMaxVolume;                  int     iOldMaxVolume       = m_pOptions->iMaxVolume;
# Line 1566  void MainForm::viewOptions (void) Line 1727  void MainForm::viewOptions (void)
1727                  bool    bOldCompletePath    = m_pOptions->bCompletePath;                  bool    bOldCompletePath    = m_pOptions->bCompletePath;
1728                  bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;                  bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;
1729                  int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;                  int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;
1730                    int     iOldBaseFontSize    = m_pOptions->iBaseFontSize;
1731                  // Load the current setup settings.                  // Load the current setup settings.
1732                  pOptionsForm->setup(m_pOptions);                  pOptionsForm->setup(m_pOptions);
1733                  // Show the setup dialog...                  // Show the setup dialog...
# Line 1574  void MainForm::viewOptions (void) Line 1736  void MainForm::viewOptions (void)
1736                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1737                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||
1738                                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||                                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||
1739                                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {                                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)     ||
1740                                    (iOldBaseFontSize   !=  m_pOptions->iBaseFontSize)) {
1741                                  QMessageBox::information(this,                                  QMessageBox::information(this,
1742                                          QSAMPLER_TITLE ": " + tr("Information"),                                          QSAMPLER_TITLE ": " + tr("Information"),
1743                                          tr("Some settings may be only effective\n"                                          tr("Some settings may be only effective\n"
1744                                          "next time you start this program."), tr("OK"));                                          "next time you start this program."));
1745                                  updateMessagesCapture();                                  updateMessagesCapture();
1746                          }                          }
1747                          // Check wheather something immediate has changed.                          // Check wheather something immediate has changed.
1748                            if (( bOldMessagesLog && !m_pOptions->bMessagesLog) ||
1749                                    (!bOldMessagesLog &&  m_pOptions->bMessagesLog) ||
1750                                    (sOldMessagesLogPath != m_pOptions->sMessagesLogPath))
1751                                    m_pMessages->setLogging(
1752                                            m_pOptions->bMessagesLog, m_pOptions->sMessagesLogPath);
1753                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||
1754                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||
1755                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
# Line 1736  void MainForm::helpAbout (void) Line 1904  void MainForm::helpAbout (void)
1904          sText += tr("Instrument editing support disabled.");          sText += tr("Instrument editing support disabled.");
1905          sText += "</font></small><br />";          sText += "</font></small><br />";
1906  #endif  #endif
1907    #ifndef CONFIG_EVENT_CHANNEL_MIDI
1908            sText += "<small><font color=\"red\">";
1909            sText += tr("Channel MIDI event support disabled.");
1910            sText += "</font></small><br />";
1911    #endif
1912    #ifndef CONFIG_EVENT_DEVICE_MIDI
1913            sText += "<small><font color=\"red\">";
1914            sText += tr("Device MIDI event support disabled.");
1915            sText += "</font></small><br />";
1916    #endif
1917    #ifndef CONFIG_MAX_VOICES
1918            sText += "<small><font color=\"red\">";
1919            sText += tr("Runtime max. voices / disk streams support disabled.");
1920            sText += "</font></small><br />";
1921    #endif
1922          sText += "<br />\n";          sText += "<br />\n";
1923          sText += tr("Using") + ": ";          sText += tr("Using") + ": ";
1924          sText += ::lscp_client_package();          sText += ::lscp_client_package();
# Line 1776  void MainForm::stabilizeForm (void) Line 1959  void MainForm::stabilizeForm (void)
1959          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));
1960    
1961          // Update the main menu state...          // Update the main menu state...
1962          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1963          bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);          bool bHasClient = (m_pOptions != NULL && m_pClient != NULL);
1964          bool bHasChannel = (bHasClient && pChannelStrip != NULL);          bool bHasChannel = (bHasClient && pChannelStrip != NULL);
1965            bool bHasChannels = (bHasClient && m_pWorkspace->windowList().count() > 0);
1966          m_ui.fileNewAction->setEnabled(bHasClient);          m_ui.fileNewAction->setEnabled(bHasClient);
1967          m_ui.fileOpenAction->setEnabled(bHasClient);          m_ui.fileOpenAction->setEnabled(bHasClient);
1968          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
# Line 1794  void MainForm::stabilizeForm (void) Line 1978  void MainForm::stabilizeForm (void)
1978          m_ui.editEditChannelAction->setEnabled(false);          m_ui.editEditChannelAction->setEnabled(false);
1979  #endif  #endif
1980          m_ui.editResetChannelAction->setEnabled(bHasChannel);          m_ui.editResetChannelAction->setEnabled(bHasChannel);
1981          m_ui.editResetAllChannelsAction->setEnabled(bHasChannel);          m_ui.editResetAllChannelsAction->setEnabled(bHasChannels);
1982          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());
1983  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
1984          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm
# Line 1806  void MainForm::stabilizeForm (void) Line 1990  void MainForm::stabilizeForm (void)
1990          m_ui.viewDevicesAction->setChecked(m_pDeviceForm          m_ui.viewDevicesAction->setChecked(m_pDeviceForm
1991                  && m_pDeviceForm->isVisible());                  && m_pDeviceForm->isVisible());
1992          m_ui.viewDevicesAction->setEnabled(bHasClient);          m_ui.viewDevicesAction->setEnabled(bHasClient);
1993          m_ui.channelsArrangeAction->setEnabled(bHasChannel);          m_ui.viewMidiDeviceStatusMenu->setEnabled(
1994                    DeviceStatusForm::getInstances().size() > 0);
1995            m_ui.channelsArrangeAction->setEnabled(bHasChannels);
1996    
1997  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
1998          // Toolbar widgets are also affected...          // Toolbar widgets are also affected...
# Line 1910  void MainForm::updateSession (void) Line 2096  void MainForm::updateSession (void)
2096          }          }
2097  #endif  #endif
2098    
2099            updateAllChannelStrips(false);
2100    
2101            // Do we auto-arrange?
2102            if (m_pOptions && m_pOptions->bAutoArrange)
2103                    channelsArrange();
2104    
2105            // Remember to refresh devices and instruments...
2106            if (m_pInstrumentListForm)
2107                    m_pInstrumentListForm->refreshInstruments();
2108            if (m_pDeviceForm)
2109                    m_pDeviceForm->refreshDevices();
2110    }
2111    
2112    void MainForm::updateAllChannelStrips(bool bRemoveDeadStrips) {
2113          // Retrieve the current channel list.          // Retrieve the current channel list.
2114          int *piChannelIDs = ::lscp_list_channels(m_pClient);          int *piChannelIDs = ::lscp_list_channels(m_pClient);
2115          if (piChannelIDs == NULL) {          if (piChannelIDs == NULL) {
# Line 1924  void MainForm::updateSession (void) Line 2124  void MainForm::updateSession (void)
2124                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {
2125                          // Check if theres already a channel strip for this one...                          // Check if theres already a channel strip for this one...
2126                          if (!channelStrip(piChannelIDs[iChannel]))                          if (!channelStrip(piChannelIDs[iChannel]))
2127                                  createChannelStrip(new qsamplerChannel(piChannelIDs[iChannel]));                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));
2128                  }                  }
                 m_pWorkspace->setUpdatesEnabled(true);  
         }  
2129    
2130          // Do we auto-arrange?                  // Do we auto-arrange?
2131          if (m_pOptions && m_pOptions->bAutoArrange)                  if (m_pOptions && m_pOptions->bAutoArrange)
2132                  channelsArrange();                          channelsArrange();
2133    
2134          // Remember to refresh devices and instruments...                  stabilizeForm();
         if (m_pInstrumentListForm)  
                 m_pInstrumentListForm->refreshInstruments();  
         if (m_pDeviceForm)  
                 m_pDeviceForm->refreshDevices();  
 }  
2135    
2136                    // remove dead channel strips
2137                    if (bRemoveDeadStrips) {
2138                            for (int i = 0; channelStripAt(i); ++i) {
2139                                    ChannelStrip* pChannelStrip = channelStripAt(i);
2140                                    bool bExists = false;
2141                                    for (int j = 0; piChannelIDs[j] >= 0; ++j) {
2142                                            if (!pChannelStrip->channel()) break;
2143                                            if (piChannelIDs[j] == pChannelStrip->channel()->channelID()) {
2144                                                    // strip exists, don't touch it
2145                                                    bExists = true;
2146                                                    break;
2147                                            }
2148                                    }
2149                                    if (!bExists) destroyChannelStrip(pChannelStrip);
2150                            }
2151                    }
2152                    m_pWorkspace->setUpdatesEnabled(true);
2153            }
2154    }
2155    
2156  // Update the recent files list and menu.  // Update the recent files list and menu.
2157  void MainForm::updateRecentFiles ( const QString& sFilename )  void MainForm::updateRecentFiles ( const QString& sFilename )
# Line 2113  void MainForm::appendMessagesError( cons Line 2325  void MainForm::appendMessagesError( cons
2325          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2326    
2327          QMessageBox::critical(this,          QMessageBox::critical(this,
2328                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));                  QSAMPLER_TITLE ": " + tr("Error"), s, QMessageBox::Cancel);
2329  }  }
2330    
2331    
# Line 2176  void MainForm::updateMessagesCapture (vo Line 2388  void MainForm::updateMessagesCapture (vo
2388  // qsamplerMainForm -- MDI channel strip management.  // qsamplerMainForm -- MDI channel strip management.
2389    
2390  // The channel strip creation executive.  // The channel strip creation executive.
2391  ChannelStrip* MainForm::createChannelStrip ( qsamplerChannel *pChannel )  ChannelStrip* MainForm::createChannelStrip ( Channel *pChannel )
2392  {  {
2393          if (m_pClient == NULL || pChannel == NULL)          if (m_pClient == NULL || pChannel == NULL)
2394                  return NULL;                  return NULL;
# Line 2218  ChannelStrip* MainForm::createChannelStr Line 2430  ChannelStrip* MainForm::createChannelStr
2430          return pChannelStrip;          return pChannelStrip;
2431  }  }
2432    
2433    void MainForm::destroyChannelStrip(ChannelStrip* pChannelStrip) {
2434            // Just delete the channel strip.
2435            delete pChannelStrip;
2436    
2437            // Do we auto-arrange?
2438            if (m_pOptions && m_pOptions->bAutoArrange)
2439                    channelsArrange();
2440    
2441            stabilizeForm();
2442    }
2443    
2444  // Retrieve the active channel strip.  // Retrieve the active channel strip.
2445  ChannelStrip* MainForm::activeChannelStrip (void)  ChannelStrip* MainForm::activeChannelStrip (void)
# Line 2229  ChannelStrip* MainForm::activeChannelStr Line 2451  ChannelStrip* MainForm::activeChannelStr
2451  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
2452  ChannelStrip* MainForm::channelStripAt ( int iChannel )  ChannelStrip* MainForm::channelStripAt ( int iChannel )
2453  {  {
2454            if (!m_pWorkspace) return NULL;
2455    
2456          QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2457          if (wlist.isEmpty())          if (wlist.isEmpty())
2458                  return NULL;                  return NULL;
2459    
2460          return static_cast<ChannelStrip *> (wlist.at(iChannel));          if (iChannel < 0 || iChannel >= wlist.size())
2461                    return NULL;
2462    
2463            return dynamic_cast<ChannelStrip *> (wlist.at(iChannel));
2464  }  }
2465    
2466    
# Line 2248  ChannelStrip* MainForm::channelStrip ( i Line 2475  ChannelStrip* MainForm::channelStrip ( i
2475                  ChannelStrip* pChannelStrip                  ChannelStrip* pChannelStrip
2476                          = static_cast<ChannelStrip*> (wlist.at(iChannel));                          = static_cast<ChannelStrip*> (wlist.at(iChannel));
2477                  if (pChannelStrip) {                  if (pChannelStrip) {
2478                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
2479                          if (pChannel && pChannel->channelID() == iChannelID)                          if (pChannel && pChannel->channelID() == iChannelID)
2480                                  return pChannelStrip;                                  return pChannelStrip;
2481                  }                  }
# Line 2386  void MainForm::startServer (void) Line 2613  void MainForm::startServer (void)
2613    
2614          // Is the server process instance still here?          // Is the server process instance still here?
2615          if (m_pServer) {          if (m_pServer) {
2616                  switch (QMessageBox::warning(this,                  if (QMessageBox::warning(this,
2617                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
2618                          tr("Could not start the LinuxSampler server.\n\n"                          tr("Could not start the LinuxSampler server.\n\n"
2619                          "Maybe it ss already started."),                          "Maybe it is already started."),
2620                          tr("Stop"), tr("Kill"), tr("Cancel"))) {                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
                 case 0:  
2621                          m_pServer->terminate();                          m_pServer->terminate();
                         break;  
                 case 1:  
2622                          m_pServer->kill();                          m_pServer->kill();
                         break;  
2623                  }                  }
2624                  return;                  return;
2625          }          }
# Line 2409  void MainForm::startServer (void) Line 2632  void MainForm::startServer (void)
2632                  return;                  return;
2633    
2634          // OK. Let's build the startup process...          // OK. Let's build the startup process...
2635          m_pServer = new QProcess(this);          m_pServer = new QProcess();
2636            bForceServerStop = true;
2637    
2638          // Setup stdout/stderr capture...          // Setup stdout/stderr capture...
2639  //      if (m_pOptions->bStdoutCapture) {  //      if (m_pOptions->bStdoutCapture) {
2640                  //m_pServer->setProcessChannelMode(  #if QT_VERSION >= 0x040200
2641                  //      QProcess::StandardOutput);                  m_pServer->setProcessChannelMode(QProcess::ForwardedChannels);
2642    #endif
2643                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2644                          SIGNAL(readyReadStandardOutput()),                          SIGNAL(readyReadStandardOutput()),
2645                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
# Line 2425  void MainForm::startServer (void) Line 2650  void MainForm::startServer (void)
2650    
2651          // The unforgiveable signal communication...          // The unforgiveable signal communication...
2652          QObject::connect(m_pServer,          QObject::connect(m_pServer,
2653                  SIGNAL(finished(int,QProcess::ExitStatus)),                  SIGNAL(finished(int, QProcess::ExitStatus)),
2654                  SLOT(processServerExit()));                  SLOT(processServerExit()));
2655    
2656          // Build process arguments...          // Build process arguments...
# Line 2456  void MainForm::startServer (void) Line 2681  void MainForm::startServer (void)
2681    
2682    
2683  // Stop linuxsampler server...  // Stop linuxsampler server...
2684  void MainForm::stopServer (void)  void MainForm::stopServer (bool bInteractive)
2685  {  {
2686          // Stop client code.          // Stop client code.
2687          stopClient();          stopClient();
2688    
2689            if (m_pServer && bInteractive) {
2690                    if (QMessageBox::question(this,
2691                            QSAMPLER_TITLE ": " + tr("The backend's fate ..."),
2692                            tr("You have the option to keep the sampler backend (LinuxSampler)\n"
2693                            "running in the background. The sampler would continue to work\n"
2694                            "according to your current sampler session and you could alter the\n"
2695                            "sampler session at any time by relaunching QSampler.\n\n"
2696                            "Do you want LinuxSampler to stop?"),
2697                            QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
2698                    {
2699                            bForceServerStop = false;
2700                    }
2701            }
2702    
2703          // And try to stop server.          // And try to stop server.
2704          if (m_pServer) {          if (m_pServer && bForceServerStop) {
2705                  appendMessages(tr("Server is stopping..."));                  appendMessages(tr("Server is stopping..."));
2706                  if (m_pServer->state() == QProcess::Running)                  if (m_pServer->state() == QProcess::Running) {
2707    #if defined(WIN32)
2708                            // Try harder...
2709                            m_pServer->kill();
2710    #else
2711                            // Try softly...
2712                          m_pServer->terminate();                          m_pServer->terminate();
2713          }  #endif
2714                    }
2715            }       // Do final processing anyway.
2716            else processServerExit();
2717    
2718          // Give it some time to terminate gracefully and stabilize...          // Give it some time to terminate gracefully and stabilize...
2719          QTime t;          QTime t;
2720          t.start();          t.start();
2721          while (t.elapsed() < QSAMPLER_TIMER_MSECS)          while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2722                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
   
         // Do final processing anyway.  
         processServerExit();  
2723  }  }
2724    
2725    
# Line 2497  void MainForm::processServerExit (void) Line 2741  void MainForm::processServerExit (void)
2741          if (m_pMessages)          if (m_pMessages)
2742                  m_pMessages->flushStdoutBuffer();                  m_pMessages->flushStdoutBuffer();
2743    
2744          if (m_pServer) {          if (m_pServer && bForceServerStop) {
2745                    if (m_pServer->state() != QProcess::NotRunning) {
2746                            appendMessages(tr("Server is being forced..."));
2747                            // Force final server shutdown...
2748                            m_pServer->kill();
2749                            // Give it some time to terminate gracefully and stabilize...
2750                            QTime t;
2751                            t.start();
2752                            while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2753                                    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2754                    }
2755                  // Force final server shutdown...                  // Force final server shutdown...
2756                  appendMessages(                  appendMessages(
2757                          tr("Server was stopped with exit status %1.")                          tr("Server was stopped with exit status %1.")
2758                          .arg(m_pServer->exitStatus()));                          .arg(m_pServer->exitStatus()));
                 m_pServer->terminate();  
                 if (!m_pServer->waitForFinished(2000))  
                         m_pServer->kill();  
                 // Destroy it.  
2759                  delete m_pServer;                  delete m_pServer;
2760                  m_pServer = NULL;                  m_pServer = NULL;
2761          }          }
# Line 2530  lscp_status_t qsampler_client_callback ( Line 2780  lscp_status_t qsampler_client_callback (
2780          // as this is run under some other thread context.          // as this is run under some other thread context.
2781          // A custom event must be posted here...          // A custom event must be posted here...
2782          QApplication::postEvent(pMainForm,          QApplication::postEvent(pMainForm,
2783                  new qsamplerCustomEvent(event, pchData, cchData));                  new LscpEvent(event, pchData, cchData));
2784    
2785          return LSCP_OK;          return LSCP_OK;
2786  }  }
# Line 2575  bool MainForm::startClient (void) Line 2825  bool MainForm::startClient (void)
2825                  .arg(::lscp_client_get_timeout(m_pClient)));                  .arg(::lscp_client_get_timeout(m_pClient)));
2826    
2827          // Subscribe to channel info change notifications...          // Subscribe to channel info change notifications...
2828            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT) != LSCP_OK)
2829                    appendMessagesClient("lscp_client_subscribe(CHANNEL_COUNT)");
2830          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)
2831                  appendMessagesClient("lscp_client_subscribe");                  appendMessagesClient("lscp_client_subscribe(CHANNEL_INFO)");
2832    
2833            DeviceStatusForm::onDevicesChanged(); // initialize
2834            updateViewMidiDeviceStatusMenu();
2835            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT) != LSCP_OK)
2836                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_COUNT)");
2837            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO) != LSCP_OK)
2838                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_INFO)");
2839            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT) != LSCP_OK)
2840                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_COUNT)");
2841            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO) != LSCP_OK)
2842                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_INFO)");
2843    
2844    #if CONFIG_EVENT_CHANNEL_MIDI
2845            // Subscribe to channel MIDI data notifications...
2846            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI) != LSCP_OK)
2847                    appendMessagesClient("lscp_client_subscribe(CHANNEL_MIDI)");
2848    #endif
2849    
2850    #if CONFIG_EVENT_DEVICE_MIDI
2851            // Subscribe to channel MIDI data notifications...
2852            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI) != LSCP_OK)
2853                    appendMessagesClient("lscp_client_subscribe(DEVICE_MIDI)");
2854    #endif
2855    
2856          // We may stop scheduling around.          // We may stop scheduling around.
2857          stopSchedule();          stopSchedule();
# Line 2603  bool MainForm::startClient (void) Line 2878  bool MainForm::startClient (void)
2878                  }                  }
2879          }          }
2880    
2881            // send the current / loaded fine tuning settings to the sampler
2882            m_pOptions->sendFineTuningSettings();
2883    
2884          // Make a new session          // Make a new session
2885          return newSession();          return newSession();
2886  }  }
# Line 2630  void MainForm::stopClient (void) Line 2908  void MainForm::stopClient (void)
2908          closeSession(false);          closeSession(false);
2909    
2910          // Close us as a client...          // Close us as a client...
2911    #if CONFIG_EVENT_DEVICE_MIDI
2912            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI);
2913    #endif
2914    #if CONFIG_EVENT_CHANNEL_MIDI
2915            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI);
2916    #endif
2917            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
2918            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
2919            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
2920            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
2921          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
2922            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT);
2923          ::lscp_client_destroy(m_pClient);          ::lscp_client_destroy(m_pClient);
2924          m_pClient = NULL;          m_pClient = NULL;
2925    

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

  ViewVC Help
Powered by ViewVC