/[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 1507 by capela, Wed Nov 21 23:22:18 2007 UTC revision 2722 by capela, Tue Mar 3 17:41:04 2015 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-2015, rncbc aka Rui Nuno Capela. All rights reserved.
5     Copyright (C) 2007, Christian Schoenebeck     Copyright (C) 2007,2008,2015 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 <QMdiArea>
39    #include <QMdiSubWindow>
40    
41  #include <QApplication>  #include <QApplication>
 #include <QWorkspace>  
42  #include <QProcess>  #include <QProcess>
43  #include <QMessageBox>  #include <QMessageBox>
44    
# Line 55  Line 58 
58  #include <QTimer>  #include <QTimer>
59  #include <QDateTime>  #include <QDateTime>
60    
61    #if QT_VERSION >= 0x050000
62    #include <QMimeData>
63    #endif
64    
65    #if QT_VERSION < 0x040500
66    namespace Qt {
67    const WindowFlags WindowCloseButtonHint = WindowFlags(0x08000000);
68    }
69    #endif
70    
71  #ifdef HAVE_SIGNAL_H  #ifdef HAVE_SIGNAL_H
72  #include <signal.h>  #include <signal.h>
# Line 77  static inline long lroundf ( float x ) Line 89  static inline long lroundf ( float x )
89  }  }
90  #endif  #endif
91    
92    
93    // All winsock apps needs this.
94    #if defined(WIN32)
95    static WSADATA _wsaData;
96    #endif
97    
98    
99    //-------------------------------------------------------------------------
100    // LADISH Level 1 support stuff.
101    
102    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
103    
104    #include <QSocketNotifier>
105    
106    #include <sys/types.h>
107    #include <sys/socket.h>
108    
109    #include <signal.h>
110    
111    // File descriptor for SIGUSR1 notifier.
112    static int g_fdUsr1[2];
113    
114    // Unix SIGUSR1 signal handler.
115    static void qsampler_sigusr1_handler ( int /* signo */ )
116    {
117            char c = 1;
118    
119            (::write(g_fdUsr1[0], &c, sizeof(c)) > 0);
120    }
121    
122    #endif  // HAVE_SIGNAL_H
123    
124    
125    //-------------------------------------------------------------------------
126    // qsampler -- namespace
127    
128    
129    namespace QSampler {
130    
131  // Timer constant stuff.  // Timer constant stuff.
132  #define QSAMPLER_TIMER_MSECS    200  #define QSAMPLER_TIMER_MSECS    200
133    
# Line 87  static inline long lroundf ( float x ) Line 138  static inline long lroundf ( float x )
138  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.
139    
140    
141  // All winsock apps needs this.  // Specialties for thread-callback comunication.
142  #if defined(WIN32)  #define QSAMPLER_LSCP_EVENT   QEvent::Type(QEvent::User + 1)
 static WSADATA _wsaData;  
 #endif  
143    
144    
145  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
146  // qsamplerCustomEvent -- specialty for callback comunication.  // LscpEvent -- specialty for LSCP callback comunication.
147    
 #define QSAMPLER_CUSTOM_EVENT   QEvent::Type(QEvent::User + 0)  
148    
149  class qsamplerCustomEvent : public QEvent  class LscpEvent : public QEvent
150  {  {
151  public:  public:
152    
153      // Constructor.          // Constructor.
154      qsamplerCustomEvent(lscp_event_t event, const char *pchData, int cchData)          LscpEvent(lscp_event_t event, const char *pchData, int cchData)
155          : QEvent(QSAMPLER_CUSTOM_EVENT)                  : QEvent(QSAMPLER_LSCP_EVENT)
156      {          {
157          m_event = event;                  m_event = event;
158          m_data  = QString::fromUtf8(pchData, cchData);                  m_data  = QString::fromUtf8(pchData, cchData);
159      }          }
160    
161      // Accessors.          // Accessors.
162      lscp_event_t event() { return m_event; }          lscp_event_t event() { return m_event; }
163      QString&     data()  { return m_data;  }          QString&     data()  { return m_data;  }
164    
165  private:  private:
166    
167      // The proper event type.          // The proper event type.
168      lscp_event_t m_event;          lscp_event_t m_event;
169      // The event data as a string.          // The event data as a string.
170      QString      m_data;          QString      m_data;
171  };  };
172    
173    
174  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
175  // qsamplerMainForm -- Main window form implementation.  // qsamplerMainForm -- Main window form implementation.
176    
 namespace QSampler {  
   
177  // Kind of singleton reference.  // Kind of singleton reference.
178  MainForm* MainForm::g_pMainForm = NULL;  MainForm* MainForm::g_pMainForm = NULL;
179    
180  MainForm::MainForm(QWidget* parent) : QMainWindow(parent) {  MainForm::MainForm ( QWidget *pParent )
181      ui.setupUi(this);          : QMainWindow(pParent)
182    {
183            m_ui.setupUi(this);
184    
185          // Pseudo-singleton reference setup.          // Pseudo-singleton reference setup.
186          g_pMainForm = this;          g_pMainForm = this;
187    
188      // Initialize some pointer references.          // Initialize some pointer references.
189      m_pOptions = NULL;          m_pOptions = NULL;
190    
191      // All child forms are to be created later, not earlier than setup.          // All child forms are to be created later, not earlier than setup.
192      m_pMessages = NULL;          m_pMessages = NULL;
193      m_pInstrumentListForm = NULL;          m_pInstrumentListForm = NULL;
194      m_pDeviceForm = NULL;          m_pDeviceForm = NULL;
195    
196      // We'll start clean.          // We'll start clean.
197      m_iUntitled   = 0;          m_iUntitled   = 0;
198      m_iDirtyCount = 0;          m_iDirtyCount = 0;
199    
200      m_pServer = NULL;          m_pServer = NULL;
201      m_pClient = NULL;          m_pClient = NULL;
202    
203      m_iStartDelay = 0;          m_iStartDelay = 0;
204      m_iTimerDelay = 0;          m_iTimerDelay = 0;
205    
206      m_iTimerSlot = 0;          m_iTimerSlot = 0;
207    
208    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
209    
 #ifdef HAVE_SIGNAL_H  
210          // Set to ignore any fatal "Broken pipe" signals.          // Set to ignore any fatal "Broken pipe" signals.
211          ::signal(SIGPIPE, SIG_IGN);          ::signal(SIGPIPE, SIG_IGN);
212  #endif  
213            // LADISH Level 1 suport.
214    
215            // Initialize file descriptors for SIGUSR1 socket notifier.
216            ::socketpair(AF_UNIX, SOCK_STREAM, 0, g_fdUsr1);
217            m_pUsr1Notifier
218                    = new QSocketNotifier(g_fdUsr1[1], QSocketNotifier::Read, this);
219    
220            QObject::connect(m_pUsr1Notifier,
221                    SIGNAL(activated(int)),
222                    SLOT(handle_sigusr1()));
223    
224            // Install SIGUSR1 signal handler.
225        struct sigaction usr1;
226        usr1.sa_handler = qsampler_sigusr1_handler;
227        sigemptyset(&usr1.sa_mask);
228        usr1.sa_flags = 0;
229        usr1.sa_flags |= SA_RESTART;
230        ::sigaction(SIGUSR1, &usr1, NULL);
231    
232    #else   // HAVE_SIGNAL_H
233    
234            m_pUsr1Notifier = NULL;
235            
236    #endif  // !HAVE_SIGNAL_H
237    
238  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
239      // Make some extras into the toolbar...          // Make some extras into the toolbar...
240          const QString& sVolumeText = tr("Master volume");          const QString& sVolumeText = tr("Master volume");
241          m_iVolumeChanging = 0;          m_iVolumeChanging = 0;
242          // Volume slider...          // Volume slider...
243          ui.channelsToolbar->addSeparator();          m_ui.channelsToolbar->addSeparator();
244          m_pVolumeSlider = new QSlider(Qt::Horizontal, ui.channelsToolbar);          m_pVolumeSlider = new QSlider(Qt::Horizontal, m_ui.channelsToolbar);
245          m_pVolumeSlider->setTickPosition(QSlider::TicksBelow);          m_pVolumeSlider->setTickPosition(QSlider::TicksBothSides);
246          m_pVolumeSlider->setTickInterval(10);          m_pVolumeSlider->setTickInterval(10);
247          m_pVolumeSlider->setPageStep(10);          m_pVolumeSlider->setPageStep(10);
248          m_pVolumeSlider->setSingleStep(10);          m_pVolumeSlider->setSingleStep(10);
# Line 181  MainForm::MainForm(QWidget* parent) : QM Line 254  MainForm::MainForm(QWidget* parent) : QM
254          QObject::connect(m_pVolumeSlider,          QObject::connect(m_pVolumeSlider,
255                  SIGNAL(valueChanged(int)),                  SIGNAL(valueChanged(int)),
256                  SLOT(volumeChanged(int)));                  SLOT(volumeChanged(int)));
257          //ui.channelsToolbar->setHorizontallyStretchable(true);          m_ui.channelsToolbar->addWidget(m_pVolumeSlider);
         //ui.channelsToolbar->setStretchableWidget(m_pVolumeSlider);  
     ui.channelsToolbar->addWidget(m_pVolumeSlider);  
258          // Volume spin-box          // Volume spin-box
259          ui.channelsToolbar->addSeparator();          m_ui.channelsToolbar->addSeparator();
260          m_pVolumeSpinBox = new QSpinBox(ui.channelsToolbar);          m_pVolumeSpinBox = new QSpinBox(m_ui.channelsToolbar);
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 QMdiArea(this);
273      m_pWorkspace->setScrollBarsEnabled(true);          m_pWorkspace->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
274            m_pWorkspace->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
275          // Set the activation connection.          // Set the activation connection.
276          QObject::connect(m_pWorkspace,          QObject::connect(m_pWorkspace,
277                  SIGNAL(windowActivated(QWidget *)),                  SIGNAL(subWindowActivated(QMdiSubWindow *)),
278                  SLOT(stabilizeForm()));                  SLOT(activateStrip(QMdiSubWindow *)));
279      // Make it shine :-)          // Make it shine :-)
280      setCentralWidget(m_pWorkspace);          setCentralWidget(m_pWorkspace);
281    
282      // Create some statusbar labels...          // Create some statusbar labels...
283      QLabel *pLabel;          QLabel *pLabel;
284      // Client status.          // Client status.
285      pLabel = new QLabel(tr("Connected"), this);          pLabel = new QLabel(tr("Connected"), this);
286      pLabel->setAlignment(Qt::AlignLeft);          pLabel->setAlignment(Qt::AlignLeft);
287      pLabel->setMinimumSize(pLabel->sizeHint());          pLabel->setMinimumSize(pLabel->sizeHint());
288      m_statusItem[QSAMPLER_STATUS_CLIENT] = pLabel;          m_statusItem[QSAMPLER_STATUS_CLIENT] = pLabel;
289      statusBar()->addWidget(pLabel);          statusBar()->addWidget(pLabel);
290      // Server address.          // Server address.
291      pLabel = new QLabel(this);          pLabel = new QLabel(this);
292      pLabel->setAlignment(Qt::AlignLeft);          pLabel->setAlignment(Qt::AlignLeft);
293      m_statusItem[QSAMPLER_STATUS_SERVER] = pLabel;          m_statusItem[QSAMPLER_STATUS_SERVER] = pLabel;
294      statusBar()->addWidget(pLabel, 1);          statusBar()->addWidget(pLabel, 1);
295      // Channel title.          // Channel title.
296      pLabel = new QLabel(this);          pLabel = new QLabel(this);
297      pLabel->setAlignment(Qt::AlignLeft);          pLabel->setAlignment(Qt::AlignLeft);
298      m_statusItem[QSAMPLER_STATUS_CHANNEL] = pLabel;          m_statusItem[QSAMPLER_STATUS_CHANNEL] = pLabel;
299      statusBar()->addWidget(pLabel, 2);          statusBar()->addWidget(pLabel, 2);
300      // Session modification status.          // Session modification status.
301      pLabel = new QLabel(tr("MOD"), this);          pLabel = new QLabel(tr("MOD"), this);
302      pLabel->setAlignment(Qt::AlignHCenter);          pLabel->setAlignment(Qt::AlignHCenter);
303      pLabel->setMinimumSize(pLabel->sizeHint());          pLabel->setMinimumSize(pLabel->sizeHint());
304      m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;          m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;
305      statusBar()->addWidget(pLabel);          statusBar()->addWidget(pLabel);
306    
307  #if defined(WIN32)  #if defined(WIN32)
308      WSAStartup(MAKEWORD(1, 1), &_wsaData);          WSAStartup(MAKEWORD(1, 1), &_wsaData);
309  #endif  #endif
310    
311          QObject::connect(ui.fileNewAction,          // Some actions surely need those
312            // shortcuts firmly attached...
313            addAction(m_ui.viewMenubarAction);
314            addAction(m_ui.viewToolbarAction);
315    
316            QObject::connect(m_ui.fileNewAction,
317                  SIGNAL(triggered()),                  SIGNAL(triggered()),
318                  SLOT(fileNew()));                  SLOT(fileNew()));
319          QObject::connect(ui.fileOpenAction,          QObject::connect(m_ui.fileOpenAction,
320                  SIGNAL(triggered()),                  SIGNAL(triggered()),
321                  SLOT(fileOpen()));                  SLOT(fileOpen()));
322          QObject::connect(ui.fileSaveAction,          QObject::connect(m_ui.fileSaveAction,
323                  SIGNAL(triggered()),                  SIGNAL(triggered()),
324                  SLOT(fileSave()));                  SLOT(fileSave()));
325          QObject::connect(ui.fileSaveAsAction,          QObject::connect(m_ui.fileSaveAsAction,
326                  SIGNAL(triggered()),                  SIGNAL(triggered()),
327                  SLOT(fileSaveAs()));                  SLOT(fileSaveAs()));
328          QObject::connect(ui.fileResetAction,          QObject::connect(m_ui.fileResetAction,
329                  SIGNAL(triggered()),                  SIGNAL(triggered()),
330                  SLOT(fileReset()));                  SLOT(fileReset()));
331          QObject::connect(ui.fileRestartAction,          QObject::connect(m_ui.fileRestartAction,
332                  SIGNAL(triggered()),                  SIGNAL(triggered()),
333                  SLOT(fileRestart()));                  SLOT(fileRestart()));
334          QObject::connect(ui.fileExitAction,          QObject::connect(m_ui.fileExitAction,
335                  SIGNAL(triggered()),                  SIGNAL(triggered()),
336                  SLOT(fileExit()));                  SLOT(fileExit()));
337          QObject::connect(ui.editAddChannelAction,          QObject::connect(m_ui.editAddChannelAction,
338                  SIGNAL(triggered()),                  SIGNAL(triggered()),
339                  SLOT(editAddChannel()));                  SLOT(editAddChannel()));
340          QObject::connect(ui.editRemoveChannelAction,          QObject::connect(m_ui.editRemoveChannelAction,
341                  SIGNAL(triggered()),                  SIGNAL(triggered()),
342                  SLOT(editRemoveChannel()));                  SLOT(editRemoveChannel()));
343          QObject::connect(ui.editSetupChannelAction,          QObject::connect(m_ui.editSetupChannelAction,
344                  SIGNAL(triggered()),                  SIGNAL(triggered()),
345                  SLOT(editSetupChannel()));                  SLOT(editSetupChannel()));
346          QObject::connect(ui.editEditChannelAction,          QObject::connect(m_ui.editEditChannelAction,
347                  SIGNAL(triggered()),                  SIGNAL(triggered()),
348                  SLOT(editEditChannel()));                  SLOT(editEditChannel()));
349          QObject::connect(ui.editResetChannelAction,          QObject::connect(m_ui.editResetChannelAction,
350                  SIGNAL(triggered()),                  SIGNAL(triggered()),
351                  SLOT(editResetChannel()));                  SLOT(editResetChannel()));
352          QObject::connect(ui.editResetAllChannelsAction,          QObject::connect(m_ui.editResetAllChannelsAction,
353                  SIGNAL(triggered()),                  SIGNAL(triggered()),
354                  SLOT(editResetAllChannels()));                  SLOT(editResetAllChannels()));
355          QObject::connect(ui.viewMenubarAction,          QObject::connect(m_ui.viewMenubarAction,
356                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
357                  SLOT(viewMenubar(bool)));                  SLOT(viewMenubar(bool)));
358          QObject::connect(ui.viewToolbarAction,          QObject::connect(m_ui.viewToolbarAction,
359                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
360                  SLOT(viewToolbar(bool)));                  SLOT(viewToolbar(bool)));
361          QObject::connect(ui.viewStatusbarAction,          QObject::connect(m_ui.viewStatusbarAction,
362                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
363                  SLOT(viewStatusbar(bool)));                  SLOT(viewStatusbar(bool)));
364          QObject::connect(ui.viewMessagesAction,          QObject::connect(m_ui.viewMessagesAction,
365                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
366                  SLOT(viewMessages(bool)));                  SLOT(viewMessages(bool)));
367          QObject::connect(ui.viewInstrumentsAction,          QObject::connect(m_ui.viewInstrumentsAction,
368                  SIGNAL(triggered()),                  SIGNAL(triggered()),
369                  SLOT(viewInstruments()));                  SLOT(viewInstruments()));
370          QObject::connect(ui.viewDevicesAction,          QObject::connect(m_ui.viewDevicesAction,
371                  SIGNAL(triggered()),                  SIGNAL(triggered()),
372                  SLOT(viewDevices()));                  SLOT(viewDevices()));
373          QObject::connect(ui.viewOptionsAction,          QObject::connect(m_ui.viewOptionsAction,
374                  SIGNAL(triggered()),                  SIGNAL(triggered()),
375                  SLOT(viewOptions()));                  SLOT(viewOptions()));
376          QObject::connect(ui.channelsArrangeAction,          QObject::connect(m_ui.channelsArrangeAction,
377                  SIGNAL(triggered()),                  SIGNAL(triggered()),
378                  SLOT(channelsArrange()));                  SLOT(channelsArrange()));
379          QObject::connect(ui.channelsAutoArrangeAction,          QObject::connect(m_ui.channelsAutoArrangeAction,
380                  SIGNAL(toggled(bool)),                  SIGNAL(toggled(bool)),
381                  SLOT(channelsAutoArrange(bool)));                  SLOT(channelsAutoArrange(bool)));
382          QObject::connect(ui.helpAboutAction,          QObject::connect(m_ui.helpAboutAction,
383                  SIGNAL(triggered()),                  SIGNAL(triggered()),
384                  SLOT(helpAbout()));                  SLOT(helpAbout()));
385          QObject::connect(ui.helpAboutQtAction,          QObject::connect(m_ui.helpAboutQtAction,
386                  SIGNAL(triggered()),                  SIGNAL(triggered()),
387                  SLOT(helpAboutQt()));                  SLOT(helpAboutQt()));
388    
389          QObject::connect(ui.fileMenu,          QObject::connect(m_ui.fileMenu,
390                  SIGNAL(aboutToShow()),                  SIGNAL(aboutToShow()),
391                  SLOT(updateRecentFilesMenu()));                  SLOT(updateRecentFilesMenu()));
392          QObject::connect(ui.channelsMenu,          QObject::connect(m_ui.channelsMenu,
393                  SIGNAL(aboutToShow()),                  SIGNAL(aboutToShow()),
394                  SLOT(channelsMenuAboutToShow()));                  SLOT(channelsMenuAboutToShow()));
395    #ifdef CONFIG_VOLUME
396            QObject::connect(m_ui.channelsToolbar,
397                    SIGNAL(orientationChanged(Qt::Orientation)),
398                    SLOT(channelsToolbarOrientation(Qt::Orientation)));
399    #endif
400  }  }
401    
402  // Destructor.  // Destructor.
403  MainForm::~MainForm()  MainForm::~MainForm()
404  {  {
405      // Do final processing anyway.          // Do final processing anyway.
406      processServerExit();          processServerExit();
407    
408  #if defined(WIN32)  #if defined(WIN32)
409      WSACleanup();          WSACleanup();
410  #endif  #endif
411    
412      // Finally drop any widgets around...  #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
413      if (m_pDeviceForm)          if (m_pUsr1Notifier)
414          delete m_pDeviceForm;                  delete m_pUsr1Notifier;
415      if (m_pInstrumentListForm)  #endif
416          delete m_pInstrumentListForm;  
417      if (m_pMessages)          // Finally drop any widgets around...
418          delete m_pMessages;          if (m_pDeviceForm)
419      if (m_pWorkspace)                  delete m_pDeviceForm;
420          delete m_pWorkspace;          if (m_pInstrumentListForm)
421                    delete m_pInstrumentListForm;
422      // Delete status item labels one by one.          if (m_pMessages)
423      if (m_statusItem[QSAMPLER_STATUS_CLIENT])                  delete m_pMessages;
424          delete m_statusItem[QSAMPLER_STATUS_CLIENT];          if (m_pWorkspace)
425      if (m_statusItem[QSAMPLER_STATUS_SERVER])                  delete m_pWorkspace;
426          delete m_statusItem[QSAMPLER_STATUS_SERVER];  
427      if (m_statusItem[QSAMPLER_STATUS_CHANNEL])          // Delete status item labels one by one.
428          delete m_statusItem[QSAMPLER_STATUS_CHANNEL];          if (m_statusItem[QSAMPLER_STATUS_CLIENT])
429      if (m_statusItem[QSAMPLER_STATUS_SESSION])                  delete m_statusItem[QSAMPLER_STATUS_CLIENT];
430          delete m_statusItem[QSAMPLER_STATUS_SESSION];          if (m_statusItem[QSAMPLER_STATUS_SERVER])
431                    delete m_statusItem[QSAMPLER_STATUS_SERVER];
432            if (m_statusItem[QSAMPLER_STATUS_CHANNEL])
433                    delete m_statusItem[QSAMPLER_STATUS_CHANNEL];
434            if (m_statusItem[QSAMPLER_STATUS_SESSION])
435                    delete m_statusItem[QSAMPLER_STATUS_SESSION];
436    
437  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
438          delete m_pVolumeSpinBox;          delete m_pVolumeSpinBox;
# Line 358  MainForm::~MainForm() Line 445  MainForm::~MainForm()
445    
446    
447  // Make and set a proper setup options step.  // Make and set a proper setup options step.
448  void MainForm::setup ( qsamplerOptions *pOptions )  void MainForm::setup ( Options *pOptions )
449  {  {
450      // We got options?          // We got options?
451      m_pOptions = pOptions;          m_pOptions = pOptions;
452    
453      // What style do we create these forms?          // What style do we create these forms?
454          Qt::WindowFlags wflags = Qt::Window          Qt::WindowFlags wflags = Qt::Window
 #if QT_VERSION >= 0x040200  
455                  | Qt::CustomizeWindowHint                  | Qt::CustomizeWindowHint
 #endif  
456                  | Qt::WindowTitleHint                  | Qt::WindowTitleHint
457                  | Qt::WindowSystemMenuHint                  | Qt::WindowSystemMenuHint
458                  | Qt::WindowMinMaxButtonsHint;                  | Qt::WindowMinMaxButtonsHint
459                    | Qt::WindowCloseButtonHint;
460          if (m_pOptions->bKeepOnTop)          if (m_pOptions->bKeepOnTop)
461                  wflags |= Qt::Tool;                  wflags |= Qt::Tool;
462      // Some child forms are to be created right now.  
463      m_pMessages = new qsamplerMessages(this);          // Some child forms are to be created right now.
464      m_pDeviceForm = new DeviceForm(this, wflags);          m_pMessages = new Messages(this);
465            m_pDeviceForm = new DeviceForm(this, wflags);
466  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
467      m_pInstrumentListForm = new InstrumentListForm(this, wflags);          m_pInstrumentListForm = new InstrumentListForm(this, wflags);
         QObject::connect(&m_pInstrumentListForm->model,  
                 SIGNAL(instrumentsChanged()),  
                 SLOT(sessionDirty()));  
468  #else  #else
469          viewInstrumentsAction->setEnabled(false);          m_ui.viewInstrumentsAction->setEnabled(false);
470  #endif  #endif
471      // Set message defaults...  
472      updateMessagesFont();          // Setup messages logging appropriately...
473      updateMessagesLimit();          m_pMessages->setLogging(
474      updateMessagesCapture();                  m_pOptions->bMessagesLog,
475      // Set the visibility signal.                  m_pOptions->sMessagesLogPath);
476    
477            // Set message defaults...
478            updateMessagesFont();
479            updateMessagesLimit();
480            updateMessagesCapture();
481            // Set the visibility signal.
482          QObject::connect(m_pMessages,          QObject::connect(m_pMessages,
483                  SIGNAL(visibilityChanged(bool)),                  SIGNAL(visibilityChanged(bool)),
484                  SLOT(stabilizeForm()));                  SLOT(stabilizeForm()));
485    
486      // Initial decorations toggle state.          // Initial decorations toggle state.
487      ui.viewMenubarAction->setChecked(m_pOptions->bMenubar);          m_ui.viewMenubarAction->setChecked(m_pOptions->bMenubar);
488      ui.viewToolbarAction->setChecked(m_pOptions->bToolbar);          m_ui.viewToolbarAction->setChecked(m_pOptions->bToolbar);
489      ui.viewStatusbarAction->setChecked(m_pOptions->bStatusbar);          m_ui.viewStatusbarAction->setChecked(m_pOptions->bStatusbar);
490      ui.channelsAutoArrangeAction->setChecked(m_pOptions->bAutoArrange);          m_ui.channelsAutoArrangeAction->setChecked(m_pOptions->bAutoArrange);
491    
492      // Initial decorations visibility state.          // Initial decorations visibility state.
493      viewMenubar(m_pOptions->bMenubar);          viewMenubar(m_pOptions->bMenubar);
494      viewToolbar(m_pOptions->bToolbar);          viewToolbar(m_pOptions->bToolbar);
495      viewStatusbar(m_pOptions->bStatusbar);          viewStatusbar(m_pOptions->bStatusbar);
496    
497      addDockWidget(Qt::BottomDockWidgetArea, m_pMessages);          addDockWidget(Qt::BottomDockWidgetArea, m_pMessages);
498    
499          // Restore whole dock windows state.          // Restore whole dock windows state.
500          QByteArray aDockables = m_pOptions->settings().value(          QByteArray aDockables = m_pOptions->settings().value(
# Line 413  void MainForm::setup ( qsamplerOptions * Line 503  void MainForm::setup ( qsamplerOptions *
503                  restoreState(aDockables);                  restoreState(aDockables);
504          }          }
505    
506      // Try to restore old window positioning and initial visibility.          // Try to restore old window positioning and initial visibility.
507      m_pOptions->loadWidgetGeometry(this);          m_pOptions->loadWidgetGeometry(this, true);
508      m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);          m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);
509      m_pOptions->loadWidgetGeometry(m_pDeviceForm);          m_pOptions->loadWidgetGeometry(m_pDeviceForm);
510    
511      // Final startup stabilization...          // Final startup stabilization...
512      updateMaxVolume();          updateMaxVolume();
513      updateRecentFilesMenu();          updateRecentFilesMenu();
514      stabilizeForm();          stabilizeForm();
515    
516      // Make it ready :-)          // Make it ready :-)
517      statusBar()->showMessage(tr("Ready"), 3000);          statusBar()->showMessage(tr("Ready"), 3000);
518    
519      // We'll try to start immediately...          // We'll try to start immediately...
520      startSchedule(0);          startSchedule(0);
521    
522      // Register the first timer slot.          // Register the first timer slot.
523      QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));          QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
524  }  }
525    
526    
527  // Window close event handlers.  // Window close event handlers.
528  bool MainForm::queryClose (void)  bool MainForm::queryClose (void)
529  {  {
530      bool bQueryClose = closeSession(false);          bool bQueryClose = closeSession(false);
531    
532      // Try to save current general state...          // Try to save current general state...
533      if (m_pOptions) {          if (m_pOptions) {
534          // Some windows default fonts is here on demand too.                  // Some windows default fonts is here on demand too.
535          if (bQueryClose && m_pMessages)                  if (bQueryClose && m_pMessages)
536              m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
537          // Try to save current positioning.                  // Try to save current positioning.
538          if (bQueryClose) {                  if (bQueryClose) {
539              // Save decorations state.                          // Save decorations state.
540              m_pOptions->bMenubar = ui.MenuBar->isVisible();                          m_pOptions->bMenubar = m_ui.MenuBar->isVisible();
541              m_pOptions->bToolbar = (ui.fileToolbar->isVisible() || ui.editToolbar->isVisible() || ui.channelsToolbar->isVisible());                          m_pOptions->bToolbar = (m_ui.fileToolbar->isVisible()
542              m_pOptions->bStatusbar = statusBar()->isVisible();                                  || m_ui.editToolbar->isVisible()
543              // Save the dock windows state.                                  || m_ui.channelsToolbar->isVisible());
544              const QString sDockables = saveState().toBase64().data();                          m_pOptions->bStatusbar = statusBar()->isVisible();
545                            // Save the dock windows state.
546                            const QString sDockables = saveState().toBase64().data();
547                          m_pOptions->settings().setValue("/Layout/DockWindows", saveState());                          m_pOptions->settings().setValue("/Layout/DockWindows", saveState());
548              // And the children, and the main windows state,.                          // And the children, and the main windows state,.
549                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);
550                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);                          m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);
551                          m_pOptions->saveWidgetGeometry(this);                          m_pOptions->saveWidgetGeometry(this, true);
552                          // Close popup widgets.                          // Close popup widgets.
553                          if (m_pInstrumentListForm)                          if (m_pInstrumentListForm)
554                                  m_pInstrumentListForm->close();                                  m_pInstrumentListForm->close();
555                          if (m_pDeviceForm)                          if (m_pDeviceForm)
556                                  m_pDeviceForm->close();                                  m_pDeviceForm->close();
557              // Stop client and/or server, gracefully.                          // Stop client and/or server, gracefully.
558              stopServer();                          stopServer(true /*interactive*/);
559          }                  }
560      }          }
561    
562      return bQueryClose;          return bQueryClose;
563  }  }
564    
565    
566  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )  void MainForm::closeEvent ( QCloseEvent *pCloseEvent )
567  {  {
568      if (queryClose())          if (queryClose()) {
569          pCloseEvent->accept();                  DeviceStatusForm::deleteAllInstances();
570      else                  pCloseEvent->accept();
571          pCloseEvent->ignore();          } else
572                    pCloseEvent->ignore();
573  }  }
574    
575    
# Line 504  void MainForm::dropEvent ( QDropEvent* p Line 597  void MainForm::dropEvent ( QDropEvent* p
597                  QListIterator<QUrl> iter(pMimeData->urls());                  QListIterator<QUrl> iter(pMimeData->urls());
598                  while (iter.hasNext()) {                  while (iter.hasNext()) {
599                          const QString& sPath = iter.next().toLocalFile();                          const QString& sPath = iter.next().toLocalFile();
600                          if (qsamplerChannel::isInstrumentFile(sPath)) {                  //      if (Channel::isDlsInstrumentFile(sPath)) {
601                            if (QFileInfo(sPath).exists()) {
602                                  // Try to create a new channel from instrument file...                                  // Try to create a new channel from instrument file...
603                                  qsamplerChannel *pChannel = new qsamplerChannel();                                  Channel *pChannel = new Channel();
604                                  if (pChannel == NULL)                                  if (pChannel == NULL)
605                                          return;                                          return;
606                                  // Start setting the instrument filename...                                  // Start setting the instrument filename...
# Line 538  void MainForm::dropEvent ( QDropEvent* p Line 632  void MainForm::dropEvent ( QDropEvent* p
632    
633    
634  // Custome event handler.  // Custome event handler.
635  void MainForm::customEvent(QEvent* pCustomEvent)  void MainForm::customEvent ( QEvent* pEvent )
636  {  {
637      // For the time being, just pump it to messages.          // For the time being, just pump it to messages.
638      if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {          if (pEvent->type() == QSAMPLER_LSCP_EVENT) {
639          qsamplerCustomEvent *pEvent = (qsamplerCustomEvent *) pCustomEvent;                  LscpEvent *pLscpEvent = static_cast<LscpEvent *> (pEvent);
640                  if (pEvent->event() == LSCP_EVENT_CHANNEL_INFO) {                  switch (pLscpEvent->event()) {
641                          int iChannelID = pEvent->data().toInt();                          case LSCP_EVENT_CHANNEL_COUNT:
642                          ChannelStrip *pChannelStrip = channelStrip(iChannelID);                                  updateAllChannelStrips(true);
643                          if (pChannelStrip)                                  break;
644                                  channelStripChanged(pChannelStrip);                          case LSCP_EVENT_CHANNEL_INFO: {
645                  } else {                                  int iChannelID = pLscpEvent->data().toInt();
646                          appendMessagesColor(tr("Notify event: %1 data: %2")                                  ChannelStrip *pChannelStrip = channelStrip(iChannelID);
647                                  .arg(::lscp_event_to_text(pEvent->event()))                                  if (pChannelStrip)
648                                  .arg(pEvent->data()), "#996699");                                          channelStripChanged(pChannelStrip);
649                                    break;
650                            }
651                            case LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT:
652                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
653                                    DeviceStatusForm::onDevicesChanged();
654                                    updateViewMidiDeviceStatusMenu();
655                                    break;
656                            case LSCP_EVENT_MIDI_INPUT_DEVICE_INFO: {
657                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
658                                    const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt();
659                                    DeviceStatusForm::onDeviceChanged(iDeviceID);
660                                    break;
661                            }
662                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT:
663                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
664                                    break;
665                            case LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO:
666                                    if (m_pDeviceForm) m_pDeviceForm->refreshDevices();
667                                    break;
668                    #if CONFIG_EVENT_CHANNEL_MIDI
669                            case LSCP_EVENT_CHANNEL_MIDI: {
670                                    const int iChannelID = pLscpEvent->data().section(' ', 0, 0).toInt();
671                                    ChannelStrip *pChannelStrip = channelStrip(iChannelID);
672                                    if (pChannelStrip)
673                                            pChannelStrip->midiActivityLedOn();
674                                    break;
675                            }
676                    #endif
677                    #if CONFIG_EVENT_DEVICE_MIDI
678                            case LSCP_EVENT_DEVICE_MIDI: {
679                                    const int iDeviceID = pLscpEvent->data().section(' ', 0, 0).toInt();
680                                    const int iPortID   = pLscpEvent->data().section(' ', 1, 1).toInt();
681                                    DeviceStatusForm *pDeviceStatusForm
682                                            = DeviceStatusForm::getInstance(iDeviceID);
683                                    if (pDeviceStatusForm)
684                                            pDeviceStatusForm->midiArrived(iPortID);
685                                    break;
686                            }
687                    #endif
688                            default:
689                                    appendMessagesColor(tr("LSCP Event: %1 data: %2")
690                                            .arg(::lscp_event_to_text(pLscpEvent->event()))
691                                            .arg(pLscpEvent->data()), "#996699");
692                  }                  }
693      }          }
694  }  }
695    
696    
697    // LADISH Level 1 -- SIGUSR1 signal handler.
698    void MainForm::handle_sigusr1 (void)
699    {
700    #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
701    
702            char c;
703    
704            if (::read(g_fdUsr1[1], &c, sizeof(c)) > 0)
705                    saveSession(false);
706    
707    #endif
708    }
709    
710    
711    void MainForm::updateViewMidiDeviceStatusMenu (void)
712    {
713            m_ui.viewMidiDeviceStatusMenu->clear();
714            const std::map<int, DeviceStatusForm *> statusForms
715                    = DeviceStatusForm::getInstances();
716            std::map<int, DeviceStatusForm *>::const_iterator iter
717                    = statusForms.begin();
718            for ( ; iter != statusForms.end(); ++iter) {
719                    DeviceStatusForm *pStatusForm = iter->second;
720                    m_ui.viewMidiDeviceStatusMenu->addAction(
721                            pStatusForm->visibleAction());
722            }
723    }
724    
725    
726  // Context menu event handler.  // Context menu event handler.
727  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )
728  {  {
729      stabilizeForm();          stabilizeForm();
730    
731      ui.editMenu->exec(pEvent->globalPos());          m_ui.editMenu->exec(pEvent->globalPos());
732  }  }
733    
734    
# Line 569  void MainForm::contextMenuEvent( QContex Line 736  void MainForm::contextMenuEvent( QContex
736  // qsamplerMainForm -- Brainless public property accessors.  // qsamplerMainForm -- Brainless public property accessors.
737    
738  // The global options settings property.  // The global options settings property.
739  qsamplerOptions *MainForm::options (void)  Options *MainForm::options (void) const
740  {  {
741      return m_pOptions;          return m_pOptions;
742  }  }
743    
744    
745  // The LSCP client descriptor property.  // The LSCP client descriptor property.
746  lscp_client_t *MainForm::client (void)  lscp_client_t *MainForm::client (void) const
747  {  {
748      return m_pClient;          return m_pClient;
749  }  }
750    
751    
# Line 595  MainForm *MainForm::getInstance (void) Line 762  MainForm *MainForm::getInstance (void)
762  // Format the displayable session filename.  // Format the displayable session filename.
763  QString MainForm::sessionName ( const QString& sFilename )  QString MainForm::sessionName ( const QString& sFilename )
764  {  {
765      bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);          bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);
766      QString sSessionName = sFilename;          QString sSessionName = sFilename;
767      if (sSessionName.isEmpty())          if (sSessionName.isEmpty())
768          sSessionName = tr("Untitled") + QString::number(m_iUntitled);                  sSessionName = tr("Untitled") + QString::number(m_iUntitled);
769      else if (!bCompletePath)          else if (!bCompletePath)
770          sSessionName = QFileInfo(sSessionName).fileName();                  sSessionName = QFileInfo(sSessionName).fileName();
771      return sSessionName;          return sSessionName;
772  }  }
773    
774    
775  // Create a new session file from scratch.  // Create a new session file from scratch.
776  bool MainForm::newSession (void)  bool MainForm::newSession (void)
777  {  {
778      // Check if we can do it.          // Check if we can do it.
779      if (!closeSession(true))          if (!closeSession(true))
780          return false;                  return false;
781    
782          // Give us what the server has, right now...          // Give us what the server has, right now...
783          updateSession();          updateSession();
784    
785      // Ok increment untitled count.          // Ok increment untitled count.
786      m_iUntitled++;          m_iUntitled++;
787    
788      // Stabilize form.          // Stabilize form.
789      m_sFilename = QString::null;          m_sFilename = QString::null;
790      m_iDirtyCount = 0;          m_iDirtyCount = 0;
791      appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));          appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));
792      stabilizeForm();          stabilizeForm();
793    
794      return true;          return true;
795  }  }
796    
797    
798  // Open an existing sampler session.  // Open an existing sampler session.
799  bool MainForm::openSession (void)  bool MainForm::openSession (void)
800  {  {
801      if (m_pOptions == NULL)          if (m_pOptions == NULL)
802          return false;                  return false;
803    
804      // Ask for the filename to open...          // Ask for the filename to open...
805          QString sFilename = QFileDialog::getOpenFileName(this,          QString sFilename = QFileDialog::getOpenFileName(this,
806                  QSAMPLER_TITLE ": " + tr("Open Session"), // Caption.                  QSAMPLER_TITLE ": " + tr("Open Session"), // Caption.
807                  m_pOptions->sSessionDir,                  // Start here.                  m_pOptions->sSessionDir,                  // Start here.
808                  tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)                  tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
809          );          );
810    
811      // Have we cancelled?          // Have we cancelled?
812      if (sFilename.isEmpty())          if (sFilename.isEmpty())
813          return false;                  return false;
814    
815      // Check if we're going to discard safely the current one...          // Check if we're going to discard safely the current one...
816      if (!closeSession(true))          if (!closeSession(true))
817          return false;                  return false;
818    
819      // Load it right away.          // Load it right away.
820      return loadSessionFile(sFilename);          return loadSessionFile(sFilename);
821  }  }
822    
823    
824  // Save current sampler session with another name.  // Save current sampler session with another name.
825  bool MainForm::saveSession ( bool bPrompt )  bool MainForm::saveSession ( bool bPrompt )
826  {  {
827      if (m_pOptions == NULL)          if (m_pOptions == NULL)
828          return false;                  return false;
829    
830      QString sFilename = m_sFilename;          QString sFilename = m_sFilename;
831    
832      // Ask for the file to save, if there's none...          // Ask for the file to save, if there's none...
833      if (bPrompt || sFilename.isEmpty()) {          if (bPrompt || sFilename.isEmpty()) {
834          // If none is given, assume default directory.                  // If none is given, assume default directory.
835          if (sFilename.isEmpty())                  if (sFilename.isEmpty())
836              sFilename = m_pOptions->sSessionDir;                          sFilename = m_pOptions->sSessionDir;
837          // Prompt the guy...                  // Prompt the guy...
838                  sFilename = QFileDialog::getSaveFileName(this,                  sFilename = QFileDialog::getSaveFileName(this,
839                          QSAMPLER_TITLE ": " + tr("Save Session"), // Caption.                          QSAMPLER_TITLE ": " + tr("Save Session"), // Caption.
840                          sFilename,                                // Start here.                          sFilename,                                // Start here.
841                          tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)                          tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
842                  );                  );
843          // Have we cancelled it?                  // Have we cancelled it?
844          if (sFilename.isEmpty())                  if (sFilename.isEmpty())
845              return false;                          return false;
846          // Enforce .lscp extension...                  // Enforce .lscp extension...
847          if (QFileInfo(sFilename).suffix().isEmpty())                  if (QFileInfo(sFilename).suffix().isEmpty())
848              sFilename += ".lscp";                          sFilename += ".lscp";
849          // Check if already exists...                  // Check if already exists...
850          if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {                  if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {
851              if (QMessageBox::warning(this,                          if (QMessageBox::warning(this,
852                                  QSAMPLER_TITLE ": " + tr("Warning"),                                  QSAMPLER_TITLE ": " + tr("Warning"),
853                  tr("The file already exists:\n\n"                                  tr("The file already exists:\n\n"
854                     "\"%1\"\n\n"                                  "\"%1\"\n\n"
855                     "Do you want to replace it?")                                  "Do you want to replace it?")
856                     .arg(sFilename),                                  .arg(sFilename),
857                  tr("Replace"), tr("Cancel")) > 0)                                  QMessageBox::Yes | QMessageBox::No)
858                  return false;                                  == QMessageBox::No)
859          }                                  return false;
860      }                  }
861            }
862    
863      // Save it right away.          // Save it right away.
864      return saveSessionFile(sFilename);          return saveSessionFile(sFilename);
865  }  }
866    
867    
868  // Close current session.  // Close current session.
869  bool MainForm::closeSession ( bool bForce )  bool MainForm::closeSession ( bool bForce )
870  {  {
871      bool bClose = true;          bool bClose = true;
872    
873      // Are we dirty enough to prompt it?          // Are we dirty enough to prompt it?
874      if (m_iDirtyCount > 0) {          if (m_iDirtyCount > 0) {
875          switch (QMessageBox::warning(this,                  switch (QMessageBox::warning(this,
876                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
877              tr("The current session has been changed:\n\n"                          tr("The current session has been changed:\n\n"
878              "\"%1\"\n\n"                          "\"%1\"\n\n"
879              "Do you want to save the changes?")                          "Do you want to save the changes?")
880              .arg(sessionName(m_sFilename)),                          .arg(sessionName(m_sFilename)),
881              tr("Save"), tr("Discard"), tr("Cancel"))) {                          QMessageBox::Save |
882          case 0:     // Save...                          QMessageBox::Discard |
883              bClose = saveSession(false);                          QMessageBox::Cancel)) {
884              // Fall thru....                  case QMessageBox::Save:
885          case 1:     // Discard                          bClose = saveSession(false);
886              break;                          // Fall thru....
887          default:    // Cancel.                  case QMessageBox::Discard:
888              bClose = false;                          break;
889              break;                  default:    // Cancel.
890          }                          bClose = false;
891      }                          break;
892                    }
893      // If we may close it, dot it.          }
     if (bClose) {  
         // Remove all channel strips from sight...  
         m_pWorkspace->setUpdatesEnabled(false);  
         QWidgetList wlist = m_pWorkspace->windowList();  
         for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {  
             ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);  
             if (pChannelStrip) {  
                 qsamplerChannel *pChannel = pChannelStrip->channel();  
                 if (bForce && pChannel)  
                     pChannel->removeChannel();  
                 delete pChannelStrip;  
             }  
         }  
         m_pWorkspace->setUpdatesEnabled(true);  
         // We're now clean, for sure.  
         m_iDirtyCount = 0;  
     }  
894    
895      return bClose;          // If we may close it, dot it.
896            if (bClose) {
897                    // Remove all channel strips from sight...
898                    m_pWorkspace->setUpdatesEnabled(false);
899                    QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
900                    for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
901                            ChannelStrip *pChannelStrip = NULL;
902                            QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
903                            if (pMdiSubWindow)
904                                    pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
905                            if (pChannelStrip) {
906                                    Channel *pChannel = pChannelStrip->channel();
907                                    if (bForce && pChannel)
908                                            pChannel->removeChannel();
909                                    delete pChannelStrip;
910                            }
911                            if (pMdiSubWindow)
912                                    delete pMdiSubWindow;
913                    }
914                    m_pWorkspace->setUpdatesEnabled(true);
915                    // We're now clean, for sure.
916                    m_iDirtyCount = 0;
917            }
918    
919            return bClose;
920  }  }
921    
922    
923  // Load a session from specific file path.  // Load a session from specific file path.
924  bool MainForm::loadSessionFile ( const QString& sFilename )  bool MainForm::loadSessionFile ( const QString& sFilename )
925  {  {
926      if (m_pClient == NULL)          if (m_pClient == NULL)
927          return false;                  return false;
928    
929      // Open and read from real file.          // Open and read from real file.
930      QFile file(sFilename);          QFile file(sFilename);
931      if (!file.open(QIODevice::ReadOnly)) {          if (!file.open(QIODevice::ReadOnly)) {
932          appendMessagesError(tr("Could not open \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
933          return false;                          tr("Could not open \"%1\" session file.\n\nSorry.")
934      }                          .arg(sFilename));
935                    return false;
936            }
937    
938          // Tell the world we'll take some time...          // Tell the world we'll take some time...
939          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
940    
941      // Read the file.          // Read the file.
942          int iLine = 0;          int iLine = 0;
943      int iErrors = 0;          int iErrors = 0;
944      QTextStream ts(&file);          QTextStream ts(&file);
945      while (!ts.atEnd()) {          while (!ts.atEnd()) {
946          // Read the line.                  // Read the line.
947          QString sCommand = ts.readLine().trimmed();                  QString sCommand = ts.readLine().trimmed();
948                  iLine++;                  iLine++;
949          // If not empty, nor a comment, call the server...                  // If not empty, nor a comment, call the server...
950          if (!sCommand.isEmpty() && sCommand[0] != '#') {                  if (!sCommand.isEmpty() && sCommand[0] != '#') {
951                          // Remember that, no matter what,                          // Remember that, no matter what,
952                          // all LSCP commands are CR/LF terminated.                          // all LSCP commands are CR/LF terminated.
953                          sCommand += "\r\n";                          sCommand += "\r\n";
# Line 782  bool MainForm::loadSessionFile ( const Q Line 959  bool MainForm::loadSessionFile ( const Q
959                                  appendMessagesClient("lscp_client_query");                                  appendMessagesClient("lscp_client_query");
960                                  iErrors++;                                  iErrors++;
961                          }                          }
962          }                  }
963          // Try to make it snappy :)                  // Try to make it snappy :)
964          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
965      }          }
966    
967      // Ok. we've read it.          // Ok. we've read it.
968      file.close();          file.close();
969    
970          // Now we'll try to create (update) the whole GUI session.          // Now we'll try to create (update) the whole GUI session.
971          updateSession();          updateSession();
# Line 797  bool MainForm::loadSessionFile ( const Q Line 974  bool MainForm::loadSessionFile ( const Q
974          QApplication::restoreOverrideCursor();          QApplication::restoreOverrideCursor();
975    
976          // Have we any errors?          // Have we any errors?
977          if (iErrors > 0)          if (iErrors > 0) {
978                  appendMessagesError(tr("Session loaded with errors\nfrom \"%1\".\n\nSorry.").arg(sFilename));                  appendMessagesError(
979                            tr("Session loaded with errors\nfrom \"%1\".\n\nSorry.")
980                            .arg(sFilename));
981            }
982    
983      // Save as default session directory.          // Save as default session directory.
984      if (m_pOptions)          if (m_pOptions)
985          m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();                  m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();
986          // We're not dirty anymore, if loaded without errors,          // We're not dirty anymore, if loaded without errors,
987          m_iDirtyCount = iErrors;          m_iDirtyCount = iErrors;
988      // Stabilize form...          // Stabilize form...
989      m_sFilename = sFilename;          m_sFilename = sFilename;
990      updateRecentFiles(sFilename);          updateRecentFiles(sFilename);
991      appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));          appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));
992    
993      // Make that an overall update.          // Make that an overall update.
994      stabilizeForm();          stabilizeForm();
995      return true;          return true;
996  }  }
997    
998    
# Line 828  bool MainForm::saveSessionFile ( const Q Line 1008  bool MainForm::saveSessionFile ( const Q
1008                  return false;                  return false;
1009          }          }
1010    
1011      // Open and write into real file.          // Open and write into real file.
1012      QFile file(sFilename);          QFile file(sFilename);
1013      if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {          if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
1014          appendMessagesError(tr("Could not open \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
1015          return false;                          tr("Could not open \"%1\" session file.\n\nSorry.")
1016      }                          .arg(sFilename));
1017                    return false;
1018            }
1019    
1020          // Tell the world we'll take some time...          // Tell the world we'll take some time...
1021          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1022    
1023      // Write the file.          // Write the file.
1024      int  iErrors = 0;          int  iErrors = 0;
1025      QTextStream ts(&file);          QTextStream ts(&file);
1026      ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;          ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;
1027      ts << "# " << tr("Version")          ts << "# " << tr("Version")
1028         << ": " QSAMPLER_VERSION << endl;          << ": " QSAMPLER_VERSION << endl;
1029      ts << "# " << tr("Build")          ts << "# " << tr("Build")
1030         << ": " __DATE__ " " __TIME__ << endl;          << ": " __DATE__ " " __TIME__ << endl;
1031      ts << "#"  << endl;          ts << "#"  << endl;
1032      ts << "# " << tr("File")          ts << "# " << tr("File")
1033         << ": " << QFileInfo(sFilename).fileName() << endl;          << ": " << QFileInfo(sFilename).fileName() << endl;
1034      ts << "# " << tr("Date")          ts << "# " << tr("Date")
1035         << ": " << QDate::currentDate().toString("MMM dd yyyy")          << ": " << QDate::currentDate().toString("MMM dd yyyy")
1036         << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;          << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;
1037      ts << "#"  << endl;          ts << "#"  << endl;
1038      ts << endl;          ts << endl;
1039    
1040          // It is assumed that this new kind of device+session file          // It is assumed that this new kind of device+session file
1041          // will be loaded from a complete initialized server...          // will be loaded from a complete initialized server...
# Line 863  bool MainForm::saveSessionFile ( const Q Line 1045  bool MainForm::saveSessionFile ( const Q
1045    
1046          // Audio device mapping.          // Audio device mapping.
1047          QMap<int, int> audioDeviceMap;          QMap<int, int> audioDeviceMap;
1048          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Audio);          piDeviceIDs = Device::getDevices(m_pClient, Device::Audio);
1049          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
1050                  ts << endl;                  ts << endl;
1051                  qsamplerDevice device(qsamplerDevice::Audio, piDeviceIDs[iDevice]);                  Device device(Device::Audio, piDeviceIDs[iDevice]);
1052                  // Audio device specification...                  // Audio device specification...
1053                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1054                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1055                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();
1056                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
1057                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
1058                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
1059                                          ++deviceParam) {                                          ++deviceParam) {
1060                          const qsamplerDeviceParam& param = deviceParam.value();                          const DeviceParam& param = deviceParam.value();
1061                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
1062                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
1063                  }                  }
1064                  ts << endl;                  ts << endl;
1065                  // Audio channel parameters...                  // Audio channel parameters...
1066                  int iPort = 0;                  int iPort = 0;
1067                  QListIterator<qsamplerDevicePort *> iter(device.ports());                  QListIterator<DevicePort *> iter(device.ports());
1068                  while (iter.hasNext()) {                  while (iter.hasNext()) {
1069                          qsamplerDevicePort *pPort = iter.next();                          DevicePort *pPort = iter.next();
1070                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1071                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1072                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1073                                                  ++portParam) {                                                  ++portParam) {
1074                                  const qsamplerDeviceParam& param = portParam.value();                                  const DeviceParam& param = portParam.value();
1075                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1076                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice
1077                                          << " " << iPort << " " << portParam.key()                                          << " " << iPort << " " << portParam.key()
# Line 905  bool MainForm::saveSessionFile ( const Q Line 1087  bool MainForm::saveSessionFile ( const Q
1087    
1088          // MIDI device mapping.          // MIDI device mapping.
1089          QMap<int, int> midiDeviceMap;          QMap<int, int> midiDeviceMap;
1090          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Midi);          piDeviceIDs = Device::getDevices(m_pClient, Device::Midi);
1091          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
1092                  ts << endl;                  ts << endl;
1093                  qsamplerDevice device(qsamplerDevice::Midi, piDeviceIDs[iDevice]);                  Device device(Device::Midi, piDeviceIDs[iDevice]);
1094                  // MIDI device specification...                  // MIDI device specification...
1095                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1096                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1097                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();
1098                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
1099                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
1100                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
1101                                          ++deviceParam) {                                          ++deviceParam) {
1102                          const qsamplerDeviceParam& param = deviceParam.value();                          const DeviceParam& param = deviceParam.value();
1103                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
1104                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
1105                  }                  }
1106                  ts << endl;                  ts << endl;
1107                  // MIDI port parameters...                  // MIDI port parameters...
1108                  int iPort = 0;                  int iPort = 0;
1109                  QListIterator<qsamplerDevicePort *> iter(device.ports());                  QListIterator<DevicePort *> iter(device.ports());
1110                  while (iter.hasNext()) {                  while (iter.hasNext()) {
1111                          qsamplerDevicePort *pPort = iter.next();                          DevicePort *pPort = iter.next();
1112                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1113                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1114                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1115                                                  ++portParam) {                                                  ++portParam) {
1116                                  const qsamplerDeviceParam& param = portParam.value();                                  const DeviceParam& param = portParam.value();
1117                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1118                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice
1119                                     << " " << iPort << " " << portParam.key()                                  << " " << iPort << " " << portParam.key()
1120                                     << "='" << param.value << "'" << endl;                                  << "='" << param.value << "'" << endl;
1121                          }                          }
1122                          iPort++;                          iPort++;
1123                  }                  }
# Line 1018  bool MainForm::saveSessionFile ( const Q Line 1200  bool MainForm::saveSessionFile ( const Q
1200  #endif  // CONFIG_MIDI_INSTRUMENT  #endif  // CONFIG_MIDI_INSTRUMENT
1201    
1202          // Sampler channel mapping.          // Sampler channel mapping.
1203      QWidgetList wlist = m_pWorkspace->windowList();          QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
1204      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
1205          ChannelStrip* pChannelStrip                  ChannelStrip *pChannelStrip = NULL;
1206                          = static_cast<ChannelStrip *> (wlist.at(iChannel));                  QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
1207          if (pChannelStrip) {                  if (pMdiSubWindow)
1208              qsamplerChannel *pChannel = pChannelStrip->channel();                          pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
1209              if (pChannel) {                  if (pChannelStrip) {
1210                  ts << "# " << tr("Channel") << " " << iChannel << endl;                          Channel *pChannel = pChannelStrip->channel();
1211                  ts << "ADD CHANNEL" << endl;                          if (pChannel) {
1212                                    ts << "# " << tr("Channel") << " " << iChannel << endl;
1213                                    ts << "ADD CHANNEL" << endl;
1214                                  if (audioDeviceMap.isEmpty()) {                                  if (audioDeviceMap.isEmpty()) {
1215                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel
1216                                                  << " " << pChannel->audioDriver() << endl;                                                  << " " << pChannel->audioDriver() << endl;
# Line 1043  bool MainForm::saveSessionFile ( const Q Line 1227  bool MainForm::saveSessionFile ( const Q
1227                                  }                                  }
1228                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel
1229                                          << " " << pChannel->midiPort() << endl;                                          << " " << pChannel->midiPort() << endl;
1230                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";                                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";
1231                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)                                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
1232                      ts << "ALL";                                          ts << "ALL";
1233                  else                                  else
1234                      ts << pChannel->midiChannel();                                          ts << pChannel->midiChannel();
1235                  ts << endl;                                  ts << endl;
1236                  ts << "LOAD ENGINE " << pChannel->engineName() << " " << iChannel << endl;                                  ts << "LOAD ENGINE " << pChannel->engineName()
1237                                            << " " << iChannel << endl;
1238                                  if (pChannel->instrumentStatus() < 100) ts << "# ";                                  if (pChannel->instrumentStatus() < 100) ts << "# ";
1239                                  ts << "LOAD INSTRUMENT NON_MODAL '" << pChannel->instrumentFile() << "' "                                  ts << "LOAD INSTRUMENT NON_MODAL '"
1240                                            << pChannel->instrumentFile() << "' "
1241                                          << pChannel->instrumentNr() << " " << iChannel << endl;                                          << pChannel->instrumentNr() << " " << iChannel << endl;
1242                                  qsamplerChannelRoutingMap::ConstIterator audioRoute;                                  ChannelRoutingMap::ConstIterator audioRoute;
1243                                  for (audioRoute = pChannel->audioRouting().begin();                                  for (audioRoute = pChannel->audioRouting().begin();
1244                                                  audioRoute != pChannel->audioRouting().end();                                                  audioRoute != pChannel->audioRouting().end();
1245                                                          ++audioRoute) {                                                          ++audioRoute) {
# Line 1067  bool MainForm::saveSessionFile ( const Q Line 1253  bool MainForm::saveSessionFile ( const Q
1253                                          ts << "SET CHANNEL MUTE " << iChannel << " 1" << endl;                                          ts << "SET CHANNEL MUTE " << iChannel << " 1" << endl;
1254                                  if (pChannel->channelSolo())                                  if (pChannel->channelSolo())
1255                                          ts << "SET CHANNEL SOLO " << iChannel << " 1" << endl;                                          ts << "SET CHANNEL SOLO " << iChannel << " 1" << endl;
1256  #ifdef CONFIG_MIDI_INSTRUMENT                          #ifdef CONFIG_MIDI_INSTRUMENT
1257                                  if (pChannel->midiMap() >= 0) {                                  if (pChannel->midiMap() >= 0) {
1258                                          ts << "SET CHANNEL MIDI_INSTRUMENT_MAP " << iChannel                                          ts << "SET CHANNEL MIDI_INSTRUMENT_MAP " << iChannel
1259                                                  << " " << midiInstrumentMap[pChannel->midiMap()] << endl;                                                  << " " << midiInstrumentMap[pChannel->midiMap()] << endl;
1260                                  }                                  }
1261  #endif                          #endif
1262  #ifdef CONFIG_FXSEND                          #ifdef CONFIG_FXSEND
1263                                  int iChannelID = pChannel->channelID();                                  int iChannelID = pChannel->channelID();
1264                                  int *piFxSends = ::lscp_list_fxsends(m_pClient, iChannelID);                                  int *piFxSends = ::lscp_list_fxsends(m_pClient, iChannelID);
1265                                  for (int iFxSend = 0;                                  for (int iFxSend = 0;
# Line 1097  bool MainForm::saveSessionFile ( const Q Line 1283  bool MainForm::saveSessionFile ( const Q
1283                                                                  << " " << iAudioSrc                                                                  << " " << iAudioSrc
1284                                                                  << " " << piRouting[iAudioSrc] << endl;                                                                  << " " << piRouting[iAudioSrc] << endl;
1285                                                  }                                                  }
1286  #ifdef CONFIG_FXSEND_LEVEL                                          #ifdef CONFIG_FXSEND_LEVEL
1287                                                  ts << "SET FX_SEND LEVEL " << iChannel                                                  ts << "SET FX_SEND LEVEL " << iChannel
1288                                                          << " " << iFxSend                                                          << " " << iFxSend
1289                                                          << " " << pFxSendInfo->level << endl;                                                          << " " << pFxSendInfo->level << endl;
1290  #endif                                          #endif
1291                                          }       // Check for errors...                                          }       // Check for errors...
1292                                          else if (::lscp_client_get_errno(m_pClient)) {                                          else if (::lscp_client_get_errno(m_pClient)) {
1293                                                  appendMessagesClient("lscp_get_fxsend_info");                                                  appendMessagesClient("lscp_get_fxsend_info");
1294                                                  iErrors++;                                                  iErrors++;
1295                                          }                                          }
1296                                  }                                  }
1297  #endif                          #endif
1298                  ts << endl;                                  ts << endl;
1299              }                          }
1300          }                  }
1301          // Try to keep it snappy :)                  // Try to keep it snappy :)
1302          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1303      }          }
1304    
1305  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
1306          ts << "# " << tr("Global volume level") << endl;          ts << "# " << tr("Global volume level") << endl;
# Line 1122  bool MainForm::saveSessionFile ( const Q Line 1308  bool MainForm::saveSessionFile ( const Q
1308          ts << endl;          ts << endl;
1309  #endif  #endif
1310    
1311      // Ok. we've wrote it.          // Ok. we've wrote it.
1312      file.close();          file.close();
1313    
1314          // We're fornerly done.          // We're fornerly done.
1315          QApplication::restoreOverrideCursor();          QApplication::restoreOverrideCursor();
1316    
1317      // Have we any errors?          // Have we any errors?
1318      if (iErrors > 0)          if (iErrors > 0) {
1319          appendMessagesError(tr("Some settings could not be saved\nto \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
1320                            tr("Some settings could not be saved\n"
1321      // Save as default session directory.                          "to \"%1\" session file.\n\nSorry.")
1322      if (m_pOptions)                          .arg(sFilename));
1323          m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();          }
1324      // We're not dirty anymore.  
1325      m_iDirtyCount = 0;          // Save as default session directory.
1326      // Stabilize form...          if (m_pOptions)
1327      m_sFilename = sFilename;                  m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();
1328      updateRecentFiles(sFilename);          // We're not dirty anymore.
1329      appendMessages(tr("Save session: \"%1\".").arg(sessionName(m_sFilename)));          m_iDirtyCount = 0;
1330      stabilizeForm();          // Stabilize form...
1331      return true;          m_sFilename = sFilename;
1332            updateRecentFiles(sFilename);
1333            appendMessages(tr("Save session: \"%1\".").arg(sessionName(m_sFilename)));
1334            stabilizeForm();
1335            return true;
1336  }  }
1337    
1338    
1339  // Session change receiver slot.  // Session change receiver slot.
1340  void MainForm::sessionDirty (void)  void MainForm::sessionDirty (void)
1341  {  {
1342      // Just mark the dirty form.          // Just mark the dirty form.
1343      m_iDirtyCount++;          m_iDirtyCount++;
1344      // and update the form status...          // and update the form status...
1345      stabilizeForm();          stabilizeForm();
1346  }  }
1347    
1348    
# Line 1162  void MainForm::sessionDirty (void) Line 1352  void MainForm::sessionDirty (void)
1352  // Create a new sampler session.  // Create a new sampler session.
1353  void MainForm::fileNew (void)  void MainForm::fileNew (void)
1354  {  {
1355      // Of course we'll start clean new.          // Of course we'll start clean new.
1356      newSession();          newSession();
1357  }  }
1358    
1359    
1360  // Open an existing sampler session.  // Open an existing sampler session.
1361  void MainForm::fileOpen (void)  void MainForm::fileOpen (void)
1362  {  {
1363      // Open it right away.          // Open it right away.
1364      openSession();          openSession();
1365  }  }
1366    
1367    
# Line 1195  void MainForm::fileOpenRecent (void) Line 1385  void MainForm::fileOpenRecent (void)
1385  // Save current sampler session.  // Save current sampler session.
1386  void MainForm::fileSave (void)  void MainForm::fileSave (void)
1387  {  {
1388      // Save it right away.          // Save it right away.
1389      saveSession(false);          saveSession(false);
1390  }  }
1391    
1392    
1393  // Save current sampler session with another name.  // Save current sampler session with another name.
1394  void MainForm::fileSaveAs (void)  void MainForm::fileSaveAs (void)
1395  {  {
1396      // Save it right away, maybe with another name.          // Save it right away, maybe with another name.
1397      saveSession(true);          saveSession(true);
1398  }  }
1399    
1400    
1401  // Reset the sampler instance.  // Reset the sampler instance.
1402  void MainForm::fileReset (void)  void MainForm::fileReset (void)
1403  {  {
1404      if (m_pClient == NULL)          if (m_pClient == NULL)
1405          return;                  return;
1406    
1407      // Ask user whether he/she want's an internal sampler reset...          // Ask user whether he/she want's an internal sampler reset...
1408      if (QMessageBox::warning(this,          if (m_pOptions && m_pOptions->bConfirmReset) {
1409                  QSAMPLER_TITLE ": " + tr("Warning"),                  const QString& sTitle = QSAMPLER_TITLE ": " + tr("Warning");
1410          tr("Resetting the sampler instance will close\n"                  const QString& sText = tr(
1411             "all device and channel configurations.\n\n"                          "Resetting the sampler instance will close\n"
1412             "Please note that this operation may cause\n"                          "all device and channel configurations.\n\n"
1413             "temporary MIDI and Audio disruption.\n\n"                          "Please note that this operation may cause\n"
1414             "Do you want to reset the sampler engine now?"),                          "temporary MIDI and Audio disruption.\n\n"
1415          tr("Reset"), tr("Cancel")) > 0)                          "Do you want to reset the sampler engine now?");
1416          return;          #if 0
1417                    if (QMessageBox::warning(this, sTitle, sText,
1418                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1419                            return;
1420            #else
1421                    QMessageBox mbox(this);
1422                    mbox.setIcon(QMessageBox::Warning);
1423                    mbox.setWindowTitle(sTitle);
1424                    mbox.setText(sText);
1425                    mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1426                    QCheckBox cbox(tr("Don't ask this again"));
1427                    cbox.setChecked(false);
1428                    cbox.blockSignals(true);
1429                    mbox.addButton(&cbox, QMessageBox::ActionRole);
1430                    if (mbox.exec() == QMessageBox::Cancel)
1431                            return;
1432                    if (cbox.isChecked())
1433                            m_pOptions->bConfirmReset = false;
1434            #endif
1435            }
1436    
1437          // Trye closing the current session, first...          // Trye closing the current session, first...
1438          if (!closeSession(true))          if (!closeSession(true))
1439                  return;                  return;
1440    
1441      // Just do the reset, after closing down current session...          // Just do the reset, after closing down current session...
1442          // Do the actual sampler reset...          // Do the actual sampler reset...
1443          if (::lscp_reset_sampler(m_pClient) != LSCP_OK) {          if (::lscp_reset_sampler(m_pClient) != LSCP_OK) {
1444                  appendMessagesClient("lscp_reset_sampler");                  appendMessagesClient("lscp_reset_sampler");
# Line 1237  void MainForm::fileReset (void) Line 1446  void MainForm::fileReset (void)
1446                  return;                  return;
1447          }          }
1448    
1449      // Log this.          // Log this.
1450      appendMessages(tr("Sampler reset."));          appendMessages(tr("Sampler reset."));
1451    
1452          // Make it a new session...          // Make it a new session...
1453          newSession();          newSession();
# Line 1248  void MainForm::fileReset (void) Line 1457  void MainForm::fileReset (void)
1457  // Restart the client/server instance.  // Restart the client/server instance.
1458  void MainForm::fileRestart (void)  void MainForm::fileRestart (void)
1459  {  {
1460      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1461          return;                  return;
1462    
1463      bool bRestart = true;          bool bRestart = true;
1464    
1465      // Ask user whether he/she want's a complete restart...          // Ask user whether he/she want's a complete restart...
1466      // (if we're currently up and running)          // (if we're currently up and running)
1467      if (bRestart && m_pClient) {          if (m_pOptions && m_pOptions->bConfirmRestart) {
1468          bRestart = (QMessageBox::warning(this,                  const QString& sTitle = QSAMPLER_TITLE ": " + tr("Warning");
1469                          QSAMPLER_TITLE ": " + tr("Warning"),                  const QString& sText = tr(
1470              tr("New settings will be effective after\n"                          "New settings will be effective after\n"
1471                 "restarting the client/server connection.\n\n"                          "restarting the client/server connection.\n\n"
1472                 "Please note that this operation may cause\n"                          "Please note that this operation may cause\n"
1473                 "temporary MIDI and Audio disruption.\n\n"                          "temporary MIDI and Audio disruption.\n\n"
1474                 "Do you want to restart the connection now?"),                          "Do you want to restart the connection now?");
1475              tr("Restart"), tr("Cancel")) == 0);          #if 0
1476      }                  if (QMessageBox::warning(this, sTitle, sText,
1477                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1478      // Are we still for it?                          bRestart = false;
1479      if (bRestart && closeSession(true)) {          #else
1480          // Stop server, it will force the client too.                  QMessageBox mbox(this);
1481          stopServer();                  mbox.setIcon(QMessageBox::Warning);
1482          // Reschedule a restart...                  mbox.setWindowTitle(sTitle);
1483          startSchedule(m_pOptions->iStartDelay);                  mbox.setText(sText);
1484      }                  mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1485                    QCheckBox cbox(tr("Don't ask this again"));
1486                    cbox.setChecked(false);
1487                    cbox.blockSignals(true);
1488                    mbox.addButton(&cbox, QMessageBox::ActionRole);
1489                    if (mbox.exec() == QMessageBox::Cancel)
1490                            bRestart = false;
1491                    else
1492                    if (cbox.isChecked())
1493                            m_pOptions->bConfirmRestart = false;
1494            #endif
1495            }
1496    
1497            // Are we still for it?
1498            if (bRestart && closeSession(true)) {
1499                    // Stop server, it will force the client too.
1500                    stopServer();
1501                    // Reschedule a restart...
1502                    startSchedule(m_pOptions->iStartDelay);
1503            }
1504  }  }
1505    
1506    
1507  // Exit application program.  // Exit application program.
1508  void MainForm::fileExit (void)  void MainForm::fileExit (void)
1509  {  {
1510      // Go for close the whole thing.          // Go for close the whole thing.
1511      close();          close();
1512  }  }
1513    
1514    
# Line 1290  void MainForm::fileExit (void) Line 1518  void MainForm::fileExit (void)
1518  // Add a new sampler channel.  // Add a new sampler channel.
1519  void MainForm::editAddChannel (void)  void MainForm::editAddChannel (void)
1520  {  {
1521      if (m_pClient == NULL)          if (m_pClient == NULL)
1522          return;                  return;
1523    
1524            // Just create the channel instance...
1525            Channel *pChannel = new Channel();
1526            if (pChannel == NULL)
1527                    return;
1528    
1529            // Before we show it up, may be we'll
1530            // better ask for some initial values?
1531            if (!pChannel->channelSetup(this)) {
1532                    delete pChannel;
1533                    return;
1534            }
1535    
1536            // And give it to the strip...
1537            // (will own the channel instance, if successful).
1538            if (!createChannelStrip(pChannel)) {
1539                    delete pChannel;
1540                    return;
1541            }
1542    
1543            // Do we auto-arrange?
1544            if (m_pOptions && m_pOptions->bAutoArrange)
1545                    channelsArrange();
1546    
1547      // Just create the channel instance...          // Make that an overall update.
1548      qsamplerChannel *pChannel = new qsamplerChannel();          m_iDirtyCount++;
1549      if (pChannel == NULL)          stabilizeForm();
         return;  
   
     // Before we show it up, may be we'll  
     // better ask for some initial values?  
     if (!pChannel->channelSetup(this)) {  
         delete pChannel;  
         return;  
     }  
   
     // And give it to the strip (will own the channel instance, if successful).  
     if (!createChannelStrip(pChannel)) {  
         delete pChannel;  
         return;  
     }  
   
     // Make that an overall update.  
     m_iDirtyCount++;  
     stabilizeForm();  
1550  }  }
1551    
1552    
1553  // Remove current sampler channel.  // Remove current sampler channel.
1554  void MainForm::editRemoveChannel (void)  void MainForm::editRemoveChannel (void)
1555  {  {
1556      if (m_pClient == NULL)          if (m_pClient == NULL)
1557          return;                  return;
1558    
1559      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1560      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1561          return;                  return;
1562    
1563      qsamplerChannel *pChannel = pChannelStrip->channel();          Channel *pChannel = pChannelStrip->channel();
1564      if (pChannel == NULL)          if (pChannel == NULL)
1565          return;                  return;
1566    
1567      // Prompt user if he/she's sure about this...          // Prompt user if he/she's sure about this...
1568      if (m_pOptions && m_pOptions->bConfirmRemove) {          if (m_pOptions && m_pOptions->bConfirmRemove) {
1569          if (QMessageBox::warning(this,                  const QString& sTitle = QSAMPLER_TITLE ": " + tr("Warning");
1570                          QSAMPLER_TITLE ": " + tr("Warning"),                  const QString& sText = tr(
1571              tr("About to remove channel:\n\n"                          "About to remove channel:\n\n"
1572                 "%1\n\n"                          "%1\n\n"
1573                 "Are you sure?")                          "Are you sure?")
1574                 .arg(pChannelStrip->windowTitle()),                          .arg(pChannelStrip->windowTitle());
1575              tr("OK"), tr("Cancel")) > 0)          #if 0
1576              return;                  if (QMessageBox::warning(this, sTitle, sText,
1577      }                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1578                            return;
1579      // Remove the existing sampler channel.          #else
1580      if (!pChannel->removeChannel())                  QMessageBox mbox(this);
1581          return;                  mbox.setIcon(QMessageBox::Warning);
1582                    mbox.setWindowTitle(sTitle);
1583      // Just delete the channel strip.                  mbox.setText(sText);
1584      delete pChannelStrip;                  mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1585                    QCheckBox cbox(tr("Don't ask this again"));
1586      // Do we auto-arrange?                  cbox.setChecked(false);
1587      if (m_pOptions && m_pOptions->bAutoArrange)                  cbox.blockSignals(true);
1588          channelsArrange();                  mbox.addButton(&cbox, QMessageBox::ActionRole);
1589                    if (mbox.exec() == QMessageBox::Cancel)
1590      // We'll be dirty, for sure...                          return;
1591      m_iDirtyCount++;                  if (cbox.isChecked())
1592      stabilizeForm();                          m_pOptions->bConfirmRemove = false;
1593            #endif
1594            }
1595    
1596            // Remove the existing sampler channel.
1597            if (!pChannel->removeChannel())
1598                    return;
1599    
1600            // We'll be dirty, for sure...
1601            m_iDirtyCount++;
1602    
1603            // Just delete the channel strip.
1604            destroyChannelStrip(pChannelStrip);
1605  }  }
1606    
1607    
1608  // Setup current sampler channel.  // Setup current sampler channel.
1609  void MainForm::editSetupChannel (void)  void MainForm::editSetupChannel (void)
1610  {  {
1611      if (m_pClient == NULL)          if (m_pClient == NULL)
1612          return;                  return;
1613    
1614      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1615      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1616          return;                  return;
1617    
1618      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1619      pChannelStrip->channelSetup();          pChannelStrip->channelSetup();
1620  }  }
1621    
1622    
1623  // Edit current sampler channel.  // Edit current sampler channel.
1624  void MainForm::editEditChannel (void)  void MainForm::editEditChannel (void)
1625  {  {
1626      if (m_pClient == NULL)          if (m_pClient == NULL)
1627          return;                  return;
1628    
1629      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1630      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1631          return;                  return;
1632    
1633      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1634      pChannelStrip->channelEdit();          pChannelStrip->channelEdit();
1635  }  }
1636    
1637    
1638  // Reset current sampler channel.  // Reset current sampler channel.
1639  void MainForm::editResetChannel (void)  void MainForm::editResetChannel (void)
1640  {  {
1641      if (m_pClient == NULL)          if (m_pClient == NULL)
1642          return;                  return;
1643    
1644      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1645      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1646          return;                  return;
1647    
1648      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1649      pChannelStrip->channelReset();          pChannelStrip->channelReset();
1650  }  }
1651    
1652    
# Line 1414  void MainForm::editResetAllChannels (voi Line 1659  void MainForm::editResetAllChannels (voi
1659          // Invoque the channel strip procedure,          // Invoque the channel strip procedure,
1660          // for all channels out there...          // for all channels out there...
1661          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
1662          QWidgetList wlist = m_pWorkspace->windowList();          QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
1663          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
1664                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip *pChannelStrip = NULL;
1665                    QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
1666                    if (pMdiSubWindow)
1667                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
1668                  if (pChannelStrip)                  if (pChannelStrip)
1669                          pChannelStrip->channelReset();                          pChannelStrip->channelReset();
1670          }          }
# Line 1430  void MainForm::editResetAllChannels (voi Line 1678  void MainForm::editResetAllChannels (voi
1678  // Show/hide the main program window menubar.  // Show/hide the main program window menubar.
1679  void MainForm::viewMenubar ( bool bOn )  void MainForm::viewMenubar ( bool bOn )
1680  {  {
1681      if (bOn)          if (bOn)
1682          ui.MenuBar->show();                  m_ui.MenuBar->show();
1683      else          else
1684          ui.MenuBar->hide();                  m_ui.MenuBar->hide();
1685  }  }
1686    
1687    
1688  // Show/hide the main program window toolbar.  // Show/hide the main program window toolbar.
1689  void MainForm::viewToolbar ( bool bOn )  void MainForm::viewToolbar ( bool bOn )
1690  {  {
1691      if (bOn) {          if (bOn) {
1692          ui.fileToolbar->show();                  m_ui.fileToolbar->show();
1693          ui.editToolbar->show();                  m_ui.editToolbar->show();
1694          ui.channelsToolbar->show();                  m_ui.channelsToolbar->show();
1695      } else {          } else {
1696          ui.fileToolbar->hide();                  m_ui.fileToolbar->hide();
1697          ui.editToolbar->hide();                  m_ui.editToolbar->hide();
1698          ui.channelsToolbar->hide();                  m_ui.channelsToolbar->hide();
1699      }          }
1700  }  }
1701    
1702    
1703  // Show/hide the main program window statusbar.  // Show/hide the main program window statusbar.
1704  void MainForm::viewStatusbar ( bool bOn )  void MainForm::viewStatusbar ( bool bOn )
1705  {  {
1706      if (bOn)          if (bOn)
1707          statusBar()->show();                  statusBar()->show();
1708      else          else
1709          statusBar()->hide();                  statusBar()->hide();
1710  }  }
1711    
1712    
1713  // Show/hide the messages window logger.  // Show/hide the messages window logger.
1714  void MainForm::viewMessages ( bool bOn )  void MainForm::viewMessages ( bool bOn )
1715  {  {
1716      if (bOn)          if (bOn)
1717          m_pMessages->show();                  m_pMessages->show();
1718      else          else
1719          m_pMessages->hide();                  m_pMessages->hide();
1720  }  }
1721    
1722    
# Line 1513  void MainForm::viewDevices (void) Line 1761  void MainForm::viewDevices (void)
1761  // Show options dialog.  // Show options dialog.
1762  void MainForm::viewOptions (void)  void MainForm::viewOptions (void)
1763  {  {
1764      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1765          return;                  return;
1766    
1767      OptionsForm* pOptionsForm = new OptionsForm(this);          OptionsForm* pOptionsForm = new OptionsForm(this);
1768      if (pOptionsForm) {          if (pOptionsForm) {
1769          // Check out some initial nullities(tm)...                  // Check out some initial nullities(tm)...
1770          ChannelStrip* pChannelStrip = activeChannelStrip();                  ChannelStrip *pChannelStrip = activeChannelStrip();
1771          if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)
1772              m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();
1773          if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)
1774              m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
1775          // To track down deferred or immediate changes.                  // To track down deferred or immediate changes.
1776          QString sOldServerHost      = m_pOptions->sServerHost;                  QString sOldServerHost      = m_pOptions->sServerHost;
1777          int     iOldServerPort      = m_pOptions->iServerPort;                  int     iOldServerPort      = m_pOptions->iServerPort;
1778          int     iOldServerTimeout   = m_pOptions->iServerTimeout;                  int     iOldServerTimeout   = m_pOptions->iServerTimeout;
1779          bool    bOldServerStart     = m_pOptions->bServerStart;                  bool    bOldServerStart     = m_pOptions->bServerStart;
1780          QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;                  QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;
1781          QString sOldDisplayFont     = m_pOptions->sDisplayFont;                  bool    bOldMessagesLog     = m_pOptions->bMessagesLog;
1782          bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;                  QString sOldMessagesLogPath = m_pOptions->sMessagesLogPath;
1783          int     iOldMaxVolume       = m_pOptions->iMaxVolume;                  QString sOldDisplayFont     = m_pOptions->sDisplayFont;
1784          QString sOldMessagesFont    = m_pOptions->sMessagesFont;                  bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;
1785          bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;                  int     iOldMaxVolume       = m_pOptions->iMaxVolume;
1786          bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;                  QString sOldMessagesFont    = m_pOptions->sMessagesFont;
1787          int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;                  bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;
1788          int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;                  bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;
1789          bool    bOldCompletePath    = m_pOptions->bCompletePath;                  int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;
1790          bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;                  int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;
1791          int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;                  bool    bOldCompletePath    = m_pOptions->bCompletePath;
1792          // Load the current setup settings.                  bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;
1793          pOptionsForm->setup(m_pOptions);                  int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;
1794          // Show the setup dialog...                  int     iOldBaseFontSize    = m_pOptions->iBaseFontSize;
1795          if (pOptionsForm->exec()) {                  // Load the current setup settings.
1796              // Warn if something will be only effective on next run.                  pOptionsForm->setup(m_pOptions);
1797              if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||                  // Show the setup dialog...
1798                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||                  if (pOptionsForm->exec()) {
1799                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||                          // Warn if something will be only effective on next run.
1800                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1801                  QMessageBox::information(this,                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||
1802                                    ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||
1803                                    (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)     ||
1804                                    (iOldBaseFontSize   !=  m_pOptions->iBaseFontSize)) {
1805                                    QMessageBox::information(this,
1806                                          QSAMPLER_TITLE ": " + tr("Information"),                                          QSAMPLER_TITLE ": " + tr("Information"),
1807                      tr("Some settings may be only effective\n"                                          tr("Some settings may be only effective\n"
1808                         "next time you start this program."), tr("OK"));                                          "next time you start this program."));
1809                  updateMessagesCapture();                                  updateMessagesCapture();
1810              }                          }
1811              // Check wheather something immediate has changed.                          // Check wheather something immediate has changed.
1812              if (( bOldCompletePath && !m_pOptions->bCompletePath) ||                          if (( bOldMessagesLog && !m_pOptions->bMessagesLog) ||
1813                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||                                  (!bOldMessagesLog &&  m_pOptions->bMessagesLog) ||
1814                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))                                  (sOldMessagesLogPath != m_pOptions->sMessagesLogPath))
1815                  updateRecentFilesMenu();                                  m_pMessages->setLogging(
1816              if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||                                          m_pOptions->bMessagesLog, m_pOptions->sMessagesLogPath);
1817                  (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||
1818                  updateInstrumentNames();                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||
1819              if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
1820                  (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))                                  updateRecentFilesMenu();
1821                  updateDisplayEffect();                          if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||
1822              if (sOldDisplayFont != m_pOptions->sDisplayFont)                                  (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))
1823                  updateDisplayFont();                                  updateInstrumentNames();
1824              if (iOldMaxVolume != m_pOptions->iMaxVolume)                          if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||
1825                  updateMaxVolume();                                  (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))
1826              if (sOldMessagesFont != m_pOptions->sMessagesFont)                                  updateDisplayEffect();
1827                  updateMessagesFont();                          if (sOldDisplayFont != m_pOptions->sDisplayFont)
1828              if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||                                  updateDisplayFont();
1829                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||                          if (iOldMaxVolume != m_pOptions->iMaxVolume)
1830                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))                                  updateMaxVolume();
1831                  updateMessagesLimit();                          if (sOldMessagesFont != m_pOptions->sMessagesFont)
1832              // And now the main thing, whether we'll do client/server recycling?                                  updateMessagesFont();
1833              if ((sOldServerHost != m_pOptions->sServerHost) ||                          if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||
1834                  (iOldServerPort != m_pOptions->iServerPort) ||                                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||
1835                  (iOldServerTimeout != m_pOptions->iServerTimeout) ||                                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))
1836                  ( bOldServerStart && !m_pOptions->bServerStart) ||                                  updateMessagesLimit();
1837                  (!bOldServerStart &&  m_pOptions->bServerStart) ||                          // And now the main thing, whether we'll do client/server recycling?
1838                  (sOldServerCmdLine != m_pOptions->sServerCmdLine && m_pOptions->bServerStart))                          if ((sOldServerHost != m_pOptions->sServerHost) ||
1839                  fileRestart();                                  (iOldServerPort != m_pOptions->iServerPort) ||
1840          }                                  (iOldServerTimeout != m_pOptions->iServerTimeout) ||
1841          // Done.                                  ( bOldServerStart && !m_pOptions->bServerStart) ||
1842          delete pOptionsForm;                                  (!bOldServerStart &&  m_pOptions->bServerStart) ||
1843      }                                  (sOldServerCmdLine != m_pOptions->sServerCmdLine
1844                                    && m_pOptions->bServerStart))
1845                                    fileRestart();
1846                    }
1847                    // Done.
1848                    delete pOptionsForm;
1849            }
1850    
1851      // This makes it.          // This makes it.
1852      stabilizeForm();          stabilizeForm();
1853  }  }
1854    
1855    
# Line 1601  void MainForm::viewOptions (void) Line 1859  void MainForm::viewOptions (void)
1859  // Arrange channel strips.  // Arrange channel strips.
1860  void MainForm::channelsArrange (void)  void MainForm::channelsArrange (void)
1861  {  {
1862      // Full width vertical tiling          // Full width vertical tiling
1863      QWidgetList wlist = m_pWorkspace->windowList();          QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
1864      if (wlist.isEmpty())          if (wlist.isEmpty())
1865          return;                  return;
   
     m_pWorkspace->setUpdatesEnabled(false);  
     int y = 0;  
     for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {  
         ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);  
     /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {  
             // Prevent flicker...  
             pChannelStrip->hide();  
             pChannelStrip->showNormal();  
         }   */  
         pChannelStrip->adjustSize();  
         int iWidth  = m_pWorkspace->width();  
         if (iWidth < pChannelStrip->width())  
             iWidth = pChannelStrip->width();  
     //  int iHeight = pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();  
         int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();  
         pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);  
         y += iHeight;  
     }  
     m_pWorkspace->setUpdatesEnabled(true);  
1866    
1867      stabilizeForm();          m_pWorkspace->setUpdatesEnabled(false);
1868            int y = 0;
1869            for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
1870                    ChannelStrip *pChannelStrip = NULL;
1871                    QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
1872                    if (pMdiSubWindow)
1873                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
1874                    if (pChannelStrip) {
1875                    /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {
1876                                    // Prevent flicker...
1877                                    pChannelStrip->hide();
1878                                    pChannelStrip->showNormal();
1879                            }   */
1880                            pChannelStrip->adjustSize();
1881                            int iWidth  = m_pWorkspace->width();
1882                            if (iWidth < pChannelStrip->width())
1883                                    iWidth = pChannelStrip->width();
1884                    //  int iHeight = pChannelStrip->height()
1885                    //              + pChannelStrip->parentWidget()->baseSize().height();
1886                            int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();
1887                            pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);
1888                            y += iHeight;
1889                    }
1890            }
1891            m_pWorkspace->setUpdatesEnabled(true);
1892    
1893            stabilizeForm();
1894  }  }
1895    
1896    
1897  // Auto-arrange channel strips.  // Auto-arrange channel strips.
1898  void MainForm::channelsAutoArrange ( bool bOn )  void MainForm::channelsAutoArrange ( bool bOn )
1899  {  {
1900      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1901          return;                  return;
1902    
1903      // Toggle the auto-arrange flag.          // Toggle the auto-arrange flag.
1904      m_pOptions->bAutoArrange = bOn;          m_pOptions->bAutoArrange = bOn;
1905    
1906      // If on, update whole workspace...          // If on, update whole workspace...
1907      if (m_pOptions->bAutoArrange)          if (m_pOptions->bAutoArrange)
1908          channelsArrange();                  channelsArrange();
1909  }  }
1910    
1911    
# Line 1651  void MainForm::channelsAutoArrange ( boo Line 1915  void MainForm::channelsAutoArrange ( boo
1915  // Show information about the Qt toolkit.  // Show information about the Qt toolkit.
1916  void MainForm::helpAboutQt (void)  void MainForm::helpAboutQt (void)
1917  {  {
1918      QMessageBox::aboutQt(this);          QMessageBox::aboutQt(this);
1919  }  }
1920    
1921    
1922  // Show information about application program.  // Show information about application program.
1923  void MainForm::helpAbout (void)  void MainForm::helpAbout (void)
1924  {  {
1925      // Stuff the about box text...          // Stuff the about box text...
1926      QString sText = "<p>\n";          QString sText = "<p>\n";
1927      sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";          sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";
1928      sText += "<br />\n";          sText += "<br />\n";
1929      sText += tr("Version") + ": <b>" QSAMPLER_VERSION "</b><br />\n";          sText += tr("Version") + ": <b>" QSAMPLER_VERSION "</b><br />\n";
1930      sText += "<small>" + tr("Build") + ": " __DATE__ " " __TIME__ "</small><br />\n";          sText += "<small>" + tr("Build") + ": " __DATE__ " " __TIME__ "</small><br />\n";
1931  #ifdef CONFIG_DEBUG  #ifdef CONFIG_DEBUG
1932      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1933      sText += tr("Debugging option enabled.");          sText += tr("Debugging option enabled.");
1934      sText += "</font></small><br />";          sText += "</font></small><br />";
1935  #endif  #endif
1936  #ifndef CONFIG_LIBGIG  #ifndef CONFIG_LIBGIG
1937      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1938      sText += tr("GIG (libgig) file support disabled.");          sText += tr("GIG (libgig) file support disabled.");
1939      sText += "</font></small><br />";          sText += "</font></small><br />";
1940  #endif  #endif
1941  #ifndef CONFIG_INSTRUMENT_NAME  #ifndef CONFIG_INSTRUMENT_NAME
1942      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1943      sText += tr("LSCP (liblscp) instrument_name support disabled.");          sText += tr("LSCP (liblscp) instrument_name support disabled.");
1944      sText += "</font></small><br />";          sText += "</font></small><br />";
1945  #endif  #endif
1946  #ifndef CONFIG_MUTE_SOLO  #ifndef CONFIG_MUTE_SOLO
1947      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1948      sText += tr("Sampler channel Mute/Solo support disabled.");          sText += tr("Sampler channel Mute/Solo support disabled.");
1949      sText += "</font></small><br />";          sText += "</font></small><br />";
1950  #endif  #endif
1951  #ifndef CONFIG_AUDIO_ROUTING  #ifndef CONFIG_AUDIO_ROUTING
1952      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1953      sText += tr("LSCP (liblscp) audio_routing support disabled.");          sText += tr("LSCP (liblscp) audio_routing support disabled.");
1954      sText += "</font></small><br />";          sText += "</font></small><br />";
1955  #endif  #endif
1956  #ifndef CONFIG_FXSEND  #ifndef CONFIG_FXSEND
1957      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1958      sText += tr("Sampler channel Effect Sends support disabled.");          sText += tr("Sampler channel Effect Sends support disabled.");
1959      sText += "</font></small><br />";          sText += "</font></small><br />";
1960  #endif  #endif
1961  #ifndef CONFIG_VOLUME  #ifndef CONFIG_VOLUME
1962      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1963      sText += tr("Global volume support disabled.");          sText += tr("Global volume support disabled.");
1964      sText += "</font></small><br />";          sText += "</font></small><br />";
1965  #endif  #endif
1966  #ifndef CONFIG_MIDI_INSTRUMENT  #ifndef CONFIG_MIDI_INSTRUMENT
1967      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1968      sText += tr("MIDI instrument mapping support disabled.");          sText += tr("MIDI instrument mapping support disabled.");
1969      sText += "</font></small><br />";          sText += "</font></small><br />";
1970  #endif  #endif
1971  #ifndef CONFIG_EDIT_INSTRUMENT  #ifndef CONFIG_EDIT_INSTRUMENT
1972      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1973      sText += tr("Instrument editing support disabled.");          sText += tr("Instrument editing support disabled.");
1974      sText += "</font></small><br />";          sText += "</font></small><br />";
1975  #endif  #endif
1976      sText += "<br />\n";  #ifndef CONFIG_EVENT_CHANNEL_MIDI
1977      sText += tr("Using") + ": ";          sText += "<small><font color=\"red\">";
1978      sText += ::lscp_client_package();          sText += tr("Channel MIDI event support disabled.");
1979      sText += " ";          sText += "</font></small><br />";
1980      sText += ::lscp_client_version();  #endif
1981    #ifndef CONFIG_EVENT_DEVICE_MIDI
1982            sText += "<small><font color=\"red\">";
1983            sText += tr("Device MIDI event support disabled.");
1984            sText += "</font></small><br />";
1985    #endif
1986    #ifndef CONFIG_MAX_VOICES
1987            sText += "<small><font color=\"red\">";
1988            sText += tr("Runtime max. voices / disk streams support disabled.");
1989            sText += "</font></small><br />";
1990    #endif
1991            sText += "<br />\n";
1992            sText += tr("Using") + ": ";
1993            sText += ::lscp_client_package();
1994            sText += " ";
1995            sText += ::lscp_client_version();
1996  #ifdef CONFIG_LIBGIG  #ifdef CONFIG_LIBGIG
1997      sText += ", ";          sText += ", ";
1998      sText += gig::libraryName().c_str();          sText += gig::libraryName().c_str();
1999      sText += " ";          sText += " ";
2000      sText += gig::libraryVersion().c_str();          sText += gig::libraryVersion().c_str();
2001  #endif  #endif
2002      sText += "<br />\n";          sText += "<br />\n";
2003      sText += "<br />\n";          sText += "<br />\n";
2004      sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";          sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";
2005      sText += "<br />\n";          sText += "<br />\n";
2006      sText += "<small>";          sText += "<small>";
2007      sText += QSAMPLER_COPYRIGHT "<br />\n";          sText += QSAMPLER_COPYRIGHT "<br />\n";
2008      sText += QSAMPLER_COPYRIGHT2 "<br />\n";          sText += QSAMPLER_COPYRIGHT2 "<br />\n";
2009      sText += "<br />\n";          sText += "<br />\n";
2010      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";
2011      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.");
2012      sText += "</small>";          sText += "</small>";
2013      sText += "</p>\n";          sText += "</p>\n";
2014    
2015      QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);          QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);
2016  }  }
2017    
2018    
# Line 1742  void MainForm::helpAbout (void) Line 2021  void MainForm::helpAbout (void)
2021    
2022  void MainForm::stabilizeForm (void)  void MainForm::stabilizeForm (void)
2023  {  {
2024      // Update the main application caption...          // Update the main application caption...
2025      QString sSessionName = sessionName(m_sFilename);          QString sSessionName = sessionName(m_sFilename);
2026      if (m_iDirtyCount > 0)          if (m_iDirtyCount > 0)
2027          sSessionName += " *";                  sSessionName += " *";
2028      setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));
2029    
2030      // Update the main menu state...          // Update the main menu state...
2031      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
2032      bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);          bool bHasClient = (m_pOptions != NULL && m_pClient != NULL);
2033      bool bHasChannel = (bHasClient && pChannelStrip != NULL);          bool bHasChannel = (bHasClient && pChannelStrip != NULL);
2034      ui.fileNewAction->setEnabled(bHasClient);          bool bHasChannels = (bHasClient && m_pWorkspace->subWindowList().count() > 0);
2035      ui.fileOpenAction->setEnabled(bHasClient);          m_ui.fileNewAction->setEnabled(bHasClient);
2036      ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);          m_ui.fileOpenAction->setEnabled(bHasClient);
2037      ui.fileSaveAsAction->setEnabled(bHasClient);          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
2038      ui.fileResetAction->setEnabled(bHasClient);          m_ui.fileSaveAsAction->setEnabled(bHasClient);
2039      ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);          m_ui.fileResetAction->setEnabled(bHasClient);
2040      ui.editAddChannelAction->setEnabled(bHasClient);          m_ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);
2041      ui.editRemoveChannelAction->setEnabled(bHasChannel);          m_ui.editAddChannelAction->setEnabled(bHasClient);
2042      ui.editSetupChannelAction->setEnabled(bHasChannel);          m_ui.editRemoveChannelAction->setEnabled(bHasChannel);
2043            m_ui.editSetupChannelAction->setEnabled(bHasChannel);
2044  #ifdef CONFIG_EDIT_INSTRUMENT  #ifdef CONFIG_EDIT_INSTRUMENT
2045      ui.editEditChannelAction->setEnabled(bHasChannel);          m_ui.editEditChannelAction->setEnabled(bHasChannel);
2046  #else  #else
2047      ui.editEditChannelAction->setEnabled(false);          m_ui.editEditChannelAction->setEnabled(false);
2048  #endif  #endif
2049      ui.editResetChannelAction->setEnabled(bHasChannel);          m_ui.editResetChannelAction->setEnabled(bHasChannel);
2050      ui.editResetAllChannelsAction->setEnabled(bHasChannel);          m_ui.editResetAllChannelsAction->setEnabled(bHasChannels);
2051      ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());
2052  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
2053          ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm
2054                  && m_pInstrumentListForm->isVisible());                  && m_pInstrumentListForm->isVisible());
2055          ui.viewInstrumentsAction->setEnabled(bHasClient);          m_ui.viewInstrumentsAction->setEnabled(bHasClient);
2056  #else  #else
2057          ui.viewInstrumentsAction->setEnabled(false);          m_ui.viewInstrumentsAction->setEnabled(false);
2058  #endif  #endif
2059          ui.viewDevicesAction->setChecked(m_pDeviceForm          m_ui.viewDevicesAction->setChecked(m_pDeviceForm
2060                  && m_pDeviceForm->isVisible());                  && m_pDeviceForm->isVisible());
2061      ui.viewDevicesAction->setEnabled(bHasClient);          m_ui.viewDevicesAction->setEnabled(bHasClient);
2062      ui.channelsArrangeAction->setEnabled(bHasChannel);          m_ui.viewMidiDeviceStatusMenu->setEnabled(
2063                    DeviceStatusForm::getInstances().size() > 0);
2064            m_ui.channelsArrangeAction->setEnabled(bHasChannels);
2065    
2066  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2067          // Toolbar widgets are also affected...          // Toolbar widgets are also affected...
2068      m_pVolumeSlider->setEnabled(bHasClient);          m_pVolumeSlider->setEnabled(bHasClient);
2069      m_pVolumeSpinBox->setEnabled(bHasClient);          m_pVolumeSpinBox->setEnabled(bHasClient);
2070  #endif  #endif
2071    
2072      // Client/Server status...          // Client/Server status...
2073      if (bHasClient) {          if (bHasClient) {
2074          m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));                  m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));
2075          m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost + ":" + QString::number(m_pOptions->iServerPort));                  m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost
2076      } else {                          + ':' + QString::number(m_pOptions->iServerPort));
2077          m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();          } else {
2078          m_statusItem[QSAMPLER_STATUS_SERVER]->clear();                  m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();
2079      }                  m_statusItem[QSAMPLER_STATUS_SERVER]->clear();
2080      // Channel status...          }
2081      if (bHasChannel)          // Channel status...
2082          m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->windowTitle());          if (bHasChannel)
2083      else                  m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->windowTitle());
2084          m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();          else
2085      // Session status...                  m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();
2086      if (m_iDirtyCount > 0)          // Session status...
2087          m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));          if (m_iDirtyCount > 0)
2088      else                  m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));
2089          m_statusItem[QSAMPLER_STATUS_SESSION]->clear();          else
2090                    m_statusItem[QSAMPLER_STATUS_SESSION]->clear();
2091    
2092      // Recent files menu.          // Recent files menu.
2093          ui.fileOpenRecentMenu->setEnabled(m_pOptions->recentFiles.count() > 0);          m_ui.fileOpenRecentMenu->setEnabled(m_pOptions->recentFiles.count() > 0);
2094  }  }
2095    
2096    
# Line 1844  void MainForm::volumeChanged ( int iVolu Line 2127  void MainForm::volumeChanged ( int iVolu
2127    
2128    
2129  // Channel change receiver slot.  // Channel change receiver slot.
2130  void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)  void MainForm::channelStripChanged ( ChannelStrip *pChannelStrip )
2131  {  {
2132          // Add this strip to the changed list...          // Add this strip to the changed list...
2133          if (!m_changedStrips.contains(pChannelStrip)) {          if (!m_changedStrips.contains(pChannelStrip)) {
# Line 1852  void MainForm::channelStripChanged(Chann Line 2135  void MainForm::channelStripChanged(Chann
2135                  pChannelStrip->resetErrorCount();                  pChannelStrip->resetErrorCount();
2136          }          }
2137    
2138      // Just mark the dirty form.          // Just mark the dirty form.
2139      m_iDirtyCount++;          m_iDirtyCount++;
2140      // and update the form status...          // and update the form status...
2141      stabilizeForm();          stabilizeForm();
2142  }  }
2143    
2144    
# Line 1882  void MainForm::updateSession (void) Line 2165  void MainForm::updateSession (void)
2165          }          }
2166  #endif  #endif
2167    
2168            updateAllChannelStrips(false);
2169    
2170            // Do we auto-arrange?
2171            if (m_pOptions && m_pOptions->bAutoArrange)
2172                    channelsArrange();
2173    
2174            // Remember to refresh devices and instruments...
2175            if (m_pInstrumentListForm)
2176                    m_pInstrumentListForm->refreshInstruments();
2177            if (m_pDeviceForm)
2178                    m_pDeviceForm->refreshDevices();
2179    }
2180    
2181    
2182    void MainForm::updateAllChannelStrips ( bool bRemoveDeadStrips )
2183    {
2184          // Retrieve the current channel list.          // Retrieve the current channel list.
2185          int *piChannelIDs = ::lscp_list_channels(m_pClient);          int *piChannelIDs = ::lscp_list_channels(m_pClient);
2186          if (piChannelIDs == NULL) {          if (piChannelIDs == NULL) {
2187                  if (::lscp_client_get_errno(m_pClient)) {                  if (::lscp_client_get_errno(m_pClient)) {
2188                          appendMessagesClient("lscp_list_channels");                          appendMessagesClient("lscp_list_channels");
2189                          appendMessagesError(tr("Could not get current list of channels.\n\nSorry."));                          appendMessagesError(
2190                                    tr("Could not get current list of channels.\n\nSorry."));
2191                  }                  }
2192          } else {          } else {
2193                  // Try to (re)create each channel.                  // Try to (re)create each channel.
2194                  m_pWorkspace->setUpdatesEnabled(false);                  m_pWorkspace->setUpdatesEnabled(false);
2195                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; ++iChannel) {
2196                          // Check if theres already a channel strip for this one...                          // Check if theres already a channel strip for this one...
2197                          if (!channelStrip(piChannelIDs[iChannel]))                          if (!channelStrip(piChannelIDs[iChannel]))
2198                                  createChannelStrip(new qsamplerChannel(piChannelIDs[iChannel]));                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));
2199                    }
2200                    // Do we auto-arrange?
2201                    if (m_pOptions && m_pOptions->bAutoArrange)
2202                            channelsArrange();
2203                    // remove dead channel strips
2204                    if (bRemoveDeadStrips) {
2205                            QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
2206                            for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
2207                                    ChannelStrip *pChannelStrip = NULL;
2208                                    QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
2209                                    if (pMdiSubWindow)
2210                                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2211                                    if (pChannelStrip) {
2212                                            bool bExists = false;
2213                                            for (int j = 0; piChannelIDs[j] >= 0; ++j) {
2214                                                    if (!pChannelStrip->channel())
2215                                                            break;
2216                                                    if (piChannelIDs[j] == pChannelStrip->channel()->channelID()) {
2217                                                            // strip exists, don't touch it
2218                                                            bExists = true;
2219                                                            break;
2220                                                    }
2221                                            }
2222                                            if (!bExists)
2223                                                    destroyChannelStrip(pChannelStrip);
2224                                    }
2225                            }
2226                  }                  }
2227                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
2228          }          }
2229    
2230      // Do we auto-arrange?          stabilizeForm();
     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();  
2231  }  }
2232    
2233    
2234  // Update the recent files list and menu.  // Update the recent files list and menu.
2235  void MainForm::updateRecentFiles ( const QString& sFilename )  void MainForm::updateRecentFiles ( const QString& sFilename )
2236  {  {
2237      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2238          return;                  return;
2239    
2240      // Remove from list if already there (avoid duplicates)          // Remove from list if already there (avoid duplicates)
2241      int iIndex = m_pOptions->recentFiles.indexOf(sFilename);          int iIndex = m_pOptions->recentFiles.indexOf(sFilename);
2242      if (iIndex >= 0)          if (iIndex >= 0)
2243          m_pOptions->recentFiles.removeAt(iIndex);                  m_pOptions->recentFiles.removeAt(iIndex);
2244      // Put it to front...          // Put it to front...
2245      m_pOptions->recentFiles.push_front(sFilename);          m_pOptions->recentFiles.push_front(sFilename);
2246  }  }
2247    
2248    
# Line 1941  void MainForm::updateRecentFilesMenu (vo Line 2260  void MainForm::updateRecentFilesMenu (vo
2260          }          }
2261    
2262          // Rebuild the recent files menu...          // Rebuild the recent files menu...
2263          ui.fileOpenRecentMenu->clear();          m_ui.fileOpenRecentMenu->clear();
2264          for (int i = 0; i < iRecentFiles; i++) {          for (int i = 0; i < iRecentFiles; i++) {
2265                  const QString& sFilename = m_pOptions->recentFiles[i];                  const QString& sFilename = m_pOptions->recentFiles[i];
2266                  if (QFileInfo(sFilename).exists()) {                  if (QFileInfo(sFilename).exists()) {
2267                          QAction *pAction = ui.fileOpenRecentMenu->addAction(                          QAction *pAction = m_ui.fileOpenRecentMenu->addAction(
2268                                  QString("&%1 %2").arg(i + 1).arg(sessionName(sFilename)),                                  QString("&%1 %2").arg(i + 1).arg(sessionName(sFilename)),
2269                                  this, SLOT(fileOpenRecent()));                                  this, SLOT(fileOpenRecent()));
2270                          pAction->setData(i);                          pAction->setData(i);
# Line 1957  void MainForm::updateRecentFilesMenu (vo Line 2276  void MainForm::updateRecentFilesMenu (vo
2276  // Force update of the channels instrument names mode.  // Force update of the channels instrument names mode.
2277  void MainForm::updateInstrumentNames (void)  void MainForm::updateInstrumentNames (void)
2278  {  {
2279      // Full channel list update...          // Full channel list update...
2280      QWidgetList wlist = m_pWorkspace->windowList();          QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
2281      if (wlist.isEmpty())          if (wlist.isEmpty())
2282          return;                  return;
2283    
2284      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2285      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
2286          ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);                  ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);
2287          if (pChannelStrip)                  if (pChannelStrip)
2288              pChannelStrip->updateInstrumentName(true);                          pChannelStrip->updateInstrumentName(true);
2289      }          }
2290      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2291  }  }
2292    
2293    
2294  // Force update of the channels display font.  // Force update of the channels display font.
2295  void MainForm::updateDisplayFont (void)  void MainForm::updateDisplayFont (void)
2296  {  {
2297      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2298          return;                  return;
2299    
2300            // Check if display font is legal.
2301            if (m_pOptions->sDisplayFont.isEmpty())
2302                    return;
2303            // Realize it.
2304            QFont font;
2305            if (!font.fromString(m_pOptions->sDisplayFont))
2306                    return;
2307    
2308      // Check if display font is legal.          // Full channel list update...
2309      if (m_pOptions->sDisplayFont.isEmpty())          QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
2310          return;          if (wlist.isEmpty())
2311      // Realize it.                  return;
2312      QFont font;  
2313      if (!font.fromString(m_pOptions->sDisplayFont))          m_pWorkspace->setUpdatesEnabled(false);
2314          return;          for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
2315                    ChannelStrip *pChannelStrip = NULL;
2316      // Full channel list update...                  QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
2317      QWidgetList wlist = m_pWorkspace->windowList();                  if (pMdiSubWindow)
2318      if (wlist.isEmpty())                          pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2319          return;                  if (pChannelStrip)
2320                            pChannelStrip->setDisplayFont(font);
2321      m_pWorkspace->setUpdatesEnabled(false);          }
2322      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          m_pWorkspace->setUpdatesEnabled(true);
         ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);  
         if (pChannelStrip)  
             pChannelStrip->setDisplayFont(font);  
     }  
     m_pWorkspace->setUpdatesEnabled(true);  
2323  }  }
2324    
2325    
2326  // Update channel strips background effect.  // Update channel strips background effect.
2327  void MainForm::updateDisplayEffect (void)  void MainForm::updateDisplayEffect (void)
2328  {  {
2329      // Full channel list update...          // Full channel list update...
2330      QWidgetList wlist = m_pWorkspace->windowList();          QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
2331      if (wlist.isEmpty())          if (wlist.isEmpty())
2332          return;                  return;
2333    
2334      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2335      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
2336          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip *pChannelStrip = NULL;
2337                    QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
2338                    if (pMdiSubWindow)
2339                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2340                  if (pChannelStrip)                  if (pChannelStrip)
2341                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2342      }          }
2343      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2344  }  }
2345    
2346    
2347  // Force update of the channels maximum volume setting.  // Force update of the channels maximum volume setting.
2348  void MainForm::updateMaxVolume (void)  void MainForm::updateMaxVolume (void)
2349  {  {
2350      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2351          return;                  return;
2352    
2353  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2354          m_iVolumeChanging++;          m_iVolumeChanging++;
# Line 2032  void MainForm::updateMaxVolume (void) Line 2357  void MainForm::updateMaxVolume (void)
2357          m_iVolumeChanging--;          m_iVolumeChanging--;
2358  #endif  #endif
2359    
2360      // Full channel list update...          // Full channel list update...
2361      QWidgetList wlist = m_pWorkspace->windowList();          QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
2362      if (wlist.isEmpty())          if (wlist.isEmpty())
2363          return;                  return;
2364    
2365      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2366      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
2367          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip *pChannelStrip = NULL;
2368          if (pChannelStrip)                  QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
2369              pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                  if (pMdiSubWindow)
2370      }                          pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2371      m_pWorkspace->setUpdatesEnabled(true);                  if (pChannelStrip)
2372                            pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2373            }
2374            m_pWorkspace->setUpdatesEnabled(true);
2375  }  }
2376    
2377    
# Line 2053  void MainForm::updateMaxVolume (void) Line 2381  void MainForm::updateMaxVolume (void)
2381  // Messages output methods.  // Messages output methods.
2382  void MainForm::appendMessages( const QString& s )  void MainForm::appendMessages( const QString& s )
2383  {  {
2384      if (m_pMessages)          if (m_pMessages)
2385          m_pMessages->appendMessages(s);                  m_pMessages->appendMessages(s);
2386    
2387      statusBar()->showMessage(s, 3000);          statusBar()->showMessage(s, 3000);
2388  }  }
2389    
2390  void MainForm::appendMessagesColor( const QString& s, const QString& c )  void MainForm::appendMessagesColor( const QString& s, const QString& c )
2391  {  {
2392      if (m_pMessages)          if (m_pMessages)
2393          m_pMessages->appendMessagesColor(s, c);                  m_pMessages->appendMessagesColor(s, c);
2394    
2395      statusBar()->showMessage(s, 3000);          statusBar()->showMessage(s, 3000);
2396  }  }
2397    
2398  void MainForm::appendMessagesText( const QString& s )  void MainForm::appendMessagesText( const QString& s )
2399  {  {
2400      if (m_pMessages)          if (m_pMessages)
2401          m_pMessages->appendMessagesText(s);                  m_pMessages->appendMessagesText(s);
2402  }  }
2403    
2404  void MainForm::appendMessagesError( const QString& s )  void MainForm::appendMessagesError( const QString& sText )
2405  {  {
2406      if (m_pMessages)          if (m_pMessages)
2407          m_pMessages->show();                  m_pMessages->show();
2408    
2409      appendMessagesColor(s.simplified(), "#ff0000");          appendMessagesColor(sText.simplified(), "#ff0000");
2410    
2411          // Make it look responsive...:)          // Make it look responsive...:)
2412          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2413    
2414      QMessageBox::critical(this,          if (m_pOptions && m_pOptions->bConfirmError) {
2415                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));                  const QString& sTitle = QSAMPLER_TITLE ": " + tr("Error");
2416            #if 0
2417                    QMessageBox::critical(this, sTitle, sText, QMessageBox::Cancel);
2418            #else
2419                    QMessageBox mbox(this);
2420                    mbox.setIcon(QMessageBox::Critical);
2421                    mbox.setWindowTitle(sTitle);
2422                    mbox.setText(sText);
2423                    mbox.setStandardButtons(QMessageBox::Cancel);
2424                    QCheckBox cbox(tr("Don't show this again"));
2425                    cbox.setChecked(false);
2426                    cbox.blockSignals(true);
2427                    mbox.addButton(&cbox, QMessageBox::ActionRole);
2428                    if (mbox.exec() && cbox.isChecked())
2429                            m_pOptions->bConfirmError = false;
2430            #endif
2431            }
2432  }  }
2433    
2434    
2435  // This is a special message format, just for client results.  // This is a special message format, just for client results.
2436  void MainForm::appendMessagesClient( const QString& s )  void MainForm::appendMessagesClient( const QString& s )
2437  {  {
2438      if (m_pClient == NULL)          if (m_pClient == NULL)
2439          return;                  return;
2440    
2441      appendMessagesColor(s + QString(": %1 (errno=%2)")          appendMessagesColor(s + QString(": %1 (errno=%2)")
2442          .arg(::lscp_client_get_result(m_pClient))                  .arg(::lscp_client_get_result(m_pClient))
2443          .arg(::lscp_client_get_errno(m_pClient)), "#996666");                  .arg(::lscp_client_get_errno(m_pClient)), "#996666");
2444    
2445          // Make it look responsive...:)          // Make it look responsive...:)
2446          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
# Line 2106  void MainForm::appendMessagesClient( con Line 2450  void MainForm::appendMessagesClient( con
2450  // Force update of the messages font.  // Force update of the messages font.
2451  void MainForm::updateMessagesFont (void)  void MainForm::updateMessagesFont (void)
2452  {  {
2453      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2454          return;                  return;
2455    
2456      if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {          if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {
2457          QFont font;                  QFont font;
2458          if (font.fromString(m_pOptions->sMessagesFont))                  if (font.fromString(m_pOptions->sMessagesFont))
2459              m_pMessages->setMessagesFont(font);                          m_pMessages->setMessagesFont(font);
2460      }          }
2461  }  }
2462    
2463    
2464  // Update messages window line limit.  // Update messages window line limit.
2465  void MainForm::updateMessagesLimit (void)  void MainForm::updateMessagesLimit (void)
2466  {  {
2467      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2468          return;                  return;
2469    
2470      if (m_pMessages) {          if (m_pMessages) {
2471          if (m_pOptions->bMessagesLimit)                  if (m_pOptions->bMessagesLimit)
2472              m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);                          m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);
2473          else                  else
2474              m_pMessages->setMessagesLimit(-1);                          m_pMessages->setMessagesLimit(-1);
2475      }          }
2476  }  }
2477    
2478    
2479  // Enablement of the messages capture feature.  // Enablement of the messages capture feature.
2480  void MainForm::updateMessagesCapture (void)  void MainForm::updateMessagesCapture (void)
2481  {  {
2482      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2483          return;                  return;
2484    
2485      if (m_pMessages)          if (m_pMessages)
2486          m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);                  m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);
2487  }  }
2488    
2489    
# Line 2147  void MainForm::updateMessagesCapture (vo Line 2491  void MainForm::updateMessagesCapture (vo
2491  // qsamplerMainForm -- MDI channel strip management.  // qsamplerMainForm -- MDI channel strip management.
2492    
2493  // The channel strip creation executive.  // The channel strip creation executive.
2494  ChannelStrip* MainForm::createChannelStrip(qsamplerChannel* pChannel)  ChannelStrip *MainForm::createChannelStrip ( Channel *pChannel )
2495  {  {
2496      if (m_pClient == NULL || pChannel == NULL)          if (m_pClient == NULL || pChannel == NULL)
2497          return NULL;                  return NULL;
2498    
2499      // Prepare for auto-arrange?          // Add a new channel itema...
2500      ChannelStrip* pChannelStrip = NULL;          ChannelStrip *pChannelStrip = new ChannelStrip();
2501      int y = 0;          if (pChannelStrip == NULL)
2502      if (m_pOptions && m_pOptions->bAutoArrange) {                  return NULL;
         QWidgetList wlist = m_pWorkspace->windowList();  
         for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {  
                         pChannelStrip = static_cast<ChannelStrip *> (wlist.at(iChannel));  
                         if (pChannelStrip) {  
                         //  y += pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();  
                                 y += pChannelStrip->parentWidget()->frameGeometry().height();  
                         }  
         }  
     }  
2503    
2504      // Add a new channel itema...          // Set some initial channel strip options...
2505      pChannelStrip = new ChannelStrip();          if (m_pOptions) {
2506      if (pChannelStrip == NULL)                  // Background display effect...
2507          return NULL;                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2508                    // We'll need a display font.
2509                    QFont font;
2510                    if (font.fromString(m_pOptions->sDisplayFont))
2511                            pChannelStrip->setDisplayFont(font);
2512                    // Maximum allowed volume setting.
2513                    pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2514            }
2515    
2516            // Add it to workspace...
2517            m_pWorkspace->addSubWindow(pChannelStrip,
2518                    Qt::SubWindow | Qt::FramelessWindowHint);
2519    
2520          m_pWorkspace->addWindow(pChannelStrip, Qt::FramelessWindowHint);          // Actual channel strip setup...
2521            pChannelStrip->setup(pChannel);
2522    
     // Actual channel strip setup...  
     pChannelStrip->setup(pChannel);  
2523          QObject::connect(pChannelStrip,          QObject::connect(pChannelStrip,
2524                  SIGNAL(channelChanged(ChannelStrip*)),                  SIGNAL(channelChanged(ChannelStrip *)),
2525                  SLOT(channelStripChanged(ChannelStrip*)));                  SLOT(channelStripChanged(ChannelStrip *)));
2526      // Set some initial aesthetic options...  
2527      if (m_pOptions) {          // Now we show up us to the world.
2528          // 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);  
     }  
2529    
2530          // This is pretty new, so we'll watch for it closely.          // This is pretty new, so we'll watch for it closely.
2531          channelStripChanged(pChannelStrip);          channelStripChanged(pChannelStrip);
2532    
2533      // Return our successful reference...          // Return our successful reference...
2534      return pChannelStrip;          return pChannelStrip;
2535    }
2536    
2537    
2538    void MainForm::destroyChannelStrip ( ChannelStrip *pChannelStrip )
2539    {
2540            QMdiSubWindow *pMdiSubWindow
2541                    = static_cast<QMdiSubWindow *> (pChannelStrip->parentWidget());
2542            if (pMdiSubWindow == NULL)
2543                    return;
2544    
2545            // Just delete the channel strip.
2546            delete pChannelStrip;
2547            delete pMdiSubWindow;
2548    
2549            // Do we auto-arrange?
2550            if (m_pOptions && m_pOptions->bAutoArrange)
2551                    channelsArrange();
2552    
2553            stabilizeForm();
2554  }  }
2555    
2556    
2557  // Retrieve the active channel strip.  // Retrieve the active channel strip.
2558  ChannelStrip* MainForm::activeChannelStrip (void)  ChannelStrip *MainForm::activeChannelStrip (void)
2559  {  {
2560      return static_cast<ChannelStrip *> (m_pWorkspace->activeWindow());          QMdiSubWindow *pMdiSubWindow = m_pWorkspace->activeSubWindow();
2561            if (pMdiSubWindow)
2562                    return static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2563            else
2564                    return NULL;
2565  }  }
2566    
2567    
2568  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
2569  ChannelStrip* MainForm::channelStripAt ( int iChannel )  ChannelStrip *MainForm::channelStripAt ( int iChannel )
2570  {  {
2571      QWidgetList wlist = m_pWorkspace->windowList();          if (!m_pWorkspace) return NULL;
2572      if (wlist.isEmpty())  
2573          return NULL;          QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
2574            if (wlist.isEmpty())
2575                    return NULL;
2576    
2577            if (iChannel < 0 || iChannel >= wlist.size())
2578                    return NULL;
2579    
2580      return static_cast<ChannelStrip *> (wlist.at(iChannel));          QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
2581            if (pMdiSubWindow)
2582                    return static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2583            else
2584                    return NULL;
2585  }  }
2586    
2587    
2588  // Retrieve a channel strip by sampler channel id.  // Retrieve a channel strip by sampler channel id.
2589  ChannelStrip* MainForm::channelStrip ( int iChannelID )  ChannelStrip *MainForm::channelStrip ( int iChannelID )
2590  {  {
2591          QWidgetList wlist = m_pWorkspace->windowList();          QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
2592          if (wlist.isEmpty())          if (wlist.isEmpty())
2593                  return NULL;                  return NULL;
2594    
2595          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
2596                  ChannelStrip* pChannelStrip                  ChannelStrip *pChannelStrip = NULL;
2597                          = static_cast<ChannelStrip*> (wlist.at(iChannel));                  QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
2598                    if (pMdiSubWindow)
2599                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2600                  if (pChannelStrip) {                  if (pChannelStrip) {
2601                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
2602                          if (pChannel && pChannel->channelID() == iChannelID)                          if (pChannel && pChannel->channelID() == iChannelID)
2603                                  return pChannelStrip;                                  return pChannelStrip;
2604                  }                  }
# Line 2250  ChannelStrip* MainForm::channelStrip ( i Line 2612  ChannelStrip* MainForm::channelStrip ( i
2612  // Construct the windows menu.  // Construct the windows menu.
2613  void MainForm::channelsMenuAboutToShow (void)  void MainForm::channelsMenuAboutToShow (void)
2614  {  {
2615      ui.channelsMenu->clear();          m_ui.channelsMenu->clear();
2616          ui.channelsMenu->addAction(ui.channelsArrangeAction);          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);
2617          ui.channelsMenu->addAction(ui.channelsAutoArrangeAction);          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);
2618    
2619      QWidgetList wlist = m_pWorkspace->windowList();          QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
2620      if (!wlist.isEmpty()) {          if (!wlist.isEmpty()) {
2621                  ui.channelsMenu->addSeparator();                  m_ui.channelsMenu->addSeparator();
2622          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
2623                          ChannelStrip* pChannelStrip                          ChannelStrip *pChannelStrip = NULL;
2624                                  = static_cast<ChannelStrip*> (wlist.at(iChannel));                          QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
2625                            if (pMdiSubWindow)
2626                                    pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2627                          if (pChannelStrip) {                          if (pChannelStrip) {
2628                                  QAction *pAction = ui.channelsMenu->addAction(                                  QAction *pAction = m_ui.channelsMenu->addAction(
2629                                          pChannelStrip->windowTitle(), this, SLOT(channelsMenuActivated()));                                          pChannelStrip->windowTitle(),
2630                                            this, SLOT(channelsMenuActivated()));
2631                                  pAction->setCheckable(true);                                  pAction->setCheckable(true);
2632                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);
2633                                  pAction->setData(iChannel);                                  pAction->setData(iChannel);
2634                          }                          }
2635          }                  }
2636      }          }
2637  }  }
2638    
2639    
# Line 2280  void MainForm::channelsMenuActivated (vo Line 2645  void MainForm::channelsMenuActivated (vo
2645          if (pAction == NULL)          if (pAction == NULL)
2646                  return;                  return;
2647    
2648          ChannelStrip* pChannelStrip = channelStripAt(pAction->data().toInt());          ChannelStrip *pChannelStrip = channelStripAt(pAction->data().toInt());
2649          if (pChannelStrip) {          if (pChannelStrip) {
2650                  pChannelStrip->showNormal();                  pChannelStrip->showNormal();
2651                  pChannelStrip->setFocus();                  pChannelStrip->setFocus();
# Line 2294  void MainForm::channelsMenuActivated (vo Line 2659  void MainForm::channelsMenuActivated (vo
2659  // Set the pseudo-timer delay schedule.  // Set the pseudo-timer delay schedule.
2660  void MainForm::startSchedule ( int iStartDelay )  void MainForm::startSchedule ( int iStartDelay )
2661  {  {
2662      m_iStartDelay  = 1 + (iStartDelay * 1000);          m_iStartDelay  = 1 + (iStartDelay * 1000);
2663      m_iTimerDelay  = 0;          m_iTimerDelay  = 0;
2664  }  }
2665    
2666  // Suspend the pseudo-timer delay schedule.  // Suspend the pseudo-timer delay schedule.
2667  void MainForm::stopSchedule (void)  void MainForm::stopSchedule (void)
2668  {  {
2669      m_iStartDelay  = 0;          m_iStartDelay  = 0;
2670      m_iTimerDelay  = 0;          m_iTimerDelay  = 0;
2671  }  }
2672    
2673  // Timer slot funtion.  // Timer slot funtion.
2674  void MainForm::timerSlot (void)  void MainForm::timerSlot (void)
2675  {  {
2676      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2677          return;                  return;
2678    
2679      // Is it the first shot on server start after a few delay?          // Is it the first shot on server start after a few delay?
2680      if (m_iTimerDelay < m_iStartDelay) {          if (m_iTimerDelay < m_iStartDelay) {
2681          m_iTimerDelay += QSAMPLER_TIMER_MSECS;                  m_iTimerDelay += QSAMPLER_TIMER_MSECS;
2682          if (m_iTimerDelay >= m_iStartDelay) {                  if (m_iTimerDelay >= m_iStartDelay) {
2683              // If we cannot start it now, maybe a lil'mo'later ;)                          // If we cannot start it now, maybe a lil'mo'later ;)
2684              if (!startClient()) {                          if (!startClient()) {
2685                  m_iStartDelay += m_iTimerDelay;                                  m_iStartDelay += m_iTimerDelay;
2686                  m_iTimerDelay  = 0;                                  m_iTimerDelay  = 0;
2687              }                          }
2688          }                  }
2689      }          }
2690    
2691          if (m_pClient) {          if (m_pClient) {
2692                  // Update the channel information for each pending strip...                  // Update the channel information for each pending strip...
# Line 2341  void MainForm::timerSlot (void) Line 2706  void MainForm::timerSlot (void)
2706                          if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime)  {                          if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime)  {
2707                                  m_iTimerSlot = 0;                                  m_iTimerSlot = 0;
2708                                  // Update the channel stream usage for each strip...                                  // Update the channel stream usage for each strip...
2709                                  QWidgetList wlist = m_pWorkspace->windowList();                                  QList<QMdiSubWindow *> wlist = m_pWorkspace->subWindowList();
2710                                  for (int iChannel = 0;                                  for (int iChannel = 0; iChannel < (int) wlist.count(); ++iChannel) {
2711                                                  iChannel < (int) wlist.count(); iChannel++) {                                          ChannelStrip *pChannelStrip = NULL;
2712                                          ChannelStrip* pChannelStrip                                          QMdiSubWindow *pMdiSubWindow = wlist.at(iChannel);
2713                                                  = (ChannelStrip*) wlist.at(iChannel);                                          if (pMdiSubWindow)
2714                                                    pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2715                                          if (pChannelStrip && pChannelStrip->isVisible())                                          if (pChannelStrip && pChannelStrip->isVisible())
2716                                                  pChannelStrip->updateChannelUsage();                                                  pChannelStrip->updateChannelUsage();
2717                                  }                                  }
# Line 2353  void MainForm::timerSlot (void) Line 2719  void MainForm::timerSlot (void)
2719                  }                  }
2720          }          }
2721    
2722      // Register the next timer slot.          // Register the next timer slot.
2723      QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));          QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
2724  }  }
2725    
2726    
# Line 2364  void MainForm::timerSlot (void) Line 2730  void MainForm::timerSlot (void)
2730  // Start linuxsampler server...  // Start linuxsampler server...
2731  void MainForm::startServer (void)  void MainForm::startServer (void)
2732  {  {
2733      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2734          return;                  return;
2735    
2736      // Aren't already a client, are we?          // Aren't already a client, are we?
2737      if (!m_pOptions->bServerStart || m_pClient)          if (!m_pOptions->bServerStart || m_pClient)
2738          return;                  return;
2739    
2740      // Is the server process instance still here?          // Is the server process instance still here?
2741      if (m_pServer) {          if (m_pServer) {
2742          switch (QMessageBox::warning(this,                  if (QMessageBox::warning(this,
2743                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
2744              tr("Could not start the LinuxSampler server.\n\n"                          tr("Could not start the LinuxSampler server.\n\n"
2745                 "Maybe it ss already started."),                          "Maybe it is already started."),
2746              tr("Stop"), tr("Kill"), tr("Cancel"))) {                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
2747            case 0:                          m_pServer->terminate();
2748              m_pServer->terminate();                          m_pServer->kill();
2749              break;                  }
2750            case 1:                  return;
2751              m_pServer->kill();          }
2752              break;  
2753          }          // Reset our timer counters...
2754          return;          stopSchedule();
2755      }  
2756            // Verify we have something to start with...
2757      // Reset our timer counters...          if (m_pOptions->sServerCmdLine.isEmpty())
2758      stopSchedule();                  return;
2759    
2760      // OK. Let's build the startup process...          // OK. Let's build the startup process...
2761      m_pServer = new QProcess(this);          m_pServer = new QProcess();
2762            bForceServerStop = true;
2763      // Setup stdout/stderr capture...  
2764          //      if (m_pOptions->bStdoutCapture) {          // Setup stdout/stderr capture...
2765                  //m_pServer->setProcessChannelMode(  //      if (m_pOptions->bStdoutCapture) {
2766                  //      QProcess::StandardOutput);                  m_pServer->setProcessChannelMode(QProcess::ForwardedChannels);
2767                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2768                          SIGNAL(readyReadStandardOutput()),                          SIGNAL(readyReadStandardOutput()),
2769                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
2770                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2771                          SIGNAL(readyReadStandardError()),                          SIGNAL(readyReadStandardError()),
2772                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
2773          //      }  //      }
2774    
2775          // The unforgiveable signal communication...          // The unforgiveable signal communication...
2776          QObject::connect(m_pServer,          QObject::connect(m_pServer,
2777                  SIGNAL(finished(int,QProcess::ExitStatus)),                  SIGNAL(finished(int, QProcess::ExitStatus)),
2778                  SLOT(processServerExit()));                  SLOT(processServerExit()));
2779    
2780      // Build process arguments...          // Build process arguments...
2781      QStringList serverCmdLine = m_pOptions->sServerCmdLine.split(' ');          QStringList args = m_pOptions->sServerCmdLine.split(' ');
2782            QString sCommand = args[0];
2783      appendMessages(tr("Server is starting..."));          args.removeAt(0);
2784      appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");  
2785            appendMessages(tr("Server is starting..."));
2786            appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");
2787    
2788      const QString prog = (serverCmdLine.size() > 0) ? serverCmdLine[0] : QString();          // Go linuxsampler, go...
2789      const QStringList args = serverCmdLine.mid(1);          m_pServer->start(sCommand, args);
2790            if (!m_pServer->waitForStarted()) {
2791      // Go jack, go...                  appendMessagesError(tr("Could not start server.\n\nSorry."));
2792      m_pServer->start(prog, args);                  processServerExit();
2793      if (!m_pServer->waitForStarted()) {                  return;
2794          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()));  
2795    
2796      // Reset (yet again) the timer counters,          // Show startup results...
2797      // but this time is deferred as the user opted.          appendMessages(
2798      startSchedule(m_pOptions->iStartDelay);                  tr("Server was started with PID=%1.").arg((long) m_pServer->pid()));
2799      stabilizeForm();  
2800            // Reset (yet again) the timer counters,
2801            // but this time is deferred as the user opted.
2802            startSchedule(m_pOptions->iStartDelay);
2803            stabilizeForm();
2804  }  }
2805    
2806    
2807  // Stop linuxsampler server...  // Stop linuxsampler server...
2808  void MainForm::stopServer (void)  void MainForm::stopServer (bool bInteractive)
2809  {  {
2810      // Stop client code.          // Stop client code.
2811      stopClient();          stopClient();
2812    
2813            if (m_pServer && bInteractive) {
2814                    if (QMessageBox::question(this,
2815                            QSAMPLER_TITLE ": " + tr("The backend's fate ..."),
2816                            tr("You have the option to keep the sampler backend (LinuxSampler)\n"
2817                            "running in the background. The sampler would continue to work\n"
2818                            "according to your current sampler session and you could alter the\n"
2819                            "sampler session at any time by relaunching QSampler.\n\n"
2820                            "Do you want LinuxSampler to stop?"),
2821                            QMessageBox::Yes | QMessageBox::No,
2822                            QMessageBox::Yes) == QMessageBox::No)
2823                    {
2824                            bForceServerStop = false;
2825                    }
2826            }
2827    
2828      // And try to stop server.          // And try to stop server.
2829      if (m_pServer) {          if (m_pServer && bForceServerStop) {
2830          appendMessages(tr("Server is stopping..."));                  appendMessages(tr("Server is stopping..."));
2831          if (m_pServer->state() == QProcess::Running)                  if (m_pServer->state() == QProcess::Running) {
2832              m_pServer->terminate();                  #if defined(WIN32)
2833       }                          // Try harder...
2834                            m_pServer->kill();
2835      // Give it some time to terminate gracefully and stabilize...                  #else
2836      QTime t;                          // Try softly...
2837      t.start();                          m_pServer->terminate();
2838      while (t.elapsed() < QSAMPLER_TIMER_MSECS)                  #endif
2839          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  }
2840            }       // Do final processing anyway.
2841            else processServerExit();
2842    
2843       // Do final processing anyway.          // Give it some time to terminate gracefully and stabilize...
2844       processServerExit();          QTime t;
2845            t.start();
2846            while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2847                    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2848  }  }
2849    
2850    
2851  // Stdout handler...  // Stdout handler...
2852  void MainForm::readServerStdout (void)  void MainForm::readServerStdout (void)
2853  {  {
2854      if (m_pMessages)          if (m_pMessages)
2855          m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());                  m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());
2856  }  }
2857    
2858    
2859  // Linuxsampler server cleanup.  // Linuxsampler server cleanup.
2860  void MainForm::processServerExit (void)  void MainForm::processServerExit (void)
2861  {  {
2862      // Force client code cleanup.          // Force client code cleanup.
2863      stopClient();          stopClient();
2864    
2865      // Flush anything that maybe pending...          // Flush anything that maybe pending...
2866      if (m_pMessages)          if (m_pMessages)
2867          m_pMessages->flushStdoutBuffer();                  m_pMessages->flushStdoutBuffer();
2868    
2869      if (m_pServer) {          if (m_pServer && bForceServerStop) {
2870          // Force final server shutdown...                  if (m_pServer->state() != QProcess::NotRunning) {
2871          appendMessages(tr("Server was stopped with exit status %1.").arg(m_pServer->exitStatus()));                          appendMessages(tr("Server is being forced..."));
2872          m_pServer->terminate();                          // Force final server shutdown...
2873          if (!m_pServer->waitForFinished(2000))                          m_pServer->kill();
2874              m_pServer->kill();                          // Give it some time to terminate gracefully and stabilize...
2875          // Destroy it.                          QTime t;
2876          delete m_pServer;                          t.start();
2877          m_pServer = NULL;                          while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2878      }                                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2879                    }
2880                    // Force final server shutdown...
2881                    appendMessages(
2882                            tr("Server was stopped with exit status %1.")
2883                            .arg(m_pServer->exitStatus()));
2884                    delete m_pServer;
2885                    m_pServer = NULL;
2886            }
2887    
2888      // Again, make status visible stable.          // Again, make status visible stable.
2889      stabilizeForm();          stabilizeForm();
2890  }  }
2891    
2892    
# Line 2501  void MainForm::processServerExit (void) Line 2894  void MainForm::processServerExit (void)
2894  // qsamplerMainForm -- Client stuff.  // qsamplerMainForm -- Client stuff.
2895    
2896  // The LSCP client callback procedure.  // The LSCP client callback procedure.
2897  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*/,
2898            lscp_event_t event, const char *pchData, int cchData, void *pvData )
2899  {  {
2900      MainForm* pMainForm = (MainForm *) pvData;          MainForm* pMainForm = (MainForm *) pvData;
2901      if (pMainForm == NULL)          if (pMainForm == NULL)
2902          return LSCP_FAILED;                  return LSCP_FAILED;
2903    
2904      // ATTN: DO NOT EVER call any GUI code here,          // ATTN: DO NOT EVER call any GUI code here,
2905      // as this is run under some other thread context.          // as this is run under some other thread context.
2906      // A custom event must be posted here...          // A custom event must be posted here...
2907      QApplication::postEvent(pMainForm, new qsamplerCustomEvent(event, pchData, cchData));          QApplication::postEvent(pMainForm,
2908                    new LscpEvent(event, pchData, cchData));
2909    
2910      return LSCP_OK;          return LSCP_OK;
2911  }  }
2912    
2913    
2914  // Start our almighty client...  // Start our almighty client...
2915  bool MainForm::startClient (void)  bool MainForm::startClient (void)
2916  {  {
2917      // Have it a setup?          // Have it a setup?
2918      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2919          return false;                  return false;
2920    
2921      // Aren't we already started, are we?          // Aren't we already started, are we?
2922      if (m_pClient)          if (m_pClient)
2923          return true;                  return true;
2924    
2925      // Log prepare here.          // Log prepare here.
2926      appendMessages(tr("Client connecting..."));          appendMessages(tr("Client connecting..."));
2927    
2928      // Create the client handle...          // Create the client handle...
2929          m_pClient = ::lscp_client_create(          m_pClient = ::lscp_client_create(
2930                  m_pOptions->sServerHost.toUtf8().constData(),                  m_pOptions->sServerHost.toUtf8().constData(),
2931                  m_pOptions->iServerPort, qsampler_client_callback, this);                  m_pOptions->iServerPort, qsampler_client_callback, this);
2932      if (m_pClient == NULL) {          if (m_pClient == NULL) {
2933          // Is this the first try?                  // Is this the first try?
2934          // maybe we need to start a local server...                  // maybe we need to start a local server...
2935          if ((m_pServer && m_pServer->state() == QProcess::Running) || !m_pOptions->bServerStart)                  if ((m_pServer && m_pServer->state() == QProcess::Running)
2936              appendMessagesError(tr("Could not connect to server as client.\n\nSorry."));                          || !m_pOptions->bServerStart) {
2937          else                          appendMessagesError(
2938              startServer();                                  tr("Could not connect to server as client.\n\nSorry."));
2939          // This is always a failure.                  } else {
2940          stabilizeForm();                          startServer();
2941          return false;                  }
2942      }                  // This is always a failure.
2943      // Just set receive timeout value, blindly.                  stabilizeForm();
2944      ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);                  return false;
2945      appendMessages(tr("Client receive timeout is set to %1 msec.").arg(::lscp_client_get_timeout(m_pClient)));          }
2946            // Just set receive timeout value, blindly.
2947            ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);
2948            appendMessages(
2949                    tr("Client receive timeout is set to %1 msec.")
2950                    .arg(::lscp_client_get_timeout(m_pClient)));
2951    
2952          // Subscribe to channel info change notifications...          // Subscribe to channel info change notifications...
2953            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT) != LSCP_OK)
2954                    appendMessagesClient("lscp_client_subscribe(CHANNEL_COUNT)");
2955          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)
2956                  appendMessagesClient("lscp_client_subscribe");                  appendMessagesClient("lscp_client_subscribe(CHANNEL_INFO)");
2957    
2958            DeviceStatusForm::onDevicesChanged(); // initialize
2959            updateViewMidiDeviceStatusMenu();
2960            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT) != LSCP_OK)
2961                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_COUNT)");
2962            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO) != LSCP_OK)
2963                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_INFO)");
2964            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT) != LSCP_OK)
2965                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_COUNT)");
2966            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO) != LSCP_OK)
2967                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_INFO)");
2968    
2969    #if CONFIG_EVENT_CHANNEL_MIDI
2970            // Subscribe to channel MIDI data notifications...
2971            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI) != LSCP_OK)
2972                    appendMessagesClient("lscp_client_subscribe(CHANNEL_MIDI)");
2973    #endif
2974    
2975    #if CONFIG_EVENT_DEVICE_MIDI
2976            // Subscribe to channel MIDI data notifications...
2977            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI) != LSCP_OK)
2978                    appendMessagesClient("lscp_client_subscribe(DEVICE_MIDI)");
2979    #endif
2980    
2981      // We may stop scheduling around.          // We may stop scheduling around.
2982      stopSchedule();          stopSchedule();
2983    
2984      // We'll accept drops from now on...          // We'll accept drops from now on...
2985      setAcceptDrops(true);          setAcceptDrops(true);
2986    
2987      // Log success here.          // Log success here.
2988      appendMessages(tr("Client connected."));          appendMessages(tr("Client connected."));
2989    
2990          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
2991          // if visible, that we're ready...          // if visible, that we're ready...
2992          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
2993              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
2994          if (m_pDeviceForm)          if (m_pDeviceForm)
2995              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
2996    
2997            // Is any session pending to be loaded?
2998            if (!m_pOptions->sSessionFile.isEmpty()) {
2999                    // Just load the prabably startup session...
3000                    if (loadSessionFile(m_pOptions->sSessionFile)) {
3001                            m_pOptions->sSessionFile = QString::null;
3002                            return true;
3003                    }
3004            }
3005    
3006      // Is any session pending to be loaded?          // send the current / loaded fine tuning settings to the sampler
3007      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;  
         }  
     }  
3008    
3009      // Make a new session          // Make a new session
3010      return newSession();          return newSession();
3011  }  }
3012    
3013    
3014  // Stop client...  // Stop client...
3015  void MainForm::stopClient (void)  void MainForm::stopClient (void)
3016  {  {
3017      if (m_pClient == NULL)          if (m_pClient == NULL)
3018          return;                  return;
   
     // Log prepare here.  
     appendMessages(tr("Client disconnecting..."));  
3019    
3020      // Clear timer counters...          // Log prepare here.
3021      stopSchedule();          appendMessages(tr("Client disconnecting..."));
3022    
3023      // We'll reject drops from now on...          // Clear timer counters...
3024      setAcceptDrops(false);          stopSchedule();
3025    
3026      // Force any channel strips around, but          // We'll reject drops from now on...
3027      // but avoid removing the corresponding          setAcceptDrops(false);
     // channels from the back-end server.  
     m_iDirtyCount = 0;  
     closeSession(false);  
3028    
3029      // Close us as a client...          // Force any channel strips around, but
3030            // but avoid removing the corresponding
3031            // channels from the back-end server.
3032            m_iDirtyCount = 0;
3033            closeSession(false);
3034    
3035            // Close us as a client...
3036    #if CONFIG_EVENT_DEVICE_MIDI
3037            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI);
3038    #endif
3039    #if CONFIG_EVENT_CHANNEL_MIDI
3040            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI);
3041    #endif
3042            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
3043            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
3044            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
3045            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
3046          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
3047      ::lscp_client_destroy(m_pClient);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT);
3048      m_pClient = NULL;          ::lscp_client_destroy(m_pClient);
3049            m_pClient = NULL;
3050    
3051          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
3052          // if visible, that we're running out...          // if visible, that we're running out...
3053          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
3054              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
3055          if (m_pDeviceForm)          if (m_pDeviceForm)
3056              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
3057    
3058      // Log final here.          // Log final here.
3059      appendMessages(tr("Client disconnected."));          appendMessages(tr("Client disconnected."));
3060    
3061      // Make visible status.          // Make visible status.
3062      stabilizeForm();          stabilizeForm();
3063  }  }
3064    
3065    
3066    // Channel strip activation/selection.
3067    void MainForm::activateStrip ( QMdiSubWindow *pMdiSubWindow )
3068    {
3069            ChannelStrip *pChannelStrip = NULL;
3070            if (pMdiSubWindow)
3071                    pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
3072            if (pChannelStrip)
3073                    pChannelStrip->setSelected(true);
3074    
3075            stabilizeForm();
3076    }
3077    
3078    
3079    // Channel toolbar orientation change.
3080    void MainForm::channelsToolbarOrientation ( Qt::Orientation orientation )
3081    {
3082    #ifdef CONFIG_VOLUME
3083            m_pVolumeSlider->setOrientation(orientation);
3084            if (orientation == Qt::Horizontal) {
3085                    m_pVolumeSlider->setMinimumHeight(24);
3086                    m_pVolumeSlider->setMaximumHeight(32);
3087                    m_pVolumeSlider->setMinimumWidth(120);
3088                    m_pVolumeSlider->setMaximumWidth(640);
3089                    m_pVolumeSpinBox->setMaximumWidth(64);
3090                    m_pVolumeSpinBox->setButtonSymbols(QSpinBox::UpDownArrows);
3091            } else {
3092                    m_pVolumeSlider->setMinimumHeight(120);
3093                    m_pVolumeSlider->setMaximumHeight(480);
3094                    m_pVolumeSlider->setMinimumWidth(24);
3095                    m_pVolumeSlider->setMaximumWidth(32);
3096                    m_pVolumeSpinBox->setMaximumWidth(32);
3097                    m_pVolumeSpinBox->setButtonSymbols(QSpinBox::NoButtons);
3098            }
3099    #endif
3100    }
3101    
3102    
3103  } // namespace QSampler  } // namespace QSampler
3104    
3105    

Legend:
Removed from v.1507  
changed lines
  Added in v.2722

  ViewVC Help
Powered by ViewVC