/[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 2112 by capela, Wed Jul 21 18:33:25 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_pSocketNotifier = 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            char c;
695    
696            if (::read(g_fdUsr1[1], &c, sizeof(c)) > 0)
697                    saveSession(false);
698    }
699    
700    
701    void MainForm::updateViewMidiDeviceStatusMenu (void)
702    {
703            m_ui.viewMidiDeviceStatusMenu->clear();
704            const std::map<int, DeviceStatusForm *> statusForms
705                    = DeviceStatusForm::getInstances();
706            std::map<int, DeviceStatusForm *>::const_iterator iter
707                    = statusForms.begin();
708            for ( ; iter != statusForms.end(); ++iter) {
709                    DeviceStatusForm *pStatusForm = iter->second;
710                    m_ui.viewMidiDeviceStatusMenu->addAction(
711                            pStatusForm->visibleAction());
712            }
713  }  }
714    
715    
716  // Context menu event handler.  // Context menu event handler.
717  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )  void MainForm::contextMenuEvent( QContextMenuEvent *pEvent )
718  {  {
719      stabilizeForm();          stabilizeForm();
720    
721      ui.editMenu->exec(pEvent->globalPos());          m_ui.editMenu->exec(pEvent->globalPos());
722  }  }
723    
724    
# Line 571  void MainForm::contextMenuEvent( QContex Line 726  void MainForm::contextMenuEvent( QContex
726  // qsamplerMainForm -- Brainless public property accessors.  // qsamplerMainForm -- Brainless public property accessors.
727    
728  // The global options settings property.  // The global options settings property.
729  qsamplerOptions *MainForm::options (void)  Options *MainForm::options (void) const
730  {  {
731      return m_pOptions;          return m_pOptions;
732  }  }
733    
734    
735  // The LSCP client descriptor property.  // The LSCP client descriptor property.
736  lscp_client_t *MainForm::client (void)  lscp_client_t *MainForm::client (void) const
737  {  {
738      return m_pClient;          return m_pClient;
739  }  }
740    
741    
# Line 597  MainForm *MainForm::getInstance (void) Line 752  MainForm *MainForm::getInstance (void)
752  // Format the displayable session filename.  // Format the displayable session filename.
753  QString MainForm::sessionName ( const QString& sFilename )  QString MainForm::sessionName ( const QString& sFilename )
754  {  {
755      bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);          bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);
756      QString sSessionName = sFilename;          QString sSessionName = sFilename;
757      if (sSessionName.isEmpty())          if (sSessionName.isEmpty())
758          sSessionName = tr("Untitled") + QString::number(m_iUntitled);                  sSessionName = tr("Untitled") + QString::number(m_iUntitled);
759      else if (!bCompletePath)          else if (!bCompletePath)
760          sSessionName = QFileInfo(sSessionName).fileName();                  sSessionName = QFileInfo(sSessionName).fileName();
761      return sSessionName;          return sSessionName;
762  }  }
763    
764    
765  // Create a new session file from scratch.  // Create a new session file from scratch.
766  bool MainForm::newSession (void)  bool MainForm::newSession (void)
767  {  {
768      // Check if we can do it.          // Check if we can do it.
769      if (!closeSession(true))          if (!closeSession(true))
770          return false;                  return false;
771    
772          // Give us what the server has, right now...          // Give us what the server has, right now...
773          updateSession();          updateSession();
774    
775      // Ok increment untitled count.          // Ok increment untitled count.
776      m_iUntitled++;          m_iUntitled++;
777    
778      // Stabilize form.          // Stabilize form.
779      m_sFilename = QString::null;          m_sFilename = QString::null;
780      m_iDirtyCount = 0;          m_iDirtyCount = 0;
781      appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));          appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));
782      stabilizeForm();          stabilizeForm();
783    
784      return true;          return true;
785  }  }
786    
787    
788  // Open an existing sampler session.  // Open an existing sampler session.
789  bool MainForm::openSession (void)  bool MainForm::openSession (void)
790  {  {
791      if (m_pOptions == NULL)          if (m_pOptions == NULL)
792          return false;                  return false;
793    
794      // Ask for the filename to open...          // Ask for the filename to open...
795      QString sFilename = QFileDialog::getOpenFileName(          QString sFilename = QFileDialog::getOpenFileName(this,
796                  m_pOptions->sSessionDir,                // Start here.                  QSAMPLER_TITLE ": " + tr("Open Session"), // Caption.
797                  tr("LSCP Session files") + " (*.lscp)", // Filter (LSCP files)                  m_pOptions->sSessionDir,                  // Start here.
798                  this, 0,                                // Parent and name (none)                  tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
799                  QSAMPLER_TITLE ": " + tr("Open Session")        // Caption.          );
800      );  
801            // Have we cancelled?
802      // Have we cancelled?          if (sFilename.isEmpty())
803      if (sFilename.isEmpty())                  return false;
804          return false;  
805            // Check if we're going to discard safely the current one...
806      // Check if we're going to discard safely the current one...          if (!closeSession(true))
807      if (!closeSession(true))                  return false;
         return false;  
808    
809      // Load it right away.          // Load it right away.
810      return loadSessionFile(sFilename);          return loadSessionFile(sFilename);
811  }  }
812    
813    
814  // Save current sampler session with another name.  // Save current sampler session with another name.
815  bool MainForm::saveSession ( bool bPrompt )  bool MainForm::saveSession ( bool bPrompt )
816  {  {
817      if (m_pOptions == NULL)          if (m_pOptions == NULL)
818          return false;                  return false;
819    
820      QString sFilename = m_sFilename;          QString sFilename = m_sFilename;
821    
822      // Ask for the file to save, if there's none...          // Ask for the file to save, if there's none...
823      if (bPrompt || sFilename.isEmpty()) {          if (bPrompt || sFilename.isEmpty()) {
824          // If none is given, assume default directory.                  // If none is given, assume default directory.
825          if (sFilename.isEmpty())                  if (sFilename.isEmpty())
826              sFilename = m_pOptions->sSessionDir;                          sFilename = m_pOptions->sSessionDir;
827          // Prompt the guy...                  // Prompt the guy...
828          sFilename = QFileDialog::getSaveFileName(                  sFilename = QFileDialog::getSaveFileName(this,
829                          sFilename,                              // Start here.                          QSAMPLER_TITLE ": " + tr("Save Session"), // Caption.
830                          tr("LSCP Session files") + " (*.lscp)", // Filter (LSCP files)                          sFilename,                                // Start here.
831                          this, 0,                                // Parent and name (none)                          tr("LSCP Session files") + " (*.lscp)"    // Filter (LSCP files)
832                          QSAMPLER_TITLE ": " + tr("Save Session")        // Caption.                  );
833          );                  // Have we cancelled it?
834          // Have we cancelled it?                  if (sFilename.isEmpty())
835          if (sFilename.isEmpty())                          return false;
836              return false;                  // Enforce .lscp extension...
837          // Enforce .lscp extension...                  if (QFileInfo(sFilename).suffix().isEmpty())
838          if (QFileInfo(sFilename).extension().isEmpty())                          sFilename += ".lscp";
839              sFilename += ".lscp";                  // Check if already exists...
840          // Check if already exists...                  if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {
841          if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {                          if (QMessageBox::warning(this,
             if (QMessageBox::warning(this,  
842                                  QSAMPLER_TITLE ": " + tr("Warning"),                                  QSAMPLER_TITLE ": " + tr("Warning"),
843                  tr("The file already exists:\n\n"                                  tr("The file already exists:\n\n"
844                     "\"%1\"\n\n"                                  "\"%1\"\n\n"
845                     "Do you want to replace it?")                                  "Do you want to replace it?")
846                     .arg(sFilename),                                  .arg(sFilename),
847                  tr("Replace"), tr("Cancel")) > 0)                                  QMessageBox::Yes | QMessageBox::No)
848                  return false;                                  == QMessageBox::No)
849          }                                  return false;
850      }                  }
851            }
852    
853      // Save it right away.          // Save it right away.
854      return saveSessionFile(sFilename);          return saveSessionFile(sFilename);
855  }  }
856    
857    
858  // Close current session.  // Close current session.
859  bool MainForm::closeSession ( bool bForce )  bool MainForm::closeSession ( bool bForce )
860  {  {
861      bool bClose = true;          bool bClose = true;
862    
863      // Are we dirty enough to prompt it?          // Are we dirty enough to prompt it?
864      if (m_iDirtyCount > 0) {          if (m_iDirtyCount > 0) {
865          switch (QMessageBox::warning(this,                  switch (QMessageBox::warning(this,
866                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
867              tr("The current session has been changed:\n\n"                          tr("The current session has been changed:\n\n"
868              "\"%1\"\n\n"                          "\"%1\"\n\n"
869              "Do you want to save the changes?")                          "Do you want to save the changes?")
870              .arg(sessionName(m_sFilename)),                          .arg(sessionName(m_sFilename)),
871              tr("Save"), tr("Discard"), tr("Cancel"))) {                          QMessageBox::Save |
872          case 0:     // Save...                          QMessageBox::Discard |
873              bClose = saveSession(false);                          QMessageBox::Cancel)) {
874              // Fall thru....                  case QMessageBox::Save:
875          case 1:     // Discard                          bClose = saveSession(false);
876              break;                          // Fall thru....
877          default:    // Cancel.                  case QMessageBox::Discard:
878              bClose = false;                          break;
879              break;                  default:    // Cancel.
880          }                          bClose = false;
881      }                          break;
882                    }
883      // If we may close it, dot it.          }
884      if (bClose) {  
885          // Remove all channel strips from sight...          // If we may close it, dot it.
886          m_pWorkspace->setUpdatesEnabled(false);          if (bClose) {
887          QWidgetList wlist = m_pWorkspace->windowList();                  // Remove all channel strips from sight...
888          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  m_pWorkspace->setUpdatesEnabled(false);
889              ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  QWidgetList wlist = m_pWorkspace->windowList();
890              if (pChannelStrip) {                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
891                  qsamplerChannel *pChannel = pChannelStrip->channel();                          ChannelStrip *pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
892                  if (bForce && pChannel)                          if (pChannelStrip) {
893                      pChannel->removeChannel();                                  Channel *pChannel = pChannelStrip->channel();
894                  delete pChannelStrip;                                  if (bForce && pChannel)
895              }                                          pChannel->removeChannel();
896          }                                  delete pChannelStrip;
897          m_pWorkspace->setUpdatesEnabled(true);                          }
898          // We're now clean, for sure.                  }
899          m_iDirtyCount = 0;                  m_pWorkspace->setUpdatesEnabled(true);
900      }                  // We're now clean, for sure.
901                    m_iDirtyCount = 0;
902            }
903    
904      return bClose;          return bClose;
905  }  }
906    
907    
908  // Load a session from specific file path.  // Load a session from specific file path.
909  bool MainForm::loadSessionFile ( const QString& sFilename )  bool MainForm::loadSessionFile ( const QString& sFilename )
910  {  {
911      if (m_pClient == NULL)          if (m_pClient == NULL)
912          return false;                  return false;
913    
914      // Open and read from real file.          // Open and read from real file.
915      QFile file(sFilename);          QFile file(sFilename);
916      if (!file.open(IO_ReadOnly)) {          if (!file.open(QIODevice::ReadOnly)) {
917          appendMessagesError(tr("Could not open \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
918          return false;                          tr("Could not open \"%1\" session file.\n\nSorry.")
919      }                          .arg(sFilename));
920                    return false;
921            }
922    
923          // Tell the world we'll take some time...          // Tell the world we'll take some time...
924          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
925    
926      // Read the file.          // Read the file.
927          int iLine = 0;          int iLine = 0;
928      int iErrors = 0;          int iErrors = 0;
929      QTextStream ts(&file);          QTextStream ts(&file);
930      while (!ts.atEnd()) {          while (!ts.atEnd()) {
931          // Read the line.                  // Read the line.
932          QString sCommand = ts.readLine().stripWhiteSpace();                  QString sCommand = ts.readLine().trimmed();
933                  iLine++;                  iLine++;
934          // If not empty, nor a comment, call the server...                  // If not empty, nor a comment, call the server...
935          if (!sCommand.isEmpty() && sCommand[0] != '#') {                  if (!sCommand.isEmpty() && sCommand[0] != '#') {
936                          // Remember that, no matter what,                          // Remember that, no matter what,
937                          // all LSCP commands are CR/LF terminated.                          // all LSCP commands are CR/LF terminated.
938                          sCommand += "\r\n";                          sCommand += "\r\n";
939                          if (::lscp_client_query(m_pClient, sCommand.latin1()) != LSCP_OK) {                          if (::lscp_client_query(m_pClient, sCommand.toUtf8().constData())
940                                    != LSCP_OK) {
941                                  appendMessagesColor(QString("%1(%2): %3")                                  appendMessagesColor(QString("%1(%2): %3")
942                                          .arg(QFileInfo(sFilename).fileName()).arg(iLine)                                          .arg(QFileInfo(sFilename).fileName()).arg(iLine)
943                                          .arg(sCommand.simplifyWhiteSpace()), "#996633");                                          .arg(sCommand.simplified()), "#996633");
944                                  appendMessagesClient("lscp_client_query");                                  appendMessagesClient("lscp_client_query");
945                                  iErrors++;                                  iErrors++;
946                          }                          }
947          }                  }
948          // Try to make it snappy :)                  // Try to make it snappy :)
949          QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
950      }          }
951    
952      // Ok. we've read it.          // Ok. we've read it.
953      file.close();          file.close();
954    
955          // Now we'll try to create (update) the whole GUI session.          // Now we'll try to create (update) the whole GUI session.
956          updateSession();          updateSession();
# Line 800  bool MainForm::loadSessionFile ( const Q Line 959  bool MainForm::loadSessionFile ( const Q
959          QApplication::restoreOverrideCursor();          QApplication::restoreOverrideCursor();
960    
961          // Have we any errors?          // Have we any errors?
962          if (iErrors > 0)          if (iErrors > 0) {
963                  appendMessagesError(tr("Session loaded with errors\nfrom \"%1\".\n\nSorry.").arg(sFilename));                  appendMessagesError(
964                            tr("Session loaded with errors\nfrom \"%1\".\n\nSorry.")
965                            .arg(sFilename));
966            }
967    
968      // Save as default session directory.          // Save as default session directory.
969      if (m_pOptions)          if (m_pOptions)
970          m_pOptions->sSessionDir = QFileInfo(sFilename).dirPath(true);                  m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();
971          // We're not dirty anymore, if loaded without errors,          // We're not dirty anymore, if loaded without errors,
972          m_iDirtyCount = iErrors;          m_iDirtyCount = iErrors;
973      // Stabilize form...          // Stabilize form...
974      m_sFilename = sFilename;          m_sFilename = sFilename;
975      updateRecentFiles(sFilename);          updateRecentFiles(sFilename);
976      appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));          appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));
977    
978      // Make that an overall update.          // Make that an overall update.
979      stabilizeForm();          stabilizeForm();
980      return true;          return true;
981  }  }
982    
983    
# Line 831  bool MainForm::saveSessionFile ( const Q Line 993  bool MainForm::saveSessionFile ( const Q
993                  return false;                  return false;
994          }          }
995    
996      // Open and write into real file.          // Open and write into real file.
997      QFile file(sFilename);          QFile file(sFilename);
998      if (!file.open(IO_WriteOnly | IO_Truncate)) {          if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
999          appendMessagesError(tr("Could not open \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
1000          return false;                          tr("Could not open \"%1\" session file.\n\nSorry.")
1001      }                          .arg(sFilename));
1002                    return false;
1003            }
1004    
1005          // Tell the world we'll take some time...          // Tell the world we'll take some time...
1006          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1007    
1008      // Write the file.          // Write the file.
1009      int  iErrors = 0;          int  iErrors = 0;
1010      QTextStream ts(&file);          QTextStream ts(&file);
1011      ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;          ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;
1012      ts << "# " << tr("Version")          ts << "# " << tr("Version")
1013         << ": " QSAMPLER_VERSION << endl;          << ": " QSAMPLER_VERSION << endl;
1014      ts << "# " << tr("Build")          ts << "# " << tr("Build")
1015         << ": " __DATE__ " " __TIME__ << endl;          << ": " __DATE__ " " __TIME__ << endl;
1016      ts << "#"  << endl;          ts << "#"  << endl;
1017      ts << "# " << tr("File")          ts << "# " << tr("File")
1018         << ": " << QFileInfo(sFilename).fileName() << endl;          << ": " << QFileInfo(sFilename).fileName() << endl;
1019      ts << "# " << tr("Date")          ts << "# " << tr("Date")
1020         << ": " << QDate::currentDate().toString("MMM dd yyyy")          << ": " << QDate::currentDate().toString("MMM dd yyyy")
1021         << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;          << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;
1022      ts << "#"  << endl;          ts << "#"  << endl;
1023      ts << endl;          ts << endl;
1024    
1025          // It is assumed that this new kind of device+session file          // It is assumed that this new kind of device+session file
1026          // will be loaded from a complete initialized server...          // will be loaded from a complete initialized server...
# Line 866  bool MainForm::saveSessionFile ( const Q Line 1030  bool MainForm::saveSessionFile ( const Q
1030    
1031          // Audio device mapping.          // Audio device mapping.
1032          QMap<int, int> audioDeviceMap;          QMap<int, int> audioDeviceMap;
1033          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Audio);          piDeviceIDs = Device::getDevices(m_pClient, Device::Audio);
1034          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
1035                  ts << endl;                  ts << endl;
1036                  qsamplerDevice device(qsamplerDevice::Audio, piDeviceIDs[iDevice]);                  Device device(Device::Audio, piDeviceIDs[iDevice]);
1037                  // Audio device specification...                  // Audio device specification...
1038                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1039                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1040                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();                  ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();
1041                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
1042                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
1043                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
1044                                          ++deviceParam) {                                          ++deviceParam) {
1045                          const qsamplerDeviceParam& param = deviceParam.data();                          const DeviceParam& param = deviceParam.value();
1046                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
1047                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
1048                  }                  }
1049                  ts << endl;                  ts << endl;
1050                  // Audio channel parameters...                  // Audio channel parameters...
1051                  int iPort = 0;                  int iPort = 0;
1052                  for (qsamplerDevicePort *pPort = device.ports().first();                  QListIterator<DevicePort *> iter(device.ports());
1053                                  pPort;                  while (iter.hasNext()) {
1054                                          pPort = device.ports().next(), ++iPort) {                          DevicePort *pPort = iter.next();
1055                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1056                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1057                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1058                                                  ++portParam) {                                                  ++portParam) {
1059                                  const qsamplerDeviceParam& param = portParam.data();                                  const DeviceParam& param = portParam.value();
1060                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1061                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice                                  ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice
1062                                          << " " << iPort << " " << portParam.key()                                          << " " << iPort << " " << portParam.key()
1063                                          << "='" << param.value << "'" << endl;                                          << "='" << param.value << "'" << endl;
1064                          }                          }
1065                            iPort++;
1066                  }                  }
1067                  // Audio device index/id mapping.                  // Audio device index/id mapping.
1068                  audioDeviceMap[device.deviceID()] = iDevice;                  audioDeviceMap[device.deviceID()] = iDevice;
1069                  // Try to keep it snappy :)                  // Try to keep it snappy :)
1070                  QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1071          }          }
1072    
1073          // MIDI device mapping.          // MIDI device mapping.
1074          QMap<int, int> midiDeviceMap;          QMap<int, int> midiDeviceMap;
1075          piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Midi);          piDeviceIDs = Device::getDevices(m_pClient, Device::Midi);
1076          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {          for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
1077                  ts << endl;                  ts << endl;
1078                  qsamplerDevice device(qsamplerDevice::Midi, piDeviceIDs[iDevice]);                  Device device(Device::Midi, piDeviceIDs[iDevice]);
1079                  // MIDI device specification...                  // MIDI device specification...
1080                  ts << "# " << device.deviceTypeName() << " " << device.driverName()                  ts << "# " << device.deviceTypeName() << " " << device.driverName()
1081                          << " " << tr("Device") << " " << iDevice << endl;                          << " " << tr("Device") << " " << iDevice << endl;
1082                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();                  ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();
1083                  qsamplerDeviceParamMap::ConstIterator deviceParam;                  DeviceParamMap::ConstIterator deviceParam;
1084                  for (deviceParam = device.params().begin();                  for (deviceParam = device.params().begin();
1085                                  deviceParam != device.params().end();                                  deviceParam != device.params().end();
1086                                          ++deviceParam) {                                          ++deviceParam) {
1087                          const qsamplerDeviceParam& param = deviceParam.data();                          const DeviceParam& param = deviceParam.value();
1088                          if (param.value.isEmpty()) ts << "# ";                          if (param.value.isEmpty()) ts << "# ";
1089                          ts << " " << deviceParam.key() << "='" << param.value << "'";                          ts << " " << deviceParam.key() << "='" << param.value << "'";
1090                  }                  }
1091                  ts << endl;                  ts << endl;
1092                  // MIDI port parameters...                  // MIDI port parameters...
1093                  int iPort = 0;                  int iPort = 0;
1094                  for (qsamplerDevicePort *pPort = device.ports().first();                  QListIterator<DevicePort *> iter(device.ports());
1095                                  pPort;                  while (iter.hasNext()) {
1096                                          pPort = device.ports().next(), ++iPort) {                          DevicePort *pPort = iter.next();
1097                          qsamplerDeviceParamMap::ConstIterator portParam;                          DeviceParamMap::ConstIterator portParam;
1098                          for (portParam = pPort->params().begin();                          for (portParam = pPort->params().begin();
1099                                          portParam != pPort->params().end();                                          portParam != pPort->params().end();
1100                                                  ++portParam) {                                                  ++portParam) {
1101                                  const qsamplerDeviceParam& param = portParam.data();                                  const DeviceParam& param = portParam.value();
1102                                  if (param.fix || param.value.isEmpty()) ts << "# ";                                  if (param.fix || param.value.isEmpty()) ts << "# ";
1103                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice                                  ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice
1104                                     << " " << iPort << " " << portParam.key()                                  << " " << iPort << " " << portParam.key()
1105                                     << "='" << param.value << "'" << endl;                                  << "='" << param.value << "'" << endl;
1106                          }                          }
1107                            iPort++;
1108                  }                  }
1109                  // MIDI device index/id mapping.                  // MIDI device index/id mapping.
1110                  midiDeviceMap[device.deviceID()] = iDevice;                  midiDeviceMap[device.deviceID()] = iDevice;
1111                  // Try to keep it snappy :)                  // Try to keep it snappy :)
1112                  QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1113          }          }
1114          ts << endl;          ts << endl;
1115    
# Line 1000  bool MainForm::saveSessionFile ( const Q Line 1166  bool MainForm::saveSessionFile ( const Q
1166                                  iErrors++;                                  iErrors++;
1167                          }                          }
1168                          // Try to keep it snappy :)                          // Try to keep it snappy :)
1169                          QApplication::processEvents(QEventLoop::ExcludeUserInput);                          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1170                  }                  }
1171                  ts << endl;                  ts << endl;
1172                  // Check for errors...                  // Check for errors...
# Line 1019  bool MainForm::saveSessionFile ( const Q Line 1185  bool MainForm::saveSessionFile ( const Q
1185  #endif  // CONFIG_MIDI_INSTRUMENT  #endif  // CONFIG_MIDI_INSTRUMENT
1186    
1187          // Sampler channel mapping.          // Sampler channel mapping.
1188      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
1189      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1190          ChannelStrip* pChannelStrip                  ChannelStrip* pChannelStrip
1191                          = static_cast<ChannelStrip *> (wlist.at(iChannel));                          = static_cast<ChannelStrip *> (wlist.at(iChannel));
1192          if (pChannelStrip) {                  if (pChannelStrip) {
1193              qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
1194              if (pChannel) {                          if (pChannel) {
1195                  ts << "# " << tr("Channel") << " " << iChannel << endl;                                  ts << "# " << tr("Channel") << " " << iChannel << endl;
1196                  ts << "ADD CHANNEL" << endl;                                  ts << "ADD CHANNEL" << endl;
1197                                  if (audioDeviceMap.isEmpty()) {                                  if (audioDeviceMap.isEmpty()) {
1198                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel
1199                                                  << " " << pChannel->audioDriver() << endl;                                                  << " " << pChannel->audioDriver() << endl;
# Line 1044  bool MainForm::saveSessionFile ( const Q Line 1210  bool MainForm::saveSessionFile ( const Q
1210                                  }                                  }
1211                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel                                  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel
1212                                          << " " << pChannel->midiPort() << endl;                                          << " " << pChannel->midiPort() << endl;
1213                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";                                  ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";
1214                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)                                  if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
1215                      ts << "ALL";                                          ts << "ALL";
1216                  else                                  else
1217                      ts << pChannel->midiChannel();                                          ts << pChannel->midiChannel();
1218                  ts << endl;                                  ts << endl;
1219                  ts << "LOAD ENGINE " << pChannel->engineName() << " " << iChannel << endl;                                  ts << "LOAD ENGINE " << pChannel->engineName()
1220                                            << " " << iChannel << endl;
1221                                  if (pChannel->instrumentStatus() < 100) ts << "# ";                                  if (pChannel->instrumentStatus() < 100) ts << "# ";
1222                                  ts << "LOAD INSTRUMENT NON_MODAL '" << pChannel->instrumentFile() << "' "                                  ts << "LOAD INSTRUMENT NON_MODAL '"
1223                                            << pChannel->instrumentFile() << "' "
1224                                          << pChannel->instrumentNr() << " " << iChannel << endl;                                          << pChannel->instrumentNr() << " " << iChannel << endl;
1225                                  qsamplerChannelRoutingMap::ConstIterator audioRoute;                                  ChannelRoutingMap::ConstIterator audioRoute;
1226                                  for (audioRoute = pChannel->audioRouting().begin();                                  for (audioRoute = pChannel->audioRouting().begin();
1227                                                  audioRoute != pChannel->audioRouting().end();                                                  audioRoute != pChannel->audioRouting().end();
1228                                                          ++audioRoute) {                                                          ++audioRoute) {
1229                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannel                                          ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannel
1230                                                  << " " << audioRoute.key()                                                  << " " << audioRoute.key()
1231                                                  << " " << audioRoute.data() << endl;                                                  << " " << audioRoute.value() << endl;
1232                                  }                                  }
1233                                  ts << "SET CHANNEL VOLUME " << iChannel                                  ts << "SET CHANNEL VOLUME " << iChannel
1234                                          << " " << pChannel->volume() << endl;                                          << " " << pChannel->volume() << endl;
# Line 1110  bool MainForm::saveSessionFile ( const Q Line 1278  bool MainForm::saveSessionFile ( const Q
1278                                          }                                          }
1279                                  }                                  }
1280  #endif  #endif
1281                  ts << endl;                                  ts << endl;
1282              }                          }
1283          }                  }
1284          // Try to keep it snappy :)                  // Try to keep it snappy :)
1285          QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1286      }          }
1287    
1288  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
1289          ts << "# " << tr("Global volume level") << endl;          ts << "# " << tr("Global volume level") << endl;
# Line 1123  bool MainForm::saveSessionFile ( const Q Line 1291  bool MainForm::saveSessionFile ( const Q
1291          ts << endl;          ts << endl;
1292  #endif  #endif
1293    
1294      // Ok. we've wrote it.          // Ok. we've wrote it.
1295      file.close();          file.close();
1296    
1297          // We're fornerly done.          // We're fornerly done.
1298          QApplication::restoreOverrideCursor();          QApplication::restoreOverrideCursor();
1299    
1300      // Have we any errors?          // Have we any errors?
1301      if (iErrors > 0)          if (iErrors > 0) {
1302          appendMessagesError(tr("Some settings could not be saved\nto \"%1\" session file.\n\nSorry.").arg(sFilename));                  appendMessagesError(
1303                            tr("Some settings could not be saved\n"
1304      // Save as default session directory.                          "to \"%1\" session file.\n\nSorry.")
1305      if (m_pOptions)                          .arg(sFilename));
1306          m_pOptions->sSessionDir = QFileInfo(sFilename).dirPath(true);          }
1307      // We're not dirty anymore.  
1308      m_iDirtyCount = 0;          // Save as default session directory.
1309      // Stabilize form...          if (m_pOptions)
1310      m_sFilename = sFilename;                  m_pOptions->sSessionDir = QFileInfo(sFilename).dir().absolutePath();
1311      updateRecentFiles(sFilename);          // We're not dirty anymore.
1312      appendMessages(tr("Save session: \"%1\".").arg(sessionName(m_sFilename)));          m_iDirtyCount = 0;
1313      stabilizeForm();          // Stabilize form...
1314      return true;          m_sFilename = sFilename;
1315            updateRecentFiles(sFilename);
1316            appendMessages(tr("Save session: \"%1\".").arg(sessionName(m_sFilename)));
1317            stabilizeForm();
1318            return true;
1319  }  }
1320    
1321    
1322  // Session change receiver slot.  // Session change receiver slot.
1323  void MainForm::sessionDirty (void)  void MainForm::sessionDirty (void)
1324  {  {
1325      // Just mark the dirty form.          // Just mark the dirty form.
1326      m_iDirtyCount++;          m_iDirtyCount++;
1327      // and update the form status...          // and update the form status...
1328      stabilizeForm();          stabilizeForm();
1329  }  }
1330    
1331    
# Line 1163  void MainForm::sessionDirty (void) Line 1335  void MainForm::sessionDirty (void)
1335  // Create a new sampler session.  // Create a new sampler session.
1336  void MainForm::fileNew (void)  void MainForm::fileNew (void)
1337  {  {
1338      // Of course we'll start clean new.          // Of course we'll start clean new.
1339      newSession();          newSession();
1340  }  }
1341    
1342    
1343  // Open an existing sampler session.  // Open an existing sampler session.
1344  void MainForm::fileOpen (void)  void MainForm::fileOpen (void)
1345  {  {
1346      // Open it right away.          // Open it right away.
1347      openSession();          openSession();
1348  }  }
1349    
1350    
1351  // Open a recent file session.  // Open a recent file session.
1352  void MainForm::fileOpenRecent ( int iIndex )  void MainForm::fileOpenRecent (void)
1353  {  {
1354      // Check if we can safely close the current session...          // Retrive filename index from action data...
1355      if (m_pOptions && closeSession(true)) {          QAction *pAction = qobject_cast<QAction *> (sender());
1356          QString sFilename = m_pOptions->recentFiles[iIndex];          if (pAction && m_pOptions) {
1357          loadSessionFile(sFilename);                  int iIndex = pAction->data().toInt();
1358      }                  if (iIndex >= 0 && iIndex < m_pOptions->recentFiles.count()) {
1359                            QString sFilename = m_pOptions->recentFiles[iIndex];
1360                            // Check if we can safely close the current session...
1361                            if (!sFilename.isEmpty() && closeSession(true))
1362                                    loadSessionFile(sFilename);
1363                    }
1364            }
1365  }  }
1366    
1367    
1368  // Save current sampler session.  // Save current sampler session.
1369  void MainForm::fileSave (void)  void MainForm::fileSave (void)
1370  {  {
1371      // Save it right away.          // Save it right away.
1372      saveSession(false);          saveSession(false);
1373  }  }
1374    
1375    
1376  // Save current sampler session with another name.  // Save current sampler session with another name.
1377  void MainForm::fileSaveAs (void)  void MainForm::fileSaveAs (void)
1378  {  {
1379      // Save it right away, maybe with another name.          // Save it right away, maybe with another name.
1380      saveSession(true);          saveSession(true);
1381  }  }
1382    
1383    
1384  // Reset the sampler instance.  // Reset the sampler instance.
1385  void MainForm::fileReset (void)  void MainForm::fileReset (void)
1386  {  {
1387      if (m_pClient == NULL)          if (m_pClient == NULL)
1388          return;                  return;
1389    
1390      // Ask user whether he/she want's an internal sampler reset...          // Ask user whether he/she want's an internal sampler reset...
1391      if (QMessageBox::warning(this,          if (QMessageBox::warning(this,
1392                  QSAMPLER_TITLE ": " + tr("Warning"),                  QSAMPLER_TITLE ": " + tr("Warning"),
1393          tr("Resetting the sampler instance will close\n"                  tr("Resetting the sampler instance will close\n"
1394             "all device and channel configurations.\n\n"                  "all device and channel configurations.\n\n"
1395             "Please note that this operation may cause\n"                  "Please note that this operation may cause\n"
1396             "temporary MIDI and Audio disruption.\n\n"                  "temporary MIDI and Audio disruption.\n\n"
1397             "Do you want to reset the sampler engine now?"),                  "Do you want to reset the sampler engine now?"),
1398          tr("Reset"), tr("Cancel")) > 0)                  QMessageBox::Ok | QMessageBox::Cancel)
1399          return;                  == QMessageBox::Cancel)
1400                    return;
1401    
1402          // Trye closing the current session, first...          // Trye closing the current session, first...
1403          if (!closeSession(true))          if (!closeSession(true))
1404                  return;                  return;
1405    
1406      // Just do the reset, after closing down current session...          // Just do the reset, after closing down current session...
1407          // Do the actual sampler reset...          // Do the actual sampler reset...
1408          if (::lscp_reset_sampler(m_pClient) != LSCP_OK) {          if (::lscp_reset_sampler(m_pClient) != LSCP_OK) {
1409                  appendMessagesClient("lscp_reset_sampler");                  appendMessagesClient("lscp_reset_sampler");
# Line 1232  void MainForm::fileReset (void) Line 1411  void MainForm::fileReset (void)
1411                  return;                  return;
1412          }          }
1413    
1414      // Log this.          // Log this.
1415      appendMessages(tr("Sampler reset."));          appendMessages(tr("Sampler reset."));
1416    
1417          // Make it a new session...          // Make it a new session...
1418          newSession();          newSession();
# Line 1243  void MainForm::fileReset (void) Line 1422  void MainForm::fileReset (void)
1422  // Restart the client/server instance.  // Restart the client/server instance.
1423  void MainForm::fileRestart (void)  void MainForm::fileRestart (void)
1424  {  {
1425      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1426          return;                  return;
1427    
1428      bool bRestart = true;          bool bRestart = true;
1429    
1430      // Ask user whether he/she want's a complete restart...          // Ask user whether he/she want's a complete restart...
1431      // (if we're currently up and running)          // (if we're currently up and running)
1432      if (bRestart && m_pClient) {          if (bRestart && m_pClient) {
1433          bRestart = (QMessageBox::warning(this,                  bRestart = (QMessageBox::warning(this,
1434                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
1435              tr("New settings will be effective after\n"                          tr("New settings will be effective after\n"
1436                 "restarting the client/server connection.\n\n"                          "restarting the client/server connection.\n\n"
1437                 "Please note that this operation may cause\n"                          "Please note that this operation may cause\n"
1438                 "temporary MIDI and Audio disruption.\n\n"                          "temporary MIDI and Audio disruption.\n\n"
1439                 "Do you want to restart the connection now?"),                          "Do you want to restart the connection now?"),
1440              tr("Restart"), tr("Cancel")) == 0);                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok);
1441      }          }
1442    
1443      // Are we still for it?          // Are we still for it?
1444      if (bRestart && closeSession(true)) {          if (bRestart && closeSession(true)) {
1445          // Stop server, it will force the client too.                  // Stop server, it will force the client too.
1446          stopServer();                  stopServer();
1447          // Reschedule a restart...                  // Reschedule a restart...
1448          startSchedule(m_pOptions->iStartDelay);                  startSchedule(m_pOptions->iStartDelay);
1449      }          }
1450  }  }
1451    
1452    
1453  // Exit application program.  // Exit application program.
1454  void MainForm::fileExit (void)  void MainForm::fileExit (void)
1455  {  {
1456      // Go for close the whole thing.          // Go for close the whole thing.
1457      close();          close();
1458  }  }
1459    
1460    
# Line 1285  void MainForm::fileExit (void) Line 1464  void MainForm::fileExit (void)
1464  // Add a new sampler channel.  // Add a new sampler channel.
1465  void MainForm::editAddChannel (void)  void MainForm::editAddChannel (void)
1466  {  {
1467      if (m_pClient == NULL)          if (m_pClient == NULL)
1468          return;                  return;
1469    
1470      // Just create the channel instance...          // Just create the channel instance...
1471      qsamplerChannel *pChannel = new qsamplerChannel();          Channel *pChannel = new Channel();
1472      if (pChannel == NULL)          if (pChannel == NULL)
1473          return;                  return;
1474    
1475      // Before we show it up, may be we'll          // Before we show it up, may be we'll
1476      // better ask for some initial values?          // better ask for some initial values?
1477      if (!pChannel->channelSetup(this)) {          if (!pChannel->channelSetup(this)) {
1478          delete pChannel;                  delete pChannel;
1479          return;                  return;
1480      }          }
1481    
1482      // And give it to the strip (will own the channel instance, if successful).          // And give it to the strip...
1483      if (!createChannelStrip(pChannel)) {          // (will own the channel instance, if successful).
1484          delete pChannel;          if (!createChannelStrip(pChannel)) {
1485          return;                  delete pChannel;
1486      }                  return;
1487            }
1488      // Make that an overall update.  
1489      m_iDirtyCount++;          // Do we auto-arrange?
1490      stabilizeForm();          if (m_pOptions && m_pOptions->bAutoArrange)
1491                    channelsArrange();
1492    
1493            // Make that an overall update.
1494            m_iDirtyCount++;
1495            stabilizeForm();
1496  }  }
1497    
1498    
1499  // Remove current sampler channel.  // Remove current sampler channel.
1500  void MainForm::editRemoveChannel (void)  void MainForm::editRemoveChannel (void)
1501  {  {
1502      if (m_pClient == NULL)          if (m_pClient == NULL)
1503          return;                  return;
1504    
1505      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1506      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1507          return;                  return;
1508    
1509      qsamplerChannel *pChannel = pChannelStrip->channel();          Channel *pChannel = pChannelStrip->channel();
1510      if (pChannel == NULL)          if (pChannel == NULL)
1511          return;                  return;
1512    
1513      // Prompt user if he/she's sure about this...          // Prompt user if he/she's sure about this...
1514      if (m_pOptions && m_pOptions->bConfirmRemove) {          if (m_pOptions && m_pOptions->bConfirmRemove) {
1515          if (QMessageBox::warning(this,                  if (QMessageBox::warning(this,
1516                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
1517              tr("About to remove channel:\n\n"                          tr("About to remove channel:\n\n"
1518                 "%1\n\n"                          "%1\n\n"
1519                 "Are you sure?")                          "Are you sure?")
1520                 .arg(pChannelStrip->caption()),                          .arg(pChannelStrip->windowTitle()),
1521              tr("OK"), tr("Cancel")) > 0)                          QMessageBox::Ok | QMessageBox::Cancel)
1522              return;                          == QMessageBox::Cancel)
1523      }                          return;
1524            }
1525      // Remove the existing sampler channel.  
1526      if (!pChannel->removeChannel())          // Remove the existing sampler channel.
1527          return;          if (!pChannel->removeChannel())
1528                    return;
1529      // Just delete the channel strip.  
1530      delete pChannelStrip;          // Just delete the channel strip.
1531            delete pChannelStrip;
1532      // Do we auto-arrange?  
1533      if (m_pOptions && m_pOptions->bAutoArrange)          // Do we auto-arrange?
1534          channelsArrange();          if (m_pOptions && m_pOptions->bAutoArrange)
1535                    channelsArrange();
1536      // We'll be dirty, for sure...  
1537      m_iDirtyCount++;          // We'll be dirty, for sure...
1538      stabilizeForm();          m_iDirtyCount++;
1539            stabilizeForm();
1540  }  }
1541    
1542    
1543  // Setup current sampler channel.  // Setup current sampler channel.
1544  void MainForm::editSetupChannel (void)  void MainForm::editSetupChannel (void)
1545  {  {
1546      if (m_pClient == NULL)          if (m_pClient == NULL)
1547          return;                  return;
1548    
1549      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1550      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1551          return;                  return;
1552    
1553      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1554      pChannelStrip->channelSetup();          pChannelStrip->channelSetup();
1555  }  }
1556    
1557    
1558  // Edit current sampler channel.  // Edit current sampler channel.
1559  void MainForm::editEditChannel (void)  void MainForm::editEditChannel (void)
1560  {  {
1561      if (m_pClient == NULL)          if (m_pClient == NULL)
1562          return;                  return;
1563    
1564      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1565      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1566          return;                  return;
1567    
1568      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1569      pChannelStrip->channelEdit();          pChannelStrip->channelEdit();
1570  }  }
1571    
1572    
1573  // Reset current sampler channel.  // Reset current sampler channel.
1574  void MainForm::editResetChannel (void)  void MainForm::editResetChannel (void)
1575  {  {
1576      if (m_pClient == NULL)          if (m_pClient == NULL)
1577          return;                  return;
1578    
1579      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip* pChannelStrip = activeChannelStrip();
1580      if (pChannelStrip == NULL)          if (pChannelStrip == NULL)
1581          return;                  return;
1582    
1583      // Just invoque the channel strip procedure.          // Just invoque the channel strip procedure.
1584      pChannelStrip->channelReset();          pChannelStrip->channelReset();
1585  }  }
1586    
1587    
# Line 1425  void MainForm::editResetAllChannels (voi Line 1610  void MainForm::editResetAllChannels (voi
1610  // Show/hide the main program window menubar.  // Show/hide the main program window menubar.
1611  void MainForm::viewMenubar ( bool bOn )  void MainForm::viewMenubar ( bool bOn )
1612  {  {
1613      if (bOn)          if (bOn)
1614          ui.MenuBar->show();                  m_ui.MenuBar->show();
1615      else          else
1616          ui.MenuBar->hide();                  m_ui.MenuBar->hide();
1617  }  }
1618    
1619    
1620  // Show/hide the main program window toolbar.  // Show/hide the main program window toolbar.
1621  void MainForm::viewToolbar ( bool bOn )  void MainForm::viewToolbar ( bool bOn )
1622  {  {
1623      if (bOn) {          if (bOn) {
1624          ui.fileToolbar->show();                  m_ui.fileToolbar->show();
1625          ui.editToolbar->show();                  m_ui.editToolbar->show();
1626          ui.channelsToolbar->show();                  m_ui.channelsToolbar->show();
1627      } else {          } else {
1628          ui.fileToolbar->hide();                  m_ui.fileToolbar->hide();
1629          ui.editToolbar->hide();                  m_ui.editToolbar->hide();
1630          ui.channelsToolbar->hide();                  m_ui.channelsToolbar->hide();
1631      }          }
1632  }  }
1633    
1634    
1635  // Show/hide the main program window statusbar.  // Show/hide the main program window statusbar.
1636  void MainForm::viewStatusbar ( bool bOn )  void MainForm::viewStatusbar ( bool bOn )
1637  {  {
1638      if (bOn)          if (bOn)
1639          statusBar()->show();                  statusBar()->show();
1640      else          else
1641          statusBar()->hide();                  statusBar()->hide();
1642  }  }
1643    
1644    
1645  // Show/hide the messages window logger.  // Show/hide the messages window logger.
1646  void MainForm::viewMessages ( bool bOn )  void MainForm::viewMessages ( bool bOn )
1647  {  {
1648      if (bOn)          if (bOn)
1649          m_pMessages->show();                  m_pMessages->show();
1650      else          else
1651          m_pMessages->hide();                  m_pMessages->hide();
1652  }  }
1653    
1654    
# Line 1480  void MainForm::viewInstruments (void) Line 1665  void MainForm::viewInstruments (void)
1665                  } else {                  } else {
1666                          m_pInstrumentListForm->show();                          m_pInstrumentListForm->show();
1667                          m_pInstrumentListForm->raise();                          m_pInstrumentListForm->raise();
1668                          m_pInstrumentListForm->setActiveWindow();                          m_pInstrumentListForm->activateWindow();
1669                  }                  }
1670          }          }
1671  }  }
# Line 1499  void MainForm::viewDevices (void) Line 1684  void MainForm::viewDevices (void)
1684                  } else {                  } else {
1685                          m_pDeviceForm->show();                          m_pDeviceForm->show();
1686                          m_pDeviceForm->raise();                          m_pDeviceForm->raise();
1687                          m_pDeviceForm->setActiveWindow();                          m_pDeviceForm->activateWindow();
1688                  }                  }
1689          }          }
1690  }  }
# Line 1508  void MainForm::viewDevices (void) Line 1693  void MainForm::viewDevices (void)
1693  // Show options dialog.  // Show options dialog.
1694  void MainForm::viewOptions (void)  void MainForm::viewOptions (void)
1695  {  {
1696      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1697          return;                  return;
1698    
1699      OptionsForm* pOptionsForm = new OptionsForm(this);          OptionsForm* pOptionsForm = new OptionsForm(this);
1700      if (pOptionsForm) {          if (pOptionsForm) {
1701          // Check out some initial nullities(tm)...                  // Check out some initial nullities(tm)...
1702          ChannelStrip* pChannelStrip = activeChannelStrip();                  ChannelStrip* pChannelStrip = activeChannelStrip();
1703          if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)                  if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)
1704              m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();                          m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();
1705          if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)                  if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)
1706              m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();                          m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
1707          // To track down deferred or immediate changes.                  // To track down deferred or immediate changes.
1708          QString sOldServerHost      = m_pOptions->sServerHost;                  QString sOldServerHost      = m_pOptions->sServerHost;
1709          int     iOldServerPort      = m_pOptions->iServerPort;                  int     iOldServerPort      = m_pOptions->iServerPort;
1710          int     iOldServerTimeout   = m_pOptions->iServerTimeout;                  int     iOldServerTimeout   = m_pOptions->iServerTimeout;
1711          bool    bOldServerStart     = m_pOptions->bServerStart;                  bool    bOldServerStart     = m_pOptions->bServerStart;
1712          QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;                  QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;
1713          QString sOldDisplayFont     = m_pOptions->sDisplayFont;                  bool    bOldMessagesLog     = m_pOptions->bMessagesLog;
1714          bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;                  QString sOldMessagesLogPath = m_pOptions->sMessagesLogPath;
1715          int     iOldMaxVolume       = m_pOptions->iMaxVolume;                  QString sOldDisplayFont     = m_pOptions->sDisplayFont;
1716          QString sOldMessagesFont    = m_pOptions->sMessagesFont;                  bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;
1717          bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;                  int     iOldMaxVolume       = m_pOptions->iMaxVolume;
1718          bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;                  QString sOldMessagesFont    = m_pOptions->sMessagesFont;
1719          int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;                  bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;
1720          int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;                  bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;
1721          bool    bOldCompletePath    = m_pOptions->bCompletePath;                  int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;
1722          bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;                  int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;
1723          int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;                  bool    bOldCompletePath    = m_pOptions->bCompletePath;
1724          // Load the current setup settings.                  bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;
1725          pOptionsForm->setup(m_pOptions);                  int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;
1726          // Show the setup dialog...                  int     iOldBaseFontSize    = m_pOptions->iBaseFontSize;
1727          if (pOptionsForm->exec()) {                  // Load the current setup settings.
1728              // Warn if something will be only effective on next run.                  pOptionsForm->setup(m_pOptions);
1729              if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||                  // Show the setup dialog...
1730                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||                  if (pOptionsForm->exec()) {
1731                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||                          // Warn if something will be only effective on next run.
1732                  (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {                          if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1733                  QMessageBox::information(this,                                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||
1734                                    ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||
1735                                    (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)     ||
1736                                    (iOldBaseFontSize   !=  m_pOptions->iBaseFontSize)) {
1737                                    QMessageBox::information(this,
1738                                          QSAMPLER_TITLE ": " + tr("Information"),                                          QSAMPLER_TITLE ": " + tr("Information"),
1739                      tr("Some settings may be only effective\n"                                          tr("Some settings may be only effective\n"
1740                         "next time you start this program."), tr("OK"));                                          "next time you start this program."));
1741                  updateMessagesCapture();                                  updateMessagesCapture();
1742              }                          }
1743              // Check wheather something immediate has changed.                          // Check wheather something immediate has changed.
1744              if (( bOldCompletePath && !m_pOptions->bCompletePath) ||                          if (( bOldMessagesLog && !m_pOptions->bMessagesLog) ||
1745                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||                                  (!bOldMessagesLog &&  m_pOptions->bMessagesLog) ||
1746                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))                                  (sOldMessagesLogPath != m_pOptions->sMessagesLogPath))
1747                  updateRecentFilesMenu();                                  m_pMessages->setLogging(
1748              if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||                                          m_pOptions->bMessagesLog, m_pOptions->sMessagesLogPath);
1749                  (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))                          if (( bOldCompletePath && !m_pOptions->bCompletePath) ||
1750                  updateInstrumentNames();                                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||
1751              if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||                                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
1752                  (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))                                  updateRecentFilesMenu();
1753                  updateDisplayEffect();                          if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||
1754              if (sOldDisplayFont != m_pOptions->sDisplayFont)                                  (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))
1755                  updateDisplayFont();                                  updateInstrumentNames();
1756              if (iOldMaxVolume != m_pOptions->iMaxVolume)                          if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||
1757                  updateMaxVolume();                                  (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))
1758              if (sOldMessagesFont != m_pOptions->sMessagesFont)                                  updateDisplayEffect();
1759                  updateMessagesFont();                          if (sOldDisplayFont != m_pOptions->sDisplayFont)
1760              if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||                                  updateDisplayFont();
1761                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||                          if (iOldMaxVolume != m_pOptions->iMaxVolume)
1762                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))                                  updateMaxVolume();
1763                  updateMessagesLimit();                          if (sOldMessagesFont != m_pOptions->sMessagesFont)
1764              // And now the main thing, whether we'll do client/server recycling?                                  updateMessagesFont();
1765              if ((sOldServerHost != m_pOptions->sServerHost) ||                          if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||
1766                  (iOldServerPort != m_pOptions->iServerPort) ||                                  (!bOldMessagesLimit &&  m_pOptions->bMessagesLimit) ||
1767                  (iOldServerTimeout != m_pOptions->iServerTimeout) ||                                  (iOldMessagesLimitLines !=  m_pOptions->iMessagesLimitLines))
1768                  ( bOldServerStart && !m_pOptions->bServerStart) ||                                  updateMessagesLimit();
1769                  (!bOldServerStart &&  m_pOptions->bServerStart) ||                          // And now the main thing, whether we'll do client/server recycling?
1770                  (sOldServerCmdLine != m_pOptions->sServerCmdLine && m_pOptions->bServerStart))                          if ((sOldServerHost != m_pOptions->sServerHost) ||
1771                  fileRestart();                                  (iOldServerPort != m_pOptions->iServerPort) ||
1772          }                                  (iOldServerTimeout != m_pOptions->iServerTimeout) ||
1773          // Done.                                  ( bOldServerStart && !m_pOptions->bServerStart) ||
1774          delete pOptionsForm;                                  (!bOldServerStart &&  m_pOptions->bServerStart) ||
1775      }                                  (sOldServerCmdLine != m_pOptions->sServerCmdLine
1776                                    && m_pOptions->bServerStart))
1777                                    fileRestart();
1778                    }
1779                    // Done.
1780                    delete pOptionsForm;
1781            }
1782    
1783      // This makes it.          // This makes it.
1784      stabilizeForm();          stabilizeForm();
1785  }  }
1786    
1787    
# Line 1596  void MainForm::viewOptions (void) Line 1791  void MainForm::viewOptions (void)
1791  // Arrange channel strips.  // Arrange channel strips.
1792  void MainForm::channelsArrange (void)  void MainForm::channelsArrange (void)
1793  {  {
1794      // Full width vertical tiling          // Full width vertical tiling
1795      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
1796      if (wlist.isEmpty())          if (wlist.isEmpty())
1797          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);  
1798    
1799      stabilizeForm();          m_pWorkspace->setUpdatesEnabled(false);
1800            int y = 0;
1801            for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1802                    ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
1803            /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {
1804                            // Prevent flicker...
1805                            pChannelStrip->hide();
1806                            pChannelStrip->showNormal();
1807                    }   */
1808                    pChannelStrip->adjustSize();
1809                    int iWidth  = m_pWorkspace->width();
1810                    if (iWidth < pChannelStrip->width())
1811                            iWidth = pChannelStrip->width();
1812            //  int iHeight = pChannelStrip->height()
1813            //              + pChannelStrip->parentWidget()->baseSize().height();
1814                    int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();
1815                    pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);
1816                    y += iHeight;
1817            }
1818            m_pWorkspace->setUpdatesEnabled(true);
1819    
1820            stabilizeForm();
1821  }  }
1822    
1823    
1824  // Auto-arrange channel strips.  // Auto-arrange channel strips.
1825  void MainForm::channelsAutoArrange ( bool bOn )  void MainForm::channelsAutoArrange ( bool bOn )
1826  {  {
1827      if (m_pOptions == NULL)          if (m_pOptions == NULL)
1828          return;                  return;
1829    
1830      // Toggle the auto-arrange flag.          // Toggle the auto-arrange flag.
1831      m_pOptions->bAutoArrange = bOn;          m_pOptions->bAutoArrange = bOn;
1832    
1833      // If on, update whole workspace...          // If on, update whole workspace...
1834      if (m_pOptions->bAutoArrange)          if (m_pOptions->bAutoArrange)
1835          channelsArrange();                  channelsArrange();
1836  }  }
1837    
1838    
# Line 1646  void MainForm::channelsAutoArrange ( boo Line 1842  void MainForm::channelsAutoArrange ( boo
1842  // Show information about the Qt toolkit.  // Show information about the Qt toolkit.
1843  void MainForm::helpAboutQt (void)  void MainForm::helpAboutQt (void)
1844  {  {
1845      QMessageBox::aboutQt(this);          QMessageBox::aboutQt(this);
1846  }  }
1847    
1848    
1849  // Show information about application program.  // Show information about application program.
1850  void MainForm::helpAbout (void)  void MainForm::helpAbout (void)
1851  {  {
1852      // Stuff the about box text...          // Stuff the about box text...
1853      QString sText = "<p>\n";          QString sText = "<p>\n";
1854      sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";          sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";
1855      sText += "<br />\n";          sText += "<br />\n";
1856      sText += tr("Version") + ": <b>" QSAMPLER_VERSION "</b><br />\n";          sText += tr("Version") + ": <b>" QSAMPLER_VERSION "</b><br />\n";
1857      sText += "<small>" + tr("Build") + ": " __DATE__ " " __TIME__ "</small><br />\n";          sText += "<small>" + tr("Build") + ": " __DATE__ " " __TIME__ "</small><br />\n";
1858  #ifdef CONFIG_DEBUG  #ifdef CONFIG_DEBUG
1859      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1860      sText += tr("Debugging option enabled.");          sText += tr("Debugging option enabled.");
1861      sText += "</font></small><br />";          sText += "</font></small><br />";
1862  #endif  #endif
1863  #ifndef CONFIG_LIBGIG  #ifndef CONFIG_LIBGIG
1864      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1865      sText += tr("GIG (libgig) file support disabled.");          sText += tr("GIG (libgig) file support disabled.");
1866      sText += "</font></small><br />";          sText += "</font></small><br />";
1867  #endif  #endif
1868  #ifndef CONFIG_INSTRUMENT_NAME  #ifndef CONFIG_INSTRUMENT_NAME
1869      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1870      sText += tr("LSCP (liblscp) instrument_name support disabled.");          sText += tr("LSCP (liblscp) instrument_name support disabled.");
1871      sText += "</font></small><br />";          sText += "</font></small><br />";
1872  #endif  #endif
1873  #ifndef CONFIG_MUTE_SOLO  #ifndef CONFIG_MUTE_SOLO
1874      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1875      sText += tr("Sampler channel Mute/Solo support disabled.");          sText += tr("Sampler channel Mute/Solo support disabled.");
1876      sText += "</font></small><br />";          sText += "</font></small><br />";
1877  #endif  #endif
1878  #ifndef CONFIG_AUDIO_ROUTING  #ifndef CONFIG_AUDIO_ROUTING
1879      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1880      sText += tr("LSCP (liblscp) audio_routing support disabled.");          sText += tr("LSCP (liblscp) audio_routing support disabled.");
1881      sText += "</font></small><br />";          sText += "</font></small><br />";
1882  #endif  #endif
1883  #ifndef CONFIG_FXSEND  #ifndef CONFIG_FXSEND
1884      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1885      sText += tr("Sampler channel Effect Sends support disabled.");          sText += tr("Sampler channel Effect Sends support disabled.");
1886      sText += "</font></small><br />";          sText += "</font></small><br />";
1887  #endif  #endif
1888  #ifndef CONFIG_VOLUME  #ifndef CONFIG_VOLUME
1889      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1890      sText += tr("Global volume support disabled.");          sText += tr("Global volume support disabled.");
1891      sText += "</font></small><br />";          sText += "</font></small><br />";
1892  #endif  #endif
1893  #ifndef CONFIG_MIDI_INSTRUMENT  #ifndef CONFIG_MIDI_INSTRUMENT
1894      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1895      sText += tr("MIDI instrument mapping support disabled.");          sText += tr("MIDI instrument mapping support disabled.");
1896      sText += "</font></small><br />";          sText += "</font></small><br />";
1897  #endif  #endif
1898  #ifndef CONFIG_EDIT_INSTRUMENT  #ifndef CONFIG_EDIT_INSTRUMENT
1899      sText += "<small><font color=\"red\">";          sText += "<small><font color=\"red\">";
1900      sText += tr("Instrument editing support disabled.");          sText += tr("Instrument editing support disabled.");
1901      sText += "</font></small><br />";          sText += "</font></small><br />";
1902  #endif  #endif
1903      sText += "<br />\n";  #ifndef CONFIG_EVENT_CHANNEL_MIDI
1904      sText += tr("Using") + ": ";          sText += "<small><font color=\"red\">";
1905      sText += ::lscp_client_package();          sText += tr("Channel MIDI event support disabled.");
1906      sText += " ";          sText += "</font></small><br />";
1907      sText += ::lscp_client_version();  #endif
1908    #ifndef CONFIG_EVENT_DEVICE_MIDI
1909            sText += "<small><font color=\"red\">";
1910            sText += tr("Device MIDI event support disabled.");
1911            sText += "</font></small><br />";
1912    #endif
1913    #ifndef CONFIG_MAX_VOICES
1914            sText += "<small><font color=\"red\">";
1915            sText += tr("Runtime max. voices / disk streams support disabled.");
1916            sText += "</font></small><br />";
1917    #endif
1918            sText += "<br />\n";
1919            sText += tr("Using") + ": ";
1920            sText += ::lscp_client_package();
1921            sText += " ";
1922            sText += ::lscp_client_version();
1923  #ifdef CONFIG_LIBGIG  #ifdef CONFIG_LIBGIG
1924      sText += ", ";          sText += ", ";
1925      sText += gig::libraryName().c_str();          sText += gig::libraryName().c_str();
1926      sText += " ";          sText += " ";
1927      sText += gig::libraryVersion().c_str();          sText += gig::libraryVersion().c_str();
1928  #endif  #endif
1929      sText += "<br />\n";          sText += "<br />\n";
1930      sText += "<br />\n";          sText += "<br />\n";
1931      sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";          sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";
1932      sText += "<br />\n";          sText += "<br />\n";
1933      sText += "<small>";          sText += "<small>";
1934      sText += QSAMPLER_COPYRIGHT "<br />\n";          sText += QSAMPLER_COPYRIGHT "<br />\n";
1935      sText += QSAMPLER_COPYRIGHT2 "<br />\n";          sText += QSAMPLER_COPYRIGHT2 "<br />\n";
1936      sText += "<br />\n";          sText += "<br />\n";
1937      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";
1938      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.");
1939      sText += "</small>";          sText += "</small>";
1940      sText += "</p>\n";          sText += "</p>\n";
1941    
1942      QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);          QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);
1943  }  }
1944    
1945    
# Line 1737  void MainForm::helpAbout (void) Line 1948  void MainForm::helpAbout (void)
1948    
1949  void MainForm::stabilizeForm (void)  void MainForm::stabilizeForm (void)
1950  {  {
1951      // Update the main application caption...          // Update the main application caption...
1952      QString sSessionName = sessionName(m_sFilename);          QString sSessionName = sessionName(m_sFilename);
1953      if (m_iDirtyCount > 0)          if (m_iDirtyCount > 0)
1954          sSessionName += " *";                  sSessionName += " *";
1955      setCaption(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));          setWindowTitle(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));
1956    
1957      // Update the main menu state...          // Update the main menu state...
1958      ChannelStrip* pChannelStrip = activeChannelStrip();          ChannelStrip *pChannelStrip = activeChannelStrip();
1959      bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);          bool bHasClient = (m_pOptions != NULL && m_pClient != NULL);
1960      bool bHasChannel = (bHasClient && pChannelStrip != NULL);          bool bHasChannel = (bHasClient && pChannelStrip != NULL);
1961      ui.fileNewAction->setEnabled(bHasClient);          bool bHasChannels = (bHasClient && m_pWorkspace->windowList().count() > 0);
1962      ui.fileOpenAction->setEnabled(bHasClient);          m_ui.fileNewAction->setEnabled(bHasClient);
1963      ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);          m_ui.fileOpenAction->setEnabled(bHasClient);
1964      ui.fileSaveAsAction->setEnabled(bHasClient);          m_ui.fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
1965      ui.fileResetAction->setEnabled(bHasClient);          m_ui.fileSaveAsAction->setEnabled(bHasClient);
1966      ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);          m_ui.fileResetAction->setEnabled(bHasClient);
1967      ui.editAddChannelAction->setEnabled(bHasClient);          m_ui.fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);
1968      ui.editRemoveChannelAction->setEnabled(bHasChannel);          m_ui.editAddChannelAction->setEnabled(bHasClient);
1969      ui.editSetupChannelAction->setEnabled(bHasChannel);          m_ui.editRemoveChannelAction->setEnabled(bHasChannel);
1970            m_ui.editSetupChannelAction->setEnabled(bHasChannel);
1971  #ifdef CONFIG_EDIT_INSTRUMENT  #ifdef CONFIG_EDIT_INSTRUMENT
1972      ui.editEditChannelAction->setEnabled(bHasChannel);          m_ui.editEditChannelAction->setEnabled(bHasChannel);
1973  #else  #else
1974      ui.editEditChannelAction->setEnabled(false);          m_ui.editEditChannelAction->setEnabled(false);
1975  #endif  #endif
1976      ui.editResetChannelAction->setEnabled(bHasChannel);          m_ui.editResetChannelAction->setEnabled(bHasChannel);
1977      ui.editResetAllChannelsAction->setEnabled(bHasChannel);          m_ui.editResetAllChannelsAction->setEnabled(bHasChannels);
1978      ui.viewMessagesAction->setOn(m_pMessages && m_pMessages->isVisible());          m_ui.viewMessagesAction->setChecked(m_pMessages && m_pMessages->isVisible());
1979  #ifdef CONFIG_MIDI_INSTRUMENT  #ifdef CONFIG_MIDI_INSTRUMENT
1980          ui.viewInstrumentsAction->setOn(m_pInstrumentListForm          m_ui.viewInstrumentsAction->setChecked(m_pInstrumentListForm
1981                  && m_pInstrumentListForm->isVisible());                  && m_pInstrumentListForm->isVisible());
1982          ui.viewInstrumentsAction->setEnabled(bHasClient);          m_ui.viewInstrumentsAction->setEnabled(bHasClient);
1983  #else  #else
1984          ui.viewInstrumentsAction->setEnabled(false);          m_ui.viewInstrumentsAction->setEnabled(false);
1985  #endif  #endif
1986          ui.viewDevicesAction->setOn(m_pDeviceForm          m_ui.viewDevicesAction->setChecked(m_pDeviceForm
1987                  && m_pDeviceForm->isVisible());                  && m_pDeviceForm->isVisible());
1988      ui.viewDevicesAction->setEnabled(bHasClient);          m_ui.viewDevicesAction->setEnabled(bHasClient);
1989      ui.channelsArrangeAction->setEnabled(bHasChannel);          m_ui.viewMidiDeviceStatusMenu->setEnabled(
1990                    DeviceStatusForm::getInstances().size() > 0);
1991            m_ui.channelsArrangeAction->setEnabled(bHasChannels);
1992    
1993  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
1994          // Toolbar widgets are also affected...          // Toolbar widgets are also affected...
1995      m_pVolumeSlider->setEnabled(bHasClient);          m_pVolumeSlider->setEnabled(bHasClient);
1996      m_pVolumeSpinBox->setEnabled(bHasClient);          m_pVolumeSpinBox->setEnabled(bHasClient);
1997  #endif  #endif
1998    
1999      // Client/Server status...          // Client/Server status...
2000      if (bHasClient) {          if (bHasClient) {
2001          m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));                  m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));
2002          m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost + ":" + QString::number(m_pOptions->iServerPort));                  m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost
2003      } else {                          + ':' + QString::number(m_pOptions->iServerPort));
2004          m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();          } else {
2005          m_statusItem[QSAMPLER_STATUS_SERVER]->clear();                  m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();
2006      }                  m_statusItem[QSAMPLER_STATUS_SERVER]->clear();
2007      // Channel status...          }
2008      if (bHasChannel)          // Channel status...
2009          m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->caption());          if (bHasChannel)
2010      else                  m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->windowTitle());
2011          m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();          else
2012      // Session status...                  m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();
2013      if (m_iDirtyCount > 0)          // Session status...
2014          m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));          if (m_iDirtyCount > 0)
2015      else                  m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));
2016          m_statusItem[QSAMPLER_STATUS_SESSION]->clear();          else
2017                    m_statusItem[QSAMPLER_STATUS_SESSION]->clear();
2018    
2019      // Recent files menu.          // Recent files menu.
2020      m_pRecentFilesMenu->setEnabled(bHasClient && m_pOptions->recentFiles.count() > 0);          m_ui.fileOpenRecentMenu->setEnabled(m_pOptions->recentFiles.count() > 0);
2021  }  }
2022    
2023    
# Line 1842  void MainForm::volumeChanged ( int iVolu Line 2057  void MainForm::volumeChanged ( int iVolu
2057  void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)  void MainForm::channelStripChanged(ChannelStrip* pChannelStrip)
2058  {  {
2059          // Add this strip to the changed list...          // Add this strip to the changed list...
2060          if (m_changedStrips.containsRef(pChannelStrip) == 0) {          if (!m_changedStrips.contains(pChannelStrip)) {
2061                  m_changedStrips.append(pChannelStrip);                  m_changedStrips.append(pChannelStrip);
2062                  pChannelStrip->resetErrorCount();                  pChannelStrip->resetErrorCount();
2063          }          }
2064    
2065      // Just mark the dirty form.          // Just mark the dirty form.
2066      m_iDirtyCount++;          m_iDirtyCount++;
2067      // and update the form status...          // and update the form status...
2068      stabilizeForm();          stabilizeForm();
2069  }  }
2070    
2071    
# Line 1870  void MainForm::updateSession (void) Line 2085  void MainForm::updateSession (void)
2085          if (iMaps < 0)          if (iMaps < 0)
2086                  appendMessagesClient("lscp_get_midi_instrument_maps");                  appendMessagesClient("lscp_get_midi_instrument_maps");
2087          else if (iMaps < 1) {          else if (iMaps < 1) {
2088                  ::lscp_add_midi_instrument_map(m_pClient, tr("Chromatic").latin1());                  ::lscp_add_midi_instrument_map(m_pClient,
2089                  ::lscp_add_midi_instrument_map(m_pClient, tr("Drum Kits").latin1());                          tr("Chromatic").toUtf8().constData());
2090                    ::lscp_add_midi_instrument_map(m_pClient,
2091                            tr("Drum Kits").toUtf8().constData());
2092          }          }
2093  #endif  #endif
2094    
2095            updateAllChannelStrips(false);
2096    
2097            // Do we auto-arrange?
2098            if (m_pOptions && m_pOptions->bAutoArrange)
2099                    channelsArrange();
2100    
2101            // Remember to refresh devices and instruments...
2102            if (m_pInstrumentListForm)
2103                    m_pInstrumentListForm->refreshInstruments();
2104            if (m_pDeviceForm)
2105                    m_pDeviceForm->refreshDevices();
2106    }
2107    
2108    void MainForm::updateAllChannelStrips(bool bRemoveDeadStrips) {
2109          // Retrieve the current channel list.          // Retrieve the current channel list.
2110          int *piChannelIDs = ::lscp_list_channels(m_pClient);          int *piChannelIDs = ::lscp_list_channels(m_pClient);
2111          if (piChannelIDs == NULL) {          if (piChannelIDs == NULL) {
2112                  if (::lscp_client_get_errno(m_pClient)) {                  if (::lscp_client_get_errno(m_pClient)) {
2113                          appendMessagesClient("lscp_list_channels");                          appendMessagesClient("lscp_list_channels");
2114                          appendMessagesError(tr("Could not get current list of channels.\n\nSorry."));                          appendMessagesError(
2115                                    tr("Could not get current list of channels.\n\nSorry."));
2116                  }                  }
2117          } else {          } else {
2118                  // Try to (re)create each channel.                  // Try to (re)create each channel.
# Line 1888  void MainForm::updateSession (void) Line 2120  void MainForm::updateSession (void)
2120                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {                  for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {
2121                          // Check if theres already a channel strip for this one...                          // Check if theres already a channel strip for this one...
2122                          if (!channelStrip(piChannelIDs[iChannel]))                          if (!channelStrip(piChannelIDs[iChannel]))
2123                                  createChannelStrip(new qsamplerChannel(piChannelIDs[iChannel]));                                  createChannelStrip(new Channel(piChannelIDs[iChannel]));
2124                    }
2125    
2126                    // Do we auto-arrange?
2127                    if (m_pOptions && m_pOptions->bAutoArrange)
2128                            channelsArrange();
2129    
2130                    stabilizeForm();
2131    
2132                    // remove dead channel strips
2133                    if (bRemoveDeadStrips) {
2134                            for (int i = 0; channelStripAt(i); ++i) {
2135                                    ChannelStrip* pChannelStrip = channelStripAt(i);
2136                                    bool bExists = false;
2137                                    for (int j = 0; piChannelIDs[j] >= 0; ++j) {
2138                                            if (!pChannelStrip->channel()) break;
2139                                            if (piChannelIDs[j] == pChannelStrip->channel()->channelID()) {
2140                                                    // strip exists, don't touch it
2141                                                    bExists = true;
2142                                                    break;
2143                                            }
2144                                    }
2145                                    if (!bExists) destroyChannelStrip(pChannelStrip);
2146                            }
2147                  }                  }
2148                  m_pWorkspace->setUpdatesEnabled(true);                  m_pWorkspace->setUpdatesEnabled(true);
2149          }          }
   
     // 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();  
2150  }  }
2151    
   
2152  // Update the recent files list and menu.  // Update the recent files list and menu.
2153  void MainForm::updateRecentFiles ( const QString& sFilename )  void MainForm::updateRecentFiles ( const QString& sFilename )
2154  {  {
2155      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2156          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);  
2157    
2158      // May update the menu.          // Remove from list if already there (avoid duplicates)
2159      updateRecentFilesMenu();          int iIndex = m_pOptions->recentFiles.indexOf(sFilename);
2160            if (iIndex >= 0)
2161                    m_pOptions->recentFiles.removeAt(iIndex);
2162            // Put it to front...
2163            m_pOptions->recentFiles.push_front(sFilename);
2164  }  }
2165    
2166    
2167  // Update the recent files list and menu.  // Update the recent files list and menu.
2168  void MainForm::updateRecentFilesMenu (void)  void MainForm::updateRecentFilesMenu (void)
2169  {  {
2170      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2171          return;                  return;
2172    
2173      // Time to keep the list under limits.          // Time to keep the list under limits.
2174      int iRecentFiles = m_pOptions->recentFiles.count();          int iRecentFiles = m_pOptions->recentFiles.count();
2175      while (iRecentFiles > m_pOptions->iMaxRecentFiles) {          while (iRecentFiles > m_pOptions->iMaxRecentFiles) {
2176          m_pOptions->recentFiles.pop_back();                  m_pOptions->recentFiles.pop_back();
2177          iRecentFiles--;                  iRecentFiles--;
2178      }          }
2179    
2180      // rebuild the recent files menu...          // Rebuild the recent files menu...
2181      m_pRecentFilesMenu->clear();          m_ui.fileOpenRecentMenu->clear();
2182      for (int i = 0; i < iRecentFiles; i++) {          for (int i = 0; i < iRecentFiles; i++) {
2183          const QString& sFilename = m_pOptions->recentFiles[i];                  const QString& sFilename = m_pOptions->recentFiles[i];
2184          if (QFileInfo(sFilename).exists()) {                  if (QFileInfo(sFilename).exists()) {
2185              m_pRecentFilesMenu->insertItem(QString("&%1 %2")                          QAction *pAction = m_ui.fileOpenRecentMenu->addAction(
2186                  .arg(i + 1).arg(sessionName(sFilename)),                                  QString("&%1 %2").arg(i + 1).arg(sessionName(sFilename)),
2187                  this, SLOT(fileOpenRecent(int)), 0, i);                                  this, SLOT(fileOpenRecent()));
2188          }                          pAction->setData(i);
2189      }                  }
2190            }
2191  }  }
2192    
2193    
2194  // Force update of the channels instrument names mode.  // Force update of the channels instrument names mode.
2195  void MainForm::updateInstrumentNames (void)  void MainForm::updateInstrumentNames (void)
2196  {  {
2197      // Full channel list update...          // Full channel list update...
2198      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2199      if (wlist.isEmpty())          if (wlist.isEmpty())
2200          return;                  return;
2201    
2202      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2203      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2204          ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);                  ChannelStrip *pChannelStrip = (ChannelStrip *) wlist.at(iChannel);
2205          if (pChannelStrip)                  if (pChannelStrip)
2206              pChannelStrip->updateInstrumentName(true);                          pChannelStrip->updateInstrumentName(true);
2207      }          }
2208      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2209  }  }
2210    
2211    
2212  // Force update of the channels display font.  // Force update of the channels display font.
2213  void MainForm::updateDisplayFont (void)  void MainForm::updateDisplayFont (void)
2214  {  {
2215      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2216          return;                  return;
2217    
2218            // Check if display font is legal.
2219            if (m_pOptions->sDisplayFont.isEmpty())
2220                    return;
2221            // Realize it.
2222            QFont font;
2223            if (!font.fromString(m_pOptions->sDisplayFont))
2224                    return;
2225    
2226            // Full channel list update...
2227            QWidgetList wlist = m_pWorkspace->windowList();
2228            if (wlist.isEmpty())
2229                    return;
2230    
2231      // Check if display font is legal.          m_pWorkspace->setUpdatesEnabled(false);
2232      if (m_pOptions->sDisplayFont.isEmpty())          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2233          return;                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2234      // Realize it.                  if (pChannelStrip)
2235      QFont font;                          pChannelStrip->setDisplayFont(font);
2236      if (!font.fromString(m_pOptions->sDisplayFont))          }
2237          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);  
2238  }  }
2239    
2240    
2241  // Update channel strips background effect.  // Update channel strips background effect.
2242  void MainForm::updateDisplayEffect (void)  void MainForm::updateDisplayEffect (void)
2243  {  {
2244     QPixmap pm;          // Full channel list update...
2245      if (m_pOptions->bDisplayEffect)          QWidgetList wlist = m_pWorkspace->windowList();
2246          pm = QPixmap(":/qsampler/pixmaps/displaybg1.png");          if (wlist.isEmpty())
2247                    return;
2248      // Full channel list update...  
2249      QWidgetList wlist = m_pWorkspace->windowList();          m_pWorkspace->setUpdatesEnabled(false);
2250      if (wlist.isEmpty())          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2251          return;                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2252                    if (pChannelStrip)
2253      m_pWorkspace->setUpdatesEnabled(false);                          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2254      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          }
2255          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);          m_pWorkspace->setUpdatesEnabled(true);
         if (pChannelStrip)  
             pChannelStrip->setDisplayBackground(pm);  
     }  
     m_pWorkspace->setUpdatesEnabled(true);  
2256  }  }
2257    
2258    
2259  // Force update of the channels maximum volume setting.  // Force update of the channels maximum volume setting.
2260  void MainForm::updateMaxVolume (void)  void MainForm::updateMaxVolume (void)
2261  {  {
2262      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2263          return;                  return;
2264    
2265  #ifdef CONFIG_VOLUME  #ifdef CONFIG_VOLUME
2266          m_iVolumeChanging++;          m_iVolumeChanging++;
2267          m_pVolumeSlider->setMaxValue(m_pOptions->iMaxVolume);          m_pVolumeSlider->setMaximum(m_pOptions->iMaxVolume);
2268          m_pVolumeSpinBox->setMaxValue(m_pOptions->iMaxVolume);          m_pVolumeSpinBox->setMaximum(m_pOptions->iMaxVolume);
2269          m_iVolumeChanging--;          m_iVolumeChanging--;
2270  #endif  #endif
2271    
2272      // Full channel list update...          // Full channel list update...
2273      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2274      if (wlist.isEmpty())          if (wlist.isEmpty())
2275          return;                  return;
2276    
2277      m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
2278      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2279          ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);
2280          if (pChannelStrip)                  if (pChannelStrip)
2281              pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);                          pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2282      }          }
2283      m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
2284  }  }
2285    
2286    
# Line 2052  void MainForm::updateMaxVolume (void) Line 2290  void MainForm::updateMaxVolume (void)
2290  // Messages output methods.  // Messages output methods.
2291  void MainForm::appendMessages( const QString& s )  void MainForm::appendMessages( const QString& s )
2292  {  {
2293      if (m_pMessages)          if (m_pMessages)
2294          m_pMessages->appendMessages(s);                  m_pMessages->appendMessages(s);
2295    
2296      statusBar()->message(s, 3000);          statusBar()->showMessage(s, 3000);
2297  }  }
2298    
2299  void MainForm::appendMessagesColor( const QString& s, const QString& c )  void MainForm::appendMessagesColor( const QString& s, const QString& c )
2300  {  {
2301      if (m_pMessages)          if (m_pMessages)
2302          m_pMessages->appendMessagesColor(s, c);                  m_pMessages->appendMessagesColor(s, c);
2303    
2304      statusBar()->message(s, 3000);          statusBar()->showMessage(s, 3000);
2305  }  }
2306    
2307  void MainForm::appendMessagesText( const QString& s )  void MainForm::appendMessagesText( const QString& s )
2308  {  {
2309      if (m_pMessages)          if (m_pMessages)
2310          m_pMessages->appendMessagesText(s);                  m_pMessages->appendMessagesText(s);
2311  }  }
2312    
2313  void MainForm::appendMessagesError( const QString& s )  void MainForm::appendMessagesError( const QString& s )
2314  {  {
2315      if (m_pMessages)          if (m_pMessages)
2316          m_pMessages->show();                  m_pMessages->show();
2317    
2318      appendMessagesColor(s.simplified(), "#ff0000");          appendMessagesColor(s.simplified(), "#ff0000");
2319    
2320          // Make it look responsive...:)          // Make it look responsive...:)
2321          QApplication::processEvents(QEventLoop::ExcludeUserInput);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2322    
2323      QMessageBox::critical(this,          QMessageBox::critical(this,
2324                  QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));                  QSAMPLER_TITLE ": " + tr("Error"), s, QMessageBox::Cancel);
2325  }  }
2326    
2327    
2328  // This is a special message format, just for client results.  // This is a special message format, just for client results.
2329  void MainForm::appendMessagesClient( const QString& s )  void MainForm::appendMessagesClient( const QString& s )
2330  {  {
2331      if (m_pClient == NULL)          if (m_pClient == NULL)
2332          return;                  return;
2333    
2334      appendMessagesColor(s + QString(": %1 (errno=%2)")          appendMessagesColor(s + QString(": %1 (errno=%2)")
2335          .arg(::lscp_client_get_result(m_pClient))                  .arg(::lscp_client_get_result(m_pClient))
2336          .arg(::lscp_client_get_errno(m_pClient)), "#996666");                  .arg(::lscp_client_get_errno(m_pClient)), "#996666");
2337    
2338          // Make it look responsive...:)          // Make it look responsive...:)
2339          QApplication::processEvents(QEventLoop::ExcludeUserInput);          QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2340  }  }
2341    
2342    
2343  // Force update of the messages font.  // Force update of the messages font.
2344  void MainForm::updateMessagesFont (void)  void MainForm::updateMessagesFont (void)
2345  {  {
2346      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2347          return;                  return;
2348    
2349      if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {          if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {
2350          QFont font;                  QFont font;
2351          if (font.fromString(m_pOptions->sMessagesFont))                  if (font.fromString(m_pOptions->sMessagesFont))
2352              m_pMessages->setMessagesFont(font);                          m_pMessages->setMessagesFont(font);
2353      }          }
2354  }  }
2355    
2356    
2357  // Update messages window line limit.  // Update messages window line limit.
2358  void MainForm::updateMessagesLimit (void)  void MainForm::updateMessagesLimit (void)
2359  {  {
2360      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2361          return;                  return;
2362    
2363      if (m_pMessages) {          if (m_pMessages) {
2364          if (m_pOptions->bMessagesLimit)                  if (m_pOptions->bMessagesLimit)
2365              m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);                          m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);
2366          else                  else
2367              m_pMessages->setMessagesLimit(-1);                          m_pMessages->setMessagesLimit(-1);
2368      }          }
2369  }  }
2370    
2371    
2372  // Enablement of the messages capture feature.  // Enablement of the messages capture feature.
2373  void MainForm::updateMessagesCapture (void)  void MainForm::updateMessagesCapture (void)
2374  {  {
2375      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2376          return;                  return;
2377    
2378      if (m_pMessages)          if (m_pMessages)
2379          m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);                  m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);
2380  }  }
2381    
2382    
# Line 2146  void MainForm::updateMessagesCapture (vo Line 2384  void MainForm::updateMessagesCapture (vo
2384  // qsamplerMainForm -- MDI channel strip management.  // qsamplerMainForm -- MDI channel strip management.
2385    
2386  // The channel strip creation executive.  // The channel strip creation executive.
2387  ChannelStrip* MainForm::createChannelStrip(qsamplerChannel* pChannel)  ChannelStrip* MainForm::createChannelStrip ( Channel *pChannel )
2388  {  {
2389      if (m_pClient == NULL || pChannel == NULL)          if (m_pClient == NULL || pChannel == NULL)
2390          return NULL;                  return NULL;
2391    
2392      // Prepare for auto-arrange?          // Add a new channel itema...
2393      ChannelStrip* pChannelStrip = NULL;          ChannelStrip *pChannelStrip = new ChannelStrip();
2394      int y = 0;          if (pChannelStrip == NULL)
2395      if (m_pOptions && m_pOptions->bAutoArrange) {                  return NULL;
2396          QWidgetList wlist = m_pWorkspace->windowList();  
2397          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          // Set some initial channel strip options...
2398              pChannelStrip = (ChannelStrip *) wlist.at(iChannel);          if (m_pOptions) {
2399                          if (pChannelStrip) {                  // Background display effect...
2400                          //  y += pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();                  pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2401                                  y += pChannelStrip->parentWidget()->frameGeometry().height();                  // We'll need a display font.
2402                          }                  QFont font;
2403          }                  if (font.fromString(m_pOptions->sDisplayFont))
2404      }                          pChannelStrip->setDisplayFont(font);
2405                    // Maximum allowed volume setting.
2406                    pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2407            }
2408    
2409      // Add a new channel itema...          // Add it to workspace...
2410      pChannelStrip = new ChannelStrip();          m_pWorkspace->addWindow(pChannelStrip, Qt::FramelessWindowHint);
     if (pChannelStrip == NULL)  
         return NULL;  
2411    
2412      m_pWorkspace->addWindow(pChannelStrip, Qt::Tool);          // Actual channel strip setup...
2413            pChannelStrip->setup(pChannel);
2414    
     // Actual channel strip setup...  
     pChannelStrip->setup(pChannel);  
2415          QObject::connect(pChannelStrip,          QObject::connect(pChannelStrip,
2416                  SIGNAL(channelChanged(ChannelStrip*)),                  SIGNAL(channelChanged(ChannelStrip*)),
2417                  SLOT(channelStripChanged(ChannelStrip*)));                  SLOT(channelStripChanged(ChannelStrip*)));
2418      // Set some initial aesthetic options...  
2419      if (m_pOptions) {          // Now we show up us to the world.
2420          // 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);  
     }  
2421    
2422          // This is pretty new, so we'll watch for it closely.          // This is pretty new, so we'll watch for it closely.
2423          channelStripChanged(pChannelStrip);          channelStripChanged(pChannelStrip);
2424    
2425      // Return our successful reference...          // Return our successful reference...
2426      return pChannelStrip;          return pChannelStrip;
2427  }  }
2428    
2429    void MainForm::destroyChannelStrip(ChannelStrip* pChannelStrip) {
2430            // Just delete the channel strip.
2431            delete pChannelStrip;
2432    
2433            // Do we auto-arrange?
2434            if (m_pOptions && m_pOptions->bAutoArrange)
2435                    channelsArrange();
2436    
2437            stabilizeForm();
2438    }
2439    
2440  // Retrieve the active channel strip.  // Retrieve the active channel strip.
2441  ChannelStrip* MainForm::activeChannelStrip (void)  ChannelStrip* MainForm::activeChannelStrip (void)
2442  {  {
2443      return (ChannelStrip*) m_pWorkspace->activeWindow();          return static_cast<ChannelStrip *> (m_pWorkspace->activeWindow());
2444  }  }
2445    
2446    
2447  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
2448  ChannelStrip* MainForm::channelStripAt ( int iChannel )  ChannelStrip* MainForm::channelStripAt ( int iChannel )
2449  {  {
2450      QWidgetList wlist = m_pWorkspace->windowList();          if (!m_pWorkspace) return NULL;
     if (wlist.isEmpty())  
         return NULL;  
2451    
2452      return (ChannelStrip*) wlist.at(iChannel);          QWidgetList wlist = m_pWorkspace->windowList();
2453            if (wlist.isEmpty())
2454                    return NULL;
2455    
2456            if (iChannel < 0 || iChannel >= wlist.size())
2457                    return NULL;
2458    
2459            return dynamic_cast<ChannelStrip *> (wlist.at(iChannel));
2460  }  }
2461    
2462    
# Line 2232  ChannelStrip* MainForm::channelStrip ( i Line 2468  ChannelStrip* MainForm::channelStrip ( i
2468                  return NULL;                  return NULL;
2469    
2470          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2471                  ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                  ChannelStrip* pChannelStrip
2472                            = static_cast<ChannelStrip*> (wlist.at(iChannel));
2473                  if (pChannelStrip) {                  if (pChannelStrip) {
2474                          qsamplerChannel *pChannel = pChannelStrip->channel();                          Channel *pChannel = pChannelStrip->channel();
2475                          if (pChannel && pChannel->channelID() == iChannelID)                          if (pChannel && pChannel->channelID() == iChannelID)
2476                                  return pChannelStrip;                                  return pChannelStrip;
2477                  }                  }
# Line 2248  ChannelStrip* MainForm::channelStrip ( i Line 2485  ChannelStrip* MainForm::channelStrip ( i
2485  // Construct the windows menu.  // Construct the windows menu.
2486  void MainForm::channelsMenuAboutToShow (void)  void MainForm::channelsMenuAboutToShow (void)
2487  {  {
2488      ui.channelsMenu->clear();          m_ui.channelsMenu->clear();
2489      ui.channelsArrangeAction->addTo(ui.channelsMenu);          m_ui.channelsMenu->addAction(m_ui.channelsArrangeAction);
2490      ui.channelsAutoArrangeAction->addTo(ui.channelsMenu);          m_ui.channelsMenu->addAction(m_ui.channelsAutoArrangeAction);
2491    
2492      QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2493      if (!wlist.isEmpty()) {          if (!wlist.isEmpty()) {
2494          ui.channelsMenu->insertSeparator();                  m_ui.channelsMenu->addSeparator();
2495          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                  for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2496              ChannelStrip* pChannelStrip = (ChannelStrip*) wlist.at(iChannel);                          ChannelStrip* pChannelStrip
2497              if (pChannelStrip) {                                  = static_cast<ChannelStrip*> (wlist.at(iChannel));
2498                  int iItemID = ui.channelsMenu->insertItem(pChannelStrip->caption(), this, SLOT(channelsMenuActivated(int)));                          if (pChannelStrip) {
2499                  ui.channelsMenu->setItemParameter(iItemID, iChannel);                                  QAction *pAction = m_ui.channelsMenu->addAction(
2500                  ui.channelsMenu->setItemChecked(iItemID, activeChannelStrip() == pChannelStrip);                                          pChannelStrip->windowTitle(),
2501              }                                          this, SLOT(channelsMenuActivated()));
2502          }                                  pAction->setCheckable(true);
2503      }                                  pAction->setChecked(activeChannelStrip() == pChannelStrip);
2504                                    pAction->setData(iChannel);
2505                            }
2506                    }
2507            }
2508  }  }
2509    
2510    
2511  // Windows menu activation slot  // Windows menu activation slot
2512  void MainForm::channelsMenuActivated ( int iChannel )  void MainForm::channelsMenuActivated (void)
2513  {  {
2514      ChannelStrip* pChannelStrip = channelStripAt(iChannel);          // Retrive channel index from action data...
2515      if (pChannelStrip)          QAction *pAction = qobject_cast<QAction *> (sender());
2516          pChannelStrip->showNormal();          if (pAction == NULL)
2517      pChannelStrip->setFocus();                  return;
2518    
2519            ChannelStrip* pChannelStrip = channelStripAt(pAction->data().toInt());
2520            if (pChannelStrip) {
2521                    pChannelStrip->showNormal();
2522                    pChannelStrip->setFocus();
2523            }
2524  }  }
2525    
2526    
# Line 2283  void MainForm::channelsMenuActivated ( i Line 2530  void MainForm::channelsMenuActivated ( i
2530  // Set the pseudo-timer delay schedule.  // Set the pseudo-timer delay schedule.
2531  void MainForm::startSchedule ( int iStartDelay )  void MainForm::startSchedule ( int iStartDelay )
2532  {  {
2533      m_iStartDelay  = 1 + (iStartDelay * 1000);          m_iStartDelay  = 1 + (iStartDelay * 1000);
2534      m_iTimerDelay  = 0;          m_iTimerDelay  = 0;
2535  }  }
2536    
2537  // Suspend the pseudo-timer delay schedule.  // Suspend the pseudo-timer delay schedule.
2538  void MainForm::stopSchedule (void)  void MainForm::stopSchedule (void)
2539  {  {
2540      m_iStartDelay  = 0;          m_iStartDelay  = 0;
2541      m_iTimerDelay  = 0;          m_iTimerDelay  = 0;
2542  }  }
2543    
2544  // Timer slot funtion.  // Timer slot funtion.
2545  void MainForm::timerSlot (void)  void MainForm::timerSlot (void)
2546  {  {
2547      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2548          return;                  return;
2549    
2550      // Is it the first shot on server start after a few delay?          // Is it the first shot on server start after a few delay?
2551      if (m_iTimerDelay < m_iStartDelay) {          if (m_iTimerDelay < m_iStartDelay) {
2552          m_iTimerDelay += QSAMPLER_TIMER_MSECS;                  m_iTimerDelay += QSAMPLER_TIMER_MSECS;
2553          if (m_iTimerDelay >= m_iStartDelay) {                  if (m_iTimerDelay >= m_iStartDelay) {
2554              // If we cannot start it now, maybe a lil'mo'later ;)                          // If we cannot start it now, maybe a lil'mo'later ;)
2555              if (!startClient()) {                          if (!startClient()) {
2556                  m_iStartDelay += m_iTimerDelay;                                  m_iStartDelay += m_iTimerDelay;
2557                  m_iTimerDelay  = 0;                                  m_iTimerDelay  = 0;
2558              }                          }
2559          }                  }
2560      }          }
2561    
2562          if (m_pClient) {          if (m_pClient) {
2563                  // Update the channel information for each pending strip...                  // Update the channel information for each pending strip...
2564                  if (m_changedStrips.count() > 0) {                  QListIterator<ChannelStrip *> iter(m_changedStrips);
2565                          for (ChannelStrip* pChannelStrip = m_changedStrips.first();                  while (iter.hasNext()) {
2566                                          pChannelStrip; pChannelStrip = m_changedStrips.next()) {                          ChannelStrip *pChannelStrip = iter.next();
2567                                  // If successfull, remove from pending list...                          // If successfull, remove from pending list...
2568                                  if (pChannelStrip->updateChannelInfo())                          if (pChannelStrip->updateChannelInfo()) {
2569                                          m_changedStrips.remove(pChannelStrip);                                  int iChannelStrip = m_changedStrips.indexOf(pChannelStrip);
2570                                    if (iChannelStrip >= 0)
2571                                            m_changedStrips.removeAt(iChannelStrip);
2572                          }                          }
2573                  }                  }
2574                  // Refresh each channel usage, on each period...                  // Refresh each channel usage, on each period...
# Line 2340  void MainForm::timerSlot (void) Line 2589  void MainForm::timerSlot (void)
2589                  }                  }
2590          }          }
2591    
2592      // Register the next timer slot.          // Register the next timer slot.
2593      QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));          QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
2594  }  }
2595    
2596    
# Line 2351  void MainForm::timerSlot (void) Line 2600  void MainForm::timerSlot (void)
2600  // Start linuxsampler server...  // Start linuxsampler server...
2601  void MainForm::startServer (void)  void MainForm::startServer (void)
2602  {  {
2603      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2604          return;                  return;
2605    
2606            // Aren't already a client, are we?
2607            if (!m_pOptions->bServerStart || m_pClient)
2608                    return;
2609    
2610      // Aren't already a client, are we?          // Is the server process instance still here?
2611      if (!m_pOptions->bServerStart || m_pClient)          if (m_pServer) {
2612          return;                  if (QMessageBox::warning(this,
   
     // Is the server process instance still here?  
     if (m_pServer) {  
         switch (QMessageBox::warning(this,  
2613                          QSAMPLER_TITLE ": " + tr("Warning"),                          QSAMPLER_TITLE ": " + tr("Warning"),
2614              tr("Could not start the LinuxSampler server.\n\n"                          tr("Could not start the LinuxSampler server.\n\n"
2615                 "Maybe it ss already started."),                          "Maybe it is already started."),
2616              tr("Stop"), tr("Kill"), tr("Cancel"))) {                          QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
2617            case 0:                          m_pServer->terminate();
2618              m_pServer->terminate();                          m_pServer->kill();
2619              break;                  }
2620            case 1:                  return;
2621              m_pServer->kill();          }
2622              break;  
2623          }          // Reset our timer counters...
2624          return;          stopSchedule();
2625      }  
2626            // Verify we have something to start with...
2627      // Reset our timer counters...          if (m_pOptions->sServerCmdLine.isEmpty())
2628      stopSchedule();                  return;
2629    
2630      // OK. Let's build the startup process...          // OK. Let's build the startup process...
2631      m_pServer = new QProcess(this);          m_pServer = new QProcess();
2632            bForceServerStop = true;
2633      // Setup stdout/stderr capture...  
2634          //      if (m_pOptions->bStdoutCapture) {          // Setup stdout/stderr capture...
2635                  //m_pServer->setProcessChannelMode(  //      if (m_pOptions->bStdoutCapture) {
2636                  //      QProcess::StandardOutput);  #if QT_VERSION >= 0x040200
2637                    m_pServer->setProcessChannelMode(QProcess::ForwardedChannels);
2638    #endif
2639                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2640                          SIGNAL(readyReadStandardOutput()),                          SIGNAL(readyReadStandardOutput()),
2641                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
2642                  QObject::connect(m_pServer,                  QObject::connect(m_pServer,
2643                          SIGNAL(readyReadStandardError()),                          SIGNAL(readyReadStandardError()),
2644                          SLOT(readServerStdout()));                          SLOT(readServerStdout()));
2645          //      }  //      }
2646    
2647          // The unforgiveable signal communication...          // The unforgiveable signal communication...
2648          QObject::connect(m_pServer,          QObject::connect(m_pServer,
2649                  SIGNAL(finished(int,QProcess::ExitStatus)),                  SIGNAL(finished(int, QProcess::ExitStatus)),
2650                  SLOT(processServerExit()));                  SLOT(processServerExit()));
2651    
2652      // Build process arguments...          // Build process arguments...
2653      QStringList serverCmdLine = QStringList::split(' ', m_pOptions->sServerCmdLine);          QStringList args = m_pOptions->sServerCmdLine.split(' ');
2654            QString sCommand = args[0];
2655      appendMessages(tr("Server is starting..."));          args.removeAt(0);
2656      appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");  
2657            appendMessages(tr("Server is starting..."));
2658            appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");
2659    
2660      const QString prog = (serverCmdLine.size() > 0) ? serverCmdLine[0] : QString();          // Go linuxsampler, go...
2661      const QStringList args = serverCmdLine.mid(1);          m_pServer->start(sCommand, args);
2662            if (!m_pServer->waitForStarted()) {
2663      // Go jack, go...                  appendMessagesError(tr("Could not start server.\n\nSorry."));
2664      m_pServer->start(prog, args);                  processServerExit();
2665      if (!m_pServer->waitForStarted()) {                  return;
2666          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()));  
2667    
2668      // Reset (yet again) the timer counters,          // Show startup results...
2669      // but this time is deferred as the user opted.          appendMessages(
2670      startSchedule(m_pOptions->iStartDelay);                  tr("Server was started with PID=%1.").arg((long) m_pServer->pid()));
2671      stabilizeForm();  
2672            // Reset (yet again) the timer counters,
2673            // but this time is deferred as the user opted.
2674            startSchedule(m_pOptions->iStartDelay);
2675            stabilizeForm();
2676  }  }
2677    
2678    
2679  // Stop linuxsampler server...  // Stop linuxsampler server...
2680  void MainForm::stopServer (void)  void MainForm::stopServer (bool bInteractive)
2681  {  {
2682      // Stop client code.          // Stop client code.
2683      stopClient();          stopClient();
2684    
2685            if (m_pServer && bInteractive) {
2686                    if (QMessageBox::question(this,
2687                            QSAMPLER_TITLE ": " + tr("The backend's fate ..."),
2688                            tr("You have the option to keep the sampler backend (LinuxSampler)\n"
2689                            "running in the background. The sampler would continue to work\n"
2690                            "according to your current sampler session and you could alter the\n"
2691                            "sampler session at any time by relaunching QSampler.\n\n"
2692                            "Do you want LinuxSampler to stop?"),
2693                            QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
2694                    {
2695                            bForceServerStop = false;
2696                    }
2697            }
2698    
2699      // And try to stop server.          // And try to stop server.
2700      if (m_pServer) {          if (m_pServer && bForceServerStop) {
2701          appendMessages(tr("Server is stopping..."));                  appendMessages(tr("Server is stopping..."));
2702          if (m_pServer->state() == QProcess::Running)                  if (m_pServer->state() == QProcess::Running) {
2703              m_pServer->terminate();  #if defined(WIN32)
2704       }                          // Try harder...
2705                            m_pServer->kill();
2706      // Give it some time to terminate gracefully and stabilize...  #else
2707      QTime t;                          // Try softly...
2708      t.start();                          m_pServer->terminate();
2709      while (t.elapsed() < QSAMPLER_TIMER_MSECS)  #endif
2710          QApplication::processEvents(QEventLoop::ExcludeUserInput);                  }
2711            }       // Do final processing anyway.
2712            else processServerExit();
2713    
2714       // Do final processing anyway.          // Give it some time to terminate gracefully and stabilize...
2715       processServerExit();          QTime t;
2716            t.start();
2717            while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2718                    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2719  }  }
2720    
2721    
2722  // Stdout handler...  // Stdout handler...
2723  void MainForm::readServerStdout (void)  void MainForm::readServerStdout (void)
2724  {  {
2725      if (m_pMessages)          if (m_pMessages)
2726          m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());                  m_pMessages->appendStdoutBuffer(m_pServer->readAllStandardOutput());
2727  }  }
2728    
2729    
2730  // Linuxsampler server cleanup.  // Linuxsampler server cleanup.
2731  void MainForm::processServerExit (void)  void MainForm::processServerExit (void)
2732  {  {
2733      // Force client code cleanup.          // Force client code cleanup.
2734      stopClient();          stopClient();
2735    
2736      // Flush anything that maybe pending...          // Flush anything that maybe pending...
2737      if (m_pMessages)          if (m_pMessages)
2738          m_pMessages->flushStdoutBuffer();                  m_pMessages->flushStdoutBuffer();
2739    
2740      if (m_pServer) {          if (m_pServer && bForceServerStop) {
2741          // Force final server shutdown...                  if (m_pServer->state() != QProcess::NotRunning) {
2742          appendMessages(tr("Server was stopped with exit status %1.").arg(m_pServer->exitStatus()));                          appendMessages(tr("Server is being forced..."));
2743          m_pServer->terminate();                          // Force final server shutdown...
2744          if (!m_pServer->waitForFinished(2000))                          m_pServer->kill();
2745              m_pServer->kill();                          // Give it some time to terminate gracefully and stabilize...
2746          // Destroy it.                          QTime t;
2747          delete m_pServer;                          t.start();
2748          m_pServer = NULL;                          while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2749      }                                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2750                    }
2751                    // Force final server shutdown...
2752                    appendMessages(
2753                            tr("Server was stopped with exit status %1.")
2754                            .arg(m_pServer->exitStatus()));
2755                    delete m_pServer;
2756                    m_pServer = NULL;
2757            }
2758    
2759      // Again, make status visible stable.          // Again, make status visible stable.
2760      stabilizeForm();          stabilizeForm();
2761  }  }
2762    
2763    
# Line 2488  void MainForm::processServerExit (void) Line 2765  void MainForm::processServerExit (void)
2765  // qsamplerMainForm -- Client stuff.  // qsamplerMainForm -- Client stuff.
2766    
2767  // The LSCP client callback procedure.  // The LSCP client callback procedure.
2768  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*/,
2769            lscp_event_t event, const char *pchData, int cchData, void *pvData )
2770  {  {
2771      MainForm* pMainForm = (MainForm *) pvData;          MainForm* pMainForm = (MainForm *) pvData;
2772      if (pMainForm == NULL)          if (pMainForm == NULL)
2773          return LSCP_FAILED;                  return LSCP_FAILED;
2774    
2775      // ATTN: DO NOT EVER call any GUI code here,          // ATTN: DO NOT EVER call any GUI code here,
2776      // as this is run under some other thread context.          // as this is run under some other thread context.
2777      // A custom event must be posted here...          // A custom event must be posted here...
2778      QApplication::postEvent(pMainForm, new qsamplerCustomEvent(event, pchData, cchData));          QApplication::postEvent(pMainForm,
2779                    new LscpEvent(event, pchData, cchData));
2780    
2781      return LSCP_OK;          return LSCP_OK;
2782  }  }
2783    
2784    
2785  // Start our almighty client...  // Start our almighty client...
2786  bool MainForm::startClient (void)  bool MainForm::startClient (void)
2787  {  {
2788      // Have it a setup?          // Have it a setup?
2789      if (m_pOptions == NULL)          if (m_pOptions == NULL)
2790          return false;                  return false;
2791    
2792      // Aren't we already started, are we?          // Aren't we already started, are we?
2793      if (m_pClient)          if (m_pClient)
2794          return true;                  return true;
2795    
2796      // Log prepare here.          // Log prepare here.
2797      appendMessages(tr("Client connecting..."));          appendMessages(tr("Client connecting..."));
2798    
2799      // Create the client handle...          // Create the client handle...
2800      m_pClient = ::lscp_client_create(m_pOptions->sServerHost.latin1(), m_pOptions->iServerPort, qsampler_client_callback, this);          m_pClient = ::lscp_client_create(
2801      if (m_pClient == NULL) {                  m_pOptions->sServerHost.toUtf8().constData(),
2802          // Is this the first try?                  m_pOptions->iServerPort, qsampler_client_callback, this);
2803          // maybe we need to start a local server...          if (m_pClient == NULL) {
2804          if ((m_pServer && m_pServer->state() == QProcess::Running) || !m_pOptions->bServerStart)                  // Is this the first try?
2805              appendMessagesError(tr("Could not connect to server as client.\n\nSorry."));                  // maybe we need to start a local server...
2806          else                  if ((m_pServer && m_pServer->state() == QProcess::Running)
2807              startServer();                          || !m_pOptions->bServerStart) {
2808          // This is always a failure.                          appendMessagesError(
2809          stabilizeForm();                                  tr("Could not connect to server as client.\n\nSorry."));
2810          return false;                  } else {
2811      }                          startServer();
2812      // Just set receive timeout value, blindly.                  }
2813      ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);                  // This is always a failure.
2814      appendMessages(tr("Client receive timeout is set to %1 msec.").arg(::lscp_client_get_timeout(m_pClient)));                  stabilizeForm();
2815                    return false;
2816            }
2817            // Just set receive timeout value, blindly.
2818            ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);
2819            appendMessages(
2820                    tr("Client receive timeout is set to %1 msec.")
2821                    .arg(::lscp_client_get_timeout(m_pClient)));
2822    
2823          // Subscribe to channel info change notifications...          // Subscribe to channel info change notifications...
2824            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT) != LSCP_OK)
2825                    appendMessagesClient("lscp_client_subscribe(CHANNEL_COUNT)");
2826          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)          if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)
2827                  appendMessagesClient("lscp_client_subscribe");                  appendMessagesClient("lscp_client_subscribe(CHANNEL_INFO)");
2828    
2829            DeviceStatusForm::onDevicesChanged(); // initialize
2830            updateViewMidiDeviceStatusMenu();
2831            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT) != LSCP_OK)
2832                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_COUNT)");
2833            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO) != LSCP_OK)
2834                    appendMessagesClient("lscp_client_subscribe(MIDI_INPUT_DEVICE_INFO)");
2835            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT) != LSCP_OK)
2836                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_COUNT)");
2837            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO) != LSCP_OK)
2838                    appendMessagesClient("lscp_client_subscribe(AUDIO_OUTPUT_DEVICE_INFO)");
2839    
2840    #if CONFIG_EVENT_CHANNEL_MIDI
2841            // Subscribe to channel MIDI data notifications...
2842            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI) != LSCP_OK)
2843                    appendMessagesClient("lscp_client_subscribe(CHANNEL_MIDI)");
2844    #endif
2845    
2846    #if CONFIG_EVENT_DEVICE_MIDI
2847            // Subscribe to channel MIDI data notifications...
2848            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI) != LSCP_OK)
2849                    appendMessagesClient("lscp_client_subscribe(DEVICE_MIDI)");
2850    #endif
2851    
2852      // We may stop scheduling around.          // We may stop scheduling around.
2853      stopSchedule();          stopSchedule();
2854    
2855      // We'll accept drops from now on...          // We'll accept drops from now on...
2856      setAcceptDrops(true);          setAcceptDrops(true);
2857    
2858      // Log success here.          // Log success here.
2859      appendMessages(tr("Client connected."));          appendMessages(tr("Client connected."));
2860    
2861          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
2862          // if visible, that we're ready...          // if visible, that we're ready...
2863          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
2864              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
2865          if (m_pDeviceForm)          if (m_pDeviceForm)
2866              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
2867    
2868            // Is any session pending to be loaded?
2869            if (!m_pOptions->sSessionFile.isEmpty()) {
2870                    // Just load the prabably startup session...
2871                    if (loadSessionFile(m_pOptions->sSessionFile)) {
2872                            m_pOptions->sSessionFile = QString::null;
2873                            return true;
2874                    }
2875            }
2876    
2877      // Is any session pending to be loaded?          // send the current / loaded fine tuning settings to the sampler
2878      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;  
         }  
     }  
2879    
2880      // Make a new session          // Make a new session
2881      return newSession();          return newSession();
2882  }  }
2883    
2884    
2885  // Stop client...  // Stop client...
2886  void MainForm::stopClient (void)  void MainForm::stopClient (void)
2887  {  {
2888      if (m_pClient == NULL)          if (m_pClient == NULL)
2889          return;                  return;
   
     // Log prepare here.  
     appendMessages(tr("Client disconnecting..."));  
2890    
2891      // Clear timer counters...          // Log prepare here.
2892      stopSchedule();          appendMessages(tr("Client disconnecting..."));
2893    
2894      // We'll reject drops from now on...          // Clear timer counters...
2895      setAcceptDrops(false);          stopSchedule();
2896    
2897      // Force any channel strips around, but          // We'll reject drops from now on...
2898      // but avoid removing the corresponding          setAcceptDrops(false);
     // channels from the back-end server.  
     m_iDirtyCount = 0;  
     closeSession(false);  
2899    
2900      // Close us as a client...          // Force any channel strips around, but
2901            // but avoid removing the corresponding
2902            // channels from the back-end server.
2903            m_iDirtyCount = 0;
2904            closeSession(false);
2905    
2906            // Close us as a client...
2907    #if CONFIG_EVENT_DEVICE_MIDI
2908            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_DEVICE_MIDI);
2909    #endif
2910    #if CONFIG_EVENT_CHANNEL_MIDI
2911            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_MIDI);
2912    #endif
2913            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_INFO);
2914            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_AUDIO_OUTPUT_DEVICE_COUNT);
2915            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_INFO);
2916            ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_MIDI_INPUT_DEVICE_COUNT);
2917          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
2918      ::lscp_client_destroy(m_pClient);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_COUNT);
2919      m_pClient = NULL;          ::lscp_client_destroy(m_pClient);
2920            m_pClient = NULL;
2921    
2922          // Hard-notify instrumnet and device configuration forms,          // Hard-notify instrumnet and device configuration forms,
2923          // if visible, that we're running out...          // if visible, that we're running out...
2924          if (m_pInstrumentListForm)          if (m_pInstrumentListForm)
2925              m_pInstrumentListForm->refreshInstruments();                  m_pInstrumentListForm->refreshInstruments();
2926          if (m_pDeviceForm)          if (m_pDeviceForm)
2927              m_pDeviceForm->refreshDevices();                  m_pDeviceForm->refreshDevices();
2928    
2929            // Log final here.
2930            appendMessages(tr("Client disconnected."));
2931    
2932            // Make visible status.
2933            stabilizeForm();
2934    }
2935    
2936    
2937      // Log final here.  // Channel strip activation/selection.
2938      appendMessages(tr("Client disconnected."));  void MainForm::activateStrip ( QWidget *pWidget )
2939    {
2940            ChannelStrip *pChannelStrip
2941                    = static_cast<ChannelStrip *> (pWidget);
2942            if (pChannelStrip)
2943                    pChannelStrip->setSelected(true);
2944    
2945      // Make visible status.          stabilizeForm();
     stabilizeForm();  
2946  }  }
2947    
2948    
2949  } // namespace QSampler  } // namespace QSampler
2950    
2951    

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

  ViewVC Help
Powered by ViewVC