/[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 1691 by schoenebeck, Thu Feb 14 22:31:26 2008 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(true /*interactive*/);
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) {                  switch (pEvent->event()) {
555                          int iChannelID = pEvent->data().toInt();                          case LSCP_EVENT_CHANNEL_INFO: {
556                          ChannelStrip *pChannelStrip = channelStrip(iChannelID);                                  int iChannelID = pEvent->data().toInt();
557                          if (pChannelStrip)                                  ChannelStrip *pChannelStrip = channelStrip(iChannelID);
558                                  channelStripChanged(pChannelStrip);                                  if (pChannelStrip)
559                  } else {                                          channelStripChanged(pChannelStrip);
560                          appendMessagesColor(tr("Notify event: %1 data: %2")                                  break;
561                                  .arg(::lscp_event_to_text(pEvent->event()))                          }
562                                  .arg(pEvent->data()), "#996699");  #if CONFIG_LSCP_CHANNEL_MIDI
563                            case LSCP_EVENT_CHANNEL_MIDI: {
564                                    int iChannelID = pEvent->data().toInt();
565                                    ChannelStrip *pChannelStrip = channelStrip(iChannelID);
566                                    if (pChannelStrip)
567                                            pChannelStrip->midiArrived();
568                                    break;
569                            }
570    #endif
571                            default:
572                                    appendMessagesColor(tr("Notify event: %1 data: %2")
573                                            .arg(::lscp_event_to_text(pEvent->event()))
574                                            .arg(pEvent->data()), "#996699");
575                  }                  }
576      }          }
577  }  }
578    
579  // Context menu event handler.  // Context menu event handler.
580  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )
581  {  {
582      stabilizeForm();          stabilizeForm();
583    
584      ui.editMenu->exec(pEvent->globalPos());          m_ui.editMenu->exec(pEvent->globalPos());
585  }  }
586    
587    
# Line 571  void MainForm::contextMenuEvent( QContex Line 589  void MainForm::contextMenuEvent( QContex
589  // qsamplerMainForm -- Brainless public property accessors.  // qsamplerMainForm -- Brainless public property accessors.
590    
591  // The global options settings property.  // The global options settings property.
592  qsamplerOptions *MainForm::options (void)  Options *MainForm::options (void) const
593  {  {
594      return m_pOptions;          return m_pOptions;
595  }  }
596    
597    
598  // The LSCP client descriptor property.  // The LSCP client descriptor property.
599  lscp_client_t *MainForm::client (void)  lscp_client_t *MainForm::client (void) const
600  {  {
601      return m_pClient;          return m_pClient;
602  }  }
603    
604    
# Line 597  MainForm *MainForm::getInstance (void) Line 615  MainForm *MainForm::getInstance (void)
615  // Format the displayable session filename.  // Format the displayable session filename.
616  QString MainForm::sessionName ( const QString& sFilename )  QString MainForm::sessionName ( const QString& sFilename )
617  {  {
618      bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);          bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);
619      QString sSessionName = sFilename;          QString sSessionName = sFilename;
620      if (sSessionName.isEmpty())          if (sSessionName.isEmpty())
621          sSessionName = tr("Untitled") + QString::number(m_iUntitled);                  sSessionName = tr("Untitled") + QString::number(m_iUntitled);
622      else if (!bCompletePath)          else if (!bCompletePath)
623          sSessionName = QFileInfo(sSessionName).fileName();                  sSessionName = QFileInfo(sSessionName).fileName();
624      return sSessionName;          return sSessionName;
625  }  }
626    
627    
628  // Create a new session file from scratch.  // Create a new session file from scratch.
629  bool MainForm::newSession (void)  bool MainForm::newSession (void)
630  {  {
631      // Check if we can do it.          // Check if we can do it.
632      if (!closeSession(true))          if (!closeSession(true))
633          return false;                  return false;
634    
635          // Give us what the server has, right now...          // Give us what the server has, right now...
636          updateSession();          updateSession();
637    
638      // Ok increment untitled count.          // Ok increment untitled count.
639      m_iUntitled++;          m_iUntitled++;
640    
641      // Stabilize form.          // Stabilize form.
642      m_sFilename = QString::null;          m_sFilename = QString::null;
643      m_iDirtyCount = 0;          m_iDirtyCount = 0;
644      appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));          appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));
645      stabilizeForm();          stabilizeForm();
646    
647      return true;          return true;
648  }  }
649    
650    
651  // Open an existing sampler session.  // Open an existing sampler session.
652  bool MainForm::openSession (void)  bool MainForm::openSession (void)
653  {  {
654      if (m_pOptions == NULL)          if (m_pOptions == NULL)
655          return false;                  return false;
656    
657            // Ask for the filename to open...
658            QString sFilename = QFileDialog::getOpenFileName(this,
659                    QSAMPLER_TITLE ": " + tr("Open Session"), // Caption.
660                    m_pOptions->sSessionDir,                  // Start here.
661                    tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
662            );
663    
664            // Have we cancelled?
665            if (sFilename.isEmpty())
666                    return false;
667    
668      // Ask for the filename to open...          // Check if we're going to discard safely the current one...
669      QString sFilename = QFileDialog::getOpenFileName(          if (!closeSession(true))
670                  m_pOptions->sSessionDir,                // Start here.                  return false;
                 tr("LSCP Session files") + " (*.lscp)", // Filter (LSCP files)  
                 this, 0,                                // Parent and name (none)  
                 QSAMPLER_TITLE ": " + tr("Open Session")        // Caption.  
     );  
   
     // Have we cancelled?  
     if (sFilename.isEmpty())  
         return false;  
   
     // Check if we're going to discard safely the current one...  
     if (!closeSession(true))  
         return false;  
671    
672      // Load it right away.          // Load it right away.
673      return loadSessionFile(sFilename);          return loadSessionFile(sFilename);
674  }  }
675    
676    
677  // Save current sampler session with another name.  // Save current sampler session with another name.
678  bool MainForm::saveSession ( bool bPrompt )  bool MainForm::saveSession ( bool bPrompt )
679  {  {
680      if (m_pOptions == NULL)          if (m_pOptions == NULL)
681          return false;                  return false;
682    
683      QString sFilename = m_sFilename;          QString sFilename = m_sFilename;
684    
685      // Ask for the file to save, if there's none...          // Ask for the file to save, if there's none...
686      if (bPrompt || sFilename.isEmpty()) {          if (bPrompt || sFilename.isEmpty()) {
687          // If none is given, assume default directory.                  // If none is given, assume default directory.
688          if (sFilename.isEmpty())                  if (sFilename.isEmpty())
689              sFilename = m_pOptions->sSessionDir;                          sFilename = m_pOptions->sSessionDir;
690          // Prompt the guy...                  // Prompt the guy...
691          sFilename = QFileDialog::getSaveFileName(                  sFilename = QFileDialog::getSaveFileName(this,
692                          sFilename,                              // Start here.                          QSAMPLER_TITLE ": " + tr("Save Session"), // Caption.
693                          tr("LSCP Session files") + " (*.lscp)", // Filter (LSCP files)                          sFilename,                                // Start here.
694                          this, 0,                                // Parent and name (none)                          tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
695                          QSAMPLER_TITLE ": " + tr("Save Session")        // Caption.                  );
696          );                  // Have we cancelled it?
697          // Have we cancelled it?                  if (sFilename.isEmpty())
698          if (sFilename.isEmpty())                          return false;
699              return false;                  // Enforce .lscp extension...
700          // Enforce .lscp extension...                  if (QFileInfo(sFilename).suffix().isEmpty())
701          if (QFileInfo(sFilename).extension().isEmpty())                          sFilename += ".lscp";
702              sFilename += ".lscp";                  // Check if already exists...
703          // Check if already exists...                  if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {
704          if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {                          if (QMessageBox::warning(this,
             if (QMessageBox::warning(this,  
705                                  QSAMPLER_TITLE ": " + tr("Warning"),                                  QSAMPLER_TITLE ": " + tr("Warning"),
706                  tr("The file already exists:\n\n"                                  tr("The file already exists:\n\n"
707                     "\"%1\"\n\n"                                  "\"%1\"\n\n"
708                     "Do you want to replace it?")                                  "Do you want to replace it?")
709                     .arg(sFilename),                                  .arg(sFilename),
710                  tr("Replace"), tr("Cancel")) > 0)                                  tr("Replace"), tr("Cancel")) > 0)
711                  return false;                                  return false;
712          }                  }
713      }          }
714    
715      // Save it right away.          // Save it right away.
716      return saveSessionFile(sFilename);          return saveSessionFile(sFilename);
717  }  }
718    
719    
720  // Close current session.  // Close current session.
721  bool MainForm::closeSession ( bool bForce )  bool MainForm::closeSession ( bool bForce )
722  {  {
723      bool bClose = true;          bool bClose = true;
724    
725      // Are we dirty enough to prompt it?          // Are we dirty enough to prompt it?
726      if (m_iDirtyCount > 0) {          if (m_iDirtyCount > 0) {
727          switch (QMessageBox::warning(this,                  switch (QMessageBox::warning(this,
728                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
729              tr("The current session has been changed:\n\n"                          tr("The current session has been changed:\n\n"
730              "\"%1\"\n\n"                          "\"%1\"\n\n"
731              "Do you want to save the changes?")                          "Do you want to save the changes?")
732              .arg(sessionName(m_sFilename)),                          .arg(sessionName(m_sFilename)),
733              tr("Save"), tr("Discard"), tr("Cancel"))) {                          tr("Save"), tr("Discard"), tr("Cancel"))) {
734          case 0:     // Save...                  case 0:     // Save...
735              bClose = saveSession(false);                          bClose = saveSession(false);
736              // Fall thru....                          // Fall thru....
737          case 1:     // Discard                  case 1:     // Discard
738              break;                          break;
739          default:    // Cancel.                  default:    // Cancel.
740              bClose = false;                          bClose = false;
741              break;                          break;
742          }                  }
743      }          }
744    
745      // If we may close it, dot it.          // If we may close it, dot it.
746      if (bClose) {          if (bClose) {
747          // Remove all channel strips from sight...                  // Remove all channel strips from sight...
748          m_pWorkspace->setUpdatesEnabled(false);                  m_pWorkspace->setUpdatesEnabled(false);
749          QWidgetList wlist = m_pWorkspace->windowList();                  QWidgetList wlist = m_pWorkspace->windowList();
750          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
751              ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                          ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
752              if (pChannelStrip) {                          if (pChannelStrip) {
753                  qsamplerChannel *pChannel = pChannelStrip->channel();                                  Channel *pChannel = pChannelStrip->channel();
754                  if (bForce && pChannel)                                  if (bForce && pChannel)
755                      pChannel->removeChannel();                                          pChannel->removeChannel();
756                  delete pChannelStrip;                                  delete pChannelStrip;
757              }                          }
758          }                  }
759          m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
760          // We're now clean, for sure.                  // We're now clean, for sure.
761          m_iDirtyCount = 0;                  m_iDirtyCount = 0;
762      }          }
763    
764      return bClose;          return bClose;
765  }  }
766    
767    
768  // Load a session from specific file path.  // Load a session from specific file path.
769  bool MainForm::loadSessionFile ( const QString& sFilename )  bool MainForm::loadSessionFile ( const QString& sFilename )
770  {  {
771      if (m_pClient == NULL)          if (m_pClient == NULL)
772          return false;                  return false;
773    
774      // Open and read from real file.          // Open and read from real file.
775      QFile file(sFilename);          QFile file(sFilename);
776      if (!file.open(IO_ReadOnly)) {          if (!file.open(QIODevice::ReadOnly)) {
777          appendMessagesError(tr("Could not open \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
778          return false;                          tr("Could not open \"%1\" session file.\n\nSorry.")
779      }                          .arg(sFilename));
780                    return false;
781            }
782    
783          // Tell the world we'll take some time...          // Tell the world we'll take some time...
784          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
785    
786      // Read the file.          // Read the file.
787          int iLine = 0;          int iLine = 0;
788      int iErrors = 0;          int iErrors = 0;
789      QTextStream ts(&file);          QTextStream ts(&file);
790      while (!ts.atEnd()) {          while (!ts.atEnd()) {
791          // Read the line.                  // Read the line.
792          QString sCommand = ts.readLine().stripWhiteSpace();                  QString sCommand = ts.readLine().trimmed();
793                  iLine++;                  iLine++;
794          // If not empty, nor a comment, call the server...                  // If not empty, nor a comment, call the server...
795          if (!sCommand.isEmpty() && sCommand[0] != '#') {                  if (!sCommand.isEmpty() && sCommand[0] != '#') {
796                          // Remember that, no matter what,                          // Remember that, no matter what,
797                          // all LSCP commands are CR/LF terminated.                          // all LSCP commands are CR/LF terminated.
798                          sCommand += "\r\n";                          sCommand += "\r\n";
799                          if (::lscp_client_query(m_pClient, sCommand.latin1()) != LSCP_OK) {                          if (::lscp_client_query(m_pClient, sCommand.toUtf8().constData())
800                                    != LSCP_OK) {
801                                  appendMessagesColor(QString("%1(%2): %3")                                  appendMessagesColor(QString("%1(%2): %3")
802                                          .arg(QFileInfo(sFilename).fileName()).arg(iLine)                                          .arg(QFileInfo(sFilename).fileName()).arg(iLine)
803                                          .arg(sCommand.simplifyWhiteSpace()), "#996633");                                          .arg(sCommand.simplified()), "#996633");
804                                  appendMessagesClient("lscp_client_query");                                  appendMessagesClient("lscp_client_query");
805                                  iErrors++;                                  iErrors++;
806                          }                          }
807          }                  }
808          // Try to make it snappy :)                  // Try to make it snappy :)
809          QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
810      }          }
811    
812      // Ok. we've read it.          // Ok. we've read it.
813      file.close();          file.close();
814    
815          // Now we'll try to create (update) the whole GUI session.          // Now we'll try to create (update) the whole GUI session.
816          updateSession();          updateSession();
# Line 800  bool MainForm::loadSessionFile ( const Q Line 819  bool MainForm::loadSessionFile ( const Q
819          QApplication::restoreOverrideCursor();          QApplication::restoreOverrideCursor();
820    
821          // Have we any errors?          // Have we any errors?
822          if (iErrors > 0)          if (iErrors > 0) {
823                  appendMessagesError(tr("Session loaded with errors\nfrom \"%1\".\n\nSorry.").arg(sFilename));                  appendMessagesError(
824                            tr("Session loaded with errors\nfrom \"%1\".\n\nSorry.")
825                            .arg(sFilename));
826            }
827    
828      // Save as default session directory.          // Save as default session directory.
829      if (m_pOptions)          if (m_pOptions)
830          m_pOptions->sSessionDir = QFileInfo(sFilename).dirPath(true);                  m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();
831          // We're not dirty anymore, if loaded without errors,          // We're not dirty anymore, if loaded without errors,
832          m_iDirtyCount = iErrors;          m_iDirtyCount = iErrors;
833      // Stabilize form...          // Stabilize form...
834      m_sFilename = sFilename;          m_sFilename = sFilename;
835      updateRecentFiles(sFilename);          updateRecentFiles(sFilename);
836      appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));          appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));
837    
838      // Make that an overall update.          // Make that an overall update.
839      stabilizeForm();          stabilizeForm();
840      return true;          return true;
841  }  }
842    
843    
# Line 831  bool MainForm::saveSessionFile ( const Q Line 853  bool MainForm::saveSessionFile ( const Q
853                  return false;                  return false;
854          }          }
855    
856      // Open and write into real file.          // Open and write into real file.
857      QFile file(sFilename);          QFile file(sFilename);
858      if (!file.open(IO_WriteOnly | IO_Truncate)) {          if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
859          appendMessagesError(tr("Could not open \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
860          return false;                          tr("Could not open \"%1\" session file.\n\nSorry.")
861      }                          .arg(sFilename));
862                    return false;
863            }
864    
865          // Tell the world we'll take some time...          // Tell the world we'll take some time...
866          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
867    
868      // Write the file.          // Write the file.
869      int  iErrors = 0;          int  iErrors = 0;
870      QTextStream ts(&file);          QTextStream ts(&file);
871      ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;          ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;
872      ts << "# " << tr("Version")          ts << "# " << tr("Version")
873         << ": " QSAMPLER_VERSION << endl;          << ": " QSAMPLER_VERSION << endl;
874      ts << "# " << tr("Build")          ts << "# " << tr("Build")
875         << ": " __DATE__ " " __TIME__ << endl;          << ": " __DATE__ " " __TIME__ << endl;
876      ts << "#"  << endl;          ts << "#"  << endl;
877      ts << "# " << tr("File")          ts << "# " << tr("File")
878         << ": " << QFileInfo(sFilename).fileName() << endl;          << ": " << QFileInfo(sFilename).fileName() << endl;
879      ts << "# " << tr("Date")          ts << "# " << tr("Date")
880         << ": " << QDate::currentDate().toString("MMM dd yyyy")          << ": " << QDate::currentDate().toString("MMM dd yyyy")
881         << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;          << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;
882      ts << "#"  << endl;          ts << "#"  << endl;
883      ts << endl;          ts << endl;
884    
885          // It is assumed that this new kind of device+session file          // It is assumed that this new kind of device+session file
886          // will be loaded from a complete initialized server...          // will be loaded from a complete initialized server...
# Line 866  bool MainForm::saveSessionFile ( const Q Line 890  bool MainForm::saveSessionFile ( const Q
890    
891          // Audio device mapping.          // Audio device mapping.
892          QMap<int, int> audioDeviceMap;          QMap<int, int> audioDeviceMap;
893          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Audio);          piDeviceIDs = Device::getDevices(m_pClient, Device::Audio);
894          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
895                  ts << endl;                  ts << endl;
896                  qsamplerDevice device(qsamplerDevice::Audio, piDeviceIDs[iDevice]);                  Device device(Device::Audio, piDeviceIDs[iDevice]);
897                  // Audio device specification...                  // Audio device specification...
898                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
899                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
900                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();
901                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
902                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
903                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
904                                          ++deviceParam) {                                          ++deviceParam) {
905                          const qsamplerDeviceParam& param = deviceParam.data();                          const DeviceParam& param = deviceParam.value();
906                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
907                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
908                  }                  }
909                  ts << endl;                  ts << endl;
910                  // Audio channel parameters...                  // Audio channel parameters...
911                  int iPort = 0;                  int iPort = 0;
912                  for (qsamplerDevicePort *pPort = device.ports().first();                  QListIterator<DevicePort *> iter(device.ports());
913                                  pPort;                  while (iter.hasNext()) {
914                                          pPort = device.ports().next(), ++iPort) {                          DevicePort *pPort = iter.next();
915                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
916                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
917                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
918                                                  ++portParam) {                                                  ++portParam) {
919                                  const qsamplerDeviceParam& param = portParam.data();                                  const DeviceParam& param = portParam.value();
920                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
921                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice
922                                          << " " << iPort << " " << portParam.key()                                          << " " << iPort << " " << portParam.key()
923                                          << "='" << param.value << "'" << endl;                                          << "='" << param.value << "'" << endl;
924                          }                          }
925                            iPort++;
926                  }                  }
927                  // Audio device index/id mapping.                  // Audio device index/id mapping.
928                  audioDeviceMap[device.deviceID()] = iDevice;                  audioDeviceMap[device.deviceID()] = iDevice;
929                  // Try to keep it snappy :)                  // Try to keep it snappy :)
930                  QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
931          }          }
932    
933          // MIDI device mapping.          // MIDI device mapping.
934          QMap<int, int> midiDeviceMap;          QMap<int, int> midiDeviceMap;
935          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Midi);          piDeviceIDs = Device::getDevices(m_pClient, Device::Midi);
936          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
937                  ts << endl;                  ts << endl;
938                  qsamplerDevice device(qsamplerDevice::Midi, piDeviceIDs[iDevice]);                  Device device(Device::Midi, piDeviceIDs[iDevice]);
939                  // MIDI device specification...                  // MIDI device specification...
940                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
941                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
942                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();
943                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
944                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
945                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
946                                          ++deviceParam) {                                          ++deviceParam) {
947                          const qsamplerDeviceParam& param = deviceParam.data();                          const DeviceParam& param = deviceParam.value();
948                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
949                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
950                  }                  }
951                  ts << endl;                  ts << endl;
952                  // MIDI port parameters...                  // MIDI port parameters...
953                  int iPort = 0;                  int iPort = 0;
954                  for (qsamplerDevicePort *pPort = device.ports().first();                  QListIterator<DevicePort *> iter(device.ports());
955                                  pPort;                  while (iter.hasNext()) {
956                                          pPort = device.ports().next(), ++iPort) {                          DevicePort *pPort = iter.next();
957                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
958                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
959                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
960                                                  ++portParam) {                                                  ++portParam) {
961                                  const qsamplerDeviceParam& param = portParam.data();                                  const DeviceParam& param = portParam.value();
962                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
963                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice
964                                     << " " << iPort << " " << portParam.key()                                  << " " << iPort << " " << portParam.key()
965                                     << "='" << param.value << "'" << endl;                                  << "='" << param.value << "'" << endl;
966                          }                          }
967                            iPort++;
968                  }                  }
969                  // MIDI device index/id mapping.                  // MIDI device index/id mapping.
970                  midiDeviceMap[device.deviceID()] = iDevice;                  midiDeviceMap[device.deviceID()] = iDevice;
971                  // Try to keep it snappy :)                  // Try to keep it snappy :)
972                  QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
973          }          }
974          ts << endl;          ts << endl;
975    
# Line 1000  bool MainForm::saveSessionFile ( const Q Line 1026  bool MainForm::saveSessionFile ( const Q
1026                                  iErrors++;                                  iErrors++;
1027                          }                          }
1028                          // Try to keep it snappy :)                          // Try to keep it snappy :)
1029                          QApplication::processEvents(QEventLoop::ExcludeUserInput);                          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1030                  }                  }
1031                  ts << endl;                  ts << endl;
1032                  // Check for errors...                  // Check for errors...
# Line 1019  bool MainForm::saveSessionFile ( const Q Line 1045  bool MainForm::saveSessionFile ( const Q
1045  #endif  // CONFIG_MIDI_INSTRUMENT  #endif  // CONFIG_MIDI_INSTRUMENT
1046    
1047          // Sampler channel mapping.          // Sampler channel mapping.
1048      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
1049      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1050          ChannelStrip* pChannelStrip                  ChannelStrip* pChannelStrip
1051                          = static_cast<ChannelStrip *> (wlist.at(iChannel));                          = static_cast<ChannelStrip *> (wlist.at(iChannel));
1052          if (pChannelStrip) {                  if (pChannelStrip) {
1053              qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
1054              if (pChannel) {                          if (pChannel) {
1055                  ts << "# " << tr("Channel") << " " << iChannel << endl;                                  ts << "# " << tr("Channel") << " " << iChannel << endl;
1056                  ts << "ADD CHANNEL" << endl;                                  ts << "ADD CHANNEL" << endl;
1057                                  if (audioDeviceMap.isEmpty()) {                                  if (audioDeviceMap.isEmpty()) {
1058                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel
1059                                                  << " " << pChannel->audioDriver() << endl;                                                  << " " << pChannel->audioDriver() << endl;
# Line 1044  bool MainForm::saveSessionFile ( const Q Line 1070  bool MainForm::saveSessionFile ( const Q
1070                                  }                                  }
1071                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel
1072                                          << " " << pChannel->midiPort() << endl;                                          << " " << pChannel->midiPort() << endl;
1073                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";                                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";
1074                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)                                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
1075                      ts << "ALL";                                          ts << "ALL";
1076                  else                                  else
1077                      ts << pChannel->midiChannel();                                          ts << pChannel->midiChannel();
1078                  ts << endl;                                  ts << endl;
1079                  ts << "LOAD ENGINE " << pChannel->engineName() << " " << iChannel << endl;                                  ts << "LOAD ENGINE " << pChannel->engineName()
1080                                            << " " << iChannel << endl;
1081                                  if (pChannel->instrumentStatus() < 100) ts << "# ";                                  if (pChannel->instrumentStatus() < 100) ts << "# ";
1082                                  ts << "LOAD INSTRUMENT NON_MODAL '" << pChannel->instrumentFile() << "' "                                  ts << "LOAD INSTRUMENT NON_MODAL '"
1083                                            << pChannel->instrumentFile() << "' "
1084                                          << pChannel->instrumentNr() << " " << iChannel << endl;                                          << pChannel->instrumentNr() << " " << iChannel << endl;
1085                                  qsamplerChannelRoutingMap::ConstIterator audioRoute;                                  ChannelRoutingMap::ConstIterator audioRoute;
1086                                  for (audioRoute = pChannel->audioRouting().begin();                                  for (audioRoute = pChannel->audioRouting().begin();
1087                                                  audioRoute != pChannel->audioRouting().end();                                                  audioRoute != pChannel->audioRouting().end();
1088                                                          ++audioRoute) {                                                          ++audioRoute) {
1089                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannel
1090                                                  << " " << audioRoute.key()                                                  << " " << audioRoute.key()
1091                                                  << " " << audioRoute.data() << endl;                                                  << " " << audioRoute.value() << endl;
1092                                  }                                  }
1093                                  ts << "SET CHANNEL VOLUME " << iChannel                                  ts << "SET CHANNEL VOLUME " << iChannel
1094                                          << " " << pChannel->volume() << endl;                                          << " " << pChannel->volume() << endl;
# Line 1110  bool MainForm::saveSessionFile ( const Q Line 1138  bool MainForm::saveSessionFile ( const Q
1138                                          }                                          }
1139                                  }                                  }
1140  #endif  #endif
1141                  ts << endl;                                  ts << endl;
1142              }                          }
1143          }                  }
1144          // Try to keep it snappy :)                  // Try to keep it snappy :)
1145          QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1146      }          }
1147    
1148  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
1149          ts << "# " << tr("Global volume level") << endl;          ts << "# " << tr("Global volume level") << endl;
# Line 1123  bool MainForm::saveSessionFile ( const Q Line 1151  bool MainForm::saveSessionFile ( const Q
1151          ts << endl;          ts << endl;
1152  #endif  #endif
1153    
1154      // Ok. we've wrote it.          // Ok. we've wrote it.
1155      file.close();          file.close();
1156    
1157          // We're fornerly done.          // We're fornerly done.
1158          QApplication::restoreOverrideCursor();          QApplication::restoreOverrideCursor();
1159    
1160      // Have we any errors?          // Have we any errors?
1161      if (iErrors > 0)          if (iErrors > 0) {
1162          appendMessagesError(tr("Some settings could not be saved\nto \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
1163                            tr("Some settings could not be saved\n"
1164      // Save as default session directory.                          "to \"%1\" session file.\n\nSorry.")
1165      if (m_pOptions)                          .arg(sFilename));
1166          m_pOptions->sSessionDir = QFileInfo(sFilename).dirPath(true);          }
1167      // We're not dirty anymore.  
1168      m_iDirtyCount = 0;          // Save as default session directory.
1169      // Stabilize form...          if (m_pOptions)
1170      m_sFilename = sFilename;                  m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();
1171      updateRecentFiles(sFilename);          // We're not dirty anymore.
1172      appendMessages(tr("Save session: \"%1\".").arg(sessionName(m_sFilename)));          m_iDirtyCount = 0;
1173      stabilizeForm();          // Stabilize form...
1174      return true;          m_sFilename = sFilename;
1175            updateRecentFiles(sFilename);
1176            appendMessages(tr("Save session: \"%1\".").arg(sessionName(m_sFilename)));
1177            stabilizeForm();
1178            return true;
1179  }  }
1180    
1181    
1182  // Session change receiver slot.  // Session change receiver slot.
1183  void MainForm::sessionDirty (void)  void MainForm::sessionDirty (void)
1184  {  {
1185      // Just mark the dirty form.          // Just mark the dirty form.
1186      m_iDirtyCount++;          m_iDirtyCount++;
1187      // and update the form status...          // and update the form status...
1188      stabilizeForm();          stabilizeForm();
1189  }  }
1190    
1191    
# Line 1163  void MainForm::sessionDirty (void) Line 1195  void MainForm::sessionDirty (void)
1195  // Create a new sampler session.  // Create a new sampler session.
1196  void MainForm::fileNew (void)  void MainForm::fileNew (void)
1197  {  {
1198      // Of course we'll start clean new.          // Of course we'll start clean new.
1199      newSession();          newSession();
1200  }  }
1201    
1202    
1203  // Open an existing sampler session.  // Open an existing sampler session.
1204  void MainForm::fileOpen (void)  void MainForm::fileOpen (void)
1205  {  {
1206      // Open it right away.          // Open it right away.
1207      openSession();          openSession();
1208  }  }
1209    
1210    
1211  // Open a recent file session.  // Open a recent file session.
1212  void MainForm::fileOpenRecent ( int iIndex )  void MainForm::fileOpenRecent (void)
1213  {  {
1214      // Check if we can safely close the current session...          // Retrive filename index from action data...
1215      if (m_pOptions && closeSession(true)) {          QAction *pAction = qobject_cast<QAction *> (sender());
1216          QString sFilename = m_pOptions->recentFiles[iIndex];          if (pAction && m_pOptions) {
1217          loadSessionFile(sFilename);                  int iIndex = pAction->data().toInt();
1218      }                  if (iIndex >= 0 && iIndex < m_pOptions->recentFiles.count()) {
1219                            QString sFilename = m_pOptions->recentFiles[iIndex];
1220                            // Check if we can safely close the current session...
1221                            if (!sFilename.isEmpty() && closeSession(true))
1222                                    loadSessionFile(sFilename);
1223                    }
1224            }
1225  }  }
1226    
1227    
1228  // Save current sampler session.  // Save current sampler session.
1229  void MainForm::fileSave (void)  void MainForm::fileSave (void)
1230  {  {
1231      // Save it right away.          // Save it right away.
1232      saveSession(false);          saveSession(false);
1233  }  }
1234    
1235    
1236  // Save current sampler session with another name.  // Save current sampler session with another name.
1237  void MainForm::fileSaveAs (void)  void MainForm::fileSaveAs (void)
1238  {  {
1239      // Save it right away, maybe with another name.          // Save it right away, maybe with another name.
1240      saveSession(true);          saveSession(true);
1241  }  }
1242    
1243    
1244  // Reset the sampler instance.  // Reset the sampler instance.
1245  void MainForm::fileReset (void)  void MainForm::fileReset (void)
1246  {  {
1247      if (m_pClient == NULL)          if (m_pClient == NULL)
1248          return;                  return;
1249    
1250      // Ask user whether he/she want's an internal sampler reset...          // Ask user whether he/she want's an internal sampler reset...
1251      if (QMessageBox::warning(this,          if (QMessageBox::warning(this,
1252                  QSAMPLER_TITLE ": " + tr("Warning"),                  QSAMPLER_TITLE ": " + tr("Warning"),
1253          tr("Resetting the sampler instance will close\n"                  tr("Resetting the sampler instance will close\n"
1254             "all device and channel configurations.\n\n"                  "all device and channel configurations.\n\n"
1255             "Please note that this operation may cause\n"                  "Please note that this operation may cause\n"
1256             "temporary MIDI and Audio disruption.\n\n"                  "temporary MIDI and Audio disruption.\n\n"
1257             "Do you want to reset the sampler engine now?"),                  "Do you want to reset the sampler engine now?"),
1258          tr("Reset"), tr("Cancel")) > 0)                  tr("Reset"), tr("Cancel")) > 0)
1259          return;                  return;
1260    
1261          // Trye closing the current session, first...          // Trye closing the current session, first...
1262          if (!closeSession(true))          if (!closeSession(true))
1263                  return;                  return;
1264    
1265      // Just do the reset, after closing down current session...          // Just do the reset, after closing down current session...
1266          // Do the actual sampler reset...          // Do the actual sampler reset...
1267          if (::lscp_reset_sampler(m_pClient) != LSCP_OK) {          if (::lscp_reset_sampler(m_pClient) != LSCP_OK) {
1268                  appendMessagesClient("lscp_reset_sampler");                  appendMessagesClient("lscp_reset_sampler");
# Line 1232  void MainForm::fileReset (void) Line 1270  void MainForm::fileReset (void)
1270                  return;                  return;
1271          }          }
1272    
1273      // Log this.          // Log this.
1274      appendMessages(tr("Sampler reset."));          appendMessages(tr("Sampler reset."));
1275    
1276          // Make it a new session...          // Make it a new session...
1277          newSession();          newSession();
# Line 1243  void MainForm::fileReset (void) Line 1281  void MainForm::fileReset (void)
1281  // Restart the client/server instance.  // Restart the client/server instance.
1282  void MainForm::fileRestart (void)  void MainForm::fileRestart (void)
1283  {  {
1284      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1285          return;                  return;
1286    
1287      bool bRestart = true;          bool bRestart = true;
1288    
1289      // Ask user whether he/she want's a complete restart...          // Ask user whether he/she want's a complete restart...
1290      // (if we're currently up and running)          // (if we're currently up and running)
1291      if (bRestart && m_pClient) {          if (bRestart && m_pClient) {
1292          bRestart = (QMessageBox::warning(this,                  bRestart = (QMessageBox::warning(this,
1293                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
1294              tr("New settings will be effective after\n"                          tr("New settings will be effective after\n"
1295                 "restarting the client/server connection.\n\n"                          "restarting the client/server connection.\n\n"
1296                 "Please note that this operation may cause\n"                          "Please note that this operation may cause\n"
1297                 "temporary MIDI and Audio disruption.\n\n"                          "temporary MIDI and Audio disruption.\n\n"
1298                 "Do you want to restart the connection now?"),                          "Do you want to restart the connection now?"),
1299              tr("Restart"), tr("Cancel")) == 0);                          tr("Restart"), tr("Cancel")) == 0);
1300      }          }
1301    
1302      // Are we still for it?          // Are we still for it?
1303      if (bRestart && closeSession(true)) {          if (bRestart && closeSession(true)) {
1304          // Stop server, it will force the client too.                  // Stop server, it will force the client too.
1305          stopServer();                  stopServer();
1306          // Reschedule a restart...                  // Reschedule a restart...
1307          startSchedule(m_pOptions->iStartDelay);                  startSchedule(m_pOptions->iStartDelay);
1308      }          }
1309  }  }
1310    
1311    
1312  // Exit application program.  // Exit application program.
1313  void MainForm::fileExit (void)  void MainForm::fileExit (void)
1314  {  {
1315      // Go for close the whole thing.          // Go for close the whole thing.
1316      close();          close();
1317  }  }
1318    
1319    
# Line 1285  void MainForm::fileExit (void) Line 1323  void MainForm::fileExit (void)
1323  // Add a new sampler channel.  // Add a new sampler channel.
1324  void MainForm::editAddChannel (void)  void MainForm::editAddChannel (void)
1325  {  {
1326      if (m_pClient == NULL)          if (m_pClient == NULL)
1327          return;                  return;
1328    
1329            // Just create the channel instance...
1330            Channel *pChannel = new Channel();
1331            if (pChannel == NULL)
1332                    return;
1333    
1334      // Just create the channel instance...          // Before we show it up, may be we'll
1335      qsamplerChannel *pChannel = new qsamplerChannel();          // better ask for some initial values?
1336      if (pChannel == NULL)          if (!pChannel->channelSetup(this)) {
1337          return;                  delete pChannel;
1338                    return;
1339      // Before we show it up, may be we'll          }
1340      // better ask for some initial values?  
1341      if (!pChannel->channelSetup(this)) {          // And give it to the strip...
1342          delete pChannel;          // (will own the channel instance, if successful).
1343          return;          if (!createChannelStrip(pChannel)) {
1344      }                  delete pChannel;
1345                    return;
1346      // And give it to the strip (will own the channel instance, if successful).          }
1347      if (!createChannelStrip(pChannel)) {  
1348          delete pChannel;          // Do we auto-arrange?
1349          return;          if (m_pOptions && m_pOptions->bAutoArrange)
1350      }                  channelsArrange();
1351    
1352      // Make that an overall update.          // Make that an overall update.
1353      m_iDirtyCount++;          m_iDirtyCount++;
1354      stabilizeForm();          stabilizeForm();
1355  }  }
1356    
1357    
1358  // Remove current sampler channel.  // Remove current sampler channel.
1359  void MainForm::editRemoveChannel (void)  void MainForm::editRemoveChannel (void)
1360  {  {
1361      if (m_pClient == NULL)          if (m_pClient == NULL)
1362          return;                  return;
1363    
1364      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1365      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1366          return;                  return;
1367    
1368      qsamplerChannel *pChannel = pChannelStrip->channel();          Channel *pChannel = pChannelStrip->channel();
1369      if (pChannel == NULL)          if (pChannel == NULL)
1370          return;                  return;
1371    
1372      // Prompt user if he/she's sure about this...          // Prompt user if he/she's sure about this...
1373      if (m_pOptions && m_pOptions->bConfirmRemove) {          if (m_pOptions && m_pOptions->bConfirmRemove) {
1374          if (QMessageBox::warning(this,                  if (QMessageBox::warning(this,
1375                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
1376              tr("About to remove channel:\n\n"                          tr("About to remove channel:\n\n"
1377                 "%1\n\n"                          "%1\n\n"
1378                 "Are you sure?")                          "Are you sure?")
1379                 .arg(pChannelStrip->caption()),                          .arg(pChannelStrip->windowTitle()),
1380              tr("OK"), tr("Cancel")) > 0)                          tr("OK"), tr("Cancel")) > 0)
1381              return;                          return;
1382      }          }
1383    
1384      // Remove the existing sampler channel.          // Remove the existing sampler channel.
1385      if (!pChannel->removeChannel())          if (!pChannel->removeChannel())
1386          return;                  return;
1387    
1388      // Just delete the channel strip.          // Just delete the channel strip.
1389      delete pChannelStrip;          delete pChannelStrip;
1390    
1391      // Do we auto-arrange?          // Do we auto-arrange?
1392      if (m_pOptions && m_pOptions->bAutoArrange)          if (m_pOptions && m_pOptions->bAutoArrange)
1393          channelsArrange();                  channelsArrange();
1394    
1395      // We'll be dirty, for sure...          // We'll be dirty, for sure...
1396      m_iDirtyCount++;          m_iDirtyCount++;
1397      stabilizeForm();          stabilizeForm();
1398  }  }
1399    
1400    
1401  // Setup current sampler channel.  // Setup current sampler channel.
1402  void MainForm::editSetupChannel (void)  void MainForm::editSetupChannel (void)
1403  {  {
1404      if (m_pClient == NULL)          if (m_pClient == NULL)
1405          return;                  return;
1406    
1407      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1408      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1409          return;                  return;
1410    
1411      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1412      pChannelStrip->channelSetup();          pChannelStrip->channelSetup();
1413  }  }
1414    
1415    
1416  // Edit current sampler channel.  // Edit current sampler channel.
1417  void MainForm::editEditChannel (void)  void MainForm::editEditChannel (void)
1418  {  {
1419      if (m_pClient == NULL)          if (m_pClient == NULL)
1420          return;                  return;
1421    
1422      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1423      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1424          return;                  return;
1425    
1426      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1427      pChannelStrip->channelEdit();          pChannelStrip->channelEdit();
1428  }  }
1429    
1430    
1431  // Reset current sampler channel.  // Reset current sampler channel.
1432  void MainForm::editResetChannel (void)  void MainForm::editResetChannel (void)
1433  {  {
1434      if (m_pClient == NULL)          if (m_pClient == NULL)
1435          return;                  return;
1436    
1437      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1438      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1439          return;                  return;
1440    
1441      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1442      pChannelStrip->channelReset();          pChannelStrip->channelReset();
1443  }  }
1444    
1445    
# Line 1425  void MainForm::editResetAllChannels (voi Line 1468  void MainForm::editResetAllChannels (voi
1468  // Show/hide the main program window menubar.  // Show/hide the main program window menubar.
1469  void MainForm::viewMenubar ( bool bOn )  void MainForm::viewMenubar ( bool bOn )
1470  {  {
1471      if (bOn)          if (bOn)
1472          ui.MenuBar->show();                  m_ui.MenuBar->show();
1473      else          else
1474          ui.MenuBar->hide();                  m_ui.MenuBar->hide();
1475  }  }
1476    
1477    
1478  // Show/hide the main program window toolbar.  // Show/hide the main program window toolbar.
1479  void MainForm::viewToolbar ( bool bOn )  void MainForm::viewToolbar ( bool bOn )
1480  {  {
1481      if (bOn) {          if (bOn) {
1482          ui.fileToolbar->show();                  m_ui.fileToolbar->show();
1483          ui.editToolbar->show();                  m_ui.editToolbar->show();
1484          ui.channelsToolbar->show();                  m_ui.channelsToolbar->show();
1485      } else {          } else {
1486          ui.fileToolbar->hide();                  m_ui.fileToolbar->hide();
1487          ui.editToolbar->hide();                  m_ui.editToolbar->hide();
1488          ui.channelsToolbar->hide();                  m_ui.channelsToolbar->hide();
1489      }          }
1490  }  }
1491    
1492    
1493  // Show/hide the main program window statusbar.  // Show/hide the main program window statusbar.
1494  void MainForm::viewStatusbar ( bool bOn )  void MainForm::viewStatusbar ( bool bOn )
1495  {  {
1496      if (bOn)          if (bOn)
1497          statusBar()->show();                  statusBar()->show();
1498      else          else
1499          statusBar()->hide();                  statusBar()->hide();
1500  }  }
1501    
1502    
1503  // Show/hide the messages window logger.  // Show/hide the messages window logger.
1504  void MainForm::viewMessages ( bool bOn )  void MainForm::viewMessages ( bool bOn )
1505  {  {
1506      if (bOn)          if (bOn)
1507          m_pMessages->show();                  m_pMessages->show();
1508      else          else
1509          m_pMessages->hide();                  m_pMessages->hide();
1510  }  }
1511    
1512    
# Line 1480  void MainForm::viewInstruments (void) Line 1523  void MainForm::viewInstruments (void)
1523                  } else {                  } else {
1524                          m_pInstrumentListForm->show();                          m_pInstrumentListForm->show();
1525                          m_pInstrumentListForm->raise();                          m_pInstrumentListForm->raise();
1526                          m_pInstrumentListForm->setActiveWindow();                          m_pInstrumentListForm->activateWindow();
1527                  }                  }
1528          }          }
1529  }  }
# Line 1499  void MainForm::viewDevices (void) Line 1542  void MainForm::viewDevices (void)
1542                  } else {                  } else {
1543                          m_pDeviceForm->show();                          m_pDeviceForm->show();
1544                          m_pDeviceForm->raise();                          m_pDeviceForm->raise();
1545                          m_pDeviceForm->setActiveWindow();                          m_pDeviceForm->activateWindow();
1546                  }                  }
1547          }          }
1548  }  }
# Line 1508  void MainForm::viewDevices (void) Line 1551  void MainForm::viewDevices (void)
1551  // Show options dialog.  // Show options dialog.
1552  void MainForm::viewOptions (void)  void MainForm::viewOptions (void)
1553  {  {
1554      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1555          return;                  return;
1556    
1557      OptionsForm* pOptionsForm = new OptionsForm(this);          OptionsForm* pOptionsForm = new OptionsForm(this);
1558      if (pOptionsForm) {          if (pOptionsForm) {
1559          // Check out some initial nullities(tm)...                  // Check out some initial nullities(tm)...
1560          ChannelStrip* pChannelStrip = activeChannelStrip();                  ChannelStrip* pChannelStrip = activeChannelStrip();
1561          if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)
1562              m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();
1563          if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)
1564              m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
1565          // To track down deferred or immediate changes.                  // To track down deferred or immediate changes.
1566          QString sOldServerHost      = m_pOptions->sServerHost;                  QString sOldServerHost      = m_pOptions->sServerHost;
1567          int     iOldServerPort      = m_pOptions->iServerPort;                  int     iOldServerPort      = m_pOptions->iServerPort;
1568          int     iOldServerTimeout   = m_pOptions->iServerTimeout;                  int     iOldServerTimeout   = m_pOptions->iServerTimeout;
1569          bool    bOldServerStart     = m_pOptions->bServerStart;                  bool    bOldServerStart     = m_pOptions->bServerStart;
1570          QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;                  QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;
1571          QString sOldDisplayFont     = m_pOptions->sDisplayFont;                  QString sOldDisplayFont     = m_pOptions->sDisplayFont;
1572          bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;                  bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;
1573          int     iOldMaxVolume       = m_pOptions->iMaxVolume;                  int     iOldMaxVolume       = m_pOptions->iMaxVolume;
1574          QString sOldMessagesFont    = m_pOptions->sMessagesFont;                  QString sOldMessagesFont    = m_pOptions->sMessagesFont;
1575          bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;                  bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;
1576          bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;                  bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;
1577          int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;                  int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;
1578          int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;                  int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;
1579          bool    bOldCompletePath    = m_pOptions->bCompletePath;                  bool    bOldCompletePath    = m_pOptions->bCompletePath;
1580          bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;                  bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;
1581          int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;                  int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;
1582          // Load the current setup settings.                  // Load the current setup settings.
1583          pOptionsForm->setup(m_pOptions);                  pOptionsForm->setup(m_pOptions);
1584          // Show the setup dialog...                  // Show the setup dialog...
1585          if (pOptionsForm->exec()) {                  if (pOptionsForm->exec()) {
1586              // Warn if something will be only effective on next run.                          // Warn if something will be only effective on next run.
1587              if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1588                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||
1589                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||                                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||
1590                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {                                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {
1591                  QMessageBox::information(this,                                  QMessageBox::information(this,
1592                                          QSAMPLER_TITLE ": " + tr("Information"),                                          QSAMPLER_TITLE ": " + tr("Information"),
1593                      tr("Some settings may be only effective\n"                                          tr("Some settings may be only effective\n"
1594                         "next time you start this program."), tr("OK"));                                          "next time you start this program."), tr("OK"));
1595                  updateMessagesCapture();                                  updateMessagesCapture();
1596              }                          }
1597              // Check wheather something immediate has changed.                          // Check wheather something immediate has changed.
1598              if (( bOldCompletePath && !m_pOptions->bCompletePath) ||                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||
1599                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||
1600                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
1601                  updateRecentFilesMenu();                                  updateRecentFilesMenu();
1602              if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||                          if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||
1603                  (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))                                  (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))
1604                  updateInstrumentNames();                                  updateInstrumentNames();
1605              if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||                          if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||
1606                  (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))                                  (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))
1607                  updateDisplayEffect();                                  updateDisplayEffect();
1608              if (sOldDisplayFont != m_pOptions->sDisplayFont)                          if (sOldDisplayFont != m_pOptions->sDisplayFont)
1609                  updateDisplayFont();                                  updateDisplayFont();
1610              if (iOldMaxVolume != m_pOptions->iMaxVolume)                          if (iOldMaxVolume != m_pOptions->iMaxVolume)
1611                  updateMaxVolume();                                  updateMaxVolume();
1612              if (sOldMessagesFont != m_pOptions->sMessagesFont)                          if (sOldMessagesFont != m_pOptions->sMessagesFont)
1613                  updateMessagesFont();                                  updateMessagesFont();
1614              if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||                          if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||
1615                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||                                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||
1616                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))                                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))
1617                  updateMessagesLimit();                                  updateMessagesLimit();
1618              // And now the main thing, whether we'll do client/server recycling?                          // And now the main thing, whether we'll do client/server recycling?
1619              if ((sOldServerHost != m_pOptions->sServerHost) ||                          if ((sOldServerHost != m_pOptions->sServerHost) ||
1620                  (iOldServerPort != m_pOptions->iServerPort) ||                                  (iOldServerPort != m_pOptions->iServerPort) ||
1621                  (iOldServerTimeout != m_pOptions->iServerTimeout) ||                                  (iOldServerTimeout != m_pOptions->iServerTimeout) ||
1622                  ( bOldServerStart && !m_pOptions->bServerStart) ||                                  ( bOldServerStart && !m_pOptions->bServerStart) ||
1623                  (!bOldServerStart &&  m_pOptions->bServerStart) ||                                  (!bOldServerStart &&  m_pOptions->bServerStart) ||
1624                  (sOldServerCmdLine != m_pOptions->sServerCmdLine && m_pOptions->bServerStart))                                  (sOldServerCmdLine != m_pOptions->sServerCmdLine
1625                  fileRestart();                                  && m_pOptions->bServerStart))
1626          }                                  fileRestart();
1627          // Done.                  }
1628          delete pOptionsForm;                  // Done.
1629      }                  delete pOptionsForm;
1630            }
1631    
1632      // This makes it.          // This makes it.
1633      stabilizeForm();          stabilizeForm();
1634  }  }
1635    
1636    
# Line 1596  void MainForm::viewOptions (void) Line 1640  void MainForm::viewOptions (void)
1640  // Arrange channel strips.  // Arrange channel strips.
1641  void MainForm::channelsArrange (void)  void MainForm::channelsArrange (void)
1642  {  {
1643      // Full width vertical tiling          // Full width vertical tiling
1644      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
1645      if (wlist.isEmpty())          if (wlist.isEmpty())
1646          return;                  return;
1647    
1648      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
1649      int y = 0;          int y = 0;
1650      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1651          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
1652      /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {          /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {
1653              // Prevent flicker...                          // Prevent flicker...
1654              pChannelStrip->hide();                          pChannelStrip->hide();
1655              pChannelStrip->showNormal();                          pChannelStrip->showNormal();
1656          }   */                  }   */
1657          pChannelStrip->adjustSize();                  pChannelStrip->adjustSize();
1658          int iWidth  = m_pWorkspace->width();                  int iWidth  = m_pWorkspace->width();
1659          if (iWidth < pChannelStrip->width())                  if (iWidth < pChannelStrip->width())
1660              iWidth = pChannelStrip->width();                          iWidth = pChannelStrip->width();
1661      //  int iHeight = pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();          //  int iHeight = pChannelStrip->height()
1662          int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();          //              + pChannelStrip->parentWidget()->baseSize().height();
1663          pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);                  int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();
1664          y += iHeight;                  pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);
1665      }                  y += iHeight;
1666      m_pWorkspace->setUpdatesEnabled(true);          }
1667            m_pWorkspace->setUpdatesEnabled(true);
1668    
1669      stabilizeForm();          stabilizeForm();
1670  }  }
1671    
1672    
1673  // Auto-arrange channel strips.  // Auto-arrange channel strips.
1674  void MainForm::channelsAutoArrange ( bool bOn )  void MainForm::channelsAutoArrange ( bool bOn )
1675  {  {
1676      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1677          return;                  return;
1678    
1679      // Toggle the auto-arrange flag.          // Toggle the auto-arrange flag.
1680      m_pOptions->bAutoArrange = bOn;          m_pOptions->bAutoArrange = bOn;
1681    
1682      // If on, update whole workspace...          // If on, update whole workspace...
1683      if (m_pOptions->bAutoArrange)          if (m_pOptions->bAutoArrange)
1684          channelsArrange();                  channelsArrange();
1685  }  }
1686    
1687    
# Line 1646  void MainForm::channelsAutoArrange ( boo Line 1691  void MainForm::channelsAutoArrange ( boo
1691  // Show information about the Qt toolkit.  // Show information about the Qt toolkit.
1692  void MainForm::helpAboutQt (void)  void MainForm::helpAboutQt (void)
1693  {  {
1694      QMessageBox::aboutQt(this);          QMessageBox::aboutQt(this);
1695  }  }
1696    
1697    
1698  // Show information about application program.  // Show information about application program.
1699  void MainForm::helpAbout (void)  void MainForm::helpAbout (void)
1700  {  {
1701      // Stuff the about box text...          // Stuff the about box text...
1702      QString sText = "<p>\n";          QString sText = "<p>\n";
1703      sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";          sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";
1704      sText += "<br />\n";          sText += "<br />\n";
1705      sText += tr("Version") + ": <b>" QSAMPLER_VERSION "</b><br />\n";          sText += tr("Version") + ": <b>" QSAMPLER_VERSION "</b><br />\n";
1706      sText += "<small>" + tr("Build") + ": " __DATE__ " " __TIME__ "</small><br />\n";          sText += "<small>" + tr("Build") + ": " __DATE__ " " __TIME__ "</small><br />\n";
1707  #ifdef CONFIG_DEBUG  #ifdef CONFIG_DEBUG
1708      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1709      sText += tr("Debugging option enabled.");          sText += tr("Debugging option enabled.");
1710      sText += "</font></small><br />";          sText += "</font></small><br />";
1711  #endif  #endif
1712  #ifndef CONFIG_LIBGIG  #ifndef CONFIG_LIBGIG
1713      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1714      sText += tr("GIG (libgig) file support disabled.");          sText += tr("GIG (libgig) file support disabled.");
1715      sText += "</font></small><br />";          sText += "</font></small><br />";
1716  #endif  #endif
1717  #ifndef CONFIG_INSTRUMENT_NAME  #ifndef CONFIG_INSTRUMENT_NAME
1718      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1719      sText += tr("LSCP (liblscp) instrument_name support disabled.");          sText += tr("LSCP (liblscp) instrument_name support disabled.");
1720      sText += "</font></small><br />";          sText += "</font></small><br />";
1721  #endif  #endif
1722  #ifndef CONFIG_MUTE_SOLO  #ifndef CONFIG_MUTE_SOLO
1723      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1724      sText += tr("Sampler channel Mute/Solo support disabled.");          sText += tr("Sampler channel Mute/Solo support disabled.");
1725      sText += "</font></small><br />";          sText += "</font></small><br />";
1726  #endif  #endif
1727  #ifndef CONFIG_AUDIO_ROUTING  #ifndef CONFIG_AUDIO_ROUTING
1728      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1729      sText += tr("LSCP (liblscp) audio_routing support disabled.");          sText += tr("LSCP (liblscp) audio_routing support disabled.");
1730      sText += "</font></small><br />";          sText += "</font></small><br />";
1731  #endif  #endif
1732  #ifndef CONFIG_FXSEND  #ifndef CONFIG_FXSEND
1733      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1734      sText += tr("Sampler channel Effect Sends support disabled.");          sText += tr("Sampler channel Effect Sends support disabled.");
1735      sText += "</font></small><br />";          sText += "</font></small><br />";
1736  #endif  #endif
1737  #ifndef CONFIG_VOLUME  #ifndef CONFIG_VOLUME
1738      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1739      sText += tr("Global volume support disabled.");          sText += tr("Global volume support disabled.");
1740      sText += "</font></small><br />";          sText += "</font></small><br />";
1741  #endif  #endif
1742  #ifndef CONFIG_MIDI_INSTRUMENT  #ifndef CONFIG_MIDI_INSTRUMENT
1743      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1744      sText += tr("MIDI instrument mapping support disabled.");          sText += tr("MIDI instrument mapping support disabled.");
1745      sText += "</font></small><br />";          sText += "</font></small><br />";
1746  #endif  #endif
1747  #ifndef CONFIG_EDIT_INSTRUMENT  #ifndef CONFIG_EDIT_INSTRUMENT
1748      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1749      sText += tr("Instrument editing support disabled.");          sText += tr("Instrument editing support disabled.");
1750      sText += "</font></small><br />";          sText += "</font></small><br />";
1751  #endif  #endif
1752      sText += "<br />\n";          sText += "<br />\n";
1753      sText += tr("Using") + ": ";          sText += tr("Using") + ": ";
1754      sText += ::lscp_client_package();          sText += ::lscp_client_package();
1755      sText += " ";          sText += " ";
1756      sText += ::lscp_client_version();          sText += ::lscp_client_version();
1757  #ifdef CONFIG_LIBGIG  #ifdef CONFIG_LIBGIG
1758      sText += ", ";          sText += ", ";
1759      sText += gig::libraryName().c_str();          sText += gig::libraryName().c_str();
1760      sText += " ";          sText += " ";
1761      sText += gig::libraryVersion().c_str();          sText += gig::libraryVersion().c_str();
1762  #endif  #endif
1763      sText += "<br />\n";          sText += "<br />\n";
1764      sText += "<br />\n";          sText += "<br />\n";
1765      sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";          sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";
1766      sText += "<br />\n";          sText += "<br />\n";
1767      sText += "<small>";          sText += "<small>";
1768      sText += QSAMPLER_COPYRIGHT "<br />\n";          sText += QSAMPLER_COPYRIGHT "<br />\n";
1769      sText += QSAMPLER_COPYRIGHT2 "<br />\n";          sText += QSAMPLER_COPYRIGHT2 "<br />\n";
1770      sText += "<br />\n";          sText += "<br />\n";
1771      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";
1772      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.");
1773      sText += "</small>";          sText += "</small>";
1774      sText += "</p>\n";          sText += "</p>\n";
1775    
1776      QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);          QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);
1777  }  }
1778    
1779    
# Line 1737  void MainForm::helpAbout (void) Line 1782  void MainForm::helpAbout (void)
1782    
1783  void MainForm::stabilizeForm (void)  void MainForm::stabilizeForm (void)
1784  {  {
1785      // Update the main application caption...          // Update the main application caption...
1786      QString sSessionName = sessionName(m_sFilename);          QString sSessionName = sessionName(m_sFilename);
1787      if (m_iDirtyCount > 0)          if (m_iDirtyCount > 0)
1788          sSessionName += " *";                  sSessionName += " *";
1789      setCaption(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));
1790    
1791      // Update the main menu state...          // Update the main menu state...
1792      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1793      bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);          bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);
1794      bool bHasChannel = (bHasClient && pChannelStrip != NULL);          bool bHasChannel = (bHasClient && pChannelStrip != NULL);
1795      ui.fileNewAction->setEnabled(bHasClient);          m_ui.fileNewAction->setEnabled(bHasClient);
1796      ui.fileOpenAction->setEnabled(bHasClient);          m_ui.fileOpenAction->setEnabled(bHasClient);
1797      ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
1798      ui.fileSaveAsAction->setEnabled(bHasClient);          m_ui.fileSaveAsAction->setEnabled(bHasClient);
1799      ui.fileResetAction->setEnabled(bHasClient);          m_ui.fileResetAction->setEnabled(bHasClient);
1800      ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);          m_ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);
1801      ui.editAddChannelAction->setEnabled(bHasClient);          m_ui.editAddChannelAction->setEnabled(bHasClient);
1802      ui.editRemoveChannelAction->setEnabled(bHasChannel);          m_ui.editRemoveChannelAction->setEnabled(bHasChannel);
1803      ui.editSetupChannelAction->setEnabled(bHasChannel);          m_ui.editSetupChannelAction->setEnabled(bHasChannel);
1804  #ifdef CONFIG_EDIT_INSTRUMENT  #ifdef CONFIG_EDIT_INSTRUMENT
1805      ui.editEditChannelAction->setEnabled(bHasChannel);          m_ui.editEditChannelAction->setEnabled(bHasChannel);
1806  #else  #else
1807      ui.editEditChannelAction->setEnabled(false);          m_ui.editEditChannelAction->setEnabled(false);
1808  #endif  #endif
1809      ui.editResetChannelAction->setEnabled(bHasChannel);          m_ui.editResetChannelAction->setEnabled(bHasChannel);
1810      ui.editResetAllChannelsAction->setEnabled(bHasChannel);          m_ui.editResetAllChannelsAction->setEnabled(bHasChannel);
1811      ui.viewMessagesAction->setOn(m_pMessages && m_pMessages->isVisible());          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());
1812  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
1813          ui.viewInstrumentsAction->setOn(m_pInstrumentListForm          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm
1814                  && m_pInstrumentListForm->isVisible());                  && m_pInstrumentListForm->isVisible());
1815          ui.viewInstrumentsAction->setEnabled(bHasClient);          m_ui.viewInstrumentsAction->setEnabled(bHasClient);
1816  #else  #else
1817          ui.viewInstrumentsAction->setEnabled(false);          m_ui.viewInstrumentsAction->setEnabled(false);
1818  #endif  #endif
1819          ui.viewDevicesAction->setOn(m_pDeviceForm          m_ui.viewDevicesAction->setChecked(m_pDeviceForm
1820                  && m_pDeviceForm->isVisible());                  && m_pDeviceForm->isVisible());
1821      ui.viewDevicesAction->setEnabled(bHasClient);          m_ui.viewDevicesAction->setEnabled(bHasClient);
1822      ui.channelsArrangeAction->setEnabled(bHasChannel);          m_ui.channelsArrangeAction->setEnabled(bHasChannel);
1823    
1824  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
1825          // Toolbar widgets are also affected...          // Toolbar widgets are also affected...
1826      m_pVolumeSlider->setEnabled(bHasClient);          m_pVolumeSlider->setEnabled(bHasClient);
1827      m_pVolumeSpinBox->setEnabled(bHasClient);          m_pVolumeSpinBox->setEnabled(bHasClient);
1828  #endif  #endif
1829    
1830      // Client/Server status...          // Client/Server status...
1831      if (bHasClient) {          if (bHasClient) {
1832          m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));                  m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));
1833          m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost + ":" + QString::number(m_pOptions->iServerPort));                  m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost
1834      } else {                          + ':' + QString::number(m_pOptions->iServerPort));
1835          m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();          } else {
1836          m_statusItem[QSAMPLER_STATUS_SERVER]->clear();                  m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();
1837      }                  m_statusItem[QSAMPLER_STATUS_SERVER]->clear();
1838      // Channel status...          }
1839      if (bHasChannel)          // Channel status...
1840          m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->caption());          if (bHasChannel)
1841      else                  m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->windowTitle());
1842          m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();          else
1843      // Session status...                  m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();
1844      if (m_iDirtyCount > 0)          // Session status...
1845          m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));          if (m_iDirtyCount > 0)
1846      else                  m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));
1847          m_statusItem[QSAMPLER_STATUS_SESSION]->clear();          else
1848                    m_statusItem[QSAMPLER_STATUS_SESSION]->clear();
1849    
1850      // Recent files menu.          // Recent files menu.
1851      m_pRecentFilesMenu->setEnabled(bHasClient && m_pOptions->recentFiles.count() > 0);          m_ui.fileOpenRecentMenu->setEnabled(m_pOptions->recentFiles.count() > 0);
1852  }  }
1853    
1854    
# Line 1842  void MainForm::volumeChanged ( int iVolu Line 1888  void MainForm::volumeChanged ( int iVolu
1888  void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)  void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)
1889  {  {
1890          // Add this strip to the changed list...          // Add this strip to the changed list...
1891          if (m_changedStrips.containsRef(pChannelStrip) == 0) {          if (!m_changedStrips.contains(pChannelStrip)) {
1892                  m_changedStrips.append(pChannelStrip);                  m_changedStrips.append(pChannelStrip);
1893                  pChannelStrip->resetErrorCount();                  pChannelStrip->resetErrorCount();
1894          }          }
1895    
1896      // Just mark the dirty form.          // Just mark the dirty form.
1897      m_iDirtyCount++;          m_iDirtyCount++;
1898      // and update the form status...          // and update the form status...
1899      stabilizeForm();          stabilizeForm();
1900  }  }
1901    
1902    
# Line 1870  void MainForm::updateSession (void) Line 1916  void MainForm::updateSession (void)
1916          if (iMaps < 0)          if (iMaps < 0)
1917                  appendMessagesClient("lscp_get_midi_instrument_maps");                  appendMessagesClient("lscp_get_midi_instrument_maps");
1918          else if (iMaps < 1) {          else if (iMaps < 1) {
1919                  ::lscp_add_midi_instrument_map(m_pClient, tr("Chromatic").latin1());                  ::lscp_add_midi_instrument_map(m_pClient,
1920                  ::lscp_add_midi_instrument_map(m_pClient, tr("Drum Kits").latin1());                          tr("Chromatic").toUtf8().constData());
1921                    ::lscp_add_midi_instrument_map(m_pClient,
1922                            tr("Drum Kits").toUtf8().constData());
1923          }          }
1924  #endif  #endif
1925    
# Line 1880  void MainForm::updateSession (void) Line 1928  void MainForm::updateSession (void)
1928          if (piChannelIDs == NULL) {          if (piChannelIDs == NULL) {
1929                  if (::lscp_client_get_errno(m_pClient)) {                  if (::lscp_client_get_errno(m_pClient)) {
1930                          appendMessagesClient("lscp_list_channels");                          appendMessagesClient("lscp_list_channels");
1931                          appendMessagesError(tr("Could not get current list of channels.\n\nSorry."));                          appendMessagesError(
1932                                    tr("Could not get current list of channels.\n\nSorry."));
1933                  }                  }
1934          } else {          } else {
1935                  // Try to (re)create each channel.                  // Try to (re)create each channel.
# Line 1888  void MainForm::updateSession (void) Line 1937  void MainForm::updateSession (void)
1937                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {
1938                          // Check if theres already a channel strip for this one...                          // Check if theres already a channel strip for this one...
1939                          if (!channelStrip(piChannelIDs[iChannel]))                          if (!channelStrip(piChannelIDs[iChannel]))
1940                                  createChannelStrip(new qsamplerChannel(piChannelIDs[iChannel]));                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));
1941                  }                  }
1942                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
1943          }          }
1944    
1945      // Do we auto-arrange?          // Do we auto-arrange?
1946      if (m_pOptions && m_pOptions->bAutoArrange)          if (m_pOptions && m_pOptions->bAutoArrange)
1947          channelsArrange();                  channelsArrange();
1948    
1949          // Remember to refresh devices and instruments...          // Remember to refresh devices and instruments...
1950          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
1951              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
1952          if (m_pDeviceForm)          if (m_pDeviceForm)
1953              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
1954  }  }
1955    
1956    
1957  // Update the recent files list and menu.  // Update the recent files list and menu.
1958  void MainForm::updateRecentFiles ( const QString& sFilename )  void MainForm::updateRecentFiles ( const QString& sFilename )
1959  {  {
1960      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1961          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);  
1962    
1963      // May update the menu.          // Remove from list if already there (avoid duplicates)
1964      updateRecentFilesMenu();          int iIndex = m_pOptions->recentFiles.indexOf(sFilename);
1965            if (iIndex >= 0)
1966                    m_pOptions->recentFiles.removeAt(iIndex);
1967            // Put it to front...
1968            m_pOptions->recentFiles.push_front(sFilename);
1969  }  }
1970    
1971    
1972  // Update the recent files list and menu.  // Update the recent files list and menu.
1973  void MainForm::updateRecentFilesMenu (void)  void MainForm::updateRecentFilesMenu (void)
1974  {  {
1975      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1976          return;                  return;
1977    
1978            // Time to keep the list under limits.
1979            int iRecentFiles = m_pOptions->recentFiles.count();
1980            while (iRecentFiles > m_pOptions->iMaxRecentFiles) {
1981                    m_pOptions->recentFiles.pop_back();
1982                    iRecentFiles--;
1983            }
1984    
1985      // Time to keep the list under limits.          // Rebuild the recent files menu...
1986      int iRecentFiles = m_pOptions->recentFiles.count();          m_ui.fileOpenRecentMenu->clear();
1987      while (iRecentFiles > m_pOptions->iMaxRecentFiles) {          for (int i = 0; i < iRecentFiles; i++) {
1988          m_pOptions->recentFiles.pop_back();                  const QString& sFilename = m_pOptions->recentFiles[i];
1989          iRecentFiles--;                  if (QFileInfo(sFilename).exists()) {
1990      }                          QAction *pAction = m_ui.fileOpenRecentMenu->addAction(
1991                                    QString("&%1 %2").arg(i + 1).arg(sessionName(sFilename)),
1992      // rebuild the recent files menu...                                  this, SLOT(fileOpenRecent()));
1993      m_pRecentFilesMenu->clear();                          pAction->setData(i);
1994      for (int i = 0; i < iRecentFiles; i++) {                  }
1995          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);  
         }  
     }  
1996  }  }
1997    
1998    
1999  // Force update of the channels instrument names mode.  // Force update of the channels instrument names mode.
2000  void MainForm::updateInstrumentNames (void)  void MainForm::updateInstrumentNames (void)
2001  {  {
2002      // Full channel list update...          // Full channel list update...
2003      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2004      if (wlist.isEmpty())          if (wlist.isEmpty())
2005          return;                  return;
2006    
2007      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2008      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2009          ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);                  ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);
2010          if (pChannelStrip)                  if (pChannelStrip)
2011              pChannelStrip->updateInstrumentName(true);                          pChannelStrip->updateInstrumentName(true);
2012      }          }
2013      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2014  }  }
2015    
2016    
2017  // Force update of the channels display font.  // Force update of the channels display font.
2018  void MainForm::updateDisplayFont (void)  void MainForm::updateDisplayFont (void)
2019  {  {
2020      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2021          return;                  return;
2022    
2023            // Check if display font is legal.
2024            if (m_pOptions->sDisplayFont.isEmpty())
2025                    return;
2026            // Realize it.
2027            QFont font;
2028            if (!font.fromString(m_pOptions->sDisplayFont))
2029                    return;
2030    
2031            // Full channel list update...
2032            QWidgetList wlist = m_pWorkspace->windowList();
2033            if (wlist.isEmpty())
2034                    return;
2035    
2036      // Check if display font is legal.          m_pWorkspace->setUpdatesEnabled(false);
2037      if (m_pOptions->sDisplayFont.isEmpty())          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2038          return;                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2039      // Realize it.                  if (pChannelStrip)
2040      QFont font;                          pChannelStrip->setDisplayFont(font);
2041      if (!font.fromString(m_pOptions->sDisplayFont))          }
2042          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);  
2043  }  }
2044    
2045    
2046  // Update channel strips background effect.  // Update channel strips background effect.
2047  void MainForm::updateDisplayEffect (void)  void MainForm::updateDisplayEffect (void)
2048  {  {
2049     QPixmap pm;          // Full channel list update...
2050      if (m_pOptions->bDisplayEffect)          QWidgetList wlist = m_pWorkspace->windowList();
2051          pm = QPixmap(":/qsampler/pixmaps/displaybg1.png");          if (wlist.isEmpty())
2052                    return;
2053      // Full channel list update...  
2054      QWidgetList wlist = m_pWorkspace->windowList();          m_pWorkspace->setUpdatesEnabled(false);
2055      if (wlist.isEmpty())          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2056          return;                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2057                    if (pChannelStrip)
2058      m_pWorkspace->setUpdatesEnabled(false);                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2059      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          }
2060          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);          m_pWorkspace->setUpdatesEnabled(true);
         if (pChannelStrip)  
             pChannelStrip->setDisplayBackground(pm);  
     }  
     m_pWorkspace->setUpdatesEnabled(true);  
2061  }  }
2062    
2063    
2064  // Force update of the channels maximum volume setting.  // Force update of the channels maximum volume setting.
2065  void MainForm::updateMaxVolume (void)  void MainForm::updateMaxVolume (void)
2066  {  {
2067      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2068          return;                  return;
2069    
2070  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2071          m_iVolumeChanging++;          m_iVolumeChanging++;
2072          m_pVolumeSlider->setMaxValue(m_pOptions->iMaxVolume);          m_pVolumeSlider->setMaximum(m_pOptions->iMaxVolume);
2073          m_pVolumeSpinBox->setMaxValue(m_pOptions->iMaxVolume);          m_pVolumeSpinBox->setMaximum(m_pOptions->iMaxVolume);
2074          m_iVolumeChanging--;          m_iVolumeChanging--;
2075  #endif  #endif
2076    
2077      // Full channel list update...          // Full channel list update...
2078      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2079      if (wlist.isEmpty())          if (wlist.isEmpty())
2080          return;                  return;
2081    
2082      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2083      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2084          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2085          if (pChannelStrip)                  if (pChannelStrip)
2086              pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                          pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2087      }          }
2088      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2089  }  }
2090    
2091    
# Line 2052  void MainForm::updateMaxVolume (void) Line 2095  void MainForm::updateMaxVolume (void)
2095  // Messages output methods.  // Messages output methods.
2096  void MainForm::appendMessages( const QString& s )  void MainForm::appendMessages( const QString& s )
2097  {  {
2098      if (m_pMessages)          if (m_pMessages)
2099          m_pMessages->appendMessages(s);                  m_pMessages->appendMessages(s);
2100    
2101      statusBar()->message(s, 3000);          statusBar()->showMessage(s, 3000);
2102  }  }
2103    
2104  void MainForm::appendMessagesColor( const QString& s, const QString& c )  void MainForm::appendMessagesColor( const QString& s, const QString& c )
2105  {  {
2106      if (m_pMessages)          if (m_pMessages)
2107          m_pMessages->appendMessagesColor(s, c);                  m_pMessages->appendMessagesColor(s, c);
2108    
2109      statusBar()->message(s, 3000);          statusBar()->showMessage(s, 3000);
2110  }  }
2111    
2112  void MainForm::appendMessagesText( const QString& s )  void MainForm::appendMessagesText( const QString& s )
2113  {  {
2114      if (m_pMessages)          if (m_pMessages)
2115          m_pMessages->appendMessagesText(s);                  m_pMessages->appendMessagesText(s);
2116  }  }
2117    
2118  void MainForm::appendMessagesError( const QString& s )  void MainForm::appendMessagesError( const QString& s )
2119  {  {
2120      if (m_pMessages)          if (m_pMessages)
2121          m_pMessages->show();                  m_pMessages->show();
2122    
2123      appendMessagesColor(s.simplified(), "#ff0000");          appendMessagesColor(s.simplified(), "#ff0000");
2124    
2125          // Make it look responsive...:)          // Make it look responsive...:)
2126          QApplication::processEvents(QEventLoop::ExcludeUserInput);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2127    
2128      QMessageBox::critical(this,          QMessageBox::critical(this,
2129                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));
2130  }  }
2131    
# Line 2090  void MainForm::appendMessagesError( cons Line 2133  void MainForm::appendMessagesError( cons
2133  // This is a special message format, just for client results.  // This is a special message format, just for client results.
2134  void MainForm::appendMessagesClient( const QString& s )  void MainForm::appendMessagesClient( const QString& s )
2135  {  {
2136      if (m_pClient == NULL)          if (m_pClient == NULL)
2137          return;                  return;
2138    
2139      appendMessagesColor(s + QString(": %1 (errno=%2)")          appendMessagesColor(s + QString(": %1 (errno=%2)")
2140          .arg(::lscp_client_get_result(m_pClient))                  .arg(::lscp_client_get_result(m_pClient))
2141          .arg(::lscp_client_get_errno(m_pClient)), "#996666");                  .arg(::lscp_client_get_errno(m_pClient)), "#996666");
2142    
2143          // Make it look responsive...:)          // Make it look responsive...:)
2144          QApplication::processEvents(QEventLoop::ExcludeUserInput);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2145  }  }
2146    
2147    
2148  // Force update of the messages font.  // Force update of the messages font.
2149  void MainForm::updateMessagesFont (void)  void MainForm::updateMessagesFont (void)
2150  {  {
2151      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2152          return;                  return;
2153    
2154      if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {          if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {
2155          QFont font;                  QFont font;
2156          if (font.fromString(m_pOptions->sMessagesFont))                  if (font.fromString(m_pOptions->sMessagesFont))
2157              m_pMessages->setMessagesFont(font);                          m_pMessages->setMessagesFont(font);
2158      }          }
2159  }  }
2160    
2161    
2162  // Update messages window line limit.  // Update messages window line limit.
2163  void MainForm::updateMessagesLimit (void)  void MainForm::updateMessagesLimit (void)
2164  {  {
2165      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2166          return;                  return;
2167    
2168      if (m_pMessages) {          if (m_pMessages) {
2169          if (m_pOptions->bMessagesLimit)                  if (m_pOptions->bMessagesLimit)
2170              m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);                          m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);
2171          else                  else
2172              m_pMessages->setMessagesLimit(-1);                          m_pMessages->setMessagesLimit(-1);
2173      }          }
2174  }  }
2175    
2176    
2177  // Enablement of the messages capture feature.  // Enablement of the messages capture feature.
2178  void MainForm::updateMessagesCapture (void)  void MainForm::updateMessagesCapture (void)
2179  {  {
2180      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2181          return;                  return;
2182    
2183      if (m_pMessages)          if (m_pMessages)
2184          m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);                  m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);
2185  }  }
2186    
2187    
# Line 2146  void MainForm::updateMessagesCapture (vo Line 2189  void MainForm::updateMessagesCapture (vo
2189  // qsamplerMainForm -- MDI channel strip management.  // qsamplerMainForm -- MDI channel strip management.
2190    
2191  // The channel strip creation executive.  // The channel strip creation executive.
2192  ChannelStrip* MainForm::createChannelStrip(qsamplerChannel* pChannel)  ChannelStrip* MainForm::createChannelStrip ( Channel *pChannel )
2193  {  {
2194      if (m_pClient == NULL || pChannel == NULL)          if (m_pClient == NULL || pChannel == NULL)
2195          return NULL;                  return NULL;
2196    
2197      // Prepare for auto-arrange?          // Add a new channel itema...
2198      ChannelStrip* pChannelStrip = NULL;          ChannelStrip *pChannelStrip = new ChannelStrip();
2199      int y = 0;          if (pChannelStrip == NULL)
2200      if (m_pOptions && m_pOptions->bAutoArrange) {                  return NULL;
         QWidgetList wlist = m_pWorkspace->windowList();  
         for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {  
             pChannelStrip = (ChannelStrip *) wlist.at(iChannel);  
                         if (pChannelStrip) {  
                         //  y += pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();  
                                 y += pChannelStrip->parentWidget()->frameGeometry().height();  
                         }  
         }  
     }  
2201    
2202      // Add a new channel itema...          // Set some initial channel strip options...
2203      pChannelStrip = new ChannelStrip();          if (m_pOptions) {
2204      if (pChannelStrip == NULL)                  // Background display effect...
2205          return NULL;                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2206                    // We'll need a display font.
2207                    QFont font;
2208                    if (font.fromString(m_pOptions->sDisplayFont))
2209                            pChannelStrip->setDisplayFont(font);
2210                    // Maximum allowed volume setting.
2211                    pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2212            }
2213    
2214      m_pWorkspace->addWindow(pChannelStrip, Qt::Tool);          // Add it to workspace...
2215            m_pWorkspace->addWindow(pChannelStrip, Qt::FramelessWindowHint);
2216    
2217            // Actual channel strip setup...
2218            pChannelStrip->setup(pChannel);
2219    
     // Actual channel strip setup...  
     pChannelStrip->setup(pChannel);  
2220          QObject::connect(pChannelStrip,          QObject::connect(pChannelStrip,
2221                  SIGNAL(channelChanged(ChannelStrip*)),                  SIGNAL(channelChanged(ChannelStrip*)),
2222                  SLOT(channelStripChanged(ChannelStrip*)));                  SLOT(channelStripChanged(ChannelStrip*)));
2223      // Set some initial aesthetic options...  
2224      if (m_pOptions) {          // Now we show up us to the world.
2225          // 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);  
     }  
2226    
2227          // This is pretty new, so we'll watch for it closely.          // This is pretty new, so we'll watch for it closely.
2228          channelStripChanged(pChannelStrip);          channelStripChanged(pChannelStrip);
2229    
2230      // Return our successful reference...          // Return our successful reference...
2231      return pChannelStrip;          return pChannelStrip;
2232  }  }
2233    
2234    
2235  // Retrieve the active channel strip.  // Retrieve the active channel strip.
2236  ChannelStrip* MainForm::activeChannelStrip (void)  ChannelStrip* MainForm::activeChannelStrip (void)
2237  {  {
2238      return (ChannelStrip*) m_pWorkspace->activeWindow();          return static_cast<ChannelStrip *> (m_pWorkspace->activeWindow());
2239  }  }
2240    
2241    
2242  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
2243  ChannelStrip* MainForm::channelStripAt ( int iChannel )  ChannelStrip* MainForm::channelStripAt ( int iChannel )
2244  {  {
2245      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2246      if (wlist.isEmpty())          if (wlist.isEmpty())
2247          return NULL;                  return NULL;
2248    
2249      return (ChannelStrip*) wlist.at(iChannel);          return static_cast<ChannelStrip *> (wlist.at(iChannel));
2250  }  }
2251    
2252    
# Line 2232  ChannelStrip* MainForm::channelStrip ( i Line 2258  ChannelStrip* MainForm::channelStrip ( i
2258                  return NULL;                  return NULL;
2259    
2260          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2261                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip
2262                            = static_cast<ChannelStrip*> (wlist.at(iChannel));
2263                  if (pChannelStrip) {                  if (pChannelStrip) {
2264                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
2265                          if (pChannel && pChannel->channelID() == iChannelID)                          if (pChannel && pChannel->channelID() == iChannelID)
2266                                  return pChannelStrip;                                  return pChannelStrip;
2267                  }                  }
# Line 2248  ChannelStrip* MainForm::channelStrip ( i Line 2275  ChannelStrip* MainForm::channelStrip ( i
2275  // Construct the windows menu.  // Construct the windows menu.
2276  void MainForm::channelsMenuAboutToShow (void)  void MainForm::channelsMenuAboutToShow (void)
2277  {  {
2278      ui.channelsMenu->clear();          m_ui.channelsMenu->clear();
2279      ui.channelsArrangeAction->addTo(ui.channelsMenu);          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);
2280      ui.channelsAutoArrangeAction->addTo(ui.channelsMenu);          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);
2281    
2282      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2283      if (!wlist.isEmpty()) {          if (!wlist.isEmpty()) {
2284          ui.channelsMenu->insertSeparator();                  m_ui.channelsMenu->addSeparator();
2285          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2286              ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                          ChannelStrip* pChannelStrip
2287              if (pChannelStrip) {                                  = static_cast<ChannelStrip*> (wlist.at(iChannel));
2288                  int iItemID = ui.channelsMenu->insertItem(pChannelStrip->caption(), this, SLOT(channelsMenuActivated(int)));                          if (pChannelStrip) {
2289                  ui.channelsMenu->setItemParameter(iItemID, iChannel);                                  QAction *pAction = m_ui.channelsMenu->addAction(
2290                  ui.channelsMenu->setItemChecked(iItemID, activeChannelStrip() == pChannelStrip);                                          pChannelStrip->windowTitle(),
2291              }                                          this, SLOT(channelsMenuActivated()));
2292          }                                  pAction->setCheckable(true);
2293      }                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);
2294                                    pAction->setData(iChannel);
2295                            }
2296                    }
2297            }
2298  }  }
2299    
2300    
2301  // Windows menu activation slot  // Windows menu activation slot
2302  void MainForm::channelsMenuActivated ( int iChannel )  void MainForm::channelsMenuActivated (void)
2303  {  {
2304      ChannelStrip* pChannelStrip = channelStripAt(iChannel);          // Retrive channel index from action data...
2305      if (pChannelStrip)          QAction *pAction = qobject_cast<QAction *> (sender());
2306          pChannelStrip->showNormal();          if (pAction == NULL)
2307      pChannelStrip->setFocus();                  return;
2308    
2309            ChannelStrip* pChannelStrip = channelStripAt(pAction->data().toInt());
2310            if (pChannelStrip) {
2311                    pChannelStrip->showNormal();
2312                    pChannelStrip->setFocus();
2313            }
2314  }  }
2315    
2316    
# Line 2283  void MainForm::channelsMenuActivated ( i Line 2320  void MainForm::channelsMenuActivated ( i
2320  // Set the pseudo-timer delay schedule.  // Set the pseudo-timer delay schedule.
2321  void MainForm::startSchedule ( int iStartDelay )  void MainForm::startSchedule ( int iStartDelay )
2322  {  {
2323      m_iStartDelay  = 1 + (iStartDelay * 1000);          m_iStartDelay  = 1 + (iStartDelay * 1000);
2324      m_iTimerDelay  = 0;          m_iTimerDelay  = 0;
2325  }  }
2326    
2327  // Suspend the pseudo-timer delay schedule.  // Suspend the pseudo-timer delay schedule.
2328  void MainForm::stopSchedule (void)  void MainForm::stopSchedule (void)
2329  {  {
2330      m_iStartDelay  = 0;          m_iStartDelay  = 0;
2331      m_iTimerDelay  = 0;          m_iTimerDelay  = 0;
2332  }  }
2333    
2334  // Timer slot funtion.  // Timer slot funtion.
2335  void MainForm::timerSlot (void)  void MainForm::timerSlot (void)
2336  {  {
2337      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2338          return;                  return;
2339    
2340      // Is it the first shot on server start after a few delay?          // Is it the first shot on server start after a few delay?
2341      if (m_iTimerDelay < m_iStartDelay) {          if (m_iTimerDelay < m_iStartDelay) {
2342          m_iTimerDelay += QSAMPLER_TIMER_MSECS;                  m_iTimerDelay += QSAMPLER_TIMER_MSECS;
2343          if (m_iTimerDelay >= m_iStartDelay) {                  if (m_iTimerDelay >= m_iStartDelay) {
2344              // If we cannot start it now, maybe a lil'mo'later ;)                          // If we cannot start it now, maybe a lil'mo'later ;)
2345              if (!startClient()) {                          if (!startClient()) {
2346                  m_iStartDelay += m_iTimerDelay;                                  m_iStartDelay += m_iTimerDelay;
2347                  m_iTimerDelay  = 0;                                  m_iTimerDelay  = 0;
2348              }                          }
2349          }                  }
2350      }          }
2351    
2352          if (m_pClient) {          if (m_pClient) {
2353                  // Update the channel information for each pending strip...                  // Update the channel information for each pending strip...
2354                  if (m_changedStrips.count() > 0) {                  QListIterator<ChannelStrip *> iter(m_changedStrips);
2355                          for (ChannelStrip* pChannelStrip = m_changedStrips.first();                  while (iter.hasNext()) {
2356                                          pChannelStrip; pChannelStrip = m_changedStrips.next()) {                          ChannelStrip *pChannelStrip = iter.next();
2357                                  // If successfull, remove from pending list...                          // If successfull, remove from pending list...
2358                                  if (pChannelStrip->updateChannelInfo())                          if (pChannelStrip->updateChannelInfo()) {
2359                                          m_changedStrips.remove(pChannelStrip);                                  int iChannelStrip = m_changedStrips.indexOf(pChannelStrip);
2360                                    if (iChannelStrip >= 0)
2361                                            m_changedStrips.removeAt(iChannelStrip);
2362                          }                          }
2363                  }                  }
2364                  // Refresh each channel usage, on each period...                  // Refresh each channel usage, on each period...
# Line 2340  void MainForm::timerSlot (void) Line 2379  void MainForm::timerSlot (void)
2379                  }                  }
2380          }          }
2381    
2382      // Register the next timer slot.          // Register the next timer slot.
2383      QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));          QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
2384  }  }
2385    
2386    
# Line 2351  void MainForm::timerSlot (void) Line 2390  void MainForm::timerSlot (void)
2390  // Start linuxsampler server...  // Start linuxsampler server...
2391  void MainForm::startServer (void)  void MainForm::startServer (void)
2392  {  {
2393      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2394          return;                  return;
2395    
2396            // Aren't already a client, are we?
2397            if (!m_pOptions->bServerStart || m_pClient)
2398                    return;
2399    
2400      // Aren't already a client, are we?          // Is the server process instance still here?
2401      if (!m_pOptions->bServerStart || m_pClient)          if (m_pServer) {
2402          return;                  switch (QMessageBox::warning(this,
   
     // Is the server process instance still here?  
     if (m_pServer) {  
         switch (QMessageBox::warning(this,  
2403                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
2404              tr("Could not start the LinuxSampler server.\n\n"                          tr("Could not start the LinuxSampler server.\n\n"
2405                 "Maybe it ss already started."),                          "Maybe it is already started."),
2406              tr("Stop"), tr("Kill"), tr("Cancel"))) {                          tr("Stop"), tr("Kill"), tr("Cancel"))) {
2407            case 0:                  case 0:
2408              m_pServer->terminate();                          m_pServer->terminate();
2409              break;                          break;
2410            case 1:                  case 1:
2411              m_pServer->kill();                          m_pServer->kill();
2412              break;                          break;
2413          }                  }
2414          return;                  return;
2415      }          }
2416    
2417      // Reset our timer counters...          // Reset our timer counters...
2418      stopSchedule();          stopSchedule();
2419    
2420      // OK. Let's build the startup process...          // Verify we have something to start with...
2421      m_pServer = new QProcess(this);          if (m_pOptions->sServerCmdLine.isEmpty())
2422                    return;
2423      // Setup stdout/stderr capture...  
2424          //      if (m_pOptions->bStdoutCapture) {          // OK. Let's build the startup process...
2425                  //m_pServer->setProcessChannelMode(          m_pServer = new QProcess();
2426                  //      QProcess::StandardOutput);          bForceServerStop = true;
2427    
2428            // Setup stdout/stderr capture...
2429    //      if (m_pOptions->bStdoutCapture) {
2430    #if QT_VERSION >= 0x040200
2431                    m_pServer->setProcessChannelMode(QProcess::ForwardedChannels);
2432    #endif
2433                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2434                          SIGNAL(readyReadStandardOutput()),                          SIGNAL(readyReadStandardOutput()),
2435                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
2436                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2437                          SIGNAL(readyReadStandardError()),                          SIGNAL(readyReadStandardError()),
2438                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
2439          //      }  //      }
2440    
2441          // The unforgiveable signal communication...          // The unforgiveable signal communication...
2442          QObject::connect(m_pServer,          QObject::connect(m_pServer,
2443                  SIGNAL(finished(int,QProcess::ExitStatus)),                  SIGNAL(finished(int, QProcess::ExitStatus)),
2444                  SLOT(processServerExit()));                  SLOT(processServerExit()));
2445    
2446      // Build process arguments...          // Build process arguments...
2447      QStringList serverCmdLine = QStringList::split(' ', m_pOptions->sServerCmdLine);          QStringList args = m_pOptions->sServerCmdLine.split(' ');
2448            QString sCommand = args[0];
2449      appendMessages(tr("Server is starting..."));          args.removeAt(0);
2450      appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");  
2451            appendMessages(tr("Server is starting..."));
2452            appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");
2453    
2454      const QString prog = (serverCmdLine.size() > 0) ? serverCmdLine[0] : QString();          // Go linuxsampler, go...
2455      const QStringList args = serverCmdLine.mid(1);          m_pServer->start(sCommand, args);
2456            if (!m_pServer->waitForStarted()) {
2457      // Go jack, go...                  appendMessagesError(tr("Could not start server.\n\nSorry."));
2458      m_pServer->start(prog, args);                  processServerExit();
2459      if (!m_pServer->waitForStarted()) {                  return;
2460          appendMessagesError(tr("Could not start server.\n\nSorry."));          }
         processServerExit();  
         return;  
     }  
   
     // Show startup results...  
     appendMessages(tr("Server was started with PID=%1.").arg((long) m_pServer->pid()));  
2461    
2462      // Reset (yet again) the timer counters,          // Show startup results...
2463      // but this time is deferred as the user opted.          appendMessages(
2464      startSchedule(m_pOptions->iStartDelay);                  tr("Server was started with PID=%1.").arg((long) m_pServer->pid()));
2465      stabilizeForm();  
2466            // Reset (yet again) the timer counters,
2467            // but this time is deferred as the user opted.
2468            startSchedule(m_pOptions->iStartDelay);
2469            stabilizeForm();
2470  }  }
2471    
2472    
2473  // Stop linuxsampler server...  // Stop linuxsampler server...
2474  void MainForm::stopServer (void)  void MainForm::stopServer (bool bInteractive)
2475  {  {
2476      // Stop client code.          // Stop client code.
2477      stopClient();          stopClient();
2478    
2479      // And try to stop server.          if (m_pServer && bInteractive) {
2480      if (m_pServer) {                  if (QMessageBox::question(this,
2481          appendMessages(tr("Server is stopping..."));                          QSAMPLER_TITLE ": " + tr("The backend's fate ..."),
2482          if (m_pServer->state() == QProcess::Running)                          tr("You have the option to keep the sampler backend (LinuxSampler)\n"
2483              m_pServer->terminate();                          "running in the background. The sampler would continue to work\n"
2484       }                          "according to your current sampler session and you could alter the\n"
2485                            "sampler session at any time by relaunching QSampler.\n\n"
2486      // Give it some time to terminate gracefully and stabilize...                          "Do you want LinuxSampler to stop or to keep running in\n"
2487      QTime t;                          "the background?"),
2488      t.start();                          tr("Stop"), tr("Keep Running")) == 1)
2489      while (t.elapsed() < QSAMPLER_TIMER_MSECS)                  {
2490          QApplication::processEvents(QEventLoop::ExcludeUserInput);                          bForceServerStop = false;
2491                    }
2492            }
2493    
2494       // Do final processing anyway.          // And try to stop server.
2495       processServerExit();          if (m_pServer && bForceServerStop) {
2496                    appendMessages(tr("Server is stopping..."));
2497                    if (m_pServer->state() == QProcess::Running) {
2498    #if defined(WIN32)
2499                            // Try harder...
2500                            m_pServer->kill();
2501    #else
2502                            // Try softly...
2503                            m_pServer->terminate();
2504    #endif
2505                    }
2506            }       // Do final processing anyway.
2507            else processServerExit();
2508    
2509            // Give it some time to terminate gracefully and stabilize...
2510            QTime t;
2511            t.start();
2512            while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2513                    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2514  }  }
2515    
2516    
2517  // Stdout handler...  // Stdout handler...
2518  void MainForm::readServerStdout (void)  void MainForm::readServerStdout (void)
2519  {  {
2520      if (m_pMessages)          if (m_pMessages)
2521          m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());                  m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());
2522  }  }
2523    
2524    
2525  // Linuxsampler server cleanup.  // Linuxsampler server cleanup.
2526  void MainForm::processServerExit (void)  void MainForm::processServerExit (void)
2527  {  {
2528      // Force client code cleanup.          // Force client code cleanup.
2529      stopClient();          stopClient();
2530    
2531      // Flush anything that maybe pending...          // Flush anything that maybe pending...
2532      if (m_pMessages)          if (m_pMessages)
2533          m_pMessages->flushStdoutBuffer();                  m_pMessages->flushStdoutBuffer();
2534    
2535      if (m_pServer) {          if (m_pServer && bForceServerStop) {
2536          // Force final server shutdown...                  if (m_pServer->state() != QProcess::NotRunning) {
2537          appendMessages(tr("Server was stopped with exit status %1.").arg(m_pServer->exitStatus()));                          appendMessages(tr("Server is being forced..."));
2538          m_pServer->terminate();                          // Force final server shutdown...
2539          if (!m_pServer->waitForFinished(2000))                          m_pServer->kill();
2540              m_pServer->kill();                          // Give it some time to terminate gracefully and stabilize...
2541          // Destroy it.                          QTime t;
2542          delete m_pServer;                          t.start();
2543          m_pServer = NULL;                          while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2544      }                                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2545                    }
2546                    // Force final server shutdown...
2547                    appendMessages(
2548                            tr("Server was stopped with exit status %1.")
2549                            .arg(m_pServer->exitStatus()));
2550                    delete m_pServer;
2551                    m_pServer = NULL;
2552            }
2553    
2554      // Again, make status visible stable.          // Again, make status visible stable.
2555      stabilizeForm();          stabilizeForm();
2556  }  }
2557    
2558    
# Line 2488  void MainForm::processServerExit (void) Line 2560  void MainForm::processServerExit (void)
2560  // qsamplerMainForm -- Client stuff.  // qsamplerMainForm -- Client stuff.
2561    
2562  // The LSCP client callback procedure.  // The LSCP client callback procedure.
2563  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*/,
2564            lscp_event_t event, const char *pchData, int cchData, void *pvData )
2565  {  {
2566      MainForm* pMainForm = (MainForm *) pvData;          MainForm* pMainForm = (MainForm *) pvData;
2567      if (pMainForm == NULL)          if (pMainForm == NULL)
2568          return LSCP_FAILED;                  return LSCP_FAILED;
2569    
2570      // ATTN: DO NOT EVER call any GUI code here,          // ATTN: DO NOT EVER call any GUI code here,
2571      // as this is run under some other thread context.          // as this is run under some other thread context.
2572      // A custom event must be posted here...          // A custom event must be posted here...
2573      QApplication::postEvent(pMainForm, new qsamplerCustomEvent(event, pchData, cchData));          QApplication::postEvent(pMainForm,
2574                    new CustomEvent(event, pchData, cchData));
2575    
2576      return LSCP_OK;          return LSCP_OK;
2577  }  }
2578    
2579    
2580  // Start our almighty client...  // Start our almighty client...
2581  bool MainForm::startClient (void)  bool MainForm::startClient (void)
2582  {  {
2583      // Have it a setup?          // Have it a setup?
2584      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2585          return false;                  return false;
2586    
2587      // Aren't we already started, are we?          // Aren't we already started, are we?
2588      if (m_pClient)          if (m_pClient)
2589          return true;                  return true;
2590    
2591      // Log prepare here.          // Log prepare here.
2592      appendMessages(tr("Client connecting..."));          appendMessages(tr("Client connecting..."));
2593    
2594      // Create the client handle...          // Create the client handle...
2595      m_pClient = ::lscp_client_create(m_pOptions->sServerHost.latin1(), m_pOptions->iServerPort, qsampler_client_callback, this);          m_pClient = ::lscp_client_create(
2596      if (m_pClient == NULL) {                  m_pOptions->sServerHost.toUtf8().constData(),
2597          // Is this the first try?                  m_pOptions->iServerPort, qsampler_client_callback, this);
2598          // maybe we need to start a local server...          if (m_pClient == NULL) {
2599          if ((m_pServer && m_pServer->state() == QProcess::Running) || !m_pOptions->bServerStart)                  // Is this the first try?
2600              appendMessagesError(tr("Could not connect to server as client.\n\nSorry."));                  // maybe we need to start a local server...
2601          else                  if ((m_pServer && m_pServer->state() == QProcess::Running)
2602              startServer();                          || !m_pOptions->bServerStart) {
2603          // This is always a failure.                          appendMessagesError(
2604          stabilizeForm();                                  tr("Could not connect to server as client.\n\nSorry."));
2605          return false;                  } else {
2606      }                          startServer();
2607      // Just set receive timeout value, blindly.                  }
2608      ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);                  // This is always a failure.
2609      appendMessages(tr("Client receive timeout is set to %1 msec.").arg(::lscp_client_get_timeout(m_pClient)));                  stabilizeForm();
2610                    return false;
2611            }
2612            // Just set receive timeout value, blindly.
2613            ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);
2614            appendMessages(
2615                    tr("Client receive timeout is set to %1 msec.")
2616                    .arg(::lscp_client_get_timeout(m_pClient)));
2617    
2618          // Subscribe to channel info change notifications...          // Subscribe to channel info change notifications...
2619          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)
2620                  appendMessagesClient("lscp_client_subscribe");                  appendMessagesClient("lscp_client_subscribe(CHANNEL_INFO)");
2621    
2622    #if CONFIG_LSCP_CHANNEL_MIDI
2623            // Subscribe to channel MIDI data notifications...
2624            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI) != LSCP_OK)
2625                    appendMessagesClient("lscp_client_subscribe(CHANNEL_MIDI)");
2626    #endif
2627    
2628      // We may stop scheduling around.          // We may stop scheduling around.
2629      stopSchedule();          stopSchedule();
2630    
2631      // We'll accept drops from now on...          // We'll accept drops from now on...
2632      setAcceptDrops(true);          setAcceptDrops(true);
2633    
2634      // Log success here.          // Log success here.
2635      appendMessages(tr("Client connected."));          appendMessages(tr("Client connected."));
2636    
2637          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
2638          // if visible, that we're ready...          // if visible, that we're ready...
2639          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
2640              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
2641          if (m_pDeviceForm)          if (m_pDeviceForm)
2642              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
2643    
2644      // Is any session pending to be loaded?          // Is any session pending to be loaded?
2645      if (!m_pOptions->sSessionFile.isEmpty()) {          if (!m_pOptions->sSessionFile.isEmpty()) {
2646          // Just load the prabably startup session...                  // Just load the prabably startup session...
2647          if (loadSessionFile(m_pOptions->sSessionFile)) {                  if (loadSessionFile(m_pOptions->sSessionFile)) {
2648              m_pOptions->sSessionFile = QString::null;                          m_pOptions->sSessionFile = QString::null;
2649              return true;                          return true;
2650          }                  }
2651      }          }
2652    
2653      // Make a new session          // Make a new session
2654      return newSession();          return newSession();
2655  }  }
2656    
2657    
2658  // Stop client...  // Stop client...
2659  void MainForm::stopClient (void)  void MainForm::stopClient (void)
2660  {  {
2661      if (m_pClient == NULL)          if (m_pClient == NULL)
2662          return;                  return;
   
     // Log prepare here.  
     appendMessages(tr("Client disconnecting..."));  
2663    
2664      // Clear timer counters...          // Log prepare here.
2665      stopSchedule();          appendMessages(tr("Client disconnecting..."));
2666    
2667      // We'll reject drops from now on...          // Clear timer counters...
2668      setAcceptDrops(false);          stopSchedule();
2669    
2670      // Force any channel strips around, but          // We'll reject drops from now on...
2671      // but avoid removing the corresponding          setAcceptDrops(false);
     // channels from the back-end server.  
     m_iDirtyCount = 0;  
     closeSession(false);  
2672    
2673      // Close us as a client...          // Force any channel strips around, but
2674            // but avoid removing the corresponding
2675            // channels from the back-end server.
2676            m_iDirtyCount = 0;
2677            closeSession(false);
2678    
2679            // Close us as a client...
2680    #if CONFIG_LSCP_CHANNEL_MIDI
2681            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI);
2682    #endif
2683          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
2684      ::lscp_client_destroy(m_pClient);          ::lscp_client_destroy(m_pClient);
2685      m_pClient = NULL;          m_pClient = NULL;
2686    
2687          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
2688          // if visible, that we're running out...          // if visible, that we're running out...
2689          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
2690              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
2691          if (m_pDeviceForm)          if (m_pDeviceForm)
2692              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
2693    
2694            // Log final here.
2695            appendMessages(tr("Client disconnected."));
2696    
2697            // Make visible status.
2698            stabilizeForm();
2699    }
2700    
2701    
2702      // Log final here.  // Channel strip activation/selection.
2703      appendMessages(tr("Client disconnected."));  void MainForm::activateStrip ( QWidget *pWidget )
2704    {
2705            ChannelStrip *pChannelStrip
2706                    = static_cast<ChannelStrip *> (pWidget);
2707            if (pChannelStrip)
2708                    pChannelStrip->setSelected(true);
2709    
2710      // Make visible status.          stabilizeForm();
     stabilizeForm();  
2711  }  }
2712    
2713    
2714  } // namespace QSampler  } // namespace QSampler
2715    
2716    

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

  ViewVC Help
Powered by ViewVC