/[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 1739 by capela, Wed May 14 17:37:45 2008 UTC
# Line 1  Line 1 
1  // qsamplerMainForm.cpp  // qsamplerMainForm.cpp
2  //  //
3  /****************************************************************************  /****************************************************************************
4     Copyright (C) 2004-2007, rncbc aka Rui Nuno Capela. All rights reserved.     Copyright (C) 2004-2008, rncbc aka Rui Nuno Capela. All rights reserved.
5     Copyright (C) 2007, Christian Schoenebeck     Copyright (C) 2007, 2008 Christian Schoenebeck
6    
7     This program is free software; you can redistribute it and/or     This program is free software; you can redistribute it and/or
8     modify it under the terms of the GNU General Public License     modify it under the terms of the GNU General Public License
# Line 20  Line 20 
20    
21  *****************************************************************************/  *****************************************************************************/
22    
23    #include "qsamplerAbout.h"
24  #include "qsamplerMainForm.h"  #include "qsamplerMainForm.h"
25    
 #include <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      // Just create the channel instance...          // Do we auto-arrange?
1401      qsamplerChannel *pChannel = new qsamplerChannel();          if (m_pOptions && m_pOptions->bAutoArrange)
1402      if (pChannel == NULL)                  channelsArrange();
1403          return;  
1404            // Make that an overall update.
1405      // Before we show it up, may be we'll          m_iDirtyCount++;
1406      // better ask for some initial values?          stabilizeForm();
     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            Channel *pChannel = pChannelStrip->channel();
1421            if (pChannel == NULL)
1422                    return;
1423    
1424      ChannelStrip* pChannelStrip = activeChannelStrip();          // Prompt user if he/she's sure about this...
1425      if (pChannelStrip == NULL)          if (m_pOptions && m_pOptions->bConfirmRemove) {
1426          return;                  if (QMessageBox::warning(this,
   
     qsamplerChannel *pChannel = pChannelStrip->channel();  
     if (pChannel == NULL)  
         return;  
   
     // 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...                  // Load the current setup settings.
1637          if (pOptionsForm->exec()) {                  pOptionsForm->setup(m_pOptions);
1638              // Warn if something will be only effective on next run.                  // Show the setup dialog...
1639              if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||                  if (pOptionsForm->exec()) {
1640                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||                          // Warn if something will be only effective on next run.
1641                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1642                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||
1643                  QMessageBox::information(this,                                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||
1644                                    (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {
1645                                    QMessageBox::information(this,
1646                                          QSAMPLER_TITLE ": " + tr("Information"),                                          QSAMPLER_TITLE ": " + tr("Information"),
1647                      tr("Some settings may be only effective\n"                                          tr("Some settings may be only effective\n"
1648                         "next time you start this program."), tr("OK"));                                          "next time you start this program."), tr("OK"));
1649                  updateMessagesCapture();                                  updateMessagesCapture();
1650              }                          }
1651              // Check wheather something immediate has changed.                          // Check wheather something immediate has changed.
1652              if (( bOldCompletePath && !m_pOptions->bCompletePath) ||                          if (( bOldMessagesLog && !m_pOptions->bMessagesLog) ||
1653                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||                                  (!bOldMessagesLog &&  m_pOptions->bMessagesLog) ||
1654                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))                                  (sOldMessagesLogPath != m_pOptions->sMessagesLogPath))
1655                  updateRecentFilesMenu();                                  m_pMessages->setLogging(
1656              if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||                                          m_pOptions->bMessagesLog, m_pOptions->sMessagesLogPath);
1657                  (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||
1658                  updateInstrumentNames();                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||
1659              if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
1660                  (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))                                  updateRecentFilesMenu();
1661                  updateDisplayEffect();                          if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||
1662              if (sOldDisplayFont != m_pOptions->sDisplayFont)                                  (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))
1663                  updateDisplayFont();                                  updateInstrumentNames();
1664              if (iOldMaxVolume != m_pOptions->iMaxVolume)                          if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||
1665                  updateMaxVolume();                                  (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))
1666              if (sOldMessagesFont != m_pOptions->sMessagesFont)                                  updateDisplayEffect();
1667                  updateMessagesFont();                          if (sOldDisplayFont != m_pOptions->sDisplayFont)
1668              if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||                                  updateDisplayFont();
1669                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||                          if (iOldMaxVolume != m_pOptions->iMaxVolume)
1670                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))                                  updateMaxVolume();
1671                  updateMessagesLimit();                          if (sOldMessagesFont != m_pOptions->sMessagesFont)
1672              // And now the main thing, whether we'll do client/server recycling?                                  updateMessagesFont();
1673              if ((sOldServerHost != m_pOptions->sServerHost) ||                          if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||
1674                  (iOldServerPort != m_pOptions->iServerPort) ||                                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||
1675                  (iOldServerTimeout != m_pOptions->iServerTimeout) ||                                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))
1676                  ( bOldServerStart && !m_pOptions->bServerStart) ||                                  updateMessagesLimit();
1677                  (!bOldServerStart &&  m_pOptions->bServerStart) ||                          // And now the main thing, whether we'll do client/server recycling?
1678                  (sOldServerCmdLine != m_pOptions->sServerCmdLine && m_pOptions->bServerStart))                          if ((sOldServerHost != m_pOptions->sServerHost) ||
1679                  fileRestart();                                  (iOldServerPort != m_pOptions->iServerPort) ||
1680          }                                  (iOldServerTimeout != m_pOptions->iServerTimeout) ||
1681          // Done.                                  ( bOldServerStart && !m_pOptions->bServerStart) ||
1682          delete pOptionsForm;                                  (!bOldServerStart &&  m_pOptions->bServerStart) ||
1683      }                                  (sOldServerCmdLine != m_pOptions->sServerCmdLine
1684                                    && m_pOptions->bServerStart))
1685                                    fileRestart();
1686                    }
1687                    // Done.
1688                    delete pOptionsForm;
1689            }
1690    
1691      // This makes it.          // This makes it.
1692      stabilizeForm();          stabilizeForm();
1693  }  }
1694    
1695    
# Line 1596  void MainForm::viewOptions (void) Line 1699  void MainForm::viewOptions (void)
1699  // Arrange channel strips.  // Arrange channel strips.
1700  void MainForm::channelsArrange (void)  void MainForm::channelsArrange (void)
1701  {  {
1702      // Full width vertical tiling          // Full width vertical tiling
1703      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
1704      if (wlist.isEmpty())          if (wlist.isEmpty())
1705          return;                  return;
1706    
1707      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
1708      int y = 0;          int y = 0;
1709      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1710          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
1711      /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {          /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {
1712              // Prevent flicker...                          // Prevent flicker...
1713              pChannelStrip->hide();                          pChannelStrip->hide();
1714              pChannelStrip->showNormal();                          pChannelStrip->showNormal();
1715          }   */                  }   */
1716          pChannelStrip->adjustSize();                  pChannelStrip->adjustSize();
1717          int iWidth  = m_pWorkspace->width();                  int iWidth  = m_pWorkspace->width();
1718          if (iWidth < pChannelStrip->width())                  if (iWidth < pChannelStrip->width())
1719              iWidth = pChannelStrip->width();                          iWidth = pChannelStrip->width();
1720      //  int iHeight = pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();          //  int iHeight = pChannelStrip->height()
1721          int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();          //              + pChannelStrip->parentWidget()->baseSize().height();
1722          pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);                  int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();
1723          y += iHeight;                  pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);
1724      }                  y += iHeight;
1725      m_pWorkspace->setUpdatesEnabled(true);          }
1726            m_pWorkspace->setUpdatesEnabled(true);
1727    
1728      stabilizeForm();          stabilizeForm();
1729  }  }
1730    
1731    
1732  // Auto-arrange channel strips.  // Auto-arrange channel strips.
1733  void MainForm::channelsAutoArrange ( bool bOn )  void MainForm::channelsAutoArrange ( bool bOn )
1734  {  {
1735      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1736          return;                  return;
1737    
1738      // Toggle the auto-arrange flag.          // Toggle the auto-arrange flag.
1739      m_pOptions->bAutoArrange = bOn;          m_pOptions->bAutoArrange = bOn;
1740    
1741      // If on, update whole workspace...          // If on, update whole workspace...
1742      if (m_pOptions->bAutoArrange)          if (m_pOptions->bAutoArrange)
1743          channelsArrange();                  channelsArrange();
1744  }  }
1745    
1746    
# Line 1646  void MainForm::channelsAutoArrange ( boo Line 1750  void MainForm::channelsAutoArrange ( boo
1750  // Show information about the Qt toolkit.  // Show information about the Qt toolkit.
1751  void MainForm::helpAboutQt (void)  void MainForm::helpAboutQt (void)
1752  {  {
1753      QMessageBox::aboutQt(this);          QMessageBox::aboutQt(this);
1754  }  }
1755    
1756    
1757  // Show information about application program.  // Show information about application program.
1758  void MainForm::helpAbout (void)  void MainForm::helpAbout (void)
1759  {  {
1760      // Stuff the about box text...          // Stuff the about box text...
1761      QString sText = "<p>\n";          QString sText = "<p>\n";
1762      sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";          sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";
1763      sText += "<br />\n";          sText += "<br />\n";
1764      sText += tr("Version") + ": <b>" QSAMPLER_VERSION "</b><br />\n";          sText += tr("Version") + ": <b>" QSAMPLER_VERSION "</b><br />\n";
1765      sText += "<small>" + tr("Build") + ": " __DATE__ " " __TIME__ "</small><br />\n";          sText += "<small>" + tr("Build") + ": " __DATE__ " " __TIME__ "</small><br />\n";
1766  #ifdef CONFIG_DEBUG  #ifdef CONFIG_DEBUG
1767      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1768      sText += tr("Debugging option enabled.");          sText += tr("Debugging option enabled.");
1769      sText += "</font></small><br />";          sText += "</font></small><br />";
1770  #endif  #endif
1771  #ifndef CONFIG_LIBGIG  #ifndef CONFIG_LIBGIG
1772      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1773      sText += tr("GIG (libgig) file support disabled.");          sText += tr("GIG (libgig) file support disabled.");
1774      sText += "</font></small><br />";          sText += "</font></small><br />";
1775  #endif  #endif
1776  #ifndef CONFIG_INSTRUMENT_NAME  #ifndef CONFIG_INSTRUMENT_NAME
1777      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1778      sText += tr("LSCP (liblscp) instrument_name support disabled.");          sText += tr("LSCP (liblscp) instrument_name support disabled.");
1779      sText += "</font></small><br />";          sText += "</font></small><br />";
1780  #endif  #endif
1781  #ifndef CONFIG_MUTE_SOLO  #ifndef CONFIG_MUTE_SOLO
1782      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1783      sText += tr("Sampler channel Mute/Solo support disabled.");          sText += tr("Sampler channel Mute/Solo support disabled.");
1784      sText += "</font></small><br />";          sText += "</font></small><br />";
1785  #endif  #endif
1786  #ifndef CONFIG_AUDIO_ROUTING  #ifndef CONFIG_AUDIO_ROUTING
1787      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1788      sText += tr("LSCP (liblscp) audio_routing support disabled.");          sText += tr("LSCP (liblscp) audio_routing support disabled.");
1789      sText += "</font></small><br />";          sText += "</font></small><br />";
1790  #endif  #endif
1791  #ifndef CONFIG_FXSEND  #ifndef CONFIG_FXSEND
1792      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1793      sText += tr("Sampler channel Effect Sends support disabled.");          sText += tr("Sampler channel Effect Sends support disabled.");
1794      sText += "</font></small><br />";          sText += "</font></small><br />";
1795  #endif  #endif
1796  #ifndef CONFIG_VOLUME  #ifndef CONFIG_VOLUME
1797      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1798      sText += tr("Global volume support disabled.");          sText += tr("Global volume support disabled.");
1799      sText += "</font></small><br />";          sText += "</font></small><br />";
1800  #endif  #endif
1801  #ifndef CONFIG_MIDI_INSTRUMENT  #ifndef CONFIG_MIDI_INSTRUMENT
1802      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1803      sText += tr("MIDI instrument mapping support disabled.");          sText += tr("MIDI instrument mapping support disabled.");
1804      sText += "</font></small><br />";          sText += "</font></small><br />";
1805  #endif  #endif
1806  #ifndef CONFIG_EDIT_INSTRUMENT  #ifndef CONFIG_EDIT_INSTRUMENT
1807      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1808      sText += tr("Instrument editing support disabled.");          sText += tr("Instrument editing support disabled.");
1809      sText += "</font></small><br />";          sText += "</font></small><br />";
1810  #endif  #endif
1811      sText += "<br />\n";          sText += "<br />\n";
1812      sText += tr("Using") + ": ";          sText += tr("Using") + ": ";
1813      sText += ::lscp_client_package();          sText += ::lscp_client_package();
1814      sText += " ";          sText += " ";
1815      sText += ::lscp_client_version();          sText += ::lscp_client_version();
1816  #ifdef CONFIG_LIBGIG  #ifdef CONFIG_LIBGIG
1817      sText += ", ";          sText += ", ";
1818      sText += gig::libraryName().c_str();          sText += gig::libraryName().c_str();
1819      sText += " ";          sText += " ";
1820      sText += gig::libraryVersion().c_str();          sText += gig::libraryVersion().c_str();
1821  #endif  #endif
1822      sText += "<br />\n";          sText += "<br />\n";
1823      sText += "<br />\n";          sText += "<br />\n";
1824      sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";          sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";
1825      sText += "<br />\n";          sText += "<br />\n";
1826      sText += "<small>";          sText += "<small>";
1827      sText += QSAMPLER_COPYRIGHT "<br />\n";          sText += QSAMPLER_COPYRIGHT "<br />\n";
1828      sText += QSAMPLER_COPYRIGHT2 "<br />\n";          sText += QSAMPLER_COPYRIGHT2 "<br />\n";
1829      sText += "<br />\n";          sText += "<br />\n";
1830      sText += tr("This program is free software; you can redistribute it and/or modify it") + "<br />\n";          sText += tr("This program is free software; you can redistribute it and/or modify it") + "<br />\n";
1831      sText += tr("under the terms of the GNU General Public License version 2 or later.");          sText += tr("under the terms of the GNU General Public License version 2 or later.");
1832      sText += "</small>";          sText += "</small>";
1833      sText += "</p>\n";          sText += "</p>\n";
1834    
1835      QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);          QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);
1836  }  }
1837    
1838    
# Line 1737  void MainForm::helpAbout (void) Line 1841  void MainForm::helpAbout (void)
1841    
1842  void MainForm::stabilizeForm (void)  void MainForm::stabilizeForm (void)
1843  {  {
1844      // Update the main application caption...          // Update the main application caption...
1845      QString sSessionName = sessionName(m_sFilename);          QString sSessionName = sessionName(m_sFilename);
1846      if (m_iDirtyCount > 0)          if (m_iDirtyCount > 0)
1847          sSessionName += " *";                  sSessionName += " *";
1848      setCaption(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));
1849    
1850      // Update the main menu state...          // Update the main menu state...
1851      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1852      bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);          bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);
1853      bool bHasChannel = (bHasClient && pChannelStrip != NULL);          bool bHasChannel = (bHasClient && pChannelStrip != NULL);
1854      ui.fileNewAction->setEnabled(bHasClient);          m_ui.fileNewAction->setEnabled(bHasClient);
1855      ui.fileOpenAction->setEnabled(bHasClient);          m_ui.fileOpenAction->setEnabled(bHasClient);
1856      ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
1857      ui.fileSaveAsAction->setEnabled(bHasClient);          m_ui.fileSaveAsAction->setEnabled(bHasClient);
1858      ui.fileResetAction->setEnabled(bHasClient);          m_ui.fileResetAction->setEnabled(bHasClient);
1859      ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);          m_ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);
1860      ui.editAddChannelAction->setEnabled(bHasClient);          m_ui.editAddChannelAction->setEnabled(bHasClient);
1861      ui.editRemoveChannelAction->setEnabled(bHasChannel);          m_ui.editRemoveChannelAction->setEnabled(bHasChannel);
1862      ui.editSetupChannelAction->setEnabled(bHasChannel);          m_ui.editSetupChannelAction->setEnabled(bHasChannel);
1863  #ifdef CONFIG_EDIT_INSTRUMENT  #ifdef CONFIG_EDIT_INSTRUMENT
1864      ui.editEditChannelAction->setEnabled(bHasChannel);          m_ui.editEditChannelAction->setEnabled(bHasChannel);
1865  #else  #else
1866      ui.editEditChannelAction->setEnabled(false);          m_ui.editEditChannelAction->setEnabled(false);
1867  #endif  #endif
1868      ui.editResetChannelAction->setEnabled(bHasChannel);          m_ui.editResetChannelAction->setEnabled(bHasChannel);
1869      ui.editResetAllChannelsAction->setEnabled(bHasChannel);          m_ui.editResetAllChannelsAction->setEnabled(bHasChannel);
1870      ui.viewMessagesAction->setOn(m_pMessages && m_pMessages->isVisible());          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());
1871  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
1872          ui.viewInstrumentsAction->setOn(m_pInstrumentListForm          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm
1873                  && m_pInstrumentListForm->isVisible());                  && m_pInstrumentListForm->isVisible());
1874          ui.viewInstrumentsAction->setEnabled(bHasClient);          m_ui.viewInstrumentsAction->setEnabled(bHasClient);
1875  #else  #else
1876          ui.viewInstrumentsAction->setEnabled(false);          m_ui.viewInstrumentsAction->setEnabled(false);
1877  #endif  #endif
1878          ui.viewDevicesAction->setOn(m_pDeviceForm          m_ui.viewDevicesAction->setChecked(m_pDeviceForm
1879                  && m_pDeviceForm->isVisible());                  && m_pDeviceForm->isVisible());
1880      ui.viewDevicesAction->setEnabled(bHasClient);          m_ui.viewDevicesAction->setEnabled(bHasClient);
1881      ui.channelsArrangeAction->setEnabled(bHasChannel);          m_ui.channelsArrangeAction->setEnabled(bHasChannel);
1882    
1883  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
1884          // Toolbar widgets are also affected...          // Toolbar widgets are also affected...
1885      m_pVolumeSlider->setEnabled(bHasClient);          m_pVolumeSlider->setEnabled(bHasClient);
1886      m_pVolumeSpinBox->setEnabled(bHasClient);          m_pVolumeSpinBox->setEnabled(bHasClient);
1887  #endif  #endif
1888    
1889      // Client/Server status...          // Client/Server status...
1890      if (bHasClient) {          if (bHasClient) {
1891          m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));                  m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));
1892          m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost + ":" + QString::number(m_pOptions->iServerPort));                  m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost
1893      } else {                          + ':' + QString::number(m_pOptions->iServerPort));
1894          m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();          } else {
1895          m_statusItem[QSAMPLER_STATUS_SERVER]->clear();                  m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();
1896      }                  m_statusItem[QSAMPLER_STATUS_SERVER]->clear();
1897      // Channel status...          }
1898      if (bHasChannel)          // Channel status...
1899          m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->caption());          if (bHasChannel)
1900      else                  m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->windowTitle());
1901          m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();          else
1902      // Session status...                  m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();
1903      if (m_iDirtyCount > 0)          // Session status...
1904          m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));          if (m_iDirtyCount > 0)
1905      else                  m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));
1906          m_statusItem[QSAMPLER_STATUS_SESSION]->clear();          else
1907                    m_statusItem[QSAMPLER_STATUS_SESSION]->clear();
1908    
1909      // Recent files menu.          // Recent files menu.
1910      m_pRecentFilesMenu->setEnabled(bHasClient && m_pOptions->recentFiles.count() > 0);          m_ui.fileOpenRecentMenu->setEnabled(m_pOptions->recentFiles.count() > 0);
1911  }  }
1912    
1913    
# Line 1842  void MainForm::volumeChanged ( int iVolu Line 1947  void MainForm::volumeChanged ( int iVolu
1947  void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)  void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)
1948  {  {
1949          // Add this strip to the changed list...          // Add this strip to the changed list...
1950          if (m_changedStrips.containsRef(pChannelStrip) == 0) {          if (!m_changedStrips.contains(pChannelStrip)) {
1951                  m_changedStrips.append(pChannelStrip);                  m_changedStrips.append(pChannelStrip);
1952                  pChannelStrip->resetErrorCount();                  pChannelStrip->resetErrorCount();
1953          }          }
1954    
1955      // Just mark the dirty form.          // Just mark the dirty form.
1956      m_iDirtyCount++;          m_iDirtyCount++;
1957      // and update the form status...          // and update the form status...
1958      stabilizeForm();          stabilizeForm();
1959  }  }
1960    
1961    
# Line 1870  void MainForm::updateSession (void) Line 1975  void MainForm::updateSession (void)
1975          if (iMaps < 0)          if (iMaps < 0)
1976                  appendMessagesClient("lscp_get_midi_instrument_maps");                  appendMessagesClient("lscp_get_midi_instrument_maps");
1977          else if (iMaps < 1) {          else if (iMaps < 1) {
1978                  ::lscp_add_midi_instrument_map(m_pClient, tr("Chromatic").latin1());                  ::lscp_add_midi_instrument_map(m_pClient,
1979                  ::lscp_add_midi_instrument_map(m_pClient, tr("Drum Kits").latin1());                          tr("Chromatic").toUtf8().constData());
1980                    ::lscp_add_midi_instrument_map(m_pClient,
1981                            tr("Drum Kits").toUtf8().constData());
1982          }          }
1983  #endif  #endif
1984    
1985            updateAllChannelStrips(false);
1986    
1987            // Do we auto-arrange?
1988            if (m_pOptions && m_pOptions->bAutoArrange)
1989                    channelsArrange();
1990    
1991            // Remember to refresh devices and instruments...
1992            if (m_pInstrumentListForm)
1993                    m_pInstrumentListForm->refreshInstruments();
1994            if (m_pDeviceForm)
1995                    m_pDeviceForm->refreshDevices();
1996    }
1997    
1998    void MainForm::updateAllChannelStrips(bool bRemoveDeadStrips) {
1999          // Retrieve the current channel list.          // Retrieve the current channel list.
2000          int *piChannelIDs = ::lscp_list_channels(m_pClient);          int *piChannelIDs = ::lscp_list_channels(m_pClient);
2001          if (piChannelIDs == NULL) {          if (piChannelIDs == NULL) {
2002                  if (::lscp_client_get_errno(m_pClient)) {                  if (::lscp_client_get_errno(m_pClient)) {
2003                          appendMessagesClient("lscp_list_channels");                          appendMessagesClient("lscp_list_channels");
2004                          appendMessagesError(tr("Could not get current list of channels.\n\nSorry."));                          appendMessagesError(
2005                                    tr("Could not get current list of channels.\n\nSorry."));
2006                  }                  }
2007          } else {          } else {
2008                  // Try to (re)create each channel.                  // Try to (re)create each channel.
# Line 1888  void MainForm::updateSession (void) Line 2010  void MainForm::updateSession (void)
2010                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {
2011                          // Check if theres already a channel strip for this one...                          // Check if theres already a channel strip for this one...
2012                          if (!channelStrip(piChannelIDs[iChannel]))                          if (!channelStrip(piChannelIDs[iChannel]))
2013                                  createChannelStrip(new qsamplerChannel(piChannelIDs[iChannel]));                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));
2014                    }
2015    
2016                    // Do we auto-arrange?
2017                    if (m_pOptions && m_pOptions->bAutoArrange)
2018                            channelsArrange();
2019    
2020                    stabilizeForm();
2021    
2022                    // remove dead channel strips
2023                    if (bRemoveDeadStrips) {
2024                            for (int i = 0; channelStripAt(i); ++i) {
2025                                    ChannelStrip* pChannelStrip = channelStripAt(i);
2026                                    bool bExists = false;
2027                                    for (int j = 0; piChannelIDs[j] >= 0; ++j) {
2028                                            if (!pChannelStrip->channel()) break;
2029                                            if (piChannelIDs[j] == pChannelStrip->channel()->channelID()) {
2030                                                    // strip exists, don't touch it
2031                                                    bExists = true;
2032                                                    break;
2033                                            }
2034                                    }
2035                                    if (!bExists) destroyChannelStrip(pChannelStrip);
2036                            }
2037                  }                  }
2038                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
2039          }          }
   
     // Do we auto-arrange?  
     if (m_pOptions && m_pOptions->bAutoArrange)  
         channelsArrange();  
   
         // Remember to refresh devices and instruments...  
         if (m_pInstrumentListForm)  
             m_pInstrumentListForm->refreshInstruments();  
         if (m_pDeviceForm)  
             m_pDeviceForm->refreshDevices();  
2040  }  }
2041    
   
2042  // Update the recent files list and menu.  // Update the recent files list and menu.
2043  void MainForm::updateRecentFiles ( const QString& sFilename )  void MainForm::updateRecentFiles ( const QString& sFilename )
2044  {  {
2045      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2046          return;                  return;
   
     // 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);  
2047    
2048      // May update the menu.          // Remove from list if already there (avoid duplicates)
2049      updateRecentFilesMenu();          int iIndex = m_pOptions->recentFiles.indexOf(sFilename);
2050            if (iIndex >= 0)
2051                    m_pOptions->recentFiles.removeAt(iIndex);
2052            // Put it to front...
2053            m_pOptions->recentFiles.push_front(sFilename);
2054  }  }
2055    
2056    
2057  // Update the recent files list and menu.  // Update the recent files list and menu.
2058  void MainForm::updateRecentFilesMenu (void)  void MainForm::updateRecentFilesMenu (void)
2059  {  {
2060      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2061          return;                  return;
2062    
2063      // Time to keep the list under limits.          // Time to keep the list under limits.
2064      int iRecentFiles = m_pOptions->recentFiles.count();          int iRecentFiles = m_pOptions->recentFiles.count();
2065      while (iRecentFiles > m_pOptions->iMaxRecentFiles) {          while (iRecentFiles > m_pOptions->iMaxRecentFiles) {
2066          m_pOptions->recentFiles.pop_back();                  m_pOptions->recentFiles.pop_back();
2067          iRecentFiles--;                  iRecentFiles--;
2068      }          }
2069    
2070      // rebuild the recent files menu...          // Rebuild the recent files menu...
2071      m_pRecentFilesMenu->clear();          m_ui.fileOpenRecentMenu->clear();
2072      for (int i = 0; i < iRecentFiles; i++) {          for (int i = 0; i < iRecentFiles; i++) {
2073          const QString& sFilename = m_pOptions->recentFiles[i];                  const QString& sFilename = m_pOptions->recentFiles[i];
2074          if (QFileInfo(sFilename).exists()) {                  if (QFileInfo(sFilename).exists()) {
2075              m_pRecentFilesMenu->insertItem(QString("&%1 %2")                          QAction *pAction = m_ui.fileOpenRecentMenu->addAction(
2076                  .arg(i + 1).arg(sessionName(sFilename)),                                  QString("&%1 %2").arg(i + 1).arg(sessionName(sFilename)),
2077                  this, SLOT(fileOpenRecent(int)), 0, i);                                  this, SLOT(fileOpenRecent()));
2078          }                          pAction->setData(i);
2079      }                  }
2080            }
2081  }  }
2082    
2083    
2084  // Force update of the channels instrument names mode.  // Force update of the channels instrument names mode.
2085  void MainForm::updateInstrumentNames (void)  void MainForm::updateInstrumentNames (void)
2086  {  {
2087      // Full channel list update...          // Full channel list update...
2088      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2089      if (wlist.isEmpty())          if (wlist.isEmpty())
2090          return;                  return;
2091    
2092      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2093      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2094          ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);                  ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);
2095          if (pChannelStrip)                  if (pChannelStrip)
2096              pChannelStrip->updateInstrumentName(true);                          pChannelStrip->updateInstrumentName(true);
2097      }          }
2098      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2099  }  }
2100    
2101    
2102  // Force update of the channels display font.  // Force update of the channels display font.
2103  void MainForm::updateDisplayFont (void)  void MainForm::updateDisplayFont (void)
2104  {  {
2105      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2106          return;                  return;
2107    
2108            // Check if display font is legal.
2109            if (m_pOptions->sDisplayFont.isEmpty())
2110                    return;
2111            // Realize it.
2112            QFont font;
2113            if (!font.fromString(m_pOptions->sDisplayFont))
2114                    return;
2115    
2116      // Check if display font is legal.          // Full channel list update...
2117      if (m_pOptions->sDisplayFont.isEmpty())          QWidgetList wlist = m_pWorkspace->windowList();
2118          return;          if (wlist.isEmpty())
2119      // Realize it.                  return;
2120      QFont font;  
2121      if (!font.fromString(m_pOptions->sDisplayFont))          m_pWorkspace->setUpdatesEnabled(false);
2122          return;          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2123                    ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2124      // Full channel list update...                  if (pChannelStrip)
2125      QWidgetList wlist = m_pWorkspace->windowList();                          pChannelStrip->setDisplayFont(font);
2126      if (wlist.isEmpty())          }
2127          return;          m_pWorkspace->setUpdatesEnabled(true);
   
     m_pWorkspace->setUpdatesEnabled(false);  
     for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {  
         ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);  
         if (pChannelStrip)  
             pChannelStrip->setDisplayFont(font);  
     }  
     m_pWorkspace->setUpdatesEnabled(true);  
2128  }  }
2129    
2130    
2131  // Update channel strips background effect.  // Update channel strips background effect.
2132  void MainForm::updateDisplayEffect (void)  void MainForm::updateDisplayEffect (void)
2133  {  {
2134     QPixmap pm;          // Full channel list update...
2135      if (m_pOptions->bDisplayEffect)          QWidgetList wlist = m_pWorkspace->windowList();
2136          pm = QPixmap(":/qsampler/pixmaps/displaybg1.png");          if (wlist.isEmpty())
2137                    return;
2138      // Full channel list update...  
2139      QWidgetList wlist = m_pWorkspace->windowList();          m_pWorkspace->setUpdatesEnabled(false);
2140      if (wlist.isEmpty())          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2141          return;                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2142                    if (pChannelStrip)
2143      m_pWorkspace->setUpdatesEnabled(false);                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2144      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          }
2145          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);          m_pWorkspace->setUpdatesEnabled(true);
         if (pChannelStrip)  
             pChannelStrip->setDisplayBackground(pm);  
     }  
     m_pWorkspace->setUpdatesEnabled(true);  
2146  }  }
2147    
2148    
2149  // Force update of the channels maximum volume setting.  // Force update of the channels maximum volume setting.
2150  void MainForm::updateMaxVolume (void)  void MainForm::updateMaxVolume (void)
2151  {  {
2152      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2153          return;                  return;
2154    
2155  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2156          m_iVolumeChanging++;          m_iVolumeChanging++;
2157          m_pVolumeSlider->setMaxValue(m_pOptions->iMaxVolume);          m_pVolumeSlider->setMaximum(m_pOptions->iMaxVolume);
2158          m_pVolumeSpinBox->setMaxValue(m_pOptions->iMaxVolume);          m_pVolumeSpinBox->setMaximum(m_pOptions->iMaxVolume);
2159          m_iVolumeChanging--;          m_iVolumeChanging--;
2160  #endif  #endif
2161    
2162      // Full channel list update...          // Full channel list update...
2163      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2164      if (wlist.isEmpty())          if (wlist.isEmpty())
2165          return;                  return;
2166    
2167      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2168      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2169          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2170          if (pChannelStrip)                  if (pChannelStrip)
2171              pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                          pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2172      }          }
2173      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2174  }  }
2175    
2176    
# Line 2052  void MainForm::updateMaxVolume (void) Line 2180  void MainForm::updateMaxVolume (void)
2180  // Messages output methods.  // Messages output methods.
2181  void MainForm::appendMessages( const QString& s )  void MainForm::appendMessages( const QString& s )
2182  {  {
2183      if (m_pMessages)          if (m_pMessages)
2184          m_pMessages->appendMessages(s);                  m_pMessages->appendMessages(s);
2185    
2186      statusBar()->message(s, 3000);          statusBar()->showMessage(s, 3000);
2187  }  }
2188    
2189  void MainForm::appendMessagesColor( const QString& s, const QString& c )  void MainForm::appendMessagesColor( const QString& s, const QString& c )
2190  {  {
2191      if (m_pMessages)          if (m_pMessages)
2192          m_pMessages->appendMessagesColor(s, c);                  m_pMessages->appendMessagesColor(s, c);
2193    
2194      statusBar()->message(s, 3000);          statusBar()->showMessage(s, 3000);
2195  }  }
2196    
2197  void MainForm::appendMessagesText( const QString& s )  void MainForm::appendMessagesText( const QString& s )
2198  {  {
2199      if (m_pMessages)          if (m_pMessages)
2200          m_pMessages->appendMessagesText(s);                  m_pMessages->appendMessagesText(s);
2201  }  }
2202    
2203  void MainForm::appendMessagesError( const QString& s )  void MainForm::appendMessagesError( const QString& s )
2204  {  {
2205      if (m_pMessages)          if (m_pMessages)
2206          m_pMessages->show();                  m_pMessages->show();
2207    
2208      appendMessagesColor(s.simplified(), "#ff0000");          appendMessagesColor(s.simplified(), "#ff0000");
2209    
2210          // Make it look responsive...:)          // Make it look responsive...:)
2211          QApplication::processEvents(QEventLoop::ExcludeUserInput);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2212    
2213      QMessageBox::critical(this,          QMessageBox::critical(this,
2214                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));
2215  }  }
2216    
# Line 2090  void MainForm::appendMessagesError( cons Line 2218  void MainForm::appendMessagesError( cons
2218  // This is a special message format, just for client results.  // This is a special message format, just for client results.
2219  void MainForm::appendMessagesClient( const QString& s )  void MainForm::appendMessagesClient( const QString& s )
2220  {  {
2221      if (m_pClient == NULL)          if (m_pClient == NULL)
2222          return;                  return;
2223    
2224      appendMessagesColor(s + QString(": %1 (errno=%2)")          appendMessagesColor(s + QString(": %1 (errno=%2)")
2225          .arg(::lscp_client_get_result(m_pClient))                  .arg(::lscp_client_get_result(m_pClient))
2226          .arg(::lscp_client_get_errno(m_pClient)), "#996666");                  .arg(::lscp_client_get_errno(m_pClient)), "#996666");
2227    
2228          // Make it look responsive...:)          // Make it look responsive...:)
2229          QApplication::processEvents(QEventLoop::ExcludeUserInput);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2230  }  }
2231    
2232    
2233  // Force update of the messages font.  // Force update of the messages font.
2234  void MainForm::updateMessagesFont (void)  void MainForm::updateMessagesFont (void)
2235  {  {
2236      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2237          return;                  return;
2238    
2239      if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {          if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {
2240          QFont font;                  QFont font;
2241          if (font.fromString(m_pOptions->sMessagesFont))                  if (font.fromString(m_pOptions->sMessagesFont))
2242              m_pMessages->setMessagesFont(font);                          m_pMessages->setMessagesFont(font);
2243      }          }
2244  }  }
2245    
2246    
2247  // Update messages window line limit.  // Update messages window line limit.
2248  void MainForm::updateMessagesLimit (void)  void MainForm::updateMessagesLimit (void)
2249  {  {
2250      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2251          return;                  return;
2252    
2253      if (m_pMessages) {          if (m_pMessages) {
2254          if (m_pOptions->bMessagesLimit)                  if (m_pOptions->bMessagesLimit)
2255              m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);                          m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);
2256          else                  else
2257              m_pMessages->setMessagesLimit(-1);                          m_pMessages->setMessagesLimit(-1);
2258      }          }
2259  }  }
2260    
2261    
2262  // Enablement of the messages capture feature.  // Enablement of the messages capture feature.
2263  void MainForm::updateMessagesCapture (void)  void MainForm::updateMessagesCapture (void)
2264  {  {
2265      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2266          return;                  return;
2267    
2268      if (m_pMessages)          if (m_pMessages)
2269          m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);                  m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);
2270  }  }
2271    
2272    
# Line 2146  void MainForm::updateMessagesCapture (vo Line 2274  void MainForm::updateMessagesCapture (vo
2274  // qsamplerMainForm -- MDI channel strip management.  // qsamplerMainForm -- MDI channel strip management.
2275    
2276  // The channel strip creation executive.  // The channel strip creation executive.
2277  ChannelStrip* MainForm::createChannelStrip(qsamplerChannel* pChannel)  ChannelStrip* MainForm::createChannelStrip ( Channel *pChannel )
2278  {  {
2279      if (m_pClient == NULL || pChannel == NULL)          if (m_pClient == NULL || pChannel == NULL)
2280          return NULL;                  return NULL;
2281    
2282      // Prepare for auto-arrange?          // Add a new channel itema...
2283      ChannelStrip* pChannelStrip = NULL;          ChannelStrip *pChannelStrip = new ChannelStrip();
2284      int y = 0;          if (pChannelStrip == NULL)
2285      if (m_pOptions && m_pOptions->bAutoArrange) {                  return NULL;
2286          QWidgetList wlist = m_pWorkspace->windowList();  
2287          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          // Set some initial channel strip options...
2288              pChannelStrip = (ChannelStrip *) wlist.at(iChannel);          if (m_pOptions) {
2289                          if (pChannelStrip) {                  // Background display effect...
2290                          //  y += pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2291                                  y += pChannelStrip->parentWidget()->frameGeometry().height();                  // We'll need a display font.
2292                          }                  QFont font;
2293          }                  if (font.fromString(m_pOptions->sDisplayFont))
2294      }                          pChannelStrip->setDisplayFont(font);
2295                    // Maximum allowed volume setting.
2296                    pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2297            }
2298    
2299      // Add a new channel itema...          // Add it to workspace...
2300      pChannelStrip = new ChannelStrip();          m_pWorkspace->addWindow(pChannelStrip, Qt::FramelessWindowHint);
     if (pChannelStrip == NULL)  
         return NULL;  
2301    
2302      m_pWorkspace->addWindow(pChannelStrip, Qt::Tool);          // Actual channel strip setup...
2303            pChannelStrip->setup(pChannel);
2304    
     // Actual channel strip setup...  
     pChannelStrip->setup(pChannel);  
2305          QObject::connect(pChannelStrip,          QObject::connect(pChannelStrip,
2306                  SIGNAL(channelChanged(ChannelStrip*)),                  SIGNAL(channelChanged(ChannelStrip*)),
2307                  SLOT(channelStripChanged(ChannelStrip*)));                  SLOT(channelStripChanged(ChannelStrip*)));
2308      // Set some initial aesthetic options...  
2309      if (m_pOptions) {          // Now we show up us to the world.
2310          // Background display effect...          pChannelStrip->show();
         pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);  
         // We'll need a display font.  
         QFont font;  
         if (font.fromString(m_pOptions->sDisplayFont))  
             pChannelStrip->setDisplayFont(font);  
         // Maximum allowed volume setting.  
         pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);  
     }  
   
     // Now we show up us to the world.  
     pChannelStrip->show();  
     // Only then, we'll auto-arrange...  
     if (m_pOptions && m_pOptions->bAutoArrange) {  
         int iWidth  = m_pWorkspace->width();  
     //  int iHeight = pChannel->height() + pChannel->parentWidget()->baseSize().height();  
         int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();        pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);  
     }  
2311    
2312          // This is pretty new, so we'll watch for it closely.          // This is pretty new, so we'll watch for it closely.
2313          channelStripChanged(pChannelStrip);          channelStripChanged(pChannelStrip);
2314    
2315      // Return our successful reference...          // Return our successful reference...
2316      return pChannelStrip;          return pChannelStrip;
2317  }  }
2318    
2319    void MainForm::destroyChannelStrip(ChannelStrip* pChannelStrip) {
2320            // Just delete the channel strip.
2321            delete pChannelStrip;
2322    
2323            // Do we auto-arrange?
2324            if (m_pOptions && m_pOptions->bAutoArrange)
2325                    channelsArrange();
2326    
2327            stabilizeForm();
2328    }
2329    
2330  // Retrieve the active channel strip.  // Retrieve the active channel strip.
2331  ChannelStrip* MainForm::activeChannelStrip (void)  ChannelStrip* MainForm::activeChannelStrip (void)
2332  {  {
2333      return (ChannelStrip*) m_pWorkspace->activeWindow();          return static_cast<ChannelStrip *> (m_pWorkspace->activeWindow());
2334  }  }
2335    
2336    
2337  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
2338  ChannelStrip* MainForm::channelStripAt ( int iChannel )  ChannelStrip* MainForm::channelStripAt ( int iChannel )
2339  {  {
2340      QWidgetList wlist = m_pWorkspace->windowList();          if (!m_pWorkspace) return NULL;
2341      if (wlist.isEmpty())  
2342          return NULL;          QWidgetList wlist = m_pWorkspace->windowList();
2343            if (wlist.isEmpty())
2344                    return NULL;
2345    
2346      return (ChannelStrip*) wlist.at(iChannel);          if (iChannel < 0 || iChannel >= wlist.size())
2347                    return NULL;
2348    
2349            return dynamic_cast<ChannelStrip *> (wlist.at(iChannel));
2350  }  }
2351    
2352    
# Line 2232  ChannelStrip* MainForm::channelStrip ( i Line 2358  ChannelStrip* MainForm::channelStrip ( i
2358                  return NULL;                  return NULL;
2359    
2360          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2361                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip
2362                            = static_cast<ChannelStrip*> (wlist.at(iChannel));
2363                  if (pChannelStrip) {                  if (pChannelStrip) {
2364                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
2365                          if (pChannel && pChannel->channelID() == iChannelID)                          if (pChannel && pChannel->channelID() == iChannelID)
2366                                  return pChannelStrip;                                  return pChannelStrip;
2367                  }                  }
# Line 2248  ChannelStrip* MainForm::channelStrip ( i Line 2375  ChannelStrip* MainForm::channelStrip ( i
2375  // Construct the windows menu.  // Construct the windows menu.
2376  void MainForm::channelsMenuAboutToShow (void)  void MainForm::channelsMenuAboutToShow (void)
2377  {  {
2378      ui.channelsMenu->clear();          m_ui.channelsMenu->clear();
2379      ui.channelsArrangeAction->addTo(ui.channelsMenu);          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);
2380      ui.channelsAutoArrangeAction->addTo(ui.channelsMenu);          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);
2381    
2382      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2383      if (!wlist.isEmpty()) {          if (!wlist.isEmpty()) {
2384          ui.channelsMenu->insertSeparator();                  m_ui.channelsMenu->addSeparator();
2385          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2386              ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                          ChannelStrip* pChannelStrip
2387              if (pChannelStrip) {                                  = static_cast<ChannelStrip*> (wlist.at(iChannel));
2388                  int iItemID = ui.channelsMenu->insertItem(pChannelStrip->caption(), this, SLOT(channelsMenuActivated(int)));                          if (pChannelStrip) {
2389                  ui.channelsMenu->setItemParameter(iItemID, iChannel);                                  QAction *pAction = m_ui.channelsMenu->addAction(
2390                  ui.channelsMenu->setItemChecked(iItemID, activeChannelStrip() == pChannelStrip);                                          pChannelStrip->windowTitle(),
2391              }                                          this, SLOT(channelsMenuActivated()));
2392          }                                  pAction->setCheckable(true);
2393      }                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);
2394                                    pAction->setData(iChannel);
2395                            }
2396                    }
2397            }
2398  }  }
2399    
2400    
2401  // Windows menu activation slot  // Windows menu activation slot
2402  void MainForm::channelsMenuActivated ( int iChannel )  void MainForm::channelsMenuActivated (void)
2403  {  {
2404      ChannelStrip* pChannelStrip = channelStripAt(iChannel);          // Retrive channel index from action data...
2405      if (pChannelStrip)          QAction *pAction = qobject_cast<QAction *> (sender());
2406          pChannelStrip->showNormal();          if (pAction == NULL)
2407      pChannelStrip->setFocus();                  return;
2408    
2409            ChannelStrip* pChannelStrip = channelStripAt(pAction->data().toInt());
2410            if (pChannelStrip) {
2411                    pChannelStrip->showNormal();
2412                    pChannelStrip->setFocus();
2413            }
2414  }  }
2415    
2416    
# Line 2283  void MainForm::channelsMenuActivated ( i Line 2420  void MainForm::channelsMenuActivated ( i
2420  // Set the pseudo-timer delay schedule.  // Set the pseudo-timer delay schedule.
2421  void MainForm::startSchedule ( int iStartDelay )  void MainForm::startSchedule ( int iStartDelay )
2422  {  {
2423      m_iStartDelay  = 1 + (iStartDelay * 1000);          m_iStartDelay  = 1 + (iStartDelay * 1000);
2424      m_iTimerDelay  = 0;          m_iTimerDelay  = 0;
2425  }  }
2426    
2427  // Suspend the pseudo-timer delay schedule.  // Suspend the pseudo-timer delay schedule.
2428  void MainForm::stopSchedule (void)  void MainForm::stopSchedule (void)
2429  {  {
2430      m_iStartDelay  = 0;          m_iStartDelay  = 0;
2431      m_iTimerDelay  = 0;          m_iTimerDelay  = 0;
2432  }  }
2433    
2434  // Timer slot funtion.  // Timer slot funtion.
2435  void MainForm::timerSlot (void)  void MainForm::timerSlot (void)
2436  {  {
2437      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2438          return;                  return;
2439    
2440      // Is it the first shot on server start after a few delay?          // Is it the first shot on server start after a few delay?
2441      if (m_iTimerDelay < m_iStartDelay) {          if (m_iTimerDelay < m_iStartDelay) {
2442          m_iTimerDelay += QSAMPLER_TIMER_MSECS;                  m_iTimerDelay += QSAMPLER_TIMER_MSECS;
2443          if (m_iTimerDelay >= m_iStartDelay) {                  if (m_iTimerDelay >= m_iStartDelay) {
2444              // If we cannot start it now, maybe a lil'mo'later ;)                          // If we cannot start it now, maybe a lil'mo'later ;)
2445              if (!startClient()) {                          if (!startClient()) {
2446                  m_iStartDelay += m_iTimerDelay;                                  m_iStartDelay += m_iTimerDelay;
2447                  m_iTimerDelay  = 0;                                  m_iTimerDelay  = 0;
2448              }                          }
2449          }                  }
2450      }          }
2451    
2452          if (m_pClient) {          if (m_pClient) {
2453                  // Update the channel information for each pending strip...                  // Update the channel information for each pending strip...
2454                  if (m_changedStrips.count() > 0) {                  QListIterator<ChannelStrip *> iter(m_changedStrips);
2455                          for (ChannelStrip* pChannelStrip = m_changedStrips.first();                  while (iter.hasNext()) {
2456                                          pChannelStrip; pChannelStrip = m_changedStrips.next()) {                          ChannelStrip *pChannelStrip = iter.next();
2457                                  // If successfull, remove from pending list...                          // If successfull, remove from pending list...
2458                                  if (pChannelStrip->updateChannelInfo())                          if (pChannelStrip->updateChannelInfo()) {
2459                                          m_changedStrips.remove(pChannelStrip);                                  int iChannelStrip = m_changedStrips.indexOf(pChannelStrip);
2460                                    if (iChannelStrip >= 0)
2461                                            m_changedStrips.removeAt(iChannelStrip);
2462                          }                          }
2463                  }                  }
2464                  // Refresh each channel usage, on each period...                  // Refresh each channel usage, on each period...
# Line 2340  void MainForm::timerSlot (void) Line 2479  void MainForm::timerSlot (void)
2479                  }                  }
2480          }          }
2481    
2482      // Register the next timer slot.          // Register the next timer slot.
2483      QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));          QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
2484  }  }
2485    
2486    
# Line 2351  void MainForm::timerSlot (void) Line 2490  void MainForm::timerSlot (void)
2490  // Start linuxsampler server...  // Start linuxsampler server...
2491  void MainForm::startServer (void)  void MainForm::startServer (void)
2492  {  {
2493      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2494          return;                  return;
2495    
2496            // Aren't already a client, are we?
2497            if (!m_pOptions->bServerStart || m_pClient)
2498                    return;
2499    
2500      // Aren't already a client, are we?          // Is the server process instance still here?
2501      if (!m_pOptions->bServerStart || m_pClient)          if (m_pServer) {
2502          return;                  switch (QMessageBox::warning(this,
   
     // Is the server process instance still here?  
     if (m_pServer) {  
         switch (QMessageBox::warning(this,  
2503                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
2504              tr("Could not start the LinuxSampler server.\n\n"                          tr("Could not start the LinuxSampler server.\n\n"
2505                 "Maybe it ss already started."),                          "Maybe it is already started."),
2506              tr("Stop"), tr("Kill"), tr("Cancel"))) {                          tr("Stop"), tr("Kill"), tr("Cancel"))) {
2507            case 0:                  case 0:
2508              m_pServer->terminate();                          m_pServer->terminate();
2509              break;                          break;
2510            case 1:                  case 1:
2511              m_pServer->kill();                          m_pServer->kill();
2512              break;                          break;
2513          }                  }
2514          return;                  return;
2515      }          }
2516    
2517      // Reset our timer counters...          // Reset our timer counters...
2518      stopSchedule();          stopSchedule();
2519    
2520      // OK. Let's build the startup process...          // Verify we have something to start with...
2521      m_pServer = new QProcess(this);          if (m_pOptions->sServerCmdLine.isEmpty())
2522                    return;
2523      // Setup stdout/stderr capture...  
2524          //      if (m_pOptions->bStdoutCapture) {          // OK. Let's build the startup process...
2525                  //m_pServer->setProcessChannelMode(          m_pServer = new QProcess();
2526                  //      QProcess::StandardOutput);          bForceServerStop = true;
2527    
2528            // Setup stdout/stderr capture...
2529    //      if (m_pOptions->bStdoutCapture) {
2530    #if QT_VERSION >= 0x040200
2531                    m_pServer->setProcessChannelMode(QProcess::ForwardedChannels);
2532    #endif
2533                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2534                          SIGNAL(readyReadStandardOutput()),                          SIGNAL(readyReadStandardOutput()),
2535                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
2536                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2537                          SIGNAL(readyReadStandardError()),                          SIGNAL(readyReadStandardError()),
2538                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
2539          //      }  //      }
2540    
2541          // The unforgiveable signal communication...          // The unforgiveable signal communication...
2542          QObject::connect(m_pServer,          QObject::connect(m_pServer,
2543                  SIGNAL(finished(int,QProcess::ExitStatus)),                  SIGNAL(finished(int, QProcess::ExitStatus)),
2544                  SLOT(processServerExit()));                  SLOT(processServerExit()));
2545    
2546      // Build process arguments...          // Build process arguments...
2547      QStringList serverCmdLine = QStringList::split(' ', m_pOptions->sServerCmdLine);          QStringList args = m_pOptions->sServerCmdLine.split(' ');
2548            QString sCommand = args[0];
2549      appendMessages(tr("Server is starting..."));          args.removeAt(0);
2550      appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");  
2551            appendMessages(tr("Server is starting..."));
2552            appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");
2553    
2554      const QString prog = (serverCmdLine.size() > 0) ? serverCmdLine[0] : QString();          // Go linuxsampler, go...
2555      const QStringList args = serverCmdLine.mid(1);          m_pServer->start(sCommand, args);
2556            if (!m_pServer->waitForStarted()) {
2557      // Go jack, go...                  appendMessagesError(tr("Could not start server.\n\nSorry."));
2558      m_pServer->start(prog, args);                  processServerExit();
2559      if (!m_pServer->waitForStarted()) {                  return;
2560          appendMessagesError(tr("Could not start server.\n\nSorry."));          }
         processServerExit();  
         return;  
     }  
   
     // Show startup results...  
     appendMessages(tr("Server was started with PID=%1.").arg((long) m_pServer->pid()));  
2561    
2562      // Reset (yet again) the timer counters,          // Show startup results...
2563      // but this time is deferred as the user opted.          appendMessages(
2564      startSchedule(m_pOptions->iStartDelay);                  tr("Server was started with PID=%1.").arg((long) m_pServer->pid()));
2565      stabilizeForm();  
2566            // Reset (yet again) the timer counters,
2567            // but this time is deferred as the user opted.
2568            startSchedule(m_pOptions->iStartDelay);
2569            stabilizeForm();
2570  }  }
2571    
2572    
2573  // Stop linuxsampler server...  // Stop linuxsampler server...
2574  void MainForm::stopServer (void)  void MainForm::stopServer (bool bInteractive)
2575  {  {
2576      // Stop client code.          // Stop client code.
2577      stopClient();          stopClient();
2578    
2579      // And try to stop server.          if (m_pServer && bInteractive) {
2580      if (m_pServer) {                  if (QMessageBox::question(this,
2581          appendMessages(tr("Server is stopping..."));                          QSAMPLER_TITLE ": " + tr("The backend's fate ..."),
2582          if (m_pServer->state() == QProcess::Running)                          tr("You have the option to keep the sampler backend (LinuxSampler)\n"
2583              m_pServer->terminate();                          "running in the background. The sampler would continue to work\n"
2584       }                          "according to your current sampler session and you could alter the\n"
2585                            "sampler session at any time by relaunching QSampler.\n\n"
2586      // Give it some time to terminate gracefully and stabilize...                          "Do you want LinuxSampler to stop or to keep running in\n"
2587      QTime t;                          "the background?"),
2588      t.start();                          tr("Stop"), tr("Keep Running")) == 1)
2589      while (t.elapsed() < QSAMPLER_TIMER_MSECS)                  {
2590          QApplication::processEvents(QEventLoop::ExcludeUserInput);                          bForceServerStop = false;
2591                    }
2592            }
2593    
2594       // Do final processing anyway.          // And try to stop server.
2595       processServerExit();          if (m_pServer && bForceServerStop) {
2596                    appendMessages(tr("Server is stopping..."));
2597                    if (m_pServer->state() == QProcess::Running) {
2598    #if defined(WIN32)
2599                            // Try harder...
2600                            m_pServer->kill();
2601    #else
2602                            // Try softly...
2603                            m_pServer->terminate();
2604    #endif
2605                    }
2606            }       // Do final processing anyway.
2607            else processServerExit();
2608    
2609            // Give it some time to terminate gracefully and stabilize...
2610            QTime t;
2611            t.start();
2612            while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2613                    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2614  }  }
2615    
2616    
2617  // Stdout handler...  // Stdout handler...
2618  void MainForm::readServerStdout (void)  void MainForm::readServerStdout (void)
2619  {  {
2620      if (m_pMessages)          if (m_pMessages)
2621          m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());                  m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());
2622  }  }
2623    
2624    
2625  // Linuxsampler server cleanup.  // Linuxsampler server cleanup.
2626  void MainForm::processServerExit (void)  void MainForm::processServerExit (void)
2627  {  {
2628      // Force client code cleanup.          // Force client code cleanup.
2629      stopClient();          stopClient();
2630    
2631      // Flush anything that maybe pending...          // Flush anything that maybe pending...
2632      if (m_pMessages)          if (m_pMessages)
2633          m_pMessages->flushStdoutBuffer();                  m_pMessages->flushStdoutBuffer();
2634    
2635      if (m_pServer) {          if (m_pServer && bForceServerStop) {
2636          // Force final server shutdown...                  if (m_pServer->state() != QProcess::NotRunning) {
2637          appendMessages(tr("Server was stopped with exit status %1.").arg(m_pServer->exitStatus()));                          appendMessages(tr("Server is being forced..."));
2638          m_pServer->terminate();                          // Force final server shutdown...
2639          if (!m_pServer->waitForFinished(2000))                          m_pServer->kill();
2640              m_pServer->kill();                          // Give it some time to terminate gracefully and stabilize...
2641          // Destroy it.                          QTime t;
2642          delete m_pServer;                          t.start();
2643          m_pServer = NULL;                          while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2644      }                                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2645                    }
2646                    // Force final server shutdown...
2647                    appendMessages(
2648                            tr("Server was stopped with exit status %1.")
2649                            .arg(m_pServer->exitStatus()));
2650                    delete m_pServer;
2651                    m_pServer = NULL;
2652            }
2653    
2654      // Again, make status visible stable.          // Again, make status visible stable.
2655      stabilizeForm();          stabilizeForm();
2656  }  }
2657    
2658    
# Line 2488  void MainForm::processServerExit (void) Line 2660  void MainForm::processServerExit (void)
2660  // qsamplerMainForm -- Client stuff.  // qsamplerMainForm -- Client stuff.
2661    
2662  // The LSCP client callback procedure.  // The LSCP client callback procedure.
2663  lscp_status_t qsampler_client_callback ( lscp_client_t */*pClient*/, lscp_event_t event, const char *pchData, int cchData, void *pvData )  lscp_status_t qsampler_client_callback ( lscp_client_t */*pClient*/,
2664            lscp_event_t event, const char *pchData, int cchData, void *pvData )
2665  {  {
2666      MainForm* pMainForm = (MainForm *) pvData;          MainForm* pMainForm = (MainForm *) pvData;
2667      if (pMainForm == NULL)          if (pMainForm == NULL)
2668          return LSCP_FAILED;                  return LSCP_FAILED;
2669    
2670      // ATTN: DO NOT EVER call any GUI code here,          // ATTN: DO NOT EVER call any GUI code here,
2671      // as this is run under some other thread context.          // as this is run under some other thread context.
2672      // A custom event must be posted here...          // A custom event must be posted here...
2673      QApplication::postEvent(pMainForm, new qsamplerCustomEvent(event, pchData, cchData));          QApplication::postEvent(pMainForm,
2674                    new CustomEvent(event, pchData, cchData));
2675    
2676      return LSCP_OK;          return LSCP_OK;
2677  }  }
2678    
2679    
2680  // Start our almighty client...  // Start our almighty client...
2681  bool MainForm::startClient (void)  bool MainForm::startClient (void)
2682  {  {
2683      // Have it a setup?          // Have it a setup?
2684      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2685          return false;                  return false;
2686    
2687      // Aren't we already started, are we?          // Aren't we already started, are we?
2688      if (m_pClient)          if (m_pClient)
2689          return true;                  return true;
2690    
2691      // Log prepare here.          // Log prepare here.
2692      appendMessages(tr("Client connecting..."));          appendMessages(tr("Client connecting..."));
2693    
2694      // Create the client handle...          // Create the client handle...
2695      m_pClient = ::lscp_client_create(m_pOptions->sServerHost.latin1(), m_pOptions->iServerPort, qsampler_client_callback, this);          m_pClient = ::lscp_client_create(
2696      if (m_pClient == NULL) {                  m_pOptions->sServerHost.toUtf8().constData(),
2697          // Is this the first try?                  m_pOptions->iServerPort, qsampler_client_callback, this);
2698          // maybe we need to start a local server...          if (m_pClient == NULL) {
2699          if ((m_pServer && m_pServer->state() == QProcess::Running) || !m_pOptions->bServerStart)                  // Is this the first try?
2700              appendMessagesError(tr("Could not connect to server as client.\n\nSorry."));                  // maybe we need to start a local server...
2701          else                  if ((m_pServer && m_pServer->state() == QProcess::Running)
2702              startServer();                          || !m_pOptions->bServerStart) {
2703          // This is always a failure.                          appendMessagesError(
2704          stabilizeForm();                                  tr("Could not connect to server as client.\n\nSorry."));
2705          return false;                  } else {
2706      }                          startServer();
2707      // Just set receive timeout value, blindly.                  }
2708      ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);                  // This is always a failure.
2709      appendMessages(tr("Client receive timeout is set to %1 msec.").arg(::lscp_client_get_timeout(m_pClient)));                  stabilizeForm();
2710                    return false;
2711            }
2712            // Just set receive timeout value, blindly.
2713            ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);
2714            appendMessages(
2715                    tr("Client receive timeout is set to %1 msec.")
2716                    .arg(::lscp_client_get_timeout(m_pClient)));
2717    
2718          // Subscribe to channel info change notifications...          // Subscribe to channel info change notifications...
2719            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT) != LSCP_OK)
2720                    appendMessagesClient("lscp_client_subscribe(CHANNEL_COUNT)");
2721          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)
2722                  appendMessagesClient("lscp_client_subscribe");                  appendMessagesClient("lscp_client_subscribe(CHANNEL_INFO)");
2723    
2724            DeviceStatusForm::onDevicesChanged(); // initialize
2725            updateViewMidiDeviceStatusMenu();
2726            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT) != LSCP_OK)
2727                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_COUNT)");
2728            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO) != LSCP_OK)
2729                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_INFO)");
2730            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT) != LSCP_OK)
2731                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_COUNT)");
2732            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO) != LSCP_OK)
2733                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_INFO)");
2734    
2735    #if CONFIG_EVENT_CHANNEL_MIDI
2736            // Subscribe to channel MIDI data notifications...
2737            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI) != LSCP_OK)
2738                    appendMessagesClient("lscp_client_subscribe(CHANNEL_MIDI)");
2739    #endif
2740    
2741    #if CONFIG_EVENT_DEVICE_MIDI
2742            // Subscribe to channel MIDI data notifications...
2743            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI) != LSCP_OK)
2744                    appendMessagesClient("lscp_client_subscribe(DEVICE_MIDI)");
2745    #endif
2746    
2747      // We may stop scheduling around.          // We may stop scheduling around.
2748      stopSchedule();          stopSchedule();
2749    
2750      // We'll accept drops from now on...          // We'll accept drops from now on...
2751      setAcceptDrops(true);          setAcceptDrops(true);
2752    
2753      // Log success here.          // Log success here.
2754      appendMessages(tr("Client connected."));          appendMessages(tr("Client connected."));
2755    
2756          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
2757          // if visible, that we're ready...          // if visible, that we're ready...
2758          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
2759              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
2760          if (m_pDeviceForm)          if (m_pDeviceForm)
2761              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
2762    
2763      // Is any session pending to be loaded?          // Is any session pending to be loaded?
2764      if (!m_pOptions->sSessionFile.isEmpty()) {          if (!m_pOptions->sSessionFile.isEmpty()) {
2765          // Just load the prabably startup session...                  // Just load the prabably startup session...
2766          if (loadSessionFile(m_pOptions->sSessionFile)) {                  if (loadSessionFile(m_pOptions->sSessionFile)) {
2767              m_pOptions->sSessionFile = QString::null;                          m_pOptions->sSessionFile = QString::null;
2768              return true;                          return true;
2769          }                  }
2770      }          }
2771    
2772      // Make a new session          // Make a new session
2773      return newSession();          return newSession();
2774  }  }
2775    
2776    
2777  // Stop client...  // Stop client...
2778  void MainForm::stopClient (void)  void MainForm::stopClient (void)
2779  {  {
2780      if (m_pClient == NULL)          if (m_pClient == NULL)
2781          return;                  return;
   
     // Log prepare here.  
     appendMessages(tr("Client disconnecting..."));  
2782    
2783      // Clear timer counters...          // Log prepare here.
2784      stopSchedule();          appendMessages(tr("Client disconnecting..."));
2785    
2786      // We'll reject drops from now on...          // Clear timer counters...
2787      setAcceptDrops(false);          stopSchedule();
2788    
2789      // Force any channel strips around, but          // We'll reject drops from now on...
2790      // but avoid removing the corresponding          setAcceptDrops(false);
     // channels from the back-end server.  
     m_iDirtyCount = 0;  
     closeSession(false);  
2791    
2792      // Close us as a client...          // Force any channel strips around, but
2793            // but avoid removing the corresponding
2794            // channels from the back-end server.
2795            m_iDirtyCount = 0;
2796            closeSession(false);
2797    
2798            // Close us as a client...
2799    #if CONFIG_EVENT_DEVICE_MIDI
2800            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI);
2801    #endif
2802    #if CONFIG_EVENT_CHANNEL_MIDI
2803            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI);
2804    #endif
2805            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
2806            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
2807            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
2808            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
2809          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
2810      ::lscp_client_destroy(m_pClient);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT);
2811      m_pClient = NULL;          ::lscp_client_destroy(m_pClient);
2812            m_pClient = NULL;
2813    
2814          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
2815          // if visible, that we're running out...          // if visible, that we're running out...
2816          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
2817              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
2818          if (m_pDeviceForm)          if (m_pDeviceForm)
2819              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
2820    
2821      // Log final here.          // Log final here.
2822      appendMessages(tr("Client disconnected."));          appendMessages(tr("Client disconnected."));
2823    
2824      // Make visible status.          // Make visible status.
2825      stabilizeForm();          stabilizeForm();
2826  }  }
2827    
2828    
2829    // Channel strip activation/selection.
2830    void MainForm::activateStrip ( QWidget *pWidget )
2831    {
2832            ChannelStrip *pChannelStrip
2833                    = static_cast<ChannelStrip *> (pWidget);
2834            if (pChannelStrip)
2835                    pChannelStrip->setSelected(true);
2836    
2837            stabilizeForm();
2838    }
2839    
2840    
2841  } // namespace QSampler  } // namespace QSampler
2842    
2843    

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

  ViewVC Help
Powered by ViewVC