/[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 1558 by capela, Thu Dec 6 09:35:33 2007 UTC revision 1702 by schoenebeck, Sun Feb 17 13:53:00 2008 UTC
# Line 2  Line 2 
2  //  //
3  /****************************************************************************  /****************************************************************************
4     Copyright (C) 2004-2007, rncbc aka Rui Nuno Capela. All rights reserved.     Copyright (C) 2004-2007, 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 471  bool MainForm::queryClose (void) Line 472  bool MainForm::queryClose (void)
472                          if (m_pDeviceForm)                          if (m_pDeviceForm)
473                                  m_pDeviceForm->close();                                  m_pDeviceForm->close();
474                          // Stop client and/or server, gracefully.                          // Stop client and/or server, gracefully.
475                          stopServer();                          stopServer(true /*interactive*/);
476                  }                  }
477          }          }
478    
# Line 481  bool MainForm::queryClose (void) Line 482  bool MainForm::queryClose (void)
482    
483  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )
484  {  {
485          if (queryClose())          if (queryClose()) {
486                    DeviceStatusForm::deleteAllInstances();
487                  pCloseEvent->accept();                  pCloseEvent->accept();
488          else          } else
489                  pCloseEvent->ignore();                  pCloseEvent->ignore();
490  }  }
491    
# Line 551  void MainForm::customEvent(QEvent* pCust Line 553  void MainForm::customEvent(QEvent* pCust
553          // For the time being, just pump it to messages.          // For the time being, just pump it to messages.
554          if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {          if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {
555                  CustomEvent *pEvent = static_cast<CustomEvent *> (pCustomEvent);                  CustomEvent *pEvent = static_cast<CustomEvent *> (pCustomEvent);
556                  if (pEvent->event() == LSCP_EVENT_CHANNEL_INFO) {                  switch (pEvent->event()) {
557                          int iChannelID = pEvent->data().toInt();                          case LSCP_EVENT_CHANNEL_COUNT:
558                          ChannelStrip *pChannelStrip = channelStrip(iChannelID);                                  updateAllChannelStrips(true);
559                          if (pChannelStrip)                                  break;
560                                  channelStripChanged(pChannelStrip);                          case LSCP_EVENT_CHANNEL_INFO: {
561                  } else {                                  int iChannelID = pEvent->data().toInt();
562                          appendMessagesColor(tr("Notify event: %1 data: %2")                                  ChannelStrip *pChannelStrip = channelStrip(iChannelID);
563                                  .arg(::lscp_event_to_text(pEvent->event()))                                  if (pChannelStrip)
564                                  .arg(pEvent->data()), "#996699");                                          channelStripChanged(pChannelStrip);
565                                    break;
566                            }
567                            case LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT:
568                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
569                                    DeviceStatusForm::onDevicesChanged();
570                                    updateViewMidiDeviceStatusMenu();
571                                    break;
572                            case LSCP_EVENT_MIDI_INPUT_DEVICE_INFO: {
573                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
574                                    const int iDeviceID = pEvent->data().section(' ', 0, 0).toInt();
575                                    DeviceStatusForm::onDeviceChanged(iDeviceID);
576                                    break;
577                            }
578                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT:
579                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
580                                    break;
581                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO:
582                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
583                                    break;
584    #if CONFIG_LSCP_CHANNEL_MIDI
585                            case LSCP_EVENT_CHANNEL_MIDI: {
586                                    const int iChannelID = pEvent->data().section(' ', 0, 0).toInt();
587                                    ChannelStrip *pChannelStrip = channelStrip(iChannelID);
588                                    if (pChannelStrip)
589                                            pChannelStrip->midiArrived();
590                                    break;
591                            }
592    #endif
593    #if CONFIG_LSCP_DEVICE_MIDI
594                            case LSCP_EVENT_DEVICE_MIDI: {
595                                    const int iDeviceID = pEvent->data().section(' ', 0, 0).toInt();
596                                    const int iPortID   = pEvent->data().section(' ', 1, 1).toInt();
597                                    DeviceStatusForm* pDeviceStatusForm =
598                                            DeviceStatusForm::getInstance(iDeviceID);
599                                    if (pDeviceStatusForm)
600                                            pDeviceStatusForm->midiArrived(iPortID);
601                                    break;
602                            }
603    #endif
604                            default:
605                                    appendMessagesColor(tr("Notify event: %1 data: %2")
606                                            .arg(::lscp_event_to_text(pEvent->event()))
607                                            .arg(pEvent->data()), "#996699");
608                  }                  }
609          }          }
610  }  }
611    
612    void MainForm::updateViewMidiDeviceStatusMenu() {
613            m_ui.viewMidiDeviceStatusMenu->clear();
614            const std::map<int, DeviceStatusForm*> statusForms =
615                    DeviceStatusForm::getInstances();
616            for (
617                    std::map<int, DeviceStatusForm*>::const_iterator iter = statusForms.begin();
618                    iter != statusForms.end(); ++iter
619            ) {
620                    DeviceStatusForm* pForm = iter->second;
621                    m_ui.viewMidiDeviceStatusMenu->addAction(
622                            pForm->visibleAction()
623                    );
624            }
625    }
626    
627  // Context menu event handler.  // Context menu event handler.
628  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )
629  {  {
# Line 1911  void MainForm::updateSession (void) Line 1971  void MainForm::updateSession (void)
1971          }          }
1972  #endif  #endif
1973    
1974            updateAllChannelStrips(false);
1975    
1976            // Do we auto-arrange?
1977            if (m_pOptions && m_pOptions->bAutoArrange)
1978                    channelsArrange();
1979    
1980            // Remember to refresh devices and instruments...
1981            if (m_pInstrumentListForm)
1982                    m_pInstrumentListForm->refreshInstruments();
1983            if (m_pDeviceForm)
1984                    m_pDeviceForm->refreshDevices();
1985    }
1986    
1987    void MainForm::updateAllChannelStrips(bool bRemoveDeadStrips) {
1988          // Retrieve the current channel list.          // Retrieve the current channel list.
1989          int *piChannelIDs = ::lscp_list_channels(m_pClient);          int *piChannelIDs = ::lscp_list_channels(m_pClient);
1990          if (piChannelIDs == NULL) {          if (piChannelIDs == NULL) {
# Line 1927  void MainForm::updateSession (void) Line 2001  void MainForm::updateSession (void)
2001                          if (!channelStrip(piChannelIDs[iChannel]))                          if (!channelStrip(piChannelIDs[iChannel]))
2002                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));
2003                  }                  }
                 m_pWorkspace->setUpdatesEnabled(true);  
         }  
2004    
2005          // Do we auto-arrange?                  // Do we auto-arrange?
2006          if (m_pOptions && m_pOptions->bAutoArrange)                  if (m_pOptions && m_pOptions->bAutoArrange)
2007                  channelsArrange();                          channelsArrange();
2008    
2009          // Remember to refresh devices and instruments...                  stabilizeForm();
         if (m_pInstrumentListForm)  
                 m_pInstrumentListForm->refreshInstruments();  
         if (m_pDeviceForm)  
                 m_pDeviceForm->refreshDevices();  
 }  
2010    
2011                    // remove dead channel strips
2012                    if (bRemoveDeadStrips) {
2013                            for (int i = 0; channelStripAt(i); ++i) {
2014                                    ChannelStrip* pChannelStrip = channelStripAt(i);
2015                                    bool bExists = false;
2016                                    for (int j = 0; piChannelIDs[j] >= 0; ++j) {
2017                                            if (!pChannelStrip->channel()) break;
2018                                            if (piChannelIDs[j] == pChannelStrip->channel()->channelID()) {
2019                                                    // strip exists, don't touch it
2020                                                    bExists = true;
2021                                                    break;
2022                                            }
2023                                    }
2024                                    if (!bExists) destroyChannelStrip(pChannelStrip);
2025                            }
2026                    }
2027                    m_pWorkspace->setUpdatesEnabled(true);
2028            }
2029    }
2030    
2031  // Update the recent files list and menu.  // Update the recent files list and menu.
2032  void MainForm::updateRecentFiles ( const QString& sFilename )  void MainForm::updateRecentFiles ( const QString& sFilename )
# Line 2219  ChannelStrip* MainForm::createChannelStr Line 2305  ChannelStrip* MainForm::createChannelStr
2305          return pChannelStrip;          return pChannelStrip;
2306  }  }
2307    
2308    void MainForm::destroyChannelStrip(ChannelStrip* pChannelStrip) {
2309            // Just delete the channel strip.
2310            delete pChannelStrip;
2311    
2312            // Do we auto-arrange?
2313            if (m_pOptions && m_pOptions->bAutoArrange)
2314                    channelsArrange();
2315    
2316            stabilizeForm();
2317    }
2318    
2319  // Retrieve the active channel strip.  // Retrieve the active channel strip.
2320  ChannelStrip* MainForm::activeChannelStrip (void)  ChannelStrip* MainForm::activeChannelStrip (void)
# Line 2230  ChannelStrip* MainForm::activeChannelStr Line 2326  ChannelStrip* MainForm::activeChannelStr
2326  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
2327  ChannelStrip* MainForm::channelStripAt ( int iChannel )  ChannelStrip* MainForm::channelStripAt ( int iChannel )
2328  {  {
2329            if (!m_pWorkspace) return NULL;
2330    
2331          QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2332          if (wlist.isEmpty())          if (wlist.isEmpty())
2333                  return NULL;                  return NULL;
2334    
2335          return static_cast<ChannelStrip *> (wlist.at(iChannel));          if (iChannel < 0 || iChannel >= wlist.size())
2336                    return NULL;
2337    
2338            return dynamic_cast<ChannelStrip *> (wlist.at(iChannel));
2339  }  }
2340    
2341    
# Line 2390  void MainForm::startServer (void) Line 2491  void MainForm::startServer (void)
2491                  switch (QMessageBox::warning(this,                  switch (QMessageBox::warning(this,
2492                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
2493                          tr("Could not start the LinuxSampler server.\n\n"                          tr("Could not start the LinuxSampler server.\n\n"
2494                          "Maybe it ss already started."),                          "Maybe it is already started."),
2495                          tr("Stop"), tr("Kill"), tr("Cancel"))) {                          tr("Stop"), tr("Kill"), tr("Cancel"))) {
2496                  case 0:                  case 0:
2497                          m_pServer->terminate();                          m_pServer->terminate();
# Line 2410  void MainForm::startServer (void) Line 2511  void MainForm::startServer (void)
2511                  return;                  return;
2512    
2513          // OK. Let's build the startup process...          // OK. Let's build the startup process...
2514          m_pServer = new QProcess(this);          m_pServer = new QProcess();
2515            bForceServerStop = true;
2516    
2517          // Setup stdout/stderr capture...          // Setup stdout/stderr capture...
2518  //      if (m_pOptions->bStdoutCapture) {  //      if (m_pOptions->bStdoutCapture) {
2519                  //m_pServer->setProcessChannelMode(  #if QT_VERSION >= 0x040200
2520                  //      QProcess::StandardOutput);                  m_pServer->setProcessChannelMode(QProcess::ForwardedChannels);
2521    #endif
2522                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2523                          SIGNAL(readyReadStandardOutput()),                          SIGNAL(readyReadStandardOutput()),
2524                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
# Line 2426  void MainForm::startServer (void) Line 2529  void MainForm::startServer (void)
2529    
2530          // The unforgiveable signal communication...          // The unforgiveable signal communication...
2531          QObject::connect(m_pServer,          QObject::connect(m_pServer,
2532                  SIGNAL(finished(int,QProcess::ExitStatus)),                  SIGNAL(finished(int, QProcess::ExitStatus)),
2533                  SLOT(processServerExit()));                  SLOT(processServerExit()));
2534    
2535          // Build process arguments...          // Build process arguments...
# Line 2457  void MainForm::startServer (void) Line 2560  void MainForm::startServer (void)
2560    
2561    
2562  // Stop linuxsampler server...  // Stop linuxsampler server...
2563  void MainForm::stopServer (void)  void MainForm::stopServer (bool bInteractive)
2564  {  {
2565          // Stop client code.          // Stop client code.
2566          stopClient();          stopClient();
2567    
2568            if (m_pServer && bInteractive) {
2569                    if (QMessageBox::question(this,
2570                            QSAMPLER_TITLE ": " + tr("The backend's fate ..."),
2571                            tr("You have the option to keep the sampler backend (LinuxSampler)\n"
2572                            "running in the background. The sampler would continue to work\n"
2573                            "according to your current sampler session and you could alter the\n"
2574                            "sampler session at any time by relaunching QSampler.\n\n"
2575                            "Do you want LinuxSampler to stop or to keep running in\n"
2576                            "the background?"),
2577                            tr("Stop"), tr("Keep Running")) == 1)
2578                    {
2579                            bForceServerStop = false;
2580                    }
2581            }
2582    
2583          // And try to stop server.          // And try to stop server.
2584          if (m_pServer) {          if (m_pServer && bForceServerStop) {
2585                  appendMessages(tr("Server is stopping..."));                  appendMessages(tr("Server is stopping..."));
2586                  if (m_pServer->state() == QProcess::Running)                  if (m_pServer->state() == QProcess::Running) {
2587    #if defined(WIN32)
2588                            // Try harder...
2589                            m_pServer->kill();
2590    #else
2591                            // Try softly...
2592                          m_pServer->terminate();                          m_pServer->terminate();
2593          }  #endif
2594                    }
2595            }       // Do final processing anyway.
2596            else processServerExit();
2597    
2598          // Give it some time to terminate gracefully and stabilize...          // Give it some time to terminate gracefully and stabilize...
2599          QTime t;          QTime t;
2600          t.start();          t.start();
2601          while (t.elapsed() < QSAMPLER_TIMER_MSECS)          while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2602                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
   
         // Do final processing anyway.  
         processServerExit();  
2603  }  }
2604    
2605    
# Line 2498  void MainForm::processServerExit (void) Line 2621  void MainForm::processServerExit (void)
2621          if (m_pMessages)          if (m_pMessages)
2622                  m_pMessages->flushStdoutBuffer();                  m_pMessages->flushStdoutBuffer();
2623    
2624          if (m_pServer) {          if (m_pServer && bForceServerStop) {
2625                    if (m_pServer->state() != QProcess::NotRunning) {
2626                            appendMessages(tr("Server is being forced..."));
2627                            // Force final server shutdown...
2628                            m_pServer->kill();
2629                            // Give it some time to terminate gracefully and stabilize...
2630                            QTime t;
2631                            t.start();
2632                            while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2633                                    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2634                    }
2635                  // Force final server shutdown...                  // Force final server shutdown...
2636                  appendMessages(                  appendMessages(
2637                          tr("Server was stopped with exit status %1.")                          tr("Server was stopped with exit status %1.")
2638                          .arg(m_pServer->exitStatus()));                          .arg(m_pServer->exitStatus()));
                 m_pServer->terminate();  
                 if (!m_pServer->waitForFinished(2000))  
                         m_pServer->kill();  
                 // Destroy it.  
2639                  delete m_pServer;                  delete m_pServer;
2640                  m_pServer = NULL;                  m_pServer = NULL;
2641          }          }
# Line 2576  bool MainForm::startClient (void) Line 2705  bool MainForm::startClient (void)
2705                  .arg(::lscp_client_get_timeout(m_pClient)));                  .arg(::lscp_client_get_timeout(m_pClient)));
2706    
2707          // Subscribe to channel info change notifications...          // Subscribe to channel info change notifications...
2708            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT) != LSCP_OK)
2709                    appendMessagesClient("lscp_client_subscribe(CHANNEL_COUNT)");
2710          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)
2711                  appendMessagesClient("lscp_client_subscribe");                  appendMessagesClient("lscp_client_subscribe(CHANNEL_INFO)");
2712    
2713            DeviceStatusForm::onDevicesChanged(); // initialize
2714            updateViewMidiDeviceStatusMenu();
2715            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT) != LSCP_OK)
2716                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_COUNT)");
2717            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO) != LSCP_OK)
2718                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_INFO)");
2719            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT) != LSCP_OK)
2720                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_COUNT)");
2721            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO) != LSCP_OK)
2722                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_INFO)");
2723    
2724    #if CONFIG_LSCP_CHANNEL_MIDI
2725            // Subscribe to channel MIDI data notifications...
2726            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI) != LSCP_OK)
2727                    appendMessagesClient("lscp_client_subscribe(CHANNEL_MIDI)");
2728    #endif
2729    
2730    #if CONFIG_LSCP_DEVICE_MIDI
2731            // Subscribe to channel MIDI data notifications...
2732            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI) != LSCP_OK)
2733                    appendMessagesClient("lscp_client_subscribe(DEVICE_MIDI)");
2734    #endif
2735    
2736          // We may stop scheduling around.          // We may stop scheduling around.
2737          stopSchedule();          stopSchedule();
# Line 2631  void MainForm::stopClient (void) Line 2785  void MainForm::stopClient (void)
2785          closeSession(false);          closeSession(false);
2786    
2787          // Close us as a client...          // Close us as a client...
2788    #if CONFIG_LSCP_DEVICE_MIDI
2789            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI);
2790    #endif
2791    #if CONFIG_LSCP_CHANNEL_MIDI
2792            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI);
2793    #endif
2794            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
2795            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
2796            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
2797            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
2798          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
2799            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT);
2800          ::lscp_client_destroy(m_pClient);          ::lscp_client_destroy(m_pClient);
2801          m_pClient = NULL;          m_pClient = NULL;
2802    

Legend:
Removed from v.1558  
changed lines
  Added in v.1702

  ViewVC Help
Powered by ViewVC