/[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 3358 by capela, Wed Oct 18 08:57:21 2017 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-2017, 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__) || defined(_WIN32) || 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__) || defined(_WIN32) || defined(WIN32)
328            WSAStartup(MAKEWORD(1, 1), &_wsaData);
329    #endif
330    
331            // Some actions surely need those
332            // shortcuts firmly attached...
333            addAction(m_ui.viewMenubarAction);
334            addAction(m_ui.viewToolbarAction);
335    
336  #if defined(WIN32)          QObject::connect(m_ui.fileNewAction,
     WSAStartup(MAKEWORD(1, 1), &_wsaData);  
 #endif  
   
         QObject::connect(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__) || defined(_WIN32) || defined(WIN32)
429      WSACleanup();          WSACleanup();
430  #endif  #endif
431    
432      // Finally drop any widgets around...  #if defined(HAVE_SIGNAL_H) && defined(HAVE_SYS_SOCKET_H)
433      if (m_pDeviceForm)          if (m_pUsr1Notifier)
434          delete m_pDeviceForm;                  delete m_pUsr1Notifier;
435      if (m_pInstrumentListForm)  #endif
436          delete m_pInstrumentListForm;  
437      if (m_pMessages)          // Finally drop any widgets around...
438          delete m_pMessages;          if (m_pDeviceForm)
439      if (m_pWorkspace)                  delete m_pDeviceForm;
440          delete m_pWorkspace;          if (m_pInstrumentListForm)
441                    delete m_pInstrumentListForm;
442      // Delete status item labels one by one.          if (m_pMessages)
443      if (m_statusItem[QSAMPLER_STATUS_CLIENT])                  delete m_pMessages;
444          delete m_statusItem[QSAMPLER_STATUS_CLIENT];          if (m_pWorkspace)
445      if (m_statusItem[QSAMPLER_STATUS_SERVER])                  delete m_pWorkspace;
446          delete m_statusItem[QSAMPLER_STATUS_SERVER];  
447      if (m_statusItem[QSAMPLER_STATUS_CHANNEL])          // Delete status item labels one by one.
448          delete m_statusItem[QSAMPLER_STATUS_CHANNEL];          if (m_statusItem[QSAMPLER_STATUS_CLIENT])
449      if (m_statusItem[QSAMPLER_STATUS_SESSION])                  delete m_statusItem[QSAMPLER_STATUS_CLIENT];
450          delete m_statusItem[QSAMPLER_STATUS_SESSION];          if (m_statusItem[QSAMPLER_STATUS_SERVER])
451                    delete m_statusItem[QSAMPLER_STATUS_SERVER];
452            if (m_statusItem[QSAMPLER_STATUS_CHANNEL])
453                    delete m_statusItem[QSAMPLER_STATUS_CHANNEL];
454            if (m_statusItem[QSAMPLER_STATUS_SESSION])
455                    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;
834    
835      // Check if we're going to discard safely the current one...          // Check if we're going to discard safely the current one...
836      if (!closeSession(true))          if (!closeSession(true))
837          return false;                  return false;
838    
839      // Load it right away.          // Load it right away.
840      return loadSessionFile(sFilename);          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.          }
914      if (bClose) {  
915          // Remove all channel strips from sight...          // If we may close it, dot it.
916          m_pWorkspace->setUpdatesEnabled(false);          if (bClose) {
917          QWidgetList wlist = m_pWorkspace->windowList();                  // Remove all channel strips from sight...
918          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  m_pWorkspace->setUpdatesEnabled(false);
919              ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  const QList<QMdiSubWindow *>& wlist
920              if (pChannelStrip) {                          = m_pWorkspace->subWindowList();
921                  qsamplerChannel *pChannel = pChannelStrip->channel();                  const int iStripCount = wlist.count();
922                  if (bForce && pChannel)                  for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
923                      pChannel->removeChannel();                          ChannelStrip *pChannelStrip = NULL;
924                  delete pChannelStrip;                          QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
925              }                          if (pMdiSubWindow)
926          }                                  pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
927          m_pWorkspace->setUpdatesEnabled(true);                          if (pChannelStrip) {
928          // We're now clean, for sure.                                  Channel *pChannel = pChannelStrip->channel();
929          m_iDirtyCount = 0;                                  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;          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") << ": " CONFIG_BUILD_VERSION << endl;
1050         << ": " QSAMPLER_VERSION << endl;  //      ts << "# " << tr("Build") << ": " CONFIG_BUILD_DATE << endl;
1051      ts << "# " << tr("Build")          ts << "#"  << endl;
1052         << ": " __DATE__ " " __TIME__ << endl;          ts << "# " << tr("File")
1053      ts << "#"  << endl;          << ": " << QFileInfo(sFilename).fileName() << endl;
1054      ts << "# " << tr("File")          ts << "# " << tr("Date")
1055         << ": " << QFileInfo(sFilename).fileName() << endl;          << ": " << QDate::currentDate().toString("MMM dd yyyy")
1056      ts << "# " << tr("Date")          << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;
1057         << ": " << QDate::currentDate().toString("MMM dd yyyy")          ts << "#"  << endl;
1058         << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;          ts << endl;
     ts << "#"  << endl;  
     ts << endl;  
1059    
1060          // It is assumed that this new kind of device+session file          // It is assumed that this new kind of device+session file
1061          // will be loaded from a complete initialized server...          // will be loaded from a complete initialized server...
# Line 860  bool MainForm::saveSessionFile ( const Q Line 1065  bool MainForm::saveSessionFile ( const Q
1065    
1066          // Audio device mapping.          // Audio device mapping.
1067          QMap<int, int> audioDeviceMap;          QMap<int, int> audioDeviceMap;
1068          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Audio);          piDeviceIDs = Device::getDevices(m_pClient, Device::Audio);
1069          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
1070                  ts << endl;                  ts << endl;
1071                  qsamplerDevice device(qsamplerDevice::Audio, piDeviceIDs[iDevice]);                  Device device(Device::Audio, piDeviceIDs[iDevice]);
1072                  // Audio device specification...                  // Audio device specification...
1073                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1074                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1075                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();
1076                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
1077                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
1078                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
1079                                          ++deviceParam) {                                          ++deviceParam) {
1080                          const qsamplerDeviceParam& param = deviceParam.value();                          const DeviceParam& param = deviceParam.value();
1081                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
1082                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
1083                  }                  }
1084                  ts << endl;                  ts << endl;
1085                  // Audio channel parameters...                  // Audio channel parameters...
1086                  int iPort = 0;                  int iPort = 0;
1087                  QListIterator<qsamplerDevicePort *> iter(device.ports());                  QListIterator<DevicePort *> iter(device.ports());
1088                  while (iter.hasNext()) {                  while (iter.hasNext()) {
1089                          qsamplerDevicePort *pPort = iter.next();                          DevicePort *pPort = iter.next();
1090                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1091                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1092                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1093                                                  ++portParam) {                                                  ++portParam) {
1094                                  const qsamplerDeviceParam& param = portParam.value();                                  const DeviceParam& param = portParam.value();
1095                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1096                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice
1097                                          << " " << iPort << " " << portParam.key()                                          << " " << iPort << " " << portParam.key()
# Line 902  bool MainForm::saveSessionFile ( const Q Line 1107  bool MainForm::saveSessionFile ( const Q
1107    
1108          // MIDI device mapping.          // MIDI device mapping.
1109          QMap<int, int> midiDeviceMap;          QMap<int, int> midiDeviceMap;
1110          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Midi);          piDeviceIDs = Device::getDevices(m_pClient, Device::Midi);
1111          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
1112                  ts << endl;                  ts << endl;
1113                  qsamplerDevice device(qsamplerDevice::Midi, piDeviceIDs[iDevice]);                  Device device(Device::Midi, piDeviceIDs[iDevice]);
1114                  // MIDI device specification...                  // MIDI device specification...
1115                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1116                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1117                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();
1118                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
1119                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
1120                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
1121                                          ++deviceParam) {                                          ++deviceParam) {
1122                          const qsamplerDeviceParam& param = deviceParam.value();                          const DeviceParam& param = deviceParam.value();
1123                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
1124                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
1125                  }                  }
1126                  ts << endl;                  ts << endl;
1127                  // MIDI port parameters...                  // MIDI port parameters...
1128                  int iPort = 0;                  int iPort = 0;
1129                  QListIterator<qsamplerDevicePort *> iter(device.ports());                  QListIterator<DevicePort *> iter(device.ports());
1130                  while (iter.hasNext()) {                  while (iter.hasNext()) {
1131                          qsamplerDevicePort *pPort = iter.next();                          DevicePort *pPort = iter.next();
1132                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1133                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1134                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1135                                                  ++portParam) {                                                  ++portParam) {
1136                                  const qsamplerDeviceParam& param = portParam.value();                                  const DeviceParam& param = portParam.value();
1137                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1138                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice
1139                                     << " " << iPort << " " << portParam.key()                                  << " " << iPort << " " << portParam.key()
1140                                     << "='" << param.value << "'" << endl;                                  << "='" << param.value << "'" << endl;
1141                          }                          }
1142                          iPort++;                          iPort++;
1143                  }                  }
# Line 948  bool MainForm::saveSessionFile ( const Q Line 1153  bool MainForm::saveSessionFile ( const Q
1153          QMap<int, int> midiInstrumentMap;          QMap<int, int> midiInstrumentMap;
1154          int *piMaps = ::lscp_list_midi_instrument_maps(m_pClient);          int *piMaps = ::lscp_list_midi_instrument_maps(m_pClient);
1155          for (int iMap = 0; piMaps && piMaps[iMap] >= 0; iMap++) {          for (int iMap = 0; piMaps && piMaps[iMap] >= 0; iMap++) {
1156                  int iMidiMap = piMaps[iMap];                  const int iMidiMap = piMaps[iMap];
1157                  const char *pszMapName                  const char *pszMapName
1158                          = ::lscp_get_midi_instrument_map_name(m_pClient, iMidiMap);                          = ::lscp_get_midi_instrument_map_name(m_pClient, iMidiMap);
1159                  ts << "# " << tr("MIDI instrument map") << " " << iMap;                  ts << "# " << tr("MIDI instrument map") << " " << iMap;
# Line 1015  bool MainForm::saveSessionFile ( const Q Line 1220  bool MainForm::saveSessionFile ( const Q
1220  #endif  // CONFIG_MIDI_INSTRUMENT  #endif  // CONFIG_MIDI_INSTRUMENT
1221    
1222          // Sampler channel mapping.          // Sampler channel mapping.
1223      QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
1224      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  = m_pWorkspace->subWindowList();
1225          ChannelStrip* pChannelStrip          const int iStripCount = wlist.count();
1226                          = static_cast<ChannelStrip *> (wlist.at(iChannel));          for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
1227          if (pChannelStrip) {                  ChannelStrip *pChannelStrip = NULL;
1228              qsamplerChannel *pChannel = pChannelStrip->channel();                  QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
1229              if (pChannel) {                  if (pMdiSubWindow)
1230                  ts << "# " << tr("Channel") << " " << iChannel << endl;                          pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
1231                  ts << "ADD CHANNEL" << endl;                  if (pChannelStrip) {
1232                            Channel *pChannel = pChannelStrip->channel();
1233                            if (pChannel) {
1234                                    const int iChannelID = pChannel->channelID();
1235                                    ts << "# " << tr("Channel") << " " << iChannelID << endl;
1236                                    ts << "ADD CHANNEL" << endl;
1237                                  if (audioDeviceMap.isEmpty()) {                                  if (audioDeviceMap.isEmpty()) {
1238                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannelID
1239                                                  << " " << pChannel->audioDriver() << endl;                                                  << " " << pChannel->audioDriver() << endl;
1240                                  } else {                                  } else {
1241                                          ts << "SET CHANNEL AUDIO_OUTPUT_DEVICE " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_DEVICE " << iChannelID
1242                                                  << " " << audioDeviceMap[pChannel->audioDevice()] << endl;                                                  << " " << audioDeviceMap[pChannel->audioDevice()] << endl;
1243                                  }                                  }
1244                                  if (midiDeviceMap.isEmpty()) {                                  if (midiDeviceMap.isEmpty()) {
1245                                          ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannel                                          ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannelID
1246                                                  << " " << pChannel->midiDriver() << endl;                                                  << " " << pChannel->midiDriver() << endl;
1247                                  } else {                                  } else {
1248                                          ts << "SET CHANNEL MIDI_INPUT_DEVICE " << iChannel                                          ts << "SET CHANNEL MIDI_INPUT_DEVICE " << iChannelID
1249                                                  << " " << midiDeviceMap[pChannel->midiDevice()] << endl;                                                  << " " << midiDeviceMap[pChannel->midiDevice()] << endl;
1250                                  }                                  }
1251                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannelID
1252                                          << " " << pChannel->midiPort() << endl;                                          << " " << pChannel->midiPort() << endl;
1253                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";                                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannelID << " ";
1254                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)                                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
1255                      ts << "ALL";                                          ts << "ALL";
1256                  else                                  else
1257                      ts << pChannel->midiChannel();                                          ts << pChannel->midiChannel();
1258                  ts << endl;                                  ts << endl;
1259                  ts << "LOAD ENGINE " << pChannel->engineName() << " " << iChannel << endl;                                  ts << "LOAD ENGINE " << pChannel->engineName()
1260                                            << " " << iChannelID << endl;
1261                                  if (pChannel->instrumentStatus() < 100) ts << "# ";                                  if (pChannel->instrumentStatus() < 100) ts << "# ";
1262                                  ts << "LOAD INSTRUMENT NON_MODAL '" << pChannel->instrumentFile() << "' "                                  ts << "LOAD INSTRUMENT NON_MODAL '"
1263                                          << pChannel->instrumentNr() << " " << iChannel << endl;                                          << pChannel->instrumentFile() << "' "
1264                                  qsamplerChannelRoutingMap::ConstIterator audioRoute;                                          << pChannel->instrumentNr() << " " << iChannelID << endl;
1265                                    ChannelRoutingMap::ConstIterator audioRoute;
1266                                  for (audioRoute = pChannel->audioRouting().begin();                                  for (audioRoute = pChannel->audioRouting().begin();
1267                                                  audioRoute != pChannel->audioRouting().end();                                                  audioRoute != pChannel->audioRouting().end();
1268                                                          ++audioRoute) {                                                          ++audioRoute) {
1269                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannelID
1270                                                  << " " << audioRoute.key()                                                  << " " << audioRoute.key()
1271                                                  << " " << audioRoute.value() << endl;                                                  << " " << audioRoute.value() << endl;
1272                                  }                                  }
1273                                  ts << "SET CHANNEL VOLUME " << iChannel                                  ts << "SET CHANNEL VOLUME " << iChannelID
1274                                          << " " << pChannel->volume() << endl;                                          << " " << pChannel->volume() << endl;
1275                                  if (pChannel->channelMute())                                  if (pChannel->channelMute())
1276                                          ts << "SET CHANNEL MUTE " << iChannel << " 1" << endl;                                          ts << "SET CHANNEL MUTE " << iChannelID << " 1" << endl;
1277                                  if (pChannel->channelSolo())                                  if (pChannel->channelSolo())
1278                                          ts << "SET CHANNEL SOLO " << iChannel << " 1" << endl;                                          ts << "SET CHANNEL SOLO " << iChannelID << " 1" << endl;
1279  #ifdef CONFIG_MIDI_INSTRUMENT                          #ifdef CONFIG_MIDI_INSTRUMENT
1280                                  if (pChannel->midiMap() >= 0) {                                  if (pChannel->midiMap() >= 0) {
1281                                          ts << "SET CHANNEL MIDI_INSTRUMENT_MAP " << iChannel                                          ts << "SET CHANNEL MIDI_INSTRUMENT_MAP " << iChannelID
1282                                                  << " " << midiInstrumentMap[pChannel->midiMap()] << endl;                                                  << " " << midiInstrumentMap[pChannel->midiMap()] << endl;
1283                                  }                                  }
1284  #endif                          #endif
1285  #ifdef CONFIG_FXSEND                          #ifdef CONFIG_FXSEND
                                 int iChannelID = pChannel->channelID();  
1286                                  int *piFxSends = ::lscp_list_fxsends(m_pClient, iChannelID);                                  int *piFxSends = ::lscp_list_fxsends(m_pClient, iChannelID);
1287                                  for (int iFxSend = 0;                                  for (int iFxSend = 0;
1288                                                  piFxSends && piFxSends[iFxSend] >= 0;                                                  piFxSends && piFxSends[iFxSend] >= 0;
# Line 1079  bool MainForm::saveSessionFile ( const Q Line 1290  bool MainForm::saveSessionFile ( const Q
1290                                          lscp_fxsend_info_t *pFxSendInfo = ::lscp_get_fxsend_info(                                          lscp_fxsend_info_t *pFxSendInfo = ::lscp_get_fxsend_info(
1291                                                  m_pClient, iChannelID, piFxSends[iFxSend]);                                                  m_pClient, iChannelID, piFxSends[iFxSend]);
1292                                          if (pFxSendInfo) {                                          if (pFxSendInfo) {
1293                                                  ts << "CREATE FX_SEND " << iChannel                                                  ts << "CREATE FX_SEND " << iChannelID
1294                                                          << " " << pFxSendInfo->midi_controller;                                                          << " " << pFxSendInfo->midi_controller;
1295                                                  if (pFxSendInfo->name)                                                  if (pFxSendInfo->name)
1296                                                          ts << " '" << pFxSendInfo->name << "'";                                                          ts << " '" << pFxSendInfo->name << "'";
# Line 1089  bool MainForm::saveSessionFile ( const Q Line 1300  bool MainForm::saveSessionFile ( const Q
1300                                                                  piRouting && piRouting[iAudioSrc] >= 0;                                                                  piRouting && piRouting[iAudioSrc] >= 0;
1301                                                                          iAudioSrc++) {                                                                          iAudioSrc++) {
1302                                                          ts << "SET FX_SEND AUDIO_OUTPUT_CHANNEL "                                                          ts << "SET FX_SEND AUDIO_OUTPUT_CHANNEL "
1303                                                                  << iChannel                                                                  << iChannelID
1304                                                                  << " " << iFxSend                                                                  << " " << iFxSend
1305                                                                  << " " << iAudioSrc                                                                  << " " << iAudioSrc
1306                                                                  << " " << piRouting[iAudioSrc] << endl;                                                                  << " " << piRouting[iAudioSrc] << endl;
1307                                                  }                                                  }
1308  #ifdef CONFIG_FXSEND_LEVEL                                          #ifdef CONFIG_FXSEND_LEVEL
1309                                                  ts << "SET FX_SEND LEVEL " << iChannel                                                  ts << "SET FX_SEND LEVEL " << iChannelID
1310                                                          << " " << iFxSend                                                          << " " << iFxSend
1311                                                          << " " << pFxSendInfo->level << endl;                                                          << " " << pFxSendInfo->level << endl;
1312  #endif                                          #endif
1313                                          }       // Check for errors...                                          }       // Check for errors...
1314                                          else if (::lscp_client_get_errno(m_pClient)) {                                          else if (::lscp_client_get_errno(m_pClient)) {
1315                                                  appendMessagesClient("lscp_get_fxsend_info");                                                  appendMessagesClient("lscp_get_fxsend_info");
1316                                                  iErrors++;                                                  iErrors++;
1317                                          }                                          }
1318                                  }                                  }
1319  #endif                          #endif
1320                  ts << endl;                                  ts << endl;
1321              }                          }
1322          }                  }
1323          // Try to keep it snappy :)                  // Try to keep it snappy :)
1324          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1325      }          }
1326    
1327  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
1328          ts << "# " << tr("Global volume level") << endl;          ts << "# " << tr("Global volume level") << endl;
# Line 1119  bool MainForm::saveSessionFile ( const Q Line 1330  bool MainForm::saveSessionFile ( const Q
1330          ts << endl;          ts << endl;
1331  #endif  #endif
1332    
1333      // Ok. we've wrote it.          // Ok. we've wrote it.
1334      file.close();          file.close();
1335    
1336          // We're fornerly done.          // We're fornerly done.
1337          QApplication::restoreOverrideCursor();          QApplication::restoreOverrideCursor();
1338    
1339      // Have we any errors?          // Have we any errors?
1340      if (iErrors > 0)          if (iErrors > 0) {
1341          appendMessagesError(tr("Some settings could not be saved\nto \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
1342                            tr("Some settings could not be saved\n"
1343      // Save as default session directory.                          "to \"%1\" session file.\n\nSorry.")
1344      if (m_pOptions)                          .arg(sFilename));
1345          m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();          }
1346      // We're not dirty anymore.  
1347      m_iDirtyCount = 0;          // Save as default session directory.
1348      // Stabilize form...          if (m_pOptions)
1349      m_sFilename = sFilename;                  m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();
1350      updateRecentFiles(sFilename);          // We're not dirty anymore.
1351      appendMessages(tr("Save session: \"%1\".").arg(sessionName(m_sFilename)));          m_iDirtyCount = 0;
1352      stabilizeForm();          // Stabilize form...
1353      return true;          m_sFilename = sFilename;
1354            updateRecentFiles(sFilename);
1355            appendMessages(tr("Save session: \"%1\".").arg(sessionName(m_sFilename)));
1356            stabilizeForm();
1357            return true;
1358  }  }
1359    
1360    
1361  // Session change receiver slot.  // Session change receiver slot.
1362  void MainForm::sessionDirty (void)  void MainForm::sessionDirty (void)
1363  {  {
1364      // Just mark the dirty form.          // Just mark the dirty form.
1365      m_iDirtyCount++;          m_iDirtyCount++;
1366      // and update the form status...          // and update the form status...
1367      stabilizeForm();          stabilizeForm();
1368  }  }
1369    
1370    
1371  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1372  // qsamplerMainForm -- File Action slots.  // QSampler::MainForm -- File Action slots.
1373    
1374  // Create a new sampler session.  // Create a new sampler session.
1375  void MainForm::fileNew (void)  void MainForm::fileNew (void)
1376  {  {
1377      // Of course we'll start clean new.          // Of course we'll start clean new.
1378      newSession();          newSession();
1379  }  }
1380    
1381    
1382  // Open an existing sampler session.  // Open an existing sampler session.
1383  void MainForm::fileOpen (void)  void MainForm::fileOpen (void)
1384  {  {
1385      // Open it right away.          // Open it right away.
1386      openSession();          openSession();
1387  }  }
1388    
1389    
# Line 1178  void MainForm::fileOpenRecent (void) Line 1393  void MainForm::fileOpenRecent (void)
1393          // Retrive filename index from action data...          // Retrive filename index from action data...
1394          QAction *pAction = qobject_cast<QAction *> (sender());          QAction *pAction = qobject_cast<QAction *> (sender());
1395          if (pAction && m_pOptions) {          if (pAction && m_pOptions) {
1396                  int iIndex = pAction->data().toInt();                  const int iIndex = pAction->data().toInt();
1397                  if (iIndex >= 0 && iIndex < m_pOptions->recentFiles.count()) {                  if (iIndex >= 0 && iIndex < m_pOptions->recentFiles.count()) {
1398                          QString sFilename = m_pOptions->recentFiles[iIndex];                          QString sFilename = m_pOptions->recentFiles[iIndex];
1399                          // 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 1407  void MainForm::fileOpenRecent (void)
1407  // Save current sampler session.  // Save current sampler session.
1408  void MainForm::fileSave (void)  void MainForm::fileSave (void)
1409  {  {
1410      // Save it right away.          // Save it right away.
1411      saveSession(false);          saveSession(false);
1412  }  }
1413    
1414    
1415  // Save current sampler session with another name.  // Save current sampler session with another name.
1416  void MainForm::fileSaveAs (void)  void MainForm::fileSaveAs (void)
1417  {  {
1418      // Save it right away, maybe with another name.          // Save it right away, maybe with another name.
1419      saveSession(true);          saveSession(true);
1420  }  }
1421    
1422    
1423  // Reset the sampler instance.  // Reset the sampler instance.
1424  void MainForm::fileReset (void)  void MainForm::fileReset (void)
1425  {  {
1426      if (m_pClient == NULL)          if (m_pClient == NULL)
1427          return;                  return;
1428    
1429      // Ask user whether he/she want's an internal sampler reset...          // Ask user whether he/she want's an internal sampler reset...
1430      if (QMessageBox::warning(this,          if (m_pOptions && m_pOptions->bConfirmReset) {
1431                  QSAMPLER_TITLE ": " + tr("Warning"),                  const QString& sTitle = QSAMPLER_TITLE ": " + tr("Warning");
1432          tr("Resetting the sampler instance will close\n"                  const QString& sText = tr(
1433             "all device and channel configurations.\n\n"                          "Resetting the sampler instance will close\n"
1434             "Please note that this operation may cause\n"                          "all device and channel configurations.\n\n"
1435             "temporary MIDI and Audio disruption.\n\n"                          "Please note that this operation may cause\n"
1436             "Do you want to reset the sampler engine now?"),                          "temporary MIDI and Audio disruption.\n\n"
1437          tr("Reset"), tr("Cancel")) > 0)                          "Do you want to reset the sampler engine now?");
1438          return;          #if 0
1439                    if (QMessageBox::warning(this, sTitle, sText,
1440                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1441                            return;
1442            #else
1443                    QMessageBox mbox(this);
1444                    mbox.setIcon(QMessageBox::Warning);
1445                    mbox.setWindowTitle(sTitle);
1446                    mbox.setText(sText);
1447                    mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1448                    QCheckBox cbox(tr("Don't ask this again"));
1449                    cbox.setChecked(false);
1450                    cbox.blockSignals(true);
1451                    mbox.addButton(&cbox, QMessageBox::ActionRole);
1452                    if (mbox.exec() == QMessageBox::Cancel)
1453                            return;
1454                    if (cbox.isChecked())
1455                            m_pOptions->bConfirmReset = false;
1456            #endif
1457            }
1458    
1459          // Trye closing the current session, first...          // Trye closing the current session, first...
1460          if (!closeSession(true))          if (!closeSession(true))
1461                  return;                  return;
1462    
1463      // Just do the reset, after closing down current session...          // Just do the reset, after closing down current session...
1464          // Do the actual sampler reset...          // Do the actual sampler reset...
1465          if (::lscp_reset_sampler(m_pClient) != LSCP_OK) {          if (::lscp_reset_sampler(m_pClient) != LSCP_OK) {
1466                  appendMessagesClient("lscp_reset_sampler");                  appendMessagesClient("lscp_reset_sampler");
# Line 1234  void MainForm::fileReset (void) Line 1468  void MainForm::fileReset (void)
1468                  return;                  return;
1469          }          }
1470    
1471      // Log this.          // Log this.
1472      appendMessages(tr("Sampler reset."));          appendMessages(tr("Sampler reset."));
1473    
1474          // Make it a new session...          // Make it a new session...
1475          newSession();          newSession();
# Line 1245  void MainForm::fileReset (void) Line 1479  void MainForm::fileReset (void)
1479  // Restart the client/server instance.  // Restart the client/server instance.
1480  void MainForm::fileRestart (void)  void MainForm::fileRestart (void)
1481  {  {
1482      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1483          return;                  return;
1484    
1485      bool bRestart = true;          bool bRestart = true;
1486    
1487      // Ask user whether he/she want's a complete restart...          // Ask user whether he/she want's a complete restart...
1488      // (if we're currently up and running)          // (if we're currently up and running)
1489      if (bRestart && m_pClient) {          if (m_pOptions && m_pOptions->bConfirmRestart) {
1490          bRestart = (QMessageBox::warning(this,                  const QString& sTitle = QSAMPLER_TITLE ": " + tr("Warning");
1491                          QSAMPLER_TITLE ": " + tr("Warning"),                  const QString& sText = tr(
1492              tr("New settings will be effective after\n"                          "New settings will be effective after\n"
1493                 "restarting the client/server connection.\n\n"                          "restarting the client/server connection.\n\n"
1494                 "Please note that this operation may cause\n"                          "Please note that this operation may cause\n"
1495                 "temporary MIDI and Audio disruption.\n\n"                          "temporary MIDI and Audio disruption.\n\n"
1496                 "Do you want to restart the connection now?"),                          "Do you want to restart the connection now?");
1497              tr("Restart"), tr("Cancel")) == 0);          #if 0
1498      }                  if (QMessageBox::warning(this, sTitle, sText,
1499                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1500      // Are we still for it?                          bRestart = false;
1501      if (bRestart && closeSession(true)) {          #else
1502          // Stop server, it will force the client too.                  QMessageBox mbox(this);
1503          stopServer();                  mbox.setIcon(QMessageBox::Warning);
1504          // Reschedule a restart...                  mbox.setWindowTitle(sTitle);
1505          startSchedule(m_pOptions->iStartDelay);                  mbox.setText(sText);
1506      }                  mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1507                    QCheckBox cbox(tr("Don't ask this again"));
1508                    cbox.setChecked(false);
1509                    cbox.blockSignals(true);
1510                    mbox.addButton(&cbox, QMessageBox::ActionRole);
1511                    if (mbox.exec() == QMessageBox::Cancel)
1512                            bRestart = false;
1513                    else
1514                    if (cbox.isChecked())
1515                            m_pOptions->bConfirmRestart = false;
1516            #endif
1517            }
1518    
1519            // Are we still for it?
1520            if (bRestart && closeSession(true)) {
1521                    // Stop server, it will force the client too.
1522                    stopServer();
1523                    // Reschedule a restart...
1524                    startSchedule(m_pOptions->iStartDelay);
1525            }
1526  }  }
1527    
1528    
1529  // Exit application program.  // Exit application program.
1530  void MainForm::fileExit (void)  void MainForm::fileExit (void)
1531  {  {
1532      // Go for close the whole thing.          // Go for close the whole thing.
1533      close();          close();
1534  }  }
1535    
1536    
1537  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1538  // qsamplerMainForm -- Edit Action slots.  // QSampler::MainForm -- Edit Action slots.
1539    
1540  // Add a new sampler channel.  // Add a new sampler channel.
1541  void MainForm::editAddChannel (void)  void MainForm::editAddChannel (void)
1542  {  {
1543      if (m_pClient == NULL)          ++m_iDirtySetup;
1544          return;          addChannelStrip();
1545            --m_iDirtySetup;
1546    }
1547    
1548    void MainForm::addChannelStrip (void)
1549    {
1550            if (m_pClient == NULL)
1551                    return;
1552    
1553            // Just create the channel instance...
1554            Channel *pChannel = new Channel();
1555            if (pChannel == NULL)
1556                    return;
1557    
1558            // Before we show it up, may be we'll
1559            // better ask for some initial values?
1560            if (!pChannel->channelSetup(this)) {
1561                    delete pChannel;
1562                    return;
1563            }
1564    
1565      // Just create the channel instance...          // And give it to the strip...
1566      qsamplerChannel *pChannel = new qsamplerChannel();          // (will own the channel instance, if successful).
1567      if (pChannel == NULL)          if (!createChannelStrip(pChannel)) {
1568          return;                  delete pChannel;
1569                    return;
1570      // Before we show it up, may be we'll          }
1571      // better ask for some initial values?  
1572      if (!pChannel->channelSetup(this)) {          // Do we auto-arrange?
1573          delete pChannel;          channelsArrangeAuto();
1574          return;  
1575      }          // Make that an overall update.
1576            m_iDirtyCount++;
1577      // And give it to the strip (will own the channel instance, if successful).          stabilizeForm();
     if (!createChannelStrip(pChannel)) {  
         delete pChannel;  
         return;  
     }  
   
     // Make that an overall update.  
     m_iDirtyCount++;  
     stabilizeForm();  
1578  }  }
1579    
1580    
1581  // Remove current sampler channel.  // Remove current sampler channel.
1582  void MainForm::editRemoveChannel (void)  void MainForm::editRemoveChannel (void)
1583  {  {
1584      if (m_pClient == NULL)          ++m_iDirtySetup;
1585          return;          removeChannelStrip();
1586            --m_iDirtySetup;
1587    }
1588    
1589      ChannelStrip* pChannelStrip = activeChannelStrip();  void MainForm::removeChannelStrip (void)
1590      if (pChannelStrip == NULL)  {
1591          return;          if (m_pClient == NULL)
1592                    return;
1593      qsamplerChannel *pChannel = pChannelStrip->channel();  
1594      if (pChannel == NULL)          ChannelStrip *pChannelStrip = activeChannelStrip();
1595          return;          if (pChannelStrip == NULL)
1596                    return;
1597      // Prompt user if he/she's sure about this...  
1598      if (m_pOptions && m_pOptions->bConfirmRemove) {          Channel *pChannel = pChannelStrip->channel();
1599          if (QMessageBox::warning(this,          if (pChannel == NULL)
1600                          QSAMPLER_TITLE ": " + tr("Warning"),                  return;
1601              tr("About to remove channel:\n\n"  
1602                 "%1\n\n"          // Prompt user if he/she's sure about this...
1603                 "Are you sure?")          if (m_pOptions && m_pOptions->bConfirmRemove) {
1604                 .arg(pChannelStrip->windowTitle()),                  const QString& sTitle = QSAMPLER_TITLE ": " + tr("Warning");
1605              tr("OK"), tr("Cancel")) > 0)                  const QString& sText = tr(
1606              return;                          "About to remove channel:\n\n"
1607      }                          "%1\n\n"
1608                            "Are you sure?")
1609      // Remove the existing sampler channel.                          .arg(pChannelStrip->windowTitle());
1610      if (!pChannel->removeChannel())          #if 0
1611          return;                  if (QMessageBox::warning(this, sTitle, sText,
1612                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
1613      // Just delete the channel strip.                          return;
1614      delete pChannelStrip;          #else
1615                    QMessageBox mbox(this);
1616      // Do we auto-arrange?                  mbox.setIcon(QMessageBox::Warning);
1617      if (m_pOptions && m_pOptions->bAutoArrange)                  mbox.setWindowTitle(sTitle);
1618          channelsArrange();                  mbox.setText(sText);
1619                    mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1620      // We'll be dirty, for sure...                  QCheckBox cbox(tr("Don't ask this again"));
1621      m_iDirtyCount++;                  cbox.setChecked(false);
1622      stabilizeForm();                  cbox.blockSignals(true);
1623                    mbox.addButton(&cbox, QMessageBox::ActionRole);
1624                    if (mbox.exec() == QMessageBox::Cancel)
1625                            return;
1626                    if (cbox.isChecked())
1627                            m_pOptions->bConfirmRemove = false;
1628            #endif
1629            }
1630    
1631            // Remove the existing sampler channel.
1632            if (!pChannel->removeChannel())
1633                    return;
1634    
1635            // Just delete the channel strip.
1636            destroyChannelStrip(pChannelStrip);
1637    
1638            // We'll be dirty, for sure...
1639            m_iDirtyCount++;
1640            stabilizeForm();
1641  }  }
1642    
1643    
1644  // Setup current sampler channel.  // Setup current sampler channel.
1645  void MainForm::editSetupChannel (void)  void MainForm::editSetupChannel (void)
1646  {  {
1647      if (m_pClient == NULL)          if (m_pClient == NULL)
1648          return;                  return;
1649    
1650      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1651      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1652          return;                  return;
1653    
1654      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1655      pChannelStrip->channelSetup();          pChannelStrip->channelSetup();
1656  }  }
1657    
1658    
1659  // Edit current sampler channel.  // Edit current sampler channel.
1660  void MainForm::editEditChannel (void)  void MainForm::editEditChannel (void)
1661  {  {
1662      if (m_pClient == NULL)          if (m_pClient == NULL)
1663          return;                  return;
1664    
1665      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1666      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1667          return;                  return;
1668    
1669      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1670      pChannelStrip->channelEdit();          pChannelStrip->channelEdit();
1671  }  }
1672    
1673    
1674  // Reset current sampler channel.  // Reset current sampler channel.
1675  void MainForm::editResetChannel (void)  void MainForm::editResetChannel (void)
1676  {  {
1677      if (m_pClient == NULL)          if (m_pClient == NULL)
1678          return;                  return;
1679    
1680      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1681      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1682          return;                  return;
1683    
1684      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1685      pChannelStrip->channelReset();          pChannelStrip->channelReset();
1686  }  }
1687    
1688    
# Line 1411  void MainForm::editResetAllChannels (voi Line 1695  void MainForm::editResetAllChannels (voi
1695          // Invoque the channel strip procedure,          // Invoque the channel strip procedure,
1696          // for all channels out there...          // for all channels out there...
1697          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
1698          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
1699          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  = m_pWorkspace->subWindowList();
1700                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);          const int iStripCount = wlist.count();
1701            for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
1702                    ChannelStrip *pChannelStrip = NULL;
1703                    QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
1704                    if (pMdiSubWindow)
1705                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
1706                  if (pChannelStrip)                  if (pChannelStrip)
1707                          pChannelStrip->channelReset();                          pChannelStrip->channelReset();
1708          }          }
# Line 1422  void MainForm::editResetAllChannels (voi Line 1711  void MainForm::editResetAllChannels (voi
1711    
1712    
1713  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1714  // qsamplerMainForm -- View Action slots.  // QSampler::MainForm -- View Action slots.
1715    
1716  // Show/hide the main program window menubar.  // Show/hide the main program window menubar.
1717  void MainForm::viewMenubar ( bool bOn )  void MainForm::viewMenubar ( bool bOn )
1718  {  {
1719      if (bOn)          if (bOn)
1720          ui.MenuBar->show();                  m_ui.MenuBar->show();
1721      else          else
1722          ui.MenuBar->hide();                  m_ui.MenuBar->hide();
1723  }  }
1724    
1725    
1726  // Show/hide the main program window toolbar.  // Show/hide the main program window toolbar.
1727  void MainForm::viewToolbar ( bool bOn )  void MainForm::viewToolbar ( bool bOn )
1728  {  {
1729      if (bOn) {          if (bOn) {
1730          ui.fileToolbar->show();                  m_ui.fileToolbar->show();
1731          ui.editToolbar->show();                  m_ui.editToolbar->show();
1732          ui.channelsToolbar->show();                  m_ui.channelsToolbar->show();
1733      } else {          } else {
1734          ui.fileToolbar->hide();                  m_ui.fileToolbar->hide();
1735          ui.editToolbar->hide();                  m_ui.editToolbar->hide();
1736          ui.channelsToolbar->hide();                  m_ui.channelsToolbar->hide();
1737      }          }
1738  }  }
1739    
1740    
1741  // Show/hide the main program window statusbar.  // Show/hide the main program window statusbar.
1742  void MainForm::viewStatusbar ( bool bOn )  void MainForm::viewStatusbar ( bool bOn )
1743  {  {
1744      if (bOn)          if (bOn)
1745          statusBar()->show();                  statusBar()->show();
1746      else          else
1747          statusBar()->hide();                  statusBar()->hide();
1748  }  }
1749    
1750    
1751  // Show/hide the messages window logger.  // Show/hide the messages window logger.
1752  void MainForm::viewMessages ( bool bOn )  void MainForm::viewMessages ( bool bOn )
1753  {  {
1754      if (bOn)          if (bOn)
1755          m_pMessages->show();                  m_pMessages->show();
1756      else          else
1757          m_pMessages->hide();                  m_pMessages->hide();
1758  }  }
1759    
1760    
# Line 1510  void MainForm::viewDevices (void) Line 1799  void MainForm::viewDevices (void)
1799  // Show options dialog.  // Show options dialog.
1800  void MainForm::viewOptions (void)  void MainForm::viewOptions (void)
1801  {  {
1802      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1803          return;                  return;
1804    
1805      OptionsForm* pOptionsForm = new OptionsForm(this);          OptionsForm* pOptionsForm = new OptionsForm(this);
1806      if (pOptionsForm) {          if (pOptionsForm) {
1807          // Check out some initial nullities(tm)...                  // Check out some initial nullities(tm)...
1808          ChannelStrip* pChannelStrip = activeChannelStrip();                  ChannelStrip *pChannelStrip = activeChannelStrip();
1809          if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)
1810              m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();
1811          if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)
1812              m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
1813          // To track down deferred or immediate changes.                  // To track down deferred or immediate changes.
1814          QString sOldServerHost      = m_pOptions->sServerHost;                  const QString sOldServerHost      = m_pOptions->sServerHost;
1815          int     iOldServerPort      = m_pOptions->iServerPort;                  const int     iOldServerPort      = m_pOptions->iServerPort;
1816          int     iOldServerTimeout   = m_pOptions->iServerTimeout;                  const int     iOldServerTimeout   = m_pOptions->iServerTimeout;
1817          bool    bOldServerStart     = m_pOptions->bServerStart;                  const bool    bOldServerStart     = m_pOptions->bServerStart;
1818          QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;                  const QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;
1819          QString sOldDisplayFont     = m_pOptions->sDisplayFont;                  const bool    bOldMessagesLog     = m_pOptions->bMessagesLog;
1820          bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;                  const QString sOldMessagesLogPath = m_pOptions->sMessagesLogPath;
1821          int     iOldMaxVolume       = m_pOptions->iMaxVolume;                  const QString sOldDisplayFont     = m_pOptions->sDisplayFont;
1822          QString sOldMessagesFont    = m_pOptions->sMessagesFont;                  const bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;
1823          bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;                  const int     iOldMaxVolume       = m_pOptions->iMaxVolume;
1824          bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;                  const QString sOldMessagesFont    = m_pOptions->sMessagesFont;
1825          int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;                  const bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;
1826          int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;                  const bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;
1827          bool    bOldCompletePath    = m_pOptions->bCompletePath;                  const int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;
1828          bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;                  const int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;
1829          int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;                  const bool    bOldCompletePath    = m_pOptions->bCompletePath;
1830          // Load the current setup settings.                  const bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;
1831          pOptionsForm->setup(m_pOptions);                  const int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;
1832          // Show the setup dialog...                  const int     iOldBaseFontSize    = m_pOptions->iBaseFontSize;
1833          if (pOptionsForm->exec()) {                  // Load the current setup settings.
1834              // Warn if something will be only effective on next run.                  pOptionsForm->setup(m_pOptions);
1835              if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||                  // Show the setup dialog...
1836                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||                  if (pOptionsForm->exec()) {
1837                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||                          // Warn if something will be only effective on next run.
1838                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1839                  QMessageBox::information(this,                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||
1840                                    ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||
1841                                    (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)     ||
1842                                    (iOldBaseFontSize   !=  m_pOptions->iBaseFontSize)) {
1843                                    QMessageBox::information(this,
1844                                          QSAMPLER_TITLE ": " + tr("Information"),                                          QSAMPLER_TITLE ": " + tr("Information"),
1845                      tr("Some settings may be only effective\n"                                          tr("Some settings may be only effective\n"
1846                         "next time you start this program."), tr("OK"));                                          "next time you start this program."));
1847                  updateMessagesCapture();                                  updateMessagesCapture();
1848              }                          }
1849              // Check wheather something immediate has changed.                          // Check wheather something immediate has changed.
1850              if (( bOldCompletePath && !m_pOptions->bCompletePath) ||                          if (( bOldMessagesLog && !m_pOptions->bMessagesLog) ||
1851                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||                                  (!bOldMessagesLog &&  m_pOptions->bMessagesLog) ||
1852                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))                                  (sOldMessagesLogPath != m_pOptions->sMessagesLogPath))
1853                  updateRecentFilesMenu();                                  m_pMessages->setLogging(
1854              if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||                                          m_pOptions->bMessagesLog, m_pOptions->sMessagesLogPath);
1855                  (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||
1856                  updateInstrumentNames();                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||
1857              if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
1858                  (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))                                  updateRecentFilesMenu();
1859                  updateDisplayEffect();                          if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||
1860              if (sOldDisplayFont != m_pOptions->sDisplayFont)                                  (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))
1861                  updateDisplayFont();                                  updateInstrumentNames();
1862              if (iOldMaxVolume != m_pOptions->iMaxVolume)                          if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||
1863                  updateMaxVolume();                                  (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))
1864              if (sOldMessagesFont != m_pOptions->sMessagesFont)                                  updateDisplayEffect();
1865                  updateMessagesFont();                          if (sOldDisplayFont != m_pOptions->sDisplayFont)
1866              if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||                                  updateDisplayFont();
1867                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||                          if (iOldMaxVolume != m_pOptions->iMaxVolume)
1868                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))                                  updateMaxVolume();
1869                  updateMessagesLimit();                          if (sOldMessagesFont != m_pOptions->sMessagesFont)
1870              // And now the main thing, whether we'll do client/server recycling?                                  updateMessagesFont();
1871              if ((sOldServerHost != m_pOptions->sServerHost) ||                          if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||
1872                  (iOldServerPort != m_pOptions->iServerPort) ||                                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||
1873                  (iOldServerTimeout != m_pOptions->iServerTimeout) ||                                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))
1874                  ( bOldServerStart && !m_pOptions->bServerStart) ||                                  updateMessagesLimit();
1875                  (!bOldServerStart &&  m_pOptions->bServerStart) ||                          // And now the main thing, whether we'll do client/server recycling?
1876                  (sOldServerCmdLine != m_pOptions->sServerCmdLine && m_pOptions->bServerStart))                          if ((sOldServerHost != m_pOptions->sServerHost) ||
1877                  fileRestart();                                  (iOldServerPort != m_pOptions->iServerPort) ||
1878          }                                  (iOldServerTimeout != m_pOptions->iServerTimeout) ||
1879          // Done.                                  ( bOldServerStart && !m_pOptions->bServerStart) ||
1880          delete pOptionsForm;                                  (!bOldServerStart &&  m_pOptions->bServerStart) ||
1881      }                                  (sOldServerCmdLine != m_pOptions->sServerCmdLine
1882                                    && m_pOptions->bServerStart))
1883                                    fileRestart();
1884                    }
1885                    // Done.
1886                    delete pOptionsForm;
1887            }
1888    
1889      // This makes it.          // This makes it.
1890      stabilizeForm();          stabilizeForm();
1891  }  }
1892    
1893    
1894  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1895  // qsamplerMainForm -- Channels action slots.  // QSampler::MainForm -- Channels action slots.
1896    
1897  // Arrange channel strips.  // Arrange channel strips.
1898  void MainForm::channelsArrange (void)  void MainForm::channelsArrange (void)
1899  {  {
1900      // Full width vertical tiling          // Full width vertical tiling
1901      QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
1902      if (wlist.isEmpty())                  = m_pWorkspace->subWindowList();
1903          return;          if (wlist.isEmpty())
1904                    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);  
1905    
1906      stabilizeForm();          m_pWorkspace->setUpdatesEnabled(false);
1907            int y = 0;
1908            const int iStripCount = wlist.count();
1909            for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
1910                    QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
1911                    if (pMdiSubWindow) {
1912                            pMdiSubWindow->adjustSize();
1913                            int iWidth = m_pWorkspace->width();
1914                            if (iWidth < pMdiSubWindow->width())
1915                                    iWidth = pMdiSubWindow->width();
1916                            const int iHeight = pMdiSubWindow->frameGeometry().height();
1917                            pMdiSubWindow->setGeometry(0, y, iWidth, iHeight);
1918                            y += iHeight;
1919                    }
1920            }
1921            m_pWorkspace->setUpdatesEnabled(true);
1922    
1923            stabilizeForm();
1924  }  }
1925    
1926    
1927  // Auto-arrange channel strips.  // Auto-arrange channel strips.
1928  void MainForm::channelsAutoArrange ( bool bOn )  void MainForm::channelsAutoArrange ( bool bOn )
1929  {  {
1930      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1931          return;                  return;
1932    
1933      // Toggle the auto-arrange flag.          // Toggle the auto-arrange flag.
1934      m_pOptions->bAutoArrange = bOn;          m_pOptions->bAutoArrange = bOn;
1935    
1936      // If on, update whole workspace...          // If on, update whole workspace...
1937      if (m_pOptions->bAutoArrange)          channelsArrangeAuto();
1938          channelsArrange();  }
1939    
1940    
1941    void MainForm::channelsArrangeAuto (void)
1942    {
1943            if (m_pOptions && m_pOptions->bAutoArrange)
1944                    channelsArrange();
1945  }  }
1946    
1947    
1948  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1949  // qsamplerMainForm -- Help Action slots.  // QSampler::MainForm -- Help Action slots.
1950    
1951  // Show information about the Qt toolkit.  // Show information about the Qt toolkit.
1952  void MainForm::helpAboutQt (void)  void MainForm::helpAboutQt (void)
1953  {  {
1954      QMessageBox::aboutQt(this);          QMessageBox::aboutQt(this);
1955  }  }
1956    
1957    
1958  // Show information about application program.  // Show information about application program.
1959  void MainForm::helpAbout (void)  void MainForm::helpAbout (void)
1960  {  {
1961      // Stuff the about box text...          QStringList list;
     QString sText = "<p>\n";  
     sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";  
     sText += "<br />\n";  
     sText += tr("Version") + ": <b>" QSAMPLER_VERSION "</b><br />\n";  
     sText += "<small>" + tr("Build") + ": " __DATE__ " " __TIME__ "</small><br />\n";  
1962  #ifdef CONFIG_DEBUG  #ifdef CONFIG_DEBUG
1963      sText += "<small><font color=\"red\">";          list << tr("Debugging option enabled.");
     sText += tr("Debugging option enabled.");  
     sText += "</font></small><br />";  
1964  #endif  #endif
1965  #ifndef CONFIG_LIBGIG  #ifndef CONFIG_LIBGIG
1966      sText += "<small><font color=\"red\">";          list << tr("GIG (libgig) file support disabled.");
     sText += tr("GIG (libgig) file support disabled.");  
     sText += "</font></small><br />";  
1967  #endif  #endif
1968  #ifndef CONFIG_INSTRUMENT_NAME  #ifndef CONFIG_INSTRUMENT_NAME
1969      sText += "<small><font color=\"red\">";          list << tr("LSCP (liblscp) instrument_name support disabled.");
     sText += tr("LSCP (liblscp) instrument_name support disabled.");  
     sText += "</font></small><br />";  
1970  #endif  #endif
1971  #ifndef CONFIG_MUTE_SOLO  #ifndef CONFIG_MUTE_SOLO
1972      sText += "<small><font color=\"red\">";          list << tr("Sampler channel Mute/Solo support disabled.");
     sText += tr("Sampler channel Mute/Solo support disabled.");  
     sText += "</font></small><br />";  
1973  #endif  #endif
1974  #ifndef CONFIG_AUDIO_ROUTING  #ifndef CONFIG_AUDIO_ROUTING
1975      sText += "<small><font color=\"red\">";          list << tr("LSCP (liblscp) audio_routing support disabled.");
     sText += tr("LSCP (liblscp) audio_routing support disabled.");  
     sText += "</font></small><br />";  
1976  #endif  #endif
1977  #ifndef CONFIG_FXSEND  #ifndef CONFIG_FXSEND
1978      sText += "<small><font color=\"red\">";          list << tr("Sampler channel Effect Sends support disabled.");
     sText += tr("Sampler channel Effect Sends support disabled.");  
     sText += "</font></small><br />";  
1979  #endif  #endif
1980  #ifndef CONFIG_VOLUME  #ifndef CONFIG_VOLUME
1981      sText += "<small><font color=\"red\">";          list << tr("Global volume support disabled.");
     sText += tr("Global volume support disabled.");  
     sText += "</font></small><br />";  
1982  #endif  #endif
1983  #ifndef CONFIG_MIDI_INSTRUMENT  #ifndef CONFIG_MIDI_INSTRUMENT
1984      sText += "<small><font color=\"red\">";          list << tr("MIDI instrument mapping support disabled.");
     sText += tr("MIDI instrument mapping support disabled.");  
     sText += "</font></small><br />";  
1985  #endif  #endif
1986  #ifndef CONFIG_EDIT_INSTRUMENT  #ifndef CONFIG_EDIT_INSTRUMENT
1987      sText += "<small><font color=\"red\">";          list << tr("Instrument editing support disabled.");
1988      sText += tr("Instrument editing support disabled.");  #endif
1989      sText += "</font></small><br />";  #ifndef CONFIG_EVENT_CHANNEL_MIDI
1990  #endif          list << tr("Channel MIDI event support disabled.");
1991      sText += "<br />\n";  #endif
1992      sText += tr("Using") + ": ";  #ifndef CONFIG_EVENT_DEVICE_MIDI
1993      sText += ::lscp_client_package();          list << tr("Device MIDI event support disabled.");
1994      sText += " ";  #endif
1995      sText += ::lscp_client_version();  #ifndef CONFIG_MAX_VOICES
1996            list << tr("Runtime max. voices / disk streams support disabled.");
1997    #endif
1998    
1999            // Stuff the about box text...
2000            QString sText = "<p>\n";
2001            sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";
2002            sText += "<br />\n";
2003            sText += tr("Version") + ": <b>" CONFIG_BUILD_VERSION "</b><br />\n";
2004    //      sText += "<small>" + tr("Build") + ": " CONFIG_BUILD_DATE "</small><br />\n";
2005            if (!list.isEmpty()) {
2006                    sText += "<small><font color=\"red\">";
2007                    sText += list.join("<br />\n");
2008                    sText += "</font></small>";
2009            }
2010            sText += "<br />\n";
2011            sText += tr("Using") + ": ";
2012            sText += ::lscp_client_package();
2013            sText += " ";
2014            sText += ::lscp_client_version();
2015  #ifdef CONFIG_LIBGIG  #ifdef CONFIG_LIBGIG
2016      sText += ", ";          sText += ", ";
2017      sText += gig::libraryName().c_str();          sText += gig::libraryName().c_str();
2018      sText += " ";          sText += " ";
2019      sText += gig::libraryVersion().c_str();          sText += gig::libraryVersion().c_str();
2020  #endif  #endif
2021      sText += "<br />\n";          sText += "<br />\n";
2022      sText += "<br />\n";          sText += "<br />\n";
2023      sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";          sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";
2024      sText += "<br />\n";          sText += "<br />\n";
2025      sText += "<small>";          sText += "<small>";
2026      sText += QSAMPLER_COPYRIGHT "<br />\n";          sText += QSAMPLER_COPYRIGHT "<br />\n";
2027      sText += QSAMPLER_COPYRIGHT2 "<br />\n";          sText += QSAMPLER_COPYRIGHT2 "<br />\n";
2028      sText += "<br />\n";          sText += "<br />\n";
2029      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";
2030      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.");
2031      sText += "</small>";          sText += "</small>";
2032      sText += "</p>\n";          sText += "</p>\n";
2033    
2034      QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);          QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);
2035  }  }
2036    
2037    
2038  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2039  // qsamplerMainForm -- Main window stabilization.  // QSampler::MainForm -- Main window stabilization.
2040    
2041  void MainForm::stabilizeForm (void)  void MainForm::stabilizeForm (void)
2042  {  {
2043      // Update the main application caption...          // Update the main application caption...
2044      QString sSessionName = sessionName(m_sFilename);          QString sSessionName = sessionName(m_sFilename);
2045      if (m_iDirtyCount > 0)          if (m_iDirtyCount > 0)
2046          sSessionName += " *";                  sSessionName += " *";
2047      setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));
2048    
2049      // Update the main menu state...          // Update the main menu state...
2050      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
2051      bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);          const QList<QMdiSubWindow *>& wlist = m_pWorkspace->subWindowList();
2052      bool bHasChannel = (bHasClient && pChannelStrip != NULL);          const bool bHasClient = (m_pOptions != NULL && m_pClient != NULL);
2053      ui.fileNewAction->setEnabled(bHasClient);          const bool bHasChannel = (bHasClient && pChannelStrip != NULL);
2054      ui.fileOpenAction->setEnabled(bHasClient);          const bool bHasChannels = (bHasClient && wlist.count() > 0);
2055      ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);          m_ui.fileNewAction->setEnabled(bHasClient);
2056      ui.fileSaveAsAction->setEnabled(bHasClient);          m_ui.fileOpenAction->setEnabled(bHasClient);
2057      ui.fileResetAction->setEnabled(bHasClient);          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
2058      ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);          m_ui.fileSaveAsAction->setEnabled(bHasClient);
2059      ui.editAddChannelAction->setEnabled(bHasClient);          m_ui.fileResetAction->setEnabled(bHasClient);
2060      ui.editRemoveChannelAction->setEnabled(bHasChannel);          m_ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);
2061      ui.editSetupChannelAction->setEnabled(bHasChannel);          m_ui.editAddChannelAction->setEnabled(bHasClient);
2062            m_ui.editRemoveChannelAction->setEnabled(bHasChannel);
2063            m_ui.editSetupChannelAction->setEnabled(bHasChannel);
2064  #ifdef CONFIG_EDIT_INSTRUMENT  #ifdef CONFIG_EDIT_INSTRUMENT
2065      ui.editEditChannelAction->setEnabled(bHasChannel);          m_ui.editEditChannelAction->setEnabled(bHasChannel);
2066  #else  #else
2067      ui.editEditChannelAction->setEnabled(false);          m_ui.editEditChannelAction->setEnabled(false);
2068  #endif  #endif
2069      ui.editResetChannelAction->setEnabled(bHasChannel);          m_ui.editResetChannelAction->setEnabled(bHasChannel);
2070      ui.editResetAllChannelsAction->setEnabled(bHasChannel);          m_ui.editResetAllChannelsAction->setEnabled(bHasChannels);
2071      ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());
2072  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
2073          ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm
2074                  && m_pInstrumentListForm->isVisible());                  && m_pInstrumentListForm->isVisible());
2075          ui.viewInstrumentsAction->setEnabled(bHasClient);          m_ui.viewInstrumentsAction->setEnabled(bHasClient);
2076  #else  #else
2077          ui.viewInstrumentsAction->setEnabled(false);          m_ui.viewInstrumentsAction->setEnabled(false);
2078  #endif  #endif
2079          ui.viewDevicesAction->setChecked(m_pDeviceForm          m_ui.viewDevicesAction->setChecked(m_pDeviceForm
2080                  && m_pDeviceForm->isVisible());                  && m_pDeviceForm->isVisible());
2081      ui.viewDevicesAction->setEnabled(bHasClient);          m_ui.viewDevicesAction->setEnabled(bHasClient);
2082      ui.channelsArrangeAction->setEnabled(bHasChannel);          m_ui.viewMidiDeviceStatusMenu->setEnabled(
2083                    DeviceStatusForm::getInstances().size() > 0);
2084            m_ui.channelsArrangeAction->setEnabled(bHasChannels);
2085    
2086  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2087          // Toolbar widgets are also affected...          // Toolbar widgets are also affected...
2088      m_pVolumeSlider->setEnabled(bHasClient);          m_pVolumeSlider->setEnabled(bHasClient);
2089      m_pVolumeSpinBox->setEnabled(bHasClient);          m_pVolumeSpinBox->setEnabled(bHasClient);
2090  #endif  #endif
2091    
2092      // Client/Server status...          // Client/Server status...
2093      if (bHasClient) {          if (bHasClient) {
2094          m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));                  m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));
2095          m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost + ":" + QString::number(m_pOptions->iServerPort));                  m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost
2096      } else {                          + ':' + QString::number(m_pOptions->iServerPort));
2097          m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();          } else {
2098          m_statusItem[QSAMPLER_STATUS_SERVER]->clear();                  m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();
2099      }                  m_statusItem[QSAMPLER_STATUS_SERVER]->clear();
2100      // Channel status...          }
2101      if (bHasChannel)          // Channel status...
2102          m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->windowTitle());          if (bHasChannel)
2103      else                  m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->windowTitle());
2104          m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();          else
2105      // Session status...                  m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();
2106      if (m_iDirtyCount > 0)          // Session status...
2107          m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));          if (m_iDirtyCount > 0)
2108      else                  m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));
2109          m_statusItem[QSAMPLER_STATUS_SESSION]->clear();          else
2110                    m_statusItem[QSAMPLER_STATUS_SESSION]->clear();
2111    
2112      // Recent files menu.          // Recent files menu.
2113          ui.fileOpenRecentMenu->setEnabled(m_pOptions->recentFiles.count() > 0);          m_ui.fileOpenRecentMenu->setEnabled(m_pOptions->recentFiles.count() > 0);
2114  }  }
2115    
2116    
# Line 1825  void MainForm::volumeChanged ( int iVolu Line 2131  void MainForm::volumeChanged ( int iVolu
2131                  m_pVolumeSpinBox->setValue(iVolume);                  m_pVolumeSpinBox->setValue(iVolume);
2132    
2133          // Do it as commanded...          // Do it as commanded...
2134          float fVolume = 0.01f * float(iVolume);          const float fVolume = 0.01f * float(iVolume);
2135          if (::lscp_set_volume(m_pClient, fVolume) == LSCP_OK)          if (::lscp_set_volume(m_pClient, fVolume) == LSCP_OK)
2136                  appendMessages(QObject::tr("Volume: %1.").arg(fVolume));                  appendMessages(QObject::tr("Volume: %1.").arg(fVolume));
2137          else          else
# Line 1841  void MainForm::volumeChanged ( int iVolu Line 2147  void MainForm::volumeChanged ( int iVolu
2147    
2148    
2149  // Channel change receiver slot.  // Channel change receiver slot.
2150  void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)  void MainForm::channelStripChanged ( ChannelStrip *pChannelStrip )
2151  {  {
2152          // Add this strip to the changed list...          // Add this strip to the changed list...
2153          if (!m_changedStrips.contains(pChannelStrip)) {          if (!m_changedStrips.contains(pChannelStrip)) {
# Line 1849  void MainForm::channelStripChanged(Chann Line 2155  void MainForm::channelStripChanged(Chann
2155                  pChannelStrip->resetErrorCount();                  pChannelStrip->resetErrorCount();
2156          }          }
2157    
2158      // Just mark the dirty form.          // Just mark the dirty form.
2159      m_iDirtyCount++;          m_iDirtyCount++;
2160      // and update the form status...          // and update the form status...
2161      stabilizeForm();          stabilizeForm();
2162  }  }
2163    
2164    
# Line 1860  void MainForm::channelStripChanged(Chann Line 2166  void MainForm::channelStripChanged(Chann
2166  void MainForm::updateSession (void)  void MainForm::updateSession (void)
2167  {  {
2168  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2169          int iVolume = ::lroundf(100.0f * ::lscp_get_volume(m_pClient));          const int iVolume = ::lroundf(100.0f * ::lscp_get_volume(m_pClient));
2170          m_iVolumeChanging++;          m_iVolumeChanging++;
2171          m_pVolumeSlider->setValue(iVolume);          m_pVolumeSlider->setValue(iVolume);
2172          m_pVolumeSpinBox->setValue(iVolume);          m_pVolumeSpinBox->setValue(iVolume);
# Line 1868  void MainForm::updateSession (void) Line 2174  void MainForm::updateSession (void)
2174  #endif  #endif
2175  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
2176          // FIXME: Make some room for default instrument maps...          // FIXME: Make some room for default instrument maps...
2177          int iMaps = ::lscp_get_midi_instrument_maps(m_pClient);          const int iMaps = ::lscp_get_midi_instrument_maps(m_pClient);
2178          if (iMaps < 0)          if (iMaps < 0)
2179                  appendMessagesClient("lscp_get_midi_instrument_maps");                  appendMessagesClient("lscp_get_midi_instrument_maps");
2180          else if (iMaps < 1) {          else if (iMaps < 1) {
# Line 1879  void MainForm::updateSession (void) Line 2185  void MainForm::updateSession (void)
2185          }          }
2186  #endif  #endif
2187    
2188            updateAllChannelStrips(false);
2189    
2190            // Do we auto-arrange?
2191            channelsArrangeAuto();
2192    
2193            // Remember to refresh devices and instruments...
2194            if (m_pInstrumentListForm)
2195                    m_pInstrumentListForm->refreshInstruments();
2196            if (m_pDeviceForm)
2197                    m_pDeviceForm->refreshDevices();
2198    }
2199    
2200    
2201    void MainForm::updateAllChannelStrips ( bool bRemoveDeadStrips )
2202    {
2203            // Skip if setting up a new channel strip...
2204            if (m_iDirtySetup > 0)
2205                    return;
2206    
2207          // Retrieve the current channel list.          // Retrieve the current channel list.
2208          int *piChannelIDs = ::lscp_list_channels(m_pClient);          int *piChannelIDs = ::lscp_list_channels(m_pClient);
2209          if (piChannelIDs == NULL) {          if (piChannelIDs == NULL) {
2210                  if (::lscp_client_get_errno(m_pClient)) {                  if (::lscp_client_get_errno(m_pClient)) {
2211                          appendMessagesClient("lscp_list_channels");                          appendMessagesClient("lscp_list_channels");
2212                          appendMessagesError(tr("Could not get current list of channels.\n\nSorry."));                          appendMessagesError(
2213                                    tr("Could not get current list of channels.\n\nSorry."));
2214                  }                  }
2215          } else {          } else {
2216                  // Try to (re)create each channel.                  // Try to (re)create each channel.
2217                  m_pWorkspace->setUpdatesEnabled(false);                  m_pWorkspace->setUpdatesEnabled(false);
2218                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; ++iChannel) {
2219                          // Check if theres already a channel strip for this one...                          // Check if theres already a channel strip for this one...
2220                          if (!channelStrip(piChannelIDs[iChannel]))                          if (!channelStrip(piChannelIDs[iChannel]))
2221                                  createChannelStrip(new qsamplerChannel(piChannelIDs[iChannel]));                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));
2222                    }
2223                    // Do we auto-arrange?
2224                    channelsArrangeAuto();
2225                    // remove dead channel strips
2226                    if (bRemoveDeadStrips) {
2227                            const QList<QMdiSubWindow *>& wlist
2228                                    = m_pWorkspace->subWindowList();
2229                            const int iStripCount = wlist.count();
2230                            for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
2231                                    ChannelStrip *pChannelStrip = NULL;
2232                                    QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2233                                    if (pMdiSubWindow)
2234                                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2235                                    if (pChannelStrip) {
2236                                            bool bExists = false;
2237                                            for (int iChannel = 0; piChannelIDs[iChannel] >= 0; ++iChannel) {
2238                                                    Channel *pChannel = pChannelStrip->channel();
2239                                                    if (pChannel == NULL)
2240                                                            break;
2241                                                    if (piChannelIDs[iChannel] == pChannel->channelID()) {
2242                                                            // strip exists, don't touch it
2243                                                            bExists = true;
2244                                                            break;
2245                                                    }
2246                                            }
2247                                            if (!bExists)
2248                                                    destroyChannelStrip(pChannelStrip);
2249                                    }
2250                            }
2251                  }                  }
2252                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
2253          }          }
2254    
2255      // 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();  
2256  }  }
2257    
2258    
2259  // Update the recent files list and menu.  // Update the recent files list and menu.
2260  void MainForm::updateRecentFiles ( const QString& sFilename )  void MainForm::updateRecentFiles ( const QString& sFilename )
2261  {  {
2262      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2263          return;                  return;
2264    
2265      // Remove from list if already there (avoid duplicates)          // Remove from list if already there (avoid duplicates)
2266      int iIndex = m_pOptions->recentFiles.indexOf(sFilename);          const int iIndex = m_pOptions->recentFiles.indexOf(sFilename);
2267      if (iIndex >= 0)          if (iIndex >= 0)
2268          m_pOptions->recentFiles.removeAt(iIndex);                  m_pOptions->recentFiles.removeAt(iIndex);
2269      // Put it to front...          // Put it to front...
2270      m_pOptions->recentFiles.push_front(sFilename);          m_pOptions->recentFiles.push_front(sFilename);
2271  }  }
2272    
2273    
# Line 1938  void MainForm::updateRecentFilesMenu (vo Line 2285  void MainForm::updateRecentFilesMenu (vo
2285          }          }
2286    
2287          // Rebuild the recent files menu...          // Rebuild the recent files menu...
2288          ui.fileOpenRecentMenu->clear();          m_ui.fileOpenRecentMenu->clear();
2289          for (int i = 0; i < iRecentFiles; i++) {          for (int i = 0; i < iRecentFiles; i++) {
2290                  const QString& sFilename = m_pOptions->recentFiles[i];                  const QString& sFilename = m_pOptions->recentFiles[i];
2291                  if (QFileInfo(sFilename).exists()) {                  if (QFileInfo(sFilename).exists()) {
2292                          QAction *pAction = ui.fileOpenRecentMenu->addAction(                          QAction *pAction = m_ui.fileOpenRecentMenu->addAction(
2293                                  QString("&%1 %2").arg(i + 1).arg(sessionName(sFilename)),                                  QString("&%1 %2").arg(i + 1).arg(sessionName(sFilename)),
2294                                  this, SLOT(fileOpenRecent()));                                  this, SLOT(fileOpenRecent()));
2295                          pAction->setData(i);                          pAction->setData(i);
# Line 1954  void MainForm::updateRecentFilesMenu (vo Line 2301  void MainForm::updateRecentFilesMenu (vo
2301  // Force update of the channels instrument names mode.  // Force update of the channels instrument names mode.
2302  void MainForm::updateInstrumentNames (void)  void MainForm::updateInstrumentNames (void)
2303  {  {
2304      // Full channel list update...          // Full channel list update...
2305      QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2306      if (wlist.isEmpty())                  = m_pWorkspace->subWindowList();
2307          return;          if (wlist.isEmpty())
2308                    return;
2309      m_pWorkspace->setUpdatesEnabled(false);  
2310      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          m_pWorkspace->setUpdatesEnabled(false);
2311          ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);          const int iStripCount = wlist.count();
2312          if (pChannelStrip)          for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
2313              pChannelStrip->updateInstrumentName(true);                  ChannelStrip *pChannelStrip = NULL;
2314      }                  QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2315      m_pWorkspace->setUpdatesEnabled(true);                  if (pMdiSubWindow)
2316                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2317                    if (pChannelStrip)
2318                            pChannelStrip->updateInstrumentName(true);
2319            }
2320            m_pWorkspace->setUpdatesEnabled(true);
2321  }  }
2322    
2323    
2324  // Force update of the channels display font.  // Force update of the channels display font.
2325  void MainForm::updateDisplayFont (void)  void MainForm::updateDisplayFont (void)
2326  {  {
2327      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2328          return;                  return;
2329    
2330      // Check if display font is legal.          // Check if display font is legal.
2331      if (m_pOptions->sDisplayFont.isEmpty())          if (m_pOptions->sDisplayFont.isEmpty())
2332          return;                  return;
2333      // Realize it.  
2334      QFont font;          // Realize it.
2335      if (!font.fromString(m_pOptions->sDisplayFont))          QFont font;
2336          return;          if (!font.fromString(m_pOptions->sDisplayFont))
2337                    return;
2338      // Full channel list update...  
2339      QWidgetList wlist = m_pWorkspace->windowList();          // Full channel list update...
2340      if (wlist.isEmpty())          const QList<QMdiSubWindow *>& wlist
2341          return;                  = m_pWorkspace->subWindowList();
2342            if (wlist.isEmpty())
2343      m_pWorkspace->setUpdatesEnabled(false);                  return;
2344      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {  
2345          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);          m_pWorkspace->setUpdatesEnabled(false);
2346          if (pChannelStrip)          const int iStripCount = wlist.count();
2347              pChannelStrip->setDisplayFont(font);          for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
2348      }                  ChannelStrip *pChannelStrip = NULL;
2349      m_pWorkspace->setUpdatesEnabled(true);                  QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2350                    if (pMdiSubWindow)
2351                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2352                    if (pChannelStrip)
2353                            pChannelStrip->setDisplayFont(font);
2354            }
2355            m_pWorkspace->setUpdatesEnabled(true);
2356  }  }
2357    
2358    
2359  // Update channel strips background effect.  // Update channel strips background effect.
2360  void MainForm::updateDisplayEffect (void)  void MainForm::updateDisplayEffect (void)
2361  {  {
2362      // Full channel list update...          // Full channel list update...
2363      QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2364      if (wlist.isEmpty())                  = m_pWorkspace->subWindowList();
2365          return;          if (wlist.isEmpty())
2366                    return;
2367      m_pWorkspace->setUpdatesEnabled(false);  
2368      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          m_pWorkspace->setUpdatesEnabled(false);
2369          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);          const int iStripCount = wlist.count();
2370            for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
2371                    ChannelStrip *pChannelStrip = NULL;
2372                    QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2373                    if (pMdiSubWindow)
2374                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2375                  if (pChannelStrip)                  if (pChannelStrip)
2376                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2377      }          }
2378      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2379  }  }
2380    
2381    
2382  // Force update of the channels maximum volume setting.  // Force update of the channels maximum volume setting.
2383  void MainForm::updateMaxVolume (void)  void MainForm::updateMaxVolume (void)
2384  {  {
2385      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2386          return;                  return;
2387    
2388  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2389          m_iVolumeChanging++;          m_iVolumeChanging++;
# Line 2029  void MainForm::updateMaxVolume (void) Line 2392  void MainForm::updateMaxVolume (void)
2392          m_iVolumeChanging--;          m_iVolumeChanging--;
2393  #endif  #endif
2394    
2395      // Full channel list update...          // Full channel list update...
2396      QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2397      if (wlist.isEmpty())                  = m_pWorkspace->subWindowList();
2398          return;          if (wlist.isEmpty())
2399                    return;
2400      m_pWorkspace->setUpdatesEnabled(false);  
2401      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          m_pWorkspace->setUpdatesEnabled(false);
2402          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);          const int iStripCount = wlist.count();
2403          if (pChannelStrip)          for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
2404              pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                  ChannelStrip *pChannelStrip = NULL;
2405      }                  QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2406      m_pWorkspace->setUpdatesEnabled(true);                  if (pMdiSubWindow)
2407                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2408                    if (pChannelStrip)
2409                            pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2410            }
2411            m_pWorkspace->setUpdatesEnabled(true);
2412  }  }
2413    
2414    
2415  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2416  // qsamplerMainForm -- Messages window form handlers.  // QSampler::MainForm -- Messages window form handlers.
2417    
2418  // Messages output methods.  // Messages output methods.
2419  void MainForm::appendMessages( const QString& s )  void MainForm::appendMessages( const QString& s )
2420  {  {
2421      if (m_pMessages)          if (m_pMessages)
2422          m_pMessages->appendMessages(s);                  m_pMessages->appendMessages(s);
2423    
2424      statusBar()->showMessage(s, 3000);          statusBar()->showMessage(s, 3000);
2425  }  }
2426    
2427  void MainForm::appendMessagesColor( const QString& s, const QString& c )  void MainForm::appendMessagesColor( const QString& s, const QString& c )
2428  {  {
2429      if (m_pMessages)          if (m_pMessages)
2430          m_pMessages->appendMessagesColor(s, c);                  m_pMessages->appendMessagesColor(s, c);
2431    
2432      statusBar()->showMessage(s, 3000);          statusBar()->showMessage(s, 3000);
2433  }  }
2434    
2435  void MainForm::appendMessagesText( const QString& s )  void MainForm::appendMessagesText( const QString& s )
2436  {  {
2437      if (m_pMessages)          if (m_pMessages)
2438          m_pMessages->appendMessagesText(s);                  m_pMessages->appendMessagesText(s);
2439  }  }
2440    
2441  void MainForm::appendMessagesError( const QString& s )  void MainForm::appendMessagesError( const QString& sText )
2442  {  {
2443      if (m_pMessages)          if (m_pMessages)
2444          m_pMessages->show();                  m_pMessages->show();
2445    
2446      appendMessagesColor(s.simplified(), "#ff0000");          appendMessagesColor(sText.simplified(), "#ff0000");
2447    
2448          // Make it look responsive...:)          // Make it look responsive...:)
2449          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2450    
2451      QMessageBox::critical(this,          if (m_pOptions && m_pOptions->bConfirmError) {
2452                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));                  const QString& sTitle = QSAMPLER_TITLE ": " + tr("Error");
2453            #if 0
2454                    QMessageBox::critical(this, sTitle, sText, QMessageBox::Cancel);
2455            #else
2456                    QMessageBox mbox(this);
2457                    mbox.setIcon(QMessageBox::Critical);
2458                    mbox.setWindowTitle(sTitle);
2459                    mbox.setText(sText);
2460                    mbox.setStandardButtons(QMessageBox::Cancel);
2461                    QCheckBox cbox(tr("Don't show this again"));
2462                    cbox.setChecked(false);
2463                    cbox.blockSignals(true);
2464                    mbox.addButton(&cbox, QMessageBox::ActionRole);
2465                    if (mbox.exec() && cbox.isChecked())
2466                            m_pOptions->bConfirmError = false;
2467            #endif
2468            }
2469  }  }
2470    
2471    
2472  // This is a special message format, just for client results.  // This is a special message format, just for client results.
2473  void MainForm::appendMessagesClient( const QString& s )  void MainForm::appendMessagesClient( const QString& s )
2474  {  {
2475      if (m_pClient == NULL)          if (m_pClient == NULL)
2476          return;                  return;
2477    
2478      appendMessagesColor(s + QString(": %1 (errno=%2)")          appendMessagesColor(s + QString(": %1 (errno=%2)")
2479          .arg(::lscp_client_get_result(m_pClient))                  .arg(::lscp_client_get_result(m_pClient))
2480          .arg(::lscp_client_get_errno(m_pClient)), "#996666");                  .arg(::lscp_client_get_errno(m_pClient)), "#996666");
2481    
2482          // Make it look responsive...:)          // Make it look responsive...:)
2483          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
# Line 2103  void MainForm::appendMessagesClient( con Line 2487  void MainForm::appendMessagesClient( con
2487  // Force update of the messages font.  // Force update of the messages font.
2488  void MainForm::updateMessagesFont (void)  void MainForm::updateMessagesFont (void)
2489  {  {
2490      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2491          return;                  return;
2492    
2493      if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {          if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {
2494          QFont font;                  QFont font;
2495          if (font.fromString(m_pOptions->sMessagesFont))                  if (font.fromString(m_pOptions->sMessagesFont))
2496              m_pMessages->setMessagesFont(font);                          m_pMessages->setMessagesFont(font);
2497      }          }
2498  }  }
2499    
2500    
2501  // Update messages window line limit.  // Update messages window line limit.
2502  void MainForm::updateMessagesLimit (void)  void MainForm::updateMessagesLimit (void)
2503  {  {
2504      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2505          return;                  return;
2506    
2507      if (m_pMessages) {          if (m_pMessages) {
2508          if (m_pOptions->bMessagesLimit)                  if (m_pOptions->bMessagesLimit)
2509              m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);                          m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);
2510          else                  else
2511              m_pMessages->setMessagesLimit(-1);                          m_pMessages->setMessagesLimit(-1);
2512      }          }
2513  }  }
2514    
2515    
2516  // Enablement of the messages capture feature.  // Enablement of the messages capture feature.
2517  void MainForm::updateMessagesCapture (void)  void MainForm::updateMessagesCapture (void)
2518  {  {
2519      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2520          return;                  return;
2521    
2522      if (m_pMessages)          if (m_pMessages)
2523          m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);                  m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);
2524  }  }
2525    
2526    
2527  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2528  // qsamplerMainForm -- MDI channel strip management.  // QSampler::MainForm -- MDI channel strip management.
2529    
2530  // The channel strip creation executive.  // The channel strip creation executive.
2531  ChannelStrip* MainForm::createChannelStrip(qsamplerChannel* pChannel)  ChannelStrip *MainForm::createChannelStrip ( Channel *pChannel )
2532  {  {
2533      if (m_pClient == NULL || pChannel == NULL)          if (m_pClient == NULL || pChannel == NULL)
2534          return NULL;                  return NULL;
2535    
2536      // Prepare for auto-arrange?          // Add a new channel itema...
2537      ChannelStrip* pChannelStrip = NULL;          ChannelStrip *pChannelStrip = new ChannelStrip();
2538      int y = 0;          if (pChannelStrip == NULL)
2539      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();  
                         }  
         }  
     }  
2540    
2541      // Add a new channel itema...          // Set some initial channel strip options...
2542      pChannelStrip = new ChannelStrip();          if (m_pOptions) {
2543      if (pChannelStrip == NULL)                  // Background display effect...
2544          return NULL;                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2545                    // We'll need a display font.
2546                    QFont font;
2547                    if (!m_pOptions->sDisplayFont.isEmpty() &&
2548                            font.fromString(m_pOptions->sDisplayFont))
2549                            pChannelStrip->setDisplayFont(font);
2550                    // Maximum allowed volume setting.
2551                    pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2552            }
2553    
2554            // Add it to workspace...
2555            m_pWorkspace->addSubWindow(pChannelStrip,
2556                    Qt::SubWindow | Qt::FramelessWindowHint);
2557    
2558      m_pWorkspace->addWindow(pChannelStrip, Qt::Tool);          // Actual channel strip setup...
2559            pChannelStrip->setup(pChannel);
2560    
     // Actual channel strip setup...  
     pChannelStrip->setup(pChannel);  
2561          QObject::connect(pChannelStrip,          QObject::connect(pChannelStrip,
2562                  SIGNAL(channelChanged(ChannelStrip*)),                  SIGNAL(channelChanged(ChannelStrip *)),
2563                  SLOT(channelStripChanged(ChannelStrip*)));                  SLOT(channelStripChanged(ChannelStrip *)));
2564      // Set some initial aesthetic options...  
2565      if (m_pOptions) {          // Now we show up us to the world.
2566          // 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);  
     }  
2567    
2568          // This is pretty new, so we'll watch for it closely.          // This is pretty new, so we'll watch for it closely.
2569          channelStripChanged(pChannelStrip);          channelStripChanged(pChannelStrip);
2570    
2571      // Return our successful reference...          // Return our successful reference...
2572      return pChannelStrip;          return pChannelStrip;
2573    }
2574    
2575    
2576    void MainForm::destroyChannelStrip ( ChannelStrip *pChannelStrip )
2577    {
2578            QMdiSubWindow *pMdiSubWindow
2579                    = static_cast<QMdiSubWindow *> (pChannelStrip->parentWidget());
2580            if (pMdiSubWindow == NULL)
2581                    return;
2582    
2583            // Just delete the channel strip.
2584            delete pChannelStrip;
2585            delete pMdiSubWindow;
2586    
2587            // Do we auto-arrange?
2588            channelsArrangeAuto();
2589  }  }
2590    
2591    
2592  // Retrieve the active channel strip.  // Retrieve the active channel strip.
2593  ChannelStrip* MainForm::activeChannelStrip (void)  ChannelStrip *MainForm::activeChannelStrip (void)
2594  {  {
2595      return static_cast<ChannelStrip *> (m_pWorkspace->activeWindow());          QMdiSubWindow *pMdiSubWindow = m_pWorkspace->activeSubWindow();
2596            if (pMdiSubWindow)
2597                    return static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2598            else
2599                    return NULL;
2600  }  }
2601    
2602    
2603  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
2604  ChannelStrip* MainForm::channelStripAt ( int iChannel )  ChannelStrip *MainForm::channelStripAt ( int iStrip )
2605  {  {
2606      QWidgetList wlist = m_pWorkspace->windowList();          if (!m_pWorkspace) return NULL;
     if (wlist.isEmpty())  
         return NULL;  
2607    
2608      return static_cast<ChannelStrip *> (wlist.at(iChannel));          const QList<QMdiSubWindow *>& wlist
2609                    = m_pWorkspace->subWindowList();
2610            if (wlist.isEmpty())
2611                    return NULL;
2612    
2613            if (iStrip < 0 || iStrip >= wlist.count())
2614                    return NULL;
2615    
2616            QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2617            if (pMdiSubWindow)
2618                    return static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2619            else
2620                    return NULL;
2621  }  }
2622    
2623    
2624  // Retrieve a channel strip by sampler channel id.  // Retrieve a channel strip by sampler channel id.
2625  ChannelStrip* MainForm::channelStrip ( int iChannelID )  ChannelStrip *MainForm::channelStrip ( int iChannelID )
2626  {  {
2627          QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2628                    = m_pWorkspace->subWindowList();
2629          if (wlist.isEmpty())          if (wlist.isEmpty())
2630                  return NULL;                  return NULL;
2631    
2632          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          const int iStripCount = wlist.count();
2633                  ChannelStrip* pChannelStrip          for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
2634                          = static_cast<ChannelStrip*> (wlist.at(iChannel));                  ChannelStrip *pChannelStrip = NULL;
2635                    QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2636                    if (pMdiSubWindow)
2637                            pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2638                  if (pChannelStrip) {                  if (pChannelStrip) {
2639                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
2640                          if (pChannel && pChannel->channelID() == iChannelID)                          if (pChannel && pChannel->channelID() == iChannelID)
2641                                  return pChannelStrip;                                  return pChannelStrip;
2642                  }                  }
# Line 2247  ChannelStrip* MainForm::channelStrip ( i Line 2650  ChannelStrip* MainForm::channelStrip ( i
2650  // Construct the windows menu.  // Construct the windows menu.
2651  void MainForm::channelsMenuAboutToShow (void)  void MainForm::channelsMenuAboutToShow (void)
2652  {  {
2653      ui.channelsMenu->clear();          m_ui.channelsMenu->clear();
2654          ui.channelsMenu->addAction(ui.channelsArrangeAction);          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);
2655          ui.channelsMenu->addAction(ui.channelsAutoArrangeAction);          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);
2656    
2657      QWidgetList wlist = m_pWorkspace->windowList();          const QList<QMdiSubWindow *>& wlist
2658      if (!wlist.isEmpty()) {                  = m_pWorkspace->subWindowList();
2659                  ui.channelsMenu->addSeparator();          if (!wlist.isEmpty()) {
2660          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  m_ui.channelsMenu->addSeparator();
2661                          ChannelStrip* pChannelStrip                  const int iStripCount = wlist.count();
2662                                  = static_cast<ChannelStrip*> (wlist.at(iChannel));                  for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
2663                            ChannelStrip *pChannelStrip = NULL;
2664                            QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2665                            if (pMdiSubWindow)
2666                                    pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2667                          if (pChannelStrip) {                          if (pChannelStrip) {
2668                                  QAction *pAction = ui.channelsMenu->addAction(                                  QAction *pAction = m_ui.channelsMenu->addAction(
2669                                          pChannelStrip->windowTitle(), this, SLOT(channelsMenuActivated()));                                          pChannelStrip->windowTitle(),
2670                                  pAction->setData(iChannel);                                          this, SLOT(channelsMenuActivated()));
2671                                    pAction->setCheckable(true);
2672                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);
2673                                    pAction->setData(iStrip);
2674                          }                          }
2675          }                  }
2676      }          }
2677  }  }
2678    
2679    
# Line 2276  void MainForm::channelsMenuActivated (vo Line 2685  void MainForm::channelsMenuActivated (vo
2685          if (pAction == NULL)          if (pAction == NULL)
2686                  return;                  return;
2687    
2688          ChannelStrip* pChannelStrip = channelStripAt(pAction->data().toInt());          ChannelStrip *pChannelStrip = channelStripAt(pAction->data().toInt());
2689          if (pChannelStrip) {          if (pChannelStrip) {
2690                  pChannelStrip->showNormal();                  pChannelStrip->showNormal();
2691                  pChannelStrip->setFocus();                  pChannelStrip->setFocus();
# Line 2285  void MainForm::channelsMenuActivated (vo Line 2694  void MainForm::channelsMenuActivated (vo
2694    
2695    
2696  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2697  // qsamplerMainForm -- Timer stuff.  // QSampler::MainForm -- Timer stuff.
2698    
2699  // Set the pseudo-timer delay schedule.  // Set the pseudo-timer delay schedule.
2700  void MainForm::startSchedule ( int iStartDelay )  void MainForm::startSchedule ( int iStartDelay )
2701  {  {
2702      m_iStartDelay  = 1 + (iStartDelay * 1000);          m_iStartDelay  = 1 + (iStartDelay * 1000);
2703      m_iTimerDelay  = 0;          m_iTimerDelay  = 0;
2704  }  }
2705    
2706  // Suspend the pseudo-timer delay schedule.  // Suspend the pseudo-timer delay schedule.
2707  void MainForm::stopSchedule (void)  void MainForm::stopSchedule (void)
2708  {  {
2709      m_iStartDelay  = 0;          m_iStartDelay  = 0;
2710      m_iTimerDelay  = 0;          m_iTimerDelay  = 0;
2711  }  }
2712    
2713  // Timer slot funtion.  // Timer slot funtion.
2714  void MainForm::timerSlot (void)  void MainForm::timerSlot (void)
2715  {  {
2716      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2717          return;                  return;
2718    
2719      // Is it the first shot on server start after a few delay?          // Is it the first shot on server start after a few delay?
2720      if (m_iTimerDelay < m_iStartDelay) {          if (m_iTimerDelay < m_iStartDelay) {
2721          m_iTimerDelay += QSAMPLER_TIMER_MSECS;                  m_iTimerDelay += QSAMPLER_TIMER_MSECS;
2722          if (m_iTimerDelay >= m_iStartDelay) {                  if (m_iTimerDelay >= m_iStartDelay) {
2723              // If we cannot start it now, maybe a lil'mo'later ;)                          // If we cannot start it now, maybe a lil'mo'later ;)
2724              if (!startClient()) {                          if (!startClient()) {
2725                  m_iStartDelay += m_iTimerDelay;                                  m_iStartDelay += m_iTimerDelay;
2726                  m_iTimerDelay  = 0;                                  m_iTimerDelay  = 0;
2727              }                          }
2728          }                  }
2729      }          }
2730    
2731          if (m_pClient) {          if (m_pClient) {
2732                  // Update the channel information for each pending strip...                  // Update the channel information for each pending strip...
# Line 2326  void MainForm::timerSlot (void) Line 2735  void MainForm::timerSlot (void)
2735                          ChannelStrip *pChannelStrip = iter.next();                          ChannelStrip *pChannelStrip = iter.next();
2736                          // If successfull, remove from pending list...                          // If successfull, remove from pending list...
2737                          if (pChannelStrip->updateChannelInfo()) {                          if (pChannelStrip->updateChannelInfo()) {
2738                                  int iChannelStrip = m_changedStrips.indexOf(pChannelStrip);                                  const int iChannelStrip = m_changedStrips.indexOf(pChannelStrip);
2739                                  if (iChannelStrip >= 0)                                  if (iChannelStrip >= 0)
2740                                          m_changedStrips.removeAt(iChannelStrip);                                          m_changedStrips.removeAt(iChannelStrip);
2741                          }                          }
# Line 2337  void MainForm::timerSlot (void) Line 2746  void MainForm::timerSlot (void)
2746                          if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime)  {                          if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime)  {
2747                                  m_iTimerSlot = 0;                                  m_iTimerSlot = 0;
2748                                  // Update the channel stream usage for each strip...                                  // Update the channel stream usage for each strip...
2749                                  QWidgetList wlist = m_pWorkspace->windowList();                                  const QList<QMdiSubWindow *>& wlist
2750                                  for (int iChannel = 0;                                          = m_pWorkspace->subWindowList();
2751                                                  iChannel < (int) wlist.count(); iChannel++) {                                  const int iStripCount = wlist.count();
2752                                          ChannelStrip* pChannelStrip                                  for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
2753                                                  = (ChannelStrip*) wlist.at(iChannel);                                          ChannelStrip *pChannelStrip = NULL;
2754                                            QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2755                                            if (pMdiSubWindow)
2756                                                    pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2757                                          if (pChannelStrip && pChannelStrip->isVisible())                                          if (pChannelStrip && pChannelStrip->isVisible())
2758                                                  pChannelStrip->updateChannelUsage();                                                  pChannelStrip->updateChannelUsage();
2759                                  }                                  }
# Line 2349  void MainForm::timerSlot (void) Line 2761  void MainForm::timerSlot (void)
2761                  }                  }
2762          }          }
2763    
2764      // Register the next timer slot.          // Register the next timer slot.
2765      QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));          QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
2766  }  }
2767    
2768    
2769  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2770  // qsamplerMainForm -- Server stuff.  // QSampler::MainForm -- Server stuff.
2771    
2772  // Start linuxsampler server...  // Start linuxsampler server...
2773  void MainForm::startServer (void)  void MainForm::startServer (void)
2774  {  {
2775      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2776          return;                  return;
2777    
2778      // Aren't already a client, are we?          // Aren't already a client, are we?
2779      if (!m_pOptions->bServerStart || m_pClient)          if (!m_pOptions->bServerStart || m_pClient)
2780          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()));  
2781    
2782      // Build process arguments...          // Is the server process instance still here?
2783      QStringList serverCmdLine = m_pOptions->sServerCmdLine.split(' ');          if (m_pServer) {
2784                    if (QMessageBox::warning(this,
2785                            QSAMPLER_TITLE ": " + tr("Warning"),
2786                            tr("Could not start the LinuxSampler server.\n\n"
2787                            "Maybe it is already started."),
2788                            QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
2789                            m_pServer->terminate();
2790                            m_pServer->kill();
2791                    }
2792                    return;
2793            }
2794    
2795      appendMessages(tr("Server is starting..."));          // Reset our timer counters...
2796      appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");          stopSchedule();
2797    
2798            // Verify we have something to start with...
2799            if (m_pOptions->sServerCmdLine.isEmpty())
2800                    return;
2801    
2802            // OK. Let's build the startup process...
2803            m_pServer = new QProcess();
2804            m_bForceServerStop = true;
2805    
2806      const QString prog = (serverCmdLine.size() > 0) ? serverCmdLine[0] : QString();          // Setup stdout/stderr capture...
2807      const QStringList args = serverCmdLine.mid(1);          m_pServer->setProcessChannelMode(QProcess::ForwardedChannels);
2808            QObject::connect(m_pServer,
2809                    SIGNAL(readyReadStandardOutput()),
2810                    SLOT(readServerStdout()));
2811            QObject::connect(m_pServer,
2812                    SIGNAL(readyReadStandardError()),
2813                    SLOT(readServerStdout()));
2814    
2815      // Go jack, go...          // The unforgiveable signal communication...
2816      m_pServer->start(prog, args);          QObject::connect(m_pServer,
2817      if (!m_pServer->waitForStarted()) {                  SIGNAL(finished(int, QProcess::ExitStatus)),
2818          appendMessagesError(tr("Could not start server.\n\nSorry."));                  SLOT(processServerExit()));
         processServerExit();  
         return;  
     }  
2819    
2820      // Show startup results...          // Build process arguments...
2821      appendMessages(tr("Server was started with PID=%1.").arg((long) m_pServer->pid()));          QStringList args = m_pOptions->sServerCmdLine.split(' ');
2822            QString sCommand = args[0];
2823            args.removeAt(0);
2824    
2825            appendMessages(tr("Server is starting..."));
2826            appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");
2827    
2828            // Go linuxsampler, go...
2829            m_pServer->start(sCommand, args);
2830            if (!m_pServer->waitForStarted()) {
2831                    appendMessagesError(tr("Could not start server.\n\nSorry."));
2832                    processServerExit();
2833                    return;
2834            }
2835    
2836      // Reset (yet again) the timer counters,          // Show startup results...
2837      // but this time is deferred as the user opted.          appendMessages(
2838      startSchedule(m_pOptions->iStartDelay);                  tr("Server was started with PID=%1.").arg((long) m_pServer->pid()));
2839      stabilizeForm();  
2840            // Reset (yet again) the timer counters,
2841            // but this time is deferred as the user opted.
2842            startSchedule(m_pOptions->iStartDelay);
2843            stabilizeForm();
2844  }  }
2845    
2846    
2847  // Stop linuxsampler server...  // Stop linuxsampler server...
2848  void MainForm::stopServer (void)  void MainForm::stopServer ( bool bInteractive )
2849  {  {
2850      // Stop client code.          // Stop client code.
2851      stopClient();          stopClient();
2852    
2853            if (m_pServer && bInteractive) {
2854                    if (QMessageBox::question(this,
2855                            QSAMPLER_TITLE ": " + tr("The backend's fate ..."),
2856                            tr("You have the option to keep the sampler backend (LinuxSampler)\n"
2857                            "running in the background. The sampler would continue to work\n"
2858                            "according to your current sampler session and you could alter the\n"
2859                            "sampler session at any time by relaunching QSampler.\n\n"
2860                            "Do you want LinuxSampler to stop?"),
2861                            QMessageBox::Yes | QMessageBox::No,
2862                            QMessageBox::Yes) == QMessageBox::No) {
2863                            m_bForceServerStop = false;
2864                    }
2865            }
2866    
2867      // And try to stop server.          // And try to stop server.
2868      if (m_pServer) {          if (m_pServer && m_bForceServerStop) {
2869          appendMessages(tr("Server is stopping..."));                  appendMessages(tr("Server is stopping..."));
2870          if (m_pServer->state() == QProcess::Running)                  if (m_pServer->state() == QProcess::Running) {
2871              m_pServer->terminate();                  #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
2872       }                          // Try harder...
2873                            m_pServer->kill();
2874      // Give it some time to terminate gracefully and stabilize...                  #else
2875      QTime t;                          // Try softly...
2876      t.start();                          m_pServer->terminate();
2877      while (t.elapsed() < QSAMPLER_TIMER_MSECS)                  #endif
2878          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);                  }
2879            }       // Do final processing anyway.
2880            else processServerExit();
2881    
2882       // Do final processing anyway.          // Give it some time to terminate gracefully and stabilize...
2883       processServerExit();          QTime t;
2884            t.start();
2885            while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2886                    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2887  }  }
2888    
2889    
2890  // Stdout handler...  // Stdout handler...
2891  void MainForm::readServerStdout (void)  void MainForm::readServerStdout (void)
2892  {  {
2893      if (m_pMessages)          if (m_pMessages)
2894          m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());                  m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());
2895  }  }
2896    
2897    
2898  // Linuxsampler server cleanup.  // Linuxsampler server cleanup.
2899  void MainForm::processServerExit (void)  void MainForm::processServerExit (void)
2900  {  {
2901      // Force client code cleanup.          // Force client code cleanup.
2902      stopClient();          stopClient();
2903    
2904      // Flush anything that maybe pending...          // Flush anything that maybe pending...
2905      if (m_pMessages)          if (m_pMessages)
2906          m_pMessages->flushStdoutBuffer();                  m_pMessages->flushStdoutBuffer();
2907    
2908      if (m_pServer) {          if (m_pServer && m_bForceServerStop) {
2909          // Force final server shutdown...                  if (m_pServer->state() != QProcess::NotRunning) {
2910          appendMessages(tr("Server was stopped with exit status %1.").arg(m_pServer->exitStatus()));                          appendMessages(tr("Server is being forced..."));
2911          m_pServer->terminate();                          // Force final server shutdown...
2912          if (!m_pServer->waitForFinished(2000))                          m_pServer->kill();
2913              m_pServer->kill();                          // Give it some time to terminate gracefully and stabilize...
2914          // Destroy it.                          QTime t;
2915          delete m_pServer;                          t.start();
2916          m_pServer = NULL;                          while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2917      }                                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2918                    }
2919                    // Force final server shutdown...
2920                    appendMessages(
2921                            tr("Server was stopped with exit status %1.")
2922                            .arg(m_pServer->exitStatus()));
2923                    delete m_pServer;
2924                    m_pServer = NULL;
2925            }
2926    
2927      // Again, make status visible stable.          // Again, make status visible stable.
2928      stabilizeForm();          stabilizeForm();
2929  }  }
2930    
2931    
2932  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2933  // qsamplerMainForm -- Client stuff.  // QSampler::MainForm -- Client stuff.
2934    
2935  // The LSCP client callback procedure.  // The LSCP client callback procedure.
2936  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*/,
2937            lscp_event_t event, const char *pchData, int cchData, void *pvData )
2938  {  {
2939      MainForm* pMainForm = (MainForm *) pvData;          MainForm* pMainForm = (MainForm *) pvData;
2940      if (pMainForm == NULL)          if (pMainForm == NULL)
2941          return LSCP_FAILED;                  return LSCP_FAILED;
2942    
2943      // ATTN: DO NOT EVER call any GUI code here,          // ATTN: DO NOT EVER call any GUI code here,
2944      // as this is run under some other thread context.          // as this is run under some other thread context.
2945      // A custom event must be posted here...          // A custom event must be posted here...
2946      QApplication::postEvent(pMainForm, new qsamplerCustomEvent(event, pchData, cchData));          QApplication::postEvent(pMainForm,
2947                    new LscpEvent(event, pchData, cchData));
2948    
2949      return LSCP_OK;          return LSCP_OK;
2950  }  }
2951    
2952    
2953  // Start our almighty client...  // Start our almighty client...
2954  bool MainForm::startClient (void)  bool MainForm::startClient (void)
2955  {  {
2956      // Have it a setup?          // Have it a setup?
2957      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2958          return false;                  return false;
   
     // Aren't we already started, are we?  
     if (m_pClient)  
         return true;  
2959    
2960      // Log prepare here.          // Aren't we already started, are we?
2961      appendMessages(tr("Client connecting..."));          if (m_pClient)
2962                    return true;
2963    
2964      // Create the client handle...          // Log prepare here.
2965            appendMessages(tr("Client connecting..."));
2966    
2967            // Create the client handle...
2968          m_pClient = ::lscp_client_create(          m_pClient = ::lscp_client_create(
2969                  m_pOptions->sServerHost.toUtf8().constData(),                  m_pOptions->sServerHost.toUtf8().constData(),
2970                  m_pOptions->iServerPort, qsampler_client_callback, this);                  m_pOptions->iServerPort, qsampler_client_callback, this);
2971      if (m_pClient == NULL) {          if (m_pClient == NULL) {
2972          // Is this the first try?                  // Is this the first try?
2973          // maybe we need to start a local server...                  // maybe we need to start a local server...
2974          if ((m_pServer && m_pServer->state() == QProcess::Running) || !m_pOptions->bServerStart)                  if ((m_pServer && m_pServer->state() == QProcess::Running)
2975              appendMessagesError(tr("Could not connect to server as client.\n\nSorry."));                          || !m_pOptions->bServerStart) {
2976          else                          appendMessagesError(
2977              startServer();                                  tr("Could not connect to server as client.\n\nSorry."));
2978          // This is always a failure.                  } else {
2979          stabilizeForm();                          startServer();
2980          return false;                  }
2981      }                  // This is always a failure.
2982      // Just set receive timeout value, blindly.                  stabilizeForm();
2983      ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);                  return false;
2984      appendMessages(tr("Client receive timeout is set to %1 msec.").arg(::lscp_client_get_timeout(m_pClient)));          }
2985    
2986            // Just set receive timeout value, blindly.
2987            ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);
2988            appendMessages(
2989                    tr("Client receive timeout is set to %1 msec.")
2990                    .arg(::lscp_client_get_timeout(m_pClient)));
2991    
2992          // Subscribe to channel info change notifications...          // Subscribe to channel info change notifications...
2993            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT) != LSCP_OK)
2994                    appendMessagesClient("lscp_client_subscribe(CHANNEL_COUNT)");
2995          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)
2996                  appendMessagesClient("lscp_client_subscribe");                  appendMessagesClient("lscp_client_subscribe(CHANNEL_INFO)");
2997    
2998      // We may stop scheduling around.          DeviceStatusForm::onDevicesChanged(); // initialize
2999      stopSchedule();          updateViewMidiDeviceStatusMenu();
3000            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT) != LSCP_OK)
3001                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_COUNT)");
3002            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO) != LSCP_OK)
3003                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_INFO)");
3004            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT) != LSCP_OK)
3005                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_COUNT)");
3006            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO) != LSCP_OK)
3007                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_INFO)");
3008    
3009    #if CONFIG_EVENT_CHANNEL_MIDI
3010            // Subscribe to channel MIDI data notifications...
3011            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI) != LSCP_OK)
3012                    appendMessagesClient("lscp_client_subscribe(CHANNEL_MIDI)");
3013    #endif
3014    
3015    #if CONFIG_EVENT_DEVICE_MIDI
3016            // Subscribe to channel MIDI data notifications...
3017            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI) != LSCP_OK)
3018                    appendMessagesClient("lscp_client_subscribe(DEVICE_MIDI)");
3019    #endif
3020    
3021            // We may stop scheduling around.
3022            stopSchedule();
3023    
3024      // We'll accept drops from now on...          // We'll accept drops from now on...
3025      setAcceptDrops(true);          setAcceptDrops(true);
3026    
3027      // Log success here.          // Log success here.
3028      appendMessages(tr("Client connected."));          appendMessages(tr("Client connected."));
3029    
3030          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
3031          // if visible, that we're ready...          // if visible, that we're ready...
3032          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
3033              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
3034          if (m_pDeviceForm)          if (m_pDeviceForm)
3035              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
3036    
3037            // Is any session pending to be loaded?
3038            if (!m_pOptions->sSessionFile.isEmpty()) {
3039                    // Just load the prabably startup session...
3040                    if (loadSessionFile(m_pOptions->sSessionFile)) {
3041                            m_pOptions->sSessionFile = QString::null;
3042                            return true;
3043                    }
3044            }
3045    
3046      // Is any session pending to be loaded?          // send the current / loaded fine tuning settings to the sampler
3047      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;  
         }  
     }  
3048    
3049      // Make a new session          // Make a new session
3050      return newSession();          return newSession();
3051  }  }
3052    
3053    
3054  // Stop client...  // Stop client...
3055  void MainForm::stopClient (void)  void MainForm::stopClient (void)
3056  {  {
3057      if (m_pClient == NULL)          if (m_pClient == NULL)
3058          return;                  return;
   
     // Log prepare here.  
     appendMessages(tr("Client disconnecting..."));  
3059    
3060      // Clear timer counters...          // Log prepare here.
3061      stopSchedule();          appendMessages(tr("Client disconnecting..."));
3062    
3063      // We'll reject drops from now on...          // Clear timer counters...
3064      setAcceptDrops(false);          stopSchedule();
3065    
3066      // Force any channel strips around, but          // We'll reject drops from now on...
3067      // but avoid removing the corresponding          setAcceptDrops(false);
     // channels from the back-end server.  
     m_iDirtyCount = 0;  
     closeSession(false);  
3068    
3069      // Close us as a client...          // Force any channel strips around, but
3070            // but avoid removing the corresponding
3071            // channels from the back-end server.
3072            m_iDirtyCount = 0;
3073            closeSession(false);
3074    
3075            // Close us as a client...
3076    #if CONFIG_EVENT_DEVICE_MIDI
3077            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI);
3078    #endif
3079    #if CONFIG_EVENT_CHANNEL_MIDI
3080            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI);
3081    #endif
3082            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
3083            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
3084            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
3085            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
3086          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
3087      ::lscp_client_destroy(m_pClient);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT);
3088      m_pClient = NULL;          ::lscp_client_destroy(m_pClient);
3089            m_pClient = NULL;
3090    
3091          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
3092          // if visible, that we're running out...          // if visible, that we're running out...
3093          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
3094              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
3095          if (m_pDeviceForm)          if (m_pDeviceForm)
3096              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
3097    
3098            // Log final here.
3099            appendMessages(tr("Client disconnected."));
3100    
3101            // Make visible status.
3102            stabilizeForm();
3103    }
3104    
     // Log final here.  
     appendMessages(tr("Client disconnected."));  
3105    
3106      // Make visible status.  // Channel strip activation/selection.
3107      stabilizeForm();  void MainForm::activateStrip ( QMdiSubWindow *pMdiSubWindow )
3108    {
3109            ChannelStrip *pChannelStrip = NULL;
3110            if (pMdiSubWindow)
3111                    pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
3112            if (pChannelStrip)
3113                    pChannelStrip->setSelected(true);
3114    
3115            stabilizeForm();
3116    }
3117    
3118    
3119    // Channel toolbar orientation change.
3120    void MainForm::channelsToolbarOrientation ( Qt::Orientation orientation )
3121    {
3122    #ifdef CONFIG_VOLUME
3123            m_pVolumeSlider->setOrientation(orientation);
3124            if (orientation == Qt::Horizontal) {
3125                    m_pVolumeSlider->setMinimumHeight(24);
3126                    m_pVolumeSlider->setMaximumHeight(32);
3127                    m_pVolumeSlider->setMinimumWidth(120);
3128                    m_pVolumeSlider->setMaximumWidth(640);
3129                    m_pVolumeSpinBox->setMaximumWidth(64);
3130                    m_pVolumeSpinBox->setButtonSymbols(QSpinBox::UpDownArrows);
3131            } else {
3132                    m_pVolumeSlider->setMinimumHeight(120);
3133                    m_pVolumeSlider->setMaximumHeight(480);
3134                    m_pVolumeSlider->setMinimumWidth(24);
3135                    m_pVolumeSlider->setMaximumWidth(32);
3136                    m_pVolumeSpinBox->setMaximumWidth(32);
3137                    m_pVolumeSpinBox->setButtonSymbols(QSpinBox::NoButtons);
3138            }
3139    #endif
3140  }  }
3141    
3142    
3143  } // namespace QSampler  } // namespace QSampler
3144    
3145    

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

  ViewVC Help
Powered by ViewVC