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

Legend:
Removed from v.1466  
changed lines
  Added in v.2459

  ViewVC Help
Powered by ViewVC