/[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 1507 by capela, Wed Nov 21 23:22:18 2007 UTC revision 1739 by capela, Wed May 14 17:37:45 2008 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-2008, 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 20  Line 20 
20    
21  *****************************************************************************/  *****************************************************************************/
22    
23    #include "qsamplerAbout.h"
24  #include "qsamplerMainForm.h"  #include "qsamplerMainForm.h"
25    
 #include "qsamplerAbout.h"  
26  #include "qsamplerOptions.h"  #include "qsamplerOptions.h"
27  #include "qsamplerChannel.h"  #include "qsamplerChannel.h"
28  #include "qsamplerMessages.h"  #include "qsamplerMessages.h"
# 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;
114          m_data  = QString::fromUtf8(pchData, cchData);                  m_data  = QString::fromUtf8(pchData, cchData);
115      }          }
116    
117      // Accessors.          // Accessors.
118      lscp_event_t event() { return m_event; }          lscp_event_t event() { return m_event; }
119      QString&     data()  { return m_data;  }          QString&     data()  { return m_data;  }
120    
121  private:  private:
122    
123      // The proper event type.          // The proper event type.
124      lscp_event_t m_event;          lscp_event_t m_event;
125      // The event data as a string.          // The event data as a string.
126      QString      m_data;          QString      m_data;
127  };  };
128    
129    
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    
136  MainForm::MainForm(QWidget* parent) : QMainWindow(parent) {  MainForm::MainForm ( QWidget *pParent )
137      ui.setupUi(this);          : QMainWindow(pParent)
138    {
139            m_ui.setupUi(this);
140    
141          // Pseudo-singleton reference setup.          // Pseudo-singleton reference setup.
142          g_pMainForm = this;          g_pMainForm = this;
143    
144      // Initialize some pointer references.          // Initialize some pointer references.
145      m_pOptions = NULL;          m_pOptions = NULL;
146    
147      // All child forms are to be created later, not earlier than setup.          // All child forms are to be created later, not earlier than setup.
148      m_pMessages = NULL;          m_pMessages = NULL;
149      m_pInstrumentListForm = NULL;          m_pInstrumentListForm = NULL;
150      m_pDeviceForm = NULL;          m_pDeviceForm = NULL;
151    
152      // We'll start clean.          // We'll start clean.
153      m_iUntitled   = 0;          m_iUntitled   = 0;
154      m_iDirtyCount = 0;          m_iDirtyCount = 0;
155    
156      m_pServer = NULL;          m_pServer = NULL;
157      m_pClient = NULL;          m_pClient = NULL;
158    
159      m_iStartDelay = 0;          m_iStartDelay = 0;
160      m_iTimerDelay = 0;          m_iTimerDelay = 0;
161    
162      m_iTimerSlot = 0;          m_iTimerSlot = 0;
163    
164  #ifdef HAVE_SIGNAL_H  #ifdef HAVE_SIGNAL_H
165          // Set to ignore any fatal "Broken pipe" signals.          // Set to ignore any fatal "Broken pipe" signals.
# Line 163  MainForm::MainForm(QWidget* parent) : QM Line 167  MainForm::MainForm(QWidget* parent) : QM
167  #endif  #endif
168    
169  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
170      // Make some extras into the toolbar...          // Make some extras into the toolbar...
171          const QString& sVolumeText = tr("Master volume");          const QString& sVolumeText = tr("Master volume");
172          m_iVolumeChanging = 0;          m_iVolumeChanging = 0;
173          // Volume slider...          // Volume slider...
174          ui.channelsToolbar->addSeparator();          m_ui.channelsToolbar->addSeparator();
175          m_pVolumeSlider = new QSlider(Qt::Horizontal, ui.channelsToolbar);          m_pVolumeSlider = new QSlider(Qt::Horizontal, m_ui.channelsToolbar);
176          m_pVolumeSlider->setTickPosition(QSlider::TicksBelow);          m_pVolumeSlider->setTickPosition(QSlider::TicksBothSides);
177          m_pVolumeSlider->setTickInterval(10);          m_pVolumeSlider->setTickInterval(10);
178          m_pVolumeSlider->setPageStep(10);          m_pVolumeSlider->setPageStep(10);
179          m_pVolumeSlider->setSingleStep(10);          m_pVolumeSlider->setSingleStep(10);
# Line 181  MainForm::MainForm(QWidget* parent) : QM Line 185  MainForm::MainForm(QWidget* parent) : QM
185          QObject::connect(m_pVolumeSlider,          QObject::connect(m_pVolumeSlider,
186                  SIGNAL(valueChanged(int)),                  SIGNAL(valueChanged(int)),
187                  SLOT(volumeChanged(int)));                  SLOT(volumeChanged(int)));
188          //ui.channelsToolbar->setHorizontallyStretchable(true);          //m_ui.channelsToolbar->setHorizontallyStretchable(true);
189          //ui.channelsToolbar->setStretchableWidget(m_pVolumeSlider);          //m_ui.channelsToolbar->setStretchableWidget(m_pVolumeSlider);
190      ui.channelsToolbar->addWidget(m_pVolumeSlider);          m_ui.channelsToolbar->addWidget(m_pVolumeSlider);
191          // Volume spin-box          // Volume spin-box
192          ui.channelsToolbar->addSeparator();          m_ui.channelsToolbar->addSeparator();
193          m_pVolumeSpinBox = new QSpinBox(ui.channelsToolbar);          m_pVolumeSpinBox = new QSpinBox(m_ui.channelsToolbar);
194            m_pVolumeSpinBox->setMaximumHeight(24);
195          m_pVolumeSpinBox->setSuffix(" %");          m_pVolumeSpinBox->setSuffix(" %");
196          m_pVolumeSpinBox->setMinimum(0);          m_pVolumeSpinBox->setMinimum(0);
197          m_pVolumeSpinBox->setMaximum(100);          m_pVolumeSpinBox->setMaximum(100);
# Line 194  MainForm::MainForm(QWidget* parent) : QM Line 199  MainForm::MainForm(QWidget* parent) : QM
199          QObject::connect(m_pVolumeSpinBox,          QObject::connect(m_pVolumeSpinBox,
200                  SIGNAL(valueChanged(int)),                  SIGNAL(valueChanged(int)),
201                  SLOT(volumeChanged(int)));                  SLOT(volumeChanged(int)));
202      ui.channelsToolbar->addWidget(m_pVolumeSpinBox);          m_ui.channelsToolbar->addWidget(m_pVolumeSpinBox);
203  #endif  #endif
204    
205      // Make it an MDI workspace.          // Make it an MDI workspace.
206      m_pWorkspace = new QWorkspace(this);          m_pWorkspace = new QWorkspace(this);
207      m_pWorkspace->setScrollBarsEnabled(true);          m_pWorkspace->setScrollBarsEnabled(true);
208          // Set the activation connection.          // Set the activation connection.
209          QObject::connect(m_pWorkspace,          QObject::connect(m_pWorkspace,
210                  SIGNAL(windowActivated(QWidget *)),                  SIGNAL(windowActivated(QWidget *)),
211                  SLOT(stabilizeForm()));                  SLOT(activateStrip(QWidget *)));
212      // Make it shine :-)          // Make it shine :-)
213      setCentralWidget(m_pWorkspace);          setCentralWidget(m_pWorkspace);
214    
215      // Create some statusbar labels...          // Create some statusbar labels...
216      QLabel *pLabel;          QLabel *pLabel;
217      // Client status.          // Client status.
218      pLabel = new QLabel(tr("Connected"), this);          pLabel = new QLabel(tr("Connected"), this);
219      pLabel->setAlignment(Qt::AlignLeft);          pLabel->setAlignment(Qt::AlignLeft);
220      pLabel->setMinimumSize(pLabel->sizeHint());          pLabel->setMinimumSize(pLabel->sizeHint());
221      m_statusItem[QSAMPLER_STATUS_CLIENT] = pLabel;          m_statusItem[QSAMPLER_STATUS_CLIENT] = pLabel;
222      statusBar()->addWidget(pLabel);          statusBar()->addWidget(pLabel);
223      // Server address.          // Server address.
224      pLabel = new QLabel(this);          pLabel = new QLabel(this);
225      pLabel->setAlignment(Qt::AlignLeft);          pLabel->setAlignment(Qt::AlignLeft);
226      m_statusItem[QSAMPLER_STATUS_SERVER] = pLabel;          m_statusItem[QSAMPLER_STATUS_SERVER] = pLabel;
227      statusBar()->addWidget(pLabel, 1);          statusBar()->addWidget(pLabel, 1);
228      // Channel title.          // Channel title.
229      pLabel = new QLabel(this);          pLabel = new QLabel(this);
230      pLabel->setAlignment(Qt::AlignLeft);          pLabel->setAlignment(Qt::AlignLeft);
231      m_statusItem[QSAMPLER_STATUS_CHANNEL] = pLabel;          m_statusItem[QSAMPLER_STATUS_CHANNEL] = pLabel;
232      statusBar()->addWidget(pLabel, 2);          statusBar()->addWidget(pLabel, 2);
233      // Session modification status.          // Session modification status.
234      pLabel = new QLabel(tr("MOD"), this);          pLabel = new QLabel(tr("MOD"), this);
235      pLabel->setAlignment(Qt::AlignHCenter);          pLabel->setAlignment(Qt::AlignHCenter);
236      pLabel->setMinimumSize(pLabel->sizeHint());          pLabel->setMinimumSize(pLabel->sizeHint());
237      m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;          m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;
238      statusBar()->addWidget(pLabel);          statusBar()->addWidget(pLabel);
239    
240  #if defined(WIN32)  #if defined(WIN32)
241      WSAStartup(MAKEWORD(1, 1), &_wsaData);          WSAStartup(MAKEWORD(1, 1), &_wsaData);
242  #endif  #endif
243    
244          QObject::connect(ui.fileNewAction,          // Some actions surely need those
245            // shortcuts firmly attached...
246            addAction(m_ui.viewMenubarAction);
247            addAction(m_ui.viewToolbarAction);
248    
249            QObject::connect(m_ui.fileNewAction,
250                  SIGNAL(triggered()),                  SIGNAL(triggered()),
251                  SLOT(fileNew()));                  SLOT(fileNew()));
252          QObject::connect(ui.fileOpenAction,          QObject::connect(m_ui.fileOpenAction,
253                  SIGNAL(triggered()),                  SIGNAL(triggered()),
254                  SLOT(fileOpen()));                  SLOT(fileOpen()));
255          QObject::connect(ui.fileSaveAction,          QObject::connect(m_ui.fileSaveAction,
256                  SIGNAL(triggered()),                  SIGNAL(triggered()),
257                  SLOT(fileSave()));                  SLOT(fileSave()));
258          QObject::connect(ui.fileSaveAsAction,          QObject::connect(m_ui.fileSaveAsAction,
259                  SIGNAL(triggered()),                  SIGNAL(triggered()),
260                  SLOT(fileSaveAs()));                  SLOT(fileSaveAs()));
261          QObject::connect(ui.fileResetAction,          QObject::connect(m_ui.fileResetAction,
262                  SIGNAL(triggered()),                  SIGNAL(triggered()),
263                  SLOT(fileReset()));                  SLOT(fileReset()));
264          QObject::connect(ui.fileRestartAction,          QObject::connect(m_ui.fileRestartAction,
265                  SIGNAL(triggered()),                  SIGNAL(triggered()),
266                  SLOT(fileRestart()));                  SLOT(fileRestart()));
267          QObject::connect(ui.fileExitAction,          QObject::connect(m_ui.fileExitAction,
268                  SIGNAL(triggered()),                  SIGNAL(triggered()),
269                  SLOT(fileExit()));                  SLOT(fileExit()));
270          QObject::connect(ui.editAddChannelAction,          QObject::connect(m_ui.editAddChannelAction,
271                  SIGNAL(triggered()),                  SIGNAL(triggered()),
272                  SLOT(editAddChannel()));                  SLOT(editAddChannel()));
273          QObject::connect(ui.editRemoveChannelAction,          QObject::connect(m_ui.editRemoveChannelAction,
274                  SIGNAL(triggered()),                  SIGNAL(triggered()),
275                  SLOT(editRemoveChannel()));                  SLOT(editRemoveChannel()));
276          QObject::connect(ui.editSetupChannelAction,          QObject::connect(m_ui.editSetupChannelAction,
277                  SIGNAL(triggered()),                  SIGNAL(triggered()),
278                  SLOT(editSetupChannel()));                  SLOT(editSetupChannel()));
279          QObject::connect(ui.editEditChannelAction,          QObject::connect(m_ui.editEditChannelAction,
280                  SIGNAL(triggered()),                  SIGNAL(triggered()),
281                  SLOT(editEditChannel()));                  SLOT(editEditChannel()));
282          QObject::connect(ui.editResetChannelAction,          QObject::connect(m_ui.editResetChannelAction,
283                  SIGNAL(triggered()),                  SIGNAL(triggered()),
284                  SLOT(editResetChannel()));                  SLOT(editResetChannel()));
285          QObject::connect(ui.editResetAllChannelsAction,          QObject::connect(m_ui.editResetAllChannelsAction,
286                  SIGNAL(triggered()),                  SIGNAL(triggered()),
287                  SLOT(editResetAllChannels()));                  SLOT(editResetAllChannels()));
288          QObject::connect(ui.viewMenubarAction,          QObject::connect(m_ui.viewMenubarAction,
289                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
290                  SLOT(viewMenubar(bool)));                  SLOT(viewMenubar(bool)));
291          QObject::connect(ui.viewToolbarAction,          QObject::connect(m_ui.viewToolbarAction,
292                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
293                  SLOT(viewToolbar(bool)));                  SLOT(viewToolbar(bool)));
294          QObject::connect(ui.viewStatusbarAction,          QObject::connect(m_ui.viewStatusbarAction,
295                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
296                  SLOT(viewStatusbar(bool)));                  SLOT(viewStatusbar(bool)));
297          QObject::connect(ui.viewMessagesAction,          QObject::connect(m_ui.viewMessagesAction,
298                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
299                  SLOT(viewMessages(bool)));                  SLOT(viewMessages(bool)));
300          QObject::connect(ui.viewInstrumentsAction,          QObject::connect(m_ui.viewInstrumentsAction,
301                  SIGNAL(triggered()),                  SIGNAL(triggered()),
302                  SLOT(viewInstruments()));                  SLOT(viewInstruments()));
303          QObject::connect(ui.viewDevicesAction,          QObject::connect(m_ui.viewDevicesAction,
304                  SIGNAL(triggered()),                  SIGNAL(triggered()),
305                  SLOT(viewDevices()));                  SLOT(viewDevices()));
306          QObject::connect(ui.viewOptionsAction,          QObject::connect(m_ui.viewOptionsAction,
307                  SIGNAL(triggered()),                  SIGNAL(triggered()),
308                  SLOT(viewOptions()));                  SLOT(viewOptions()));
309          QObject::connect(ui.channelsArrangeAction,          QObject::connect(m_ui.channelsArrangeAction,
310                  SIGNAL(triggered()),                  SIGNAL(triggered()),
311                  SLOT(channelsArrange()));                  SLOT(channelsArrange()));
312          QObject::connect(ui.channelsAutoArrangeAction,          QObject::connect(m_ui.channelsAutoArrangeAction,
313                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
314                  SLOT(channelsAutoArrange(bool)));                  SLOT(channelsAutoArrange(bool)));
315          QObject::connect(ui.helpAboutAction,          QObject::connect(m_ui.helpAboutAction,
316                  SIGNAL(triggered()),                  SIGNAL(triggered()),
317                  SLOT(helpAbout()));                  SLOT(helpAbout()));
318          QObject::connect(ui.helpAboutQtAction,          QObject::connect(m_ui.helpAboutQtAction,
319                  SIGNAL(triggered()),                  SIGNAL(triggered()),
320                  SLOT(helpAboutQt()));                  SLOT(helpAboutQt()));
321    
322          QObject::connect(ui.fileMenu,          QObject::connect(m_ui.fileMenu,
323                  SIGNAL(aboutToShow()),                  SIGNAL(aboutToShow()),
324                  SLOT(updateRecentFilesMenu()));                  SLOT(updateRecentFilesMenu()));
325          QObject::connect(ui.channelsMenu,          QObject::connect(m_ui.channelsMenu,
326                  SIGNAL(aboutToShow()),                  SIGNAL(aboutToShow()),
327                  SLOT(channelsMenuAboutToShow()));                  SLOT(channelsMenuAboutToShow()));
328  }  }
# Line 320  MainForm::MainForm(QWidget* parent) : QM Line 330  MainForm::MainForm(QWidget* parent) : QM
330  // Destructor.  // Destructor.
331  MainForm::~MainForm()  MainForm::~MainForm()
332  {  {
333      // Do final processing anyway.          // Do final processing anyway.
334      processServerExit();          processServerExit();
335    
336  #if defined(WIN32)  #if defined(WIN32)
337      WSACleanup();          WSACleanup();
338  #endif  #endif
339    
340      // Finally drop any widgets around...          // Finally drop any widgets around...
341      if (m_pDeviceForm)          if (m_pDeviceForm)
342          delete m_pDeviceForm;                  delete m_pDeviceForm;
343      if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
344          delete m_pInstrumentListForm;                  delete m_pInstrumentListForm;
345      if (m_pMessages)          if (m_pMessages)
346          delete m_pMessages;                  delete m_pMessages;
347      if (m_pWorkspace)          if (m_pWorkspace)
348          delete m_pWorkspace;                  delete m_pWorkspace;
349    
350      // Delete status item labels one by one.          // Delete status item labels one by one.
351      if (m_statusItem[QSAMPLER_STATUS_CLIENT])          if (m_statusItem[QSAMPLER_STATUS_CLIENT])
352          delete m_statusItem[QSAMPLER_STATUS_CLIENT];                  delete m_statusItem[QSAMPLER_STATUS_CLIENT];
353      if (m_statusItem[QSAMPLER_STATUS_SERVER])          if (m_statusItem[QSAMPLER_STATUS_SERVER])
354          delete m_statusItem[QSAMPLER_STATUS_SERVER];                  delete m_statusItem[QSAMPLER_STATUS_SERVER];
355      if (m_statusItem[QSAMPLER_STATUS_CHANNEL])          if (m_statusItem[QSAMPLER_STATUS_CHANNEL])
356          delete m_statusItem[QSAMPLER_STATUS_CHANNEL];                  delete m_statusItem[QSAMPLER_STATUS_CHANNEL];
357      if (m_statusItem[QSAMPLER_STATUS_SESSION])          if (m_statusItem[QSAMPLER_STATUS_SESSION])
358          delete m_statusItem[QSAMPLER_STATUS_SESSION];                  delete m_statusItem[QSAMPLER_STATUS_SESSION];
359    
360  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
361          delete m_pVolumeSpinBox;          delete m_pVolumeSpinBox;
# Line 358  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;
375    
376      // What style do we create these forms?          // What style do we create these forms?
377          Qt::WindowFlags wflags = Qt::Window          Qt::WindowFlags wflags = Qt::Window
378  #if QT_VERSION >= 0x040200  #if QT_VERSION >= 0x040200
379                  | Qt::CustomizeWindowHint                  | Qt::CustomizeWindowHint
# Line 373  void MainForm::setup ( qsamplerOptions * Line 383  void MainForm::setup ( qsamplerOptions *
383                  | Qt::WindowMinMaxButtonsHint;                  | Qt::WindowMinMaxButtonsHint;
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);
         QObject::connect(&m_pInstrumentListForm->model,  
                 SIGNAL(instrumentsChanged()),  
                 SLOT(sessionDirty()));  
391  #else  #else
392          viewInstrumentsAction->setEnabled(false);          viewInstrumentsAction->setEnabled(false);
393  #endif  #endif
394      // Set message defaults...          // Setup messages logging appropriately...
395      updateMessagesFont();          m_pMessages->setLogging(
396      updateMessagesLimit();                  m_pOptions->bMessagesLog,
397      updateMessagesCapture();                  m_pOptions->sMessagesLogPath);
398      // Set the visibility signal.          // Set message defaults...
399            updateMessagesFont();
400            updateMessagesLimit();
401            updateMessagesCapture();
402            // Set the visibility signal.
403          QObject::connect(m_pMessages,          QObject::connect(m_pMessages,
404                  SIGNAL(visibilityChanged(bool)),                  SIGNAL(visibilityChanged(bool)),
405                  SLOT(stabilizeForm()));                  SLOT(stabilizeForm()));
406    
407      // Initial decorations toggle state.          // Initial decorations toggle state.
408      ui.viewMenubarAction->setChecked(m_pOptions->bMenubar);          m_ui.viewMenubarAction->setChecked(m_pOptions->bMenubar);
409      ui.viewToolbarAction->setChecked(m_pOptions->bToolbar);          m_ui.viewToolbarAction->setChecked(m_pOptions->bToolbar);
410      ui.viewStatusbarAction->setChecked(m_pOptions->bStatusbar);          m_ui.viewStatusbarAction->setChecked(m_pOptions->bStatusbar);
411      ui.channelsAutoArrangeAction->setChecked(m_pOptions->bAutoArrange);          m_ui.channelsAutoArrangeAction->setChecked(m_pOptions->bAutoArrange);
412    
413      // Initial decorations visibility state.          // Initial decorations visibility state.
414      viewMenubar(m_pOptions->bMenubar);          viewMenubar(m_pOptions->bMenubar);
415      viewToolbar(m_pOptions->bToolbar);          viewToolbar(m_pOptions->bToolbar);
416      viewStatusbar(m_pOptions->bStatusbar);          viewStatusbar(m_pOptions->bStatusbar);
417    
418      addDockWidget(Qt::BottomDockWidgetArea, m_pMessages);          addDockWidget(Qt::BottomDockWidgetArea, m_pMessages);
419    
420          // Restore whole dock windows state.          // Restore whole dock windows state.
421          QByteArray aDockables = m_pOptions->settings().value(          QByteArray aDockables = m_pOptions->settings().value(
# Line 413  void MainForm::setup ( qsamplerOptions * Line 424  void MainForm::setup ( qsamplerOptions *
424                  restoreState(aDockables);                  restoreState(aDockables);
425          }          }
426    
427      // Try to restore old window positioning and initial visibility.          // Try to restore old window positioning and initial visibility.
428      m_pOptions->loadWidgetGeometry(this);          m_pOptions->loadWidgetGeometry(this);
429      m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);          m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);
430      m_pOptions->loadWidgetGeometry(m_pDeviceForm);          m_pOptions->loadWidgetGeometry(m_pDeviceForm);
431    
432      // Final startup stabilization...          // Final startup stabilization...
433      updateMaxVolume();          updateMaxVolume();
434      updateRecentFilesMenu();          updateRecentFilesMenu();
435      stabilizeForm();          stabilizeForm();
436    
437      // Make it ready :-)          // Make it ready :-)
438      statusBar()->showMessage(tr("Ready"), 3000);          statusBar()->showMessage(tr("Ready"), 3000);
439    
440      // We'll try to start immediately...          // We'll try to start immediately...
441      startSchedule(0);          startSchedule(0);
442    
443      // Register the first timer slot.          // Register the first timer slot.
444      QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));          QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
445  }  }
446    
447    
448  // Window close event handlers.  // Window close event handlers.
449  bool MainForm::queryClose (void)  bool MainForm::queryClose (void)
450  {  {
451      bool bQueryClose = closeSession(false);          bool bQueryClose = closeSession(false);
452    
453      // Try to save current general state...          // Try to save current general state...
454      if (m_pOptions) {          if (m_pOptions) {
455          // Some windows default fonts is here on demand too.                  // Some windows default fonts is here on demand too.
456          if (bQueryClose && m_pMessages)                  if (bQueryClose && m_pMessages)
457              m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
458          // Try to save current positioning.                  // Try to save current positioning.
459          if (bQueryClose) {                  if (bQueryClose) {
460              // Save decorations state.                          // Save decorations state.
461              m_pOptions->bMenubar = ui.MenuBar->isVisible();                          m_pOptions->bMenubar = m_ui.MenuBar->isVisible();
462              m_pOptions->bToolbar = (ui.fileToolbar->isVisible() || ui.editToolbar->isVisible() || ui.channelsToolbar->isVisible());                          m_pOptions->bToolbar = (m_ui.fileToolbar->isVisible()
463              m_pOptions->bStatusbar = statusBar()->isVisible();                                  || m_ui.editToolbar->isVisible()
464              // Save the dock windows state.                                  || m_ui.channelsToolbar->isVisible());
465              const QString sDockables = saveState().toBase64().data();                          m_pOptions->bStatusbar = statusBar()->isVisible();
466                            // Save the dock windows state.
467                            const QString sDockables = saveState().toBase64().data();
468                          m_pOptions->settings().setValue("/Layout/DockWindows", saveState());                          m_pOptions->settings().setValue("/Layout/DockWindows", saveState());
469              // And the children, and the main windows state,.                          // And the children, and the main windows state,.
470                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);
471                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);
472                          m_pOptions->saveWidgetGeometry(this);                          m_pOptions->saveWidgetGeometry(this);
# Line 462  bool MainForm::queryClose (void) Line 475  bool MainForm::queryClose (void)
475                                  m_pInstrumentListForm->close();                                  m_pInstrumentListForm->close();
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    
483      return bQueryClose;          return bQueryClose;
484  }  }
485    
486    
487  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )
488  {  {
489      if (queryClose())          if (queryClose()) {
490          pCloseEvent->accept();                  DeviceStatusForm::deleteAllInstances();
491      else                  pCloseEvent->accept();
492          pCloseEvent->ignore();          } else
493                    pCloseEvent->ignore();
494  }  }
495    
496    
# Line 504  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 540  void MainForm::dropEvent ( QDropEvent* p Line 554  void MainForm::dropEvent ( QDropEvent* p
554  // Custome event handler.  // Custome event handler.
555  void MainForm::customEvent(QEvent* pCustomEvent)  void MainForm::customEvent(QEvent* pCustomEvent)
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  {  {
634      stabilizeForm();          stabilizeForm();
635    
636      ui.editMenu->exec(pEvent->globalPos());          m_ui.editMenu->exec(pEvent->globalPos());
637  }  }
638    
639    
# Line 569  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)  Options *MainForm::options (void) const
645  {  {
646      return m_pOptions;          return m_pOptions;
647  }  }
648    
649    
650  // The LSCP client descriptor property.  // The LSCP client descriptor property.
651  lscp_client_t *MainForm::client (void)  lscp_client_t *MainForm::client (void) const
652  {  {
653      return m_pClient;          return m_pClient;
654  }  }
655    
656    
# Line 595  MainForm *MainForm::getInstance (void) Line 667  MainForm *MainForm::getInstance (void)
667  // Format the displayable session filename.  // Format the displayable session filename.
668  QString MainForm::sessionName ( const QString& sFilename )  QString MainForm::sessionName ( const QString& sFilename )
669  {  {
670      bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);          bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);
671      QString sSessionName = sFilename;          QString sSessionName = sFilename;
672      if (sSessionName.isEmpty())          if (sSessionName.isEmpty())
673          sSessionName = tr("Untitled") + QString::number(m_iUntitled);                  sSessionName = tr("Untitled") + QString::number(m_iUntitled);
674      else if (!bCompletePath)          else if (!bCompletePath)
675          sSessionName = QFileInfo(sSessionName).fileName();                  sSessionName = QFileInfo(sSessionName).fileName();
676      return sSessionName;          return sSessionName;
677  }  }
678    
679    
680  // Create a new session file from scratch.  // Create a new session file from scratch.
681  bool MainForm::newSession (void)  bool MainForm::newSession (void)
682  {  {
683      // Check if we can do it.          // Check if we can do it.
684      if (!closeSession(true))          if (!closeSession(true))
685          return false;                  return false;
686    
687          // Give us what the server has, right now...          // Give us what the server has, right now...
688          updateSession();          updateSession();
689    
690      // Ok increment untitled count.          // Ok increment untitled count.
691      m_iUntitled++;          m_iUntitled++;
692    
693      // Stabilize form.          // Stabilize form.
694      m_sFilename = QString::null;          m_sFilename = QString::null;
695      m_iDirtyCount = 0;          m_iDirtyCount = 0;
696      appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));          appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));
697      stabilizeForm();          stabilizeForm();
698    
699      return true;          return true;
700  }  }
701    
702    
703  // Open an existing sampler session.  // Open an existing sampler session.
704  bool MainForm::openSession (void)  bool MainForm::openSession (void)
705  {  {
706      if (m_pOptions == NULL)          if (m_pOptions == NULL)
707          return false;                  return false;
708    
709      // Ask for the filename to open...          // Ask for the filename to open...
710          QString sFilename = QFileDialog::getOpenFileName(this,          QString sFilename = QFileDialog::getOpenFileName(this,
711                  QSAMPLER_TITLE ": " + tr("Open Session"), // Caption.                  QSAMPLER_TITLE ": " + tr("Open Session"), // Caption.
712                  m_pOptions->sSessionDir,                  // Start here.                  m_pOptions->sSessionDir,                  // Start here.
713                  tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)                  tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
714          );          );
715    
716      // Have we cancelled?          // Have we cancelled?
717      if (sFilename.isEmpty())          if (sFilename.isEmpty())
718          return false;                  return false;
719    
720      // Check if we're going to discard safely the current one...          // Check if we're going to discard safely the current one...
721      if (!closeSession(true))          if (!closeSession(true))
722          return false;                  return false;
723    
724      // Load it right away.          // Load it right away.
725      return loadSessionFile(sFilename);          return loadSessionFile(sFilename);
726  }  }
727    
728    
729  // Save current sampler session with another name.  // Save current sampler session with another name.
730  bool MainForm::saveSession ( bool bPrompt )  bool MainForm::saveSession ( bool bPrompt )
731  {  {
732      if (m_pOptions == NULL)          if (m_pOptions == NULL)
733          return false;                  return false;
734    
735      QString sFilename = m_sFilename;          QString sFilename = m_sFilename;
736    
737      // Ask for the file to save, if there's none...          // Ask for the file to save, if there's none...
738      if (bPrompt || sFilename.isEmpty()) {          if (bPrompt || sFilename.isEmpty()) {
739          // If none is given, assume default directory.                  // If none is given, assume default directory.
740          if (sFilename.isEmpty())                  if (sFilename.isEmpty())
741              sFilename = m_pOptions->sSessionDir;                          sFilename = m_pOptions->sSessionDir;
742          // Prompt the guy...                  // Prompt the guy...
743                  sFilename = QFileDialog::getSaveFileName(this,                  sFilename = QFileDialog::getSaveFileName(this,
744                          QSAMPLER_TITLE ": " + tr("Save Session"), // Caption.                          QSAMPLER_TITLE ": " + tr("Save Session"), // Caption.
745                          sFilename,                                // Start here.                          sFilename,                                // Start here.
746                          tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)                          tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
747                  );                  );
748          // Have we cancelled it?                  // Have we cancelled it?
749          if (sFilename.isEmpty())                  if (sFilename.isEmpty())
750              return false;                          return false;
751          // Enforce .lscp extension...                  // Enforce .lscp extension...
752          if (QFileInfo(sFilename).suffix().isEmpty())                  if (QFileInfo(sFilename).suffix().isEmpty())
753              sFilename += ".lscp";                          sFilename += ".lscp";
754          // Check if already exists...                  // Check if already exists...
755          if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {                  if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {
756              if (QMessageBox::warning(this,                          if (QMessageBox::warning(this,
757                                  QSAMPLER_TITLE ": " + tr("Warning"),                                  QSAMPLER_TITLE ": " + tr("Warning"),
758                  tr("The file already exists:\n\n"                                  tr("The file already exists:\n\n"
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)                                  tr("Replace"), tr("Cancel")) > 0)
763                  return false;                                  return false;
764          }                  }
765      }          }
766    
767      // Save it right away.          // Save it right away.
768      return saveSessionFile(sFilename);          return saveSessionFile(sFilename);
769  }  }
770    
771    
772  // Close current session.  // Close current session.
773  bool MainForm::closeSession ( bool bForce )  bool MainForm::closeSession ( bool bForce )
774  {  {
775      bool bClose = true;          bool bClose = true;
776    
777      // Are we dirty enough to prompt it?          // Are we dirty enough to prompt it?
778      if (m_iDirtyCount > 0) {          if (m_iDirtyCount > 0) {
779          switch (QMessageBox::warning(this,                  switch (QMessageBox::warning(this,
780                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
781              tr("The current session has been changed:\n\n"                          tr("The current session has been changed:\n\n"
782              "\"%1\"\n\n"                          "\"%1\"\n\n"
783              "Do you want to save the changes?")                          "Do you want to save the changes?")
784              .arg(sessionName(m_sFilename)),                          .arg(sessionName(m_sFilename)),
785              tr("Save"), tr("Discard"), tr("Cancel"))) {                          tr("Save"), tr("Discard"), tr("Cancel"))) {
786          case 0:     // Save...                  case 0:     // Save...
787              bClose = saveSession(false);                          bClose = saveSession(false);
788              // Fall thru....                          // Fall thru....
789          case 1:     // Discard                  case 1:     // Discard
790              break;                          break;
791          default:    // Cancel.                  default:    // Cancel.
792              bClose = false;                          bClose = false;
793              break;                          break;
794          }                  }
795      }          }
   
     // If we may close it, dot it.  
     if (bClose) {  
         // Remove all channel strips from sight...  
         m_pWorkspace->setUpdatesEnabled(false);  
         QWidgetList wlist = m_pWorkspace->windowList();  
         for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {  
             ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);  
             if (pChannelStrip) {  
                 qsamplerChannel *pChannel = pChannelStrip->channel();  
                 if (bForce && pChannel)  
                     pChannel->removeChannel();  
                 delete pChannelStrip;  
             }  
         }  
         m_pWorkspace->setUpdatesEnabled(true);  
         // We're now clean, for sure.  
         m_iDirtyCount = 0;  
     }  
796    
797      return bClose;          // If we may close it, dot it.
798            if (bClose) {
799                    // Remove all channel strips from sight...
800                    m_pWorkspace->setUpdatesEnabled(false);
801                    QWidgetList wlist = m_pWorkspace->windowList();
802                    for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
803                            ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
804                            if (pChannelStrip) {
805                                    Channel *pChannel = pChannelStrip->channel();
806                                    if (bForce && pChannel)
807                                            pChannel->removeChannel();
808                                    delete pChannelStrip;
809                            }
810                    }
811                    m_pWorkspace->setUpdatesEnabled(true);
812                    // We're now clean, for sure.
813                    m_iDirtyCount = 0;
814            }
815    
816            return bClose;
817  }  }
818    
819    
820  // Load a session from specific file path.  // Load a session from specific file path.
821  bool MainForm::loadSessionFile ( const QString& sFilename )  bool MainForm::loadSessionFile ( const QString& sFilename )
822  {  {
823      if (m_pClient == NULL)          if (m_pClient == NULL)
824          return false;                  return false;
825    
826      // Open and read from real file.          // Open and read from real file.
827      QFile file(sFilename);          QFile file(sFilename);
828      if (!file.open(QIODevice::ReadOnly)) {          if (!file.open(QIODevice::ReadOnly)) {
829          appendMessagesError(tr("Could not open \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
830          return false;                          tr("Could not open \"%1\" session file.\n\nSorry.")
831      }                          .arg(sFilename));
832                    return false;
833            }
834    
835          // Tell the world we'll take some time...          // Tell the world we'll take some time...
836          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
837    
838      // Read the file.          // Read the file.
839          int iLine = 0;          int iLine = 0;
840      int iErrors = 0;          int iErrors = 0;
841      QTextStream ts(&file);          QTextStream ts(&file);
842      while (!ts.atEnd()) {          while (!ts.atEnd()) {
843          // Read the line.                  // Read the line.
844          QString sCommand = ts.readLine().trimmed();                  QString sCommand = ts.readLine().trimmed();
845                  iLine++;                  iLine++;
846          // If not empty, nor a comment, call the server...                  // If not empty, nor a comment, call the server...
847          if (!sCommand.isEmpty() && sCommand[0] != '#') {                  if (!sCommand.isEmpty() && sCommand[0] != '#') {
848                          // Remember that, no matter what,                          // Remember that, no matter what,
849                          // all LSCP commands are CR/LF terminated.                          // all LSCP commands are CR/LF terminated.
850                          sCommand += "\r\n";                          sCommand += "\r\n";
# Line 782  bool MainForm::loadSessionFile ( const Q Line 856  bool MainForm::loadSessionFile ( const Q
856                                  appendMessagesClient("lscp_client_query");                                  appendMessagesClient("lscp_client_query");
857                                  iErrors++;                                  iErrors++;
858                          }                          }
859          }                  }
860          // Try to make it snappy :)                  // Try to make it snappy :)
861          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
862      }          }
863    
864      // Ok. we've read it.          // Ok. we've read it.
865      file.close();          file.close();
866    
867          // Now we'll try to create (update) the whole GUI session.          // Now we'll try to create (update) the whole GUI session.
868          updateSession();          updateSession();
# Line 797  bool MainForm::loadSessionFile ( const Q Line 871  bool MainForm::loadSessionFile ( const Q
871          QApplication::restoreOverrideCursor();          QApplication::restoreOverrideCursor();
872    
873          // Have we any errors?          // Have we any errors?
874          if (iErrors > 0)          if (iErrors > 0) {
875                  appendMessagesError(tr("Session loaded with errors\nfrom \"%1\".\n\nSorry.").arg(sFilename));                  appendMessagesError(
876                            tr("Session loaded with errors\nfrom \"%1\".\n\nSorry.")
877                            .arg(sFilename));
878            }
879    
880      // Save as default session directory.          // Save as default session directory.
881      if (m_pOptions)          if (m_pOptions)
882          m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();                  m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();
883          // We're not dirty anymore, if loaded without errors,          // We're not dirty anymore, if loaded without errors,
884          m_iDirtyCount = iErrors;          m_iDirtyCount = iErrors;
885      // Stabilize form...          // Stabilize form...
886      m_sFilename = sFilename;          m_sFilename = sFilename;
887      updateRecentFiles(sFilename);          updateRecentFiles(sFilename);
888      appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));          appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));
889    
890      // Make that an overall update.          // Make that an overall update.
891      stabilizeForm();          stabilizeForm();
892      return true;          return true;
893  }  }
894    
895    
# Line 828  bool MainForm::saveSessionFile ( const Q Line 905  bool MainForm::saveSessionFile ( const Q
905                  return false;                  return false;
906          }          }
907    
908      // Open and write into real file.          // Open and write into real file.
909      QFile file(sFilename);          QFile file(sFilename);
910      if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {          if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
911          appendMessagesError(tr("Could not open \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
912          return false;                          tr("Could not open \"%1\" session file.\n\nSorry.")
913      }                          .arg(sFilename));
914                    return false;
915            }
916    
917          // Tell the world we'll take some time...          // Tell the world we'll take some time...
918          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
919    
920      // Write the file.          // Write the file.
921      int  iErrors = 0;          int  iErrors = 0;
922      QTextStream ts(&file);          QTextStream ts(&file);
923      ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;          ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;
924      ts << "# " << tr("Version")          ts << "# " << tr("Version")
925         << ": " QSAMPLER_VERSION << endl;          << ": " QSAMPLER_VERSION << endl;
926      ts << "# " << tr("Build")          ts << "# " << tr("Build")
927         << ": " __DATE__ " " __TIME__ << endl;          << ": " __DATE__ " " __TIME__ << endl;
928      ts << "#"  << endl;          ts << "#"  << endl;
929      ts << "# " << tr("File")          ts << "# " << tr("File")
930         << ": " << QFileInfo(sFilename).fileName() << endl;          << ": " << QFileInfo(sFilename).fileName() << endl;
931      ts << "# " << tr("Date")          ts << "# " << tr("Date")
932         << ": " << QDate::currentDate().toString("MMM dd yyyy")          << ": " << QDate::currentDate().toString("MMM dd yyyy")
933         << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;          << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;
934      ts << "#"  << endl;          ts << "#"  << endl;
935      ts << endl;          ts << endl;
936    
937          // It is assumed that this new kind of device+session file          // It is assumed that this new kind of device+session file
938          // will be loaded from a complete initialized server...          // will be loaded from a complete initialized server...
# Line 863  bool MainForm::saveSessionFile ( const Q Line 942  bool MainForm::saveSessionFile ( const Q
942    
943          // Audio device mapping.          // Audio device mapping.
944          QMap<int, int> audioDeviceMap;          QMap<int, int> audioDeviceMap;
945          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Audio);          piDeviceIDs = Device::getDevices(m_pClient, Device::Audio);
946          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
947                  ts << endl;                  ts << endl;
948                  qsamplerDevice device(qsamplerDevice::Audio, piDeviceIDs[iDevice]);                  Device device(Device::Audio, piDeviceIDs[iDevice]);
949                  // Audio device specification...                  // Audio device specification...
950                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
951                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
952                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();
953                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
954                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
955                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
956                                          ++deviceParam) {                                          ++deviceParam) {
957                          const qsamplerDeviceParam& param = deviceParam.value();                          const DeviceParam& param = deviceParam.value();
958                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
959                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
960                  }                  }
961                  ts << endl;                  ts << endl;
962                  // Audio channel parameters...                  // Audio channel parameters...
963                  int iPort = 0;                  int iPort = 0;
964                  QListIterator<qsamplerDevicePort *> iter(device.ports());                  QListIterator<DevicePort *> iter(device.ports());
965                  while (iter.hasNext()) {                  while (iter.hasNext()) {
966                          qsamplerDevicePort *pPort = iter.next();                          DevicePort *pPort = iter.next();
967                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
968                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
969                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
970                                                  ++portParam) {                                                  ++portParam) {
971                                  const qsamplerDeviceParam& param = portParam.value();                                  const DeviceParam& param = portParam.value();
972                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
973                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice
974                                          << " " << iPort << " " << portParam.key()                                          << " " << iPort << " " << portParam.key()
# Line 905  bool MainForm::saveSessionFile ( const Q Line 984  bool MainForm::saveSessionFile ( const Q
984    
985          // MIDI device mapping.          // MIDI device mapping.
986          QMap<int, int> midiDeviceMap;          QMap<int, int> midiDeviceMap;
987          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Midi);          piDeviceIDs = Device::getDevices(m_pClient, Device::Midi);
988          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
989                  ts << endl;                  ts << endl;
990                  qsamplerDevice device(qsamplerDevice::Midi, piDeviceIDs[iDevice]);                  Device device(Device::Midi, piDeviceIDs[iDevice]);
991                  // MIDI device specification...                  // MIDI device specification...
992                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
993                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
994                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();
995                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
996                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
997                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
998                                          ++deviceParam) {                                          ++deviceParam) {
999                          const qsamplerDeviceParam& param = deviceParam.value();                          const DeviceParam& param = deviceParam.value();
1000                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
1001                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
1002                  }                  }
1003                  ts << endl;                  ts << endl;
1004                  // MIDI port parameters...                  // MIDI port parameters...
1005                  int iPort = 0;                  int iPort = 0;
1006                  QListIterator<qsamplerDevicePort *> iter(device.ports());                  QListIterator<DevicePort *> iter(device.ports());
1007                  while (iter.hasNext()) {                  while (iter.hasNext()) {
1008                          qsamplerDevicePort *pPort = iter.next();                          DevicePort *pPort = iter.next();
1009                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1010                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1011                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1012                                                  ++portParam) {                                                  ++portParam) {
1013                                  const qsamplerDeviceParam& param = portParam.value();                                  const DeviceParam& param = portParam.value();
1014                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1015                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice
1016                                     << " " << iPort << " " << portParam.key()                                  << " " << iPort << " " << portParam.key()
1017                                     << "='" << param.value << "'" << endl;                                  << "='" << param.value << "'" << endl;
1018                          }                          }
1019                          iPort++;                          iPort++;
1020                  }                  }
# Line 1018  bool MainForm::saveSessionFile ( const Q Line 1097  bool MainForm::saveSessionFile ( const Q
1097  #endif  // CONFIG_MIDI_INSTRUMENT  #endif  // CONFIG_MIDI_INSTRUMENT
1098    
1099          // Sampler channel mapping.          // Sampler channel mapping.
1100      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
1101      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1102          ChannelStrip* pChannelStrip                  ChannelStrip* pChannelStrip
1103                          = static_cast<ChannelStrip *> (wlist.at(iChannel));                          = static_cast<ChannelStrip *> (wlist.at(iChannel));
1104          if (pChannelStrip) {                  if (pChannelStrip) {
1105              qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
1106              if (pChannel) {                          if (pChannel) {
1107                  ts << "# " << tr("Channel") << " " << iChannel << endl;                                  ts << "# " << tr("Channel") << " " << iChannel << endl;
1108                  ts << "ADD CHANNEL" << endl;                                  ts << "ADD CHANNEL" << endl;
1109                                  if (audioDeviceMap.isEmpty()) {                                  if (audioDeviceMap.isEmpty()) {
1110                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel
1111                                                  << " " << pChannel->audioDriver() << endl;                                                  << " " << pChannel->audioDriver() << endl;
# Line 1043  bool MainForm::saveSessionFile ( const Q Line 1122  bool MainForm::saveSessionFile ( const Q
1122                                  }                                  }
1123                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel
1124                                          << " " << pChannel->midiPort() << endl;                                          << " " << pChannel->midiPort() << endl;
1125                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";                                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";
1126                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)                                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
1127                      ts << "ALL";                                          ts << "ALL";
1128                  else                                  else
1129                      ts << pChannel->midiChannel();                                          ts << pChannel->midiChannel();
1130                  ts << endl;                                  ts << endl;
1131                  ts << "LOAD ENGINE " << pChannel->engineName() << " " << iChannel << endl;                                  ts << "LOAD ENGINE " << pChannel->engineName()
1132                                            << " " << iChannel << endl;
1133                                  if (pChannel->instrumentStatus() < 100) ts << "# ";                                  if (pChannel->instrumentStatus() < 100) ts << "# ";
1134                                  ts << "LOAD INSTRUMENT NON_MODAL '" << pChannel->instrumentFile() << "' "                                  ts << "LOAD INSTRUMENT NON_MODAL '"
1135                                            << pChannel->instrumentFile() << "' "
1136                                          << pChannel->instrumentNr() << " " << iChannel << endl;                                          << pChannel->instrumentNr() << " " << iChannel << endl;
1137                                  qsamplerChannelRoutingMap::ConstIterator audioRoute;                                  ChannelRoutingMap::ConstIterator audioRoute;
1138                                  for (audioRoute = pChannel->audioRouting().begin();                                  for (audioRoute = pChannel->audioRouting().begin();
1139                                                  audioRoute != pChannel->audioRouting().end();                                                  audioRoute != pChannel->audioRouting().end();
1140                                                          ++audioRoute) {                                                          ++audioRoute) {
# Line 1109  bool MainForm::saveSessionFile ( const Q Line 1190  bool MainForm::saveSessionFile ( const Q
1190                                          }                                          }
1191                                  }                                  }
1192  #endif  #endif
1193                  ts << endl;                                  ts << endl;
1194              }                          }
1195          }                  }
1196          // Try to keep it snappy :)                  // Try to keep it snappy :)
1197          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1198      }          }
1199    
1200  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
1201          ts << "# " << tr("Global volume level") << endl;          ts << "# " << tr("Global volume level") << endl;
# Line 1122  bool MainForm::saveSessionFile ( const Q Line 1203  bool MainForm::saveSessionFile ( const Q
1203          ts << endl;          ts << endl;
1204  #endif  #endif
1205    
1206      // Ok. we've wrote it.          // Ok. we've wrote it.
1207      file.close();          file.close();
1208    
1209          // We're fornerly done.          // We're fornerly done.
1210          QApplication::restoreOverrideCursor();          QApplication::restoreOverrideCursor();
1211    
1212      // Have we any errors?          // Have we any errors?
1213      if (iErrors > 0)          if (iErrors > 0) {
1214          appendMessagesError(tr("Some settings could not be saved\nto \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
1215                            tr("Some settings could not be saved\n"
1216      // Save as default session directory.                          "to \"%1\" session file.\n\nSorry.")
1217      if (m_pOptions)                          .arg(sFilename));
1218          m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();          }
1219      // We're not dirty anymore.  
1220      m_iDirtyCount = 0;          // Save as default session directory.
1221      // Stabilize form...          if (m_pOptions)
1222      m_sFilename = sFilename;                  m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();
1223      updateRecentFiles(sFilename);          // We're not dirty anymore.
1224      appendMessages(tr("Save session: \"%1\".").arg(sessionName(m_sFilename)));          m_iDirtyCount = 0;
1225      stabilizeForm();          // Stabilize form...
1226      return true;          m_sFilename = sFilename;
1227            updateRecentFiles(sFilename);
1228            appendMessages(tr("Save session: \"%1\".").arg(sessionName(m_sFilename)));
1229            stabilizeForm();
1230            return true;
1231  }  }
1232    
1233    
1234  // Session change receiver slot.  // Session change receiver slot.
1235  void MainForm::sessionDirty (void)  void MainForm::sessionDirty (void)
1236  {  {
1237      // Just mark the dirty form.          // Just mark the dirty form.
1238      m_iDirtyCount++;          m_iDirtyCount++;
1239      // and update the form status...          // and update the form status...
1240      stabilizeForm();          stabilizeForm();
1241  }  }
1242    
1243    
# Line 1162  void MainForm::sessionDirty (void) Line 1247  void MainForm::sessionDirty (void)
1247  // Create a new sampler session.  // Create a new sampler session.
1248  void MainForm::fileNew (void)  void MainForm::fileNew (void)
1249  {  {
1250      // Of course we'll start clean new.          // Of course we'll start clean new.
1251      newSession();          newSession();
1252  }  }
1253    
1254    
1255  // Open an existing sampler session.  // Open an existing sampler session.
1256  void MainForm::fileOpen (void)  void MainForm::fileOpen (void)
1257  {  {
1258      // Open it right away.          // Open it right away.
1259      openSession();          openSession();
1260  }  }
1261    
1262    
# Line 1195  void MainForm::fileOpenRecent (void) Line 1280  void MainForm::fileOpenRecent (void)
1280  // Save current sampler session.  // Save current sampler session.
1281  void MainForm::fileSave (void)  void MainForm::fileSave (void)
1282  {  {
1283      // Save it right away.          // Save it right away.
1284      saveSession(false);          saveSession(false);
1285  }  }
1286    
1287    
1288  // Save current sampler session with another name.  // Save current sampler session with another name.
1289  void MainForm::fileSaveAs (void)  void MainForm::fileSaveAs (void)
1290  {  {
1291      // Save it right away, maybe with another name.          // Save it right away, maybe with another name.
1292      saveSession(true);          saveSession(true);
1293  }  }
1294    
1295    
1296  // Reset the sampler instance.  // Reset the sampler instance.
1297  void MainForm::fileReset (void)  void MainForm::fileReset (void)
1298  {  {
1299      if (m_pClient == NULL)          if (m_pClient == NULL)
1300          return;                  return;
1301    
1302      // Ask user whether he/she want's an internal sampler reset...          // Ask user whether he/she want's an internal sampler reset...
1303      if (QMessageBox::warning(this,          if (QMessageBox::warning(this,
1304                  QSAMPLER_TITLE ": " + tr("Warning"),                  QSAMPLER_TITLE ": " + tr("Warning"),
1305          tr("Resetting the sampler instance will close\n"                  tr("Resetting the sampler instance will close\n"
1306             "all device and channel configurations.\n\n"                  "all device and channel configurations.\n\n"
1307             "Please note that this operation may cause\n"                  "Please note that this operation may cause\n"
1308             "temporary MIDI and Audio disruption.\n\n"                  "temporary MIDI and Audio disruption.\n\n"
1309             "Do you want to reset the sampler engine now?"),                  "Do you want to reset the sampler engine now?"),
1310          tr("Reset"), tr("Cancel")) > 0)                  tr("Reset"), tr("Cancel")) > 0)
1311          return;                  return;
1312    
1313          // Trye closing the current session, first...          // Trye closing the current session, first...
1314          if (!closeSession(true))          if (!closeSession(true))
1315                  return;                  return;
1316    
1317      // Just do the reset, after closing down current session...          // Just do the reset, after closing down current session...
1318          // Do the actual sampler reset...          // Do the actual sampler reset...
1319          if (::lscp_reset_sampler(m_pClient) != LSCP_OK) {          if (::lscp_reset_sampler(m_pClient) != LSCP_OK) {
1320                  appendMessagesClient("lscp_reset_sampler");                  appendMessagesClient("lscp_reset_sampler");
# Line 1237  void MainForm::fileReset (void) Line 1322  void MainForm::fileReset (void)
1322                  return;                  return;
1323          }          }
1324    
1325      // Log this.          // Log this.
1326      appendMessages(tr("Sampler reset."));          appendMessages(tr("Sampler reset."));
1327    
1328          // Make it a new session...          // Make it a new session...
1329          newSession();          newSession();
# Line 1248  void MainForm::fileReset (void) Line 1333  void MainForm::fileReset (void)
1333  // Restart the client/server instance.  // Restart the client/server instance.
1334  void MainForm::fileRestart (void)  void MainForm::fileRestart (void)
1335  {  {
1336      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1337          return;                  return;
1338    
1339      bool bRestart = true;          bool bRestart = true;
1340    
1341      // Ask user whether he/she want's a complete restart...          // Ask user whether he/she want's a complete restart...
1342      // (if we're currently up and running)          // (if we're currently up and running)
1343      if (bRestart && m_pClient) {          if (bRestart && m_pClient) {
1344          bRestart = (QMessageBox::warning(this,                  bRestart = (QMessageBox::warning(this,
1345                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
1346              tr("New settings will be effective after\n"                          tr("New settings will be effective after\n"
1347                 "restarting the client/server connection.\n\n"                          "restarting the client/server connection.\n\n"
1348                 "Please note that this operation may cause\n"                          "Please note that this operation may cause\n"
1349                 "temporary MIDI and Audio disruption.\n\n"                          "temporary MIDI and Audio disruption.\n\n"
1350                 "Do you want to restart the connection now?"),                          "Do you want to restart the connection now?"),
1351              tr("Restart"), tr("Cancel")) == 0);                          tr("Restart"), tr("Cancel")) == 0);
1352      }          }
1353    
1354      // Are we still for it?          // Are we still for it?
1355      if (bRestart && closeSession(true)) {          if (bRestart && closeSession(true)) {
1356          // Stop server, it will force the client too.                  // Stop server, it will force the client too.
1357          stopServer();                  stopServer();
1358          // Reschedule a restart...                  // Reschedule a restart...
1359          startSchedule(m_pOptions->iStartDelay);                  startSchedule(m_pOptions->iStartDelay);
1360      }          }
1361  }  }
1362    
1363    
1364  // Exit application program.  // Exit application program.
1365  void MainForm::fileExit (void)  void MainForm::fileExit (void)
1366  {  {
1367      // Go for close the whole thing.          // Go for close the whole thing.
1368      close();          close();
1369  }  }
1370    
1371    
# Line 1290  void MainForm::fileExit (void) Line 1375  void MainForm::fileExit (void)
1375  // Add a new sampler channel.  // Add a new sampler channel.
1376  void MainForm::editAddChannel (void)  void MainForm::editAddChannel (void)
1377  {  {
1378      if (m_pClient == NULL)          if (m_pClient == NULL)
1379          return;                  return;
1380    
1381            // Just create the channel instance...
1382            Channel *pChannel = new Channel();
1383            if (pChannel == NULL)
1384                    return;
1385    
1386      // Just create the channel instance...          // Before we show it up, may be we'll
1387      qsamplerChannel *pChannel = new qsamplerChannel();          // better ask for some initial values?
1388      if (pChannel == NULL)          if (!pChannel->channelSetup(this)) {
1389          return;                  delete pChannel;
1390                    return;
1391      // Before we show it up, may be we'll          }
1392      // better ask for some initial values?  
1393      if (!pChannel->channelSetup(this)) {          // And give it to the strip...
1394          delete pChannel;          // (will own the channel instance, if successful).
1395          return;          if (!createChannelStrip(pChannel)) {
1396      }                  delete pChannel;
1397                    return;
1398      // And give it to the strip (will own the channel instance, if successful).          }
1399      if (!createChannelStrip(pChannel)) {  
1400          delete pChannel;          // Do we auto-arrange?
1401          return;          if (m_pOptions && m_pOptions->bAutoArrange)
1402      }                  channelsArrange();
1403    
1404      // Make that an overall update.          // Make that an overall update.
1405      m_iDirtyCount++;          m_iDirtyCount++;
1406      stabilizeForm();          stabilizeForm();
1407  }  }
1408    
1409    
1410  // Remove current sampler channel.  // Remove current sampler channel.
1411  void MainForm::editRemoveChannel (void)  void MainForm::editRemoveChannel (void)
1412  {  {
1413      if (m_pClient == NULL)          if (m_pClient == NULL)
1414          return;                  return;
1415    
1416      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1417      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1418          return;                  return;
1419    
1420      qsamplerChannel *pChannel = pChannelStrip->channel();          Channel *pChannel = pChannelStrip->channel();
1421      if (pChannel == NULL)          if (pChannel == NULL)
1422          return;                  return;
1423    
1424      // Prompt user if he/she's sure about this...          // Prompt user if he/she's sure about this...
1425      if (m_pOptions && m_pOptions->bConfirmRemove) {          if (m_pOptions && m_pOptions->bConfirmRemove) {
1426          if (QMessageBox::warning(this,                  if (QMessageBox::warning(this,
1427                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
1428              tr("About to remove channel:\n\n"                          tr("About to remove channel:\n\n"
1429                 "%1\n\n"                          "%1\n\n"
1430                 "Are you sure?")                          "Are you sure?")
1431                 .arg(pChannelStrip->windowTitle()),                          .arg(pChannelStrip->windowTitle()),
1432              tr("OK"), tr("Cancel")) > 0)                          tr("OK"), tr("Cancel")) > 0)
1433              return;                          return;
1434      }          }
1435    
1436      // Remove the existing sampler channel.          // Remove the existing sampler channel.
1437      if (!pChannel->removeChannel())          if (!pChannel->removeChannel())
1438          return;                  return;
1439    
1440      // Just delete the channel strip.          // Just delete the channel strip.
1441      delete pChannelStrip;          delete pChannelStrip;
1442    
1443      // Do we auto-arrange?          // Do we auto-arrange?
1444      if (m_pOptions && m_pOptions->bAutoArrange)          if (m_pOptions && m_pOptions->bAutoArrange)
1445          channelsArrange();                  channelsArrange();
1446    
1447      // We'll be dirty, for sure...          // We'll be dirty, for sure...
1448      m_iDirtyCount++;          m_iDirtyCount++;
1449      stabilizeForm();          stabilizeForm();
1450  }  }
1451    
1452    
1453  // Setup current sampler channel.  // Setup current sampler channel.
1454  void MainForm::editSetupChannel (void)  void MainForm::editSetupChannel (void)
1455  {  {
1456      if (m_pClient == NULL)          if (m_pClient == NULL)
1457          return;                  return;
1458    
1459      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1460      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1461          return;                  return;
1462    
1463      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1464      pChannelStrip->channelSetup();          pChannelStrip->channelSetup();
1465  }  }
1466    
1467    
1468  // Edit current sampler channel.  // Edit current sampler channel.
1469  void MainForm::editEditChannel (void)  void MainForm::editEditChannel (void)
1470  {  {
1471      if (m_pClient == NULL)          if (m_pClient == NULL)
1472          return;                  return;
1473    
1474      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1475      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1476          return;                  return;
1477    
1478      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1479      pChannelStrip->channelEdit();          pChannelStrip->channelEdit();
1480  }  }
1481    
1482    
1483  // Reset current sampler channel.  // Reset current sampler channel.
1484  void MainForm::editResetChannel (void)  void MainForm::editResetChannel (void)
1485  {  {
1486      if (m_pClient == NULL)          if (m_pClient == NULL)
1487          return;                  return;
1488    
1489      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1490      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1491          return;                  return;
1492    
1493      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1494      pChannelStrip->channelReset();          pChannelStrip->channelReset();
1495  }  }
1496    
1497    
# Line 1430  void MainForm::editResetAllChannels (voi Line 1520  void MainForm::editResetAllChannels (voi
1520  // Show/hide the main program window menubar.  // Show/hide the main program window menubar.
1521  void MainForm::viewMenubar ( bool bOn )  void MainForm::viewMenubar ( bool bOn )
1522  {  {
1523      if (bOn)          if (bOn)
1524          ui.MenuBar->show();                  m_ui.MenuBar->show();
1525      else          else
1526          ui.MenuBar->hide();                  m_ui.MenuBar->hide();
1527  }  }
1528    
1529    
1530  // Show/hide the main program window toolbar.  // Show/hide the main program window toolbar.
1531  void MainForm::viewToolbar ( bool bOn )  void MainForm::viewToolbar ( bool bOn )
1532  {  {
1533      if (bOn) {          if (bOn) {
1534          ui.fileToolbar->show();                  m_ui.fileToolbar->show();
1535          ui.editToolbar->show();                  m_ui.editToolbar->show();
1536          ui.channelsToolbar->show();                  m_ui.channelsToolbar->show();
1537      } else {          } else {
1538          ui.fileToolbar->hide();                  m_ui.fileToolbar->hide();
1539          ui.editToolbar->hide();                  m_ui.editToolbar->hide();
1540          ui.channelsToolbar->hide();                  m_ui.channelsToolbar->hide();
1541      }          }
1542  }  }
1543    
1544    
1545  // Show/hide the main program window statusbar.  // Show/hide the main program window statusbar.
1546  void MainForm::viewStatusbar ( bool bOn )  void MainForm::viewStatusbar ( bool bOn )
1547  {  {
1548      if (bOn)          if (bOn)
1549          statusBar()->show();                  statusBar()->show();
1550      else          else
1551          statusBar()->hide();                  statusBar()->hide();
1552  }  }
1553    
1554    
1555  // Show/hide the messages window logger.  // Show/hide the messages window logger.
1556  void MainForm::viewMessages ( bool bOn )  void MainForm::viewMessages ( bool bOn )
1557  {  {
1558      if (bOn)          if (bOn)
1559          m_pMessages->show();                  m_pMessages->show();
1560      else          else
1561          m_pMessages->hide();                  m_pMessages->hide();
1562  }  }
1563    
1564    
# Line 1513  void MainForm::viewDevices (void) Line 1603  void MainForm::viewDevices (void)
1603  // Show options dialog.  // Show options dialog.
1604  void MainForm::viewOptions (void)  void MainForm::viewOptions (void)
1605  {  {
1606      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1607          return;                  return;
1608    
1609      OptionsForm* pOptionsForm = new OptionsForm(this);          OptionsForm* pOptionsForm = new OptionsForm(this);
1610      if (pOptionsForm) {          if (pOptionsForm) {
1611          // Check out some initial nullities(tm)...                  // Check out some initial nullities(tm)...
1612          ChannelStrip* pChannelStrip = activeChannelStrip();                  ChannelStrip* pChannelStrip = activeChannelStrip();
1613          if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)
1614              m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();
1615          if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)
1616              m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
1617          // To track down deferred or immediate changes.                  // To track down deferred or immediate changes.
1618          QString sOldServerHost      = m_pOptions->sServerHost;                  QString sOldServerHost      = m_pOptions->sServerHost;
1619          int     iOldServerPort      = m_pOptions->iServerPort;                  int     iOldServerPort      = m_pOptions->iServerPort;
1620          int     iOldServerTimeout   = m_pOptions->iServerTimeout;                  int     iOldServerTimeout   = m_pOptions->iServerTimeout;
1621          bool    bOldServerStart     = m_pOptions->bServerStart;                  bool    bOldServerStart     = m_pOptions->bServerStart;
1622          QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;                  QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;
1623          QString sOldDisplayFont     = m_pOptions->sDisplayFont;                  bool    bOldMessagesLog     = m_pOptions->bMessagesLog;
1624          bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;                  QString sOldMessagesLogPath = m_pOptions->sMessagesLogPath;
1625          int     iOldMaxVolume       = m_pOptions->iMaxVolume;                  QString sOldDisplayFont     = m_pOptions->sDisplayFont;
1626          QString sOldMessagesFont    = m_pOptions->sMessagesFont;                  bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;
1627          bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;                  int     iOldMaxVolume       = m_pOptions->iMaxVolume;
1628          bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;                  QString sOldMessagesFont    = m_pOptions->sMessagesFont;
1629          int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;                  bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;
1630          int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;                  bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;
1631          bool    bOldCompletePath    = m_pOptions->bCompletePath;                  int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;
1632          bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;                  int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;
1633          int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;                  bool    bOldCompletePath    = m_pOptions->bCompletePath;
1634          // Load the current setup settings.                  bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;
1635          pOptionsForm->setup(m_pOptions);                  int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;
1636          // Show the setup dialog...                  // Load the current setup settings.
1637          if (pOptionsForm->exec()) {                  pOptionsForm->setup(m_pOptions);
1638              // Warn if something will be only effective on next run.                  // Show the setup dialog...
1639              if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||                  if (pOptionsForm->exec()) {
1640                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||                          // Warn if something will be only effective on next run.
1641                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1642                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||
1643                  QMessageBox::information(this,                                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||
1644                                    (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {
1645                                    QMessageBox::information(this,
1646                                          QSAMPLER_TITLE ": " + tr("Information"),                                          QSAMPLER_TITLE ": " + tr("Information"),
1647                      tr("Some settings may be only effective\n"                                          tr("Some settings may be only effective\n"
1648                         "next time you start this program."), tr("OK"));                                          "next time you start this program."), tr("OK"));
1649                  updateMessagesCapture();                                  updateMessagesCapture();
1650              }                          }
1651              // Check wheather something immediate has changed.                          // Check wheather something immediate has changed.
1652              if (( bOldCompletePath && !m_pOptions->bCompletePath) ||                          if (( bOldMessagesLog && !m_pOptions->bMessagesLog) ||
1653                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||                                  (!bOldMessagesLog &&  m_pOptions->bMessagesLog) ||
1654                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))                                  (sOldMessagesLogPath != m_pOptions->sMessagesLogPath))
1655                  updateRecentFilesMenu();                                  m_pMessages->setLogging(
1656              if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||                                          m_pOptions->bMessagesLog, m_pOptions->sMessagesLogPath);
1657                  (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||
1658                  updateInstrumentNames();                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||
1659              if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
1660                  (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))                                  updateRecentFilesMenu();
1661                  updateDisplayEffect();                          if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||
1662              if (sOldDisplayFont != m_pOptions->sDisplayFont)                                  (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))
1663                  updateDisplayFont();                                  updateInstrumentNames();
1664              if (iOldMaxVolume != m_pOptions->iMaxVolume)                          if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||
1665                  updateMaxVolume();                                  (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))
1666              if (sOldMessagesFont != m_pOptions->sMessagesFont)                                  updateDisplayEffect();
1667                  updateMessagesFont();                          if (sOldDisplayFont != m_pOptions->sDisplayFont)
1668              if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||                                  updateDisplayFont();
1669                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||                          if (iOldMaxVolume != m_pOptions->iMaxVolume)
1670                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))                                  updateMaxVolume();
1671                  updateMessagesLimit();                          if (sOldMessagesFont != m_pOptions->sMessagesFont)
1672              // And now the main thing, whether we'll do client/server recycling?                                  updateMessagesFont();
1673              if ((sOldServerHost != m_pOptions->sServerHost) ||                          if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||
1674                  (iOldServerPort != m_pOptions->iServerPort) ||                                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||
1675                  (iOldServerTimeout != m_pOptions->iServerTimeout) ||                                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))
1676                  ( bOldServerStart && !m_pOptions->bServerStart) ||                                  updateMessagesLimit();
1677                  (!bOldServerStart &&  m_pOptions->bServerStart) ||                          // And now the main thing, whether we'll do client/server recycling?
1678                  (sOldServerCmdLine != m_pOptions->sServerCmdLine && m_pOptions->bServerStart))                          if ((sOldServerHost != m_pOptions->sServerHost) ||
1679                  fileRestart();                                  (iOldServerPort != m_pOptions->iServerPort) ||
1680          }                                  (iOldServerTimeout != m_pOptions->iServerTimeout) ||
1681          // Done.                                  ( bOldServerStart && !m_pOptions->bServerStart) ||
1682          delete pOptionsForm;                                  (!bOldServerStart &&  m_pOptions->bServerStart) ||
1683      }                                  (sOldServerCmdLine != m_pOptions->sServerCmdLine
1684                                    && m_pOptions->bServerStart))
1685                                    fileRestart();
1686                    }
1687                    // Done.
1688                    delete pOptionsForm;
1689            }
1690    
1691      // This makes it.          // This makes it.
1692      stabilizeForm();          stabilizeForm();
1693  }  }
1694    
1695    
# Line 1601  void MainForm::viewOptions (void) Line 1699  void MainForm::viewOptions (void)
1699  // Arrange channel strips.  // Arrange channel strips.
1700  void MainForm::channelsArrange (void)  void MainForm::channelsArrange (void)
1701  {  {
1702      // Full width vertical tiling          // Full width vertical tiling
1703      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
1704      if (wlist.isEmpty())          if (wlist.isEmpty())
1705          return;                  return;
1706    
1707      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
1708      int y = 0;          int y = 0;
1709      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1710          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
1711      /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {          /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {
1712              // Prevent flicker...                          // Prevent flicker...
1713              pChannelStrip->hide();                          pChannelStrip->hide();
1714              pChannelStrip->showNormal();                          pChannelStrip->showNormal();
1715          }   */                  }   */
1716          pChannelStrip->adjustSize();                  pChannelStrip->adjustSize();
1717          int iWidth  = m_pWorkspace->width();                  int iWidth  = m_pWorkspace->width();
1718          if (iWidth < pChannelStrip->width())                  if (iWidth < pChannelStrip->width())
1719              iWidth = pChannelStrip->width();                          iWidth = pChannelStrip->width();
1720      //  int iHeight = pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();          //  int iHeight = pChannelStrip->height()
1721          int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();          //              + pChannelStrip->parentWidget()->baseSize().height();
1722          pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);                  int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();
1723          y += iHeight;                  pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);
1724      }                  y += iHeight;
1725      m_pWorkspace->setUpdatesEnabled(true);          }
1726            m_pWorkspace->setUpdatesEnabled(true);
1727    
1728      stabilizeForm();          stabilizeForm();
1729  }  }
1730    
1731    
1732  // Auto-arrange channel strips.  // Auto-arrange channel strips.
1733  void MainForm::channelsAutoArrange ( bool bOn )  void MainForm::channelsAutoArrange ( bool bOn )
1734  {  {
1735      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1736          return;                  return;
1737    
1738      // Toggle the auto-arrange flag.          // Toggle the auto-arrange flag.
1739      m_pOptions->bAutoArrange = bOn;          m_pOptions->bAutoArrange = bOn;
1740    
1741      // If on, update whole workspace...          // If on, update whole workspace...
1742      if (m_pOptions->bAutoArrange)          if (m_pOptions->bAutoArrange)
1743          channelsArrange();                  channelsArrange();
1744  }  }
1745    
1746    
# Line 1651  void MainForm::channelsAutoArrange ( boo Line 1750  void MainForm::channelsAutoArrange ( boo
1750  // Show information about the Qt toolkit.  // Show information about the Qt toolkit.
1751  void MainForm::helpAboutQt (void)  void MainForm::helpAboutQt (void)
1752  {  {
1753      QMessageBox::aboutQt(this);          QMessageBox::aboutQt(this);
1754  }  }
1755    
1756    
1757  // Show information about application program.  // Show information about application program.
1758  void MainForm::helpAbout (void)  void MainForm::helpAbout (void)
1759  {  {
1760      // Stuff the about box text...          // Stuff the about box text...
1761      QString sText = "<p>\n";          QString sText = "<p>\n";
1762      sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";          sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";
1763      sText += "<br />\n";          sText += "<br />\n";
1764      sText += tr("Version") + ": <b>" QSAMPLER_VERSION "</b><br />\n";          sText += tr("Version") + ": <b>" QSAMPLER_VERSION "</b><br />\n";
1765      sText += "<small>" + tr("Build") + ": " __DATE__ " " __TIME__ "</small><br />\n";          sText += "<small>" + tr("Build") + ": " __DATE__ " " __TIME__ "</small><br />\n";
1766  #ifdef CONFIG_DEBUG  #ifdef CONFIG_DEBUG
1767      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1768      sText += tr("Debugging option enabled.");          sText += tr("Debugging option enabled.");
1769      sText += "</font></small><br />";          sText += "</font></small><br />";
1770  #endif  #endif
1771  #ifndef CONFIG_LIBGIG  #ifndef CONFIG_LIBGIG
1772      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1773      sText += tr("GIG (libgig) file support disabled.");          sText += tr("GIG (libgig) file support disabled.");
1774      sText += "</font></small><br />";          sText += "</font></small><br />";
1775  #endif  #endif
1776  #ifndef CONFIG_INSTRUMENT_NAME  #ifndef CONFIG_INSTRUMENT_NAME
1777      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1778      sText += tr("LSCP (liblscp) instrument_name support disabled.");          sText += tr("LSCP (liblscp) instrument_name support disabled.");
1779      sText += "</font></small><br />";          sText += "</font></small><br />";
1780  #endif  #endif
1781  #ifndef CONFIG_MUTE_SOLO  #ifndef CONFIG_MUTE_SOLO
1782      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1783      sText += tr("Sampler channel Mute/Solo support disabled.");          sText += tr("Sampler channel Mute/Solo support disabled.");
1784      sText += "</font></small><br />";          sText += "</font></small><br />";
1785  #endif  #endif
1786  #ifndef CONFIG_AUDIO_ROUTING  #ifndef CONFIG_AUDIO_ROUTING
1787      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1788      sText += tr("LSCP (liblscp) audio_routing support disabled.");          sText += tr("LSCP (liblscp) audio_routing support disabled.");
1789      sText += "</font></small><br />";          sText += "</font></small><br />";
1790  #endif  #endif
1791  #ifndef CONFIG_FXSEND  #ifndef CONFIG_FXSEND
1792      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1793      sText += tr("Sampler channel Effect Sends support disabled.");          sText += tr("Sampler channel Effect Sends support disabled.");
1794      sText += "</font></small><br />";          sText += "</font></small><br />";
1795  #endif  #endif
1796  #ifndef CONFIG_VOLUME  #ifndef CONFIG_VOLUME
1797      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1798      sText += tr("Global volume support disabled.");          sText += tr("Global volume support disabled.");
1799      sText += "</font></small><br />";          sText += "</font></small><br />";
1800  #endif  #endif
1801  #ifndef CONFIG_MIDI_INSTRUMENT  #ifndef CONFIG_MIDI_INSTRUMENT
1802      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1803      sText += tr("MIDI instrument mapping support disabled.");          sText += tr("MIDI instrument mapping support disabled.");
1804      sText += "</font></small><br />";          sText += "</font></small><br />";
1805  #endif  #endif
1806  #ifndef CONFIG_EDIT_INSTRUMENT  #ifndef CONFIG_EDIT_INSTRUMENT
1807      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1808      sText += tr("Instrument editing support disabled.");          sText += tr("Instrument editing support disabled.");
1809      sText += "</font></small><br />";          sText += "</font></small><br />";
1810  #endif  #endif
1811      sText += "<br />\n";          sText += "<br />\n";
1812      sText += tr("Using") + ": ";          sText += tr("Using") + ": ";
1813      sText += ::lscp_client_package();          sText += ::lscp_client_package();
1814      sText += " ";          sText += " ";
1815      sText += ::lscp_client_version();          sText += ::lscp_client_version();
1816  #ifdef CONFIG_LIBGIG  #ifdef CONFIG_LIBGIG
1817      sText += ", ";          sText += ", ";
1818      sText += gig::libraryName().c_str();          sText += gig::libraryName().c_str();
1819      sText += " ";          sText += " ";
1820      sText += gig::libraryVersion().c_str();          sText += gig::libraryVersion().c_str();
1821  #endif  #endif
1822      sText += "<br />\n";          sText += "<br />\n";
1823      sText += "<br />\n";          sText += "<br />\n";
1824      sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";          sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";
1825      sText += "<br />\n";          sText += "<br />\n";
1826      sText += "<small>";          sText += "<small>";
1827      sText += QSAMPLER_COPYRIGHT "<br />\n";          sText += QSAMPLER_COPYRIGHT "<br />\n";
1828      sText += QSAMPLER_COPYRIGHT2 "<br />\n";          sText += QSAMPLER_COPYRIGHT2 "<br />\n";
1829      sText += "<br />\n";          sText += "<br />\n";
1830      sText += tr("This program is free software; you can redistribute it and/or modify it") + "<br />\n";          sText += tr("This program is free software; you can redistribute it and/or modify it") + "<br />\n";
1831      sText += tr("under the terms of the GNU General Public License version 2 or later.");          sText += tr("under the terms of the GNU General Public License version 2 or later.");
1832      sText += "</small>";          sText += "</small>";
1833      sText += "</p>\n";          sText += "</p>\n";
1834    
1835      QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);          QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);
1836  }  }
1837    
1838    
# Line 1742  void MainForm::helpAbout (void) Line 1841  void MainForm::helpAbout (void)
1841    
1842  void MainForm::stabilizeForm (void)  void MainForm::stabilizeForm (void)
1843  {  {
1844      // Update the main application caption...          // Update the main application caption...
1845      QString sSessionName = sessionName(m_sFilename);          QString sSessionName = sessionName(m_sFilename);
1846      if (m_iDirtyCount > 0)          if (m_iDirtyCount > 0)
1847          sSessionName += " *";                  sSessionName += " *";
1848      setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));
1849    
1850      // Update the main menu state...          // Update the main menu state...
1851      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1852      bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);          bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);
1853      bool bHasChannel = (bHasClient && pChannelStrip != NULL);          bool bHasChannel = (bHasClient && pChannelStrip != NULL);
1854      ui.fileNewAction->setEnabled(bHasClient);          m_ui.fileNewAction->setEnabled(bHasClient);
1855      ui.fileOpenAction->setEnabled(bHasClient);          m_ui.fileOpenAction->setEnabled(bHasClient);
1856      ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
1857      ui.fileSaveAsAction->setEnabled(bHasClient);          m_ui.fileSaveAsAction->setEnabled(bHasClient);
1858      ui.fileResetAction->setEnabled(bHasClient);          m_ui.fileResetAction->setEnabled(bHasClient);
1859      ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);          m_ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);
1860      ui.editAddChannelAction->setEnabled(bHasClient);          m_ui.editAddChannelAction->setEnabled(bHasClient);
1861      ui.editRemoveChannelAction->setEnabled(bHasChannel);          m_ui.editRemoveChannelAction->setEnabled(bHasChannel);
1862      ui.editSetupChannelAction->setEnabled(bHasChannel);          m_ui.editSetupChannelAction->setEnabled(bHasChannel);
1863  #ifdef CONFIG_EDIT_INSTRUMENT  #ifdef CONFIG_EDIT_INSTRUMENT
1864      ui.editEditChannelAction->setEnabled(bHasChannel);          m_ui.editEditChannelAction->setEnabled(bHasChannel);
1865  #else  #else
1866      ui.editEditChannelAction->setEnabled(false);          m_ui.editEditChannelAction->setEnabled(false);
1867  #endif  #endif
1868      ui.editResetChannelAction->setEnabled(bHasChannel);          m_ui.editResetChannelAction->setEnabled(bHasChannel);
1869      ui.editResetAllChannelsAction->setEnabled(bHasChannel);          m_ui.editResetAllChannelsAction->setEnabled(bHasChannel);
1870      ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());
1871  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
1872          ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm
1873                  && m_pInstrumentListForm->isVisible());                  && m_pInstrumentListForm->isVisible());
1874          ui.viewInstrumentsAction->setEnabled(bHasClient);          m_ui.viewInstrumentsAction->setEnabled(bHasClient);
1875  #else  #else
1876          ui.viewInstrumentsAction->setEnabled(false);          m_ui.viewInstrumentsAction->setEnabled(false);
1877  #endif  #endif
1878          ui.viewDevicesAction->setChecked(m_pDeviceForm          m_ui.viewDevicesAction->setChecked(m_pDeviceForm
1879                  && m_pDeviceForm->isVisible());                  && m_pDeviceForm->isVisible());
1880      ui.viewDevicesAction->setEnabled(bHasClient);          m_ui.viewDevicesAction->setEnabled(bHasClient);
1881      ui.channelsArrangeAction->setEnabled(bHasChannel);          m_ui.channelsArrangeAction->setEnabled(bHasChannel);
1882    
1883  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
1884          // Toolbar widgets are also affected...          // Toolbar widgets are also affected...
1885      m_pVolumeSlider->setEnabled(bHasClient);          m_pVolumeSlider->setEnabled(bHasClient);
1886      m_pVolumeSpinBox->setEnabled(bHasClient);          m_pVolumeSpinBox->setEnabled(bHasClient);
1887  #endif  #endif
1888    
1889      // Client/Server status...          // Client/Server status...
1890      if (bHasClient) {          if (bHasClient) {
1891          m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));                  m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));
1892          m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost + ":" + QString::number(m_pOptions->iServerPort));                  m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost
1893      } else {                          + ':' + QString::number(m_pOptions->iServerPort));
1894          m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();          } else {
1895          m_statusItem[QSAMPLER_STATUS_SERVER]->clear();                  m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();
1896      }                  m_statusItem[QSAMPLER_STATUS_SERVER]->clear();
1897      // Channel status...          }
1898      if (bHasChannel)          // Channel status...
1899          m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->windowTitle());          if (bHasChannel)
1900      else                  m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->windowTitle());
1901          m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();          else
1902      // Session status...                  m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();
1903      if (m_iDirtyCount > 0)          // Session status...
1904          m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));          if (m_iDirtyCount > 0)
1905      else                  m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));
1906          m_statusItem[QSAMPLER_STATUS_SESSION]->clear();          else
1907                    m_statusItem[QSAMPLER_STATUS_SESSION]->clear();
1908    
1909      // Recent files menu.          // Recent files menu.
1910          ui.fileOpenRecentMenu->setEnabled(m_pOptions->recentFiles.count() > 0);          m_ui.fileOpenRecentMenu->setEnabled(m_pOptions->recentFiles.count() > 0);
1911  }  }
1912    
1913    
# Line 1852  void MainForm::channelStripChanged(Chann Line 1952  void MainForm::channelStripChanged(Chann
1952                  pChannelStrip->resetErrorCount();                  pChannelStrip->resetErrorCount();
1953          }          }
1954    
1955      // Just mark the dirty form.          // Just mark the dirty form.
1956      m_iDirtyCount++;          m_iDirtyCount++;
1957      // and update the form status...          // and update the form status...
1958      stabilizeForm();          stabilizeForm();
1959  }  }
1960    
1961    
# Line 1882  void MainForm::updateSession (void) Line 1982  void MainForm::updateSession (void)
1982          }          }
1983  #endif  #endif
1984    
1985            updateAllChannelStrips(false);
1986    
1987            // Do we auto-arrange?
1988            if (m_pOptions && m_pOptions->bAutoArrange)
1989                    channelsArrange();
1990    
1991            // Remember to refresh devices and instruments...
1992            if (m_pInstrumentListForm)
1993                    m_pInstrumentListForm->refreshInstruments();
1994            if (m_pDeviceForm)
1995                    m_pDeviceForm->refreshDevices();
1996    }
1997    
1998    void MainForm::updateAllChannelStrips(bool bRemoveDeadStrips) {
1999          // Retrieve the current channel list.          // Retrieve the current channel list.
2000          int *piChannelIDs = ::lscp_list_channels(m_pClient);          int *piChannelIDs = ::lscp_list_channels(m_pClient);
2001          if (piChannelIDs == NULL) {          if (piChannelIDs == NULL) {
2002                  if (::lscp_client_get_errno(m_pClient)) {                  if (::lscp_client_get_errno(m_pClient)) {
2003                          appendMessagesClient("lscp_list_channels");                          appendMessagesClient("lscp_list_channels");
2004                          appendMessagesError(tr("Could not get current list of channels.\n\nSorry."));                          appendMessagesError(
2005                                    tr("Could not get current list of channels.\n\nSorry."));
2006                  }                  }
2007          } else {          } else {
2008                  // Try to (re)create each channel.                  // Try to (re)create each channel.
# Line 1895  void MainForm::updateSession (void) Line 2010  void MainForm::updateSession (void)
2010                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {
2011                          // Check if theres already a channel strip for this one...                          // Check if theres already a channel strip for this one...
2012                          if (!channelStrip(piChannelIDs[iChannel]))                          if (!channelStrip(piChannelIDs[iChannel]))
2013                                  createChannelStrip(new qsamplerChannel(piChannelIDs[iChannel]));                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));
2014                    }
2015    
2016                    // Do we auto-arrange?
2017                    if (m_pOptions && m_pOptions->bAutoArrange)
2018                            channelsArrange();
2019    
2020                    stabilizeForm();
2021    
2022                    // remove dead channel strips
2023                    if (bRemoveDeadStrips) {
2024                            for (int i = 0; channelStripAt(i); ++i) {
2025                                    ChannelStrip* pChannelStrip = channelStripAt(i);
2026                                    bool bExists = false;
2027                                    for (int j = 0; piChannelIDs[j] >= 0; ++j) {
2028                                            if (!pChannelStrip->channel()) break;
2029                                            if (piChannelIDs[j] == pChannelStrip->channel()->channelID()) {
2030                                                    // strip exists, don't touch it
2031                                                    bExists = true;
2032                                                    break;
2033                                            }
2034                                    }
2035                                    if (!bExists) destroyChannelStrip(pChannelStrip);
2036                            }
2037                  }                  }
2038                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
2039          }          }
   
     // Do we auto-arrange?  
     if (m_pOptions && m_pOptions->bAutoArrange)  
         channelsArrange();  
   
         // Remember to refresh devices and instruments...  
         if (m_pInstrumentListForm)  
             m_pInstrumentListForm->refreshInstruments();  
         if (m_pDeviceForm)  
             m_pDeviceForm->refreshDevices();  
2040  }  }
2041    
   
2042  // Update the recent files list and menu.  // Update the recent files list and menu.
2043  void MainForm::updateRecentFiles ( const QString& sFilename )  void MainForm::updateRecentFiles ( const QString& sFilename )
2044  {  {
2045      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2046          return;                  return;
2047    
2048      // Remove from list if already there (avoid duplicates)          // Remove from list if already there (avoid duplicates)
2049      int iIndex = m_pOptions->recentFiles.indexOf(sFilename);          int iIndex = m_pOptions->recentFiles.indexOf(sFilename);
2050      if (iIndex >= 0)          if (iIndex >= 0)
2051          m_pOptions->recentFiles.removeAt(iIndex);                  m_pOptions->recentFiles.removeAt(iIndex);
2052      // Put it to front...          // Put it to front...
2053      m_pOptions->recentFiles.push_front(sFilename);          m_pOptions->recentFiles.push_front(sFilename);
2054  }  }
2055    
2056    
# Line 1941  void MainForm::updateRecentFilesMenu (vo Line 2068  void MainForm::updateRecentFilesMenu (vo
2068          }          }
2069    
2070          // Rebuild the recent files menu...          // Rebuild the recent files menu...
2071          ui.fileOpenRecentMenu->clear();          m_ui.fileOpenRecentMenu->clear();
2072          for (int i = 0; i < iRecentFiles; i++) {          for (int i = 0; i < iRecentFiles; i++) {
2073                  const QString& sFilename = m_pOptions->recentFiles[i];                  const QString& sFilename = m_pOptions->recentFiles[i];
2074                  if (QFileInfo(sFilename).exists()) {                  if (QFileInfo(sFilename).exists()) {
2075                          QAction *pAction = ui.fileOpenRecentMenu->addAction(                          QAction *pAction = m_ui.fileOpenRecentMenu->addAction(
2076                                  QString("&%1 %2").arg(i + 1).arg(sessionName(sFilename)),                                  QString("&%1 %2").arg(i + 1).arg(sessionName(sFilename)),
2077                                  this, SLOT(fileOpenRecent()));                                  this, SLOT(fileOpenRecent()));
2078                          pAction->setData(i);                          pAction->setData(i);
# Line 1957  void MainForm::updateRecentFilesMenu (vo Line 2084  void MainForm::updateRecentFilesMenu (vo
2084  // Force update of the channels instrument names mode.  // Force update of the channels instrument names mode.
2085  void MainForm::updateInstrumentNames (void)  void MainForm::updateInstrumentNames (void)
2086  {  {
2087      // Full channel list update...          // Full channel list update...
2088      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2089      if (wlist.isEmpty())          if (wlist.isEmpty())
2090          return;                  return;
2091    
2092      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2093      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2094          ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);                  ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);
2095          if (pChannelStrip)                  if (pChannelStrip)
2096              pChannelStrip->updateInstrumentName(true);                          pChannelStrip->updateInstrumentName(true);
2097      }          }
2098      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2099  }  }
2100    
2101    
2102  // Force update of the channels display font.  // Force update of the channels display font.
2103  void MainForm::updateDisplayFont (void)  void MainForm::updateDisplayFont (void)
2104  {  {
2105      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2106          return;                  return;
2107    
2108            // Check if display font is legal.
2109            if (m_pOptions->sDisplayFont.isEmpty())
2110                    return;
2111            // Realize it.
2112            QFont font;
2113            if (!font.fromString(m_pOptions->sDisplayFont))
2114                    return;
2115    
2116            // Full channel list update...
2117            QWidgetList wlist = m_pWorkspace->windowList();
2118            if (wlist.isEmpty())
2119                    return;
2120    
2121      // Check if display font is legal.          m_pWorkspace->setUpdatesEnabled(false);
2122      if (m_pOptions->sDisplayFont.isEmpty())          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2123          return;                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2124      // Realize it.                  if (pChannelStrip)
2125      QFont font;                          pChannelStrip->setDisplayFont(font);
2126      if (!font.fromString(m_pOptions->sDisplayFont))          }
2127          return;          m_pWorkspace->setUpdatesEnabled(true);
   
     // Full channel list update...  
     QWidgetList wlist = m_pWorkspace->windowList();  
     if (wlist.isEmpty())  
         return;  
   
     m_pWorkspace->setUpdatesEnabled(false);  
     for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {  
         ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);  
         if (pChannelStrip)  
             pChannelStrip->setDisplayFont(font);  
     }  
     m_pWorkspace->setUpdatesEnabled(true);  
2128  }  }
2129    
2130    
2131  // Update channel strips background effect.  // Update channel strips background effect.
2132  void MainForm::updateDisplayEffect (void)  void MainForm::updateDisplayEffect (void)
2133  {  {
2134      // Full channel list update...          // Full channel list update...
2135      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2136      if (wlist.isEmpty())          if (wlist.isEmpty())
2137          return;                  return;
2138    
2139      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2140      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2141          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2142                  if (pChannelStrip)                  if (pChannelStrip)
2143                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2144      }          }
2145      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2146  }  }
2147    
2148    
2149  // Force update of the channels maximum volume setting.  // Force update of the channels maximum volume setting.
2150  void MainForm::updateMaxVolume (void)  void MainForm::updateMaxVolume (void)
2151  {  {
2152      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2153          return;                  return;
2154    
2155  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2156          m_iVolumeChanging++;          m_iVolumeChanging++;
# Line 2032  void MainForm::updateMaxVolume (void) Line 2159  void MainForm::updateMaxVolume (void)
2159          m_iVolumeChanging--;          m_iVolumeChanging--;
2160  #endif  #endif
2161    
2162      // Full channel list update...          // Full channel list update...
2163      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2164      if (wlist.isEmpty())          if (wlist.isEmpty())
2165          return;                  return;
2166    
2167      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2168      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2169          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2170          if (pChannelStrip)                  if (pChannelStrip)
2171              pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                          pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2172      }          }
2173      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2174  }  }
2175    
2176    
# Line 2053  void MainForm::updateMaxVolume (void) Line 2180  void MainForm::updateMaxVolume (void)
2180  // Messages output methods.  // Messages output methods.
2181  void MainForm::appendMessages( const QString& s )  void MainForm::appendMessages( const QString& s )
2182  {  {
2183      if (m_pMessages)          if (m_pMessages)
2184          m_pMessages->appendMessages(s);                  m_pMessages->appendMessages(s);
2185    
2186      statusBar()->showMessage(s, 3000);          statusBar()->showMessage(s, 3000);
2187  }  }
2188    
2189  void MainForm::appendMessagesColor( const QString& s, const QString& c )  void MainForm::appendMessagesColor( const QString& s, const QString& c )
2190  {  {
2191      if (m_pMessages)          if (m_pMessages)
2192          m_pMessages->appendMessagesColor(s, c);                  m_pMessages->appendMessagesColor(s, c);
2193    
2194      statusBar()->showMessage(s, 3000);          statusBar()->showMessage(s, 3000);
2195  }  }
2196    
2197  void MainForm::appendMessagesText( const QString& s )  void MainForm::appendMessagesText( const QString& s )
2198  {  {
2199      if (m_pMessages)          if (m_pMessages)
2200          m_pMessages->appendMessagesText(s);                  m_pMessages->appendMessagesText(s);
2201  }  }
2202    
2203  void MainForm::appendMessagesError( const QString& s )  void MainForm::appendMessagesError( const QString& s )
2204  {  {
2205      if (m_pMessages)          if (m_pMessages)
2206          m_pMessages->show();                  m_pMessages->show();
2207    
2208      appendMessagesColor(s.simplified(), "#ff0000");          appendMessagesColor(s.simplified(), "#ff0000");
2209    
2210          // Make it look responsive...:)          // Make it look responsive...:)
2211          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2212    
2213      QMessageBox::critical(this,          QMessageBox::critical(this,
2214                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));
2215  }  }
2216    
# Line 2091  void MainForm::appendMessagesError( cons Line 2218  void MainForm::appendMessagesError( cons
2218  // This is a special message format, just for client results.  // This is a special message format, just for client results.
2219  void MainForm::appendMessagesClient( const QString& s )  void MainForm::appendMessagesClient( const QString& s )
2220  {  {
2221      if (m_pClient == NULL)          if (m_pClient == NULL)
2222          return;                  return;
2223    
2224      appendMessagesColor(s + QString(": %1 (errno=%2)")          appendMessagesColor(s + QString(": %1 (errno=%2)")
2225          .arg(::lscp_client_get_result(m_pClient))                  .arg(::lscp_client_get_result(m_pClient))
2226          .arg(::lscp_client_get_errno(m_pClient)), "#996666");                  .arg(::lscp_client_get_errno(m_pClient)), "#996666");
2227    
2228          // Make it look responsive...:)          // Make it look responsive...:)
2229          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
# Line 2106  void MainForm::appendMessagesClient( con Line 2233  void MainForm::appendMessagesClient( con
2233  // Force update of the messages font.  // Force update of the messages font.
2234  void MainForm::updateMessagesFont (void)  void MainForm::updateMessagesFont (void)
2235  {  {
2236      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2237          return;                  return;
2238    
2239      if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {          if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {
2240          QFont font;                  QFont font;
2241          if (font.fromString(m_pOptions->sMessagesFont))                  if (font.fromString(m_pOptions->sMessagesFont))
2242              m_pMessages->setMessagesFont(font);                          m_pMessages->setMessagesFont(font);
2243      }          }
2244  }  }
2245    
2246    
2247  // Update messages window line limit.  // Update messages window line limit.
2248  void MainForm::updateMessagesLimit (void)  void MainForm::updateMessagesLimit (void)
2249  {  {
2250      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2251          return;                  return;
2252    
2253      if (m_pMessages) {          if (m_pMessages) {
2254          if (m_pOptions->bMessagesLimit)                  if (m_pOptions->bMessagesLimit)
2255              m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);                          m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);
2256          else                  else
2257              m_pMessages->setMessagesLimit(-1);                          m_pMessages->setMessagesLimit(-1);
2258      }          }
2259  }  }
2260    
2261    
2262  // Enablement of the messages capture feature.  // Enablement of the messages capture feature.
2263  void MainForm::updateMessagesCapture (void)  void MainForm::updateMessagesCapture (void)
2264  {  {
2265      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2266          return;                  return;
2267    
2268      if (m_pMessages)          if (m_pMessages)
2269          m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);                  m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);
2270  }  }
2271    
2272    
# Line 2147  void MainForm::updateMessagesCapture (vo Line 2274  void MainForm::updateMessagesCapture (vo
2274  // qsamplerMainForm -- MDI channel strip management.  // qsamplerMainForm -- MDI channel strip management.
2275    
2276  // The channel strip creation executive.  // The channel strip creation executive.
2277  ChannelStrip* MainForm::createChannelStrip(qsamplerChannel* pChannel)  ChannelStrip* MainForm::createChannelStrip ( Channel *pChannel )
2278  {  {
2279      if (m_pClient == NULL || pChannel == NULL)          if (m_pClient == NULL || pChannel == NULL)
2280          return NULL;                  return NULL;
2281    
2282      // Prepare for auto-arrange?          // Add a new channel itema...
2283      ChannelStrip* pChannelStrip = NULL;          ChannelStrip *pChannelStrip = new ChannelStrip();
2284      int y = 0;          if (pChannelStrip == NULL)
2285      if (m_pOptions && m_pOptions->bAutoArrange) {                  return NULL;
         QWidgetList wlist = m_pWorkspace->windowList();  
         for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {  
                         pChannelStrip = static_cast<ChannelStrip *> (wlist.at(iChannel));  
                         if (pChannelStrip) {  
                         //  y += pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();  
                                 y += pChannelStrip->parentWidget()->frameGeometry().height();  
                         }  
         }  
     }  
2286    
2287      // Add a new channel itema...          // Set some initial channel strip options...
2288      pChannelStrip = new ChannelStrip();          if (m_pOptions) {
2289      if (pChannelStrip == NULL)                  // Background display effect...
2290          return NULL;                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2291                    // We'll need a display font.
2292                    QFont font;
2293                    if (font.fromString(m_pOptions->sDisplayFont))
2294                            pChannelStrip->setDisplayFont(font);
2295                    // Maximum allowed volume setting.
2296                    pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2297            }
2298    
2299            // Add it to workspace...
2300          m_pWorkspace->addWindow(pChannelStrip, Qt::FramelessWindowHint);          m_pWorkspace->addWindow(pChannelStrip, Qt::FramelessWindowHint);
2301    
2302      // Actual channel strip setup...          // Actual channel strip setup...
2303      pChannelStrip->setup(pChannel);          pChannelStrip->setup(pChannel);
2304    
2305          QObject::connect(pChannelStrip,          QObject::connect(pChannelStrip,
2306                  SIGNAL(channelChanged(ChannelStrip*)),                  SIGNAL(channelChanged(ChannelStrip*)),
2307                  SLOT(channelStripChanged(ChannelStrip*)));                  SLOT(channelStripChanged(ChannelStrip*)));
2308      // Set some initial aesthetic options...  
2309      if (m_pOptions) {          // Now we show up us to the world.
2310          // Background display effect...          pChannelStrip->show();
         pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);  
         // We'll need a display font.  
         QFont font;  
         if (font.fromString(m_pOptions->sDisplayFont))  
             pChannelStrip->setDisplayFont(font);  
         // Maximum allowed volume setting.  
         pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);  
     }  
   
     // Now we show up us to the world.  
     pChannelStrip->show();  
     // Only then, we'll auto-arrange...  
     if (m_pOptions && m_pOptions->bAutoArrange) {  
         int iWidth  = m_pWorkspace->width();  
     //  int iHeight = pChannel->height() + pChannel->parentWidget()->baseSize().height();  
         int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();        pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);  
     }  
2311    
2312          // This is pretty new, so we'll watch for it closely.          // This is pretty new, so we'll watch for it closely.
2313          channelStripChanged(pChannelStrip);          channelStripChanged(pChannelStrip);
2314    
2315      // Return our successful reference...          // Return our successful reference...
2316      return pChannelStrip;          return pChannelStrip;
2317  }  }
2318    
2319    void MainForm::destroyChannelStrip(ChannelStrip* pChannelStrip) {
2320            // Just delete the channel strip.
2321            delete pChannelStrip;
2322    
2323            // Do we auto-arrange?
2324            if (m_pOptions && m_pOptions->bAutoArrange)
2325                    channelsArrange();
2326    
2327            stabilizeForm();
2328    }
2329    
2330  // Retrieve the active channel strip.  // Retrieve the active channel strip.
2331  ChannelStrip* MainForm::activeChannelStrip (void)  ChannelStrip* MainForm::activeChannelStrip (void)
2332  {  {
2333      return static_cast<ChannelStrip *> (m_pWorkspace->activeWindow());          return static_cast<ChannelStrip *> (m_pWorkspace->activeWindow());
2334  }  }
2335    
2336    
2337  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
2338  ChannelStrip* MainForm::channelStripAt ( int iChannel )  ChannelStrip* MainForm::channelStripAt ( int iChannel )
2339  {  {
2340      QWidgetList wlist = m_pWorkspace->windowList();          if (!m_pWorkspace) return NULL;
     if (wlist.isEmpty())  
         return NULL;  
2341    
2342      return static_cast<ChannelStrip *> (wlist.at(iChannel));          QWidgetList wlist = m_pWorkspace->windowList();
2343            if (wlist.isEmpty())
2344                    return NULL;
2345    
2346            if (iChannel < 0 || iChannel >= wlist.size())
2347                    return NULL;
2348    
2349            return dynamic_cast<ChannelStrip *> (wlist.at(iChannel));
2350  }  }
2351    
2352    
# Line 2236  ChannelStrip* MainForm::channelStrip ( i Line 2361  ChannelStrip* MainForm::channelStrip ( i
2361                  ChannelStrip* pChannelStrip                  ChannelStrip* pChannelStrip
2362                          = static_cast<ChannelStrip*> (wlist.at(iChannel));                          = static_cast<ChannelStrip*> (wlist.at(iChannel));
2363                  if (pChannelStrip) {                  if (pChannelStrip) {
2364                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
2365                          if (pChannel && pChannel->channelID() == iChannelID)                          if (pChannel && pChannel->channelID() == iChannelID)
2366                                  return pChannelStrip;                                  return pChannelStrip;
2367                  }                  }
# Line 2250  ChannelStrip* MainForm::channelStrip ( i Line 2375  ChannelStrip* MainForm::channelStrip ( i
2375  // Construct the windows menu.  // Construct the windows menu.
2376  void MainForm::channelsMenuAboutToShow (void)  void MainForm::channelsMenuAboutToShow (void)
2377  {  {
2378      ui.channelsMenu->clear();          m_ui.channelsMenu->clear();
2379          ui.channelsMenu->addAction(ui.channelsArrangeAction);          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);
2380          ui.channelsMenu->addAction(ui.channelsAutoArrangeAction);          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);
2381    
2382      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2383      if (!wlist.isEmpty()) {          if (!wlist.isEmpty()) {
2384                  ui.channelsMenu->addSeparator();                  m_ui.channelsMenu->addSeparator();
2385          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2386                          ChannelStrip* pChannelStrip                          ChannelStrip* pChannelStrip
2387                                  = static_cast<ChannelStrip*> (wlist.at(iChannel));                                  = static_cast<ChannelStrip*> (wlist.at(iChannel));
2388                          if (pChannelStrip) {                          if (pChannelStrip) {
2389                                  QAction *pAction = ui.channelsMenu->addAction(                                  QAction *pAction = m_ui.channelsMenu->addAction(
2390                                          pChannelStrip->windowTitle(), this, SLOT(channelsMenuActivated()));                                          pChannelStrip->windowTitle(),
2391                                            this, SLOT(channelsMenuActivated()));
2392                                  pAction->setCheckable(true);                                  pAction->setCheckable(true);
2393                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);
2394                                  pAction->setData(iChannel);                                  pAction->setData(iChannel);
2395                          }                          }
2396          }                  }
2397      }          }
2398  }  }
2399    
2400    
# Line 2294  void MainForm::channelsMenuActivated (vo Line 2420  void MainForm::channelsMenuActivated (vo
2420  // Set the pseudo-timer delay schedule.  // Set the pseudo-timer delay schedule.
2421  void MainForm::startSchedule ( int iStartDelay )  void MainForm::startSchedule ( int iStartDelay )
2422  {  {
2423      m_iStartDelay  = 1 + (iStartDelay * 1000);          m_iStartDelay  = 1 + (iStartDelay * 1000);
2424      m_iTimerDelay  = 0;          m_iTimerDelay  = 0;
2425  }  }
2426    
2427  // Suspend the pseudo-timer delay schedule.  // Suspend the pseudo-timer delay schedule.
2428  void MainForm::stopSchedule (void)  void MainForm::stopSchedule (void)
2429  {  {
2430      m_iStartDelay  = 0;          m_iStartDelay  = 0;
2431      m_iTimerDelay  = 0;          m_iTimerDelay  = 0;
2432  }  }
2433    
2434  // Timer slot funtion.  // Timer slot funtion.
2435  void MainForm::timerSlot (void)  void MainForm::timerSlot (void)
2436  {  {
2437      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2438          return;                  return;
2439    
2440      // Is it the first shot on server start after a few delay?          // Is it the first shot on server start after a few delay?
2441      if (m_iTimerDelay < m_iStartDelay) {          if (m_iTimerDelay < m_iStartDelay) {
2442          m_iTimerDelay += QSAMPLER_TIMER_MSECS;                  m_iTimerDelay += QSAMPLER_TIMER_MSECS;
2443          if (m_iTimerDelay >= m_iStartDelay) {                  if (m_iTimerDelay >= m_iStartDelay) {
2444              // If we cannot start it now, maybe a lil'mo'later ;)                          // If we cannot start it now, maybe a lil'mo'later ;)
2445              if (!startClient()) {                          if (!startClient()) {
2446                  m_iStartDelay += m_iTimerDelay;                                  m_iStartDelay += m_iTimerDelay;
2447                  m_iTimerDelay  = 0;                                  m_iTimerDelay  = 0;
2448              }                          }
2449          }                  }
2450      }          }
2451    
2452          if (m_pClient) {          if (m_pClient) {
2453                  // Update the channel information for each pending strip...                  // Update the channel information for each pending strip...
# Line 2353  void MainForm::timerSlot (void) Line 2479  void MainForm::timerSlot (void)
2479                  }                  }
2480          }          }
2481    
2482      // Register the next timer slot.          // Register the next timer slot.
2483      QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));          QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
2484  }  }
2485    
2486    
# Line 2364  void MainForm::timerSlot (void) Line 2490  void MainForm::timerSlot (void)
2490  // Start linuxsampler server...  // Start linuxsampler server...
2491  void MainForm::startServer (void)  void MainForm::startServer (void)
2492  {  {
2493      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2494          return;                  return;
2495    
2496            // Aren't already a client, are we?
2497            if (!m_pOptions->bServerStart || m_pClient)
2498                    return;
2499    
2500      // Aren't already a client, are we?          // Is the server process instance still here?
2501      if (!m_pOptions->bServerStart || m_pClient)          if (m_pServer) {
2502          return;                  switch (QMessageBox::warning(this,
   
     // Is the server process instance still here?  
     if (m_pServer) {  
         switch (QMessageBox::warning(this,  
2503                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
2504              tr("Could not start the LinuxSampler server.\n\n"                          tr("Could not start the LinuxSampler server.\n\n"
2505                 "Maybe it ss already started."),                          "Maybe it is already started."),
2506              tr("Stop"), tr("Kill"), tr("Cancel"))) {                          tr("Stop"), tr("Kill"), tr("Cancel"))) {
2507            case 0:                  case 0:
2508              m_pServer->terminate();                          m_pServer->terminate();
2509              break;                          break;
2510            case 1:                  case 1:
2511              m_pServer->kill();                          m_pServer->kill();
2512              break;                          break;
2513          }                  }
2514          return;                  return;
2515      }          }
2516    
2517      // Reset our timer counters...          // Reset our timer counters...
2518      stopSchedule();          stopSchedule();
2519    
2520      // OK. Let's build the startup process...          // Verify we have something to start with...
2521      m_pServer = new QProcess(this);          if (m_pOptions->sServerCmdLine.isEmpty())
2522                    return;
2523      // Setup stdout/stderr capture...  
2524          //      if (m_pOptions->bStdoutCapture) {          // OK. Let's build the startup process...
2525                  //m_pServer->setProcessChannelMode(          m_pServer = new QProcess();
2526                  //      QProcess::StandardOutput);          bForceServerStop = true;
2527    
2528            // Setup stdout/stderr capture...
2529    //      if (m_pOptions->bStdoutCapture) {
2530    #if QT_VERSION >= 0x040200
2531                    m_pServer->setProcessChannelMode(QProcess::ForwardedChannels);
2532    #endif
2533                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2534                          SIGNAL(readyReadStandardOutput()),                          SIGNAL(readyReadStandardOutput()),
2535                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
2536                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2537                          SIGNAL(readyReadStandardError()),                          SIGNAL(readyReadStandardError()),
2538                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
2539          //      }  //      }
2540    
2541          // The unforgiveable signal communication...          // The unforgiveable signal communication...
2542          QObject::connect(m_pServer,          QObject::connect(m_pServer,
2543                  SIGNAL(finished(int,QProcess::ExitStatus)),                  SIGNAL(finished(int, QProcess::ExitStatus)),
2544                  SLOT(processServerExit()));                  SLOT(processServerExit()));
2545    
2546      // Build process arguments...          // Build process arguments...
2547      QStringList serverCmdLine = m_pOptions->sServerCmdLine.split(' ');          QStringList args = m_pOptions->sServerCmdLine.split(' ');
2548            QString sCommand = args[0];
2549      appendMessages(tr("Server is starting..."));          args.removeAt(0);
2550      appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");  
2551            appendMessages(tr("Server is starting..."));
2552            appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");
2553    
2554      const QString prog = (serverCmdLine.size() > 0) ? serverCmdLine[0] : QString();          // Go linuxsampler, go...
2555      const QStringList args = serverCmdLine.mid(1);          m_pServer->start(sCommand, args);
2556            if (!m_pServer->waitForStarted()) {
2557      // Go jack, go...                  appendMessagesError(tr("Could not start server.\n\nSorry."));
2558      m_pServer->start(prog, args);                  processServerExit();
2559      if (!m_pServer->waitForStarted()) {                  return;
2560          appendMessagesError(tr("Could not start server.\n\nSorry."));          }
         processServerExit();  
         return;  
     }  
   
     // Show startup results...  
     appendMessages(tr("Server was started with PID=%1.").arg((long) m_pServer->pid()));  
2561    
2562      // Reset (yet again) the timer counters,          // Show startup results...
2563      // but this time is deferred as the user opted.          appendMessages(
2564      startSchedule(m_pOptions->iStartDelay);                  tr("Server was started with PID=%1.").arg((long) m_pServer->pid()));
2565      stabilizeForm();  
2566            // Reset (yet again) the timer counters,
2567            // but this time is deferred as the user opted.
2568            startSchedule(m_pOptions->iStartDelay);
2569            stabilizeForm();
2570  }  }
2571    
2572    
2573  // Stop linuxsampler server...  // Stop linuxsampler server...
2574  void MainForm::stopServer (void)  void MainForm::stopServer (bool bInteractive)
2575  {  {
2576      // Stop client code.          // Stop client code.
2577      stopClient();          stopClient();
2578    
2579      // And try to stop server.          if (m_pServer && bInteractive) {
2580      if (m_pServer) {                  if (QMessageBox::question(this,
2581          appendMessages(tr("Server is stopping..."));                          QSAMPLER_TITLE ": " + tr("The backend's fate ..."),
2582          if (m_pServer->state() == QProcess::Running)                          tr("You have the option to keep the sampler backend (LinuxSampler)\n"
2583              m_pServer->terminate();                          "running in the background. The sampler would continue to work\n"
2584       }                          "according to your current sampler session and you could alter the\n"
2585                            "sampler session at any time by relaunching QSampler.\n\n"
2586      // Give it some time to terminate gracefully and stabilize...                          "Do you want LinuxSampler to stop or to keep running in\n"
2587      QTime t;                          "the background?"),
2588      t.start();                          tr("Stop"), tr("Keep Running")) == 1)
2589      while (t.elapsed() < QSAMPLER_TIMER_MSECS)                  {
2590          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                          bForceServerStop = false;
2591                    }
2592            }
2593    
2594       // Do final processing anyway.          // And try to stop server.
2595       processServerExit();          if (m_pServer && bForceServerStop) {
2596                    appendMessages(tr("Server is stopping..."));
2597                    if (m_pServer->state() == QProcess::Running) {
2598    #if defined(WIN32)
2599                            // Try harder...
2600                            m_pServer->kill();
2601    #else
2602                            // Try softly...
2603                            m_pServer->terminate();
2604    #endif
2605                    }
2606            }       // Do final processing anyway.
2607            else processServerExit();
2608    
2609            // Give it some time to terminate gracefully and stabilize...
2610            QTime t;
2611            t.start();
2612            while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2613                    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2614  }  }
2615    
2616    
2617  // Stdout handler...  // Stdout handler...
2618  void MainForm::readServerStdout (void)  void MainForm::readServerStdout (void)
2619  {  {
2620      if (m_pMessages)          if (m_pMessages)
2621          m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());                  m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());
2622  }  }
2623    
2624    
2625  // Linuxsampler server cleanup.  // Linuxsampler server cleanup.
2626  void MainForm::processServerExit (void)  void MainForm::processServerExit (void)
2627  {  {
2628      // Force client code cleanup.          // Force client code cleanup.
2629      stopClient();          stopClient();
2630    
2631      // Flush anything that maybe pending...          // Flush anything that maybe pending...
2632      if (m_pMessages)          if (m_pMessages)
2633          m_pMessages->flushStdoutBuffer();                  m_pMessages->flushStdoutBuffer();
2634    
2635      if (m_pServer) {          if (m_pServer && bForceServerStop) {
2636          // Force final server shutdown...                  if (m_pServer->state() != QProcess::NotRunning) {
2637          appendMessages(tr("Server was stopped with exit status %1.").arg(m_pServer->exitStatus()));                          appendMessages(tr("Server is being forced..."));
2638          m_pServer->terminate();                          // Force final server shutdown...
2639          if (!m_pServer->waitForFinished(2000))                          m_pServer->kill();
2640              m_pServer->kill();                          // Give it some time to terminate gracefully and stabilize...
2641          // Destroy it.                          QTime t;
2642          delete m_pServer;                          t.start();
2643          m_pServer = NULL;                          while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2644      }                                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2645                    }
2646                    // Force final server shutdown...
2647                    appendMessages(
2648                            tr("Server was stopped with exit status %1.")
2649                            .arg(m_pServer->exitStatus()));
2650                    delete m_pServer;
2651                    m_pServer = NULL;
2652            }
2653    
2654      // Again, make status visible stable.          // Again, make status visible stable.
2655      stabilizeForm();          stabilizeForm();
2656  }  }
2657    
2658    
# Line 2501  void MainForm::processServerExit (void) Line 2660  void MainForm::processServerExit (void)
2660  // qsamplerMainForm -- Client stuff.  // qsamplerMainForm -- Client stuff.
2661    
2662  // The LSCP client callback procedure.  // The LSCP client callback procedure.
2663  lscp_status_t qsampler_client_callback ( lscp_client_t */*pClient*/, lscp_event_t event, const char *pchData, int cchData, void *pvData )  lscp_status_t qsampler_client_callback ( lscp_client_t */*pClient*/,
2664            lscp_event_t event, const char *pchData, int cchData, void *pvData )
2665  {  {
2666      MainForm* pMainForm = (MainForm *) pvData;          MainForm* pMainForm = (MainForm *) pvData;
2667      if (pMainForm == NULL)          if (pMainForm == NULL)
2668          return LSCP_FAILED;                  return LSCP_FAILED;
2669    
2670      // ATTN: DO NOT EVER call any GUI code here,          // ATTN: DO NOT EVER call any GUI code here,
2671      // as this is run under some other thread context.          // as this is run under some other thread context.
2672      // A custom event must be posted here...          // A custom event must be posted here...
2673      QApplication::postEvent(pMainForm, new qsamplerCustomEvent(event, pchData, cchData));          QApplication::postEvent(pMainForm,
2674                    new CustomEvent(event, pchData, cchData));
2675    
2676      return LSCP_OK;          return LSCP_OK;
2677  }  }
2678    
2679    
2680  // Start our almighty client...  // Start our almighty client...
2681  bool MainForm::startClient (void)  bool MainForm::startClient (void)
2682  {  {
2683      // Have it a setup?          // Have it a setup?
2684      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2685          return false;                  return false;
   
     // Aren't we already started, are we?  
     if (m_pClient)  
         return true;  
2686    
2687      // Log prepare here.          // Aren't we already started, are we?
2688      appendMessages(tr("Client connecting..."));          if (m_pClient)
2689                    return true;
2690    
2691      // Create the client handle...          // Log prepare here.
2692            appendMessages(tr("Client connecting..."));
2693    
2694            // Create the client handle...
2695          m_pClient = ::lscp_client_create(          m_pClient = ::lscp_client_create(
2696                  m_pOptions->sServerHost.toUtf8().constData(),                  m_pOptions->sServerHost.toUtf8().constData(),
2697                  m_pOptions->iServerPort, qsampler_client_callback, this);                  m_pOptions->iServerPort, qsampler_client_callback, this);
2698      if (m_pClient == NULL) {          if (m_pClient == NULL) {
2699          // Is this the first try?                  // Is this the first try?
2700          // maybe we need to start a local server...                  // maybe we need to start a local server...
2701          if ((m_pServer && m_pServer->state() == QProcess::Running) || !m_pOptions->bServerStart)                  if ((m_pServer && m_pServer->state() == QProcess::Running)
2702              appendMessagesError(tr("Could not connect to server as client.\n\nSorry."));                          || !m_pOptions->bServerStart) {
2703          else                          appendMessagesError(
2704              startServer();                                  tr("Could not connect to server as client.\n\nSorry."));
2705          // This is always a failure.                  } else {
2706          stabilizeForm();                          startServer();
2707          return false;                  }
2708      }                  // This is always a failure.
2709      // Just set receive timeout value, blindly.                  stabilizeForm();
2710      ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);                  return false;
2711      appendMessages(tr("Client receive timeout is set to %1 msec.").arg(::lscp_client_get_timeout(m_pClient)));          }
2712            // Just set receive timeout value, blindly.
2713            ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);
2714            appendMessages(
2715                    tr("Client receive timeout is set to %1 msec.")
2716                    .arg(::lscp_client_get_timeout(m_pClient)));
2717    
2718          // Subscribe to channel info change notifications...          // Subscribe to channel info change notifications...
2719            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT) != LSCP_OK)
2720                    appendMessagesClient("lscp_client_subscribe(CHANNEL_COUNT)");
2721          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)
2722                  appendMessagesClient("lscp_client_subscribe");                  appendMessagesClient("lscp_client_subscribe(CHANNEL_INFO)");
2723    
2724      // We may stop scheduling around.          DeviceStatusForm::onDevicesChanged(); // initialize
2725      stopSchedule();          updateViewMidiDeviceStatusMenu();
2726            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT) != LSCP_OK)
2727                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_COUNT)");
2728            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO) != LSCP_OK)
2729                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_INFO)");
2730            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT) != LSCP_OK)
2731                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_COUNT)");
2732            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO) != LSCP_OK)
2733                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_INFO)");
2734    
2735    #if CONFIG_EVENT_CHANNEL_MIDI
2736            // Subscribe to channel MIDI data notifications...
2737            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI) != LSCP_OK)
2738                    appendMessagesClient("lscp_client_subscribe(CHANNEL_MIDI)");
2739    #endif
2740    
2741    #if CONFIG_EVENT_DEVICE_MIDI
2742            // Subscribe to channel MIDI data notifications...
2743            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI) != LSCP_OK)
2744                    appendMessagesClient("lscp_client_subscribe(DEVICE_MIDI)");
2745    #endif
2746    
2747            // We may stop scheduling around.
2748            stopSchedule();
2749    
2750      // We'll accept drops from now on...          // We'll accept drops from now on...
2751      setAcceptDrops(true);          setAcceptDrops(true);
2752    
2753      // Log success here.          // Log success here.
2754      appendMessages(tr("Client connected."));          appendMessages(tr("Client connected."));
2755    
2756          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
2757          // if visible, that we're ready...          // if visible, that we're ready...
2758          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
2759              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
2760          if (m_pDeviceForm)          if (m_pDeviceForm)
2761              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
2762    
2763      // Is any session pending to be loaded?          // Is any session pending to be loaded?
2764      if (!m_pOptions->sSessionFile.isEmpty()) {          if (!m_pOptions->sSessionFile.isEmpty()) {
2765          // Just load the prabably startup session...                  // Just load the prabably startup session...
2766          if (loadSessionFile(m_pOptions->sSessionFile)) {                  if (loadSessionFile(m_pOptions->sSessionFile)) {
2767              m_pOptions->sSessionFile = QString::null;                          m_pOptions->sSessionFile = QString::null;
2768              return true;                          return true;
2769          }                  }
2770      }          }
2771    
2772      // Make a new session          // Make a new session
2773      return newSession();          return newSession();
2774  }  }
2775    
2776    
2777  // Stop client...  // Stop client...
2778  void MainForm::stopClient (void)  void MainForm::stopClient (void)
2779  {  {
2780      if (m_pClient == NULL)          if (m_pClient == NULL)
2781          return;                  return;
   
     // Log prepare here.  
     appendMessages(tr("Client disconnecting..."));  
2782    
2783      // Clear timer counters...          // Log prepare here.
2784      stopSchedule();          appendMessages(tr("Client disconnecting..."));
2785    
2786      // We'll reject drops from now on...          // Clear timer counters...
2787      setAcceptDrops(false);          stopSchedule();
2788    
2789      // Force any channel strips around, but          // We'll reject drops from now on...
2790      // but avoid removing the corresponding          setAcceptDrops(false);
     // channels from the back-end server.  
     m_iDirtyCount = 0;  
     closeSession(false);  
2791    
2792      // Close us as a client...          // Force any channel strips around, but
2793            // but avoid removing the corresponding
2794            // channels from the back-end server.
2795            m_iDirtyCount = 0;
2796            closeSession(false);
2797    
2798            // Close us as a client...
2799    #if CONFIG_EVENT_DEVICE_MIDI
2800            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI);
2801    #endif
2802    #if CONFIG_EVENT_CHANNEL_MIDI
2803            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI);
2804    #endif
2805            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
2806            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
2807            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
2808            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
2809          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
2810      ::lscp_client_destroy(m_pClient);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT);
2811      m_pClient = NULL;          ::lscp_client_destroy(m_pClient);
2812            m_pClient = NULL;
2813    
2814          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
2815          // if visible, that we're running out...          // if visible, that we're running out...
2816          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
2817              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
2818          if (m_pDeviceForm)          if (m_pDeviceForm)
2819              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
2820    
2821            // Log final here.
2822            appendMessages(tr("Client disconnected."));
2823    
2824            // Make visible status.
2825            stabilizeForm();
2826    }
2827    
2828    
2829      // Log final here.  // Channel strip activation/selection.
2830      appendMessages(tr("Client disconnected."));  void MainForm::activateStrip ( QWidget *pWidget )
2831    {
2832            ChannelStrip *pChannelStrip
2833                    = static_cast<ChannelStrip *> (pWidget);
2834            if (pChannelStrip)
2835                    pChannelStrip->setSelected(true);
2836    
2837      // Make visible status.          stabilizeForm();
     stabilizeForm();  
2838  }  }
2839    
2840    
2841  } // namespace QSampler  } // namespace QSampler
2842    
2843    

Legend:
Removed from v.1507  
changed lines
  Added in v.1739

  ViewVC Help
Powered by ViewVC