/[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 2108 by capela, Thu Jul 15 08:03:32 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    namespace QSampler {
97    
98  // Timer constant stuff.  // Timer constant stuff.
99  #define QSAMPLER_TIMER_MSECS    200  #define QSAMPLER_TIMER_MSECS    200
100    
# Line 87  static inline long lroundf ( float x ) Line 105  static inline long lroundf ( float x )
105  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.
106    
107    
108  // All winsock apps needs this.  // Specialties for thread-callback comunication.
109  #if defined(WIN32)  #define QSAMPLER_LSCP_EVENT   QEvent::Type(QEvent::User + 1)
110  static WSADATA _wsaData;  #define QSAMPLER_SAVE_EVENT   QEvent::Type(QEvent::User + 2)
 #endif  
111    
112    
113  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
114  // qsamplerCustomEvent -- specialty for callback comunication.  // LscpEvent -- specialty for LSCP callback comunication.
115    
 #define QSAMPLER_CUSTOM_EVENT   QEvent::Type(QEvent::User + 0)  
116    
117  class qsamplerCustomEvent : public QEvent  class LscpEvent : public QEvent
118  {  {
119  public:  public:
120    
121          // Constructor.          // Constructor.
122          qsamplerCustomEvent(lscp_event_t event, const char *pchData, int cchData)          LscpEvent(lscp_event_t event, const char *pchData, int cchData)
123                  : QEvent(QSAMPLER_CUSTOM_EVENT)                  : QEvent(QSAMPLER_LSCP_EVENT)
124          {          {
125                  m_event = event;                  m_event = event;
126                  m_data  = QString::fromUtf8(pchData, cchData);                  m_data  = QString::fromUtf8(pchData, cchData);
# Line 124  private: Line 140  private:
140    
141    
142  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
143  // qsamplerMainForm -- Main window form implementation.  // LADISH Level 1 support stuff.
144    
145    void qsampler_on_sigusr1 ( int /*signo*/ )
146    {
147            QApplication::postEvent(
148                    MainForm::getInstance(),
149                    new QEvent(QSAMPLER_SAVE_EVENT));
150    }
151    
152  namespace QSampler {  
153    //-------------------------------------------------------------------------
154    // qsamplerMainForm -- Main window form implementation.
155    
156  // Kind of singleton reference.  // Kind of singleton reference.
157  MainForm* MainForm::g_pMainForm = NULL;  MainForm* MainForm::g_pMainForm = NULL;
# Line 162  MainForm::MainForm ( QWidget *pParent ) Line 187  MainForm::MainForm ( QWidget *pParent )
187  #ifdef HAVE_SIGNAL_H  #ifdef HAVE_SIGNAL_H
188          // Set to ignore any fatal "Broken pipe" signals.          // Set to ignore any fatal "Broken pipe" signals.
189          ::signal(SIGPIPE, SIG_IGN);          ::signal(SIGPIPE, SIG_IGN);
190            // LADISH Level 1 suport.
191            ::signal(SIGUSR1, qsampler_on_sigusr1);
192  #endif  #endif
193    
194  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
# Line 366  MainForm::~MainForm() Line 393  MainForm::~MainForm()
393    
394    
395  // Make and set a proper setup options step.  // Make and set a proper setup options step.
396  void MainForm::setup ( qsamplerOptions *pOptions )  void MainForm::setup ( Options *pOptions )
397  {  {
398          // We got options?          // We got options?
399          m_pOptions = pOptions;          m_pOptions = pOptions;
400    
401          // What style do we create these forms?          // What style do we create these forms?
402          Qt::WindowFlags wflags = Qt::Window          Qt::WindowFlags wflags = Qt::Window
 #if QT_VERSION >= 0x040200  
403                  | Qt::CustomizeWindowHint                  | Qt::CustomizeWindowHint
 #endif  
404                  | Qt::WindowTitleHint                  | Qt::WindowTitleHint
405                  | Qt::WindowSystemMenuHint                  | Qt::WindowSystemMenuHint
406                  | Qt::WindowMinMaxButtonsHint;                  | Qt::WindowMinMaxButtonsHint
407                    | Qt::WindowCloseButtonHint;
408          if (m_pOptions->bKeepOnTop)          if (m_pOptions->bKeepOnTop)
409                  wflags |= Qt::Tool;                  wflags |= Qt::Tool;
410    
411          // Some child forms are to be created right now.          // Some child forms are to be created right now.
412          m_pMessages = new qsamplerMessages(this);          m_pMessages = new Messages(this);
413          m_pDeviceForm = new DeviceForm(this, wflags);          m_pDeviceForm = new DeviceForm(this, wflags);
414  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
415          m_pInstrumentListForm = new InstrumentListForm(this, wflags);          m_pInstrumentListForm = new InstrumentListForm(this, wflags);
416  #else  #else
417          viewInstrumentsAction->setEnabled(false);          m_ui.viewInstrumentsAction->setEnabled(false);
418  #endif  #endif
419    
420            // Setup messages logging appropriately...
421            m_pMessages->setLogging(
422                    m_pOptions->bMessagesLog,
423                    m_pOptions->sMessagesLogPath);
424    
425          // Set message defaults...          // Set message defaults...
426          updateMessagesFont();          updateMessagesFont();
427          updateMessagesLimit();          updateMessagesLimit();
# Line 419  void MainForm::setup ( qsamplerOptions * Line 452  void MainForm::setup ( qsamplerOptions *
452          }          }
453    
454          // Try to restore old window positioning and initial visibility.          // Try to restore old window positioning and initial visibility.
455          m_pOptions->loadWidgetGeometry(this);          m_pOptions->loadWidgetGeometry(this, true);
456          m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);          m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);
457          m_pOptions->loadWidgetGeometry(m_pDeviceForm);          m_pOptions->loadWidgetGeometry(m_pDeviceForm);
458    
# Line 463  bool MainForm::queryClose (void) Line 496  bool MainForm::queryClose (void)
496                          // And the children, and the main windows state,.                          // And the children, and the main windows state,.
497                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);
498                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);
499                          m_pOptions->saveWidgetGeometry(this);                          m_pOptions->saveWidgetGeometry(this, true);
500                          // Close popup widgets.                          // Close popup widgets.
501                          if (m_pInstrumentListForm)                          if (m_pInstrumentListForm)
502                                  m_pInstrumentListForm->close();                                  m_pInstrumentListForm->close();
503                          if (m_pDeviceForm)                          if (m_pDeviceForm)
504                                  m_pDeviceForm->close();                                  m_pDeviceForm->close();
505                          // Stop client and/or server, gracefully.                          // Stop client and/or server, gracefully.
506                          stopServer();                          stopServer(true /*interactive*/);
507                  }                  }
508          }          }
509    
# Line 480  bool MainForm::queryClose (void) Line 513  bool MainForm::queryClose (void)
513    
514  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )
515  {  {
516          if (queryClose())          if (queryClose()) {
517                    DeviceStatusForm::deleteAllInstances();
518                  pCloseEvent->accept();                  pCloseEvent->accept();
519          else          } else
520                  pCloseEvent->ignore();                  pCloseEvent->ignore();
521  }  }
522    
# Line 511  void MainForm::dropEvent ( QDropEvent* p Line 545  void MainForm::dropEvent ( QDropEvent* p
545                  QListIterator<QUrl> iter(pMimeData->urls());                  QListIterator<QUrl> iter(pMimeData->urls());
546                  while (iter.hasNext()) {                  while (iter.hasNext()) {
547                          const QString& sPath = iter.next().toLocalFile();                          const QString& sPath = iter.next().toLocalFile();
548                          if (qsamplerChannel::isInstrumentFile(sPath)) {                  //      if (Channel::isDlsInstrumentFile(sPath)) {
549                            if (QFileInfo(sPath).exists()) {
550                                  // Try to create a new channel from instrument file...                                  // Try to create a new channel from instrument file...
551                                  qsamplerChannel *pChannel = new qsamplerChannel();                                  Channel *pChannel = new Channel();
552                                  if (pChannel == NULL)                                  if (pChannel == NULL)
553                                          return;                                          return;
554                                  // Start setting the instrument filename...                                  // Start setting the instrument filename...
# Line 545  void MainForm::dropEvent ( QDropEvent* p Line 580  void MainForm::dropEvent ( QDropEvent* p
580    
581    
582  // Custome event handler.  // Custome event handler.
583  void MainForm::customEvent(QEvent* pCustomEvent)  void MainForm::customEvent ( QEvent* pEvent )
584  {  {
585          // For the time being, just pump it to messages.          // For the time being, just pump it to messages.
586          if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {          if (pEvent->type() == QSAMPLER_LSCP_EVENT) {
587                  qsamplerCustomEvent *pEvent = (qsamplerCustomEvent *) pCustomEvent;                  LscpEvent *pLscpEvent = static_cast<LscpEvent *> (pEvent);
588                  if (pEvent->event() == LSCP_EVENT_CHANNEL_INFO) {                  switch (pLscpEvent->event()) {
589                          int iChannelID = pEvent->data().toInt();                          case LSCP_EVENT_CHANNEL_COUNT:
590                          ChannelStrip *pChannelStrip = channelStrip(iChannelID);                                  updateAllChannelStrips(true);
591                          if (pChannelStrip)                                  break;
592                                  channelStripChanged(pChannelStrip);                          case LSCP_EVENT_CHANNEL_INFO: {
593                  } else {                                  int iChannelID = pLscpEvent->data().toInt();
594                          appendMessagesColor(tr("Notify event: %1 data: %2")                                  ChannelStrip *pChannelStrip = channelStrip(iChannelID);
595                                  .arg(::lscp_event_to_text(pEvent->event()))                                  if (pChannelStrip)
596                                  .arg(pEvent->data()), "#996699");                                          channelStripChanged(pChannelStrip);
597                  }                                  break;
598                            }
599                            case LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT:
600                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
601                                    DeviceStatusForm::onDevicesChanged();
602                                    updateViewMidiDeviceStatusMenu();
603                                    break;
604                            case LSCP_EVENT_MIDI_INPUT_DEVICE_INFO: {
605                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
606                                    const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt();
607                                    DeviceStatusForm::onDeviceChanged(iDeviceID);
608                                    break;
609                            }
610                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT:
611                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
612                                    break;
613                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO:
614                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
615                                    break;
616                    #if CONFIG_EVENT_CHANNEL_MIDI
617                            case LSCP_EVENT_CHANNEL_MIDI: {
618                                    const int iChannelID = pLscpEvent->data().section(' ', 0, 0).toInt();
619                                    ChannelStrip *pChannelStrip = channelStrip(iChannelID);
620                                    if (pChannelStrip)
621                                            pChannelStrip->midiActivityLedOn();
622                                    break;
623                            }
624                    #endif
625                    #if CONFIG_EVENT_DEVICE_MIDI
626                            case LSCP_EVENT_DEVICE_MIDI: {
627                                    const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt();
628                                    const int iPortID   = pLscpEvent->data().section(' ', 1, 1).toInt();
629                                    DeviceStatusForm *pDeviceStatusForm
630                                            = DeviceStatusForm::getInstance(iDeviceID);
631                                    if (pDeviceStatusForm)
632                                            pDeviceStatusForm->midiArrived(iPortID);
633                                    break;
634                            }
635                    #endif
636                            default:
637                                    appendMessagesColor(tr("LSCP Event: %1 data: %2")
638                                            .arg(::lscp_event_to_text(pLscpEvent->event()))
639                                            .arg(pLscpEvent->data()), "#996699");
640                    }
641            }       // LADISH1 Level 1 support...
642            else if (pEvent->type() == QSAMPLER_SAVE_EVENT)
643                    saveSession(false);
644    }
645    
646    
647    void MainForm::updateViewMidiDeviceStatusMenu (void)
648    {
649            m_ui.viewMidiDeviceStatusMenu->clear();
650            const std::map<int, DeviceStatusForm *> statusForms
651                    = DeviceStatusForm::getInstances();
652            std::map<int, DeviceStatusForm *>::const_iterator iter
653                    = statusForms.begin();
654            for ( ; iter != statusForms.end(); ++iter) {
655                    DeviceStatusForm *pStatusForm = iter->second;
656                    m_ui.viewMidiDeviceStatusMenu->addAction(
657                            pStatusForm->visibleAction());
658          }          }
659  }  }
660    
661    
662  // Context menu event handler.  // Context menu event handler.
663  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )
664  {  {
# Line 576  void MainForm::contextMenuEvent( QContex Line 672  void MainForm::contextMenuEvent( QContex
672  // qsamplerMainForm -- Brainless public property accessors.  // qsamplerMainForm -- Brainless public property accessors.
673    
674  // The global options settings property.  // The global options settings property.
675  qsamplerOptions *MainForm::options (void) const  Options *MainForm::options (void) const
676  {  {
677          return m_pOptions;          return m_pOptions;
678  }  }
# Line 694  bool MainForm::saveSession ( bool bPromp Line 790  bool MainForm::saveSession ( bool bPromp
790                                  "\"%1\"\n\n"                                  "\"%1\"\n\n"
791                                  "Do you want to replace it?")                                  "Do you want to replace it?")
792                                  .arg(sFilename),                                  .arg(sFilename),
793                                  tr("Replace"), tr("Cancel")) > 0)                                  QMessageBox::Yes | QMessageBox::No)
794                                    == QMessageBox::No)
795                                  return false;                                  return false;
796                  }                  }
797          }          }
# Line 717  bool MainForm::closeSession ( bool bForc Line 814  bool MainForm::closeSession ( bool bForc
814                          "\"%1\"\n\n"                          "\"%1\"\n\n"
815                          "Do you want to save the changes?")                          "Do you want to save the changes?")
816                          .arg(sessionName(m_sFilename)),                          .arg(sessionName(m_sFilename)),
817                          tr("Save"), tr("Discard"), tr("Cancel"))) {                          QMessageBox::Save |
818                  case 0:     // Save...                          QMessageBox::Discard |
819                            QMessageBox::Cancel)) {
820                    case QMessageBox::Save:
821                          bClose = saveSession(false);                          bClose = saveSession(false);
822                          // Fall thru....                          // Fall thru....
823                  case 1:     // Discard                  case QMessageBox::Discard:
824                          break;                          break;
825                  default:    // Cancel.                  default:    // Cancel.
826                          bClose = false;                          bClose = false;
# Line 737  bool MainForm::closeSession ( bool bForc Line 836  bool MainForm::closeSession ( bool bForc
836                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
837                          ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                          ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
838                          if (pChannelStrip) {                          if (pChannelStrip) {
839                                  qsamplerChannel *pChannel = pChannelStrip->channel();                                  Channel *pChannel = pChannelStrip->channel();
840                                  if (bForce && pChannel)                                  if (bForce && pChannel)
841                                          pChannel->removeChannel();                                          pChannel->removeChannel();
842                                  delete pChannelStrip;                                  delete pChannelStrip;
# Line 877  bool MainForm::saveSessionFile ( const Q Line 976  bool MainForm::saveSessionFile ( const Q
976    
977          // Audio device mapping.          // Audio device mapping.
978          QMap<int, int> audioDeviceMap;          QMap<int, int> audioDeviceMap;
979          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Audio);          piDeviceIDs = Device::getDevices(m_pClient, Device::Audio);
980          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
981                  ts << endl;                  ts << endl;
982                  qsamplerDevice device(qsamplerDevice::Audio, piDeviceIDs[iDevice]);                  Device device(Device::Audio, piDeviceIDs[iDevice]);
983                  // Audio device specification...                  // Audio device specification...
984                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
985                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
986                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();
987                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
988                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
989                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
990                                          ++deviceParam) {                                          ++deviceParam) {
991                          const qsamplerDeviceParam& param = deviceParam.value();                          const DeviceParam& param = deviceParam.value();
992                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
993                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
994                  }                  }
995                  ts << endl;                  ts << endl;
996                  // Audio channel parameters...                  // Audio channel parameters...
997                  int iPort = 0;                  int iPort = 0;
998                  QListIterator<qsamplerDevicePort *> iter(device.ports());                  QListIterator<DevicePort *> iter(device.ports());
999                  while (iter.hasNext()) {                  while (iter.hasNext()) {
1000                          qsamplerDevicePort *pPort = iter.next();                          DevicePort *pPort = iter.next();
1001                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1002                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1003                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1004                                                  ++portParam) {                                                  ++portParam) {
1005                                  const qsamplerDeviceParam& param = portParam.value();                                  const DeviceParam& param = portParam.value();
1006                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1007                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice
1008                                          << " " << iPort << " " << portParam.key()                                          << " " << iPort << " " << portParam.key()
# Line 919  bool MainForm::saveSessionFile ( const Q Line 1018  bool MainForm::saveSessionFile ( const Q
1018    
1019          // MIDI device mapping.          // MIDI device mapping.
1020          QMap<int, int> midiDeviceMap;          QMap<int, int> midiDeviceMap;
1021          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Midi);          piDeviceIDs = Device::getDevices(m_pClient, Device::Midi);
1022          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
1023                  ts << endl;                  ts << endl;
1024                  qsamplerDevice device(qsamplerDevice::Midi, piDeviceIDs[iDevice]);                  Device device(Device::Midi, piDeviceIDs[iDevice]);
1025                  // MIDI device specification...                  // MIDI device specification...
1026                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1027                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1028                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();
1029                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
1030                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
1031                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
1032                                          ++deviceParam) {                                          ++deviceParam) {
1033                          const qsamplerDeviceParam& param = deviceParam.value();                          const DeviceParam& param = deviceParam.value();
1034                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
1035                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
1036                  }                  }
1037                  ts << endl;                  ts << endl;
1038                  // MIDI port parameters...                  // MIDI port parameters...
1039                  int iPort = 0;                  int iPort = 0;
1040                  QListIterator<qsamplerDevicePort *> iter(device.ports());                  QListIterator<DevicePort *> iter(device.ports());
1041                  while (iter.hasNext()) {                  while (iter.hasNext()) {
1042                          qsamplerDevicePort *pPort = iter.next();                          DevicePort *pPort = iter.next();
1043                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1044                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1045                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1046                                                  ++portParam) {                                                  ++portParam) {
1047                                  const qsamplerDeviceParam& param = portParam.value();                                  const DeviceParam& param = portParam.value();
1048                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1049                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice
1050                                  << " " << iPort << " " << portParam.key()                                  << " " << iPort << " " << portParam.key()
# Line 1037  bool MainForm::saveSessionFile ( const Q Line 1136  bool MainForm::saveSessionFile ( const Q
1136                  ChannelStrip* pChannelStrip                  ChannelStrip* pChannelStrip
1137                          = static_cast<ChannelStrip *> (wlist.at(iChannel));                          = static_cast<ChannelStrip *> (wlist.at(iChannel));
1138                  if (pChannelStrip) {                  if (pChannelStrip) {
1139                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
1140                          if (pChannel) {                          if (pChannel) {
1141                                  ts << "# " << tr("Channel") << " " << iChannel << endl;                                  ts << "# " << tr("Channel") << " " << iChannel << endl;
1142                                  ts << "ADD CHANNEL" << endl;                                  ts << "ADD CHANNEL" << endl;
# Line 1069  bool MainForm::saveSessionFile ( const Q Line 1168  bool MainForm::saveSessionFile ( const Q
1168                                  ts << "LOAD INSTRUMENT NON_MODAL '"                                  ts << "LOAD INSTRUMENT NON_MODAL '"
1169                                          << pChannel->instrumentFile() << "' "                                          << pChannel->instrumentFile() << "' "
1170                                          << pChannel->instrumentNr() << " " << iChannel << endl;                                          << pChannel->instrumentNr() << " " << iChannel << endl;
1171                                  qsamplerChannelRoutingMap::ConstIterator audioRoute;                                  ChannelRoutingMap::ConstIterator audioRoute;
1172                                  for (audioRoute = pChannel->audioRouting().begin();                                  for (audioRoute = pChannel->audioRouting().begin();
1173                                                  audioRoute != pChannel->audioRouting().end();                                                  audioRoute != pChannel->audioRouting().end();
1174                                                          ++audioRoute) {                                                          ++audioRoute) {
# Line 1242  void MainForm::fileReset (void) Line 1341  void MainForm::fileReset (void)
1341                  "Please note that this operation may cause\n"                  "Please note that this operation may cause\n"
1342                  "temporary MIDI and Audio disruption.\n\n"                  "temporary MIDI and Audio disruption.\n\n"
1343                  "Do you want to reset the sampler engine now?"),                  "Do you want to reset the sampler engine now?"),
1344                  tr("Reset"), tr("Cancel")) > 0)                  QMessageBox::Ok | QMessageBox::Cancel)
1345                    == QMessageBox::Cancel)
1346                  return;                  return;
1347    
1348          // Trye closing the current session, first...          // Trye closing the current session, first...
# Line 1283  void MainForm::fileRestart (void) Line 1383  void MainForm::fileRestart (void)
1383                          "Please note that this operation may cause\n"                          "Please note that this operation may cause\n"
1384                          "temporary MIDI and Audio disruption.\n\n"                          "temporary MIDI and Audio disruption.\n\n"
1385                          "Do you want to restart the connection now?"),                          "Do you want to restart the connection now?"),
1386                          tr("Restart"), tr("Cancel")) == 0);                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok);
1387          }          }
1388    
1389          // Are we still for it?          // Are we still for it?
# Line 1314  void MainForm::editAddChannel (void) Line 1414  void MainForm::editAddChannel (void)
1414                  return;                  return;
1415    
1416          // Just create the channel instance...          // Just create the channel instance...
1417          qsamplerChannel *pChannel = new qsamplerChannel();          Channel *pChannel = new Channel();
1418          if (pChannel == NULL)          if (pChannel == NULL)
1419                  return;                  return;
1420    
# Line 1352  void MainForm::editRemoveChannel (void) Line 1452  void MainForm::editRemoveChannel (void)
1452          if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1453                  return;                  return;
1454    
1455          qsamplerChannel *pChannel = pChannelStrip->channel();          Channel *pChannel = pChannelStrip->channel();
1456          if (pChannel == NULL)          if (pChannel == NULL)
1457                  return;                  return;
1458    
# Line 1364  void MainForm::editRemoveChannel (void) Line 1464  void MainForm::editRemoveChannel (void)
1464                          "%1\n\n"                          "%1\n\n"
1465                          "Are you sure?")                          "Are you sure?")
1466                          .arg(pChannelStrip->windowTitle()),                          .arg(pChannelStrip->windowTitle()),
1467                          tr("OK"), tr("Cancel")) > 0)                          QMessageBox::Ok | QMessageBox::Cancel)
1468                            == QMessageBox::Cancel)
1469                          return;                          return;
1470          }          }
1471    
# Line 1555  void MainForm::viewOptions (void) Line 1656  void MainForm::viewOptions (void)
1656                  int     iOldServerTimeout   = m_pOptions->iServerTimeout;                  int     iOldServerTimeout   = m_pOptions->iServerTimeout;
1657                  bool    bOldServerStart     = m_pOptions->bServerStart;                  bool    bOldServerStart     = m_pOptions->bServerStart;
1658                  QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;                  QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;
1659                    bool    bOldMessagesLog     = m_pOptions->bMessagesLog;
1660                    QString sOldMessagesLogPath = m_pOptions->sMessagesLogPath;
1661                  QString sOldDisplayFont     = m_pOptions->sDisplayFont;                  QString sOldDisplayFont     = m_pOptions->sDisplayFont;
1662                  bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;                  bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;
1663                  int     iOldMaxVolume       = m_pOptions->iMaxVolume;                  int     iOldMaxVolume       = m_pOptions->iMaxVolume;
# Line 1566  void MainForm::viewOptions (void) Line 1669  void MainForm::viewOptions (void)
1669                  bool    bOldCompletePath    = m_pOptions->bCompletePath;                  bool    bOldCompletePath    = m_pOptions->bCompletePath;
1670                  bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;                  bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;
1671                  int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;                  int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;
1672                    int     iOldBaseFontSize    = m_pOptions->iBaseFontSize;
1673                  // Load the current setup settings.                  // Load the current setup settings.
1674                  pOptionsForm->setup(m_pOptions);                  pOptionsForm->setup(m_pOptions);
1675                  // Show the setup dialog...                  // Show the setup dialog...
# Line 1574  void MainForm::viewOptions (void) Line 1678  void MainForm::viewOptions (void)
1678                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1679                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||
1680                                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||                                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||
1681                                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {                                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)     ||
1682                                    (iOldBaseFontSize   !=  m_pOptions->iBaseFontSize)) {
1683                                  QMessageBox::information(this,                                  QMessageBox::information(this,
1684                                          QSAMPLER_TITLE ": " + tr("Information"),                                          QSAMPLER_TITLE ": " + tr("Information"),
1685                                          tr("Some settings may be only effective\n"                                          tr("Some settings may be only effective\n"
1686                                          "next time you start this program."), tr("OK"));                                          "next time you start this program."));
1687                                  updateMessagesCapture();                                  updateMessagesCapture();
1688                          }                          }
1689                          // Check wheather something immediate has changed.                          // Check wheather something immediate has changed.
1690                            if (( bOldMessagesLog && !m_pOptions->bMessagesLog) ||
1691                                    (!bOldMessagesLog &&  m_pOptions->bMessagesLog) ||
1692                                    (sOldMessagesLogPath != m_pOptions->sMessagesLogPath))
1693                                    m_pMessages->setLogging(
1694                                            m_pOptions->bMessagesLog, m_pOptions->sMessagesLogPath);
1695                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||
1696                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||
1697                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
# Line 1736  void MainForm::helpAbout (void) Line 1846  void MainForm::helpAbout (void)
1846          sText += tr("Instrument editing support disabled.");          sText += tr("Instrument editing support disabled.");
1847          sText += "</font></small><br />";          sText += "</font></small><br />";
1848  #endif  #endif
1849    #ifndef CONFIG_EVENT_CHANNEL_MIDI
1850            sText += "<small><font color=\"red\">";
1851            sText += tr("Channel MIDI event support disabled.");
1852            sText += "</font></small><br />";
1853    #endif
1854    #ifndef CONFIG_EVENT_DEVICE_MIDI
1855            sText += "<small><font color=\"red\">";
1856            sText += tr("Device MIDI event support disabled.");
1857            sText += "</font></small><br />";
1858    #endif
1859    #ifndef CONFIG_MAX_VOICES
1860            sText += "<small><font color=\"red\">";
1861            sText += tr("Runtime max. voices / disk streams support disabled.");
1862            sText += "</font></small><br />";
1863    #endif
1864          sText += "<br />\n";          sText += "<br />\n";
1865          sText += tr("Using") + ": ";          sText += tr("Using") + ": ";
1866          sText += ::lscp_client_package();          sText += ::lscp_client_package();
# Line 1776  void MainForm::stabilizeForm (void) Line 1901  void MainForm::stabilizeForm (void)
1901          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));
1902    
1903          // Update the main menu state...          // Update the main menu state...
1904          ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1905          bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);          bool bHasClient = (m_pOptions != NULL && m_pClient != NULL);
1906          bool bHasChannel = (bHasClient && pChannelStrip != NULL);          bool bHasChannel = (bHasClient && pChannelStrip != NULL);
1907            bool bHasChannels = (bHasClient && m_pWorkspace->windowList().count() > 0);
1908          m_ui.fileNewAction->setEnabled(bHasClient);          m_ui.fileNewAction->setEnabled(bHasClient);
1909          m_ui.fileOpenAction->setEnabled(bHasClient);          m_ui.fileOpenAction->setEnabled(bHasClient);
1910          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
# Line 1794  void MainForm::stabilizeForm (void) Line 1920  void MainForm::stabilizeForm (void)
1920          m_ui.editEditChannelAction->setEnabled(false);          m_ui.editEditChannelAction->setEnabled(false);
1921  #endif  #endif
1922          m_ui.editResetChannelAction->setEnabled(bHasChannel);          m_ui.editResetChannelAction->setEnabled(bHasChannel);
1923          m_ui.editResetAllChannelsAction->setEnabled(bHasChannel);          m_ui.editResetAllChannelsAction->setEnabled(bHasChannels);
1924          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());
1925  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
1926          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm
# Line 1806  void MainForm::stabilizeForm (void) Line 1932  void MainForm::stabilizeForm (void)
1932          m_ui.viewDevicesAction->setChecked(m_pDeviceForm          m_ui.viewDevicesAction->setChecked(m_pDeviceForm
1933                  && m_pDeviceForm->isVisible());                  && m_pDeviceForm->isVisible());
1934          m_ui.viewDevicesAction->setEnabled(bHasClient);          m_ui.viewDevicesAction->setEnabled(bHasClient);
1935          m_ui.channelsArrangeAction->setEnabled(bHasChannel);          m_ui.viewMidiDeviceStatusMenu->setEnabled(
1936                    DeviceStatusForm::getInstances().size() > 0);
1937            m_ui.channelsArrangeAction->setEnabled(bHasChannels);
1938    
1939  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
1940          // Toolbar widgets are also affected...          // Toolbar widgets are also affected...
# Line 1910  void MainForm::updateSession (void) Line 2038  void MainForm::updateSession (void)
2038          }          }
2039  #endif  #endif
2040    
2041            updateAllChannelStrips(false);
2042    
2043            // Do we auto-arrange?
2044            if (m_pOptions && m_pOptions->bAutoArrange)
2045                    channelsArrange();
2046    
2047            // Remember to refresh devices and instruments...
2048            if (m_pInstrumentListForm)
2049                    m_pInstrumentListForm->refreshInstruments();
2050            if (m_pDeviceForm)
2051                    m_pDeviceForm->refreshDevices();
2052    }
2053    
2054    void MainForm::updateAllChannelStrips(bool bRemoveDeadStrips) {
2055          // Retrieve the current channel list.          // Retrieve the current channel list.
2056          int *piChannelIDs = ::lscp_list_channels(m_pClient);          int *piChannelIDs = ::lscp_list_channels(m_pClient);
2057          if (piChannelIDs == NULL) {          if (piChannelIDs == NULL) {
# Line 1924  void MainForm::updateSession (void) Line 2066  void MainForm::updateSession (void)
2066                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {
2067                          // Check if theres already a channel strip for this one...                          // Check if theres already a channel strip for this one...
2068                          if (!channelStrip(piChannelIDs[iChannel]))                          if (!channelStrip(piChannelIDs[iChannel]))
2069                                  createChannelStrip(new qsamplerChannel(piChannelIDs[iChannel]));                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));
2070                  }                  }
                 m_pWorkspace->setUpdatesEnabled(true);  
         }  
2071    
2072          // Do we auto-arrange?                  // Do we auto-arrange?
2073          if (m_pOptions && m_pOptions->bAutoArrange)                  if (m_pOptions && m_pOptions->bAutoArrange)
2074                  channelsArrange();                          channelsArrange();
2075    
2076          // Remember to refresh devices and instruments...                  stabilizeForm();
         if (m_pInstrumentListForm)  
                 m_pInstrumentListForm->refreshInstruments();  
         if (m_pDeviceForm)  
                 m_pDeviceForm->refreshDevices();  
 }  
2077    
2078                    // remove dead channel strips
2079                    if (bRemoveDeadStrips) {
2080                            for (int i = 0; channelStripAt(i); ++i) {
2081                                    ChannelStrip* pChannelStrip = channelStripAt(i);
2082                                    bool bExists = false;
2083                                    for (int j = 0; piChannelIDs[j] >= 0; ++j) {
2084                                            if (!pChannelStrip->channel()) break;
2085                                            if (piChannelIDs[j] == pChannelStrip->channel()->channelID()) {
2086                                                    // strip exists, don't touch it
2087                                                    bExists = true;
2088                                                    break;
2089                                            }
2090                                    }
2091                                    if (!bExists) destroyChannelStrip(pChannelStrip);
2092                            }
2093                    }
2094                    m_pWorkspace->setUpdatesEnabled(true);
2095            }
2096    }
2097    
2098  // Update the recent files list and menu.  // Update the recent files list and menu.
2099  void MainForm::updateRecentFiles ( const QString& sFilename )  void MainForm::updateRecentFiles ( const QString& sFilename )
# Line 2113  void MainForm::appendMessagesError( cons Line 2267  void MainForm::appendMessagesError( cons
2267          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2268    
2269          QMessageBox::critical(this,          QMessageBox::critical(this,
2270                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));                  QSAMPLER_TITLE ": " + tr("Error"), s, QMessageBox::Cancel);
2271  }  }
2272    
2273    
# Line 2176  void MainForm::updateMessagesCapture (vo Line 2330  void MainForm::updateMessagesCapture (vo
2330  // qsamplerMainForm -- MDI channel strip management.  // qsamplerMainForm -- MDI channel strip management.
2331    
2332  // The channel strip creation executive.  // The channel strip creation executive.
2333  ChannelStrip* MainForm::createChannelStrip ( qsamplerChannel *pChannel )  ChannelStrip* MainForm::createChannelStrip ( Channel *pChannel )
2334  {  {
2335          if (m_pClient == NULL || pChannel == NULL)          if (m_pClient == NULL || pChannel == NULL)
2336                  return NULL;                  return NULL;
# Line 2218  ChannelStrip* MainForm::createChannelStr Line 2372  ChannelStrip* MainForm::createChannelStr
2372          return pChannelStrip;          return pChannelStrip;
2373  }  }
2374    
2375    void MainForm::destroyChannelStrip(ChannelStrip* pChannelStrip) {
2376            // Just delete the channel strip.
2377            delete pChannelStrip;
2378    
2379            // Do we auto-arrange?
2380            if (m_pOptions && m_pOptions->bAutoArrange)
2381                    channelsArrange();
2382    
2383            stabilizeForm();
2384    }
2385    
2386  // Retrieve the active channel strip.  // Retrieve the active channel strip.
2387  ChannelStrip* MainForm::activeChannelStrip (void)  ChannelStrip* MainForm::activeChannelStrip (void)
# Line 2229  ChannelStrip* MainForm::activeChannelStr Line 2393  ChannelStrip* MainForm::activeChannelStr
2393  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
2394  ChannelStrip* MainForm::channelStripAt ( int iChannel )  ChannelStrip* MainForm::channelStripAt ( int iChannel )
2395  {  {
2396            if (!m_pWorkspace) return NULL;
2397    
2398          QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2399          if (wlist.isEmpty())          if (wlist.isEmpty())
2400                  return NULL;                  return NULL;
2401    
2402          return static_cast<ChannelStrip *> (wlist.at(iChannel));          if (iChannel < 0 || iChannel >= wlist.size())
2403                    return NULL;
2404    
2405            return dynamic_cast<ChannelStrip *> (wlist.at(iChannel));
2406  }  }
2407    
2408    
# Line 2248  ChannelStrip* MainForm::channelStrip ( i Line 2417  ChannelStrip* MainForm::channelStrip ( i
2417                  ChannelStrip* pChannelStrip                  ChannelStrip* pChannelStrip
2418                          = static_cast<ChannelStrip*> (wlist.at(iChannel));                          = static_cast<ChannelStrip*> (wlist.at(iChannel));
2419                  if (pChannelStrip) {                  if (pChannelStrip) {
2420                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
2421                          if (pChannel && pChannel->channelID() == iChannelID)                          if (pChannel && pChannel->channelID() == iChannelID)
2422                                  return pChannelStrip;                                  return pChannelStrip;
2423                  }                  }
# Line 2386  void MainForm::startServer (void) Line 2555  void MainForm::startServer (void)
2555    
2556          // Is the server process instance still here?          // Is the server process instance still here?
2557          if (m_pServer) {          if (m_pServer) {
2558                  switch (QMessageBox::warning(this,                  if (QMessageBox::warning(this,
2559                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
2560                          tr("Could not start the LinuxSampler server.\n\n"                          tr("Could not start the LinuxSampler server.\n\n"
2561                          "Maybe it ss already started."),                          "Maybe it is already started."),
2562                          tr("Stop"), tr("Kill"), tr("Cancel"))) {                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
                 case 0:  
2563                          m_pServer->terminate();                          m_pServer->terminate();
                         break;  
                 case 1:  
2564                          m_pServer->kill();                          m_pServer->kill();
                         break;  
2565                  }                  }
2566                  return;                  return;
2567          }          }
# Line 2409  void MainForm::startServer (void) Line 2574  void MainForm::startServer (void)
2574                  return;                  return;
2575    
2576          // OK. Let's build the startup process...          // OK. Let's build the startup process...
2577          m_pServer = new QProcess(this);          m_pServer = new QProcess();
2578            bForceServerStop = true;
2579    
2580          // Setup stdout/stderr capture...          // Setup stdout/stderr capture...
2581  //      if (m_pOptions->bStdoutCapture) {  //      if (m_pOptions->bStdoutCapture) {
2582                  //m_pServer->setProcessChannelMode(  #if QT_VERSION >= 0x040200
2583                  //      QProcess::StandardOutput);                  m_pServer->setProcessChannelMode(QProcess::ForwardedChannels);
2584    #endif
2585                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2586                          SIGNAL(readyReadStandardOutput()),                          SIGNAL(readyReadStandardOutput()),
2587                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
# Line 2425  void MainForm::startServer (void) Line 2592  void MainForm::startServer (void)
2592    
2593          // The unforgiveable signal communication...          // The unforgiveable signal communication...
2594          QObject::connect(m_pServer,          QObject::connect(m_pServer,
2595                  SIGNAL(finished(int,QProcess::ExitStatus)),                  SIGNAL(finished(int, QProcess::ExitStatus)),
2596                  SLOT(processServerExit()));                  SLOT(processServerExit()));
2597    
2598          // Build process arguments...          // Build process arguments...
# Line 2456  void MainForm::startServer (void) Line 2623  void MainForm::startServer (void)
2623    
2624    
2625  // Stop linuxsampler server...  // Stop linuxsampler server...
2626  void MainForm::stopServer (void)  void MainForm::stopServer (bool bInteractive)
2627  {  {
2628          // Stop client code.          // Stop client code.
2629          stopClient();          stopClient();
2630    
2631            if (m_pServer && bInteractive) {
2632                    if (QMessageBox::question(this,
2633                            QSAMPLER_TITLE ": " + tr("The backend's fate ..."),
2634                            tr("You have the option to keep the sampler backend (LinuxSampler)\n"
2635                            "running in the background. The sampler would continue to work\n"
2636                            "according to your current sampler session and you could alter the\n"
2637                            "sampler session at any time by relaunching QSampler.\n\n"
2638                            "Do you want LinuxSampler to stop?"),
2639                            QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
2640                    {
2641                            bForceServerStop = false;
2642                    }
2643            }
2644    
2645          // And try to stop server.          // And try to stop server.
2646          if (m_pServer) {          if (m_pServer && bForceServerStop) {
2647                  appendMessages(tr("Server is stopping..."));                  appendMessages(tr("Server is stopping..."));
2648                  if (m_pServer->state() == QProcess::Running)                  if (m_pServer->state() == QProcess::Running) {
2649    #if defined(WIN32)
2650                            // Try harder...
2651                            m_pServer->kill();
2652    #else
2653                            // Try softly...
2654                          m_pServer->terminate();                          m_pServer->terminate();
2655          }  #endif
2656                    }
2657            }       // Do final processing anyway.
2658            else processServerExit();
2659    
2660          // Give it some time to terminate gracefully and stabilize...          // Give it some time to terminate gracefully and stabilize...
2661          QTime t;          QTime t;
2662          t.start();          t.start();
2663          while (t.elapsed() < QSAMPLER_TIMER_MSECS)          while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2664                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
   
         // Do final processing anyway.  
         processServerExit();  
2665  }  }
2666    
2667    
# Line 2497  void MainForm::processServerExit (void) Line 2683  void MainForm::processServerExit (void)
2683          if (m_pMessages)          if (m_pMessages)
2684                  m_pMessages->flushStdoutBuffer();                  m_pMessages->flushStdoutBuffer();
2685    
2686          if (m_pServer) {          if (m_pServer && bForceServerStop) {
2687                    if (m_pServer->state() != QProcess::NotRunning) {
2688                            appendMessages(tr("Server is being forced..."));
2689                            // Force final server shutdown...
2690                            m_pServer->kill();
2691                            // Give it some time to terminate gracefully and stabilize...
2692                            QTime t;
2693                            t.start();
2694                            while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2695                                    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2696                    }
2697                  // Force final server shutdown...                  // Force final server shutdown...
2698                  appendMessages(                  appendMessages(
2699                          tr("Server was stopped with exit status %1.")                          tr("Server was stopped with exit status %1.")
2700                          .arg(m_pServer->exitStatus()));                          .arg(m_pServer->exitStatus()));
                 m_pServer->terminate();  
                 if (!m_pServer->waitForFinished(2000))  
                         m_pServer->kill();  
                 // Destroy it.  
2701                  delete m_pServer;                  delete m_pServer;
2702                  m_pServer = NULL;                  m_pServer = NULL;
2703          }          }
# Line 2530  lscp_status_t qsampler_client_callback ( Line 2722  lscp_status_t qsampler_client_callback (
2722          // as this is run under some other thread context.          // as this is run under some other thread context.
2723          // A custom event must be posted here...          // A custom event must be posted here...
2724          QApplication::postEvent(pMainForm,          QApplication::postEvent(pMainForm,
2725                  new qsamplerCustomEvent(event, pchData, cchData));                  new LscpEvent(event, pchData, cchData));
2726    
2727          return LSCP_OK;          return LSCP_OK;
2728  }  }
# Line 2575  bool MainForm::startClient (void) Line 2767  bool MainForm::startClient (void)
2767                  .arg(::lscp_client_get_timeout(m_pClient)));                  .arg(::lscp_client_get_timeout(m_pClient)));
2768    
2769          // Subscribe to channel info change notifications...          // Subscribe to channel info change notifications...
2770            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT) != LSCP_OK)
2771                    appendMessagesClient("lscp_client_subscribe(CHANNEL_COUNT)");
2772          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)
2773                  appendMessagesClient("lscp_client_subscribe");                  appendMessagesClient("lscp_client_subscribe(CHANNEL_INFO)");
2774    
2775            DeviceStatusForm::onDevicesChanged(); // initialize
2776            updateViewMidiDeviceStatusMenu();
2777            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT) != LSCP_OK)
2778                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_COUNT)");
2779            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO) != LSCP_OK)
2780                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_INFO)");
2781            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT) != LSCP_OK)
2782                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_COUNT)");
2783            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO) != LSCP_OK)
2784                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_INFO)");
2785    
2786    #if CONFIG_EVENT_CHANNEL_MIDI
2787            // Subscribe to channel MIDI data notifications...
2788            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI) != LSCP_OK)
2789                    appendMessagesClient("lscp_client_subscribe(CHANNEL_MIDI)");
2790    #endif
2791    
2792    #if CONFIG_EVENT_DEVICE_MIDI
2793            // Subscribe to channel MIDI data notifications...
2794            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI) != LSCP_OK)
2795                    appendMessagesClient("lscp_client_subscribe(DEVICE_MIDI)");
2796    #endif
2797    
2798          // We may stop scheduling around.          // We may stop scheduling around.
2799          stopSchedule();          stopSchedule();
# Line 2603  bool MainForm::startClient (void) Line 2820  bool MainForm::startClient (void)
2820                  }                  }
2821          }          }
2822    
2823            // send the current / loaded fine tuning settings to the sampler
2824            m_pOptions->sendFineTuningSettings();
2825    
2826          // Make a new session          // Make a new session
2827          return newSession();          return newSession();
2828  }  }
# Line 2630  void MainForm::stopClient (void) Line 2850  void MainForm::stopClient (void)
2850          closeSession(false);          closeSession(false);
2851    
2852          // Close us as a client...          // Close us as a client...
2853    #if CONFIG_EVENT_DEVICE_MIDI
2854            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI);
2855    #endif
2856    #if CONFIG_EVENT_CHANNEL_MIDI
2857            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI);
2858    #endif
2859            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
2860            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
2861            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
2862            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
2863          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
2864            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT);
2865          ::lscp_client_destroy(m_pClient);          ::lscp_client_destroy(m_pClient);
2866          m_pClient = NULL;          m_pClient = NULL;
2867    

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

  ViewVC Help
Powered by ViewVC