/[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 1470 by schoenebeck, Sun Nov 4 23:37:47 2007 UTC revision 1702 by schoenebeck, Sun Feb 17 13:53:00 2008 UTC
# Line 2  Line 2 
2  //  //
3  /****************************************************************************  /****************************************************************************
4     Copyright (C) 2004-2007, rncbc aka Rui Nuno Capela. All rights reserved.     Copyright (C) 2004-2007, rncbc aka Rui Nuno Capela. All rights reserved.
5     Copyright (C) 2007, Christian Schoenebeck     Copyright (C) 2007, 2008 Christian Schoenebeck
6    
7     This program is free software; you can redistribute it and/or     This program is free software; you can redistribute it and/or
8     modify it under the terms of the GNU General Public License     modify it under the terms of the GNU General Public License
# Line 20  Line 20 
20    
21  *****************************************************************************/  *****************************************************************************/
22    
23    #include "qsamplerAbout.h"
24  #include "qsamplerMainForm.h"  #include "qsamplerMainForm.h"
25    
 #include <qapplication.h>  
 #include <qeventloop.h>  
 #include <qworkspace.h>  
 #include <qprocess.h>  
 #include <qmessagebox.h>  
 //#include <qdragobject.h>  
 #include <qregexp.h>  
 #include <qfiledialog.h>  
 #include <qfileinfo.h>  
 #include <qfile.h>  
 #include <qtextstream.h>  
 #include <qstatusbar.h>  
 #include <qslider.h>  
 #include <qspinbox.h>  
 #include <qlabel.h>  
 #include <qtimer.h>  
 #include <qtooltip.h>  
   
 #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 51  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>
39    #include <QWorkspace>
40    #include <QProcess>
41    #include <QMessageBox>
42    
43    #include <QRegExp>
44    #include <QTextStream>
45    #include <QFileDialog>
46    #include <QFileInfo>
47    #include <QFile>
48    #include <QUrl>
49    
50    #include <QDragEnterEvent>
51    
52    #include <QStatusBar>
53    #include <QSpinBox>
54    #include <QSlider>
55    #include <QLabel>
56    #include <QTimer>
57    #include <QDateTime>
58    
59    
60  #ifdef HAVE_SIGNAL_H  #ifdef HAVE_SIGNAL_H
61  #include <signal.h>  #include <signal.h>
# Line 73  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 83  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.setLatin1(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 159  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->setTickmarks(QSlider::Below);          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->setRange(0, 100);          m_pVolumeSlider->setSingleStep(10);
180            m_pVolumeSlider->setMinimum(0);
181            m_pVolumeSlider->setMaximum(100);
182          m_pVolumeSlider->setMaximumHeight(26);          m_pVolumeSlider->setMaximumHeight(26);
183          m_pVolumeSlider->setMinimumWidth(160);          m_pVolumeSlider->setMinimumWidth(160);
184          QToolTip::add(m_pVolumeSlider, sVolumeText);          m_pVolumeSlider->setToolTip(sVolumeText);
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->setRange(0, 100);          m_pVolumeSpinBox->setMinimum(0);
197          QToolTip::add(m_pVolumeSpinBox, sVolumeText);          m_pVolumeSpinBox->setMaximum(100);
198            m_pVolumeSpinBox->setToolTip(sVolumeText);
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);
   
     // Create the recent files sub-menu.  
     m_pRecentFilesMenu = new Q3PopupMenu(this);  
     ui.fileMenu->insertSeparator(4);  
     ui.fileMenu->insertItem(tr("Recent &Files"), m_pRecentFilesMenu, 0, 5);  
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                  SIGNAL(activated()),          // shortcuts firmly attached...
246            addAction(m_ui.viewMenubarAction);
247            addAction(m_ui.viewToolbarAction);
248    
249            QObject::connect(m_ui.fileNewAction,
250                    SIGNAL(triggered()),
251                  SLOT(fileNew()));                  SLOT(fileNew()));
252          QObject::connect(ui.fileOpenAction,          QObject::connect(m_ui.fileOpenAction,
253                  SIGNAL(activated()),                  SIGNAL(triggered()),
254                  SLOT(fileOpen()));                  SLOT(fileOpen()));
255          QObject::connect(ui.fileSaveAction,          QObject::connect(m_ui.fileSaveAction,
256                  SIGNAL(activated()),                  SIGNAL(triggered()),
257                  SLOT(fileSave()));                  SLOT(fileSave()));
258          QObject::connect(ui.fileSaveAsAction,          QObject::connect(m_ui.fileSaveAsAction,
259                  SIGNAL(activated()),                  SIGNAL(triggered()),
260                  SLOT(fileSaveAs()));                  SLOT(fileSaveAs()));
261          QObject::connect(ui.fileResetAction,          QObject::connect(m_ui.fileResetAction,
262                  SIGNAL(activated()),                  SIGNAL(triggered()),
263                  SLOT(fileReset()));                  SLOT(fileReset()));
264          QObject::connect(ui.fileRestartAction,          QObject::connect(m_ui.fileRestartAction,
265                  SIGNAL(activated()),                  SIGNAL(triggered()),
266                  SLOT(fileRestart()));                  SLOT(fileRestart()));
267          QObject::connect(ui.fileExitAction,          QObject::connect(m_ui.fileExitAction,
268                  SIGNAL(activated()),                  SIGNAL(triggered()),
269                  SLOT(fileExit()));                  SLOT(fileExit()));
270          QObject::connect(ui.editAddChannelAction,          QObject::connect(m_ui.editAddChannelAction,
271                  SIGNAL(activated()),                  SIGNAL(triggered()),
272                  SLOT(editAddChannel()));                  SLOT(editAddChannel()));
273          QObject::connect(ui.editRemoveChannelAction,          QObject::connect(m_ui.editRemoveChannelAction,
274                  SIGNAL(activated()),                  SIGNAL(triggered()),
275                  SLOT(editRemoveChannel()));                  SLOT(editRemoveChannel()));
276          QObject::connect(ui.editSetupChannelAction,          QObject::connect(m_ui.editSetupChannelAction,
277                  SIGNAL(activated()),                  SIGNAL(triggered()),
278                  SLOT(editSetupChannel()));                  SLOT(editSetupChannel()));
279          QObject::connect(ui.editEditChannelAction,          QObject::connect(m_ui.editEditChannelAction,
280                  SIGNAL(activated()),                  SIGNAL(triggered()),
281                  SLOT(editEditChannel()));                  SLOT(editEditChannel()));
282          QObject::connect(ui.editResetChannelAction,          QObject::connect(m_ui.editResetChannelAction,
283                  SIGNAL(activated()),                  SIGNAL(triggered()),
284                  SLOT(editResetChannel()));                  SLOT(editResetChannel()));
285          QObject::connect(ui.editResetAllChannelsAction,          QObject::connect(m_ui.editResetAllChannelsAction,
286                  SIGNAL(activated()),                  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(activated()),                  SIGNAL(triggered()),
302                  SLOT(viewInstruments()));                  SLOT(viewInstruments()));
303          QObject::connect(ui.viewDevicesAction,          QObject::connect(m_ui.viewDevicesAction,
304                  SIGNAL(activated()),                  SIGNAL(triggered()),
305                  SLOT(viewDevices()));                  SLOT(viewDevices()));
306          QObject::connect(ui.viewOptionsAction,          QObject::connect(m_ui.viewOptionsAction,
307                  SIGNAL(activated()),                  SIGNAL(triggered()),
308                  SLOT(viewOptions()));                  SLOT(viewOptions()));
309          QObject::connect(ui.channelsArrangeAction,          QObject::connect(m_ui.channelsArrangeAction,
310                  SIGNAL(activated()),                  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(activated()),                  SIGNAL(triggered()),
317                  SLOT(helpAbout()));                  SLOT(helpAbout()));
318          QObject::connect(ui.helpAboutQtAction,          QObject::connect(m_ui.helpAboutQtAction,
319                  SIGNAL(activated()),                  SIGNAL(triggered()),
320                  SLOT(helpAboutQt()));                  SLOT(helpAboutQt()));
321    
322            QObject::connect(m_ui.fileMenu,
323                    SIGNAL(aboutToShow()),
324                    SLOT(updateRecentFilesMenu()));
325            QObject::connect(m_ui.channelsMenu,
326                    SIGNAL(aboutToShow()),
327                    SLOT(channelsMenuAboutToShow()));
328  }  }
329    
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;
362          delete m_pVolumeSlider;          delete m_pVolumeSlider;
363  #endif  #endif
364    
     // Delete recentfiles menu.  
     if (m_pRecentFilesMenu)  
         delete m_pRecentFilesMenu;  
   
365          // Pseudo-singleton reference shut-down.          // Pseudo-singleton reference shut-down.
366          g_pMainForm = NULL;          g_pMainForm = NULL;
367  }  }
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::WFlags wflags = Qt::WStyle_Customize          Qt::WindowFlags wflags = Qt::Window
378                  | Qt::WStyle_NormalBorder  #if QT_VERSION >= 0x040200
379                  | Qt::WStyle_Title                  | Qt::CustomizeWindowHint
380                  | Qt::WStyle_SysMenu  #endif
381                  | Qt::WStyle_MinMax                  | Qt::WindowTitleHint
382                  | Qt::WType_TopLevel;                  | Qt::WindowSystemMenuHint
383      if (m_pOptions->bKeepOnTop)                  | Qt::WindowMinMaxButtonsHint;
384          wflags |= Qt::WStyle_Tool;          if (m_pOptions->bKeepOnTop)
385      // Some child forms are to be created right now.                  wflags |= Qt::Tool;
386      m_pMessages = new qsamplerMessages(this);          // Some child forms are to be created right now.
387      m_pDeviceForm = new DeviceForm(this, wflags);          m_pMessages = new Messages(this);
388            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...          // Set message defaults...
395      updateMessagesFont();          updateMessagesFont();
396      updateMessagesLimit();          updateMessagesLimit();
397      updateMessagesCapture();          updateMessagesCapture();
398      // Set the visibility signal.          // Set the visibility signal.
399          QObject::connect(m_pMessages,          QObject::connect(m_pMessages,
400                  SIGNAL(visibilityChanged(bool)),                  SIGNAL(visibilityChanged(bool)),
401                  SLOT(stabilizeForm()));                  SLOT(stabilizeForm()));
402    
403      // Initial decorations toggle state.          // Initial decorations toggle state.
404      ui.viewMenubarAction->setOn(m_pOptions->bMenubar);          m_ui.viewMenubarAction->setChecked(m_pOptions->bMenubar);
405      ui.viewToolbarAction->setOn(m_pOptions->bToolbar);          m_ui.viewToolbarAction->setChecked(m_pOptions->bToolbar);
406      ui.viewStatusbarAction->setOn(m_pOptions->bStatusbar);          m_ui.viewStatusbarAction->setChecked(m_pOptions->bStatusbar);
407      ui.channelsAutoArrangeAction->setOn(m_pOptions->bAutoArrange);          m_ui.channelsAutoArrangeAction->setChecked(m_pOptions->bAutoArrange);
408    
409      // Initial decorations visibility state.          // Initial decorations visibility state.
410      viewMenubar(m_pOptions->bMenubar);          viewMenubar(m_pOptions->bMenubar);
411      viewToolbar(m_pOptions->bToolbar);          viewToolbar(m_pOptions->bToolbar);
412      viewStatusbar(m_pOptions->bStatusbar);          viewStatusbar(m_pOptions->bStatusbar);
413    
414      addDockWidget(Qt::BottomDockWidgetArea, m_pMessages);          addDockWidget(Qt::BottomDockWidgetArea, m_pMessages);
415    
416      // Restore whole toolbar & dock windows states.          // Restore whole dock windows state.
417      QString sDockables = m_pOptions->settings().readEntry("/Layout/DockWindowsBase64" , QString::null);          QByteArray aDockables = m_pOptions->settings().value(
418      if (!sDockables.isEmpty()) {                  "/Layout/DockWindows").toByteArray();
419          restoreState(QByteArray::fromBase64(sDockables.toAscii()));          if (!aDockables.isEmpty()) {
420      }                  restoreState(aDockables);
421      // Try to restore old window positioning and initial visibility.          }
422      m_pOptions->loadWidgetGeometry(this);  
423      m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);          // Try to restore old window positioning and initial visibility.
424      m_pOptions->loadWidgetGeometry(m_pDeviceForm);          m_pOptions->loadWidgetGeometry(this);
425            m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);
426      // Final startup stabilization...          m_pOptions->loadWidgetGeometry(m_pDeviceForm);
427      updateMaxVolume();  
428      updateRecentFilesMenu();          // Final startup stabilization...
429      stabilizeForm();          updateMaxVolume();
430            updateRecentFilesMenu();
431            stabilizeForm();
432    
433      // Make it ready :-)          // Make it ready :-)
434      statusBar()->message(tr("Ready"), 3000);          statusBar()->showMessage(tr("Ready"), 3000);
435    
436      // We'll try to start immediately...          // We'll try to start immediately...
437      startSchedule(0);          startSchedule(0);
438    
439      // Register the first timer slot.          // Register the first timer slot.
440      QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));          QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
441  }  }
442    
443    
444  // Window close event handlers.  // Window close event handlers.
445  bool MainForm::queryClose (void)  bool MainForm::queryClose (void)
446  {  {
447      bool bQueryClose = closeSession(false);          bool bQueryClose = closeSession(false);
448    
449      // Try to save current general state...          // Try to save current general state...
450      if (m_pOptions) {          if (m_pOptions) {
451          // Some windows default fonts is here on demand too.                  // Some windows default fonts is here on demand too.
452          if (bQueryClose && m_pMessages)                  if (bQueryClose && m_pMessages)
453              m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
454          // Try to save current positioning.                  // Try to save current positioning.
455          if (bQueryClose) {                  if (bQueryClose) {
456              // Save decorations state.                          // Save decorations state.
457              m_pOptions->bMenubar = ui.MenuBar->isVisible();                          m_pOptions->bMenubar = m_ui.MenuBar->isVisible();
458              m_pOptions->bToolbar = (ui.fileToolbar->isVisible() || ui.editToolbar->isVisible() || ui.channelsToolbar->isVisible());                          m_pOptions->bToolbar = (m_ui.fileToolbar->isVisible()
459              m_pOptions->bStatusbar = statusBar()->isVisible();                                  || m_ui.editToolbar->isVisible()
460              // Save the dock windows state.                                  || m_ui.channelsToolbar->isVisible());
461              const QString sDockables = saveState().toBase64().data();                          m_pOptions->bStatusbar = statusBar()->isVisible();
462              m_pOptions->settings().writeEntry("/Layout/DockWindowsBase64", sDockables);                          // Save the dock windows state.
463              // And the children, and the main windows state,.                          const QString sDockables = saveState().toBase64().data();
464                            m_pOptions->settings().setValue("/Layout/DockWindows", saveState());
465                            // And the children, and the main windows state,.
466                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);
467                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);
468                          m_pOptions->saveWidgetGeometry(this);                          m_pOptions->saveWidgetGeometry(this);
# Line 454  bool MainForm::queryClose (void) Line 471  bool MainForm::queryClose (void)
471                                  m_pInstrumentListForm->close();                                  m_pInstrumentListForm->close();
472                          if (m_pDeviceForm)                          if (m_pDeviceForm)
473                                  m_pDeviceForm->close();                                  m_pDeviceForm->close();
474              // Stop client and/or server, gracefully.                          // Stop client and/or server, gracefully.
475              stopServer();                          stopServer(true /*interactive*/);
476          }                  }
477      }          }
478    
479      return bQueryClose;          return bQueryClose;
480  }  }
481    
482    
483  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )
484  {  {
485      if (queryClose())          if (queryClose()) {
486          pCloseEvent->accept();                  DeviceStatusForm::deleteAllInstances();
487      else                  pCloseEvent->accept();
488          pCloseEvent->ignore();          } else
489  }                  pCloseEvent->ignore();
   
   
 // Drag'n'drop file handler.  
 bool MainForm::decodeDragFiles ( const QMimeSource *pEvent, QStringList& files )  
 {  
     bool bDecode = false;  
   
     if (Q3TextDrag::canDecode(pEvent)) {  
         QString sText;  
         bDecode = Q3TextDrag::decode(pEvent, sText);  
         if (bDecode) {  
             files = QStringList::split('\n', sText);  
             for (QStringList::Iterator iter = files.begin(); iter != files.end(); iter++)  
                 *iter = QUrl((*iter).stripWhiteSpace().replace(QRegExp("^file:"), QString::null)).path();  
         }  
     }  
   
     return bDecode;  
490  }  }
491    
492    
493  // Window drag-n-drop event handlers.  // Window drag-n-drop event handlers.
494  void MainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )  void MainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )
495  {  {
496          QStringList files;          // Accept external drags only...
497          pDragEnterEvent->accept(decodeDragFiles(pDragEnterEvent, files));          if (pDragEnterEvent->source() == NULL
498                    && pDragEnterEvent->mimeData()->hasUrls()) {
499                    pDragEnterEvent->accept();
500            } else {
501                    pDragEnterEvent->ignore();
502            }
503  }  }
504    
505    
506  void MainForm::dropEvent ( QDropEvent* pDropEvent )  void MainForm::dropEvent ( QDropEvent* pDropEvent )
507  {  {
508      QStringList files;          // Accept externally originated drops only...
509            if (pDropEvent->source())
510      if (!decodeDragFiles(pDropEvent, files))                  return;
         return;  
511    
512          for (QStringList::Iterator iter = files.begin(); iter != files.end(); iter++) {          const QMimeData *pMimeData = pDropEvent->mimeData();
513                  const QString& sPath = *iter;          if (pMimeData->hasUrls()) {
514                  if (qsamplerChannel::isInstrumentFile(sPath)) {                  QListIterator<QUrl> iter(pMimeData->urls());
515                          // Try to create a new channel from instrument file...                  while (iter.hasNext()) {
516                          qsamplerChannel *pChannel = new qsamplerChannel();                          const QString& sPath = iter.next().toLocalFile();
517                          if (pChannel == NULL)                          if (Channel::isInstrumentFile(sPath)) {
518                                  return;                                  // Try to create a new channel from instrument file...
519                          // Start setting the instrument filename...                                  Channel *pChannel = new Channel();
520                          pChannel->setInstrument(sPath, 0);                                  if (pChannel == NULL)
521                          // Before we show it up, may be we'll                                          return;
522                          // better ask for some initial values?                                  // Start setting the instrument filename...
523                          if (!pChannel->channelSetup(this)) {                                  pChannel->setInstrument(sPath, 0);
524                                  delete pChannel;                                  // Before we show it up, may be we'll
525                                  return;                                  // better ask for some initial values?
526                          }                                  if (!pChannel->channelSetup(this)) {
527                          // Finally, give it to a new channel strip...                                          delete pChannel;
528                          if (!createChannelStrip(pChannel)) {                                          return;
529                                  delete pChannel;                                  }
530                                  return;                                  // Finally, give it to a new channel strip...
531                                    if (!createChannelStrip(pChannel)) {
532                                            delete pChannel;
533                                            return;
534                                    }
535                                    // Make that an overall update.
536                                    m_iDirtyCount++;
537                                    stabilizeForm();
538                            }   // Otherwise, load an usual session file (LSCP script)...
539                            else if (closeSession(true)) {
540                                    loadSessionFile(sPath);
541                                    break;
542                          }                          }
                         // Make that an overall update.  
                         m_iDirtyCount++;  
                         stabilizeForm();  
                 }   // Otherwise, load an usual session file (LSCP script)...  
                 else if (closeSession(true)) {  
                         loadSessionFile(sPath);  
                         break;  
543                  }                  }
544                  // Make it look responsive...:)                  // Make it look responsive...:)
545                  QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
546          }          }
547  }  }
548    
549    
550  // Custome event handler.  // Custome event handler.
551  void MainForm::customEvent(QEvent* pCustomEvent)  void MainForm::customEvent(QEvent* pCustomEvent)
552  {  {
553      // For the time being, just pump it to messages.          // For the time being, just pump it to messages.
554      if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {          if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {
555          qsamplerCustomEvent *pEvent = (qsamplerCustomEvent *) pCustomEvent;                  CustomEvent *pEvent = static_cast<CustomEvent *> (pCustomEvent);
556                  if (pEvent->event() == LSCP_EVENT_CHANNEL_INFO) {                  switch (pEvent->event()) {
557                          int iChannelID = pEvent->data().toInt();                          case LSCP_EVENT_CHANNEL_COUNT:
558                          ChannelStrip *pChannelStrip = channelStrip(iChannelID);                                  updateAllChannelStrips(true);
559                          if (pChannelStrip)                                  break;
560                                  channelStripChanged(pChannelStrip);                          case LSCP_EVENT_CHANNEL_INFO: {
561                  } else {                                  int iChannelID = pEvent->data().toInt();
562                          appendMessagesColor(tr("Notify event: %1 data: %2")                                  ChannelStrip *pChannelStrip = channelStrip(iChannelID);
563                                  .arg(::lscp_event_to_text(pEvent->event()))                                  if (pChannelStrip)
564                                  .arg(pEvent->data()), "#996699");                                          channelStripChanged(pChannelStrip);
565                                    break;
566                            }
567                            case LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT:
568                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
569                                    DeviceStatusForm::onDevicesChanged();
570                                    updateViewMidiDeviceStatusMenu();
571                                    break;
572                            case LSCP_EVENT_MIDI_INPUT_DEVICE_INFO: {
573                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
574                                    const int iDeviceID = pEvent->data().section(' ', 0, 0).toInt();
575                                    DeviceStatusForm::onDeviceChanged(iDeviceID);
576                                    break;
577                            }
578                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT:
579                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
580                                    break;
581                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO:
582                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
583                                    break;
584    #if CONFIG_LSCP_CHANNEL_MIDI
585                            case LSCP_EVENT_CHANNEL_MIDI: {
586                                    const int iChannelID = pEvent->data().section(' ', 0, 0).toInt();
587                                    ChannelStrip *pChannelStrip = channelStrip(iChannelID);
588                                    if (pChannelStrip)
589                                            pChannelStrip->midiArrived();
590                                    break;
591                            }
592    #endif
593    #if CONFIG_LSCP_DEVICE_MIDI
594                            case LSCP_EVENT_DEVICE_MIDI: {
595                                    const int iDeviceID = pEvent->data().section(' ', 0, 0).toInt();
596                                    const int iPortID   = pEvent->data().section(' ', 1, 1).toInt();
597                                    DeviceStatusForm* pDeviceStatusForm =
598                                            DeviceStatusForm::getInstance(iDeviceID);
599                                    if (pDeviceStatusForm)
600                                            pDeviceStatusForm->midiArrived(iPortID);
601                                    break;
602                            }
603    #endif
604                            default:
605                                    appendMessagesColor(tr("Notify event: %1 data: %2")
606                                            .arg(::lscp_event_to_text(pEvent->event()))
607                                            .arg(pEvent->data()), "#996699");
608                  }                  }
609      }          }
610    }
611    
612    void MainForm::updateViewMidiDeviceStatusMenu() {
613            m_ui.viewMidiDeviceStatusMenu->clear();
614            const std::map<int, DeviceStatusForm*> statusForms =
615                    DeviceStatusForm::getInstances();
616            for (
617                    std::map<int, DeviceStatusForm*>::const_iterator iter = statusForms.begin();
618                    iter != statusForms.end(); ++iter
619            ) {
620                    DeviceStatusForm* pForm = iter->second;
621                    m_ui.viewMidiDeviceStatusMenu->addAction(
622                            pForm->visibleAction()
623                    );
624            }
625  }  }
626    
627  // Context menu event handler.  // Context menu event handler.
628  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )
629  {  {
630      stabilizeForm();          stabilizeForm();
631    
632      ui.editMenu->exec(pEvent->globalPos());          m_ui.editMenu->exec(pEvent->globalPos());
633  }  }
634    
635    
# Line 571  void MainForm::contextMenuEvent( QContex Line 637  void MainForm::contextMenuEvent( QContex
637  // qsamplerMainForm -- Brainless public property accessors.  // qsamplerMainForm -- Brainless public property accessors.
638    
639  // The global options settings property.  // The global options settings property.
640  qsamplerOptions *MainForm::options (void)  Options *MainForm::options (void) const
641  {  {
642      return m_pOptions;          return m_pOptions;
643  }  }
644    
645    
646  // The LSCP client descriptor property.  // The LSCP client descriptor property.
647  lscp_client_t *MainForm::client (void)  lscp_client_t *MainForm::client (void) const
648  {  {
649      return m_pClient;          return m_pClient;
650  }  }
651    
652    
# Line 597  MainForm *MainForm::getInstance (void) Line 663  MainForm *MainForm::getInstance (void)
663  // Format the displayable session filename.  // Format the displayable session filename.
664  QString MainForm::sessionName ( const QString& sFilename )  QString MainForm::sessionName ( const QString& sFilename )
665  {  {
666      bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);          bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);
667      QString sSessionName = sFilename;          QString sSessionName = sFilename;
668      if (sSessionName.isEmpty())          if (sSessionName.isEmpty())
669          sSessionName = tr("Untitled") + QString::number(m_iUntitled);                  sSessionName = tr("Untitled") + QString::number(m_iUntitled);
670      else if (!bCompletePath)          else if (!bCompletePath)
671          sSessionName = QFileInfo(sSessionName).fileName();                  sSessionName = QFileInfo(sSessionName).fileName();
672      return sSessionName;          return sSessionName;
673  }  }
674    
675    
676  // Create a new session file from scratch.  // Create a new session file from scratch.
677  bool MainForm::newSession (void)  bool MainForm::newSession (void)
678  {  {
679      // Check if we can do it.          // Check if we can do it.
680      if (!closeSession(true))          if (!closeSession(true))
681          return false;                  return false;
682    
683          // Give us what the server has, right now...          // Give us what the server has, right now...
684          updateSession();          updateSession();
685    
686      // Ok increment untitled count.          // Ok increment untitled count.
687      m_iUntitled++;          m_iUntitled++;
688    
689      // Stabilize form.          // Stabilize form.
690      m_sFilename = QString::null;          m_sFilename = QString::null;
691      m_iDirtyCount = 0;          m_iDirtyCount = 0;
692      appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));          appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));
693      stabilizeForm();          stabilizeForm();
694    
695      return true;          return true;
696  }  }
697    
698    
699  // Open an existing sampler session.  // Open an existing sampler session.
700  bool MainForm::openSession (void)  bool MainForm::openSession (void)
701  {  {
702      if (m_pOptions == NULL)          if (m_pOptions == NULL)
703          return false;                  return false;
704    
705      // Ask for the filename to open...          // Ask for the filename to open...
706      QString sFilename = QFileDialog::getOpenFileName(          QString sFilename = QFileDialog::getOpenFileName(this,
707                  m_pOptions->sSessionDir,                // Start here.                  QSAMPLER_TITLE ": " + tr("Open Session"), // Caption.
708                  tr("LSCP Session files") + " (*.lscp)", // Filter (LSCP files)                  m_pOptions->sSessionDir,                  // Start here.
709                  this, 0,                                // Parent and name (none)                  tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
710                  QSAMPLER_TITLE ": " + tr("Open Session")        // Caption.          );
     );  
   
     // Have we cancelled?  
     if (sFilename.isEmpty())  
         return false;  
   
     // Check if we're going to discard safely the current one...  
     if (!closeSession(true))  
         return false;  
711    
712      // Load it right away.          // Have we cancelled?
713      return loadSessionFile(sFilename);          if (sFilename.isEmpty())
714                    return false;
715    
716            // Check if we're going to discard safely the current one...
717            if (!closeSession(true))
718                    return false;
719    
720            // Load it right away.
721            return loadSessionFile(sFilename);
722  }  }
723    
724    
725  // Save current sampler session with another name.  // Save current sampler session with another name.
726  bool MainForm::saveSession ( bool bPrompt )  bool MainForm::saveSession ( bool bPrompt )
727  {  {
728      if (m_pOptions == NULL)          if (m_pOptions == NULL)
729          return false;                  return false;
730    
731      QString sFilename = m_sFilename;          QString sFilename = m_sFilename;
732    
733      // Ask for the file to save, if there's none...          // Ask for the file to save, if there's none...
734      if (bPrompt || sFilename.isEmpty()) {          if (bPrompt || sFilename.isEmpty()) {
735          // If none is given, assume default directory.                  // If none is given, assume default directory.
736          if (sFilename.isEmpty())                  if (sFilename.isEmpty())
737              sFilename = m_pOptions->sSessionDir;                          sFilename = m_pOptions->sSessionDir;
738          // Prompt the guy...                  // Prompt the guy...
739          sFilename = QFileDialog::getSaveFileName(                  sFilename = QFileDialog::getSaveFileName(this,
740                          sFilename,                              // Start here.                          QSAMPLER_TITLE ": " + tr("Save Session"), // Caption.
741                          tr("LSCP Session files") + " (*.lscp)", // Filter (LSCP files)                          sFilename,                                // Start here.
742                          this, 0,                                // Parent and name (none)                          tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
743                          QSAMPLER_TITLE ": " + tr("Save Session")        // Caption.                  );
744          );                  // Have we cancelled it?
745          // Have we cancelled it?                  if (sFilename.isEmpty())
746          if (sFilename.isEmpty())                          return false;
747              return false;                  // Enforce .lscp extension...
748          // Enforce .lscp extension...                  if (QFileInfo(sFilename).suffix().isEmpty())
749          if (QFileInfo(sFilename).extension().isEmpty())                          sFilename += ".lscp";
750              sFilename += ".lscp";                  // Check if already exists...
751          // Check if already exists...                  if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {
752          if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {                          if (QMessageBox::warning(this,
             if (QMessageBox::warning(this,  
753                                  QSAMPLER_TITLE ": " + tr("Warning"),                                  QSAMPLER_TITLE ": " + tr("Warning"),
754                  tr("The file already exists:\n\n"                                  tr("The file already exists:\n\n"
755                     "\"%1\"\n\n"                                  "\"%1\"\n\n"
756                     "Do you want to replace it?")                                  "Do you want to replace it?")
757                     .arg(sFilename),                                  .arg(sFilename),
758                  tr("Replace"), tr("Cancel")) > 0)                                  tr("Replace"), tr("Cancel")) > 0)
759                  return false;                                  return false;
760          }                  }
761      }          }
762    
763      // Save it right away.          // Save it right away.
764      return saveSessionFile(sFilename);          return saveSessionFile(sFilename);
765  }  }
766    
767    
768  // Close current session.  // Close current session.
769  bool MainForm::closeSession ( bool bForce )  bool MainForm::closeSession ( bool bForce )
770  {  {
771      bool bClose = true;          bool bClose = true;
772    
773      // Are we dirty enough to prompt it?          // Are we dirty enough to prompt it?
774      if (m_iDirtyCount > 0) {          if (m_iDirtyCount > 0) {
775          switch (QMessageBox::warning(this,                  switch (QMessageBox::warning(this,
776                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
777              tr("The current session has been changed:\n\n"                          tr("The current session has been changed:\n\n"
778              "\"%1\"\n\n"                          "\"%1\"\n\n"
779              "Do you want to save the changes?")                          "Do you want to save the changes?")
780              .arg(sessionName(m_sFilename)),                          .arg(sessionName(m_sFilename)),
781              tr("Save"), tr("Discard"), tr("Cancel"))) {                          tr("Save"), tr("Discard"), tr("Cancel"))) {
782          case 0:     // Save...                  case 0:     // Save...
783              bClose = saveSession(false);                          bClose = saveSession(false);
784              // Fall thru....                          // Fall thru....
785          case 1:     // Discard                  case 1:     // Discard
786              break;                          break;
787          default:    // Cancel.                  default:    // Cancel.
788              bClose = false;                          bClose = false;
789              break;                          break;
790          }                  }
791      }          }
   
     // 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;  
     }  
792    
793      return bClose;          // If we may close it, dot it.
794            if (bClose) {
795                    // Remove all channel strips from sight...
796                    m_pWorkspace->setUpdatesEnabled(false);
797                    QWidgetList wlist = m_pWorkspace->windowList();
798                    for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
799                            ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
800                            if (pChannelStrip) {
801                                    Channel *pChannel = pChannelStrip->channel();
802                                    if (bForce && pChannel)
803                                            pChannel->removeChannel();
804                                    delete pChannelStrip;
805                            }
806                    }
807                    m_pWorkspace->setUpdatesEnabled(true);
808                    // We're now clean, for sure.
809                    m_iDirtyCount = 0;
810            }
811    
812            return bClose;
813  }  }
814    
815    
816  // Load a session from specific file path.  // Load a session from specific file path.
817  bool MainForm::loadSessionFile ( const QString& sFilename )  bool MainForm::loadSessionFile ( const QString& sFilename )
818  {  {
819      if (m_pClient == NULL)          if (m_pClient == NULL)
820          return false;                  return false;
821    
822      // Open and read from real file.          // Open and read from real file.
823      QFile file(sFilename);          QFile file(sFilename);
824      if (!file.open(IO_ReadOnly)) {          if (!file.open(QIODevice::ReadOnly)) {
825          appendMessagesError(tr("Could not open \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
826          return false;                          tr("Could not open \"%1\" session file.\n\nSorry.")
827      }                          .arg(sFilename));
828                    return false;
829            }
830    
831          // Tell the world we'll take some time...          // Tell the world we'll take some time...
832          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
833    
834      // Read the file.          // Read the file.
835          int iLine = 0;          int iLine = 0;
836      int iErrors = 0;          int iErrors = 0;
837      QTextStream ts(&file);          QTextStream ts(&file);
838      while (!ts.atEnd()) {          while (!ts.atEnd()) {
839          // Read the line.                  // Read the line.
840          QString sCommand = ts.readLine().stripWhiteSpace();                  QString sCommand = ts.readLine().trimmed();
841                  iLine++;                  iLine++;
842          // If not empty, nor a comment, call the server...                  // If not empty, nor a comment, call the server...
843          if (!sCommand.isEmpty() && sCommand[0] != '#') {                  if (!sCommand.isEmpty() && sCommand[0] != '#') {
844                          // Remember that, no matter what,                          // Remember that, no matter what,
845                          // all LSCP commands are CR/LF terminated.                          // all LSCP commands are CR/LF terminated.
846                          sCommand += "\r\n";                          sCommand += "\r\n";
847                          if (::lscp_client_query(m_pClient, sCommand.latin1()) != LSCP_OK) {                          if (::lscp_client_query(m_pClient, sCommand.toUtf8().constData())
848                                    != LSCP_OK) {
849                                  appendMessagesColor(QString("%1(%2): %3")                                  appendMessagesColor(QString("%1(%2): %3")
850                                          .arg(QFileInfo(sFilename).fileName()).arg(iLine)                                          .arg(QFileInfo(sFilename).fileName()).arg(iLine)
851                                          .arg(sCommand.simplifyWhiteSpace()), "#996633");                                          .arg(sCommand.simplified()), "#996633");
852                                  appendMessagesClient("lscp_client_query");                                  appendMessagesClient("lscp_client_query");
853                                  iErrors++;                                  iErrors++;
854                          }                          }
855          }                  }
856          // Try to make it snappy :)                  // Try to make it snappy :)
857          QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
858      }          }
859    
860      // Ok. we've read it.          // Ok. we've read it.
861      file.close();          file.close();
862    
863          // Now we'll try to create (update) the whole GUI session.          // Now we'll try to create (update) the whole GUI session.
864          updateSession();          updateSession();
# Line 800  bool MainForm::loadSessionFile ( const Q Line 867  bool MainForm::loadSessionFile ( const Q
867          QApplication::restoreOverrideCursor();          QApplication::restoreOverrideCursor();
868    
869          // Have we any errors?          // Have we any errors?
870          if (iErrors > 0)          if (iErrors > 0) {
871                  appendMessagesError(tr("Session loaded with errors\nfrom \"%1\".\n\nSorry.").arg(sFilename));                  appendMessagesError(
872                            tr("Session loaded with errors\nfrom \"%1\".\n\nSorry.")
873                            .arg(sFilename));
874            }
875    
876      // Save as default session directory.          // Save as default session directory.
877      if (m_pOptions)          if (m_pOptions)
878          m_pOptions->sSessionDir = QFileInfo(sFilename).dirPath(true);                  m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();
879          // We're not dirty anymore, if loaded without errors,          // We're not dirty anymore, if loaded without errors,
880          m_iDirtyCount = iErrors;          m_iDirtyCount = iErrors;
881      // Stabilize form...          // Stabilize form...
882      m_sFilename = sFilename;          m_sFilename = sFilename;
883      updateRecentFiles(sFilename);          updateRecentFiles(sFilename);
884      appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));          appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));
885    
886      // Make that an overall update.          // Make that an overall update.
887      stabilizeForm();          stabilizeForm();
888      return true;          return true;
889  }  }
890    
891    
# Line 831  bool MainForm::saveSessionFile ( const Q Line 901  bool MainForm::saveSessionFile ( const Q
901                  return false;                  return false;
902          }          }
903    
904      // Open and write into real file.          // Open and write into real file.
905      QFile file(sFilename);          QFile file(sFilename);
906      if (!file.open(IO_WriteOnly | IO_Truncate)) {          if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
907          appendMessagesError(tr("Could not open \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
908          return false;                          tr("Could not open \"%1\" session file.\n\nSorry.")
909      }                          .arg(sFilename));
910                    return false;
911            }
912    
913          // Tell the world we'll take some time...          // Tell the world we'll take some time...
914          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
915    
916      // Write the file.          // Write the file.
917      int  iErrors = 0;          int  iErrors = 0;
918      QTextStream ts(&file);          QTextStream ts(&file);
919      ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;          ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;
920      ts << "# " << tr("Version")          ts << "# " << tr("Version")
921         << ": " QSAMPLER_VERSION << endl;          << ": " QSAMPLER_VERSION << endl;
922      ts << "# " << tr("Build")          ts << "# " << tr("Build")
923         << ": " __DATE__ " " __TIME__ << endl;          << ": " __DATE__ " " __TIME__ << endl;
924      ts << "#"  << endl;          ts << "#"  << endl;
925      ts << "# " << tr("File")          ts << "# " << tr("File")
926         << ": " << QFileInfo(sFilename).fileName() << endl;          << ": " << QFileInfo(sFilename).fileName() << endl;
927      ts << "# " << tr("Date")          ts << "# " << tr("Date")
928         << ": " << QDate::currentDate().toString("MMM dd yyyy")          << ": " << QDate::currentDate().toString("MMM dd yyyy")
929         << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;          << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;
930      ts << "#"  << endl;          ts << "#"  << endl;
931      ts << endl;          ts << endl;
932    
933          // It is assumed that this new kind of device+session file          // It is assumed that this new kind of device+session file
934          // will be loaded from a complete initialized server...          // will be loaded from a complete initialized server...
# Line 866  bool MainForm::saveSessionFile ( const Q Line 938  bool MainForm::saveSessionFile ( const Q
938    
939          // Audio device mapping.          // Audio device mapping.
940          QMap<int, int> audioDeviceMap;          QMap<int, int> audioDeviceMap;
941          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Audio);          piDeviceIDs = Device::getDevices(m_pClient, Device::Audio);
942          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
943                  ts << endl;                  ts << endl;
944                  qsamplerDevice device(qsamplerDevice::Audio, piDeviceIDs[iDevice]);                  Device device(Device::Audio, piDeviceIDs[iDevice]);
945                  // Audio device specification...                  // Audio device specification...
946                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
947                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
948                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();
949                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
950                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
951                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
952                                          ++deviceParam) {                                          ++deviceParam) {
953                          const qsamplerDeviceParam& param = deviceParam.data();                          const DeviceParam& param = deviceParam.value();
954                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
955                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
956                  }                  }
957                  ts << endl;                  ts << endl;
958                  // Audio channel parameters...                  // Audio channel parameters...
959                  int iPort = 0;                  int iPort = 0;
960                  for (qsamplerDevicePort *pPort = device.ports().first();                  QListIterator<DevicePort *> iter(device.ports());
961                                  pPort;                  while (iter.hasNext()) {
962                                          pPort = device.ports().next(), ++iPort) {                          DevicePort *pPort = iter.next();
963                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
964                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
965                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
966                                                  ++portParam) {                                                  ++portParam) {
967                                  const qsamplerDeviceParam& param = portParam.data();                                  const DeviceParam& param = portParam.value();
968                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
969                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice
970                                          << " " << iPort << " " << portParam.key()                                          << " " << iPort << " " << portParam.key()
971                                          << "='" << param.value << "'" << endl;                                          << "='" << param.value << "'" << endl;
972                          }                          }
973                            iPort++;
974                  }                  }
975                  // Audio device index/id mapping.                  // Audio device index/id mapping.
976                  audioDeviceMap[device.deviceID()] = iDevice;                  audioDeviceMap[device.deviceID()] = iDevice;
977                  // Try to keep it snappy :)                  // Try to keep it snappy :)
978                  QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
979          }          }
980    
981          // MIDI device mapping.          // MIDI device mapping.
982          QMap<int, int> midiDeviceMap;          QMap<int, int> midiDeviceMap;
983          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Midi);          piDeviceIDs = Device::getDevices(m_pClient, Device::Midi);
984          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
985                  ts << endl;                  ts << endl;
986                  qsamplerDevice device(qsamplerDevice::Midi, piDeviceIDs[iDevice]);                  Device device(Device::Midi, piDeviceIDs[iDevice]);
987                  // MIDI device specification...                  // MIDI device specification...
988                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
989                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
990                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();
991                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
992                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
993                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
994                                          ++deviceParam) {                                          ++deviceParam) {
995                          const qsamplerDeviceParam& param = deviceParam.data();                          const DeviceParam& param = deviceParam.value();
996                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
997                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
998                  }                  }
999                  ts << endl;                  ts << endl;
1000                  // MIDI port parameters...                  // MIDI port parameters...
1001                  int iPort = 0;                  int iPort = 0;
1002                  for (qsamplerDevicePort *pPort = device.ports().first();                  QListIterator<DevicePort *> iter(device.ports());
1003                                  pPort;                  while (iter.hasNext()) {
1004                                          pPort = device.ports().next(), ++iPort) {                          DevicePort *pPort = iter.next();
1005                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1006                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1007                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1008                                                  ++portParam) {                                                  ++portParam) {
1009                                  const qsamplerDeviceParam& param = portParam.data();                                  const DeviceParam& param = portParam.value();
1010                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1011                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice
1012                                     << " " << iPort << " " << portParam.key()                                  << " " << iPort << " " << portParam.key()
1013                                     << "='" << param.value << "'" << endl;                                  << "='" << param.value << "'" << endl;
1014                          }                          }
1015                            iPort++;
1016                  }                  }
1017                  // MIDI device index/id mapping.                  // MIDI device index/id mapping.
1018                  midiDeviceMap[device.deviceID()] = iDevice;                  midiDeviceMap[device.deviceID()] = iDevice;
1019                  // Try to keep it snappy :)                  // Try to keep it snappy :)
1020                  QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1021          }          }
1022          ts << endl;          ts << endl;
1023    
# Line 1000  bool MainForm::saveSessionFile ( const Q Line 1074  bool MainForm::saveSessionFile ( const Q
1074                                  iErrors++;                                  iErrors++;
1075                          }                          }
1076                          // Try to keep it snappy :)                          // Try to keep it snappy :)
1077                          QApplication::processEvents(QEventLoop::ExcludeUserInput);                          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1078                  }                  }
1079                  ts << endl;                  ts << endl;
1080                  // Check for errors...                  // Check for errors...
# Line 1019  bool MainForm::saveSessionFile ( const Q Line 1093  bool MainForm::saveSessionFile ( const Q
1093  #endif  // CONFIG_MIDI_INSTRUMENT  #endif  // CONFIG_MIDI_INSTRUMENT
1094    
1095          // Sampler channel mapping.          // Sampler channel mapping.
1096      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
1097      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1098          ChannelStrip* pChannelStrip                  ChannelStrip* pChannelStrip
1099                          = static_cast<ChannelStrip *> (wlist.at(iChannel));                          = static_cast<ChannelStrip *> (wlist.at(iChannel));
1100          if (pChannelStrip) {                  if (pChannelStrip) {
1101              qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
1102              if (pChannel) {                          if (pChannel) {
1103                  ts << "# " << tr("Channel") << " " << iChannel << endl;                                  ts << "# " << tr("Channel") << " " << iChannel << endl;
1104                  ts << "ADD CHANNEL" << endl;                                  ts << "ADD CHANNEL" << endl;
1105                                  if (audioDeviceMap.isEmpty()) {                                  if (audioDeviceMap.isEmpty()) {
1106                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel
1107                                                  << " " << pChannel->audioDriver() << endl;                                                  << " " << pChannel->audioDriver() << endl;
# Line 1044  bool MainForm::saveSessionFile ( const Q Line 1118  bool MainForm::saveSessionFile ( const Q
1118                                  }                                  }
1119                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel
1120                                          << " " << pChannel->midiPort() << endl;                                          << " " << pChannel->midiPort() << endl;
1121                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";                                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";
1122                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)                                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
1123                      ts << "ALL";                                          ts << "ALL";
1124                  else                                  else
1125                      ts << pChannel->midiChannel();                                          ts << pChannel->midiChannel();
1126                  ts << endl;                                  ts << endl;
1127                  ts << "LOAD ENGINE " << pChannel->engineName() << " " << iChannel << endl;                                  ts << "LOAD ENGINE " << pChannel->engineName()
1128                                            << " " << iChannel << endl;
1129                                  if (pChannel->instrumentStatus() < 100) ts << "# ";                                  if (pChannel->instrumentStatus() < 100) ts << "# ";
1130                                  ts << "LOAD INSTRUMENT NON_MODAL '" << pChannel->instrumentFile() << "' "                                  ts << "LOAD INSTRUMENT NON_MODAL '"
1131                                            << pChannel->instrumentFile() << "' "
1132                                          << pChannel->instrumentNr() << " " << iChannel << endl;                                          << pChannel->instrumentNr() << " " << iChannel << endl;
1133                                  qsamplerChannelRoutingMap::ConstIterator audioRoute;                                  ChannelRoutingMap::ConstIterator audioRoute;
1134                                  for (audioRoute = pChannel->audioRouting().begin();                                  for (audioRoute = pChannel->audioRouting().begin();
1135                                                  audioRoute != pChannel->audioRouting().end();                                                  audioRoute != pChannel->audioRouting().end();
1136                                                          ++audioRoute) {                                                          ++audioRoute) {
1137                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannel
1138                                                  << " " << audioRoute.key()                                                  << " " << audioRoute.key()
1139                                                  << " " << audioRoute.data() << endl;                                                  << " " << audioRoute.value() << endl;
1140                                  }                                  }
1141                                  ts << "SET CHANNEL VOLUME " << iChannel                                  ts << "SET CHANNEL VOLUME " << iChannel
1142                                          << " " << pChannel->volume() << endl;                                          << " " << pChannel->volume() << endl;
# Line 1110  bool MainForm::saveSessionFile ( const Q Line 1186  bool MainForm::saveSessionFile ( const Q
1186                                          }                                          }
1187                                  }                                  }
1188  #endif  #endif
1189                  ts << endl;                                  ts << endl;
1190              }                          }
1191          }                  }
1192          // Try to keep it snappy :)                  // Try to keep it snappy :)
1193          QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1194      }          }
1195    
1196  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
1197          ts << "# " << tr("Global volume level") << endl;          ts << "# " << tr("Global volume level") << endl;
# Line 1123  bool MainForm::saveSessionFile ( const Q Line 1199  bool MainForm::saveSessionFile ( const Q
1199          ts << endl;          ts << endl;
1200  #endif  #endif
1201    
1202      // Ok. we've wrote it.          // Ok. we've wrote it.
1203      file.close();          file.close();
1204    
1205          // We're fornerly done.          // We're fornerly done.
1206          QApplication::restoreOverrideCursor();          QApplication::restoreOverrideCursor();
1207    
1208      // Have we any errors?          // Have we any errors?
1209      if (iErrors > 0)          if (iErrors > 0) {
1210          appendMessagesError(tr("Some settings could not be saved\nto \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
1211                            tr("Some settings could not be saved\n"
1212      // Save as default session directory.                          "to \"%1\" session file.\n\nSorry.")
1213      if (m_pOptions)                          .arg(sFilename));
1214          m_pOptions->sSessionDir = QFileInfo(sFilename).dirPath(true);          }
1215      // We're not dirty anymore.  
1216      m_iDirtyCount = 0;          // Save as default session directory.
1217      // Stabilize form...          if (m_pOptions)
1218      m_sFilename = sFilename;                  m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();
1219      updateRecentFiles(sFilename);          // We're not dirty anymore.
1220      appendMessages(tr("Save session: \"%1\".").arg(sessionName(m_sFilename)));          m_iDirtyCount = 0;
1221      stabilizeForm();          // Stabilize form...
1222      return true;          m_sFilename = sFilename;
1223            updateRecentFiles(sFilename);
1224            appendMessages(tr("Save session: \"%1\".").arg(sessionName(m_sFilename)));
1225            stabilizeForm();
1226            return true;
1227  }  }
1228    
1229    
1230  // Session change receiver slot.  // Session change receiver slot.
1231  void MainForm::sessionDirty (void)  void MainForm::sessionDirty (void)
1232  {  {
1233      // Just mark the dirty form.          // Just mark the dirty form.
1234      m_iDirtyCount++;          m_iDirtyCount++;
1235      // and update the form status...          // and update the form status...
1236      stabilizeForm();          stabilizeForm();
1237  }  }
1238    
1239    
# Line 1163  void MainForm::sessionDirty (void) Line 1243  void MainForm::sessionDirty (void)
1243  // Create a new sampler session.  // Create a new sampler session.
1244  void MainForm::fileNew (void)  void MainForm::fileNew (void)
1245  {  {
1246      // Of course we'll start clean new.          // Of course we'll start clean new.
1247      newSession();          newSession();
1248  }  }
1249    
1250    
1251  // Open an existing sampler session.  // Open an existing sampler session.
1252  void MainForm::fileOpen (void)  void MainForm::fileOpen (void)
1253  {  {
1254      // Open it right away.          // Open it right away.
1255      openSession();          openSession();
1256  }  }
1257    
1258    
1259  // Open a recent file session.  // Open a recent file session.
1260  void MainForm::fileOpenRecent ( int iIndex )  void MainForm::fileOpenRecent (void)
1261  {  {
1262      // Check if we can safely close the current session...          // Retrive filename index from action data...
1263      if (m_pOptions && closeSession(true)) {          QAction *pAction = qobject_cast<QAction *> (sender());
1264          QString sFilename = m_pOptions->recentFiles[iIndex];          if (pAction && m_pOptions) {
1265          loadSessionFile(sFilename);                  int iIndex = pAction->data().toInt();
1266      }                  if (iIndex >= 0 && iIndex < m_pOptions->recentFiles.count()) {
1267                            QString sFilename = m_pOptions->recentFiles[iIndex];
1268                            // Check if we can safely close the current session...
1269                            if (!sFilename.isEmpty() && closeSession(true))
1270                                    loadSessionFile(sFilename);
1271                    }
1272            }
1273  }  }
1274    
1275    
1276  // Save current sampler session.  // Save current sampler session.
1277  void MainForm::fileSave (void)  void MainForm::fileSave (void)
1278  {  {
1279      // Save it right away.          // Save it right away.
1280      saveSession(false);          saveSession(false);
1281  }  }
1282    
1283    
1284  // Save current sampler session with another name.  // Save current sampler session with another name.
1285  void MainForm::fileSaveAs (void)  void MainForm::fileSaveAs (void)
1286  {  {
1287      // Save it right away, maybe with another name.          // Save it right away, maybe with another name.
1288      saveSession(true);          saveSession(true);
1289  }  }
1290    
1291    
1292  // Reset the sampler instance.  // Reset the sampler instance.
1293  void MainForm::fileReset (void)  void MainForm::fileReset (void)
1294  {  {
1295      if (m_pClient == NULL)          if (m_pClient == NULL)
1296          return;                  return;
1297    
1298      // Ask user whether he/she want's an internal sampler reset...          // Ask user whether he/she want's an internal sampler reset...
1299      if (QMessageBox::warning(this,          if (QMessageBox::warning(this,
1300                  QSAMPLER_TITLE ": " + tr("Warning"),                  QSAMPLER_TITLE ": " + tr("Warning"),
1301          tr("Resetting the sampler instance will close\n"                  tr("Resetting the sampler instance will close\n"
1302             "all device and channel configurations.\n\n"                  "all device and channel configurations.\n\n"
1303             "Please note that this operation may cause\n"                  "Please note that this operation may cause\n"
1304             "temporary MIDI and Audio disruption.\n\n"                  "temporary MIDI and Audio disruption.\n\n"
1305             "Do you want to reset the sampler engine now?"),                  "Do you want to reset the sampler engine now?"),
1306          tr("Reset"), tr("Cancel")) > 0)                  tr("Reset"), tr("Cancel")) > 0)
1307          return;                  return;
1308    
1309          // Trye closing the current session, first...          // Trye closing the current session, first...
1310          if (!closeSession(true))          if (!closeSession(true))
1311                  return;                  return;
1312    
1313      // Just do the reset, after closing down current session...          // Just do the reset, after closing down current session...
1314          // Do the actual sampler reset...          // Do the actual sampler reset...
1315          if (::lscp_reset_sampler(m_pClient) != LSCP_OK) {          if (::lscp_reset_sampler(m_pClient) != LSCP_OK) {
1316                  appendMessagesClient("lscp_reset_sampler");                  appendMessagesClient("lscp_reset_sampler");
# Line 1232  void MainForm::fileReset (void) Line 1318  void MainForm::fileReset (void)
1318                  return;                  return;
1319          }          }
1320    
1321      // Log this.          // Log this.
1322      appendMessages(tr("Sampler reset."));          appendMessages(tr("Sampler reset."));
1323    
1324          // Make it a new session...          // Make it a new session...
1325          newSession();          newSession();
# Line 1243  void MainForm::fileReset (void) Line 1329  void MainForm::fileReset (void)
1329  // Restart the client/server instance.  // Restart the client/server instance.
1330  void MainForm::fileRestart (void)  void MainForm::fileRestart (void)
1331  {  {
1332      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1333          return;                  return;
1334    
1335      bool bRestart = true;          bool bRestart = true;
1336    
1337      // Ask user whether he/she want's a complete restart...          // Ask user whether he/she want's a complete restart...
1338      // (if we're currently up and running)          // (if we're currently up and running)
1339      if (bRestart && m_pClient) {          if (bRestart && m_pClient) {
1340          bRestart = (QMessageBox::warning(this,                  bRestart = (QMessageBox::warning(this,
1341                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
1342              tr("New settings will be effective after\n"                          tr("New settings will be effective after\n"
1343                 "restarting the client/server connection.\n\n"                          "restarting the client/server connection.\n\n"
1344                 "Please note that this operation may cause\n"                          "Please note that this operation may cause\n"
1345                 "temporary MIDI and Audio disruption.\n\n"                          "temporary MIDI and Audio disruption.\n\n"
1346                 "Do you want to restart the connection now?"),                          "Do you want to restart the connection now?"),
1347              tr("Restart"), tr("Cancel")) == 0);                          tr("Restart"), tr("Cancel")) == 0);
1348      }          }
1349    
1350      // Are we still for it?          // Are we still for it?
1351      if (bRestart && closeSession(true)) {          if (bRestart && closeSession(true)) {
1352          // Stop server, it will force the client too.                  // Stop server, it will force the client too.
1353          stopServer();                  stopServer();
1354          // Reschedule a restart...                  // Reschedule a restart...
1355          startSchedule(m_pOptions->iStartDelay);                  startSchedule(m_pOptions->iStartDelay);
1356      }          }
1357  }  }
1358    
1359    
1360  // Exit application program.  // Exit application program.
1361  void MainForm::fileExit (void)  void MainForm::fileExit (void)
1362  {  {
1363      // Go for close the whole thing.          // Go for close the whole thing.
1364      close();          close();
1365  }  }
1366    
1367    
# Line 1285  void MainForm::fileExit (void) Line 1371  void MainForm::fileExit (void)
1371  // Add a new sampler channel.  // Add a new sampler channel.
1372  void MainForm::editAddChannel (void)  void MainForm::editAddChannel (void)
1373  {  {
1374      if (m_pClient == NULL)          if (m_pClient == NULL)
1375          return;                  return;
1376    
1377            // Just create the channel instance...
1378            Channel *pChannel = new Channel();
1379            if (pChannel == NULL)
1380                    return;
1381    
1382            // Before we show it up, may be we'll
1383            // better ask for some initial values?
1384            if (!pChannel->channelSetup(this)) {
1385                    delete pChannel;
1386                    return;
1387            }
1388    
1389            // And give it to the strip...
1390            // (will own the channel instance, if successful).
1391            if (!createChannelStrip(pChannel)) {
1392                    delete pChannel;
1393                    return;
1394            }
1395    
1396            // Do we auto-arrange?
1397            if (m_pOptions && m_pOptions->bAutoArrange)
1398                    channelsArrange();
1399    
1400      // Just create the channel instance...          // Make that an overall update.
1401      qsamplerChannel *pChannel = new qsamplerChannel();          m_iDirtyCount++;
1402      if (pChannel == NULL)          stabilizeForm();
         return;  
   
     // Before we show it up, may be we'll  
     // better ask for some initial values?  
     if (!pChannel->channelSetup(this)) {  
         delete pChannel;  
         return;  
     }  
   
     // And give it to the strip (will own the channel instance, if successful).  
     if (!createChannelStrip(pChannel)) {  
         delete pChannel;  
         return;  
     }  
   
     // Make that an overall update.  
     m_iDirtyCount++;  
     stabilizeForm();  
1403  }  }
1404    
1405    
1406  // Remove current sampler channel.  // Remove current sampler channel.
1407  void MainForm::editRemoveChannel (void)  void MainForm::editRemoveChannel (void)
1408  {  {
1409      if (m_pClient == NULL)          if (m_pClient == NULL)
1410          return;                  return;
1411    
1412            ChannelStrip* pChannelStrip = activeChannelStrip();
1413            if (pChannelStrip == NULL)
1414                    return;
1415    
1416      ChannelStrip* pChannelStrip = activeChannelStrip();          Channel *pChannel = pChannelStrip->channel();
1417      if (pChannelStrip == NULL)          if (pChannel == NULL)
1418          return;                  return;
1419    
1420      qsamplerChannel *pChannel = pChannelStrip->channel();          // Prompt user if he/she's sure about this...
1421      if (pChannel == NULL)          if (m_pOptions && m_pOptions->bConfirmRemove) {
1422          return;                  if (QMessageBox::warning(this,
   
     // Prompt user if he/she's sure about this...  
     if (m_pOptions && m_pOptions->bConfirmRemove) {  
         if (QMessageBox::warning(this,  
1423                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
1424              tr("About to remove channel:\n\n"                          tr("About to remove channel:\n\n"
1425                 "%1\n\n"                          "%1\n\n"
1426                 "Are you sure?")                          "Are you sure?")
1427                 .arg(pChannelStrip->caption()),                          .arg(pChannelStrip->windowTitle()),
1428              tr("OK"), tr("Cancel")) > 0)                          tr("OK"), tr("Cancel")) > 0)
1429              return;                          return;
1430      }          }
1431    
1432      // Remove the existing sampler channel.          // Remove the existing sampler channel.
1433      if (!pChannel->removeChannel())          if (!pChannel->removeChannel())
1434          return;                  return;
1435    
1436      // Just delete the channel strip.          // Just delete the channel strip.
1437      delete pChannelStrip;          delete pChannelStrip;
1438    
1439      // Do we auto-arrange?          // Do we auto-arrange?
1440      if (m_pOptions && m_pOptions->bAutoArrange)          if (m_pOptions && m_pOptions->bAutoArrange)
1441          channelsArrange();                  channelsArrange();
1442    
1443      // We'll be dirty, for sure...          // We'll be dirty, for sure...
1444      m_iDirtyCount++;          m_iDirtyCount++;
1445      stabilizeForm();          stabilizeForm();
1446  }  }
1447    
1448    
1449  // Setup current sampler channel.  // Setup current sampler channel.
1450  void MainForm::editSetupChannel (void)  void MainForm::editSetupChannel (void)
1451  {  {
1452      if (m_pClient == NULL)          if (m_pClient == NULL)
1453          return;                  return;
1454    
1455      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1456      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1457          return;                  return;
1458    
1459      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1460      pChannelStrip->channelSetup();          pChannelStrip->channelSetup();
1461  }  }
1462    
1463    
1464  // Edit current sampler channel.  // Edit current sampler channel.
1465  void MainForm::editEditChannel (void)  void MainForm::editEditChannel (void)
1466  {  {
1467      if (m_pClient == NULL)          if (m_pClient == NULL)
1468          return;                  return;
1469    
1470      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1471      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1472          return;                  return;
1473    
1474      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1475      pChannelStrip->channelEdit();          pChannelStrip->channelEdit();
1476  }  }
1477    
1478    
1479  // Reset current sampler channel.  // Reset current sampler channel.
1480  void MainForm::editResetChannel (void)  void MainForm::editResetChannel (void)
1481  {  {
1482      if (m_pClient == NULL)          if (m_pClient == NULL)
1483          return;                  return;
1484    
1485      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1486      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1487          return;                  return;
1488    
1489      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1490      pChannelStrip->channelReset();          pChannelStrip->channelReset();
1491  }  }
1492    
1493    
# Line 1425  void MainForm::editResetAllChannels (voi Line 1516  void MainForm::editResetAllChannels (voi
1516  // Show/hide the main program window menubar.  // Show/hide the main program window menubar.
1517  void MainForm::viewMenubar ( bool bOn )  void MainForm::viewMenubar ( bool bOn )
1518  {  {
1519      if (bOn)          if (bOn)
1520          ui.MenuBar->show();                  m_ui.MenuBar->show();
1521      else          else
1522          ui.MenuBar->hide();                  m_ui.MenuBar->hide();
1523  }  }
1524    
1525    
1526  // Show/hide the main program window toolbar.  // Show/hide the main program window toolbar.
1527  void MainForm::viewToolbar ( bool bOn )  void MainForm::viewToolbar ( bool bOn )
1528  {  {
1529      if (bOn) {          if (bOn) {
1530          ui.fileToolbar->show();                  m_ui.fileToolbar->show();
1531          ui.editToolbar->show();                  m_ui.editToolbar->show();
1532          ui.channelsToolbar->show();                  m_ui.channelsToolbar->show();
1533      } else {          } else {
1534          ui.fileToolbar->hide();                  m_ui.fileToolbar->hide();
1535          ui.editToolbar->hide();                  m_ui.editToolbar->hide();
1536          ui.channelsToolbar->hide();                  m_ui.channelsToolbar->hide();
1537      }          }
1538  }  }
1539    
1540    
1541  // Show/hide the main program window statusbar.  // Show/hide the main program window statusbar.
1542  void MainForm::viewStatusbar ( bool bOn )  void MainForm::viewStatusbar ( bool bOn )
1543  {  {
1544      if (bOn)          if (bOn)
1545          statusBar()->show();                  statusBar()->show();
1546      else          else
1547          statusBar()->hide();                  statusBar()->hide();
1548  }  }
1549    
1550    
1551  // Show/hide the messages window logger.  // Show/hide the messages window logger.
1552  void MainForm::viewMessages ( bool bOn )  void MainForm::viewMessages ( bool bOn )
1553  {  {
1554      if (bOn)          if (bOn)
1555          m_pMessages->show();                  m_pMessages->show();
1556      else          else
1557          m_pMessages->hide();                  m_pMessages->hide();
1558  }  }
1559    
1560    
# Line 1480  void MainForm::viewInstruments (void) Line 1571  void MainForm::viewInstruments (void)
1571                  } else {                  } else {
1572                          m_pInstrumentListForm->show();                          m_pInstrumentListForm->show();
1573                          m_pInstrumentListForm->raise();                          m_pInstrumentListForm->raise();
1574                          m_pInstrumentListForm->setActiveWindow();                          m_pInstrumentListForm->activateWindow();
1575                  }                  }
1576          }          }
1577  }  }
# Line 1499  void MainForm::viewDevices (void) Line 1590  void MainForm::viewDevices (void)
1590                  } else {                  } else {
1591                          m_pDeviceForm->show();                          m_pDeviceForm->show();
1592                          m_pDeviceForm->raise();                          m_pDeviceForm->raise();
1593                          m_pDeviceForm->setActiveWindow();                          m_pDeviceForm->activateWindow();
1594                  }                  }
1595          }          }
1596  }  }
# Line 1508  void MainForm::viewDevices (void) Line 1599  void MainForm::viewDevices (void)
1599  // Show options dialog.  // Show options dialog.
1600  void MainForm::viewOptions (void)  void MainForm::viewOptions (void)
1601  {  {
1602      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1603          return;                  return;
1604    
1605      OptionsForm* pOptionsForm = new OptionsForm(this);          OptionsForm* pOptionsForm = new OptionsForm(this);
1606      if (pOptionsForm) {          if (pOptionsForm) {
1607          // Check out some initial nullities(tm)...                  // Check out some initial nullities(tm)...
1608          ChannelStrip* pChannelStrip = activeChannelStrip();                  ChannelStrip* pChannelStrip = activeChannelStrip();
1609          if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)
1610              m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();
1611          if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)
1612              m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
1613          // To track down deferred or immediate changes.                  // To track down deferred or immediate changes.
1614          QString sOldServerHost      = m_pOptions->sServerHost;                  QString sOldServerHost      = m_pOptions->sServerHost;
1615          int     iOldServerPort      = m_pOptions->iServerPort;                  int     iOldServerPort      = m_pOptions->iServerPort;
1616          int     iOldServerTimeout   = m_pOptions->iServerTimeout;                  int     iOldServerTimeout   = m_pOptions->iServerTimeout;
1617          bool    bOldServerStart     = m_pOptions->bServerStart;                  bool    bOldServerStart     = m_pOptions->bServerStart;
1618          QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;                  QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;
1619          QString sOldDisplayFont     = m_pOptions->sDisplayFont;                  QString sOldDisplayFont     = m_pOptions->sDisplayFont;
1620          bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;                  bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;
1621          int     iOldMaxVolume       = m_pOptions->iMaxVolume;                  int     iOldMaxVolume       = m_pOptions->iMaxVolume;
1622          QString sOldMessagesFont    = m_pOptions->sMessagesFont;                  QString sOldMessagesFont    = m_pOptions->sMessagesFont;
1623          bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;                  bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;
1624          bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;                  bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;
1625          int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;                  int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;
1626          int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;                  int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;
1627          bool    bOldCompletePath    = m_pOptions->bCompletePath;                  bool    bOldCompletePath    = m_pOptions->bCompletePath;
1628          bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;                  bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;
1629          int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;                  int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;
1630          // Load the current setup settings.                  // Load the current setup settings.
1631          pOptionsForm->setup(m_pOptions);                  pOptionsForm->setup(m_pOptions);
1632          // Show the setup dialog...                  // Show the setup dialog...
1633          if (pOptionsForm->exec()) {                  if (pOptionsForm->exec()) {
1634              // Warn if something will be only effective on next run.                          // Warn if something will be only effective on next run.
1635              if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1636                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||
1637                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||                                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||
1638                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {                                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {
1639                  QMessageBox::information(this,                                  QMessageBox::information(this,
1640                                          QSAMPLER_TITLE ": " + tr("Information"),                                          QSAMPLER_TITLE ": " + tr("Information"),
1641                      tr("Some settings may be only effective\n"                                          tr("Some settings may be only effective\n"
1642                         "next time you start this program."), tr("OK"));                                          "next time you start this program."), tr("OK"));
1643                  updateMessagesCapture();                                  updateMessagesCapture();
1644              }                          }
1645              // Check wheather something immediate has changed.                          // Check wheather something immediate has changed.
1646              if (( bOldCompletePath && !m_pOptions->bCompletePath) ||                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||
1647                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||
1648                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
1649                  updateRecentFilesMenu();                                  updateRecentFilesMenu();
1650              if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||                          if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||
1651                  (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))                                  (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))
1652                  updateInstrumentNames();                                  updateInstrumentNames();
1653              if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||                          if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||
1654                  (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))                                  (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))
1655                  updateDisplayEffect();                                  updateDisplayEffect();
1656              if (sOldDisplayFont != m_pOptions->sDisplayFont)                          if (sOldDisplayFont != m_pOptions->sDisplayFont)
1657                  updateDisplayFont();                                  updateDisplayFont();
1658              if (iOldMaxVolume != m_pOptions->iMaxVolume)                          if (iOldMaxVolume != m_pOptions->iMaxVolume)
1659                  updateMaxVolume();                                  updateMaxVolume();
1660              if (sOldMessagesFont != m_pOptions->sMessagesFont)                          if (sOldMessagesFont != m_pOptions->sMessagesFont)
1661                  updateMessagesFont();                                  updateMessagesFont();
1662              if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||                          if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||
1663                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||                                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||
1664                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))                                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))
1665                  updateMessagesLimit();                                  updateMessagesLimit();
1666              // And now the main thing, whether we'll do client/server recycling?                          // And now the main thing, whether we'll do client/server recycling?
1667              if ((sOldServerHost != m_pOptions->sServerHost) ||                          if ((sOldServerHost != m_pOptions->sServerHost) ||
1668                  (iOldServerPort != m_pOptions->iServerPort) ||                                  (iOldServerPort != m_pOptions->iServerPort) ||
1669                  (iOldServerTimeout != m_pOptions->iServerTimeout) ||                                  (iOldServerTimeout != m_pOptions->iServerTimeout) ||
1670                  ( bOldServerStart && !m_pOptions->bServerStart) ||                                  ( bOldServerStart && !m_pOptions->bServerStart) ||
1671                  (!bOldServerStart &&  m_pOptions->bServerStart) ||                                  (!bOldServerStart &&  m_pOptions->bServerStart) ||
1672                  (sOldServerCmdLine != m_pOptions->sServerCmdLine && m_pOptions->bServerStart))                                  (sOldServerCmdLine != m_pOptions->sServerCmdLine
1673                  fileRestart();                                  && m_pOptions->bServerStart))
1674          }                                  fileRestart();
1675          // Done.                  }
1676          delete pOptionsForm;                  // Done.
1677      }                  delete pOptionsForm;
1678            }
1679    
1680      // This makes it.          // This makes it.
1681      stabilizeForm();          stabilizeForm();
1682  }  }
1683    
1684    
# Line 1596  void MainForm::viewOptions (void) Line 1688  void MainForm::viewOptions (void)
1688  // Arrange channel strips.  // Arrange channel strips.
1689  void MainForm::channelsArrange (void)  void MainForm::channelsArrange (void)
1690  {  {
1691      // Full width vertical tiling          // Full width vertical tiling
1692      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
1693      if (wlist.isEmpty())          if (wlist.isEmpty())
1694          return;                  return;
1695    
1696      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
1697      int y = 0;          int y = 0;
1698      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1699          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
1700      /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {          /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {
1701              // Prevent flicker...                          // Prevent flicker...
1702              pChannelStrip->hide();                          pChannelStrip->hide();
1703              pChannelStrip->showNormal();                          pChannelStrip->showNormal();
1704          }   */                  }   */
1705          pChannelStrip->adjustSize();                  pChannelStrip->adjustSize();
1706          int iWidth  = m_pWorkspace->width();                  int iWidth  = m_pWorkspace->width();
1707          if (iWidth < pChannelStrip->width())                  if (iWidth < pChannelStrip->width())
1708              iWidth = pChannelStrip->width();                          iWidth = pChannelStrip->width();
1709      //  int iHeight = pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();          //  int iHeight = pChannelStrip->height()
1710          int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();          //              + pChannelStrip->parentWidget()->baseSize().height();
1711          pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);                  int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();
1712          y += iHeight;                  pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);
1713      }                  y += iHeight;
1714      m_pWorkspace->setUpdatesEnabled(true);          }
1715            m_pWorkspace->setUpdatesEnabled(true);
1716    
1717      stabilizeForm();          stabilizeForm();
1718  }  }
1719    
1720    
1721  // Auto-arrange channel strips.  // Auto-arrange channel strips.
1722  void MainForm::channelsAutoArrange ( bool bOn )  void MainForm::channelsAutoArrange ( bool bOn )
1723  {  {
1724      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1725          return;                  return;
1726    
1727      // Toggle the auto-arrange flag.          // Toggle the auto-arrange flag.
1728      m_pOptions->bAutoArrange = bOn;          m_pOptions->bAutoArrange = bOn;
1729    
1730      // If on, update whole workspace...          // If on, update whole workspace...
1731      if (m_pOptions->bAutoArrange)          if (m_pOptions->bAutoArrange)
1732          channelsArrange();                  channelsArrange();
1733  }  }
1734    
1735    
# Line 1646  void MainForm::channelsAutoArrange ( boo Line 1739  void MainForm::channelsAutoArrange ( boo
1739  // Show information about the Qt toolkit.  // Show information about the Qt toolkit.
1740  void MainForm::helpAboutQt (void)  void MainForm::helpAboutQt (void)
1741  {  {
1742      QMessageBox::aboutQt(this);          QMessageBox::aboutQt(this);
1743  }  }
1744    
1745    
1746  // Show information about application program.  // Show information about application program.
1747  void MainForm::helpAbout (void)  void MainForm::helpAbout (void)
1748  {  {
1749      // Stuff the about box text...          // Stuff the about box text...
1750      QString sText = "<p>\n";          QString sText = "<p>\n";
1751      sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";          sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";
1752      sText += "<br />\n";          sText += "<br />\n";
1753      sText += tr("Version") + ": <b>" QSAMPLER_VERSION "</b><br />\n";          sText += tr("Version") + ": <b>" QSAMPLER_VERSION "</b><br />\n";
1754      sText += "<small>" + tr("Build") + ": " __DATE__ " " __TIME__ "</small><br />\n";          sText += "<small>" + tr("Build") + ": " __DATE__ " " __TIME__ "</small><br />\n";
1755  #ifdef CONFIG_DEBUG  #ifdef CONFIG_DEBUG
1756      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1757      sText += tr("Debugging option enabled.");          sText += tr("Debugging option enabled.");
1758      sText += "</font></small><br />";          sText += "</font></small><br />";
1759  #endif  #endif
1760  #ifndef CONFIG_LIBGIG  #ifndef CONFIG_LIBGIG
1761      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1762      sText += tr("GIG (libgig) file support disabled.");          sText += tr("GIG (libgig) file support disabled.");
1763      sText += "</font></small><br />";          sText += "</font></small><br />";
1764  #endif  #endif
1765  #ifndef CONFIG_INSTRUMENT_NAME  #ifndef CONFIG_INSTRUMENT_NAME
1766      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1767      sText += tr("LSCP (liblscp) instrument_name support disabled.");          sText += tr("LSCP (liblscp) instrument_name support disabled.");
1768      sText += "</font></small><br />";          sText += "</font></small><br />";
1769  #endif  #endif
1770  #ifndef CONFIG_MUTE_SOLO  #ifndef CONFIG_MUTE_SOLO
1771      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1772      sText += tr("Sampler channel Mute/Solo support disabled.");          sText += tr("Sampler channel Mute/Solo support disabled.");
1773      sText += "</font></small><br />";          sText += "</font></small><br />";
1774  #endif  #endif
1775  #ifndef CONFIG_AUDIO_ROUTING  #ifndef CONFIG_AUDIO_ROUTING
1776      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1777      sText += tr("LSCP (liblscp) audio_routing support disabled.");          sText += tr("LSCP (liblscp) audio_routing support disabled.");
1778      sText += "</font></small><br />";          sText += "</font></small><br />";
1779  #endif  #endif
1780  #ifndef CONFIG_FXSEND  #ifndef CONFIG_FXSEND
1781      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1782      sText += tr("Sampler channel Effect Sends support disabled.");          sText += tr("Sampler channel Effect Sends support disabled.");
1783      sText += "</font></small><br />";          sText += "</font></small><br />";
1784  #endif  #endif
1785  #ifndef CONFIG_VOLUME  #ifndef CONFIG_VOLUME
1786      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1787      sText += tr("Global volume support disabled.");          sText += tr("Global volume support disabled.");
1788      sText += "</font></small><br />";          sText += "</font></small><br />";
1789  #endif  #endif
1790  #ifndef CONFIG_MIDI_INSTRUMENT  #ifndef CONFIG_MIDI_INSTRUMENT
1791      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1792      sText += tr("MIDI instrument mapping support disabled.");          sText += tr("MIDI instrument mapping support disabled.");
1793      sText += "</font></small><br />";          sText += "</font></small><br />";
1794  #endif  #endif
1795  #ifndef CONFIG_EDIT_INSTRUMENT  #ifndef CONFIG_EDIT_INSTRUMENT
1796      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1797      sText += tr("Instrument editing support disabled.");          sText += tr("Instrument editing support disabled.");
1798      sText += "</font></small><br />";          sText += "</font></small><br />";
1799  #endif  #endif
1800      sText += "<br />\n";          sText += "<br />\n";
1801      sText += tr("Using") + ": ";          sText += tr("Using") + ": ";
1802      sText += ::lscp_client_package();          sText += ::lscp_client_package();
1803      sText += " ";          sText += " ";
1804      sText += ::lscp_client_version();          sText += ::lscp_client_version();
1805  #ifdef CONFIG_LIBGIG  #ifdef CONFIG_LIBGIG
1806      sText += ", ";          sText += ", ";
1807      sText += gig::libraryName().c_str();          sText += gig::libraryName().c_str();
1808      sText += " ";          sText += " ";
1809      sText += gig::libraryVersion().c_str();          sText += gig::libraryVersion().c_str();
1810  #endif  #endif
1811      sText += "<br />\n";          sText += "<br />\n";
1812      sText += "<br />\n";          sText += "<br />\n";
1813      sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";          sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";
1814      sText += "<br />\n";          sText += "<br />\n";
1815      sText += "<small>";          sText += "<small>";
1816      sText += QSAMPLER_COPYRIGHT "<br />\n";          sText += QSAMPLER_COPYRIGHT "<br />\n";
1817      sText += QSAMPLER_COPYRIGHT2 "<br />\n";          sText += QSAMPLER_COPYRIGHT2 "<br />\n";
1818      sText += "<br />\n";          sText += "<br />\n";
1819      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";
1820      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.");
1821      sText += "</small>";          sText += "</small>";
1822      sText += "</p>\n";          sText += "</p>\n";
1823    
1824      QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);          QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);
1825  }  }
1826    
1827    
# Line 1737  void MainForm::helpAbout (void) Line 1830  void MainForm::helpAbout (void)
1830    
1831  void MainForm::stabilizeForm (void)  void MainForm::stabilizeForm (void)
1832  {  {
1833      // Update the main application caption...          // Update the main application caption...
1834      QString sSessionName = sessionName(m_sFilename);          QString sSessionName = sessionName(m_sFilename);
1835      if (m_iDirtyCount > 0)          if (m_iDirtyCount > 0)
1836          sSessionName += " *";                  sSessionName += " *";
1837      setCaption(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));
1838    
1839      // Update the main menu state...          // Update the main menu state...
1840      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1841      bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);          bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);
1842      bool bHasChannel = (bHasClient && pChannelStrip != NULL);          bool bHasChannel = (bHasClient && pChannelStrip != NULL);
1843      ui.fileNewAction->setEnabled(bHasClient);          m_ui.fileNewAction->setEnabled(bHasClient);
1844      ui.fileOpenAction->setEnabled(bHasClient);          m_ui.fileOpenAction->setEnabled(bHasClient);
1845      ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
1846      ui.fileSaveAsAction->setEnabled(bHasClient);          m_ui.fileSaveAsAction->setEnabled(bHasClient);
1847      ui.fileResetAction->setEnabled(bHasClient);          m_ui.fileResetAction->setEnabled(bHasClient);
1848      ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);          m_ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);
1849      ui.editAddChannelAction->setEnabled(bHasClient);          m_ui.editAddChannelAction->setEnabled(bHasClient);
1850      ui.editRemoveChannelAction->setEnabled(bHasChannel);          m_ui.editRemoveChannelAction->setEnabled(bHasChannel);
1851      ui.editSetupChannelAction->setEnabled(bHasChannel);          m_ui.editSetupChannelAction->setEnabled(bHasChannel);
1852  #ifdef CONFIG_EDIT_INSTRUMENT  #ifdef CONFIG_EDIT_INSTRUMENT
1853      ui.editEditChannelAction->setEnabled(bHasChannel);          m_ui.editEditChannelAction->setEnabled(bHasChannel);
1854  #else  #else
1855      ui.editEditChannelAction->setEnabled(false);          m_ui.editEditChannelAction->setEnabled(false);
1856  #endif  #endif
1857      ui.editResetChannelAction->setEnabled(bHasChannel);          m_ui.editResetChannelAction->setEnabled(bHasChannel);
1858      ui.editResetAllChannelsAction->setEnabled(bHasChannel);          m_ui.editResetAllChannelsAction->setEnabled(bHasChannel);
1859      ui.viewMessagesAction->setOn(m_pMessages && m_pMessages->isVisible());          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());
1860  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
1861          ui.viewInstrumentsAction->setOn(m_pInstrumentListForm          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm
1862                  && m_pInstrumentListForm->isVisible());                  && m_pInstrumentListForm->isVisible());
1863          ui.viewInstrumentsAction->setEnabled(bHasClient);          m_ui.viewInstrumentsAction->setEnabled(bHasClient);
1864  #else  #else
1865          ui.viewInstrumentsAction->setEnabled(false);          m_ui.viewInstrumentsAction->setEnabled(false);
1866  #endif  #endif
1867          ui.viewDevicesAction->setOn(m_pDeviceForm          m_ui.viewDevicesAction->setChecked(m_pDeviceForm
1868                  && m_pDeviceForm->isVisible());                  && m_pDeviceForm->isVisible());
1869      ui.viewDevicesAction->setEnabled(bHasClient);          m_ui.viewDevicesAction->setEnabled(bHasClient);
1870      ui.channelsArrangeAction->setEnabled(bHasChannel);          m_ui.channelsArrangeAction->setEnabled(bHasChannel);
1871    
1872  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
1873          // Toolbar widgets are also affected...          // Toolbar widgets are also affected...
1874      m_pVolumeSlider->setEnabled(bHasClient);          m_pVolumeSlider->setEnabled(bHasClient);
1875      m_pVolumeSpinBox->setEnabled(bHasClient);          m_pVolumeSpinBox->setEnabled(bHasClient);
1876  #endif  #endif
1877    
1878      // Client/Server status...          // Client/Server status...
1879      if (bHasClient) {          if (bHasClient) {
1880          m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));                  m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));
1881          m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost + ":" + QString::number(m_pOptions->iServerPort));                  m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost
1882      } else {                          + ':' + QString::number(m_pOptions->iServerPort));
1883          m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();          } else {
1884          m_statusItem[QSAMPLER_STATUS_SERVER]->clear();                  m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();
1885      }                  m_statusItem[QSAMPLER_STATUS_SERVER]->clear();
1886      // Channel status...          }
1887      if (bHasChannel)          // Channel status...
1888          m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->caption());          if (bHasChannel)
1889      else                  m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->windowTitle());
1890          m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();          else
1891      // Session status...                  m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();
1892      if (m_iDirtyCount > 0)          // Session status...
1893          m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));          if (m_iDirtyCount > 0)
1894      else                  m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));
1895          m_statusItem[QSAMPLER_STATUS_SESSION]->clear();          else
1896                    m_statusItem[QSAMPLER_STATUS_SESSION]->clear();
1897    
1898      // Recent files menu.          // Recent files menu.
1899      m_pRecentFilesMenu->setEnabled(bHasClient && m_pOptions->recentFiles.count() > 0);          m_ui.fileOpenRecentMenu->setEnabled(m_pOptions->recentFiles.count() > 0);
1900  }  }
1901    
1902    
# Line 1842  void MainForm::volumeChanged ( int iVolu Line 1936  void MainForm::volumeChanged ( int iVolu
1936  void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)  void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)
1937  {  {
1938          // Add this strip to the changed list...          // Add this strip to the changed list...
1939          if (m_changedStrips.containsRef(pChannelStrip) == 0) {          if (!m_changedStrips.contains(pChannelStrip)) {
1940                  m_changedStrips.append(pChannelStrip);                  m_changedStrips.append(pChannelStrip);
1941                  pChannelStrip->resetErrorCount();                  pChannelStrip->resetErrorCount();
1942          }          }
1943    
1944      // Just mark the dirty form.          // Just mark the dirty form.
1945      m_iDirtyCount++;          m_iDirtyCount++;
1946      // and update the form status...          // and update the form status...
1947      stabilizeForm();          stabilizeForm();
1948  }  }
1949    
1950    
# Line 1870  void MainForm::updateSession (void) Line 1964  void MainForm::updateSession (void)
1964          if (iMaps < 0)          if (iMaps < 0)
1965                  appendMessagesClient("lscp_get_midi_instrument_maps");                  appendMessagesClient("lscp_get_midi_instrument_maps");
1966          else if (iMaps < 1) {          else if (iMaps < 1) {
1967                  ::lscp_add_midi_instrument_map(m_pClient, tr("Chromatic").latin1());                  ::lscp_add_midi_instrument_map(m_pClient,
1968                  ::lscp_add_midi_instrument_map(m_pClient, tr("Drum Kits").latin1());                          tr("Chromatic").toUtf8().constData());
1969                    ::lscp_add_midi_instrument_map(m_pClient,
1970                            tr("Drum Kits").toUtf8().constData());
1971          }          }
1972  #endif  #endif
1973    
1974            updateAllChannelStrips(false);
1975    
1976            // Do we auto-arrange?
1977            if (m_pOptions && m_pOptions->bAutoArrange)
1978                    channelsArrange();
1979    
1980            // Remember to refresh devices and instruments...
1981            if (m_pInstrumentListForm)
1982                    m_pInstrumentListForm->refreshInstruments();
1983            if (m_pDeviceForm)
1984                    m_pDeviceForm->refreshDevices();
1985    }
1986    
1987    void MainForm::updateAllChannelStrips(bool bRemoveDeadStrips) {
1988          // Retrieve the current channel list.          // Retrieve the current channel list.
1989          int *piChannelIDs = ::lscp_list_channels(m_pClient);          int *piChannelIDs = ::lscp_list_channels(m_pClient);
1990          if (piChannelIDs == NULL) {          if (piChannelIDs == NULL) {
1991                  if (::lscp_client_get_errno(m_pClient)) {                  if (::lscp_client_get_errno(m_pClient)) {
1992                          appendMessagesClient("lscp_list_channels");                          appendMessagesClient("lscp_list_channels");
1993                          appendMessagesError(tr("Could not get current list of channels.\n\nSorry."));                          appendMessagesError(
1994                                    tr("Could not get current list of channels.\n\nSorry."));
1995                  }                  }
1996          } else {          } else {
1997                  // Try to (re)create each channel.                  // Try to (re)create each channel.
# Line 1888  void MainForm::updateSession (void) Line 1999  void MainForm::updateSession (void)
1999                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {
2000                          // Check if theres already a channel strip for this one...                          // Check if theres already a channel strip for this one...
2001                          if (!channelStrip(piChannelIDs[iChannel]))                          if (!channelStrip(piChannelIDs[iChannel]))
2002                                  createChannelStrip(new qsamplerChannel(piChannelIDs[iChannel]));                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));
2003                    }
2004    
2005                    // Do we auto-arrange?
2006                    if (m_pOptions && m_pOptions->bAutoArrange)
2007                            channelsArrange();
2008    
2009                    stabilizeForm();
2010    
2011                    // remove dead channel strips
2012                    if (bRemoveDeadStrips) {
2013                            for (int i = 0; channelStripAt(i); ++i) {
2014                                    ChannelStrip* pChannelStrip = channelStripAt(i);
2015                                    bool bExists = false;
2016                                    for (int j = 0; piChannelIDs[j] >= 0; ++j) {
2017                                            if (!pChannelStrip->channel()) break;
2018                                            if (piChannelIDs[j] == pChannelStrip->channel()->channelID()) {
2019                                                    // strip exists, don't touch it
2020                                                    bExists = true;
2021                                                    break;
2022                                            }
2023                                    }
2024                                    if (!bExists) destroyChannelStrip(pChannelStrip);
2025                            }
2026                  }                  }
2027                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
2028          }          }
   
     // 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();  
2029  }  }
2030    
   
2031  // Update the recent files list and menu.  // Update the recent files list and menu.
2032  void MainForm::updateRecentFiles ( const QString& sFilename )  void MainForm::updateRecentFiles ( const QString& sFilename )
2033  {  {
2034      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2035          return;                  return;
   
     // Remove from list if already there (avoid duplicates)  
     QStringList::Iterator iter = m_pOptions->recentFiles.find(sFilename);  
     if (iter != m_pOptions->recentFiles.end())  
         m_pOptions->recentFiles.remove(iter);  
     // Put it to front...  
     m_pOptions->recentFiles.push_front(sFilename);  
2036    
2037      // May update the menu.          // Remove from list if already there (avoid duplicates)
2038      updateRecentFilesMenu();          int iIndex = m_pOptions->recentFiles.indexOf(sFilename);
2039            if (iIndex >= 0)
2040                    m_pOptions->recentFiles.removeAt(iIndex);
2041            // Put it to front...
2042            m_pOptions->recentFiles.push_front(sFilename);
2043  }  }
2044    
2045    
2046  // Update the recent files list and menu.  // Update the recent files list and menu.
2047  void MainForm::updateRecentFilesMenu (void)  void MainForm::updateRecentFilesMenu (void)
2048  {  {
2049      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2050          return;                  return;
2051    
2052            // Time to keep the list under limits.
2053            int iRecentFiles = m_pOptions->recentFiles.count();
2054            while (iRecentFiles > m_pOptions->iMaxRecentFiles) {
2055                    m_pOptions->recentFiles.pop_back();
2056                    iRecentFiles--;
2057            }
2058    
2059      // Time to keep the list under limits.          // Rebuild the recent files menu...
2060      int iRecentFiles = m_pOptions->recentFiles.count();          m_ui.fileOpenRecentMenu->clear();
2061      while (iRecentFiles > m_pOptions->iMaxRecentFiles) {          for (int i = 0; i < iRecentFiles; i++) {
2062          m_pOptions->recentFiles.pop_back();                  const QString& sFilename = m_pOptions->recentFiles[i];
2063          iRecentFiles--;                  if (QFileInfo(sFilename).exists()) {
2064      }                          QAction *pAction = m_ui.fileOpenRecentMenu->addAction(
2065                                    QString("&%1 %2").arg(i + 1).arg(sessionName(sFilename)),
2066      // rebuild the recent files menu...                                  this, SLOT(fileOpenRecent()));
2067      m_pRecentFilesMenu->clear();                          pAction->setData(i);
2068      for (int i = 0; i < iRecentFiles; i++) {                  }
2069          const QString& sFilename = m_pOptions->recentFiles[i];          }
         if (QFileInfo(sFilename).exists()) {  
             m_pRecentFilesMenu->insertItem(QString("&%1 %2")  
                 .arg(i + 1).arg(sessionName(sFilename)),  
                 this, SLOT(fileOpenRecent(int)), 0, i);  
         }  
     }  
2070  }  }
2071    
2072    
2073  // Force update of the channels instrument names mode.  // Force update of the channels instrument names mode.
2074  void MainForm::updateInstrumentNames (void)  void MainForm::updateInstrumentNames (void)
2075  {  {
2076      // Full channel list update...          // Full channel list update...
2077      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2078      if (wlist.isEmpty())          if (wlist.isEmpty())
2079          return;                  return;
2080    
2081      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2082      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2083          ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);                  ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);
2084          if (pChannelStrip)                  if (pChannelStrip)
2085              pChannelStrip->updateInstrumentName(true);                          pChannelStrip->updateInstrumentName(true);
2086      }          }
2087      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2088  }  }
2089    
2090    
2091  // Force update of the channels display font.  // Force update of the channels display font.
2092  void MainForm::updateDisplayFont (void)  void MainForm::updateDisplayFont (void)
2093  {  {
2094      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2095          return;                  return;
2096    
2097            // Check if display font is legal.
2098            if (m_pOptions->sDisplayFont.isEmpty())
2099                    return;
2100            // Realize it.
2101            QFont font;
2102            if (!font.fromString(m_pOptions->sDisplayFont))
2103                    return;
2104    
2105            // Full channel list update...
2106            QWidgetList wlist = m_pWorkspace->windowList();
2107            if (wlist.isEmpty())
2108                    return;
2109    
2110      // Check if display font is legal.          m_pWorkspace->setUpdatesEnabled(false);
2111      if (m_pOptions->sDisplayFont.isEmpty())          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2112          return;                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2113      // Realize it.                  if (pChannelStrip)
2114      QFont font;                          pChannelStrip->setDisplayFont(font);
2115      if (!font.fromString(m_pOptions->sDisplayFont))          }
2116          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);  
2117  }  }
2118    
2119    
2120  // Update channel strips background effect.  // Update channel strips background effect.
2121  void MainForm::updateDisplayEffect (void)  void MainForm::updateDisplayEffect (void)
2122  {  {
2123     QPixmap pm;          // Full channel list update...
2124      if (m_pOptions->bDisplayEffect)          QWidgetList wlist = m_pWorkspace->windowList();
2125          pm = QPixmap(":/qsampler/pixmaps/displaybg1.png");          if (wlist.isEmpty())
2126                    return;
2127      // Full channel list update...  
2128      QWidgetList wlist = m_pWorkspace->windowList();          m_pWorkspace->setUpdatesEnabled(false);
2129      if (wlist.isEmpty())          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2130          return;                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2131                    if (pChannelStrip)
2132      m_pWorkspace->setUpdatesEnabled(false);                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2133      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          }
2134          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);          m_pWorkspace->setUpdatesEnabled(true);
         if (pChannelStrip)  
             pChannelStrip->setDisplayBackground(pm);  
     }  
     m_pWorkspace->setUpdatesEnabled(true);  
2135  }  }
2136    
2137    
2138  // Force update of the channels maximum volume setting.  // Force update of the channels maximum volume setting.
2139  void MainForm::updateMaxVolume (void)  void MainForm::updateMaxVolume (void)
2140  {  {
2141      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2142          return;                  return;
2143    
2144  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2145          m_iVolumeChanging++;          m_iVolumeChanging++;
2146          m_pVolumeSlider->setMaxValue(m_pOptions->iMaxVolume);          m_pVolumeSlider->setMaximum(m_pOptions->iMaxVolume);
2147          m_pVolumeSpinBox->setMaxValue(m_pOptions->iMaxVolume);          m_pVolumeSpinBox->setMaximum(m_pOptions->iMaxVolume);
2148          m_iVolumeChanging--;          m_iVolumeChanging--;
2149  #endif  #endif
2150    
2151      // Full channel list update...          // Full channel list update...
2152      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2153      if (wlist.isEmpty())          if (wlist.isEmpty())
2154          return;                  return;
2155    
2156      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2157      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2158          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2159          if (pChannelStrip)                  if (pChannelStrip)
2160              pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                          pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2161      }          }
2162      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2163  }  }
2164    
2165    
# Line 2052  void MainForm::updateMaxVolume (void) Line 2169  void MainForm::updateMaxVolume (void)
2169  // Messages output methods.  // Messages output methods.
2170  void MainForm::appendMessages( const QString& s )  void MainForm::appendMessages( const QString& s )
2171  {  {
2172      if (m_pMessages)          if (m_pMessages)
2173          m_pMessages->appendMessages(s);                  m_pMessages->appendMessages(s);
2174    
2175      statusBar()->message(s, 3000);          statusBar()->showMessage(s, 3000);
2176  }  }
2177    
2178  void MainForm::appendMessagesColor( const QString& s, const QString& c )  void MainForm::appendMessagesColor( const QString& s, const QString& c )
2179  {  {
2180      if (m_pMessages)          if (m_pMessages)
2181          m_pMessages->appendMessagesColor(s, c);                  m_pMessages->appendMessagesColor(s, c);
2182    
2183      statusBar()->message(s, 3000);          statusBar()->showMessage(s, 3000);
2184  }  }
2185    
2186  void MainForm::appendMessagesText( const QString& s )  void MainForm::appendMessagesText( const QString& s )
2187  {  {
2188      if (m_pMessages)          if (m_pMessages)
2189          m_pMessages->appendMessagesText(s);                  m_pMessages->appendMessagesText(s);
2190  }  }
2191    
2192  void MainForm::appendMessagesError( const QString& s )  void MainForm::appendMessagesError( const QString& s )
2193  {  {
2194      if (m_pMessages)          if (m_pMessages)
2195          m_pMessages->show();                  m_pMessages->show();
2196    
2197      appendMessagesColor(s.simplifyWhiteSpace(), "#ff0000");          appendMessagesColor(s.simplified(), "#ff0000");
2198    
2199          // Make it look responsive...:)          // Make it look responsive...:)
2200          QApplication::processEvents(QEventLoop::ExcludeUserInput);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2201    
2202      QMessageBox::critical(this,          QMessageBox::critical(this,
2203                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));
2204  }  }
2205    
# Line 2090  void MainForm::appendMessagesError( cons Line 2207  void MainForm::appendMessagesError( cons
2207  // This is a special message format, just for client results.  // This is a special message format, just for client results.
2208  void MainForm::appendMessagesClient( const QString& s )  void MainForm::appendMessagesClient( const QString& s )
2209  {  {
2210      if (m_pClient == NULL)          if (m_pClient == NULL)
2211          return;                  return;
2212    
2213      appendMessagesColor(s + QString(": %1 (errno=%2)")          appendMessagesColor(s + QString(": %1 (errno=%2)")
2214          .arg(::lscp_client_get_result(m_pClient))                  .arg(::lscp_client_get_result(m_pClient))
2215          .arg(::lscp_client_get_errno(m_pClient)), "#996666");                  .arg(::lscp_client_get_errno(m_pClient)), "#996666");
2216    
2217          // Make it look responsive...:)          // Make it look responsive...:)
2218          QApplication::processEvents(QEventLoop::ExcludeUserInput);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2219  }  }
2220    
2221    
2222  // Force update of the messages font.  // Force update of the messages font.
2223  void MainForm::updateMessagesFont (void)  void MainForm::updateMessagesFont (void)
2224  {  {
2225      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2226          return;                  return;
2227    
2228      if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {          if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {
2229          QFont font;                  QFont font;
2230          if (font.fromString(m_pOptions->sMessagesFont))                  if (font.fromString(m_pOptions->sMessagesFont))
2231              m_pMessages->setMessagesFont(font);                          m_pMessages->setMessagesFont(font);
2232      }          }
2233  }  }
2234    
2235    
2236  // Update messages window line limit.  // Update messages window line limit.
2237  void MainForm::updateMessagesLimit (void)  void MainForm::updateMessagesLimit (void)
2238  {  {
2239      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2240          return;                  return;
2241    
2242      if (m_pMessages) {          if (m_pMessages) {
2243          if (m_pOptions->bMessagesLimit)                  if (m_pOptions->bMessagesLimit)
2244              m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);                          m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);
2245          else                  else
2246              m_pMessages->setMessagesLimit(-1);                          m_pMessages->setMessagesLimit(-1);
2247      }          }
2248  }  }
2249    
2250    
2251  // Enablement of the messages capture feature.  // Enablement of the messages capture feature.
2252  void MainForm::updateMessagesCapture (void)  void MainForm::updateMessagesCapture (void)
2253  {  {
2254      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2255          return;                  return;
2256    
2257      if (m_pMessages)          if (m_pMessages)
2258          m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);                  m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);
2259  }  }
2260    
2261    
# Line 2146  void MainForm::updateMessagesCapture (vo Line 2263  void MainForm::updateMessagesCapture (vo
2263  // qsamplerMainForm -- MDI channel strip management.  // qsamplerMainForm -- MDI channel strip management.
2264    
2265  // The channel strip creation executive.  // The channel strip creation executive.
2266  ChannelStrip* MainForm::createChannelStrip(qsamplerChannel* pChannel)  ChannelStrip* MainForm::createChannelStrip ( Channel *pChannel )
2267  {  {
2268      if (m_pClient == NULL || pChannel == NULL)          if (m_pClient == NULL || pChannel == NULL)
2269          return NULL;                  return NULL;
2270    
2271      // Prepare for auto-arrange?          // Add a new channel itema...
2272      ChannelStrip* pChannelStrip = NULL;          ChannelStrip *pChannelStrip = new ChannelStrip();
2273      int y = 0;          if (pChannelStrip == NULL)
2274      if (m_pOptions && m_pOptions->bAutoArrange) {                  return NULL;
         QWidgetList wlist = m_pWorkspace->windowList();  
         for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {  
             pChannelStrip = (ChannelStrip *) wlist.at(iChannel);  
                         if (pChannelStrip) {  
                         //  y += pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();  
                                 y += pChannelStrip->parentWidget()->frameGeometry().height();  
                         }  
         }  
     }  
2275    
2276      // Add a new channel itema...          // Set some initial channel strip options...
2277      Qt::WFlags wflags = Qt::WStyle_Customize | Qt::WStyle_Tool | Qt::WStyle_Title | Qt::WStyle_NoBorder;          if (m_pOptions) {
2278      pChannelStrip = new ChannelStrip(m_pWorkspace, wflags);                  // Background display effect...
2279      if (pChannelStrip == NULL)                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2280          return NULL;                  // We'll need a display font.
2281                    QFont font;
2282                    if (font.fromString(m_pOptions->sDisplayFont))
2283                            pChannelStrip->setDisplayFont(font);
2284                    // Maximum allowed volume setting.
2285                    pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2286            }
2287    
2288            // Add it to workspace...
2289            m_pWorkspace->addWindow(pChannelStrip, Qt::FramelessWindowHint);
2290    
2291            // Actual channel strip setup...
2292            pChannelStrip->setup(pChannel);
2293    
     // Actual channel strip setup...  
     pChannelStrip->setup(pChannel);  
2294          QObject::connect(pChannelStrip,          QObject::connect(pChannelStrip,
2295                  SIGNAL(channelChanged(qsamplerChannelStrip *)),                  SIGNAL(channelChanged(ChannelStrip*)),
2296                  SLOT(channelStripChanged(qsamplerChannelStrip *)));                  SLOT(channelStripChanged(ChannelStrip*)));
2297      // Set some initial aesthetic options...  
2298      if (m_pOptions) {          // Now we show up us to the world.
2299          // 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);  
     }  
2300    
2301          // This is pretty new, so we'll watch for it closely.          // This is pretty new, so we'll watch for it closely.
2302          channelStripChanged(pChannelStrip);          channelStripChanged(pChannelStrip);
2303    
2304      // Return our successful reference...          // Return our successful reference...
2305      return pChannelStrip;          return pChannelStrip;
2306  }  }
2307    
2308    void MainForm::destroyChannelStrip(ChannelStrip* pChannelStrip) {
2309            // Just delete the channel strip.
2310            delete pChannelStrip;
2311    
2312            // Do we auto-arrange?
2313            if (m_pOptions && m_pOptions->bAutoArrange)
2314                    channelsArrange();
2315    
2316            stabilizeForm();
2317    }
2318    
2319  // Retrieve the active channel strip.  // Retrieve the active channel strip.
2320  ChannelStrip* MainForm::activeChannelStrip (void)  ChannelStrip* MainForm::activeChannelStrip (void)
2321  {  {
2322      return (ChannelStrip*) m_pWorkspace->activeWindow();          return static_cast<ChannelStrip *> (m_pWorkspace->activeWindow());
2323  }  }
2324    
2325    
2326  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
2327  ChannelStrip* MainForm::channelStripAt ( int iChannel )  ChannelStrip* MainForm::channelStripAt ( int iChannel )
2328  {  {
2329      QWidgetList wlist = m_pWorkspace->windowList();          if (!m_pWorkspace) return NULL;
2330      if (wlist.isEmpty())  
2331          return NULL;          QWidgetList wlist = m_pWorkspace->windowList();
2332            if (wlist.isEmpty())
2333                    return NULL;
2334    
2335      return (ChannelStrip*) wlist.at(iChannel);          if (iChannel < 0 || iChannel >= wlist.size())
2336                    return NULL;
2337    
2338            return dynamic_cast<ChannelStrip *> (wlist.at(iChannel));
2339  }  }
2340    
2341    
# Line 2231  ChannelStrip* MainForm::channelStrip ( i Line 2347  ChannelStrip* MainForm::channelStrip ( i
2347                  return NULL;                  return NULL;
2348    
2349          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2350                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip
2351                            = static_cast<ChannelStrip*> (wlist.at(iChannel));
2352                  if (pChannelStrip) {                  if (pChannelStrip) {
2353                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
2354                          if (pChannel && pChannel->channelID() == iChannelID)                          if (pChannel && pChannel->channelID() == iChannelID)
2355                                  return pChannelStrip;                                  return pChannelStrip;
2356                  }                  }
# Line 2247  ChannelStrip* MainForm::channelStrip ( i Line 2364  ChannelStrip* MainForm::channelStrip ( i
2364  // Construct the windows menu.  // Construct the windows menu.
2365  void MainForm::channelsMenuAboutToShow (void)  void MainForm::channelsMenuAboutToShow (void)
2366  {  {
2367      ui.channelsMenu->clear();          m_ui.channelsMenu->clear();
2368      ui.channelsArrangeAction->addTo(ui.channelsMenu);          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);
2369      ui.channelsAutoArrangeAction->addTo(ui.channelsMenu);          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);
2370    
2371      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2372      if (!wlist.isEmpty()) {          if (!wlist.isEmpty()) {
2373          ui.channelsMenu->insertSeparator();                  m_ui.channelsMenu->addSeparator();
2374          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2375              ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                          ChannelStrip* pChannelStrip
2376              if (pChannelStrip) {                                  = static_cast<ChannelStrip*> (wlist.at(iChannel));
2377                  int iItemID = ui.channelsMenu->insertItem(pChannelStrip->caption(), this, SLOT(channelsMenuActivated(int)));                          if (pChannelStrip) {
2378                  ui.channelsMenu->setItemParameter(iItemID, iChannel);                                  QAction *pAction = m_ui.channelsMenu->addAction(
2379                  ui.channelsMenu->setItemChecked(iItemID, activeChannelStrip() == pChannelStrip);                                          pChannelStrip->windowTitle(),
2380              }                                          this, SLOT(channelsMenuActivated()));
2381          }                                  pAction->setCheckable(true);
2382      }                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);
2383                                    pAction->setData(iChannel);
2384                            }
2385                    }
2386            }
2387  }  }
2388    
2389    
2390  // Windows menu activation slot  // Windows menu activation slot
2391  void MainForm::channelsMenuActivated ( int iChannel )  void MainForm::channelsMenuActivated (void)
2392  {  {
2393      ChannelStrip* pChannelStrip = channelStripAt(iChannel);          // Retrive channel index from action data...
2394      if (pChannelStrip)          QAction *pAction = qobject_cast<QAction *> (sender());
2395          pChannelStrip->showNormal();          if (pAction == NULL)
2396      pChannelStrip->setFocus();                  return;
2397    
2398            ChannelStrip* pChannelStrip = channelStripAt(pAction->data().toInt());
2399            if (pChannelStrip) {
2400                    pChannelStrip->showNormal();
2401                    pChannelStrip->setFocus();
2402            }
2403  }  }
2404    
2405    
# Line 2282  void MainForm::channelsMenuActivated ( i Line 2409  void MainForm::channelsMenuActivated ( i
2409  // Set the pseudo-timer delay schedule.  // Set the pseudo-timer delay schedule.
2410  void MainForm::startSchedule ( int iStartDelay )  void MainForm::startSchedule ( int iStartDelay )
2411  {  {
2412      m_iStartDelay  = 1 + (iStartDelay * 1000);          m_iStartDelay  = 1 + (iStartDelay * 1000);
2413      m_iTimerDelay  = 0;          m_iTimerDelay  = 0;
2414  }  }
2415    
2416  // Suspend the pseudo-timer delay schedule.  // Suspend the pseudo-timer delay schedule.
2417  void MainForm::stopSchedule (void)  void MainForm::stopSchedule (void)
2418  {  {
2419      m_iStartDelay  = 0;          m_iStartDelay  = 0;
2420      m_iTimerDelay  = 0;          m_iTimerDelay  = 0;
2421  }  }
2422    
2423  // Timer slot funtion.  // Timer slot funtion.
2424  void MainForm::timerSlot (void)  void MainForm::timerSlot (void)
2425  {  {
2426      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2427          return;                  return;
2428    
2429      // Is it the first shot on server start after a few delay?          // Is it the first shot on server start after a few delay?
2430      if (m_iTimerDelay < m_iStartDelay) {          if (m_iTimerDelay < m_iStartDelay) {
2431          m_iTimerDelay += QSAMPLER_TIMER_MSECS;                  m_iTimerDelay += QSAMPLER_TIMER_MSECS;
2432          if (m_iTimerDelay >= m_iStartDelay) {                  if (m_iTimerDelay >= m_iStartDelay) {
2433              // If we cannot start it now, maybe a lil'mo'later ;)                          // If we cannot start it now, maybe a lil'mo'later ;)
2434              if (!startClient()) {                          if (!startClient()) {
2435                  m_iStartDelay += m_iTimerDelay;                                  m_iStartDelay += m_iTimerDelay;
2436                  m_iTimerDelay  = 0;                                  m_iTimerDelay  = 0;
2437              }                          }
2438          }                  }
2439      }          }
2440    
2441          if (m_pClient) {          if (m_pClient) {
2442                  // Update the channel information for each pending strip...                  // Update the channel information for each pending strip...
2443                  if (m_changedStrips.count() > 0) {                  QListIterator<ChannelStrip *> iter(m_changedStrips);
2444                          for (ChannelStrip* pChannelStrip = m_changedStrips.first();                  while (iter.hasNext()) {
2445                                          pChannelStrip; pChannelStrip = m_changedStrips.next()) {                          ChannelStrip *pChannelStrip = iter.next();
2446                                  // If successfull, remove from pending list...                          // If successfull, remove from pending list...
2447                                  if (pChannelStrip->updateChannelInfo())                          if (pChannelStrip->updateChannelInfo()) {
2448                                          m_changedStrips.remove(pChannelStrip);                                  int iChannelStrip = m_changedStrips.indexOf(pChannelStrip);
2449                                    if (iChannelStrip >= 0)
2450                                            m_changedStrips.removeAt(iChannelStrip);
2451                          }                          }
2452                  }                  }
2453                  // Refresh each channel usage, on each period...                  // Refresh each channel usage, on each period...
# Line 2339  void MainForm::timerSlot (void) Line 2468  void MainForm::timerSlot (void)
2468                  }                  }
2469          }          }
2470    
2471      // Register the next timer slot.          // Register the next timer slot.
2472      QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));          QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
2473  }  }
2474    
2475    
# Line 2350  void MainForm::timerSlot (void) Line 2479  void MainForm::timerSlot (void)
2479  // Start linuxsampler server...  // Start linuxsampler server...
2480  void MainForm::startServer (void)  void MainForm::startServer (void)
2481  {  {
2482      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2483          return;                  return;
2484    
2485            // Aren't already a client, are we?
2486            if (!m_pOptions->bServerStart || m_pClient)
2487                    return;
2488    
2489      // Aren't already a client, are we?          // Is the server process instance still here?
2490      if (!m_pOptions->bServerStart || m_pClient)          if (m_pServer) {
2491          return;                  switch (QMessageBox::warning(this,
   
     // Is the server process instance still here?  
     if (m_pServer) {  
         switch (QMessageBox::warning(this,  
2492                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
2493              tr("Could not start the LinuxSampler server.\n\n"                          tr("Could not start the LinuxSampler server.\n\n"
2494                 "Maybe it ss already started."),                          "Maybe it is already started."),
2495              tr("Stop"), tr("Kill"), tr("Cancel"))) {                          tr("Stop"), tr("Kill"), tr("Cancel"))) {
2496            case 0:                  case 0:
2497              m_pServer->terminate();                          m_pServer->terminate();
2498              break;                          break;
2499            case 1:                  case 1:
2500              m_pServer->kill();                          m_pServer->kill();
2501              break;                          break;
2502          }                  }
2503          return;                  return;
2504      }          }
2505    
2506      // Reset our timer counters...          // Reset our timer counters...
2507      stopSchedule();          stopSchedule();
2508    
2509      // OK. Let's build the startup process...          // Verify we have something to start with...
2510      m_pServer = new QProcess(this);          if (m_pOptions->sServerCmdLine.isEmpty())
2511                    return;
2512      // Setup stdout/stderr capture...  
2513          //      if (m_pOptions->bStdoutCapture) {          // OK. Let's build the startup process...
2514                  //m_pServer->setProcessChannelMode(          m_pServer = new QProcess();
2515                  //      QProcess::StandardOutput);          bForceServerStop = true;
2516    
2517            // Setup stdout/stderr capture...
2518    //      if (m_pOptions->bStdoutCapture) {
2519    #if QT_VERSION >= 0x040200
2520                    m_pServer->setProcessChannelMode(QProcess::ForwardedChannels);
2521    #endif
2522                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2523                          SIGNAL(readyReadStandardOutput()),                          SIGNAL(readyReadStandardOutput()),
2524                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
2525                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2526                          SIGNAL(readyReadStandardError()),                          SIGNAL(readyReadStandardError()),
2527                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
2528          //      }  //      }
2529    
2530          // The unforgiveable signal communication...          // The unforgiveable signal communication...
2531          QObject::connect(m_pServer,          QObject::connect(m_pServer,
2532                  SIGNAL(finished(int,QProcess::ExitStatus)),                  SIGNAL(finished(int, QProcess::ExitStatus)),
2533                  SLOT(processServerExit()));                  SLOT(processServerExit()));
2534    
2535      // Build process arguments...          // Build process arguments...
2536      QStringList serverCmdLine = QStringList::split(' ', m_pOptions->sServerCmdLine);          QStringList args = m_pOptions->sServerCmdLine.split(' ');
2537            QString sCommand = args[0];
2538      appendMessages(tr("Server is starting..."));          args.removeAt(0);
2539      appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");  
2540            appendMessages(tr("Server is starting..."));
2541            appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");
2542    
2543      const QString prog = (serverCmdLine.size() > 0) ? serverCmdLine[0] : QString();          // Go linuxsampler, go...
2544      const QStringList args = serverCmdLine.mid(1);          m_pServer->start(sCommand, args);
2545            if (!m_pServer->waitForStarted()) {
2546      // Go jack, go...                  appendMessagesError(tr("Could not start server.\n\nSorry."));
2547      m_pServer->start(prog, args);                  processServerExit();
2548      if (!m_pServer->waitForStarted()) {                  return;
2549          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()));  
2550    
2551      // Reset (yet again) the timer counters,          // Show startup results...
2552      // but this time is deferred as the user opted.          appendMessages(
2553      startSchedule(m_pOptions->iStartDelay);                  tr("Server was started with PID=%1.").arg((long) m_pServer->pid()));
2554      stabilizeForm();  
2555            // Reset (yet again) the timer counters,
2556            // but this time is deferred as the user opted.
2557            startSchedule(m_pOptions->iStartDelay);
2558            stabilizeForm();
2559  }  }
2560    
2561    
2562  // Stop linuxsampler server...  // Stop linuxsampler server...
2563  void MainForm::stopServer (void)  void MainForm::stopServer (bool bInteractive)
2564  {  {
2565      // Stop client code.          // Stop client code.
2566      stopClient();          stopClient();
2567    
2568      // And try to stop server.          if (m_pServer && bInteractive) {
2569      if (m_pServer) {                  if (QMessageBox::question(this,
2570          appendMessages(tr("Server is stopping..."));                          QSAMPLER_TITLE ": " + tr("The backend's fate ..."),
2571          if (m_pServer->state() == QProcess::Running)                          tr("You have the option to keep the sampler backend (LinuxSampler)\n"
2572              m_pServer->terminate();                          "running in the background. The sampler would continue to work\n"
2573       }                          "according to your current sampler session and you could alter the\n"
2574                            "sampler session at any time by relaunching QSampler.\n\n"
2575      // Give it some time to terminate gracefully and stabilize...                          "Do you want LinuxSampler to stop or to keep running in\n"
2576      QTime t;                          "the background?"),
2577      t.start();                          tr("Stop"), tr("Keep Running")) == 1)
2578      while (t.elapsed() < QSAMPLER_TIMER_MSECS)                  {
2579          QApplication::processEvents(QEventLoop::ExcludeUserInput);                          bForceServerStop = false;
2580                    }
2581            }
2582    
2583       // Do final processing anyway.          // And try to stop server.
2584       processServerExit();          if (m_pServer && bForceServerStop) {
2585                    appendMessages(tr("Server is stopping..."));
2586                    if (m_pServer->state() == QProcess::Running) {
2587    #if defined(WIN32)
2588                            // Try harder...
2589                            m_pServer->kill();
2590    #else
2591                            // Try softly...
2592                            m_pServer->terminate();
2593    #endif
2594                    }
2595            }       // Do final processing anyway.
2596            else processServerExit();
2597    
2598            // Give it some time to terminate gracefully and stabilize...
2599            QTime t;
2600            t.start();
2601            while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2602                    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2603  }  }
2604    
2605    
2606  // Stdout handler...  // Stdout handler...
2607  void MainForm::readServerStdout (void)  void MainForm::readServerStdout (void)
2608  {  {
2609      if (m_pMessages)          if (m_pMessages)
2610          m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());                  m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());
2611  }  }
2612    
2613    
2614  // Linuxsampler server cleanup.  // Linuxsampler server cleanup.
2615  void MainForm::processServerExit (void)  void MainForm::processServerExit (void)
2616  {  {
2617      // Force client code cleanup.          // Force client code cleanup.
2618      stopClient();          stopClient();
2619    
2620      // Flush anything that maybe pending...          // Flush anything that maybe pending...
2621      if (m_pMessages)          if (m_pMessages)
2622          m_pMessages->flushStdoutBuffer();                  m_pMessages->flushStdoutBuffer();
2623    
2624      if (m_pServer) {          if (m_pServer && bForceServerStop) {
2625          // Force final server shutdown...                  if (m_pServer->state() != QProcess::NotRunning) {
2626          appendMessages(tr("Server was stopped with exit status %1.").arg(m_pServer->exitStatus()));                          appendMessages(tr("Server is being forced..."));
2627          m_pServer->terminate();                          // Force final server shutdown...
2628          if (!m_pServer->waitForFinished(2000))                          m_pServer->kill();
2629              m_pServer->kill();                          // Give it some time to terminate gracefully and stabilize...
2630          // Destroy it.                          QTime t;
2631          delete m_pServer;                          t.start();
2632          m_pServer = NULL;                          while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2633      }                                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2634                    }
2635                    // Force final server shutdown...
2636                    appendMessages(
2637                            tr("Server was stopped with exit status %1.")
2638                            .arg(m_pServer->exitStatus()));
2639                    delete m_pServer;
2640                    m_pServer = NULL;
2641            }
2642    
2643      // Again, make status visible stable.          // Again, make status visible stable.
2644      stabilizeForm();          stabilizeForm();
2645  }  }
2646    
2647    
# Line 2487  void MainForm::processServerExit (void) Line 2649  void MainForm::processServerExit (void)
2649  // qsamplerMainForm -- Client stuff.  // qsamplerMainForm -- Client stuff.
2650    
2651  // The LSCP client callback procedure.  // The LSCP client callback procedure.
2652  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*/,
2653            lscp_event_t event, const char *pchData, int cchData, void *pvData )
2654  {  {
2655      MainForm* pMainForm = (MainForm *) pvData;          MainForm* pMainForm = (MainForm *) pvData;
2656      if (pMainForm == NULL)          if (pMainForm == NULL)
2657          return LSCP_FAILED;                  return LSCP_FAILED;
2658    
2659      // ATTN: DO NOT EVER call any GUI code here,          // ATTN: DO NOT EVER call any GUI code here,
2660      // as this is run under some other thread context.          // as this is run under some other thread context.
2661      // A custom event must be posted here...          // A custom event must be posted here...
2662      QApplication::postEvent(pMainForm, new qsamplerCustomEvent(event, pchData, cchData));          QApplication::postEvent(pMainForm,
2663                    new CustomEvent(event, pchData, cchData));
2664    
2665      return LSCP_OK;          return LSCP_OK;
2666  }  }
2667    
2668    
2669  // Start our almighty client...  // Start our almighty client...
2670  bool MainForm::startClient (void)  bool MainForm::startClient (void)
2671  {  {
2672      // Have it a setup?          // Have it a setup?
2673      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2674          return false;                  return false;
2675    
2676      // Aren't we already started, are we?          // Aren't we already started, are we?
2677      if (m_pClient)          if (m_pClient)
2678          return true;                  return true;
2679    
2680      // Log prepare here.          // Log prepare here.
2681      appendMessages(tr("Client connecting..."));          appendMessages(tr("Client connecting..."));
2682    
2683      // Create the client handle...          // Create the client handle...
2684      m_pClient = ::lscp_client_create(m_pOptions->sServerHost.latin1(), m_pOptions->iServerPort, qsampler_client_callback, this);          m_pClient = ::lscp_client_create(
2685      if (m_pClient == NULL) {                  m_pOptions->sServerHost.toUtf8().constData(),
2686          // Is this the first try?                  m_pOptions->iServerPort, qsampler_client_callback, this);
2687          // maybe we need to start a local server...          if (m_pClient == NULL) {
2688          if ((m_pServer && m_pServer->state() == QProcess::Running) || !m_pOptions->bServerStart)                  // Is this the first try?
2689              appendMessagesError(tr("Could not connect to server as client.\n\nSorry."));                  // maybe we need to start a local server...
2690          else                  if ((m_pServer && m_pServer->state() == QProcess::Running)
2691              startServer();                          || !m_pOptions->bServerStart) {
2692          // This is always a failure.                          appendMessagesError(
2693          stabilizeForm();                                  tr("Could not connect to server as client.\n\nSorry."));
2694          return false;                  } else {
2695      }                          startServer();
2696      // Just set receive timeout value, blindly.                  }
2697      ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);                  // This is always a failure.
2698      appendMessages(tr("Client receive timeout is set to %1 msec.").arg(::lscp_client_get_timeout(m_pClient)));                  stabilizeForm();
2699                    return false;
2700            }
2701            // Just set receive timeout value, blindly.
2702            ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);
2703            appendMessages(
2704                    tr("Client receive timeout is set to %1 msec.")
2705                    .arg(::lscp_client_get_timeout(m_pClient)));
2706    
2707          // Subscribe to channel info change notifications...          // Subscribe to channel info change notifications...
2708            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT) != LSCP_OK)
2709                    appendMessagesClient("lscp_client_subscribe(CHANNEL_COUNT)");
2710          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)
2711                  appendMessagesClient("lscp_client_subscribe");                  appendMessagesClient("lscp_client_subscribe(CHANNEL_INFO)");
2712    
2713            DeviceStatusForm::onDevicesChanged(); // initialize
2714            updateViewMidiDeviceStatusMenu();
2715            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT) != LSCP_OK)
2716                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_COUNT)");
2717            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO) != LSCP_OK)
2718                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_INFO)");
2719            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT) != LSCP_OK)
2720                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_COUNT)");
2721            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO) != LSCP_OK)
2722                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_INFO)");
2723    
2724    #if CONFIG_LSCP_CHANNEL_MIDI
2725            // Subscribe to channel MIDI data notifications...
2726            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI) != LSCP_OK)
2727                    appendMessagesClient("lscp_client_subscribe(CHANNEL_MIDI)");
2728    #endif
2729    
2730    #if CONFIG_LSCP_DEVICE_MIDI
2731            // Subscribe to channel MIDI data notifications...
2732            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI) != LSCP_OK)
2733                    appendMessagesClient("lscp_client_subscribe(DEVICE_MIDI)");
2734    #endif
2735    
2736      // We may stop scheduling around.          // We may stop scheduling around.
2737      stopSchedule();          stopSchedule();
2738    
2739      // We'll accept drops from now on...          // We'll accept drops from now on...
2740      setAcceptDrops(true);          setAcceptDrops(true);
2741    
2742      // Log success here.          // Log success here.
2743      appendMessages(tr("Client connected."));          appendMessages(tr("Client connected."));
2744    
2745          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
2746          // if visible, that we're ready...          // if visible, that we're ready...
2747          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
2748              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
2749          if (m_pDeviceForm)          if (m_pDeviceForm)
2750              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
2751    
2752      // Is any session pending to be loaded?          // Is any session pending to be loaded?
2753      if (!m_pOptions->sSessionFile.isEmpty()) {          if (!m_pOptions->sSessionFile.isEmpty()) {
2754          // Just load the prabably startup session...                  // Just load the prabably startup session...
2755          if (loadSessionFile(m_pOptions->sSessionFile)) {                  if (loadSessionFile(m_pOptions->sSessionFile)) {
2756              m_pOptions->sSessionFile = QString::null;                          m_pOptions->sSessionFile = QString::null;
2757              return true;                          return true;
2758          }                  }
2759      }          }
2760    
2761      // Make a new session          // Make a new session
2762      return newSession();          return newSession();
2763  }  }
2764    
2765    
2766  // Stop client...  // Stop client...
2767  void MainForm::stopClient (void)  void MainForm::stopClient (void)
2768  {  {
2769      if (m_pClient == NULL)          if (m_pClient == NULL)
2770          return;                  return;
   
     // Log prepare here.  
     appendMessages(tr("Client disconnecting..."));  
2771    
2772      // Clear timer counters...          // Log prepare here.
2773      stopSchedule();          appendMessages(tr("Client disconnecting..."));
2774    
2775      // We'll reject drops from now on...          // Clear timer counters...
2776      setAcceptDrops(false);          stopSchedule();
2777    
2778      // Force any channel strips around, but          // We'll reject drops from now on...
2779      // but avoid removing the corresponding          setAcceptDrops(false);
     // channels from the back-end server.  
     m_iDirtyCount = 0;  
     closeSession(false);  
2780    
2781      // Close us as a client...          // Force any channel strips around, but
2782            // but avoid removing the corresponding
2783            // channels from the back-end server.
2784            m_iDirtyCount = 0;
2785            closeSession(false);
2786    
2787            // Close us as a client...
2788    #if CONFIG_LSCP_DEVICE_MIDI
2789            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI);
2790    #endif
2791    #if CONFIG_LSCP_CHANNEL_MIDI
2792            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI);
2793    #endif
2794            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
2795            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
2796            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
2797            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
2798          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
2799      ::lscp_client_destroy(m_pClient);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT);
2800      m_pClient = NULL;          ::lscp_client_destroy(m_pClient);
2801            m_pClient = NULL;
2802    
2803          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
2804          // if visible, that we're running out...          // if visible, that we're running out...
2805          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
2806              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
2807          if (m_pDeviceForm)          if (m_pDeviceForm)
2808              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
2809    
2810      // Log final here.          // Log final here.
2811      appendMessages(tr("Client disconnected."));          appendMessages(tr("Client disconnected."));
2812    
2813      // Make visible status.          // Make visible status.
2814      stabilizeForm();          stabilizeForm();
2815  }  }
2816    
2817    
2818    // Channel strip activation/selection.
2819    void MainForm::activateStrip ( QWidget *pWidget )
2820    {
2821            ChannelStrip *pChannelStrip
2822                    = static_cast<ChannelStrip *> (pWidget);
2823            if (pChannelStrip)
2824                    pChannelStrip->setSelected(true);
2825    
2826            stabilizeForm();
2827    }
2828    
2829    
2830  } // namespace QSampler  } // namespace QSampler
2831    
2832    

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

  ViewVC Help
Powered by ViewVC