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

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

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

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

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

  ViewVC Help
Powered by ViewVC