/[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 463 by capela, Tue Mar 15 15:32: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 470  bool qsamplerMainForm::loadSessionFile ( Line 598  bool qsamplerMainForm::loadSessionFile (
598              if (::lscp_client_query(m_pClient, sCommand.latin1()) != LSCP_OK) {              if (::lscp_client_query(m_pClient, sCommand.latin1()) != LSCP_OK) {
599                  appendMessagesClient("lscp_client_query");                  appendMessagesClient("lscp_client_query");
600                  iErrors++;                  iErrors++;
601                    break;
602              }              }
603          }          }
604          // Try to make it snappy :)          // Try to make it snappy :)
# Line 481  bool qsamplerMainForm::loadSessionFile ( Line 610  bool qsamplerMainForm::loadSessionFile (
610    
611      // Have we any errors?      // Have we any errors?
612      if (iErrors > 0)      if (iErrors > 0)
613          appendMessagesError(tr("Some setttings could not be loaded\nfrom \"%1\" session file.\n\nSorry.").arg(sFilename));          appendMessagesError(tr("Session could not be loaded\nfrom \"%1\".\n\nSorry.").arg(sFilename));
614    
615      // Now we'll try to create the whole GUI session.          // Now we'll try to create (update) the whole GUI session.
616      int iChannels = ::lscp_get_channels(m_pClient);          updateSession();
     if (iChannels < 0) {  
         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);  
617    
618      // Save as default session directory.      // Save as default session directory.
619      if (m_pOptions)      if (m_pOptions)
# Line 507  bool qsamplerMainForm::loadSessionFile ( Line 624  bool qsamplerMainForm::loadSessionFile (
624      m_sFilename = sFilename;      m_sFilename = sFilename;
625      updateRecentFiles(sFilename);      updateRecentFiles(sFilename);
626      appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));      appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));
627        
628        // Make that an overall update.
629      stabilizeForm();      stabilizeForm();
630      return true;      return true;
631  }  }
# Line 523  bool qsamplerMainForm::saveSessionFile ( Line 642  bool qsamplerMainForm::saveSessionFile (
642      }      }
643    
644      // Write the file.      // Write the file.
645      int iErrors = 0;      int  iErrors = 0;
646      QTextStream ts(&file);      QTextStream ts(&file);
647      ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;      ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;
648      ts << "# " << tr("Version")      ts << "# " << tr("Version")
# Line 534  bool qsamplerMainForm::saveSessionFile ( Line 653  bool qsamplerMainForm::saveSessionFile (
653      ts << "# " << tr("File")      ts << "# " << tr("File")
654         << ": " << QFileInfo(sFilename).fileName() << endl;         << ": " << QFileInfo(sFilename).fileName() << endl;
655      ts << "# " << tr("Date")      ts << "# " << tr("Date")
656         << ": " << QDate::currentDate().toString("MMMM dd yyyy")         << ": " << QDate::currentDate().toString("MMM dd yyyy")
657         << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;         << " "  << QTime::currentTime().toString("hh:mm:ss") << endl;
658      ts << "#"  << endl;      ts << "#"  << endl;
659      ts << endl;      ts << endl;
660            // It is assumed that this new kind of device+session file
661            // will be loaded from a complete
662            int *piDeviceIDs;
663            int  iDevice;
664            ts << "RESET" << endl;
665            // Audio device mapping.
666            QMap<int, int> audioDeviceMap;
667            piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Audio);
668            for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
669                    ts << endl;
670                    qsamplerDevice device(m_pClient, qsamplerDevice::Audio, piDeviceIDs[iDevice]);
671                    // Audio device specification...
672            ts << "# " << device.deviceTypeName() << " " << device.driverName()
673                       << " " << tr("Device") << " " << iDevice << endl;
674                    ts << "CREATE AUDIO_OUTPUT_DEVICE " << device.driverName();
675                    qsamplerDeviceParamMap::ConstIterator deviceParam;
676                    for (deviceParam = device.params().begin();
677                                    deviceParam != device.params().end();
678                                            ++deviceParam) {
679                            ts << " " << deviceParam.key()
680                               << "='" << deviceParam.data().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                                    ts << "SET AUDIO_OUTPUT_CHANNEL_PARAMETER " << iDevice
693                                       << " " << iPort << " " << portParam.key()
694                                       << "='" << portParam.data().value << "'" << endl;
695                            }
696                    }
697                    // Set device index/id mapping.
698                    audioDeviceMap[device.deviceID()] = iDevice;
699            // Try to keep it snappy :)
700            QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
701            }
702            // MIDI device mapping.
703            QMap<int, int> midiDeviceMap;
704            piDeviceIDs = qsamplerDevice::getDevices(m_pClient, qsamplerDevice::Midi);
705            for (iDevice = 0; piDeviceIDs && piDeviceIDs[iDevice] >= 0; iDevice++) {
706                    ts << endl;
707                    qsamplerDevice device(m_pClient, qsamplerDevice::Midi, piDeviceIDs[iDevice]);
708                    // MIDI device specification...
709            ts << "# " << device.deviceTypeName() << " " << device.driverName()
710                       << " " << tr("Device") << " " << iDevice << endl;
711                    ts << "CREATE MIDI_INPUT_DEVICE " << device.driverName();
712                    qsamplerDeviceParamMap::ConstIterator deviceParam;
713                    for (deviceParam = device.params().begin();
714                                    deviceParam != device.params().end();
715                                            ++deviceParam) {
716                            ts << " " << deviceParam.key()
717                               << "='" << deviceParam.data().value << "'";
718                    }
719                    ts << endl;
720                    // MIDI port parameters...
721                    int iPort = 0;
722                    for (qsamplerDevicePort *pPort = device.ports().first();
723                                    pPort;
724                                            pPort = device.ports().next(), ++iPort) {
725                            qsamplerDeviceParamMap::ConstIterator portParam;
726                            for (portParam = pPort->params().begin();
727                                            portParam != pPort->params().end();
728                                                    ++portParam) {
729                                    ts << "SET MIDI_INPUT_PORT_PARAMETER " << iDevice
730                                       << " " << iPort << " " << portParam.key()
731                                       << "='" << portParam.data().value << "'" << endl;
732                            }
733                    }
734            }
735            ts << endl;
736            // Sampler channel mapping.
737      QWidgetList wlist = m_pWorkspace->windowList();      QWidgetList wlist = m_pWorkspace->windowList();
738      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
739          qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel);          qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
740          int iChannelID = pChannel->channelID();          if (pChannelStrip) {
741          ts << "# " << pChannel->caption() << endl;              qsamplerChannel *pChannel = pChannelStrip->channel();
742          ts << "ADD CHANNEL" << endl;              if (pChannel) {
743          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannelID << " " << pChannel->audioDriver() << endl;                  ts << "# " << tr("Channel") << " " << iChannel << endl;
744          ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannelID << " " << pChannel->midiDriver() << endl;                  ts << "ADD CHANNEL" << endl;
745      //  ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannelID << " " << pChannel->midiPort() << endl;                  if (audioDeviceMap.isEmpty()) {
746          ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannelID << " " << pChannel->midiChannel() << endl;                          ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel
747          ts << "LOAD ENGINE " << pChannel->engineName() << " " << iChannelID << endl;                                              << " " << pChannel->audioDriver() << endl;
748          ts << "LOAD INSTRUMENT " << pChannel->instrumentFile() << " " << pChannel->instrumentNr() << " " << iChannelID << endl;                              } else {
749          ts << "SET CHANNEL VOLUME " << iChannelID << " " << pChannel->volume() << endl;                          ts << "SET CHANNEL AUDIO_OUTPUT_DEVICE " << iChannel
750          ts << endl;                                             << " " << audioDeviceMap[pChannel->audioDevice()] << endl;
751                                    }
752                    if (midiDeviceMap.isEmpty()) {
753                            ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannel
754                                           << " " << pChannel->midiDriver() << endl;
755                                } else {
756                            ts << "SET CHANNEL MIDI_INPUT_DEVICE " << iChannel
757                                               << " " << midiDeviceMap[pChannel->midiDevice()] << endl;
758                                }
759                    ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel
760                                   << " " << pChannel->midiPort() << endl;
761                    ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";
762                    if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
763                        ts << "ALL";
764                    else
765                        ts << pChannel->midiChannel();
766                    ts << endl;
767                    ts << "LOAD ENGINE " << pChannel->engineName() << " " << iChannel << endl;
768                    ts << "LOAD INSTRUMENT NON_MODAL '" << pChannel->instrumentFile() << "' " << pChannel->instrumentNr() << " " << iChannel << endl;
769                    ts << "SET CHANNEL VOLUME " << iChannel << " " << pChannel->volume() << endl;
770                    ts << endl;
771                }
772            }
773          // Try to keep it snappy :)          // Try to keep it snappy :)
774          QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);          QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
775      }      }
# Line 577  bool qsamplerMainForm::saveSessionFile ( Line 795  bool qsamplerMainForm::saveSessionFile (
795  }  }
796    
797    
798    // Session change receiver slot.
799    void qsamplerMainForm::sessionDirty (void)
800    {
801        // Just mark the dirty form.
802        m_iDirtyCount++;
803        // and update the form status...
804        stabilizeForm();
805    }
806    
807    
808  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
809  // qsamplerMainForm -- File Action slots.  // qsamplerMainForm -- File Action slots.
810    
# Line 623  void qsamplerMainForm::fileSaveAs (void) Line 851  void qsamplerMainForm::fileSaveAs (void)
851  }  }
852    
853    
854    // Reset the sampler instance.
855    void qsamplerMainForm::fileReset (void)
856    {
857        if (m_pClient == NULL)
858            return;
859    
860        // Ask user whether he/she want's an internal sampler reset...
861        if (QMessageBox::warning(this, tr("Warning"),
862            tr("Resetting the sampler instance will close\n"
863               "all device and channel configurations.\n\n"
864               "Please note that this operation may cause\n"
865               "temporary MIDI and Audio disruption\n\n"
866               "Do you want to reset the sampler engine now?"),
867            tr("Reset"), tr("Cancel")) > 0)
868            return;
869    
870        // Just do the reset, after closing down current session...
871        if (closeSession(true) && ::lscp_reset_sampler(m_pClient) != LSCP_OK) {
872            appendMessagesClient("lscp_reset_sampler");
873            appendMessagesError(tr("Could not reset sampler instance.\n\nSorry."));
874            return;
875        }
876    
877        // Log this.
878        appendMessages(tr("Sampler reset."));
879    
880            // Make it a new session...
881            newSession();
882    }
883    
884    
885  // Restart the client/server instance.  // Restart the client/server instance.
886  void qsamplerMainForm::fileRestart (void)  void qsamplerMainForm::fileRestart (void)
887  {  {
# Line 670  void qsamplerMainForm::editAddChannel (v Line 929  void qsamplerMainForm::editAddChannel (v
929      if (m_pClient == NULL)      if (m_pClient == NULL)
930          return;          return;
931    
932      // Create the new sampler channel.      // Just create the channel instance...
933      int iChannelID = ::lscp_add_channel(m_pClient);      qsamplerChannel *pChannel = new qsamplerChannel(this);
934      if (iChannelID < 0) {      if (pChannel == NULL)
         appendMessagesClient("lscp_add_channel");  
         appendMessagesError(tr("Could not create the new channel.\n\nSorry."));  
935          return;          return;
     }  
   
     // Log this happening.  
     appendMessages(tr("Channel %1 created.").arg(iChannelID));  
936    
937      // Just create the channel strip with given id.      // Before we show it up, may be we'll
938      createChannel(iChannelID, true);      // better ask for some initial values?
939        if (!pChannel->channelSetup(this)) {
940            delete pChannel;
941            return;
942        }
943        
944        // And give it to the strip (will own the channel instance, if successful).
945        if (!createChannelStrip(pChannel)) {
946            delete pChannel;
947            return;
948        }
949    
950      // We'll be dirty, for sure...      // Make that an overall update.
951      m_iDirtyCount++;      m_iDirtyCount++;
     // Stabilize form anyway.  
952      stabilizeForm();      stabilizeForm();
953  }  }
954    
# Line 697  void qsamplerMainForm::editRemoveChannel Line 959  void qsamplerMainForm::editRemoveChannel
959      if (m_pClient == NULL)      if (m_pClient == NULL)
960          return;          return;
961    
962      qsamplerChannelStrip *pChannel = activeChannel();      qsamplerChannelStrip *pChannelStrip = activeChannelStrip();
963        if (pChannelStrip == NULL)
964            return;
965            
966        qsamplerChannel *pChannel = pChannelStrip->channel();
967      if (pChannel == NULL)      if (pChannel == NULL)
968          return;          return;
969    
# Line 707  void qsamplerMainForm::editRemoveChannel Line 973  void qsamplerMainForm::editRemoveChannel
973              tr("About to remove channel:\n\n"              tr("About to remove channel:\n\n"
974                 "%1\n\n"                 "%1\n\n"
975                 "Are you sure?")                 "Are you sure?")
976                 .arg(pChannel->caption()),                 .arg(pChannelStrip->caption()),
977              tr("OK"), tr("Cancel")) > 0)              tr("OK"), tr("Cancel")) > 0)
978              return;              return;
979      }      }
980    
981      // Remove the existing sampler channel.      // Remove the existing sampler channel.
982      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."));  
983          return;          return;
     }  
984    
     // Log this happening.  
     appendMessages(tr("Channel %1 removed.").arg(pChannel->channelID()));  
       
985      // Just delete the channel strip.      // Just delete the channel strip.
986      delete pChannel;      delete pChannelStrip;
987        
988      // Do we auto-arrange?      // Do we auto-arrange?
989      if (m_pOptions && m_pOptions->bAutoArrange)      if (m_pOptions && m_pOptions->bAutoArrange)
990          channelsArrange();          channelsArrange();
# Line 740  void qsamplerMainForm::editSetupChannel Line 1001  void qsamplerMainForm::editSetupChannel
1001      if (m_pClient == NULL)      if (m_pClient == NULL)
1002          return;          return;
1003    
1004      qsamplerChannelStrip *pChannel = activeChannel();      qsamplerChannelStrip *pChannelStrip = activeChannelStrip();
1005      if (pChannel == NULL)      if (pChannelStrip == NULL)
1006          return;          return;
1007    
1008      // Just invoque the channel strip procedure.      // Just invoque the channel strip procedure.
1009      pChannel->channelSetup();      pChannelStrip->channelSetup();
1010  }  }
1011    
1012    
# Line 755  void qsamplerMainForm::editResetChannel Line 1016  void qsamplerMainForm::editResetChannel
1016      if (m_pClient == NULL)      if (m_pClient == NULL)
1017          return;          return;
1018    
1019      qsamplerChannelStrip *pChannel = activeChannel();      qsamplerChannelStrip *pChannelStrip = activeChannelStrip();
1020      if (pChannel == NULL)      if (pChannelStrip == NULL)
1021          return;          return;
1022    
1023      // Remove the existing sampler channel.      // Just invoque the channel strip procedure.
1024      if (::lscp_reset_channel(m_pClient, pChannel->channelID()) != LSCP_OK) {      pChannelStrip->channelReset();
1025          appendMessagesClient("lscp_reset_channel");  }
         appendMessagesError(tr("Could not reset channel.\n\nSorry."));  
         return;  
     }  
1026    
     // Log this.  
     appendMessages(tr("Channel %1 reset.").arg(pChannel->channelID()));  
1027    
1028      // Refresh channel strip info.  // Reset all sampler channels.
1029      pChannel->updateChannelInfo();  void qsamplerMainForm::editResetAllChannels (void)
1030    {
1031        if (m_pClient == NULL)
1032            return;
1033    
1034        // Invoque the channel strip procedure,
1035            // for all channels out there...
1036        m_pWorkspace->setUpdatesEnabled(false);
1037        QWidgetList wlist = m_pWorkspace->windowList();
1038        for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1039            qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1040            if (pChannelStrip)
1041                    pChannelStrip->channelReset();
1042        }
1043        m_pWorkspace->setUpdatesEnabled(true);
1044  }  }
1045    
1046    
# Line 822  void qsamplerMainForm::viewMessages ( bo Line 1092  void qsamplerMainForm::viewMessages ( bo
1092  }  }
1093    
1094    
1095    // Show/hide the device configurator form.
1096    void qsamplerMainForm::viewDevices (void)
1097    {
1098        if (m_pOptions == NULL)
1099            return;
1100    
1101        if (m_pDeviceForm) {
1102            m_pOptions->saveWidgetGeometry(m_pDeviceForm);
1103                    m_pDeviceForm->setClient(m_pClient);
1104            if (m_pDeviceForm->isVisible()) {
1105                m_pDeviceForm->hide();
1106            } else {
1107                m_pDeviceForm->show();
1108                m_pDeviceForm->raise();
1109                m_pDeviceForm->setActiveWindow();
1110            }
1111        }
1112    }
1113    
1114    
1115  // Show options dialog.  // Show options dialog.
1116  void qsamplerMainForm::viewOptions (void)  void qsamplerMainForm::viewOptions (void)
1117  {  {
# Line 831  void qsamplerMainForm::viewOptions (void Line 1121  void qsamplerMainForm::viewOptions (void
1121      qsamplerOptionsForm *pOptionsForm = new qsamplerOptionsForm(this);      qsamplerOptionsForm *pOptionsForm = new qsamplerOptionsForm(this);
1122      if (pOptionsForm) {      if (pOptionsForm) {
1123          // Check out some initial nullities(tm)...          // Check out some initial nullities(tm)...
1124          qsamplerChannelStrip *pChannel = activeChannel();          qsamplerChannelStrip *pChannelStrip = activeChannelStrip();
1125          if (m_pOptions->sDisplayFont.isEmpty() && pChannel)          if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)
1126              m_pOptions->sDisplayFont = pChannel->displayFont().toString();              m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();
1127          if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)          if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)
1128              m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();              m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
1129          // To track down deferred or immediate changes.          // To track down deferred or immediate changes.
# Line 843  void qsamplerMainForm::viewOptions (void Line 1133  void qsamplerMainForm::viewOptions (void
1133          bool    bOldServerStart     = m_pOptions->bServerStart;          bool    bOldServerStart     = m_pOptions->bServerStart;
1134          QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;          QString sOldServerCmdLine   = m_pOptions->sServerCmdLine;
1135          QString sOldDisplayFont     = m_pOptions->sDisplayFont;          QString sOldDisplayFont     = m_pOptions->sDisplayFont;
1136            bool    bOldDisplayEffect   = m_pOptions->bDisplayEffect;
1137          int     iOldMaxVolume       = m_pOptions->iMaxVolume;          int     iOldMaxVolume       = m_pOptions->iMaxVolume;
1138          QString sOldMessagesFont    = m_pOptions->sMessagesFont;          QString sOldMessagesFont    = m_pOptions->sMessagesFont;
1139            bool    bOldKeepOnTop       = m_pOptions->bKeepOnTop;
1140          bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;          bool    bOldStdoutCapture   = m_pOptions->bStdoutCapture;
1141          int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;          int     bOldMessagesLimit   = m_pOptions->bMessagesLimit;
1142          int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;          int     iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;
1143          bool    bOldCompletePath    = m_pOptions->bCompletePath;          bool    bOldCompletePath    = m_pOptions->bCompletePath;
1144            bool    bOldInstrumentNames = m_pOptions->bInstrumentNames;
1145          int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;          int     iOldMaxRecentFiles  = m_pOptions->iMaxRecentFiles;
1146          // Load the current setup settings.          // Load the current setup settings.
1147          pOptionsForm->setup(m_pOptions);          pOptionsForm->setup(m_pOptions);
# Line 856  void qsamplerMainForm::viewOptions (void Line 1149  void qsamplerMainForm::viewOptions (void
1149          if (pOptionsForm->exec()) {          if (pOptionsForm->exec()) {
1150              // Warn if something will be only effective on next run.              // Warn if something will be only effective on next run.
1151              if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||              if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1152                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture)) {                  (!bOldStdoutCapture &&  m_pOptions->bStdoutCapture) ||
1153                    ( bOldKeepOnTop     && !m_pOptions->bKeepOnTop)     ||
1154                    (!bOldKeepOnTop     &&  m_pOptions->bKeepOnTop)) {
1155                  QMessageBox::information(this, tr("Information"),                  QMessageBox::information(this, tr("Information"),
1156                      tr("Some settings may be only effective\n"                      tr("Some settings may be only effective\n"
1157                         "next time you start this program."), tr("OK"));                         "next time you start this program."), tr("OK"));
# Line 867  void qsamplerMainForm::viewOptions (void Line 1162  void qsamplerMainForm::viewOptions (void
1162                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||                  (!bOldCompletePath &&  m_pOptions->bCompletePath) ||
1163                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))                  (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
1164                  updateRecentFilesMenu();                  updateRecentFilesMenu();
1165                if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||
1166                    (!bOldInstrumentNames &&  m_pOptions->bInstrumentNames))
1167                    updateInstrumentNames();
1168                if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||
1169                    (!bOldDisplayEffect &&  m_pOptions->bDisplayEffect))
1170                    updateDisplayEffect();
1171              if (sOldDisplayFont != m_pOptions->sDisplayFont)              if (sOldDisplayFont != m_pOptions->sDisplayFont)
1172                  updateDisplayFont();                  updateDisplayFont();
1173              if (iOldMaxVolume != m_pOptions->iMaxVolume)              if (iOldMaxVolume != m_pOptions->iMaxVolume)
# Line 909  void qsamplerMainForm::channelsArrange ( Line 1210  void qsamplerMainForm::channelsArrange (
1210      m_pWorkspace->setUpdatesEnabled(false);      m_pWorkspace->setUpdatesEnabled(false);
1211      int y = 0;      int y = 0;
1212      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1213          qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel);          qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1214      /*  if (pChannel->testWState(WState_Maximized | WState_Minimized)) {      /*  if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {
1215              // Prevent flicker...              // Prevent flicker...
1216              pChannel->hide();              pChannelStrip->hide();
1217              pChannel->showNormal();              pChannelStrip->showNormal();
1218          }   */          }   */
1219          pChannel->adjustSize();          pChannelStrip->adjustSize();
1220          int iWidth  = m_pWorkspace->width();          int iWidth  = m_pWorkspace->width();
1221          if (iWidth < pChannel->width())          if (iWidth < pChannelStrip->width())
1222              iWidth = pChannel->width();              iWidth = pChannelStrip->width();
1223      //  int iHeight = pChannel->height() + pChannel->parentWidget()->baseSize().height();      //  int iHeight = pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();
1224          int iHeight = pChannel->parentWidget()->frameGeometry().height();          int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();
1225          pChannel->parentWidget()->setGeometry(0, y, iWidth, iHeight);          pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);
1226          y += iHeight;          y += iHeight;
1227      }      }
1228      m_pWorkspace->setUpdatesEnabled(true);      m_pWorkspace->setUpdatesEnabled(true);
# Line 969  void qsamplerMainForm::helpAbout (void) Line 1270  void qsamplerMainForm::helpAbout (void)
1270      sText += tr("Debugging option enabled.");      sText += tr("Debugging option enabled.");
1271      sText += "</font></small><br />";      sText += "</font></small><br />";
1272  #endif  #endif
1273    #ifndef CONFIG_LIBGIG
1274        sText += "<small><font color=\"red\">";
1275        sText += tr("GIG (libgig) file support disabled.");
1276        sText += "</font></small><br />";
1277    #endif
1278    #ifndef CONFIG_INSTRUMENT_NAME
1279        sText += "<small><font color=\"red\">";
1280        sText += tr("LSCP (liblscp) instrument_name support disabled.");
1281        sText += "</font></small><br />";
1282    #endif
1283      sText += "<br />\n";      sText += "<br />\n";
1284      sText += tr("Using") + ": ";      sText += tr("Using") + ": ";
1285      sText += ::lscp_client_package();      sText += ::lscp_client_package();
# Line 996  void qsamplerMainForm::helpAbout (void) Line 1307  void qsamplerMainForm::helpAbout (void)
1307  void qsamplerMainForm::stabilizeForm (void)  void qsamplerMainForm::stabilizeForm (void)
1308  {  {
1309      // Update the main application caption...      // Update the main application caption...
1310      QString sSessioName = sessionName(m_sFilename);      QString sSessionName = sessionName(m_sFilename);
1311      if (m_iDirtyCount > 0)      if (m_iDirtyCount > 0)
1312          sSessioName += '*';          sSessionName += '*';
1313      setCaption(tr(QSAMPLER_TITLE " - [%1]").arg(sSessioName));      setCaption(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));
1314    
1315      // Update the main menu state...      // Update the main menu state...
1316      qsamplerChannelStrip *pChannel = activeChannel();      qsamplerChannelStrip *pChannelStrip = activeChannelStrip();
1317      bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);      bool bHasClient  = (m_pOptions != NULL && m_pClient != NULL);
1318      bool bHasChannel = (bHasClient && pChannel != NULL);      bool bHasChannel = (bHasClient && pChannelStrip != NULL);
1319      fileNewAction->setEnabled(bHasClient);      fileNewAction->setEnabled(bHasClient);
1320      fileOpenAction->setEnabled(bHasClient);      fileOpenAction->setEnabled(bHasClient);
1321      fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);      fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
1322      fileSaveAsAction->setEnabled(bHasClient);      fileSaveAsAction->setEnabled(bHasClient);
1323        fileResetAction->setEnabled(bHasClient);
1324      fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);      fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);
1325      editAddChannelAction->setEnabled(bHasClient);      editAddChannelAction->setEnabled(bHasClient);
1326      editRemoveChannelAction->setEnabled(bHasChannel);      editRemoveChannelAction->setEnabled(bHasChannel);
1327      editSetupChannelAction->setEnabled(bHasChannel);      editSetupChannelAction->setEnabled(bHasChannel);
1328      editResetChannelAction->setEnabled(bHasChannel);      editResetChannelAction->setEnabled(bHasChannel);
1329      channelsArrangeAction->setEnabled(bHasChannel);      editResetAllChannelsAction->setEnabled(bHasChannel);
1330      viewMessagesAction->setOn(m_pMessages && m_pMessages->isVisible());      viewMessagesAction->setOn(m_pMessages && m_pMessages->isVisible());
1331        viewDevicesAction->setOn(m_pDeviceForm && m_pDeviceForm->isVisible());
1332        viewDevicesAction->setEnabled(bHasClient);
1333        channelsArrangeAction->setEnabled(bHasChannel);
1334    
1335      // Client/Server status...      // Client/Server status...
1336      if (bHasClient) {      if (bHasClient) {
1337          m_status[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));          m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));
1338          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));
1339      } else {      } else {
1340          m_status[QSAMPLER_STATUS_CLIENT]->clear();          m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();
1341          m_status[QSAMPLER_STATUS_SERVER]->clear();          m_statusItem[QSAMPLER_STATUS_SERVER]->clear();
1342      }      }
1343      // Channel status...      // Channel status...
1344      if (bHasChannel)      if (bHasChannel)
1345          m_status[QSAMPLER_STATUS_CHANNEL]->setText(pChannel->caption());          m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->caption());
1346      else      else
1347          m_status[QSAMPLER_STATUS_CHANNEL]->clear();          m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();
1348      // Session status...      // Session status...
1349      if (m_iDirtyCount > 0)      if (m_iDirtyCount > 0)
1350          m_status[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));          m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));
1351      else      else
1352          m_status[QSAMPLER_STATUS_SESSION]->clear();          m_statusItem[QSAMPLER_STATUS_SESSION]->clear();
1353    
1354      // Recent files menu.      // Recent files menu.
1355      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 1361  void qsamplerMainForm::stabilizeForm (vo
1361    
1362    
1363  // Channel change receiver slot.  // Channel change receiver slot.
1364  void qsamplerMainForm::channelChanged( qsamplerChannelStrip * )  void qsamplerMainForm::channelStripChanged( qsamplerChannelStrip *pChannelStrip )
1365  {  {
1366            // Add this strip to the changed list...
1367            if (m_changedStrips.containsRef(pChannelStrip) == 0)
1368                    m_changedStrips.append(pChannelStrip);
1369    
1370      // Just mark the dirty form.      // Just mark the dirty form.
1371      m_iDirtyCount++;      m_iDirtyCount++;
1372      // and update the form status...      // and update the form status...
# Line 1055  void qsamplerMainForm::channelChanged( q Line 1374  void qsamplerMainForm::channelChanged( q
1374  }  }
1375    
1376    
1377    // Grab and restore current sampler channels session.
1378    void qsamplerMainForm::updateSession (void)
1379    {
1380            // Retrieve the current channel list.
1381            int *piChannelIDs = ::lscp_list_channels(m_pClient);
1382            if (piChannelIDs == NULL) {
1383                    if (::lscp_client_get_errno(m_pClient)) {
1384                            appendMessagesClient("lscp_list_channels");
1385                            appendMessagesError(tr("Could not get current list of channels.\n\nSorry."));
1386                    }
1387                    return;
1388            }
1389    
1390            // Try to (re)create each channel.
1391            m_pWorkspace->setUpdatesEnabled(false);
1392            for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {
1393                    // Check if theres already a channel strip for this one...
1394                    if (!channelStrip(piChannelIDs[iChannel]))
1395                            createChannelStrip(new qsamplerChannel(this, piChannelIDs[iChannel]));
1396                    // Make it visibly responsive...
1397                    QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
1398            }
1399            m_pWorkspace->setUpdatesEnabled(true);
1400    }
1401    
1402    
1403  // Update the recent files list and menu.  // Update the recent files list and menu.
1404  void qsamplerMainForm::updateRecentFiles ( const QString& sFilename )  void qsamplerMainForm::updateRecentFiles ( const QString& sFilename )
1405  {  {
# Line 1099  void qsamplerMainForm::updateRecentFiles Line 1444  void qsamplerMainForm::updateRecentFiles
1444  }  }
1445    
1446    
1447    // Force update of the channels instrument names mode.
1448    void qsamplerMainForm::updateInstrumentNames (void)
1449    {
1450        // Full channel list update...
1451        QWidgetList wlist = m_pWorkspace->windowList();
1452        if (wlist.isEmpty())
1453            return;
1454    
1455        m_pWorkspace->setUpdatesEnabled(false);
1456        for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1457            qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1458            if (pChannelStrip)
1459                pChannelStrip->updateInstrumentName(true);
1460        }
1461        m_pWorkspace->setUpdatesEnabled(true);
1462    }
1463    
1464    
1465  // Force update of the channels display font.  // Force update of the channels display font.
1466  void qsamplerMainForm::updateDisplayFont (void)  void qsamplerMainForm::updateDisplayFont (void)
1467  {  {
# Line 1120  void qsamplerMainForm::updateDisplayFont Line 1483  void qsamplerMainForm::updateDisplayFont
1483    
1484      m_pWorkspace->setUpdatesEnabled(false);      m_pWorkspace->setUpdatesEnabled(false);
1485      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1486          qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel);          qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1487          pChannel->setDisplayFont(font);          if (pChannelStrip)
1488                pChannelStrip->setDisplayFont(font);
1489        }
1490        m_pWorkspace->setUpdatesEnabled(true);
1491    }
1492    
1493    
1494    // Update channel strips background effect.
1495    void qsamplerMainForm::updateDisplayEffect (void)
1496    {
1497       QPixmap pm;
1498        if (m_pOptions->bDisplayEffect)
1499            pm = QPixmap::fromMimeSource("displaybg1.png");
1500    
1501        // Full channel list update...
1502        QWidgetList wlist = m_pWorkspace->windowList();
1503        if (wlist.isEmpty())
1504            return;
1505    
1506        m_pWorkspace->setUpdatesEnabled(false);
1507        for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1508            qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1509            if (pChannelStrip)
1510                pChannelStrip->setDisplayBackground(pm);
1511      }      }
1512      m_pWorkspace->setUpdatesEnabled(true);      m_pWorkspace->setUpdatesEnabled(true);
1513  }  }
# Line 1140  void qsamplerMainForm::updateMaxVolume ( Line 1526  void qsamplerMainForm::updateMaxVolume (
1526    
1527      m_pWorkspace->setUpdatesEnabled(false);      m_pWorkspace->setUpdatesEnabled(false);
1528      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {      for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1529          qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel);          qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1530          pChannel->setMaxVolume(m_pOptions->iMaxVolume);          if (pChannelStrip)
1531                pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
1532      }      }
1533      m_pWorkspace->setUpdatesEnabled(true);      m_pWorkspace->setUpdatesEnabled(true);
1534  }  }
# Line 1240  void qsamplerMainForm::updateMessagesCap Line 1627  void qsamplerMainForm::updateMessagesCap
1627  // qsamplerMainForm -- MDI channel strip management.  // qsamplerMainForm -- MDI channel strip management.
1628    
1629  // The channel strip creation executive.  // The channel strip creation executive.
1630  void qsamplerMainForm::createChannel ( int iChannelID, bool bPrompt )  qsamplerChannelStrip *qsamplerMainForm::createChannelStrip ( qsamplerChannel *pChannel )
1631  {  {
1632      if (m_pClient == NULL)      if (m_pClient == NULL || pChannel == NULL)
1633          return;          return NULL;
1634    
1635      // Prepare for auto-arrange?      // Prepare for auto-arrange?
1636      qsamplerChannelStrip *pChannel = NULL;      qsamplerChannelStrip *pChannelStrip = NULL;
1637      int y = 0;      int y = 0;
1638      if (m_pOptions && m_pOptions->bAutoArrange) {      if (m_pOptions && m_pOptions->bAutoArrange) {
1639          QWidgetList wlist = m_pWorkspace->windowList();          QWidgetList wlist = m_pWorkspace->windowList();
1640          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1641              pChannel = (qsamplerChannelStrip *) wlist.at(iChannel);              pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1642          //  y += pChannel->height() + pChannel->parentWidget()->baseSize().height();                          if (pChannelStrip) {
1643              y += pChannel->parentWidget()->frameGeometry().height();                          //  y += pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();
1644                                    y += pChannelStrip->parentWidget()->frameGeometry().height();
1645                            }
1646          }          }
1647      }      }
1648    
1649      // Add a new channel itema...      // Add a new channel itema...
1650      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;
1651      pChannel = new qsamplerChannelStrip(m_pWorkspace, 0, wflags);      pChannelStrip = new qsamplerChannelStrip(m_pWorkspace, 0, wflags);
1652      pChannel->setMaxVolume(m_pOptions->iMaxVolume);      if (pChannelStrip == NULL)
1653      pChannel->setup(this, iChannelID);          return NULL;
1654      // We'll need a display font.          
1655      QFont font;      // Actual channel strip setup...
1656      if (m_pOptions && font.fromString(m_pOptions->sDisplayFont))      pChannelStrip->setup(pChannel);
1657          pChannel->setDisplayFont(font);      QObject::connect(pChannelStrip, SIGNAL(channelChanged(qsamplerChannelStrip *)), this, SLOT(channelStripChanged(qsamplerChannelStrip *)));
1658      // Track channel setup changes.      // Set some initial aesthetic options...
1659      QObject::connect(pChannel, SIGNAL(channelChanged(qsamplerChannelStrip *)), this, SLOT(channelChanged(qsamplerChannelStrip *)));      if (m_pOptions) {
1660      // Before we show it up, may be we'll          // Background display effect...
1661      // better ask for some initial values?          pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
1662      if (bPrompt)          // We'll need a display font.
1663          pChannel->channelSetup();                QFont font;
1664            if (font.fromString(m_pOptions->sDisplayFont))
1665                pChannelStrip->setDisplayFont(font);
1666            // Maximum allowed volume setting.
1667            pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
1668        }
1669    
1670      // Now we show up us to the world.      // Now we show up us to the world.
1671      pChannel->show();      pChannelStrip->show();
1672      // Only then, we'll auto-arrange...      // Only then, we'll auto-arrange...
1673      if (m_pOptions && m_pOptions->bAutoArrange) {      if (m_pOptions && m_pOptions->bAutoArrange) {
1674          int iWidth  = m_pWorkspace->width();          int iWidth  = m_pWorkspace->width();
1675      //  int iHeight = pChannel->height() + pChannel->parentWidget()->baseSize().height();      //  int iHeight = pChannel->height() + pChannel->parentWidget()->baseSize().height();
1676          int iHeight = pChannel->parentWidget()->frameGeometry().height();          int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();
1677          pChannel->parentWidget()->setGeometry(0, y, iWidth, iHeight);          pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);
1678      }      }
1679    
1680            // This is pretty new, so we'll watch for it closely.
1681            channelStripChanged(pChannelStrip);
1682    
1683        // Return our successful reference...
1684        return pChannelStrip;
1685  }  }
1686    
1687    
1688  // Retrieve the active channel strip.  // Retrieve the active channel strip.
1689  qsamplerChannelStrip *qsamplerMainForm::activeChannel (void)  qsamplerChannelStrip *qsamplerMainForm::activeChannelStrip (void)
1690  {  {
1691      return (qsamplerChannelStrip *) m_pWorkspace->activeWindow();      return (qsamplerChannelStrip *) m_pWorkspace->activeWindow();
1692  }  }
1693    
1694    
1695  // Retrieve a channel strip by index.  // Retrieve a channel strip by index.
1696  qsamplerChannelStrip *qsamplerMainForm::channelAt ( int iChannel )  qsamplerChannelStrip *qsamplerMainForm::channelStripAt ( int iChannel )
1697  {  {
1698      QWidgetList wlist = m_pWorkspace->windowList();      QWidgetList wlist = m_pWorkspace->windowList();
1699      if (wlist.isEmpty())      if (wlist.isEmpty())
1700          return 0;          return NULL;
1701    
1702      return (qsamplerChannelStrip *) wlist.at(iChannel);      return (qsamplerChannelStrip *) wlist.at(iChannel);
1703  }  }
1704    
1705    
1706    // Retrieve a channel strip by sampler channel id.
1707    qsamplerChannelStrip *qsamplerMainForm::channelStrip ( int iChannelID )
1708    {
1709            QWidgetList wlist = m_pWorkspace->windowList();
1710            if (wlist.isEmpty())
1711                    return NULL;
1712            
1713            for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1714                    qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1715                    if (pChannelStrip) {
1716                            qsamplerChannel *pChannel = pChannelStrip->channel();
1717                            if (pChannel && pChannel->channelID() == iChannelID)
1718                                    return pChannelStrip;
1719                    }
1720            }
1721    
1722            // Not found.
1723            return NULL;
1724    }
1725    
1726    
1727  // Construct the windows menu.  // Construct the windows menu.
1728  void qsamplerMainForm::channelsMenuAboutToShow (void)  void qsamplerMainForm::channelsMenuAboutToShow (void)
1729  {  {
# Line 1313  void qsamplerMainForm::channelsMenuAbout Line 1735  void qsamplerMainForm::channelsMenuAbout
1735      if (!wlist.isEmpty()) {      if (!wlist.isEmpty()) {
1736          channelsMenu->insertSeparator();          channelsMenu->insertSeparator();
1737          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {          for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1738              qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel);              qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1739              int iItemID = channelsMenu->insertItem(pChannel->caption(), this, SLOT(channelsMenuActivated(int)));              if (pChannelStrip) {
1740              channelsMenu->setItemParameter(iItemID, iChannel);                  int iItemID = channelsMenu->insertItem(pChannelStrip->caption(), this, SLOT(channelsMenuActivated(int)));
1741              channelsMenu->setItemChecked(iItemID, activeChannel() == pChannel);                  channelsMenu->setItemParameter(iItemID, iChannel);
1742                    channelsMenu->setItemChecked(iItemID, activeChannelStrip() == pChannelStrip);
1743                }
1744          }          }
1745      }      }
1746  }  }
# Line 1325  void qsamplerMainForm::channelsMenuAbout Line 1749  void qsamplerMainForm::channelsMenuAbout
1749  // Windows menu activation slot  // Windows menu activation slot
1750  void qsamplerMainForm::channelsMenuActivated ( int iChannel )  void qsamplerMainForm::channelsMenuActivated ( int iChannel )
1751  {  {
1752      qsamplerChannelStrip *pChannel = channelAt(iChannel);      qsamplerChannelStrip *pChannelStrip = channelStripAt(iChannel);
1753      if (pChannel)      if (pChannelStrip)
1754          pChannel->showNormal();          pChannelStrip->showNormal();
1755      pChannel->setFocus();      pChannelStrip->setFocus();
1756  }  }
1757    
1758    
# Line 1368  void qsamplerMainForm::timerSlot (void) Line 1792  void qsamplerMainForm::timerSlot (void)
1792      }      }
1793            
1794          // Refresh each channel usage, on each period...          // Refresh each channel usage, on each period...
1795      if (m_pClient && m_pOptions->bAutoRefresh && m_pWorkspace->isUpdatesEnabled()) {      if (m_pClient && (m_changedStrips.count() > 0 || m_pOptions->bAutoRefresh)) {
1796          m_iTimerSlot += QSAMPLER_TIMER_MSECS;          m_iTimerSlot += QSAMPLER_TIMER_MSECS;
1797          if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime)  {          if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime && m_pWorkspace->isUpdatesEnabled())  {
1798              m_iTimerSlot = 0;              m_iTimerSlot = 0;
1799                // Update the channel information for each pending strip...
1800                for (qsamplerChannelStrip *pChannelStrip = m_changedStrips.first();
1801                        pChannelStrip;
1802                                                    pChannelStrip = m_changedStrips.next()) {
1803                                    // If successfull, remove from pending list...
1804                                    if (pChannelStrip->updateChannelInfo())
1805                        m_changedStrips.remove(pChannelStrip);
1806                            }
1807                // Update the channel stream usage for each strip...
1808              QWidgetList wlist = m_pWorkspace->windowList();              QWidgetList wlist = m_pWorkspace->windowList();
1809              for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {              for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1810                  qsamplerChannelStrip *pChannel = (qsamplerChannelStrip *) wlist.at(iChannel);                  qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1811                  if (pChannel->isVisible())                  if (pChannelStrip && pChannelStrip->isVisible())
1812                      pChannel->updateChannelUsage();                      pChannelStrip->updateChannelUsage();
1813              }              }
1814          }          }
1815      }      }
# Line 1513  void qsamplerMainForm::processServerExit Line 1946  void qsamplerMainForm::processServerExit
1946  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
1947  // qsamplerMainForm -- Client stuff.  // qsamplerMainForm -- Client stuff.
1948    
   
1949  // The LSCP client callback procedure.  // The LSCP client callback procedure.
1950  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 )
1951  {  {
1952      qsamplerMainForm *pMainForm = (qsamplerMainForm *) pvData;      qsamplerMainForm *pMainForm = (qsamplerMainForm *) pvData;
1953      if (pMainForm == NULL)      if (pMainForm == NULL)
1954          return LSCP_FAILED;          return LSCP_FAILED;
1955    
1956      char *pszBuffer = (char *) malloc(cchBuffer + 1);      // ATTN: DO NOT EVER call any GUI code here,
1957      if (pszBuffer == NULL)      // as this is run under some other thread context.
1958          return LSCP_FAILED;      // A custom event must be posted here...
1959        QApplication::postEvent(pMainForm, new qsamplerCustomEvent(event, pchData, cchData));
     memcpy(pszBuffer, pchBuffer, cchBuffer);  
     pszBuffer[cchBuffer] = (char) 0;  
     pMainForm->appendMessagesColor(pszBuffer, "#996699");  
     free(pszBuffer);  
1960    
1961      return LSCP_OK;      return LSCP_OK;
1962  }  }
# Line 1574  bool qsamplerMainForm::startClient (void Line 2002  bool qsamplerMainForm::startClient (void
2002      // Log success here.      // Log success here.
2003      appendMessages(tr("Client connected."));      appendMessages(tr("Client connected."));
2004    
2005            // Hard-notify device configuration form,
2006            // if visible, that we're ready...
2007            if (m_pDeviceForm && m_pDeviceForm->isVisible())
2008                m_pDeviceForm->setClient(m_pClient);
2009                
2010      // Is any session pending to be loaded?      // Is any session pending to be loaded?
2011      if (!m_pOptions->sSessionFile.isEmpty()) {      if (!m_pOptions->sSessionFile.isEmpty()) {
2012          // Just load the prabably startup session...          // Just load the prabably startup session...
# Line 1594  void qsamplerMainForm::stopClient (void) Line 2027  void qsamplerMainForm::stopClient (void)
2027      if (m_pClient == NULL)      if (m_pClient == NULL)
2028          return;          return;
2029    
2030            // Hard-notify device configuration form,
2031            // if visible, that we're running out...
2032            if (m_pDeviceForm && m_pDeviceForm->isVisible())
2033                m_pDeviceForm->setClient(NULL);
2034    
2035      // Log prepare here.      // Log prepare here.
2036      appendMessages(tr("Client disconnecting..."));      appendMessages(tr("Client disconnecting..."));
2037    

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

  ViewVC Help
Powered by ViewVC