/[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 2108 by capela, Thu Jul 15 08:03:32 2010 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-2010, 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    #if QT_VERSION < 0x040500
60    namespace Qt {
61    const WindowFlags WindowCloseButtonHint = WindowFlags(0x08000000);
62    #if QT_VERSION < 0x040200
63    const WindowFlags CustomizeWindowHint   = WindowFlags(0x02000000);
64    #endif
65    }
66    #endif
67    
68  #ifdef HAVE_SIGNAL_H  #ifdef HAVE_SIGNAL_H
69  #include <signal.h>  #include <signal.h>
# Line 73  static inline long lroundf ( float x ) Line 86  static inline long lroundf ( float x )
86  }  }
87  #endif  #endif
88    
89    
90    // All winsock apps needs this.
91    #if defined(WIN32)
92    static WSADATA _wsaData;
93    #endif
94    
95    
96    namespace QSampler {
97    
98  // Timer constant stuff.  // Timer constant stuff.
99  #define QSAMPLER_TIMER_MSECS    200  #define QSAMPLER_TIMER_MSECS    200
100    
# Line 83  static inline long lroundf ( float x ) Line 105  static inline long lroundf ( float x )
105  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.
106    
107    
108  // All winsock apps needs this.  // Specialties for thread-callback comunication.
109  #if defined(WIN32)  #define QSAMPLER_LSCP_EVENT   QEvent::Type(QEvent::User + 1)
110  static WSADATA _wsaData;  #define QSAMPLER_SAVE_EVENT   QEvent::Type(QEvent::User + 2)
 #endif  
111    
112    
113  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
114  // qsamplerCustomEvent -- specialty for callback comunication.  // LscpEvent -- specialty for LSCP callback comunication.
115    
 #define QSAMPLER_CUSTOM_EVENT   QEvent::Type(QEvent::User + 0)  
116    
117  class qsamplerCustomEvent : public QEvent  class LscpEvent : public QEvent
118  {  {
119  public:  public:
120    
121      // Constructor.          // Constructor.
122      qsamplerCustomEvent(lscp_event_t event, const char *pchData, int cchData)          LscpEvent(lscp_event_t event, const char *pchData, int cchData)
123          : QEvent(QSAMPLER_CUSTOM_EVENT)                  : QEvent(QSAMPLER_LSCP_EVENT)
124      {          {
125          m_event = event;                  m_event = event;
126          m_data.setLatin1(pchData, cchData);                  m_data  = QString::fromUtf8(pchData, cchData);
127      }          }
128    
129      // Accessors.          // Accessors.
130      lscp_event_t event() { return m_event; }          lscp_event_t event() { return m_event; }
131      QString&     data()  { return m_data;  }          QString&     data()  { return m_data;  }
132    
133  private:  private:
134    
135      // The proper event type.          // The proper event type.
136      lscp_event_t m_event;          lscp_event_t m_event;
137      // The event data as a string.          // The event data as a string.
138      QString      m_data;          QString      m_data;
139  };  };
140    
141    
142  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
143  // qsamplerMainForm -- Main window form implementation.  // LADISH Level 1 support stuff.
144    
145  namespace QSampler {  void qsampler_on_sigusr1 ( int /*signo*/ )
146    {
147            QApplication::postEvent(
148                    MainForm::getInstance(),
149                    new QEvent(QSAMPLER_SAVE_EVENT));
150    }
151    
152    
153    //-------------------------------------------------------------------------
154    // qsamplerMainForm -- Main window form implementation.
155    
156  // Kind of singleton reference.  // Kind of singleton reference.
157  MainForm* MainForm::g_pMainForm = NULL;  MainForm* MainForm::g_pMainForm = NULL;
158    
159  MainForm::MainForm(QWidget* parent) : QMainWindow(parent) {  MainForm::MainForm ( QWidget *pParent )
160      ui.setupUi(this);          : QMainWindow(pParent)
161    {
162            m_ui.setupUi(this);
163    
164          // Pseudo-singleton reference setup.          // Pseudo-singleton reference setup.
165          g_pMainForm = this;          g_pMainForm = this;
166    
167      // Initialize some pointer references.          // Initialize some pointer references.
168      m_pOptions = NULL;          m_pOptions = NULL;
169    
170      // All child forms are to be created later, not earlier than setup.          // All child forms are to be created later, not earlier than setup.
171      m_pMessages = NULL;          m_pMessages = NULL;
172      m_pInstrumentListForm = NULL;          m_pInstrumentListForm = NULL;
173      m_pDeviceForm = NULL;          m_pDeviceForm = NULL;
174    
175      // We'll start clean.          // We'll start clean.
176      m_iUntitled   = 0;          m_iUntitled   = 0;
177      m_iDirtyCount = 0;          m_iDirtyCount = 0;
178    
179      m_pServer = NULL;          m_pServer = NULL;
180      m_pClient = NULL;          m_pClient = NULL;
181    
182      m_iStartDelay = 0;          m_iStartDelay = 0;
183      m_iTimerDelay = 0;          m_iTimerDelay = 0;
184    
185      m_iTimerSlot = 0;          m_iTimerSlot = 0;
186    
187  #ifdef HAVE_SIGNAL_H  #ifdef HAVE_SIGNAL_H
188          // Set to ignore any fatal "Broken pipe" signals.          // Set to ignore any fatal "Broken pipe" signals.
189          ::signal(SIGPIPE, SIG_IGN);          ::signal(SIGPIPE, SIG_IGN);
190            // LADISH Level 1 suport.
191            ::signal(SIGUSR1, qsampler_on_sigusr1);
192  #endif  #endif
193    
194  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
195      // Make some extras into the toolbar...          // Make some extras into the toolbar...
196          const QString& sVolumeText = tr("Master volume");          const QString& sVolumeText = tr("Master volume");
197          m_iVolumeChanging = 0;          m_iVolumeChanging = 0;
198          // Volume slider...          // Volume slider...
199          ui.channelsToolbar->addSeparator();          m_ui.channelsToolbar->addSeparator();
200          m_pVolumeSlider = new QSlider(Qt::Horizontal, ui.channelsToolbar);          m_pVolumeSlider = new QSlider(Qt::Horizontal, m_ui.channelsToolbar);
201          m_pVolumeSlider->setTickmarks(QSlider::Below);          m_pVolumeSlider->setTickPosition(QSlider::TicksBothSides);
202          m_pVolumeSlider->setTickInterval(10);          m_pVolumeSlider->setTickInterval(10);
203          m_pVolumeSlider->setPageStep(10);          m_pVolumeSlider->setPageStep(10);
204          m_pVolumeSlider->setRange(0, 100);          m_pVolumeSlider->setSingleStep(10);
205            m_pVolumeSlider->setMinimum(0);
206            m_pVolumeSlider->setMaximum(100);
207          m_pVolumeSlider->setMaximumHeight(26);          m_pVolumeSlider->setMaximumHeight(26);
208          m_pVolumeSlider->setMinimumWidth(160);          m_pVolumeSlider->setMinimumWidth(160);
209          QToolTip::add(m_pVolumeSlider, sVolumeText);          m_pVolumeSlider->setToolTip(sVolumeText);
210          QObject::connect(m_pVolumeSlider,          QObject::connect(m_pVolumeSlider,
211                  SIGNAL(valueChanged(int)),                  SIGNAL(valueChanged(int)),
212                  SLOT(volumeChanged(int)));                  SLOT(volumeChanged(int)));
213          //ui.channelsToolbar->setHorizontallyStretchable(true);          //m_ui.channelsToolbar->setHorizontallyStretchable(true);
214          //ui.channelsToolbar->setStretchableWidget(m_pVolumeSlider);          //m_ui.channelsToolbar->setStretchableWidget(m_pVolumeSlider);
215      ui.channelsToolbar->addWidget(m_pVolumeSlider);          m_ui.channelsToolbar->addWidget(m_pVolumeSlider);
216          // Volume spin-box          // Volume spin-box
217          ui.channelsToolbar->addSeparator();          m_ui.channelsToolbar->addSeparator();
218          m_pVolumeSpinBox = new QSpinBox(ui.channelsToolbar);          m_pVolumeSpinBox = new QSpinBox(m_ui.channelsToolbar);
219            m_pVolumeSpinBox->setMaximumHeight(24);
220          m_pVolumeSpinBox->setSuffix(" %");          m_pVolumeSpinBox->setSuffix(" %");
221          m_pVolumeSpinBox->setRange(0, 100);          m_pVolumeSpinBox->setMinimum(0);
222          QToolTip::add(m_pVolumeSpinBox, sVolumeText);          m_pVolumeSpinBox->setMaximum(100);
223            m_pVolumeSpinBox->setToolTip(sVolumeText);
224          QObject::connect(m_pVolumeSpinBox,          QObject::connect(m_pVolumeSpinBox,
225                  SIGNAL(valueChanged(int)),                  SIGNAL(valueChanged(int)),
226                  SLOT(volumeChanged(int)));                  SLOT(volumeChanged(int)));
227      ui.channelsToolbar->addWidget(m_pVolumeSpinBox);          m_ui.channelsToolbar->addWidget(m_pVolumeSpinBox);
228  #endif  #endif
229    
230      // Make it an MDI workspace.          // Make it an MDI workspace.
231      m_pWorkspace = new QWorkspace(this);          m_pWorkspace = new QWorkspace(this);
232      m_pWorkspace->setScrollBarsEnabled(true);          m_pWorkspace->setScrollBarsEnabled(true);
233          // Set the activation connection.          // Set the activation connection.
234          QObject::connect(m_pWorkspace,          QObject::connect(m_pWorkspace,
235                  SIGNAL(windowActivated(QWidget *)),                  SIGNAL(windowActivated(QWidget *)),
236                  SLOT(stabilizeForm()));                  SLOT(activateStrip(QWidget *)));
237      // Make it shine :-)          // Make it shine :-)
238      setCentralWidget(m_pWorkspace);          setCentralWidget(m_pWorkspace);
239    
240      // Create some statusbar labels...          // Create some statusbar labels...
241      QLabel *pLabel;          QLabel *pLabel;
242      // Client status.          // Client status.
243      pLabel = new QLabel(tr("Connected"), this);          pLabel = new QLabel(tr("Connected"), this);
244      pLabel->setAlignment(Qt::AlignLeft);          pLabel->setAlignment(Qt::AlignLeft);
245      pLabel->setMinimumSize(pLabel->sizeHint());          pLabel->setMinimumSize(pLabel->sizeHint());
246      m_statusItem[QSAMPLER_STATUS_CLIENT] = pLabel;          m_statusItem[QSAMPLER_STATUS_CLIENT] = pLabel;
247      statusBar()->addWidget(pLabel);          statusBar()->addWidget(pLabel);
248      // Server address.          // Server address.
249      pLabel = new QLabel(this);          pLabel = new QLabel(this);
250      pLabel->setAlignment(Qt::AlignLeft);          pLabel->setAlignment(Qt::AlignLeft);
251      m_statusItem[QSAMPLER_STATUS_SERVER] = pLabel;          m_statusItem[QSAMPLER_STATUS_SERVER] = pLabel;
252      statusBar()->addWidget(pLabel, 1);          statusBar()->addWidget(pLabel, 1);
253      // Channel title.          // Channel title.
254      pLabel = new QLabel(this);          pLabel = new QLabel(this);
255      pLabel->setAlignment(Qt::AlignLeft);          pLabel->setAlignment(Qt::AlignLeft);
256      m_statusItem[QSAMPLER_STATUS_CHANNEL] = pLabel;          m_statusItem[QSAMPLER_STATUS_CHANNEL] = pLabel;
257      statusBar()->addWidget(pLabel, 2);          statusBar()->addWidget(pLabel, 2);
258      // Session modification status.          // Session modification status.
259      pLabel = new QLabel(tr("MOD"), this);          pLabel = new QLabel(tr("MOD"), this);
260      pLabel->setAlignment(Qt::AlignHCenter);          pLabel->setAlignment(Qt::AlignHCenter);
261      pLabel->setMinimumSize(pLabel->sizeHint());          pLabel->setMinimumSize(pLabel->sizeHint());
262      m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;          m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;
263      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);  
264    
265  #if defined(WIN32)  #if defined(WIN32)
266      WSAStartup(MAKEWORD(1, 1), &_wsaData);          WSAStartup(MAKEWORD(1, 1), &_wsaData);
267  #endif  #endif
268    
269          QObject::connect(ui.fileNewAction,          // Some actions surely need those
270                  SIGNAL(activated()),          // shortcuts firmly attached...
271            addAction(m_ui.viewMenubarAction);
272            addAction(m_ui.viewToolbarAction);
273    
274            QObject::connect(m_ui.fileNewAction,
275                    SIGNAL(triggered()),
276                  SLOT(fileNew()));                  SLOT(fileNew()));
277          QObject::connect(ui.fileOpenAction,          QObject::connect(m_ui.fileOpenAction,
278                  SIGNAL(activated()),                  SIGNAL(triggered()),
279                  SLOT(fileOpen()));                  SLOT(fileOpen()));
280          QObject::connect(ui.fileSaveAction,          QObject::connect(m_ui.fileSaveAction,
281                  SIGNAL(activated()),                  SIGNAL(triggered()),
282                  SLOT(fileSave()));                  SLOT(fileSave()));
283          QObject::connect(ui.fileSaveAsAction,          QObject::connect(m_ui.fileSaveAsAction,
284                  SIGNAL(activated()),                  SIGNAL(triggered()),
285                  SLOT(fileSaveAs()));                  SLOT(fileSaveAs()));
286          QObject::connect(ui.fileResetAction,          QObject::connect(m_ui.fileResetAction,
287                  SIGNAL(activated()),                  SIGNAL(triggered()),
288                  SLOT(fileReset()));                  SLOT(fileReset()));
289          QObject::connect(ui.fileRestartAction,          QObject::connect(m_ui.fileRestartAction,
290                  SIGNAL(activated()),                  SIGNAL(triggered()),
291                  SLOT(fileRestart()));                  SLOT(fileRestart()));
292          QObject::connect(ui.fileExitAction,          QObject::connect(m_ui.fileExitAction,
293                  SIGNAL(activated()),                  SIGNAL(triggered()),
294                  SLOT(fileExit()));                  SLOT(fileExit()));
295          QObject::connect(ui.editAddChannelAction,          QObject::connect(m_ui.editAddChannelAction,
296                  SIGNAL(activated()),                  SIGNAL(triggered()),
297                  SLOT(editAddChannel()));                  SLOT(editAddChannel()));
298          QObject::connect(ui.editRemoveChannelAction,          QObject::connect(m_ui.editRemoveChannelAction,
299                  SIGNAL(activated()),                  SIGNAL(triggered()),
300                  SLOT(editRemoveChannel()));                  SLOT(editRemoveChannel()));
301          QObject::connect(ui.editSetupChannelAction,          QObject::connect(m_ui.editSetupChannelAction,
302                  SIGNAL(activated()),                  SIGNAL(triggered()),
303                  SLOT(editSetupChannel()));                  SLOT(editSetupChannel()));
304          QObject::connect(ui.editEditChannelAction,          QObject::connect(m_ui.editEditChannelAction,
305                  SIGNAL(activated()),                  SIGNAL(triggered()),
306                  SLOT(editEditChannel()));                  SLOT(editEditChannel()));
307          QObject::connect(ui.editResetChannelAction,          QObject::connect(m_ui.editResetChannelAction,
308                  SIGNAL(activated()),                  SIGNAL(triggered()),
309                  SLOT(editResetChannel()));                  SLOT(editResetChannel()));
310          QObject::connect(ui.editResetAllChannelsAction,          QObject::connect(m_ui.editResetAllChannelsAction,
311                  SIGNAL(activated()),                  SIGNAL(triggered()),
312                  SLOT(editResetAllChannels()));                  SLOT(editResetAllChannels()));
313          QObject::connect(ui.viewMenubarAction,          QObject::connect(m_ui.viewMenubarAction,
314                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
315                  SLOT(viewMenubar(bool)));                  SLOT(viewMenubar(bool)));
316          QObject::connect(ui.viewToolbarAction,          QObject::connect(m_ui.viewToolbarAction,
317                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
318                  SLOT(viewToolbar(bool)));                  SLOT(viewToolbar(bool)));
319          QObject::connect(ui.viewStatusbarAction,          QObject::connect(m_ui.viewStatusbarAction,
320                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
321                  SLOT(viewStatusbar(bool)));                  SLOT(viewStatusbar(bool)));
322          QObject::connect(ui.viewMessagesAction,          QObject::connect(m_ui.viewMessagesAction,
323                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
324                  SLOT(viewMessages(bool)));                  SLOT(viewMessages(bool)));
325          QObject::connect(ui.viewInstrumentsAction,          QObject::connect(m_ui.viewInstrumentsAction,
326                  SIGNAL(activated()),                  SIGNAL(triggered()),
327                  SLOT(viewInstruments()));                  SLOT(viewInstruments()));
328          QObject::connect(ui.viewDevicesAction,          QObject::connect(m_ui.viewDevicesAction,
329                  SIGNAL(activated()),                  SIGNAL(triggered()),
330                  SLOT(viewDevices()));                  SLOT(viewDevices()));
331          QObject::connect(ui.viewOptionsAction,          QObject::connect(m_ui.viewOptionsAction,
332                  SIGNAL(activated()),                  SIGNAL(triggered()),
333                  SLOT(viewOptions()));                  SLOT(viewOptions()));
334          QObject::connect(ui.channelsArrangeAction,          QObject::connect(m_ui.channelsArrangeAction,
335                  SIGNAL(activated()),                  SIGNAL(triggered()),
336                  SLOT(channelsArrange()));                  SLOT(channelsArrange()));
337          QObject::connect(ui.channelsAutoArrangeAction,          QObject::connect(m_ui.channelsAutoArrangeAction,
338                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
339                  SLOT(channelsAutoArrange(bool)));                  SLOT(channelsAutoArrange(bool)));
340          QObject::connect(ui.helpAboutAction,          QObject::connect(m_ui.helpAboutAction,
341                  SIGNAL(activated()),                  SIGNAL(triggered()),
342                  SLOT(helpAbout()));                  SLOT(helpAbout()));
343          QObject::connect(ui.helpAboutQtAction,          QObject::connect(m_ui.helpAboutQtAction,
344                  SIGNAL(activated()),                  SIGNAL(triggered()),
345                  SLOT(helpAboutQt()));                  SLOT(helpAboutQt()));
346    
347            QObject::connect(m_ui.fileMenu,
348                    SIGNAL(aboutToShow()),
349                    SLOT(updateRecentFilesMenu()));
350            QObject::connect(m_ui.channelsMenu,
351                    SIGNAL(aboutToShow()),
352                    SLOT(channelsMenuAboutToShow()));
353  }  }
354    
355  // Destructor.  // Destructor.
356  MainForm::~MainForm()  MainForm::~MainForm()
357  {  {
358      // Do final processing anyway.          // Do final processing anyway.
359      processServerExit();          processServerExit();
360    
361  #if defined(WIN32)  #if defined(WIN32)
362      WSACleanup();          WSACleanup();
363  #endif  #endif
364    
365      // Finally drop any widgets around...          // Finally drop any widgets around...
366      if (m_pDeviceForm)          if (m_pDeviceForm)
367          delete m_pDeviceForm;                  delete m_pDeviceForm;
368      if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
369          delete m_pInstrumentListForm;                  delete m_pInstrumentListForm;
370      if (m_pMessages)          if (m_pMessages)
371          delete m_pMessages;                  delete m_pMessages;
372      if (m_pWorkspace)          if (m_pWorkspace)
373          delete m_pWorkspace;                  delete m_pWorkspace;
374    
375      // Delete status item labels one by one.          // Delete status item labels one by one.
376      if (m_statusItem[QSAMPLER_STATUS_CLIENT])          if (m_statusItem[QSAMPLER_STATUS_CLIENT])
377          delete m_statusItem[QSAMPLER_STATUS_CLIENT];                  delete m_statusItem[QSAMPLER_STATUS_CLIENT];
378      if (m_statusItem[QSAMPLER_STATUS_SERVER])          if (m_statusItem[QSAMPLER_STATUS_SERVER])
379          delete m_statusItem[QSAMPLER_STATUS_SERVER];                  delete m_statusItem[QSAMPLER_STATUS_SERVER];
380      if (m_statusItem[QSAMPLER_STATUS_CHANNEL])          if (m_statusItem[QSAMPLER_STATUS_CHANNEL])
381          delete m_statusItem[QSAMPLER_STATUS_CHANNEL];                  delete m_statusItem[QSAMPLER_STATUS_CHANNEL];
382      if (m_statusItem[QSAMPLER_STATUS_SESSION])          if (m_statusItem[QSAMPLER_STATUS_SESSION])
383          delete m_statusItem[QSAMPLER_STATUS_SESSION];                  delete m_statusItem[QSAMPLER_STATUS_SESSION];
384    
385  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
386          delete m_pVolumeSpinBox;          delete m_pVolumeSpinBox;
387          delete m_pVolumeSlider;          delete m_pVolumeSlider;
388  #endif  #endif
389    
     // Delete recentfiles menu.  
     if (m_pRecentFilesMenu)  
         delete m_pRecentFilesMenu;  
   
390          // Pseudo-singleton reference shut-down.          // Pseudo-singleton reference shut-down.
391          g_pMainForm = NULL;          g_pMainForm = NULL;
392  }  }
393    
394    
395  // Make and set a proper setup options step.  // Make and set a proper setup options step.
396  void MainForm::setup ( qsamplerOptions *pOptions )  void MainForm::setup ( Options *pOptions )
397  {  {
398      // We got options?          // We got options?
399      m_pOptions = pOptions;          m_pOptions = pOptions;
400    
401      // What style do we create these forms?          // What style do we create these forms?
402          Qt::WFlags wflags = Qt::WStyle_Customize          Qt::WindowFlags wflags = Qt::Window
403                  | Qt::WStyle_NormalBorder                  | Qt::CustomizeWindowHint
404                  | Qt::WStyle_Title                  | Qt::WindowTitleHint
405                  | Qt::WStyle_SysMenu                  | Qt::WindowSystemMenuHint
406                  | Qt::WStyle_MinMax                  | Qt::WindowMinMaxButtonsHint
407                  | Qt::WType_TopLevel;                  | Qt::WindowCloseButtonHint;
408      if (m_pOptions->bKeepOnTop)          if (m_pOptions->bKeepOnTop)
409          wflags |= Qt::WStyle_Tool;                  wflags |= Qt::Tool;
410      // Some child forms are to be created right now.  
411      m_pMessages = new qsamplerMessages(this);          // Some child forms are to be created right now.
412      m_pDeviceForm = new DeviceForm(this, wflags);          m_pMessages = new Messages(this);
413            m_pDeviceForm = new DeviceForm(this, wflags);
414  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
415      m_pInstrumentListForm = new InstrumentListForm(this, wflags);          m_pInstrumentListForm = new InstrumentListForm(this, wflags);
         QObject::connect(&m_pInstrumentListForm->model,  
                 SIGNAL(instrumentsChanged()),  
                 SLOT(sessionDirty()));  
416  #else  #else
417          viewInstrumentsAction->setEnabled(false);          m_ui.viewInstrumentsAction->setEnabled(false);
418  #endif  #endif
419      // Set message defaults...  
420      updateMessagesFont();          // Setup messages logging appropriately...
421      updateMessagesLimit();          m_pMessages->setLogging(
422      updateMessagesCapture();                  m_pOptions->bMessagesLog,
423      // Set the visibility signal.                  m_pOptions->sMessagesLogPath);
424    
425            // Set message defaults...
426            updateMessagesFont();
427            updateMessagesLimit();
428            updateMessagesCapture();
429            // Set the visibility signal.
430          QObject::connect(m_pMessages,          QObject::connect(m_pMessages,
431                  SIGNAL(visibilityChanged(bool)),                  SIGNAL(visibilityChanged(bool)),
432                  SLOT(stabilizeForm()));                  SLOT(stabilizeForm()));
433    
434      // Initial decorations toggle state.          // Initial decorations toggle state.
435      ui.viewMenubarAction->setOn(m_pOptions->bMenubar);          m_ui.viewMenubarAction->setChecked(m_pOptions->bMenubar);
436      ui.viewToolbarAction->setOn(m_pOptions->bToolbar);          m_ui.viewToolbarAction->setChecked(m_pOptions->bToolbar);
437      ui.viewStatusbarAction->setOn(m_pOptions->bStatusbar);          m_ui.viewStatusbarAction->setChecked(m_pOptions->bStatusbar);
438      ui.channelsAutoArrangeAction->setOn(m_pOptions->bAutoArrange);          m_ui.channelsAutoArrangeAction->setChecked(m_pOptions->bAutoArrange);
439    
440      // Initial decorations visibility state.          // Initial decorations visibility state.
441      viewMenubar(m_pOptions->bMenubar);          viewMenubar(m_pOptions->bMenubar);
442      viewToolbar(m_pOptions->bToolbar);          viewToolbar(m_pOptions->bToolbar);
443      viewStatusbar(m_pOptions->bStatusbar);          viewStatusbar(m_pOptions->bStatusbar);
444    
445      addDockWidget(Qt::BottomDockWidgetArea, m_pMessages);          addDockWidget(Qt::BottomDockWidgetArea, m_pMessages);
446    
447      // Restore whole toolbar & dock windows states.          // Restore whole dock windows state.
448      QString sDockables = m_pOptions->settings().readEntry("/Layout/DockWindowsBase64" , QString::null);          QByteArray aDockables = m_pOptions->settings().value(
449      if (!sDockables.isEmpty()) {                  "/Layout/DockWindows").toByteArray();
450          restoreState(QByteArray::fromBase64(sDockables.toAscii()));          if (!aDockables.isEmpty()) {
451      }                  restoreState(aDockables);
452      // Try to restore old window positioning and initial visibility.          }
453      m_pOptions->loadWidgetGeometry(this);  
454      m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);          // Try to restore old window positioning and initial visibility.
455      m_pOptions->loadWidgetGeometry(m_pDeviceForm);          m_pOptions->loadWidgetGeometry(this, true);
456            m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);
457      // Final startup stabilization...          m_pOptions->loadWidgetGeometry(m_pDeviceForm);
458      updateMaxVolume();  
459      updateRecentFilesMenu();          // Final startup stabilization...
460      stabilizeForm();          updateMaxVolume();
461            updateRecentFilesMenu();
462            stabilizeForm();
463    
464      // Make it ready :-)          // Make it ready :-)
465      statusBar()->message(tr("Ready"), 3000);          statusBar()->showMessage(tr("Ready"), 3000);
466    
467      // We'll try to start immediately...          // We'll try to start immediately...
468      startSchedule(0);          startSchedule(0);
469    
470      // Register the first timer slot.          // Register the first timer slot.
471      QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));          QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
472  }  }
473    
474    
475  // Window close event handlers.  // Window close event handlers.
476  bool MainForm::queryClose (void)  bool MainForm::queryClose (void)
477  {  {
478      bool bQueryClose = closeSession(false);          bool bQueryClose = closeSession(false);
479    
480      // Try to save current general state...          // Try to save current general state...
481      if (m_pOptions) {          if (m_pOptions) {
482          // Some windows default fonts is here on demand too.                  // Some windows default fonts is here on demand too.
483          if (bQueryClose && m_pMessages)                  if (bQueryClose && m_pMessages)
484              m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
485          // Try to save current positioning.                  // Try to save current positioning.
486          if (bQueryClose) {                  if (bQueryClose) {
487              // Save decorations state.                          // Save decorations state.
488              m_pOptions->bMenubar = ui.MenuBar->isVisible();                          m_pOptions->bMenubar = m_ui.MenuBar->isVisible();
489              m_pOptions->bToolbar = (ui.fileToolbar->isVisible() || ui.editToolbar->isVisible() || ui.channelsToolbar->isVisible());                          m_pOptions->bToolbar = (m_ui.fileToolbar->isVisible()
490              m_pOptions->bStatusbar = statusBar()->isVisible();                                  || m_ui.editToolbar->isVisible()
491              // Save the dock windows state.                                  || m_ui.channelsToolbar->isVisible());
492              const QString sDockables = saveState().toBase64().data();                          m_pOptions->bStatusbar = statusBar()->isVisible();
493              m_pOptions->settings().writeEntry("/Layout/DockWindowsBase64", sDockables);                          // Save the dock windows state.
494              // And the children, and the main windows state,.                          const QString sDockables = saveState().toBase64().data();
495                            m_pOptions->settings().setValue("/Layout/DockWindows", saveState());
496                            // And the children, and the main windows state,.
497                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);
498                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);
499                          m_pOptions->saveWidgetGeometry(this);                          m_pOptions->saveWidgetGeometry(this, true);
500                          // Close popup widgets.                          // Close popup widgets.
501                          if (m_pInstrumentListForm)                          if (m_pInstrumentListForm)
502                                  m_pInstrumentListForm->close();                                  m_pInstrumentListForm->close();
503                          if (m_pDeviceForm)                          if (m_pDeviceForm)
504                                  m_pDeviceForm->close();                                  m_pDeviceForm->close();
505              // Stop client and/or server, gracefully.                          // Stop client and/or server, gracefully.
506              stopServer();                          stopServer(true /*interactive*/);
507          }                  }
508      }          }
509    
510      return bQueryClose;          return bQueryClose;
511  }  }
512    
513    
514  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )
515  {  {
516      if (queryClose())          if (queryClose()) {
517          pCloseEvent->accept();                  DeviceStatusForm::deleteAllInstances();
518      else                  pCloseEvent->accept();
519          pCloseEvent->ignore();          } else
520  }                  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;  
521  }  }
522    
523    
524  // Window drag-n-drop event handlers.  // Window drag-n-drop event handlers.
525  void MainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )  void MainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )
526  {  {
527          QStringList files;          // Accept external drags only...
528          pDragEnterEvent->accept(decodeDragFiles(pDragEnterEvent, files));          if (pDragEnterEvent->source() == NULL
529                    && pDragEnterEvent->mimeData()->hasUrls()) {
530                    pDragEnterEvent->accept();
531            } else {
532                    pDragEnterEvent->ignore();
533            }
534  }  }
535    
536    
537  void MainForm::dropEvent ( QDropEvent* pDropEvent )  void MainForm::dropEvent ( QDropEvent* pDropEvent )
538  {  {
539      QStringList files;          // Accept externally originated drops only...
540            if (pDropEvent->source())
541      if (!decodeDragFiles(pDropEvent, files))                  return;
         return;  
542    
543          for (QStringList::Iterator iter = files.begin(); iter != files.end(); iter++) {          const QMimeData *pMimeData = pDropEvent->mimeData();
544                  const QString& sPath = *iter;          if (pMimeData->hasUrls()) {
545                  if (qsamplerChannel::isInstrumentFile(sPath)) {                  QListIterator<QUrl> iter(pMimeData->urls());
546                          // Try to create a new channel from instrument file...                  while (iter.hasNext()) {
547                          qsamplerChannel *pChannel = new qsamplerChannel();                          const QString& sPath = iter.next().toLocalFile();
548                          if (pChannel == NULL)                  //      if (Channel::isDlsInstrumentFile(sPath)) {
549                                  return;                          if (QFileInfo(sPath).exists()) {
550                          // Start setting the instrument filename...                                  // Try to create a new channel from instrument file...
551                          pChannel->setInstrument(sPath, 0);                                  Channel *pChannel = new Channel();
552                          // Before we show it up, may be we'll                                  if (pChannel == NULL)
553                          // better ask for some initial values?                                          return;
554                          if (!pChannel->channelSetup(this)) {                                  // Start setting the instrument filename...
555                                  delete pChannel;                                  pChannel->setInstrument(sPath, 0);
556                                  return;                                  // Before we show it up, may be we'll
557                          }                                  // better ask for some initial values?
558                          // Finally, give it to a new channel strip...                                  if (!pChannel->channelSetup(this)) {
559                          if (!createChannelStrip(pChannel)) {                                          delete pChannel;
560                                  delete pChannel;                                          return;
561                                  return;                                  }
562                                    // Finally, give it to a new channel strip...
563                                    if (!createChannelStrip(pChannel)) {
564                                            delete pChannel;
565                                            return;
566                                    }
567                                    // Make that an overall update.
568                                    m_iDirtyCount++;
569                                    stabilizeForm();
570                            }   // Otherwise, load an usual session file (LSCP script)...
571                            else if (closeSession(true)) {
572                                    loadSessionFile(sPath);
573                                    break;
574                          }                          }
                         // Make that an overall update.  
                         m_iDirtyCount++;  
                         stabilizeForm();  
                 }   // Otherwise, load an usual session file (LSCP script)...  
                 else if (closeSession(true)) {  
                         loadSessionFile(sPath);  
                         break;  
575                  }                  }
576                  // Make it look responsive...:)                  // Make it look responsive...:)
577                  QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
578          }          }
579  }  }
580    
581    
582  // Custome event handler.  // Custome event handler.
583  void MainForm::customEvent(QEvent* pCustomEvent)  void MainForm::customEvent ( QEvent* pEvent )
584  {  {
585      // For the time being, just pump it to messages.          // For the time being, just pump it to messages.
586      if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {          if (pEvent->type() == QSAMPLER_LSCP_EVENT) {
587          qsamplerCustomEvent *pEvent = (qsamplerCustomEvent *) pCustomEvent;                  LscpEvent *pLscpEvent = static_cast<LscpEvent *> (pEvent);
588                  if (pEvent->event() == LSCP_EVENT_CHANNEL_INFO) {                  switch (pLscpEvent->event()) {
589                          int iChannelID = pEvent->data().toInt();                          case LSCP_EVENT_CHANNEL_COUNT:
590                          ChannelStrip *pChannelStrip = channelStrip(iChannelID);                                  updateAllChannelStrips(true);
591                          if (pChannelStrip)                                  break;
592                                  channelStripChanged(pChannelStrip);                          case LSCP_EVENT_CHANNEL_INFO: {
593                  } else {                                  int iChannelID = pLscpEvent->data().toInt();
594                          appendMessagesColor(tr("Notify event: %1 data: %2")                                  ChannelStrip *pChannelStrip = channelStrip(iChannelID);
595                                  .arg(::lscp_event_to_text(pEvent->event()))                                  if (pChannelStrip)
596                                  .arg(pEvent->data()), "#996699");                                          channelStripChanged(pChannelStrip);
597                                    break;
598                            }
599                            case LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT:
600                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
601                                    DeviceStatusForm::onDevicesChanged();
602                                    updateViewMidiDeviceStatusMenu();
603                                    break;
604                            case LSCP_EVENT_MIDI_INPUT_DEVICE_INFO: {
605                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
606                                    const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt();
607                                    DeviceStatusForm::onDeviceChanged(iDeviceID);
608                                    break;
609                            }
610                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT:
611                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
612                                    break;
613                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO:
614                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
615                                    break;
616                    #if CONFIG_EVENT_CHANNEL_MIDI
617                            case LSCP_EVENT_CHANNEL_MIDI: {
618                                    const int iChannelID = pLscpEvent->data().section(' ', 0, 0).toInt();
619                                    ChannelStrip *pChannelStrip = channelStrip(iChannelID);
620                                    if (pChannelStrip)
621                                            pChannelStrip->midiActivityLedOn();
622                                    break;
623                            }
624                    #endif
625                    #if CONFIG_EVENT_DEVICE_MIDI
626                            case LSCP_EVENT_DEVICE_MIDI: {
627                                    const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt();
628                                    const int iPortID   = pLscpEvent->data().section(' ', 1, 1).toInt();
629                                    DeviceStatusForm *pDeviceStatusForm
630                                            = DeviceStatusForm::getInstance(iDeviceID);
631                                    if (pDeviceStatusForm)
632                                            pDeviceStatusForm->midiArrived(iPortID);
633                                    break;
634                            }
635                    #endif
636                            default:
637                                    appendMessagesColor(tr("LSCP Event: %1 data: %2")
638                                            .arg(::lscp_event_to_text(pLscpEvent->event()))
639                                            .arg(pLscpEvent->data()), "#996699");
640                  }                  }
641      }          }       // LADISH1 Level 1 support...
642            else if (pEvent->type() == QSAMPLER_SAVE_EVENT)
643                    saveSession(false);
644  }  }
645    
646    
647    void MainForm::updateViewMidiDeviceStatusMenu (void)
648    {
649            m_ui.viewMidiDeviceStatusMenu->clear();
650            const std::map<int, DeviceStatusForm *> statusForms
651                    = DeviceStatusForm::getInstances();
652            std::map<int, DeviceStatusForm *>::const_iterator iter
653                    = statusForms.begin();
654            for ( ; iter != statusForms.end(); ++iter) {
655                    DeviceStatusForm *pStatusForm = iter->second;
656                    m_ui.viewMidiDeviceStatusMenu->addAction(
657                            pStatusForm->visibleAction());
658            }
659    }
660    
661    
662  // Context menu event handler.  // Context menu event handler.
663  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )
664  {  {
665      stabilizeForm();          stabilizeForm();
666    
667      ui.editMenu->exec(pEvent->globalPos());          m_ui.editMenu->exec(pEvent->globalPos());
668  }  }
669    
670    
# Line 571  void MainForm::contextMenuEvent( QContex Line 672  void MainForm::contextMenuEvent( QContex
672  // qsamplerMainForm -- Brainless public property accessors.  // qsamplerMainForm -- Brainless public property accessors.
673    
674  // The global options settings property.  // The global options settings property.
675  qsamplerOptions *MainForm::options (void)  Options *MainForm::options (void) const
676  {  {
677      return m_pOptions;          return m_pOptions;
678  }  }
679    
680    
681  // The LSCP client descriptor property.  // The LSCP client descriptor property.
682  lscp_client_t *MainForm::client (void)  lscp_client_t *MainForm::client (void) const
683  {  {
684      return m_pClient;          return m_pClient;
685  }  }
686    
687    
# Line 597  MainForm *MainForm::getInstance (void) Line 698  MainForm *MainForm::getInstance (void)
698  // Format the displayable session filename.  // Format the displayable session filename.
699  QString MainForm::sessionName ( const QString& sFilename )  QString MainForm::sessionName ( const QString& sFilename )
700  {  {
701      bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);          bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);
702      QString sSessionName = sFilename;          QString sSessionName = sFilename;
703      if (sSessionName.isEmpty())          if (sSessionName.isEmpty())
704          sSessionName = tr("Untitled") + QString::number(m_iUntitled);                  sSessionName = tr("Untitled") + QString::number(m_iUntitled);
705      else if (!bCompletePath)          else if (!bCompletePath)
706          sSessionName = QFileInfo(sSessionName).fileName();                  sSessionName = QFileInfo(sSessionName).fileName();
707      return sSessionName;          return sSessionName;
708  }  }
709    
710    
711  // Create a new session file from scratch.  // Create a new session file from scratch.
712  bool MainForm::newSession (void)  bool MainForm::newSession (void)
713  {  {
714      // Check if we can do it.          // Check if we can do it.
715      if (!closeSession(true))          if (!closeSession(true))
716          return false;                  return false;
717    
718          // Give us what the server has, right now...          // Give us what the server has, right now...
719          updateSession();          updateSession();
720    
721      // Ok increment untitled count.          // Ok increment untitled count.
722      m_iUntitled++;          m_iUntitled++;
723    
724      // Stabilize form.          // Stabilize form.
725      m_sFilename = QString::null;          m_sFilename = QString::null;
726      m_iDirtyCount = 0;          m_iDirtyCount = 0;
727      appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));          appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));
728      stabilizeForm();          stabilizeForm();
729    
730      return true;          return true;
731  }  }
732    
733    
734  // Open an existing sampler session.  // Open an existing sampler session.
735  bool MainForm::openSession (void)  bool MainForm::openSession (void)
736  {  {
737      if (m_pOptions == NULL)          if (m_pOptions == NULL)
738          return false;                  return false;
739    
740            // Ask for the filename to open...
741            QString sFilename = QFileDialog::getOpenFileName(this,
742                    QSAMPLER_TITLE ": " + tr("Open Session"), // Caption.
743                    m_pOptions->sSessionDir,                  // Start here.
744                    tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
745            );
746    
747      // Ask for the filename to open...          // Have we cancelled?
748      QString sFilename = QFileDialog::getOpenFileName(          if (sFilename.isEmpty())
749                  m_pOptions->sSessionDir,                // Start here.                  return false;
750                  tr("LSCP Session files") + " (*.lscp)", // Filter (LSCP files)  
751                  this, 0,                                // Parent and name (none)          // Check if we're going to discard safely the current one...
752                  QSAMPLER_TITLE ": " + tr("Open Session")        // Caption.          if (!closeSession(true))
753      );                  return false;
   
     // Have we cancelled?  
     if (sFilename.isEmpty())  
         return false;  
   
     // Check if we're going to discard safely the current one...  
     if (!closeSession(true))  
         return false;  
754    
755      // Load it right away.          // Load it right away.
756      return loadSessionFile(sFilename);          return loadSessionFile(sFilename);
757  }  }
758    
759    
760  // Save current sampler session with another name.  // Save current sampler session with another name.
761  bool MainForm::saveSession ( bool bPrompt )  bool MainForm::saveSession ( bool bPrompt )
762  {  {
763      if (m_pOptions == NULL)          if (m_pOptions == NULL)
764          return false;                  return false;
765    
766      QString sFilename = m_sFilename;          QString sFilename = m_sFilename;
767    
768      // Ask for the file to save, if there's none...          // Ask for the file to save, if there's none...
769      if (bPrompt || sFilename.isEmpty()) {          if (bPrompt || sFilename.isEmpty()) {
770          // If none is given, assume default directory.                  // If none is given, assume default directory.
771          if (sFilename.isEmpty())                  if (sFilename.isEmpty())
772              sFilename = m_pOptions->sSessionDir;                          sFilename = m_pOptions->sSessionDir;
773          // Prompt the guy...                  // Prompt the guy...
774          sFilename = QFileDialog::getSaveFileName(                  sFilename = QFileDialog::getSaveFileName(this,
775                          sFilename,                              // Start here.                          QSAMPLER_TITLE ": " + tr("Save Session"), // Caption.
776                          tr("LSCP Session files") + " (*.lscp)", // Filter (LSCP files)                          sFilename,                                // Start here.
777                          this, 0,                                // Parent and name (none)                          tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
778                          QSAMPLER_TITLE ": " + tr("Save Session")        // Caption.                  );
779          );                  // Have we cancelled it?
780          // Have we cancelled it?                  if (sFilename.isEmpty())
781          if (sFilename.isEmpty())                          return false;
782              return false;                  // Enforce .lscp extension...
783          // Enforce .lscp extension...                  if (QFileInfo(sFilename).suffix().isEmpty())
784          if (QFileInfo(sFilename).extension().isEmpty())                          sFilename += ".lscp";
785              sFilename += ".lscp";                  // Check if already exists...
786          // Check if already exists...                  if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {
787          if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {                          if (QMessageBox::warning(this,
             if (QMessageBox::warning(this,  
788                                  QSAMPLER_TITLE ": " + tr("Warning"),                                  QSAMPLER_TITLE ": " + tr("Warning"),
789                  tr("The file already exists:\n\n"                                  tr("The file already exists:\n\n"
790                     "\"%1\"\n\n"                                  "\"%1\"\n\n"
791                     "Do you want to replace it?")                                  "Do you want to replace it?")
792                     .arg(sFilename),                                  .arg(sFilename),
793                  tr("Replace"), tr("Cancel")) > 0)                                  QMessageBox::Yes | QMessageBox::No)
794                  return false;                                  == QMessageBox::No)
795          }                                  return false;
796      }                  }
797            }
798    
799      // Save it right away.          // Save it right away.
800      return saveSessionFile(sFilename);          return saveSessionFile(sFilename);
801  }  }
802    
803    
804  // Close current session.  // Close current session.
805  bool MainForm::closeSession ( bool bForce )  bool MainForm::closeSession ( bool bForce )
806  {  {
807      bool bClose = true;          bool bClose = true;
808    
809      // Are we dirty enough to prompt it?          // Are we dirty enough to prompt it?
810      if (m_iDirtyCount > 0) {          if (m_iDirtyCount > 0) {
811          switch (QMessageBox::warning(this,                  switch (QMessageBox::warning(this,
812                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
813              tr("The current session has been changed:\n\n"                          tr("The current session has been changed:\n\n"
814              "\"%1\"\n\n"                          "\"%1\"\n\n"
815              "Do you want to save the changes?")                          "Do you want to save the changes?")
816              .arg(sessionName(m_sFilename)),                          .arg(sessionName(m_sFilename)),
817              tr("Save"), tr("Discard"), tr("Cancel"))) {                          QMessageBox::Save |
818          case 0:     // Save...                          QMessageBox::Discard |
819              bClose = saveSession(false);                          QMessageBox::Cancel)) {
820              // Fall thru....                  case QMessageBox::Save:
821          case 1:     // Discard                          bClose = saveSession(false);
822              break;                          // Fall thru....
823          default:    // Cancel.                  case QMessageBox::Discard:
824              bClose = false;                          break;
825              break;                  default:    // Cancel.
826          }                          bClose = false;
827      }                          break;
828                    }
829      // 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;  
     }  
830    
831      return bClose;          // If we may close it, dot it.
832            if (bClose) {
833                    // Remove all channel strips from sight...
834                    m_pWorkspace->setUpdatesEnabled(false);
835                    QWidgetList wlist = m_pWorkspace->windowList();
836                    for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
837                            ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
838                            if (pChannelStrip) {
839                                    Channel *pChannel = pChannelStrip->channel();
840                                    if (bForce && pChannel)
841                                            pChannel->removeChannel();
842                                    delete pChannelStrip;
843                            }
844                    }
845                    m_pWorkspace->setUpdatesEnabled(true);
846                    // We're now clean, for sure.
847                    m_iDirtyCount = 0;
848            }
849    
850            return bClose;
851  }  }
852    
853    
854  // Load a session from specific file path.  // Load a session from specific file path.
855  bool MainForm::loadSessionFile ( const QString& sFilename )  bool MainForm::loadSessionFile ( const QString& sFilename )
856  {  {
857      if (m_pClient == NULL)          if (m_pClient == NULL)
858          return false;                  return false;
859    
860      // Open and read from real file.          // Open and read from real file.
861      QFile file(sFilename);          QFile file(sFilename);
862      if (!file.open(IO_ReadOnly)) {          if (!file.open(QIODevice::ReadOnly)) {
863          appendMessagesError(tr("Could not open \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
864          return false;                          tr("Could not open \"%1\" session file.\n\nSorry.")
865      }                          .arg(sFilename));
866                    return false;
867            }
868    
869          // Tell the world we'll take some time...          // Tell the world we'll take some time...
870          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
871    
872      // Read the file.          // Read the file.
873          int iLine = 0;          int iLine = 0;
874      int iErrors = 0;          int iErrors = 0;
875      QTextStream ts(&file);          QTextStream ts(&file);
876      while (!ts.atEnd()) {          while (!ts.atEnd()) {
877          // Read the line.                  // Read the line.
878          QString sCommand = ts.readLine().stripWhiteSpace();                  QString sCommand = ts.readLine().trimmed();
879                  iLine++;                  iLine++;
880          // If not empty, nor a comment, call the server...                  // If not empty, nor a comment, call the server...
881          if (!sCommand.isEmpty() && sCommand[0] != '#') {                  if (!sCommand.isEmpty() && sCommand[0] != '#') {
882                          // Remember that, no matter what,                          // Remember that, no matter what,
883                          // all LSCP commands are CR/LF terminated.                          // all LSCP commands are CR/LF terminated.
884                          sCommand += "\r\n";                          sCommand += "\r\n";
885                          if (::lscp_client_query(m_pClient, sCommand.latin1()) != LSCP_OK) {                          if (::lscp_client_query(m_pClient, sCommand.toUtf8().constData())
886                                    != LSCP_OK) {
887                                  appendMessagesColor(QString("%1(%2): %3")                                  appendMessagesColor(QString("%1(%2): %3")
888                                          .arg(QFileInfo(sFilename).fileName()).arg(iLine)                                          .arg(QFileInfo(sFilename).fileName()).arg(iLine)
889                                          .arg(sCommand.simplifyWhiteSpace()), "#996633");                                          .arg(sCommand.simplified()), "#996633");
890                                  appendMessagesClient("lscp_client_query");                                  appendMessagesClient("lscp_client_query");
891                                  iErrors++;                                  iErrors++;
892                          }                          }
893          }                  }
894          // Try to make it snappy :)                  // Try to make it snappy :)
895          QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
896      }          }
897    
898      // Ok. we've read it.          // Ok. we've read it.
899      file.close();          file.close();
900    
901          // Now we'll try to create (update) the whole GUI session.          // Now we'll try to create (update) the whole GUI session.
902          updateSession();          updateSession();
# Line 800  bool MainForm::loadSessionFile ( const Q Line 905  bool MainForm::loadSessionFile ( const Q
905          QApplication::restoreOverrideCursor();          QApplication::restoreOverrideCursor();
906    
907          // Have we any errors?          // Have we any errors?
908          if (iErrors > 0)          if (iErrors > 0) {
909                  appendMessagesError(tr("Session loaded with errors\nfrom \"%1\".\n\nSorry.").arg(sFilename));                  appendMessagesError(
910                            tr("Session loaded with errors\nfrom \"%1\".\n\nSorry.")
911                            .arg(sFilename));
912            }
913    
914      // Save as default session directory.          // Save as default session directory.
915      if (m_pOptions)          if (m_pOptions)
916          m_pOptions->sSessionDir = QFileInfo(sFilename).dirPath(true);                  m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();
917          // We're not dirty anymore, if loaded without errors,          // We're not dirty anymore, if loaded without errors,
918          m_iDirtyCount = iErrors;          m_iDirtyCount = iErrors;
919      // Stabilize form...          // Stabilize form...
920      m_sFilename = sFilename;          m_sFilename = sFilename;
921      updateRecentFiles(sFilename);          updateRecentFiles(sFilename);
922      appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));          appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));
923    
924      // Make that an overall update.          // Make that an overall update.
925      stabilizeForm();          stabilizeForm();
926      return true;          return true;
927  }  }
928    
929    
# Line 831  bool MainForm::saveSessionFile ( const Q Line 939  bool MainForm::saveSessionFile ( const Q
939                  return false;                  return false;
940          }          }
941    
942      // Open and write into real file.          // Open and write into real file.
943      QFile file(sFilename);          QFile file(sFilename);
944      if (!file.open(IO_WriteOnly | IO_Truncate)) {          if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
945          appendMessagesError(tr("Could not open \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
946          return false;                          tr("Could not open \"%1\" session file.\n\nSorry.")
947      }                          .arg(sFilename));
948                    return false;
949            }
950    
951          // Tell the world we'll take some time...          // Tell the world we'll take some time...
952          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
953    
954      // Write the file.          // Write the file.
955      int  iErrors = 0;          int  iErrors = 0;
956      QTextStream ts(&file);          QTextStream ts(&file);
957      ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;          ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;
958      ts << "# " << tr("Version")          ts << "# " << tr("Version")
959         << ": " QSAMPLER_VERSION << endl;          << ": " QSAMPLER_VERSION << endl;
960      ts << "# " << tr("Build")          ts << "# " << tr("Build")
961         << ": " __DATE__ " " __TIME__ << endl;          << ": " __DATE__ " " __TIME__ << endl;
962      ts << "#"  << endl;          ts << "#"  << endl;
963      ts << "# " << tr("File")          ts << "# " << tr("File")
964         << ": " << QFileInfo(sFilename).fileName() << endl;          << ": " << QFileInfo(sFilename).fileName() << endl;
965      ts << "# " << tr("Date")          ts << "# " << tr("Date")
966         << ": " << QDate::currentDate().toString("MMM dd yyyy")          << ": " << QDate::currentDate().toString("MMM dd yyyy")
967         << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;          << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;
968      ts << "#"  << endl;          ts << "#"  << endl;
969      ts << endl;          ts << endl;
970    
971          // It is assumed that this new kind of device+session file          // It is assumed that this new kind of device+session file
972          // will be loaded from a complete initialized server...          // will be loaded from a complete initialized server...
# Line 866  bool MainForm::saveSessionFile ( const Q Line 976  bool MainForm::saveSessionFile ( const Q
976    
977          // Audio device mapping.          // Audio device mapping.
978          QMap<int, int> audioDeviceMap;          QMap<int, int> audioDeviceMap;
979          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Audio);          piDeviceIDs = Device::getDevices(m_pClient, Device::Audio);
980          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
981                  ts << endl;                  ts << endl;
982                  qsamplerDevice device(qsamplerDevice::Audio, piDeviceIDs[iDevice]);                  Device device(Device::Audio, piDeviceIDs[iDevice]);
983                  // Audio device specification...                  // Audio device specification...
984                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
985                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
986                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();
987                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
988                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
989                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
990                                          ++deviceParam) {                                          ++deviceParam) {
991                          const qsamplerDeviceParam& param = deviceParam.data();                          const DeviceParam& param = deviceParam.value();
992                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
993                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
994                  }                  }
995                  ts << endl;                  ts << endl;
996                  // Audio channel parameters...                  // Audio channel parameters...
997                  int iPort = 0;                  int iPort = 0;
998                  for (qsamplerDevicePort *pPort = device.ports().first();                  QListIterator<DevicePort *> iter(device.ports());
999                                  pPort;                  while (iter.hasNext()) {
1000                                          pPort = device.ports().next(), ++iPort) {                          DevicePort *pPort = iter.next();
1001                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1002                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1003                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1004                                                  ++portParam) {                                                  ++portParam) {
1005                                  const qsamplerDeviceParam& param = portParam.data();                                  const DeviceParam& param = portParam.value();
1006                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1007                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice
1008                                          << " " << iPort << " " << portParam.key()                                          << " " << iPort << " " << portParam.key()
1009                                          << "='" << param.value << "'" << endl;                                          << "='" << param.value << "'" << endl;
1010                          }                          }
1011                            iPort++;
1012                  }                  }
1013                  // Audio device index/id mapping.                  // Audio device index/id mapping.
1014                  audioDeviceMap[device.deviceID()] = iDevice;                  audioDeviceMap[device.deviceID()] = iDevice;
1015                  // Try to keep it snappy :)                  // Try to keep it snappy :)
1016                  QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1017          }          }
1018    
1019          // MIDI device mapping.          // MIDI device mapping.
1020          QMap<int, int> midiDeviceMap;          QMap<int, int> midiDeviceMap;
1021          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Midi);          piDeviceIDs = Device::getDevices(m_pClient, Device::Midi);
1022          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
1023                  ts << endl;                  ts << endl;
1024                  qsamplerDevice device(qsamplerDevice::Midi, piDeviceIDs[iDevice]);                  Device device(Device::Midi, piDeviceIDs[iDevice]);
1025                  // MIDI device specification...                  // MIDI device specification...
1026                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1027                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1028                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();
1029                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
1030                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
1031                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
1032                                          ++deviceParam) {                                          ++deviceParam) {
1033                          const qsamplerDeviceParam& param = deviceParam.data();                          const DeviceParam& param = deviceParam.value();
1034                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
1035                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
1036                  }                  }
1037                  ts << endl;                  ts << endl;
1038                  // MIDI port parameters...                  // MIDI port parameters...
1039                  int iPort = 0;                  int iPort = 0;
1040                  for (qsamplerDevicePort *pPort = device.ports().first();                  QListIterator<DevicePort *> iter(device.ports());
1041                                  pPort;                  while (iter.hasNext()) {
1042                                          pPort = device.ports().next(), ++iPort) {                          DevicePort *pPort = iter.next();
1043                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1044                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1045                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1046                                                  ++portParam) {                                                  ++portParam) {
1047                                  const qsamplerDeviceParam& param = portParam.data();                                  const DeviceParam& param = portParam.value();
1048                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1049                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice
1050                                     << " " << iPort << " " << portParam.key()                                  << " " << iPort << " " << portParam.key()
1051                                     << "='" << param.value << "'" << endl;                                  << "='" << param.value << "'" << endl;
1052                          }                          }
1053                            iPort++;
1054                  }                  }
1055                  // MIDI device index/id mapping.                  // MIDI device index/id mapping.
1056                  midiDeviceMap[device.deviceID()] = iDevice;                  midiDeviceMap[device.deviceID()] = iDevice;
1057                  // Try to keep it snappy :)                  // Try to keep it snappy :)
1058                  QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1059          }          }
1060          ts << endl;          ts << endl;
1061    
# Line 1000  bool MainForm::saveSessionFile ( const Q Line 1112  bool MainForm::saveSessionFile ( const Q
1112                                  iErrors++;                                  iErrors++;
1113                          }                          }
1114                          // Try to keep it snappy :)                          // Try to keep it snappy :)
1115                          QApplication::processEvents(QEventLoop::ExcludeUserInput);                          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1116                  }                  }
1117                  ts << endl;                  ts << endl;
1118                  // Check for errors...                  // Check for errors...
# Line 1019  bool MainForm::saveSessionFile ( const Q Line 1131  bool MainForm::saveSessionFile ( const Q
1131  #endif  // CONFIG_MIDI_INSTRUMENT  #endif  // CONFIG_MIDI_INSTRUMENT
1132    
1133          // Sampler channel mapping.          // Sampler channel mapping.
1134      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
1135      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1136          ChannelStrip* pChannelStrip                  ChannelStrip* pChannelStrip
1137                          = static_cast<ChannelStrip *> (wlist.at(iChannel));                          = static_cast<ChannelStrip *> (wlist.at(iChannel));
1138          if (pChannelStrip) {                  if (pChannelStrip) {
1139              qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
1140              if (pChannel) {                          if (pChannel) {
1141                  ts << "# " << tr("Channel") << " " << iChannel << endl;                                  ts << "# " << tr("Channel") << " " << iChannel << endl;
1142                  ts << "ADD CHANNEL" << endl;                                  ts << "ADD CHANNEL" << endl;
1143                                  if (audioDeviceMap.isEmpty()) {                                  if (audioDeviceMap.isEmpty()) {
1144                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel
1145                                                  << " " << pChannel->audioDriver() << endl;                                                  << " " << pChannel->audioDriver() << endl;
# Line 1044  bool MainForm::saveSessionFile ( const Q Line 1156  bool MainForm::saveSessionFile ( const Q
1156                                  }                                  }
1157                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel
1158                                          << " " << pChannel->midiPort() << endl;                                          << " " << pChannel->midiPort() << endl;
1159                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";                                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";
1160                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)                                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
1161                      ts << "ALL";                                          ts << "ALL";
1162                  else                                  else
1163                      ts << pChannel->midiChannel();                                          ts << pChannel->midiChannel();
1164                  ts << endl;                                  ts << endl;
1165                  ts << "LOAD ENGINE " << pChannel->engineName() << " " << iChannel << endl;                                  ts << "LOAD ENGINE " << pChannel->engineName()
1166                                            << " " << iChannel << endl;
1167                                  if (pChannel->instrumentStatus() < 100) ts << "# ";                                  if (pChannel->instrumentStatus() < 100) ts << "# ";
1168                                  ts << "LOAD INSTRUMENT NON_MODAL '" << pChannel->instrumentFile() << "' "                                  ts << "LOAD INSTRUMENT NON_MODAL '"
1169                                            << pChannel->instrumentFile() << "' "
1170                                          << pChannel->instrumentNr() << " " << iChannel << endl;                                          << pChannel->instrumentNr() << " " << iChannel << endl;
1171                                  qsamplerChannelRoutingMap::ConstIterator audioRoute;                                  ChannelRoutingMap::ConstIterator audioRoute;
1172                                  for (audioRoute = pChannel->audioRouting().begin();                                  for (audioRoute = pChannel->audioRouting().begin();
1173                                                  audioRoute != pChannel->audioRouting().end();                                                  audioRoute != pChannel->audioRouting().end();
1174                                                          ++audioRoute) {                                                          ++audioRoute) {
1175                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannel
1176                                                  << " " << audioRoute.key()                                                  << " " << audioRoute.key()
1177                                                  << " " << audioRoute.data() << endl;                                                  << " " << audioRoute.value() << endl;
1178                                  }                                  }
1179                                  ts << "SET CHANNEL VOLUME " << iChannel                                  ts << "SET CHANNEL VOLUME " << iChannel
1180                                          << " " << pChannel->volume() << endl;                                          << " " << pChannel->volume() << endl;
# Line 1110  bool MainForm::saveSessionFile ( const Q Line 1224  bool MainForm::saveSessionFile ( const Q
1224                                          }                                          }
1225                                  }                                  }
1226  #endif  #endif
1227                  ts << endl;                                  ts << endl;
1228              }                          }
1229          }                  }
1230          // Try to keep it snappy :)                  // Try to keep it snappy :)
1231          QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1232      }          }
1233    
1234  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
1235          ts << "# " << tr("Global volume level") << endl;          ts << "# " << tr("Global volume level") << endl;
# Line 1123  bool MainForm::saveSessionFile ( const Q Line 1237  bool MainForm::saveSessionFile ( const Q
1237          ts << endl;          ts << endl;
1238  #endif  #endif
1239    
1240      // Ok. we've wrote it.          // Ok. we've wrote it.
1241      file.close();          file.close();
1242    
1243          // We're fornerly done.          // We're fornerly done.
1244          QApplication::restoreOverrideCursor();          QApplication::restoreOverrideCursor();
1245    
1246      // Have we any errors?          // Have we any errors?
1247      if (iErrors > 0)          if (iErrors > 0) {
1248          appendMessagesError(tr("Some settings could not be saved\nto \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
1249                            tr("Some settings could not be saved\n"
1250      // Save as default session directory.                          "to \"%1\" session file.\n\nSorry.")
1251      if (m_pOptions)                          .arg(sFilename));
1252          m_pOptions->sSessionDir = QFileInfo(sFilename).dirPath(true);          }
1253      // We're not dirty anymore.  
1254      m_iDirtyCount = 0;          // Save as default session directory.
1255      // Stabilize form...          if (m_pOptions)
1256      m_sFilename = sFilename;                  m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();
1257      updateRecentFiles(sFilename);          // We're not dirty anymore.
1258      appendMessages(tr("Save session: \"%1\".").arg(sessionName(m_sFilename)));          m_iDirtyCount = 0;
1259      stabilizeForm();          // Stabilize form...
1260      return true;          m_sFilename = sFilename;
1261            updateRecentFiles(sFilename);
1262            appendMessages(tr("Save session: \"%1\".").arg(sessionName(m_sFilename)));
1263            stabilizeForm();
1264            return true;
1265  }  }
1266    
1267    
1268  // Session change receiver slot.  // Session change receiver slot.
1269  void MainForm::sessionDirty (void)  void MainForm::sessionDirty (void)
1270  {  {
1271      // Just mark the dirty form.          // Just mark the dirty form.
1272      m_iDirtyCount++;          m_iDirtyCount++;
1273      // and update the form status...          // and update the form status...
1274      stabilizeForm();          stabilizeForm();
1275  }  }
1276    
1277    
# Line 1163  void MainForm::sessionDirty (void) Line 1281  void MainForm::sessionDirty (void)
1281  // Create a new sampler session.  // Create a new sampler session.
1282  void MainForm::fileNew (void)  void MainForm::fileNew (void)
1283  {  {
1284      // Of course we'll start clean new.          // Of course we'll start clean new.
1285      newSession();          newSession();
1286  }  }
1287    
1288    
1289  // Open an existing sampler session.  // Open an existing sampler session.
1290  void MainForm::fileOpen (void)  void MainForm::fileOpen (void)
1291  {  {
1292      // Open it right away.          // Open it right away.
1293      openSession();          openSession();
1294  }  }
1295    
1296    
1297  // Open a recent file session.  // Open a recent file session.
1298  void MainForm::fileOpenRecent ( int iIndex )  void MainForm::fileOpenRecent (void)
1299  {  {
1300      // Check if we can safely close the current session...          // Retrive filename index from action data...
1301      if (m_pOptions && closeSession(true)) {          QAction *pAction = qobject_cast<QAction *> (sender());
1302          QString sFilename = m_pOptions->recentFiles[iIndex];          if (pAction && m_pOptions) {
1303          loadSessionFile(sFilename);                  int iIndex = pAction->data().toInt();
1304      }                  if (iIndex >= 0 && iIndex < m_pOptions->recentFiles.count()) {
1305                            QString sFilename = m_pOptions->recentFiles[iIndex];
1306                            // Check if we can safely close the current session...
1307                            if (!sFilename.isEmpty() && closeSession(true))
1308                                    loadSessionFile(sFilename);
1309                    }
1310            }
1311  }  }
1312    
1313    
1314  // Save current sampler session.  // Save current sampler session.
1315  void MainForm::fileSave (void)  void MainForm::fileSave (void)
1316  {  {
1317      // Save it right away.          // Save it right away.
1318      saveSession(false);          saveSession(false);
1319  }  }
1320    
1321    
1322  // Save current sampler session with another name.  // Save current sampler session with another name.
1323  void MainForm::fileSaveAs (void)  void MainForm::fileSaveAs (void)
1324  {  {
1325      // Save it right away, maybe with another name.          // Save it right away, maybe with another name.
1326      saveSession(true);          saveSession(true);
1327  }  }
1328    
1329    
1330  // Reset the sampler instance.  // Reset the sampler instance.
1331  void MainForm::fileReset (void)  void MainForm::fileReset (void)
1332  {  {
1333      if (m_pClient == NULL)          if (m_pClient == NULL)
1334          return;                  return;
1335    
1336      // Ask user whether he/she want's an internal sampler reset...          // Ask user whether he/she want's an internal sampler reset...
1337      if (QMessageBox::warning(this,          if (QMessageBox::warning(this,
1338                  QSAMPLER_TITLE ": " + tr("Warning"),                  QSAMPLER_TITLE ": " + tr("Warning"),
1339          tr("Resetting the sampler instance will close\n"                  tr("Resetting the sampler instance will close\n"
1340             "all device and channel configurations.\n\n"                  "all device and channel configurations.\n\n"
1341             "Please note that this operation may cause\n"                  "Please note that this operation may cause\n"
1342             "temporary MIDI and Audio disruption.\n\n"                  "temporary MIDI and Audio disruption.\n\n"
1343             "Do you want to reset the sampler engine now?"),                  "Do you want to reset the sampler engine now?"),
1344          tr("Reset"), tr("Cancel")) > 0)                  QMessageBox::Ok | QMessageBox::Cancel)
1345          return;                  == QMessageBox::Cancel)
1346                    return;
1347    
1348          // Trye closing the current session, first...          // Trye closing the current session, first...
1349          if (!closeSession(true))          if (!closeSession(true))
1350                  return;                  return;
1351    
1352      // Just do the reset, after closing down current session...          // Just do the reset, after closing down current session...
1353          // Do the actual sampler reset...          // Do the actual sampler reset...
1354          if (::lscp_reset_sampler(m_pClient) != LSCP_OK) {          if (::lscp_reset_sampler(m_pClient) != LSCP_OK) {
1355                  appendMessagesClient("lscp_reset_sampler");                  appendMessagesClient("lscp_reset_sampler");
# Line 1232  void MainForm::fileReset (void) Line 1357  void MainForm::fileReset (void)
1357                  return;                  return;
1358          }          }
1359    
1360      // Log this.          // Log this.
1361      appendMessages(tr("Sampler reset."));          appendMessages(tr("Sampler reset."));
1362    
1363          // Make it a new session...          // Make it a new session...
1364          newSession();          newSession();
# Line 1243  void MainForm::fileReset (void) Line 1368  void MainForm::fileReset (void)
1368  // Restart the client/server instance.  // Restart the client/server instance.
1369  void MainForm::fileRestart (void)  void MainForm::fileRestart (void)
1370  {  {
1371      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1372          return;                  return;
1373    
1374      bool bRestart = true;          bool bRestart = true;
1375    
1376      // Ask user whether he/she want's a complete restart...          // Ask user whether he/she want's a complete restart...
1377      // (if we're currently up and running)          // (if we're currently up and running)
1378      if (bRestart && m_pClient) {          if (bRestart && m_pClient) {
1379          bRestart = (QMessageBox::warning(this,                  bRestart = (QMessageBox::warning(this,
1380                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
1381              tr("New settings will be effective after\n"                          tr("New settings will be effective after\n"
1382                 "restarting the client/server connection.\n\n"                          "restarting the client/server connection.\n\n"
1383                 "Please note that this operation may cause\n"                          "Please note that this operation may cause\n"
1384                 "temporary MIDI and Audio disruption.\n\n"                          "temporary MIDI and Audio disruption.\n\n"
1385                 "Do you want to restart the connection now?"),                          "Do you want to restart the connection now?"),
1386              tr("Restart"), tr("Cancel")) == 0);                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok);
1387      }          }
1388    
1389      // Are we still for it?          // Are we still for it?
1390      if (bRestart && closeSession(true)) {          if (bRestart && closeSession(true)) {
1391          // Stop server, it will force the client too.                  // Stop server, it will force the client too.
1392          stopServer();                  stopServer();
1393          // Reschedule a restart...                  // Reschedule a restart...
1394          startSchedule(m_pOptions->iStartDelay);                  startSchedule(m_pOptions->iStartDelay);
1395      }          }
1396  }  }
1397    
1398    
1399  // Exit application program.  // Exit application program.
1400  void MainForm::fileExit (void)  void MainForm::fileExit (void)
1401  {  {
1402      // Go for close the whole thing.          // Go for close the whole thing.
1403      close();          close();
1404  }  }
1405    
1406    
# Line 1285  void MainForm::fileExit (void) Line 1410  void MainForm::fileExit (void)
1410  // Add a new sampler channel.  // Add a new sampler channel.
1411  void MainForm::editAddChannel (void)  void MainForm::editAddChannel (void)
1412  {  {
1413      if (m_pClient == NULL)          if (m_pClient == NULL)
1414          return;                  return;
1415    
1416            // Just create the channel instance...
1417            Channel *pChannel = new Channel();
1418            if (pChannel == NULL)
1419                    return;
1420    
1421            // Before we show it up, may be we'll
1422            // better ask for some initial values?
1423            if (!pChannel->channelSetup(this)) {
1424                    delete pChannel;
1425                    return;
1426            }
1427    
1428            // And give it to the strip...
1429            // (will own the channel instance, if successful).
1430            if (!createChannelStrip(pChannel)) {
1431                    delete pChannel;
1432                    return;
1433            }
1434    
1435            // Do we auto-arrange?
1436            if (m_pOptions && m_pOptions->bAutoArrange)
1437                    channelsArrange();
1438    
1439      // Just create the channel instance...          // Make that an overall update.
1440      qsamplerChannel *pChannel = new qsamplerChannel();          m_iDirtyCount++;
1441      if (pChannel == NULL)          stabilizeForm();
         return;  
   
     // Before we show it up, may be we'll  
     // better ask for some initial values?  
     if (!pChannel->channelSetup(this)) {  
         delete pChannel;  
         return;  
     }  
   
     // And give it to the strip (will own the channel instance, if successful).  
     if (!createChannelStrip(pChannel)) {  
         delete pChannel;  
         return;  
     }  
   
     // Make that an overall update.  
     m_iDirtyCount++;  
     stabilizeForm();  
1442  }  }
1443    
1444    
1445  // Remove current sampler channel.  // Remove current sampler channel.
1446  void MainForm::editRemoveChannel (void)  void MainForm::editRemoveChannel (void)
1447  {  {
1448      if (m_pClient == NULL)          if (m_pClient == NULL)
1449          return;                  return;
1450    
1451      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1452      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1453          return;                  return;
1454    
1455      qsamplerChannel *pChannel = pChannelStrip->channel();          Channel *pChannel = pChannelStrip->channel();
1456      if (pChannel == NULL)          if (pChannel == NULL)
1457          return;                  return;
1458    
1459      // Prompt user if he/she's sure about this...          // Prompt user if he/she's sure about this...
1460      if (m_pOptions && m_pOptions->bConfirmRemove) {          if (m_pOptions && m_pOptions->bConfirmRemove) {
1461          if (QMessageBox::warning(this,                  if (QMessageBox::warning(this,
1462                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
1463              tr("About to remove channel:\n\n"                          tr("About to remove channel:\n\n"
1464                 "%1\n\n"                          "%1\n\n"
1465                 "Are you sure?")                          "Are you sure?")
1466                 .arg(pChannelStrip->caption()),                          .arg(pChannelStrip->windowTitle()),
1467              tr("OK"), tr("Cancel")) > 0)                          QMessageBox::Ok | QMessageBox::Cancel)
1468              return;                          == QMessageBox::Cancel)
1469      }                          return;
1470            }
1471      // Remove the existing sampler channel.  
1472      if (!pChannel->removeChannel())          // Remove the existing sampler channel.
1473          return;          if (!pChannel->removeChannel())
1474                    return;
1475      // Just delete the channel strip.  
1476      delete pChannelStrip;          // Just delete the channel strip.
1477            delete pChannelStrip;
1478      // Do we auto-arrange?  
1479      if (m_pOptions && m_pOptions->bAutoArrange)          // Do we auto-arrange?
1480          channelsArrange();          if (m_pOptions && m_pOptions->bAutoArrange)
1481                    channelsArrange();
1482      // We'll be dirty, for sure...  
1483      m_iDirtyCount++;          // We'll be dirty, for sure...
1484      stabilizeForm();          m_iDirtyCount++;
1485            stabilizeForm();
1486  }  }
1487    
1488    
1489  // Setup current sampler channel.  // Setup current sampler channel.
1490  void MainForm::editSetupChannel (void)  void MainForm::editSetupChannel (void)
1491  {  {
1492      if (m_pClient == NULL)          if (m_pClient == NULL)
1493          return;                  return;
1494    
1495      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1496      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1497          return;                  return;
1498    
1499      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1500      pChannelStrip->channelSetup();          pChannelStrip->channelSetup();
1501  }  }
1502    
1503    
1504  // Edit current sampler channel.  // Edit current sampler channel.
1505  void MainForm::editEditChannel (void)  void MainForm::editEditChannel (void)
1506  {  {
1507      if (m_pClient == NULL)          if (m_pClient == NULL)
1508          return;                  return;
1509    
1510      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1511      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1512          return;                  return;
1513    
1514      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1515      pChannelStrip->channelEdit();          pChannelStrip->channelEdit();
1516  }  }
1517    
1518    
1519  // Reset current sampler channel.  // Reset current sampler channel.
1520  void MainForm::editResetChannel (void)  void MainForm::editResetChannel (void)
1521  {  {
1522      if (m_pClient == NULL)          if (m_pClient == NULL)
1523          return;                  return;
1524    
1525      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1526      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1527          return;                  return;
1528    
1529      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1530      pChannelStrip->channelReset();          pChannelStrip->channelReset();
1531  }  }
1532    
1533    
# Line 1425  void MainForm::editResetAllChannels (voi Line 1556  void MainForm::editResetAllChannels (voi
1556  // Show/hide the main program window menubar.  // Show/hide the main program window menubar.
1557  void MainForm::viewMenubar ( bool bOn )  void MainForm::viewMenubar ( bool bOn )
1558  {  {
1559      if (bOn)          if (bOn)
1560          ui.MenuBar->show();                  m_ui.MenuBar->show();
1561      else          else
1562          ui.MenuBar->hide();                  m_ui.MenuBar->hide();
1563  }  }
1564    
1565    
1566  // Show/hide the main program window toolbar.  // Show/hide the main program window toolbar.
1567  void MainForm::viewToolbar ( bool bOn )  void MainForm::viewToolbar ( bool bOn )
1568  {  {
1569      if (bOn) {          if (bOn) {
1570          ui.fileToolbar->show();                  m_ui.fileToolbar->show();
1571          ui.editToolbar->show();                  m_ui.editToolbar->show();
1572          ui.channelsToolbar->show();                  m_ui.channelsToolbar->show();
1573      } else {          } else {
1574          ui.fileToolbar->hide();                  m_ui.fileToolbar->hide();
1575          ui.editToolbar->hide();                  m_ui.editToolbar->hide();
1576          ui.channelsToolbar->hide();                  m_ui.channelsToolbar->hide();
1577      }          }
1578  }  }
1579    
1580    
1581  // Show/hide the main program window statusbar.  // Show/hide the main program window statusbar.
1582  void MainForm::viewStatusbar ( bool bOn )  void MainForm::viewStatusbar ( bool bOn )
1583  {  {
1584      if (bOn)          if (bOn)
1585          statusBar()->show();                  statusBar()->show();
1586      else          else
1587          statusBar()->hide();                  statusBar()->hide();
1588  }  }
1589    
1590    
1591  // Show/hide the messages window logger.  // Show/hide the messages window logger.
1592  void MainForm::viewMessages ( bool bOn )  void MainForm::viewMessages ( bool bOn )
1593  {  {
1594      if (bOn)          if (bOn)
1595          m_pMessages->show();                  m_pMessages->show();
1596      else          else
1597          m_pMessages->hide();                  m_pMessages->hide();
1598  }  }
1599    
1600    
# Line 1480  void MainForm::viewInstruments (void) Line 1611  void MainForm::viewInstruments (void)
1611                  } else {                  } else {
1612                          m_pInstrumentListForm->show();                          m_pInstrumentListForm->show();
1613                          m_pInstrumentListForm->raise();                          m_pInstrumentListForm->raise();
1614                          m_pInstrumentListForm->setActiveWindow();                          m_pInstrumentListForm->activateWindow();
1615                  }                  }
1616          }          }
1617  }  }
# Line 1499  void MainForm::viewDevices (void) Line 1630  void MainForm::viewDevices (void)
1630                  } else {                  } else {
1631                          m_pDeviceForm->show();                          m_pDeviceForm->show();
1632                          m_pDeviceForm->raise();                          m_pDeviceForm->raise();
1633                          m_pDeviceForm->setActiveWindow();                          m_pDeviceForm->activateWindow();
1634                  }                  }
1635          }          }
1636  }  }
# Line 1508  void MainForm::viewDevices (void) Line 1639  void MainForm::viewDevices (void)
1639  // Show options dialog.  // Show options dialog.
1640  void MainForm::viewOptions (void)  void MainForm::viewOptions (void)
1641  {  {
1642      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1643          return;                  return;
1644    
1645      OptionsForm* pOptionsForm = new OptionsForm(this);          OptionsForm* pOptionsForm = new OptionsForm(this);
1646      if (pOptionsForm) {          if (pOptionsForm) {
1647          // Check out some initial nullities(tm)...                  // Check out some initial nullities(tm)...
1648          ChannelStrip* pChannelStrip = activeChannelStrip();                  ChannelStrip* pChannelStrip = activeChannelStrip();
1649          if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)
1650              m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();
1651          if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)
1652              m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
1653          // To track down deferred or immediate changes.                  // To track down deferred or immediate changes.
1654          QString sOldServerHost      = m_pOptions->sServerHost;                  QString sOldServerHost      = m_pOptions->sServerHost;
1655          int     iOldServerPort      = m_pOptions->iServerPort;                  int     iOldServerPort      = m_pOptions->iServerPort;
1656          int     iOldServerTimeout   = m_pOptions->iServerTimeout;                  int     iOldServerTimeout   = m_pOptions->iServerTimeout;
1657          bool    bOldServerStart     = m_pOptions->bServerStart;                  bool    bOldServerStart     = m_pOptions->bServerStart;
1658          QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;                  QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;
1659          QString sOldDisplayFont     = m_pOptions->sDisplayFont;                  bool    bOldMessagesLog     = m_pOptions->bMessagesLog;
1660          bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;                  QString sOldMessagesLogPath = m_pOptions->sMessagesLogPath;
1661          int     iOldMaxVolume       = m_pOptions->iMaxVolume;                  QString sOldDisplayFont     = m_pOptions->sDisplayFont;
1662          QString sOldMessagesFont    = m_pOptions->sMessagesFont;                  bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;
1663          bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;                  int     iOldMaxVolume       = m_pOptions->iMaxVolume;
1664          bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;                  QString sOldMessagesFont    = m_pOptions->sMessagesFont;
1665          int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;                  bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;
1666          int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;                  bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;
1667          bool    bOldCompletePath    = m_pOptions->bCompletePath;                  int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;
1668          bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;                  int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;
1669          int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;                  bool    bOldCompletePath    = m_pOptions->bCompletePath;
1670          // Load the current setup settings.                  bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;
1671          pOptionsForm->setup(m_pOptions);                  int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;
1672          // Show the setup dialog...                  int     iOldBaseFontSize    = m_pOptions->iBaseFontSize;
1673          if (pOptionsForm->exec()) {                  // Load the current setup settings.
1674              // Warn if something will be only effective on next run.                  pOptionsForm->setup(m_pOptions);
1675              if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||                  // Show the setup dialog...
1676                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||                  if (pOptionsForm->exec()) {
1677                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||                          // Warn if something will be only effective on next run.
1678                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1679                  QMessageBox::information(this,                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||
1680                                    ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||
1681                                    (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)     ||
1682                                    (iOldBaseFontSize   !=  m_pOptions->iBaseFontSize)) {
1683                                    QMessageBox::information(this,
1684                                          QSAMPLER_TITLE ": " + tr("Information"),                                          QSAMPLER_TITLE ": " + tr("Information"),
1685                      tr("Some settings may be only effective\n"                                          tr("Some settings may be only effective\n"
1686                         "next time you start this program."), tr("OK"));                                          "next time you start this program."));
1687                  updateMessagesCapture();                                  updateMessagesCapture();
1688              }                          }
1689              // Check wheather something immediate has changed.                          // Check wheather something immediate has changed.
1690              if (( bOldCompletePath && !m_pOptions->bCompletePath) ||                          if (( bOldMessagesLog && !m_pOptions->bMessagesLog) ||
1691                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||                                  (!bOldMessagesLog &&  m_pOptions->bMessagesLog) ||
1692                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))                                  (sOldMessagesLogPath != m_pOptions->sMessagesLogPath))
1693                  updateRecentFilesMenu();                                  m_pMessages->setLogging(
1694              if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||                                          m_pOptions->bMessagesLog, m_pOptions->sMessagesLogPath);
1695                  (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||
1696                  updateInstrumentNames();                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||
1697              if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
1698                  (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))                                  updateRecentFilesMenu();
1699                  updateDisplayEffect();                          if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||
1700              if (sOldDisplayFont != m_pOptions->sDisplayFont)                                  (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))
1701                  updateDisplayFont();                                  updateInstrumentNames();
1702              if (iOldMaxVolume != m_pOptions->iMaxVolume)                          if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||
1703                  updateMaxVolume();                                  (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))
1704              if (sOldMessagesFont != m_pOptions->sMessagesFont)                                  updateDisplayEffect();
1705                  updateMessagesFont();                          if (sOldDisplayFont != m_pOptions->sDisplayFont)
1706              if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||                                  updateDisplayFont();
1707                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||                          if (iOldMaxVolume != m_pOptions->iMaxVolume)
1708                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))                                  updateMaxVolume();
1709                  updateMessagesLimit();                          if (sOldMessagesFont != m_pOptions->sMessagesFont)
1710              // And now the main thing, whether we'll do client/server recycling?                                  updateMessagesFont();
1711              if ((sOldServerHost != m_pOptions->sServerHost) ||                          if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||
1712                  (iOldServerPort != m_pOptions->iServerPort) ||                                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||
1713                  (iOldServerTimeout != m_pOptions->iServerTimeout) ||                                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))
1714                  ( bOldServerStart && !m_pOptions->bServerStart) ||                                  updateMessagesLimit();
1715                  (!bOldServerStart &&  m_pOptions->bServerStart) ||                          // And now the main thing, whether we'll do client/server recycling?
1716                  (sOldServerCmdLine != m_pOptions->sServerCmdLine && m_pOptions->bServerStart))                          if ((sOldServerHost != m_pOptions->sServerHost) ||
1717                  fileRestart();                                  (iOldServerPort != m_pOptions->iServerPort) ||
1718          }                                  (iOldServerTimeout != m_pOptions->iServerTimeout) ||
1719          // Done.                                  ( bOldServerStart && !m_pOptions->bServerStart) ||
1720          delete pOptionsForm;                                  (!bOldServerStart &&  m_pOptions->bServerStart) ||
1721      }                                  (sOldServerCmdLine != m_pOptions->sServerCmdLine
1722                                    && m_pOptions->bServerStart))
1723                                    fileRestart();
1724                    }
1725                    // Done.
1726                    delete pOptionsForm;
1727            }
1728    
1729      // This makes it.          // This makes it.
1730      stabilizeForm();          stabilizeForm();
1731  }  }
1732    
1733    
# Line 1596  void MainForm::viewOptions (void) Line 1737  void MainForm::viewOptions (void)
1737  // Arrange channel strips.  // Arrange channel strips.
1738  void MainForm::channelsArrange (void)  void MainForm::channelsArrange (void)
1739  {  {
1740      // Full width vertical tiling          // Full width vertical tiling
1741      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
1742      if (wlist.isEmpty())          if (wlist.isEmpty())
1743          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);  
1744    
1745      stabilizeForm();          m_pWorkspace->setUpdatesEnabled(false);
1746            int y = 0;
1747            for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1748                    ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
1749            /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {
1750                            // Prevent flicker...
1751                            pChannelStrip->hide();
1752                            pChannelStrip->showNormal();
1753                    }   */
1754                    pChannelStrip->adjustSize();
1755                    int iWidth  = m_pWorkspace->width();
1756                    if (iWidth < pChannelStrip->width())
1757                            iWidth = pChannelStrip->width();
1758            //  int iHeight = pChannelStrip->height()
1759            //              + pChannelStrip->parentWidget()->baseSize().height();
1760                    int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();
1761                    pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);
1762                    y += iHeight;
1763            }
1764            m_pWorkspace->setUpdatesEnabled(true);
1765    
1766            stabilizeForm();
1767  }  }
1768    
1769    
1770  // Auto-arrange channel strips.  // Auto-arrange channel strips.
1771  void MainForm::channelsAutoArrange ( bool bOn )  void MainForm::channelsAutoArrange ( bool bOn )
1772  {  {
1773      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1774          return;                  return;
1775    
1776      // Toggle the auto-arrange flag.          // Toggle the auto-arrange flag.
1777      m_pOptions->bAutoArrange = bOn;          m_pOptions->bAutoArrange = bOn;
1778    
1779      // If on, update whole workspace...          // If on, update whole workspace...
1780      if (m_pOptions->bAutoArrange)          if (m_pOptions->bAutoArrange)
1781          channelsArrange();                  channelsArrange();
1782  }  }
1783    
1784    
# Line 1646  void MainForm::channelsAutoArrange ( boo Line 1788  void MainForm::channelsAutoArrange ( boo
1788  // Show information about the Qt toolkit.  // Show information about the Qt toolkit.
1789  void MainForm::helpAboutQt (void)  void MainForm::helpAboutQt (void)
1790  {  {
1791      QMessageBox::aboutQt(this);          QMessageBox::aboutQt(this);
1792  }  }
1793    
1794    
1795  // Show information about application program.  // Show information about application program.
1796  void MainForm::helpAbout (void)  void MainForm::helpAbout (void)
1797  {  {
1798      // Stuff the about box text...          // Stuff the about box text...
1799      QString sText = "<p>\n";          QString sText = "<p>\n";
1800      sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";          sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";
1801      sText += "<br />\n";          sText += "<br />\n";
1802      sText += tr("Version") + ": <b>" QSAMPLER_VERSION "</b><br />\n";          sText += tr("Version") + ": <b>" QSAMPLER_VERSION "</b><br />\n";
1803      sText += "<small>" + tr("Build") + ": " __DATE__ " " __TIME__ "</small><br />\n";          sText += "<small>" + tr("Build") + ": " __DATE__ " " __TIME__ "</small><br />\n";
1804  #ifdef CONFIG_DEBUG  #ifdef CONFIG_DEBUG
1805      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1806      sText += tr("Debugging option enabled.");          sText += tr("Debugging option enabled.");
1807      sText += "</font></small><br />";          sText += "</font></small><br />";
1808  #endif  #endif
1809  #ifndef CONFIG_LIBGIG  #ifndef CONFIG_LIBGIG
1810      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1811      sText += tr("GIG (libgig) file support disabled.");          sText += tr("GIG (libgig) file support disabled.");
1812      sText += "</font></small><br />";          sText += "</font></small><br />";
1813  #endif  #endif
1814  #ifndef CONFIG_INSTRUMENT_NAME  #ifndef CONFIG_INSTRUMENT_NAME
1815      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1816      sText += tr("LSCP (liblscp) instrument_name support disabled.");          sText += tr("LSCP (liblscp) instrument_name support disabled.");
1817      sText += "</font></small><br />";          sText += "</font></small><br />";
1818  #endif  #endif
1819  #ifndef CONFIG_MUTE_SOLO  #ifndef CONFIG_MUTE_SOLO
1820      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1821      sText += tr("Sampler channel Mute/Solo support disabled.");          sText += tr("Sampler channel Mute/Solo support disabled.");
1822      sText += "</font></small><br />";          sText += "</font></small><br />";
1823  #endif  #endif
1824  #ifndef CONFIG_AUDIO_ROUTING  #ifndef CONFIG_AUDIO_ROUTING
1825      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1826      sText += tr("LSCP (liblscp) audio_routing support disabled.");          sText += tr("LSCP (liblscp) audio_routing support disabled.");
1827      sText += "</font></small><br />";          sText += "</font></small><br />";
1828  #endif  #endif
1829  #ifndef CONFIG_FXSEND  #ifndef CONFIG_FXSEND
1830      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1831      sText += tr("Sampler channel Effect Sends support disabled.");          sText += tr("Sampler channel Effect Sends support disabled.");
1832      sText += "</font></small><br />";          sText += "</font></small><br />";
1833  #endif  #endif
1834  #ifndef CONFIG_VOLUME  #ifndef CONFIG_VOLUME
1835      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1836      sText += tr("Global volume support disabled.");          sText += tr("Global volume support disabled.");
1837      sText += "</font></small><br />";          sText += "</font></small><br />";
1838  #endif  #endif
1839  #ifndef CONFIG_MIDI_INSTRUMENT  #ifndef CONFIG_MIDI_INSTRUMENT
1840      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1841      sText += tr("MIDI instrument mapping support disabled.");          sText += tr("MIDI instrument mapping support disabled.");
1842      sText += "</font></small><br />";          sText += "</font></small><br />";
1843  #endif  #endif
1844  #ifndef CONFIG_EDIT_INSTRUMENT  #ifndef CONFIG_EDIT_INSTRUMENT
1845      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1846      sText += tr("Instrument editing support disabled.");          sText += tr("Instrument editing support disabled.");
1847      sText += "</font></small><br />";          sText += "</font></small><br />";
1848  #endif  #endif
1849      sText += "<br />\n";  #ifndef CONFIG_EVENT_CHANNEL_MIDI
1850      sText += tr("Using") + ": ";          sText += "<small><font color=\"red\">";
1851      sText += ::lscp_client_package();          sText += tr("Channel MIDI event support disabled.");
1852      sText += " ";          sText += "</font></small><br />";
1853      sText += ::lscp_client_version();  #endif
1854    #ifndef CONFIG_EVENT_DEVICE_MIDI
1855            sText += "<small><font color=\"red\">";
1856            sText += tr("Device MIDI event support disabled.");
1857            sText += "</font></small><br />";
1858    #endif
1859    #ifndef CONFIG_MAX_VOICES
1860            sText += "<small><font color=\"red\">";
1861            sText += tr("Runtime max. voices / disk streams support disabled.");
1862            sText += "</font></small><br />";
1863    #endif
1864            sText += "<br />\n";
1865            sText += tr("Using") + ": ";
1866            sText += ::lscp_client_package();
1867            sText += " ";
1868            sText += ::lscp_client_version();
1869  #ifdef CONFIG_LIBGIG  #ifdef CONFIG_LIBGIG
1870      sText += ", ";          sText += ", ";
1871      sText += gig::libraryName().c_str();          sText += gig::libraryName().c_str();
1872      sText += " ";          sText += " ";
1873      sText += gig::libraryVersion().c_str();          sText += gig::libraryVersion().c_str();
1874  #endif  #endif
1875      sText += "<br />\n";          sText += "<br />\n";
1876      sText += "<br />\n";          sText += "<br />\n";
1877      sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";          sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";
1878      sText += "<br />\n";          sText += "<br />\n";
1879      sText += "<small>";          sText += "<small>";
1880      sText += QSAMPLER_COPYRIGHT "<br />\n";          sText += QSAMPLER_COPYRIGHT "<br />\n";
1881      sText += QSAMPLER_COPYRIGHT2 "<br />\n";          sText += QSAMPLER_COPYRIGHT2 "<br />\n";
1882      sText += "<br />\n";          sText += "<br />\n";
1883      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";
1884      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.");
1885      sText += "</small>";          sText += "</small>";
1886      sText += "</p>\n";          sText += "</p>\n";
1887    
1888      QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);          QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);
1889  }  }
1890    
1891    
# Line 1737  void MainForm::helpAbout (void) Line 1894  void MainForm::helpAbout (void)
1894    
1895  void MainForm::stabilizeForm (void)  void MainForm::stabilizeForm (void)
1896  {  {
1897      // Update the main application caption...          // Update the main application caption...
1898      QString sSessionName = sessionName(m_sFilename);          QString sSessionName = sessionName(m_sFilename);
1899      if (m_iDirtyCount > 0)          if (m_iDirtyCount > 0)
1900          sSessionName += " *";                  sSessionName += " *";
1901      setCaption(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));
1902    
1903      // Update the main menu state...          // Update the main menu state...
1904      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1905      bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);          bool bHasClient = (m_pOptions != NULL && m_pClient != NULL);
1906      bool bHasChannel = (bHasClient && pChannelStrip != NULL);          bool bHasChannel = (bHasClient && pChannelStrip != NULL);
1907      ui.fileNewAction->setEnabled(bHasClient);          bool bHasChannels = (bHasClient && m_pWorkspace->windowList().count() > 0);
1908      ui.fileOpenAction->setEnabled(bHasClient);          m_ui.fileNewAction->setEnabled(bHasClient);
1909      ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);          m_ui.fileOpenAction->setEnabled(bHasClient);
1910      ui.fileSaveAsAction->setEnabled(bHasClient);          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
1911      ui.fileResetAction->setEnabled(bHasClient);          m_ui.fileSaveAsAction->setEnabled(bHasClient);
1912      ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);          m_ui.fileResetAction->setEnabled(bHasClient);
1913      ui.editAddChannelAction->setEnabled(bHasClient);          m_ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);
1914      ui.editRemoveChannelAction->setEnabled(bHasChannel);          m_ui.editAddChannelAction->setEnabled(bHasClient);
1915      ui.editSetupChannelAction->setEnabled(bHasChannel);          m_ui.editRemoveChannelAction->setEnabled(bHasChannel);
1916            m_ui.editSetupChannelAction->setEnabled(bHasChannel);
1917  #ifdef CONFIG_EDIT_INSTRUMENT  #ifdef CONFIG_EDIT_INSTRUMENT
1918      ui.editEditChannelAction->setEnabled(bHasChannel);          m_ui.editEditChannelAction->setEnabled(bHasChannel);
1919  #else  #else
1920      ui.editEditChannelAction->setEnabled(false);          m_ui.editEditChannelAction->setEnabled(false);
1921  #endif  #endif
1922      ui.editResetChannelAction->setEnabled(bHasChannel);          m_ui.editResetChannelAction->setEnabled(bHasChannel);
1923      ui.editResetAllChannelsAction->setEnabled(bHasChannel);          m_ui.editResetAllChannelsAction->setEnabled(bHasChannels);
1924      ui.viewMessagesAction->setOn(m_pMessages && m_pMessages->isVisible());          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());
1925  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
1926          ui.viewInstrumentsAction->setOn(m_pInstrumentListForm          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm
1927                  && m_pInstrumentListForm->isVisible());                  && m_pInstrumentListForm->isVisible());
1928          ui.viewInstrumentsAction->setEnabled(bHasClient);          m_ui.viewInstrumentsAction->setEnabled(bHasClient);
1929  #else  #else
1930          ui.viewInstrumentsAction->setEnabled(false);          m_ui.viewInstrumentsAction->setEnabled(false);
1931  #endif  #endif
1932          ui.viewDevicesAction->setOn(m_pDeviceForm          m_ui.viewDevicesAction->setChecked(m_pDeviceForm
1933                  && m_pDeviceForm->isVisible());                  && m_pDeviceForm->isVisible());
1934      ui.viewDevicesAction->setEnabled(bHasClient);          m_ui.viewDevicesAction->setEnabled(bHasClient);
1935      ui.channelsArrangeAction->setEnabled(bHasChannel);          m_ui.viewMidiDeviceStatusMenu->setEnabled(
1936                    DeviceStatusForm::getInstances().size() > 0);
1937            m_ui.channelsArrangeAction->setEnabled(bHasChannels);
1938    
1939  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
1940          // Toolbar widgets are also affected...          // Toolbar widgets are also affected...
1941      m_pVolumeSlider->setEnabled(bHasClient);          m_pVolumeSlider->setEnabled(bHasClient);
1942      m_pVolumeSpinBox->setEnabled(bHasClient);          m_pVolumeSpinBox->setEnabled(bHasClient);
1943  #endif  #endif
1944    
1945      // Client/Server status...          // Client/Server status...
1946      if (bHasClient) {          if (bHasClient) {
1947          m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));                  m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));
1948          m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost + ":" + QString::number(m_pOptions->iServerPort));                  m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost
1949      } else {                          + ':' + QString::number(m_pOptions->iServerPort));
1950          m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();          } else {
1951          m_statusItem[QSAMPLER_STATUS_SERVER]->clear();                  m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();
1952      }                  m_statusItem[QSAMPLER_STATUS_SERVER]->clear();
1953      // Channel status...          }
1954      if (bHasChannel)          // Channel status...
1955          m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->caption());          if (bHasChannel)
1956      else                  m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->windowTitle());
1957          m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();          else
1958      // Session status...                  m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();
1959      if (m_iDirtyCount > 0)          // Session status...
1960          m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));          if (m_iDirtyCount > 0)
1961      else                  m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));
1962          m_statusItem[QSAMPLER_STATUS_SESSION]->clear();          else
1963                    m_statusItem[QSAMPLER_STATUS_SESSION]->clear();
1964    
1965      // Recent files menu.          // Recent files menu.
1966      m_pRecentFilesMenu->setEnabled(bHasClient && m_pOptions->recentFiles.count() > 0);          m_ui.fileOpenRecentMenu->setEnabled(m_pOptions->recentFiles.count() > 0);
1967  }  }
1968    
1969    
# Line 1842  void MainForm::volumeChanged ( int iVolu Line 2003  void MainForm::volumeChanged ( int iVolu
2003  void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)  void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)
2004  {  {
2005          // Add this strip to the changed list...          // Add this strip to the changed list...
2006          if (m_changedStrips.containsRef(pChannelStrip) == 0) {          if (!m_changedStrips.contains(pChannelStrip)) {
2007                  m_changedStrips.append(pChannelStrip);                  m_changedStrips.append(pChannelStrip);
2008                  pChannelStrip->resetErrorCount();                  pChannelStrip->resetErrorCount();
2009          }          }
2010    
2011      // Just mark the dirty form.          // Just mark the dirty form.
2012      m_iDirtyCount++;          m_iDirtyCount++;
2013      // and update the form status...          // and update the form status...
2014      stabilizeForm();          stabilizeForm();
2015  }  }
2016    
2017    
# Line 1870  void MainForm::updateSession (void) Line 2031  void MainForm::updateSession (void)
2031          if (iMaps < 0)          if (iMaps < 0)
2032                  appendMessagesClient("lscp_get_midi_instrument_maps");                  appendMessagesClient("lscp_get_midi_instrument_maps");
2033          else if (iMaps < 1) {          else if (iMaps < 1) {
2034                  ::lscp_add_midi_instrument_map(m_pClient, tr("Chromatic").latin1());                  ::lscp_add_midi_instrument_map(m_pClient,
2035                  ::lscp_add_midi_instrument_map(m_pClient, tr("Drum Kits").latin1());                          tr("Chromatic").toUtf8().constData());
2036                    ::lscp_add_midi_instrument_map(m_pClient,
2037                            tr("Drum Kits").toUtf8().constData());
2038          }          }
2039  #endif  #endif
2040    
2041            updateAllChannelStrips(false);
2042    
2043            // Do we auto-arrange?
2044            if (m_pOptions && m_pOptions->bAutoArrange)
2045                    channelsArrange();
2046    
2047            // Remember to refresh devices and instruments...
2048            if (m_pInstrumentListForm)
2049                    m_pInstrumentListForm->refreshInstruments();
2050            if (m_pDeviceForm)
2051                    m_pDeviceForm->refreshDevices();
2052    }
2053    
2054    void MainForm::updateAllChannelStrips(bool bRemoveDeadStrips) {
2055          // Retrieve the current channel list.          // Retrieve the current channel list.
2056          int *piChannelIDs = ::lscp_list_channels(m_pClient);          int *piChannelIDs = ::lscp_list_channels(m_pClient);
2057          if (piChannelIDs == NULL) {          if (piChannelIDs == NULL) {
2058                  if (::lscp_client_get_errno(m_pClient)) {                  if (::lscp_client_get_errno(m_pClient)) {
2059                          appendMessagesClient("lscp_list_channels");                          appendMessagesClient("lscp_list_channels");
2060                          appendMessagesError(tr("Could not get current list of channels.\n\nSorry."));                          appendMessagesError(
2061                                    tr("Could not get current list of channels.\n\nSorry."));
2062                  }                  }
2063          } else {          } else {
2064                  // Try to (re)create each channel.                  // Try to (re)create each channel.
# Line 1888  void MainForm::updateSession (void) Line 2066  void MainForm::updateSession (void)
2066                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {
2067                          // Check if theres already a channel strip for this one...                          // Check if theres already a channel strip for this one...
2068                          if (!channelStrip(piChannelIDs[iChannel]))                          if (!channelStrip(piChannelIDs[iChannel]))
2069                                  createChannelStrip(new qsamplerChannel(piChannelIDs[iChannel]));                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));
2070                    }
2071    
2072                    // Do we auto-arrange?
2073                    if (m_pOptions && m_pOptions->bAutoArrange)
2074                            channelsArrange();
2075    
2076                    stabilizeForm();
2077    
2078                    // remove dead channel strips
2079                    if (bRemoveDeadStrips) {
2080                            for (int i = 0; channelStripAt(i); ++i) {
2081                                    ChannelStrip* pChannelStrip = channelStripAt(i);
2082                                    bool bExists = false;
2083                                    for (int j = 0; piChannelIDs[j] >= 0; ++j) {
2084                                            if (!pChannelStrip->channel()) break;
2085                                            if (piChannelIDs[j] == pChannelStrip->channel()->channelID()) {
2086                                                    // strip exists, don't touch it
2087                                                    bExists = true;
2088                                                    break;
2089                                            }
2090                                    }
2091                                    if (!bExists) destroyChannelStrip(pChannelStrip);
2092                            }
2093                  }                  }
2094                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
2095          }          }
   
     // 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();  
2096  }  }
2097    
   
2098  // Update the recent files list and menu.  // Update the recent files list and menu.
2099  void MainForm::updateRecentFiles ( const QString& sFilename )  void MainForm::updateRecentFiles ( const QString& sFilename )
2100  {  {
2101      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2102          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);  
2103    
2104      // May update the menu.          // Remove from list if already there (avoid duplicates)
2105      updateRecentFilesMenu();          int iIndex = m_pOptions->recentFiles.indexOf(sFilename);
2106            if (iIndex >= 0)
2107                    m_pOptions->recentFiles.removeAt(iIndex);
2108            // Put it to front...
2109            m_pOptions->recentFiles.push_front(sFilename);
2110  }  }
2111    
2112    
2113  // Update the recent files list and menu.  // Update the recent files list and menu.
2114  void MainForm::updateRecentFilesMenu (void)  void MainForm::updateRecentFilesMenu (void)
2115  {  {
2116      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2117          return;                  return;
2118    
2119            // Time to keep the list under limits.
2120            int iRecentFiles = m_pOptions->recentFiles.count();
2121            while (iRecentFiles > m_pOptions->iMaxRecentFiles) {
2122                    m_pOptions->recentFiles.pop_back();
2123                    iRecentFiles--;
2124            }
2125    
2126      // Time to keep the list under limits.          // Rebuild the recent files menu...
2127      int iRecentFiles = m_pOptions->recentFiles.count();          m_ui.fileOpenRecentMenu->clear();
2128      while (iRecentFiles > m_pOptions->iMaxRecentFiles) {          for (int i = 0; i < iRecentFiles; i++) {
2129          m_pOptions->recentFiles.pop_back();                  const QString& sFilename = m_pOptions->recentFiles[i];
2130          iRecentFiles--;                  if (QFileInfo(sFilename).exists()) {
2131      }                          QAction *pAction = m_ui.fileOpenRecentMenu->addAction(
2132                                    QString("&%1 %2").arg(i + 1).arg(sessionName(sFilename)),
2133      // rebuild the recent files menu...                                  this, SLOT(fileOpenRecent()));
2134      m_pRecentFilesMenu->clear();                          pAction->setData(i);
2135      for (int i = 0; i < iRecentFiles; i++) {                  }
2136          const QString& sFilename = m_pOptions->recentFiles[i];          }
         if (QFileInfo(sFilename).exists()) {  
             m_pRecentFilesMenu->insertItem(QString("&%1 %2")  
                 .arg(i + 1).arg(sessionName(sFilename)),  
                 this, SLOT(fileOpenRecent(int)), 0, i);  
         }  
     }  
2137  }  }
2138    
2139    
2140  // Force update of the channels instrument names mode.  // Force update of the channels instrument names mode.
2141  void MainForm::updateInstrumentNames (void)  void MainForm::updateInstrumentNames (void)
2142  {  {
2143      // Full channel list update...          // Full channel list update...
2144      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2145      if (wlist.isEmpty())          if (wlist.isEmpty())
2146          return;                  return;
2147    
2148      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2149      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2150          ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);                  ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);
2151          if (pChannelStrip)                  if (pChannelStrip)
2152              pChannelStrip->updateInstrumentName(true);                          pChannelStrip->updateInstrumentName(true);
2153      }          }
2154      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2155  }  }
2156    
2157    
2158  // Force update of the channels display font.  // Force update of the channels display font.
2159  void MainForm::updateDisplayFont (void)  void MainForm::updateDisplayFont (void)
2160  {  {
2161      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2162          return;                  return;
2163    
2164      // Check if display font is legal.          // Check if display font is legal.
2165      if (m_pOptions->sDisplayFont.isEmpty())          if (m_pOptions->sDisplayFont.isEmpty())
2166          return;                  return;
2167      // Realize it.          // Realize it.
2168      QFont font;          QFont font;
2169      if (!font.fromString(m_pOptions->sDisplayFont))          if (!font.fromString(m_pOptions->sDisplayFont))
2170          return;                  return;
2171    
2172      // Full channel list update...          // Full channel list update...
2173      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2174      if (wlist.isEmpty())          if (wlist.isEmpty())
2175          return;                  return;
2176    
2177      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2178      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2179          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2180          if (pChannelStrip)                  if (pChannelStrip)
2181              pChannelStrip->setDisplayFont(font);                          pChannelStrip->setDisplayFont(font);
2182      }          }
2183      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2184  }  }
2185    
2186    
2187  // Update channel strips background effect.  // Update channel strips background effect.
2188  void MainForm::updateDisplayEffect (void)  void MainForm::updateDisplayEffect (void)
2189  {  {
2190     QPixmap pm;          // Full channel list update...
2191      if (m_pOptions->bDisplayEffect)          QWidgetList wlist = m_pWorkspace->windowList();
2192          pm = QPixmap(":/qsampler/pixmaps/displaybg1.png");          if (wlist.isEmpty())
2193                    return;
2194      // Full channel list update...  
2195      QWidgetList wlist = m_pWorkspace->windowList();          m_pWorkspace->setUpdatesEnabled(false);
2196      if (wlist.isEmpty())          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2197          return;                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2198                    if (pChannelStrip)
2199      m_pWorkspace->setUpdatesEnabled(false);                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2200      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          }
2201          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);          m_pWorkspace->setUpdatesEnabled(true);
         if (pChannelStrip)  
             pChannelStrip->setDisplayBackground(pm);  
     }  
     m_pWorkspace->setUpdatesEnabled(true);  
2202  }  }
2203    
2204    
2205  // Force update of the channels maximum volume setting.  // Force update of the channels maximum volume setting.
2206  void MainForm::updateMaxVolume (void)  void MainForm::updateMaxVolume (void)
2207  {  {
2208      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2209          return;                  return;
2210    
2211  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2212          m_iVolumeChanging++;          m_iVolumeChanging++;
2213          m_pVolumeSlider->setMaxValue(m_pOptions->iMaxVolume);          m_pVolumeSlider->setMaximum(m_pOptions->iMaxVolume);
2214          m_pVolumeSpinBox->setMaxValue(m_pOptions->iMaxVolume);          m_pVolumeSpinBox->setMaximum(m_pOptions->iMaxVolume);
2215          m_iVolumeChanging--;          m_iVolumeChanging--;
2216  #endif  #endif
2217    
2218      // Full channel list update...          // Full channel list update...
2219      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2220      if (wlist.isEmpty())          if (wlist.isEmpty())
2221          return;                  return;
2222    
2223      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2224      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2225          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2226          if (pChannelStrip)                  if (pChannelStrip)
2227              pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                          pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2228      }          }
2229      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2230  }  }
2231    
2232    
# Line 2052  void MainForm::updateMaxVolume (void) Line 2236  void MainForm::updateMaxVolume (void)
2236  // Messages output methods.  // Messages output methods.
2237  void MainForm::appendMessages( const QString& s )  void MainForm::appendMessages( const QString& s )
2238  {  {
2239      if (m_pMessages)          if (m_pMessages)
2240          m_pMessages->appendMessages(s);                  m_pMessages->appendMessages(s);
2241    
2242      statusBar()->message(s, 3000);          statusBar()->showMessage(s, 3000);
2243  }  }
2244    
2245  void MainForm::appendMessagesColor( const QString& s, const QString& c )  void MainForm::appendMessagesColor( const QString& s, const QString& c )
2246  {  {
2247      if (m_pMessages)          if (m_pMessages)
2248          m_pMessages->appendMessagesColor(s, c);                  m_pMessages->appendMessagesColor(s, c);
2249    
2250      statusBar()->message(s, 3000);          statusBar()->showMessage(s, 3000);
2251  }  }
2252    
2253  void MainForm::appendMessagesText( const QString& s )  void MainForm::appendMessagesText( const QString& s )
2254  {  {
2255      if (m_pMessages)          if (m_pMessages)
2256          m_pMessages->appendMessagesText(s);                  m_pMessages->appendMessagesText(s);
2257  }  }
2258    
2259  void MainForm::appendMessagesError( const QString& s )  void MainForm::appendMessagesError( const QString& s )
2260  {  {
2261      if (m_pMessages)          if (m_pMessages)
2262          m_pMessages->show();                  m_pMessages->show();
2263    
2264      appendMessagesColor(s.simplified(), "#ff0000");          appendMessagesColor(s.simplified(), "#ff0000");
2265    
2266          // Make it look responsive...:)          // Make it look responsive...:)
2267          QApplication::processEvents(QEventLoop::ExcludeUserInput);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2268    
2269      QMessageBox::critical(this,          QMessageBox::critical(this,
2270                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));                  QSAMPLER_TITLE ": " + tr("Error"), s, QMessageBox::Cancel);
2271  }  }
2272    
2273    
2274  // This is a special message format, just for client results.  // This is a special message format, just for client results.
2275  void MainForm::appendMessagesClient( const QString& s )  void MainForm::appendMessagesClient( const QString& s )
2276  {  {
2277      if (m_pClient == NULL)          if (m_pClient == NULL)
2278          return;                  return;
2279    
2280      appendMessagesColor(s + QString(": %1 (errno=%2)")          appendMessagesColor(s + QString(": %1 (errno=%2)")
2281          .arg(::lscp_client_get_result(m_pClient))                  .arg(::lscp_client_get_result(m_pClient))
2282          .arg(::lscp_client_get_errno(m_pClient)), "#996666");                  .arg(::lscp_client_get_errno(m_pClient)), "#996666");
2283    
2284          // Make it look responsive...:)          // Make it look responsive...:)
2285          QApplication::processEvents(QEventLoop::ExcludeUserInput);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2286  }  }
2287    
2288    
2289  // Force update of the messages font.  // Force update of the messages font.
2290  void MainForm::updateMessagesFont (void)  void MainForm::updateMessagesFont (void)
2291  {  {
2292      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2293          return;                  return;
2294    
2295      if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {          if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {
2296          QFont font;                  QFont font;
2297          if (font.fromString(m_pOptions->sMessagesFont))                  if (font.fromString(m_pOptions->sMessagesFont))
2298              m_pMessages->setMessagesFont(font);                          m_pMessages->setMessagesFont(font);
2299      }          }
2300  }  }
2301    
2302    
2303  // Update messages window line limit.  // Update messages window line limit.
2304  void MainForm::updateMessagesLimit (void)  void MainForm::updateMessagesLimit (void)
2305  {  {
2306      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2307          return;                  return;
2308    
2309      if (m_pMessages) {          if (m_pMessages) {
2310          if (m_pOptions->bMessagesLimit)                  if (m_pOptions->bMessagesLimit)
2311              m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);                          m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);
2312          else                  else
2313              m_pMessages->setMessagesLimit(-1);                          m_pMessages->setMessagesLimit(-1);
2314      }          }
2315  }  }
2316    
2317    
2318  // Enablement of the messages capture feature.  // Enablement of the messages capture feature.
2319  void MainForm::updateMessagesCapture (void)  void MainForm::updateMessagesCapture (void)
2320  {  {
2321      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2322          return;                  return;
2323    
2324      if (m_pMessages)          if (m_pMessages)
2325          m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);                  m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);
2326  }  }
2327    
2328    
# Line 2146  void MainForm::updateMessagesCapture (vo Line 2330  void MainForm::updateMessagesCapture (vo
2330  // qsamplerMainForm -- MDI channel strip management.  // qsamplerMainForm -- MDI channel strip management.
2331    
2332  // The channel strip creation executive.  // The channel strip creation executive.
2333  ChannelStrip* MainForm::createChannelStrip(qsamplerChannel* pChannel)  ChannelStrip* MainForm::createChannelStrip ( Channel *pChannel )
2334  {  {
2335      if (m_pClient == NULL || pChannel == NULL)          if (m_pClient == NULL || pChannel == NULL)
2336          return NULL;                  return NULL;
2337    
2338      // Prepare for auto-arrange?          // Add a new channel itema...
2339      ChannelStrip* pChannelStrip = NULL;          ChannelStrip *pChannelStrip = new ChannelStrip();
2340      int y = 0;          if (pChannelStrip == NULL)
2341      if (m_pOptions && m_pOptions->bAutoArrange) {                  return NULL;
         QWidgetList wlist = m_pWorkspace->windowList();  
         for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {  
             pChannelStrip = (ChannelStrip *) wlist.at(iChannel);  
                         if (pChannelStrip) {  
                         //  y += pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();  
                                 y += pChannelStrip->parentWidget()->frameGeometry().height();  
                         }  
         }  
     }  
2342    
2343      // Add a new channel itema...          // Set some initial channel strip options...
2344      pChannelStrip = new ChannelStrip();          if (m_pOptions) {
2345      if (pChannelStrip == NULL)                  // Background display effect...
2346          return NULL;                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2347                    // We'll need a display font.
2348                    QFont font;
2349                    if (font.fromString(m_pOptions->sDisplayFont))
2350                            pChannelStrip->setDisplayFont(font);
2351                    // Maximum allowed volume setting.
2352                    pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2353            }
2354    
2355            // Add it to workspace...
2356            m_pWorkspace->addWindow(pChannelStrip, Qt::FramelessWindowHint);
2357    
2358      m_pWorkspace->addWindow(pChannelStrip, Qt::Tool);          // Actual channel strip setup...
2359            pChannelStrip->setup(pChannel);
2360    
     // Actual channel strip setup...  
     pChannelStrip->setup(pChannel);  
2361          QObject::connect(pChannelStrip,          QObject::connect(pChannelStrip,
2362                  SIGNAL(channelChanged(ChannelStrip*)),                  SIGNAL(channelChanged(ChannelStrip*)),
2363                  SLOT(channelStripChanged(ChannelStrip*)));                  SLOT(channelStripChanged(ChannelStrip*)));
2364      // Set some initial aesthetic options...  
2365      if (m_pOptions) {          // Now we show up us to the world.
2366          // 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);  
     }  
2367    
2368          // This is pretty new, so we'll watch for it closely.          // This is pretty new, so we'll watch for it closely.
2369          channelStripChanged(pChannelStrip);          channelStripChanged(pChannelStrip);
2370    
2371      // Return our successful reference...          // Return our successful reference...
2372      return pChannelStrip;          return pChannelStrip;
2373  }  }
2374    
2375    void MainForm::destroyChannelStrip(ChannelStrip* pChannelStrip) {
2376            // Just delete the channel strip.
2377            delete pChannelStrip;
2378    
2379            // Do we auto-arrange?
2380            if (m_pOptions && m_pOptions->bAutoArrange)
2381                    channelsArrange();
2382    
2383            stabilizeForm();
2384    }
2385    
2386  // Retrieve the active channel strip.  // Retrieve the active channel strip.
2387  ChannelStrip* MainForm::activeChannelStrip (void)  ChannelStrip* MainForm::activeChannelStrip (void)
2388  {  {
2389      return (ChannelStrip*) m_pWorkspace->activeWindow();          return static_cast<ChannelStrip *> (m_pWorkspace->activeWindow());
2390  }  }
2391    
2392    
2393  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
2394  ChannelStrip* MainForm::channelStripAt ( int iChannel )  ChannelStrip* MainForm::channelStripAt ( int iChannel )
2395  {  {
2396      QWidgetList wlist = m_pWorkspace->windowList();          if (!m_pWorkspace) return NULL;
     if (wlist.isEmpty())  
         return NULL;  
2397    
2398      return (ChannelStrip*) wlist.at(iChannel);          QWidgetList wlist = m_pWorkspace->windowList();
2399            if (wlist.isEmpty())
2400                    return NULL;
2401    
2402            if (iChannel < 0 || iChannel >= wlist.size())
2403                    return NULL;
2404    
2405            return dynamic_cast<ChannelStrip *> (wlist.at(iChannel));
2406  }  }
2407    
2408    
# Line 2232  ChannelStrip* MainForm::channelStrip ( i Line 2414  ChannelStrip* MainForm::channelStrip ( i
2414                  return NULL;                  return NULL;
2415    
2416          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2417                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip
2418                            = static_cast<ChannelStrip*> (wlist.at(iChannel));
2419                  if (pChannelStrip) {                  if (pChannelStrip) {
2420                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
2421                          if (pChannel && pChannel->channelID() == iChannelID)                          if (pChannel && pChannel->channelID() == iChannelID)
2422                                  return pChannelStrip;                                  return pChannelStrip;
2423                  }                  }
# Line 2248  ChannelStrip* MainForm::channelStrip ( i Line 2431  ChannelStrip* MainForm::channelStrip ( i
2431  // Construct the windows menu.  // Construct the windows menu.
2432  void MainForm::channelsMenuAboutToShow (void)  void MainForm::channelsMenuAboutToShow (void)
2433  {  {
2434      ui.channelsMenu->clear();          m_ui.channelsMenu->clear();
2435      ui.channelsArrangeAction->addTo(ui.channelsMenu);          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);
2436      ui.channelsAutoArrangeAction->addTo(ui.channelsMenu);          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);
2437    
2438      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2439      if (!wlist.isEmpty()) {          if (!wlist.isEmpty()) {
2440          ui.channelsMenu->insertSeparator();                  m_ui.channelsMenu->addSeparator();
2441          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2442              ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                          ChannelStrip* pChannelStrip
2443              if (pChannelStrip) {                                  = static_cast<ChannelStrip*> (wlist.at(iChannel));
2444                  int iItemID = ui.channelsMenu->insertItem(pChannelStrip->caption(), this, SLOT(channelsMenuActivated(int)));                          if (pChannelStrip) {
2445                  ui.channelsMenu->setItemParameter(iItemID, iChannel);                                  QAction *pAction = m_ui.channelsMenu->addAction(
2446                  ui.channelsMenu->setItemChecked(iItemID, activeChannelStrip() == pChannelStrip);                                          pChannelStrip->windowTitle(),
2447              }                                          this, SLOT(channelsMenuActivated()));
2448          }                                  pAction->setCheckable(true);
2449      }                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);
2450                                    pAction->setData(iChannel);
2451                            }
2452                    }
2453            }
2454  }  }
2455    
2456    
2457  // Windows menu activation slot  // Windows menu activation slot
2458  void MainForm::channelsMenuActivated ( int iChannel )  void MainForm::channelsMenuActivated (void)
2459  {  {
2460      ChannelStrip* pChannelStrip = channelStripAt(iChannel);          // Retrive channel index from action data...
2461      if (pChannelStrip)          QAction *pAction = qobject_cast<QAction *> (sender());
2462          pChannelStrip->showNormal();          if (pAction == NULL)
2463      pChannelStrip->setFocus();                  return;
2464    
2465            ChannelStrip* pChannelStrip = channelStripAt(pAction->data().toInt());
2466            if (pChannelStrip) {
2467                    pChannelStrip->showNormal();
2468                    pChannelStrip->setFocus();
2469            }
2470  }  }
2471    
2472    
# Line 2283  void MainForm::channelsMenuActivated ( i Line 2476  void MainForm::channelsMenuActivated ( i
2476  // Set the pseudo-timer delay schedule.  // Set the pseudo-timer delay schedule.
2477  void MainForm::startSchedule ( int iStartDelay )  void MainForm::startSchedule ( int iStartDelay )
2478  {  {
2479      m_iStartDelay  = 1 + (iStartDelay * 1000);          m_iStartDelay  = 1 + (iStartDelay * 1000);
2480      m_iTimerDelay  = 0;          m_iTimerDelay  = 0;
2481  }  }
2482    
2483  // Suspend the pseudo-timer delay schedule.  // Suspend the pseudo-timer delay schedule.
2484  void MainForm::stopSchedule (void)  void MainForm::stopSchedule (void)
2485  {  {
2486      m_iStartDelay  = 0;          m_iStartDelay  = 0;
2487      m_iTimerDelay  = 0;          m_iTimerDelay  = 0;
2488  }  }
2489    
2490  // Timer slot funtion.  // Timer slot funtion.
2491  void MainForm::timerSlot (void)  void MainForm::timerSlot (void)
2492  {  {
2493      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2494          return;                  return;
2495    
2496      // Is it the first shot on server start after a few delay?          // Is it the first shot on server start after a few delay?
2497      if (m_iTimerDelay < m_iStartDelay) {          if (m_iTimerDelay < m_iStartDelay) {
2498          m_iTimerDelay += QSAMPLER_TIMER_MSECS;                  m_iTimerDelay += QSAMPLER_TIMER_MSECS;
2499          if (m_iTimerDelay >= m_iStartDelay) {                  if (m_iTimerDelay >= m_iStartDelay) {
2500              // If we cannot start it now, maybe a lil'mo'later ;)                          // If we cannot start it now, maybe a lil'mo'later ;)
2501              if (!startClient()) {                          if (!startClient()) {
2502                  m_iStartDelay += m_iTimerDelay;                                  m_iStartDelay += m_iTimerDelay;
2503                  m_iTimerDelay  = 0;                                  m_iTimerDelay  = 0;
2504              }                          }
2505          }                  }
2506      }          }
2507    
2508          if (m_pClient) {          if (m_pClient) {
2509                  // Update the channel information for each pending strip...                  // Update the channel information for each pending strip...
2510                  if (m_changedStrips.count() > 0) {                  QListIterator<ChannelStrip *> iter(m_changedStrips);
2511                          for (ChannelStrip* pChannelStrip = m_changedStrips.first();                  while (iter.hasNext()) {
2512                                          pChannelStrip; pChannelStrip = m_changedStrips.next()) {                          ChannelStrip *pChannelStrip = iter.next();
2513                                  // If successfull, remove from pending list...                          // If successfull, remove from pending list...
2514                                  if (pChannelStrip->updateChannelInfo())                          if (pChannelStrip->updateChannelInfo()) {
2515                                          m_changedStrips.remove(pChannelStrip);                                  int iChannelStrip = m_changedStrips.indexOf(pChannelStrip);
2516                                    if (iChannelStrip >= 0)
2517                                            m_changedStrips.removeAt(iChannelStrip);
2518                          }                          }
2519                  }                  }
2520                  // Refresh each channel usage, on each period...                  // Refresh each channel usage, on each period...
# Line 2340  void MainForm::timerSlot (void) Line 2535  void MainForm::timerSlot (void)
2535                  }                  }
2536          }          }
2537    
2538      // Register the next timer slot.          // Register the next timer slot.
2539      QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));          QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
2540  }  }
2541    
2542    
# Line 2351  void MainForm::timerSlot (void) Line 2546  void MainForm::timerSlot (void)
2546  // Start linuxsampler server...  // Start linuxsampler server...
2547  void MainForm::startServer (void)  void MainForm::startServer (void)
2548  {  {
2549      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2550          return;                  return;
2551    
2552            // Aren't already a client, are we?
2553            if (!m_pOptions->bServerStart || m_pClient)
2554                    return;
2555    
2556      // Aren't already a client, are we?          // Is the server process instance still here?
2557      if (!m_pOptions->bServerStart || m_pClient)          if (m_pServer) {
2558          return;                  if (QMessageBox::warning(this,
   
     // Is the server process instance still here?  
     if (m_pServer) {  
         switch (QMessageBox::warning(this,  
2559                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
2560              tr("Could not start the LinuxSampler server.\n\n"                          tr("Could not start the LinuxSampler server.\n\n"
2561                 "Maybe it ss already started."),                          "Maybe it is already started."),
2562              tr("Stop"), tr("Kill"), tr("Cancel"))) {                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
2563            case 0:                          m_pServer->terminate();
2564              m_pServer->terminate();                          m_pServer->kill();
2565              break;                  }
2566            case 1:                  return;
2567              m_pServer->kill();          }
2568              break;  
2569          }          // Reset our timer counters...
2570          return;          stopSchedule();
2571      }  
2572            // Verify we have something to start with...
2573      // Reset our timer counters...          if (m_pOptions->sServerCmdLine.isEmpty())
2574      stopSchedule();                  return;
2575    
2576      // OK. Let's build the startup process...          // OK. Let's build the startup process...
2577      m_pServer = new QProcess(this);          m_pServer = new QProcess();
2578            bForceServerStop = true;
2579      // Setup stdout/stderr capture...  
2580          //      if (m_pOptions->bStdoutCapture) {          // Setup stdout/stderr capture...
2581                  //m_pServer->setProcessChannelMode(  //      if (m_pOptions->bStdoutCapture) {
2582                  //      QProcess::StandardOutput);  #if QT_VERSION >= 0x040200
2583                    m_pServer->setProcessChannelMode(QProcess::ForwardedChannels);
2584    #endif
2585                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2586                          SIGNAL(readyReadStandardOutput()),                          SIGNAL(readyReadStandardOutput()),
2587                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
2588                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2589                          SIGNAL(readyReadStandardError()),                          SIGNAL(readyReadStandardError()),
2590                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
2591          //      }  //      }
2592    
2593          // The unforgiveable signal communication...          // The unforgiveable signal communication...
2594          QObject::connect(m_pServer,          QObject::connect(m_pServer,
2595                  SIGNAL(finished(int,QProcess::ExitStatus)),                  SIGNAL(finished(int, QProcess::ExitStatus)),
2596                  SLOT(processServerExit()));                  SLOT(processServerExit()));
2597    
2598      // Build process arguments...          // Build process arguments...
2599      QStringList serverCmdLine = QStringList::split(' ', m_pOptions->sServerCmdLine);          QStringList args = m_pOptions->sServerCmdLine.split(' ');
2600            QString sCommand = args[0];
2601      appendMessages(tr("Server is starting..."));          args.removeAt(0);
2602      appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");  
2603            appendMessages(tr("Server is starting..."));
2604            appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");
2605    
2606      const QString prog = (serverCmdLine.size() > 0) ? serverCmdLine[0] : QString();          // Go linuxsampler, go...
2607      const QStringList args = serverCmdLine.mid(1);          m_pServer->start(sCommand, args);
2608            if (!m_pServer->waitForStarted()) {
2609      // Go jack, go...                  appendMessagesError(tr("Could not start server.\n\nSorry."));
2610      m_pServer->start(prog, args);                  processServerExit();
2611      if (!m_pServer->waitForStarted()) {                  return;
2612          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()));  
2613    
2614      // Reset (yet again) the timer counters,          // Show startup results...
2615      // but this time is deferred as the user opted.          appendMessages(
2616      startSchedule(m_pOptions->iStartDelay);                  tr("Server was started with PID=%1.").arg((long) m_pServer->pid()));
2617      stabilizeForm();  
2618            // Reset (yet again) the timer counters,
2619            // but this time is deferred as the user opted.
2620            startSchedule(m_pOptions->iStartDelay);
2621            stabilizeForm();
2622  }  }
2623    
2624    
2625  // Stop linuxsampler server...  // Stop linuxsampler server...
2626  void MainForm::stopServer (void)  void MainForm::stopServer (bool bInteractive)
2627  {  {
2628      // Stop client code.          // Stop client code.
2629      stopClient();          stopClient();
2630    
2631      // And try to stop server.          if (m_pServer && bInteractive) {
2632      if (m_pServer) {                  if (QMessageBox::question(this,
2633          appendMessages(tr("Server is stopping..."));                          QSAMPLER_TITLE ": " + tr("The backend's fate ..."),
2634          if (m_pServer->state() == QProcess::Running)                          tr("You have the option to keep the sampler backend (LinuxSampler)\n"
2635              m_pServer->terminate();                          "running in the background. The sampler would continue to work\n"
2636       }                          "according to your current sampler session and you could alter the\n"
2637                            "sampler session at any time by relaunching QSampler.\n\n"
2638      // Give it some time to terminate gracefully and stabilize...                          "Do you want LinuxSampler to stop?"),
2639      QTime t;                          QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
2640      t.start();                  {
2641      while (t.elapsed() < QSAMPLER_TIMER_MSECS)                          bForceServerStop = false;
2642          QApplication::processEvents(QEventLoop::ExcludeUserInput);                  }
2643            }
2644    
2645       // Do final processing anyway.          // And try to stop server.
2646       processServerExit();          if (m_pServer && bForceServerStop) {
2647                    appendMessages(tr("Server is stopping..."));
2648                    if (m_pServer->state() == QProcess::Running) {
2649    #if defined(WIN32)
2650                            // Try harder...
2651                            m_pServer->kill();
2652    #else
2653                            // Try softly...
2654                            m_pServer->terminate();
2655    #endif
2656                    }
2657            }       // Do final processing anyway.
2658            else processServerExit();
2659    
2660            // Give it some time to terminate gracefully and stabilize...
2661            QTime t;
2662            t.start();
2663            while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2664                    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2665  }  }
2666    
2667    
2668  // Stdout handler...  // Stdout handler...
2669  void MainForm::readServerStdout (void)  void MainForm::readServerStdout (void)
2670  {  {
2671      if (m_pMessages)          if (m_pMessages)
2672          m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());                  m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());
2673  }  }
2674    
2675    
2676  // Linuxsampler server cleanup.  // Linuxsampler server cleanup.
2677  void MainForm::processServerExit (void)  void MainForm::processServerExit (void)
2678  {  {
2679      // Force client code cleanup.          // Force client code cleanup.
2680      stopClient();          stopClient();
2681    
2682      // Flush anything that maybe pending...          // Flush anything that maybe pending...
2683      if (m_pMessages)          if (m_pMessages)
2684          m_pMessages->flushStdoutBuffer();                  m_pMessages->flushStdoutBuffer();
2685    
2686      if (m_pServer) {          if (m_pServer && bForceServerStop) {
2687          // Force final server shutdown...                  if (m_pServer->state() != QProcess::NotRunning) {
2688          appendMessages(tr("Server was stopped with exit status %1.").arg(m_pServer->exitStatus()));                          appendMessages(tr("Server is being forced..."));
2689          m_pServer->terminate();                          // Force final server shutdown...
2690          if (!m_pServer->waitForFinished(2000))                          m_pServer->kill();
2691              m_pServer->kill();                          // Give it some time to terminate gracefully and stabilize...
2692          // Destroy it.                          QTime t;
2693          delete m_pServer;                          t.start();
2694          m_pServer = NULL;                          while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2695      }                                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2696                    }
2697                    // Force final server shutdown...
2698                    appendMessages(
2699                            tr("Server was stopped with exit status %1.")
2700                            .arg(m_pServer->exitStatus()));
2701                    delete m_pServer;
2702                    m_pServer = NULL;
2703            }
2704    
2705      // Again, make status visible stable.          // Again, make status visible stable.
2706      stabilizeForm();          stabilizeForm();
2707  }  }
2708    
2709    
# Line 2488  void MainForm::processServerExit (void) Line 2711  void MainForm::processServerExit (void)
2711  // qsamplerMainForm -- Client stuff.  // qsamplerMainForm -- Client stuff.
2712    
2713  // The LSCP client callback procedure.  // The LSCP client callback procedure.
2714  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*/,
2715            lscp_event_t event, const char *pchData, int cchData, void *pvData )
2716  {  {
2717      MainForm* pMainForm = (MainForm *) pvData;          MainForm* pMainForm = (MainForm *) pvData;
2718      if (pMainForm == NULL)          if (pMainForm == NULL)
2719          return LSCP_FAILED;                  return LSCP_FAILED;
2720    
2721      // ATTN: DO NOT EVER call any GUI code here,          // ATTN: DO NOT EVER call any GUI code here,
2722      // as this is run under some other thread context.          // as this is run under some other thread context.
2723      // A custom event must be posted here...          // A custom event must be posted here...
2724      QApplication::postEvent(pMainForm, new qsamplerCustomEvent(event, pchData, cchData));          QApplication::postEvent(pMainForm,
2725                    new LscpEvent(event, pchData, cchData));
2726    
2727      return LSCP_OK;          return LSCP_OK;
2728  }  }
2729    
2730    
2731  // Start our almighty client...  // Start our almighty client...
2732  bool MainForm::startClient (void)  bool MainForm::startClient (void)
2733  {  {
2734      // Have it a setup?          // Have it a setup?
2735      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2736          return false;                  return false;
2737    
2738      // Aren't we already started, are we?          // Aren't we already started, are we?
2739      if (m_pClient)          if (m_pClient)
2740          return true;                  return true;
2741    
2742      // Log prepare here.          // Log prepare here.
2743      appendMessages(tr("Client connecting..."));          appendMessages(tr("Client connecting..."));
2744    
2745      // Create the client handle...          // Create the client handle...
2746      m_pClient = ::lscp_client_create(m_pOptions->sServerHost.latin1(), m_pOptions->iServerPort, qsampler_client_callback, this);          m_pClient = ::lscp_client_create(
2747      if (m_pClient == NULL) {                  m_pOptions->sServerHost.toUtf8().constData(),
2748          // Is this the first try?                  m_pOptions->iServerPort, qsampler_client_callback, this);
2749          // maybe we need to start a local server...          if (m_pClient == NULL) {
2750          if ((m_pServer && m_pServer->state() == QProcess::Running) || !m_pOptions->bServerStart)                  // Is this the first try?
2751              appendMessagesError(tr("Could not connect to server as client.\n\nSorry."));                  // maybe we need to start a local server...
2752          else                  if ((m_pServer && m_pServer->state() == QProcess::Running)
2753              startServer();                          || !m_pOptions->bServerStart) {
2754          // This is always a failure.                          appendMessagesError(
2755          stabilizeForm();                                  tr("Could not connect to server as client.\n\nSorry."));
2756          return false;                  } else {
2757      }                          startServer();
2758      // Just set receive timeout value, blindly.                  }
2759      ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);                  // This is always a failure.
2760      appendMessages(tr("Client receive timeout is set to %1 msec.").arg(::lscp_client_get_timeout(m_pClient)));                  stabilizeForm();
2761                    return false;
2762            }
2763            // Just set receive timeout value, blindly.
2764            ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);
2765            appendMessages(
2766                    tr("Client receive timeout is set to %1 msec.")
2767                    .arg(::lscp_client_get_timeout(m_pClient)));
2768    
2769          // Subscribe to channel info change notifications...          // Subscribe to channel info change notifications...
2770            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT) != LSCP_OK)
2771                    appendMessagesClient("lscp_client_subscribe(CHANNEL_COUNT)");
2772          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)
2773                  appendMessagesClient("lscp_client_subscribe");                  appendMessagesClient("lscp_client_subscribe(CHANNEL_INFO)");
2774    
2775            DeviceStatusForm::onDevicesChanged(); // initialize
2776            updateViewMidiDeviceStatusMenu();
2777            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT) != LSCP_OK)
2778                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_COUNT)");
2779            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO) != LSCP_OK)
2780                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_INFO)");
2781            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT) != LSCP_OK)
2782                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_COUNT)");
2783            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO) != LSCP_OK)
2784                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_INFO)");
2785    
2786    #if CONFIG_EVENT_CHANNEL_MIDI
2787            // Subscribe to channel MIDI data notifications...
2788            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI) != LSCP_OK)
2789                    appendMessagesClient("lscp_client_subscribe(CHANNEL_MIDI)");
2790    #endif
2791    
2792    #if CONFIG_EVENT_DEVICE_MIDI
2793            // Subscribe to channel MIDI data notifications...
2794            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI) != LSCP_OK)
2795                    appendMessagesClient("lscp_client_subscribe(DEVICE_MIDI)");
2796    #endif
2797    
2798      // We may stop scheduling around.          // We may stop scheduling around.
2799      stopSchedule();          stopSchedule();
2800    
2801      // We'll accept drops from now on...          // We'll accept drops from now on...
2802      setAcceptDrops(true);          setAcceptDrops(true);
2803    
2804      // Log success here.          // Log success here.
2805      appendMessages(tr("Client connected."));          appendMessages(tr("Client connected."));
2806    
2807          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
2808          // if visible, that we're ready...          // if visible, that we're ready...
2809          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
2810              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
2811          if (m_pDeviceForm)          if (m_pDeviceForm)
2812              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
2813    
2814            // Is any session pending to be loaded?
2815            if (!m_pOptions->sSessionFile.isEmpty()) {
2816                    // Just load the prabably startup session...
2817                    if (loadSessionFile(m_pOptions->sSessionFile)) {
2818                            m_pOptions->sSessionFile = QString::null;
2819                            return true;
2820                    }
2821            }
2822    
2823      // Is any session pending to be loaded?          // send the current / loaded fine tuning settings to the sampler
2824      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;  
         }  
     }  
2825    
2826      // Make a new session          // Make a new session
2827      return newSession();          return newSession();
2828  }  }
2829    
2830    
2831  // Stop client...  // Stop client...
2832  void MainForm::stopClient (void)  void MainForm::stopClient (void)
2833  {  {
2834      if (m_pClient == NULL)          if (m_pClient == NULL)
2835          return;                  return;
   
     // Log prepare here.  
     appendMessages(tr("Client disconnecting..."));  
2836    
2837      // Clear timer counters...          // Log prepare here.
2838      stopSchedule();          appendMessages(tr("Client disconnecting..."));
2839    
2840      // We'll reject drops from now on...          // Clear timer counters...
2841      setAcceptDrops(false);          stopSchedule();
2842    
2843      // Force any channel strips around, but          // We'll reject drops from now on...
2844      // but avoid removing the corresponding          setAcceptDrops(false);
     // channels from the back-end server.  
     m_iDirtyCount = 0;  
     closeSession(false);  
2845    
2846      // Close us as a client...          // Force any channel strips around, but
2847            // but avoid removing the corresponding
2848            // channels from the back-end server.
2849            m_iDirtyCount = 0;
2850            closeSession(false);
2851    
2852            // Close us as a client...
2853    #if CONFIG_EVENT_DEVICE_MIDI
2854            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI);
2855    #endif
2856    #if CONFIG_EVENT_CHANNEL_MIDI
2857            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI);
2858    #endif
2859            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
2860            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
2861            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
2862            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
2863          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
2864      ::lscp_client_destroy(m_pClient);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT);
2865      m_pClient = NULL;          ::lscp_client_destroy(m_pClient);
2866            m_pClient = NULL;
2867    
2868          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
2869          // if visible, that we're running out...          // if visible, that we're running out...
2870          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
2871              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
2872          if (m_pDeviceForm)          if (m_pDeviceForm)
2873              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
2874    
2875      // Log final here.          // Log final here.
2876      appendMessages(tr("Client disconnected."));          appendMessages(tr("Client disconnected."));
2877    
2878      // Make visible status.          // Make visible status.
2879      stabilizeForm();          stabilizeForm();
2880  }  }
2881    
2882    
2883    // Channel strip activation/selection.
2884    void MainForm::activateStrip ( QWidget *pWidget )
2885    {
2886            ChannelStrip *pChannelStrip
2887                    = static_cast<ChannelStrip *> (pWidget);
2888            if (pChannelStrip)
2889                    pChannelStrip->setSelected(true);
2890    
2891            stabilizeForm();
2892    }
2893    
2894    
2895  } // namespace QSampler  } // namespace QSampler
2896    
2897    

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

  ViewVC Help
Powered by ViewVC