/[svn]/qsampler/trunk/src/qsamplerMainForm.cpp
ViewVC logotype

Diff of /qsampler/trunk/src/qsamplerMainForm.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

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

  ViewVC Help
Powered by ViewVC