/[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 1470 by schoenebeck, Sun Nov 4 23:37:47 2007 UTC revision 1515 by capela, Fri Nov 23 18:15:33 2007 UTC
# 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 52  Line 34 
34  #include "qsamplerDeviceForm.h"  #include "qsamplerDeviceForm.h"
35  #include "qsamplerOptionsForm.h"  #include "qsamplerOptionsForm.h"
36    
37    #include <QApplication>
38    #include <QWorkspace>
39    #include <QProcess>
40    #include <QMessageBox>
41    
42    #include <QRegExp>
43    #include <QTextStream>
44    #include <QFileDialog>
45    #include <QFileInfo>
46    #include <QFile>
47    #include <QUrl>
48    
49    #include <QDragEnterEvent>
50    
51    #include <QStatusBar>
52    #include <QSpinBox>
53    #include <QSlider>
54    #include <QLabel>
55    #include <QTimer>
56    #include <QDateTime>
57    
58    
59  #ifdef HAVE_SIGNAL_H  #ifdef HAVE_SIGNAL_H
60  #include <signal.h>  #include <signal.h>
61  #endif  #endif
# Line 98  class qsamplerCustomEvent : public QEven Line 102  class qsamplerCustomEvent : public QEven
102  {  {
103  public:  public:
104    
105      // Constructor.          // Constructor.
106      qsamplerCustomEvent(lscp_event_t event, const char *pchData, int cchData)          qsamplerCustomEvent(lscp_event_t event, const char *pchData, int cchData)
107          : QEvent(QSAMPLER_CUSTOM_EVENT)                  : QEvent(QSAMPLER_CUSTOM_EVENT)
108      {          {
109          m_event = event;                  m_event = event;
110          m_data.setLatin1(pchData, cchData);                  m_data  = QString::fromUtf8(pchData, cchData);
111      }          }
112    
113      // Accessors.          // Accessors.
114      lscp_event_t event() { return m_event; }          lscp_event_t event() { return m_event; }
115      QString&     data()  { return m_data;  }          QString&     data()  { return m_data;  }
116    
117  private:  private:
118    
119      // The proper event type.          // The proper event type.
120      lscp_event_t m_event;          lscp_event_t m_event;
121      // The event data as a string.          // The event data as a string.
122      QString      m_data;          QString      m_data;
123  };  };
124    
125    
# Line 127  namespace QSampler { Line 131  namespace QSampler {
131  // Kind of singleton reference.  // Kind of singleton reference.
132  MainForm* MainForm::g_pMainForm = NULL;  MainForm* MainForm::g_pMainForm = NULL;
133    
134  MainForm::MainForm(QWidget* parent) : QMainWindow(parent) {  MainForm::MainForm ( QWidget *pParent )
135      ui.setupUi(this);          : QMainWindow(pParent)
136    {
137            m_ui.setupUi(this);
138    
139          // Pseudo-singleton reference setup.          // Pseudo-singleton reference setup.
140          g_pMainForm = this;          g_pMainForm = this;
141    
142      // Initialize some pointer references.          // Initialize some pointer references.
143      m_pOptions = NULL;          m_pOptions = NULL;
144    
145      // All child forms are to be created later, not earlier than setup.          // All child forms are to be created later, not earlier than setup.
146      m_pMessages = NULL;          m_pMessages = NULL;
147      m_pInstrumentListForm = NULL;          m_pInstrumentListForm = NULL;
148      m_pDeviceForm = NULL;          m_pDeviceForm = NULL;
149    
150      // We'll start clean.          // We'll start clean.
151      m_iUntitled   = 0;          m_iUntitled   = 0;
152      m_iDirtyCount = 0;          m_iDirtyCount = 0;
153    
154      m_pServer = NULL;          m_pServer = NULL;
155      m_pClient = NULL;          m_pClient = NULL;
156    
157      m_iStartDelay = 0;          m_iStartDelay = 0;
158      m_iTimerDelay = 0;          m_iTimerDelay = 0;
159    
160      m_iTimerSlot = 0;          m_iTimerSlot = 0;
161    
162  #ifdef HAVE_SIGNAL_H  #ifdef HAVE_SIGNAL_H
163          // Set to ignore any fatal "Broken pipe" signals.          // Set to ignore any fatal "Broken pipe" signals.
# Line 159  MainForm::MainForm(QWidget* parent) : QM Line 165  MainForm::MainForm(QWidget* parent) : QM
165  #endif  #endif
166    
167  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
168      // Make some extras into the toolbar...          // Make some extras into the toolbar...
169          const QString& sVolumeText = tr("Master volume");          const QString& sVolumeText = tr("Master volume");
170          m_iVolumeChanging = 0;          m_iVolumeChanging = 0;
171          // Volume slider...          // Volume slider...
172          ui.channelsToolbar->addSeparator();          m_ui.channelsToolbar->addSeparator();
173          m_pVolumeSlider = new QSlider(Qt::Horizontal, ui.channelsToolbar);          m_pVolumeSlider = new QSlider(Qt::Horizontal, m_ui.channelsToolbar);
174          m_pVolumeSlider->setTickmarks(QSlider::Below);          m_pVolumeSlider->setTickPosition(QSlider::TicksBothSides);
175          m_pVolumeSlider->setTickInterval(10);          m_pVolumeSlider->setTickInterval(10);
176          m_pVolumeSlider->setPageStep(10);          m_pVolumeSlider->setPageStep(10);
177          m_pVolumeSlider->setRange(0, 100);          m_pVolumeSlider->setSingleStep(10);
178            m_pVolumeSlider->setMinimum(0);
179            m_pVolumeSlider->setMaximum(100);
180          m_pVolumeSlider->setMaximumHeight(26);          m_pVolumeSlider->setMaximumHeight(26);
181          m_pVolumeSlider->setMinimumWidth(160);          m_pVolumeSlider->setMinimumWidth(160);
182          QToolTip::add(m_pVolumeSlider, sVolumeText);          m_pVolumeSlider->setToolTip(sVolumeText);
183          QObject::connect(m_pVolumeSlider,          QObject::connect(m_pVolumeSlider,
184                  SIGNAL(valueChanged(int)),                  SIGNAL(valueChanged(int)),
185                  SLOT(volumeChanged(int)));                  SLOT(volumeChanged(int)));
186          //ui.channelsToolbar->setHorizontallyStretchable(true);          //m_ui.channelsToolbar->setHorizontallyStretchable(true);
187          //ui.channelsToolbar->setStretchableWidget(m_pVolumeSlider);          //m_ui.channelsToolbar->setStretchableWidget(m_pVolumeSlider);
188      ui.channelsToolbar->addWidget(m_pVolumeSlider);          m_ui.channelsToolbar->addWidget(m_pVolumeSlider);
189          // Volume spin-box          // Volume spin-box
190          ui.channelsToolbar->addSeparator();          m_ui.channelsToolbar->addSeparator();
191          m_pVolumeSpinBox = new QSpinBox(ui.channelsToolbar);          m_pVolumeSpinBox = new QSpinBox(m_ui.channelsToolbar);
192            m_pVolumeSpinBox->setMaximumHeight(24);
193          m_pVolumeSpinBox->setSuffix(" %");          m_pVolumeSpinBox->setSuffix(" %");
194          m_pVolumeSpinBox->setRange(0, 100);          m_pVolumeSpinBox->setMinimum(0);
195          QToolTip::add(m_pVolumeSpinBox, sVolumeText);          m_pVolumeSpinBox->setMaximum(100);
196            m_pVolumeSpinBox->setToolTip(sVolumeText);
197          QObject::connect(m_pVolumeSpinBox,          QObject::connect(m_pVolumeSpinBox,
198                  SIGNAL(valueChanged(int)),                  SIGNAL(valueChanged(int)),
199                  SLOT(volumeChanged(int)));                  SLOT(volumeChanged(int)));
200      ui.channelsToolbar->addWidget(m_pVolumeSpinBox);          m_ui.channelsToolbar->addWidget(m_pVolumeSpinBox);
201  #endif  #endif
202    
203      // Make it an MDI workspace.          // Make it an MDI workspace.
204      m_pWorkspace = new QWorkspace(this);          m_pWorkspace = new QWorkspace(this);
205      m_pWorkspace->setScrollBarsEnabled(true);          m_pWorkspace->setScrollBarsEnabled(true);
206          // Set the activation connection.          // Set the activation connection.
207          QObject::connect(m_pWorkspace,          QObject::connect(m_pWorkspace,
208                  SIGNAL(windowActivated(QWidget *)),                  SIGNAL(windowActivated(QWidget *)),
209                  SLOT(stabilizeForm()));                  SLOT(activateStrip(QWidget *)));
210      // Make it shine :-)          // Make it shine :-)
211      setCentralWidget(m_pWorkspace);          setCentralWidget(m_pWorkspace);
212    
213      // Create some statusbar labels...          // Create some statusbar labels...
214      QLabel *pLabel;          QLabel *pLabel;
215      // Client status.          // Client status.
216      pLabel = new QLabel(tr("Connected"), this);          pLabel = new QLabel(tr("Connected"), this);
217      pLabel->setAlignment(Qt::AlignLeft);          pLabel->setAlignment(Qt::AlignLeft);
218      pLabel->setMinimumSize(pLabel->sizeHint());          pLabel->setMinimumSize(pLabel->sizeHint());
219      m_statusItem[QSAMPLER_STATUS_CLIENT] = pLabel;          m_statusItem[QSAMPLER_STATUS_CLIENT] = pLabel;
220      statusBar()->addWidget(pLabel);          statusBar()->addWidget(pLabel);
221      // Server address.          // Server address.
222      pLabel = new QLabel(this);          pLabel = new QLabel(this);
223      pLabel->setAlignment(Qt::AlignLeft);          pLabel->setAlignment(Qt::AlignLeft);
224      m_statusItem[QSAMPLER_STATUS_SERVER] = pLabel;          m_statusItem[QSAMPLER_STATUS_SERVER] = pLabel;
225      statusBar()->addWidget(pLabel, 1);          statusBar()->addWidget(pLabel, 1);
226      // Channel title.          // Channel title.
227      pLabel = new QLabel(this);          pLabel = new QLabel(this);
228      pLabel->setAlignment(Qt::AlignLeft);          pLabel->setAlignment(Qt::AlignLeft);
229      m_statusItem[QSAMPLER_STATUS_CHANNEL] = pLabel;          m_statusItem[QSAMPLER_STATUS_CHANNEL] = pLabel;
230      statusBar()->addWidget(pLabel, 2);          statusBar()->addWidget(pLabel, 2);
231      // Session modification status.          // Session modification status.
232      pLabel = new QLabel(tr("MOD"), this);          pLabel = new QLabel(tr("MOD"), this);
233      pLabel->setAlignment(Qt::AlignHCenter);          pLabel->setAlignment(Qt::AlignHCenter);
234      pLabel->setMinimumSize(pLabel->sizeHint());          pLabel->setMinimumSize(pLabel->sizeHint());
235      m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;          m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;
236      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);  
237    
238  #if defined(WIN32)  #if defined(WIN32)
239      WSAStartup(MAKEWORD(1, 1), &_wsaData);          WSAStartup(MAKEWORD(1, 1), &_wsaData);
240  #endif  #endif
241    
242          QObject::connect(ui.fileNewAction,          // Some actions surely need those
243                  SIGNAL(activated()),          // shortcuts firmly attached...
244            addAction(m_ui.viewMenubarAction);
245            addAction(m_ui.viewToolbarAction);
246    
247            QObject::connect(m_ui.fileNewAction,
248                    SIGNAL(triggered()),
249                  SLOT(fileNew()));                  SLOT(fileNew()));
250          QObject::connect(ui.fileOpenAction,          QObject::connect(m_ui.fileOpenAction,
251                  SIGNAL(activated()),                  SIGNAL(triggered()),
252                  SLOT(fileOpen()));                  SLOT(fileOpen()));
253          QObject::connect(ui.fileSaveAction,          QObject::connect(m_ui.fileSaveAction,
254                  SIGNAL(activated()),                  SIGNAL(triggered()),
255                  SLOT(fileSave()));                  SLOT(fileSave()));
256          QObject::connect(ui.fileSaveAsAction,          QObject::connect(m_ui.fileSaveAsAction,
257                  SIGNAL(activated()),                  SIGNAL(triggered()),
258                  SLOT(fileSaveAs()));                  SLOT(fileSaveAs()));
259          QObject::connect(ui.fileResetAction,          QObject::connect(m_ui.fileResetAction,
260                  SIGNAL(activated()),                  SIGNAL(triggered()),
261                  SLOT(fileReset()));                  SLOT(fileReset()));
262          QObject::connect(ui.fileRestartAction,          QObject::connect(m_ui.fileRestartAction,
263                  SIGNAL(activated()),                  SIGNAL(triggered()),
264                  SLOT(fileRestart()));                  SLOT(fileRestart()));
265          QObject::connect(ui.fileExitAction,          QObject::connect(m_ui.fileExitAction,
266                  SIGNAL(activated()),                  SIGNAL(triggered()),
267                  SLOT(fileExit()));                  SLOT(fileExit()));
268          QObject::connect(ui.editAddChannelAction,          QObject::connect(m_ui.editAddChannelAction,
269                  SIGNAL(activated()),                  SIGNAL(triggered()),
270                  SLOT(editAddChannel()));                  SLOT(editAddChannel()));
271          QObject::connect(ui.editRemoveChannelAction,          QObject::connect(m_ui.editRemoveChannelAction,
272                  SIGNAL(activated()),                  SIGNAL(triggered()),
273                  SLOT(editRemoveChannel()));                  SLOT(editRemoveChannel()));
274          QObject::connect(ui.editSetupChannelAction,          QObject::connect(m_ui.editSetupChannelAction,
275                  SIGNAL(activated()),                  SIGNAL(triggered()),
276                  SLOT(editSetupChannel()));                  SLOT(editSetupChannel()));
277          QObject::connect(ui.editEditChannelAction,          QObject::connect(m_ui.editEditChannelAction,
278                  SIGNAL(activated()),                  SIGNAL(triggered()),
279                  SLOT(editEditChannel()));                  SLOT(editEditChannel()));
280          QObject::connect(ui.editResetChannelAction,          QObject::connect(m_ui.editResetChannelAction,
281                  SIGNAL(activated()),                  SIGNAL(triggered()),
282                  SLOT(editResetChannel()));                  SLOT(editResetChannel()));
283          QObject::connect(ui.editResetAllChannelsAction,          QObject::connect(m_ui.editResetAllChannelsAction,
284                  SIGNAL(activated()),                  SIGNAL(triggered()),
285                  SLOT(editResetAllChannels()));                  SLOT(editResetAllChannels()));
286          QObject::connect(ui.viewMenubarAction,          QObject::connect(m_ui.viewMenubarAction,
287                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
288                  SLOT(viewMenubar(bool)));                  SLOT(viewMenubar(bool)));
289          QObject::connect(ui.viewToolbarAction,          QObject::connect(m_ui.viewToolbarAction,
290                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
291                  SLOT(viewToolbar(bool)));                  SLOT(viewToolbar(bool)));
292          QObject::connect(ui.viewStatusbarAction,          QObject::connect(m_ui.viewStatusbarAction,
293                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
294                  SLOT(viewStatusbar(bool)));                  SLOT(viewStatusbar(bool)));
295          QObject::connect(ui.viewMessagesAction,          QObject::connect(m_ui.viewMessagesAction,
296                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
297                  SLOT(viewMessages(bool)));                  SLOT(viewMessages(bool)));
298          QObject::connect(ui.viewInstrumentsAction,          QObject::connect(m_ui.viewInstrumentsAction,
299                  SIGNAL(activated()),                  SIGNAL(triggered()),
300                  SLOT(viewInstruments()));                  SLOT(viewInstruments()));
301          QObject::connect(ui.viewDevicesAction,          QObject::connect(m_ui.viewDevicesAction,
302                  SIGNAL(activated()),                  SIGNAL(triggered()),
303                  SLOT(viewDevices()));                  SLOT(viewDevices()));
304          QObject::connect(ui.viewOptionsAction,          QObject::connect(m_ui.viewOptionsAction,
305                  SIGNAL(activated()),                  SIGNAL(triggered()),
306                  SLOT(viewOptions()));                  SLOT(viewOptions()));
307          QObject::connect(ui.channelsArrangeAction,          QObject::connect(m_ui.channelsArrangeAction,
308                  SIGNAL(activated()),                  SIGNAL(triggered()),
309                  SLOT(channelsArrange()));                  SLOT(channelsArrange()));
310          QObject::connect(ui.channelsAutoArrangeAction,          QObject::connect(m_ui.channelsAutoArrangeAction,
311                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
312                  SLOT(channelsAutoArrange(bool)));                  SLOT(channelsAutoArrange(bool)));
313          QObject::connect(ui.helpAboutAction,          QObject::connect(m_ui.helpAboutAction,
314                  SIGNAL(activated()),                  SIGNAL(triggered()),
315                  SLOT(helpAbout()));                  SLOT(helpAbout()));
316          QObject::connect(ui.helpAboutQtAction,          QObject::connect(m_ui.helpAboutQtAction,
317                  SIGNAL(activated()),                  SIGNAL(triggered()),
318                  SLOT(helpAboutQt()));                  SLOT(helpAboutQt()));
319    
320            QObject::connect(m_ui.fileMenu,
321                    SIGNAL(aboutToShow()),
322                    SLOT(updateRecentFilesMenu()));
323            QObject::connect(m_ui.channelsMenu,
324                    SIGNAL(aboutToShow()),
325                    SLOT(channelsMenuAboutToShow()));
326  }  }
327    
328  // Destructor.  // Destructor.
329  MainForm::~MainForm()  MainForm::~MainForm()
330  {  {
331      // Do final processing anyway.          // Do final processing anyway.
332      processServerExit();          processServerExit();
333    
334  #if defined(WIN32)  #if defined(WIN32)
335      WSACleanup();          WSACleanup();
336  #endif  #endif
337    
338      // Finally drop any widgets around...          // Finally drop any widgets around...
339      if (m_pDeviceForm)          if (m_pDeviceForm)
340          delete m_pDeviceForm;                  delete m_pDeviceForm;
341      if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
342          delete m_pInstrumentListForm;                  delete m_pInstrumentListForm;
343      if (m_pMessages)          if (m_pMessages)
344          delete m_pMessages;                  delete m_pMessages;
345      if (m_pWorkspace)          if (m_pWorkspace)
346          delete m_pWorkspace;                  delete m_pWorkspace;
347    
348      // Delete status item labels one by one.          // Delete status item labels one by one.
349      if (m_statusItem[QSAMPLER_STATUS_CLIENT])          if (m_statusItem[QSAMPLER_STATUS_CLIENT])
350          delete m_statusItem[QSAMPLER_STATUS_CLIENT];                  delete m_statusItem[QSAMPLER_STATUS_CLIENT];
351      if (m_statusItem[QSAMPLER_STATUS_SERVER])          if (m_statusItem[QSAMPLER_STATUS_SERVER])
352          delete m_statusItem[QSAMPLER_STATUS_SERVER];                  delete m_statusItem[QSAMPLER_STATUS_SERVER];
353      if (m_statusItem[QSAMPLER_STATUS_CHANNEL])          if (m_statusItem[QSAMPLER_STATUS_CHANNEL])
354          delete m_statusItem[QSAMPLER_STATUS_CHANNEL];                  delete m_statusItem[QSAMPLER_STATUS_CHANNEL];
355      if (m_statusItem[QSAMPLER_STATUS_SESSION])          if (m_statusItem[QSAMPLER_STATUS_SESSION])
356          delete m_statusItem[QSAMPLER_STATUS_SESSION];                  delete m_statusItem[QSAMPLER_STATUS_SESSION];
357    
358  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
359          delete m_pVolumeSpinBox;          delete m_pVolumeSpinBox;
360          delete m_pVolumeSlider;          delete m_pVolumeSlider;
361  #endif  #endif
362    
     // Delete recentfiles menu.  
     if (m_pRecentFilesMenu)  
         delete m_pRecentFilesMenu;  
   
363          // Pseudo-singleton reference shut-down.          // Pseudo-singleton reference shut-down.
364          g_pMainForm = NULL;          g_pMainForm = NULL;
365  }  }
# Line 355  MainForm::~MainForm() Line 368  MainForm::~MainForm()
368  // Make and set a proper setup options step.  // Make and set a proper setup options step.
369  void MainForm::setup ( qsamplerOptions *pOptions )  void MainForm::setup ( qsamplerOptions *pOptions )
370  {  {
371      // We got options?          // We got options?
372      m_pOptions = pOptions;          m_pOptions = pOptions;
373    
374      // What style do we create these forms?          // What style do we create these forms?
375          Qt::WFlags wflags = Qt::WStyle_Customize          Qt::WindowFlags wflags = Qt::Window
376                  | Qt::WStyle_NormalBorder  #if QT_VERSION >= 0x040200
377                  | Qt::WStyle_Title                  | Qt::CustomizeWindowHint
378                  | Qt::WStyle_SysMenu  #endif
379                  | Qt::WStyle_MinMax                  | Qt::WindowTitleHint
380                  | Qt::WType_TopLevel;                  | Qt::WindowSystemMenuHint
381      if (m_pOptions->bKeepOnTop)                  | Qt::WindowMinMaxButtonsHint;
382          wflags |= Qt::WStyle_Tool;          if (m_pOptions->bKeepOnTop)
383      // Some child forms are to be created right now.                  wflags |= Qt::Tool;
384      m_pMessages = new qsamplerMessages(this);          // Some child forms are to be created right now.
385      m_pDeviceForm = new DeviceForm(this, wflags);          m_pMessages = new qsamplerMessages(this);
386            m_pDeviceForm = new DeviceForm(this, wflags);
387  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
388      m_pInstrumentListForm = new InstrumentListForm(this, wflags);          m_pInstrumentListForm = new InstrumentListForm(this, wflags);
         QObject::connect(&m_pInstrumentListForm->model,  
                 SIGNAL(instrumentsChanged()),  
                 SLOT(sessionDirty()));  
389  #else  #else
390          viewInstrumentsAction->setEnabled(false);          viewInstrumentsAction->setEnabled(false);
391  #endif  #endif
392      // Set message defaults...          // Set message defaults...
393      updateMessagesFont();          updateMessagesFont();
394      updateMessagesLimit();          updateMessagesLimit();
395      updateMessagesCapture();          updateMessagesCapture();
396      // Set the visibility signal.          // Set the visibility signal.
397          QObject::connect(m_pMessages,          QObject::connect(m_pMessages,
398                  SIGNAL(visibilityChanged(bool)),                  SIGNAL(visibilityChanged(bool)),
399                  SLOT(stabilizeForm()));                  SLOT(stabilizeForm()));
400    
401      // Initial decorations toggle state.          // Initial decorations toggle state.
402      ui.viewMenubarAction->setOn(m_pOptions->bMenubar);          m_ui.viewMenubarAction->setChecked(m_pOptions->bMenubar);
403      ui.viewToolbarAction->setOn(m_pOptions->bToolbar);          m_ui.viewToolbarAction->setChecked(m_pOptions->bToolbar);
404      ui.viewStatusbarAction->setOn(m_pOptions->bStatusbar);          m_ui.viewStatusbarAction->setChecked(m_pOptions->bStatusbar);
405      ui.channelsAutoArrangeAction->setOn(m_pOptions->bAutoArrange);          m_ui.channelsAutoArrangeAction->setChecked(m_pOptions->bAutoArrange);
406    
407      // Initial decorations visibility state.          // Initial decorations visibility state.
408      viewMenubar(m_pOptions->bMenubar);          viewMenubar(m_pOptions->bMenubar);
409      viewToolbar(m_pOptions->bToolbar);          viewToolbar(m_pOptions->bToolbar);
410      viewStatusbar(m_pOptions->bStatusbar);          viewStatusbar(m_pOptions->bStatusbar);
411    
412      addDockWidget(Qt::BottomDockWidgetArea, m_pMessages);          addDockWidget(Qt::BottomDockWidgetArea, m_pMessages);
413    
414      // Restore whole toolbar & dock windows states.          // Restore whole dock windows state.
415      QString sDockables = m_pOptions->settings().readEntry("/Layout/DockWindowsBase64" , QString::null);          QByteArray aDockables = m_pOptions->settings().value(
416      if (!sDockables.isEmpty()) {                  "/Layout/DockWindows").toByteArray();
417          restoreState(QByteArray::fromBase64(sDockables.toAscii()));          if (!aDockables.isEmpty()) {
418      }                  restoreState(aDockables);
419      // Try to restore old window positioning and initial visibility.          }
420      m_pOptions->loadWidgetGeometry(this);  
421      m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);          // Try to restore old window positioning and initial visibility.
422      m_pOptions->loadWidgetGeometry(m_pDeviceForm);          m_pOptions->loadWidgetGeometry(this);
423            m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);
424      // Final startup stabilization...          m_pOptions->loadWidgetGeometry(m_pDeviceForm);
425      updateMaxVolume();  
426      updateRecentFilesMenu();          // Final startup stabilization...
427      stabilizeForm();          updateMaxVolume();
428            updateRecentFilesMenu();
429            stabilizeForm();
430    
431      // Make it ready :-)          // Make it ready :-)
432      statusBar()->message(tr("Ready"), 3000);          statusBar()->showMessage(tr("Ready"), 3000);
433    
434      // We'll try to start immediately...          // We'll try to start immediately...
435      startSchedule(0);          startSchedule(0);
436    
437      // Register the first timer slot.          // Register the first timer slot.
438      QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));          QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
439  }  }
440    
441    
442  // Window close event handlers.  // Window close event handlers.
443  bool MainForm::queryClose (void)  bool MainForm::queryClose (void)
444  {  {
445      bool bQueryClose = closeSession(false);          bool bQueryClose = closeSession(false);
446    
447      // Try to save current general state...          // Try to save current general state...
448      if (m_pOptions) {          if (m_pOptions) {
449          // Some windows default fonts is here on demand too.                  // Some windows default fonts is here on demand too.
450          if (bQueryClose && m_pMessages)                  if (bQueryClose && m_pMessages)
451              m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
452          // Try to save current positioning.                  // Try to save current positioning.
453          if (bQueryClose) {                  if (bQueryClose) {
454              // Save decorations state.                          // Save decorations state.
455              m_pOptions->bMenubar = ui.MenuBar->isVisible();                          m_pOptions->bMenubar = m_ui.MenuBar->isVisible();
456              m_pOptions->bToolbar = (ui.fileToolbar->isVisible() || ui.editToolbar->isVisible() || ui.channelsToolbar->isVisible());                          m_pOptions->bToolbar = (m_ui.fileToolbar->isVisible()
457              m_pOptions->bStatusbar = statusBar()->isVisible();                                  || m_ui.editToolbar->isVisible()
458              // Save the dock windows state.                                  || m_ui.channelsToolbar->isVisible());
459              const QString sDockables = saveState().toBase64().data();                          m_pOptions->bStatusbar = statusBar()->isVisible();
460              m_pOptions->settings().writeEntry("/Layout/DockWindowsBase64", sDockables);                          // Save the dock windows state.
461              // And the children, and the main windows state,.                          const QString sDockables = saveState().toBase64().data();
462                            m_pOptions->settings().setValue("/Layout/DockWindows", saveState());
463                            // And the children, and the main windows state,.
464                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);
465                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);
466                          m_pOptions->saveWidgetGeometry(this);                          m_pOptions->saveWidgetGeometry(this);
# Line 454  bool MainForm::queryClose (void) Line 469  bool MainForm::queryClose (void)
469                                  m_pInstrumentListForm->close();                                  m_pInstrumentListForm->close();
470                          if (m_pDeviceForm)                          if (m_pDeviceForm)
471                                  m_pDeviceForm->close();                                  m_pDeviceForm->close();
472              // Stop client and/or server, gracefully.                          // Stop client and/or server, gracefully.
473              stopServer();                          stopServer();
474          }                  }
475      }          }
476    
477      return bQueryClose;          return bQueryClose;
478  }  }
479    
480    
481  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )
482  {  {
483      if (queryClose())          if (queryClose())
484          pCloseEvent->accept();                  pCloseEvent->accept();
485      else          else
486          pCloseEvent->ignore();                  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;  
487  }  }
488    
489    
490  // Window drag-n-drop event handlers.  // Window drag-n-drop event handlers.
491  void MainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )  void MainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )
492  {  {
493          QStringList files;          // Accept external drags only...
494          pDragEnterEvent->accept(decodeDragFiles(pDragEnterEvent, files));          if (pDragEnterEvent->source() == NULL
495                    && pDragEnterEvent->mimeData()->hasUrls()) {
496                    pDragEnterEvent->accept();
497            } else {
498                    pDragEnterEvent->ignore();
499            }
500  }  }
501    
502    
503  void MainForm::dropEvent ( QDropEvent* pDropEvent )  void MainForm::dropEvent ( QDropEvent* pDropEvent )
504  {  {
505      QStringList files;          // Accept externally originated drops only...
506            if (pDropEvent->source())
507      if (!decodeDragFiles(pDropEvent, files))                  return;
         return;  
508    
509          for (QStringList::Iterator iter = files.begin(); iter != files.end(); iter++) {          const QMimeData *pMimeData = pDropEvent->mimeData();
510                  const QString& sPath = *iter;          if (pMimeData->hasUrls()) {
511                  if (qsamplerChannel::isInstrumentFile(sPath)) {                  QListIterator<QUrl> iter(pMimeData->urls());
512                          // Try to create a new channel from instrument file...                  while (iter.hasNext()) {
513                          qsamplerChannel *pChannel = new qsamplerChannel();                          const QString& sPath = iter.next().toLocalFile();
514                          if (pChannel == NULL)                          if (qsamplerChannel::isInstrumentFile(sPath)) {
515                                  return;                                  // Try to create a new channel from instrument file...
516                          // Start setting the instrument filename...                                  qsamplerChannel *pChannel = new qsamplerChannel();
517                          pChannel->setInstrument(sPath, 0);                                  if (pChannel == NULL)
518                          // Before we show it up, may be we'll                                          return;
519                          // better ask for some initial values?                                  // Start setting the instrument filename...
520                          if (!pChannel->channelSetup(this)) {                                  pChannel->setInstrument(sPath, 0);
521                                  delete pChannel;                                  // Before we show it up, may be we'll
522                                  return;                                  // better ask for some initial values?
523                          }                                  if (!pChannel->channelSetup(this)) {
524                          // Finally, give it to a new channel strip...                                          delete pChannel;
525                          if (!createChannelStrip(pChannel)) {                                          return;
526                                  delete pChannel;                                  }
527                                  return;                                  // Finally, give it to a new channel strip...
528                                    if (!createChannelStrip(pChannel)) {
529                                            delete pChannel;
530                                            return;
531                                    }
532                                    // Make that an overall update.
533                                    m_iDirtyCount++;
534                                    stabilizeForm();
535                            }   // Otherwise, load an usual session file (LSCP script)...
536                            else if (closeSession(true)) {
537                                    loadSessionFile(sPath);
538                                    break;
539                          }                          }
                         // Make that an overall update.  
                         m_iDirtyCount++;  
                         stabilizeForm();  
                 }   // Otherwise, load an usual session file (LSCP script)...  
                 else if (closeSession(true)) {  
                         loadSessionFile(sPath);  
                         break;  
540                  }                  }
541                  // Make it look responsive...:)                  // Make it look responsive...:)
542                  QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
543          }          }
544  }  }
545    
546    
547  // Custome event handler.  // Custome event handler.
548  void MainForm::customEvent(QEvent* pCustomEvent)  void MainForm::customEvent(QEvent* pCustomEvent)
549  {  {
550      // For the time being, just pump it to messages.          // For the time being, just pump it to messages.
551      if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {          if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {
552          qsamplerCustomEvent *pEvent = (qsamplerCustomEvent *) pCustomEvent;                  qsamplerCustomEvent *pEvent = (qsamplerCustomEvent *) pCustomEvent;
553                  if (pEvent->event() == LSCP_EVENT_CHANNEL_INFO) {                  if (pEvent->event() == LSCP_EVENT_CHANNEL_INFO) {
554                          int iChannelID = pEvent->data().toInt();                          int iChannelID = pEvent->data().toInt();
555                          ChannelStrip *pChannelStrip = channelStrip(iChannelID);                          ChannelStrip *pChannelStrip = channelStrip(iChannelID);
# Line 555  void MainForm::customEvent(QEvent* pCust Line 560  void MainForm::customEvent(QEvent* pCust
560                                  .arg(::lscp_event_to_text(pEvent->event()))                                  .arg(::lscp_event_to_text(pEvent->event()))
561                                  .arg(pEvent->data()), "#996699");                                  .arg(pEvent->data()), "#996699");
562                  }                  }
563      }          }
564  }  }
565    
566  // Context menu event handler.  // Context menu event handler.
567  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )
568  {  {
569      stabilizeForm();          stabilizeForm();
570    
571      ui.editMenu->exec(pEvent->globalPos());          m_ui.editMenu->exec(pEvent->globalPos());
572  }  }
573    
574    
# Line 571  void MainForm::contextMenuEvent( QContex Line 576  void MainForm::contextMenuEvent( QContex
576  // qsamplerMainForm -- Brainless public property accessors.  // qsamplerMainForm -- Brainless public property accessors.
577    
578  // The global options settings property.  // The global options settings property.
579  qsamplerOptions *MainForm::options (void)  qsamplerOptions *MainForm::options (void) const
580  {  {
581      return m_pOptions;          return m_pOptions;
582  }  }
583    
584    
585  // The LSCP client descriptor property.  // The LSCP client descriptor property.
586  lscp_client_t *MainForm::client (void)  lscp_client_t *MainForm::client (void) const
587  {  {
588      return m_pClient;          return m_pClient;
589  }  }
590    
591    
# Line 597  MainForm *MainForm::getInstance (void) Line 602  MainForm *MainForm::getInstance (void)
602  // Format the displayable session filename.  // Format the displayable session filename.
603  QString MainForm::sessionName ( const QString& sFilename )  QString MainForm::sessionName ( const QString& sFilename )
604  {  {
605      bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);          bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);
606      QString sSessionName = sFilename;          QString sSessionName = sFilename;
607      if (sSessionName.isEmpty())          if (sSessionName.isEmpty())
608          sSessionName = tr("Untitled") + QString::number(m_iUntitled);                  sSessionName = tr("Untitled") + QString::number(m_iUntitled);
609      else if (!bCompletePath)          else if (!bCompletePath)
610          sSessionName = QFileInfo(sSessionName).fileName();                  sSessionName = QFileInfo(sSessionName).fileName();
611      return sSessionName;          return sSessionName;
612  }  }
613    
614    
615  // Create a new session file from scratch.  // Create a new session file from scratch.
616  bool MainForm::newSession (void)  bool MainForm::newSession (void)
617  {  {
618      // Check if we can do it.          // Check if we can do it.
619      if (!closeSession(true))          if (!closeSession(true))
620          return false;                  return false;
621    
622          // Give us what the server has, right now...          // Give us what the server has, right now...
623          updateSession();          updateSession();
624    
625      // Ok increment untitled count.          // Ok increment untitled count.
626      m_iUntitled++;          m_iUntitled++;
627    
628      // Stabilize form.          // Stabilize form.
629      m_sFilename = QString::null;          m_sFilename = QString::null;
630      m_iDirtyCount = 0;          m_iDirtyCount = 0;
631      appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));          appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));
632      stabilizeForm();          stabilizeForm();
633    
634      return true;          return true;
635  }  }
636    
637    
638  // Open an existing sampler session.  // Open an existing sampler session.
639  bool MainForm::openSession (void)  bool MainForm::openSession (void)
640  {  {
641      if (m_pOptions == NULL)          if (m_pOptions == NULL)
642          return false;                  return false;
643    
644      // Ask for the filename to open...          // Ask for the filename to open...
645      QString sFilename = QFileDialog::getOpenFileName(          QString sFilename = QFileDialog::getOpenFileName(this,
646                  m_pOptions->sSessionDir,                // Start here.                  QSAMPLER_TITLE ": " + tr("Open Session"), // Caption.
647                  tr("LSCP Session files") + " (*.lscp)", // Filter (LSCP files)                  m_pOptions->sSessionDir,                  // Start here.
648                  this, 0,                                // Parent and name (none)                  tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
649                  QSAMPLER_TITLE ": " + tr("Open Session")        // Caption.          );
650      );  
651            // Have we cancelled?
652      // Have we cancelled?          if (sFilename.isEmpty())
653      if (sFilename.isEmpty())                  return false;
654          return false;  
655            // Check if we're going to discard safely the current one...
656      // Check if we're going to discard safely the current one...          if (!closeSession(true))
657      if (!closeSession(true))                  return false;
         return false;  
658    
659      // Load it right away.          // Load it right away.
660      return loadSessionFile(sFilename);          return loadSessionFile(sFilename);
661  }  }
662    
663    
664  // Save current sampler session with another name.  // Save current sampler session with another name.
665  bool MainForm::saveSession ( bool bPrompt )  bool MainForm::saveSession ( bool bPrompt )
666  {  {
667      if (m_pOptions == NULL)          if (m_pOptions == NULL)
668          return false;                  return false;
669    
670      QString sFilename = m_sFilename;          QString sFilename = m_sFilename;
671    
672      // Ask for the file to save, if there's none...          // Ask for the file to save, if there's none...
673      if (bPrompt || sFilename.isEmpty()) {          if (bPrompt || sFilename.isEmpty()) {
674          // If none is given, assume default directory.                  // If none is given, assume default directory.
675          if (sFilename.isEmpty())                  if (sFilename.isEmpty())
676              sFilename = m_pOptions->sSessionDir;                          sFilename = m_pOptions->sSessionDir;
677          // Prompt the guy...                  // Prompt the guy...
678          sFilename = QFileDialog::getSaveFileName(                  sFilename = QFileDialog::getSaveFileName(this,
679                          sFilename,                              // Start here.                          QSAMPLER_TITLE ": " + tr("Save Session"), // Caption.
680                          tr("LSCP Session files") + " (*.lscp)", // Filter (LSCP files)                          sFilename,                                // Start here.
681                          this, 0,                                // Parent and name (none)                          tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
682                          QSAMPLER_TITLE ": " + tr("Save Session")        // Caption.                  );
683          );                  // Have we cancelled it?
684          // Have we cancelled it?                  if (sFilename.isEmpty())
685          if (sFilename.isEmpty())                          return false;
686              return false;                  // Enforce .lscp extension...
687          // Enforce .lscp extension...                  if (QFileInfo(sFilename).suffix().isEmpty())
688          if (QFileInfo(sFilename).extension().isEmpty())                          sFilename += ".lscp";
689              sFilename += ".lscp";                  // Check if already exists...
690          // Check if already exists...                  if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {
691          if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {                          if (QMessageBox::warning(this,
             if (QMessageBox::warning(this,  
692                                  QSAMPLER_TITLE ": " + tr("Warning"),                                  QSAMPLER_TITLE ": " + tr("Warning"),
693                  tr("The file already exists:\n\n"                                  tr("The file already exists:\n\n"
694                     "\"%1\"\n\n"                                  "\"%1\"\n\n"
695                     "Do you want to replace it?")                                  "Do you want to replace it?")
696                     .arg(sFilename),                                  .arg(sFilename),
697                  tr("Replace"), tr("Cancel")) > 0)                                  tr("Replace"), tr("Cancel")) > 0)
698                  return false;                                  return false;
699          }                  }
700      }          }
701    
702      // Save it right away.          // Save it right away.
703      return saveSessionFile(sFilename);          return saveSessionFile(sFilename);
704  }  }
705    
706    
707  // Close current session.  // Close current session.
708  bool MainForm::closeSession ( bool bForce )  bool MainForm::closeSession ( bool bForce )
709  {  {
710      bool bClose = true;          bool bClose = true;
711    
712      // Are we dirty enough to prompt it?          // Are we dirty enough to prompt it?
713      if (m_iDirtyCount > 0) {          if (m_iDirtyCount > 0) {
714          switch (QMessageBox::warning(this,                  switch (QMessageBox::warning(this,
715                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
716              tr("The current session has been changed:\n\n"                          tr("The current session has been changed:\n\n"
717              "\"%1\"\n\n"                          "\"%1\"\n\n"
718              "Do you want to save the changes?")                          "Do you want to save the changes?")
719              .arg(sessionName(m_sFilename)),                          .arg(sessionName(m_sFilename)),
720              tr("Save"), tr("Discard"), tr("Cancel"))) {                          tr("Save"), tr("Discard"), tr("Cancel"))) {
721          case 0:     // Save...                  case 0:     // Save...
722              bClose = saveSession(false);                          bClose = saveSession(false);
723              // Fall thru....                          // Fall thru....
724          case 1:     // Discard                  case 1:     // Discard
725              break;                          break;
726          default:    // Cancel.                  default:    // Cancel.
727              bClose = false;                          bClose = false;
728              break;                          break;
729          }                  }
730      }          }
731    
732      // If we may close it, dot it.          // If we may close it, dot it.
733      if (bClose) {          if (bClose) {
734          // Remove all channel strips from sight...                  // Remove all channel strips from sight...
735          m_pWorkspace->setUpdatesEnabled(false);                  m_pWorkspace->setUpdatesEnabled(false);
736          QWidgetList wlist = m_pWorkspace->windowList();                  QWidgetList wlist = m_pWorkspace->windowList();
737          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
738              ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                          ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
739              if (pChannelStrip) {                          if (pChannelStrip) {
740                  qsamplerChannel *pChannel = pChannelStrip->channel();                                  qsamplerChannel *pChannel = pChannelStrip->channel();
741                  if (bForce && pChannel)                                  if (bForce && pChannel)
742                      pChannel->removeChannel();                                          pChannel->removeChannel();
743                  delete pChannelStrip;                                  delete pChannelStrip;
744              }                          }
745          }                  }
746          m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
747          // We're now clean, for sure.                  // We're now clean, for sure.
748          m_iDirtyCount = 0;                  m_iDirtyCount = 0;
749      }          }
750    
751      return bClose;          return bClose;
752  }  }
753    
754    
755  // Load a session from specific file path.  // Load a session from specific file path.
756  bool MainForm::loadSessionFile ( const QString& sFilename )  bool MainForm::loadSessionFile ( const QString& sFilename )
757  {  {
758      if (m_pClient == NULL)          if (m_pClient == NULL)
759          return false;                  return false;
760    
761      // Open and read from real file.          // Open and read from real file.
762      QFile file(sFilename);          QFile file(sFilename);
763      if (!file.open(IO_ReadOnly)) {          if (!file.open(QIODevice::ReadOnly)) {
764          appendMessagesError(tr("Could not open \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
765          return false;                          tr("Could not open \"%1\" session file.\n\nSorry.")
766      }                          .arg(sFilename));
767                    return false;
768            }
769    
770          // Tell the world we'll take some time...          // Tell the world we'll take some time...
771          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
772    
773      // Read the file.          // Read the file.
774          int iLine = 0;          int iLine = 0;
775      int iErrors = 0;          int iErrors = 0;
776      QTextStream ts(&file);          QTextStream ts(&file);
777      while (!ts.atEnd()) {          while (!ts.atEnd()) {
778          // Read the line.                  // Read the line.
779          QString sCommand = ts.readLine().stripWhiteSpace();                  QString sCommand = ts.readLine().trimmed();
780                  iLine++;                  iLine++;
781          // If not empty, nor a comment, call the server...                  // If not empty, nor a comment, call the server...
782          if (!sCommand.isEmpty() && sCommand[0] != '#') {                  if (!sCommand.isEmpty() && sCommand[0] != '#') {
783                          // Remember that, no matter what,                          // Remember that, no matter what,
784                          // all LSCP commands are CR/LF terminated.                          // all LSCP commands are CR/LF terminated.
785                          sCommand += "\r\n";                          sCommand += "\r\n";
786                          if (::lscp_client_query(m_pClient, sCommand.latin1()) != LSCP_OK) {                          if (::lscp_client_query(m_pClient, sCommand.toUtf8().constData())
787                                    != LSCP_OK) {
788                                  appendMessagesColor(QString("%1(%2): %3")                                  appendMessagesColor(QString("%1(%2): %3")
789                                          .arg(QFileInfo(sFilename).fileName()).arg(iLine)                                          .arg(QFileInfo(sFilename).fileName()).arg(iLine)
790                                          .arg(sCommand.simplifyWhiteSpace()), "#996633");                                          .arg(sCommand.simplified()), "#996633");
791                                  appendMessagesClient("lscp_client_query");                                  appendMessagesClient("lscp_client_query");
792                                  iErrors++;                                  iErrors++;
793                          }                          }
794          }                  }
795          // Try to make it snappy :)                  // Try to make it snappy :)
796          QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
797      }          }
798    
799      // Ok. we've read it.          // Ok. we've read it.
800      file.close();          file.close();
801    
802          // Now we'll try to create (update) the whole GUI session.          // Now we'll try to create (update) the whole GUI session.
803          updateSession();          updateSession();
# Line 800  bool MainForm::loadSessionFile ( const Q Line 806  bool MainForm::loadSessionFile ( const Q
806          QApplication::restoreOverrideCursor();          QApplication::restoreOverrideCursor();
807    
808          // Have we any errors?          // Have we any errors?
809          if (iErrors > 0)          if (iErrors > 0) {
810                  appendMessagesError(tr("Session loaded with errors\nfrom \"%1\".\n\nSorry.").arg(sFilename));                  appendMessagesError(
811                            tr("Session loaded with errors\nfrom \"%1\".\n\nSorry.")
812                            .arg(sFilename));
813            }
814    
815      // Save as default session directory.          // Save as default session directory.
816      if (m_pOptions)          if (m_pOptions)
817          m_pOptions->sSessionDir = QFileInfo(sFilename).dirPath(true);                  m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();
818          // We're not dirty anymore, if loaded without errors,          // We're not dirty anymore, if loaded without errors,
819          m_iDirtyCount = iErrors;          m_iDirtyCount = iErrors;
820      // Stabilize form...          // Stabilize form...
821      m_sFilename = sFilename;          m_sFilename = sFilename;
822      updateRecentFiles(sFilename);          updateRecentFiles(sFilename);
823      appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));          appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));
824    
825      // Make that an overall update.          // Make that an overall update.
826      stabilizeForm();          stabilizeForm();
827      return true;          return true;
828  }  }
829    
830    
# Line 831  bool MainForm::saveSessionFile ( const Q Line 840  bool MainForm::saveSessionFile ( const Q
840                  return false;                  return false;
841          }          }
842    
843      // Open and write into real file.          // Open and write into real file.
844      QFile file(sFilename);          QFile file(sFilename);
845      if (!file.open(IO_WriteOnly | IO_Truncate)) {          if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
846          appendMessagesError(tr("Could not open \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
847          return false;                          tr("Could not open \"%1\" session file.\n\nSorry.")
848      }                          .arg(sFilename));
849                    return false;
850            }
851    
852          // Tell the world we'll take some time...          // Tell the world we'll take some time...
853          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
854    
855      // Write the file.          // Write the file.
856      int  iErrors = 0;          int  iErrors = 0;
857      QTextStream ts(&file);          QTextStream ts(&file);
858      ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;          ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;
859      ts << "# " << tr("Version")          ts << "# " << tr("Version")
860         << ": " QSAMPLER_VERSION << endl;          << ": " QSAMPLER_VERSION << endl;
861      ts << "# " << tr("Build")          ts << "# " << tr("Build")
862         << ": " __DATE__ " " __TIME__ << endl;          << ": " __DATE__ " " __TIME__ << endl;
863      ts << "#"  << endl;          ts << "#"  << endl;
864      ts << "# " << tr("File")          ts << "# " << tr("File")
865         << ": " << QFileInfo(sFilename).fileName() << endl;          << ": " << QFileInfo(sFilename).fileName() << endl;
866      ts << "# " << tr("Date")          ts << "# " << tr("Date")
867         << ": " << QDate::currentDate().toString("MMM dd yyyy")          << ": " << QDate::currentDate().toString("MMM dd yyyy")
868         << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;          << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;
869      ts << "#"  << endl;          ts << "#"  << endl;
870      ts << endl;          ts << endl;
871    
872          // It is assumed that this new kind of device+session file          // It is assumed that this new kind of device+session file
873          // will be loaded from a complete initialized server...          // will be loaded from a complete initialized server...
# Line 878  bool MainForm::saveSessionFile ( const Q Line 889  bool MainForm::saveSessionFile ( const Q
889                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
890                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
891                                          ++deviceParam) {                                          ++deviceParam) {
892                          const qsamplerDeviceParam& param = deviceParam.data();                          const qsamplerDeviceParam& param = deviceParam.value();
893                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
894                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
895                  }                  }
896                  ts << endl;                  ts << endl;
897                  // Audio channel parameters...                  // Audio channel parameters...
898                  int iPort = 0;                  int iPort = 0;
899                  for (qsamplerDevicePort *pPort = device.ports().first();                  QListIterator<qsamplerDevicePort *> iter(device.ports());
900                                  pPort;                  while (iter.hasNext()) {
901                                          pPort = device.ports().next(), ++iPort) {                          qsamplerDevicePort *pPort = iter.next();
902                          qsamplerDeviceParamMap::ConstIterator portParam;                          qsamplerDeviceParamMap::ConstIterator portParam;
903                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
904                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
905                                                  ++portParam) {                                                  ++portParam) {
906                                  const qsamplerDeviceParam& param = portParam.data();                                  const qsamplerDeviceParam& param = portParam.value();
907                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
908                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice
909                                          << " " << iPort << " " << portParam.key()                                          << " " << iPort << " " << portParam.key()
910                                          << "='" << param.value << "'" << endl;                                          << "='" << param.value << "'" << endl;
911                          }                          }
912                            iPort++;
913                  }                  }
914                  // Audio device index/id mapping.                  // Audio device index/id mapping.
915                  audioDeviceMap[device.deviceID()] = iDevice;                  audioDeviceMap[device.deviceID()] = iDevice;
916                  // Try to keep it snappy :)                  // Try to keep it snappy :)
917                  QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
918          }          }
919    
920          // MIDI device mapping.          // MIDI device mapping.
# Line 919  bool MainForm::saveSessionFile ( const Q Line 931  bool MainForm::saveSessionFile ( const Q
931                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
932                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
933                                          ++deviceParam) {                                          ++deviceParam) {
934                          const qsamplerDeviceParam& param = deviceParam.data();                          const qsamplerDeviceParam& param = deviceParam.value();
935                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
936                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
937                  }                  }
938                  ts << endl;                  ts << endl;
939                  // MIDI port parameters...                  // MIDI port parameters...
940                  int iPort = 0;                  int iPort = 0;
941                  for (qsamplerDevicePort *pPort = device.ports().first();                  QListIterator<qsamplerDevicePort *> iter(device.ports());
942                                  pPort;                  while (iter.hasNext()) {
943                                          pPort = device.ports().next(), ++iPort) {                          qsamplerDevicePort *pPort = iter.next();
944                          qsamplerDeviceParamMap::ConstIterator portParam;                          qsamplerDeviceParamMap::ConstIterator portParam;
945                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
946                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
947                                                  ++portParam) {                                                  ++portParam) {
948                                  const qsamplerDeviceParam& param = portParam.data();                                  const qsamplerDeviceParam& param = portParam.value();
949                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
950                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice
951                                     << " " << iPort << " " << portParam.key()                                  << " " << iPort << " " << portParam.key()
952                                     << "='" << param.value << "'" << endl;                                  << "='" << param.value << "'" << endl;
953                          }                          }
954                            iPort++;
955                  }                  }
956                  // MIDI device index/id mapping.                  // MIDI device index/id mapping.
957                  midiDeviceMap[device.deviceID()] = iDevice;                  midiDeviceMap[device.deviceID()] = iDevice;
958                  // Try to keep it snappy :)                  // Try to keep it snappy :)
959                  QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
960          }          }
961          ts << endl;          ts << endl;
962    
# Line 1000  bool MainForm::saveSessionFile ( const Q Line 1013  bool MainForm::saveSessionFile ( const Q
1013                                  iErrors++;                                  iErrors++;
1014                          }                          }
1015                          // Try to keep it snappy :)                          // Try to keep it snappy :)
1016                          QApplication::processEvents(QEventLoop::ExcludeUserInput);                          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1017                  }                  }
1018                  ts << endl;                  ts << endl;
1019                  // Check for errors...                  // Check for errors...
# Line 1019  bool MainForm::saveSessionFile ( const Q Line 1032  bool MainForm::saveSessionFile ( const Q
1032  #endif  // CONFIG_MIDI_INSTRUMENT  #endif  // CONFIG_MIDI_INSTRUMENT
1033    
1034          // Sampler channel mapping.          // Sampler channel mapping.
1035      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
1036      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1037          ChannelStrip* pChannelStrip                  ChannelStrip* pChannelStrip
1038                          = static_cast<ChannelStrip *> (wlist.at(iChannel));                          = static_cast<ChannelStrip *> (wlist.at(iChannel));
1039          if (pChannelStrip) {                  if (pChannelStrip) {
1040              qsamplerChannel *pChannel = pChannelStrip->channel();                          qsamplerChannel *pChannel = pChannelStrip->channel();
1041              if (pChannel) {                          if (pChannel) {
1042                  ts << "# " << tr("Channel") << " " << iChannel << endl;                                  ts << "# " << tr("Channel") << " " << iChannel << endl;
1043                  ts << "ADD CHANNEL" << endl;                                  ts << "ADD CHANNEL" << endl;
1044                                  if (audioDeviceMap.isEmpty()) {                                  if (audioDeviceMap.isEmpty()) {
1045                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel
1046                                                  << " " << pChannel->audioDriver() << endl;                                                  << " " << pChannel->audioDriver() << endl;
# Line 1044  bool MainForm::saveSessionFile ( const Q Line 1057  bool MainForm::saveSessionFile ( const Q
1057                                  }                                  }
1058                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel
1059                                          << " " << pChannel->midiPort() << endl;                                          << " " << pChannel->midiPort() << endl;
1060                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";                                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";
1061                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)                                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
1062                      ts << "ALL";                                          ts << "ALL";
1063                  else                                  else
1064                      ts << pChannel->midiChannel();                                          ts << pChannel->midiChannel();
1065                  ts << endl;                                  ts << endl;
1066                  ts << "LOAD ENGINE " << pChannel->engineName() << " " << iChannel << endl;                                  ts << "LOAD ENGINE " << pChannel->engineName()
1067                                            << " " << iChannel << endl;
1068                                  if (pChannel->instrumentStatus() < 100) ts << "# ";                                  if (pChannel->instrumentStatus() < 100) ts << "# ";
1069                                  ts << "LOAD INSTRUMENT NON_MODAL '" << pChannel->instrumentFile() << "' "                                  ts << "LOAD INSTRUMENT NON_MODAL '"
1070                                            << pChannel->instrumentFile() << "' "
1071                                          << pChannel->instrumentNr() << " " << iChannel << endl;                                          << pChannel->instrumentNr() << " " << iChannel << endl;
1072                                  qsamplerChannelRoutingMap::ConstIterator audioRoute;                                  qsamplerChannelRoutingMap::ConstIterator audioRoute;
1073                                  for (audioRoute = pChannel->audioRouting().begin();                                  for (audioRoute = pChannel->audioRouting().begin();
# Line 1060  bool MainForm::saveSessionFile ( const Q Line 1075  bool MainForm::saveSessionFile ( const Q
1075                                                          ++audioRoute) {                                                          ++audioRoute) {
1076                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannel
1077                                                  << " " << audioRoute.key()                                                  << " " << audioRoute.key()
1078                                                  << " " << audioRoute.data() << endl;                                                  << " " << audioRoute.value() << endl;
1079                                  }                                  }
1080                                  ts << "SET CHANNEL VOLUME " << iChannel                                  ts << "SET CHANNEL VOLUME " << iChannel
1081                                          << " " << pChannel->volume() << endl;                                          << " " << pChannel->volume() << endl;
# Line 1110  bool MainForm::saveSessionFile ( const Q Line 1125  bool MainForm::saveSessionFile ( const Q
1125                                          }                                          }
1126                                  }                                  }
1127  #endif  #endif
1128                  ts << endl;                                  ts << endl;
1129              }                          }
1130          }                  }
1131          // Try to keep it snappy :)                  // Try to keep it snappy :)
1132          QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1133      }          }
1134    
1135  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
1136          ts << "# " << tr("Global volume level") << endl;          ts << "# " << tr("Global volume level") << endl;
# Line 1123  bool MainForm::saveSessionFile ( const Q Line 1138  bool MainForm::saveSessionFile ( const Q
1138          ts << endl;          ts << endl;
1139  #endif  #endif
1140    
1141      // Ok. we've wrote it.          // Ok. we've wrote it.
1142      file.close();          file.close();
1143    
1144          // We're fornerly done.          // We're fornerly done.
1145          QApplication::restoreOverrideCursor();          QApplication::restoreOverrideCursor();
1146    
1147      // Have we any errors?          // Have we any errors?
1148      if (iErrors > 0)          if (iErrors > 0) {
1149          appendMessagesError(tr("Some settings could not be saved\nto \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
1150                            tr("Some settings could not be saved\n"
1151      // Save as default session directory.                          "to \"%1\" session file.\n\nSorry.")
1152      if (m_pOptions)                          .arg(sFilename));
1153          m_pOptions->sSessionDir = QFileInfo(sFilename).dirPath(true);          }
1154      // We're not dirty anymore.  
1155      m_iDirtyCount = 0;          // Save as default session directory.
1156      // Stabilize form...          if (m_pOptions)
1157      m_sFilename = sFilename;                  m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();
1158      updateRecentFiles(sFilename);          // We're not dirty anymore.
1159      appendMessages(tr("Save session: \"%1\".").arg(sessionName(m_sFilename)));          m_iDirtyCount = 0;
1160      stabilizeForm();          // Stabilize form...
1161      return true;          m_sFilename = sFilename;
1162            updateRecentFiles(sFilename);
1163            appendMessages(tr("Save session: \"%1\".").arg(sessionName(m_sFilename)));
1164            stabilizeForm();
1165            return true;
1166  }  }
1167    
1168    
1169  // Session change receiver slot.  // Session change receiver slot.
1170  void MainForm::sessionDirty (void)  void MainForm::sessionDirty (void)
1171  {  {
1172      // Just mark the dirty form.          // Just mark the dirty form.
1173      m_iDirtyCount++;          m_iDirtyCount++;
1174      // and update the form status...          // and update the form status...
1175      stabilizeForm();          stabilizeForm();
1176  }  }
1177    
1178    
# Line 1163  void MainForm::sessionDirty (void) Line 1182  void MainForm::sessionDirty (void)
1182  // Create a new sampler session.  // Create a new sampler session.
1183  void MainForm::fileNew (void)  void MainForm::fileNew (void)
1184  {  {
1185      // Of course we'll start clean new.          // Of course we'll start clean new.
1186      newSession();          newSession();
1187  }  }
1188    
1189    
1190  // Open an existing sampler session.  // Open an existing sampler session.
1191  void MainForm::fileOpen (void)  void MainForm::fileOpen (void)
1192  {  {
1193      // Open it right away.          // Open it right away.
1194      openSession();          openSession();
1195  }  }
1196    
1197    
1198  // Open a recent file session.  // Open a recent file session.
1199  void MainForm::fileOpenRecent ( int iIndex )  void MainForm::fileOpenRecent (void)
1200  {  {
1201      // Check if we can safely close the current session...          // Retrive filename index from action data...
1202      if (m_pOptions && closeSession(true)) {          QAction *pAction = qobject_cast<QAction *> (sender());
1203          QString sFilename = m_pOptions->recentFiles[iIndex];          if (pAction && m_pOptions) {
1204          loadSessionFile(sFilename);                  int iIndex = pAction->data().toInt();
1205      }                  if (iIndex >= 0 && iIndex < m_pOptions->recentFiles.count()) {
1206                            QString sFilename = m_pOptions->recentFiles[iIndex];
1207                            // Check if we can safely close the current session...
1208                            if (!sFilename.isEmpty() && closeSession(true))
1209                                    loadSessionFile(sFilename);
1210                    }
1211            }
1212  }  }
1213    
1214    
1215  // Save current sampler session.  // Save current sampler session.
1216  void MainForm::fileSave (void)  void MainForm::fileSave (void)
1217  {  {
1218      // Save it right away.          // Save it right away.
1219      saveSession(false);          saveSession(false);
1220  }  }
1221    
1222    
1223  // Save current sampler session with another name.  // Save current sampler session with another name.
1224  void MainForm::fileSaveAs (void)  void MainForm::fileSaveAs (void)
1225  {  {
1226      // Save it right away, maybe with another name.          // Save it right away, maybe with another name.
1227      saveSession(true);          saveSession(true);
1228  }  }
1229    
1230    
1231  // Reset the sampler instance.  // Reset the sampler instance.
1232  void MainForm::fileReset (void)  void MainForm::fileReset (void)
1233  {  {
1234      if (m_pClient == NULL)          if (m_pClient == NULL)
1235          return;                  return;
1236    
1237      // Ask user whether he/she want's an internal sampler reset...          // Ask user whether he/she want's an internal sampler reset...
1238      if (QMessageBox::warning(this,          if (QMessageBox::warning(this,
1239                  QSAMPLER_TITLE ": " + tr("Warning"),                  QSAMPLER_TITLE ": " + tr("Warning"),
1240          tr("Resetting the sampler instance will close\n"                  tr("Resetting the sampler instance will close\n"
1241             "all device and channel configurations.\n\n"                  "all device and channel configurations.\n\n"
1242             "Please note that this operation may cause\n"                  "Please note that this operation may cause\n"
1243             "temporary MIDI and Audio disruption.\n\n"                  "temporary MIDI and Audio disruption.\n\n"
1244             "Do you want to reset the sampler engine now?"),                  "Do you want to reset the sampler engine now?"),
1245          tr("Reset"), tr("Cancel")) > 0)                  tr("Reset"), tr("Cancel")) > 0)
1246          return;                  return;
1247    
1248          // Trye closing the current session, first...          // Trye closing the current session, first...
1249          if (!closeSession(true))          if (!closeSession(true))
1250                  return;                  return;
1251    
1252      // Just do the reset, after closing down current session...          // Just do the reset, after closing down current session...
1253          // Do the actual sampler reset...          // Do the actual sampler reset...
1254          if (::lscp_reset_sampler(m_pClient) != LSCP_OK) {          if (::lscp_reset_sampler(m_pClient) != LSCP_OK) {
1255                  appendMessagesClient("lscp_reset_sampler");                  appendMessagesClient("lscp_reset_sampler");
# Line 1232  void MainForm::fileReset (void) Line 1257  void MainForm::fileReset (void)
1257                  return;                  return;
1258          }          }
1259    
1260      // Log this.          // Log this.
1261      appendMessages(tr("Sampler reset."));          appendMessages(tr("Sampler reset."));
1262    
1263          // Make it a new session...          // Make it a new session...
1264          newSession();          newSession();
# Line 1243  void MainForm::fileReset (void) Line 1268  void MainForm::fileReset (void)
1268  // Restart the client/server instance.  // Restart the client/server instance.
1269  void MainForm::fileRestart (void)  void MainForm::fileRestart (void)
1270  {  {
1271      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1272          return;                  return;
1273    
1274      bool bRestart = true;          bool bRestart = true;
1275    
1276      // Ask user whether he/she want's a complete restart...          // Ask user whether he/she want's a complete restart...
1277      // (if we're currently up and running)          // (if we're currently up and running)
1278      if (bRestart && m_pClient) {          if (bRestart && m_pClient) {
1279          bRestart = (QMessageBox::warning(this,                  bRestart = (QMessageBox::warning(this,
1280                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
1281              tr("New settings will be effective after\n"                          tr("New settings will be effective after\n"
1282                 "restarting the client/server connection.\n\n"                          "restarting the client/server connection.\n\n"
1283                 "Please note that this operation may cause\n"                          "Please note that this operation may cause\n"
1284                 "temporary MIDI and Audio disruption.\n\n"                          "temporary MIDI and Audio disruption.\n\n"
1285                 "Do you want to restart the connection now?"),                          "Do you want to restart the connection now?"),
1286              tr("Restart"), tr("Cancel")) == 0);                          tr("Restart"), tr("Cancel")) == 0);
1287      }          }
1288    
1289      // Are we still for it?          // Are we still for it?
1290      if (bRestart && closeSession(true)) {          if (bRestart && closeSession(true)) {
1291          // Stop server, it will force the client too.                  // Stop server, it will force the client too.
1292          stopServer();                  stopServer();
1293          // Reschedule a restart...                  // Reschedule a restart...
1294          startSchedule(m_pOptions->iStartDelay);                  startSchedule(m_pOptions->iStartDelay);
1295      }          }
1296  }  }
1297    
1298    
1299  // Exit application program.  // Exit application program.
1300  void MainForm::fileExit (void)  void MainForm::fileExit (void)
1301  {  {
1302      // Go for close the whole thing.          // Go for close the whole thing.
1303      close();          close();
1304  }  }
1305    
1306    
# Line 1285  void MainForm::fileExit (void) Line 1310  void MainForm::fileExit (void)
1310  // Add a new sampler channel.  // Add a new sampler channel.
1311  void MainForm::editAddChannel (void)  void MainForm::editAddChannel (void)
1312  {  {
1313      if (m_pClient == NULL)          if (m_pClient == NULL)
1314          return;                  return;
1315    
1316      // Just create the channel instance...          // Just create the channel instance...
1317      qsamplerChannel *pChannel = new qsamplerChannel();          qsamplerChannel *pChannel = new qsamplerChannel();
1318      if (pChannel == NULL)          if (pChannel == NULL)
1319          return;                  return;
1320    
1321      // Before we show it up, may be we'll          // Before we show it up, may be we'll
1322      // better ask for some initial values?          // better ask for some initial values?
1323      if (!pChannel->channelSetup(this)) {          if (!pChannel->channelSetup(this)) {
1324          delete pChannel;                  delete pChannel;
1325          return;                  return;
1326      }          }
1327    
1328      // And give it to the strip (will own the channel instance, if successful).          // And give it to the strip...
1329      if (!createChannelStrip(pChannel)) {          // (will own the channel instance, if successful).
1330          delete pChannel;          if (!createChannelStrip(pChannel)) {
1331          return;                  delete pChannel;
1332      }                  return;
1333            }
1334      // Make that an overall update.  
1335      m_iDirtyCount++;          // Do we auto-arrange?
1336      stabilizeForm();          if (m_pOptions && m_pOptions->bAutoArrange)
1337                    channelsArrange();
1338    
1339            // Make that an overall update.
1340            m_iDirtyCount++;
1341            stabilizeForm();
1342  }  }
1343    
1344    
1345  // Remove current sampler channel.  // Remove current sampler channel.
1346  void MainForm::editRemoveChannel (void)  void MainForm::editRemoveChannel (void)
1347  {  {
1348      if (m_pClient == NULL)          if (m_pClient == NULL)
1349          return;                  return;
1350    
1351            ChannelStrip* pChannelStrip = activeChannelStrip();
1352            if (pChannelStrip == NULL)
1353                    return;
1354    
1355      ChannelStrip* pChannelStrip = activeChannelStrip();          qsamplerChannel *pChannel = pChannelStrip->channel();
1356      if (pChannelStrip == NULL)          if (pChannel == NULL)
1357          return;                  return;
1358    
1359      qsamplerChannel *pChannel = pChannelStrip->channel();          // Prompt user if he/she's sure about this...
1360      if (pChannel == NULL)          if (m_pOptions && m_pOptions->bConfirmRemove) {
1361          return;                  if (QMessageBox::warning(this,
   
     // Prompt user if he/she's sure about this...  
     if (m_pOptions && m_pOptions->bConfirmRemove) {  
         if (QMessageBox::warning(this,  
1362                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
1363              tr("About to remove channel:\n\n"                          tr("About to remove channel:\n\n"
1364                 "%1\n\n"                          "%1\n\n"
1365                 "Are you sure?")                          "Are you sure?")
1366                 .arg(pChannelStrip->caption()),                          .arg(pChannelStrip->windowTitle()),
1367              tr("OK"), tr("Cancel")) > 0)                          tr("OK"), tr("Cancel")) > 0)
1368              return;                          return;
1369      }          }
1370    
1371      // Remove the existing sampler channel.          // Remove the existing sampler channel.
1372      if (!pChannel->removeChannel())          if (!pChannel->removeChannel())
1373          return;                  return;
1374    
1375      // Just delete the channel strip.          // Just delete the channel strip.
1376      delete pChannelStrip;          delete pChannelStrip;
1377    
1378      // Do we auto-arrange?          // Do we auto-arrange?
1379      if (m_pOptions && m_pOptions->bAutoArrange)          if (m_pOptions && m_pOptions->bAutoArrange)
1380          channelsArrange();                  channelsArrange();
1381    
1382      // We'll be dirty, for sure...          // We'll be dirty, for sure...
1383      m_iDirtyCount++;          m_iDirtyCount++;
1384      stabilizeForm();          stabilizeForm();
1385  }  }
1386    
1387    
1388  // Setup current sampler channel.  // Setup current sampler channel.
1389  void MainForm::editSetupChannel (void)  void MainForm::editSetupChannel (void)
1390  {  {
1391      if (m_pClient == NULL)          if (m_pClient == NULL)
1392          return;                  return;
1393    
1394      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1395      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1396          return;                  return;
1397    
1398      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1399      pChannelStrip->channelSetup();          pChannelStrip->channelSetup();
1400  }  }
1401    
1402    
1403  // Edit current sampler channel.  // Edit current sampler channel.
1404  void MainForm::editEditChannel (void)  void MainForm::editEditChannel (void)
1405  {  {
1406      if (m_pClient == NULL)          if (m_pClient == NULL)
1407          return;                  return;
1408    
1409      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1410      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1411          return;                  return;
1412    
1413      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1414      pChannelStrip->channelEdit();          pChannelStrip->channelEdit();
1415  }  }
1416    
1417    
1418  // Reset current sampler channel.  // Reset current sampler channel.
1419  void MainForm::editResetChannel (void)  void MainForm::editResetChannel (void)
1420  {  {
1421      if (m_pClient == NULL)          if (m_pClient == NULL)
1422          return;                  return;
1423    
1424      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1425      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1426          return;                  return;
1427    
1428      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1429      pChannelStrip->channelReset();          pChannelStrip->channelReset();
1430  }  }
1431    
1432    
# Line 1425  void MainForm::editResetAllChannels (voi Line 1455  void MainForm::editResetAllChannels (voi
1455  // Show/hide the main program window menubar.  // Show/hide the main program window menubar.
1456  void MainForm::viewMenubar ( bool bOn )  void MainForm::viewMenubar ( bool bOn )
1457  {  {
1458      if (bOn)          if (bOn)
1459          ui.MenuBar->show();                  m_ui.MenuBar->show();
1460      else          else
1461          ui.MenuBar->hide();                  m_ui.MenuBar->hide();
1462  }  }
1463    
1464    
1465  // Show/hide the main program window toolbar.  // Show/hide the main program window toolbar.
1466  void MainForm::viewToolbar ( bool bOn )  void MainForm::viewToolbar ( bool bOn )
1467  {  {
1468      if (bOn) {          if (bOn) {
1469          ui.fileToolbar->show();                  m_ui.fileToolbar->show();
1470          ui.editToolbar->show();                  m_ui.editToolbar->show();
1471          ui.channelsToolbar->show();                  m_ui.channelsToolbar->show();
1472      } else {          } else {
1473          ui.fileToolbar->hide();                  m_ui.fileToolbar->hide();
1474          ui.editToolbar->hide();                  m_ui.editToolbar->hide();
1475          ui.channelsToolbar->hide();                  m_ui.channelsToolbar->hide();
1476      }          }
1477  }  }
1478    
1479    
1480  // Show/hide the main program window statusbar.  // Show/hide the main program window statusbar.
1481  void MainForm::viewStatusbar ( bool bOn )  void MainForm::viewStatusbar ( bool bOn )
1482  {  {
1483      if (bOn)          if (bOn)
1484          statusBar()->show();                  statusBar()->show();
1485      else          else
1486          statusBar()->hide();                  statusBar()->hide();
1487  }  }
1488    
1489    
1490  // Show/hide the messages window logger.  // Show/hide the messages window logger.
1491  void MainForm::viewMessages ( bool bOn )  void MainForm::viewMessages ( bool bOn )
1492  {  {
1493      if (bOn)          if (bOn)
1494          m_pMessages->show();                  m_pMessages->show();
1495      else          else
1496          m_pMessages->hide();                  m_pMessages->hide();
1497  }  }
1498    
1499    
# Line 1480  void MainForm::viewInstruments (void) Line 1510  void MainForm::viewInstruments (void)
1510                  } else {                  } else {
1511                          m_pInstrumentListForm->show();                          m_pInstrumentListForm->show();
1512                          m_pInstrumentListForm->raise();                          m_pInstrumentListForm->raise();
1513                          m_pInstrumentListForm->setActiveWindow();                          m_pInstrumentListForm->activateWindow();
1514                  }                  }
1515          }          }
1516  }  }
# Line 1499  void MainForm::viewDevices (void) Line 1529  void MainForm::viewDevices (void)
1529                  } else {                  } else {
1530                          m_pDeviceForm->show();                          m_pDeviceForm->show();
1531                          m_pDeviceForm->raise();                          m_pDeviceForm->raise();
1532                          m_pDeviceForm->setActiveWindow();                          m_pDeviceForm->activateWindow();
1533                  }                  }
1534          }          }
1535  }  }
# Line 1508  void MainForm::viewDevices (void) Line 1538  void MainForm::viewDevices (void)
1538  // Show options dialog.  // Show options dialog.
1539  void MainForm::viewOptions (void)  void MainForm::viewOptions (void)
1540  {  {
1541      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1542          return;                  return;
1543    
1544      OptionsForm* pOptionsForm = new OptionsForm(this);          OptionsForm* pOptionsForm = new OptionsForm(this);
1545      if (pOptionsForm) {          if (pOptionsForm) {
1546          // Check out some initial nullities(tm)...                  // Check out some initial nullities(tm)...
1547          ChannelStrip* pChannelStrip = activeChannelStrip();                  ChannelStrip* pChannelStrip = activeChannelStrip();
1548          if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)
1549              m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();
1550          if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)
1551              m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
1552          // To track down deferred or immediate changes.                  // To track down deferred or immediate changes.
1553          QString sOldServerHost      = m_pOptions->sServerHost;                  QString sOldServerHost      = m_pOptions->sServerHost;
1554          int     iOldServerPort      = m_pOptions->iServerPort;                  int     iOldServerPort      = m_pOptions->iServerPort;
1555          int     iOldServerTimeout   = m_pOptions->iServerTimeout;                  int     iOldServerTimeout   = m_pOptions->iServerTimeout;
1556          bool    bOldServerStart     = m_pOptions->bServerStart;                  bool    bOldServerStart     = m_pOptions->bServerStart;
1557          QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;                  QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;
1558          QString sOldDisplayFont     = m_pOptions->sDisplayFont;                  QString sOldDisplayFont     = m_pOptions->sDisplayFont;
1559          bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;                  bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;
1560          int     iOldMaxVolume       = m_pOptions->iMaxVolume;                  int     iOldMaxVolume       = m_pOptions->iMaxVolume;
1561          QString sOldMessagesFont    = m_pOptions->sMessagesFont;                  QString sOldMessagesFont    = m_pOptions->sMessagesFont;
1562          bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;                  bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;
1563          bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;                  bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;
1564          int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;                  int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;
1565          int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;                  int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;
1566          bool    bOldCompletePath    = m_pOptions->bCompletePath;                  bool    bOldCompletePath    = m_pOptions->bCompletePath;
1567          bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;                  bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;
1568          int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;                  int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;
1569          // Load the current setup settings.                  // Load the current setup settings.
1570          pOptionsForm->setup(m_pOptions);                  pOptionsForm->setup(m_pOptions);
1571          // Show the setup dialog...                  // Show the setup dialog...
1572          if (pOptionsForm->exec()) {                  if (pOptionsForm->exec()) {
1573              // Warn if something will be only effective on next run.                          // Warn if something will be only effective on next run.
1574              if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1575                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||
1576                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||                                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||
1577                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {                                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {
1578                  QMessageBox::information(this,                                  QMessageBox::information(this,
1579                                          QSAMPLER_TITLE ": " + tr("Information"),                                          QSAMPLER_TITLE ": " + tr("Information"),
1580                      tr("Some settings may be only effective\n"                                          tr("Some settings may be only effective\n"
1581                         "next time you start this program."), tr("OK"));                                          "next time you start this program."), tr("OK"));
1582                  updateMessagesCapture();                                  updateMessagesCapture();
1583              }                          }
1584              // Check wheather something immediate has changed.                          // Check wheather something immediate has changed.
1585              if (( bOldCompletePath && !m_pOptions->bCompletePath) ||                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||
1586                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||
1587                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
1588                  updateRecentFilesMenu();                                  updateRecentFilesMenu();
1589              if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||                          if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||
1590                  (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))                                  (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))
1591                  updateInstrumentNames();                                  updateInstrumentNames();
1592              if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||                          if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||
1593                  (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))                                  (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))
1594                  updateDisplayEffect();                                  updateDisplayEffect();
1595              if (sOldDisplayFont != m_pOptions->sDisplayFont)                          if (sOldDisplayFont != m_pOptions->sDisplayFont)
1596                  updateDisplayFont();                                  updateDisplayFont();
1597              if (iOldMaxVolume != m_pOptions->iMaxVolume)                          if (iOldMaxVolume != m_pOptions->iMaxVolume)
1598                  updateMaxVolume();                                  updateMaxVolume();
1599              if (sOldMessagesFont != m_pOptions->sMessagesFont)                          if (sOldMessagesFont != m_pOptions->sMessagesFont)
1600                  updateMessagesFont();                                  updateMessagesFont();
1601              if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||                          if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||
1602                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||                                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||
1603                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))                                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))
1604                  updateMessagesLimit();                                  updateMessagesLimit();
1605              // And now the main thing, whether we'll do client/server recycling?                          // And now the main thing, whether we'll do client/server recycling?
1606              if ((sOldServerHost != m_pOptions->sServerHost) ||                          if ((sOldServerHost != m_pOptions->sServerHost) ||
1607                  (iOldServerPort != m_pOptions->iServerPort) ||                                  (iOldServerPort != m_pOptions->iServerPort) ||
1608                  (iOldServerTimeout != m_pOptions->iServerTimeout) ||                                  (iOldServerTimeout != m_pOptions->iServerTimeout) ||
1609                  ( bOldServerStart && !m_pOptions->bServerStart) ||                                  ( bOldServerStart && !m_pOptions->bServerStart) ||
1610                  (!bOldServerStart &&  m_pOptions->bServerStart) ||                                  (!bOldServerStart &&  m_pOptions->bServerStart) ||
1611                  (sOldServerCmdLine != m_pOptions->sServerCmdLine && m_pOptions->bServerStart))                                  (sOldServerCmdLine != m_pOptions->sServerCmdLine
1612                  fileRestart();                                  && m_pOptions->bServerStart))
1613          }                                  fileRestart();
1614          // Done.                  }
1615          delete pOptionsForm;                  // Done.
1616      }                  delete pOptionsForm;
1617            }
1618    
1619      // This makes it.          // This makes it.
1620      stabilizeForm();          stabilizeForm();
1621  }  }
1622    
1623    
# Line 1596  void MainForm::viewOptions (void) Line 1627  void MainForm::viewOptions (void)
1627  // Arrange channel strips.  // Arrange channel strips.
1628  void MainForm::channelsArrange (void)  void MainForm::channelsArrange (void)
1629  {  {
1630      // Full width vertical tiling          // Full width vertical tiling
1631      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
1632      if (wlist.isEmpty())          if (wlist.isEmpty())
1633          return;                  return;
1634    
1635      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
1636      int y = 0;          int y = 0;
1637      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1638          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
1639      /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {          /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {
1640              // Prevent flicker...                          // Prevent flicker...
1641              pChannelStrip->hide();                          pChannelStrip->hide();
1642              pChannelStrip->showNormal();                          pChannelStrip->showNormal();
1643          }   */                  }   */
1644          pChannelStrip->adjustSize();                  pChannelStrip->adjustSize();
1645          int iWidth  = m_pWorkspace->width();                  int iWidth  = m_pWorkspace->width();
1646          if (iWidth < pChannelStrip->width())                  if (iWidth < pChannelStrip->width())
1647              iWidth = pChannelStrip->width();                          iWidth = pChannelStrip->width();
1648      //  int iHeight = pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();          //  int iHeight = pChannelStrip->height()
1649          int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();          //              + pChannelStrip->parentWidget()->baseSize().height();
1650          pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);                  int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();
1651          y += iHeight;                  pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);
1652      }                  y += iHeight;
1653      m_pWorkspace->setUpdatesEnabled(true);          }
1654            m_pWorkspace->setUpdatesEnabled(true);
1655    
1656      stabilizeForm();          stabilizeForm();
1657  }  }
1658    
1659    
1660  // Auto-arrange channel strips.  // Auto-arrange channel strips.
1661  void MainForm::channelsAutoArrange ( bool bOn )  void MainForm::channelsAutoArrange ( bool bOn )
1662  {  {
1663      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1664          return;                  return;
1665    
1666      // Toggle the auto-arrange flag.          // Toggle the auto-arrange flag.
1667      m_pOptions->bAutoArrange = bOn;          m_pOptions->bAutoArrange = bOn;
1668    
1669      // If on, update whole workspace...          // If on, update whole workspace...
1670      if (m_pOptions->bAutoArrange)          if (m_pOptions->bAutoArrange)
1671          channelsArrange();                  channelsArrange();
1672  }  }
1673    
1674    
# Line 1646  void MainForm::channelsAutoArrange ( boo Line 1678  void MainForm::channelsAutoArrange ( boo
1678  // Show information about the Qt toolkit.  // Show information about the Qt toolkit.
1679  void MainForm::helpAboutQt (void)  void MainForm::helpAboutQt (void)
1680  {  {
1681      QMessageBox::aboutQt(this);          QMessageBox::aboutQt(this);
1682  }  }
1683    
1684    
1685  // Show information about application program.  // Show information about application program.
1686  void MainForm::helpAbout (void)  void MainForm::helpAbout (void)
1687  {  {
1688      // Stuff the about box text...          // Stuff the about box text...
1689      QString sText = "<p>\n";          QString sText = "<p>\n";
1690      sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";          sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";
1691      sText += "<br />\n";          sText += "<br />\n";
1692      sText += tr("Version") + ": <b>" QSAMPLER_VERSION "</b><br />\n";          sText += tr("Version") + ": <b>" QSAMPLER_VERSION "</b><br />\n";
1693      sText += "<small>" + tr("Build") + ": " __DATE__ " " __TIME__ "</small><br />\n";          sText += "<small>" + tr("Build") + ": " __DATE__ " " __TIME__ "</small><br />\n";
1694  #ifdef CONFIG_DEBUG  #ifdef CONFIG_DEBUG
1695      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1696      sText += tr("Debugging option enabled.");          sText += tr("Debugging option enabled.");
1697      sText += "</font></small><br />";          sText += "</font></small><br />";
1698  #endif  #endif
1699  #ifndef CONFIG_LIBGIG  #ifndef CONFIG_LIBGIG
1700      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1701      sText += tr("GIG (libgig) file support disabled.");          sText += tr("GIG (libgig) file support disabled.");
1702      sText += "</font></small><br />";          sText += "</font></small><br />";
1703  #endif  #endif
1704  #ifndef CONFIG_INSTRUMENT_NAME  #ifndef CONFIG_INSTRUMENT_NAME
1705      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1706      sText += tr("LSCP (liblscp) instrument_name support disabled.");          sText += tr("LSCP (liblscp) instrument_name support disabled.");
1707      sText += "</font></small><br />";          sText += "</font></small><br />";
1708  #endif  #endif
1709  #ifndef CONFIG_MUTE_SOLO  #ifndef CONFIG_MUTE_SOLO
1710      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1711      sText += tr("Sampler channel Mute/Solo support disabled.");          sText += tr("Sampler channel Mute/Solo support disabled.");
1712      sText += "</font></small><br />";          sText += "</font></small><br />";
1713  #endif  #endif
1714  #ifndef CONFIG_AUDIO_ROUTING  #ifndef CONFIG_AUDIO_ROUTING
1715      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1716      sText += tr("LSCP (liblscp) audio_routing support disabled.");          sText += tr("LSCP (liblscp) audio_routing support disabled.");
1717      sText += "</font></small><br />";          sText += "</font></small><br />";
1718  #endif  #endif
1719  #ifndef CONFIG_FXSEND  #ifndef CONFIG_FXSEND
1720      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1721      sText += tr("Sampler channel Effect Sends support disabled.");          sText += tr("Sampler channel Effect Sends support disabled.");
1722      sText += "</font></small><br />";          sText += "</font></small><br />";
1723  #endif  #endif
1724  #ifndef CONFIG_VOLUME  #ifndef CONFIG_VOLUME
1725      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1726      sText += tr("Global volume support disabled.");          sText += tr("Global volume support disabled.");
1727      sText += "</font></small><br />";          sText += "</font></small><br />";
1728  #endif  #endif
1729  #ifndef CONFIG_MIDI_INSTRUMENT  #ifndef CONFIG_MIDI_INSTRUMENT
1730      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1731      sText += tr("MIDI instrument mapping support disabled.");          sText += tr("MIDI instrument mapping support disabled.");
1732      sText += "</font></small><br />";          sText += "</font></small><br />";
1733  #endif  #endif
1734  #ifndef CONFIG_EDIT_INSTRUMENT  #ifndef CONFIG_EDIT_INSTRUMENT
1735      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1736      sText += tr("Instrument editing support disabled.");          sText += tr("Instrument editing support disabled.");
1737      sText += "</font></small><br />";          sText += "</font></small><br />";
1738  #endif  #endif
1739      sText += "<br />\n";          sText += "<br />\n";
1740      sText += tr("Using") + ": ";          sText += tr("Using") + ": ";
1741      sText += ::lscp_client_package();          sText += ::lscp_client_package();
1742      sText += " ";          sText += " ";
1743      sText += ::lscp_client_version();          sText += ::lscp_client_version();
1744  #ifdef CONFIG_LIBGIG  #ifdef CONFIG_LIBGIG
1745      sText += ", ";          sText += ", ";
1746      sText += gig::libraryName().c_str();          sText += gig::libraryName().c_str();
1747      sText += " ";          sText += " ";
1748      sText += gig::libraryVersion().c_str();          sText += gig::libraryVersion().c_str();
1749  #endif  #endif
1750      sText += "<br />\n";          sText += "<br />\n";
1751      sText += "<br />\n";          sText += "<br />\n";
1752      sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";          sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";
1753      sText += "<br />\n";          sText += "<br />\n";
1754      sText += "<small>";          sText += "<small>";
1755      sText += QSAMPLER_COPYRIGHT "<br />\n";          sText += QSAMPLER_COPYRIGHT "<br />\n";
1756      sText += QSAMPLER_COPYRIGHT2 "<br />\n";          sText += QSAMPLER_COPYRIGHT2 "<br />\n";
1757      sText += "<br />\n";          sText += "<br />\n";
1758      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";
1759      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.");
1760      sText += "</small>";          sText += "</small>";
1761      sText += "</p>\n";          sText += "</p>\n";
1762    
1763      QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);          QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);
1764  }  }
1765    
1766    
# Line 1737  void MainForm::helpAbout (void) Line 1769  void MainForm::helpAbout (void)
1769    
1770  void MainForm::stabilizeForm (void)  void MainForm::stabilizeForm (void)
1771  {  {
1772      // Update the main application caption...          // Update the main application caption...
1773      QString sSessionName = sessionName(m_sFilename);          QString sSessionName = sessionName(m_sFilename);
1774      if (m_iDirtyCount > 0)          if (m_iDirtyCount > 0)
1775          sSessionName += " *";                  sSessionName += " *";
1776      setCaption(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));
1777    
1778      // Update the main menu state...          // Update the main menu state...
1779      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1780      bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);          bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);
1781      bool bHasChannel = (bHasClient && pChannelStrip != NULL);          bool bHasChannel = (bHasClient && pChannelStrip != NULL);
1782      ui.fileNewAction->setEnabled(bHasClient);          m_ui.fileNewAction->setEnabled(bHasClient);
1783      ui.fileOpenAction->setEnabled(bHasClient);          m_ui.fileOpenAction->setEnabled(bHasClient);
1784      ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
1785      ui.fileSaveAsAction->setEnabled(bHasClient);          m_ui.fileSaveAsAction->setEnabled(bHasClient);
1786      ui.fileResetAction->setEnabled(bHasClient);          m_ui.fileResetAction->setEnabled(bHasClient);
1787      ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);          m_ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);
1788      ui.editAddChannelAction->setEnabled(bHasClient);          m_ui.editAddChannelAction->setEnabled(bHasClient);
1789      ui.editRemoveChannelAction->setEnabled(bHasChannel);          m_ui.editRemoveChannelAction->setEnabled(bHasChannel);
1790      ui.editSetupChannelAction->setEnabled(bHasChannel);          m_ui.editSetupChannelAction->setEnabled(bHasChannel);
1791  #ifdef CONFIG_EDIT_INSTRUMENT  #ifdef CONFIG_EDIT_INSTRUMENT
1792      ui.editEditChannelAction->setEnabled(bHasChannel);          m_ui.editEditChannelAction->setEnabled(bHasChannel);
1793  #else  #else
1794      ui.editEditChannelAction->setEnabled(false);          m_ui.editEditChannelAction->setEnabled(false);
1795  #endif  #endif
1796      ui.editResetChannelAction->setEnabled(bHasChannel);          m_ui.editResetChannelAction->setEnabled(bHasChannel);
1797      ui.editResetAllChannelsAction->setEnabled(bHasChannel);          m_ui.editResetAllChannelsAction->setEnabled(bHasChannel);
1798      ui.viewMessagesAction->setOn(m_pMessages && m_pMessages->isVisible());          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());
1799  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
1800          ui.viewInstrumentsAction->setOn(m_pInstrumentListForm          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm
1801                  && m_pInstrumentListForm->isVisible());                  && m_pInstrumentListForm->isVisible());
1802          ui.viewInstrumentsAction->setEnabled(bHasClient);          m_ui.viewInstrumentsAction->setEnabled(bHasClient);
1803  #else  #else
1804          ui.viewInstrumentsAction->setEnabled(false);          m_ui.viewInstrumentsAction->setEnabled(false);
1805  #endif  #endif
1806          ui.viewDevicesAction->setOn(m_pDeviceForm          m_ui.viewDevicesAction->setChecked(m_pDeviceForm
1807                  && m_pDeviceForm->isVisible());                  && m_pDeviceForm->isVisible());
1808      ui.viewDevicesAction->setEnabled(bHasClient);          m_ui.viewDevicesAction->setEnabled(bHasClient);
1809      ui.channelsArrangeAction->setEnabled(bHasChannel);          m_ui.channelsArrangeAction->setEnabled(bHasChannel);
1810    
1811  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
1812          // Toolbar widgets are also affected...          // Toolbar widgets are also affected...
1813      m_pVolumeSlider->setEnabled(bHasClient);          m_pVolumeSlider->setEnabled(bHasClient);
1814      m_pVolumeSpinBox->setEnabled(bHasClient);          m_pVolumeSpinBox->setEnabled(bHasClient);
1815  #endif  #endif
1816    
1817      // Client/Server status...          // Client/Server status...
1818      if (bHasClient) {          if (bHasClient) {
1819          m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));                  m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));
1820          m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost + ":" + QString::number(m_pOptions->iServerPort));                  m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost
1821      } else {                          + ':' + QString::number(m_pOptions->iServerPort));
1822          m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();          } else {
1823          m_statusItem[QSAMPLER_STATUS_SERVER]->clear();                  m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();
1824      }                  m_statusItem[QSAMPLER_STATUS_SERVER]->clear();
1825      // Channel status...          }
1826      if (bHasChannel)          // Channel status...
1827          m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->caption());          if (bHasChannel)
1828      else                  m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->windowTitle());
1829          m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();          else
1830      // Session status...                  m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();
1831      if (m_iDirtyCount > 0)          // Session status...
1832          m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));          if (m_iDirtyCount > 0)
1833      else                  m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));
1834          m_statusItem[QSAMPLER_STATUS_SESSION]->clear();          else
1835                    m_statusItem[QSAMPLER_STATUS_SESSION]->clear();
1836    
1837      // Recent files menu.          // Recent files menu.
1838      m_pRecentFilesMenu->setEnabled(bHasClient && m_pOptions->recentFiles.count() > 0);          m_ui.fileOpenRecentMenu->setEnabled(m_pOptions->recentFiles.count() > 0);
1839  }  }
1840    
1841    
# Line 1842  void MainForm::volumeChanged ( int iVolu Line 1875  void MainForm::volumeChanged ( int iVolu
1875  void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)  void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)
1876  {  {
1877          // Add this strip to the changed list...          // Add this strip to the changed list...
1878          if (m_changedStrips.containsRef(pChannelStrip) == 0) {          if (!m_changedStrips.contains(pChannelStrip)) {
1879                  m_changedStrips.append(pChannelStrip);                  m_changedStrips.append(pChannelStrip);
1880                  pChannelStrip->resetErrorCount();                  pChannelStrip->resetErrorCount();
1881          }          }
1882    
1883      // Just mark the dirty form.          // Just mark the dirty form.
1884      m_iDirtyCount++;          m_iDirtyCount++;
1885      // and update the form status...          // and update the form status...
1886      stabilizeForm();          stabilizeForm();
1887  }  }
1888    
1889    
# Line 1870  void MainForm::updateSession (void) Line 1903  void MainForm::updateSession (void)
1903          if (iMaps < 0)          if (iMaps < 0)
1904                  appendMessagesClient("lscp_get_midi_instrument_maps");                  appendMessagesClient("lscp_get_midi_instrument_maps");
1905          else if (iMaps < 1) {          else if (iMaps < 1) {
1906                  ::lscp_add_midi_instrument_map(m_pClient, tr("Chromatic").latin1());                  ::lscp_add_midi_instrument_map(m_pClient,
1907                  ::lscp_add_midi_instrument_map(m_pClient, tr("Drum Kits").latin1());                          tr("Chromatic").toUtf8().constData());
1908                    ::lscp_add_midi_instrument_map(m_pClient,
1909                            tr("Drum Kits").toUtf8().constData());
1910          }          }
1911  #endif  #endif
1912    
# Line 1880  void MainForm::updateSession (void) Line 1915  void MainForm::updateSession (void)
1915          if (piChannelIDs == NULL) {          if (piChannelIDs == NULL) {
1916                  if (::lscp_client_get_errno(m_pClient)) {                  if (::lscp_client_get_errno(m_pClient)) {
1917                          appendMessagesClient("lscp_list_channels");                          appendMessagesClient("lscp_list_channels");
1918                          appendMessagesError(tr("Could not get current list of channels.\n\nSorry."));                          appendMessagesError(
1919                                    tr("Could not get current list of channels.\n\nSorry."));
1920                  }                  }
1921          } else {          } else {
1922                  // Try to (re)create each channel.                  // Try to (re)create each channel.
# Line 1893  void MainForm::updateSession (void) Line 1929  void MainForm::updateSession (void)
1929                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
1930          }          }
1931    
1932      // Do we auto-arrange?          // Do we auto-arrange?
1933      if (m_pOptions && m_pOptions->bAutoArrange)          if (m_pOptions && m_pOptions->bAutoArrange)
1934          channelsArrange();                  channelsArrange();
1935    
1936          // Remember to refresh devices and instruments...          // Remember to refresh devices and instruments...
1937          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
1938              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
1939          if (m_pDeviceForm)          if (m_pDeviceForm)
1940              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
1941  }  }
1942    
1943    
1944  // Update the recent files list and menu.  // Update the recent files list and menu.
1945  void MainForm::updateRecentFiles ( const QString& sFilename )  void MainForm::updateRecentFiles ( const QString& sFilename )
1946  {  {
1947      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1948          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);  
1949    
1950      // May update the menu.          // Remove from list if already there (avoid duplicates)
1951      updateRecentFilesMenu();          int iIndex = m_pOptions->recentFiles.indexOf(sFilename);
1952            if (iIndex >= 0)
1953                    m_pOptions->recentFiles.removeAt(iIndex);
1954            // Put it to front...
1955            m_pOptions->recentFiles.push_front(sFilename);
1956  }  }
1957    
1958    
1959  // Update the recent files list and menu.  // Update the recent files list and menu.
1960  void MainForm::updateRecentFilesMenu (void)  void MainForm::updateRecentFilesMenu (void)
1961  {  {
1962      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1963          return;                  return;
1964    
1965      // Time to keep the list under limits.          // Time to keep the list under limits.
1966      int iRecentFiles = m_pOptions->recentFiles.count();          int iRecentFiles = m_pOptions->recentFiles.count();
1967      while (iRecentFiles > m_pOptions->iMaxRecentFiles) {          while (iRecentFiles > m_pOptions->iMaxRecentFiles) {
1968          m_pOptions->recentFiles.pop_back();                  m_pOptions->recentFiles.pop_back();
1969          iRecentFiles--;                  iRecentFiles--;
1970      }          }
1971    
1972      // rebuild the recent files menu...          // Rebuild the recent files menu...
1973      m_pRecentFilesMenu->clear();          m_ui.fileOpenRecentMenu->clear();
1974      for (int i = 0; i < iRecentFiles; i++) {          for (int i = 0; i < iRecentFiles; i++) {
1975          const QString& sFilename = m_pOptions->recentFiles[i];                  const QString& sFilename = m_pOptions->recentFiles[i];
1976          if (QFileInfo(sFilename).exists()) {                  if (QFileInfo(sFilename).exists()) {
1977              m_pRecentFilesMenu->insertItem(QString("&%1 %2")                          QAction *pAction = m_ui.fileOpenRecentMenu->addAction(
1978                  .arg(i + 1).arg(sessionName(sFilename)),                                  QString("&%1 %2").arg(i + 1).arg(sessionName(sFilename)),
1979                  this, SLOT(fileOpenRecent(int)), 0, i);                                  this, SLOT(fileOpenRecent()));
1980          }                          pAction->setData(i);
1981      }                  }
1982            }
1983  }  }
1984    
1985    
1986  // Force update of the channels instrument names mode.  // Force update of the channels instrument names mode.
1987  void MainForm::updateInstrumentNames (void)  void MainForm::updateInstrumentNames (void)
1988  {  {
1989      // Full channel list update...          // Full channel list update...
1990      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
1991      if (wlist.isEmpty())          if (wlist.isEmpty())
1992          return;                  return;
1993    
1994      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
1995      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1996          ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);                  ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);
1997          if (pChannelStrip)                  if (pChannelStrip)
1998              pChannelStrip->updateInstrumentName(true);                          pChannelStrip->updateInstrumentName(true);
1999      }          }
2000      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2001  }  }
2002    
2003    
2004  // Force update of the channels display font.  // Force update of the channels display font.
2005  void MainForm::updateDisplayFont (void)  void MainForm::updateDisplayFont (void)
2006  {  {
2007      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2008          return;                  return;
2009    
2010            // Check if display font is legal.
2011            if (m_pOptions->sDisplayFont.isEmpty())
2012                    return;
2013            // Realize it.
2014            QFont font;
2015            if (!font.fromString(m_pOptions->sDisplayFont))
2016                    return;
2017    
2018            // Full channel list update...
2019            QWidgetList wlist = m_pWorkspace->windowList();
2020            if (wlist.isEmpty())
2021                    return;
2022    
2023      // Check if display font is legal.          m_pWorkspace->setUpdatesEnabled(false);
2024      if (m_pOptions->sDisplayFont.isEmpty())          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2025          return;                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2026      // Realize it.                  if (pChannelStrip)
2027      QFont font;                          pChannelStrip->setDisplayFont(font);
2028      if (!font.fromString(m_pOptions->sDisplayFont))          }
2029          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);  
2030  }  }
2031    
2032    
2033  // Update channel strips background effect.  // Update channel strips background effect.
2034  void MainForm::updateDisplayEffect (void)  void MainForm::updateDisplayEffect (void)
2035  {  {
2036     QPixmap pm;          // Full channel list update...
2037      if (m_pOptions->bDisplayEffect)          QWidgetList wlist = m_pWorkspace->windowList();
2038          pm = QPixmap(":/qsampler/pixmaps/displaybg1.png");          if (wlist.isEmpty())
2039                    return;
2040      // Full channel list update...  
2041      QWidgetList wlist = m_pWorkspace->windowList();          m_pWorkspace->setUpdatesEnabled(false);
2042      if (wlist.isEmpty())          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2043          return;                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2044                    if (pChannelStrip)
2045      m_pWorkspace->setUpdatesEnabled(false);                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2046      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          }
2047          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);          m_pWorkspace->setUpdatesEnabled(true);
         if (pChannelStrip)  
             pChannelStrip->setDisplayBackground(pm);  
     }  
     m_pWorkspace->setUpdatesEnabled(true);  
2048  }  }
2049    
2050    
2051  // Force update of the channels maximum volume setting.  // Force update of the channels maximum volume setting.
2052  void MainForm::updateMaxVolume (void)  void MainForm::updateMaxVolume (void)
2053  {  {
2054      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2055          return;                  return;
2056    
2057  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2058          m_iVolumeChanging++;          m_iVolumeChanging++;
2059          m_pVolumeSlider->setMaxValue(m_pOptions->iMaxVolume);          m_pVolumeSlider->setMaximum(m_pOptions->iMaxVolume);
2060          m_pVolumeSpinBox->setMaxValue(m_pOptions->iMaxVolume);          m_pVolumeSpinBox->setMaximum(m_pOptions->iMaxVolume);
2061          m_iVolumeChanging--;          m_iVolumeChanging--;
2062  #endif  #endif
2063    
2064      // Full channel list update...          // Full channel list update...
2065      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2066      if (wlist.isEmpty())          if (wlist.isEmpty())
2067          return;                  return;
2068    
2069      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2070      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2071          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2072          if (pChannelStrip)                  if (pChannelStrip)
2073              pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                          pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2074      }          }
2075      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2076  }  }
2077    
2078    
# Line 2052  void MainForm::updateMaxVolume (void) Line 2082  void MainForm::updateMaxVolume (void)
2082  // Messages output methods.  // Messages output methods.
2083  void MainForm::appendMessages( const QString& s )  void MainForm::appendMessages( const QString& s )
2084  {  {
2085      if (m_pMessages)          if (m_pMessages)
2086          m_pMessages->appendMessages(s);                  m_pMessages->appendMessages(s);
2087    
2088      statusBar()->message(s, 3000);          statusBar()->showMessage(s, 3000);
2089  }  }
2090    
2091  void MainForm::appendMessagesColor( const QString& s, const QString& c )  void MainForm::appendMessagesColor( const QString& s, const QString& c )
2092  {  {
2093      if (m_pMessages)          if (m_pMessages)
2094          m_pMessages->appendMessagesColor(s, c);                  m_pMessages->appendMessagesColor(s, c);
2095    
2096      statusBar()->message(s, 3000);          statusBar()->showMessage(s, 3000);
2097  }  }
2098    
2099  void MainForm::appendMessagesText( const QString& s )  void MainForm::appendMessagesText( const QString& s )
2100  {  {
2101      if (m_pMessages)          if (m_pMessages)
2102          m_pMessages->appendMessagesText(s);                  m_pMessages->appendMessagesText(s);
2103  }  }
2104    
2105  void MainForm::appendMessagesError( const QString& s )  void MainForm::appendMessagesError( const QString& s )
2106  {  {
2107      if (m_pMessages)          if (m_pMessages)
2108          m_pMessages->show();                  m_pMessages->show();
2109    
2110      appendMessagesColor(s.simplifyWhiteSpace(), "#ff0000");          appendMessagesColor(s.simplified(), "#ff0000");
2111    
2112          // Make it look responsive...:)          // Make it look responsive...:)
2113          QApplication::processEvents(QEventLoop::ExcludeUserInput);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2114    
2115      QMessageBox::critical(this,          QMessageBox::critical(this,
2116                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));
2117  }  }
2118    
# Line 2090  void MainForm::appendMessagesError( cons Line 2120  void MainForm::appendMessagesError( cons
2120  // This is a special message format, just for client results.  // This is a special message format, just for client results.
2121  void MainForm::appendMessagesClient( const QString& s )  void MainForm::appendMessagesClient( const QString& s )
2122  {  {
2123      if (m_pClient == NULL)          if (m_pClient == NULL)
2124          return;                  return;
2125    
2126      appendMessagesColor(s + QString(": %1 (errno=%2)")          appendMessagesColor(s + QString(": %1 (errno=%2)")
2127          .arg(::lscp_client_get_result(m_pClient))                  .arg(::lscp_client_get_result(m_pClient))
2128          .arg(::lscp_client_get_errno(m_pClient)), "#996666");                  .arg(::lscp_client_get_errno(m_pClient)), "#996666");
2129    
2130          // Make it look responsive...:)          // Make it look responsive...:)
2131          QApplication::processEvents(QEventLoop::ExcludeUserInput);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2132  }  }
2133    
2134    
2135  // Force update of the messages font.  // Force update of the messages font.
2136  void MainForm::updateMessagesFont (void)  void MainForm::updateMessagesFont (void)
2137  {  {
2138      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2139          return;                  return;
2140    
2141      if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {          if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {
2142          QFont font;                  QFont font;
2143          if (font.fromString(m_pOptions->sMessagesFont))                  if (font.fromString(m_pOptions->sMessagesFont))
2144              m_pMessages->setMessagesFont(font);                          m_pMessages->setMessagesFont(font);
2145      }          }
2146  }  }
2147    
2148    
2149  // Update messages window line limit.  // Update messages window line limit.
2150  void MainForm::updateMessagesLimit (void)  void MainForm::updateMessagesLimit (void)
2151  {  {
2152      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2153          return;                  return;
2154    
2155      if (m_pMessages) {          if (m_pMessages) {
2156          if (m_pOptions->bMessagesLimit)                  if (m_pOptions->bMessagesLimit)
2157              m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);                          m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);
2158          else                  else
2159              m_pMessages->setMessagesLimit(-1);                          m_pMessages->setMessagesLimit(-1);
2160      }          }
2161  }  }
2162    
2163    
2164  // Enablement of the messages capture feature.  // Enablement of the messages capture feature.
2165  void MainForm::updateMessagesCapture (void)  void MainForm::updateMessagesCapture (void)
2166  {  {
2167      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2168          return;                  return;
2169    
2170      if (m_pMessages)          if (m_pMessages)
2171          m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);                  m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);
2172  }  }
2173    
2174    
# Line 2146  void MainForm::updateMessagesCapture (vo Line 2176  void MainForm::updateMessagesCapture (vo
2176  // qsamplerMainForm -- MDI channel strip management.  // qsamplerMainForm -- MDI channel strip management.
2177    
2178  // The channel strip creation executive.  // The channel strip creation executive.
2179  ChannelStrip* MainForm::createChannelStrip(qsamplerChannel* pChannel)  ChannelStrip* MainForm::createChannelStrip ( qsamplerChannel *pChannel )
2180  {  {
2181      if (m_pClient == NULL || pChannel == NULL)          if (m_pClient == NULL || pChannel == NULL)
2182          return NULL;                  return NULL;
2183    
2184      // Prepare for auto-arrange?          // Add a new channel itema...
2185      ChannelStrip* pChannelStrip = NULL;          ChannelStrip *pChannelStrip = new ChannelStrip();
2186      int y = 0;          if (pChannelStrip == NULL)
2187      if (m_pOptions && m_pOptions->bAutoArrange) {                  return NULL;
         QWidgetList wlist = m_pWorkspace->windowList();  
         for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {  
             pChannelStrip = (ChannelStrip *) wlist.at(iChannel);  
                         if (pChannelStrip) {  
                         //  y += pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();  
                                 y += pChannelStrip->parentWidget()->frameGeometry().height();  
                         }  
         }  
     }  
2188    
2189      // Add a new channel itema...          // Set some initial channel strip options...
2190      Qt::WFlags wflags = Qt::WStyle_Customize | Qt::WStyle_Tool | Qt::WStyle_Title | Qt::WStyle_NoBorder;          if (m_pOptions) {
2191      pChannelStrip = new ChannelStrip(m_pWorkspace, wflags);                  // Background display effect...
2192      if (pChannelStrip == NULL)                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2193          return NULL;                  // We'll need a display font.
2194                    QFont font;
2195                    if (font.fromString(m_pOptions->sDisplayFont))
2196                            pChannelStrip->setDisplayFont(font);
2197                    // Maximum allowed volume setting.
2198                    pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2199            }
2200    
2201            // Add it to workspace...
2202            m_pWorkspace->addWindow(pChannelStrip, Qt::FramelessWindowHint);
2203    
2204            // Actual channel strip setup...
2205            pChannelStrip->setup(pChannel);
2206    
     // Actual channel strip setup...  
     pChannelStrip->setup(pChannel);  
2207          QObject::connect(pChannelStrip,          QObject::connect(pChannelStrip,
2208                  SIGNAL(channelChanged(qsamplerChannelStrip *)),                  SIGNAL(channelChanged(ChannelStrip*)),
2209                  SLOT(channelStripChanged(qsamplerChannelStrip *)));                  SLOT(channelStripChanged(ChannelStrip*)));
2210      // Set some initial aesthetic options...  
2211      if (m_pOptions) {          // Now we show up us to the world.
2212          // 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);  
     }  
2213    
2214          // This is pretty new, so we'll watch for it closely.          // This is pretty new, so we'll watch for it closely.
2215          channelStripChanged(pChannelStrip);          channelStripChanged(pChannelStrip);
2216    
2217      // Return our successful reference...          // Return our successful reference...
2218      return pChannelStrip;          return pChannelStrip;
2219  }  }
2220    
2221    
2222  // Retrieve the active channel strip.  // Retrieve the active channel strip.
2223  ChannelStrip* MainForm::activeChannelStrip (void)  ChannelStrip* MainForm::activeChannelStrip (void)
2224  {  {
2225      return (ChannelStrip*) m_pWorkspace->activeWindow();          return static_cast<ChannelStrip *> (m_pWorkspace->activeWindow());
2226  }  }
2227    
2228    
2229  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
2230  ChannelStrip* MainForm::channelStripAt ( int iChannel )  ChannelStrip* MainForm::channelStripAt ( int iChannel )
2231  {  {
2232      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2233      if (wlist.isEmpty())          if (wlist.isEmpty())
2234          return NULL;                  return NULL;
2235    
2236      return (ChannelStrip*) wlist.at(iChannel);          return static_cast<ChannelStrip *> (wlist.at(iChannel));
2237  }  }
2238    
2239    
# Line 2231  ChannelStrip* MainForm::channelStrip ( i Line 2245  ChannelStrip* MainForm::channelStrip ( i
2245                  return NULL;                  return NULL;
2246    
2247          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2248                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip
2249                            = static_cast<ChannelStrip*> (wlist.at(iChannel));
2250                  if (pChannelStrip) {                  if (pChannelStrip) {
2251                          qsamplerChannel *pChannel = pChannelStrip->channel();                          qsamplerChannel *pChannel = pChannelStrip->channel();
2252                          if (pChannel && pChannel->channelID() == iChannelID)                          if (pChannel && pChannel->channelID() == iChannelID)
# Line 2247  ChannelStrip* MainForm::channelStrip ( i Line 2262  ChannelStrip* MainForm::channelStrip ( i
2262  // Construct the windows menu.  // Construct the windows menu.
2263  void MainForm::channelsMenuAboutToShow (void)  void MainForm::channelsMenuAboutToShow (void)
2264  {  {
2265      ui.channelsMenu->clear();          m_ui.channelsMenu->clear();
2266      ui.channelsArrangeAction->addTo(ui.channelsMenu);          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);
2267      ui.channelsAutoArrangeAction->addTo(ui.channelsMenu);          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);
2268    
2269      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2270      if (!wlist.isEmpty()) {          if (!wlist.isEmpty()) {
2271          ui.channelsMenu->insertSeparator();                  m_ui.channelsMenu->addSeparator();
2272          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2273              ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                          ChannelStrip* pChannelStrip
2274              if (pChannelStrip) {                                  = static_cast<ChannelStrip*> (wlist.at(iChannel));
2275                  int iItemID = ui.channelsMenu->insertItem(pChannelStrip->caption(), this, SLOT(channelsMenuActivated(int)));                          if (pChannelStrip) {
2276                  ui.channelsMenu->setItemParameter(iItemID, iChannel);                                  QAction *pAction = m_ui.channelsMenu->addAction(
2277                  ui.channelsMenu->setItemChecked(iItemID, activeChannelStrip() == pChannelStrip);                                          pChannelStrip->windowTitle(),
2278              }                                          this, SLOT(channelsMenuActivated()));
2279          }                                  pAction->setCheckable(true);
2280      }                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);
2281                                    pAction->setData(iChannel);
2282                            }
2283                    }
2284            }
2285  }  }
2286    
2287    
2288  // Windows menu activation slot  // Windows menu activation slot
2289  void MainForm::channelsMenuActivated ( int iChannel )  void MainForm::channelsMenuActivated (void)
2290  {  {
2291      ChannelStrip* pChannelStrip = channelStripAt(iChannel);          // Retrive channel index from action data...
2292      if (pChannelStrip)          QAction *pAction = qobject_cast<QAction *> (sender());
2293          pChannelStrip->showNormal();          if (pAction == NULL)
2294      pChannelStrip->setFocus();                  return;
2295    
2296            ChannelStrip* pChannelStrip = channelStripAt(pAction->data().toInt());
2297            if (pChannelStrip) {
2298                    pChannelStrip->showNormal();
2299                    pChannelStrip->setFocus();
2300            }
2301  }  }
2302    
2303    
# Line 2282  void MainForm::channelsMenuActivated ( i Line 2307  void MainForm::channelsMenuActivated ( i
2307  // Set the pseudo-timer delay schedule.  // Set the pseudo-timer delay schedule.
2308  void MainForm::startSchedule ( int iStartDelay )  void MainForm::startSchedule ( int iStartDelay )
2309  {  {
2310      m_iStartDelay  = 1 + (iStartDelay * 1000);          m_iStartDelay  = 1 + (iStartDelay * 1000);
2311      m_iTimerDelay  = 0;          m_iTimerDelay  = 0;
2312  }  }
2313    
2314  // Suspend the pseudo-timer delay schedule.  // Suspend the pseudo-timer delay schedule.
2315  void MainForm::stopSchedule (void)  void MainForm::stopSchedule (void)
2316  {  {
2317      m_iStartDelay  = 0;          m_iStartDelay  = 0;
2318      m_iTimerDelay  = 0;          m_iTimerDelay  = 0;
2319  }  }
2320    
2321  // Timer slot funtion.  // Timer slot funtion.
2322  void MainForm::timerSlot (void)  void MainForm::timerSlot (void)
2323  {  {
2324      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2325          return;                  return;
2326    
2327      // Is it the first shot on server start after a few delay?          // Is it the first shot on server start after a few delay?
2328      if (m_iTimerDelay < m_iStartDelay) {          if (m_iTimerDelay < m_iStartDelay) {
2329          m_iTimerDelay += QSAMPLER_TIMER_MSECS;                  m_iTimerDelay += QSAMPLER_TIMER_MSECS;
2330          if (m_iTimerDelay >= m_iStartDelay) {                  if (m_iTimerDelay >= m_iStartDelay) {
2331              // If we cannot start it now, maybe a lil'mo'later ;)                          // If we cannot start it now, maybe a lil'mo'later ;)
2332              if (!startClient()) {                          if (!startClient()) {
2333                  m_iStartDelay += m_iTimerDelay;                                  m_iStartDelay += m_iTimerDelay;
2334                  m_iTimerDelay  = 0;                                  m_iTimerDelay  = 0;
2335              }                          }
2336          }                  }
2337      }          }
2338    
2339          if (m_pClient) {          if (m_pClient) {
2340                  // Update the channel information for each pending strip...                  // Update the channel information for each pending strip...
2341                  if (m_changedStrips.count() > 0) {                  QListIterator<ChannelStrip *> iter(m_changedStrips);
2342                          for (ChannelStrip* pChannelStrip = m_changedStrips.first();                  while (iter.hasNext()) {
2343                                          pChannelStrip; pChannelStrip = m_changedStrips.next()) {                          ChannelStrip *pChannelStrip = iter.next();
2344                                  // If successfull, remove from pending list...                          // If successfull, remove from pending list...
2345                                  if (pChannelStrip->updateChannelInfo())                          if (pChannelStrip->updateChannelInfo()) {
2346                                          m_changedStrips.remove(pChannelStrip);                                  int iChannelStrip = m_changedStrips.indexOf(pChannelStrip);
2347                                    if (iChannelStrip >= 0)
2348                                            m_changedStrips.removeAt(iChannelStrip);
2349                          }                          }
2350                  }                  }
2351                  // Refresh each channel usage, on each period...                  // Refresh each channel usage, on each period...
# Line 2339  void MainForm::timerSlot (void) Line 2366  void MainForm::timerSlot (void)
2366                  }                  }
2367          }          }
2368    
2369      // Register the next timer slot.          // Register the next timer slot.
2370      QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));          QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
2371  }  }
2372    
2373    
# Line 2350  void MainForm::timerSlot (void) Line 2377  void MainForm::timerSlot (void)
2377  // Start linuxsampler server...  // Start linuxsampler server...
2378  void MainForm::startServer (void)  void MainForm::startServer (void)
2379  {  {
2380      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2381          return;                  return;
2382    
2383      // Aren't already a client, are we?          // Aren't already a client, are we?
2384      if (!m_pOptions->bServerStart || m_pClient)          if (!m_pOptions->bServerStart || m_pClient)
2385          return;                  return;
2386    
2387      // Is the server process instance still here?          // Is the server process instance still here?
2388      if (m_pServer) {          if (m_pServer) {
2389          switch (QMessageBox::warning(this,                  switch (QMessageBox::warning(this,
2390                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
2391              tr("Could not start the LinuxSampler server.\n\n"                          tr("Could not start the LinuxSampler server.\n\n"
2392                 "Maybe it ss already started."),                          "Maybe it ss already started."),
2393              tr("Stop"), tr("Kill"), tr("Cancel"))) {                          tr("Stop"), tr("Kill"), tr("Cancel"))) {
2394            case 0:                  case 0:
2395              m_pServer->terminate();                          m_pServer->terminate();
2396              break;                          break;
2397            case 1:                  case 1:
2398              m_pServer->kill();                          m_pServer->kill();
2399              break;                          break;
2400          }                  }
2401          return;                  return;
2402      }          }
2403    
2404      // Reset our timer counters...          // Reset our timer counters...
2405      stopSchedule();          stopSchedule();
2406    
2407      // OK. Let's build the startup process...          // Verify we have something to start with...
2408      m_pServer = new QProcess(this);          if (m_pOptions->sServerCmdLine.isEmpty())
2409                    return;
2410    
2411      // Setup stdout/stderr capture...          // OK. Let's build the startup process...
2412          //      if (m_pOptions->bStdoutCapture) {          m_pServer = new QProcess(this);
2413    
2414            // Setup stdout/stderr capture...
2415    //      if (m_pOptions->bStdoutCapture) {
2416                  //m_pServer->setProcessChannelMode(                  //m_pServer->setProcessChannelMode(
2417                  //      QProcess::StandardOutput);                  //      QProcess::StandardOutput);
2418                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
# Line 2390  void MainForm::startServer (void) Line 2421  void MainForm::startServer (void)
2421                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2422                          SIGNAL(readyReadStandardError()),                          SIGNAL(readyReadStandardError()),
2423                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
2424          //      }  //      }
2425    
2426          // The unforgiveable signal communication...          // The unforgiveable signal communication...
2427          QObject::connect(m_pServer,          QObject::connect(m_pServer,
2428                  SIGNAL(finished(int,QProcess::ExitStatus)),                  SIGNAL(finished(int,QProcess::ExitStatus)),
2429                  SLOT(processServerExit()));                  SLOT(processServerExit()));
2430    
2431      // Build process arguments...          // Build process arguments...
2432      QStringList serverCmdLine = QStringList::split(' ', m_pOptions->sServerCmdLine);          QStringList args = m_pOptions->sServerCmdLine.split(' ');
2433            QString sCommand = args[0];
2434      appendMessages(tr("Server is starting..."));          args.removeAt(0);
2435      appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");  
2436            appendMessages(tr("Server is starting..."));
2437            appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");
2438    
2439      const QString prog = (serverCmdLine.size() > 0) ? serverCmdLine[0] : QString();          // Go linuxsampler, go...
2440      const QStringList args = serverCmdLine.mid(1);          m_pServer->start(sCommand, args);
2441            if (!m_pServer->waitForStarted()) {
2442      // Go jack, go...                  appendMessagesError(tr("Could not start server.\n\nSorry."));
2443      m_pServer->start(prog, args);                  processServerExit();
2444      if (!m_pServer->waitForStarted()) {                  return;
2445          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()));  
2446    
2447      // Reset (yet again) the timer counters,          // Show startup results...
2448      // but this time is deferred as the user opted.          appendMessages(
2449      startSchedule(m_pOptions->iStartDelay);                  tr("Server was started with PID=%1.").arg((long) m_pServer->pid()));
2450      stabilizeForm();  
2451            // Reset (yet again) the timer counters,
2452            // but this time is deferred as the user opted.
2453            startSchedule(m_pOptions->iStartDelay);
2454            stabilizeForm();
2455  }  }
2456    
2457    
2458  // Stop linuxsampler server...  // Stop linuxsampler server...
2459  void MainForm::stopServer (void)  void MainForm::stopServer (void)
2460  {  {
2461      // Stop client code.          // Stop client code.
2462      stopClient();          stopClient();
2463    
2464      // And try to stop server.          // And try to stop server.
2465      if (m_pServer) {          if (m_pServer) {
2466          appendMessages(tr("Server is stopping..."));                  appendMessages(tr("Server is stopping..."));
2467          if (m_pServer->state() == QProcess::Running)                  if (m_pServer->state() == QProcess::Running)
2468              m_pServer->terminate();                          m_pServer->terminate();
2469       }          }
   
     // Give it some time to terminate gracefully and stabilize...  
     QTime t;  
     t.start();  
     while (t.elapsed() < QSAMPLER_TIMER_MSECS)  
         QApplication::processEvents(QEventLoop::ExcludeUserInput);  
2470    
2471       // Do final processing anyway.          // Give it some time to terminate gracefully and stabilize...
2472       processServerExit();          QTime t;
2473            t.start();
2474            while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2475                    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2476    
2477            // Do final processing anyway.
2478            processServerExit();
2479  }  }
2480    
2481    
2482  // Stdout handler...  // Stdout handler...
2483  void MainForm::readServerStdout (void)  void MainForm::readServerStdout (void)
2484  {  {
2485      if (m_pMessages)          if (m_pMessages)
2486          m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());                  m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());
2487  }  }
2488    
2489    
2490  // Linuxsampler server cleanup.  // Linuxsampler server cleanup.
2491  void MainForm::processServerExit (void)  void MainForm::processServerExit (void)
2492  {  {
2493      // Force client code cleanup.          // Force client code cleanup.
2494      stopClient();          stopClient();
2495    
2496      // Flush anything that maybe pending...          // Flush anything that maybe pending...
2497      if (m_pMessages)          if (m_pMessages)
2498          m_pMessages->flushStdoutBuffer();                  m_pMessages->flushStdoutBuffer();
2499    
2500      if (m_pServer) {          if (m_pServer) {
2501          // Force final server shutdown...                  // Force final server shutdown...
2502          appendMessages(tr("Server was stopped with exit status %1.").arg(m_pServer->exitStatus()));                  appendMessages(
2503          m_pServer->terminate();                          tr("Server was stopped with exit status %1.")
2504          if (!m_pServer->waitForFinished(2000))                          .arg(m_pServer->exitStatus()));
2505              m_pServer->kill();                  m_pServer->terminate();
2506          // Destroy it.                  if (!m_pServer->waitForFinished(2000))
2507          delete m_pServer;                          m_pServer->kill();
2508          m_pServer = NULL;                  // Destroy it.
2509      }                  delete m_pServer;
2510                    m_pServer = NULL;
2511            }
2512    
2513      // Again, make status visible stable.          // Again, make status visible stable.
2514      stabilizeForm();          stabilizeForm();
2515  }  }
2516    
2517    
# Line 2487  void MainForm::processServerExit (void) Line 2519  void MainForm::processServerExit (void)
2519  // qsamplerMainForm -- Client stuff.  // qsamplerMainForm -- Client stuff.
2520    
2521  // The LSCP client callback procedure.  // The LSCP client callback procedure.
2522  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*/,
2523            lscp_event_t event, const char *pchData, int cchData, void *pvData )
2524  {  {
2525      MainForm* pMainForm = (MainForm *) pvData;          MainForm* pMainForm = (MainForm *) pvData;
2526      if (pMainForm == NULL)          if (pMainForm == NULL)
2527          return LSCP_FAILED;                  return LSCP_FAILED;
2528    
2529      // ATTN: DO NOT EVER call any GUI code here,          // ATTN: DO NOT EVER call any GUI code here,
2530      // as this is run under some other thread context.          // as this is run under some other thread context.
2531      // A custom event must be posted here...          // A custom event must be posted here...
2532      QApplication::postEvent(pMainForm, new qsamplerCustomEvent(event, pchData, cchData));          QApplication::postEvent(pMainForm,
2533                    new qsamplerCustomEvent(event, pchData, cchData));
2534    
2535      return LSCP_OK;          return LSCP_OK;
2536  }  }
2537    
2538    
2539  // Start our almighty client...  // Start our almighty client...
2540  bool MainForm::startClient (void)  bool MainForm::startClient (void)
2541  {  {
2542      // Have it a setup?          // Have it a setup?
2543      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2544          return false;                  return false;
2545    
2546      // Aren't we already started, are we?          // Aren't we already started, are we?
2547      if (m_pClient)          if (m_pClient)
2548          return true;                  return true;
2549    
2550      // Log prepare here.          // Log prepare here.
2551      appendMessages(tr("Client connecting..."));          appendMessages(tr("Client connecting..."));
2552    
2553      // Create the client handle...          // Create the client handle...
2554      m_pClient = ::lscp_client_create(m_pOptions->sServerHost.latin1(), m_pOptions->iServerPort, qsampler_client_callback, this);          m_pClient = ::lscp_client_create(
2555      if (m_pClient == NULL) {                  m_pOptions->sServerHost.toUtf8().constData(),
2556          // Is this the first try?                  m_pOptions->iServerPort, qsampler_client_callback, this);
2557          // maybe we need to start a local server...          if (m_pClient == NULL) {
2558          if ((m_pServer && m_pServer->state() == QProcess::Running) || !m_pOptions->bServerStart)                  // Is this the first try?
2559              appendMessagesError(tr("Could not connect to server as client.\n\nSorry."));                  // maybe we need to start a local server...
2560          else                  if ((m_pServer && m_pServer->state() == QProcess::Running)
2561              startServer();                          || !m_pOptions->bServerStart) {
2562          // This is always a failure.                          appendMessagesError(
2563          stabilizeForm();                                  tr("Could not connect to server as client.\n\nSorry."));
2564          return false;                  } else {
2565      }                          startServer();
2566      // Just set receive timeout value, blindly.                  }
2567      ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);                  // This is always a failure.
2568      appendMessages(tr("Client receive timeout is set to %1 msec.").arg(::lscp_client_get_timeout(m_pClient)));                  stabilizeForm();
2569                    return false;
2570            }
2571            // Just set receive timeout value, blindly.
2572            ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);
2573            appendMessages(
2574                    tr("Client receive timeout is set to %1 msec.")
2575                    .arg(::lscp_client_get_timeout(m_pClient)));
2576    
2577          // Subscribe to channel info change notifications...          // Subscribe to channel info change notifications...
2578          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)
2579                  appendMessagesClient("lscp_client_subscribe");                  appendMessagesClient("lscp_client_subscribe");
2580    
2581      // We may stop scheduling around.          // We may stop scheduling around.
2582      stopSchedule();          stopSchedule();
2583    
2584      // We'll accept drops from now on...          // We'll accept drops from now on...
2585      setAcceptDrops(true);          setAcceptDrops(true);
2586    
2587      // Log success here.          // Log success here.
2588      appendMessages(tr("Client connected."));          appendMessages(tr("Client connected."));
2589    
2590          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
2591          // if visible, that we're ready...          // if visible, that we're ready...
2592          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
2593              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
2594          if (m_pDeviceForm)          if (m_pDeviceForm)
2595              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
2596    
2597      // Is any session pending to be loaded?          // Is any session pending to be loaded?
2598      if (!m_pOptions->sSessionFile.isEmpty()) {          if (!m_pOptions->sSessionFile.isEmpty()) {
2599          // Just load the prabably startup session...                  // Just load the prabably startup session...
2600          if (loadSessionFile(m_pOptions->sSessionFile)) {                  if (loadSessionFile(m_pOptions->sSessionFile)) {
2601              m_pOptions->sSessionFile = QString::null;                          m_pOptions->sSessionFile = QString::null;
2602              return true;                          return true;
2603          }                  }
2604      }          }
2605    
2606      // Make a new session          // Make a new session
2607      return newSession();          return newSession();
2608  }  }
2609    
2610    
2611  // Stop client...  // Stop client...
2612  void MainForm::stopClient (void)  void MainForm::stopClient (void)
2613  {  {
2614      if (m_pClient == NULL)          if (m_pClient == NULL)
2615          return;                  return;
2616    
2617      // Log prepare here.          // Log prepare here.
2618      appendMessages(tr("Client disconnecting..."));          appendMessages(tr("Client disconnecting..."));
2619    
2620      // Clear timer counters...          // Clear timer counters...
2621      stopSchedule();          stopSchedule();
2622    
2623      // We'll reject drops from now on...          // We'll reject drops from now on...
2624      setAcceptDrops(false);          setAcceptDrops(false);
2625    
2626      // Force any channel strips around, but          // Force any channel strips around, but
2627      // but avoid removing the corresponding          // but avoid removing the corresponding
2628      // channels from the back-end server.          // channels from the back-end server.
2629      m_iDirtyCount = 0;          m_iDirtyCount = 0;
2630      closeSession(false);          closeSession(false);
2631    
2632      // Close us as a client...          // Close us as a client...
2633          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
2634      ::lscp_client_destroy(m_pClient);          ::lscp_client_destroy(m_pClient);
2635      m_pClient = NULL;          m_pClient = NULL;
2636    
2637          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
2638          // if visible, that we're running out...          // if visible, that we're running out...
2639          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
2640              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
2641          if (m_pDeviceForm)          if (m_pDeviceForm)
2642              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
2643    
2644      // Log final here.          // Log final here.
2645      appendMessages(tr("Client disconnected."));          appendMessages(tr("Client disconnected."));
2646    
2647      // Make visible status.          // Make visible status.
2648      stabilizeForm();          stabilizeForm();
2649  }  }
2650    
2651    
2652    // Channel strip activation/selection.
2653    void MainForm::activateStrip ( QWidget *pWidget )
2654    {
2655            ChannelStrip *pChannelStrip
2656                    = static_cast<ChannelStrip *> (pWidget);
2657            if (pChannelStrip)
2658                    pChannelStrip->setSelected(true);
2659    
2660            stabilizeForm();
2661    }
2662    
2663    
2664  } // namespace QSampler  } // namespace QSampler
2665    
2666    

Legend:
Removed from v.1470  
changed lines
  Added in v.1515

  ViewVC Help
Powered by ViewVC