/[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 1890 by capela, Tue Apr 28 09:06:43 2009 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-2009, 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)                                  QMessageBox::Yes | QMessageBox::No)
763                  return false;                                  == QMessageBox::No)
764          }                                  return false;
765      }                  }
766            }
767    
768      // Save it right away.          // Save it right away.
769      return saveSessionFile(sFilename);          return saveSessionFile(sFilename);
770  }  }
771    
772    
773  // Close current session.  // Close current session.
774  bool MainForm::closeSession ( bool bForce )  bool MainForm::closeSession ( bool bForce )
775  {  {
776      bool bClose = true;          bool bClose = true;
777    
778      // Are we dirty enough to prompt it?          // Are we dirty enough to prompt it?
779      if (m_iDirtyCount > 0) {          if (m_iDirtyCount > 0) {
780          switch (QMessageBox::warning(this,                  switch (QMessageBox::warning(this,
781                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
782              tr("The current session has been changed:\n\n"                          tr("The current session has been changed:\n\n"
783              "\"%1\"\n\n"                          "\"%1\"\n\n"
784              "Do you want to save the changes?")                          "Do you want to save the changes?")
785              .arg(sessionName(m_sFilename)),                          .arg(sessionName(m_sFilename)),
786              tr("Save"), tr("Discard"), tr("Cancel"))) {                          QMessageBox::Save |
787          case 0:     // Save...                          QMessageBox::Discard |
788              bClose = saveSession(false);                          QMessageBox::Cancel)) {
789              // Fall thru....                  case QMessageBox::Save:
790          case 1:     // Discard                          bClose = saveSession(false);
791              break;                          // Fall thru....
792          default:    // Cancel.                  case QMessageBox::Discard:
793              bClose = false;                          break;
794              break;                  default:    // Cancel.
795          }                          bClose = false;
796      }                          break;
797                    }
798      // 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;  
     }  
799    
800      return bClose;          // If we may close it, dot it.
801            if (bClose) {
802                    // Remove all channel strips from sight...
803                    m_pWorkspace->setUpdatesEnabled(false);
804                    QWidgetList wlist = m_pWorkspace->windowList();
805                    for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
806                            ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
807                            if (pChannelStrip) {
808                                    Channel *pChannel = pChannelStrip->channel();
809                                    if (bForce && pChannel)
810                                            pChannel->removeChannel();
811                                    delete pChannelStrip;
812                            }
813                    }
814                    m_pWorkspace->setUpdatesEnabled(true);
815                    // We're now clean, for sure.
816                    m_iDirtyCount = 0;
817            }
818    
819            return bClose;
820  }  }
821    
822    
823  // Load a session from specific file path.  // Load a session from specific file path.
824  bool MainForm::loadSessionFile ( const QString& sFilename )  bool MainForm::loadSessionFile ( const QString& sFilename )
825  {  {
826      if (m_pClient == NULL)          if (m_pClient == NULL)
827          return false;                  return false;
828    
829      // Open and read from real file.          // Open and read from real file.
830      QFile file(sFilename);          QFile file(sFilename);
831      if (!file.open(IO_ReadOnly)) {          if (!file.open(QIODevice::ReadOnly)) {
832          appendMessagesError(tr("Could not open \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
833          return false;                          tr("Could not open \"%1\" session file.\n\nSorry.")
834      }                          .arg(sFilename));
835                    return false;
836            }
837    
838          // Tell the world we'll take some time...          // Tell the world we'll take some time...
839          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
840    
841      // Read the file.          // Read the file.
842          int iLine = 0;          int iLine = 0;
843      int iErrors = 0;          int iErrors = 0;
844      QTextStream ts(&file);          QTextStream ts(&file);
845      while (!ts.atEnd()) {          while (!ts.atEnd()) {
846          // Read the line.                  // Read the line.
847          QString sCommand = ts.readLine().stripWhiteSpace();                  QString sCommand = ts.readLine().trimmed();
848                  iLine++;                  iLine++;
849          // If not empty, nor a comment, call the server...                  // If not empty, nor a comment, call the server...
850          if (!sCommand.isEmpty() && sCommand[0] != '#') {                  if (!sCommand.isEmpty() && sCommand[0] != '#') {
851                          // Remember that, no matter what,                          // Remember that, no matter what,
852                          // all LSCP commands are CR/LF terminated.                          // all LSCP commands are CR/LF terminated.
853                          sCommand += "\r\n";                          sCommand += "\r\n";
854                          if (::lscp_client_query(m_pClient, sCommand.latin1()) != LSCP_OK) {                          if (::lscp_client_query(m_pClient, sCommand.toUtf8().constData())
855                                    != LSCP_OK) {
856                                  appendMessagesColor(QString("%1(%2): %3")                                  appendMessagesColor(QString("%1(%2): %3")
857                                          .arg(QFileInfo(sFilename).fileName()).arg(iLine)                                          .arg(QFileInfo(sFilename).fileName()).arg(iLine)
858                                          .arg(sCommand.simplifyWhiteSpace()), "#996633");                                          .arg(sCommand.simplified()), "#996633");
859                                  appendMessagesClient("lscp_client_query");                                  appendMessagesClient("lscp_client_query");
860                                  iErrors++;                                  iErrors++;
861                          }                          }
862          }                  }
863          // Try to make it snappy :)                  // Try to make it snappy :)
864          QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
865      }          }
866    
867      // Ok. we've read it.          // Ok. we've read it.
868      file.close();          file.close();
869    
870          // Now we'll try to create (update) the whole GUI session.          // Now we'll try to create (update) the whole GUI session.
871          updateSession();          updateSession();
# Line 800  bool MainForm::loadSessionFile ( const Q Line 874  bool MainForm::loadSessionFile ( const Q
874          QApplication::restoreOverrideCursor();          QApplication::restoreOverrideCursor();
875    
876          // Have we any errors?          // Have we any errors?
877          if (iErrors > 0)          if (iErrors > 0) {
878                  appendMessagesError(tr("Session loaded with errors\nfrom \"%1\".\n\nSorry.").arg(sFilename));                  appendMessagesError(
879                            tr("Session loaded with errors\nfrom \"%1\".\n\nSorry.")
880                            .arg(sFilename));
881            }
882    
883      // Save as default session directory.          // Save as default session directory.
884      if (m_pOptions)          if (m_pOptions)
885          m_pOptions->sSessionDir = QFileInfo(sFilename).dirPath(true);                  m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();
886          // We're not dirty anymore, if loaded without errors,          // We're not dirty anymore, if loaded without errors,
887          m_iDirtyCount = iErrors;          m_iDirtyCount = iErrors;
888      // Stabilize form...          // Stabilize form...
889      m_sFilename = sFilename;          m_sFilename = sFilename;
890      updateRecentFiles(sFilename);          updateRecentFiles(sFilename);
891      appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));          appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));
892    
893      // Make that an overall update.          // Make that an overall update.
894      stabilizeForm();          stabilizeForm();
895      return true;          return true;
896  }  }
897    
898    
# Line 831  bool MainForm::saveSessionFile ( const Q Line 908  bool MainForm::saveSessionFile ( const Q
908                  return false;                  return false;
909          }          }
910    
911      // Open and write into real file.          // Open and write into real file.
912      QFile file(sFilename);          QFile file(sFilename);
913      if (!file.open(IO_WriteOnly | IO_Truncate)) {          if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
914          appendMessagesError(tr("Could not open \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
915          return false;                          tr("Could not open \"%1\" session file.\n\nSorry.")
916      }                          .arg(sFilename));
917                    return false;
918            }
919    
920          // Tell the world we'll take some time...          // Tell the world we'll take some time...
921          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
922    
923      // Write the file.          // Write the file.
924      int  iErrors = 0;          int  iErrors = 0;
925      QTextStream ts(&file);          QTextStream ts(&file);
926      ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;          ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;
927      ts << "# " << tr("Version")          ts << "# " << tr("Version")
928         << ": " QSAMPLER_VERSION << endl;          << ": " QSAMPLER_VERSION << endl;
929      ts << "# " << tr("Build")          ts << "# " << tr("Build")
930         << ": " __DATE__ " " __TIME__ << endl;          << ": " __DATE__ " " __TIME__ << endl;
931      ts << "#"  << endl;          ts << "#"  << endl;
932      ts << "# " << tr("File")          ts << "# " << tr("File")
933         << ": " << QFileInfo(sFilename).fileName() << endl;          << ": " << QFileInfo(sFilename).fileName() << endl;
934      ts << "# " << tr("Date")          ts << "# " << tr("Date")
935         << ": " << QDate::currentDate().toString("MMM dd yyyy")          << ": " << QDate::currentDate().toString("MMM dd yyyy")
936         << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;          << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;
937      ts << "#"  << endl;          ts << "#"  << endl;
938      ts << endl;          ts << endl;
939    
940          // It is assumed that this new kind of device+session file          // It is assumed that this new kind of device+session file
941          // will be loaded from a complete initialized server...          // will be loaded from a complete initialized server...
# Line 866  bool MainForm::saveSessionFile ( const Q Line 945  bool MainForm::saveSessionFile ( const Q
945    
946          // Audio device mapping.          // Audio device mapping.
947          QMap<int, int> audioDeviceMap;          QMap<int, int> audioDeviceMap;
948          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Audio);          piDeviceIDs = Device::getDevices(m_pClient, Device::Audio);
949          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
950                  ts << endl;                  ts << endl;
951                  qsamplerDevice device(qsamplerDevice::Audio, piDeviceIDs[iDevice]);                  Device device(Device::Audio, piDeviceIDs[iDevice]);
952                  // Audio device specification...                  // Audio device specification...
953                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
954                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
955                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();
956                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
957                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
958                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
959                                          ++deviceParam) {                                          ++deviceParam) {
960                          const qsamplerDeviceParam& param = deviceParam.data();                          const DeviceParam& param = deviceParam.value();
961                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
962                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
963                  }                  }
964                  ts << endl;                  ts << endl;
965                  // Audio channel parameters...                  // Audio channel parameters...
966                  int iPort = 0;                  int iPort = 0;
967                  for (qsamplerDevicePort *pPort = device.ports().first();                  QListIterator<DevicePort *> iter(device.ports());
968                                  pPort;                  while (iter.hasNext()) {
969                                          pPort = device.ports().next(), ++iPort) {                          DevicePort *pPort = iter.next();
970                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
971                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
972                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
973                                                  ++portParam) {                                                  ++portParam) {
974                                  const qsamplerDeviceParam& param = portParam.data();                                  const DeviceParam& param = portParam.value();
975                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
976                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice
977                                          << " " << iPort << " " << portParam.key()                                          << " " << iPort << " " << portParam.key()
978                                          << "='" << param.value << "'" << endl;                                          << "='" << param.value << "'" << endl;
979                          }                          }
980                            iPort++;
981                  }                  }
982                  // Audio device index/id mapping.                  // Audio device index/id mapping.
983                  audioDeviceMap[device.deviceID()] = iDevice;                  audioDeviceMap[device.deviceID()] = iDevice;
984                  // Try to keep it snappy :)                  // Try to keep it snappy :)
985                  QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
986          }          }
987    
988          // MIDI device mapping.          // MIDI device mapping.
989          QMap<int, int> midiDeviceMap;          QMap<int, int> midiDeviceMap;
990          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Midi);          piDeviceIDs = Device::getDevices(m_pClient, Device::Midi);
991          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
992                  ts << endl;                  ts << endl;
993                  qsamplerDevice device(qsamplerDevice::Midi, piDeviceIDs[iDevice]);                  Device device(Device::Midi, piDeviceIDs[iDevice]);
994                  // MIDI device specification...                  // MIDI device specification...
995                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
996                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
997                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();
998                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
999                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
1000                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
1001                                          ++deviceParam) {                                          ++deviceParam) {
1002                          const qsamplerDeviceParam& param = deviceParam.data();                          const DeviceParam& param = deviceParam.value();
1003                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
1004                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
1005                  }                  }
1006                  ts << endl;                  ts << endl;
1007                  // MIDI port parameters...                  // MIDI port parameters...
1008                  int iPort = 0;                  int iPort = 0;
1009                  for (qsamplerDevicePort *pPort = device.ports().first();                  QListIterator<DevicePort *> iter(device.ports());
1010                                  pPort;                  while (iter.hasNext()) {
1011                                          pPort = device.ports().next(), ++iPort) {                          DevicePort *pPort = iter.next();
1012                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1013                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1014                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1015                                                  ++portParam) {                                                  ++portParam) {
1016                                  const qsamplerDeviceParam& param = portParam.data();                                  const DeviceParam& param = portParam.value();
1017                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1018                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice
1019                                     << " " << iPort << " " << portParam.key()                                  << " " << iPort << " " << portParam.key()
1020                                     << "='" << param.value << "'" << endl;                                  << "='" << param.value << "'" << endl;
1021                          }                          }
1022                            iPort++;
1023                  }                  }
1024                  // MIDI device index/id mapping.                  // MIDI device index/id mapping.
1025                  midiDeviceMap[device.deviceID()] = iDevice;                  midiDeviceMap[device.deviceID()] = iDevice;
1026                  // Try to keep it snappy :)                  // Try to keep it snappy :)
1027                  QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1028          }          }
1029          ts << endl;          ts << endl;
1030    
# Line 1000  bool MainForm::saveSessionFile ( const Q Line 1081  bool MainForm::saveSessionFile ( const Q
1081                                  iErrors++;                                  iErrors++;
1082                          }                          }
1083                          // Try to keep it snappy :)                          // Try to keep it snappy :)
1084                          QApplication::processEvents(QEventLoop::ExcludeUserInput);                          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1085                  }                  }
1086                  ts << endl;                  ts << endl;
1087                  // Check for errors...                  // Check for errors...
# Line 1019  bool MainForm::saveSessionFile ( const Q Line 1100  bool MainForm::saveSessionFile ( const Q
1100  #endif  // CONFIG_MIDI_INSTRUMENT  #endif  // CONFIG_MIDI_INSTRUMENT
1101    
1102          // Sampler channel mapping.          // Sampler channel mapping.
1103      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
1104      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1105          ChannelStrip* pChannelStrip                  ChannelStrip* pChannelStrip
1106                          = static_cast<ChannelStrip *> (wlist.at(iChannel));                          = static_cast<ChannelStrip *> (wlist.at(iChannel));
1107          if (pChannelStrip) {                  if (pChannelStrip) {
1108              qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
1109              if (pChannel) {                          if (pChannel) {
1110                  ts << "# " << tr("Channel") << " " << iChannel << endl;                                  ts << "# " << tr("Channel") << " " << iChannel << endl;
1111                  ts << "ADD CHANNEL" << endl;                                  ts << "ADD CHANNEL" << endl;
1112                                  if (audioDeviceMap.isEmpty()) {                                  if (audioDeviceMap.isEmpty()) {
1113                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel
1114                                                  << " " << pChannel->audioDriver() << endl;                                                  << " " << pChannel->audioDriver() << endl;
# Line 1044  bool MainForm::saveSessionFile ( const Q Line 1125  bool MainForm::saveSessionFile ( const Q
1125                                  }                                  }
1126                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel
1127                                          << " " << pChannel->midiPort() << endl;                                          << " " << pChannel->midiPort() << endl;
1128                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";                                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";
1129                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)                                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
1130                      ts << "ALL";                                          ts << "ALL";
1131                  else                                  else
1132                      ts << pChannel->midiChannel();                                          ts << pChannel->midiChannel();
1133                  ts << endl;                                  ts << endl;
1134                  ts << "LOAD ENGINE " << pChannel->engineName() << " " << iChannel << endl;                                  ts << "LOAD ENGINE " << pChannel->engineName()
1135                                            << " " << iChannel << endl;
1136                                  if (pChannel->instrumentStatus() < 100) ts << "# ";                                  if (pChannel->instrumentStatus() < 100) ts << "# ";
1137                                  ts << "LOAD INSTRUMENT NON_MODAL '" << pChannel->instrumentFile() << "' "                                  ts << "LOAD INSTRUMENT NON_MODAL '"
1138                                            << pChannel->instrumentFile() << "' "
1139                                          << pChannel->instrumentNr() << " " << iChannel << endl;                                          << pChannel->instrumentNr() << " " << iChannel << endl;
1140                                  qsamplerChannelRoutingMap::ConstIterator audioRoute;                                  ChannelRoutingMap::ConstIterator audioRoute;
1141                                  for (audioRoute = pChannel->audioRouting().begin();                                  for (audioRoute = pChannel->audioRouting().begin();
1142                                                  audioRoute != pChannel->audioRouting().end();                                                  audioRoute != pChannel->audioRouting().end();
1143                                                          ++audioRoute) {                                                          ++audioRoute) {
1144                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannel
1145                                                  << " " << audioRoute.key()                                                  << " " << audioRoute.key()
1146                                                  << " " << audioRoute.data() << endl;                                                  << " " << audioRoute.value() << endl;
1147                                  }                                  }
1148                                  ts << "SET CHANNEL VOLUME " << iChannel                                  ts << "SET CHANNEL VOLUME " << iChannel
1149                                          << " " << pChannel->volume() << endl;                                          << " " << pChannel->volume() << endl;
# Line 1110  bool MainForm::saveSessionFile ( const Q Line 1193  bool MainForm::saveSessionFile ( const Q
1193                                          }                                          }
1194                                  }                                  }
1195  #endif  #endif
1196                  ts << endl;                                  ts << endl;
1197              }                          }
1198          }                  }
1199          // Try to keep it snappy :)                  // Try to keep it snappy :)
1200          QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1201      }          }
1202    
1203  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
1204          ts << "# " << tr("Global volume level") << endl;          ts << "# " << tr("Global volume level") << endl;
# Line 1123  bool MainForm::saveSessionFile ( const Q Line 1206  bool MainForm::saveSessionFile ( const Q
1206          ts << endl;          ts << endl;
1207  #endif  #endif
1208    
1209      // Ok. we've wrote it.          // Ok. we've wrote it.
1210      file.close();          file.close();
1211    
1212          // We're fornerly done.          // We're fornerly done.
1213          QApplication::restoreOverrideCursor();          QApplication::restoreOverrideCursor();
1214    
1215      // Have we any errors?          // Have we any errors?
1216      if (iErrors > 0)          if (iErrors > 0) {
1217          appendMessagesError(tr("Some settings could not be saved\nto \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
1218                            tr("Some settings could not be saved\n"
1219      // Save as default session directory.                          "to \"%1\" session file.\n\nSorry.")
1220      if (m_pOptions)                          .arg(sFilename));
1221          m_pOptions->sSessionDir = QFileInfo(sFilename).dirPath(true);          }
1222      // We're not dirty anymore.  
1223      m_iDirtyCount = 0;          // Save as default session directory.
1224      // Stabilize form...          if (m_pOptions)
1225      m_sFilename = sFilename;                  m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();
1226      updateRecentFiles(sFilename);          // We're not dirty anymore.
1227      appendMessages(tr("Save session: \"%1\".").arg(sessionName(m_sFilename)));          m_iDirtyCount = 0;
1228      stabilizeForm();          // Stabilize form...
1229      return true;          m_sFilename = sFilename;
1230            updateRecentFiles(sFilename);
1231            appendMessages(tr("Save session: \"%1\".").arg(sessionName(m_sFilename)));
1232            stabilizeForm();
1233            return true;
1234  }  }
1235    
1236    
1237  // Session change receiver slot.  // Session change receiver slot.
1238  void MainForm::sessionDirty (void)  void MainForm::sessionDirty (void)
1239  {  {
1240      // Just mark the dirty form.          // Just mark the dirty form.
1241      m_iDirtyCount++;          m_iDirtyCount++;
1242      // and update the form status...          // and update the form status...
1243      stabilizeForm();          stabilizeForm();
1244  }  }
1245    
1246    
# Line 1163  void MainForm::sessionDirty (void) Line 1250  void MainForm::sessionDirty (void)
1250  // Create a new sampler session.  // Create a new sampler session.
1251  void MainForm::fileNew (void)  void MainForm::fileNew (void)
1252  {  {
1253      // Of course we'll start clean new.          // Of course we'll start clean new.
1254      newSession();          newSession();
1255  }  }
1256    
1257    
1258  // Open an existing sampler session.  // Open an existing sampler session.
1259  void MainForm::fileOpen (void)  void MainForm::fileOpen (void)
1260  {  {
1261      // Open it right away.          // Open it right away.
1262      openSession();          openSession();
1263  }  }
1264    
1265    
1266  // Open a recent file session.  // Open a recent file session.
1267  void MainForm::fileOpenRecent ( int iIndex )  void MainForm::fileOpenRecent (void)
1268  {  {
1269      // Check if we can safely close the current session...          // Retrive filename index from action data...
1270      if (m_pOptions && closeSession(true)) {          QAction *pAction = qobject_cast<QAction *> (sender());
1271          QString sFilename = m_pOptions->recentFiles[iIndex];          if (pAction && m_pOptions) {
1272          loadSessionFile(sFilename);                  int iIndex = pAction->data().toInt();
1273      }                  if (iIndex >= 0 && iIndex < m_pOptions->recentFiles.count()) {
1274                            QString sFilename = m_pOptions->recentFiles[iIndex];
1275                            // Check if we can safely close the current session...
1276                            if (!sFilename.isEmpty() && closeSession(true))
1277                                    loadSessionFile(sFilename);
1278                    }
1279            }
1280  }  }
1281    
1282    
1283  // Save current sampler session.  // Save current sampler session.
1284  void MainForm::fileSave (void)  void MainForm::fileSave (void)
1285  {  {
1286      // Save it right away.          // Save it right away.
1287      saveSession(false);          saveSession(false);
1288  }  }
1289    
1290    
1291  // Save current sampler session with another name.  // Save current sampler session with another name.
1292  void MainForm::fileSaveAs (void)  void MainForm::fileSaveAs (void)
1293  {  {
1294      // Save it right away, maybe with another name.          // Save it right away, maybe with another name.
1295      saveSession(true);          saveSession(true);
1296  }  }
1297    
1298    
1299  // Reset the sampler instance.  // Reset the sampler instance.
1300  void MainForm::fileReset (void)  void MainForm::fileReset (void)
1301  {  {
1302      if (m_pClient == NULL)          if (m_pClient == NULL)
1303          return;                  return;
1304    
1305      // Ask user whether he/she want's an internal sampler reset...          // Ask user whether he/she want's an internal sampler reset...
1306      if (QMessageBox::warning(this,          if (QMessageBox::warning(this,
1307                  QSAMPLER_TITLE ": " + tr("Warning"),                  QSAMPLER_TITLE ": " + tr("Warning"),
1308          tr("Resetting the sampler instance will close\n"                  tr("Resetting the sampler instance will close\n"
1309             "all device and channel configurations.\n\n"                  "all device and channel configurations.\n\n"
1310             "Please note that this operation may cause\n"                  "Please note that this operation may cause\n"
1311             "temporary MIDI and Audio disruption.\n\n"                  "temporary MIDI and Audio disruption.\n\n"
1312             "Do you want to reset the sampler engine now?"),                  "Do you want to reset the sampler engine now?"),
1313          tr("Reset"), tr("Cancel")) > 0)                  QMessageBox::Ok | QMessageBox::Cancel)
1314          return;                  == QMessageBox::Cancel)
1315                    return;
1316    
1317          // Trye closing the current session, first...          // Trye closing the current session, first...
1318          if (!closeSession(true))          if (!closeSession(true))
1319                  return;                  return;
1320    
1321      // Just do the reset, after closing down current session...          // Just do the reset, after closing down current session...
1322          // Do the actual sampler reset...          // Do the actual sampler reset...
1323          if (::lscp_reset_sampler(m_pClient) != LSCP_OK) {          if (::lscp_reset_sampler(m_pClient) != LSCP_OK) {
1324                  appendMessagesClient("lscp_reset_sampler");                  appendMessagesClient("lscp_reset_sampler");
# Line 1232  void MainForm::fileReset (void) Line 1326  void MainForm::fileReset (void)
1326                  return;                  return;
1327          }          }
1328    
1329      // Log this.          // Log this.
1330      appendMessages(tr("Sampler reset."));          appendMessages(tr("Sampler reset."));
1331    
1332          // Make it a new session...          // Make it a new session...
1333          newSession();          newSession();
# Line 1243  void MainForm::fileReset (void) Line 1337  void MainForm::fileReset (void)
1337  // Restart the client/server instance.  // Restart the client/server instance.
1338  void MainForm::fileRestart (void)  void MainForm::fileRestart (void)
1339  {  {
1340      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1341          return;                  return;
1342    
1343      bool bRestart = true;          bool bRestart = true;
1344    
1345      // Ask user whether he/she want's a complete restart...          // Ask user whether he/she want's a complete restart...
1346      // (if we're currently up and running)          // (if we're currently up and running)
1347      if (bRestart && m_pClient) {          if (bRestart && m_pClient) {
1348          bRestart = (QMessageBox::warning(this,                  bRestart = (QMessageBox::warning(this,
1349                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
1350              tr("New settings will be effective after\n"                          tr("New settings will be effective after\n"
1351                 "restarting the client/server connection.\n\n"                          "restarting the client/server connection.\n\n"
1352                 "Please note that this operation may cause\n"                          "Please note that this operation may cause\n"
1353                 "temporary MIDI and Audio disruption.\n\n"                          "temporary MIDI and Audio disruption.\n\n"
1354                 "Do you want to restart the connection now?"),                          "Do you want to restart the connection now?"),
1355              tr("Restart"), tr("Cancel")) == 0);                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok);
1356      }          }
1357    
1358      // Are we still for it?          // Are we still for it?
1359      if (bRestart && closeSession(true)) {          if (bRestart && closeSession(true)) {
1360          // Stop server, it will force the client too.                  // Stop server, it will force the client too.
1361          stopServer();                  stopServer();
1362          // Reschedule a restart...                  // Reschedule a restart...
1363          startSchedule(m_pOptions->iStartDelay);                  startSchedule(m_pOptions->iStartDelay);
1364      }          }
1365  }  }
1366    
1367    
1368  // Exit application program.  // Exit application program.
1369  void MainForm::fileExit (void)  void MainForm::fileExit (void)
1370  {  {
1371      // Go for close the whole thing.          // Go for close the whole thing.
1372      close();          close();
1373  }  }
1374    
1375    
# Line 1285  void MainForm::fileExit (void) Line 1379  void MainForm::fileExit (void)
1379  // Add a new sampler channel.  // Add a new sampler channel.
1380  void MainForm::editAddChannel (void)  void MainForm::editAddChannel (void)
1381  {  {
1382      if (m_pClient == NULL)          if (m_pClient == NULL)
1383          return;                  return;
1384    
1385            // Just create the channel instance...
1386            Channel *pChannel = new Channel();
1387            if (pChannel == NULL)
1388                    return;
1389    
1390            // Before we show it up, may be we'll
1391            // better ask for some initial values?
1392            if (!pChannel->channelSetup(this)) {
1393                    delete pChannel;
1394                    return;
1395            }
1396    
1397            // And give it to the strip...
1398            // (will own the channel instance, if successful).
1399            if (!createChannelStrip(pChannel)) {
1400                    delete pChannel;
1401                    return;
1402            }
1403    
1404      // Just create the channel instance...          // Do we auto-arrange?
1405      qsamplerChannel *pChannel = new qsamplerChannel();          if (m_pOptions && m_pOptions->bAutoArrange)
1406      if (pChannel == NULL)                  channelsArrange();
1407          return;  
1408            // Make that an overall update.
1409      // Before we show it up, may be we'll          m_iDirtyCount++;
1410      // 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();  
1411  }  }
1412    
1413    
1414  // Remove current sampler channel.  // Remove current sampler channel.
1415  void MainForm::editRemoveChannel (void)  void MainForm::editRemoveChannel (void)
1416  {  {
1417      if (m_pClient == NULL)          if (m_pClient == NULL)
1418          return;                  return;
1419    
1420            ChannelStrip* pChannelStrip = activeChannelStrip();
1421            if (pChannelStrip == NULL)
1422                    return;
1423    
1424            Channel *pChannel = pChannelStrip->channel();
1425            if (pChannel == NULL)
1426                    return;
1427    
1428      ChannelStrip* pChannelStrip = activeChannelStrip();          // Prompt user if he/she's sure about this...
1429      if (pChannelStrip == NULL)          if (m_pOptions && m_pOptions->bConfirmRemove) {
1430          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,  
1431                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
1432              tr("About to remove channel:\n\n"                          tr("About to remove channel:\n\n"
1433                 "%1\n\n"                          "%1\n\n"
1434                 "Are you sure?")                          "Are you sure?")
1435                 .arg(pChannelStrip->caption()),                          .arg(pChannelStrip->windowTitle()),
1436              tr("OK"), tr("Cancel")) > 0)                          QMessageBox::Ok | QMessageBox::Cancel)
1437              return;                          == QMessageBox::Cancel)
1438      }                          return;
1439            }
1440      // Remove the existing sampler channel.  
1441      if (!pChannel->removeChannel())          // Remove the existing sampler channel.
1442          return;          if (!pChannel->removeChannel())
1443                    return;
1444      // Just delete the channel strip.  
1445      delete pChannelStrip;          // Just delete the channel strip.
1446            delete pChannelStrip;
1447      // Do we auto-arrange?  
1448      if (m_pOptions && m_pOptions->bAutoArrange)          // Do we auto-arrange?
1449          channelsArrange();          if (m_pOptions && m_pOptions->bAutoArrange)
1450                    channelsArrange();
1451      // We'll be dirty, for sure...  
1452      m_iDirtyCount++;          // We'll be dirty, for sure...
1453      stabilizeForm();          m_iDirtyCount++;
1454            stabilizeForm();
1455  }  }
1456    
1457    
1458  // Setup current sampler channel.  // Setup current sampler channel.
1459  void MainForm::editSetupChannel (void)  void MainForm::editSetupChannel (void)
1460  {  {
1461      if (m_pClient == NULL)          if (m_pClient == NULL)
1462          return;                  return;
1463    
1464      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1465      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1466          return;                  return;
1467    
1468      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1469      pChannelStrip->channelSetup();          pChannelStrip->channelSetup();
1470  }  }
1471    
1472    
1473  // Edit current sampler channel.  // Edit current sampler channel.
1474  void MainForm::editEditChannel (void)  void MainForm::editEditChannel (void)
1475  {  {
1476      if (m_pClient == NULL)          if (m_pClient == NULL)
1477          return;                  return;
1478    
1479      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1480      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1481          return;                  return;
1482    
1483      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1484      pChannelStrip->channelEdit();          pChannelStrip->channelEdit();
1485  }  }
1486    
1487    
1488  // Reset current sampler channel.  // Reset current sampler channel.
1489  void MainForm::editResetChannel (void)  void MainForm::editResetChannel (void)
1490  {  {
1491      if (m_pClient == NULL)          if (m_pClient == NULL)
1492          return;                  return;
1493    
1494      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1495      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1496          return;                  return;
1497    
1498      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1499      pChannelStrip->channelReset();          pChannelStrip->channelReset();
1500  }  }
1501    
1502    
# Line 1425  void MainForm::editResetAllChannels (voi Line 1525  void MainForm::editResetAllChannels (voi
1525  // Show/hide the main program window menubar.  // Show/hide the main program window menubar.
1526  void MainForm::viewMenubar ( bool bOn )  void MainForm::viewMenubar ( bool bOn )
1527  {  {
1528      if (bOn)          if (bOn)
1529          ui.MenuBar->show();                  m_ui.MenuBar->show();
1530      else          else
1531          ui.MenuBar->hide();                  m_ui.MenuBar->hide();
1532  }  }
1533    
1534    
1535  // Show/hide the main program window toolbar.  // Show/hide the main program window toolbar.
1536  void MainForm::viewToolbar ( bool bOn )  void MainForm::viewToolbar ( bool bOn )
1537  {  {
1538      if (bOn) {          if (bOn) {
1539          ui.fileToolbar->show();                  m_ui.fileToolbar->show();
1540          ui.editToolbar->show();                  m_ui.editToolbar->show();
1541          ui.channelsToolbar->show();                  m_ui.channelsToolbar->show();
1542      } else {          } else {
1543          ui.fileToolbar->hide();                  m_ui.fileToolbar->hide();
1544          ui.editToolbar->hide();                  m_ui.editToolbar->hide();
1545          ui.channelsToolbar->hide();                  m_ui.channelsToolbar->hide();
1546      }          }
1547  }  }
1548    
1549    
1550  // Show/hide the main program window statusbar.  // Show/hide the main program window statusbar.
1551  void MainForm::viewStatusbar ( bool bOn )  void MainForm::viewStatusbar ( bool bOn )
1552  {  {
1553      if (bOn)          if (bOn)
1554          statusBar()->show();                  statusBar()->show();
1555      else          else
1556          statusBar()->hide();                  statusBar()->hide();
1557  }  }
1558    
1559    
1560  // Show/hide the messages window logger.  // Show/hide the messages window logger.
1561  void MainForm::viewMessages ( bool bOn )  void MainForm::viewMessages ( bool bOn )
1562  {  {
1563      if (bOn)          if (bOn)
1564          m_pMessages->show();                  m_pMessages->show();
1565      else          else
1566          m_pMessages->hide();                  m_pMessages->hide();
1567  }  }
1568    
1569    
# Line 1480  void MainForm::viewInstruments (void) Line 1580  void MainForm::viewInstruments (void)
1580                  } else {                  } else {
1581                          m_pInstrumentListForm->show();                          m_pInstrumentListForm->show();
1582                          m_pInstrumentListForm->raise();                          m_pInstrumentListForm->raise();
1583                          m_pInstrumentListForm->setActiveWindow();                          m_pInstrumentListForm->activateWindow();
1584                  }                  }
1585          }          }
1586  }  }
# Line 1499  void MainForm::viewDevices (void) Line 1599  void MainForm::viewDevices (void)
1599                  } else {                  } else {
1600                          m_pDeviceForm->show();                          m_pDeviceForm->show();
1601                          m_pDeviceForm->raise();                          m_pDeviceForm->raise();
1602                          m_pDeviceForm->setActiveWindow();                          m_pDeviceForm->activateWindow();
1603                  }                  }
1604          }          }
1605  }  }
# Line 1508  void MainForm::viewDevices (void) Line 1608  void MainForm::viewDevices (void)
1608  // Show options dialog.  // Show options dialog.
1609  void MainForm::viewOptions (void)  void MainForm::viewOptions (void)
1610  {  {
1611      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1612          return;                  return;
1613    
1614      OptionsForm* pOptionsForm = new OptionsForm(this);          OptionsForm* pOptionsForm = new OptionsForm(this);
1615      if (pOptionsForm) {          if (pOptionsForm) {
1616          // Check out some initial nullities(tm)...                  // Check out some initial nullities(tm)...
1617          ChannelStrip* pChannelStrip = activeChannelStrip();                  ChannelStrip* pChannelStrip = activeChannelStrip();
1618          if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)
1619              m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();
1620          if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)
1621              m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
1622          // To track down deferred or immediate changes.                  // To track down deferred or immediate changes.
1623          QString sOldServerHost      = m_pOptions->sServerHost;                  QString sOldServerHost      = m_pOptions->sServerHost;
1624          int     iOldServerPort      = m_pOptions->iServerPort;                  int     iOldServerPort      = m_pOptions->iServerPort;
1625          int     iOldServerTimeout   = m_pOptions->iServerTimeout;                  int     iOldServerTimeout   = m_pOptions->iServerTimeout;
1626          bool    bOldServerStart     = m_pOptions->bServerStart;                  bool    bOldServerStart     = m_pOptions->bServerStart;
1627          QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;                  QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;
1628          QString sOldDisplayFont     = m_pOptions->sDisplayFont;                  bool    bOldMessagesLog     = m_pOptions->bMessagesLog;
1629          bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;                  QString sOldMessagesLogPath = m_pOptions->sMessagesLogPath;
1630          int     iOldMaxVolume       = m_pOptions->iMaxVolume;                  QString sOldDisplayFont     = m_pOptions->sDisplayFont;
1631          QString sOldMessagesFont    = m_pOptions->sMessagesFont;                  bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;
1632          bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;                  int     iOldMaxVolume       = m_pOptions->iMaxVolume;
1633          bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;                  QString sOldMessagesFont    = m_pOptions->sMessagesFont;
1634          int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;                  bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;
1635          int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;                  bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;
1636          bool    bOldCompletePath    = m_pOptions->bCompletePath;                  int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;
1637          bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;                  int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;
1638          int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;                  bool    bOldCompletePath    = m_pOptions->bCompletePath;
1639          // Load the current setup settings.                  bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;
1640          pOptionsForm->setup(m_pOptions);                  int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;
1641          // Show the setup dialog...                  int     iOldBaseFontSize    = m_pOptions->iBaseFontSize;
1642          if (pOptionsForm->exec()) {                  // Load the current setup settings.
1643              // Warn if something will be only effective on next run.                  pOptionsForm->setup(m_pOptions);
1644              if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||                  // Show the setup dialog...
1645                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||                  if (pOptionsForm->exec()) {
1646                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||                          // Warn if something will be only effective on next run.
1647                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1648                  QMessageBox::information(this,                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||
1649                                    ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||
1650                                    (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)     ||
1651                                    (iOldBaseFontSize   !=  m_pOptions->iBaseFontSize)) {
1652                                    QMessageBox::information(this,
1653                                          QSAMPLER_TITLE ": " + tr("Information"),                                          QSAMPLER_TITLE ": " + tr("Information"),
1654                      tr("Some settings may be only effective\n"                                          tr("Some settings may be only effective\n"
1655                         "next time you start this program."), tr("OK"));                                          "next time you start this program."));
1656                  updateMessagesCapture();                                  updateMessagesCapture();
1657              }                          }
1658              // Check wheather something immediate has changed.                          // Check wheather something immediate has changed.
1659              if (( bOldCompletePath && !m_pOptions->bCompletePath) ||                          if (( bOldMessagesLog && !m_pOptions->bMessagesLog) ||
1660                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||                                  (!bOldMessagesLog &&  m_pOptions->bMessagesLog) ||
1661                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))                                  (sOldMessagesLogPath != m_pOptions->sMessagesLogPath))
1662                  updateRecentFilesMenu();                                  m_pMessages->setLogging(
1663              if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||                                          m_pOptions->bMessagesLog, m_pOptions->sMessagesLogPath);
1664                  (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||
1665                  updateInstrumentNames();                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||
1666              if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
1667                  (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))                                  updateRecentFilesMenu();
1668                  updateDisplayEffect();                          if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||
1669              if (sOldDisplayFont != m_pOptions->sDisplayFont)                                  (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))
1670                  updateDisplayFont();                                  updateInstrumentNames();
1671              if (iOldMaxVolume != m_pOptions->iMaxVolume)                          if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||
1672                  updateMaxVolume();                                  (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))
1673              if (sOldMessagesFont != m_pOptions->sMessagesFont)                                  updateDisplayEffect();
1674                  updateMessagesFont();                          if (sOldDisplayFont != m_pOptions->sDisplayFont)
1675              if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||                                  updateDisplayFont();
1676                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||                          if (iOldMaxVolume != m_pOptions->iMaxVolume)
1677                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))                                  updateMaxVolume();
1678                  updateMessagesLimit();                          if (sOldMessagesFont != m_pOptions->sMessagesFont)
1679              // And now the main thing, whether we'll do client/server recycling?                                  updateMessagesFont();
1680              if ((sOldServerHost != m_pOptions->sServerHost) ||                          if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||
1681                  (iOldServerPort != m_pOptions->iServerPort) ||                                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||
1682                  (iOldServerTimeout != m_pOptions->iServerTimeout) ||                                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))
1683                  ( bOldServerStart && !m_pOptions->bServerStart) ||                                  updateMessagesLimit();
1684                  (!bOldServerStart &&  m_pOptions->bServerStart) ||                          // And now the main thing, whether we'll do client/server recycling?
1685                  (sOldServerCmdLine != m_pOptions->sServerCmdLine && m_pOptions->bServerStart))                          if ((sOldServerHost != m_pOptions->sServerHost) ||
1686                  fileRestart();                                  (iOldServerPort != m_pOptions->iServerPort) ||
1687          }                                  (iOldServerTimeout != m_pOptions->iServerTimeout) ||
1688          // Done.                                  ( bOldServerStart && !m_pOptions->bServerStart) ||
1689          delete pOptionsForm;                                  (!bOldServerStart &&  m_pOptions->bServerStart) ||
1690      }                                  (sOldServerCmdLine != m_pOptions->sServerCmdLine
1691                                    && m_pOptions->bServerStart))
1692                                    fileRestart();
1693                    }
1694                    // Done.
1695                    delete pOptionsForm;
1696            }
1697    
1698      // This makes it.          // This makes it.
1699      stabilizeForm();          stabilizeForm();
1700  }  }
1701    
1702    
# Line 1596  void MainForm::viewOptions (void) Line 1706  void MainForm::viewOptions (void)
1706  // Arrange channel strips.  // Arrange channel strips.
1707  void MainForm::channelsArrange (void)  void MainForm::channelsArrange (void)
1708  {  {
1709      // Full width vertical tiling          // Full width vertical tiling
1710      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
1711      if (wlist.isEmpty())          if (wlist.isEmpty())
1712          return;                  return;
   
     m_pWorkspace->setUpdatesEnabled(false);  
     int y = 0;  
     for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {  
         ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);  
     /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {  
             // Prevent flicker...  
             pChannelStrip->hide();  
             pChannelStrip->showNormal();  
         }   */  
         pChannelStrip->adjustSize();  
         int iWidth  = m_pWorkspace->width();  
         if (iWidth < pChannelStrip->width())  
             iWidth = pChannelStrip->width();  
     //  int iHeight = pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();  
         int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();  
         pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);  
         y += iHeight;  
     }  
     m_pWorkspace->setUpdatesEnabled(true);  
1713    
1714      stabilizeForm();          m_pWorkspace->setUpdatesEnabled(false);
1715            int y = 0;
1716            for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1717                    ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
1718            /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {
1719                            // Prevent flicker...
1720                            pChannelStrip->hide();
1721                            pChannelStrip->showNormal();
1722                    }   */
1723                    pChannelStrip->adjustSize();
1724                    int iWidth  = m_pWorkspace->width();
1725                    if (iWidth < pChannelStrip->width())
1726                            iWidth = pChannelStrip->width();
1727            //  int iHeight = pChannelStrip->height()
1728            //              + pChannelStrip->parentWidget()->baseSize().height();
1729                    int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();
1730                    pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);
1731                    y += iHeight;
1732            }
1733            m_pWorkspace->setUpdatesEnabled(true);
1734    
1735            stabilizeForm();
1736  }  }
1737    
1738    
1739  // Auto-arrange channel strips.  // Auto-arrange channel strips.
1740  void MainForm::channelsAutoArrange ( bool bOn )  void MainForm::channelsAutoArrange ( bool bOn )
1741  {  {
1742      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1743          return;                  return;
1744    
1745      // Toggle the auto-arrange flag.          // Toggle the auto-arrange flag.
1746      m_pOptions->bAutoArrange = bOn;          m_pOptions->bAutoArrange = bOn;
1747    
1748      // If on, update whole workspace...          // If on, update whole workspace...
1749      if (m_pOptions->bAutoArrange)          if (m_pOptions->bAutoArrange)
1750          channelsArrange();                  channelsArrange();
1751  }  }
1752    
1753    
# Line 1646  void MainForm::channelsAutoArrange ( boo Line 1757  void MainForm::channelsAutoArrange ( boo
1757  // Show information about the Qt toolkit.  // Show information about the Qt toolkit.
1758  void MainForm::helpAboutQt (void)  void MainForm::helpAboutQt (void)
1759  {  {
1760      QMessageBox::aboutQt(this);          QMessageBox::aboutQt(this);
1761  }  }
1762    
1763    
1764  // Show information about application program.  // Show information about application program.
1765  void MainForm::helpAbout (void)  void MainForm::helpAbout (void)
1766  {  {
1767      // Stuff the about box text...          // Stuff the about box text...
1768      QString sText = "<p>\n";          QString sText = "<p>\n";
1769      sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";          sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";
1770      sText += "<br />\n";          sText += "<br />\n";
1771      sText += tr("Version") + ": <b>" QSAMPLER_VERSION "</b><br />\n";          sText += tr("Version") + ": <b>" QSAMPLER_VERSION "</b><br />\n";
1772      sText += "<small>" + tr("Build") + ": " __DATE__ " " __TIME__ "</small><br />\n";          sText += "<small>" + tr("Build") + ": " __DATE__ " " __TIME__ "</small><br />\n";
1773  #ifdef CONFIG_DEBUG  #ifdef CONFIG_DEBUG
1774      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1775      sText += tr("Debugging option enabled.");          sText += tr("Debugging option enabled.");
1776      sText += "</font></small><br />";          sText += "</font></small><br />";
1777  #endif  #endif
1778  #ifndef CONFIG_LIBGIG  #ifndef CONFIG_LIBGIG
1779      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1780      sText += tr("GIG (libgig) file support disabled.");          sText += tr("GIG (libgig) file support disabled.");
1781      sText += "</font></small><br />";          sText += "</font></small><br />";
1782  #endif  #endif
1783  #ifndef CONFIG_INSTRUMENT_NAME  #ifndef CONFIG_INSTRUMENT_NAME
1784      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1785      sText += tr("LSCP (liblscp) instrument_name support disabled.");          sText += tr("LSCP (liblscp) instrument_name support disabled.");
1786      sText += "</font></small><br />";          sText += "</font></small><br />";
1787  #endif  #endif
1788  #ifndef CONFIG_MUTE_SOLO  #ifndef CONFIG_MUTE_SOLO
1789      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1790      sText += tr("Sampler channel Mute/Solo support disabled.");          sText += tr("Sampler channel Mute/Solo support disabled.");
1791      sText += "</font></small><br />";          sText += "</font></small><br />";
1792  #endif  #endif
1793  #ifndef CONFIG_AUDIO_ROUTING  #ifndef CONFIG_AUDIO_ROUTING
1794      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1795      sText += tr("LSCP (liblscp) audio_routing support disabled.");          sText += tr("LSCP (liblscp) audio_routing support disabled.");
1796      sText += "</font></small><br />";          sText += "</font></small><br />";
1797  #endif  #endif
1798  #ifndef CONFIG_FXSEND  #ifndef CONFIG_FXSEND
1799      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1800      sText += tr("Sampler channel Effect Sends support disabled.");          sText += tr("Sampler channel Effect Sends support disabled.");
1801      sText += "</font></small><br />";          sText += "</font></small><br />";
1802  #endif  #endif
1803  #ifndef CONFIG_VOLUME  #ifndef CONFIG_VOLUME
1804      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1805      sText += tr("Global volume support disabled.");          sText += tr("Global volume support disabled.");
1806      sText += "</font></small><br />";          sText += "</font></small><br />";
1807  #endif  #endif
1808  #ifndef CONFIG_MIDI_INSTRUMENT  #ifndef CONFIG_MIDI_INSTRUMENT
1809      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1810      sText += tr("MIDI instrument mapping support disabled.");          sText += tr("MIDI instrument mapping support disabled.");
1811      sText += "</font></small><br />";          sText += "</font></small><br />";
1812  #endif  #endif
1813  #ifndef CONFIG_EDIT_INSTRUMENT  #ifndef CONFIG_EDIT_INSTRUMENT
1814      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1815      sText += tr("Instrument editing support disabled.");          sText += tr("Instrument editing support disabled.");
1816      sText += "</font></small><br />";          sText += "</font></small><br />";
1817  #endif  #endif
1818      sText += "<br />\n";  #ifndef CONFIG_EVENT_CHANNEL_MIDI
1819      sText += tr("Using") + ": ";          sText += "<small><font color=\"red\">";
1820      sText += ::lscp_client_package();          sText += tr("Channel MIDI event support disabled.");
1821      sText += " ";          sText += "</font></small><br />";
1822      sText += ::lscp_client_version();  #endif
1823    #ifndef CONFIG_EVENT_DEVICE_MIDI
1824            sText += "<small><font color=\"red\">";
1825            sText += tr("Device MIDI event support disabled.");
1826            sText += "</font></small><br />";
1827    #endif
1828    #ifndef CONFIG_MAX_VOICES
1829            sText += "<small><font color=\"red\">";
1830            sText += tr("Runtime max. voices / disk streams support disabled.");
1831            sText += "</font></small><br />";
1832    #endif
1833            sText += "<br />\n";
1834            sText += tr("Using") + ": ";
1835            sText += ::lscp_client_package();
1836            sText += " ";
1837            sText += ::lscp_client_version();
1838  #ifdef CONFIG_LIBGIG  #ifdef CONFIG_LIBGIG
1839      sText += ", ";          sText += ", ";
1840      sText += gig::libraryName().c_str();          sText += gig::libraryName().c_str();
1841      sText += " ";          sText += " ";
1842      sText += gig::libraryVersion().c_str();          sText += gig::libraryVersion().c_str();
1843  #endif  #endif
1844      sText += "<br />\n";          sText += "<br />\n";
1845      sText += "<br />\n";          sText += "<br />\n";
1846      sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";          sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";
1847      sText += "<br />\n";          sText += "<br />\n";
1848      sText += "<small>";          sText += "<small>";
1849      sText += QSAMPLER_COPYRIGHT "<br />\n";          sText += QSAMPLER_COPYRIGHT "<br />\n";
1850      sText += QSAMPLER_COPYRIGHT2 "<br />\n";          sText += QSAMPLER_COPYRIGHT2 "<br />\n";
1851      sText += "<br />\n";          sText += "<br />\n";
1852      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";
1853      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.");
1854      sText += "</small>";          sText += "</small>";
1855      sText += "</p>\n";          sText += "</p>\n";
1856    
1857      QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);          QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);
1858  }  }
1859    
1860    
# Line 1737  void MainForm::helpAbout (void) Line 1863  void MainForm::helpAbout (void)
1863    
1864  void MainForm::stabilizeForm (void)  void MainForm::stabilizeForm (void)
1865  {  {
1866      // Update the main application caption...          // Update the main application caption...
1867      QString sSessionName = sessionName(m_sFilename);          QString sSessionName = sessionName(m_sFilename);
1868      if (m_iDirtyCount > 0)          if (m_iDirtyCount > 0)
1869          sSessionName += " *";                  sSessionName += " *";
1870      setCaption(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));
1871    
1872      // Update the main menu state...          // Update the main menu state...
1873      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1874      bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);          bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);
1875      bool bHasChannel = (bHasClient && pChannelStrip != NULL);          bool bHasChannel = (bHasClient && pChannelStrip != NULL);
1876      ui.fileNewAction->setEnabled(bHasClient);          m_ui.fileNewAction->setEnabled(bHasClient);
1877      ui.fileOpenAction->setEnabled(bHasClient);          m_ui.fileOpenAction->setEnabled(bHasClient);
1878      ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
1879      ui.fileSaveAsAction->setEnabled(bHasClient);          m_ui.fileSaveAsAction->setEnabled(bHasClient);
1880      ui.fileResetAction->setEnabled(bHasClient);          m_ui.fileResetAction->setEnabled(bHasClient);
1881      ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);          m_ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);
1882      ui.editAddChannelAction->setEnabled(bHasClient);          m_ui.editAddChannelAction->setEnabled(bHasClient);
1883      ui.editRemoveChannelAction->setEnabled(bHasChannel);          m_ui.editRemoveChannelAction->setEnabled(bHasChannel);
1884      ui.editSetupChannelAction->setEnabled(bHasChannel);          m_ui.editSetupChannelAction->setEnabled(bHasChannel);
1885  #ifdef CONFIG_EDIT_INSTRUMENT  #ifdef CONFIG_EDIT_INSTRUMENT
1886      ui.editEditChannelAction->setEnabled(bHasChannel);          m_ui.editEditChannelAction->setEnabled(bHasChannel);
1887  #else  #else
1888      ui.editEditChannelAction->setEnabled(false);          m_ui.editEditChannelAction->setEnabled(false);
1889  #endif  #endif
1890      ui.editResetChannelAction->setEnabled(bHasChannel);          m_ui.editResetChannelAction->setEnabled(bHasChannel);
1891      ui.editResetAllChannelsAction->setEnabled(bHasChannel);          m_ui.editResetAllChannelsAction->setEnabled(bHasChannel);
1892      ui.viewMessagesAction->setOn(m_pMessages && m_pMessages->isVisible());          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());
1893  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
1894          ui.viewInstrumentsAction->setOn(m_pInstrumentListForm          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm
1895                  && m_pInstrumentListForm->isVisible());                  && m_pInstrumentListForm->isVisible());
1896          ui.viewInstrumentsAction->setEnabled(bHasClient);          m_ui.viewInstrumentsAction->setEnabled(bHasClient);
1897  #else  #else
1898          ui.viewInstrumentsAction->setEnabled(false);          m_ui.viewInstrumentsAction->setEnabled(false);
1899  #endif  #endif
1900          ui.viewDevicesAction->setOn(m_pDeviceForm          m_ui.viewDevicesAction->setChecked(m_pDeviceForm
1901                  && m_pDeviceForm->isVisible());                  && m_pDeviceForm->isVisible());
1902      ui.viewDevicesAction->setEnabled(bHasClient);          m_ui.viewDevicesAction->setEnabled(bHasClient);
1903      ui.channelsArrangeAction->setEnabled(bHasChannel);          m_ui.channelsArrangeAction->setEnabled(bHasChannel);
1904    
1905  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
1906          // Toolbar widgets are also affected...          // Toolbar widgets are also affected...
1907      m_pVolumeSlider->setEnabled(bHasClient);          m_pVolumeSlider->setEnabled(bHasClient);
1908      m_pVolumeSpinBox->setEnabled(bHasClient);          m_pVolumeSpinBox->setEnabled(bHasClient);
1909  #endif  #endif
1910    
1911      // Client/Server status...          // Client/Server status...
1912      if (bHasClient) {          if (bHasClient) {
1913          m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));                  m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));
1914          m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost + ":" + QString::number(m_pOptions->iServerPort));                  m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost
1915      } else {                          + ':' + QString::number(m_pOptions->iServerPort));
1916          m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();          } else {
1917          m_statusItem[QSAMPLER_STATUS_SERVER]->clear();                  m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();
1918      }                  m_statusItem[QSAMPLER_STATUS_SERVER]->clear();
1919      // Channel status...          }
1920      if (bHasChannel)          // Channel status...
1921          m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->caption());          if (bHasChannel)
1922      else                  m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->windowTitle());
1923          m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();          else
1924      // Session status...                  m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();
1925      if (m_iDirtyCount > 0)          // Session status...
1926          m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));          if (m_iDirtyCount > 0)
1927      else                  m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));
1928          m_statusItem[QSAMPLER_STATUS_SESSION]->clear();          else
1929                    m_statusItem[QSAMPLER_STATUS_SESSION]->clear();
1930    
1931      // Recent files menu.          // Recent files menu.
1932      m_pRecentFilesMenu->setEnabled(bHasClient && m_pOptions->recentFiles.count() > 0);          m_ui.fileOpenRecentMenu->setEnabled(m_pOptions->recentFiles.count() > 0);
1933  }  }
1934    
1935    
# Line 1842  void MainForm::volumeChanged ( int iVolu Line 1969  void MainForm::volumeChanged ( int iVolu
1969  void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)  void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)
1970  {  {
1971          // Add this strip to the changed list...          // Add this strip to the changed list...
1972          if (m_changedStrips.containsRef(pChannelStrip) == 0) {          if (!m_changedStrips.contains(pChannelStrip)) {
1973                  m_changedStrips.append(pChannelStrip);                  m_changedStrips.append(pChannelStrip);
1974                  pChannelStrip->resetErrorCount();                  pChannelStrip->resetErrorCount();
1975          }          }
1976    
1977      // Just mark the dirty form.          // Just mark the dirty form.
1978      m_iDirtyCount++;          m_iDirtyCount++;
1979      // and update the form status...          // and update the form status...
1980      stabilizeForm();          stabilizeForm();
1981  }  }
1982    
1983    
# Line 1870  void MainForm::updateSession (void) Line 1997  void MainForm::updateSession (void)
1997          if (iMaps < 0)          if (iMaps < 0)
1998                  appendMessagesClient("lscp_get_midi_instrument_maps");                  appendMessagesClient("lscp_get_midi_instrument_maps");
1999          else if (iMaps < 1) {          else if (iMaps < 1) {
2000                  ::lscp_add_midi_instrument_map(m_pClient, tr("Chromatic").latin1());                  ::lscp_add_midi_instrument_map(m_pClient,
2001                  ::lscp_add_midi_instrument_map(m_pClient, tr("Drum Kits").latin1());                          tr("Chromatic").toUtf8().constData());
2002                    ::lscp_add_midi_instrument_map(m_pClient,
2003                            tr("Drum Kits").toUtf8().constData());
2004          }          }
2005  #endif  #endif
2006    
2007            updateAllChannelStrips(false);
2008    
2009            // Do we auto-arrange?
2010            if (m_pOptions && m_pOptions->bAutoArrange)
2011                    channelsArrange();
2012    
2013            // Remember to refresh devices and instruments...
2014            if (m_pInstrumentListForm)
2015                    m_pInstrumentListForm->refreshInstruments();
2016            if (m_pDeviceForm)
2017                    m_pDeviceForm->refreshDevices();
2018    }
2019    
2020    void MainForm::updateAllChannelStrips(bool bRemoveDeadStrips) {
2021          // Retrieve the current channel list.          // Retrieve the current channel list.
2022          int *piChannelIDs = ::lscp_list_channels(m_pClient);          int *piChannelIDs = ::lscp_list_channels(m_pClient);
2023          if (piChannelIDs == NULL) {          if (piChannelIDs == NULL) {
2024                  if (::lscp_client_get_errno(m_pClient)) {                  if (::lscp_client_get_errno(m_pClient)) {
2025                          appendMessagesClient("lscp_list_channels");                          appendMessagesClient("lscp_list_channels");
2026                          appendMessagesError(tr("Could not get current list of channels.\n\nSorry."));                          appendMessagesError(
2027                                    tr("Could not get current list of channels.\n\nSorry."));
2028                  }                  }
2029          } else {          } else {
2030                  // Try to (re)create each channel.                  // Try to (re)create each channel.
# Line 1888  void MainForm::updateSession (void) Line 2032  void MainForm::updateSession (void)
2032                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {
2033                          // Check if theres already a channel strip for this one...                          // Check if theres already a channel strip for this one...
2034                          if (!channelStrip(piChannelIDs[iChannel]))                          if (!channelStrip(piChannelIDs[iChannel]))
2035                                  createChannelStrip(new qsamplerChannel(piChannelIDs[iChannel]));                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));
2036                    }
2037    
2038                    // Do we auto-arrange?
2039                    if (m_pOptions && m_pOptions->bAutoArrange)
2040                            channelsArrange();
2041    
2042                    stabilizeForm();
2043    
2044                    // remove dead channel strips
2045                    if (bRemoveDeadStrips) {
2046                            for (int i = 0; channelStripAt(i); ++i) {
2047                                    ChannelStrip* pChannelStrip = channelStripAt(i);
2048                                    bool bExists = false;
2049                                    for (int j = 0; piChannelIDs[j] >= 0; ++j) {
2050                                            if (!pChannelStrip->channel()) break;
2051                                            if (piChannelIDs[j] == pChannelStrip->channel()->channelID()) {
2052                                                    // strip exists, don't touch it
2053                                                    bExists = true;
2054                                                    break;
2055                                            }
2056                                    }
2057                                    if (!bExists) destroyChannelStrip(pChannelStrip);
2058                            }
2059                  }                  }
2060                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
2061          }          }
   
     // 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();  
2062  }  }
2063    
   
2064  // Update the recent files list and menu.  // Update the recent files list and menu.
2065  void MainForm::updateRecentFiles ( const QString& sFilename )  void MainForm::updateRecentFiles ( const QString& sFilename )
2066  {  {
2067      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2068          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);  
2069    
2070      // May update the menu.          // Remove from list if already there (avoid duplicates)
2071      updateRecentFilesMenu();          int iIndex = m_pOptions->recentFiles.indexOf(sFilename);
2072            if (iIndex >= 0)
2073                    m_pOptions->recentFiles.removeAt(iIndex);
2074            // Put it to front...
2075            m_pOptions->recentFiles.push_front(sFilename);
2076  }  }
2077    
2078    
2079  // Update the recent files list and menu.  // Update the recent files list and menu.
2080  void MainForm::updateRecentFilesMenu (void)  void MainForm::updateRecentFilesMenu (void)
2081  {  {
2082      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2083          return;                  return;
2084    
2085      // Time to keep the list under limits.          // Time to keep the list under limits.
2086      int iRecentFiles = m_pOptions->recentFiles.count();          int iRecentFiles = m_pOptions->recentFiles.count();
2087      while (iRecentFiles > m_pOptions->iMaxRecentFiles) {          while (iRecentFiles > m_pOptions->iMaxRecentFiles) {
2088          m_pOptions->recentFiles.pop_back();                  m_pOptions->recentFiles.pop_back();
2089          iRecentFiles--;                  iRecentFiles--;
2090      }          }
2091    
2092      // rebuild the recent files menu...          // Rebuild the recent files menu...
2093      m_pRecentFilesMenu->clear();          m_ui.fileOpenRecentMenu->clear();
2094      for (int i = 0; i < iRecentFiles; i++) {          for (int i = 0; i < iRecentFiles; i++) {
2095          const QString& sFilename = m_pOptions->recentFiles[i];                  const QString& sFilename = m_pOptions->recentFiles[i];
2096          if (QFileInfo(sFilename).exists()) {                  if (QFileInfo(sFilename).exists()) {
2097              m_pRecentFilesMenu->insertItem(QString("&%1 %2")                          QAction *pAction = m_ui.fileOpenRecentMenu->addAction(
2098                  .arg(i + 1).arg(sessionName(sFilename)),                                  QString("&%1 %2").arg(i + 1).arg(sessionName(sFilename)),
2099                  this, SLOT(fileOpenRecent(int)), 0, i);                                  this, SLOT(fileOpenRecent()));
2100          }                          pAction->setData(i);
2101      }                  }
2102            }
2103  }  }
2104    
2105    
2106  // Force update of the channels instrument names mode.  // Force update of the channels instrument names mode.
2107  void MainForm::updateInstrumentNames (void)  void MainForm::updateInstrumentNames (void)
2108  {  {
2109      // Full channel list update...          // Full channel list update...
2110      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2111      if (wlist.isEmpty())          if (wlist.isEmpty())
2112          return;                  return;
2113    
2114      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2115      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2116          ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);                  ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);
2117          if (pChannelStrip)                  if (pChannelStrip)
2118              pChannelStrip->updateInstrumentName(true);                          pChannelStrip->updateInstrumentName(true);
2119      }          }
2120      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2121  }  }
2122    
2123    
2124  // Force update of the channels display font.  // Force update of the channels display font.
2125  void MainForm::updateDisplayFont (void)  void MainForm::updateDisplayFont (void)
2126  {  {
2127      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2128          return;                  return;
2129    
2130            // Check if display font is legal.
2131            if (m_pOptions->sDisplayFont.isEmpty())
2132                    return;
2133            // Realize it.
2134            QFont font;
2135            if (!font.fromString(m_pOptions->sDisplayFont))
2136                    return;
2137    
2138      // Check if display font is legal.          // Full channel list update...
2139      if (m_pOptions->sDisplayFont.isEmpty())          QWidgetList wlist = m_pWorkspace->windowList();
2140          return;          if (wlist.isEmpty())
2141      // Realize it.                  return;
2142      QFont font;  
2143      if (!font.fromString(m_pOptions->sDisplayFont))          m_pWorkspace->setUpdatesEnabled(false);
2144          return;          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2145                    ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2146      // Full channel list update...                  if (pChannelStrip)
2147      QWidgetList wlist = m_pWorkspace->windowList();                          pChannelStrip->setDisplayFont(font);
2148      if (wlist.isEmpty())          }
2149          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);  
2150  }  }
2151    
2152    
2153  // Update channel strips background effect.  // Update channel strips background effect.
2154  void MainForm::updateDisplayEffect (void)  void MainForm::updateDisplayEffect (void)
2155  {  {
2156     QPixmap pm;          // Full channel list update...
2157      if (m_pOptions->bDisplayEffect)          QWidgetList wlist = m_pWorkspace->windowList();
2158          pm = QPixmap(":/qsampler/pixmaps/displaybg1.png");          if (wlist.isEmpty())
2159                    return;
2160      // Full channel list update...  
2161      QWidgetList wlist = m_pWorkspace->windowList();          m_pWorkspace->setUpdatesEnabled(false);
2162      if (wlist.isEmpty())          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2163          return;                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2164                    if (pChannelStrip)
2165      m_pWorkspace->setUpdatesEnabled(false);                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2166      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          }
2167          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);          m_pWorkspace->setUpdatesEnabled(true);
         if (pChannelStrip)  
             pChannelStrip->setDisplayBackground(pm);  
     }  
     m_pWorkspace->setUpdatesEnabled(true);  
2168  }  }
2169    
2170    
2171  // Force update of the channels maximum volume setting.  // Force update of the channels maximum volume setting.
2172  void MainForm::updateMaxVolume (void)  void MainForm::updateMaxVolume (void)
2173  {  {
2174      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2175          return;                  return;
2176    
2177  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2178          m_iVolumeChanging++;          m_iVolumeChanging++;
2179          m_pVolumeSlider->setMaxValue(m_pOptions->iMaxVolume);          m_pVolumeSlider->setMaximum(m_pOptions->iMaxVolume);
2180          m_pVolumeSpinBox->setMaxValue(m_pOptions->iMaxVolume);          m_pVolumeSpinBox->setMaximum(m_pOptions->iMaxVolume);
2181          m_iVolumeChanging--;          m_iVolumeChanging--;
2182  #endif  #endif
2183    
2184      // Full channel list update...          // Full channel list update...
2185      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2186      if (wlist.isEmpty())          if (wlist.isEmpty())
2187          return;                  return;
2188    
2189      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2190      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2191          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2192          if (pChannelStrip)                  if (pChannelStrip)
2193              pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                          pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2194      }          }
2195      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2196  }  }
2197    
2198    
# Line 2052  void MainForm::updateMaxVolume (void) Line 2202  void MainForm::updateMaxVolume (void)
2202  // Messages output methods.  // Messages output methods.
2203  void MainForm::appendMessages( const QString& s )  void MainForm::appendMessages( const QString& s )
2204  {  {
2205      if (m_pMessages)          if (m_pMessages)
2206          m_pMessages->appendMessages(s);                  m_pMessages->appendMessages(s);
2207    
2208      statusBar()->message(s, 3000);          statusBar()->showMessage(s, 3000);
2209  }  }
2210    
2211  void MainForm::appendMessagesColor( const QString& s, const QString& c )  void MainForm::appendMessagesColor( const QString& s, const QString& c )
2212  {  {
2213      if (m_pMessages)          if (m_pMessages)
2214          m_pMessages->appendMessagesColor(s, c);                  m_pMessages->appendMessagesColor(s, c);
2215    
2216      statusBar()->message(s, 3000);          statusBar()->showMessage(s, 3000);
2217  }  }
2218    
2219  void MainForm::appendMessagesText( const QString& s )  void MainForm::appendMessagesText( const QString& s )
2220  {  {
2221      if (m_pMessages)          if (m_pMessages)
2222          m_pMessages->appendMessagesText(s);                  m_pMessages->appendMessagesText(s);
2223  }  }
2224    
2225  void MainForm::appendMessagesError( const QString& s )  void MainForm::appendMessagesError( const QString& s )
2226  {  {
2227      if (m_pMessages)          if (m_pMessages)
2228          m_pMessages->show();                  m_pMessages->show();
2229    
2230      appendMessagesColor(s.simplified(), "#ff0000");          appendMessagesColor(s.simplified(), "#ff0000");
2231    
2232          // Make it look responsive...:)          // Make it look responsive...:)
2233          QApplication::processEvents(QEventLoop::ExcludeUserInput);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2234    
2235      QMessageBox::critical(this,          QMessageBox::critical(this,
2236                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));                  QSAMPLER_TITLE ": " + tr("Error"), s, QMessageBox::Cancel);
2237  }  }
2238    
2239    
2240  // This is a special message format, just for client results.  // This is a special message format, just for client results.
2241  void MainForm::appendMessagesClient( const QString& s )  void MainForm::appendMessagesClient( const QString& s )
2242  {  {
2243      if (m_pClient == NULL)          if (m_pClient == NULL)
2244          return;                  return;
2245    
2246      appendMessagesColor(s + QString(": %1 (errno=%2)")          appendMessagesColor(s + QString(": %1 (errno=%2)")
2247          .arg(::lscp_client_get_result(m_pClient))                  .arg(::lscp_client_get_result(m_pClient))
2248          .arg(::lscp_client_get_errno(m_pClient)), "#996666");                  .arg(::lscp_client_get_errno(m_pClient)), "#996666");
2249    
2250          // Make it look responsive...:)          // Make it look responsive...:)
2251          QApplication::processEvents(QEventLoop::ExcludeUserInput);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2252  }  }
2253    
2254    
2255  // Force update of the messages font.  // Force update of the messages font.
2256  void MainForm::updateMessagesFont (void)  void MainForm::updateMessagesFont (void)
2257  {  {
2258      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2259          return;                  return;
2260    
2261      if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {          if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {
2262          QFont font;                  QFont font;
2263          if (font.fromString(m_pOptions->sMessagesFont))                  if (font.fromString(m_pOptions->sMessagesFont))
2264              m_pMessages->setMessagesFont(font);                          m_pMessages->setMessagesFont(font);
2265      }          }
2266  }  }
2267    
2268    
2269  // Update messages window line limit.  // Update messages window line limit.
2270  void MainForm::updateMessagesLimit (void)  void MainForm::updateMessagesLimit (void)
2271  {  {
2272      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2273          return;                  return;
2274    
2275      if (m_pMessages) {          if (m_pMessages) {
2276          if (m_pOptions->bMessagesLimit)                  if (m_pOptions->bMessagesLimit)
2277              m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);                          m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);
2278          else                  else
2279              m_pMessages->setMessagesLimit(-1);                          m_pMessages->setMessagesLimit(-1);
2280      }          }
2281  }  }
2282    
2283    
2284  // Enablement of the messages capture feature.  // Enablement of the messages capture feature.
2285  void MainForm::updateMessagesCapture (void)  void MainForm::updateMessagesCapture (void)
2286  {  {
2287      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2288          return;                  return;
2289    
2290      if (m_pMessages)          if (m_pMessages)
2291          m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);                  m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);
2292  }  }
2293    
2294    
# Line 2146  void MainForm::updateMessagesCapture (vo Line 2296  void MainForm::updateMessagesCapture (vo
2296  // qsamplerMainForm -- MDI channel strip management.  // qsamplerMainForm -- MDI channel strip management.
2297    
2298  // The channel strip creation executive.  // The channel strip creation executive.
2299  ChannelStrip* MainForm::createChannelStrip(qsamplerChannel* pChannel)  ChannelStrip* MainForm::createChannelStrip ( Channel *pChannel )
2300  {  {
2301      if (m_pClient == NULL || pChannel == NULL)          if (m_pClient == NULL || pChannel == NULL)
2302          return NULL;                  return NULL;
2303    
2304      // Prepare for auto-arrange?          // Add a new channel itema...
2305      ChannelStrip* pChannelStrip = NULL;          ChannelStrip *pChannelStrip = new ChannelStrip();
2306      int y = 0;          if (pChannelStrip == NULL)
2307      if (m_pOptions && m_pOptions->bAutoArrange) {                  return NULL;
2308          QWidgetList wlist = m_pWorkspace->windowList();  
2309          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          // Set some initial channel strip options...
2310              pChannelStrip = (ChannelStrip *) wlist.at(iChannel);          if (m_pOptions) {
2311                          if (pChannelStrip) {                  // Background display effect...
2312                          //  y += pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2313                                  y += pChannelStrip->parentWidget()->frameGeometry().height();                  // We'll need a display font.
2314                          }                  QFont font;
2315          }                  if (font.fromString(m_pOptions->sDisplayFont))
2316      }                          pChannelStrip->setDisplayFont(font);
2317                    // Maximum allowed volume setting.
2318                    pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2319            }
2320    
2321      // Add a new channel itema...          // Add it to workspace...
2322      pChannelStrip = new ChannelStrip();          m_pWorkspace->addWindow(pChannelStrip, Qt::FramelessWindowHint);
     if (pChannelStrip == NULL)  
         return NULL;  
2323    
2324      m_pWorkspace->addWindow(pChannelStrip, Qt::Tool);          // Actual channel strip setup...
2325            pChannelStrip->setup(pChannel);
2326    
     // Actual channel strip setup...  
     pChannelStrip->setup(pChannel);  
2327          QObject::connect(pChannelStrip,          QObject::connect(pChannelStrip,
2328                  SIGNAL(channelChanged(ChannelStrip*)),                  SIGNAL(channelChanged(ChannelStrip*)),
2329                  SLOT(channelStripChanged(ChannelStrip*)));                  SLOT(channelStripChanged(ChannelStrip*)));
2330      // Set some initial aesthetic options...  
2331      if (m_pOptions) {          // Now we show up us to the world.
2332          // 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);  
     }  
2333    
2334          // This is pretty new, so we'll watch for it closely.          // This is pretty new, so we'll watch for it closely.
2335          channelStripChanged(pChannelStrip);          channelStripChanged(pChannelStrip);
2336    
2337      // Return our successful reference...          // Return our successful reference...
2338      return pChannelStrip;          return pChannelStrip;
2339  }  }
2340    
2341    void MainForm::destroyChannelStrip(ChannelStrip* pChannelStrip) {
2342            // Just delete the channel strip.
2343            delete pChannelStrip;
2344    
2345            // Do we auto-arrange?
2346            if (m_pOptions && m_pOptions->bAutoArrange)
2347                    channelsArrange();
2348    
2349            stabilizeForm();
2350    }
2351    
2352  // Retrieve the active channel strip.  // Retrieve the active channel strip.
2353  ChannelStrip* MainForm::activeChannelStrip (void)  ChannelStrip* MainForm::activeChannelStrip (void)
2354  {  {
2355      return (ChannelStrip*) m_pWorkspace->activeWindow();          return static_cast<ChannelStrip *> (m_pWorkspace->activeWindow());
2356  }  }
2357    
2358    
2359  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
2360  ChannelStrip* MainForm::channelStripAt ( int iChannel )  ChannelStrip* MainForm::channelStripAt ( int iChannel )
2361  {  {
2362      QWidgetList wlist = m_pWorkspace->windowList();          if (!m_pWorkspace) return NULL;
2363      if (wlist.isEmpty())  
2364          return NULL;          QWidgetList wlist = m_pWorkspace->windowList();
2365            if (wlist.isEmpty())
2366                    return NULL;
2367    
2368      return (ChannelStrip*) wlist.at(iChannel);          if (iChannel < 0 || iChannel >= wlist.size())
2369                    return NULL;
2370    
2371            return dynamic_cast<ChannelStrip *> (wlist.at(iChannel));
2372  }  }
2373    
2374    
# Line 2232  ChannelStrip* MainForm::channelStrip ( i Line 2380  ChannelStrip* MainForm::channelStrip ( i
2380                  return NULL;                  return NULL;
2381    
2382          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2383                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip
2384                            = static_cast<ChannelStrip*> (wlist.at(iChannel));
2385                  if (pChannelStrip) {                  if (pChannelStrip) {
2386                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
2387                          if (pChannel && pChannel->channelID() == iChannelID)                          if (pChannel && pChannel->channelID() == iChannelID)
2388                                  return pChannelStrip;                                  return pChannelStrip;
2389                  }                  }
# Line 2248  ChannelStrip* MainForm::channelStrip ( i Line 2397  ChannelStrip* MainForm::channelStrip ( i
2397  // Construct the windows menu.  // Construct the windows menu.
2398  void MainForm::channelsMenuAboutToShow (void)  void MainForm::channelsMenuAboutToShow (void)
2399  {  {
2400      ui.channelsMenu->clear();          m_ui.channelsMenu->clear();
2401      ui.channelsArrangeAction->addTo(ui.channelsMenu);          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);
2402      ui.channelsAutoArrangeAction->addTo(ui.channelsMenu);          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);
2403    
2404      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2405      if (!wlist.isEmpty()) {          if (!wlist.isEmpty()) {
2406          ui.channelsMenu->insertSeparator();                  m_ui.channelsMenu->addSeparator();
2407          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2408              ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                          ChannelStrip* pChannelStrip
2409              if (pChannelStrip) {                                  = static_cast<ChannelStrip*> (wlist.at(iChannel));
2410                  int iItemID = ui.channelsMenu->insertItem(pChannelStrip->caption(), this, SLOT(channelsMenuActivated(int)));                          if (pChannelStrip) {
2411                  ui.channelsMenu->setItemParameter(iItemID, iChannel);                                  QAction *pAction = m_ui.channelsMenu->addAction(
2412                  ui.channelsMenu->setItemChecked(iItemID, activeChannelStrip() == pChannelStrip);                                          pChannelStrip->windowTitle(),
2413              }                                          this, SLOT(channelsMenuActivated()));
2414          }                                  pAction->setCheckable(true);
2415      }                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);
2416                                    pAction->setData(iChannel);
2417                            }
2418                    }
2419            }
2420  }  }
2421    
2422    
2423  // Windows menu activation slot  // Windows menu activation slot
2424  void MainForm::channelsMenuActivated ( int iChannel )  void MainForm::channelsMenuActivated (void)
2425  {  {
2426      ChannelStrip* pChannelStrip = channelStripAt(iChannel);          // Retrive channel index from action data...
2427      if (pChannelStrip)          QAction *pAction = qobject_cast<QAction *> (sender());
2428          pChannelStrip->showNormal();          if (pAction == NULL)
2429      pChannelStrip->setFocus();                  return;
2430    
2431            ChannelStrip* pChannelStrip = channelStripAt(pAction->data().toInt());
2432            if (pChannelStrip) {
2433                    pChannelStrip->showNormal();
2434                    pChannelStrip->setFocus();
2435            }
2436  }  }
2437    
2438    
# Line 2283  void MainForm::channelsMenuActivated ( i Line 2442  void MainForm::channelsMenuActivated ( i
2442  // Set the pseudo-timer delay schedule.  // Set the pseudo-timer delay schedule.
2443  void MainForm::startSchedule ( int iStartDelay )  void MainForm::startSchedule ( int iStartDelay )
2444  {  {
2445      m_iStartDelay  = 1 + (iStartDelay * 1000);          m_iStartDelay  = 1 + (iStartDelay * 1000);
2446      m_iTimerDelay  = 0;          m_iTimerDelay  = 0;
2447  }  }
2448    
2449  // Suspend the pseudo-timer delay schedule.  // Suspend the pseudo-timer delay schedule.
2450  void MainForm::stopSchedule (void)  void MainForm::stopSchedule (void)
2451  {  {
2452      m_iStartDelay  = 0;          m_iStartDelay  = 0;
2453      m_iTimerDelay  = 0;          m_iTimerDelay  = 0;
2454  }  }
2455    
2456  // Timer slot funtion.  // Timer slot funtion.
2457  void MainForm::timerSlot (void)  void MainForm::timerSlot (void)
2458  {  {
2459      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2460          return;                  return;
2461    
2462      // Is it the first shot on server start after a few delay?          // Is it the first shot on server start after a few delay?
2463      if (m_iTimerDelay < m_iStartDelay) {          if (m_iTimerDelay < m_iStartDelay) {
2464          m_iTimerDelay += QSAMPLER_TIMER_MSECS;                  m_iTimerDelay += QSAMPLER_TIMER_MSECS;
2465          if (m_iTimerDelay >= m_iStartDelay) {                  if (m_iTimerDelay >= m_iStartDelay) {
2466              // If we cannot start it now, maybe a lil'mo'later ;)                          // If we cannot start it now, maybe a lil'mo'later ;)
2467              if (!startClient()) {                          if (!startClient()) {
2468                  m_iStartDelay += m_iTimerDelay;                                  m_iStartDelay += m_iTimerDelay;
2469                  m_iTimerDelay  = 0;                                  m_iTimerDelay  = 0;
2470              }                          }
2471          }                  }
2472      }          }
2473    
2474          if (m_pClient) {          if (m_pClient) {
2475                  // Update the channel information for each pending strip...                  // Update the channel information for each pending strip...
2476                  if (m_changedStrips.count() > 0) {                  QListIterator<ChannelStrip *> iter(m_changedStrips);
2477                          for (ChannelStrip* pChannelStrip = m_changedStrips.first();                  while (iter.hasNext()) {
2478                                          pChannelStrip; pChannelStrip = m_changedStrips.next()) {                          ChannelStrip *pChannelStrip = iter.next();
2479                                  // If successfull, remove from pending list...                          // If successfull, remove from pending list...
2480                                  if (pChannelStrip->updateChannelInfo())                          if (pChannelStrip->updateChannelInfo()) {
2481                                          m_changedStrips.remove(pChannelStrip);                                  int iChannelStrip = m_changedStrips.indexOf(pChannelStrip);
2482                                    if (iChannelStrip >= 0)
2483                                            m_changedStrips.removeAt(iChannelStrip);
2484                          }                          }
2485                  }                  }
2486                  // Refresh each channel usage, on each period...                  // Refresh each channel usage, on each period...
# Line 2340  void MainForm::timerSlot (void) Line 2501  void MainForm::timerSlot (void)
2501                  }                  }
2502          }          }
2503    
2504      // Register the next timer slot.          // Register the next timer slot.
2505      QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));          QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
2506  }  }
2507    
2508    
# Line 2351  void MainForm::timerSlot (void) Line 2512  void MainForm::timerSlot (void)
2512  // Start linuxsampler server...  // Start linuxsampler server...
2513  void MainForm::startServer (void)  void MainForm::startServer (void)
2514  {  {
2515      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2516          return;                  return;
2517    
2518      // Aren't already a client, are we?          // Aren't already a client, are we?
2519      if (!m_pOptions->bServerStart || m_pClient)          if (!m_pOptions->bServerStart || m_pClient)
2520          return;                  return;
2521    
2522      // Is the server process instance still here?          // Is the server process instance still here?
2523      if (m_pServer) {          if (m_pServer) {
2524          switch (QMessageBox::warning(this,                  if (QMessageBox::warning(this,
2525                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
2526              tr("Could not start the LinuxSampler server.\n\n"                          tr("Could not start the LinuxSampler server.\n\n"
2527                 "Maybe it ss already started."),                          "Maybe it is already started."),
2528              tr("Stop"), tr("Kill"), tr("Cancel"))) {                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
2529            case 0:                          m_pServer->terminate();
2530              m_pServer->terminate();                          m_pServer->kill();
2531              break;                  }
2532            case 1:                  return;
2533              m_pServer->kill();          }
2534              break;  
2535          }          // Reset our timer counters...
2536          return;          stopSchedule();
2537      }  
2538            // Verify we have something to start with...
2539      // Reset our timer counters...          if (m_pOptions->sServerCmdLine.isEmpty())
2540      stopSchedule();                  return;
2541    
2542      // OK. Let's build the startup process...          // OK. Let's build the startup process...
2543      m_pServer = new QProcess(this);          m_pServer = new QProcess();
2544            bForceServerStop = true;
2545      // Setup stdout/stderr capture...  
2546          //      if (m_pOptions->bStdoutCapture) {          // Setup stdout/stderr capture...
2547                  //m_pServer->setProcessChannelMode(  //      if (m_pOptions->bStdoutCapture) {
2548                  //      QProcess::StandardOutput);  #if QT_VERSION >= 0x040200
2549                    m_pServer->setProcessChannelMode(QProcess::ForwardedChannels);
2550    #endif
2551                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2552                          SIGNAL(readyReadStandardOutput()),                          SIGNAL(readyReadStandardOutput()),
2553                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
2554                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2555                          SIGNAL(readyReadStandardError()),                          SIGNAL(readyReadStandardError()),
2556                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
2557          //      }  //      }
2558    
2559          // The unforgiveable signal communication...          // The unforgiveable signal communication...
2560          QObject::connect(m_pServer,          QObject::connect(m_pServer,
2561                  SIGNAL(finished(int,QProcess::ExitStatus)),                  SIGNAL(finished(int, QProcess::ExitStatus)),
2562                  SLOT(processServerExit()));                  SLOT(processServerExit()));
2563    
2564      // Build process arguments...          // Build process arguments...
2565      QStringList serverCmdLine = QStringList::split(' ', m_pOptions->sServerCmdLine);          QStringList args = m_pOptions->sServerCmdLine.split(' ');
2566            QString sCommand = args[0];
2567      appendMessages(tr("Server is starting..."));          args.removeAt(0);
2568      appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");  
2569            appendMessages(tr("Server is starting..."));
2570            appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");
2571    
2572      const QString prog = (serverCmdLine.size() > 0) ? serverCmdLine[0] : QString();          // Go linuxsampler, go...
2573      const QStringList args = serverCmdLine.mid(1);          m_pServer->start(sCommand, args);
2574            if (!m_pServer->waitForStarted()) {
2575      // Go jack, go...                  appendMessagesError(tr("Could not start server.\n\nSorry."));
2576      m_pServer->start(prog, args);                  processServerExit();
2577      if (!m_pServer->waitForStarted()) {                  return;
2578          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()));  
2579    
2580      // Reset (yet again) the timer counters,          // Show startup results...
2581      // but this time is deferred as the user opted.          appendMessages(
2582      startSchedule(m_pOptions->iStartDelay);                  tr("Server was started with PID=%1.").arg((long) m_pServer->pid()));
2583      stabilizeForm();  
2584            // Reset (yet again) the timer counters,
2585            // but this time is deferred as the user opted.
2586            startSchedule(m_pOptions->iStartDelay);
2587            stabilizeForm();
2588  }  }
2589    
2590    
2591  // Stop linuxsampler server...  // Stop linuxsampler server...
2592  void MainForm::stopServer (void)  void MainForm::stopServer (bool bInteractive)
2593  {  {
2594      // Stop client code.          // Stop client code.
2595      stopClient();          stopClient();
2596    
2597      // And try to stop server.          if (m_pServer && bInteractive) {
2598      if (m_pServer) {                  if (QMessageBox::question(this,
2599          appendMessages(tr("Server is stopping..."));                          QSAMPLER_TITLE ": " + tr("The backend's fate ..."),
2600          if (m_pServer->state() == QProcess::Running)                          tr("You have the option to keep the sampler backend (LinuxSampler)\n"
2601              m_pServer->terminate();                          "running in the background. The sampler would continue to work\n"
2602       }                          "according to your current sampler session and you could alter the\n"
2603                            "sampler session at any time by relaunching QSampler.\n\n"
2604      // Give it some time to terminate gracefully and stabilize...                          "Do you want LinuxSampler to stop?"),
2605      QTime t;                          QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
2606      t.start();                  {
2607      while (t.elapsed() < QSAMPLER_TIMER_MSECS)                          bForceServerStop = false;
2608          QApplication::processEvents(QEventLoop::ExcludeUserInput);                  }
2609            }
2610    
2611       // Do final processing anyway.          // And try to stop server.
2612       processServerExit();          if (m_pServer && bForceServerStop) {
2613                    appendMessages(tr("Server is stopping..."));
2614                    if (m_pServer->state() == QProcess::Running) {
2615    #if defined(WIN32)
2616                            // Try harder...
2617                            m_pServer->kill();
2618    #else
2619                            // Try softly...
2620                            m_pServer->terminate();
2621    #endif
2622                    }
2623            }       // Do final processing anyway.
2624            else processServerExit();
2625    
2626            // Give it some time to terminate gracefully and stabilize...
2627            QTime t;
2628            t.start();
2629            while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2630                    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2631  }  }
2632    
2633    
2634  // Stdout handler...  // Stdout handler...
2635  void MainForm::readServerStdout (void)  void MainForm::readServerStdout (void)
2636  {  {
2637      if (m_pMessages)          if (m_pMessages)
2638          m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());                  m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());
2639  }  }
2640    
2641    
2642  // Linuxsampler server cleanup.  // Linuxsampler server cleanup.
2643  void MainForm::processServerExit (void)  void MainForm::processServerExit (void)
2644  {  {
2645      // Force client code cleanup.          // Force client code cleanup.
2646      stopClient();          stopClient();
2647    
2648      // Flush anything that maybe pending...          // Flush anything that maybe pending...
2649      if (m_pMessages)          if (m_pMessages)
2650          m_pMessages->flushStdoutBuffer();                  m_pMessages->flushStdoutBuffer();
2651    
2652      if (m_pServer) {          if (m_pServer && bForceServerStop) {
2653          // Force final server shutdown...                  if (m_pServer->state() != QProcess::NotRunning) {
2654          appendMessages(tr("Server was stopped with exit status %1.").arg(m_pServer->exitStatus()));                          appendMessages(tr("Server is being forced..."));
2655          m_pServer->terminate();                          // Force final server shutdown...
2656          if (!m_pServer->waitForFinished(2000))                          m_pServer->kill();
2657              m_pServer->kill();                          // Give it some time to terminate gracefully and stabilize...
2658          // Destroy it.                          QTime t;
2659          delete m_pServer;                          t.start();
2660          m_pServer = NULL;                          while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2661      }                                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2662                    }
2663                    // Force final server shutdown...
2664                    appendMessages(
2665                            tr("Server was stopped with exit status %1.")
2666                            .arg(m_pServer->exitStatus()));
2667                    delete m_pServer;
2668                    m_pServer = NULL;
2669            }
2670    
2671      // Again, make status visible stable.          // Again, make status visible stable.
2672      stabilizeForm();          stabilizeForm();
2673  }  }
2674    
2675    
# Line 2488  void MainForm::processServerExit (void) Line 2677  void MainForm::processServerExit (void)
2677  // qsamplerMainForm -- Client stuff.  // qsamplerMainForm -- Client stuff.
2678    
2679  // The LSCP client callback procedure.  // The LSCP client callback procedure.
2680  lscp_status_t qsampler_client_callback ( lscp_client_t */*pClient*/, lscp_event_t event, const char *pchData, int cchData, void *pvData )  lscp_status_t qsampler_client_callback ( lscp_client_t */*pClient*/,
2681            lscp_event_t event, const char *pchData, int cchData, void *pvData )
2682  {  {
2683      MainForm* pMainForm = (MainForm *) pvData;          MainForm* pMainForm = (MainForm *) pvData;
2684      if (pMainForm == NULL)          if (pMainForm == NULL)
2685          return LSCP_FAILED;                  return LSCP_FAILED;
2686    
2687      // ATTN: DO NOT EVER call any GUI code here,          // ATTN: DO NOT EVER call any GUI code here,
2688      // as this is run under some other thread context.          // as this is run under some other thread context.
2689      // A custom event must be posted here...          // A custom event must be posted here...
2690      QApplication::postEvent(pMainForm, new qsamplerCustomEvent(event, pchData, cchData));          QApplication::postEvent(pMainForm,
2691                    new CustomEvent(event, pchData, cchData));
2692    
2693      return LSCP_OK;          return LSCP_OK;
2694  }  }
2695    
2696    
2697  // Start our almighty client...  // Start our almighty client...
2698  bool MainForm::startClient (void)  bool MainForm::startClient (void)
2699  {  {
2700      // Have it a setup?          // Have it a setup?
2701      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2702          return false;                  return false;
2703    
2704      // Aren't we already started, are we?          // Aren't we already started, are we?
2705      if (m_pClient)          if (m_pClient)
2706          return true;                  return true;
2707    
2708      // Log prepare here.          // Log prepare here.
2709      appendMessages(tr("Client connecting..."));          appendMessages(tr("Client connecting..."));
2710    
2711      // Create the client handle...          // Create the client handle...
2712      m_pClient = ::lscp_client_create(m_pOptions->sServerHost.latin1(), m_pOptions->iServerPort, qsampler_client_callback, this);          m_pClient = ::lscp_client_create(
2713      if (m_pClient == NULL) {                  m_pOptions->sServerHost.toUtf8().constData(),
2714          // Is this the first try?                  m_pOptions->iServerPort, qsampler_client_callback, this);
2715          // maybe we need to start a local server...          if (m_pClient == NULL) {
2716          if ((m_pServer && m_pServer->state() == QProcess::Running) || !m_pOptions->bServerStart)                  // Is this the first try?
2717              appendMessagesError(tr("Could not connect to server as client.\n\nSorry."));                  // maybe we need to start a local server...
2718          else                  if ((m_pServer && m_pServer->state() == QProcess::Running)
2719              startServer();                          || !m_pOptions->bServerStart) {
2720          // This is always a failure.                          appendMessagesError(
2721          stabilizeForm();                                  tr("Could not connect to server as client.\n\nSorry."));
2722          return false;                  } else {
2723      }                          startServer();
2724      // Just set receive timeout value, blindly.                  }
2725      ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);                  // This is always a failure.
2726      appendMessages(tr("Client receive timeout is set to %1 msec.").arg(::lscp_client_get_timeout(m_pClient)));                  stabilizeForm();
2727                    return false;
2728            }
2729            // Just set receive timeout value, blindly.
2730            ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);
2731            appendMessages(
2732                    tr("Client receive timeout is set to %1 msec.")
2733                    .arg(::lscp_client_get_timeout(m_pClient)));
2734    
2735          // Subscribe to channel info change notifications...          // Subscribe to channel info change notifications...
2736            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT) != LSCP_OK)
2737                    appendMessagesClient("lscp_client_subscribe(CHANNEL_COUNT)");
2738          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)
2739                  appendMessagesClient("lscp_client_subscribe");                  appendMessagesClient("lscp_client_subscribe(CHANNEL_INFO)");
2740    
2741      // We may stop scheduling around.          DeviceStatusForm::onDevicesChanged(); // initialize
2742      stopSchedule();          updateViewMidiDeviceStatusMenu();
2743            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT) != LSCP_OK)
2744                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_COUNT)");
2745            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO) != LSCP_OK)
2746                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_INFO)");
2747            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT) != LSCP_OK)
2748                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_COUNT)");
2749            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO) != LSCP_OK)
2750                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_INFO)");
2751    
2752    #if CONFIG_EVENT_CHANNEL_MIDI
2753            // Subscribe to channel MIDI data notifications...
2754            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI) != LSCP_OK)
2755                    appendMessagesClient("lscp_client_subscribe(CHANNEL_MIDI)");
2756    #endif
2757    
2758    #if CONFIG_EVENT_DEVICE_MIDI
2759            // Subscribe to channel MIDI data notifications...
2760            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI) != LSCP_OK)
2761                    appendMessagesClient("lscp_client_subscribe(DEVICE_MIDI)");
2762    #endif
2763    
2764            // We may stop scheduling around.
2765            stopSchedule();
2766    
2767      // We'll accept drops from now on...          // We'll accept drops from now on...
2768      setAcceptDrops(true);          setAcceptDrops(true);
2769    
2770      // Log success here.          // Log success here.
2771      appendMessages(tr("Client connected."));          appendMessages(tr("Client connected."));
2772    
2773          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
2774          // if visible, that we're ready...          // if visible, that we're ready...
2775          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
2776              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
2777          if (m_pDeviceForm)          if (m_pDeviceForm)
2778              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
2779    
2780            // Is any session pending to be loaded?
2781            if (!m_pOptions->sSessionFile.isEmpty()) {
2782                    // Just load the prabably startup session...
2783                    if (loadSessionFile(m_pOptions->sSessionFile)) {
2784                            m_pOptions->sSessionFile = QString::null;
2785                            return true;
2786                    }
2787            }
2788    
2789      // Is any session pending to be loaded?          // send the current / loaded fine tuning settings to the sampler
2790      if (!m_pOptions->sSessionFile.isEmpty()) {          m_pOptions->sendFineTuningSettings();
         // Just load the prabably startup session...  
         if (loadSessionFile(m_pOptions->sSessionFile)) {  
             m_pOptions->sSessionFile = QString::null;  
             return true;  
         }  
     }  
2791    
2792      // Make a new session          // Make a new session
2793      return newSession();          return newSession();
2794  }  }
2795    
2796    
2797  // Stop client...  // Stop client...
2798  void MainForm::stopClient (void)  void MainForm::stopClient (void)
2799  {  {
2800      if (m_pClient == NULL)          if (m_pClient == NULL)
2801          return;                  return;
   
     // Log prepare here.  
     appendMessages(tr("Client disconnecting..."));  
2802    
2803      // Clear timer counters...          // Log prepare here.
2804      stopSchedule();          appendMessages(tr("Client disconnecting..."));
2805    
2806      // We'll reject drops from now on...          // Clear timer counters...
2807      setAcceptDrops(false);          stopSchedule();
2808    
2809      // Force any channel strips around, but          // We'll reject drops from now on...
2810      // but avoid removing the corresponding          setAcceptDrops(false);
     // channels from the back-end server.  
     m_iDirtyCount = 0;  
     closeSession(false);  
2811    
2812      // Close us as a client...          // Force any channel strips around, but
2813            // but avoid removing the corresponding
2814            // channels from the back-end server.
2815            m_iDirtyCount = 0;
2816            closeSession(false);
2817    
2818            // Close us as a client...
2819    #if CONFIG_EVENT_DEVICE_MIDI
2820            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI);
2821    #endif
2822    #if CONFIG_EVENT_CHANNEL_MIDI
2823            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI);
2824    #endif
2825            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
2826            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
2827            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
2828            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
2829          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
2830      ::lscp_client_destroy(m_pClient);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT);
2831      m_pClient = NULL;          ::lscp_client_destroy(m_pClient);
2832            m_pClient = NULL;
2833    
2834          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
2835          // if visible, that we're running out...          // if visible, that we're running out...
2836          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
2837              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
2838          if (m_pDeviceForm)          if (m_pDeviceForm)
2839              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
2840    
2841      // Log final here.          // Log final here.
2842      appendMessages(tr("Client disconnected."));          appendMessages(tr("Client disconnected."));
2843    
2844      // Make visible status.          // Make visible status.
2845      stabilizeForm();          stabilizeForm();
2846  }  }
2847    
2848    
2849    // Channel strip activation/selection.
2850    void MainForm::activateStrip ( QWidget *pWidget )
2851    {
2852            ChannelStrip *pChannelStrip
2853                    = static_cast<ChannelStrip *> (pWidget);
2854            if (pChannelStrip)
2855                    pChannelStrip->setSelected(true);
2856    
2857            stabilizeForm();
2858    }
2859    
2860    
2861  } // namespace QSampler  } // namespace QSampler
2862    
2863    

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

  ViewVC Help
Powered by ViewVC