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

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

  ViewVC Help
Powered by ViewVC