/[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 1470 by schoenebeck, Sun Nov 4 23:37:47 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 <qapplication.h>  
 #include <qeventloop.h>  
 #include <qworkspace.h>  
 #include <qprocess.h>  
 #include <qmessagebox.h>  
 //#include <qdragobject.h>  
 #include <qregexp.h>  
 #include <qfiledialog.h>  
 #include <qfileinfo.h>  
 #include <qfile.h>  
 #include <qtextstream.h>  
 #include <qstatusbar.h>  
 #include <qslider.h>  
 #include <qspinbox.h>  
 #include <qlabel.h>  
 #include <qtimer.h>  
 #include <qtooltip.h>  
   
 #include "qsamplerAbout.h"  
26  #include "qsamplerOptions.h"  #include "qsamplerOptions.h"
27  #include "qsamplerChannel.h"  #include "qsamplerChannel.h"
28  #include "qsamplerMessages.h"  #include "qsamplerMessages.h"
# Line 51  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>
42    #include <QProcess>
43    #include <QMessageBox>
44    
45    #include <QRegExp>
46    #include <QTextStream>
47    #include <QFileDialog>
48    #include <QFileInfo>
49    #include <QFile>
50    #include <QUrl>
51    
52    #include <QDragEnterEvent>
53    
54    #include <QStatusBar>
55    #include <QSpinBox>
56    #include <QSlider>
57    #include <QLabel>
58    #include <QTimer>
59    #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 73  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 83  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.
   
 #define QSAMPLER_CUSTOM_EVENT   QEvent::Type(QEvent::User + 0)  
147    
148  class qsamplerCustomEvent : public QEvent  class LscpEvent : 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.setLatin1(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  namespace QSampler {  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    
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->setTickmarks(QSlider::Below);          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->setRange(0, 100);          m_pVolumeSlider->setSingleStep(10);
269            m_pVolumeSlider->setMinimum(0);
270            m_pVolumeSlider->setMaximum(100);
271          m_pVolumeSlider->setMaximumHeight(26);          m_pVolumeSlider->setMaximumHeight(26);
272          m_pVolumeSlider->setMinimumWidth(160);          m_pVolumeSlider->setMinimumWidth(160);
273          QToolTip::add(m_pVolumeSlider, sVolumeText);          m_pVolumeSlider->setToolTip(sVolumeText);
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->setRange(0, 100);          m_pVolumeSpinBox->setMinimum(0);
283          QToolTip::add(m_pVolumeSpinBox, sVolumeText);          m_pVolumeSpinBox->setMaximum(100);
284            m_pVolumeSpinBox->setToolTip(sVolumeText);
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...
303            QLabel *pLabel;
304            // Client status.
305            pLabel = new QLabel(tr("Connected"), this);
306            pLabel->setAlignment(Qt::AlignLeft);
307            pLabel->setMinimumSize(pLabel->sizeHint());
308            m_statusItem[QSAMPLER_STATUS_CLIENT] = pLabel;
309            statusBar()->addWidget(pLabel);
310            // Server address.
311            pLabel = new QLabel(this);
312            pLabel->setAlignment(Qt::AlignLeft);
313            m_statusItem[QSAMPLER_STATUS_SERVER] = pLabel;
314            statusBar()->addWidget(pLabel, 1);
315            // Channel title.
316            pLabel = new QLabel(this);
317            pLabel->setAlignment(Qt::AlignLeft);
318            m_statusItem[QSAMPLER_STATUS_CHANNEL] = pLabel;
319            statusBar()->addWidget(pLabel, 2);
320            // Session modification status.
321            pLabel = new QLabel(tr("MOD"), this);
322            pLabel->setAlignment(Qt::AlignHCenter);
323            pLabel->setMinimumSize(pLabel->sizeHint());
324            m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;
325            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      // Create some statusbar labels...          QObject::connect(m_ui.fileNewAction,
337      QLabel *pLabel;                  SIGNAL(triggered()),
     // Client status.  
     pLabel = new QLabel(tr("Connected"), this);  
     pLabel->setAlignment(Qt::AlignLeft);  
     pLabel->setMinimumSize(pLabel->sizeHint());  
     m_statusItem[QSAMPLER_STATUS_CLIENT] = pLabel;  
     statusBar()->addWidget(pLabel);  
     // Server address.  
     pLabel = new QLabel(this);  
     pLabel->setAlignment(Qt::AlignLeft);  
     m_statusItem[QSAMPLER_STATUS_SERVER] = pLabel;  
     statusBar()->addWidget(pLabel, 1);  
     // Channel title.  
     pLabel = new QLabel(this);  
     pLabel->setAlignment(Qt::AlignLeft);  
     m_statusItem[QSAMPLER_STATUS_CHANNEL] = pLabel;  
     statusBar()->addWidget(pLabel, 2);  
     // Session modification status.  
     pLabel = new QLabel(tr("MOD"), this);  
     pLabel->setAlignment(Qt::AlignHCenter);  
     pLabel->setMinimumSize(pLabel->sizeHint());  
     m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;  
     statusBar()->addWidget(pLabel);  
   
     // Create the recent files sub-menu.  
     m_pRecentFilesMenu = new Q3PopupMenu(this);  
     ui.fileMenu->insertSeparator(4);  
     ui.fileMenu->insertItem(tr("Recent &Files"), m_pRecentFilesMenu, 0, 5);  
   
 #if defined(WIN32)  
     WSAStartup(MAKEWORD(1, 1), &_wsaData);  
 #endif  
   
         QObject::connect(ui.fileNewAction,  
                 SIGNAL(activated()),  
338                  SLOT(fileNew()));                  SLOT(fileNew()));
339          QObject::connect(ui.fileOpenAction,          QObject::connect(m_ui.fileOpenAction,
340                  SIGNAL(activated()),                  SIGNAL(triggered()),
341                  SLOT(fileOpen()));                  SLOT(fileOpen()));
342          QObject::connect(ui.fileSaveAction,          QObject::connect(m_ui.fileSaveAction,
343                  SIGNAL(activated()),                  SIGNAL(triggered()),
344                  SLOT(fileSave()));                  SLOT(fileSave()));
345          QObject::connect(ui.fileSaveAsAction,          QObject::connect(m_ui.fileSaveAsAction,
346                  SIGNAL(activated()),                  SIGNAL(triggered()),
347                  SLOT(fileSaveAs()));                  SLOT(fileSaveAs()));
348          QObject::connect(ui.fileResetAction,          QObject::connect(m_ui.fileResetAction,
349                  SIGNAL(activated()),                  SIGNAL(triggered()),
350                  SLOT(fileReset()));                  SLOT(fileReset()));
351          QObject::connect(ui.fileRestartAction,          QObject::connect(m_ui.fileRestartAction,
352                  SIGNAL(activated()),                  SIGNAL(triggered()),
353                  SLOT(fileRestart()));                  SLOT(fileRestart()));
354          QObject::connect(ui.fileExitAction,          QObject::connect(m_ui.fileExitAction,
355                  SIGNAL(activated()),                  SIGNAL(triggered()),
356                  SLOT(fileExit()));                  SLOT(fileExit()));
357          QObject::connect(ui.editAddChannelAction,          QObject::connect(m_ui.editAddChannelAction,
358                  SIGNAL(activated()),                  SIGNAL(triggered()),
359                  SLOT(editAddChannel()));                  SLOT(editAddChannel()));
360          QObject::connect(ui.editRemoveChannelAction,          QObject::connect(m_ui.editRemoveChannelAction,
361                  SIGNAL(activated()),                  SIGNAL(triggered()),
362                  SLOT(editRemoveChannel()));                  SLOT(editRemoveChannel()));
363          QObject::connect(ui.editSetupChannelAction,          QObject::connect(m_ui.editSetupChannelAction,
364                  SIGNAL(activated()),                  SIGNAL(triggered()),
365                  SLOT(editSetupChannel()));                  SLOT(editSetupChannel()));
366          QObject::connect(ui.editEditChannelAction,          QObject::connect(m_ui.editEditChannelAction,
367                  SIGNAL(activated()),                  SIGNAL(triggered()),
368                  SLOT(editEditChannel()));                  SLOT(editEditChannel()));
369          QObject::connect(ui.editResetChannelAction,          QObject::connect(m_ui.editResetChannelAction,
370                  SIGNAL(activated()),                  SIGNAL(triggered()),
371                  SLOT(editResetChannel()));                  SLOT(editResetChannel()));
372          QObject::connect(ui.editResetAllChannelsAction,          QObject::connect(m_ui.editResetAllChannelsAction,
373                  SIGNAL(activated()),                  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(activated()),                  SIGNAL(triggered()),
389                  SLOT(viewInstruments()));                  SLOT(viewInstruments()));
390          QObject::connect(ui.viewDevicesAction,          QObject::connect(m_ui.viewDevicesAction,
391                  SIGNAL(activated()),                  SIGNAL(triggered()),
392                  SLOT(viewDevices()));                  SLOT(viewDevices()));
393          QObject::connect(ui.viewOptionsAction,          QObject::connect(m_ui.viewOptionsAction,
394                  SIGNAL(activated()),                  SIGNAL(triggered()),
395                  SLOT(viewOptions()));                  SLOT(viewOptions()));
396          QObject::connect(ui.channelsArrangeAction,          QObject::connect(m_ui.channelsArrangeAction,
397                  SIGNAL(activated()),                  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(activated()),                  SIGNAL(triggered()),
404                  SLOT(helpAbout()));                  SLOT(helpAbout()));
405          QObject::connect(ui.helpAboutQtAction,          QObject::connect(m_ui.helpAboutQtAction,
406                  SIGNAL(activated()),                  SIGNAL(triggered()),
407                  SLOT(helpAboutQt()));                  SLOT(helpAboutQt()));
408    
409            QObject::connect(m_ui.fileMenu,
410                    SIGNAL(aboutToShow()),
411                    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;
459          delete m_pVolumeSlider;          delete m_pVolumeSlider;
460  #endif  #endif
461    
     // Delete recentfiles menu.  
     if (m_pRecentFilesMenu)  
         delete m_pRecentFilesMenu;  
   
462          // Pseudo-singleton reference shut-down.          // Pseudo-singleton reference shut-down.
463          g_pMainForm = NULL;          g_pMainForm = NULL;
464  }  }
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::WFlags wflags = Qt::WStyle_Customize          Qt::WindowFlags wflags = Qt::Window
475                  | Qt::WStyle_NormalBorder                  | Qt::CustomizeWindowHint
476                  | Qt::WStyle_Title                  | Qt::WindowTitleHint
477                  | Qt::WStyle_SysMenu                  | Qt::WindowSystemMenuHint
478                  | Qt::WStyle_MinMax                  | Qt::WindowMinMaxButtonsHint
479                  | Qt::WType_TopLevel;                  | Qt::WindowCloseButtonHint;
480      if (m_pOptions->bKeepOnTop)          if (m_pOptions->bKeepOnTop)
481          wflags |= Qt::WStyle_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->setOn(m_pOptions->bMenubar);          m_ui.viewMenubarAction->setChecked(m_pOptions->bMenubar);
509      ui.viewToolbarAction->setOn(m_pOptions->bToolbar);          m_ui.viewToolbarAction->setChecked(m_pOptions->bToolbar);
510      ui.viewStatusbarAction->setOn(m_pOptions->bStatusbar);          m_ui.viewStatusbarAction->setChecked(m_pOptions->bStatusbar);
511      ui.channelsAutoArrangeAction->setOn(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 toolbar & dock windows states.          // Restore whole dock windows state.
521      QString sDockables = m_pOptions->settings().readEntry("/Layout/DockWindowsBase64" , QString::null);          QByteArray aDockables = m_pOptions->settings().value(
522      if (!sDockables.isEmpty()) {                  "/Layout/DockWindows").toByteArray();
523          restoreState(QByteArray::fromBase64(sDockables.toAscii()));          if (!aDockables.isEmpty()) {
524      }                  restoreState(aDockables);
525      // Try to restore old window positioning and initial visibility.          }
     m_pOptions->loadWidgetGeometry(this);  
     m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);  
     m_pOptions->loadWidgetGeometry(m_pDeviceForm);  
   
     // Final startup stabilization...  
     updateMaxVolume();  
     updateRecentFilesMenu();  
     stabilizeForm();  
526    
527      // Make it ready :-)          // Try to restore old window positioning and initial visibility.
528      statusBar()->message(tr("Ready"), 3000);          m_pOptions->loadWidgetGeometry(this, true);
529            m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);
530            m_pOptions->loadWidgetGeometry(m_pDeviceForm);
531    
532            // Final startup stabilization...
533            updateMaxVolume();
534            updateRecentFilesMenu();
535            stabilizeForm();
536    
537      // We'll try to start immediately...          // Make it ready :-)
538      startSchedule(0);          statusBar()->showMessage(tr("Ready"), 3000);
539    
540      // Register the first timer slot.          // We'll try to start immediately...
541      QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));          startSchedule(0);
542    
543            // Register the first timer slot.
544            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              m_pOptions->settings().writeEntry("/Layout/DockWindowsBase64", sDockables);                          // Save the dock windows state.
567              // And the children, and the main windows state,.                          m_pOptions->settings().setValue("/Layout/DockWindows", saveState());
568                            // 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();
   
   
 // Drag'n'drop file handler.  
 bool MainForm::decodeDragFiles ( const QMimeSource *pEvent, QStringList& files )  
 {  
     bool bDecode = false;  
   
     if (Q3TextDrag::canDecode(pEvent)) {  
         QString sText;  
         bDecode = Q3TextDrag::decode(pEvent, sText);  
         if (bDecode) {  
             files = QStringList::split('\n', sText);  
             for (QStringList::Iterator iter = files.begin(); iter != files.end(); iter++)  
                 *iter = QUrl((*iter).stripWhiteSpace().replace(QRegExp("^file:"), QString::null)).path();  
         }  
     }  
   
     return bDecode;  
593  }  }
594    
595    
596  // Window drag-n-drop event handlers.  // Window drag-n-drop event handlers.
597  void MainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )  void MainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )
598  {  {
599          QStringList files;          // Accept external drags only...
600          pDragEnterEvent->accept(decodeDragFiles(pDragEnterEvent, files));          if (pDragEnterEvent->source() == NULL
601                    && pDragEnterEvent->mimeData()->hasUrls()) {
602                    pDragEnterEvent->accept();
603            } else {
604                    pDragEnterEvent->ignore();
605            }
606  }  }
607    
608    
609  void MainForm::dropEvent ( QDropEvent* pDropEvent )  void MainForm::dropEvent ( QDropEvent *pDropEvent )
610  {  {
611      QStringList files;          // Accept externally originated drops only...
612            if (pDropEvent->source())
613                    return;
614    
615      if (!decodeDragFiles(pDropEvent, files))          const QMimeData *pMimeData = pDropEvent->mimeData();
616          return;          if (pMimeData->hasUrls()) {
617                    QListIterator<QUrl> iter(pMimeData->urls());
618          for (QStringList::Iterator iter = files.begin(); iter != files.end(); iter++) {                  while (iter.hasNext()) {
619                  const QString& sPath = *iter;                          const QString& sPath = iter.next().toLocalFile();
620                  if (qsamplerChannel::isInstrumentFile(sPath)) {                  //      if (Channel::isDlsInstrumentFile(sPath)) {
621                          // Try to create a new channel from instrument file...                          if (QFileInfo(sPath).exists()) {
622                          qsamplerChannel *pChannel = new qsamplerChannel();                                  // Try to create a new channel from instrument file...
623                          if (pChannel == NULL)                                  Channel *pChannel = new Channel();
624                                  return;                                  if (pChannel == NULL)
625                          // Start setting the instrument filename...                                          return;
626                          pChannel->setInstrument(sPath, 0);                                  // Start setting the instrument filename...
627                          // Before we show it up, may be we'll                                  pChannel->setInstrument(sPath, 0);
628                          // better ask for some initial values?                                  // Before we show it up, may be we'll
629                          if (!pChannel->channelSetup(this)) {                                  // better ask for some initial values?
630                                  delete pChannel;                                  if (!pChannel->channelSetup(this)) {
631                                  return;                                          delete pChannel;
632                          }                                          return;
633                          // Finally, give it to a new channel strip...                                  }
634                          if (!createChannelStrip(pChannel)) {                                  // Finally, give it to a new channel strip...
635                                  delete pChannel;                                  if (!createChannelStrip(pChannel)) {
636                                  return;                                          delete pChannel;
637                                            return;
638                                    }
639                                    // Make that an overall update.
640                                    m_iDirtyCount++;
641                                    stabilizeForm();
642                            }   // Otherwise, load an usual session file (LSCP script)...
643                            else if (closeSession(true)) {
644                                    loadSessionFile(sPath);
645                                    break;
646                          }                          }
                         // Make that an overall update.  
                         m_iDirtyCount++;  
                         stabilizeForm();  
                 }   // Otherwise, load an usual session file (LSCP script)...  
                 else if (closeSession(true)) {  
                         loadSessionFile(sPath);  
                         break;  
647                  }                  }
648                  // Make it look responsive...:)                  // Make it look responsive...:)
649                  QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
650          }          }
651  }  }
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 592  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...
825            QString sFilename = QFileDialog::getOpenFileName(this,
826                    QSAMPLER_TITLE ": " + tr("Open Session"), // Caption.
827                    m_pOptions->sSessionDir,                  // Start here.
828                    tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
829            );
830    
831      // Ask for the filename to open...          // Have we cancelled?
832      QString sFilename = QFileDialog::getOpenFileName(          if (sFilename.isEmpty())
833                  m_pOptions->sSessionDir,                // Start here.                  return false;
                 tr("LSCP Session files") + " (*.lscp)", // Filter (LSCP files)  
                 this, 0,                                // Parent and name (none)  
                 QSAMPLER_TITLE ": " + tr("Open Session")        // Caption.  
     );  
   
     // Have we cancelled?  
     if (sFilename.isEmpty())  
         return false;  
   
     // Check if we're going to discard safely the current one...  
     if (!closeSession(true))  
         return false;  
834    
835      // Load it right away.          // Check if we're going to discard safely the current one...
836      return loadSessionFile(sFilename);          if (!closeSession(true))
837                    return false;
838    
839            // Load it right away.
840            return loadSessionFile(sFilename);
841  }  }
842    
843    
844  // Save current sampler session with another name.  // Save current sampler session with another name.
845  bool MainForm::saveSession ( bool bPrompt )  bool MainForm::saveSession ( bool bPrompt )
846  {  {
847      if (m_pOptions == NULL)          if (m_pOptions == NULL)
848          return false;                  return false;
849    
850      QString sFilename = m_sFilename;          QString sFilename = m_sFilename;
851    
852      // Ask for the file to save, if there's none...          // Ask for the file to save, if there's none...
853      if (bPrompt || sFilename.isEmpty()) {          if (bPrompt || sFilename.isEmpty()) {
854          // If none is given, assume default directory.                  // If none is given, assume default directory.
855          if (sFilename.isEmpty())                  if (sFilename.isEmpty())
856              sFilename = m_pOptions->sSessionDir;                          sFilename = m_pOptions->sSessionDir;
857          // Prompt the guy...                  // Prompt the guy...
858          sFilename = QFileDialog::getSaveFileName(                  sFilename = QFileDialog::getSaveFileName(this,
859                          sFilename,                              // Start here.                          QSAMPLER_TITLE ": " + tr("Save Session"), // Caption.
860                          tr("LSCP Session files") + " (*.lscp)", // Filter (LSCP files)                          sFilename,                                // Start here.
861                          this, 0,                                // Parent and name (none)                          tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
862                          QSAMPLER_TITLE ": " + tr("Save Session")        // Caption.                  );
863          );                  // Have we cancelled it?
864          // Have we cancelled it?                  if (sFilename.isEmpty())
865          if (sFilename.isEmpty())                          return false;
866              return false;                  // Enforce .lscp extension...
867          // Enforce .lscp extension...                  if (QFileInfo(sFilename).suffix().isEmpty())
868          if (QFileInfo(sFilename).extension().isEmpty())                          sFilename += ".lscp";
869              sFilename += ".lscp";                  // Check if already exists...
870          // Check if already exists...                  if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {
871          if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {                          if (QMessageBox::warning(this,
             if (QMessageBox::warning(this,  
872                                  QSAMPLER_TITLE ": " + tr("Warning"),                                  QSAMPLER_TITLE ": " + tr("Warning"),
873                  tr("The file already exists:\n\n"                                  tr("The file already exists:\n\n"
874                     "\"%1\"\n\n"                                  "\"%1\"\n\n"
875                     "Do you want to replace it?")                                  "Do you want to replace it?")
876                     .arg(sFilename),                                  .arg(sFilename),
877                  tr("Replace"), tr("Cancel")) > 0)                                  QMessageBox::Yes | QMessageBox::No)
878                  return false;                                  == QMessageBox::No)
879          }                                  return false;
880      }                  }
881            }
882    
883      // Save it right away.          // Save it right away.
884      return saveSessionFile(sFilename);          return saveSessionFile(sFilename);
885  }  }
886    
887    
888  // Close current session.  // Close current session.
889  bool MainForm::closeSession ( bool bForce )  bool MainForm::closeSession ( bool bForce )
890  {  {
891      bool bClose = true;          bool bClose = true;
892    
893      // Are we dirty enough to prompt it?          // Are we dirty enough to prompt it?
894      if (m_iDirtyCount > 0) {          if (m_iDirtyCount > 0) {
895          switch (QMessageBox::warning(this,                  switch (QMessageBox::warning(this,
896                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
897              tr("The current session has been changed:\n\n"                          tr("The current session has been changed:\n\n"
898              "\"%1\"\n\n"                          "\"%1\"\n\n"
899              "Do you want to save the changes?")                          "Do you want to save the changes?")
900              .arg(sessionName(m_sFilename)),                          .arg(sessionName(m_sFilename)),
901              tr("Save"), tr("Discard"), tr("Cancel"))) {                          QMessageBox::Save |
902          case 0:     // Save...                          QMessageBox::Discard |
903              bClose = saveSession(false);                          QMessageBox::Cancel)) {
904              // Fall thru....                  case QMessageBox::Save:
905          case 1:     // Discard                          bClose = saveSession(false);
906              break;                          // Fall thru....
907          default:    // Cancel.                  case QMessageBox::Discard:
908              bClose = false;                          break;
909              break;                  default:    // Cancel.
910          }                          bClose = false;
911      }                          break;
912                    }
913      // If we may close it, dot it.          }
     if (bClose) {  
         // Remove all channel strips from sight...  
         m_pWorkspace->setUpdatesEnabled(false);  
         QWidgetList wlist = m_pWorkspace->windowList();  
         for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {  
             ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);  
             if (pChannelStrip) {  
                 qsamplerChannel *pChannel = pChannelStrip->channel();  
                 if (bForce && pChannel)  
                     pChannel->removeChannel();  
                 delete pChannelStrip;  
             }  
         }  
         m_pWorkspace->setUpdatesEnabled(true);  
         // We're now clean, for sure.  
         m_iDirtyCount = 0;  
     }  
914    
915      return bClose;          // If we may close it, dot it.
916            if (bClose) {
917                    // Remove all channel strips from sight...
918                    m_pWorkspace->setUpdatesEnabled(false);
919                    const QList<QMdiSubWindow *>& wlist
920                            = m_pWorkspace->subWindowList();
921                    const int iStripCount = wlist.count();
922                    for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
923                            ChannelStrip *pChannelStrip = NULL;
924                            QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
925                            if (pMdiSubWindow)
926                                    pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
927                            if (pChannelStrip) {
928                                    Channel *pChannel = pChannelStrip->channel();
929                                    if (bForce && pChannel)
930                                            pChannel->removeChannel();
931                                    delete pChannelStrip;
932                            }
933                            if (pMdiSubWindow)
934                                    delete pMdiSubWindow;
935                    }
936                    m_pWorkspace->setUpdatesEnabled(true);
937                    // We're now clean, for sure.
938                    m_iDirtyCount = 0;
939            }
940    
941            return bClose;
942  }  }
943    
944    
945  // Load a session from specific file path.  // Load a session from specific file path.
946  bool MainForm::loadSessionFile ( const QString& sFilename )  bool MainForm::loadSessionFile ( const QString& sFilename )
947  {  {
948      if (m_pClient == NULL)          if (m_pClient == NULL)
949          return false;                  return false;
950    
951      // Open and read from real file.          // Open and read from real file.
952      QFile file(sFilename);          QFile file(sFilename);
953      if (!file.open(IO_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().stripWhiteSpace();                  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";
976                          if (::lscp_client_query(m_pClient, sCommand.latin1()) != LSCP_OK) {                          if (::lscp_client_query(m_pClient, sCommand.toUtf8().constData())
977                                    != LSCP_OK) {
978                                  appendMessagesColor(QString("%1(%2): %3")                                  appendMessagesColor(QString("%1(%2): %3")
979                                          .arg(QFileInfo(sFilename).fileName()).arg(iLine)                                          .arg(QFileInfo(sFilename).fileName()).arg(iLine)
980                                          .arg(sCommand.simplifyWhiteSpace()), "#996633");                                          .arg(sCommand.simplified()), "#996633");
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::ExcludeUserInput);                  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 800  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).dirPath(true);                  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 831  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(IO_WriteOnly | IO_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 866  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.data();                          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                  for (qsamplerDevicePort *pPort = device.ports().first();                  QListIterator<DevicePort *> iter(device.ports());
1088                                  pPort;                  while (iter.hasNext()) {
1089                                          pPort = device.ports().next(), ++iPort) {                          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.data();                                  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()
1098                                          << "='" << param.value << "'" << endl;                                          << "='" << param.value << "'" << endl;
1099                          }                          }
1100                            iPort++;
1101                  }                  }
1102                  // Audio device index/id mapping.                  // Audio device index/id mapping.
1103                  audioDeviceMap[device.deviceID()] = iDevice;                  audioDeviceMap[device.deviceID()] = iDevice;
1104                  // Try to keep it snappy :)                  // Try to keep it snappy :)
1105                  QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1106          }          }
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.data();                          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                  for (qsamplerDevicePort *pPort = device.ports().first();                  QListIterator<DevicePort *> iter(device.ports());
1130                                  pPort;                  while (iter.hasNext()) {
1131                                          pPort = device.ports().next(), ++iPort) {                          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.data();                                  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++;
1143                  }                  }
1144                  // MIDI device index/id mapping.                  // MIDI device index/id mapping.
1145                  midiDeviceMap[device.deviceID()] = iDevice;                  midiDeviceMap[device.deviceID()] = iDevice;
1146                  // Try to keep it snappy :)                  // Try to keep it snappy :)
1147                  QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1148          }          }
1149          ts << endl;          ts << endl;
1150    
# Line 952  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 1000  bool MainForm::saveSessionFile ( const Q Line 1201  bool MainForm::saveSessionFile ( const Q
1201                                  iErrors++;                                  iErrors++;
1202                          }                          }
1203                          // Try to keep it snappy :)                          // Try to keep it snappy :)
1204                          QApplication::processEvents(QEventLoop::ExcludeUserInput);                          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1205                  }                  }
1206                  ts << endl;                  ts << endl;
1207                  // Check for errors...                  // Check for errors...
# Line 1019  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.data() << 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 1083  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 1093  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::ExcludeUserInput);                  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 1123  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).dirPath(true);          }
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    
1390  // Open a recent file session.  // Open a recent file session.
1391  void MainForm::fileOpenRecent ( int iIndex )  void MainForm::fileOpenRecent (void)
1392  {  {
1393      // Check if we can safely close the current session...          // Retrive filename index from action data...
1394      if (m_pOptions && closeSession(true)) {          QAction *pAction = qobject_cast<QAction *> (sender());
1395          QString sFilename = m_pOptions->recentFiles[iIndex];          if (pAction && m_pOptions) {
1396          loadSessionFile(sFilename);                  const int iIndex = pAction->data().toInt();
1397      }                  if (iIndex >= 0 && iIndex < m_pOptions->recentFiles.count()) {
1398                            QString sFilename = m_pOptions->recentFiles[iIndex];
1399                            // Check if we can safely close the current session...
1400                            if (!sFilename.isEmpty() && closeSession(true))
1401                                    loadSessionFile(sFilename);
1402                    }
1403            }
1404  }  }
1405    
1406    
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 1232  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 1243  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...          // Just create the channel instance...
1554      qsamplerChannel *pChannel = new qsamplerChannel();          Channel *pChannel = new Channel();
1555      if (pChannel == NULL)          if (pChannel == NULL)
1556          return;                  return;
1557    
1558      // Before we show it up, may be we'll          // Before we show it up, may be we'll
1559      // better ask for some initial values?          // better ask for some initial values?
1560      if (!pChannel->channelSetup(this)) {          if (!pChannel->channelSetup(this)) {
1561          delete pChannel;                  delete pChannel;
1562          return;                  return;
1563      }          }
1564    
1565      // And give it to the strip (will own the channel instance, if successful).          // And give it to the strip...
1566      if (!createChannelStrip(pChannel)) {          // (will own the channel instance, if successful).
1567          delete pChannel;          if (!createChannelStrip(pChannel)) {
1568          return;                  delete pChannel;
1569      }                  return;
1570            }
1571      // Make that an overall update.  
1572      m_iDirtyCount++;          // Do we auto-arrange?
1573      stabilizeForm();          channelsArrangeAuto();
1574    
1575            // Make that an overall update.
1576            m_iDirtyCount++;
1577            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->caption()),                  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 1409  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 1420  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 1480  void MainForm::viewInstruments (void) Line 1771  void MainForm::viewInstruments (void)
1771                  } else {                  } else {
1772                          m_pInstrumentListForm->show();                          m_pInstrumentListForm->show();
1773                          m_pInstrumentListForm->raise();                          m_pInstrumentListForm->raise();
1774                          m_pInstrumentListForm->setActiveWindow();                          m_pInstrumentListForm->activateWindow();
1775                  }                  }
1776          }          }
1777  }  }
# Line 1499  void MainForm::viewDevices (void) Line 1790  void MainForm::viewDevices (void)
1790                  } else {                  } else {
1791                          m_pDeviceForm->show();                          m_pDeviceForm->show();
1792                          m_pDeviceForm->raise();                          m_pDeviceForm->raise();
1793                          m_pDeviceForm->setActiveWindow();                          m_pDeviceForm->activateWindow();
1794                  }                  }
1795          }          }
1796  }  }
# Line 1508  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      setCaption(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->setOn(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->setOn(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->setOn(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->caption());          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      m_pRecentFilesMenu->setEnabled(bHasClient && m_pOptions->recentFiles.count() > 0);          m_ui.fileOpenRecentMenu->setEnabled(m_pOptions->recentFiles.count() > 0);
2114  }  }
2115    
2116    
# Line 1823  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 1839  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.containsRef(pChannelStrip) == 0) {          if (!m_changedStrips.contains(pChannelStrip)) {
2154                  m_changedStrips.append(pChannelStrip);                  m_changedStrips.append(pChannelStrip);
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 1858  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 1866  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) {
2181                  ::lscp_add_midi_instrument_map(m_pClient, tr("Chromatic").latin1());                  ::lscp_add_midi_instrument_map(m_pClient,
2182                  ::lscp_add_midi_instrument_map(m_pClient, tr("Drum Kits").latin1());                          tr("Chromatic").toUtf8().constData());
2183                    ::lscp_add_midi_instrument_map(m_pClient,
2184                            tr("Drum Kits").toUtf8().constData());
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;
   
     // Remove from list if already there (avoid duplicates)  
     QStringList::Iterator iter = m_pOptions->recentFiles.find(sFilename);  
     if (iter != m_pOptions->recentFiles.end())  
         m_pOptions->recentFiles.remove(iter);  
     // Put it to front...  
     m_pOptions->recentFiles.push_front(sFilename);  
2264    
2265      // May update the menu.          // Remove from list if already there (avoid duplicates)
2266      updateRecentFilesMenu();          const int iIndex = m_pOptions->recentFiles.indexOf(sFilename);
2267            if (iIndex >= 0)
2268                    m_pOptions->recentFiles.removeAt(iIndex);
2269            // Put it to front...
2270            m_pOptions->recentFiles.push_front(sFilename);
2271  }  }
2272    
2273    
2274  // Update the recent files list and menu.  // Update the recent files list and menu.
2275  void MainForm::updateRecentFilesMenu (void)  void MainForm::updateRecentFilesMenu (void)
2276  {  {
2277      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2278          return;                  return;
2279    
2280      // Time to keep the list under limits.          // Time to keep the list under limits.
2281      int iRecentFiles = m_pOptions->recentFiles.count();          int iRecentFiles = m_pOptions->recentFiles.count();
2282      while (iRecentFiles > m_pOptions->iMaxRecentFiles) {          while (iRecentFiles > m_pOptions->iMaxRecentFiles) {
2283          m_pOptions->recentFiles.pop_back();                  m_pOptions->recentFiles.pop_back();
2284          iRecentFiles--;                  iRecentFiles--;
2285      }          }
2286    
2287      // rebuild the recent files menu...          // Rebuild the recent files menu...
2288      m_pRecentFilesMenu->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              m_pRecentFilesMenu->insertItem(QString("&%1 %2")                          QAction *pAction = m_ui.fileOpenRecentMenu->addAction(
2293                  .arg(i + 1).arg(sessionName(sFilename)),                                  QString("&%1 %2").arg(i + 1).arg(sessionName(sFilename)),
2294                  this, SLOT(fileOpenRecent(int)), 0, i);                                  this, SLOT(fileOpenRecent()));
2295          }                          pAction->setData(i);
2296      }                  }
2297            }
2298  }  }
2299    
2300    
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     QPixmap pm;          // Full channel list update...
2363      if (m_pOptions->bDisplayEffect)          const QList<QMdiSubWindow *>& wlist
2364          pm = QPixmap(":/qsampler/pixmaps/displaybg1.png");                  = m_pWorkspace->subWindowList();
2365            if (wlist.isEmpty())
2366      // Full channel list update...                  return;
2367      QWidgetList wlist = m_pWorkspace->windowList();  
2368      if (wlist.isEmpty())          m_pWorkspace->setUpdatesEnabled(false);
2369          return;          const int iStripCount = wlist.count();
2370            for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
2371      m_pWorkspace->setUpdatesEnabled(false);                  ChannelStrip *pChannelStrip = NULL;
2372      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2373          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  if (pMdiSubWindow)
2374          if (pChannelStrip)                          pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2375              pChannelStrip->setDisplayBackground(pm);                  if (pChannelStrip)
2376      }                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2377      m_pWorkspace->setUpdatesEnabled(true);          }
2378            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++;
2390          m_pVolumeSlider->setMaxValue(m_pOptions->iMaxVolume);          m_pVolumeSlider->setMaximum(m_pOptions->iMaxVolume);
2391          m_pVolumeSpinBox->setMaxValue(m_pOptions->iMaxVolume);          m_pVolumeSpinBox->setMaximum(m_pOptions->iMaxVolume);
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()->message(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()->message(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.simplifyWhiteSpace(), "#ff0000");          appendMessagesColor(sText.simplified(), "#ff0000");
2447    
2448          // Make it look responsive...:)          // Make it look responsive...:)
2449          QApplication::processEvents(QEventLoop::ExcludeUserInput);          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::ExcludeUserInput);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2484  }  }
2485    
2486    
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;
2540          QWidgetList wlist = m_pWorkspace->windowList();  
2541          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          // Set some initial channel strip options...
2542              pChannelStrip = (ChannelStrip *) wlist.at(iChannel);          if (m_pOptions) {
2543                          if (pChannelStrip) {                  // Background display effect...
2544                          //  y += pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2545                                  y += pChannelStrip->parentWidget()->frameGeometry().height();                  // 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      // Add a new channel itema...          // Actual channel strip setup...
2559      Qt::WFlags wflags = Qt::WStyle_Customize | Qt::WStyle_Tool | Qt::WStyle_Title | Qt::WStyle_NoBorder;          pChannelStrip->setup(pChannel);
     pChannelStrip = new ChannelStrip(m_pWorkspace, wflags);  
     if (pChannelStrip == NULL)  
         return NULL;  
2560    
     // Actual channel strip setup...  
     pChannelStrip->setup(pChannel);  
2561          QObject::connect(pChannelStrip,          QObject::connect(pChannelStrip,
2562                  SIGNAL(channelChanged(qsamplerChannelStrip *)),                  SIGNAL(channelChanged(ChannelStrip *)),
2563                  SLOT(channelStripChanged(qsamplerChannelStrip *)));                  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 (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;
2607      if (wlist.isEmpty())  
2608          return NULL;          const QList<QMdiSubWindow *>& wlist
2609                    = m_pWorkspace->subWindowList();
2610            if (wlist.isEmpty())
2611                    return NULL;
2612    
2613      return (ChannelStrip*) wlist.at(iChannel);          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 = (ChannelStrip*) wlist.at(iChannel);          for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
2634                    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.channelsArrangeAction->addTo(ui.channelsMenu);          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);
2655      ui.channelsAutoArrangeAction->addTo(ui.channelsMenu);          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->insertSeparator();          if (!wlist.isEmpty()) {
2660          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  m_ui.channelsMenu->addSeparator();
2661              ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  const int iStripCount = wlist.count();
2662              if (pChannelStrip) {                  for (int iStrip = 0; iStrip < iStripCount; ++iStrip) {
2663                  int iItemID = ui.channelsMenu->insertItem(pChannelStrip->caption(), this, SLOT(channelsMenuActivated(int)));                          ChannelStrip *pChannelStrip = NULL;
2664                  ui.channelsMenu->setItemParameter(iItemID, iChannel);                          QMdiSubWindow *pMdiSubWindow = wlist.at(iStrip);
2665                  ui.channelsMenu->setItemChecked(iItemID, activeChannelStrip() == pChannelStrip);                          if (pMdiSubWindow)
2666              }                                  pChannelStrip = static_cast<ChannelStrip *> (pMdiSubWindow->widget());
2667          }                          if (pChannelStrip) {
2668      }                                  QAction *pAction = m_ui.channelsMenu->addAction(
2669                                            pChannelStrip->windowTitle(),
2670                                            this, SLOT(channelsMenuActivated()));
2671                                    pAction->setCheckable(true);
2672                                    pAction->setChecked(activeChannelStrip() == pChannelStrip);
2673                                    pAction->setData(iStrip);
2674                            }
2675                    }
2676            }
2677  }  }
2678    
2679    
2680  // Windows menu activation slot  // Windows menu activation slot
2681  void MainForm::channelsMenuActivated ( int iChannel )  void MainForm::channelsMenuActivated (void)
2682  {  {
2683      ChannelStrip* pChannelStrip = channelStripAt(iChannel);          // Retrive channel index from action data...
2684      if (pChannelStrip)          QAction *pAction = qobject_cast<QAction *> (sender());
2685          pChannelStrip->showNormal();          if (pAction == NULL)
2686      pChannelStrip->setFocus();                  return;
2687    
2688            ChannelStrip *pChannelStrip = channelStripAt(pAction->data().toInt());
2689            if (pChannelStrip) {
2690                    pChannelStrip->showNormal();
2691                    pChannelStrip->setFocus();
2692            }
2693  }  }
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...
2733                  if (m_changedStrips.count() > 0) {                  QListIterator<ChannelStrip *> iter(m_changedStrips);
2734                          for (ChannelStrip* pChannelStrip = m_changedStrips.first();                  while (iter.hasNext()) {
2735                                          pChannelStrip; pChannelStrip = m_changedStrips.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                                          m_changedStrips.remove(pChannelStrip);                                  const int iChannelStrip = m_changedStrips.indexOf(pChannelStrip);
2739                                    if (iChannelStrip >= 0)
2740                                            m_changedStrips.removeAt(iChannelStrip);
2741                          }                          }
2742                  }                  }
2743                  // Refresh each channel usage, on each period...                  // Refresh each channel usage, on each period...
# Line 2327  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 2339  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 = QStringList::split(' ', m_pOptions->sServerCmdLine);          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      // And try to stop server.          if (m_pServer && bInteractive) {
2854      if (m_pServer) {                  if (QMessageBox::question(this,
2855          appendMessages(tr("Server is stopping..."));                          QSAMPLER_TITLE ": " + tr("The backend's fate ..."),
2856          if (m_pServer->state() == QProcess::Running)                          tr("You have the option to keep the sampler backend (LinuxSampler)\n"
2857              m_pServer->terminate();                          "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      // Give it some time to terminate gracefully and stabilize...                          "Do you want LinuxSampler to stop?"),
2861      QTime t;                          QMessageBox::Yes | QMessageBox::No,
2862      t.start();                          QMessageBox::Yes) == QMessageBox::No) {
2863      while (t.elapsed() < QSAMPLER_TIMER_MSECS)                          m_bForceServerStop = false;
2864          QApplication::processEvents(QEventLoop::ExcludeUserInput);                  }
2865            }
2866    
2867            // And try to stop server.
2868            if (m_pServer && m_bForceServerStop) {
2869                    appendMessages(tr("Server is stopping..."));
2870                    if (m_pServer->state() == QProcess::Running) {
2871                    #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
2872                            // Try harder...
2873                            m_pServer->kill();
2874                    #else
2875                            // Try softly...
2876                            m_pServer->terminate();
2877                    #endif
2878                    }
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;
2959    
2960      // Aren't we already started, are we?          // Aren't we already started, are we?
2961      if (m_pClient)          if (m_pClient)
2962          return true;                  return true;
2963    
2964      // Log prepare here.          // Log prepare here.
2965      appendMessages(tr("Client connecting..."));          appendMessages(tr("Client connecting..."));
2966    
2967      // Create the client handle...          // Create the client handle...
2968      m_pClient = ::lscp_client_create(m_pOptions->sServerHost.latin1(), m_pOptions->iServerPort, qsampler_client_callback, this);          m_pClient = ::lscp_client_create(
2969      if (m_pClient == NULL) {                  m_pOptions->sServerHost.toUtf8().constData(),
2970          // Is this the first try?                  m_pOptions->iServerPort, qsampler_client_callback, this);
2971          // maybe we need to start a local server...          if (m_pClient == NULL) {
2972          if ((m_pServer && m_pServer->state() == QProcess::Running) || !m_pOptions->bServerStart)                  // Is this the first try?
2973              appendMessagesError(tr("Could not connect to server as client.\n\nSorry."));                  // maybe we need to start a local server...
2974          else                  if ((m_pServer && m_pServer->state() == QProcess::Running)
2975              startServer();                          || !m_pOptions->bServerStart) {
2976          // This is always a failure.                          appendMessagesError(
2977          stabilizeForm();                                  tr("Could not connect to server as client.\n\nSorry."));
2978          return false;                  } else {
2979      }                          startServer();
2980      // Just set receive timeout value, blindly.                  }
2981      ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);                  // This is always a failure.
2982      appendMessages(tr("Client receive timeout is set to %1 msec.").arg(::lscp_client_get_timeout(m_pClient)));                  stabilizeForm();
2983                    return false;
2984            }
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            DeviceStatusForm::onDevicesChanged(); // initialize
2999            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.          // We may stop scheduling around.
3022      stopSchedule();          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    
3105    
3106      // Log final here.  // Channel strip activation/selection.
3107      appendMessages(tr("Client disconnected."));  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      // Make visible status.          stabilizeForm();
     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.1470  
changed lines
  Added in v.3358

  ViewVC Help
Powered by ViewVC