/[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 122 by capela, Sat Jun 12 13:21:35 2004 UTC revision 484 by capela, Tue Mar 22 12:55:29 2005 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-2005, 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 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>
# Line 36  Line 37 
37    
38  #include "qsamplerAbout.h"  #include "qsamplerAbout.h"
39  #include "qsamplerOptions.h"  #include "qsamplerOptions.h"
40    #include "qsamplerChannel.h"
41  #include "qsamplerMessages.h"  #include "qsamplerMessages.h"
42    
43  #include "qsamplerChannelStrip.h"  #include "qsamplerChannelStrip.h"
44    
45    #include "qsamplerDeviceForm.h"
46  #include "qsamplerOptionsForm.h"  #include "qsamplerOptionsForm.h"
47    
48  #include "config.h"  #include "config.h"
49    
50    #ifdef HAVE_SIGNAL_H
51    #include <signal.h>
52    #endif
53    
54  // Timer constant stuff.  // Timer constant stuff.
55  #define QSAMPLER_TIMER_MSECS    200  #define QSAMPLER_TIMER_MSECS    200
# Line 54  Line 61 
61  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.  #define QSAMPLER_STATUS_SESSION 3       // Current session modification state.
62    
63    
64    // All winsock apps needs this.
65  #if defined(WIN32)  #if defined(WIN32)
66  static WSADATA _wsaData;  static WSADATA _wsaData;
67  #endif  #endif
68    
69    
70    //-------------------------------------------------------------------------
71    // qsamplerCustomEvent -- specialty for callback comunication.
72    
73    #define QSAMPLER_CUSTOM_EVENT   1000
74    
75    class qsamplerCustomEvent : public QCustomEvent
76    {
77    public:
78    
79        // Constructor.
80        qsamplerCustomEvent(lscp_event_t event, const char *pchData, int cchData)
81            : QCustomEvent(QSAMPLER_CUSTOM_EVENT)
82        {
83            m_event = event;
84            m_data.setLatin1(pchData, cchData);
85        }
86    
87        // Accessors.
88        lscp_event_t event() { return m_event; }
89        QString&     data()  { return m_data;  }
90    
91    private:
92    
93        // The proper event type.
94        lscp_event_t m_event;
95        // The event data as a string.
96        QString      m_data;
97    };
98    
99    
100  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
101  // qsamplerMainForm -- Main window form implementation.  // qsamplerMainForm -- Main window form implementation.
102    
# Line 68  void qsamplerMainForm::init (void) Line 107  void qsamplerMainForm::init (void)
107      m_pOptions = NULL;      m_pOptions = NULL;
108    
109      // All child forms are to be created later, not earlier than setup.      // All child forms are to be created later, not earlier than setup.
110      m_pMessages = NULL;      m_pMessages   = NULL;
111        m_pDeviceForm = NULL;
112    
113      // We'll start clean.      // We'll start clean.
114      m_iUntitled = 0;      m_iUntitled   = 0;
115      m_iDirtyCount = 0;      m_iDirtyCount = 0;
116    
117      m_pServer = NULL;      m_pServer = NULL;
# Line 82  void qsamplerMainForm::init (void) Line 122  void qsamplerMainForm::init (void)
122    
123      m_iTimerSlot = 0;      m_iTimerSlot = 0;
124    
125    #ifdef HAVE_SIGNAL_H
126            // Set to ignore any fatal "Broken pipe" signals.
127            ::signal(SIGPIPE, SIG_IGN);
128    #endif
129    
130      // Make it an MDI workspace.      // Make it an MDI workspace.
131      m_pWorkspace = new QWorkspace(this);      m_pWorkspace = new QWorkspace(this);
132      m_pWorkspace->setScrollBarsEnabled(true);      m_pWorkspace->setScrollBarsEnabled(true);
# Line 96  void qsamplerMainForm::init (void) Line 141  void qsamplerMainForm::init (void)
141      pLabel = new QLabel(tr("Connected"), this);      pLabel = new QLabel(tr("Connected"), this);
142      pLabel->setAlignment(Qt::AlignLeft);      pLabel->setAlignment(Qt::AlignLeft);
143      pLabel->setMinimumSize(pLabel->sizeHint());      pLabel->setMinimumSize(pLabel->sizeHint());
144      m_status[QSAMPLER_STATUS_CLIENT] = pLabel;      m_statusItem[QSAMPLER_STATUS_CLIENT] = pLabel;
145      statusBar()->addWidget(pLabel);      statusBar()->addWidget(pLabel);
146      // Server address.      // Server address.
147      pLabel = new QLabel(this);      pLabel = new QLabel(this);
148      pLabel->setAlignment(Qt::AlignLeft);      pLabel->setAlignment(Qt::AlignLeft);
149      m_status[QSAMPLER_STATUS_SERVER] = pLabel;      m_statusItem[QSAMPLER_STATUS_SERVER] = pLabel;
150      statusBar()->addWidget(pLabel, 1);      statusBar()->addWidget(pLabel, 1);
151      // Channel title.      // Channel title.
152      pLabel = new QLabel(this);      pLabel = new QLabel(this);
153      pLabel->setAlignment(Qt::AlignLeft);      pLabel->setAlignment(Qt::AlignLeft);
154      m_status[QSAMPLER_STATUS_CHANNEL] = pLabel;      m_statusItem[QSAMPLER_STATUS_CHANNEL] = pLabel;
155      statusBar()->addWidget(pLabel, 2);      statusBar()->addWidget(pLabel, 2);
156      // Session modification status.      // Session modification status.
157      pLabel = new QLabel(tr("MOD"), this);      pLabel = new QLabel(tr("MOD"), this);
158      pLabel->setAlignment(Qt::AlignHCenter);      pLabel->setAlignment(Qt::AlignHCenter);
159      pLabel->setMinimumSize(pLabel->sizeHint());      pLabel->setMinimumSize(pLabel->sizeHint());
160      m_status[QSAMPLER_STATUS_SESSION] = pLabel;      m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;
161      statusBar()->addWidget(pLabel);      statusBar()->addWidget(pLabel);
162    
163      // Create the recent files sub-menu.      // Create the recent files sub-menu.
# Line 131  void qsamplerMainForm::destroy (void) Line 176  void qsamplerMainForm::destroy (void)
176  {  {
177      // Do final processing anyway.      // Do final processing anyway.
178      processServerExit();      processServerExit();
179        
180      // Delete recentfiles menu.  #if defined(WIN32)
181      if (m_pRecentFilesMenu)      WSACleanup();
182          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];  
183    
184      // Finally drop any widgets around...      // Finally drop any widgets around...
185        if (m_pDeviceForm)
186            delete m_pDeviceForm;
187      if (m_pMessages)      if (m_pMessages)
188          delete m_pMessages;          delete m_pMessages;
189      if (m_pWorkspace)      if (m_pWorkspace)
190          delete m_pWorkspace;          delete m_pWorkspace;
191    
192  #if defined(WIN32)      // Delete status item labels one by one.
193      WSACleanup();      if (m_statusItem[QSAMPLER_STATUS_CLIENT])
194  #endif          delete m_statusItem[QSAMPLER_STATUS_CLIENT];
195        if (m_statusItem[QSAMPLER_STATUS_SERVER])
196            delete m_statusItem[QSAMPLER_STATUS_SERVER];
197        if (m_statusItem[QSAMPLER_STATUS_CHANNEL])
198            delete m_statusItem[QSAMPLER_STATUS_CHANNEL];
199        if (m_statusItem[QSAMPLER_STATUS_SESSION])
200            delete m_statusItem[QSAMPLER_STATUS_SESSION];
201    
202        // Delete recentfiles menu.
203        if (m_pRecentFilesMenu)
204            delete m_pRecentFilesMenu;
205  }  }
206    
207    
# Line 163  void qsamplerMainForm::setup ( qsamplerO Line 211  void qsamplerMainForm::setup ( qsamplerO
211      // We got options?      // We got options?
212      m_pOptions = pOptions;      m_pOptions = pOptions;
213    
214        // What style do we create these forms?
215        WFlags wflags = Qt::WType_TopLevel;
216        if (m_pOptions->bKeepOnTop)
217            wflags |= Qt::WStyle_Tool;
218      // Some child forms are to be created right now.      // Some child forms are to be created right now.
219      m_pMessages = new qsamplerMessages(this);      m_pMessages = new qsamplerMessages(this);
220        m_pDeviceForm = new qsamplerDeviceForm(this, 0, wflags);
221      // Set message defaults...      // Set message defaults...
222      updateMessagesFont();      updateMessagesFont();
223      updateMessagesLimit();      updateMessagesLimit();
# Line 193  void qsamplerMainForm::setup ( qsamplerO Line 246  void qsamplerMainForm::setup ( qsamplerO
246          QTextIStream istr(&sDockables);          QTextIStream istr(&sDockables);
247          istr >> *this;          istr >> *this;
248      }      }
249      // Try to restore old window positioning.      // Try to restore old window positioning and initial visibility.
250      m_pOptions->loadWidgetGeometry(this);      m_pOptions->loadWidgetGeometry(this);
251        m_pOptions->loadWidgetGeometry(m_pDeviceForm);
252    
253      // Final startup stabilization...      // Final startup stabilization...
254      updateRecentFilesMenu();      updateRecentFilesMenu();
# Line 232  bool qsamplerMainForm::queryClose (void) Line 286  bool qsamplerMainForm::queryClose (void)
286              QTextOStream ostr(&sDockables);              QTextOStream ostr(&sDockables);
287              ostr << *this;              ostr << *this;
288              m_pOptions->settings().writeEntry("/Layout/DockWindows", sDockables);              m_pOptions->settings().writeEntry("/Layout/DockWindows", sDockables);
289              // And the main windows state.              // And the children, and the main windows state,.
290                    m_pOptions->saveWidgetGeometry(m_pDeviceForm);
291              m_pOptions->saveWidgetGeometry(this);              m_pOptions->saveWidgetGeometry(this);
292                    // Close popup widgets.
293                    if (m_pDeviceForm)
294                        m_pDeviceForm->close();
295              // Stop client and/or server, gracefully.              // Stop client and/or server, gracefully.
296              stopServer();              stopServer();
297          }          }
# Line 252  void qsamplerMainForm::closeEvent ( QClo Line 310  void qsamplerMainForm::closeEvent ( QClo
310  }  }
311    
312    
313  void qsamplerMainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )  // Drag'n'drop file handler.
314    bool qsamplerMainForm::decodeDragFiles ( const QMimeSource *pEvent, QStringList& files )
315  {  {
316      bool bAccept = false;      bool bDecode = false;
317    
318      if (QTextDrag::canDecode(pDragEnterEvent)) {      if (QTextDrag::canDecode(pEvent)) {
319          QString sUrl;          QString sText;
320          if (QTextDrag::decode(pDragEnterEvent, sUrl) && m_pClient)          bDecode = QTextDrag::decode(pEvent, sText);
321              bAccept = QFileInfo(QUrl(sUrl).path()).exists();          if (bDecode) {
322                files = QStringList::split('\n', sText);
323                for (QStringList::Iterator iter = files.begin(); iter != files.end(); iter++)
324                    *iter = QUrl((*iter).stripWhiteSpace().replace(QRegExp("^file:"), QString::null)).path();
325            }
326      }      }
327    
328      pDragEnterEvent->accept(bAccept);      return bDecode;
329    }
330    
331    
332    // Window drag-n-drop event handlers.
333    void qsamplerMainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )
334    {
335            QStringList files;
336            pDragEnterEvent->accept(decodeDragFiles(pDragEnterEvent, files));
337  }  }
338    
339    
340  void qsamplerMainForm::dropEvent ( QDropEvent* pDropEvent )  void qsamplerMainForm::dropEvent ( QDropEvent* pDropEvent )
341  {  {
342      if (QTextDrag::canDecode(pDropEvent)) {      QStringList files;
343          QString sUrl;  
344          if (QTextDrag::decode(pDropEvent, sUrl) && closeSession(true))      if (!decodeDragFiles(pDropEvent, files))
345              loadSessionFile(QUrl(sUrl).path());          return;
346    
347        for (QStringList::Iterator iter = files.begin(); iter != files.end(); iter++) {
348                    const QString& sPath = *iter;
349                    if (qsamplerChannel::isInstrumentFile(sPath)) {
350                            // Try to create a new channel from instrument file...
351                        qsamplerChannel *pChannel = new qsamplerChannel(this);
352                        if (pChannel == NULL)
353                            return;
354                            // Start setting the instrument filename...
355                            pChannel->setInstrument(sPath, 0);
356                        // Before we show it up, may be we'll
357                        // better ask for some initial values?
358                        if (!pChannel->channelSetup(this)) {
359                            delete pChannel;
360                            return;
361                        }
362                        // Finally, give it to a new channel strip...
363                            if (!createChannelStrip(pChannel)) {
364                            delete pChannel;
365                            return;
366                            }
367                        // Make that an overall update.
368                        m_iDirtyCount++;
369                        stabilizeForm();
370                    }   // Otherwise, load an usual session file (LSCP script)...
371                    else if (closeSession(true))
372                            loadSessionFile(sPath);
373                    // Make it look responsive...:)
374                    QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
375            }
376    }
377    
378    
379    // Custome event handler.
380    void qsamplerMainForm::customEvent ( QCustomEvent *pCustomEvent )
381    {
382        // For the time being, just pump it to messages.
383        if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {
384            qsamplerCustomEvent *pEvent = (qsamplerCustomEvent *) pCustomEvent;
385            appendMessagesColor(tr("Notify event: %1 data: %2")
386                .arg(::lscp_event_to_text(pEvent->event()))
387                .arg(pEvent->data()), "#996699");
388      }      }
389  }  }
390    
391    
392    // Context menu event handler.
393    void qsamplerMainForm::contextMenuEvent( QContextMenuEvent *pEvent )
394    {
395        stabilizeForm();
396        
397        editMenu->exec(pEvent->globalPos());
398    }
399    
400    
401  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
402  // qsamplerMainForm -- Brainless public property accessors.  // qsamplerMainForm -- Brainless public property accessors.
403    
# Line 315  bool qsamplerMainForm::newSession (void) Line 437  bool qsamplerMainForm::newSession (void)
437      if (!closeSession(true))      if (!closeSession(true))
438          return false;          return false;
439    
440            // Give us what the server has, right now...
441            updateSession();
442    
443      // Ok increment untitled count.      // Ok increment untitled count.
444      m_iUntitled++;      m_iUntitled++;
445    
# Line 428  bool qsamplerMainForm::closeSession ( bo Line 553  bool qsamplerMainForm::closeSession ( bo
553          m_pWorkspace->setUpdatesEnabled(false);          m_pWorkspace->setUpdatesEnabled(false);
554          QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
555          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
556              qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel);              qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
557              if (bForce && ::lscp_remove_channel(m_pClient, pChannel->channelID()) != LSCP_OK)              if (pChannelStrip) {
558                  appendMessagesClient("lscp_remove_channel");                  qsamplerChannel *pChannel = pChannelStrip->channel();
559              delete pChannel;                  if (bForce && pChannel)
560                        pChannel->removeChannel();
561                    delete pChannelStrip;
562                }
563          }          }
564          m_pWorkspace->setUpdatesEnabled(true);          m_pWorkspace->setUpdatesEnabled(true);
565          // We're now clean, for sure.          // We're now clean, for sure.
# Line 479  bool qsamplerMainForm::loadSessionFile ( Line 607  bool qsamplerMainForm::loadSessionFile (
607      // Ok. we've read it.      // Ok. we've read it.
608      file.close();      file.close();
609    
610      // Have we any errors?          // Now we'll try to create (update) the whole GUI session.
611      if (iErrors > 0)          updateSession();
         appendMessagesError(tr("Some setttings could not be loaded\nfrom \"%1\" session file.\n\nSorry.").arg(sFilename));  
612    
613      // Now we'll try to create the whole GUI session.          // Have we any errors?
614      int iChannels = ::lscp_get_channels(m_pClient);          if (iErrors > 0)
615      if (iChannels < 0) {                  appendMessagesError(tr("Session loaded with errors\nfrom \"%1\".\n\nSorry.").arg(sFilename));
         appendMessagesClient("lscp_get_channels");  
         appendMessagesError(tr("Could not get current number of channels.\n\nSorry."));  
     }  
       
     // 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);  
616    
617      // Save as default session directory.      // Save as default session directory.
618      if (m_pOptions)      if (m_pOptions)
619          m_pOptions->sSessionDir = QFileInfo(sFilename).dirPath(true);          m_pOptions->sSessionDir = QFileInfo(sFilename).dirPath(true);
620      // We're not dirty anymore.          // We're not dirty anymore, if loaded without errors,
621      m_iDirtyCount = 0;          m_iDirtyCount = iErrors;
622      // Stabilize form...      // Stabilize form...
623      m_sFilename = sFilename;      m_sFilename = sFilename;
624      updateRecentFiles(sFilename);      updateRecentFiles(sFilename);
625      appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));      appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));
626        
627        // Make that an overall update.
628      stabilizeForm();      stabilizeForm();
629      return true;      return true;
630  }  }
# Line 523  bool qsamplerMainForm::saveSessionFile ( Line 641  bool qsamplerMainForm::saveSessionFile (
641      }      }
642    
643      // Write the file.      // Write the file.
644      int iErrors = 0;      int  iErrors = 0;
645      QTextStream ts(&file);      QTextStream ts(&file);
646      ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;      ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;
647      ts << "# " << tr("Version")      ts << "# " << tr("Version")
# Line 534  bool qsamplerMainForm::saveSessionFile ( Line 652  bool qsamplerMainForm::saveSessionFile (
652      ts << "# " << tr("File")      ts << "# " << tr("File")
653         << ": " << QFileInfo(sFilename).fileName() << endl;         << ": " << QFileInfo(sFilename).fileName() << endl;
654      ts << "# " << tr("Date")      ts << "# " << tr("Date")
655         << ": " << QDate::currentDate().toString("MMMM dd yyyy")         << ": " << QDate::currentDate().toString("MMM dd yyyy")
656         << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;         << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;
657      ts << "#"  << endl;      ts << "#"  << endl;
658      ts << endl;      ts << endl;
659            // It is assumed that this new kind of device+session file
660            // will be loaded from a complete
661            int *piDeviceIDs;
662            int  iDevice;
663            ts << "RESET" << endl;
664            // Audio device mapping.
665            QMap<int, int> audioDeviceMap;
666            piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Audio);
667            for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
668                    ts << endl;
669                    qsamplerDevice device(this, qsamplerDevice::Audio, piDeviceIDs[iDevice]);
670                    // Audio device specification...
671                    ts << "# " << device.deviceTypeName() << " " << device.driverName()
672                       << " " << tr("Device") << " " << iDevice << endl;
673                    ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();
674                    qsamplerDeviceParamMap::ConstIterator deviceParam;
675                    for (deviceParam = device.params().begin();
676                                    deviceParam != device.params().end();
677                                            ++deviceParam) {
678                            const qsamplerDeviceParam& param = deviceParam.data();
679                            if (param.value.isEmpty()) ts << "# ";
680                            ts << " " << deviceParam.key() << "='" << param.value << "'";
681                    }
682                    ts << endl;
683                    // Audio channel parameters...
684                    int iPort = 0;
685                    for (qsamplerDevicePort *pPort = device.ports().first();
686                                    pPort;
687                                            pPort = device.ports().next(), ++iPort) {
688                            qsamplerDeviceParamMap::ConstIterator portParam;
689                            for (portParam = pPort->params().begin();
690                                            portParam != pPort->params().end();
691                                                    ++portParam) {
692                                    const qsamplerDeviceParam& param = portParam.data();
693                                    if (param.fix || param.value.isEmpty()) ts << "# ";
694                                    ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice
695                                       << " " << iPort << " " << portParam.key()
696                                       << "='" << param.value << "'" << endl;
697                            }
698                    }
699                    // Audio device index/id mapping.
700                    audioDeviceMap[device.deviceID()] = iDevice;
701            // Try to keep it snappy :)
702            QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
703            }
704            // MIDI device mapping.
705            QMap<int, int> midiDeviceMap;
706            piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Midi);
707            for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
708                    ts << endl;
709                    qsamplerDevice device(this, qsamplerDevice::Midi, piDeviceIDs[iDevice]);
710                    // MIDI device specification...
711            ts << "# " << device.deviceTypeName() << " " << device.driverName()
712                       << " " << tr("Device") << " " << iDevice << endl;
713                    ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();
714                    qsamplerDeviceParamMap::ConstIterator deviceParam;
715                    for (deviceParam = device.params().begin();
716                                    deviceParam != device.params().end();
717                                            ++deviceParam) {
718                            const qsamplerDeviceParam& param = deviceParam.data();
719                            if (param.value.isEmpty()) ts << "# ";
720                            ts << " " << deviceParam.key() << "='" << param.value << "'";
721                    }
722                    ts << endl;
723                    // MIDI port parameters...
724                    int iPort = 0;
725                    for (qsamplerDevicePort *pPort = device.ports().first();
726                                    pPort;
727                                            pPort = device.ports().next(), ++iPort) {
728                            qsamplerDeviceParamMap::ConstIterator portParam;
729                            for (portParam = pPort->params().begin();
730                                            portParam != pPort->params().end();
731                                                    ++portParam) {
732                                    const qsamplerDeviceParam& param = portParam.data();
733                                    if (param.fix || param.value.isEmpty()) ts << "# ";
734                                    ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice
735                                       << " " << iPort << " " << portParam.key()
736                                       << "='" << param.value << "'" << endl;
737                            }
738                    }
739                    // MIDI device index/id mapping.
740                    midiDeviceMap[device.deviceID()] = iDevice;
741            // Try to keep it snappy :)
742            QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
743            }
744            ts << endl;
745            // Sampler channel mapping.
746      QWidgetList wlist = m_pWorkspace->windowList();      QWidgetList wlist = m_pWorkspace->windowList();
747      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
748          qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel);          qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
749          int iChannelID = pChannel->channelID();          if (pChannelStrip) {
750          ts << "# " << pChannel->caption() << endl;              qsamplerChannel *pChannel = pChannelStrip->channel();
751          ts << "ADD CHANNEL" << endl;              if (pChannel) {
752          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannelID << " " << pChannel->audioDriver() << endl;                  ts << "# " << tr("Channel") << " " << iChannel << endl;
753          ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannelID << " " << pChannel->midiDriver() << endl;                  ts << "ADD CHANNEL" << endl;
754      //  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannelID << " " << pChannel->midiPort() << endl;                  if (audioDeviceMap.isEmpty()) {
755          ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannelID << " " << pChannel->midiChannel() << endl;                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel
756          ts << "LOAD ENGINE " << pChannel->engineName() << " " << iChannelID << endl;                                              << " " << pChannel->audioDriver() << endl;
757          ts << "LOAD INSTRUMENT " << pChannel->instrumentFile() << " " << pChannel->instrumentNr() << " " << iChannelID << endl;                              } else {
758          ts << "SET CHANNEL VOLUME " << iChannelID << " " << pChannel->volume() << endl;                          ts << "SET CHANNEL AUDIO_OUTPUT_DEVICE " << iChannel
759          ts << endl;                                             << " " << audioDeviceMap[pChannel->audioDevice()] << endl;
760                                    }
761                    if (midiDeviceMap.isEmpty()) {
762                            ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannel
763                                           << " " << pChannel->midiDriver() << endl;
764                                } else {
765                            ts << "SET CHANNEL MIDI_INPUT_DEVICE " << iChannel
766                                               << " " << midiDeviceMap[pChannel->midiDevice()] << endl;
767                                }
768                    ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel
769                                   << " " << pChannel->midiPort() << endl;
770                    ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";
771                    if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
772                        ts << "ALL";
773                    else
774                        ts << pChannel->midiChannel();
775                    ts << endl;
776                    ts << "LOAD ENGINE " << pChannel->engineName() << " " << iChannel << endl;
777                    ts << "LOAD INSTRUMENT NON_MODAL '" << pChannel->instrumentFile() << "' " << pChannel->instrumentNr() << " " << iChannel << endl;
778                    ts << "SET CHANNEL VOLUME " << iChannel << " " << pChannel->volume() << endl;
779                    ts << endl;
780                }
781            }
782          // Try to keep it snappy :)          // Try to keep it snappy :)
783          QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);          QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
784      }      }
# Line 577  bool qsamplerMainForm::saveSessionFile ( Line 804  bool qsamplerMainForm::saveSessionFile (
804  }  }
805    
806    
807    // Session change receiver slot.
808    void qsamplerMainForm::sessionDirty (void)
809    {
810        // Just mark the dirty form.
811        m_iDirtyCount++;
812        // and update the form status...
813        stabilizeForm();
814    }
815    
816    
817  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
818  // qsamplerMainForm -- File Action slots.  // qsamplerMainForm -- File Action slots.
819    
# Line 623  void qsamplerMainForm::fileSaveAs (void) Line 860  void qsamplerMainForm::fileSaveAs (void)
860  }  }
861    
862    
863    // Reset the sampler instance.
864    void qsamplerMainForm::fileReset (void)
865    {
866        if (m_pClient == NULL)
867            return;
868    
869        // Ask user whether he/she want's an internal sampler reset...
870        if (QMessageBox::warning(this, tr("Warning"),
871            tr("Resetting the sampler instance will close\n"
872               "all device and channel configurations.\n\n"
873               "Please note that this operation may cause\n"
874               "temporary MIDI and Audio disruption\n\n"
875               "Do you want to reset the sampler engine now?"),
876            tr("Reset"), tr("Cancel")) > 0)
877            return;
878    
879        // Just do the reset, after closing down current session...
880        if (closeSession(true) && ::lscp_reset_sampler(m_pClient) != LSCP_OK) {
881            appendMessagesClient("lscp_reset_sampler");
882            appendMessagesError(tr("Could not reset sampler instance.\n\nSorry."));
883            return;
884        }
885    
886        // Log this.
887        appendMessages(tr("Sampler reset."));
888    
889            // Make it a new session...
890            newSession();
891    }
892    
893    
894  // Restart the client/server instance.  // Restart the client/server instance.
895  void qsamplerMainForm::fileRestart (void)  void qsamplerMainForm::fileRestart (void)
896  {  {
# Line 670  void qsamplerMainForm::editAddChannel (v Line 938  void qsamplerMainForm::editAddChannel (v
938      if (m_pClient == NULL)      if (m_pClient == NULL)
939          return;          return;
940    
941      // Create the new sampler channel.      // Just create the channel instance...
942      int iChannelID = ::lscp_add_channel(m_pClient);      qsamplerChannel *pChannel = new qsamplerChannel(this);
943      if (iChannelID < 0) {      if (pChannel == NULL)
         appendMessagesClient("lscp_add_channel");  
         appendMessagesError(tr("Could not create the new channel.\n\nSorry."));  
944          return;          return;
     }  
   
     // Log this happening.  
     appendMessages(tr("Channel %1 created.").arg(iChannelID));  
945    
946      // Just create the channel strip with given id.      // Before we show it up, may be we'll
947      createChannel(iChannelID, true);      // better ask for some initial values?
948        if (!pChannel->channelSetup(this)) {
949            delete pChannel;
950            return;
951        }
952        
953        // And give it to the strip (will own the channel instance, if successful).
954        if (!createChannelStrip(pChannel)) {
955            delete pChannel;
956            return;
957        }
958    
959      // We'll be dirty, for sure...      // Make that an overall update.
960      m_iDirtyCount++;      m_iDirtyCount++;
     // Stabilize form anyway.  
961      stabilizeForm();      stabilizeForm();
962  }  }
963    
# Line 697  void qsamplerMainForm::editRemoveChannel Line 968  void qsamplerMainForm::editRemoveChannel
968      if (m_pClient == NULL)      if (m_pClient == NULL)
969          return;          return;
970    
971      qsamplerChannelStrip *pChannel = activeChannel();      qsamplerChannelStrip *pChannelStrip = activeChannelStrip();
972        if (pChannelStrip == NULL)
973            return;
974            
975        qsamplerChannel *pChannel = pChannelStrip->channel();
976      if (pChannel == NULL)      if (pChannel == NULL)
977          return;          return;
978    
# Line 707  void qsamplerMainForm::editRemoveChannel Line 982  void qsamplerMainForm::editRemoveChannel
982              tr("About to remove channel:\n\n"              tr("About to remove channel:\n\n"
983                 "%1\n\n"                 "%1\n\n"
984                 "Are you sure?")                 "Are you sure?")
985                 .arg(pChannel->caption()),                 .arg(pChannelStrip->caption()),
986              tr("OK"), tr("Cancel")) > 0)              tr("OK"), tr("Cancel")) > 0)
987              return;              return;
988      }      }
989    
990      // Remove the existing sampler channel.      // Remove the existing sampler channel.
991      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."));  
992          return;          return;
     }  
993    
     // Log this happening.  
     appendMessages(tr("Channel %1 removed.").arg(pChannel->channelID()));  
       
994      // Just delete the channel strip.      // Just delete the channel strip.
995      delete pChannel;      delete pChannelStrip;
996        
997      // Do we auto-arrange?      // Do we auto-arrange?
998      if (m_pOptions && m_pOptions->bAutoArrange)      if (m_pOptions && m_pOptions->bAutoArrange)
999          channelsArrange();          channelsArrange();
# Line 740  void qsamplerMainForm::editSetupChannel Line 1010  void qsamplerMainForm::editSetupChannel
1010      if (m_pClient == NULL)      if (m_pClient == NULL)
1011          return;          return;
1012    
1013      qsamplerChannelStrip *pChannel = activeChannel();      qsamplerChannelStrip *pChannelStrip = activeChannelStrip();
1014      if (pChannel == NULL)      if (pChannelStrip == NULL)
1015          return;          return;
1016    
1017      // Just invoque the channel strip procedure.      // Just invoque the channel strip procedure.
1018      pChannel->channelSetup();      pChannelStrip->channelSetup();
1019  }  }
1020    
1021    
# Line 755  void qsamplerMainForm::editResetChannel Line 1025  void qsamplerMainForm::editResetChannel
1025      if (m_pClient == NULL)      if (m_pClient == NULL)
1026          return;          return;
1027    
1028      qsamplerChannelStrip *pChannel = activeChannel();      qsamplerChannelStrip *pChannelStrip = activeChannelStrip();
1029      if (pChannel == NULL)      if (pChannelStrip == NULL)
1030          return;          return;
1031    
1032      // Remove the existing sampler channel.      // Just invoque the channel strip procedure.
1033      if (::lscp_reset_channel(m_pClient, pChannel->channelID()) != LSCP_OK) {      pChannelStrip->channelReset();
1034          appendMessagesClient("lscp_reset_channel");  }
         appendMessagesError(tr("Could not reset channel.\n\nSorry."));  
         return;  
     }  
1035    
     // Log this.  
     appendMessages(tr("Channel %1 reset.").arg(pChannel->channelID()));  
1036    
1037      // Refresh channel strip info.  // Reset all sampler channels.
1038      pChannel->updateChannelInfo();  void qsamplerMainForm::editResetAllChannels (void)
1039    {
1040        if (m_pClient == NULL)
1041            return;
1042    
1043        // Invoque the channel strip procedure,
1044            // for all channels out there...
1045        m_pWorkspace->setUpdatesEnabled(false);
1046        QWidgetList wlist = m_pWorkspace->windowList();
1047        for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1048            qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1049            if (pChannelStrip)
1050                    pChannelStrip->channelReset();
1051        }
1052        m_pWorkspace->setUpdatesEnabled(true);
1053  }  }
1054    
1055    
# Line 822  void qsamplerMainForm::viewMessages ( bo Line 1101  void qsamplerMainForm::viewMessages ( bo
1101  }  }
1102    
1103    
1104    // Show/hide the device configurator form.
1105    void qsamplerMainForm::viewDevices (void)
1106    {
1107        if (m_pOptions == NULL)
1108            return;
1109    
1110        if (m_pDeviceForm) {
1111            m_pOptions->saveWidgetGeometry(m_pDeviceForm);
1112                    m_pDeviceForm->setClient(m_pClient);
1113            if (m_pDeviceForm->isVisible()) {
1114                m_pDeviceForm->hide();
1115            } else {
1116                m_pDeviceForm->show();
1117                m_pDeviceForm->raise();
1118                m_pDeviceForm->setActiveWindow();
1119            }
1120        }
1121    }
1122    
1123    
1124  // Show options dialog.  // Show options dialog.
1125  void qsamplerMainForm::viewOptions (void)  void qsamplerMainForm::viewOptions (void)
1126  {  {
# Line 831  void qsamplerMainForm::viewOptions (void Line 1130  void qsamplerMainForm::viewOptions (void
1130      qsamplerOptionsForm *pOptionsForm = new qsamplerOptionsForm(this);      qsamplerOptionsForm *pOptionsForm = new qsamplerOptionsForm(this);
1131      if (pOptionsForm) {      if (pOptionsForm) {
1132          // Check out some initial nullities(tm)...          // Check out some initial nullities(tm)...
1133          qsamplerChannelStrip *pChannel = activeChannel();          qsamplerChannelStrip *pChannelStrip = activeChannelStrip();
1134          if (m_pOptions->sDisplayFont.isEmpty() && pChannel)          if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)
1135              m_pOptions->sDisplayFont = pChannel->displayFont().toString();              m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();
1136          if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)          if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)
1137              m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();              m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
1138          // To track down deferred or immediate changes.          // To track down deferred or immediate changes.
# Line 843  void qsamplerMainForm::viewOptions (void Line 1142  void qsamplerMainForm::viewOptions (void
1142          bool    bOldServerStart     = m_pOptions->bServerStart;          bool    bOldServerStart     = m_pOptions->bServerStart;
1143          QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;          QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;
1144          QString sOldDisplayFont     = m_pOptions->sDisplayFont;          QString sOldDisplayFont     = m_pOptions->sDisplayFont;
1145            bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;
1146          int     iOldMaxVolume       = m_pOptions->iMaxVolume;          int     iOldMaxVolume       = m_pOptions->iMaxVolume;
1147          QString sOldMessagesFont    = m_pOptions->sMessagesFont;          QString sOldMessagesFont    = m_pOptions->sMessagesFont;
1148            bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;
1149          bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;          bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;
1150          int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;          int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;
1151          int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;          int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;
1152          bool    bOldCompletePath    = m_pOptions->bCompletePath;          bool    bOldCompletePath    = m_pOptions->bCompletePath;
1153            bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;
1154          int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;          int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;
1155          // Load the current setup settings.          // Load the current setup settings.
1156          pOptionsForm->setup(m_pOptions);          pOptionsForm->setup(m_pOptions);
# Line 856  void qsamplerMainForm::viewOptions (void Line 1158  void qsamplerMainForm::viewOptions (void
1158          if (pOptionsForm->exec()) {          if (pOptionsForm->exec()) {
1159              // Warn if something will be only effective on next run.              // Warn if something will be only effective on next run.
1160              if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||              if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1161                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture)) {                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||
1162                    ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||
1163                    (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {
1164                  QMessageBox::information(this, tr("Information"),                  QMessageBox::information(this, tr("Information"),
1165                      tr("Some settings may be only effective\n"                      tr("Some settings may be only effective\n"
1166                         "next time you start this program."), tr("OK"));                         "next time you start this program."), tr("OK"));
# Line 867  void qsamplerMainForm::viewOptions (void Line 1171  void qsamplerMainForm::viewOptions (void
1171                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||
1172                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
1173                  updateRecentFilesMenu();                  updateRecentFilesMenu();
1174                if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||
1175                    (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))
1176                    updateInstrumentNames();
1177                if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||
1178                    (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))
1179                    updateDisplayEffect();
1180              if (sOldDisplayFont != m_pOptions->sDisplayFont)              if (sOldDisplayFont != m_pOptions->sDisplayFont)
1181                  updateDisplayFont();                  updateDisplayFont();
1182              if (iOldMaxVolume != m_pOptions->iMaxVolume)              if (iOldMaxVolume != m_pOptions->iMaxVolume)
# Line 909  void qsamplerMainForm::channelsArrange ( Line 1219  void qsamplerMainForm::channelsArrange (
1219      m_pWorkspace->setUpdatesEnabled(false);      m_pWorkspace->setUpdatesEnabled(false);
1220      int y = 0;      int y = 0;
1221      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1222          qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel);          qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1223      /*  if (pChannel->testWState(WState_Maximized | WState_Minimized)) {      /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {
1224              // Prevent flicker...              // Prevent flicker...
1225              pChannel->hide();              pChannelStrip->hide();
1226              pChannel->showNormal();              pChannelStrip->showNormal();
1227          }   */          }   */
1228          pChannel->adjustSize();          pChannelStrip->adjustSize();
1229          int iWidth  = m_pWorkspace->width();          int iWidth  = m_pWorkspace->width();
1230          if (iWidth < pChannel->width())          if (iWidth < pChannelStrip->width())
1231              iWidth = pChannel->width();              iWidth = pChannelStrip->width();
1232      //  int iHeight = pChannel->height() + pChannel->parentWidget()->baseSize().height();      //  int iHeight = pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();
1233          int iHeight = pChannel->parentWidget()->frameGeometry().height();          int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();
1234          pChannel->parentWidget()->setGeometry(0, y, iWidth, iHeight);          pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);
1235          y += iHeight;          y += iHeight;
1236      }      }
1237      m_pWorkspace->setUpdatesEnabled(true);      m_pWorkspace->setUpdatesEnabled(true);
# Line 969  void qsamplerMainForm::helpAbout (void) Line 1279  void qsamplerMainForm::helpAbout (void)
1279      sText += tr("Debugging option enabled.");      sText += tr("Debugging option enabled.");
1280      sText += "</font></small><br />";      sText += "</font></small><br />";
1281  #endif  #endif
1282    #ifndef CONFIG_LIBGIG
1283        sText += "<small><font color=\"red\">";
1284        sText += tr("GIG (libgig) file support disabled.");
1285        sText += "</font></small><br />";
1286    #endif
1287    #ifndef CONFIG_INSTRUMENT_NAME
1288        sText += "<small><font color=\"red\">";
1289        sText += tr("LSCP (liblscp) instrument_name support disabled.");
1290        sText += "</font></small><br />";
1291    #endif
1292      sText += "<br />\n";      sText += "<br />\n";
1293      sText += tr("Using") + ": ";      sText += tr("Using") + ": ";
1294      sText += ::lscp_client_package();      sText += ::lscp_client_package();
# Line 996  void qsamplerMainForm::helpAbout (void) Line 1316  void qsamplerMainForm::helpAbout (void)
1316  void qsamplerMainForm::stabilizeForm (void)  void qsamplerMainForm::stabilizeForm (void)
1317  {  {
1318      // Update the main application caption...      // Update the main application caption...
1319      QString sSessioName = sessionName(m_sFilename);      QString sSessionName = sessionName(m_sFilename);
1320      if (m_iDirtyCount > 0)      if (m_iDirtyCount > 0)
1321          sSessioName += '*';          sSessionName += '*';
1322      setCaption(tr(QSAMPLER_TITLE " - [%1]").arg(sSessioName));      setCaption(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));
1323    
1324      // Update the main menu state...      // Update the main menu state...
1325      qsamplerChannelStrip *pChannel = activeChannel();      qsamplerChannelStrip *pChannelStrip = activeChannelStrip();
1326      bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);      bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);
1327      bool bHasChannel = (bHasClient && pChannel != NULL);      bool bHasChannel = (bHasClient && pChannelStrip != NULL);
1328      fileNewAction->setEnabled(bHasClient);      fileNewAction->setEnabled(bHasClient);
1329      fileOpenAction->setEnabled(bHasClient);      fileOpenAction->setEnabled(bHasClient);
1330      fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);      fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
1331      fileSaveAsAction->setEnabled(bHasClient);      fileSaveAsAction->setEnabled(bHasClient);
1332        fileResetAction->setEnabled(bHasClient);
1333      fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);      fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);
1334      editAddChannelAction->setEnabled(bHasClient);      editAddChannelAction->setEnabled(bHasClient);
1335      editRemoveChannelAction->setEnabled(bHasChannel);      editRemoveChannelAction->setEnabled(bHasChannel);
1336      editSetupChannelAction->setEnabled(bHasChannel);      editSetupChannelAction->setEnabled(bHasChannel);
1337      editResetChannelAction->setEnabled(bHasChannel);      editResetChannelAction->setEnabled(bHasChannel);
1338      channelsArrangeAction->setEnabled(bHasChannel);      editResetAllChannelsAction->setEnabled(bHasChannel);
1339      viewMessagesAction->setOn(m_pMessages && m_pMessages->isVisible());      viewMessagesAction->setOn(m_pMessages && m_pMessages->isVisible());
1340        viewDevicesAction->setOn(m_pDeviceForm && m_pDeviceForm->isVisible());
1341        viewDevicesAction->setEnabled(bHasClient);
1342        channelsArrangeAction->setEnabled(bHasChannel);
1343    
1344      // Client/Server status...      // Client/Server status...
1345      if (bHasClient) {      if (bHasClient) {
1346          m_status[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));          m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));
1347          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));
1348      } else {      } else {
1349          m_status[QSAMPLER_STATUS_CLIENT]->clear();          m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();
1350          m_status[QSAMPLER_STATUS_SERVER]->clear();          m_statusItem[QSAMPLER_STATUS_SERVER]->clear();
1351      }      }
1352      // Channel status...      // Channel status...
1353      if (bHasChannel)      if (bHasChannel)
1354          m_status[QSAMPLER_STATUS_CHANNEL]->setText(pChannel->caption());          m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->caption());
1355      else      else
1356          m_status[QSAMPLER_STATUS_CHANNEL]->clear();          m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();
1357      // Session status...      // Session status...
1358      if (m_iDirtyCount > 0)      if (m_iDirtyCount > 0)
1359          m_status[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));          m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));
1360      else      else
1361          m_status[QSAMPLER_STATUS_SESSION]->clear();          m_statusItem[QSAMPLER_STATUS_SESSION]->clear();
1362    
1363      // Recent files menu.      // Recent files menu.
1364      m_pRecentFilesMenu->setEnabled(bHasClient && m_pOptions->recentFiles.count() > 0);      m_pRecentFilesMenu->setEnabled(bHasClient && m_pOptions->recentFiles.count() > 0);
# Line 1046  void qsamplerMainForm::stabilizeForm (vo Line 1370  void qsamplerMainForm::stabilizeForm (vo
1370    
1371    
1372  // Channel change receiver slot.  // Channel change receiver slot.
1373  void qsamplerMainForm::channelChanged( qsamplerChannelStrip * )  void qsamplerMainForm::channelStripChanged( qsamplerChannelStrip *pChannelStrip )
1374  {  {
1375            // Add this strip to the changed list...
1376            if (m_changedStrips.containsRef(pChannelStrip) == 0)
1377                    m_changedStrips.append(pChannelStrip);
1378    
1379      // Just mark the dirty form.      // Just mark the dirty form.
1380      m_iDirtyCount++;      m_iDirtyCount++;
1381      // and update the form status...      // and update the form status...
# Line 1055  void qsamplerMainForm::channelChanged( q Line 1383  void qsamplerMainForm::channelChanged( q
1383  }  }
1384    
1385    
1386    // Grab and restore current sampler channels session.
1387    void qsamplerMainForm::updateSession (void)
1388    {
1389            // Retrieve the current channel list.
1390            int *piChannelIDs = ::lscp_list_channels(m_pClient);
1391            if (piChannelIDs == NULL) {
1392                    if (::lscp_client_get_errno(m_pClient)) {
1393                            appendMessagesClient("lscp_list_channels");
1394                            appendMessagesError(tr("Could not get current list of channels.\n\nSorry."));
1395                    }
1396                    return;
1397            }
1398    
1399            // Try to (re)create each channel.
1400            m_pWorkspace->setUpdatesEnabled(false);
1401            for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {
1402                    // Check if theres already a channel strip for this one...
1403                    if (!channelStrip(piChannelIDs[iChannel]))
1404                            createChannelStrip(new qsamplerChannel(this, piChannelIDs[iChannel]));
1405                    // Make it visibly responsive...
1406                    QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
1407            }
1408            m_pWorkspace->setUpdatesEnabled(true);
1409            
1410            // Remember to refresh devices
1411            if (m_pDeviceForm)
1412                m_pDeviceForm->refreshDevices();
1413    }
1414    
1415    
1416  // Update the recent files list and menu.  // Update the recent files list and menu.
1417  void qsamplerMainForm::updateRecentFiles ( const QString& sFilename )  void qsamplerMainForm::updateRecentFiles ( const QString& sFilename )
1418  {  {
# Line 1099  void qsamplerMainForm::updateRecentFiles Line 1457  void qsamplerMainForm::updateRecentFiles
1457  }  }
1458    
1459    
1460    // Force update of the channels instrument names mode.
1461    void qsamplerMainForm::updateInstrumentNames (void)
1462    {
1463        // Full channel list update...
1464        QWidgetList wlist = m_pWorkspace->windowList();
1465        if (wlist.isEmpty())
1466            return;
1467    
1468        m_pWorkspace->setUpdatesEnabled(false);
1469        for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1470            qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1471            if (pChannelStrip)
1472                pChannelStrip->updateInstrumentName(true);
1473        }
1474        m_pWorkspace->setUpdatesEnabled(true);
1475    }
1476    
1477    
1478  // Force update of the channels display font.  // Force update of the channels display font.
1479  void qsamplerMainForm::updateDisplayFont (void)  void qsamplerMainForm::updateDisplayFont (void)
1480  {  {
# Line 1120  void qsamplerMainForm::updateDisplayFont Line 1496  void qsamplerMainForm::updateDisplayFont
1496    
1497      m_pWorkspace->setUpdatesEnabled(false);      m_pWorkspace->setUpdatesEnabled(false);
1498      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1499          qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel);          qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1500          pChannel->setDisplayFont(font);          if (pChannelStrip)
1501                pChannelStrip->setDisplayFont(font);
1502        }
1503        m_pWorkspace->setUpdatesEnabled(true);
1504    }
1505    
1506    
1507    // Update channel strips background effect.
1508    void qsamplerMainForm::updateDisplayEffect (void)
1509    {
1510       QPixmap pm;
1511        if (m_pOptions->bDisplayEffect)
1512            pm = QPixmap::fromMimeSource("displaybg1.png");
1513    
1514        // Full channel list update...
1515        QWidgetList wlist = m_pWorkspace->windowList();
1516        if (wlist.isEmpty())
1517            return;
1518    
1519        m_pWorkspace->setUpdatesEnabled(false);
1520        for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1521            qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1522            if (pChannelStrip)
1523                pChannelStrip->setDisplayBackground(pm);
1524      }      }
1525      m_pWorkspace->setUpdatesEnabled(true);      m_pWorkspace->setUpdatesEnabled(true);
1526  }  }
# Line 1140  void qsamplerMainForm::updateMaxVolume ( Line 1539  void qsamplerMainForm::updateMaxVolume (
1539    
1540      m_pWorkspace->setUpdatesEnabled(false);      m_pWorkspace->setUpdatesEnabled(false);
1541      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1542          qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel);          qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1543          pChannel->setMaxVolume(m_pOptions->iMaxVolume);          if (pChannelStrip)
1544                pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
1545      }      }
1546      m_pWorkspace->setUpdatesEnabled(true);      m_pWorkspace->setUpdatesEnabled(true);
1547  }  }
# Line 1240  void qsamplerMainForm::updateMessagesCap Line 1640  void qsamplerMainForm::updateMessagesCap
1640  // qsamplerMainForm -- MDI channel strip management.  // qsamplerMainForm -- MDI channel strip management.
1641    
1642  // The channel strip creation executive.  // The channel strip creation executive.
1643  void qsamplerMainForm::createChannel ( int iChannelID, bool bPrompt )  qsamplerChannelStrip *qsamplerMainForm::createChannelStrip ( qsamplerChannel *pChannel )
1644  {  {
1645      if (m_pClient == NULL)      if (m_pClient == NULL || pChannel == NULL)
1646          return;          return NULL;
1647    
1648      // Prepare for auto-arrange?      // Prepare for auto-arrange?
1649      qsamplerChannelStrip *pChannel = NULL;      qsamplerChannelStrip *pChannelStrip = NULL;
1650      int y = 0;      int y = 0;
1651      if (m_pOptions && m_pOptions->bAutoArrange) {      if (m_pOptions && m_pOptions->bAutoArrange) {
1652          QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
1653          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1654              pChannel = (qsamplerChannelStrip *) wlist.at(iChannel);              pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1655          //  y += pChannel->height() + pChannel->parentWidget()->baseSize().height();                          if (pChannelStrip) {
1656              y += pChannel->parentWidget()->frameGeometry().height();                          //  y += pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();
1657                                    y += pChannelStrip->parentWidget()->frameGeometry().height();
1658                            }
1659          }          }
1660      }      }
1661    
1662      // Add a new channel itema...      // Add a new channel itema...
1663      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;
1664      pChannel = new qsamplerChannelStrip(m_pWorkspace, 0, wflags);      pChannelStrip = new qsamplerChannelStrip(m_pWorkspace, 0, wflags);
1665      pChannel->setMaxVolume(m_pOptions->iMaxVolume);      if (pChannelStrip == NULL)
1666      pChannel->setup(this, iChannelID);          return NULL;
1667      // We'll need a display font.          
1668      QFont font;      // Actual channel strip setup...
1669      if (m_pOptions && font.fromString(m_pOptions->sDisplayFont))      pChannelStrip->setup(pChannel);
1670          pChannel->setDisplayFont(font);      QObject::connect(pChannelStrip, SIGNAL(channelChanged(qsamplerChannelStrip *)), this, SLOT(channelStripChanged(qsamplerChannelStrip *)));
1671      // Track channel setup changes.      // Set some initial aesthetic options...
1672      QObject::connect(pChannel, SIGNAL(channelChanged(qsamplerChannelStrip *)), this, SLOT(channelChanged(qsamplerChannelStrip *)));      if (m_pOptions) {
1673      // Before we show it up, may be we'll          // Background display effect...
1674      // better ask for some initial values?          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
1675      if (bPrompt)          // We'll need a display font.
1676          pChannel->channelSetup();                QFont font;
1677            if (font.fromString(m_pOptions->sDisplayFont))
1678                pChannelStrip->setDisplayFont(font);
1679            // Maximum allowed volume setting.
1680            pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
1681        }
1682    
1683      // Now we show up us to the world.      // Now we show up us to the world.
1684      pChannel->show();      pChannelStrip->show();
1685      // Only then, we'll auto-arrange...      // Only then, we'll auto-arrange...
1686      if (m_pOptions && m_pOptions->bAutoArrange) {      if (m_pOptions && m_pOptions->bAutoArrange) {
1687          int iWidth  = m_pWorkspace->width();          int iWidth  = m_pWorkspace->width();
1688      //  int iHeight = pChannel->height() + pChannel->parentWidget()->baseSize().height();      //  int iHeight = pChannel->height() + pChannel->parentWidget()->baseSize().height();
1689          int iHeight = pChannel->parentWidget()->frameGeometry().height();          int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();
1690          pChannel->parentWidget()->setGeometry(0, y, iWidth, iHeight);          pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);
1691      }      }
1692    
1693            // This is pretty new, so we'll watch for it closely.
1694            channelStripChanged(pChannelStrip);
1695    
1696        // Return our successful reference...
1697        return pChannelStrip;
1698  }  }
1699    
1700    
1701  // Retrieve the active channel strip.  // Retrieve the active channel strip.
1702  qsamplerChannelStrip *qsamplerMainForm::activeChannel (void)  qsamplerChannelStrip *qsamplerMainForm::activeChannelStrip (void)
1703  {  {
1704      return (qsamplerChannelStrip *) m_pWorkspace->activeWindow();      return (qsamplerChannelStrip *) m_pWorkspace->activeWindow();
1705  }  }
1706    
1707    
1708  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
1709  qsamplerChannelStrip *qsamplerMainForm::channelAt ( int iChannel )  qsamplerChannelStrip *qsamplerMainForm::channelStripAt ( int iChannel )
1710  {  {
1711      QWidgetList wlist = m_pWorkspace->windowList();      QWidgetList wlist = m_pWorkspace->windowList();
1712      if (wlist.isEmpty())      if (wlist.isEmpty())
1713          return 0;          return NULL;
1714    
1715      return (qsamplerChannelStrip *) wlist.at(iChannel);      return (qsamplerChannelStrip *) wlist.at(iChannel);
1716  }  }
1717    
1718    
1719    // Retrieve a channel strip by sampler channel id.
1720    qsamplerChannelStrip *qsamplerMainForm::channelStrip ( int iChannelID )
1721    {
1722            QWidgetList wlist = m_pWorkspace->windowList();
1723            if (wlist.isEmpty())
1724                    return NULL;
1725            
1726            for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1727                    qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1728                    if (pChannelStrip) {
1729                            qsamplerChannel *pChannel = pChannelStrip->channel();
1730                            if (pChannel && pChannel->channelID() == iChannelID)
1731                                    return pChannelStrip;
1732                    }
1733            }
1734    
1735            // Not found.
1736            return NULL;
1737    }
1738    
1739    
1740  // Construct the windows menu.  // Construct the windows menu.
1741  void qsamplerMainForm::channelsMenuAboutToShow (void)  void qsamplerMainForm::channelsMenuAboutToShow (void)
1742  {  {
# Line 1313  void qsamplerMainForm::channelsMenuAbout Line 1748  void qsamplerMainForm::channelsMenuAbout
1748      if (!wlist.isEmpty()) {      if (!wlist.isEmpty()) {
1749          channelsMenu->insertSeparator();          channelsMenu->insertSeparator();
1750          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1751              qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel);              qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1752              int iItemID = channelsMenu->insertItem(pChannel->caption(), this, SLOT(channelsMenuActivated(int)));              if (pChannelStrip) {
1753              channelsMenu->setItemParameter(iItemID, iChannel);                  int iItemID = channelsMenu->insertItem(pChannelStrip->caption(), this, SLOT(channelsMenuActivated(int)));
1754              channelsMenu->setItemChecked(iItemID, activeChannel() == pChannel);                  channelsMenu->setItemParameter(iItemID, iChannel);
1755                    channelsMenu->setItemChecked(iItemID, activeChannelStrip() == pChannelStrip);
1756                }
1757          }          }
1758      }      }
1759  }  }
# Line 1325  void qsamplerMainForm::channelsMenuAbout Line 1762  void qsamplerMainForm::channelsMenuAbout
1762  // Windows menu activation slot  // Windows menu activation slot
1763  void qsamplerMainForm::channelsMenuActivated ( int iChannel )  void qsamplerMainForm::channelsMenuActivated ( int iChannel )
1764  {  {
1765      qsamplerChannelStrip *pChannel = channelAt(iChannel);      qsamplerChannelStrip *pChannelStrip = channelStripAt(iChannel);
1766      if (pChannel)      if (pChannelStrip)
1767          pChannel->showNormal();          pChannelStrip->showNormal();
1768      pChannel->setFocus();      pChannelStrip->setFocus();
1769  }  }
1770    
1771    
# Line 1368  void qsamplerMainForm::timerSlot (void) Line 1805  void qsamplerMainForm::timerSlot (void)
1805      }      }
1806            
1807          // Refresh each channel usage, on each period...          // Refresh each channel usage, on each period...
1808      if (m_pClient && m_pOptions->bAutoRefresh && m_pWorkspace->isUpdatesEnabled()) {      if (m_pClient && (m_changedStrips.count() > 0 || m_pOptions->bAutoRefresh)) {
1809          m_iTimerSlot += QSAMPLER_TIMER_MSECS;          m_iTimerSlot += QSAMPLER_TIMER_MSECS;
1810          if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime)  {          if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime && m_pWorkspace->isUpdatesEnabled())  {
1811              m_iTimerSlot = 0;              m_iTimerSlot = 0;
1812                // Update the channel information for each pending strip...
1813                for (qsamplerChannelStrip *pChannelStrip = m_changedStrips.first();
1814                        pChannelStrip;
1815                                                    pChannelStrip = m_changedStrips.next()) {
1816                                    // If successfull, remove from pending list...
1817                                    if (pChannelStrip->updateChannelInfo())
1818                        m_changedStrips.remove(pChannelStrip);
1819                            }
1820                // Update the channel stream usage for each strip...
1821              QWidgetList wlist = m_pWorkspace->windowList();              QWidgetList wlist = m_pWorkspace->windowList();
1822              for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {              for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1823                  qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel);                  qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1824                  if (pChannel->isVisible())                  if (pChannelStrip && pChannelStrip->isVisible())
1825                      pChannel->updateChannelUsage();                      pChannelStrip->updateChannelUsage();
1826              }              }
1827          }          }
1828      }      }
# Line 1513  void qsamplerMainForm::processServerExit Line 1959  void qsamplerMainForm::processServerExit
1959  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1960  // qsamplerMainForm -- Client stuff.  // qsamplerMainForm -- Client stuff.
1961    
   
1962  // The LSCP client callback procedure.  // The LSCP client callback procedure.
1963  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 )
1964  {  {
1965      qsamplerMainForm *pMainForm = (qsamplerMainForm *) pvData;      qsamplerMainForm *pMainForm = (qsamplerMainForm *) pvData;
1966      if (pMainForm == NULL)      if (pMainForm == NULL)
1967          return LSCP_FAILED;          return LSCP_FAILED;
1968    
1969      char *pszBuffer = (char *) malloc(cchBuffer + 1);      // ATTN: DO NOT EVER call any GUI code here,
1970      if (pszBuffer == NULL)      // as this is run under some other thread context.
1971          return LSCP_FAILED;      // A custom event must be posted here...
1972        QApplication::postEvent(pMainForm, new qsamplerCustomEvent(event, pchData, cchData));
     memcpy(pszBuffer, pchBuffer, cchBuffer);  
     pszBuffer[cchBuffer] = (char) 0;  
     pMainForm->appendMessagesColor(pszBuffer, "#996699");  
     free(pszBuffer);  
1973    
1974      return LSCP_OK;      return LSCP_OK;
1975  }  }
# Line 1574  bool qsamplerMainForm::startClient (void Line 2015  bool qsamplerMainForm::startClient (void
2015      // Log success here.      // Log success here.
2016      appendMessages(tr("Client connected."));      appendMessages(tr("Client connected."));
2017    
2018            // Hard-notify device configuration form,
2019            // if visible, that we're ready...
2020            if (m_pDeviceForm && m_pDeviceForm->isVisible())
2021                m_pDeviceForm->setClient(m_pClient);
2022                
2023      // Is any session pending to be loaded?      // Is any session pending to be loaded?
2024      if (!m_pOptions->sSessionFile.isEmpty()) {      if (!m_pOptions->sSessionFile.isEmpty()) {
2025          // Just load the prabably startup session...          // Just load the prabably startup session...
# Line 1594  void qsamplerMainForm::stopClient (void) Line 2040  void qsamplerMainForm::stopClient (void)
2040      if (m_pClient == NULL)      if (m_pClient == NULL)
2041          return;          return;
2042    
2043            // Hard-notify device configuration form,
2044            // if visible, that we're running out...
2045            if (m_pDeviceForm && m_pDeviceForm->isVisible())
2046                m_pDeviceForm->setClient(NULL);
2047    
2048      // Log prepare here.      // Log prepare here.
2049      appendMessages(tr("Client disconnecting..."));      appendMessages(tr("Client disconnecting..."));
2050    

Legend:
Removed from v.122  
changed lines
  Added in v.484

  ViewVC Help
Powered by ViewVC