/[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 1890 by capela, Tue Apr 28 09:06:43 2009 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-2009, 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 77  static inline long lroundf ( float x ) Line 78  static inline long lroundf ( float x )
78  }  }
79  #endif  #endif
80    
81    
82    // All winsock apps needs this.
83    #if defined(WIN32)
84    static WSADATA _wsaData;
85    #endif
86    
87    
88    namespace QSampler {
89    
90  // Timer constant stuff.  // Timer constant stuff.
91  #define QSAMPLER_TIMER_MSECS    200  #define QSAMPLER_TIMER_MSECS    200
92    
# Line 87  static inline long lroundf ( float x ) Line 97  static inline long lroundf ( float x )
97  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.
98    
99    
 // All winsock apps needs this.  
 #if defined(WIN32)  
 static WSADATA _wsaData;  
 #endif  
   
   
100  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
101  // qsamplerCustomEvent -- specialty for callback comunication.  // CustomEvent -- specialty for callback comunication.
102    
103  #define QSAMPLER_CUSTOM_EVENT   QEvent::Type(QEvent::User + 0)  #define QSAMPLER_CUSTOM_EVENT   QEvent::Type(QEvent::User + 0)
104    
105  class qsamplerCustomEvent : public QEvent  class CustomEvent : public QEvent
106  {  {
107  public:  public:
108    
109          // Constructor.          // Constructor.
110          qsamplerCustomEvent(lscp_event_t event, const char *pchData, int cchData)          CustomEvent(lscp_event_t event, const char *pchData, int cchData)
111                  : QEvent(QSAMPLER_CUSTOM_EVENT)                  : QEvent(QSAMPLER_CUSTOM_EVENT)
112          {          {
113                  m_event = event;                  m_event = event;
# Line 126  private: Line 130  private:
130  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
131  // qsamplerMainForm -- Main window form implementation.  // qsamplerMainForm -- Main window form implementation.
132    
 namespace QSampler {  
   
133  // Kind of singleton reference.  // Kind of singleton reference.
134  MainForm* MainForm::g_pMainForm = NULL;  MainForm* MainForm::g_pMainForm = NULL;
135    
# Line 366  MainForm::~MainForm() Line 368  MainForm::~MainForm()
368    
369    
370  // Make and set a proper setup options step.  // Make and set a proper setup options step.
371  void MainForm::setup ( qsamplerOptions *pOptions )  void MainForm::setup ( Options *pOptions )
372  {  {
373          // We got options?          // We got options?
374          m_pOptions = pOptions;          m_pOptions = pOptions;
# Line 382  void MainForm::setup ( qsamplerOptions * Line 384  void MainForm::setup ( qsamplerOptions *
384          if (m_pOptions->bKeepOnTop)          if (m_pOptions->bKeepOnTop)
385                  wflags |= Qt::Tool;                  wflags |= Qt::Tool;
386          // Some child forms are to be created right now.          // Some child forms are to be created right now.
387          m_pMessages = new qsamplerMessages(this);          m_pMessages = new Messages(this);
388          m_pDeviceForm = new DeviceForm(this, wflags);          m_pDeviceForm = new DeviceForm(this, wflags);
389  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
390          m_pInstrumentListForm = new InstrumentListForm(this, wflags);          m_pInstrumentListForm = new InstrumentListForm(this, wflags);
391  #else  #else
392          viewInstrumentsAction->setEnabled(false);          viewInstrumentsAction->setEnabled(false);
393  #endif  #endif
394            // Setup messages logging appropriately...
395            m_pMessages->setLogging(
396                    m_pOptions->bMessagesLog,
397                    m_pOptions->sMessagesLogPath);
398          // Set message defaults...          // Set message defaults...
399          updateMessagesFont();          updateMessagesFont();
400          updateMessagesLimit();          updateMessagesLimit();
# Line 470  bool MainForm::queryClose (void) Line 476  bool MainForm::queryClose (void)
476                          if (m_pDeviceForm)                          if (m_pDeviceForm)
477                                  m_pDeviceForm->close();                                  m_pDeviceForm->close();
478                          // Stop client and/or server, gracefully.                          // Stop client and/or server, gracefully.
479                          stopServer();                          stopServer(true /*interactive*/);
480                  }                  }
481          }          }
482    
# Line 480  bool MainForm::queryClose (void) Line 486  bool MainForm::queryClose (void)
486    
487  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )
488  {  {
489          if (queryClose())          if (queryClose()) {
490                    DeviceStatusForm::deleteAllInstances();
491                  pCloseEvent->accept();                  pCloseEvent->accept();
492          else          } else
493                  pCloseEvent->ignore();                  pCloseEvent->ignore();
494  }  }
495    
# Line 511  void MainForm::dropEvent ( QDropEvent* p Line 518  void MainForm::dropEvent ( QDropEvent* p
518                  QListIterator<QUrl> iter(pMimeData->urls());                  QListIterator<QUrl> iter(pMimeData->urls());
519                  while (iter.hasNext()) {                  while (iter.hasNext()) {
520                          const QString& sPath = iter.next().toLocalFile();                          const QString& sPath = iter.next().toLocalFile();
521                          if (qsamplerChannel::isInstrumentFile(sPath)) {                          if (Channel::isInstrumentFile(sPath)) {
522                                  // Try to create a new channel from instrument file...                                  // Try to create a new channel from instrument file...
523                                  qsamplerChannel *pChannel = new qsamplerChannel();                                  Channel *pChannel = new Channel();
524                                  if (pChannel == NULL)                                  if (pChannel == NULL)
525                                          return;                                          return;
526                                  // Start setting the instrument filename...                                  // Start setting the instrument filename...
# Line 549  void MainForm::customEvent(QEvent* pCust Line 556  void MainForm::customEvent(QEvent* pCust
556  {  {
557          // For the time being, just pump it to messages.          // For the time being, just pump it to messages.
558          if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {          if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {
559                  qsamplerCustomEvent *pEvent = (qsamplerCustomEvent *) pCustomEvent;                  CustomEvent *pEvent = static_cast<CustomEvent *> (pCustomEvent);
560                  if (pEvent->event() == LSCP_EVENT_CHANNEL_INFO) {                  switch (pEvent->event()) {
561                          int iChannelID = pEvent->data().toInt();                          case LSCP_EVENT_CHANNEL_COUNT:
562                          ChannelStrip *pChannelStrip = channelStrip(iChannelID);                                  updateAllChannelStrips(true);
563                          if (pChannelStrip)                                  break;
564                                  channelStripChanged(pChannelStrip);                          case LSCP_EVENT_CHANNEL_INFO: {
565                  } else {                                  int iChannelID = pEvent->data().toInt();
566                          appendMessagesColor(tr("Notify event: %1 data: %2")                                  ChannelStrip *pChannelStrip = channelStrip(iChannelID);
567                                  .arg(::lscp_event_to_text(pEvent->event()))                                  if (pChannelStrip)
568                                  .arg(pEvent->data()), "#996699");                                          channelStripChanged(pChannelStrip);
569                                    break;
570                            }
571                            case LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT:
572                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
573                                    DeviceStatusForm::onDevicesChanged();
574                                    updateViewMidiDeviceStatusMenu();
575                                    break;
576                            case LSCP_EVENT_MIDI_INPUT_DEVICE_INFO: {
577                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
578                                    const int iDeviceID = pEvent->data().section(' ', 0, 0).toInt();
579                                    DeviceStatusForm::onDeviceChanged(iDeviceID);
580                                    break;
581                            }
582                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT:
583                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
584                                    break;
585                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO:
586                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
587                                    break;
588    #if CONFIG_EVENT_CHANNEL_MIDI
589                            case LSCP_EVENT_CHANNEL_MIDI: {
590                                    const int iChannelID = pEvent->data().section(' ', 0, 0).toInt();
591                                    ChannelStrip *pChannelStrip = channelStrip(iChannelID);
592                                    if (pChannelStrip)
593                                            pChannelStrip->midiArrived();
594                                    break;
595                            }
596    #endif
597    #if CONFIG_EVENT_DEVICE_MIDI
598                            case LSCP_EVENT_DEVICE_MIDI: {
599                                    const int iDeviceID = pEvent->data().section(' ', 0, 0).toInt();
600                                    const int iPortID   = pEvent->data().section(' ', 1, 1).toInt();
601                                    DeviceStatusForm* pDeviceStatusForm =
602                                            DeviceStatusForm::getInstance(iDeviceID);
603                                    if (pDeviceStatusForm)
604                                            pDeviceStatusForm->midiArrived(iPortID);
605                                    break;
606                            }
607    #endif
608                            default:
609                                    appendMessagesColor(tr("Notify event: %1 data: %2")
610                                            .arg(::lscp_event_to_text(pEvent->event()))
611                                            .arg(pEvent->data()), "#996699");
612                  }                  }
613          }          }
614  }  }
615    
616    void MainForm::updateViewMidiDeviceStatusMenu() {
617            m_ui.viewMidiDeviceStatusMenu->clear();
618            const std::map<int, DeviceStatusForm*> statusForms =
619                    DeviceStatusForm::getInstances();
620            for (
621                    std::map<int, DeviceStatusForm*>::const_iterator iter = statusForms.begin();
622                    iter != statusForms.end(); ++iter
623            ) {
624                    DeviceStatusForm* pForm = iter->second;
625                    m_ui.viewMidiDeviceStatusMenu->addAction(
626                            pForm->visibleAction()
627                    );
628            }
629    }
630    
631  // Context menu event handler.  // Context menu event handler.
632  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )
633  {  {
# Line 576  void MainForm::contextMenuEvent( QContex Line 641  void MainForm::contextMenuEvent( QContex
641  // qsamplerMainForm -- Brainless public property accessors.  // qsamplerMainForm -- Brainless public property accessors.
642    
643  // The global options settings property.  // The global options settings property.
644  qsamplerOptions *MainForm::options (void) const  Options *MainForm::options (void) const
645  {  {
646          return m_pOptions;          return m_pOptions;
647  }  }
# Line 694  bool MainForm::saveSession ( bool bPromp Line 759  bool MainForm::saveSession ( bool bPromp
759                                  "\"%1\"\n\n"                                  "\"%1\"\n\n"
760                                  "Do you want to replace it?")                                  "Do you want to replace it?")
761                                  .arg(sFilename),                                  .arg(sFilename),
762                                  tr("Replace"), tr("Cancel")) > 0)                                  QMessageBox::Yes | QMessageBox::No)
763                                    == QMessageBox::No)
764                                  return false;                                  return false;
765                  }                  }
766          }          }
# Line 717  bool MainForm::closeSession ( bool bForc Line 783  bool MainForm::closeSession ( bool bForc
783                          "\"%1\"\n\n"                          "\"%1\"\n\n"
784                          "Do you want to save the changes?")                          "Do you want to save the changes?")
785                          .arg(sessionName(m_sFilename)),                          .arg(sessionName(m_sFilename)),
786                          tr("Save"), tr("Discard"), tr("Cancel"))) {                          QMessageBox::Save |
787                  case 0:     // Save...                          QMessageBox::Discard |
788                            QMessageBox::Cancel)) {
789                    case QMessageBox::Save:
790                          bClose = saveSession(false);                          bClose = saveSession(false);
791                          // Fall thru....                          // Fall thru....
792                  case 1:     // Discard                  case QMessageBox::Discard:
793                          break;                          break;
794                  default:    // Cancel.                  default:    // Cancel.
795                          bClose = false;                          bClose = false;
# Line 737  bool MainForm::closeSession ( bool bForc Line 805  bool MainForm::closeSession ( bool bForc
805                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
806                          ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                          ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
807                          if (pChannelStrip) {                          if (pChannelStrip) {
808                                  qsamplerChannel *pChannel = pChannelStrip->channel();                                  Channel *pChannel = pChannelStrip->channel();
809                                  if (bForce && pChannel)                                  if (bForce && pChannel)
810                                          pChannel->removeChannel();                                          pChannel->removeChannel();
811                                  delete pChannelStrip;                                  delete pChannelStrip;
# Line 877  bool MainForm::saveSessionFile ( const Q Line 945  bool MainForm::saveSessionFile ( const Q
945    
946          // Audio device mapping.          // Audio device mapping.
947          QMap<int, int> audioDeviceMap;          QMap<int, int> audioDeviceMap;
948          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Audio);          piDeviceIDs = Device::getDevices(m_pClient, Device::Audio);
949          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
950                  ts << endl;                  ts << endl;
951                  qsamplerDevice device(qsamplerDevice::Audio, piDeviceIDs[iDevice]);                  Device device(Device::Audio, piDeviceIDs[iDevice]);
952                  // Audio device specification...                  // Audio device specification...
953                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
954                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
955                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();
956                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
957                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
958                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
959                                          ++deviceParam) {                                          ++deviceParam) {
960                          const qsamplerDeviceParam& param = deviceParam.value();                          const DeviceParam& param = deviceParam.value();
961                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
962                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
963                  }                  }
964                  ts << endl;                  ts << endl;
965                  // Audio channel parameters...                  // Audio channel parameters...
966                  int iPort = 0;                  int iPort = 0;
967                  QListIterator<qsamplerDevicePort *> iter(device.ports());                  QListIterator<DevicePort *> iter(device.ports());
968                  while (iter.hasNext()) {                  while (iter.hasNext()) {
969                          qsamplerDevicePort *pPort = iter.next();                          DevicePort *pPort = iter.next();
970                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
971                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
972                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
973                                                  ++portParam) {                                                  ++portParam) {
974                                  const qsamplerDeviceParam& param = portParam.value();                                  const DeviceParam& param = portParam.value();
975                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
976                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice
977                                          << " " << iPort << " " << portParam.key()                                          << " " << iPort << " " << portParam.key()
# Line 919  bool MainForm::saveSessionFile ( const Q Line 987  bool MainForm::saveSessionFile ( const Q
987    
988          // MIDI device mapping.          // MIDI device mapping.
989          QMap<int, int> midiDeviceMap;          QMap<int, int> midiDeviceMap;
990          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Midi);          piDeviceIDs = Device::getDevices(m_pClient, Device::Midi);
991          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
992                  ts << endl;                  ts << endl;
993                  qsamplerDevice device(qsamplerDevice::Midi, piDeviceIDs[iDevice]);                  Device device(Device::Midi, piDeviceIDs[iDevice]);
994                  // MIDI device specification...                  // MIDI device specification...
995                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
996                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
997                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();
998                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
999                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
1000                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
1001                                          ++deviceParam) {                                          ++deviceParam) {
1002                          const qsamplerDeviceParam& param = deviceParam.value();                          const DeviceParam& param = deviceParam.value();
1003                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
1004                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
1005                  }                  }
1006                  ts << endl;                  ts << endl;
1007                  // MIDI port parameters...                  // MIDI port parameters...
1008                  int iPort = 0;                  int iPort = 0;
1009                  QListIterator<qsamplerDevicePort *> iter(device.ports());                  QListIterator<DevicePort *> iter(device.ports());
1010                  while (iter.hasNext()) {                  while (iter.hasNext()) {
1011                          qsamplerDevicePort *pPort = iter.next();                          DevicePort *pPort = iter.next();
1012                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1013                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1014                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1015                                                  ++portParam) {                                                  ++portParam) {
1016                                  const qsamplerDeviceParam& param = portParam.value();                                  const DeviceParam& param = portParam.value();
1017                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1018                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice
1019                                  << " " << iPort << " " << portParam.key()                                  << " " << iPort << " " << portParam.key()
# Line 1037  bool MainForm::saveSessionFile ( const Q Line 1105  bool MainForm::saveSessionFile ( const Q
1105                  ChannelStrip* pChannelStrip                  ChannelStrip* pChannelStrip
1106                          = static_cast<ChannelStrip *> (wlist.at(iChannel));                          = static_cast<ChannelStrip *> (wlist.at(iChannel));
1107                  if (pChannelStrip) {                  if (pChannelStrip) {
1108                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
1109                          if (pChannel) {                          if (pChannel) {
1110                                  ts << "# " << tr("Channel") << " " << iChannel << endl;                                  ts << "# " << tr("Channel") << " " << iChannel << endl;
1111                                  ts << "ADD CHANNEL" << endl;                                  ts << "ADD CHANNEL" << endl;
# Line 1069  bool MainForm::saveSessionFile ( const Q Line 1137  bool MainForm::saveSessionFile ( const Q
1137                                  ts << "LOAD INSTRUMENT NON_MODAL '"                                  ts << "LOAD INSTRUMENT NON_MODAL '"
1138                                          << pChannel->instrumentFile() << "' "                                          << pChannel->instrumentFile() << "' "
1139                                          << pChannel->instrumentNr() << " " << iChannel << endl;                                          << pChannel->instrumentNr() << " " << iChannel << endl;
1140                                  qsamplerChannelRoutingMap::ConstIterator audioRoute;                                  ChannelRoutingMap::ConstIterator audioRoute;
1141                                  for (audioRoute = pChannel->audioRouting().begin();                                  for (audioRoute = pChannel->audioRouting().begin();
1142                                                  audioRoute != pChannel->audioRouting().end();                                                  audioRoute != pChannel->audioRouting().end();
1143                                                          ++audioRoute) {                                                          ++audioRoute) {
# Line 1242  void MainForm::fileReset (void) Line 1310  void MainForm::fileReset (void)
1310                  "Please note that this operation may cause\n"                  "Please note that this operation may cause\n"
1311                  "temporary MIDI and Audio disruption.\n\n"                  "temporary MIDI and Audio disruption.\n\n"
1312                  "Do you want to reset the sampler engine now?"),                  "Do you want to reset the sampler engine now?"),
1313                  tr("Reset"), tr("Cancel")) > 0)                  QMessageBox::Ok | QMessageBox::Cancel)
1314                    == QMessageBox::Cancel)
1315                  return;                  return;
1316    
1317          // Trye closing the current session, first...          // Trye closing the current session, first...
# Line 1283  void MainForm::fileRestart (void) Line 1352  void MainForm::fileRestart (void)
1352                          "Please note that this operation may cause\n"                          "Please note that this operation may cause\n"
1353                          "temporary MIDI and Audio disruption.\n\n"                          "temporary MIDI and Audio disruption.\n\n"
1354                          "Do you want to restart the connection now?"),                          "Do you want to restart the connection now?"),
1355                          tr("Restart"), tr("Cancel")) == 0);                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok);
1356          }          }
1357    
1358          // Are we still for it?          // Are we still for it?
# Line 1314  void MainForm::editAddChannel (void) Line 1383  void MainForm::editAddChannel (void)
1383                  return;                  return;
1384    
1385          // Just create the channel instance...          // Just create the channel instance...
1386          qsamplerChannel *pChannel = new qsamplerChannel();          Channel *pChannel = new Channel();
1387          if (pChannel == NULL)          if (pChannel == NULL)
1388                  return;                  return;
1389    
# Line 1352  void MainForm::editRemoveChannel (void) Line 1421  void MainForm::editRemoveChannel (void)
1421          if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1422                  return;                  return;
1423    
1424          qsamplerChannel *pChannel = pChannelStrip->channel();          Channel *pChannel = pChannelStrip->channel();
1425          if (pChannel == NULL)          if (pChannel == NULL)
1426                  return;                  return;
1427    
# Line 1364  void MainForm::editRemoveChannel (void) Line 1433  void MainForm::editRemoveChannel (void)
1433                          "%1\n\n"                          "%1\n\n"
1434                          "Are you sure?")                          "Are you sure?")
1435                          .arg(pChannelStrip->windowTitle()),                          .arg(pChannelStrip->windowTitle()),
1436                          tr("OK"), tr("Cancel")) > 0)                          QMessageBox::Ok | QMessageBox::Cancel)
1437                            == QMessageBox::Cancel)
1438                          return;                          return;
1439          }          }
1440    
# Line 1555  void MainForm::viewOptions (void) Line 1625  void MainForm::viewOptions (void)
1625                  int     iOldServerTimeout   = m_pOptions->iServerTimeout;                  int     iOldServerTimeout   = m_pOptions->iServerTimeout;
1626                  bool    bOldServerStart     = m_pOptions->bServerStart;                  bool    bOldServerStart     = m_pOptions->bServerStart;
1627                  QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;                  QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;
1628                    bool    bOldMessagesLog     = m_pOptions->bMessagesLog;
1629                    QString sOldMessagesLogPath = m_pOptions->sMessagesLogPath;
1630                  QString sOldDisplayFont     = m_pOptions->sDisplayFont;                  QString sOldDisplayFont     = m_pOptions->sDisplayFont;
1631                  bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;                  bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;
1632                  int     iOldMaxVolume       = m_pOptions->iMaxVolume;                  int     iOldMaxVolume       = m_pOptions->iMaxVolume;
# Line 1566  void MainForm::viewOptions (void) Line 1638  void MainForm::viewOptions (void)
1638                  bool    bOldCompletePath    = m_pOptions->bCompletePath;                  bool    bOldCompletePath    = m_pOptions->bCompletePath;
1639                  bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;                  bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;
1640                  int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;                  int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;
1641                    int     iOldBaseFontSize    = m_pOptions->iBaseFontSize;
1642                  // Load the current setup settings.                  // Load the current setup settings.
1643                  pOptionsForm->setup(m_pOptions);                  pOptionsForm->setup(m_pOptions);
1644                  // Show the setup dialog...                  // Show the setup dialog...
# Line 1574  void MainForm::viewOptions (void) Line 1647  void MainForm::viewOptions (void)
1647                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1648                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||
1649                                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||                                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||
1650                                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {                                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)     ||
1651                                    (iOldBaseFontSize   !=  m_pOptions->iBaseFontSize)) {
1652                                  QMessageBox::information(this,                                  QMessageBox::information(this,
1653                                          QSAMPLER_TITLE ": " + tr("Information"),                                          QSAMPLER_TITLE ": " + tr("Information"),
1654                                          tr("Some settings may be only effective\n"                                          tr("Some settings may be only effective\n"
1655                                          "next time you start this program."), tr("OK"));                                          "next time you start this program."));
1656                                  updateMessagesCapture();                                  updateMessagesCapture();
1657                          }                          }
1658                          // Check wheather something immediate has changed.                          // Check wheather something immediate has changed.
1659                            if (( bOldMessagesLog && !m_pOptions->bMessagesLog) ||
1660                                    (!bOldMessagesLog &&  m_pOptions->bMessagesLog) ||
1661                                    (sOldMessagesLogPath != m_pOptions->sMessagesLogPath))
1662                                    m_pMessages->setLogging(
1663                                            m_pOptions->bMessagesLog, m_pOptions->sMessagesLogPath);
1664                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||
1665                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||
1666                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
# Line 1736  void MainForm::helpAbout (void) Line 1815  void MainForm::helpAbout (void)
1815          sText += tr("Instrument editing support disabled.");          sText += tr("Instrument editing support disabled.");
1816          sText += "</font></small><br />";          sText += "</font></small><br />";
1817  #endif  #endif
1818    #ifndef CONFIG_EVENT_CHANNEL_MIDI
1819            sText += "<small><font color=\"red\">";
1820            sText += tr("Channel MIDI event support disabled.");
1821            sText += "</font></small><br />";
1822    #endif
1823    #ifndef CONFIG_EVENT_DEVICE_MIDI
1824            sText += "<small><font color=\"red\">";
1825            sText += tr("Device MIDI event support disabled.");
1826            sText += "</font></small><br />";
1827    #endif
1828    #ifndef CONFIG_MAX_VOICES
1829            sText += "<small><font color=\"red\">";
1830            sText += tr("Runtime max. voices / disk streams support disabled.");
1831            sText += "</font></small><br />";
1832    #endif
1833          sText += "<br />\n";          sText += "<br />\n";
1834          sText += tr("Using") + ": ";          sText += tr("Using") + ": ";
1835          sText += ::lscp_client_package();          sText += ::lscp_client_package();
# Line 1910  void MainForm::updateSession (void) Line 2004  void MainForm::updateSession (void)
2004          }          }
2005  #endif  #endif
2006    
2007            updateAllChannelStrips(false);
2008    
2009            // Do we auto-arrange?
2010            if (m_pOptions && m_pOptions->bAutoArrange)
2011                    channelsArrange();
2012    
2013            // Remember to refresh devices and instruments...
2014            if (m_pInstrumentListForm)
2015                    m_pInstrumentListForm->refreshInstruments();
2016            if (m_pDeviceForm)
2017                    m_pDeviceForm->refreshDevices();
2018    }
2019    
2020    void MainForm::updateAllChannelStrips(bool bRemoveDeadStrips) {
2021          // Retrieve the current channel list.          // Retrieve the current channel list.
2022          int *piChannelIDs = ::lscp_list_channels(m_pClient);          int *piChannelIDs = ::lscp_list_channels(m_pClient);
2023          if (piChannelIDs == NULL) {          if (piChannelIDs == NULL) {
# Line 1924  void MainForm::updateSession (void) Line 2032  void MainForm::updateSession (void)
2032                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {
2033                          // Check if theres already a channel strip for this one...                          // Check if theres already a channel strip for this one...
2034                          if (!channelStrip(piChannelIDs[iChannel]))                          if (!channelStrip(piChannelIDs[iChannel]))
2035                                  createChannelStrip(new qsamplerChannel(piChannelIDs[iChannel]));                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));
2036                  }                  }
                 m_pWorkspace->setUpdatesEnabled(true);  
         }  
2037    
2038          // Do we auto-arrange?                  // Do we auto-arrange?
2039          if (m_pOptions && m_pOptions->bAutoArrange)                  if (m_pOptions && m_pOptions->bAutoArrange)
2040                  channelsArrange();                          channelsArrange();
2041    
2042          // Remember to refresh devices and instruments...                  stabilizeForm();
         if (m_pInstrumentListForm)  
                 m_pInstrumentListForm->refreshInstruments();  
         if (m_pDeviceForm)  
                 m_pDeviceForm->refreshDevices();  
 }  
2043    
2044                    // remove dead channel strips
2045                    if (bRemoveDeadStrips) {
2046                            for (int i = 0; channelStripAt(i); ++i) {
2047                                    ChannelStrip* pChannelStrip = channelStripAt(i);
2048                                    bool bExists = false;
2049                                    for (int j = 0; piChannelIDs[j] >= 0; ++j) {
2050                                            if (!pChannelStrip->channel()) break;
2051                                            if (piChannelIDs[j] == pChannelStrip->channel()->channelID()) {
2052                                                    // strip exists, don't touch it
2053                                                    bExists = true;
2054                                                    break;
2055                                            }
2056                                    }
2057                                    if (!bExists) destroyChannelStrip(pChannelStrip);
2058                            }
2059                    }
2060                    m_pWorkspace->setUpdatesEnabled(true);
2061            }
2062    }
2063    
2064  // Update the recent files list and menu.  // Update the recent files list and menu.
2065  void MainForm::updateRecentFiles ( const QString& sFilename )  void MainForm::updateRecentFiles ( const QString& sFilename )
# Line 2113  void MainForm::appendMessagesError( cons Line 2233  void MainForm::appendMessagesError( cons
2233          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2234    
2235          QMessageBox::critical(this,          QMessageBox::critical(this,
2236                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));                  QSAMPLER_TITLE ": " + tr("Error"), s, QMessageBox::Cancel);
2237  }  }
2238    
2239    
# Line 2176  void MainForm::updateMessagesCapture (vo Line 2296  void MainForm::updateMessagesCapture (vo
2296  // qsamplerMainForm -- MDI channel strip management.  // qsamplerMainForm -- MDI channel strip management.
2297    
2298  // The channel strip creation executive.  // The channel strip creation executive.
2299  ChannelStrip* MainForm::createChannelStrip ( qsamplerChannel *pChannel )  ChannelStrip* MainForm::createChannelStrip ( Channel *pChannel )
2300  {  {
2301          if (m_pClient == NULL || pChannel == NULL)          if (m_pClient == NULL || pChannel == NULL)
2302                  return NULL;                  return NULL;
# Line 2218  ChannelStrip* MainForm::createChannelStr Line 2338  ChannelStrip* MainForm::createChannelStr
2338          return pChannelStrip;          return pChannelStrip;
2339  }  }
2340    
2341    void MainForm::destroyChannelStrip(ChannelStrip* pChannelStrip) {
2342            // Just delete the channel strip.
2343            delete pChannelStrip;
2344    
2345            // Do we auto-arrange?
2346            if (m_pOptions && m_pOptions->bAutoArrange)
2347                    channelsArrange();
2348    
2349            stabilizeForm();
2350    }
2351    
2352  // Retrieve the active channel strip.  // Retrieve the active channel strip.
2353  ChannelStrip* MainForm::activeChannelStrip (void)  ChannelStrip* MainForm::activeChannelStrip (void)
# Line 2229  ChannelStrip* MainForm::activeChannelStr Line 2359  ChannelStrip* MainForm::activeChannelStr
2359  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
2360  ChannelStrip* MainForm::channelStripAt ( int iChannel )  ChannelStrip* MainForm::channelStripAt ( int iChannel )
2361  {  {
2362            if (!m_pWorkspace) return NULL;
2363    
2364          QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2365          if (wlist.isEmpty())          if (wlist.isEmpty())
2366                  return NULL;                  return NULL;
2367    
2368          return static_cast<ChannelStrip *> (wlist.at(iChannel));          if (iChannel < 0 || iChannel >= wlist.size())
2369                    return NULL;
2370    
2371            return dynamic_cast<ChannelStrip *> (wlist.at(iChannel));
2372  }  }
2373    
2374    
# Line 2248  ChannelStrip* MainForm::channelStrip ( i Line 2383  ChannelStrip* MainForm::channelStrip ( i
2383                  ChannelStrip* pChannelStrip                  ChannelStrip* pChannelStrip
2384                          = static_cast<ChannelStrip*> (wlist.at(iChannel));                          = static_cast<ChannelStrip*> (wlist.at(iChannel));
2385                  if (pChannelStrip) {                  if (pChannelStrip) {
2386                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
2387                          if (pChannel && pChannel->channelID() == iChannelID)                          if (pChannel && pChannel->channelID() == iChannelID)
2388                                  return pChannelStrip;                                  return pChannelStrip;
2389                  }                  }
# Line 2386  void MainForm::startServer (void) Line 2521  void MainForm::startServer (void)
2521    
2522          // Is the server process instance still here?          // Is the server process instance still here?
2523          if (m_pServer) {          if (m_pServer) {
2524                  switch (QMessageBox::warning(this,                  if (QMessageBox::warning(this,
2525                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
2526                          tr("Could not start the LinuxSampler server.\n\n"                          tr("Could not start the LinuxSampler server.\n\n"
2527                          "Maybe it ss already started."),                          "Maybe it is already started."),
2528                          tr("Stop"), tr("Kill"), tr("Cancel"))) {                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
                 case 0:  
2529                          m_pServer->terminate();                          m_pServer->terminate();
                         break;  
                 case 1:  
2530                          m_pServer->kill();                          m_pServer->kill();
                         break;  
2531                  }                  }
2532                  return;                  return;
2533          }          }
# Line 2409  void MainForm::startServer (void) Line 2540  void MainForm::startServer (void)
2540                  return;                  return;
2541    
2542          // OK. Let's build the startup process...          // OK. Let's build the startup process...
2543          m_pServer = new QProcess(this);          m_pServer = new QProcess();
2544            bForceServerStop = true;
2545    
2546          // Setup stdout/stderr capture...          // Setup stdout/stderr capture...
2547  //      if (m_pOptions->bStdoutCapture) {  //      if (m_pOptions->bStdoutCapture) {
2548                  //m_pServer->setProcessChannelMode(  #if QT_VERSION >= 0x040200
2549                  //      QProcess::StandardOutput);                  m_pServer->setProcessChannelMode(QProcess::ForwardedChannels);
2550    #endif
2551                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2552                          SIGNAL(readyReadStandardOutput()),                          SIGNAL(readyReadStandardOutput()),
2553                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
# Line 2425  void MainForm::startServer (void) Line 2558  void MainForm::startServer (void)
2558    
2559          // The unforgiveable signal communication...          // The unforgiveable signal communication...
2560          QObject::connect(m_pServer,          QObject::connect(m_pServer,
2561                  SIGNAL(finished(int,QProcess::ExitStatus)),                  SIGNAL(finished(int, QProcess::ExitStatus)),
2562                  SLOT(processServerExit()));                  SLOT(processServerExit()));
2563    
2564          // Build process arguments...          // Build process arguments...
# Line 2456  void MainForm::startServer (void) Line 2589  void MainForm::startServer (void)
2589    
2590    
2591  // Stop linuxsampler server...  // Stop linuxsampler server...
2592  void MainForm::stopServer (void)  void MainForm::stopServer (bool bInteractive)
2593  {  {
2594          // Stop client code.          // Stop client code.
2595          stopClient();          stopClient();
2596    
2597            if (m_pServer && bInteractive) {
2598                    if (QMessageBox::question(this,
2599                            QSAMPLER_TITLE ": " + tr("The backend's fate ..."),
2600                            tr("You have the option to keep the sampler backend (LinuxSampler)\n"
2601                            "running in the background. The sampler would continue to work\n"
2602                            "according to your current sampler session and you could alter the\n"
2603                            "sampler session at any time by relaunching QSampler.\n\n"
2604                            "Do you want LinuxSampler to stop?"),
2605                            QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
2606                    {
2607                            bForceServerStop = false;
2608                    }
2609            }
2610    
2611          // And try to stop server.          // And try to stop server.
2612          if (m_pServer) {          if (m_pServer && bForceServerStop) {
2613                  appendMessages(tr("Server is stopping..."));                  appendMessages(tr("Server is stopping..."));
2614                  if (m_pServer->state() == QProcess::Running)                  if (m_pServer->state() == QProcess::Running) {
2615    #if defined(WIN32)
2616                            // Try harder...
2617                            m_pServer->kill();
2618    #else
2619                            // Try softly...
2620                          m_pServer->terminate();                          m_pServer->terminate();
2621          }  #endif
2622                    }
2623            }       // Do final processing anyway.
2624            else processServerExit();
2625    
2626          // Give it some time to terminate gracefully and stabilize...          // Give it some time to terminate gracefully and stabilize...
2627          QTime t;          QTime t;
2628          t.start();          t.start();
2629          while (t.elapsed() < QSAMPLER_TIMER_MSECS)          while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2630                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
   
         // Do final processing anyway.  
         processServerExit();  
2631  }  }
2632    
2633    
# Line 2497  void MainForm::processServerExit (void) Line 2649  void MainForm::processServerExit (void)
2649          if (m_pMessages)          if (m_pMessages)
2650                  m_pMessages->flushStdoutBuffer();                  m_pMessages->flushStdoutBuffer();
2651    
2652          if (m_pServer) {          if (m_pServer && bForceServerStop) {
2653                    if (m_pServer->state() != QProcess::NotRunning) {
2654                            appendMessages(tr("Server is being forced..."));
2655                            // Force final server shutdown...
2656                            m_pServer->kill();
2657                            // Give it some time to terminate gracefully and stabilize...
2658                            QTime t;
2659                            t.start();
2660                            while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2661                                    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2662                    }
2663                  // Force final server shutdown...                  // Force final server shutdown...
2664                  appendMessages(                  appendMessages(
2665                          tr("Server was stopped with exit status %1.")                          tr("Server was stopped with exit status %1.")
2666                          .arg(m_pServer->exitStatus()));                          .arg(m_pServer->exitStatus()));
                 m_pServer->terminate();  
                 if (!m_pServer->waitForFinished(2000))  
                         m_pServer->kill();  
                 // Destroy it.  
2667                  delete m_pServer;                  delete m_pServer;
2668                  m_pServer = NULL;                  m_pServer = NULL;
2669          }          }
# Line 2530  lscp_status_t qsampler_client_callback ( Line 2688  lscp_status_t qsampler_client_callback (
2688          // as this is run under some other thread context.          // as this is run under some other thread context.
2689          // A custom event must be posted here...          // A custom event must be posted here...
2690          QApplication::postEvent(pMainForm,          QApplication::postEvent(pMainForm,
2691                  new qsamplerCustomEvent(event, pchData, cchData));                  new CustomEvent(event, pchData, cchData));
2692    
2693          return LSCP_OK;          return LSCP_OK;
2694  }  }
# Line 2575  bool MainForm::startClient (void) Line 2733  bool MainForm::startClient (void)
2733                  .arg(::lscp_client_get_timeout(m_pClient)));                  .arg(::lscp_client_get_timeout(m_pClient)));
2734    
2735          // Subscribe to channel info change notifications...          // Subscribe to channel info change notifications...
2736            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT) != LSCP_OK)
2737                    appendMessagesClient("lscp_client_subscribe(CHANNEL_COUNT)");
2738          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)
2739                  appendMessagesClient("lscp_client_subscribe");                  appendMessagesClient("lscp_client_subscribe(CHANNEL_INFO)");
2740    
2741            DeviceStatusForm::onDevicesChanged(); // initialize
2742            updateViewMidiDeviceStatusMenu();
2743            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT) != LSCP_OK)
2744                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_COUNT)");
2745            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO) != LSCP_OK)
2746                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_INFO)");
2747            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT) != LSCP_OK)
2748                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_COUNT)");
2749            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO) != LSCP_OK)
2750                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_INFO)");
2751    
2752    #if CONFIG_EVENT_CHANNEL_MIDI
2753            // Subscribe to channel MIDI data notifications...
2754            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI) != LSCP_OK)
2755                    appendMessagesClient("lscp_client_subscribe(CHANNEL_MIDI)");
2756    #endif
2757    
2758    #if CONFIG_EVENT_DEVICE_MIDI
2759            // Subscribe to channel MIDI data notifications...
2760            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI) != LSCP_OK)
2761                    appendMessagesClient("lscp_client_subscribe(DEVICE_MIDI)");
2762    #endif
2763    
2764          // We may stop scheduling around.          // We may stop scheduling around.
2765          stopSchedule();          stopSchedule();
# Line 2603  bool MainForm::startClient (void) Line 2786  bool MainForm::startClient (void)
2786                  }                  }
2787          }          }
2788    
2789            // send the current / loaded fine tuning settings to the sampler
2790            m_pOptions->sendFineTuningSettings();
2791    
2792          // Make a new session          // Make a new session
2793          return newSession();          return newSession();
2794  }  }
# Line 2630  void MainForm::stopClient (void) Line 2816  void MainForm::stopClient (void)
2816          closeSession(false);          closeSession(false);
2817    
2818          // Close us as a client...          // Close us as a client...
2819    #if CONFIG_EVENT_DEVICE_MIDI
2820            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI);
2821    #endif
2822    #if CONFIG_EVENT_CHANNEL_MIDI
2823            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI);
2824    #endif
2825            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
2826            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
2827            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
2828            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
2829          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
2830            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT);
2831          ::lscp_client_destroy(m_pClient);          ::lscp_client_destroy(m_pClient);
2832          m_pClient = NULL;          m_pClient = NULL;
2833    

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

  ViewVC Help
Powered by ViewVC