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

Legend:
Removed from v.1475  
changed lines
  Added in v.2441

  ViewVC Help
Powered by ViewVC