/[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 1499 by capela, Tue Nov 20 16:48:04 2007 UTC revision 2112 by capela, Wed Jul 21 18:33:25 2010 UTC
# Line 1  Line 1 
1  // qsamplerMainForm.cpp  // qsamplerMainForm.cpp
2  //  //
3  /****************************************************************************  /****************************************************************************
4     Copyright (C) 2004-2007, rncbc aka Rui Nuno Capela. All rights reserved.     Copyright (C) 2004-2010, rncbc aka Rui Nuno Capela. All rights reserved.
5     Copyright (C) 2007, Christian Schoenebeck     Copyright (C) 2007, 2008 Christian Schoenebeck
6    
7     This program is free software; you can redistribute it and/or     This program is free software; you can redistribute it and/or
8     modify it under the terms of the GNU General Public License     modify it under the terms of the GNU General Public License
# Line 20  Line 20 
20    
21  *****************************************************************************/  *****************************************************************************/
22    
23    #include "qsamplerAbout.h"
24  #include "qsamplerMainForm.h"  #include "qsamplerMainForm.h"
25    
 #include "qsamplerAbout.h"  
26  #include "qsamplerOptions.h"  #include "qsamplerOptions.h"
27  #include "qsamplerChannel.h"  #include "qsamplerChannel.h"
28  #include "qsamplerMessages.h"  #include "qsamplerMessages.h"
# Line 33  Line 33 
33  #include "qsamplerInstrumentListForm.h"  #include "qsamplerInstrumentListForm.h"
34  #include "qsamplerDeviceForm.h"  #include "qsamplerDeviceForm.h"
35  #include "qsamplerOptionsForm.h"  #include "qsamplerOptionsForm.h"
36    #include "qsamplerDeviceStatusForm.h"
37    
38  #include <QApplication>  #include <QApplication>
39  #include <QWorkspace>  #include <QWorkspace>
# Line 55  Line 56 
56  #include <QTimer>  #include <QTimer>
57  #include <QDateTime>  #include <QDateTime>
58    
59    #if QT_VERSION < 0x040500
60    namespace Qt {
61    const WindowFlags WindowCloseButtonHint = WindowFlags(0x08000000);
62    #if QT_VERSION < 0x040200
63    const WindowFlags CustomizeWindowHint   = WindowFlags(0x02000000);
64    #endif
65    }
66    #endif
67    
68  #ifdef HAVE_SIGNAL_H  #ifdef HAVE_SIGNAL_H
69  #include <signal.h>  #include <signal.h>
# Line 77  static inline long lroundf ( float x ) Line 86  static inline long lroundf ( float x )
86  }  }
87  #endif  #endif
88    
89    
90    // All winsock apps needs this.
91    #if defined(WIN32)
92    static WSADATA _wsaData;
93    #endif
94    
95    
96    //-------------------------------------------------------------------------
97    // LADISH Level 1 support stuff.
98    
99    #ifdef HAVE_SIGNAL_H
100    
101    #include <QSocketNotifier>
102    
103    #include <sys/types.h>
104    #include <sys/socket.h>
105    
106    #include <signal.h>
107    
108    // File descriptor for SIGUSR1 notifier.
109    static int g_fdUsr1[2];
110    
111    // Unix SIGUSR1 signal handler.
112    static void qsampler_sigusr1_handler ( int /* signo */ )
113    {
114            char c = 1;
115    
116            (::write(g_fdUsr1[0], &c, sizeof(c)) > 0);
117    }
118    
119    #endif  // HAVE_SIGNAL_H
120    
121    
122    //-------------------------------------------------------------------------
123    // qsampler -- namespace
124    
125    
126    namespace QSampler {
127    
128  // Timer constant stuff.  // Timer constant stuff.
129  #define QSAMPLER_TIMER_MSECS    200  #define QSAMPLER_TIMER_MSECS    200
130    
# Line 87  static inline long lroundf ( float x ) Line 135  static inline long lroundf ( float x )
135  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.
136    
137    
138  // All winsock apps needs this.  // Specialties for thread-callback comunication.
139  #if defined(WIN32)  #define QSAMPLER_LSCP_EVENT   QEvent::Type(QEvent::User + 1)
 static WSADATA _wsaData;  
 #endif  
140    
141    
142  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
143  // qsamplerCustomEvent -- specialty for callback comunication.  // LscpEvent -- specialty for LSCP callback comunication.
144    
 #define QSAMPLER_CUSTOM_EVENT   QEvent::Type(QEvent::User + 0)  
145    
146  class qsamplerCustomEvent : public QEvent  class LscpEvent : public QEvent
147  {  {
148  public:  public:
149    
150      // Constructor.          // Constructor.
151      qsamplerCustomEvent(lscp_event_t event, const char *pchData, int cchData)          LscpEvent(lscp_event_t event, const char *pchData, int cchData)
152          : QEvent(QSAMPLER_CUSTOM_EVENT)                  : QEvent(QSAMPLER_LSCP_EVENT)
153      {          {
154          m_event = event;                  m_event = event;
155          m_data  = QString::fromUtf8(pchData, cchData);                  m_data  = QString::fromUtf8(pchData, cchData);
156      }          }
157    
158      // Accessors.          // Accessors.
159      lscp_event_t event() { return m_event; }          lscp_event_t event() { return m_event; }
160      QString&     data()  { return m_data;  }          QString&     data()  { return m_data;  }
161    
162  private:  private:
163    
164      // The proper event type.          // The proper event type.
165      lscp_event_t m_event;          lscp_event_t m_event;
166      // The event data as a string.          // The event data as a string.
167      QString      m_data;          QString      m_data;
168  };  };
169    
170    
171  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
172  // qsamplerMainForm -- Main window form implementation.  // qsamplerMainForm -- Main window form implementation.
173    
 namespace QSampler {  
   
174  // Kind of singleton reference.  // Kind of singleton reference.
175  MainForm* MainForm::g_pMainForm = NULL;  MainForm* MainForm::g_pMainForm = NULL;
176    
177  MainForm::MainForm(QWidget* parent) : QMainWindow(parent) {  MainForm::MainForm ( QWidget *pParent )
178      ui.setupUi(this);          : QMainWindow(pParent)
179    {
180            m_ui.setupUi(this);
181    
182          // Pseudo-singleton reference setup.          // Pseudo-singleton reference setup.
183          g_pMainForm = this;          g_pMainForm = this;
184    
185      // Initialize some pointer references.          // Initialize some pointer references.
186      m_pOptions = NULL;          m_pOptions = NULL;
187    
188      // All child forms are to be created later, not earlier than setup.          // All child forms are to be created later, not earlier than setup.
189      m_pMessages = NULL;          m_pMessages = NULL;
190      m_pInstrumentListForm = NULL;          m_pInstrumentListForm = NULL;
191      m_pDeviceForm = NULL;          m_pDeviceForm = NULL;
192    
193      // We'll start clean.          // We'll start clean.
194      m_iUntitled   = 0;          m_iUntitled   = 0;
195      m_iDirtyCount = 0;          m_iDirtyCount = 0;
196    
197      m_pServer = NULL;          m_pServer = NULL;
198      m_pClient = NULL;          m_pClient = NULL;
199    
200      m_iStartDelay = 0;          m_iStartDelay = 0;
201      m_iTimerDelay = 0;          m_iTimerDelay = 0;
202    
203      m_iTimerSlot = 0;          m_iTimerSlot = 0;
204    
205  #ifdef HAVE_SIGNAL_H  #ifdef HAVE_SIGNAL_H
206    
207          // Set to ignore any fatal "Broken pipe" signals.          // Set to ignore any fatal "Broken pipe" signals.
208          ::signal(SIGPIPE, SIG_IGN);          ::signal(SIGPIPE, SIG_IGN);
209  #endif  
210            // LADISH Level 1 suport.
211    
212            // Initialize file descriptors for SIGUSR1 socket notifier.
213            ::socketpair(AF_UNIX, SOCK_STREAM, 0, g_fdUsr1);
214            m_pUsr1Notifier
215                    = new QSocketNotifier(g_fdUsr1[1], QSocketNotifier::Read, this);
216    
217            QObject::connect(m_pUsr1Notifier,
218                    SIGNAL(activated(int)),
219                    SLOT(handle_sigusr1()));
220    
221            // Install SIGUSR1 signal handler.
222        struct sigaction usr1;
223        usr1.sa_handler = qsampler_sigusr1_handler;
224        ::sigemptyset(&usr1.sa_mask);
225        usr1.sa_flags = 0;
226        usr1.sa_flags |= SA_RESTART;
227        ::sigaction(SIGUSR1, &usr1, NULL);
228    
229    #else   // HAVE_SIGNAL_H
230    
231            m_pSocketNotifier = NULL;
232            
233    #endif  // !HAVE_SIGNAL_H
234    
235  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
236      // Make some extras into the toolbar...          // Make some extras into the toolbar...
237          const QString& sVolumeText = tr("Master volume");          const QString& sVolumeText = tr("Master volume");
238          m_iVolumeChanging = 0;          m_iVolumeChanging = 0;
239          // Volume slider...          // Volume slider...
240          ui.channelsToolbar->addSeparator();          m_ui.channelsToolbar->addSeparator();
241          m_pVolumeSlider = new QSlider(Qt::Horizontal, ui.channelsToolbar);          m_pVolumeSlider = new QSlider(Qt::Horizontal, m_ui.channelsToolbar);
242          m_pVolumeSlider->setTickPosition(QSlider::TicksBelow);          m_pVolumeSlider->setTickPosition(QSlider::TicksBothSides);
243          m_pVolumeSlider->setTickInterval(10);          m_pVolumeSlider->setTickInterval(10);
244          m_pVolumeSlider->setPageStep(10);          m_pVolumeSlider->setPageStep(10);
245          m_pVolumeSlider->setSingleStep(10);          m_pVolumeSlider->setSingleStep(10);
# Line 181  MainForm::MainForm(QWidget* parent) : QM Line 251  MainForm::MainForm(QWidget* parent) : QM
251          QObject::connect(m_pVolumeSlider,          QObject::connect(m_pVolumeSlider,
252                  SIGNAL(valueChanged(int)),                  SIGNAL(valueChanged(int)),
253                  SLOT(volumeChanged(int)));                  SLOT(volumeChanged(int)));
254          //ui.channelsToolbar->setHorizontallyStretchable(true);          //m_ui.channelsToolbar->setHorizontallyStretchable(true);
255          //ui.channelsToolbar->setStretchableWidget(m_pVolumeSlider);          //m_ui.channelsToolbar->setStretchableWidget(m_pVolumeSlider);
256      ui.channelsToolbar->addWidget(m_pVolumeSlider);          m_ui.channelsToolbar->addWidget(m_pVolumeSlider);
257          // Volume spin-box          // Volume spin-box
258          ui.channelsToolbar->addSeparator();          m_ui.channelsToolbar->addSeparator();
259          m_pVolumeSpinBox = new QSpinBox(ui.channelsToolbar);          m_pVolumeSpinBox = new QSpinBox(m_ui.channelsToolbar);
260            m_pVolumeSpinBox->setMaximumHeight(24);
261          m_pVolumeSpinBox->setSuffix(" %");          m_pVolumeSpinBox->setSuffix(" %");
262          m_pVolumeSpinBox->setMinimum(0);          m_pVolumeSpinBox->setMinimum(0);
263          m_pVolumeSpinBox->setMaximum(100);          m_pVolumeSpinBox->setMaximum(100);
# Line 194  MainForm::MainForm(QWidget* parent) : QM Line 265  MainForm::MainForm(QWidget* parent) : QM
265          QObject::connect(m_pVolumeSpinBox,          QObject::connect(m_pVolumeSpinBox,
266                  SIGNAL(valueChanged(int)),                  SIGNAL(valueChanged(int)),
267                  SLOT(volumeChanged(int)));                  SLOT(volumeChanged(int)));
268      ui.channelsToolbar->addWidget(m_pVolumeSpinBox);          m_ui.channelsToolbar->addWidget(m_pVolumeSpinBox);
269  #endif  #endif
270    
271      // Make it an MDI workspace.          // Make it an MDI workspace.
272      m_pWorkspace = new QWorkspace(this);          m_pWorkspace = new QWorkspace(this);
273      m_pWorkspace->setScrollBarsEnabled(true);          m_pWorkspace->setScrollBarsEnabled(true);
274          // Set the activation connection.          // Set the activation connection.
275          QObject::connect(m_pWorkspace,          QObject::connect(m_pWorkspace,
276                  SIGNAL(windowActivated(QWidget *)),                  SIGNAL(windowActivated(QWidget *)),
277                  SLOT(stabilizeForm()));                  SLOT(activateStrip(QWidget *)));
278      // Make it shine :-)          // Make it shine :-)
279      setCentralWidget(m_pWorkspace);          setCentralWidget(m_pWorkspace);
280    
281      // Create some statusbar labels...          // Create some statusbar labels...
282      QLabel *pLabel;          QLabel *pLabel;
283      // Client status.          // Client status.
284      pLabel = new QLabel(tr("Connected"), this);          pLabel = new QLabel(tr("Connected"), this);
285      pLabel->setAlignment(Qt::AlignLeft);          pLabel->setAlignment(Qt::AlignLeft);
286      pLabel->setMinimumSize(pLabel->sizeHint());          pLabel->setMinimumSize(pLabel->sizeHint());
287      m_statusItem[QSAMPLER_STATUS_CLIENT] = pLabel;          m_statusItem[QSAMPLER_STATUS_CLIENT] = pLabel;
288      statusBar()->addWidget(pLabel);          statusBar()->addWidget(pLabel);
289      // Server address.          // Server address.
290      pLabel = new QLabel(this);          pLabel = new QLabel(this);
291      pLabel->setAlignment(Qt::AlignLeft);          pLabel->setAlignment(Qt::AlignLeft);
292      m_statusItem[QSAMPLER_STATUS_SERVER] = pLabel;          m_statusItem[QSAMPLER_STATUS_SERVER] = pLabel;
293      statusBar()->addWidget(pLabel, 1);          statusBar()->addWidget(pLabel, 1);
294      // Channel title.          // Channel title.
295      pLabel = new QLabel(this);          pLabel = new QLabel(this);
296      pLabel->setAlignment(Qt::AlignLeft);          pLabel->setAlignment(Qt::AlignLeft);
297      m_statusItem[QSAMPLER_STATUS_CHANNEL] = pLabel;          m_statusItem[QSAMPLER_STATUS_CHANNEL] = pLabel;
298      statusBar()->addWidget(pLabel, 2);          statusBar()->addWidget(pLabel, 2);
299      // Session modification status.          // Session modification status.
300      pLabel = new QLabel(tr("MOD"), this);          pLabel = new QLabel(tr("MOD"), this);
301      pLabel->setAlignment(Qt::AlignHCenter);          pLabel->setAlignment(Qt::AlignHCenter);
302      pLabel->setMinimumSize(pLabel->sizeHint());          pLabel->setMinimumSize(pLabel->sizeHint());
303      m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;          m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;
304      statusBar()->addWidget(pLabel);          statusBar()->addWidget(pLabel);
305    
306  #if defined(WIN32)  #if defined(WIN32)
307      WSAStartup(MAKEWORD(1, 1), &_wsaData);          WSAStartup(MAKEWORD(1, 1), &_wsaData);
308  #endif  #endif
309    
310          QObject::connect(ui.fileNewAction,          // Some actions surely need those
311            // shortcuts firmly attached...
312            addAction(m_ui.viewMenubarAction);
313            addAction(m_ui.viewToolbarAction);
314    
315            QObject::connect(m_ui.fileNewAction,
316                  SIGNAL(triggered()),                  SIGNAL(triggered()),
317                  SLOT(fileNew()));                  SLOT(fileNew()));
318          QObject::connect(ui.fileOpenAction,          QObject::connect(m_ui.fileOpenAction,
319                  SIGNAL(triggered()),                  SIGNAL(triggered()),
320                  SLOT(fileOpen()));                  SLOT(fileOpen()));
321          QObject::connect(ui.fileSaveAction,          QObject::connect(m_ui.fileSaveAction,
322                  SIGNAL(triggered()),                  SIGNAL(triggered()),
323                  SLOT(fileSave()));                  SLOT(fileSave()));
324          QObject::connect(ui.fileSaveAsAction,          QObject::connect(m_ui.fileSaveAsAction,
325                  SIGNAL(triggered()),                  SIGNAL(triggered()),
326                  SLOT(fileSaveAs()));                  SLOT(fileSaveAs()));
327          QObject::connect(ui.fileResetAction,          QObject::connect(m_ui.fileResetAction,
328                  SIGNAL(triggered()),                  SIGNAL(triggered()),
329                  SLOT(fileReset()));                  SLOT(fileReset()));
330          QObject::connect(ui.fileRestartAction,          QObject::connect(m_ui.fileRestartAction,
331                  SIGNAL(triggered()),                  SIGNAL(triggered()),
332                  SLOT(fileRestart()));                  SLOT(fileRestart()));
333          QObject::connect(ui.fileExitAction,          QObject::connect(m_ui.fileExitAction,
334                  SIGNAL(triggered()),                  SIGNAL(triggered()),
335                  SLOT(fileExit()));                  SLOT(fileExit()));
336          QObject::connect(ui.editAddChannelAction,          QObject::connect(m_ui.editAddChannelAction,
337                  SIGNAL(triggered()),                  SIGNAL(triggered()),
338                  SLOT(editAddChannel()));                  SLOT(editAddChannel()));
339          QObject::connect(ui.editRemoveChannelAction,          QObject::connect(m_ui.editRemoveChannelAction,
340                  SIGNAL(triggered()),                  SIGNAL(triggered()),
341                  SLOT(editRemoveChannel()));                  SLOT(editRemoveChannel()));
342          QObject::connect(ui.editSetupChannelAction,          QObject::connect(m_ui.editSetupChannelAction,
343                  SIGNAL(triggered()),                  SIGNAL(triggered()),
344                  SLOT(editSetupChannel()));                  SLOT(editSetupChannel()));
345          QObject::connect(ui.editEditChannelAction,          QObject::connect(m_ui.editEditChannelAction,
346                  SIGNAL(triggered()),                  SIGNAL(triggered()),
347                  SLOT(editEditChannel()));                  SLOT(editEditChannel()));
348          QObject::connect(ui.editResetChannelAction,          QObject::connect(m_ui.editResetChannelAction,
349                  SIGNAL(triggered()),                  SIGNAL(triggered()),
350                  SLOT(editResetChannel()));                  SLOT(editResetChannel()));
351          QObject::connect(ui.editResetAllChannelsAction,          QObject::connect(m_ui.editResetAllChannelsAction,
352                  SIGNAL(triggered()),                  SIGNAL(triggered()),
353                  SLOT(editResetAllChannels()));                  SLOT(editResetAllChannels()));
354          QObject::connect(ui.viewMenubarAction,          QObject::connect(m_ui.viewMenubarAction,
355                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
356                  SLOT(viewMenubar(bool)));                  SLOT(viewMenubar(bool)));
357          QObject::connect(ui.viewToolbarAction,          QObject::connect(m_ui.viewToolbarAction,
358                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
359                  SLOT(viewToolbar(bool)));                  SLOT(viewToolbar(bool)));
360          QObject::connect(ui.viewStatusbarAction,          QObject::connect(m_ui.viewStatusbarAction,
361                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
362                  SLOT(viewStatusbar(bool)));                  SLOT(viewStatusbar(bool)));
363          QObject::connect(ui.viewMessagesAction,          QObject::connect(m_ui.viewMessagesAction,
364                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
365                  SLOT(viewMessages(bool)));                  SLOT(viewMessages(bool)));
366          QObject::connect(ui.viewInstrumentsAction,          QObject::connect(m_ui.viewInstrumentsAction,
367                  SIGNAL(triggered()),                  SIGNAL(triggered()),
368                  SLOT(viewInstruments()));                  SLOT(viewInstruments()));
369          QObject::connect(ui.viewDevicesAction,          QObject::connect(m_ui.viewDevicesAction,
370                  SIGNAL(triggered()),                  SIGNAL(triggered()),
371                  SLOT(viewDevices()));                  SLOT(viewDevices()));
372          QObject::connect(ui.viewOptionsAction,          QObject::connect(m_ui.viewOptionsAction,
373                  SIGNAL(triggered()),                  SIGNAL(triggered()),
374                  SLOT(viewOptions()));                  SLOT(viewOptions()));
375          QObject::connect(ui.channelsArrangeAction,          QObject::connect(m_ui.channelsArrangeAction,
376                  SIGNAL(triggered()),                  SIGNAL(triggered()),
377                  SLOT(channelsArrange()));                  SLOT(channelsArrange()));
378          QObject::connect(ui.channelsAutoArrangeAction,          QObject::connect(m_ui.channelsAutoArrangeAction,
379                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
380                  SLOT(channelsAutoArrange(bool)));                  SLOT(channelsAutoArrange(bool)));
381          QObject::connect(ui.helpAboutAction,          QObject::connect(m_ui.helpAboutAction,
382                  SIGNAL(triggered()),                  SIGNAL(triggered()),
383                  SLOT(helpAbout()));                  SLOT(helpAbout()));
384          QObject::connect(ui.helpAboutQtAction,          QObject::connect(m_ui.helpAboutQtAction,
385                  SIGNAL(triggered()),                  SIGNAL(triggered()),
386                  SLOT(helpAboutQt()));                  SLOT(helpAboutQt()));
387    
388          QObject::connect(ui.fileMenu,          QObject::connect(m_ui.fileMenu,
389                  SIGNAL(aboutToShow()),                  SIGNAL(aboutToShow()),
390                  SLOT(updateRecentFilesMenu()));                  SLOT(updateRecentFilesMenu()));
391            QObject::connect(m_ui.channelsMenu,
392                    SIGNAL(aboutToShow()),
393                    SLOT(channelsMenuAboutToShow()));
394  }  }
395    
396  // Destructor.  // Destructor.
397  MainForm::~MainForm()  MainForm::~MainForm()
398  {  {
399      // Do final processing anyway.          // Do final processing anyway.
400      processServerExit();          processServerExit();
401    
402  #if defined(WIN32)  #if defined(WIN32)
403      WSACleanup();          WSACleanup();
404    #endif
405    
406    #ifdef HAVE_SIGNAL_H
407            if (m_pUsr1Notifier)
408                    delete m_pUsr1Notifier;
409  #endif  #endif
410    
411      // Finally drop any widgets around...          // Finally drop any widgets around...
412      if (m_pDeviceForm)          if (m_pDeviceForm)
413          delete m_pDeviceForm;                  delete m_pDeviceForm;
414      if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
415          delete m_pInstrumentListForm;                  delete m_pInstrumentListForm;
416      if (m_pMessages)          if (m_pMessages)
417          delete m_pMessages;                  delete m_pMessages;
418      if (m_pWorkspace)          if (m_pWorkspace)
419          delete m_pWorkspace;                  delete m_pWorkspace;
420    
421      // Delete status item labels one by one.          // Delete status item labels one by one.
422      if (m_statusItem[QSAMPLER_STATUS_CLIENT])          if (m_statusItem[QSAMPLER_STATUS_CLIENT])
423          delete m_statusItem[QSAMPLER_STATUS_CLIENT];                  delete m_statusItem[QSAMPLER_STATUS_CLIENT];
424      if (m_statusItem[QSAMPLER_STATUS_SERVER])          if (m_statusItem[QSAMPLER_STATUS_SERVER])
425          delete m_statusItem[QSAMPLER_STATUS_SERVER];                  delete m_statusItem[QSAMPLER_STATUS_SERVER];
426      if (m_statusItem[QSAMPLER_STATUS_CHANNEL])          if (m_statusItem[QSAMPLER_STATUS_CHANNEL])
427          delete m_statusItem[QSAMPLER_STATUS_CHANNEL];                  delete m_statusItem[QSAMPLER_STATUS_CHANNEL];
428      if (m_statusItem[QSAMPLER_STATUS_SESSION])          if (m_statusItem[QSAMPLER_STATUS_SESSION])
429          delete m_statusItem[QSAMPLER_STATUS_SESSION];                  delete m_statusItem[QSAMPLER_STATUS_SESSION];
430    
431  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
432          delete m_pVolumeSpinBox;          delete m_pVolumeSpinBox;
# Line 355  MainForm::~MainForm() Line 439  MainForm::~MainForm()
439    
440    
441  // Make and set a proper setup options step.  // Make and set a proper setup options step.
442  void MainForm::setup ( qsamplerOptions *pOptions )  void MainForm::setup ( Options *pOptions )
443  {  {
444      // We got options?          // We got options?
445      m_pOptions = pOptions;          m_pOptions = pOptions;
446    
447      // What style do we create these forms?          // What style do we create these forms?
448          Qt::WindowFlags wflags = Qt::Window          Qt::WindowFlags wflags = Qt::Window
 #if QT_VERSION >= 0x040200  
449                  | Qt::CustomizeWindowHint                  | Qt::CustomizeWindowHint
 #endif  
450                  | Qt::WindowTitleHint                  | Qt::WindowTitleHint
451                  | Qt::WindowSystemMenuHint                  | Qt::WindowSystemMenuHint
452                  | Qt::WindowMinMaxButtonsHint;                  | Qt::WindowMinMaxButtonsHint
453                    | Qt::WindowCloseButtonHint;
454          if (m_pOptions->bKeepOnTop)          if (m_pOptions->bKeepOnTop)
455                  wflags |= Qt::Tool;                  wflags |= Qt::Tool;
456      // Some child forms are to be created right now.  
457      m_pMessages = new qsamplerMessages(this);          // Some child forms are to be created right now.
458      m_pDeviceForm = new DeviceForm(this, wflags);          m_pMessages = new Messages(this);
459            m_pDeviceForm = new DeviceForm(this, wflags);
460  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
461      m_pInstrumentListForm = new InstrumentListForm(this, wflags);          m_pInstrumentListForm = new InstrumentListForm(this, wflags);
         QObject::connect(&m_pInstrumentListForm->model,  
                 SIGNAL(instrumentsChanged()),  
                 SLOT(sessionDirty()));  
462  #else  #else
463          viewInstrumentsAction->setEnabled(false);          m_ui.viewInstrumentsAction->setEnabled(false);
464  #endif  #endif
465      // Set message defaults...  
466      updateMessagesFont();          // Setup messages logging appropriately...
467      updateMessagesLimit();          m_pMessages->setLogging(
468      updateMessagesCapture();                  m_pOptions->bMessagesLog,
469      // Set the visibility signal.                  m_pOptions->sMessagesLogPath);
470    
471            // Set message defaults...
472            updateMessagesFont();
473            updateMessagesLimit();
474            updateMessagesCapture();
475            // Set the visibility signal.
476          QObject::connect(m_pMessages,          QObject::connect(m_pMessages,
477                  SIGNAL(visibilityChanged(bool)),                  SIGNAL(visibilityChanged(bool)),
478                  SLOT(stabilizeForm()));                  SLOT(stabilizeForm()));
479    
480      // Initial decorations toggle state.          // Initial decorations toggle state.
481      ui.viewMenubarAction->setChecked(m_pOptions->bMenubar);          m_ui.viewMenubarAction->setChecked(m_pOptions->bMenubar);
482      ui.viewToolbarAction->setChecked(m_pOptions->bToolbar);          m_ui.viewToolbarAction->setChecked(m_pOptions->bToolbar);
483      ui.viewStatusbarAction->setChecked(m_pOptions->bStatusbar);          m_ui.viewStatusbarAction->setChecked(m_pOptions->bStatusbar);
484      ui.channelsAutoArrangeAction->setChecked(m_pOptions->bAutoArrange);          m_ui.channelsAutoArrangeAction->setChecked(m_pOptions->bAutoArrange);
485    
486      // Initial decorations visibility state.          // Initial decorations visibility state.
487      viewMenubar(m_pOptions->bMenubar);          viewMenubar(m_pOptions->bMenubar);
488      viewToolbar(m_pOptions->bToolbar);          viewToolbar(m_pOptions->bToolbar);
489      viewStatusbar(m_pOptions->bStatusbar);          viewStatusbar(m_pOptions->bStatusbar);
490    
491      addDockWidget(Qt::BottomDockWidgetArea, m_pMessages);          addDockWidget(Qt::BottomDockWidgetArea, m_pMessages);
492    
493          // Restore whole dock windows state.          // Restore whole dock windows state.
494          QByteArray aDockables = m_pOptions->settings().value(          QByteArray aDockables = m_pOptions->settings().value(
# Line 410  void MainForm::setup ( qsamplerOptions * Line 497  void MainForm::setup ( qsamplerOptions *
497                  restoreState(aDockables);                  restoreState(aDockables);
498          }          }
499    
500      // Try to restore old window positioning and initial visibility.          // Try to restore old window positioning and initial visibility.
501      m_pOptions->loadWidgetGeometry(this);          m_pOptions->loadWidgetGeometry(this, true);
502      m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);          m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);
503      m_pOptions->loadWidgetGeometry(m_pDeviceForm);          m_pOptions->loadWidgetGeometry(m_pDeviceForm);
504    
505      // Final startup stabilization...          // Final startup stabilization...
506      updateMaxVolume();          updateMaxVolume();
507      updateRecentFilesMenu();          updateRecentFilesMenu();
508      stabilizeForm();          stabilizeForm();
509    
510      // Make it ready :-)          // Make it ready :-)
511      statusBar()->showMessage(tr("Ready"), 3000);          statusBar()->showMessage(tr("Ready"), 3000);
512    
513      // We'll try to start immediately...          // We'll try to start immediately...
514      startSchedule(0);          startSchedule(0);
515    
516      // Register the first timer slot.          // Register the first timer slot.
517      QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));          QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
518  }  }
519    
520    
521  // Window close event handlers.  // Window close event handlers.
522  bool MainForm::queryClose (void)  bool MainForm::queryClose (void)
523  {  {
524      bool bQueryClose = closeSession(false);          bool bQueryClose = closeSession(false);
525    
526      // Try to save current general state...          // Try to save current general state...
527      if (m_pOptions) {          if (m_pOptions) {
528          // Some windows default fonts is here on demand too.                  // Some windows default fonts is here on demand too.
529          if (bQueryClose && m_pMessages)                  if (bQueryClose && m_pMessages)
530              m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
531          // Try to save current positioning.                  // Try to save current positioning.
532          if (bQueryClose) {                  if (bQueryClose) {
533              // Save decorations state.                          // Save decorations state.
534              m_pOptions->bMenubar = ui.MenuBar->isVisible();                          m_pOptions->bMenubar = m_ui.MenuBar->isVisible();
535              m_pOptions->bToolbar = (ui.fileToolbar->isVisible() || ui.editToolbar->isVisible() || ui.channelsToolbar->isVisible());                          m_pOptions->bToolbar = (m_ui.fileToolbar->isVisible()
536              m_pOptions->bStatusbar = statusBar()->isVisible();                                  || m_ui.editToolbar->isVisible()
537              // Save the dock windows state.                                  || m_ui.channelsToolbar->isVisible());
538              const QString sDockables = saveState().toBase64().data();                          m_pOptions->bStatusbar = statusBar()->isVisible();
539                            // Save the dock windows state.
540                            const QString sDockables = saveState().toBase64().data();
541                          m_pOptions->settings().setValue("/Layout/DockWindows", saveState());                          m_pOptions->settings().setValue("/Layout/DockWindows", saveState());
542              // And the children, and the main windows state,.                          // And the children, and the main windows state,.
543                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);
544                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);
545                          m_pOptions->saveWidgetGeometry(this);                          m_pOptions->saveWidgetGeometry(this, true);
546                          // Close popup widgets.                          // Close popup widgets.
547                          if (m_pInstrumentListForm)                          if (m_pInstrumentListForm)
548                                  m_pInstrumentListForm->close();                                  m_pInstrumentListForm->close();
549                          if (m_pDeviceForm)                          if (m_pDeviceForm)
550                                  m_pDeviceForm->close();                                  m_pDeviceForm->close();
551              // Stop client and/or server, gracefully.                          // Stop client and/or server, gracefully.
552              stopServer();                          stopServer(true /*interactive*/);
553          }                  }
554      }          }
555    
556      return bQueryClose;          return bQueryClose;
557  }  }
558    
559    
560  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )
561  {  {
562      if (queryClose())          if (queryClose()) {
563          pCloseEvent->accept();                  DeviceStatusForm::deleteAllInstances();
564      else                  pCloseEvent->accept();
565          pCloseEvent->ignore();          } else
566                    pCloseEvent->ignore();
567  }  }
568    
569    
# Line 501  void MainForm::dropEvent ( QDropEvent* p Line 591  void MainForm::dropEvent ( QDropEvent* p
591                  QListIterator<QUrl> iter(pMimeData->urls());                  QListIterator<QUrl> iter(pMimeData->urls());
592                  while (iter.hasNext()) {                  while (iter.hasNext()) {
593                          const QString& sPath = iter.next().toLocalFile();                          const QString& sPath = iter.next().toLocalFile();
594                          if (qsamplerChannel::isInstrumentFile(sPath)) {                  //      if (Channel::isDlsInstrumentFile(sPath)) {
595                            if (QFileInfo(sPath).exists()) {
596                                  // Try to create a new channel from instrument file...                                  // Try to create a new channel from instrument file...
597                                  qsamplerChannel *pChannel = new qsamplerChannel();                                  Channel *pChannel = new Channel();
598                                  if (pChannel == NULL)                                  if (pChannel == NULL)
599                                          return;                                          return;
600                                  // Start setting the instrument filename...                                  // Start setting the instrument filename...
# Line 535  void MainForm::dropEvent ( QDropEvent* p Line 626  void MainForm::dropEvent ( QDropEvent* p
626    
627    
628  // Custome event handler.  // Custome event handler.
629  void MainForm::customEvent(QEvent* pCustomEvent)  void MainForm::customEvent ( QEvent* pEvent )
630  {  {
631      // For the time being, just pump it to messages.          // For the time being, just pump it to messages.
632      if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {          if (pEvent->type() == QSAMPLER_LSCP_EVENT) {
633          qsamplerCustomEvent *pEvent = (qsamplerCustomEvent *) pCustomEvent;                  LscpEvent *pLscpEvent = static_cast<LscpEvent *> (pEvent);
634                  if (pEvent->event() == LSCP_EVENT_CHANNEL_INFO) {                  switch (pLscpEvent->event()) {
635                          int iChannelID = pEvent->data().toInt();                          case LSCP_EVENT_CHANNEL_COUNT:
636                          ChannelStrip *pChannelStrip = channelStrip(iChannelID);                                  updateAllChannelStrips(true);
637                          if (pChannelStrip)                                  break;
638                                  channelStripChanged(pChannelStrip);                          case LSCP_EVENT_CHANNEL_INFO: {
639                  } else {                                  int iChannelID = pLscpEvent->data().toInt();
640                          appendMessagesColor(tr("Notify event: %1 data: %2")                                  ChannelStrip *pChannelStrip = channelStrip(iChannelID);
641                                  .arg(::lscp_event_to_text(pEvent->event()))                                  if (pChannelStrip)
642                                  .arg(pEvent->data()), "#996699");                                          channelStripChanged(pChannelStrip);
643                                    break;
644                            }
645                            case LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT:
646                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
647                                    DeviceStatusForm::onDevicesChanged();
648                                    updateViewMidiDeviceStatusMenu();
649                                    break;
650                            case LSCP_EVENT_MIDI_INPUT_DEVICE_INFO: {
651                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
652                                    const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt();
653                                    DeviceStatusForm::onDeviceChanged(iDeviceID);
654                                    break;
655                            }
656                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT:
657                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
658                                    break;
659                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO:
660                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
661                                    break;
662                    #if CONFIG_EVENT_CHANNEL_MIDI
663                            case LSCP_EVENT_CHANNEL_MIDI: {
664                                    const int iChannelID = pLscpEvent->data().section(' ', 0, 0).toInt();
665                                    ChannelStrip *pChannelStrip = channelStrip(iChannelID);
666                                    if (pChannelStrip)
667                                            pChannelStrip->midiActivityLedOn();
668                                    break;
669                            }
670                    #endif
671                    #if CONFIG_EVENT_DEVICE_MIDI
672                            case LSCP_EVENT_DEVICE_MIDI: {
673                                    const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt();
674                                    const int iPortID   = pLscpEvent->data().section(' ', 1, 1).toInt();
675                                    DeviceStatusForm *pDeviceStatusForm
676                                            = DeviceStatusForm::getInstance(iDeviceID);
677                                    if (pDeviceStatusForm)
678                                            pDeviceStatusForm->midiArrived(iPortID);
679                                    break;
680                            }
681                    #endif
682                            default:
683                                    appendMessagesColor(tr("LSCP Event: %1 data: %2")
684                                            .arg(::lscp_event_to_text(pLscpEvent->event()))
685                                            .arg(pLscpEvent->data()), "#996699");
686                  }                  }
687      }          }
688    }
689    
690    
691    // LADISH Level 1 -- SIGUSR1 signal handler.
692    void MainForm::handle_sigusr1 (void)
693    {
694            char c;
695    
696            if (::read(g_fdUsr1[1], &c, sizeof(c)) > 0)
697                    saveSession(false);
698  }  }
699    
700    
701    void MainForm::updateViewMidiDeviceStatusMenu (void)
702    {
703            m_ui.viewMidiDeviceStatusMenu->clear();
704            const std::map<int, DeviceStatusForm *> statusForms
705                    = DeviceStatusForm::getInstances();
706            std::map<int, DeviceStatusForm *>::const_iterator iter
707                    = statusForms.begin();
708            for ( ; iter != statusForms.end(); ++iter) {
709                    DeviceStatusForm *pStatusForm = iter->second;
710                    m_ui.viewMidiDeviceStatusMenu->addAction(
711                            pStatusForm->visibleAction());
712            }
713    }
714    
715    
716  // Context menu event handler.  // Context menu event handler.
717  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )
718  {  {
719      stabilizeForm();          stabilizeForm();
720    
721      ui.editMenu->exec(pEvent->globalPos());          m_ui.editMenu->exec(pEvent->globalPos());
722  }  }
723    
724    
# Line 566  void MainForm::contextMenuEvent( QContex Line 726  void MainForm::contextMenuEvent( QContex
726  // qsamplerMainForm -- Brainless public property accessors.  // qsamplerMainForm -- Brainless public property accessors.
727    
728  // The global options settings property.  // The global options settings property.
729  qsamplerOptions *MainForm::options (void)  Options *MainForm::options (void) const
730  {  {
731      return m_pOptions;          return m_pOptions;
732  }  }
733    
734    
735  // The LSCP client descriptor property.  // The LSCP client descriptor property.
736  lscp_client_t *MainForm::client (void)  lscp_client_t *MainForm::client (void) const
737  {  {
738      return m_pClient;          return m_pClient;
739  }  }
740    
741    
# Line 592  MainForm *MainForm::getInstance (void) Line 752  MainForm *MainForm::getInstance (void)
752  // Format the displayable session filename.  // Format the displayable session filename.
753  QString MainForm::sessionName ( const QString& sFilename )  QString MainForm::sessionName ( const QString& sFilename )
754  {  {
755      bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);          bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);
756      QString sSessionName = sFilename;          QString sSessionName = sFilename;
757      if (sSessionName.isEmpty())          if (sSessionName.isEmpty())
758          sSessionName = tr("Untitled") + QString::number(m_iUntitled);                  sSessionName = tr("Untitled") + QString::number(m_iUntitled);
759      else if (!bCompletePath)          else if (!bCompletePath)
760          sSessionName = QFileInfo(sSessionName).fileName();                  sSessionName = QFileInfo(sSessionName).fileName();
761      return sSessionName;          return sSessionName;
762  }  }
763    
764    
765  // Create a new session file from scratch.  // Create a new session file from scratch.
766  bool MainForm::newSession (void)  bool MainForm::newSession (void)
767  {  {
768      // Check if we can do it.          // Check if we can do it.
769      if (!closeSession(true))          if (!closeSession(true))
770          return false;                  return false;
771    
772          // Give us what the server has, right now...          // Give us what the server has, right now...
773          updateSession();          updateSession();
774    
775      // Ok increment untitled count.          // Ok increment untitled count.
776      m_iUntitled++;          m_iUntitled++;
777    
778      // Stabilize form.          // Stabilize form.
779      m_sFilename = QString::null;          m_sFilename = QString::null;
780      m_iDirtyCount = 0;          m_iDirtyCount = 0;
781      appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));          appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));
782      stabilizeForm();          stabilizeForm();
783    
784      return true;          return true;
785  }  }
786    
787    
788  // Open an existing sampler session.  // Open an existing sampler session.
789  bool MainForm::openSession (void)  bool MainForm::openSession (void)
790  {  {
791      if (m_pOptions == NULL)          if (m_pOptions == NULL)
792          return false;                  return false;
793    
794      // Ask for the filename to open...          // Ask for the filename to open...
795          QString sFilename = QFileDialog::getOpenFileName(this,          QString sFilename = QFileDialog::getOpenFileName(this,
796                  QSAMPLER_TITLE ": " + tr("Open Session"), // Caption.                  QSAMPLER_TITLE ": " + tr("Open Session"), // Caption.
797                  m_pOptions->sSessionDir,                  // Start here.                  m_pOptions->sSessionDir,                  // Start here.
798                  tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)                  tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
799          );          );
800    
801      // Have we cancelled?          // Have we cancelled?
802      if (sFilename.isEmpty())          if (sFilename.isEmpty())
803          return false;                  return false;
   
     // Check if we're going to discard safely the current one...  
     if (!closeSession(true))  
         return false;  
804    
805      // Load it right away.          // Check if we're going to discard safely the current one...
806      return loadSessionFile(sFilename);          if (!closeSession(true))
807                    return false;
808    
809            // Load it right away.
810            return loadSessionFile(sFilename);
811  }  }
812    
813    
814  // Save current sampler session with another name.  // Save current sampler session with another name.
815  bool MainForm::saveSession ( bool bPrompt )  bool MainForm::saveSession ( bool bPrompt )
816  {  {
817      if (m_pOptions == NULL)          if (m_pOptions == NULL)
818          return false;                  return false;
819    
820      QString sFilename = m_sFilename;          QString sFilename = m_sFilename;
821    
822      // Ask for the file to save, if there's none...          // Ask for the file to save, if there's none...
823      if (bPrompt || sFilename.isEmpty()) {          if (bPrompt || sFilename.isEmpty()) {
824          // If none is given, assume default directory.                  // If none is given, assume default directory.
825          if (sFilename.isEmpty())                  if (sFilename.isEmpty())
826              sFilename = m_pOptions->sSessionDir;                          sFilename = m_pOptions->sSessionDir;
827          // Prompt the guy...                  // Prompt the guy...
828                  sFilename = QFileDialog::getSaveFileName(this,                  sFilename = QFileDialog::getSaveFileName(this,
829                          QSAMPLER_TITLE ": " + tr("Save Session"), // Caption.                          QSAMPLER_TITLE ": " + tr("Save Session"), // Caption.
830                          sFilename,                                // Start here.                          sFilename,                                // Start here.
831                          tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)                          tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
832                  );                  );
833          // Have we cancelled it?                  // Have we cancelled it?
834          if (sFilename.isEmpty())                  if (sFilename.isEmpty())
835              return false;                          return false;
836          // Enforce .lscp extension...                  // Enforce .lscp extension...
837          if (QFileInfo(sFilename).suffix().isEmpty())                  if (QFileInfo(sFilename).suffix().isEmpty())
838              sFilename += ".lscp";                          sFilename += ".lscp";
839          // Check if already exists...                  // Check if already exists...
840          if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {                  if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {
841              if (QMessageBox::warning(this,                          if (QMessageBox::warning(this,
842                                  QSAMPLER_TITLE ": " + tr("Warning"),                                  QSAMPLER_TITLE ": " + tr("Warning"),
843                  tr("The file already exists:\n\n"                                  tr("The file already exists:\n\n"
844                     "\"%1\"\n\n"                                  "\"%1\"\n\n"
845                     "Do you want to replace it?")                                  "Do you want to replace it?")
846                     .arg(sFilename),                                  .arg(sFilename),
847                  tr("Replace"), tr("Cancel")) > 0)                                  QMessageBox::Yes | QMessageBox::No)
848                  return false;                                  == QMessageBox::No)
849          }                                  return false;
850      }                  }
851            }
852    
853      // Save it right away.          // Save it right away.
854      return saveSessionFile(sFilename);          return saveSessionFile(sFilename);
855  }  }
856    
857    
858  // Close current session.  // Close current session.
859  bool MainForm::closeSession ( bool bForce )  bool MainForm::closeSession ( bool bForce )
860  {  {
861      bool bClose = true;          bool bClose = true;
862    
863      // Are we dirty enough to prompt it?          // Are we dirty enough to prompt it?
864      if (m_iDirtyCount > 0) {          if (m_iDirtyCount > 0) {
865          switch (QMessageBox::warning(this,                  switch (QMessageBox::warning(this,
866                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
867              tr("The current session has been changed:\n\n"                          tr("The current session has been changed:\n\n"
868              "\"%1\"\n\n"                          "\"%1\"\n\n"
869              "Do you want to save the changes?")                          "Do you want to save the changes?")
870              .arg(sessionName(m_sFilename)),                          .arg(sessionName(m_sFilename)),
871              tr("Save"), tr("Discard"), tr("Cancel"))) {                          QMessageBox::Save |
872          case 0:     // Save...                          QMessageBox::Discard |
873              bClose = saveSession(false);                          QMessageBox::Cancel)) {
874              // Fall thru....                  case QMessageBox::Save:
875          case 1:     // Discard                          bClose = saveSession(false);
876              break;                          // Fall thru....
877          default:    // Cancel.                  case QMessageBox::Discard:
878              bClose = false;                          break;
879              break;                  default:    // Cancel.
880          }                          bClose = false;
881      }                          break;
882                    }
883      // If we may close it, dot it.          }
884      if (bClose) {  
885          // Remove all channel strips from sight...          // If we may close it, dot it.
886          m_pWorkspace->setUpdatesEnabled(false);          if (bClose) {
887          QWidgetList wlist = m_pWorkspace->windowList();                  // Remove all channel strips from sight...
888          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  m_pWorkspace->setUpdatesEnabled(false);
889              ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  QWidgetList wlist = m_pWorkspace->windowList();
890              if (pChannelStrip) {                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
891                  qsamplerChannel *pChannel = pChannelStrip->channel();                          ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
892                  if (bForce && pChannel)                          if (pChannelStrip) {
893                      pChannel->removeChannel();                                  Channel *pChannel = pChannelStrip->channel();
894                  delete pChannelStrip;                                  if (bForce && pChannel)
895              }                                          pChannel->removeChannel();
896          }                                  delete pChannelStrip;
897          m_pWorkspace->setUpdatesEnabled(true);                          }
898          // We're now clean, for sure.                  }
899          m_iDirtyCount = 0;                  m_pWorkspace->setUpdatesEnabled(true);
900      }                  // We're now clean, for sure.
901                    m_iDirtyCount = 0;
902            }
903    
904      return bClose;          return bClose;
905  }  }
906    
907    
908  // Load a session from specific file path.  // Load a session from specific file path.
909  bool MainForm::loadSessionFile ( const QString& sFilename )  bool MainForm::loadSessionFile ( const QString& sFilename )
910  {  {
911      if (m_pClient == NULL)          if (m_pClient == NULL)
912          return false;                  return false;
913    
914      // Open and read from real file.          // Open and read from real file.
915      QFile file(sFilename);          QFile file(sFilename);
916      if (!file.open(QIODevice::ReadOnly)) {          if (!file.open(QIODevice::ReadOnly)) {
917          appendMessagesError(tr("Could not open \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
918          return false;                          tr("Could not open \"%1\" session file.\n\nSorry.")
919      }                          .arg(sFilename));
920                    return false;
921            }
922    
923          // Tell the world we'll take some time...          // Tell the world we'll take some time...
924          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
925    
926      // Read the file.          // Read the file.
927          int iLine = 0;          int iLine = 0;
928      int iErrors = 0;          int iErrors = 0;
929      QTextStream ts(&file);          QTextStream ts(&file);
930      while (!ts.atEnd()) {          while (!ts.atEnd()) {
931          // Read the line.                  // Read the line.
932          QString sCommand = ts.readLine().trimmed();                  QString sCommand = ts.readLine().trimmed();
933                  iLine++;                  iLine++;
934          // If not empty, nor a comment, call the server...                  // If not empty, nor a comment, call the server...
935          if (!sCommand.isEmpty() && sCommand[0] != '#') {                  if (!sCommand.isEmpty() && sCommand[0] != '#') {
936                          // Remember that, no matter what,                          // Remember that, no matter what,
937                          // all LSCP commands are CR/LF terminated.                          // all LSCP commands are CR/LF terminated.
938                          sCommand += "\r\n";                          sCommand += "\r\n";
# Line 779  bool MainForm::loadSessionFile ( const Q Line 944  bool MainForm::loadSessionFile ( const Q
944                                  appendMessagesClient("lscp_client_query");                                  appendMessagesClient("lscp_client_query");
945                                  iErrors++;                                  iErrors++;
946                          }                          }
947          }                  }
948          // Try to make it snappy :)                  // Try to make it snappy :)
949          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
950      }          }
951    
952      // Ok. we've read it.          // Ok. we've read it.
953      file.close();          file.close();
954    
955          // Now we'll try to create (update) the whole GUI session.          // Now we'll try to create (update) the whole GUI session.
956          updateSession();          updateSession();
# Line 794  bool MainForm::loadSessionFile ( const Q Line 959  bool MainForm::loadSessionFile ( const Q
959          QApplication::restoreOverrideCursor();          QApplication::restoreOverrideCursor();
960    
961          // Have we any errors?          // Have we any errors?
962          if (iErrors > 0)          if (iErrors > 0) {
963                  appendMessagesError(tr("Session loaded with errors\nfrom \"%1\".\n\nSorry.").arg(sFilename));                  appendMessagesError(
964                            tr("Session loaded with errors\nfrom \"%1\".\n\nSorry.")
965                            .arg(sFilename));
966            }
967    
968      // Save as default session directory.          // Save as default session directory.
969      if (m_pOptions)          if (m_pOptions)
970          m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();                  m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();
971          // We're not dirty anymore, if loaded without errors,          // We're not dirty anymore, if loaded without errors,
972          m_iDirtyCount = iErrors;          m_iDirtyCount = iErrors;
973      // Stabilize form...          // Stabilize form...
974      m_sFilename = sFilename;          m_sFilename = sFilename;
975      updateRecentFiles(sFilename);          updateRecentFiles(sFilename);
976      appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));          appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));
977    
978      // Make that an overall update.          // Make that an overall update.
979      stabilizeForm();          stabilizeForm();
980      return true;          return true;
981  }  }
982    
983    
# Line 825  bool MainForm::saveSessionFile ( const Q Line 993  bool MainForm::saveSessionFile ( const Q
993                  return false;                  return false;
994          }          }
995    
996      // Open and write into real file.          // Open and write into real file.
997      QFile file(sFilename);          QFile file(sFilename);
998      if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {          if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
999          appendMessagesError(tr("Could not open \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
1000          return false;                          tr("Could not open \"%1\" session file.\n\nSorry.")
1001      }                          .arg(sFilename));
1002                    return false;
1003            }
1004    
1005          // Tell the world we'll take some time...          // Tell the world we'll take some time...
1006          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1007    
1008      // Write the file.          // Write the file.
1009      int  iErrors = 0;          int  iErrors = 0;
1010      QTextStream ts(&file);          QTextStream ts(&file);
1011      ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;          ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;
1012      ts << "# " << tr("Version")          ts << "# " << tr("Version")
1013         << ": " QSAMPLER_VERSION << endl;          << ": " QSAMPLER_VERSION << endl;
1014      ts << "# " << tr("Build")          ts << "# " << tr("Build")
1015         << ": " __DATE__ " " __TIME__ << endl;          << ": " __DATE__ " " __TIME__ << endl;
1016      ts << "#"  << endl;          ts << "#"  << endl;
1017      ts << "# " << tr("File")          ts << "# " << tr("File")
1018         << ": " << QFileInfo(sFilename).fileName() << endl;          << ": " << QFileInfo(sFilename).fileName() << endl;
1019      ts << "# " << tr("Date")          ts << "# " << tr("Date")
1020         << ": " << QDate::currentDate().toString("MMM dd yyyy")          << ": " << QDate::currentDate().toString("MMM dd yyyy")
1021         << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;          << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;
1022      ts << "#"  << endl;          ts << "#"  << endl;
1023      ts << endl;          ts << endl;
1024    
1025          // It is assumed that this new kind of device+session file          // It is assumed that this new kind of device+session file
1026          // will be loaded from a complete initialized server...          // will be loaded from a complete initialized server...
# Line 860  bool MainForm::saveSessionFile ( const Q Line 1030  bool MainForm::saveSessionFile ( const Q
1030    
1031          // Audio device mapping.          // Audio device mapping.
1032          QMap<int, int> audioDeviceMap;          QMap<int, int> audioDeviceMap;
1033          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Audio);          piDeviceIDs = Device::getDevices(m_pClient, Device::Audio);
1034          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
1035                  ts << endl;                  ts << endl;
1036                  qsamplerDevice device(qsamplerDevice::Audio, piDeviceIDs[iDevice]);                  Device device(Device::Audio, piDeviceIDs[iDevice]);
1037                  // Audio device specification...                  // Audio device specification...
1038                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1039                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1040                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();
1041                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
1042                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
1043                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
1044                                          ++deviceParam) {                                          ++deviceParam) {
1045                          const qsamplerDeviceParam& param = deviceParam.value();                          const DeviceParam& param = deviceParam.value();
1046                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
1047                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
1048                  }                  }
1049                  ts << endl;                  ts << endl;
1050                  // Audio channel parameters...                  // Audio channel parameters...
1051                  int iPort = 0;                  int iPort = 0;
1052                  QListIterator<qsamplerDevicePort *> iter(device.ports());                  QListIterator<DevicePort *> iter(device.ports());
1053                  while (iter.hasNext()) {                  while (iter.hasNext()) {
1054                          qsamplerDevicePort *pPort = iter.next();                          DevicePort *pPort = iter.next();
1055                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1056                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1057                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1058                                                  ++portParam) {                                                  ++portParam) {
1059                                  const qsamplerDeviceParam& param = portParam.value();                                  const DeviceParam& param = portParam.value();
1060                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1061                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice
1062                                          << " " << iPort << " " << portParam.key()                                          << " " << iPort << " " << portParam.key()
# Line 902  bool MainForm::saveSessionFile ( const Q Line 1072  bool MainForm::saveSessionFile ( const Q
1072    
1073          // MIDI device mapping.          // MIDI device mapping.
1074          QMap<int, int> midiDeviceMap;          QMap<int, int> midiDeviceMap;
1075          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Midi);          piDeviceIDs = Device::getDevices(m_pClient, Device::Midi);
1076          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
1077                  ts << endl;                  ts << endl;
1078                  qsamplerDevice device(qsamplerDevice::Midi, piDeviceIDs[iDevice]);                  Device device(Device::Midi, piDeviceIDs[iDevice]);
1079                  // MIDI device specification...                  // MIDI device specification...
1080                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1081                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1082                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();
1083                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
1084                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
1085                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
1086                                          ++deviceParam) {                                          ++deviceParam) {
1087                          const qsamplerDeviceParam& param = deviceParam.value();                          const DeviceParam& param = deviceParam.value();
1088                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
1089                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
1090                  }                  }
1091                  ts << endl;                  ts << endl;
1092                  // MIDI port parameters...                  // MIDI port parameters...
1093                  int iPort = 0;                  int iPort = 0;
1094                  QListIterator<qsamplerDevicePort *> iter(device.ports());                  QListIterator<DevicePort *> iter(device.ports());
1095                  while (iter.hasNext()) {                  while (iter.hasNext()) {
1096                          qsamplerDevicePort *pPort = iter.next();                          DevicePort *pPort = iter.next();
1097                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1098                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1099                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1100                                                  ++portParam) {                                                  ++portParam) {
1101                                  const qsamplerDeviceParam& param = portParam.value();                                  const DeviceParam& param = portParam.value();
1102                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1103                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice
1104                                     << " " << iPort << " " << portParam.key()                                  << " " << iPort << " " << portParam.key()
1105                                     << "='" << param.value << "'" << endl;                                  << "='" << param.value << "'" << endl;
1106                          }                          }
1107                          iPort++;                          iPort++;
1108                  }                  }
# Line 1015  bool MainForm::saveSessionFile ( const Q Line 1185  bool MainForm::saveSessionFile ( const Q
1185  #endif  // CONFIG_MIDI_INSTRUMENT  #endif  // CONFIG_MIDI_INSTRUMENT
1186    
1187          // Sampler channel mapping.          // Sampler channel mapping.
1188      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
1189      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1190          ChannelStrip* pChannelStrip                  ChannelStrip* pChannelStrip
1191                          = static_cast<ChannelStrip *> (wlist.at(iChannel));                          = static_cast<ChannelStrip *> (wlist.at(iChannel));
1192          if (pChannelStrip) {                  if (pChannelStrip) {
1193              qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
1194              if (pChannel) {                          if (pChannel) {
1195                  ts << "# " << tr("Channel") << " " << iChannel << endl;                                  ts << "# " << tr("Channel") << " " << iChannel << endl;
1196                  ts << "ADD CHANNEL" << endl;                                  ts << "ADD CHANNEL" << endl;
1197                                  if (audioDeviceMap.isEmpty()) {                                  if (audioDeviceMap.isEmpty()) {
1198                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel
1199                                                  << " " << pChannel->audioDriver() << endl;                                                  << " " << pChannel->audioDriver() << endl;
# Line 1040  bool MainForm::saveSessionFile ( const Q Line 1210  bool MainForm::saveSessionFile ( const Q
1210                                  }                                  }
1211                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel
1212                                          << " " << pChannel->midiPort() << endl;                                          << " " << pChannel->midiPort() << endl;
1213                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";                                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";
1214                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)                                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
1215                      ts << "ALL";                                          ts << "ALL";
1216                  else                                  else
1217                      ts << pChannel->midiChannel();                                          ts << pChannel->midiChannel();
1218                  ts << endl;                                  ts << endl;
1219                  ts << "LOAD ENGINE " << pChannel->engineName() << " " << iChannel << endl;                                  ts << "LOAD ENGINE " << pChannel->engineName()
1220                                            << " " << iChannel << endl;
1221                                  if (pChannel->instrumentStatus() < 100) ts << "# ";                                  if (pChannel->instrumentStatus() < 100) ts << "# ";
1222                                  ts << "LOAD INSTRUMENT NON_MODAL '" << pChannel->instrumentFile() << "' "                                  ts << "LOAD INSTRUMENT NON_MODAL '"
1223                                            << pChannel->instrumentFile() << "' "
1224                                          << pChannel->instrumentNr() << " " << iChannel << endl;                                          << pChannel->instrumentNr() << " " << iChannel << endl;
1225                                  qsamplerChannelRoutingMap::ConstIterator audioRoute;                                  ChannelRoutingMap::ConstIterator audioRoute;
1226                                  for (audioRoute = pChannel->audioRouting().begin();                                  for (audioRoute = pChannel->audioRouting().begin();
1227                                                  audioRoute != pChannel->audioRouting().end();                                                  audioRoute != pChannel->audioRouting().end();
1228                                                          ++audioRoute) {                                                          ++audioRoute) {
# Line 1106  bool MainForm::saveSessionFile ( const Q Line 1278  bool MainForm::saveSessionFile ( const Q
1278                                          }                                          }
1279                                  }                                  }
1280  #endif  #endif
1281                  ts << endl;                                  ts << endl;
1282              }                          }
1283          }                  }
1284          // Try to keep it snappy :)                  // Try to keep it snappy :)
1285          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1286      }          }
1287    
1288  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
1289          ts << "# " << tr("Global volume level") << endl;          ts << "# " << tr("Global volume level") << endl;
# Line 1119  bool MainForm::saveSessionFile ( const Q Line 1291  bool MainForm::saveSessionFile ( const Q
1291          ts << endl;          ts << endl;
1292  #endif  #endif
1293    
1294      // Ok. we've wrote it.          // Ok. we've wrote it.
1295      file.close();          file.close();
1296    
1297          // We're fornerly done.          // We're fornerly done.
1298          QApplication::restoreOverrideCursor();          QApplication::restoreOverrideCursor();
1299    
1300      // Have we any errors?          // Have we any errors?
1301      if (iErrors > 0)          if (iErrors > 0) {
1302          appendMessagesError(tr("Some settings could not be saved\nto \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
1303                            tr("Some settings could not be saved\n"
1304      // Save as default session directory.                          "to \"%1\" session file.\n\nSorry.")
1305      if (m_pOptions)                          .arg(sFilename));
1306          m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();          }
1307      // We're not dirty anymore.  
1308      m_iDirtyCount = 0;          // Save as default session directory.
1309      // Stabilize form...          if (m_pOptions)
1310      m_sFilename = sFilename;                  m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();
1311      updateRecentFiles(sFilename);          // We're not dirty anymore.
1312      appendMessages(tr("Save session: \"%1\".").arg(sessionName(m_sFilename)));          m_iDirtyCount = 0;
1313      stabilizeForm();          // Stabilize form...
1314      return true;          m_sFilename = sFilename;
1315            updateRecentFiles(sFilename);
1316            appendMessages(tr("Save session: \"%1\".").arg(sessionName(m_sFilename)));
1317            stabilizeForm();
1318            return true;
1319  }  }
1320    
1321    
1322  // Session change receiver slot.  // Session change receiver slot.
1323  void MainForm::sessionDirty (void)  void MainForm::sessionDirty (void)
1324  {  {
1325      // Just mark the dirty form.          // Just mark the dirty form.
1326      m_iDirtyCount++;          m_iDirtyCount++;
1327      // and update the form status...          // and update the form status...
1328      stabilizeForm();          stabilizeForm();
1329  }  }
1330    
1331    
# Line 1159  void MainForm::sessionDirty (void) Line 1335  void MainForm::sessionDirty (void)
1335  // Create a new sampler session.  // Create a new sampler session.
1336  void MainForm::fileNew (void)  void MainForm::fileNew (void)
1337  {  {
1338      // Of course we'll start clean new.          // Of course we'll start clean new.
1339      newSession();          newSession();
1340  }  }
1341    
1342    
1343  // Open an existing sampler session.  // Open an existing sampler session.
1344  void MainForm::fileOpen (void)  void MainForm::fileOpen (void)
1345  {  {
1346      // Open it right away.          // Open it right away.
1347      openSession();          openSession();
1348  }  }
1349    
1350    
# Line 1192  void MainForm::fileOpenRecent (void) Line 1368  void MainForm::fileOpenRecent (void)
1368  // Save current sampler session.  // Save current sampler session.
1369  void MainForm::fileSave (void)  void MainForm::fileSave (void)
1370  {  {
1371      // Save it right away.          // Save it right away.
1372      saveSession(false);          saveSession(false);
1373  }  }
1374    
1375    
1376  // Save current sampler session with another name.  // Save current sampler session with another name.
1377  void MainForm::fileSaveAs (void)  void MainForm::fileSaveAs (void)
1378  {  {
1379      // Save it right away, maybe with another name.          // Save it right away, maybe with another name.
1380      saveSession(true);          saveSession(true);
1381  }  }
1382    
1383    
1384  // Reset the sampler instance.  // Reset the sampler instance.
1385  void MainForm::fileReset (void)  void MainForm::fileReset (void)
1386  {  {
1387      if (m_pClient == NULL)          if (m_pClient == NULL)
1388          return;                  return;
1389    
1390      // Ask user whether he/she want's an internal sampler reset...          // Ask user whether he/she want's an internal sampler reset...
1391      if (QMessageBox::warning(this,          if (QMessageBox::warning(this,
1392                  QSAMPLER_TITLE ": " + tr("Warning"),                  QSAMPLER_TITLE ": " + tr("Warning"),
1393          tr("Resetting the sampler instance will close\n"                  tr("Resetting the sampler instance will close\n"
1394             "all device and channel configurations.\n\n"                  "all device and channel configurations.\n\n"
1395             "Please note that this operation may cause\n"                  "Please note that this operation may cause\n"
1396             "temporary MIDI and Audio disruption.\n\n"                  "temporary MIDI and Audio disruption.\n\n"
1397             "Do you want to reset the sampler engine now?"),                  "Do you want to reset the sampler engine now?"),
1398          tr("Reset"), tr("Cancel")) > 0)                  QMessageBox::Ok | QMessageBox::Cancel)
1399          return;                  == QMessageBox::Cancel)
1400                    return;
1401    
1402          // Trye closing the current session, first...          // Trye closing the current session, first...
1403          if (!closeSession(true))          if (!closeSession(true))
1404                  return;                  return;
1405    
1406      // Just do the reset, after closing down current session...          // Just do the reset, after closing down current session...
1407          // Do the actual sampler reset...          // Do the actual sampler reset...
1408          if (::lscp_reset_sampler(m_pClient) != LSCP_OK) {          if (::lscp_reset_sampler(m_pClient) != LSCP_OK) {
1409                  appendMessagesClient("lscp_reset_sampler");                  appendMessagesClient("lscp_reset_sampler");
# Line 1234  void MainForm::fileReset (void) Line 1411  void MainForm::fileReset (void)
1411                  return;                  return;
1412          }          }
1413    
1414      // Log this.          // Log this.
1415      appendMessages(tr("Sampler reset."));          appendMessages(tr("Sampler reset."));
1416    
1417          // Make it a new session...          // Make it a new session...
1418          newSession();          newSession();
# Line 1245  void MainForm::fileReset (void) Line 1422  void MainForm::fileReset (void)
1422  // Restart the client/server instance.  // Restart the client/server instance.
1423  void MainForm::fileRestart (void)  void MainForm::fileRestart (void)
1424  {  {
1425      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1426          return;                  return;
1427    
1428      bool bRestart = true;          bool bRestart = true;
1429    
1430      // Ask user whether he/she want's a complete restart...          // Ask user whether he/she want's a complete restart...
1431      // (if we're currently up and running)          // (if we're currently up and running)
1432      if (bRestart && m_pClient) {          if (bRestart && m_pClient) {
1433          bRestart = (QMessageBox::warning(this,                  bRestart = (QMessageBox::warning(this,
1434                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
1435              tr("New settings will be effective after\n"                          tr("New settings will be effective after\n"
1436                 "restarting the client/server connection.\n\n"                          "restarting the client/server connection.\n\n"
1437                 "Please note that this operation may cause\n"                          "Please note that this operation may cause\n"
1438                 "temporary MIDI and Audio disruption.\n\n"                          "temporary MIDI and Audio disruption.\n\n"
1439                 "Do you want to restart the connection now?"),                          "Do you want to restart the connection now?"),
1440              tr("Restart"), tr("Cancel")) == 0);                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok);
1441      }          }
1442    
1443      // Are we still for it?          // Are we still for it?
1444      if (bRestart && closeSession(true)) {          if (bRestart && closeSession(true)) {
1445          // Stop server, it will force the client too.                  // Stop server, it will force the client too.
1446          stopServer();                  stopServer();
1447          // Reschedule a restart...                  // Reschedule a restart...
1448          startSchedule(m_pOptions->iStartDelay);                  startSchedule(m_pOptions->iStartDelay);
1449      }          }
1450  }  }
1451    
1452    
1453  // Exit application program.  // Exit application program.
1454  void MainForm::fileExit (void)  void MainForm::fileExit (void)
1455  {  {
1456      // Go for close the whole thing.          // Go for close the whole thing.
1457      close();          close();
1458  }  }
1459    
1460    
# Line 1287  void MainForm::fileExit (void) Line 1464  void MainForm::fileExit (void)
1464  // Add a new sampler channel.  // Add a new sampler channel.
1465  void MainForm::editAddChannel (void)  void MainForm::editAddChannel (void)
1466  {  {
1467      if (m_pClient == NULL)          if (m_pClient == NULL)
1468          return;                  return;
1469    
1470            // Just create the channel instance...
1471            Channel *pChannel = new Channel();
1472            if (pChannel == NULL)
1473                    return;
1474    
1475            // Before we show it up, may be we'll
1476            // better ask for some initial values?
1477            if (!pChannel->channelSetup(this)) {
1478                    delete pChannel;
1479                    return;
1480            }
1481    
1482      // Just create the channel instance...          // And give it to the strip...
1483      qsamplerChannel *pChannel = new qsamplerChannel();          // (will own the channel instance, if successful).
1484      if (pChannel == NULL)          if (!createChannelStrip(pChannel)) {
1485          return;                  delete pChannel;
1486                    return;
1487      // Before we show it up, may be we'll          }
1488      // better ask for some initial values?  
1489      if (!pChannel->channelSetup(this)) {          // Do we auto-arrange?
1490          delete pChannel;          if (m_pOptions && m_pOptions->bAutoArrange)
1491          return;                  channelsArrange();
1492      }  
1493            // Make that an overall update.
1494      // And give it to the strip (will own the channel instance, if successful).          m_iDirtyCount++;
1495      if (!createChannelStrip(pChannel)) {          stabilizeForm();
         delete pChannel;  
         return;  
     }  
   
     // Make that an overall update.  
     m_iDirtyCount++;  
     stabilizeForm();  
1496  }  }
1497    
1498    
1499  // Remove current sampler channel.  // Remove current sampler channel.
1500  void MainForm::editRemoveChannel (void)  void MainForm::editRemoveChannel (void)
1501  {  {
1502      if (m_pClient == NULL)          if (m_pClient == NULL)
1503          return;                  return;
1504    
1505            ChannelStrip* pChannelStrip = activeChannelStrip();
1506            if (pChannelStrip == NULL)
1507                    return;
1508    
1509            Channel *pChannel = pChannelStrip->channel();
1510            if (pChannel == NULL)
1511                    return;
1512    
1513      ChannelStrip* pChannelStrip = activeChannelStrip();          // Prompt user if he/she's sure about this...
1514      if (pChannelStrip == NULL)          if (m_pOptions && m_pOptions->bConfirmRemove) {
1515          return;                  if (QMessageBox::warning(this,
   
     qsamplerChannel *pChannel = pChannelStrip->channel();  
     if (pChannel == NULL)  
         return;  
   
     // Prompt user if he/she's sure about this...  
     if (m_pOptions && m_pOptions->bConfirmRemove) {  
         if (QMessageBox::warning(this,  
1516                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
1517              tr("About to remove channel:\n\n"                          tr("About to remove channel:\n\n"
1518                 "%1\n\n"                          "%1\n\n"
1519                 "Are you sure?")                          "Are you sure?")
1520                 .arg(pChannelStrip->windowTitle()),                          .arg(pChannelStrip->windowTitle()),
1521              tr("OK"), tr("Cancel")) > 0)                          QMessageBox::Ok | QMessageBox::Cancel)
1522              return;                          == QMessageBox::Cancel)
1523      }                          return;
1524            }
1525      // Remove the existing sampler channel.  
1526      if (!pChannel->removeChannel())          // Remove the existing sampler channel.
1527          return;          if (!pChannel->removeChannel())
1528                    return;
1529      // Just delete the channel strip.  
1530      delete pChannelStrip;          // Just delete the channel strip.
1531            delete pChannelStrip;
1532      // Do we auto-arrange?  
1533      if (m_pOptions && m_pOptions->bAutoArrange)          // Do we auto-arrange?
1534          channelsArrange();          if (m_pOptions && m_pOptions->bAutoArrange)
1535                    channelsArrange();
1536      // We'll be dirty, for sure...  
1537      m_iDirtyCount++;          // We'll be dirty, for sure...
1538      stabilizeForm();          m_iDirtyCount++;
1539            stabilizeForm();
1540  }  }
1541    
1542    
1543  // Setup current sampler channel.  // Setup current sampler channel.
1544  void MainForm::editSetupChannel (void)  void MainForm::editSetupChannel (void)
1545  {  {
1546      if (m_pClient == NULL)          if (m_pClient == NULL)
1547          return;                  return;
1548    
1549      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1550      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1551          return;                  return;
1552    
1553      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1554      pChannelStrip->channelSetup();          pChannelStrip->channelSetup();
1555  }  }
1556    
1557    
1558  // Edit current sampler channel.  // Edit current sampler channel.
1559  void MainForm::editEditChannel (void)  void MainForm::editEditChannel (void)
1560  {  {
1561      if (m_pClient == NULL)          if (m_pClient == NULL)
1562          return;                  return;
1563    
1564      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1565      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1566          return;                  return;
1567    
1568      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1569      pChannelStrip->channelEdit();          pChannelStrip->channelEdit();
1570  }  }
1571    
1572    
1573  // Reset current sampler channel.  // Reset current sampler channel.
1574  void MainForm::editResetChannel (void)  void MainForm::editResetChannel (void)
1575  {  {
1576      if (m_pClient == NULL)          if (m_pClient == NULL)
1577          return;                  return;
1578    
1579      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1580      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1581          return;                  return;
1582    
1583      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1584      pChannelStrip->channelReset();          pChannelStrip->channelReset();
1585  }  }
1586    
1587    
# Line 1427  void MainForm::editResetAllChannels (voi Line 1610  void MainForm::editResetAllChannels (voi
1610  // Show/hide the main program window menubar.  // Show/hide the main program window menubar.
1611  void MainForm::viewMenubar ( bool bOn )  void MainForm::viewMenubar ( bool bOn )
1612  {  {
1613      if (bOn)          if (bOn)
1614          ui.MenuBar->show();                  m_ui.MenuBar->show();
1615      else          else
1616          ui.MenuBar->hide();                  m_ui.MenuBar->hide();
1617  }  }
1618    
1619    
1620  // Show/hide the main program window toolbar.  // Show/hide the main program window toolbar.
1621  void MainForm::viewToolbar ( bool bOn )  void MainForm::viewToolbar ( bool bOn )
1622  {  {
1623      if (bOn) {          if (bOn) {
1624          ui.fileToolbar->show();                  m_ui.fileToolbar->show();
1625          ui.editToolbar->show();                  m_ui.editToolbar->show();
1626          ui.channelsToolbar->show();                  m_ui.channelsToolbar->show();
1627      } else {          } else {
1628          ui.fileToolbar->hide();                  m_ui.fileToolbar->hide();
1629          ui.editToolbar->hide();                  m_ui.editToolbar->hide();
1630          ui.channelsToolbar->hide();                  m_ui.channelsToolbar->hide();
1631      }          }
1632  }  }
1633    
1634    
1635  // Show/hide the main program window statusbar.  // Show/hide the main program window statusbar.
1636  void MainForm::viewStatusbar ( bool bOn )  void MainForm::viewStatusbar ( bool bOn )
1637  {  {
1638      if (bOn)          if (bOn)
1639          statusBar()->show();                  statusBar()->show();
1640      else          else
1641          statusBar()->hide();                  statusBar()->hide();
1642  }  }
1643    
1644    
1645  // Show/hide the messages window logger.  // Show/hide the messages window logger.
1646  void MainForm::viewMessages ( bool bOn )  void MainForm::viewMessages ( bool bOn )
1647  {  {
1648      if (bOn)          if (bOn)
1649          m_pMessages->show();                  m_pMessages->show();
1650      else          else
1651          m_pMessages->hide();                  m_pMessages->hide();
1652  }  }
1653    
1654    
# Line 1510  void MainForm::viewDevices (void) Line 1693  void MainForm::viewDevices (void)
1693  // Show options dialog.  // Show options dialog.
1694  void MainForm::viewOptions (void)  void MainForm::viewOptions (void)
1695  {  {
1696      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1697          return;                  return;
1698    
1699      OptionsForm* pOptionsForm = new OptionsForm(this);          OptionsForm* pOptionsForm = new OptionsForm(this);
1700      if (pOptionsForm) {          if (pOptionsForm) {
1701          // Check out some initial nullities(tm)...                  // Check out some initial nullities(tm)...
1702          ChannelStrip* pChannelStrip = activeChannelStrip();                  ChannelStrip* pChannelStrip = activeChannelStrip();
1703          if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)
1704              m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();
1705          if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)
1706              m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
1707          // To track down deferred or immediate changes.                  // To track down deferred or immediate changes.
1708          QString sOldServerHost      = m_pOptions->sServerHost;                  QString sOldServerHost      = m_pOptions->sServerHost;
1709          int     iOldServerPort      = m_pOptions->iServerPort;                  int     iOldServerPort      = m_pOptions->iServerPort;
1710          int     iOldServerTimeout   = m_pOptions->iServerTimeout;                  int     iOldServerTimeout   = m_pOptions->iServerTimeout;
1711          bool    bOldServerStart     = m_pOptions->bServerStart;                  bool    bOldServerStart     = m_pOptions->bServerStart;
1712          QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;                  QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;
1713          QString sOldDisplayFont     = m_pOptions->sDisplayFont;                  bool    bOldMessagesLog     = m_pOptions->bMessagesLog;
1714          bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;                  QString sOldMessagesLogPath = m_pOptions->sMessagesLogPath;
1715          int     iOldMaxVolume       = m_pOptions->iMaxVolume;                  QString sOldDisplayFont     = m_pOptions->sDisplayFont;
1716          QString sOldMessagesFont    = m_pOptions->sMessagesFont;                  bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;
1717          bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;                  int     iOldMaxVolume       = m_pOptions->iMaxVolume;
1718          bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;                  QString sOldMessagesFont    = m_pOptions->sMessagesFont;
1719          int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;                  bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;
1720          int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;                  bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;
1721          bool    bOldCompletePath    = m_pOptions->bCompletePath;                  int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;
1722          bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;                  int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;
1723          int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;                  bool    bOldCompletePath    = m_pOptions->bCompletePath;
1724          // Load the current setup settings.                  bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;
1725          pOptionsForm->setup(m_pOptions);                  int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;
1726          // Show the setup dialog...                  int     iOldBaseFontSize    = m_pOptions->iBaseFontSize;
1727          if (pOptionsForm->exec()) {                  // Load the current setup settings.
1728              // Warn if something will be only effective on next run.                  pOptionsForm->setup(m_pOptions);
1729              if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||                  // Show the setup dialog...
1730                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||                  if (pOptionsForm->exec()) {
1731                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||                          // Warn if something will be only effective on next run.
1732                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1733                  QMessageBox::information(this,                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||
1734                                    ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||
1735                                    (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)     ||
1736                                    (iOldBaseFontSize   !=  m_pOptions->iBaseFontSize)) {
1737                                    QMessageBox::information(this,
1738                                          QSAMPLER_TITLE ": " + tr("Information"),                                          QSAMPLER_TITLE ": " + tr("Information"),
1739                      tr("Some settings may be only effective\n"                                          tr("Some settings may be only effective\n"
1740                         "next time you start this program."), tr("OK"));                                          "next time you start this program."));
1741                  updateMessagesCapture();                                  updateMessagesCapture();
1742              }                          }
1743              // Check wheather something immediate has changed.                          // Check wheather something immediate has changed.
1744              if (( bOldCompletePath && !m_pOptions->bCompletePath) ||                          if (( bOldMessagesLog && !m_pOptions->bMessagesLog) ||
1745                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||                                  (!bOldMessagesLog &&  m_pOptions->bMessagesLog) ||
1746                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))                                  (sOldMessagesLogPath != m_pOptions->sMessagesLogPath))
1747                  updateRecentFilesMenu();                                  m_pMessages->setLogging(
1748              if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||                                          m_pOptions->bMessagesLog, m_pOptions->sMessagesLogPath);
1749                  (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||
1750                  updateInstrumentNames();                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||
1751              if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
1752                  (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))                                  updateRecentFilesMenu();
1753                  updateDisplayEffect();                          if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||
1754              if (sOldDisplayFont != m_pOptions->sDisplayFont)                                  (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))
1755                  updateDisplayFont();                                  updateInstrumentNames();
1756              if (iOldMaxVolume != m_pOptions->iMaxVolume)                          if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||
1757                  updateMaxVolume();                                  (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))
1758              if (sOldMessagesFont != m_pOptions->sMessagesFont)                                  updateDisplayEffect();
1759                  updateMessagesFont();                          if (sOldDisplayFont != m_pOptions->sDisplayFont)
1760              if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||                                  updateDisplayFont();
1761                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||                          if (iOldMaxVolume != m_pOptions->iMaxVolume)
1762                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))                                  updateMaxVolume();
1763                  updateMessagesLimit();                          if (sOldMessagesFont != m_pOptions->sMessagesFont)
1764              // And now the main thing, whether we'll do client/server recycling?                                  updateMessagesFont();
1765              if ((sOldServerHost != m_pOptions->sServerHost) ||                          if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||
1766                  (iOldServerPort != m_pOptions->iServerPort) ||                                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||
1767                  (iOldServerTimeout != m_pOptions->iServerTimeout) ||                                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))
1768                  ( bOldServerStart && !m_pOptions->bServerStart) ||                                  updateMessagesLimit();
1769                  (!bOldServerStart &&  m_pOptions->bServerStart) ||                          // And now the main thing, whether we'll do client/server recycling?
1770                  (sOldServerCmdLine != m_pOptions->sServerCmdLine && m_pOptions->bServerStart))                          if ((sOldServerHost != m_pOptions->sServerHost) ||
1771                  fileRestart();                                  (iOldServerPort != m_pOptions->iServerPort) ||
1772          }                                  (iOldServerTimeout != m_pOptions->iServerTimeout) ||
1773          // Done.                                  ( bOldServerStart && !m_pOptions->bServerStart) ||
1774          delete pOptionsForm;                                  (!bOldServerStart &&  m_pOptions->bServerStart) ||
1775      }                                  (sOldServerCmdLine != m_pOptions->sServerCmdLine
1776                                    && m_pOptions->bServerStart))
1777                                    fileRestart();
1778                    }
1779                    // Done.
1780                    delete pOptionsForm;
1781            }
1782    
1783      // This makes it.          // This makes it.
1784      stabilizeForm();          stabilizeForm();
1785  }  }
1786    
1787    
# Line 1598  void MainForm::viewOptions (void) Line 1791  void MainForm::viewOptions (void)
1791  // Arrange channel strips.  // Arrange channel strips.
1792  void MainForm::channelsArrange (void)  void MainForm::channelsArrange (void)
1793  {  {
1794      // Full width vertical tiling          // Full width vertical tiling
1795      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
1796      if (wlist.isEmpty())          if (wlist.isEmpty())
1797          return;                  return;
1798    
1799      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
1800      int y = 0;          int y = 0;
1801      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1802          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
1803      /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {          /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {
1804              // Prevent flicker...                          // Prevent flicker...
1805              pChannelStrip->hide();                          pChannelStrip->hide();
1806              pChannelStrip->showNormal();                          pChannelStrip->showNormal();
1807          }   */                  }   */
1808          pChannelStrip->adjustSize();                  pChannelStrip->adjustSize();
1809          int iWidth  = m_pWorkspace->width();                  int iWidth  = m_pWorkspace->width();
1810          if (iWidth < pChannelStrip->width())                  if (iWidth < pChannelStrip->width())
1811              iWidth = pChannelStrip->width();                          iWidth = pChannelStrip->width();
1812      //  int iHeight = pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();          //  int iHeight = pChannelStrip->height()
1813          int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();          //              + pChannelStrip->parentWidget()->baseSize().height();
1814          pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);                  int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();
1815          y += iHeight;                  pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);
1816      }                  y += iHeight;
1817      m_pWorkspace->setUpdatesEnabled(true);          }
1818            m_pWorkspace->setUpdatesEnabled(true);
1819    
1820      stabilizeForm();          stabilizeForm();
1821  }  }
1822    
1823    
1824  // Auto-arrange channel strips.  // Auto-arrange channel strips.
1825  void MainForm::channelsAutoArrange ( bool bOn )  void MainForm::channelsAutoArrange ( bool bOn )
1826  {  {
1827      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1828          return;                  return;
1829    
1830      // Toggle the auto-arrange flag.          // Toggle the auto-arrange flag.
1831      m_pOptions->bAutoArrange = bOn;          m_pOptions->bAutoArrange = bOn;
1832    
1833      // If on, update whole workspace...          // If on, update whole workspace...
1834      if (m_pOptions->bAutoArrange)          if (m_pOptions->bAutoArrange)
1835          channelsArrange();                  channelsArrange();
1836  }  }
1837    
1838    
# Line 1648  void MainForm::channelsAutoArrange ( boo Line 1842  void MainForm::channelsAutoArrange ( boo
1842  // Show information about the Qt toolkit.  // Show information about the Qt toolkit.
1843  void MainForm::helpAboutQt (void)  void MainForm::helpAboutQt (void)
1844  {  {
1845      QMessageBox::aboutQt(this);          QMessageBox::aboutQt(this);
1846  }  }
1847    
1848    
1849  // Show information about application program.  // Show information about application program.
1850  void MainForm::helpAbout (void)  void MainForm::helpAbout (void)
1851  {  {
1852      // Stuff the about box text...          // Stuff the about box text...
1853      QString sText = "<p>\n";          QString sText = "<p>\n";
1854      sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";          sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";
1855      sText += "<br />\n";          sText += "<br />\n";
1856      sText += tr("Version") + ": <b>" QSAMPLER_VERSION "</b><br />\n";          sText += tr("Version") + ": <b>" QSAMPLER_VERSION "</b><br />\n";
1857      sText += "<small>" + tr("Build") + ": " __DATE__ " " __TIME__ "</small><br />\n";          sText += "<small>" + tr("Build") + ": " __DATE__ " " __TIME__ "</small><br />\n";
1858  #ifdef CONFIG_DEBUG  #ifdef CONFIG_DEBUG
1859      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1860      sText += tr("Debugging option enabled.");          sText += tr("Debugging option enabled.");
1861      sText += "</font></small><br />";          sText += "</font></small><br />";
1862  #endif  #endif
1863  #ifndef CONFIG_LIBGIG  #ifndef CONFIG_LIBGIG
1864      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1865      sText += tr("GIG (libgig) file support disabled.");          sText += tr("GIG (libgig) file support disabled.");
1866      sText += "</font></small><br />";          sText += "</font></small><br />";
1867  #endif  #endif
1868  #ifndef CONFIG_INSTRUMENT_NAME  #ifndef CONFIG_INSTRUMENT_NAME
1869      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1870      sText += tr("LSCP (liblscp) instrument_name support disabled.");          sText += tr("LSCP (liblscp) instrument_name support disabled.");
1871      sText += "</font></small><br />";          sText += "</font></small><br />";
1872  #endif  #endif
1873  #ifndef CONFIG_MUTE_SOLO  #ifndef CONFIG_MUTE_SOLO
1874      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1875      sText += tr("Sampler channel Mute/Solo support disabled.");          sText += tr("Sampler channel Mute/Solo support disabled.");
1876      sText += "</font></small><br />";          sText += "</font></small><br />";
1877  #endif  #endif
1878  #ifndef CONFIG_AUDIO_ROUTING  #ifndef CONFIG_AUDIO_ROUTING
1879      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1880      sText += tr("LSCP (liblscp) audio_routing support disabled.");          sText += tr("LSCP (liblscp) audio_routing support disabled.");
1881      sText += "</font></small><br />";          sText += "</font></small><br />";
1882  #endif  #endif
1883  #ifndef CONFIG_FXSEND  #ifndef CONFIG_FXSEND
1884      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1885      sText += tr("Sampler channel Effect Sends support disabled.");          sText += tr("Sampler channel Effect Sends support disabled.");
1886      sText += "</font></small><br />";          sText += "</font></small><br />";
1887  #endif  #endif
1888  #ifndef CONFIG_VOLUME  #ifndef CONFIG_VOLUME
1889      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1890      sText += tr("Global volume support disabled.");          sText += tr("Global volume support disabled.");
1891      sText += "</font></small><br />";          sText += "</font></small><br />";
1892  #endif  #endif
1893  #ifndef CONFIG_MIDI_INSTRUMENT  #ifndef CONFIG_MIDI_INSTRUMENT
1894      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1895      sText += tr("MIDI instrument mapping support disabled.");          sText += tr("MIDI instrument mapping support disabled.");
1896      sText += "</font></small><br />";          sText += "</font></small><br />";
1897  #endif  #endif
1898  #ifndef CONFIG_EDIT_INSTRUMENT  #ifndef CONFIG_EDIT_INSTRUMENT
1899      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1900      sText += tr("Instrument editing support disabled.");          sText += tr("Instrument editing support disabled.");
1901      sText += "</font></small><br />";          sText += "</font></small><br />";
1902  #endif  #endif
1903      sText += "<br />\n";  #ifndef CONFIG_EVENT_CHANNEL_MIDI
1904      sText += tr("Using") + ": ";          sText += "<small><font color=\"red\">";
1905      sText += ::lscp_client_package();          sText += tr("Channel MIDI event support disabled.");
1906      sText += " ";          sText += "</font></small><br />";
1907      sText += ::lscp_client_version();  #endif
1908    #ifndef CONFIG_EVENT_DEVICE_MIDI
1909            sText += "<small><font color=\"red\">";
1910            sText += tr("Device MIDI event support disabled.");
1911            sText += "</font></small><br />";
1912    #endif
1913    #ifndef CONFIG_MAX_VOICES
1914            sText += "<small><font color=\"red\">";
1915            sText += tr("Runtime max. voices / disk streams support disabled.");
1916            sText += "</font></small><br />";
1917    #endif
1918            sText += "<br />\n";
1919            sText += tr("Using") + ": ";
1920            sText += ::lscp_client_package();
1921            sText += " ";
1922            sText += ::lscp_client_version();
1923  #ifdef CONFIG_LIBGIG  #ifdef CONFIG_LIBGIG
1924      sText += ", ";          sText += ", ";
1925      sText += gig::libraryName().c_str();          sText += gig::libraryName().c_str();
1926      sText += " ";          sText += " ";
1927      sText += gig::libraryVersion().c_str();          sText += gig::libraryVersion().c_str();
1928  #endif  #endif
1929      sText += "<br />\n";          sText += "<br />\n";
1930      sText += "<br />\n";          sText += "<br />\n";
1931      sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";          sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";
1932      sText += "<br />\n";          sText += "<br />\n";
1933      sText += "<small>";          sText += "<small>";
1934      sText += QSAMPLER_COPYRIGHT "<br />\n";          sText += QSAMPLER_COPYRIGHT "<br />\n";
1935      sText += QSAMPLER_COPYRIGHT2 "<br />\n";          sText += QSAMPLER_COPYRIGHT2 "<br />\n";
1936      sText += "<br />\n";          sText += "<br />\n";
1937      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";
1938      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.");
1939      sText += "</small>";          sText += "</small>";
1940      sText += "</p>\n";          sText += "</p>\n";
1941    
1942      QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);          QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);
1943  }  }
1944    
1945    
# Line 1739  void MainForm::helpAbout (void) Line 1948  void MainForm::helpAbout (void)
1948    
1949  void MainForm::stabilizeForm (void)  void MainForm::stabilizeForm (void)
1950  {  {
1951      // Update the main application caption...          // Update the main application caption...
1952      QString sSessionName = sessionName(m_sFilename);          QString sSessionName = sessionName(m_sFilename);
1953      if (m_iDirtyCount > 0)          if (m_iDirtyCount > 0)
1954          sSessionName += " *";                  sSessionName += " *";
1955      setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));
1956    
1957      // Update the main menu state...          // Update the main menu state...
1958      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1959      bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);          bool bHasClient = (m_pOptions != NULL && m_pClient != NULL);
1960      bool bHasChannel = (bHasClient && pChannelStrip != NULL);          bool bHasChannel = (bHasClient && pChannelStrip != NULL);
1961      ui.fileNewAction->setEnabled(bHasClient);          bool bHasChannels = (bHasClient && m_pWorkspace->windowList().count() > 0);
1962      ui.fileOpenAction->setEnabled(bHasClient);          m_ui.fileNewAction->setEnabled(bHasClient);
1963      ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);          m_ui.fileOpenAction->setEnabled(bHasClient);
1964      ui.fileSaveAsAction->setEnabled(bHasClient);          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
1965      ui.fileResetAction->setEnabled(bHasClient);          m_ui.fileSaveAsAction->setEnabled(bHasClient);
1966      ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);          m_ui.fileResetAction->setEnabled(bHasClient);
1967      ui.editAddChannelAction->setEnabled(bHasClient);          m_ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);
1968      ui.editRemoveChannelAction->setEnabled(bHasChannel);          m_ui.editAddChannelAction->setEnabled(bHasClient);
1969      ui.editSetupChannelAction->setEnabled(bHasChannel);          m_ui.editRemoveChannelAction->setEnabled(bHasChannel);
1970            m_ui.editSetupChannelAction->setEnabled(bHasChannel);
1971  #ifdef CONFIG_EDIT_INSTRUMENT  #ifdef CONFIG_EDIT_INSTRUMENT
1972      ui.editEditChannelAction->setEnabled(bHasChannel);          m_ui.editEditChannelAction->setEnabled(bHasChannel);
1973  #else  #else
1974      ui.editEditChannelAction->setEnabled(false);          m_ui.editEditChannelAction->setEnabled(false);
1975  #endif  #endif
1976      ui.editResetChannelAction->setEnabled(bHasChannel);          m_ui.editResetChannelAction->setEnabled(bHasChannel);
1977      ui.editResetAllChannelsAction->setEnabled(bHasChannel);          m_ui.editResetAllChannelsAction->setEnabled(bHasChannels);
1978      ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());
1979  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
1980          ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm
1981                  && m_pInstrumentListForm->isVisible());                  && m_pInstrumentListForm->isVisible());
1982          ui.viewInstrumentsAction->setEnabled(bHasClient);          m_ui.viewInstrumentsAction->setEnabled(bHasClient);
1983  #else  #else
1984          ui.viewInstrumentsAction->setEnabled(false);          m_ui.viewInstrumentsAction->setEnabled(false);
1985  #endif  #endif
1986          ui.viewDevicesAction->setChecked(m_pDeviceForm          m_ui.viewDevicesAction->setChecked(m_pDeviceForm
1987                  && m_pDeviceForm->isVisible());                  && m_pDeviceForm->isVisible());
1988      ui.viewDevicesAction->setEnabled(bHasClient);          m_ui.viewDevicesAction->setEnabled(bHasClient);
1989      ui.channelsArrangeAction->setEnabled(bHasChannel);          m_ui.viewMidiDeviceStatusMenu->setEnabled(
1990                    DeviceStatusForm::getInstances().size() > 0);
1991            m_ui.channelsArrangeAction->setEnabled(bHasChannels);
1992    
1993  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
1994          // Toolbar widgets are also affected...          // Toolbar widgets are also affected...
1995      m_pVolumeSlider->setEnabled(bHasClient);          m_pVolumeSlider->setEnabled(bHasClient);
1996      m_pVolumeSpinBox->setEnabled(bHasClient);          m_pVolumeSpinBox->setEnabled(bHasClient);
1997  #endif  #endif
1998    
1999      // Client/Server status...          // Client/Server status...
2000      if (bHasClient) {          if (bHasClient) {
2001          m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));                  m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));
2002          m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost + ":" + QString::number(m_pOptions->iServerPort));                  m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost
2003      } else {                          + ':' + QString::number(m_pOptions->iServerPort));
2004          m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();          } else {
2005          m_statusItem[QSAMPLER_STATUS_SERVER]->clear();                  m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();
2006      }                  m_statusItem[QSAMPLER_STATUS_SERVER]->clear();
2007      // Channel status...          }
2008      if (bHasChannel)          // Channel status...
2009          m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->windowTitle());          if (bHasChannel)
2010      else                  m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->windowTitle());
2011          m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();          else
2012      // Session status...                  m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();
2013      if (m_iDirtyCount > 0)          // Session status...
2014          m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));          if (m_iDirtyCount > 0)
2015      else                  m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));
2016          m_statusItem[QSAMPLER_STATUS_SESSION]->clear();          else
2017                    m_statusItem[QSAMPLER_STATUS_SESSION]->clear();
2018    
2019      // Recent files menu.          // Recent files menu.
2020          ui.fileOpenRecentMenu->setEnabled(m_pOptions->recentFiles.count() > 0);          m_ui.fileOpenRecentMenu->setEnabled(m_pOptions->recentFiles.count() > 0);
2021  }  }
2022    
2023    
# Line 1849  void MainForm::channelStripChanged(Chann Line 2062  void MainForm::channelStripChanged(Chann
2062                  pChannelStrip->resetErrorCount();                  pChannelStrip->resetErrorCount();
2063          }          }
2064    
2065      // Just mark the dirty form.          // Just mark the dirty form.
2066      m_iDirtyCount++;          m_iDirtyCount++;
2067      // and update the form status...          // and update the form status...
2068      stabilizeForm();          stabilizeForm();
2069  }  }
2070    
2071    
# Line 1879  void MainForm::updateSession (void) Line 2092  void MainForm::updateSession (void)
2092          }          }
2093  #endif  #endif
2094    
2095            updateAllChannelStrips(false);
2096    
2097            // Do we auto-arrange?
2098            if (m_pOptions && m_pOptions->bAutoArrange)
2099                    channelsArrange();
2100    
2101            // Remember to refresh devices and instruments...
2102            if (m_pInstrumentListForm)
2103                    m_pInstrumentListForm->refreshInstruments();
2104            if (m_pDeviceForm)
2105                    m_pDeviceForm->refreshDevices();
2106    }
2107    
2108    void MainForm::updateAllChannelStrips(bool bRemoveDeadStrips) {
2109          // Retrieve the current channel list.          // Retrieve the current channel list.
2110          int *piChannelIDs = ::lscp_list_channels(m_pClient);          int *piChannelIDs = ::lscp_list_channels(m_pClient);
2111          if (piChannelIDs == NULL) {          if (piChannelIDs == NULL) {
2112                  if (::lscp_client_get_errno(m_pClient)) {                  if (::lscp_client_get_errno(m_pClient)) {
2113                          appendMessagesClient("lscp_list_channels");                          appendMessagesClient("lscp_list_channels");
2114                          appendMessagesError(tr("Could not get current list of channels.\n\nSorry."));                          appendMessagesError(
2115                                    tr("Could not get current list of channels.\n\nSorry."));
2116                  }                  }
2117          } else {          } else {
2118                  // Try to (re)create each channel.                  // Try to (re)create each channel.
# Line 1892  void MainForm::updateSession (void) Line 2120  void MainForm::updateSession (void)
2120                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {
2121                          // Check if theres already a channel strip for this one...                          // Check if theres already a channel strip for this one...
2122                          if (!channelStrip(piChannelIDs[iChannel]))                          if (!channelStrip(piChannelIDs[iChannel]))
2123                                  createChannelStrip(new qsamplerChannel(piChannelIDs[iChannel]));                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));
2124                    }
2125    
2126                    // Do we auto-arrange?
2127                    if (m_pOptions && m_pOptions->bAutoArrange)
2128                            channelsArrange();
2129    
2130                    stabilizeForm();
2131    
2132                    // remove dead channel strips
2133                    if (bRemoveDeadStrips) {
2134                            for (int i = 0; channelStripAt(i); ++i) {
2135                                    ChannelStrip* pChannelStrip = channelStripAt(i);
2136                                    bool bExists = false;
2137                                    for (int j = 0; piChannelIDs[j] >= 0; ++j) {
2138                                            if (!pChannelStrip->channel()) break;
2139                                            if (piChannelIDs[j] == pChannelStrip->channel()->channelID()) {
2140                                                    // strip exists, don't touch it
2141                                                    bExists = true;
2142                                                    break;
2143                                            }
2144                                    }
2145                                    if (!bExists) destroyChannelStrip(pChannelStrip);
2146                            }
2147                  }                  }
2148                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
2149          }          }
   
     // Do we auto-arrange?  
     if (m_pOptions && m_pOptions->bAutoArrange)  
         channelsArrange();  
   
         // Remember to refresh devices and instruments...  
         if (m_pInstrumentListForm)  
             m_pInstrumentListForm->refreshInstruments();  
         if (m_pDeviceForm)  
             m_pDeviceForm->refreshDevices();  
2150  }  }
2151    
   
2152  // Update the recent files list and menu.  // Update the recent files list and menu.
2153  void MainForm::updateRecentFiles ( const QString& sFilename )  void MainForm::updateRecentFiles ( const QString& sFilename )
2154  {  {
2155      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2156          return;                  return;
2157    
2158      // Remove from list if already there (avoid duplicates)          // Remove from list if already there (avoid duplicates)
2159      int iIndex = m_pOptions->recentFiles.indexOf(sFilename);          int iIndex = m_pOptions->recentFiles.indexOf(sFilename);
2160      if (iIndex >= 0)          if (iIndex >= 0)
2161          m_pOptions->recentFiles.removeAt(iIndex);                  m_pOptions->recentFiles.removeAt(iIndex);
2162      // Put it to front...          // Put it to front...
2163      m_pOptions->recentFiles.push_front(sFilename);          m_pOptions->recentFiles.push_front(sFilename);
2164  }  }
2165    
2166    
# Line 1938  void MainForm::updateRecentFilesMenu (vo Line 2178  void MainForm::updateRecentFilesMenu (vo
2178          }          }
2179    
2180          // Rebuild the recent files menu...          // Rebuild the recent files menu...
2181          ui.fileOpenRecentMenu->clear();          m_ui.fileOpenRecentMenu->clear();
2182          for (int i = 0; i < iRecentFiles; i++) {          for (int i = 0; i < iRecentFiles; i++) {
2183                  const QString& sFilename = m_pOptions->recentFiles[i];                  const QString& sFilename = m_pOptions->recentFiles[i];
2184                  if (QFileInfo(sFilename).exists()) {                  if (QFileInfo(sFilename).exists()) {
2185                          QAction *pAction = ui.fileOpenRecentMenu->addAction(                          QAction *pAction = m_ui.fileOpenRecentMenu->addAction(
2186                                  QString("&%1 %2").arg(i + 1).arg(sessionName(sFilename)),                                  QString("&%1 %2").arg(i + 1).arg(sessionName(sFilename)),
2187                                  this, SLOT(fileOpenRecent()));                                  this, SLOT(fileOpenRecent()));
2188                          pAction->setData(i);                          pAction->setData(i);
# Line 1954  void MainForm::updateRecentFilesMenu (vo Line 2194  void MainForm::updateRecentFilesMenu (vo
2194  // Force update of the channels instrument names mode.  // Force update of the channels instrument names mode.
2195  void MainForm::updateInstrumentNames (void)  void MainForm::updateInstrumentNames (void)
2196  {  {
2197      // Full channel list update...          // Full channel list update...
2198      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2199      if (wlist.isEmpty())          if (wlist.isEmpty())
2200          return;                  return;
2201    
2202      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2203      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2204          ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);                  ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);
2205          if (pChannelStrip)                  if (pChannelStrip)
2206              pChannelStrip->updateInstrumentName(true);                          pChannelStrip->updateInstrumentName(true);
2207      }          }
2208      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2209  }  }
2210    
2211    
2212  // Force update of the channels display font.  // Force update of the channels display font.
2213  void MainForm::updateDisplayFont (void)  void MainForm::updateDisplayFont (void)
2214  {  {
2215      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2216          return;                  return;
2217    
2218            // Check if display font is legal.
2219            if (m_pOptions->sDisplayFont.isEmpty())
2220                    return;
2221            // Realize it.
2222            QFont font;
2223            if (!font.fromString(m_pOptions->sDisplayFont))
2224                    return;
2225    
2226      // Check if display font is legal.          // Full channel list update...
2227      if (m_pOptions->sDisplayFont.isEmpty())          QWidgetList wlist = m_pWorkspace->windowList();
2228          return;          if (wlist.isEmpty())
2229      // Realize it.                  return;
2230      QFont font;  
2231      if (!font.fromString(m_pOptions->sDisplayFont))          m_pWorkspace->setUpdatesEnabled(false);
2232          return;          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2233                    ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2234      // Full channel list update...                  if (pChannelStrip)
2235      QWidgetList wlist = m_pWorkspace->windowList();                          pChannelStrip->setDisplayFont(font);
2236      if (wlist.isEmpty())          }
2237          return;          m_pWorkspace->setUpdatesEnabled(true);
   
     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);  
2238  }  }
2239    
2240    
2241  // Update channel strips background effect.  // Update channel strips background effect.
2242  void MainForm::updateDisplayEffect (void)  void MainForm::updateDisplayEffect (void)
2243  {  {
2244      // Full channel list update...          // Full channel list update...
2245      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2246      if (wlist.isEmpty())          if (wlist.isEmpty())
2247          return;                  return;
2248    
2249      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2250      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2251          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2252                  if (pChannelStrip)                  if (pChannelStrip)
2253                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2254      }          }
2255      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2256  }  }
2257    
2258    
2259  // Force update of the channels maximum volume setting.  // Force update of the channels maximum volume setting.
2260  void MainForm::updateMaxVolume (void)  void MainForm::updateMaxVolume (void)
2261  {  {
2262      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2263          return;                  return;
2264    
2265  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2266          m_iVolumeChanging++;          m_iVolumeChanging++;
# Line 2029  void MainForm::updateMaxVolume (void) Line 2269  void MainForm::updateMaxVolume (void)
2269          m_iVolumeChanging--;          m_iVolumeChanging--;
2270  #endif  #endif
2271    
2272      // Full channel list update...          // Full channel list update...
2273      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2274      if (wlist.isEmpty())          if (wlist.isEmpty())
2275          return;                  return;
2276    
2277      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2278      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2279          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2280          if (pChannelStrip)                  if (pChannelStrip)
2281              pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                          pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2282      }          }
2283      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2284  }  }
2285    
2286    
# Line 2050  void MainForm::updateMaxVolume (void) Line 2290  void MainForm::updateMaxVolume (void)
2290  // Messages output methods.  // Messages output methods.
2291  void MainForm::appendMessages( const QString& s )  void MainForm::appendMessages( const QString& s )
2292  {  {
2293      if (m_pMessages)          if (m_pMessages)
2294          m_pMessages->appendMessages(s);                  m_pMessages->appendMessages(s);
2295    
2296      statusBar()->showMessage(s, 3000);          statusBar()->showMessage(s, 3000);
2297  }  }
2298    
2299  void MainForm::appendMessagesColor( const QString& s, const QString& c )  void MainForm::appendMessagesColor( const QString& s, const QString& c )
2300  {  {
2301      if (m_pMessages)          if (m_pMessages)
2302          m_pMessages->appendMessagesColor(s, c);                  m_pMessages->appendMessagesColor(s, c);
2303    
2304      statusBar()->showMessage(s, 3000);          statusBar()->showMessage(s, 3000);
2305  }  }
2306    
2307  void MainForm::appendMessagesText( const QString& s )  void MainForm::appendMessagesText( const QString& s )
2308  {  {
2309      if (m_pMessages)          if (m_pMessages)
2310          m_pMessages->appendMessagesText(s);                  m_pMessages->appendMessagesText(s);
2311  }  }
2312    
2313  void MainForm::appendMessagesError( const QString& s )  void MainForm::appendMessagesError( const QString& s )
2314  {  {
2315      if (m_pMessages)          if (m_pMessages)
2316          m_pMessages->show();                  m_pMessages->show();
2317    
2318      appendMessagesColor(s.simplified(), "#ff0000");          appendMessagesColor(s.simplified(), "#ff0000");
2319    
2320          // Make it look responsive...:)          // Make it look responsive...:)
2321          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2322    
2323      QMessageBox::critical(this,          QMessageBox::critical(this,
2324                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));                  QSAMPLER_TITLE ": " + tr("Error"), s, QMessageBox::Cancel);
2325  }  }
2326    
2327    
2328  // This is a special message format, just for client results.  // This is a special message format, just for client results.
2329  void MainForm::appendMessagesClient( const QString& s )  void MainForm::appendMessagesClient( const QString& s )
2330  {  {
2331      if (m_pClient == NULL)          if (m_pClient == NULL)
2332          return;                  return;
2333    
2334      appendMessagesColor(s + QString(": %1 (errno=%2)")          appendMessagesColor(s + QString(": %1 (errno=%2)")
2335          .arg(::lscp_client_get_result(m_pClient))                  .arg(::lscp_client_get_result(m_pClient))
2336          .arg(::lscp_client_get_errno(m_pClient)), "#996666");                  .arg(::lscp_client_get_errno(m_pClient)), "#996666");
2337    
2338          // Make it look responsive...:)          // Make it look responsive...:)
2339          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
# Line 2103  void MainForm::appendMessagesClient( con Line 2343  void MainForm::appendMessagesClient( con
2343  // Force update of the messages font.  // Force update of the messages font.
2344  void MainForm::updateMessagesFont (void)  void MainForm::updateMessagesFont (void)
2345  {  {
2346      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2347          return;                  return;
2348    
2349      if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {          if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {
2350          QFont font;                  QFont font;
2351          if (font.fromString(m_pOptions->sMessagesFont))                  if (font.fromString(m_pOptions->sMessagesFont))
2352              m_pMessages->setMessagesFont(font);                          m_pMessages->setMessagesFont(font);
2353      }          }
2354  }  }
2355    
2356    
2357  // Update messages window line limit.  // Update messages window line limit.
2358  void MainForm::updateMessagesLimit (void)  void MainForm::updateMessagesLimit (void)
2359  {  {
2360      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2361          return;                  return;
2362    
2363      if (m_pMessages) {          if (m_pMessages) {
2364          if (m_pOptions->bMessagesLimit)                  if (m_pOptions->bMessagesLimit)
2365              m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);                          m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);
2366          else                  else
2367              m_pMessages->setMessagesLimit(-1);                          m_pMessages->setMessagesLimit(-1);
2368      }          }
2369  }  }
2370    
2371    
2372  // Enablement of the messages capture feature.  // Enablement of the messages capture feature.
2373  void MainForm::updateMessagesCapture (void)  void MainForm::updateMessagesCapture (void)
2374  {  {
2375      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2376          return;                  return;
2377    
2378      if (m_pMessages)          if (m_pMessages)
2379          m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);                  m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);
2380  }  }
2381    
2382    
# Line 2144  void MainForm::updateMessagesCapture (vo Line 2384  void MainForm::updateMessagesCapture (vo
2384  // qsamplerMainForm -- MDI channel strip management.  // qsamplerMainForm -- MDI channel strip management.
2385    
2386  // The channel strip creation executive.  // The channel strip creation executive.
2387  ChannelStrip* MainForm::createChannelStrip(qsamplerChannel* pChannel)  ChannelStrip* MainForm::createChannelStrip ( Channel *pChannel )
2388  {  {
2389      if (m_pClient == NULL || pChannel == NULL)          if (m_pClient == NULL || pChannel == NULL)
2390          return NULL;                  return NULL;
2391    
2392      // Prepare for auto-arrange?          // Add a new channel itema...
2393      ChannelStrip* pChannelStrip = NULL;          ChannelStrip *pChannelStrip = new ChannelStrip();
2394      int y = 0;          if (pChannelStrip == NULL)
2395      if (m_pOptions && m_pOptions->bAutoArrange) {                  return NULL;
2396          QWidgetList wlist = m_pWorkspace->windowList();  
2397          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          // Set some initial channel strip options...
2398                          pChannelStrip = static_cast<ChannelStrip *> (wlist.at(iChannel));          if (m_pOptions) {
2399                          if (pChannelStrip) {                  // Background display effect...
2400                          //  y += pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2401                                  y += pChannelStrip->parentWidget()->frameGeometry().height();                  // We'll need a display font.
2402                          }                  QFont font;
2403          }                  if (font.fromString(m_pOptions->sDisplayFont))
2404      }                          pChannelStrip->setDisplayFont(font);
2405                    // Maximum allowed volume setting.
2406                    pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2407            }
2408    
2409      // Add a new channel itema...          // Add it to workspace...
2410      pChannelStrip = new ChannelStrip();          m_pWorkspace->addWindow(pChannelStrip, Qt::FramelessWindowHint);
     if (pChannelStrip == NULL)  
         return NULL;  
2411    
2412      m_pWorkspace->addWindow(pChannelStrip, Qt::Tool);          // Actual channel strip setup...
2413            pChannelStrip->setup(pChannel);
2414    
     // Actual channel strip setup...  
     pChannelStrip->setup(pChannel);  
2415          QObject::connect(pChannelStrip,          QObject::connect(pChannelStrip,
2416                  SIGNAL(channelChanged(ChannelStrip*)),                  SIGNAL(channelChanged(ChannelStrip*)),
2417                  SLOT(channelStripChanged(ChannelStrip*)));                  SLOT(channelStripChanged(ChannelStrip*)));
2418      // Set some initial aesthetic options...  
2419      if (m_pOptions) {          // Now we show up us to the world.
2420          // 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);  
     }  
2421    
2422          // This is pretty new, so we'll watch for it closely.          // This is pretty new, so we'll watch for it closely.
2423          channelStripChanged(pChannelStrip);          channelStripChanged(pChannelStrip);
2424    
2425      // Return our successful reference...          // Return our successful reference...
2426      return pChannelStrip;          return pChannelStrip;
2427  }  }
2428    
2429    void MainForm::destroyChannelStrip(ChannelStrip* pChannelStrip) {
2430            // Just delete the channel strip.
2431            delete pChannelStrip;
2432    
2433            // Do we auto-arrange?
2434            if (m_pOptions && m_pOptions->bAutoArrange)
2435                    channelsArrange();
2436    
2437            stabilizeForm();
2438    }
2439    
2440  // Retrieve the active channel strip.  // Retrieve the active channel strip.
2441  ChannelStrip* MainForm::activeChannelStrip (void)  ChannelStrip* MainForm::activeChannelStrip (void)
2442  {  {
2443      return static_cast<ChannelStrip *> (m_pWorkspace->activeWindow());          return static_cast<ChannelStrip *> (m_pWorkspace->activeWindow());
2444  }  }
2445    
2446    
2447  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
2448  ChannelStrip* MainForm::channelStripAt ( int iChannel )  ChannelStrip* MainForm::channelStripAt ( int iChannel )
2449  {  {
2450      QWidgetList wlist = m_pWorkspace->windowList();          if (!m_pWorkspace) return NULL;
2451      if (wlist.isEmpty())  
2452          return NULL;          QWidgetList wlist = m_pWorkspace->windowList();
2453            if (wlist.isEmpty())
2454                    return NULL;
2455    
2456            if (iChannel < 0 || iChannel >= wlist.size())
2457                    return NULL;
2458    
2459      return static_cast<ChannelStrip *> (wlist.at(iChannel));          return dynamic_cast<ChannelStrip *> (wlist.at(iChannel));
2460  }  }
2461    
2462    
# Line 2233  ChannelStrip* MainForm::channelStrip ( i Line 2471  ChannelStrip* MainForm::channelStrip ( i
2471                  ChannelStrip* pChannelStrip                  ChannelStrip* pChannelStrip
2472                          = static_cast<ChannelStrip*> (wlist.at(iChannel));                          = static_cast<ChannelStrip*> (wlist.at(iChannel));
2473                  if (pChannelStrip) {                  if (pChannelStrip) {
2474                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
2475                          if (pChannel && pChannel->channelID() == iChannelID)                          if (pChannel && pChannel->channelID() == iChannelID)
2476                                  return pChannelStrip;                                  return pChannelStrip;
2477                  }                  }
# Line 2247  ChannelStrip* MainForm::channelStrip ( i Line 2485  ChannelStrip* MainForm::channelStrip ( i
2485  // Construct the windows menu.  // Construct the windows menu.
2486  void MainForm::channelsMenuAboutToShow (void)  void MainForm::channelsMenuAboutToShow (void)
2487  {  {
2488      ui.channelsMenu->clear();          m_ui.channelsMenu->clear();
2489          ui.channelsMenu->addAction(ui.channelsArrangeAction);          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);
2490          ui.channelsMenu->addAction(ui.channelsAutoArrangeAction);          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);
2491    
2492      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2493      if (!wlist.isEmpty()) {          if (!wlist.isEmpty()) {
2494                  ui.channelsMenu->addSeparator();                  m_ui.channelsMenu->addSeparator();
2495          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2496                          ChannelStrip* pChannelStrip                          ChannelStrip* pChannelStrip
2497                                  = static_cast<ChannelStrip*> (wlist.at(iChannel));                                  = static_cast<ChannelStrip*> (wlist.at(iChannel));
2498                          if (pChannelStrip) {                          if (pChannelStrip) {
2499                                  QAction *pAction = ui.channelsMenu->addAction(                                  QAction *pAction = m_ui.channelsMenu->addAction(
2500                                          pChannelStrip->windowTitle(), this, SLOT(channelsMenuActivated()));                                          pChannelStrip->windowTitle(),
2501                                  pAction->setData(iChannel);                                          this, SLOT(channelsMenuActivated()));
2502                                    pAction->setCheckable(true);
2503                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);
2504                                    pAction->setData(iChannel);
2505                          }                          }
2506          }                  }
2507      }          }
2508  }  }
2509    
2510    
# Line 2290  void MainForm::channelsMenuActivated (vo Line 2530  void MainForm::channelsMenuActivated (vo
2530  // Set the pseudo-timer delay schedule.  // Set the pseudo-timer delay schedule.
2531  void MainForm::startSchedule ( int iStartDelay )  void MainForm::startSchedule ( int iStartDelay )
2532  {  {
2533      m_iStartDelay  = 1 + (iStartDelay * 1000);          m_iStartDelay  = 1 + (iStartDelay * 1000);
2534      m_iTimerDelay  = 0;          m_iTimerDelay  = 0;
2535  }  }
2536    
2537  // Suspend the pseudo-timer delay schedule.  // Suspend the pseudo-timer delay schedule.
2538  void MainForm::stopSchedule (void)  void MainForm::stopSchedule (void)
2539  {  {
2540      m_iStartDelay  = 0;          m_iStartDelay  = 0;
2541      m_iTimerDelay  = 0;          m_iTimerDelay  = 0;
2542  }  }
2543    
2544  // Timer slot funtion.  // Timer slot funtion.
2545  void MainForm::timerSlot (void)  void MainForm::timerSlot (void)
2546  {  {
2547      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2548          return;                  return;
2549    
2550      // Is it the first shot on server start after a few delay?          // Is it the first shot on server start after a few delay?
2551      if (m_iTimerDelay < m_iStartDelay) {          if (m_iTimerDelay < m_iStartDelay) {
2552          m_iTimerDelay += QSAMPLER_TIMER_MSECS;                  m_iTimerDelay += QSAMPLER_TIMER_MSECS;
2553          if (m_iTimerDelay >= m_iStartDelay) {                  if (m_iTimerDelay >= m_iStartDelay) {
2554              // If we cannot start it now, maybe a lil'mo'later ;)                          // If we cannot start it now, maybe a lil'mo'later ;)
2555              if (!startClient()) {                          if (!startClient()) {
2556                  m_iStartDelay += m_iTimerDelay;                                  m_iStartDelay += m_iTimerDelay;
2557                  m_iTimerDelay  = 0;                                  m_iTimerDelay  = 0;
2558              }                          }
2559          }                  }
2560      }          }
2561    
2562          if (m_pClient) {          if (m_pClient) {
2563                  // Update the channel information for each pending strip...                  // Update the channel information for each pending strip...
# Line 2349  void MainForm::timerSlot (void) Line 2589  void MainForm::timerSlot (void)
2589                  }                  }
2590          }          }
2591    
2592      // Register the next timer slot.          // Register the next timer slot.
2593      QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));          QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
2594  }  }
2595    
2596    
# Line 2360  void MainForm::timerSlot (void) Line 2600  void MainForm::timerSlot (void)
2600  // Start linuxsampler server...  // Start linuxsampler server...
2601  void MainForm::startServer (void)  void MainForm::startServer (void)
2602  {  {
2603      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2604          return;                  return;
2605    
2606            // Aren't already a client, are we?
2607            if (!m_pOptions->bServerStart || m_pClient)
2608                    return;
2609    
2610      // Aren't already a client, are we?          // Is the server process instance still here?
2611      if (!m_pOptions->bServerStart || m_pClient)          if (m_pServer) {
2612          return;                  if (QMessageBox::warning(this,
   
     // Is the server process instance still here?  
     if (m_pServer) {  
         switch (QMessageBox::warning(this,  
2613                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
2614              tr("Could not start the LinuxSampler server.\n\n"                          tr("Could not start the LinuxSampler server.\n\n"
2615                 "Maybe it ss already started."),                          "Maybe it is already started."),
2616              tr("Stop"), tr("Kill"), tr("Cancel"))) {                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
2617            case 0:                          m_pServer->terminate();
2618              m_pServer->terminate();                          m_pServer->kill();
2619              break;                  }
2620            case 1:                  return;
2621              m_pServer->kill();          }
2622              break;  
2623          }          // Reset our timer counters...
2624          return;          stopSchedule();
2625      }  
2626            // Verify we have something to start with...
2627      // Reset our timer counters...          if (m_pOptions->sServerCmdLine.isEmpty())
2628      stopSchedule();                  return;
2629    
2630      // OK. Let's build the startup process...          // OK. Let's build the startup process...
2631      m_pServer = new QProcess(this);          m_pServer = new QProcess();
2632            bForceServerStop = true;
2633      // Setup stdout/stderr capture...  
2634          //      if (m_pOptions->bStdoutCapture) {          // Setup stdout/stderr capture...
2635                  //m_pServer->setProcessChannelMode(  //      if (m_pOptions->bStdoutCapture) {
2636                  //      QProcess::StandardOutput);  #if QT_VERSION >= 0x040200
2637                    m_pServer->setProcessChannelMode(QProcess::ForwardedChannels);
2638    #endif
2639                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2640                          SIGNAL(readyReadStandardOutput()),                          SIGNAL(readyReadStandardOutput()),
2641                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
2642                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2643                          SIGNAL(readyReadStandardError()),                          SIGNAL(readyReadStandardError()),
2644                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
2645          //      }  //      }
2646    
2647          // The unforgiveable signal communication...          // The unforgiveable signal communication...
2648          QObject::connect(m_pServer,          QObject::connect(m_pServer,
2649                  SIGNAL(finished(int,QProcess::ExitStatus)),                  SIGNAL(finished(int, QProcess::ExitStatus)),
2650                  SLOT(processServerExit()));                  SLOT(processServerExit()));
2651    
2652      // Build process arguments...          // Build process arguments...
2653      QStringList serverCmdLine = m_pOptions->sServerCmdLine.split(' ');          QStringList args = m_pOptions->sServerCmdLine.split(' ');
2654            QString sCommand = args[0];
2655      appendMessages(tr("Server is starting..."));          args.removeAt(0);
2656      appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");  
2657            appendMessages(tr("Server is starting..."));
2658            appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");
2659    
2660      const QString prog = (serverCmdLine.size() > 0) ? serverCmdLine[0] : QString();          // Go linuxsampler, go...
2661      const QStringList args = serverCmdLine.mid(1);          m_pServer->start(sCommand, args);
2662            if (!m_pServer->waitForStarted()) {
2663      // Go jack, go...                  appendMessagesError(tr("Could not start server.\n\nSorry."));
2664      m_pServer->start(prog, args);                  processServerExit();
2665      if (!m_pServer->waitForStarted()) {                  return;
2666          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()));  
2667    
2668      // Reset (yet again) the timer counters,          // Show startup results...
2669      // but this time is deferred as the user opted.          appendMessages(
2670      startSchedule(m_pOptions->iStartDelay);                  tr("Server was started with PID=%1.").arg((long) m_pServer->pid()));
2671      stabilizeForm();  
2672            // Reset (yet again) the timer counters,
2673            // but this time is deferred as the user opted.
2674            startSchedule(m_pOptions->iStartDelay);
2675            stabilizeForm();
2676  }  }
2677    
2678    
2679  // Stop linuxsampler server...  // Stop linuxsampler server...
2680  void MainForm::stopServer (void)  void MainForm::stopServer (bool bInteractive)
2681  {  {
2682      // Stop client code.          // Stop client code.
2683      stopClient();          stopClient();
2684    
2685      // And try to stop server.          if (m_pServer && bInteractive) {
2686      if (m_pServer) {                  if (QMessageBox::question(this,
2687          appendMessages(tr("Server is stopping..."));                          QSAMPLER_TITLE ": " + tr("The backend's fate ..."),
2688          if (m_pServer->state() == QProcess::Running)                          tr("You have the option to keep the sampler backend (LinuxSampler)\n"
2689              m_pServer->terminate();                          "running in the background. The sampler would continue to work\n"
2690       }                          "according to your current sampler session and you could alter the\n"
2691                            "sampler session at any time by relaunching QSampler.\n\n"
2692      // Give it some time to terminate gracefully and stabilize...                          "Do you want LinuxSampler to stop?"),
2693      QTime t;                          QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
2694      t.start();                  {
2695      while (t.elapsed() < QSAMPLER_TIMER_MSECS)                          bForceServerStop = false;
2696          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  }
2697            }
2698    
2699       // Do final processing anyway.          // And try to stop server.
2700       processServerExit();          if (m_pServer && bForceServerStop) {
2701                    appendMessages(tr("Server is stopping..."));
2702                    if (m_pServer->state() == QProcess::Running) {
2703    #if defined(WIN32)
2704                            // Try harder...
2705                            m_pServer->kill();
2706    #else
2707                            // Try softly...
2708                            m_pServer->terminate();
2709    #endif
2710                    }
2711            }       // Do final processing anyway.
2712            else processServerExit();
2713    
2714            // Give it some time to terminate gracefully and stabilize...
2715            QTime t;
2716            t.start();
2717            while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2718                    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2719  }  }
2720    
2721    
2722  // Stdout handler...  // Stdout handler...
2723  void MainForm::readServerStdout (void)  void MainForm::readServerStdout (void)
2724  {  {
2725      if (m_pMessages)          if (m_pMessages)
2726          m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());                  m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());
2727  }  }
2728    
2729    
2730  // Linuxsampler server cleanup.  // Linuxsampler server cleanup.
2731  void MainForm::processServerExit (void)  void MainForm::processServerExit (void)
2732  {  {
2733      // Force client code cleanup.          // Force client code cleanup.
2734      stopClient();          stopClient();
2735    
2736      // Flush anything that maybe pending...          // Flush anything that maybe pending...
2737      if (m_pMessages)          if (m_pMessages)
2738          m_pMessages->flushStdoutBuffer();                  m_pMessages->flushStdoutBuffer();
2739    
2740      if (m_pServer) {          if (m_pServer && bForceServerStop) {
2741          // Force final server shutdown...                  if (m_pServer->state() != QProcess::NotRunning) {
2742          appendMessages(tr("Server was stopped with exit status %1.").arg(m_pServer->exitStatus()));                          appendMessages(tr("Server is being forced..."));
2743          m_pServer->terminate();                          // Force final server shutdown...
2744          if (!m_pServer->waitForFinished(2000))                          m_pServer->kill();
2745              m_pServer->kill();                          // Give it some time to terminate gracefully and stabilize...
2746          // Destroy it.                          QTime t;
2747          delete m_pServer;                          t.start();
2748          m_pServer = NULL;                          while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2749      }                                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2750                    }
2751                    // Force final server shutdown...
2752                    appendMessages(
2753                            tr("Server was stopped with exit status %1.")
2754                            .arg(m_pServer->exitStatus()));
2755                    delete m_pServer;
2756                    m_pServer = NULL;
2757            }
2758    
2759      // Again, make status visible stable.          // Again, make status visible stable.
2760      stabilizeForm();          stabilizeForm();
2761  }  }
2762    
2763    
# Line 2497  void MainForm::processServerExit (void) Line 2765  void MainForm::processServerExit (void)
2765  // qsamplerMainForm -- Client stuff.  // qsamplerMainForm -- Client stuff.
2766    
2767  // The LSCP client callback procedure.  // The LSCP client callback procedure.
2768  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*/,
2769            lscp_event_t event, const char *pchData, int cchData, void *pvData )
2770  {  {
2771      MainForm* pMainForm = (MainForm *) pvData;          MainForm* pMainForm = (MainForm *) pvData;
2772      if (pMainForm == NULL)          if (pMainForm == NULL)
2773          return LSCP_FAILED;                  return LSCP_FAILED;
2774    
2775      // ATTN: DO NOT EVER call any GUI code here,          // ATTN: DO NOT EVER call any GUI code here,
2776      // as this is run under some other thread context.          // as this is run under some other thread context.
2777      // A custom event must be posted here...          // A custom event must be posted here...
2778      QApplication::postEvent(pMainForm, new qsamplerCustomEvent(event, pchData, cchData));          QApplication::postEvent(pMainForm,
2779                    new LscpEvent(event, pchData, cchData));
2780    
2781      return LSCP_OK;          return LSCP_OK;
2782  }  }
2783    
2784    
2785  // Start our almighty client...  // Start our almighty client...
2786  bool MainForm::startClient (void)  bool MainForm::startClient (void)
2787  {  {
2788      // Have it a setup?          // Have it a setup?
2789      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2790          return false;                  return false;
2791    
2792      // Aren't we already started, are we?          // Aren't we already started, are we?
2793      if (m_pClient)          if (m_pClient)
2794          return true;                  return true;
2795    
2796      // Log prepare here.          // Log prepare here.
2797      appendMessages(tr("Client connecting..."));          appendMessages(tr("Client connecting..."));
2798    
2799      // Create the client handle...          // Create the client handle...
2800          m_pClient = ::lscp_client_create(          m_pClient = ::lscp_client_create(
2801                  m_pOptions->sServerHost.toUtf8().constData(),                  m_pOptions->sServerHost.toUtf8().constData(),
2802                  m_pOptions->iServerPort, qsampler_client_callback, this);                  m_pOptions->iServerPort, qsampler_client_callback, this);
2803      if (m_pClient == NULL) {          if (m_pClient == NULL) {
2804          // Is this the first try?                  // Is this the first try?
2805          // maybe we need to start a local server...                  // maybe we need to start a local server...
2806          if ((m_pServer && m_pServer->state() == QProcess::Running) || !m_pOptions->bServerStart)                  if ((m_pServer && m_pServer->state() == QProcess::Running)
2807              appendMessagesError(tr("Could not connect to server as client.\n\nSorry."));                          || !m_pOptions->bServerStart) {
2808          else                          appendMessagesError(
2809              startServer();                                  tr("Could not connect to server as client.\n\nSorry."));
2810          // This is always a failure.                  } else {
2811          stabilizeForm();                          startServer();
2812          return false;                  }
2813      }                  // This is always a failure.
2814      // Just set receive timeout value, blindly.                  stabilizeForm();
2815      ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);                  return false;
2816      appendMessages(tr("Client receive timeout is set to %1 msec.").arg(::lscp_client_get_timeout(m_pClient)));          }
2817            // Just set receive timeout value, blindly.
2818            ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);
2819            appendMessages(
2820                    tr("Client receive timeout is set to %1 msec.")
2821                    .arg(::lscp_client_get_timeout(m_pClient)));
2822    
2823          // Subscribe to channel info change notifications...          // Subscribe to channel info change notifications...
2824            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT) != LSCP_OK)
2825                    appendMessagesClient("lscp_client_subscribe(CHANNEL_COUNT)");
2826          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)
2827                  appendMessagesClient("lscp_client_subscribe");                  appendMessagesClient("lscp_client_subscribe(CHANNEL_INFO)");
2828    
2829            DeviceStatusForm::onDevicesChanged(); // initialize
2830            updateViewMidiDeviceStatusMenu();
2831            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT) != LSCP_OK)
2832                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_COUNT)");
2833            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO) != LSCP_OK)
2834                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_INFO)");
2835            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT) != LSCP_OK)
2836                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_COUNT)");
2837            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO) != LSCP_OK)
2838                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_INFO)");
2839    
2840    #if CONFIG_EVENT_CHANNEL_MIDI
2841            // Subscribe to channel MIDI data notifications...
2842            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI) != LSCP_OK)
2843                    appendMessagesClient("lscp_client_subscribe(CHANNEL_MIDI)");
2844    #endif
2845    
2846    #if CONFIG_EVENT_DEVICE_MIDI
2847            // Subscribe to channel MIDI data notifications...
2848            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI) != LSCP_OK)
2849                    appendMessagesClient("lscp_client_subscribe(DEVICE_MIDI)");
2850    #endif
2851    
2852      // We may stop scheduling around.          // We may stop scheduling around.
2853      stopSchedule();          stopSchedule();
2854    
2855      // We'll accept drops from now on...          // We'll accept drops from now on...
2856      setAcceptDrops(true);          setAcceptDrops(true);
2857    
2858      // Log success here.          // Log success here.
2859      appendMessages(tr("Client connected."));          appendMessages(tr("Client connected."));
2860    
2861          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
2862          // if visible, that we're ready...          // if visible, that we're ready...
2863          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
2864              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
2865          if (m_pDeviceForm)          if (m_pDeviceForm)
2866              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
2867    
2868            // Is any session pending to be loaded?
2869            if (!m_pOptions->sSessionFile.isEmpty()) {
2870                    // Just load the prabably startup session...
2871                    if (loadSessionFile(m_pOptions->sSessionFile)) {
2872                            m_pOptions->sSessionFile = QString::null;
2873                            return true;
2874                    }
2875            }
2876    
2877      // Is any session pending to be loaded?          // send the current / loaded fine tuning settings to the sampler
2878      if (!m_pOptions->sSessionFile.isEmpty()) {          m_pOptions->sendFineTuningSettings();
         // Just load the prabably startup session...  
         if (loadSessionFile(m_pOptions->sSessionFile)) {  
             m_pOptions->sSessionFile = QString::null;  
             return true;  
         }  
     }  
2879    
2880      // Make a new session          // Make a new session
2881      return newSession();          return newSession();
2882  }  }
2883    
2884    
2885  // Stop client...  // Stop client...
2886  void MainForm::stopClient (void)  void MainForm::stopClient (void)
2887  {  {
2888      if (m_pClient == NULL)          if (m_pClient == NULL)
2889          return;                  return;
   
     // Log prepare here.  
     appendMessages(tr("Client disconnecting..."));  
2890    
2891      // Clear timer counters...          // Log prepare here.
2892      stopSchedule();          appendMessages(tr("Client disconnecting..."));
2893    
2894      // We'll reject drops from now on...          // Clear timer counters...
2895      setAcceptDrops(false);          stopSchedule();
2896    
2897      // Force any channel strips around, but          // We'll reject drops from now on...
2898      // but avoid removing the corresponding          setAcceptDrops(false);
     // channels from the back-end server.  
     m_iDirtyCount = 0;  
     closeSession(false);  
2899    
2900      // Close us as a client...          // Force any channel strips around, but
2901            // but avoid removing the corresponding
2902            // channels from the back-end server.
2903            m_iDirtyCount = 0;
2904            closeSession(false);
2905    
2906            // Close us as a client...
2907    #if CONFIG_EVENT_DEVICE_MIDI
2908            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI);
2909    #endif
2910    #if CONFIG_EVENT_CHANNEL_MIDI
2911            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI);
2912    #endif
2913            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
2914            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
2915            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
2916            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
2917          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
2918      ::lscp_client_destroy(m_pClient);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT);
2919      m_pClient = NULL;          ::lscp_client_destroy(m_pClient);
2920            m_pClient = NULL;
2921    
2922          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
2923          // if visible, that we're running out...          // if visible, that we're running out...
2924          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
2925              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
2926          if (m_pDeviceForm)          if (m_pDeviceForm)
2927              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
2928    
2929      // Log final here.          // Log final here.
2930      appendMessages(tr("Client disconnected."));          appendMessages(tr("Client disconnected."));
2931    
2932      // Make visible status.          // Make visible status.
2933      stabilizeForm();          stabilizeForm();
2934  }  }
2935    
2936    
2937    // Channel strip activation/selection.
2938    void MainForm::activateStrip ( QWidget *pWidget )
2939    {
2940            ChannelStrip *pChannelStrip
2941                    = static_cast<ChannelStrip *> (pWidget);
2942            if (pChannelStrip)
2943                    pChannelStrip->setSelected(true);
2944    
2945            stabilizeForm();
2946    }
2947    
2948    
2949  } // namespace QSampler  } // namespace QSampler
2950    
2951    

Legend:
Removed from v.1499  
changed lines
  Added in v.2112

  ViewVC Help
Powered by ViewVC