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

Legend:
Removed from v.1475  
changed lines
  Added in v.1815

  ViewVC Help
Powered by ViewVC