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

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

  ViewVC Help
Powered by ViewVC