/[svn]/qsampler/trunk/src/qsamplerMainForm.ui.h
ViewVC logotype

Diff of /qsampler/trunk/src/qsamplerMainForm.ui.h

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 119 by capela, Wed Jun 9 20:24:48 2004 UTC revision 1367 by capela, Mon Oct 1 22:03:35 2007 UTC
# Line 2  Line 2 
2  //  //
3  // ui.h extension file, included from the uic-generated form implementation.  // ui.h extension file, included from the uic-generated form implementation.
4  /****************************************************************************  /****************************************************************************
5     Copyright (C) 2004, rncbc aka Rui Nuno Capela. All rights reserved.     Copyright (C) 2004-2007, rncbc aka Rui Nuno Capela. All rights reserved.
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 14  Line 14 
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.     GNU General Public License for more details.
16    
17     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License along
18     along with this program; if not, write to the Free Software     with this program; if not, write to the Free Software Foundation, Inc.,
19     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20    
21  *****************************************************************************/  *****************************************************************************/
22    
# Line 26  Line 26 
26  #include <qprocess.h>  #include <qprocess.h>
27  #include <qmessagebox.h>  #include <qmessagebox.h>
28  #include <qdragobject.h>  #include <qdragobject.h>
29    #include <qregexp.h>
30  #include <qfiledialog.h>  #include <qfiledialog.h>
31  #include <qfileinfo.h>  #include <qfileinfo.h>
32  #include <qfile.h>  #include <qfile.h>
33  #include <qtextstream.h>  #include <qtextstream.h>
34  #include <qstatusbar.h>  #include <qstatusbar.h>
35    #include <qslider.h>
36    #include <qspinbox.h>
37  #include <qlabel.h>  #include <qlabel.h>
38  #include <qtimer.h>  #include <qtimer.h>
39    #include <qtooltip.h>
40    
41  #include "qsamplerAbout.h"  #include "qsamplerAbout.h"
42  #include "qsamplerOptions.h"  #include "qsamplerOptions.h"
43    #include "qsamplerChannel.h"
44  #include "qsamplerMessages.h"  #include "qsamplerMessages.h"
45    
46  #include "qsamplerChannelStrip.h"  #include "qsamplerChannelStrip.h"
47    #include "qsamplerInstrumentList.h"
48    
49    #include "qsamplerInstrumentListForm.h"
50    #include "qsamplerDeviceForm.h"
51  #include "qsamplerOptionsForm.h"  #include "qsamplerOptionsForm.h"
52    
53  #include "config.h"  #ifdef HAVE_SIGNAL_H
54    #include <signal.h>
55    #endif
56    
57    #ifdef CONFIG_LIBGIG
58    #include <gig.h>
59    #endif
60    
61    // Needed for lroundf()
62    #include <math.h>
63    
64    #ifndef CONFIG_ROUND
65    static inline long lroundf ( float x )
66    {
67            if (x >= 0.0f)
68                    return long(x + 0.5f);
69            else
70                    return long(x - 0.5f);
71    }
72    #endif
73    
74  // Timer constant stuff.  // Timer constant stuff.
75  #define QSAMPLER_TIMER_MSECS    200  #define QSAMPLER_TIMER_MSECS    200
# Line 54  Line 81 
81  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.
82    
83    
84    // All winsock apps needs this.
85  #if defined(WIN32)  #if defined(WIN32)
86  static WSADATA _wsaData;  static WSADATA _wsaData;
87  #endif  #endif
88    
89    
90    //-------------------------------------------------------------------------
91    // qsamplerCustomEvent -- specialty for callback comunication.
92    
93    #define QSAMPLER_CUSTOM_EVENT   1000
94    
95    class qsamplerCustomEvent : public QCustomEvent
96    {
97    public:
98    
99        // Constructor.
100        qsamplerCustomEvent(lscp_event_t event, const char *pchData, int cchData)
101            : QCustomEvent(QSAMPLER_CUSTOM_EVENT)
102        {
103            m_event = event;
104            m_data.setLatin1(pchData, cchData);
105        }
106    
107        // Accessors.
108        lscp_event_t event() { return m_event; }
109        QString&     data()  { return m_data;  }
110    
111    private:
112    
113        // The proper event type.
114        lscp_event_t m_event;
115        // The event data as a string.
116        QString      m_data;
117    };
118    
119    
120  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
121  // qsamplerMainForm -- Main window form implementation.  // qsamplerMainForm -- Main window form implementation.
122    
123    // Kind of singleton reference.
124    qsamplerMainForm *qsamplerMainForm::g_pMainForm = NULL;
125    
126    
127  // Kind of constructor.  // Kind of constructor.
128  void qsamplerMainForm::init (void)  void qsamplerMainForm::init (void)
129  {  {
130            // Pseudo-singleton reference setup.
131            g_pMainForm = this;
132    
133      // Initialize some pointer references.      // Initialize some pointer references.
134      m_pOptions = NULL;      m_pOptions = NULL;
135    
136      // All child forms are to be created later, not earlier than setup.      // All child forms are to be created later, not earlier than setup.
137      m_pMessages = NULL;      m_pMessages = NULL;
138        m_pInstrumentListForm = NULL;
139        m_pDeviceForm = NULL;
140    
141      // We'll start clean.      // We'll start clean.
142      m_iUntitled = 0;      m_iUntitled   = 0;
143      m_iDirtyCount = 0;      m_iDirtyCount = 0;
144    
145      m_pServer = NULL;      m_pServer = NULL;
# Line 82  void qsamplerMainForm::init (void) Line 150  void qsamplerMainForm::init (void)
150    
151      m_iTimerSlot = 0;      m_iTimerSlot = 0;
152    
153    #ifdef HAVE_SIGNAL_H
154            // Set to ignore any fatal "Broken pipe" signals.
155            ::signal(SIGPIPE, SIG_IGN);
156    #endif
157    
158    #ifdef CONFIG_VOLUME
159        // Make some extras into the toolbar...
160            const QString& sVolumeText = tr("Master volume");
161            m_iVolumeChanging = 0;
162            // Volume slider...
163            channelsToolbar->addSeparator();
164            m_pVolumeSlider = new QSlider(Qt::Horizontal, channelsToolbar);
165            m_pVolumeSlider->setTickmarks(QSlider::Below);
166            m_pVolumeSlider->setTickInterval(10);
167            m_pVolumeSlider->setPageStep(10);
168            m_pVolumeSlider->setRange(0, 100);
169            m_pVolumeSlider->setMaximumHeight(22);
170            m_pVolumeSlider->setMinimumWidth(160);
171            QToolTip::add(m_pVolumeSlider, sVolumeText);
172            QObject::connect(m_pVolumeSlider,
173                    SIGNAL(valueChanged(int)),
174                    SLOT(volumeChanged(int)));
175            channelsToolbar->setHorizontallyStretchable(true);
176            channelsToolbar->setStretchableWidget(m_pVolumeSlider);
177            // Volume spin-box
178            channelsToolbar->addSeparator();
179            m_pVolumeSpinBox = new QSpinBox(channelsToolbar);
180            m_pVolumeSpinBox->setSuffix(" %");
181            m_pVolumeSpinBox->setRange(0, 100);
182            QToolTip::add(m_pVolumeSpinBox, sVolumeText);
183            QObject::connect(m_pVolumeSpinBox,
184                    SIGNAL(valueChanged(int)),
185                    SLOT(volumeChanged(int)));
186    #endif
187    
188      // Make it an MDI workspace.      // Make it an MDI workspace.
189      m_pWorkspace = new QWorkspace(this);      m_pWorkspace = new QWorkspace(this);
190      m_pWorkspace->setScrollBarsEnabled(true);      m_pWorkspace->setScrollBarsEnabled(true);
191      // Set the activation connection.          // Set the activation connection.
192      QObject::connect(m_pWorkspace, SIGNAL(windowActivated(QWidget *)), this, SLOT(stabilizeForm()));          QObject::connect(m_pWorkspace,
193                    SIGNAL(windowActivated(QWidget *)),
194                    SLOT(stabilizeForm()));
195      // Make it shine :-)      // Make it shine :-)
196      setCentralWidget(m_pWorkspace);      setCentralWidget(m_pWorkspace);
197    
# Line 96  void qsamplerMainForm::init (void) Line 201  void qsamplerMainForm::init (void)
201      pLabel = new QLabel(tr("Connected"), this);      pLabel = new QLabel(tr("Connected"), this);
202      pLabel->setAlignment(Qt::AlignLeft);      pLabel->setAlignment(Qt::AlignLeft);
203      pLabel->setMinimumSize(pLabel->sizeHint());      pLabel->setMinimumSize(pLabel->sizeHint());
204      m_status[QSAMPLER_STATUS_CLIENT] = pLabel;      m_statusItem[QSAMPLER_STATUS_CLIENT] = pLabel;
205      statusBar()->addWidget(pLabel);      statusBar()->addWidget(pLabel);
206      // Server address.      // Server address.
207      pLabel = new QLabel(this);      pLabel = new QLabel(this);
208      pLabel->setAlignment(Qt::AlignLeft);      pLabel->setAlignment(Qt::AlignLeft);
209      m_status[QSAMPLER_STATUS_SERVER] = pLabel;      m_statusItem[QSAMPLER_STATUS_SERVER] = pLabel;
210      statusBar()->addWidget(pLabel, 1);      statusBar()->addWidget(pLabel, 1);
211      // Channel title.      // Channel title.
212      pLabel = new QLabel(this);      pLabel = new QLabel(this);
213      pLabel->setAlignment(Qt::AlignLeft);      pLabel->setAlignment(Qt::AlignLeft);
214      m_status[QSAMPLER_STATUS_CHANNEL] = pLabel;      m_statusItem[QSAMPLER_STATUS_CHANNEL] = pLabel;
215      statusBar()->addWidget(pLabel, 2);      statusBar()->addWidget(pLabel, 2);
216      // Session modification status.      // Session modification status.
217      pLabel = new QLabel(tr("MOD"), this);      pLabel = new QLabel(tr("MOD"), this);
218      pLabel->setAlignment(Qt::AlignHCenter);      pLabel->setAlignment(Qt::AlignHCenter);
219      pLabel->setMinimumSize(pLabel->sizeHint());      pLabel->setMinimumSize(pLabel->sizeHint());
220      m_status[QSAMPLER_STATUS_SESSION] = pLabel;      m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;
221      statusBar()->addWidget(pLabel);      statusBar()->addWidget(pLabel);
222    
223      // Create the recent files sub-menu.      // Create the recent files sub-menu.
# Line 131  void qsamplerMainForm::destroy (void) Line 236  void qsamplerMainForm::destroy (void)
236  {  {
237      // Do final processing anyway.      // Do final processing anyway.
238      processServerExit();      processServerExit();
239        
240      // Delete recentfiles menu.  #if defined(WIN32)
241      if (m_pRecentFilesMenu)      WSACleanup();
242          delete m_pRecentFilesMenu;  #endif
     // Delete status item labels one by one.  
     if (m_status[QSAMPLER_STATUS_CLIENT])  
         delete m_status[QSAMPLER_STATUS_CLIENT];  
     if (m_status[QSAMPLER_STATUS_SERVER])  
         delete m_status[QSAMPLER_STATUS_SERVER];  
     if (m_status[QSAMPLER_STATUS_CHANNEL])  
         delete m_status[QSAMPLER_STATUS_CHANNEL];  
     if (m_status[QSAMPLER_STATUS_SESSION])  
         delete m_status[QSAMPLER_STATUS_SESSION];  
243    
244      // Finally drop any widgets around...      // Finally drop any widgets around...
245        if (m_pDeviceForm)
246            delete m_pDeviceForm;
247        if (m_pInstrumentListForm)
248            delete m_pInstrumentListForm;
249      if (m_pMessages)      if (m_pMessages)
250          delete m_pMessages;          delete m_pMessages;
251      if (m_pWorkspace)      if (m_pWorkspace)
252          delete m_pWorkspace;          delete m_pWorkspace;
253    
254  #if defined(WIN32)      // Delete status item labels one by one.
255      WSACleanup();      if (m_statusItem[QSAMPLER_STATUS_CLIENT])
256            delete m_statusItem[QSAMPLER_STATUS_CLIENT];
257        if (m_statusItem[QSAMPLER_STATUS_SERVER])
258            delete m_statusItem[QSAMPLER_STATUS_SERVER];
259        if (m_statusItem[QSAMPLER_STATUS_CHANNEL])
260            delete m_statusItem[QSAMPLER_STATUS_CHANNEL];
261        if (m_statusItem[QSAMPLER_STATUS_SESSION])
262            delete m_statusItem[QSAMPLER_STATUS_SESSION];
263    
264    #ifdef CONFIG_VOLUME
265            delete m_pVolumeSpinBox;
266            delete m_pVolumeSlider;
267  #endif  #endif
268    
269        // Delete recentfiles menu.
270        if (m_pRecentFilesMenu)
271            delete m_pRecentFilesMenu;
272    
273            // Pseudo-singleton reference shut-down.
274            g_pMainForm = NULL;
275  }  }
276    
277    
# Line 163  void qsamplerMainForm::setup ( qsamplerO Line 281  void qsamplerMainForm::setup ( qsamplerO
281      // We got options?      // We got options?
282      m_pOptions = pOptions;      m_pOptions = pOptions;
283    
284        // What style do we create these forms?
285            Qt::WFlags wflags = Qt::WStyle_Customize
286                    | Qt::WStyle_NormalBorder
287                    | Qt::WStyle_Title
288                    | Qt::WStyle_SysMenu
289                    | Qt::WStyle_MinMax
290                    | Qt::WType_TopLevel;
291        if (m_pOptions->bKeepOnTop)
292            wflags |= Qt::WStyle_Tool;
293      // Some child forms are to be created right now.      // Some child forms are to be created right now.
294      m_pMessages = new qsamplerMessages(this);      m_pMessages = new qsamplerMessages(this);
295        m_pDeviceForm = new qsamplerDeviceForm(this, 0, wflags);
296    #ifdef CONFIG_MIDI_INSTRUMENT
297        m_pInstrumentListForm = new qsamplerInstrumentListForm(this, 0, wflags);
298            QObject::connect(m_pInstrumentListForm->InstrumentList,
299                    SIGNAL(instrumentsChanged()),
300                    SLOT(sessionDirty()));
301    #else
302            viewInstrumentsAction->setEnabled(false);
303    #endif
304      // Set message defaults...      // Set message defaults...
305      updateMessagesFont();      updateMessagesFont();
306      updateMessagesLimit();      updateMessagesLimit();
307      updateMessagesCapture();      updateMessagesCapture();
308      // Set the visibility signal.      // Set the visibility signal.
309      QObject::connect(m_pMessages, SIGNAL(visibilityChanged(bool)), this, SLOT(stabilizeForm()));          QObject::connect(m_pMessages,
310                    SIGNAL(visibilityChanged(bool)),
311                    SLOT(stabilizeForm()));
312    
313      // Initial decorations toggle state.      // Initial decorations toggle state.
314      viewMenubarAction->setOn(m_pOptions->bMenubar);      viewMenubarAction->setOn(m_pOptions->bMenubar);
# Line 193  void qsamplerMainForm::setup ( qsamplerO Line 331  void qsamplerMainForm::setup ( qsamplerO
331          QTextIStream istr(&sDockables);          QTextIStream istr(&sDockables);
332          istr >> *this;          istr >> *this;
333      }      }
334      // Try to restore old window positioning.      // Try to restore old window positioning and initial visibility.
335      m_pOptions->loadWidgetGeometry(this);      m_pOptions->loadWidgetGeometry(this);
336        m_pOptions->loadWidgetGeometry(m_pInstrumentListForm);
337        m_pOptions->loadWidgetGeometry(m_pDeviceForm);
338    
339      // Final startup stabilization...      // Final startup stabilization...
340        updateMaxVolume();
341      updateRecentFilesMenu();      updateRecentFilesMenu();
342      stabilizeForm();      stabilizeForm();
343    
# Line 232  bool qsamplerMainForm::queryClose (void) Line 373  bool qsamplerMainForm::queryClose (void)
373              QTextOStream ostr(&sDockables);              QTextOStream ostr(&sDockables);
374              ostr << *this;              ostr << *this;
375              m_pOptions->settings().writeEntry("/Layout/DockWindows", sDockables);              m_pOptions->settings().writeEntry("/Layout/DockWindows", sDockables);
376              // And the main windows state.              // And the children, and the main windows state,.
377              m_pOptions->saveWidgetGeometry(this);                          m_pOptions->saveWidgetGeometry(m_pDeviceForm);
378                            m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);
379                            m_pOptions->saveWidgetGeometry(this);
380                            // Close popup widgets.
381                            if (m_pInstrumentListForm)
382                                    m_pInstrumentListForm->close();
383                            if (m_pDeviceForm)
384                                    m_pDeviceForm->close();
385              // Stop client and/or server, gracefully.              // Stop client and/or server, gracefully.
386              stopServer();              stopServer();
387          }          }
# Line 252  void qsamplerMainForm::closeEvent ( QClo Line 400  void qsamplerMainForm::closeEvent ( QClo
400  }  }
401    
402    
403  void qsamplerMainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )  // Drag'n'drop file handler.
404    bool qsamplerMainForm::decodeDragFiles ( const QMimeSource *pEvent, QStringList& files )
405  {  {
406      bool bAccept = false;      bool bDecode = false;
407    
408      if (QTextDrag::canDecode(pDragEnterEvent)) {      if (QTextDrag::canDecode(pEvent)) {
409          QString sUrl;          QString sText;
410          if (QTextDrag::decode(pDragEnterEvent, sUrl) && m_pClient)          bDecode = QTextDrag::decode(pEvent, sText);
411              bAccept = QFileInfo(QUrl(sUrl).path()).exists();          if (bDecode) {
412                files = QStringList::split('\n', sText);
413                for (QStringList::Iterator iter = files.begin(); iter != files.end(); iter++)
414                    *iter = QUrl((*iter).stripWhiteSpace().replace(QRegExp("^file:"), QString::null)).path();
415            }
416      }      }
417    
418      pDragEnterEvent->accept(bAccept);      return bDecode;
419    }
420    
421    
422    // Window drag-n-drop event handlers.
423    void qsamplerMainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )
424    {
425            QStringList files;
426            pDragEnterEvent->accept(decodeDragFiles(pDragEnterEvent, files));
427  }  }
428    
429    
430  void qsamplerMainForm::dropEvent ( QDropEvent* pDropEvent )  void qsamplerMainForm::dropEvent ( QDropEvent* pDropEvent )
431  {  {
432      if (QTextDrag::canDecode(pDropEvent)) {      QStringList files;
433          QString sUrl;  
434          if (QTextDrag::decode(pDropEvent, sUrl) && closeSession(true))      if (!decodeDragFiles(pDropEvent, files))
435              loadSessionFile(QUrl(sUrl).path());          return;
436    
437            for (QStringList::Iterator iter = files.begin(); iter != files.end(); iter++) {
438                    const QString& sPath = *iter;
439                    if (qsamplerChannel::isInstrumentFile(sPath)) {
440                            // Try to create a new channel from instrument file...
441                            qsamplerChannel *pChannel = new qsamplerChannel();
442                            if (pChannel == NULL)
443                                    return;
444                            // Start setting the instrument filename...
445                            pChannel->setInstrument(sPath, 0);
446                            // Before we show it up, may be we'll
447                            // better ask for some initial values?
448                            if (!pChannel->channelSetup(this)) {
449                                    delete pChannel;
450                                    return;
451                            }
452                            // Finally, give it to a new channel strip...
453                            if (!createChannelStrip(pChannel)) {
454                                    delete pChannel;
455                                    return;
456                            }
457                            // Make that an overall update.
458                            m_iDirtyCount++;
459                            stabilizeForm();
460                    }   // Otherwise, load an usual session file (LSCP script)...
461                    else if (closeSession(true)) {
462                            loadSessionFile(sPath);
463                            break;
464                    }
465                    // Make it look responsive...:)
466                    QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
467            }
468    }
469    
470    
471    // Custome event handler.
472    void qsamplerMainForm::customEvent ( QCustomEvent *pCustomEvent )
473    {
474        // For the time being, just pump it to messages.
475        if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {
476            qsamplerCustomEvent *pEvent = (qsamplerCustomEvent *) pCustomEvent;
477                    if (pEvent->event() == LSCP_EVENT_CHANNEL_INFO) {
478                            int iChannelID = pEvent->data().toInt();
479                            qsamplerChannelStrip *pChannelStrip = channelStrip(iChannelID);
480                            if (pChannelStrip)
481                                    channelStripChanged(pChannelStrip);
482                    } else {
483                            appendMessagesColor(tr("Notify event: %1 data: %2")
484                                    .arg(::lscp_event_to_text(pEvent->event()))
485                                    .arg(pEvent->data()), "#996699");
486                    }
487      }      }
488  }  }
489    
490    
491    // Context menu event handler.
492    void qsamplerMainForm::contextMenuEvent( QContextMenuEvent *pEvent )
493    {
494        stabilizeForm();
495    
496        editMenu->exec(pEvent->globalPos());
497    }
498    
499    
500  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
501  // qsamplerMainForm -- Brainless public property accessors.  // qsamplerMainForm -- Brainless public property accessors.
502    
# Line 285  qsamplerOptions *qsamplerMainForm::optio Line 506  qsamplerOptions *qsamplerMainForm::optio
506      return m_pOptions;      return m_pOptions;
507  }  }
508    
509    
510  // The LSCP client descriptor property.  // The LSCP client descriptor property.
511  lscp_client_t *qsamplerMainForm::client (void)  lscp_client_t *qsamplerMainForm::client (void)
512  {  {
# Line 292  lscp_client_t *qsamplerMainForm::client Line 514  lscp_client_t *qsamplerMainForm::client
514  }  }
515    
516    
517    // The pseudo-singleton instance accessor.
518    qsamplerMainForm *qsamplerMainForm::getInstance (void)
519    {
520            return g_pMainForm;
521    }
522    
523    
524  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
525  // qsamplerMainForm -- Session file stuff.  // qsamplerMainForm -- Session file stuff.
526    
# Line 315  bool qsamplerMainForm::newSession (void) Line 544  bool qsamplerMainForm::newSession (void)
544      if (!closeSession(true))      if (!closeSession(true))
545          return false;          return false;
546    
547            // Give us what the server has, right now...
548            updateSession();
549    
550      // Ok increment untitled count.      // Ok increment untitled count.
551      m_iUntitled++;      m_iUntitled++;
552    
# Line 336  bool qsamplerMainForm::openSession (void Line 568  bool qsamplerMainForm::openSession (void
568    
569      // Ask for the filename to open...      // Ask for the filename to open...
570      QString sFilename = QFileDialog::getOpenFileName(      QString sFilename = QFileDialog::getOpenFileName(
571              m_pOptions->sSessionDir,                // Start here.                  m_pOptions->sSessionDir,                // Start here.
572              tr("LSCP Session files") + " (*.lscp)", // Filter (LSCP files)                  tr("LSCP Session files") + " (*.lscp)", // Filter (LSCP files)
573              this, 0,                                // Parent and name (none)                  this, 0,                                // Parent and name (none)
574              tr("Open Session")                      // Caption.                  QSAMPLER_TITLE ": " + tr("Open Session")        // Caption.
575      );      );
576    
577      // Have we cancelled?      // Have we cancelled?
# Line 370  bool qsamplerMainForm::saveSession ( boo Line 602  bool qsamplerMainForm::saveSession ( boo
602              sFilename = m_pOptions->sSessionDir;              sFilename = m_pOptions->sSessionDir;
603          // Prompt the guy...          // Prompt the guy...
604          sFilename = QFileDialog::getSaveFileName(          sFilename = QFileDialog::getSaveFileName(
605                  sFilename,                              // Start here.                          sFilename,                              // Start here.
606                  tr("LSCP Session files") + " (*.lscp)", // Filter (LSCP files)                          tr("LSCP Session files") + " (*.lscp)", // Filter (LSCP files)
607                  this, 0,                                // Parent and name (none)                          this, 0,                                // Parent and name (none)
608                  tr("Save Session")                      // Caption.                          QSAMPLER_TITLE ": " + tr("Save Session")        // Caption.
609          );          );
610          // Have we cancelled it?          // Have we cancelled it?
611          if (sFilename.isEmpty())          if (sFilename.isEmpty())
# Line 383  bool qsamplerMainForm::saveSession ( boo Line 615  bool qsamplerMainForm::saveSession ( boo
615              sFilename += ".lscp";              sFilename += ".lscp";
616          // Check if already exists...          // Check if already exists...
617          if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {          if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {
618              if (QMessageBox::warning(this, tr("Warning"),              if (QMessageBox::warning(this,
619                                    QSAMPLER_TITLE ": " + tr("Warning"),
620                  tr("The file already exists:\n\n"                  tr("The file already exists:\n\n"
621                     "\"%1\"\n\n"                     "\"%1\"\n\n"
622                     "Do you want to replace it?")                     "Do you want to replace it?")
# Line 405  bool qsamplerMainForm::closeSession ( bo Line 638  bool qsamplerMainForm::closeSession ( bo
638    
639      // Are we dirty enough to prompt it?      // Are we dirty enough to prompt it?
640      if (m_iDirtyCount > 0) {      if (m_iDirtyCount > 0) {
641          switch (QMessageBox::warning(this, tr("Warning"),          switch (QMessageBox::warning(this,
642                            QSAMPLER_TITLE ": " + tr("Warning"),
643              tr("The current session has been changed:\n\n"              tr("The current session has been changed:\n\n"
644              "\"%1\"\n\n"              "\"%1\"\n\n"
645              "Do you want to save the changes?")              "Do you want to save the changes?")
# Line 428  bool qsamplerMainForm::closeSession ( bo Line 662  bool qsamplerMainForm::closeSession ( bo
662          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
663          QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
664          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
665              qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel);              qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
666              if (bForce && ::lscp_remove_channel(m_pClient, pChannel->channelID()) != LSCP_OK)              if (pChannelStrip) {
667                  appendMessagesClient("lscp_remove_channel");                  qsamplerChannel *pChannel = pChannelStrip->channel();
668              delete pChannel;                  if (bForce && pChannel)
669                        pChannel->removeChannel();
670                    delete pChannelStrip;
671                }
672          }          }
673          m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
674          // We're now clean, for sure.          // We're now clean, for sure.
# Line 455  bool qsamplerMainForm::loadSessionFile ( Line 692  bool qsamplerMainForm::loadSessionFile (
692          return false;          return false;
693      }      }
694    
695            // Tell the world we'll take some time...
696            QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
697    
698      // Read the file.      // Read the file.
699            int iLine = 0;
700      int iErrors = 0;      int iErrors = 0;
701      QTextStream ts(&file);      QTextStream ts(&file);
702      while (!ts.atEnd()) {      while (!ts.atEnd()) {
703          // Read the line.          // Read the line.
704          QString sCommand = ts.readLine().simplifyWhiteSpace();          QString sCommand = ts.readLine().stripWhiteSpace();
705                    iLine++;
706          // If not empty, nor a comment, call the server...          // If not empty, nor a comment, call the server...
707          if (!sCommand.isEmpty() && sCommand[0] != '#') {          if (!sCommand.isEmpty() && sCommand[0] != '#') {
708              appendMessagesColor(sCommand, "#996633");                          // Remember that, no matter what,
709              // Remember that, no matter what,                          // all LSCP commands are CR/LF terminated.
710              // all LSCP commands are CR/LF terminated.                          sCommand += "\r\n";
711              sCommand += "\r\n";                          if (::lscp_client_query(m_pClient, sCommand.latin1()) != LSCP_OK) {
712              if (::lscp_client_query(m_pClient, sCommand.latin1()) != LSCP_OK) {                                  appendMessagesColor(QString("%1(%2): %3")
713                  appendMessagesClient("lscp_client_query");                                          .arg(QFileInfo(sFilename).fileName()).arg(iLine)
714                  iErrors++;                                          .arg(sCommand.simplifyWhiteSpace()), "#996633");
715              }                                  appendMessagesClient("lscp_client_query");
716                                    iErrors++;
717                            }
718          }          }
719          // Try to make it snappy :)          // Try to make it snappy :)
720          QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);          QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
# Line 479  bool qsamplerMainForm::loadSessionFile ( Line 723  bool qsamplerMainForm::loadSessionFile (
723      // Ok. we've read it.      // Ok. we've read it.
724      file.close();      file.close();
725    
726      // Have we any errors?          // Now we'll try to create (update) the whole GUI session.
727      if (iErrors > 0)          updateSession();
         appendMessagesError(tr("Some setttings could not be loaded\nfrom \"%1\" session file.\n\nSorry.").arg(sFilename));  
728    
729      // Now we'll try to create the whole GUI session.          // We're fornerly done.
730      int iChannels = ::lscp_get_channels(m_pClient);          QApplication::restoreOverrideCursor();
731      if (iChannels < 0) {  
732          appendMessagesClient("lscp_get_channels");          // Have we any errors?
733          appendMessagesError(tr("Could not get current number of channels.\n\nSorry."));          if (iErrors > 0)
734      }                  appendMessagesError(tr("Session loaded with errors\nfrom \"%1\".\n\nSorry.").arg(sFilename));
       
     // Try to (re)create each channel.  
     m_pWorkspace->setUpdatesEnabled(false);  
     for (int iChannelID = 0; iChannelID < iChannels; iChannelID++) {  
         createChannel(iChannelID, false);  
         QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);  
     }  
     m_pWorkspace->setUpdatesEnabled(true);  
735    
736      // Save as default session directory.      // Save as default session directory.
737      if (m_pOptions)      if (m_pOptions)
738          m_pOptions->sSessionDir = QFileInfo(sFilename).dirPath(true);          m_pOptions->sSessionDir = QFileInfo(sFilename).dirPath(true);
739      // We're not dirty anymore.          // We're not dirty anymore, if loaded without errors,
740      m_iDirtyCount = 0;          m_iDirtyCount = iErrors;
741      // Stabilize form...      // Stabilize form...
742      m_sFilename = sFilename;      m_sFilename = sFilename;
743      updateRecentFiles(sFilename);      updateRecentFiles(sFilename);
744      appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));      appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));
745    
746        // Make that an overall update.
747      stabilizeForm();      stabilizeForm();
748      return true;      return true;
749  }  }
# Line 515  bool qsamplerMainForm::loadSessionFile ( Line 752  bool qsamplerMainForm::loadSessionFile (
752  // Save current session to specific file path.  // Save current session to specific file path.
753  bool qsamplerMainForm::saveSessionFile ( const QString& sFilename )  bool qsamplerMainForm::saveSessionFile ( const QString& sFilename )
754  {  {
755            if (m_pClient == NULL)
756                    return false;
757    
758            // Check whether server is apparently OK...
759            if (::lscp_get_channels(m_pClient) < 0) {
760                    appendMessagesClient("lscp_get_channels");
761                    return false;
762            }
763    
764      // Open and write into real file.      // Open and write into real file.
765      QFile file(sFilename);      QFile file(sFilename);
766      if (!file.open(IO_WriteOnly | IO_Truncate)) {      if (!file.open(IO_WriteOnly | IO_Truncate)) {
# Line 522  bool qsamplerMainForm::saveSessionFile ( Line 768  bool qsamplerMainForm::saveSessionFile (
768          return false;          return false;
769      }      }
770    
771            // Tell the world we'll take some time...
772            QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
773    
774      // Write the file.      // Write the file.
775      int iErrors = 0;      int  iErrors = 0;
776      QTextStream ts(&file);      QTextStream ts(&file);
777      ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;      ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;
778      ts << "# " << tr("Version")      ts << "# " << tr("Version")
# Line 534  bool qsamplerMainForm::saveSessionFile ( Line 783  bool qsamplerMainForm::saveSessionFile (
783      ts << "# " << tr("File")      ts << "# " << tr("File")
784         << ": " << QFileInfo(sFilename).fileName() << endl;         << ": " << QFileInfo(sFilename).fileName() << endl;
785      ts << "# " << tr("Date")      ts << "# " << tr("Date")
786         << ": " << QDate::currentDate().toString("MMMM dd yyyy")         << ": " << QDate::currentDate().toString("MMM dd yyyy")
787         << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;         << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;
788      ts << "#"  << endl;      ts << "#"  << endl;
789      ts << endl;      ts << endl;
790    
791            // It is assumed that this new kind of device+session file
792            // will be loaded from a complete initialized server...
793            int *piDeviceIDs;
794            int  iDevice;
795            ts << "RESET" << endl;
796    
797            // Audio device mapping.
798            QMap<int, int> audioDeviceMap;
799            piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Audio);
800            for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
801                    ts << endl;
802                    qsamplerDevice device(qsamplerDevice::Audio, piDeviceIDs[iDevice]);
803                    // Audio device specification...
804                    ts << "# " << device.deviceTypeName() << " " << device.driverName()
805                            << " " << tr("Device") << " " << iDevice << endl;
806                    ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();
807                    qsamplerDeviceParamMap::ConstIterator deviceParam;
808                    for (deviceParam = device.params().begin();
809                                    deviceParam != device.params().end();
810                                            ++deviceParam) {
811                            const qsamplerDeviceParam& param = deviceParam.data();
812                            if (param.value.isEmpty()) ts << "# ";
813                            ts << " " << deviceParam.key() << "='" << param.value << "'";
814                    }
815                    ts << endl;
816                    // Audio channel parameters...
817                    int iPort = 0;
818                    for (qsamplerDevicePort *pPort = device.ports().first();
819                                    pPort;
820                                            pPort = device.ports().next(), ++iPort) {
821                            qsamplerDeviceParamMap::ConstIterator portParam;
822                            for (portParam = pPort->params().begin();
823                                            portParam != pPort->params().end();
824                                                    ++portParam) {
825                                    const qsamplerDeviceParam& param = portParam.data();
826                                    if (param.fix || param.value.isEmpty()) ts << "# ";
827                                    ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice
828                                            << " " << iPort << " " << portParam.key()
829                                            << "='" << param.value << "'" << endl;
830                            }
831                    }
832                    // Audio device index/id mapping.
833                    audioDeviceMap[device.deviceID()] = iDevice;
834                    // Try to keep it snappy :)
835                    QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
836            }
837    
838            // MIDI device mapping.
839            QMap<int, int> midiDeviceMap;
840            piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Midi);
841            for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
842                    ts << endl;
843                    qsamplerDevice device(qsamplerDevice::Midi, piDeviceIDs[iDevice]);
844                    // MIDI device specification...
845                    ts << "# " << device.deviceTypeName() << " " << device.driverName()
846                            << " " << tr("Device") << " " << iDevice << endl;
847                    ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();
848                    qsamplerDeviceParamMap::ConstIterator deviceParam;
849                    for (deviceParam = device.params().begin();
850                                    deviceParam != device.params().end();
851                                            ++deviceParam) {
852                            const qsamplerDeviceParam& param = deviceParam.data();
853                            if (param.value.isEmpty()) ts << "# ";
854                            ts << " " << deviceParam.key() << "='" << param.value << "'";
855                    }
856                    ts << endl;
857                    // MIDI port parameters...
858                    int iPort = 0;
859                    for (qsamplerDevicePort *pPort = device.ports().first();
860                                    pPort;
861                                            pPort = device.ports().next(), ++iPort) {
862                            qsamplerDeviceParamMap::ConstIterator portParam;
863                            for (portParam = pPort->params().begin();
864                                            portParam != pPort->params().end();
865                                                    ++portParam) {
866                                    const qsamplerDeviceParam& param = portParam.data();
867                                    if (param.fix || param.value.isEmpty()) ts << "# ";
868                                    ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice
869                                       << " " << iPort << " " << portParam.key()
870                                       << "='" << param.value << "'" << endl;
871                            }
872                    }
873                    // MIDI device index/id mapping.
874                    midiDeviceMap[device.deviceID()] = iDevice;
875                    // Try to keep it snappy :)
876                    QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
877            }
878            ts << endl;
879    
880    #ifdef CONFIG_MIDI_INSTRUMENT
881            // MIDI instrument mapping...
882            QMap<int, int> midiInstrumentMap;
883            int *piMaps = ::lscp_list_midi_instrument_maps(m_pClient);
884            for (int iMap = 0; piMaps && piMaps[iMap] >= 0; iMap++) {
885                    int iMidiMap = piMaps[iMap];
886                    const char *pszMapName
887                            = ::lscp_get_midi_instrument_map_name(m_pClient, iMidiMap);
888                    ts << "# " << tr("MIDI instrument map") << " " << iMap;
889                    if (pszMapName)
890                            ts << " - " << pszMapName;
891                    ts << endl;
892                    ts << "ADD MIDI_INSTRUMENT_MAP";
893                    if (pszMapName)
894                            ts << " '" << pszMapName << "'";
895                    ts << endl;
896                    // MIDI instrument mapping...
897                    lscp_midi_instrument_t *pInstrs
898                            = ::lscp_list_midi_instruments(m_pClient, iMidiMap);
899                    for (int iInstr = 0; pInstrs && pInstrs[iInstr].map >= 0; iInstr++) {
900                            lscp_midi_instrument_info_t *pInstrInfo
901                                    = ::lscp_get_midi_instrument_info(m_pClient, &pInstrs[iInstr]);
902                            if (pInstrInfo) {
903                                    ts << "MAP MIDI_INSTRUMENT "
904                                            << iMap                        << " "
905                                            << pInstrs[iInstr].bank        << " "
906                                            << pInstrs[iInstr].prog        << " "
907                                            << pInstrInfo->engine_name     << " '"
908                                            << pInstrInfo->instrument_file << "' "
909                                            << pInstrInfo->instrument_nr   << " "
910                                            << pInstrInfo->volume          << " ";
911                                    switch (pInstrInfo->load_mode) {
912                                            case LSCP_LOAD_PERSISTENT:
913                                                    ts << "PERSISTENT";
914                                                    break;
915                                            case LSCP_LOAD_ON_DEMAND_HOLD:
916                                                    ts << "ON_DEMAND_HOLD";
917                                                    break;
918                                            case LSCP_LOAD_ON_DEMAND:
919                                            case LSCP_LOAD_DEFAULT:
920                                            default:
921                                                    ts << "ON_DEMAND";
922                                                    break;
923                                    }
924                                    if (pInstrInfo->name)
925                                            ts << " '" << pInstrInfo->name << "'";
926                                    ts << endl;
927                            }       // Check for errors...
928                            else if (::lscp_client_get_errno(m_pClient)) {
929                                    appendMessagesClient("lscp_get_midi_instrument_info");
930                                    iErrors++;
931                            }
932                            // Try to keep it snappy :)
933                            QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
934                    }
935                    ts << endl;
936                    // Check for errors...
937                    if (pInstrs == NULL && ::lscp_client_get_errno(m_pClient)) {
938                            appendMessagesClient("lscp_list_midi_instruments");
939                            iErrors++;
940                    }
941                    // MIDI strument index/id mapping.
942                    midiInstrumentMap[iMidiMap] = iMap;
943            }
944            // Check for errors...
945            if (piMaps == NULL && ::lscp_client_get_errno(m_pClient)) {
946                    appendMessagesClient("lscp_list_midi_instrument_maps");
947                    iErrors++;
948            }
949    #endif  // CONFIG_MIDI_INSTRUMENT
950    
951            // Sampler channel mapping.
952      QWidgetList wlist = m_pWorkspace->windowList();      QWidgetList wlist = m_pWorkspace->windowList();
953      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
954          qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel);          qsamplerChannelStrip *pChannelStrip
955          int iChannelID = pChannel->channelID();                          = static_cast<qsamplerChannelStrip *> (wlist.at(iChannel));
956          ts << "# " << pChannel->caption() << endl;          if (pChannelStrip) {
957          ts << "ADD CHANNEL" << endl;              qsamplerChannel *pChannel = pChannelStrip->channel();
958          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannelID << " " << pChannel->audioDriver() << endl;              if (pChannel) {
959          ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannelID << " " << pChannel->midiDriver() << endl;                  ts << "# " << tr("Channel") << " " << iChannel << endl;
960      //  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannelID << " " << pChannel->midiPort() << endl;                  ts << "ADD CHANNEL" << endl;
961          ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannelID << " " << pChannel->midiChannel() << endl;                                  if (audioDeviceMap.isEmpty()) {
962          ts << "LOAD ENGINE " << pChannel->engineName() << " " << iChannelID << endl;                                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel
963          ts << "LOAD INSTRUMENT " << pChannel->instrumentFile() << " " << pChannel->instrumentNr() << " " << iChannelID << endl;                                                  << " " << pChannel->audioDriver() << endl;
964          ts << "SET CHANNEL VOLUME " << iChannelID << " " << pChannel->volume() << endl;                                  } else {
965          ts << endl;                                          ts << "SET CHANNEL AUDIO_OUTPUT_DEVICE " << iChannel
966                                                    << " " << audioDeviceMap[pChannel->audioDevice()] << endl;
967                                    }
968                                    if (midiDeviceMap.isEmpty()) {
969                                            ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannel
970                                                    << " " << pChannel->midiDriver() << endl;
971                                    } else {
972                                            ts << "SET CHANNEL MIDI_INPUT_DEVICE " << iChannel
973                                                    << " " << midiDeviceMap[pChannel->midiDevice()] << endl;
974                                    }
975                                    ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel
976                                            << " " << pChannel->midiPort() << endl;
977                    ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";
978                    if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
979                        ts << "ALL";
980                    else
981                        ts << pChannel->midiChannel();
982                    ts << endl;
983                    ts << "LOAD ENGINE " << pChannel->engineName() << " " << iChannel << endl;
984                                    if (pChannel->instrumentStatus() < 100) ts << "# ";
985                                    ts << "LOAD INSTRUMENT NON_MODAL '" << pChannel->instrumentFile() << "' "
986                                            << pChannel->instrumentNr() << " " << iChannel << endl;
987                                    qsamplerChannelRoutingMap::ConstIterator audioRoute;
988                                    for (audioRoute = pChannel->audioRouting().begin();
989                                                    audioRoute != pChannel->audioRouting().end();
990                                                            ++audioRoute) {
991                                            ts << "SET CHANNEL AUDIO_OUTPUT_CHANNEL " << iChannel
992                                                    << " " << audioRoute.key()
993                                                    << " " << audioRoute.data() << endl;
994                                    }
995                                    ts << "SET CHANNEL VOLUME " << iChannel
996                                            << " " << pChannel->volume() << endl;
997                                    if (pChannel->channelMute())
998                                            ts << "SET CHANNEL MUTE " << iChannel << " 1" << endl;
999                                    if (pChannel->channelSolo())
1000                                            ts << "SET CHANNEL SOLO " << iChannel << " 1" << endl;
1001    #ifdef CONFIG_MIDI_INSTRUMENT
1002                                    if (pChannel->midiMap() >= 0) {
1003                                            ts << "SET CHANNEL MIDI_INSTRUMENT_MAP " << iChannel
1004                                                    << " " << midiInstrumentMap[pChannel->midiMap()] << endl;
1005                                    }
1006    #endif
1007    #ifdef CONFIG_FXSEND
1008                                    int iChannelID = pChannel->channelID();
1009                                    int *piFxSends = ::lscp_list_fxsends(m_pClient, iChannelID);
1010                                    for (int iFxSend = 0;
1011                                                    piFxSends && piFxSends[iFxSend] >= 0;
1012                                                            iFxSend++) {
1013                                            lscp_fxsend_info_t *pFxSendInfo = ::lscp_get_fxsend_info(
1014                                                    m_pClient, iChannelID, piFxSends[iFxSend]);
1015                                            if (pFxSendInfo) {
1016                                                    ts << "CREATE FX_SEND " << iChannel
1017                                                            << " " << pFxSendInfo->midi_controller;
1018                                                    if (pFxSendInfo->name)
1019                                                            ts << " '" << pFxSendInfo->name << "'";
1020                                                    ts << endl;
1021                                                    int *piRouting = pFxSendInfo->audio_routing;
1022                                                    for (int iAudioSrc = 0;
1023                                                                    piRouting && piRouting[iAudioSrc] >= 0;
1024                                                                            iAudioSrc++) {
1025                                                            ts << "SET FX_SEND AUDIO_OUTPUT_CHANNEL "
1026                                                                    << iChannel
1027                                                                    << " " << iFxSend
1028                                                                    << " " << iAudioSrc
1029                                                                    << " " << piRouting[iAudioSrc] << endl;
1030                                                    }
1031    #ifdef CONFIG_FXSEND_LEVEL
1032                                                    ts << "SET FX_SEND LEVEL " << iChannel
1033                                                            << " " << iFxSend
1034                                                            << " " << pFxSendInfo->level << endl;                                                  
1035    #endif
1036                                            }       // Check for errors...
1037                                            else if (::lscp_client_get_errno(m_pClient)) {
1038                                                    appendMessagesClient("lscp_get_fxsend_info");
1039                                                    iErrors++;
1040                                            }
1041                                    }
1042    #endif
1043                    ts << endl;
1044                }
1045            }
1046          // Try to keep it snappy :)          // Try to keep it snappy :)
1047          QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);          QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
1048      }      }
1049    
1050    #ifdef CONFIG_VOLUME
1051            ts << "# " << tr("Global volume level") << endl;
1052            ts << "SET VOLUME " << ::lscp_get_volume(m_pClient) << endl;
1053            ts << endl;
1054    #endif
1055    
1056      // Ok. we've wrote it.      // Ok. we've wrote it.
1057      file.close();      file.close();
1058    
1059            // We're fornerly done.
1060            QApplication::restoreOverrideCursor();
1061    
1062      // Have we any errors?      // Have we any errors?
1063      if (iErrors > 0)      if (iErrors > 0)
1064          appendMessagesError(tr("Some settings could not be saved\nto \"%1\" session file.\n\nSorry.").arg(sFilename));          appendMessagesError(tr("Some settings could not be saved\nto \"%1\" session file.\n\nSorry.").arg(sFilename));
# Line 577  bool qsamplerMainForm::saveSessionFile ( Line 1077  bool qsamplerMainForm::saveSessionFile (
1077  }  }
1078    
1079    
1080    // Session change receiver slot.
1081    void qsamplerMainForm::sessionDirty (void)
1082    {
1083        // Just mark the dirty form.
1084        m_iDirtyCount++;
1085        // and update the form status...
1086        stabilizeForm();
1087    }
1088    
1089    
1090  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1091  // qsamplerMainForm -- File Action slots.  // qsamplerMainForm -- File Action slots.
1092    
# Line 623  void qsamplerMainForm::fileSaveAs (void) Line 1133  void qsamplerMainForm::fileSaveAs (void)
1133  }  }
1134    
1135    
1136    // Reset the sampler instance.
1137    void qsamplerMainForm::fileReset (void)
1138    {
1139        if (m_pClient == NULL)
1140            return;
1141    
1142        // Ask user whether he/she want's an internal sampler reset...
1143        if (QMessageBox::warning(this,
1144                    QSAMPLER_TITLE ": " + tr("Warning"),
1145            tr("Resetting the sampler instance will close\n"
1146               "all device and channel configurations.\n\n"
1147               "Please note that this operation may cause\n"
1148               "temporary MIDI and Audio disruption.\n\n"
1149               "Do you want to reset the sampler engine now?"),
1150            tr("Reset"), tr("Cancel")) > 0)
1151            return;
1152    
1153            // Trye closing the current session, first...
1154            if (!closeSession(true))
1155                    return;
1156    
1157        // Just do the reset, after closing down current session...
1158            // Do the actual sampler reset...
1159            if (::lscp_reset_sampler(m_pClient) != LSCP_OK) {
1160                    appendMessagesClient("lscp_reset_sampler");
1161                    appendMessagesError(tr("Could not reset sampler instance.\n\nSorry."));
1162                    return;
1163            }
1164    
1165        // Log this.
1166        appendMessages(tr("Sampler reset."));
1167    
1168            // Make it a new session...
1169            newSession();
1170    }
1171    
1172    
1173  // Restart the client/server instance.  // Restart the client/server instance.
1174  void qsamplerMainForm::fileRestart (void)  void qsamplerMainForm::fileRestart (void)
1175  {  {
1176      if (m_pOptions == NULL)      if (m_pOptions == NULL)
1177          return;          return;
1178            
1179      bool bRestart = true;      bool bRestart = true;
1180        
1181      // Ask user whether he/she want's a complete restart...      // Ask user whether he/she want's a complete restart...
1182      // (if we're currently up and running)      // (if we're currently up and running)
1183      if (bRestart && m_pClient) {      if (bRestart && m_pClient) {
1184          bRestart = (QMessageBox::warning(this, tr("Warning"),          bRestart = (QMessageBox::warning(this,
1185                            QSAMPLER_TITLE ": " + tr("Warning"),
1186              tr("New settings will be effective after\n"              tr("New settings will be effective after\n"
1187                 "restarting the client/server connection.\n\n"                 "restarting the client/server connection.\n\n"
1188                 "Please note that this operation may cause\n"                 "Please note that this operation may cause\n"
1189                 "temporary MIDI and Audio disruption\n\n"                 "temporary MIDI and Audio disruption.\n\n"
1190                 "Do you want to restart the connection now?"),                 "Do you want to restart the connection now?"),
1191              tr("Restart"), tr("Cancel")) == 0);              tr("Restart"), tr("Cancel")) == 0);
1192      }      }
# Line 670  void qsamplerMainForm::editAddChannel (v Line 1218  void qsamplerMainForm::editAddChannel (v
1218      if (m_pClient == NULL)      if (m_pClient == NULL)
1219          return;          return;
1220    
1221      // Create the new sampler channel.      // Just create the channel instance...
1222      int iChannelID = ::lscp_add_channel(m_pClient);      qsamplerChannel *pChannel = new qsamplerChannel();
1223      if (iChannelID < 0) {      if (pChannel == NULL)
         appendMessagesClient("lscp_add_channel");  
         appendMessagesError(tr("Could not create the new channel.\n\nSorry."));  
1224          return;          return;
     }  
1225    
1226      // Log this happening.      // Before we show it up, may be we'll
1227      appendMessages(tr("Channel %1 created.").arg(iChannelID));      // better ask for some initial values?
1228        if (!pChannel->channelSetup(this)) {
1229            delete pChannel;
1230            return;
1231        }
1232    
1233      // Just create the channel strip with given id.      // And give it to the strip (will own the channel instance, if successful).
1234      createChannel(iChannelID, true);      if (!createChannelStrip(pChannel)) {
1235            delete pChannel;
1236            return;
1237        }
1238    
1239      // We'll be dirty, for sure...      // Make that an overall update.
1240      m_iDirtyCount++;      m_iDirtyCount++;
     // Stabilize form anyway.  
1241      stabilizeForm();      stabilizeForm();
1242  }  }
1243    
# Line 697  void qsamplerMainForm::editRemoveChannel Line 1248  void qsamplerMainForm::editRemoveChannel
1248      if (m_pClient == NULL)      if (m_pClient == NULL)
1249          return;          return;
1250    
1251      qsamplerChannelStrip *pChannel = activeChannel();      qsamplerChannelStrip *pChannelStrip = activeChannelStrip();
1252        if (pChannelStrip == NULL)
1253            return;
1254    
1255        qsamplerChannel *pChannel = pChannelStrip->channel();
1256      if (pChannel == NULL)      if (pChannel == NULL)
1257          return;          return;
1258    
1259      // Prompt user if he/she's sure about this...      // Prompt user if he/she's sure about this...
1260      if (m_pOptions && m_pOptions->bConfirmRemove) {      if (m_pOptions && m_pOptions->bConfirmRemove) {
1261          if (QMessageBox::warning(this, tr("Warning"),          if (QMessageBox::warning(this,
1262                            QSAMPLER_TITLE ": " + tr("Warning"),
1263              tr("About to remove channel:\n\n"              tr("About to remove channel:\n\n"
1264                 "%1\n\n"                 "%1\n\n"
1265                 "Are you sure?")                 "Are you sure?")
1266                 .arg(pChannel->caption()),                 .arg(pChannelStrip->caption()),
1267              tr("OK"), tr("Cancel")) > 0)              tr("OK"), tr("Cancel")) > 0)
1268              return;              return;
1269      }      }
1270    
1271      // Remove the existing sampler channel.      // Remove the existing sampler channel.
1272      if (::lscp_remove_channel(m_pClient, pChannel->channelID()) != LSCP_OK) {      if (!pChannel->removeChannel())
         appendMessagesClient("lscp_remove_channel");  
         appendMessagesError(tr("Could not remove channel.\n\nSorry."));  
1273          return;          return;
     }  
1274    
     // Log this happening.  
     appendMessages(tr("Channel %1 removed.").arg(pChannel->channelID()));  
       
1275      // Just delete the channel strip.      // Just delete the channel strip.
1276      delete pChannel;      delete pChannelStrip;
1277    
1278      // Do we auto-arrange?      // Do we auto-arrange?
1279      if (m_pOptions && m_pOptions->bAutoArrange)      if (m_pOptions && m_pOptions->bAutoArrange)
1280          channelsArrange();          channelsArrange();
# Line 740  void qsamplerMainForm::editSetupChannel Line 1291  void qsamplerMainForm::editSetupChannel
1291      if (m_pClient == NULL)      if (m_pClient == NULL)
1292          return;          return;
1293    
1294      qsamplerChannelStrip *pChannel = activeChannel();      qsamplerChannelStrip *pChannelStrip = activeChannelStrip();
1295      if (pChannel == NULL)      if (pChannelStrip == NULL)
1296          return;          return;
1297    
1298      // Just invoque the channel strip procedure.      // Just invoque the channel strip procedure.
1299      pChannel->channelSetup();      pChannelStrip->channelSetup();
1300  }  }
1301    
1302    
# Line 755  void qsamplerMainForm::editResetChannel Line 1306  void qsamplerMainForm::editResetChannel
1306      if (m_pClient == NULL)      if (m_pClient == NULL)
1307          return;          return;
1308    
1309      qsamplerChannelStrip *pChannel = activeChannel();      qsamplerChannelStrip *pChannelStrip = activeChannelStrip();
1310      if (pChannel == NULL)      if (pChannelStrip == NULL)
1311          return;          return;
1312    
1313      // Remove the existing sampler channel.      // Just invoque the channel strip procedure.
1314      if (::lscp_reset_channel(m_pClient, pChannel->channelID()) != LSCP_OK) {      pChannelStrip->channelReset();
1315          appendMessagesClient("lscp_reset_channel");  }
         appendMessagesError(tr("Could not reset channel.\n\nSorry."));  
         return;  
     }  
1316    
     // Log this.  
     appendMessages(tr("Channel %1 reset.").arg(pChannel->channelID()));  
1317    
1318      // Refresh channel strip info.  // Reset all sampler channels.
1319      pChannel->updateChannelInfo();  void qsamplerMainForm::editResetAllChannels (void)
1320    {
1321            if (m_pClient == NULL)
1322                    return;
1323    
1324            // Invoque the channel strip procedure,
1325            // for all channels out there...
1326            m_pWorkspace->setUpdatesEnabled(false);
1327            QWidgetList wlist = m_pWorkspace->windowList();
1328            for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1329                    qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1330                    if (pChannelStrip)
1331                            pChannelStrip->channelReset();
1332            }
1333            m_pWorkspace->setUpdatesEnabled(true);
1334  }  }
1335    
1336    
# Line 822  void qsamplerMainForm::viewMessages ( bo Line 1382  void qsamplerMainForm::viewMessages ( bo
1382  }  }
1383    
1384    
1385    // Show/hide the MIDI instrument list-view form.
1386    void qsamplerMainForm::viewInstruments (void)
1387    {
1388            if (m_pOptions == NULL)
1389                    return;
1390    
1391            if (m_pInstrumentListForm) {
1392                    m_pOptions->saveWidgetGeometry(m_pInstrumentListForm);
1393                    if (m_pInstrumentListForm->isVisible()) {
1394                            m_pInstrumentListForm->hide();
1395                    } else {
1396                            m_pInstrumentListForm->show();
1397                            m_pInstrumentListForm->raise();
1398                            m_pInstrumentListForm->setActiveWindow();
1399                    }
1400            }
1401    }
1402    
1403    
1404    // Show/hide the device configurator form.
1405    void qsamplerMainForm::viewDevices (void)
1406    {
1407            if (m_pOptions == NULL)
1408                    return;
1409    
1410            if (m_pDeviceForm) {
1411                    m_pOptions->saveWidgetGeometry(m_pDeviceForm);
1412                    if (m_pDeviceForm->isVisible()) {
1413                            m_pDeviceForm->hide();
1414                    } else {
1415                            m_pDeviceForm->show();
1416                            m_pDeviceForm->raise();
1417                            m_pDeviceForm->setActiveWindow();
1418                    }
1419            }
1420    }
1421    
1422    
1423  // Show options dialog.  // Show options dialog.
1424  void qsamplerMainForm::viewOptions (void)  void qsamplerMainForm::viewOptions (void)
1425  {  {
# Line 831  void qsamplerMainForm::viewOptions (void Line 1429  void qsamplerMainForm::viewOptions (void
1429      qsamplerOptionsForm *pOptionsForm = new qsamplerOptionsForm(this);      qsamplerOptionsForm *pOptionsForm = new qsamplerOptionsForm(this);
1430      if (pOptionsForm) {      if (pOptionsForm) {
1431          // Check out some initial nullities(tm)...          // Check out some initial nullities(tm)...
1432          qsamplerChannelStrip *pChannel = activeChannel();          qsamplerChannelStrip *pChannelStrip = activeChannelStrip();
1433          if (m_pOptions->sDisplayFont.isEmpty() && pChannel)          if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)
1434              m_pOptions->sDisplayFont = pChannel->displayFont().toString();              m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();
1435          if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)          if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)
1436              m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();              m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
1437          // To track down deferred or immediate changes.          // To track down deferred or immediate changes.
# Line 843  void qsamplerMainForm::viewOptions (void Line 1441  void qsamplerMainForm::viewOptions (void
1441          bool    bOldServerStart     = m_pOptions->bServerStart;          bool    bOldServerStart     = m_pOptions->bServerStart;
1442          QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;          QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;
1443          QString sOldDisplayFont     = m_pOptions->sDisplayFont;          QString sOldDisplayFont     = m_pOptions->sDisplayFont;
1444            bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;
1445          int     iOldMaxVolume       = m_pOptions->iMaxVolume;          int     iOldMaxVolume       = m_pOptions->iMaxVolume;
1446          QString sOldMessagesFont    = m_pOptions->sMessagesFont;          QString sOldMessagesFont    = m_pOptions->sMessagesFont;
1447            bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;
1448          bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;          bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;
1449          int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;          int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;
1450          int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;          int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;
1451          bool    bOldCompletePath    = m_pOptions->bCompletePath;          bool    bOldCompletePath    = m_pOptions->bCompletePath;
1452            bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;
1453          int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;          int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;
1454          // Load the current setup settings.          // Load the current setup settings.
1455          pOptionsForm->setup(m_pOptions);          pOptionsForm->setup(m_pOptions);
# Line 856  void qsamplerMainForm::viewOptions (void Line 1457  void qsamplerMainForm::viewOptions (void
1457          if (pOptionsForm->exec()) {          if (pOptionsForm->exec()) {
1458              // Warn if something will be only effective on next run.              // Warn if something will be only effective on next run.
1459              if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||              if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1460                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture)) {                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||
1461                  QMessageBox::information(this, tr("Information"),                  ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||
1462                    (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {
1463                    QMessageBox::information(this,
1464                                            QSAMPLER_TITLE ": " + tr("Information"),
1465                      tr("Some settings may be only effective\n"                      tr("Some settings may be only effective\n"
1466                         "next time you start this program."), tr("OK"));                         "next time you start this program."), tr("OK"));
1467                  updateMessagesCapture();                  updateMessagesCapture();
# Line 867  void qsamplerMainForm::viewOptions (void Line 1471  void qsamplerMainForm::viewOptions (void
1471                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||
1472                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
1473                  updateRecentFilesMenu();                  updateRecentFilesMenu();
1474                if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||
1475                    (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))
1476                    updateInstrumentNames();
1477                if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||
1478                    (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))
1479                    updateDisplayEffect();
1480              if (sOldDisplayFont != m_pOptions->sDisplayFont)              if (sOldDisplayFont != m_pOptions->sDisplayFont)
1481                  updateDisplayFont();                  updateDisplayFont();
1482              if (iOldMaxVolume != m_pOptions->iMaxVolume)              if (iOldMaxVolume != m_pOptions->iMaxVolume)
# Line 909  void qsamplerMainForm::channelsArrange ( Line 1519  void qsamplerMainForm::channelsArrange (
1519      m_pWorkspace->setUpdatesEnabled(false);      m_pWorkspace->setUpdatesEnabled(false);
1520      int y = 0;      int y = 0;
1521      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1522          qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel);          qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1523      /*  if (pChannel->testWState(WState_Maximized | WState_Minimized)) {      /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {
1524              // Prevent flicker...              // Prevent flicker...
1525              pChannel->hide();              pChannelStrip->hide();
1526              pChannel->showNormal();              pChannelStrip->showNormal();
1527          }   */          }   */
1528          pChannel->adjustSize();          pChannelStrip->adjustSize();
1529          int iWidth  = m_pWorkspace->width();          int iWidth  = m_pWorkspace->width();
1530          if (iWidth < pChannel->width())          if (iWidth < pChannelStrip->width())
1531              iWidth = pChannel->width();              iWidth = pChannelStrip->width();
1532      //  int iHeight = pChannel->height() + pChannel->parentWidget()->baseSize().height();      //  int iHeight = pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();
1533          int iHeight = pChannel->parentWidget()->frameGeometry().height();          int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();
1534          pChannel->parentWidget()->setGeometry(0, y, iWidth, iHeight);          pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);
1535          y += iHeight;          y += iHeight;
1536      }      }
1537      m_pWorkspace->setUpdatesEnabled(true);      m_pWorkspace->setUpdatesEnabled(true);
1538        
1539      stabilizeForm();      stabilizeForm();
1540  }  }
1541    
# Line 969  void qsamplerMainForm::helpAbout (void) Line 1579  void qsamplerMainForm::helpAbout (void)
1579      sText += tr("Debugging option enabled.");      sText += tr("Debugging option enabled.");
1580      sText += "</font></small><br />";      sText += "</font></small><br />";
1581  #endif  #endif
1582    #ifndef CONFIG_LIBGIG
1583        sText += "<small><font color=\"red\">";
1584        sText += tr("GIG (libgig) file support disabled.");
1585        sText += "</font></small><br />";
1586    #endif
1587    #ifndef CONFIG_INSTRUMENT_NAME
1588        sText += "<small><font color=\"red\">";
1589        sText += tr("LSCP (liblscp) instrument_name support disabled.");
1590        sText += "</font></small><br />";
1591    #endif
1592    #ifndef CONFIG_MUTE_SOLO
1593        sText += "<small><font color=\"red\">";
1594        sText += tr("Sampler channel Mute/Solo support disabled.");
1595        sText += "</font></small><br />";
1596    #endif
1597    #ifndef CONFIG_AUDIO_ROUTING
1598        sText += "<small><font color=\"red\">";
1599        sText += tr("LSCP (liblscp) audio_routing support disabled.");
1600        sText += "</font></small><br />";
1601    #endif
1602    #ifndef CONFIG_FXSEND
1603        sText += "<small><font color=\"red\">";
1604        sText += tr("Sampler channel Effect Sends support disabled.");
1605        sText += "</font></small><br />";
1606    #endif
1607    #ifndef CONFIG_VOLUME
1608        sText += "<small><font color=\"red\">";
1609        sText += tr("Global volume support disabled.");
1610        sText += "</font></small><br />";
1611    #endif
1612    #ifndef CONFIG_MIDI_INSTRUMENT
1613        sText += "<small><font color=\"red\">";
1614        sText += tr("MIDI instrument mapping support disabled.");
1615        sText += "</font></small><br />";
1616    #endif
1617    #ifndef CONFIG_EDIT_INSTRUMENT
1618        sText += "<small><font color=\"red\">";
1619        sText += tr("Instrument editing support disabled.");
1620        sText += "</font></small><br />";
1621    #endif
1622      sText += "<br />\n";      sText += "<br />\n";
1623      sText += tr("Using") + ": ";      sText += tr("Using") + ": ";
1624      sText += ::lscp_client_package();      sText += ::lscp_client_package();
1625      sText += " ";      sText += " ";
1626      sText += ::lscp_client_version();      sText += ::lscp_client_version();
1627    #ifdef CONFIG_LIBGIG
1628        sText += ", ";
1629        sText += gig::libraryName().c_str();
1630        sText += " ";
1631        sText += gig::libraryVersion().c_str();
1632    #endif
1633      sText += "<br />\n";      sText += "<br />\n";
1634      sText += "<br />\n";      sText += "<br />\n";
1635      sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";      sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";
# Line 996  void qsamplerMainForm::helpAbout (void) Line 1652  void qsamplerMainForm::helpAbout (void)
1652  void qsamplerMainForm::stabilizeForm (void)  void qsamplerMainForm::stabilizeForm (void)
1653  {  {
1654      // Update the main application caption...      // Update the main application caption...
1655      QString sSessioName = sessionName(m_sFilename);      QString sSessionName = sessionName(m_sFilename);
1656      if (m_iDirtyCount > 0)      if (m_iDirtyCount > 0)
1657          sSessioName += '*';          sSessionName += " *";
1658      setCaption(tr(QSAMPLER_TITLE " - [%1]").arg(sSessioName));      setCaption(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));
1659    
1660      // Update the main menu state...      // Update the main menu state...
1661      qsamplerChannelStrip *pChannel = activeChannel();      qsamplerChannelStrip *pChannelStrip = activeChannelStrip();
1662      bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);      bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);
1663      bool bHasChannel = (bHasClient && pChannel != NULL);      bool bHasChannel = (bHasClient && pChannelStrip != NULL);
1664      fileNewAction->setEnabled(bHasClient);      fileNewAction->setEnabled(bHasClient);
1665      fileOpenAction->setEnabled(bHasClient);      fileOpenAction->setEnabled(bHasClient);
1666      fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);      fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
1667      fileSaveAsAction->setEnabled(bHasClient);      fileSaveAsAction->setEnabled(bHasClient);
1668        fileResetAction->setEnabled(bHasClient);
1669      fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);      fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);
1670      editAddChannelAction->setEnabled(bHasClient);      editAddChannelAction->setEnabled(bHasClient);
1671      editRemoveChannelAction->setEnabled(bHasChannel);      editRemoveChannelAction->setEnabled(bHasChannel);
1672      editSetupChannelAction->setEnabled(bHasChannel);      editSetupChannelAction->setEnabled(bHasChannel);
1673      editResetChannelAction->setEnabled(bHasChannel);      editResetChannelAction->setEnabled(bHasChannel);
1674      channelsArrangeAction->setEnabled(bHasChannel);      editResetAllChannelsAction->setEnabled(bHasChannel);
1675      viewMessagesAction->setOn(m_pMessages && m_pMessages->isVisible());      viewMessagesAction->setOn(m_pMessages && m_pMessages->isVisible());
1676    #ifdef CONFIG_MIDI_INSTRUMENT
1677            viewInstrumentsAction->setOn(m_pInstrumentListForm
1678                    && m_pInstrumentListForm->isVisible());
1679            viewInstrumentsAction->setEnabled(bHasClient);
1680    #endif
1681            viewDevicesAction->setOn(m_pDeviceForm
1682                    && m_pDeviceForm->isVisible());
1683        viewDevicesAction->setEnabled(bHasClient);
1684        channelsArrangeAction->setEnabled(bHasChannel);
1685    
1686    #ifdef CONFIG_VOLUME
1687            // Toolbar widgets are also affected...
1688        m_pVolumeSlider->setEnabled(bHasClient);
1689        m_pVolumeSpinBox->setEnabled(bHasClient);
1690    #endif
1691    
1692      // Client/Server status...      // Client/Server status...
1693      if (bHasClient) {      if (bHasClient) {
1694          m_status[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));          m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));
1695          m_status[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost + ":" + QString::number(m_pOptions->iServerPort));          m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost + ":" + QString::number(m_pOptions->iServerPort));
1696      } else {      } else {
1697          m_status[QSAMPLER_STATUS_CLIENT]->clear();          m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();
1698          m_status[QSAMPLER_STATUS_SERVER]->clear();          m_statusItem[QSAMPLER_STATUS_SERVER]->clear();
1699      }      }
1700      // Channel status...      // Channel status...
1701      if (bHasChannel)      if (bHasChannel)
1702          m_status[QSAMPLER_STATUS_CHANNEL]->setText(pChannel->caption());          m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->caption());
1703      else      else
1704          m_status[QSAMPLER_STATUS_CHANNEL]->clear();          m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();
1705      // Session status...      // Session status...
1706      if (m_iDirtyCount > 0)      if (m_iDirtyCount > 0)
1707          m_status[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));          m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));
1708      else      else
1709          m_status[QSAMPLER_STATUS_SESSION]->clear();          m_statusItem[QSAMPLER_STATUS_SESSION]->clear();
1710    
1711      // Recent files menu.      // Recent files menu.
1712      m_pRecentFilesMenu->setEnabled(bHasClient && m_pOptions->recentFiles.count() > 0);      m_pRecentFilesMenu->setEnabled(bHasClient && m_pOptions->recentFiles.count() > 0);
# Line 1045  void qsamplerMainForm::stabilizeForm (vo Line 1717  void qsamplerMainForm::stabilizeForm (vo
1717  }  }
1718    
1719    
1720    // Global volume change receiver slot.
1721    void qsamplerMainForm::volumeChanged ( int iVolume )
1722    {
1723    #ifdef CONFIG_VOLUME
1724    
1725            if (m_iVolumeChanging > 0)
1726                    return;
1727            
1728            m_iVolumeChanging++;
1729    
1730            // Update the toolbar widgets...
1731            if (m_pVolumeSlider->value()  != iVolume)
1732                    m_pVolumeSlider->setValue(iVolume);
1733            if (m_pVolumeSpinBox->value() != iVolume)
1734                    m_pVolumeSpinBox->setValue(iVolume);
1735    
1736            // Do it as commanded...
1737            float fVolume = 0.01f * float(iVolume);
1738            if (::lscp_set_volume(m_pClient, fVolume) == LSCP_OK)
1739                    appendMessages(QObject::tr("Volume: %1.").arg(fVolume));
1740            else
1741                    appendMessagesClient("lscp_set_volume");
1742    
1743            m_iVolumeChanging--;
1744    
1745            m_iDirtyCount++;
1746            stabilizeForm();
1747    
1748    #endif
1749    }
1750    
1751    
1752  // Channel change receiver slot.  // Channel change receiver slot.
1753  void qsamplerMainForm::channelChanged( qsamplerChannelStrip * )  void qsamplerMainForm::channelStripChanged( qsamplerChannelStrip *pChannelStrip )
1754  {  {
1755            // Add this strip to the changed list...
1756            if (m_changedStrips.containsRef(pChannelStrip) == 0) {
1757                    m_changedStrips.append(pChannelStrip);
1758                    pChannelStrip->resetErrorCount();
1759            }
1760    
1761      // Just mark the dirty form.      // Just mark the dirty form.
1762      m_iDirtyCount++;      m_iDirtyCount++;
1763      // and update the form status...      // and update the form status...
# Line 1055  void qsamplerMainForm::channelChanged( q Line 1765  void qsamplerMainForm::channelChanged( q
1765  }  }
1766    
1767    
1768    // Grab and restore current sampler channels session.
1769    void qsamplerMainForm::updateSession (void)
1770    {
1771    #ifdef CONFIG_VOLUME
1772            int iVolume = ::lroundf(100.0f * ::lscp_get_volume(m_pClient));
1773            m_iVolumeChanging++;
1774            m_pVolumeSlider->setValue(iVolume);
1775            m_pVolumeSpinBox->setValue(iVolume);
1776            m_iVolumeChanging--;
1777    #endif
1778    #ifdef CONFIG_MIDI_INSTRUMENT
1779            // FIXME: Make some room for default instrument maps...
1780            int iMaps = ::lscp_get_midi_instrument_maps(m_pClient);
1781            if (iMaps < 0)
1782                    appendMessagesClient("lscp_get_midi_instrument_maps");
1783            else if (iMaps < 1) {
1784                    ::lscp_add_midi_instrument_map(m_pClient, tr("Chromatic").latin1());
1785                    ::lscp_add_midi_instrument_map(m_pClient, tr("Drum Kits").latin1());
1786            }
1787    #endif
1788    
1789            // Retrieve the current channel list.
1790            int *piChannelIDs = ::lscp_list_channels(m_pClient);
1791            if (piChannelIDs == NULL) {
1792                    if (::lscp_client_get_errno(m_pClient)) {
1793                            appendMessagesClient("lscp_list_channels");
1794                            appendMessagesError(tr("Could not get current list of channels.\n\nSorry."));
1795                    }
1796            } else {
1797                    // Try to (re)create each channel.
1798                    m_pWorkspace->setUpdatesEnabled(false);
1799                    for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {
1800                            // Check if theres already a channel strip for this one...
1801                            if (!channelStrip(piChannelIDs[iChannel]))
1802                                    createChannelStrip(new qsamplerChannel(piChannelIDs[iChannel]));
1803                    }
1804                    m_pWorkspace->setUpdatesEnabled(true);
1805            }
1806    
1807        // Do we auto-arrange?
1808        if (m_pOptions && m_pOptions->bAutoArrange)
1809            channelsArrange();
1810    
1811            // Remember to refresh devices and instruments...
1812            if (m_pInstrumentListForm)
1813                m_pInstrumentListForm->refreshInstruments();
1814            if (m_pDeviceForm)
1815                m_pDeviceForm->refreshDevices();
1816    }
1817    
1818    
1819  // Update the recent files list and menu.  // Update the recent files list and menu.
1820  void qsamplerMainForm::updateRecentFiles ( const QString& sFilename )  void qsamplerMainForm::updateRecentFiles ( const QString& sFilename )
1821  {  {
# Line 1099  void qsamplerMainForm::updateRecentFiles Line 1860  void qsamplerMainForm::updateRecentFiles
1860  }  }
1861    
1862    
1863    // Force update of the channels instrument names mode.
1864    void qsamplerMainForm::updateInstrumentNames (void)
1865    {
1866        // Full channel list update...
1867        QWidgetList wlist = m_pWorkspace->windowList();
1868        if (wlist.isEmpty())
1869            return;
1870    
1871        m_pWorkspace->setUpdatesEnabled(false);
1872        for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1873            qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1874            if (pChannelStrip)
1875                pChannelStrip->updateInstrumentName(true);
1876        }
1877        m_pWorkspace->setUpdatesEnabled(true);
1878    }
1879    
1880    
1881  // Force update of the channels display font.  // Force update of the channels display font.
1882  void qsamplerMainForm::updateDisplayFont (void)  void qsamplerMainForm::updateDisplayFont (void)
1883  {  {
# Line 1120  void qsamplerMainForm::updateDisplayFont Line 1899  void qsamplerMainForm::updateDisplayFont
1899    
1900      m_pWorkspace->setUpdatesEnabled(false);      m_pWorkspace->setUpdatesEnabled(false);
1901      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1902          qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel);          qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1903          pChannel->setDisplayFont(font);          if (pChannelStrip)
1904                pChannelStrip->setDisplayFont(font);
1905        }
1906        m_pWorkspace->setUpdatesEnabled(true);
1907    }
1908    
1909    
1910    // Update channel strips background effect.
1911    void qsamplerMainForm::updateDisplayEffect (void)
1912    {
1913       QPixmap pm;
1914        if (m_pOptions->bDisplayEffect)
1915            pm = QPixmap::fromMimeSource("displaybg1.png");
1916    
1917        // Full channel list update...
1918        QWidgetList wlist = m_pWorkspace->windowList();
1919        if (wlist.isEmpty())
1920            return;
1921    
1922        m_pWorkspace->setUpdatesEnabled(false);
1923        for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1924            qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1925            if (pChannelStrip)
1926                pChannelStrip->setDisplayBackground(pm);
1927      }      }
1928      m_pWorkspace->setUpdatesEnabled(true);      m_pWorkspace->setUpdatesEnabled(true);
1929  }  }
# Line 1133  void qsamplerMainForm::updateMaxVolume ( Line 1935  void qsamplerMainForm::updateMaxVolume (
1935      if (m_pOptions == NULL)      if (m_pOptions == NULL)
1936          return;          return;
1937    
1938    #ifdef CONFIG_VOLUME
1939            m_iVolumeChanging++;
1940            m_pVolumeSlider->setMaxValue(m_pOptions->iMaxVolume);
1941            m_pVolumeSpinBox->setMaxValue(m_pOptions->iMaxVolume);
1942            m_iVolumeChanging--;
1943    #endif
1944    
1945      // Full channel list update...      // Full channel list update...
1946      QWidgetList wlist = m_pWorkspace->windowList();      QWidgetList wlist = m_pWorkspace->windowList();
1947      if (wlist.isEmpty())      if (wlist.isEmpty())
# Line 1140  void qsamplerMainForm::updateMaxVolume ( Line 1949  void qsamplerMainForm::updateMaxVolume (
1949    
1950      m_pWorkspace->setUpdatesEnabled(false);      m_pWorkspace->setUpdatesEnabled(false);
1951      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1952          qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel);          qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1953          pChannel->setMaxVolume(m_pOptions->iMaxVolume);          if (pChannelStrip)
1954                pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
1955      }      }
1956      m_pWorkspace->setUpdatesEnabled(true);      m_pWorkspace->setUpdatesEnabled(true);
1957  }  }
# Line 1180  void qsamplerMainForm::appendMessagesErr Line 1990  void qsamplerMainForm::appendMessagesErr
1990    
1991      appendMessagesColor(s.simplifyWhiteSpace(), "#ff0000");      appendMessagesColor(s.simplifyWhiteSpace(), "#ff0000");
1992    
1993      QMessageBox::critical(this, tr("Error"), s, tr("Cancel"));          // Make it look responsive...:)
1994            QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
1995    
1996        QMessageBox::critical(this,
1997                    QSAMPLER_TITLE ": " + tr("Error"), s, tr("Cancel"));
1998  }  }
1999    
2000    
# Line 1193  void qsamplerMainForm::appendMessagesCli Line 2007  void qsamplerMainForm::appendMessagesCli
2007      appendMessagesColor(s + QString(": %1 (errno=%2)")      appendMessagesColor(s + QString(": %1 (errno=%2)")
2008          .arg(::lscp_client_get_result(m_pClient))          .arg(::lscp_client_get_result(m_pClient))
2009          .arg(::lscp_client_get_errno(m_pClient)), "#996666");          .arg(::lscp_client_get_errno(m_pClient)), "#996666");
2010    
2011            // Make it look responsive...:)
2012            QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
2013  }  }
2014    
2015    
# Line 1220  void qsamplerMainForm::updateMessagesLim Line 2037  void qsamplerMainForm::updateMessagesLim
2037          if (m_pOptions->bMessagesLimit)          if (m_pOptions->bMessagesLimit)
2038              m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);              m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);
2039          else          else
2040              m_pMessages->setMessagesLimit(0);              m_pMessages->setMessagesLimit(-1);
2041      }      }
2042  }  }
2043    
# Line 1240  void qsamplerMainForm::updateMessagesCap Line 2057  void qsamplerMainForm::updateMessagesCap
2057  // qsamplerMainForm -- MDI channel strip management.  // qsamplerMainForm -- MDI channel strip management.
2058    
2059  // The channel strip creation executive.  // The channel strip creation executive.
2060  void qsamplerMainForm::createChannel ( int iChannelID, bool bPrompt )  qsamplerChannelStrip *qsamplerMainForm::createChannelStrip ( qsamplerChannel *pChannel )
2061  {  {
2062      if (m_pClient == NULL)      if (m_pClient == NULL || pChannel == NULL)
2063          return;          return NULL;
2064    
2065      // Prepare for auto-arrange?      // Prepare for auto-arrange?
2066      qsamplerChannelStrip *pChannel = NULL;      qsamplerChannelStrip *pChannelStrip = NULL;
2067      int y = 0;      int y = 0;
2068      if (m_pOptions && m_pOptions->bAutoArrange) {      if (m_pOptions && m_pOptions->bAutoArrange) {
2069          QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
2070          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2071              pChannel = (qsamplerChannelStrip *) wlist.at(iChannel);              pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
2072          //  y += pChannel->height() + pChannel->parentWidget()->baseSize().height();                          if (pChannelStrip) {
2073              y += pChannel->parentWidget()->frameGeometry().height();                          //  y += pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();
2074                                    y += pChannelStrip->parentWidget()->frameGeometry().height();
2075                            }
2076          }          }
2077      }      }
2078    
2079      // Add a new channel itema...      // Add a new channel itema...
2080      WFlags wflags = Qt::WStyle_Customize | Qt::WStyle_Tool | Qt::WStyle_Title | Qt::WStyle_NoBorder;      WFlags wflags = Qt::WStyle_Customize | Qt::WStyle_Tool | Qt::WStyle_Title | Qt::WStyle_NoBorder;
2081      pChannel = new qsamplerChannelStrip(m_pWorkspace, 0, wflags);      pChannelStrip = new qsamplerChannelStrip(m_pWorkspace, 0, wflags);
2082      pChannel->setMaxVolume(m_pOptions->iMaxVolume);      if (pChannelStrip == NULL)
2083      pChannel->setup(this, iChannelID);          return NULL;
2084      // We'll need a display font.  
2085      QFont font;      // Actual channel strip setup...
2086      if (m_pOptions && font.fromString(m_pOptions->sDisplayFont))      pChannelStrip->setup(pChannel);
2087          pChannel->setDisplayFont(font);          QObject::connect(pChannelStrip,
2088      // Track channel setup changes.                  SIGNAL(channelChanged(qsamplerChannelStrip *)),
2089      QObject::connect(pChannel, SIGNAL(channelChanged(qsamplerChannelStrip *)), this, SLOT(channelChanged(qsamplerChannelStrip *)));                  SLOT(channelStripChanged(qsamplerChannelStrip *)));
2090      // Before we show it up, may be we'll      // Set some initial aesthetic options...
2091      // better ask for some initial values?      if (m_pOptions) {
2092      if (bPrompt)          // Background display effect...
2093          pChannel->channelSetup();                pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
2094            // We'll need a display font.
2095            QFont font;
2096            if (font.fromString(m_pOptions->sDisplayFont))
2097                pChannelStrip->setDisplayFont(font);
2098            // Maximum allowed volume setting.
2099            pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
2100        }
2101    
2102      // Now we show up us to the world.      // Now we show up us to the world.
2103      pChannel->show();      pChannelStrip->show();
2104      // Only then, we'll auto-arrange...      // Only then, we'll auto-arrange...
2105      if (m_pOptions && m_pOptions->bAutoArrange) {      if (m_pOptions && m_pOptions->bAutoArrange) {
2106          int iWidth  = m_pWorkspace->width();          int iWidth  = m_pWorkspace->width();
2107      //  int iHeight = pChannel->height() + pChannel->parentWidget()->baseSize().height();      //  int iHeight = pChannel->height() + pChannel->parentWidget()->baseSize().height();
2108          int iHeight = pChannel->parentWidget()->frameGeometry().height();          int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();
2109          pChannel->parentWidget()->setGeometry(0, y, iWidth, iHeight);          pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);
2110      }      }
2111    
2112            // This is pretty new, so we'll watch for it closely.
2113            channelStripChanged(pChannelStrip);
2114    
2115        // Return our successful reference...
2116        return pChannelStrip;
2117  }  }
2118    
2119    
2120  // Retrieve the active channel strip.  // Retrieve the active channel strip.
2121  qsamplerChannelStrip *qsamplerMainForm::activeChannel (void)  qsamplerChannelStrip *qsamplerMainForm::activeChannelStrip (void)
2122  {  {
2123      return (qsamplerChannelStrip *) m_pWorkspace->activeWindow();      return (qsamplerChannelStrip *) m_pWorkspace->activeWindow();
2124  }  }
2125    
2126    
2127  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
2128  qsamplerChannelStrip *qsamplerMainForm::channelAt ( int iChannel )  qsamplerChannelStrip *qsamplerMainForm::channelStripAt ( int iChannel )
2129  {  {
2130      QWidgetList wlist = m_pWorkspace->windowList();      QWidgetList wlist = m_pWorkspace->windowList();
2131      if (wlist.isEmpty())      if (wlist.isEmpty())
2132          return 0;          return NULL;
2133    
2134      return (qsamplerChannelStrip *) wlist.at(iChannel);      return (qsamplerChannelStrip *) wlist.at(iChannel);
2135  }  }
2136    
2137    
2138    // Retrieve a channel strip by sampler channel id.
2139    qsamplerChannelStrip *qsamplerMainForm::channelStrip ( int iChannelID )
2140    {
2141            QWidgetList wlist = m_pWorkspace->windowList();
2142            if (wlist.isEmpty())
2143                    return NULL;
2144    
2145            for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2146                    qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
2147                    if (pChannelStrip) {
2148                            qsamplerChannel *pChannel = pChannelStrip->channel();
2149                            if (pChannel && pChannel->channelID() == iChannelID)
2150                                    return pChannelStrip;
2151                    }
2152            }
2153    
2154            // Not found.
2155            return NULL;
2156    }
2157    
2158    
2159  // Construct the windows menu.  // Construct the windows menu.
2160  void qsamplerMainForm::channelsMenuAboutToShow (void)  void qsamplerMainForm::channelsMenuAboutToShow (void)
2161  {  {
# Line 1313  void qsamplerMainForm::channelsMenuAbout Line 2167  void qsamplerMainForm::channelsMenuAbout
2167      if (!wlist.isEmpty()) {      if (!wlist.isEmpty()) {
2168          channelsMenu->insertSeparator();          channelsMenu->insertSeparator();
2169          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
2170              qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel);              qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
2171              int iItemID = channelsMenu->insertItem(pChannel->caption(), this, SLOT(channelsMenuActivated(int)));              if (pChannelStrip) {
2172              channelsMenu->setItemParameter(iItemID, iChannel);                  int iItemID = channelsMenu->insertItem(pChannelStrip->caption(), this, SLOT(channelsMenuActivated(int)));
2173              channelsMenu->setItemChecked(iItemID, activeChannel() == pChannel);                  channelsMenu->setItemParameter(iItemID, iChannel);
2174                    channelsMenu->setItemChecked(iItemID, activeChannelStrip() == pChannelStrip);
2175                }
2176          }          }
2177      }      }
2178  }  }
# Line 1325  void qsamplerMainForm::channelsMenuAbout Line 2181  void qsamplerMainForm::channelsMenuAbout
2181  // Windows menu activation slot  // Windows menu activation slot
2182  void qsamplerMainForm::channelsMenuActivated ( int iChannel )  void qsamplerMainForm::channelsMenuActivated ( int iChannel )
2183  {  {
2184      qsamplerChannelStrip *pChannel = channelAt(iChannel);      qsamplerChannelStrip *pChannelStrip = channelStripAt(iChannel);
2185      if (pChannel)      if (pChannelStrip)
2186          pChannel->showNormal();          pChannelStrip->showNormal();
2187      pChannel->setFocus();      pChannelStrip->setFocus();
2188  }  }
2189    
2190    
# Line 1366  void qsamplerMainForm::timerSlot (void) Line 2222  void qsamplerMainForm::timerSlot (void)
2222              }              }
2223          }          }
2224      }      }
2225        
2226          // Refresh each channel usage, on each period...          if (m_pClient) {
2227      if (m_pClient && m_pOptions->bAutoRefresh && m_pWorkspace->isUpdatesEnabled()) {                  // Update the channel information for each pending strip...
2228          m_iTimerSlot += QSAMPLER_TIMER_MSECS;                  if (m_changedStrips.count() > 0) {
2229          if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime)  {                          for (qsamplerChannelStrip *pChannelStrip = m_changedStrips.first();
2230              m_iTimerSlot = 0;                                          pChannelStrip; pChannelStrip = m_changedStrips.next()) {
2231              QWidgetList wlist = m_pWorkspace->windowList();                                  // If successfull, remove from pending list...
2232              for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {                                  if (pChannelStrip->updateChannelInfo())
2233                  qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel);                                          m_changedStrips.remove(pChannelStrip);
2234                  if (pChannel->isVisible())                          }
2235                      pChannel->updateChannelUsage();                  }
2236              }                  // Refresh each channel usage, on each period...
2237          }                  if (m_pOptions->bAutoRefresh) {
2238      }                          m_iTimerSlot += QSAMPLER_TIMER_MSECS;
2239                            if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime)  {
2240                                    m_iTimerSlot = 0;
2241                                    // Update the channel stream usage for each strip...
2242                                    QWidgetList wlist = m_pWorkspace->windowList();
2243                                    for (int iChannel = 0;
2244                                                    iChannel < (int) wlist.count(); iChannel++) {
2245                                            qsamplerChannelStrip *pChannelStrip
2246                                                    = (qsamplerChannelStrip *) wlist.at(iChannel);
2247                                            if (pChannelStrip && pChannelStrip->isVisible())
2248                                                    pChannelStrip->updateChannelUsage();
2249                                    }
2250                            }
2251                    }
2252            }
2253    
2254      // Register the next timer slot.      // Register the next timer slot.
2255      QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));      QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
# Line 1401  void qsamplerMainForm::startServer (void Line 2271  void qsamplerMainForm::startServer (void
2271    
2272      // Is the server process instance still here?      // Is the server process instance still here?
2273      if (m_pServer) {      if (m_pServer) {
2274          switch (QMessageBox::warning(this, tr("Warning"),          switch (QMessageBox::warning(this,
2275                            QSAMPLER_TITLE ": " + tr("Warning"),
2276              tr("Could not start the LinuxSampler server.\n\n"              tr("Could not start the LinuxSampler server.\n\n"
2277                 "Maybe it ss already started."),                 "Maybe it ss already started."),
2278              tr("Stop"), tr("Kill"), tr("Cancel"))) {              tr("Stop"), tr("Kill"), tr("Cancel"))) {
# Line 1422  void qsamplerMainForm::startServer (void Line 2293  void qsamplerMainForm::startServer (void
2293      m_pServer = new QProcess(this);      m_pServer = new QProcess(this);
2294    
2295      // Setup stdout/stderr capture...      // Setup stdout/stderr capture...
2296      //if (m_pOptions->bStdoutCapture) {          //      if (m_pOptions->bStdoutCapture) {
2297          m_pServer->setCommunication(QProcess::Stdout | QProcess::Stderr | QProcess::DupStderr);                  m_pServer->setCommunication(
2298          QObject::connect(m_pServer, SIGNAL(readyReadStdout()), this, SLOT(readServerStdout()));                          QProcess::Stdout | QProcess::Stderr | QProcess::DupStderr);
2299          QObject::connect(m_pServer, SIGNAL(readyReadStderr()), this, SLOT(readServerStdout()));                  QObject::connect(m_pServer,
2300      //}                          SIGNAL(readyReadStdout()),
2301      // The unforgiveable signal communication...                          SLOT(readServerStdout()));
2302      QObject::connect(m_pServer, SIGNAL(processExited()), this, SLOT(processServerExit()));                  QObject::connect(m_pServer,
2303                            SIGNAL(readyReadStderr()),
2304                            SLOT(readServerStdout()));
2305            //      }
2306            // The unforgiveable signal communication...
2307            QObject::connect(m_pServer,
2308                    SIGNAL(processExited()),
2309                    SLOT(processServerExit()));
2310    
2311      // Build process arguments...      // Build process arguments...
2312      m_pServer->setArguments(QStringList::split(' ', m_pOptions->sServerCmdLine));      m_pServer->setArguments(QStringList::split(' ', m_pOptions->sServerCmdLine));
# Line 1462  void qsamplerMainForm::stopServer (void) Line 2340  void qsamplerMainForm::stopServer (void)
2340      // And try to stop server.      // And try to stop server.
2341      if (m_pServer) {      if (m_pServer) {
2342          appendMessages(tr("Server is stopping..."));          appendMessages(tr("Server is stopping..."));
2343          if (m_pServer->isRunning()) {          if (m_pServer->isRunning())
2344              m_pServer->tryTerminate();              m_pServer->tryTerminate();
             return;  
         }  
2345       }       }
2346    
2347        // Give it some time to terminate gracefully and stabilize...
2348        QTime t;
2349        t.start();
2350        while (t.elapsed() < QSAMPLER_TIMER_MSECS)
2351            QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
2352    
2353       // Do final processing anyway.       // Do final processing anyway.
2354       processServerExit();       processServerExit();
2355  }  }
# Line 1509  void qsamplerMainForm::processServerExit Line 2391  void qsamplerMainForm::processServerExit
2391  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
2392  // qsamplerMainForm -- Client stuff.  // qsamplerMainForm -- Client stuff.
2393    
   
2394  // The LSCP client callback procedure.  // The LSCP client callback procedure.
2395  lscp_status_t qsampler_client_callback ( lscp_client_t *pClient, const char *pchBuffer, int cchBuffer, void *pvData )  lscp_status_t qsampler_client_callback ( lscp_client_t */*pClient*/, lscp_event_t event, const char *pchData, int cchData, void *pvData )
2396  {  {
2397      qsamplerMainForm *pMainForm = (qsamplerMainForm *) pvData;      qsamplerMainForm *pMainForm = (qsamplerMainForm *) pvData;
2398      if (pMainForm == NULL)      if (pMainForm == NULL)
2399          return LSCP_FAILED;          return LSCP_FAILED;
2400    
2401      char *pszBuffer = (char *) malloc(cchBuffer + 1);      // ATTN: DO NOT EVER call any GUI code here,
2402      if (pszBuffer == NULL)      // as this is run under some other thread context.
2403          return LSCP_FAILED;      // A custom event must be posted here...
2404        QApplication::postEvent(pMainForm, new qsamplerCustomEvent(event, pchData, cchData));
     memcpy(pszBuffer, pchBuffer, cchBuffer);  
     pszBuffer[cchBuffer] = (char) 0;  
     pMainForm->appendMessagesColor(pszBuffer, "#996699");  
     free(pszBuffer);  
2405    
2406      return LSCP_OK;      return LSCP_OK;
2407  }  }
# Line 1561  bool qsamplerMainForm::startClient (void Line 2438  bool qsamplerMainForm::startClient (void
2438      ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);      ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);
2439      appendMessages(tr("Client receive timeout is set to %1 msec.").arg(::lscp_client_get_timeout(m_pClient)));      appendMessages(tr("Client receive timeout is set to %1 msec.").arg(::lscp_client_get_timeout(m_pClient)));
2440    
2441            // Subscribe to channel info change notifications...
2442            if (::lscp_client_subscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO) != LSCP_OK)
2443                    appendMessagesClient("lscp_client_subscribe");
2444    
2445      // We may stop scheduling around.      // We may stop scheduling around.
2446      stopSchedule();      stopSchedule();
2447    
# Line 1570  bool qsamplerMainForm::startClient (void Line 2451  bool qsamplerMainForm::startClient (void
2451      // Log success here.      // Log success here.
2452      appendMessages(tr("Client connected."));      appendMessages(tr("Client connected."));
2453    
2454            // Hard-notify instrumnet and device configuration forms,
2455            // if visible, that we're ready...
2456            if (m_pInstrumentListForm)
2457                m_pInstrumentListForm->refreshInstruments();
2458            if (m_pDeviceForm)
2459                m_pDeviceForm->refreshDevices();
2460    
2461      // Is any session pending to be loaded?      // Is any session pending to be loaded?
2462      if (!m_pOptions->sSessionFile.isEmpty()) {      if (!m_pOptions->sSessionFile.isEmpty()) {
2463          // Just load the prabably startup session...          // Just load the prabably startup session...
# Line 1604  void qsamplerMainForm::stopClient (void) Line 2492  void qsamplerMainForm::stopClient (void)
2492      // channels from the back-end server.      // channels from the back-end server.
2493      m_iDirtyCount = 0;      m_iDirtyCount = 0;
2494      closeSession(false);      closeSession(false);
2495        
2496      // Close us as a client...      // Close us as a client...
2497      lscp_client_destroy(m_pClient);          ::lscp_client_unsubscribe(m_pClient, LSCP_EVENT_CHANNEL_INFO);
2498        ::lscp_client_destroy(m_pClient);
2499      m_pClient = NULL;      m_pClient = NULL;
2500    
2501            // Hard-notify instrumnet and device configuration forms,
2502            // if visible, that we're running out...
2503            if (m_pInstrumentListForm)
2504                m_pInstrumentListForm->refreshInstruments();
2505            if (m_pDeviceForm)
2506                m_pDeviceForm->refreshDevices();
2507    
2508      // Log final here.      // Log final here.
2509      appendMessages(tr("Client disconnected."));      appendMessages(tr("Client disconnected."));
2510    

Legend:
Removed from v.119  
changed lines
  Added in v.1367

  ViewVC Help
Powered by ViewVC