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

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

  ViewVC Help
Powered by ViewVC