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

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

  ViewVC Help
Powered by ViewVC