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

Legend:
Removed from v.1473  
changed lines
  Added in v.2717

  ViewVC Help
Powered by ViewVC