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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 428 - (hide annotations) (download) (as text)
Mon Mar 7 17:05:55 2005 UTC (19 years ago) by capela
File MIME type: text/x-c++hdr
File size: 61268 byte(s)
More device configuration interface preparations.

1 capela 109 // qsamplerMainForm.ui.h
2     //
3     // ui.h extension file, included from the uic-generated form implementation.
4     /****************************************************************************
5 capela 341 Copyright (C) 2004-2005, rncbc aka Rui Nuno Capela. All rights reserved.
6 capela 109
7     This program is free software; you can redistribute it and/or
8     modify it under the terms of the GNU General Public License
9     as published by the Free Software Foundation; either version 2
10     of the License, or (at your option) any later version.
11    
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     GNU General Public License for more details.
16    
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20    
21     *****************************************************************************/
22    
23     #include <qapplication.h>
24     #include <qeventloop.h>
25     #include <qworkspace.h>
26     #include <qprocess.h>
27     #include <qmessagebox.h>
28     #include <qdragobject.h>
29 capela 388 #include <qregexp.h>
30 capela 109 #include <qfiledialog.h>
31     #include <qfileinfo.h>
32     #include <qfile.h>
33     #include <qtextstream.h>
34     #include <qstatusbar.h>
35     #include <qlabel.h>
36     #include <qtimer.h>
37    
38     #include "qsamplerAbout.h"
39     #include "qsamplerOptions.h"
40 capela 264 #include "qsamplerChannel.h"
41 capela 109 #include "qsamplerMessages.h"
42    
43     #include "qsamplerChannelStrip.h"
44 capela 428
45     #include "qsamplerDeviceForm.h"
46 capela 109 #include "qsamplerOptionsForm.h"
47    
48     #include "config.h"
49    
50 capela 340 #ifdef HAVE_SIGNAL_H
51     #include <signal.h>
52     #endif
53 capela 109
54     // Timer constant stuff.
55     #define QSAMPLER_TIMER_MSECS 200
56    
57     // Status bar item indexes
58     #define QSAMPLER_STATUS_CLIENT 0 // Client connection state.
59     #define QSAMPLER_STATUS_SERVER 1 // Currenr server address (host:port)
60     #define QSAMPLER_STATUS_CHANNEL 2 // Active channel caption.
61     #define QSAMPLER_STATUS_SESSION 3 // Current session modification state.
62    
63    
64 capela 149 // All winsock apps needs this.
65 capela 109 #if defined(WIN32)
66     static WSADATA _wsaData;
67     #endif
68    
69 capela 149
70 capela 109 //-------------------------------------------------------------------------
71 capela 149 // 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 capela 109 // qsamplerMainForm -- Main window form implementation.
102    
103     // Kind of constructor.
104     void qsamplerMainForm::init (void)
105     {
106     // Initialize some pointer references.
107     m_pOptions = NULL;
108    
109     // All child forms are to be created later, not earlier than setup.
110 capela 428 m_pMessages = NULL;
111     m_pDeviceForm = NULL;
112 capela 109
113     // We'll start clean.
114 capela 400 m_iUntitled = 0;
115     m_iDirtyCount = 0;
116 capela 109
117     m_pServer = NULL;
118     m_pClient = NULL;
119    
120     m_iStartDelay = 0;
121     m_iTimerDelay = 0;
122    
123     m_iTimerSlot = 0;
124    
125 capela 340 #ifdef HAVE_SIGNAL_H
126     // Set to ignore any fatal "Broken pipe" signals.
127     ::signal(SIGPIPE, SIG_IGN);
128     #endif
129    
130 capela 109 // Make it an MDI workspace.
131     m_pWorkspace = new QWorkspace(this);
132     m_pWorkspace->setScrollBarsEnabled(true);
133     // Set the activation connection.
134     QObject::connect(m_pWorkspace, SIGNAL(windowActivated(QWidget *)), this, SLOT(stabilizeForm()));
135     // Make it shine :-)
136     setCentralWidget(m_pWorkspace);
137    
138     // Create some statusbar labels...
139     QLabel *pLabel;
140     // Client status.
141     pLabel = new QLabel(tr("Connected"), this);
142     pLabel->setAlignment(Qt::AlignLeft);
143     pLabel->setMinimumSize(pLabel->sizeHint());
144 capela 428 m_statusItem[QSAMPLER_STATUS_CLIENT] = pLabel;
145 capela 109 statusBar()->addWidget(pLabel);
146     // Server address.
147     pLabel = new QLabel(this);
148     pLabel->setAlignment(Qt::AlignLeft);
149 capela 428 m_statusItem[QSAMPLER_STATUS_SERVER] = pLabel;
150 capela 109 statusBar()->addWidget(pLabel, 1);
151     // Channel title.
152     pLabel = new QLabel(this);
153     pLabel->setAlignment(Qt::AlignLeft);
154 capela 428 m_statusItem[QSAMPLER_STATUS_CHANNEL] = pLabel;
155 capela 109 statusBar()->addWidget(pLabel, 2);
156     // Session modification status.
157     pLabel = new QLabel(tr("MOD"), this);
158     pLabel->setAlignment(Qt::AlignHCenter);
159     pLabel->setMinimumSize(pLabel->sizeHint());
160 capela 428 m_statusItem[QSAMPLER_STATUS_SESSION] = pLabel;
161 capela 109 statusBar()->addWidget(pLabel);
162    
163     // Create the recent files sub-menu.
164     m_pRecentFilesMenu = new QPopupMenu(this);
165     fileMenu->insertSeparator(4);
166     fileMenu->insertItem(tr("Recent &Files"), m_pRecentFilesMenu, 0, 5);
167    
168     #if defined(WIN32)
169     WSAStartup(MAKEWORD(1, 1), &_wsaData);
170     #endif
171     }
172    
173    
174     // Kind of destructor.
175     void qsamplerMainForm::destroy (void)
176     {
177     // Do final processing anyway.
178     processServerExit();
179 capela 418
180     #if defined(WIN32)
181     WSACleanup();
182     #endif
183    
184     // Finally drop any widgets around...
185 capela 428 if (m_pDeviceForm)
186     delete m_pDeviceForm;
187 capela 418 if (m_pMessages)
188     delete m_pMessages;
189     if (m_pWorkspace)
190     delete m_pWorkspace;
191    
192 capela 109 // Delete status item labels one by one.
193 capela 428 if (m_statusItem[QSAMPLER_STATUS_CLIENT])
194     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 capela 109
202 capela 418 // Delete recentfiles menu.
203     if (m_pRecentFilesMenu)
204     delete m_pRecentFilesMenu;
205 capela 109 }
206    
207    
208     // Make and set a proper setup options step.
209     void qsamplerMainForm::setup ( qsamplerOptions *pOptions )
210     {
211     // We got options?
212     m_pOptions = pOptions;
213    
214     // Some child forms are to be created right now.
215     m_pMessages = new qsamplerMessages(this);
216 capela 428 m_pDeviceForm = new qsamplerDeviceForm(this);
217 capela 109 // Set message defaults...
218     updateMessagesFont();
219     updateMessagesLimit();
220     updateMessagesCapture();
221     // Set the visibility signal.
222     QObject::connect(m_pMessages, SIGNAL(visibilityChanged(bool)), this, SLOT(stabilizeForm()));
223    
224     // Initial decorations toggle state.
225     viewMenubarAction->setOn(m_pOptions->bMenubar);
226     viewToolbarAction->setOn(m_pOptions->bToolbar);
227     viewStatusbarAction->setOn(m_pOptions->bStatusbar);
228     channelsAutoArrangeAction->setOn(m_pOptions->bAutoArrange);
229    
230     // Initial decorations visibility state.
231     viewMenubar(m_pOptions->bMenubar);
232     viewToolbar(m_pOptions->bToolbar);
233     viewStatusbar(m_pOptions->bStatusbar);
234    
235     // Restore whole dock windows state.
236     QString sDockables = m_pOptions->settings().readEntry("/Layout/DockWindows" , QString::null);
237     if (sDockables.isEmpty()) {
238     // Message window is forced to dock on the bottom.
239     moveDockWindow(m_pMessages, Qt::DockBottom);
240     } else {
241     // Make it as the last time.
242     QTextIStream istr(&sDockables);
243     istr >> *this;
244     }
245 capela 428 // Try to restore old window positioning and initial visibility.
246 capela 109 m_pOptions->loadWidgetGeometry(this);
247 capela 428 m_pOptions->loadWidgetGeometry(m_pDeviceForm);
248 capela 109
249     // Final startup stabilization...
250     updateRecentFilesMenu();
251     stabilizeForm();
252    
253     // Make it ready :-)
254     statusBar()->message(tr("Ready"), 3000);
255    
256     // We'll try to start immediately...
257     startSchedule(0);
258    
259     // Register the first timer slot.
260     QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
261     }
262    
263    
264     // Window close event handlers.
265     bool qsamplerMainForm::queryClose (void)
266     {
267     bool bQueryClose = closeSession(false);
268    
269     // Try to save current general state...
270     if (m_pOptions) {
271     // Some windows default fonts is here on demand too.
272     if (bQueryClose && m_pMessages)
273     m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
274 capela 428 // Other windows just need asking if it can close gracefully...
275     if (bQueryClose && m_pDeviceForm)
276     bQueryClose = m_pDeviceForm->queryClose();
277 capela 109 // Try to save current positioning.
278     if (bQueryClose) {
279     // Save decorations state.
280     m_pOptions->bMenubar = MenuBar->isVisible();
281     m_pOptions->bToolbar = (fileToolbar->isVisible() || editToolbar->isVisible() || channelsToolbar->isVisible());
282     m_pOptions->bStatusbar = statusBar()->isVisible();
283     // Save the dock windows state.
284     QString sDockables;
285     QTextOStream ostr(&sDockables);
286     ostr << *this;
287     m_pOptions->settings().writeEntry("/Layout/DockWindows", sDockables);
288 capela 428 // And the children, and the main windows state,.
289     m_pOptions->saveWidgetGeometry(m_pDeviceForm);
290 capela 109 m_pOptions->saveWidgetGeometry(this);
291 capela 428 // Close popup widgets.
292     if (m_pDeviceForm)
293     m_pDeviceForm->close();
294 capela 109 // Stop client and/or server, gracefully.
295     stopServer();
296     }
297     }
298    
299     return bQueryClose;
300     }
301    
302    
303     void qsamplerMainForm::closeEvent ( QCloseEvent *pCloseEvent )
304     {
305     if (queryClose())
306     pCloseEvent->accept();
307     else
308     pCloseEvent->ignore();
309     }
310    
311    
312 capela 388 // Drag'n'drop file handler.
313     bool qsamplerMainForm::decodeDragFiles ( const QMimeSource *pEvent, QStringList& files )
314 capela 109 {
315 capela 388 bool bDecode = false;
316 capela 109
317 capela 388 if (QTextDrag::canDecode(pEvent)) {
318     QString sText;
319     bDecode = QTextDrag::decode(pEvent, sText);
320     if (bDecode) {
321     files = QStringList::split('\n', sText);
322     for (QStringList::Iterator iter = files.begin(); iter != files.end(); iter++)
323 capela 409 *iter = QUrl((*iter).stripWhiteSpace().replace(QRegExp("^file:"), QString::null)).path();
324 capela 388 }
325 capela 109 }
326    
327 capela 388 return bDecode;
328 capela 109 }
329    
330    
331 capela 388 // Window drag-n-drop event handlers.
332     void qsamplerMainForm::dragEnterEvent ( QDragEnterEvent* pDragEnterEvent )
333     {
334 capela 395 QStringList files;
335     pDragEnterEvent->accept(decodeDragFiles(pDragEnterEvent, files));
336 capela 388 }
337    
338    
339 capela 109 void qsamplerMainForm::dropEvent ( QDropEvent* pDropEvent )
340     {
341 capela 388 QStringList files;
342 capela 391
343     if (!decodeDragFiles(pDropEvent, files))
344     return;
345    
346     for (QStringList::Iterator iter = files.begin(); iter != files.end(); iter++) {
347 capela 409 const QString& sPath = *iter;
348 capela 391 if (qsamplerChannel::isInstrumentFile(sPath)) {
349     // Try to create a new channel from instrument file...
350     qsamplerChannel *pChannel = new qsamplerChannel(this);
351     if (pChannel == NULL)
352     return;
353     // Start setting the instrument filename...
354     pChannel->setInstrument(sPath, 0);
355     // Before we show it up, may be we'll
356     // better ask for some initial values?
357     if (!pChannel->channelSetup(this)) {
358     delete pChannel;
359     return;
360     }
361     // Finally, give it to a new channel strip...
362     if (!createChannelStrip(pChannel)) {
363     delete pChannel;
364     return;
365     }
366     // Make that an overall update.
367     m_iDirtyCount++;
368     stabilizeForm();
369     } // Otherwise, load an usual session file (LSCP script)...
370     else if (closeSession(true))
371     loadSessionFile(sPath);
372     // Make it look responsive...:)
373     QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
374     }
375 capela 109 }
376    
377    
378 capela 149 // Custome event handler.
379     void qsamplerMainForm::customEvent ( QCustomEvent *pCustomEvent )
380     {
381     // For the time being, just pump it to messages.
382     if (pCustomEvent->type() == QSAMPLER_CUSTOM_EVENT) {
383     qsamplerCustomEvent *pEvent = (qsamplerCustomEvent *) pCustomEvent;
384     appendMessagesColor(tr("Notify event: %1 data: %2")
385     .arg(::lscp_event_to_text(pEvent->event()))
386     .arg(pEvent->data()), "#996699");
387     }
388     }
389    
390    
391 capela 127 // Context menu event handler.
392     void qsamplerMainForm::contextMenuEvent( QContextMenuEvent *pEvent )
393     {
394     stabilizeForm();
395    
396     editMenu->exec(pEvent->globalPos());
397     }
398    
399    
400 capela 109 //-------------------------------------------------------------------------
401     // qsamplerMainForm -- Brainless public property accessors.
402    
403     // The global options settings property.
404     qsamplerOptions *qsamplerMainForm::options (void)
405     {
406     return m_pOptions;
407     }
408    
409     // The LSCP client descriptor property.
410     lscp_client_t *qsamplerMainForm::client (void)
411     {
412     return m_pClient;
413     }
414    
415    
416     //-------------------------------------------------------------------------
417     // qsamplerMainForm -- Session file stuff.
418    
419     // Format the displayable session filename.
420     QString qsamplerMainForm::sessionName ( const QString& sFilename )
421     {
422     bool bCompletePath = (m_pOptions && m_pOptions->bCompletePath);
423     QString sSessionName = sFilename;
424     if (sSessionName.isEmpty())
425     sSessionName = tr("Untitled") + QString::number(m_iUntitled);
426     else if (!bCompletePath)
427     sSessionName = QFileInfo(sSessionName).fileName();
428     return sSessionName;
429     }
430    
431    
432     // Create a new session file from scratch.
433     bool qsamplerMainForm::newSession (void)
434     {
435     // Check if we can do it.
436     if (!closeSession(true))
437     return false;
438    
439 capela 395 // Give us what the server has, right now...
440     updateSession();
441    
442 capela 109 // Ok increment untitled count.
443     m_iUntitled++;
444    
445     // Stabilize form.
446     m_sFilename = QString::null;
447     m_iDirtyCount = 0;
448     appendMessages(tr("New session: \"%1\".").arg(sessionName(m_sFilename)));
449     stabilizeForm();
450    
451     return true;
452     }
453    
454    
455     // Open an existing sampler session.
456     bool qsamplerMainForm::openSession (void)
457     {
458     if (m_pOptions == NULL)
459     return false;
460    
461     // Ask for the filename to open...
462     QString sFilename = QFileDialog::getOpenFileName(
463     m_pOptions->sSessionDir, // Start here.
464     tr("LSCP Session files") + " (*.lscp)", // Filter (LSCP files)
465     this, 0, // Parent and name (none)
466     tr("Open Session") // Caption.
467     );
468    
469     // Have we cancelled?
470     if (sFilename.isEmpty())
471     return false;
472    
473     // Check if we're going to discard safely the current one...
474     if (!closeSession(true))
475     return false;
476    
477     // Load it right away.
478     return loadSessionFile(sFilename);
479     }
480    
481    
482     // Save current sampler session with another name.
483     bool qsamplerMainForm::saveSession ( bool bPrompt )
484     {
485     if (m_pOptions == NULL)
486     return false;
487    
488     QString sFilename = m_sFilename;
489    
490     // Ask for the file to save, if there's none...
491     if (bPrompt || sFilename.isEmpty()) {
492     // If none is given, assume default directory.
493     if (sFilename.isEmpty())
494     sFilename = m_pOptions->sSessionDir;
495     // Prompt the guy...
496     sFilename = QFileDialog::getSaveFileName(
497     sFilename, // Start here.
498     tr("LSCP Session files") + " (*.lscp)", // Filter (LSCP files)
499     this, 0, // Parent and name (none)
500     tr("Save Session") // Caption.
501     );
502     // Have we cancelled it?
503     if (sFilename.isEmpty())
504     return false;
505     // Enforce .lscp extension...
506     if (QFileInfo(sFilename).extension().isEmpty())
507     sFilename += ".lscp";
508     // Check if already exists...
509     if (sFilename != m_sFilename && QFileInfo(sFilename).exists()) {
510     if (QMessageBox::warning(this, tr("Warning"),
511     tr("The file already exists:\n\n"
512     "\"%1\"\n\n"
513     "Do you want to replace it?")
514     .arg(sFilename),
515     tr("Replace"), tr("Cancel")) > 0)
516     return false;
517     }
518     }
519    
520     // Save it right away.
521     return saveSessionFile(sFilename);
522     }
523    
524    
525     // Close current session.
526     bool qsamplerMainForm::closeSession ( bool bForce )
527     {
528     bool bClose = true;
529    
530     // Are we dirty enough to prompt it?
531     if (m_iDirtyCount > 0) {
532     switch (QMessageBox::warning(this, tr("Warning"),
533     tr("The current session has been changed:\n\n"
534     "\"%1\"\n\n"
535     "Do you want to save the changes?")
536     .arg(sessionName(m_sFilename)),
537     tr("Save"), tr("Discard"), tr("Cancel"))) {
538     case 0: // Save...
539     bClose = saveSession(false);
540     // Fall thru....
541     case 1: // Discard
542     break;
543     default: // Cancel.
544     bClose = false;
545     break;
546     }
547     }
548    
549     // If we may close it, dot it.
550     if (bClose) {
551     // Remove all channel strips from sight...
552     m_pWorkspace->setUpdatesEnabled(false);
553     QWidgetList wlist = m_pWorkspace->windowList();
554     for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
555 capela 264 qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
556     if (pChannelStrip) {
557     qsamplerChannel *pChannel = pChannelStrip->channel();
558 capela 295 if (bForce && pChannel)
559     pChannel->removeChannel();
560 capela 264 delete pChannelStrip;
561     }
562 capela 109 }
563     m_pWorkspace->setUpdatesEnabled(true);
564     // We're now clean, for sure.
565     m_iDirtyCount = 0;
566     }
567    
568     return bClose;
569     }
570    
571    
572     // Load a session from specific file path.
573     bool qsamplerMainForm::loadSessionFile ( const QString& sFilename )
574     {
575     if (m_pClient == NULL)
576     return false;
577    
578     // Open and read from real file.
579     QFile file(sFilename);
580     if (!file.open(IO_ReadOnly)) {
581     appendMessagesError(tr("Could not open \"%1\" session file.\n\nSorry.").arg(sFilename));
582     return false;
583     }
584    
585     // Read the file.
586     int iErrors = 0;
587     QTextStream ts(&file);
588     while (!ts.atEnd()) {
589     // Read the line.
590     QString sCommand = ts.readLine().simplifyWhiteSpace();
591     // If not empty, nor a comment, call the server...
592     if (!sCommand.isEmpty() && sCommand[0] != '#') {
593     appendMessagesColor(sCommand, "#996633");
594     // Remember that, no matter what,
595     // all LSCP commands are CR/LF terminated.
596     sCommand += "\r\n";
597     if (::lscp_client_query(m_pClient, sCommand.latin1()) != LSCP_OK) {
598     appendMessagesClient("lscp_client_query");
599     iErrors++;
600 capela 388 break;
601 capela 109 }
602     }
603     // Try to make it snappy :)
604     QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
605     }
606    
607     // Ok. we've read it.
608     file.close();
609    
610     // Have we any errors?
611     if (iErrors > 0)
612 capela 388 appendMessagesError(tr("Session could not be loaded\nfrom \"%1\".\n\nSorry.").arg(sFilename));
613 capela 109
614 capela 395 // Now we'll try to create (update) the whole GUI session.
615     updateSession();
616 capela 109
617     // Save as default session directory.
618     if (m_pOptions)
619     m_pOptions->sSessionDir = QFileInfo(sFilename).dirPath(true);
620     // We're not dirty anymore.
621     m_iDirtyCount = 0;
622     // Stabilize form...
623     m_sFilename = sFilename;
624     updateRecentFiles(sFilename);
625     appendMessages(tr("Open session: \"%1\".").arg(sessionName(m_sFilename)));
626 capela 301
627     // Make that an overall update.
628 capela 109 stabilizeForm();
629     return true;
630     }
631    
632    
633     // Save current session to specific file path.
634     bool qsamplerMainForm::saveSessionFile ( const QString& sFilename )
635     {
636     // Open and write into real file.
637     QFile file(sFilename);
638     if (!file.open(IO_WriteOnly | IO_Truncate)) {
639     appendMessagesError(tr("Could not open \"%1\" session file.\n\nSorry.").arg(sFilename));
640     return false;
641     }
642    
643     // Write the file.
644     int iErrors = 0;
645     QTextStream ts(&file);
646     ts << "# " << QSAMPLER_TITLE " - " << tr(QSAMPLER_SUBTITLE) << endl;
647     ts << "# " << tr("Version")
648     << ": " QSAMPLER_VERSION << endl;
649     ts << "# " << tr("Build")
650     << ": " __DATE__ " " __TIME__ << endl;
651     ts << "#" << endl;
652     ts << "# " << tr("File")
653     << ": " << QFileInfo(sFilename).fileName() << endl;
654     ts << "# " << tr("Date")
655     << ": " << QDate::currentDate().toString("MMMM dd yyyy")
656     << " " << QTime::currentTime().toString("hh:mm:ss") << endl;
657     ts << "#" << endl;
658     ts << endl;
659     QWidgetList wlist = m_pWorkspace->windowList();
660     for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
661 capela 264 qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
662     if (pChannelStrip) {
663     qsamplerChannel *pChannel = pChannelStrip->channel();
664     if (pChannel) {
665 capela 409 ts << "# Channel " << iChannel << endl;
666 capela 264 ts << "ADD CHANNEL" << endl;
667 capela 409 ts << "SET CHANNEL AUDIO_OUTPUT_TYPE " << iChannel << " " << pChannel->audioDriver() << endl;
668     ts << "SET CHANNEL MIDI_INPUT_TYPE " << iChannel << " " << pChannel->midiDriver() << endl;
669     // ts << "SET CHANNEL MIDI_INPUT_PORT " << iChannel << " " << pChannel->midiPort() << endl;
670     ts << "SET CHANNEL MIDI_INPUT_CHANNEL " << iChannel << " ";
671 capela 304 if (pChannel->midiChannel() == LSCP_MIDI_CHANNEL_ALL)
672     ts << "ALL";
673     else
674 capela 264 ts << pChannel->midiChannel();
675     ts << endl;
676 capela 409 ts << "LOAD ENGINE " << pChannel->engineName() << " " << iChannel << endl;
677     ts << "LOAD INSTRUMENT NON_MODAL '" << pChannel->instrumentFile() << "' " << pChannel->instrumentNr() << " " << iChannel << endl;
678     ts << "SET CHANNEL VOLUME " << iChannel << " " << pChannel->volume() << endl;
679 capela 264 ts << endl;
680     }
681     }
682 capela 109 // Try to keep it snappy :)
683     QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
684     }
685    
686     // Ok. we've wrote it.
687     file.close();
688    
689     // Have we any errors?
690     if (iErrors > 0)
691     appendMessagesError(tr("Some settings could not be saved\nto \"%1\" session file.\n\nSorry.").arg(sFilename));
692    
693     // Save as default session directory.
694     if (m_pOptions)
695     m_pOptions->sSessionDir = QFileInfo(sFilename).dirPath(true);
696     // We're not dirty anymore.
697     m_iDirtyCount = 0;
698     // Stabilize form...
699     m_sFilename = sFilename;
700     updateRecentFiles(sFilename);
701     appendMessages(tr("Save session: \"%1\".").arg(sessionName(m_sFilename)));
702     stabilizeForm();
703     return true;
704     }
705    
706    
707     //-------------------------------------------------------------------------
708     // qsamplerMainForm -- File Action slots.
709    
710     // Create a new sampler session.
711     void qsamplerMainForm::fileNew (void)
712     {
713     // Of course we'll start clean new.
714     newSession();
715     }
716    
717    
718     // Open an existing sampler session.
719     void qsamplerMainForm::fileOpen (void)
720     {
721     // Open it right away.
722     openSession();
723     }
724    
725    
726     // Open a recent file session.
727     void qsamplerMainForm::fileOpenRecent ( int iIndex )
728     {
729     // Check if we can safely close the current session...
730     if (m_pOptions && closeSession(true)) {
731     QString sFilename = m_pOptions->recentFiles[iIndex];
732     loadSessionFile(sFilename);
733     }
734     }
735    
736    
737     // Save current sampler session.
738     void qsamplerMainForm::fileSave (void)
739     {
740     // Save it right away.
741     saveSession(false);
742     }
743    
744    
745     // Save current sampler session with another name.
746     void qsamplerMainForm::fileSaveAs (void)
747     {
748     // Save it right away, maybe with another name.
749     saveSession(true);
750     }
751    
752    
753 capela 255 // Reset the sampler instance.
754     void qsamplerMainForm::fileReset (void)
755     {
756     if (m_pClient == NULL)
757     return;
758    
759     // Ask user whether he/she want's an internal sampler reset...
760     if (QMessageBox::warning(this, tr("Warning"),
761     tr("Resetting the sampler instance will close\n"
762     "all device and channel configurations.\n\n"
763     "Please note that this operation may cause\n"
764     "temporary MIDI and Audio disruption\n\n"
765     "Do you want to reset the sampler engine now?"),
766     tr("Reset"), tr("Cancel")) > 0)
767     return;
768    
769     // Just do the reset, after closing down current session...
770 capela 261 if (closeSession(true) && ::lscp_reset_sampler(m_pClient) != LSCP_OK) {
771 capela 255 appendMessagesClient("lscp_reset_sampler");
772 capela 261 appendMessagesError(tr("Could not reset sampler instance.\n\nSorry."));
773     return;
774     }
775    
776     // Log this.
777     appendMessages(tr("Sampler reset."));
778 capela 395
779     // Make it a new session...
780     newSession();
781 capela 255 }
782    
783    
784 capela 109 // Restart the client/server instance.
785     void qsamplerMainForm::fileRestart (void)
786     {
787     if (m_pOptions == NULL)
788     return;
789    
790     bool bRestart = true;
791    
792     // Ask user whether he/she want's a complete restart...
793     // (if we're currently up and running)
794     if (bRestart && m_pClient) {
795     bRestart = (QMessageBox::warning(this, tr("Warning"),
796     tr("New settings will be effective after\n"
797     "restarting the client/server connection.\n\n"
798     "Please note that this operation may cause\n"
799     "temporary MIDI and Audio disruption\n\n"
800     "Do you want to restart the connection now?"),
801     tr("Restart"), tr("Cancel")) == 0);
802     }
803    
804     // Are we still for it?
805     if (bRestart && closeSession(true)) {
806     // Stop server, it will force the client too.
807     stopServer();
808     // Reschedule a restart...
809     startSchedule(m_pOptions->iStartDelay);
810     }
811     }
812    
813    
814     // Exit application program.
815     void qsamplerMainForm::fileExit (void)
816     {
817     // Go for close the whole thing.
818     close();
819     }
820    
821    
822     //-------------------------------------------------------------------------
823     // qsamplerMainForm -- Edit Action slots.
824    
825     // Add a new sampler channel.
826     void qsamplerMainForm::editAddChannel (void)
827     {
828     if (m_pClient == NULL)
829     return;
830    
831 capela 303 // Just create the channel instance...
832     qsamplerChannel *pChannel = new qsamplerChannel(this);
833     if (pChannel == NULL)
834     return;
835    
836     // Before we show it up, may be we'll
837     // better ask for some initial values?
838     if (!pChannel->channelSetup(this)) {
839     delete pChannel;
840     return;
841     }
842    
843     // And give it to the strip (will own the channel instance, if successful).
844     if (!createChannelStrip(pChannel)) {
845     delete pChannel;
846     return;
847     }
848    
849     // Make that an overall update.
850     m_iDirtyCount++;
851     stabilizeForm();
852 capela 109 }
853    
854    
855     // Remove current sampler channel.
856     void qsamplerMainForm::editRemoveChannel (void)
857     {
858     if (m_pClient == NULL)
859     return;
860    
861 capela 264 qsamplerChannelStrip *pChannelStrip = activeChannelStrip();
862     if (pChannelStrip == NULL)
863     return;
864    
865     qsamplerChannel *pChannel = pChannelStrip->channel();
866 capela 109 if (pChannel == NULL)
867     return;
868    
869     // Prompt user if he/she's sure about this...
870     if (m_pOptions && m_pOptions->bConfirmRemove) {
871     if (QMessageBox::warning(this, tr("Warning"),
872     tr("About to remove channel:\n\n"
873     "%1\n\n"
874     "Are you sure?")
875 capela 264 .arg(pChannelStrip->caption()),
876 capela 109 tr("OK"), tr("Cancel")) > 0)
877     return;
878     }
879    
880     // Remove the existing sampler channel.
881 capela 295 if (!pChannel->removeChannel())
882 capela 109 return;
883    
884     // Just delete the channel strip.
885 capela 265 delete pChannelStrip;
886    
887 capela 109 // Do we auto-arrange?
888     if (m_pOptions && m_pOptions->bAutoArrange)
889     channelsArrange();
890    
891     // We'll be dirty, for sure...
892     m_iDirtyCount++;
893     stabilizeForm();
894     }
895    
896    
897     // Setup current sampler channel.
898     void qsamplerMainForm::editSetupChannel (void)
899     {
900     if (m_pClient == NULL)
901     return;
902    
903 capela 264 qsamplerChannelStrip *pChannelStrip = activeChannelStrip();
904     if (pChannelStrip == NULL)
905 capela 109 return;
906    
907     // Just invoque the channel strip procedure.
908 capela 295 pChannelStrip->channelSetup();
909 capela 109 }
910    
911    
912     // Reset current sampler channel.
913     void qsamplerMainForm::editResetChannel (void)
914     {
915     if (m_pClient == NULL)
916     return;
917    
918 capela 264 qsamplerChannelStrip *pChannelStrip = activeChannelStrip();
919     if (pChannelStrip == NULL)
920     return;
921    
922 capela 400 // Just invoque the channel strip procedure.
923     pChannelStrip->channelReset();
924 capela 109 }
925    
926    
927 capela 404 // Reset all sampler channels.
928     void qsamplerMainForm::editResetAllChannels (void)
929     {
930     if (m_pClient == NULL)
931     return;
932    
933     // Invoque the channel strip procedure,
934     // for all channels out there...
935     m_pWorkspace->setUpdatesEnabled(false);
936     QWidgetList wlist = m_pWorkspace->windowList();
937     for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
938     qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
939     if (pChannelStrip)
940     pChannelStrip->channelReset();
941     }
942     m_pWorkspace->setUpdatesEnabled(true);
943     }
944    
945    
946 capela 109 //-------------------------------------------------------------------------
947     // qsamplerMainForm -- View Action slots.
948    
949     // Show/hide the main program window menubar.
950     void qsamplerMainForm::viewMenubar ( bool bOn )
951     {
952     if (bOn)
953     MenuBar->show();
954     else
955     MenuBar->hide();
956     }
957    
958    
959     // Show/hide the main program window toolbar.
960     void qsamplerMainForm::viewToolbar ( bool bOn )
961     {
962     if (bOn) {
963     fileToolbar->show();
964     editToolbar->show();
965     channelsToolbar->show();
966     } else {
967     fileToolbar->hide();
968     editToolbar->hide();
969     channelsToolbar->hide();
970     }
971     }
972    
973    
974     // Show/hide the main program window statusbar.
975     void qsamplerMainForm::viewStatusbar ( bool bOn )
976     {
977     if (bOn)
978     statusBar()->show();
979     else
980     statusBar()->hide();
981     }
982    
983    
984     // Show/hide the messages window logger.
985     void qsamplerMainForm::viewMessages ( bool bOn )
986     {
987     if (bOn)
988     m_pMessages->show();
989     else
990     m_pMessages->hide();
991     }
992    
993    
994 capela 428 // Show/hide the device configurator form.
995     void qsamplerMainForm::viewDevices (void)
996     {
997     if (m_pOptions == NULL)
998     return;
999    
1000     if (m_pDeviceForm) {
1001     m_pOptions->saveWidgetGeometry(m_pDeviceForm);
1002     m_pDeviceForm->setClient(m_pClient);
1003     if (m_pDeviceForm->isVisible()) {
1004     m_pDeviceForm->hide();
1005     } else {
1006     m_pDeviceForm->show();
1007     m_pDeviceForm->raise();
1008     m_pDeviceForm->setActiveWindow();
1009     }
1010     }
1011     }
1012    
1013    
1014 capela 109 // Show options dialog.
1015     void qsamplerMainForm::viewOptions (void)
1016     {
1017     if (m_pOptions == NULL)
1018     return;
1019    
1020     qsamplerOptionsForm *pOptionsForm = new qsamplerOptionsForm(this);
1021     if (pOptionsForm) {
1022     // Check out some initial nullities(tm)...
1023 capela 264 qsamplerChannelStrip *pChannelStrip = activeChannelStrip();
1024     if (m_pOptions->sDisplayFont.isEmpty() && pChannelStrip)
1025     m_pOptions->sDisplayFont = pChannelStrip->displayFont().toString();
1026 capela 109 if (m_pOptions->sMessagesFont.isEmpty() && m_pMessages)
1027     m_pOptions->sMessagesFont = m_pMessages->messagesFont().toString();
1028     // To track down deferred or immediate changes.
1029     QString sOldServerHost = m_pOptions->sServerHost;
1030     int iOldServerPort = m_pOptions->iServerPort;
1031     int iOldServerTimeout = m_pOptions->iServerTimeout;
1032     bool bOldServerStart = m_pOptions->bServerStart;
1033     QString sOldServerCmdLine = m_pOptions->sServerCmdLine;
1034     QString sOldDisplayFont = m_pOptions->sDisplayFont;
1035 capela 267 bool bOldDisplayEffect = m_pOptions->bDisplayEffect;
1036 capela 119 int iOldMaxVolume = m_pOptions->iMaxVolume;
1037 capela 109 QString sOldMessagesFont = m_pOptions->sMessagesFont;
1038     bool bOldStdoutCapture = m_pOptions->bStdoutCapture;
1039     int bOldMessagesLimit = m_pOptions->bMessagesLimit;
1040     int iOldMessagesLimitLines = m_pOptions->iMessagesLimitLines;
1041     bool bOldCompletePath = m_pOptions->bCompletePath;
1042 capela 371 bool bOldInstrumentNames = m_pOptions->bInstrumentNames;
1043 capela 109 int iOldMaxRecentFiles = m_pOptions->iMaxRecentFiles;
1044     // Load the current setup settings.
1045     pOptionsForm->setup(m_pOptions);
1046     // Show the setup dialog...
1047     if (pOptionsForm->exec()) {
1048     // Warn if something will be only effective on next run.
1049     if (( bOldStdoutCapture && !m_pOptions->bStdoutCapture) ||
1050     (!bOldStdoutCapture && m_pOptions->bStdoutCapture)) {
1051     QMessageBox::information(this, tr("Information"),
1052     tr("Some settings may be only effective\n"
1053     "next time you start this program."), tr("OK"));
1054     updateMessagesCapture();
1055     }
1056     // Check wheather something immediate has changed.
1057     if (( bOldCompletePath && !m_pOptions->bCompletePath) ||
1058     (!bOldCompletePath && m_pOptions->bCompletePath) ||
1059     (iOldMaxRecentFiles != m_pOptions->iMaxRecentFiles))
1060     updateRecentFilesMenu();
1061 capela 371 if (( bOldInstrumentNames && !m_pOptions->bInstrumentNames) ||
1062     (!bOldInstrumentNames && m_pOptions->bInstrumentNames))
1063     updateInstrumentNames();
1064 capela 267 if (( bOldDisplayEffect && !m_pOptions->bDisplayEffect) ||
1065     (!bOldDisplayEffect && m_pOptions->bDisplayEffect))
1066     updateDisplayEffect();
1067 capela 109 if (sOldDisplayFont != m_pOptions->sDisplayFont)
1068     updateDisplayFont();
1069 capela 119 if (iOldMaxVolume != m_pOptions->iMaxVolume)
1070     updateMaxVolume();
1071 capela 109 if (sOldMessagesFont != m_pOptions->sMessagesFont)
1072     updateMessagesFont();
1073     if (( bOldMessagesLimit && !m_pOptions->bMessagesLimit) ||
1074     (!bOldMessagesLimit && m_pOptions->bMessagesLimit) ||
1075     (iOldMessagesLimitLines != m_pOptions->iMessagesLimitLines))
1076     updateMessagesLimit();
1077     // And now the main thing, whether we'll do client/server recycling?
1078     if ((sOldServerHost != m_pOptions->sServerHost) ||
1079     (iOldServerPort != m_pOptions->iServerPort) ||
1080     (iOldServerTimeout != m_pOptions->iServerTimeout) ||
1081     ( bOldServerStart && !m_pOptions->bServerStart) ||
1082     (!bOldServerStart && m_pOptions->bServerStart) ||
1083     (sOldServerCmdLine != m_pOptions->sServerCmdLine && m_pOptions->bServerStart))
1084     fileRestart();
1085     }
1086     // Done.
1087     delete pOptionsForm;
1088     }
1089    
1090     // This makes it.
1091     stabilizeForm();
1092     }
1093    
1094    
1095     //-------------------------------------------------------------------------
1096     // qsamplerMainForm -- Channels action slots.
1097    
1098     // Arrange channel strips.
1099     void qsamplerMainForm::channelsArrange (void)
1100     {
1101     // Full width vertical tiling
1102     QWidgetList wlist = m_pWorkspace->windowList();
1103     if (wlist.isEmpty())
1104     return;
1105    
1106     m_pWorkspace->setUpdatesEnabled(false);
1107     int y = 0;
1108     for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1109 capela 264 qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1110     /* if (pChannelStrip->testWState(WState_Maximized | WState_Minimized)) {
1111 capela 109 // Prevent flicker...
1112 capela 264 pChannelStrip->hide();
1113     pChannelStrip->showNormal();
1114 capela 109 } */
1115 capela 264 pChannelStrip->adjustSize();
1116 capela 109 int iWidth = m_pWorkspace->width();
1117 capela 264 if (iWidth < pChannelStrip->width())
1118     iWidth = pChannelStrip->width();
1119     // int iHeight = pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();
1120     int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();
1121     pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);
1122 capela 109 y += iHeight;
1123     }
1124     m_pWorkspace->setUpdatesEnabled(true);
1125    
1126     stabilizeForm();
1127     }
1128    
1129    
1130     // Auto-arrange channel strips.
1131     void qsamplerMainForm::channelsAutoArrange ( bool bOn )
1132     {
1133     if (m_pOptions == NULL)
1134     return;
1135    
1136     // Toggle the auto-arrange flag.
1137     m_pOptions->bAutoArrange = bOn;
1138    
1139     // If on, update whole workspace...
1140     if (m_pOptions->bAutoArrange)
1141     channelsArrange();
1142     }
1143    
1144    
1145     //-------------------------------------------------------------------------
1146     // qsamplerMainForm -- Help Action slots.
1147    
1148     // Show information about the Qt toolkit.
1149     void qsamplerMainForm::helpAboutQt (void)
1150     {
1151     QMessageBox::aboutQt(this);
1152     }
1153    
1154    
1155     // Show information about application program.
1156     void qsamplerMainForm::helpAbout (void)
1157     {
1158     // Stuff the about box text...
1159     QString sText = "<p>\n";
1160     sText += "<b>" QSAMPLER_TITLE " - " + tr(QSAMPLER_SUBTITLE) + "</b><br />\n";
1161     sText += "<br />\n";
1162     sText += tr("Version") + ": <b>" QSAMPLER_VERSION "</b><br />\n";
1163     sText += "<small>" + tr("Build") + ": " __DATE__ " " __TIME__ "</small><br />\n";
1164     #ifdef CONFIG_DEBUG
1165     sText += "<small><font color=\"red\">";
1166     sText += tr("Debugging option enabled.");
1167     sText += "</font></small><br />";
1168     #endif
1169 capela 176 #ifndef CONFIG_LIBGIG
1170     sText += "<small><font color=\"red\">";
1171     sText += tr("GIG (libgig) file support disabled.");
1172     sText += "</font></small><br />";
1173     #endif
1174 capela 382 #ifndef CONFIG_INSTRUMENT_NAME
1175     sText += "<small><font color=\"red\">";
1176     sText += tr("LSCP (liblscp) instrument_name support disabled.");
1177     sText += "</font></small><br />";
1178     #endif
1179 capela 109 sText += "<br />\n";
1180     sText += tr("Using") + ": ";
1181     sText += ::lscp_client_package();
1182     sText += " ";
1183     sText += ::lscp_client_version();
1184     sText += "<br />\n";
1185     sText += "<br />\n";
1186     sText += tr("Website") + ": <a href=\"" QSAMPLER_WEBSITE "\">" QSAMPLER_WEBSITE "</a><br />\n";
1187     sText += "<br />\n";
1188     sText += "<small>";
1189     sText += QSAMPLER_COPYRIGHT "<br />\n";
1190     sText += "<br />\n";
1191     sText += tr("This program is free software; you can redistribute it and/or modify it") + "<br />\n";
1192     sText += tr("under the terms of the GNU General Public License version 2 or later.");
1193     sText += "</small>";
1194     sText += "</p>\n";
1195    
1196     QMessageBox::about(this, tr("About") + " " QSAMPLER_TITLE, sText);
1197     }
1198    
1199    
1200     //-------------------------------------------------------------------------
1201     // qsamplerMainForm -- Main window stabilization.
1202    
1203     void qsamplerMainForm::stabilizeForm (void)
1204     {
1205     // Update the main application caption...
1206 capela 418 QString sSessionName = sessionName(m_sFilename);
1207 capela 109 if (m_iDirtyCount > 0)
1208 capela 418 sSessionName += '*';
1209     setCaption(tr(QSAMPLER_TITLE " - [%1]").arg(sSessionName));
1210 capela 109
1211     // Update the main menu state...
1212 capela 264 qsamplerChannelStrip *pChannelStrip = activeChannelStrip();
1213 capela 109 bool bHasClient = (m_pOptions != NULL && m_pClient != NULL);
1214 capela 264 bool bHasChannel = (bHasClient && pChannelStrip != NULL);
1215 capela 109 fileNewAction->setEnabled(bHasClient);
1216     fileOpenAction->setEnabled(bHasClient);
1217     fileSaveAction->setEnabled(bHasClient && m_iDirtyCount > 0);
1218     fileSaveAsAction->setEnabled(bHasClient);
1219 capela 255 fileResetAction->setEnabled(bHasClient);
1220 capela 109 fileRestartAction->setEnabled(bHasClient || m_pServer == NULL);
1221     editAddChannelAction->setEnabled(bHasClient);
1222     editRemoveChannelAction->setEnabled(bHasChannel);
1223     editSetupChannelAction->setEnabled(bHasChannel);
1224     editResetChannelAction->setEnabled(bHasChannel);
1225 capela 404 editResetAllChannelsAction->setEnabled(bHasChannel);
1226 capela 428 viewMessagesAction->setOn(m_pMessages && m_pMessages->isVisible());
1227     viewDevicesAction->setOn(m_pDeviceForm && m_pDeviceForm->isVisible());
1228     viewDevicesAction->setEnabled(bHasClient);
1229 capela 109 channelsArrangeAction->setEnabled(bHasChannel);
1230    
1231     // Client/Server status...
1232     if (bHasClient) {
1233 capela 428 m_statusItem[QSAMPLER_STATUS_CLIENT]->setText(tr("Connected"));
1234     m_statusItem[QSAMPLER_STATUS_SERVER]->setText(m_pOptions->sServerHost + ":" + QString::number(m_pOptions->iServerPort));
1235 capela 109 } else {
1236 capela 428 m_statusItem[QSAMPLER_STATUS_CLIENT]->clear();
1237     m_statusItem[QSAMPLER_STATUS_SERVER]->clear();
1238 capela 109 }
1239     // Channel status...
1240     if (bHasChannel)
1241 capela 428 m_statusItem[QSAMPLER_STATUS_CHANNEL]->setText(pChannelStrip->caption());
1242 capela 109 else
1243 capela 428 m_statusItem[QSAMPLER_STATUS_CHANNEL]->clear();
1244 capela 109 // Session status...
1245     if (m_iDirtyCount > 0)
1246 capela 428 m_statusItem[QSAMPLER_STATUS_SESSION]->setText(tr("MOD"));
1247 capela 109 else
1248 capela 428 m_statusItem[QSAMPLER_STATUS_SESSION]->clear();
1249 capela 109
1250     // Recent files menu.
1251     m_pRecentFilesMenu->setEnabled(bHasClient && m_pOptions->recentFiles.count() > 0);
1252    
1253     // Always make the latest message visible.
1254     if (m_pMessages)
1255     m_pMessages->scrollToBottom();
1256     }
1257    
1258    
1259     // Channel change receiver slot.
1260 capela 400 void qsamplerMainForm::channelStripChanged( qsamplerChannelStrip *pChannelStrip )
1261 capela 109 {
1262 capela 400 // Add this strip to the changed list...
1263     if (m_changedStrips.containsRef(pChannelStrip) == 0)
1264     m_changedStrips.append(pChannelStrip);
1265    
1266 capela 109 // Just mark the dirty form.
1267     m_iDirtyCount++;
1268     // and update the form status...
1269     stabilizeForm();
1270     }
1271    
1272    
1273 capela 395 // Grab and restore current sampler channels session.
1274     void qsamplerMainForm::updateSession (void)
1275     {
1276     // Retrieve the current channel list.
1277     int *piChannelIDs = ::lscp_list_channels(m_pClient);
1278     if (piChannelIDs == NULL) {
1279     if (::lscp_client_get_errno(m_pClient)) {
1280     appendMessagesClient("lscp_list_channels");
1281     appendMessagesError(tr("Could not get current list of channels.\n\nSorry."));
1282     }
1283     return;
1284     }
1285    
1286     // Try to (re)create each channel.
1287     m_pWorkspace->setUpdatesEnabled(false);
1288     for (int iChannel = 0; piChannelIDs[iChannel] >= 0; iChannel++) {
1289     // Check if theres already a channel strip for this one...
1290     if (!channelStrip(piChannelIDs[iChannel]))
1291     createChannelStrip(new qsamplerChannel(this, piChannelIDs[iChannel]));
1292     // Make it visibly responsive...
1293     QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
1294     }
1295     m_pWorkspace->setUpdatesEnabled(true);
1296     }
1297    
1298    
1299 capela 109 // Update the recent files list and menu.
1300     void qsamplerMainForm::updateRecentFiles ( const QString& sFilename )
1301     {
1302     if (m_pOptions == NULL)
1303     return;
1304    
1305     // Remove from list if already there (avoid duplicates)
1306     QStringList::Iterator iter = m_pOptions->recentFiles.find(sFilename);
1307     if (iter != m_pOptions->recentFiles.end())
1308     m_pOptions->recentFiles.remove(iter);
1309     // Put it to front...
1310     m_pOptions->recentFiles.push_front(sFilename);
1311    
1312     // May update the menu.
1313     updateRecentFilesMenu();
1314     }
1315    
1316    
1317     // Update the recent files list and menu.
1318     void qsamplerMainForm::updateRecentFilesMenu (void)
1319     {
1320     if (m_pOptions == NULL)
1321     return;
1322    
1323     // Time to keep the list under limits.
1324     int iRecentFiles = m_pOptions->recentFiles.count();
1325     while (iRecentFiles > m_pOptions->iMaxRecentFiles) {
1326     m_pOptions->recentFiles.pop_back();
1327     iRecentFiles--;
1328     }
1329    
1330     // rebuild the recent files menu...
1331     m_pRecentFilesMenu->clear();
1332     for (int i = 0; i < iRecentFiles; i++) {
1333     const QString& sFilename = m_pOptions->recentFiles[i];
1334     if (QFileInfo(sFilename).exists()) {
1335     m_pRecentFilesMenu->insertItem(QString("&%1 %2")
1336     .arg(i + 1).arg(sessionName(sFilename)),
1337     this, SLOT(fileOpenRecent(int)), 0, i);
1338     }
1339     }
1340     }
1341    
1342    
1343 capela 371 // Force update of the channels instrument names mode.
1344     void qsamplerMainForm::updateInstrumentNames (void)
1345     {
1346     // Full channel list update...
1347     QWidgetList wlist = m_pWorkspace->windowList();
1348     if (wlist.isEmpty())
1349     return;
1350    
1351     m_pWorkspace->setUpdatesEnabled(false);
1352     for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1353     qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1354     if (pChannelStrip)
1355     pChannelStrip->updateInstrumentName(true);
1356     }
1357     m_pWorkspace->setUpdatesEnabled(true);
1358     }
1359    
1360    
1361 capela 109 // Force update of the channels display font.
1362     void qsamplerMainForm::updateDisplayFont (void)
1363     {
1364     if (m_pOptions == NULL)
1365     return;
1366    
1367     // Check if display font is legal.
1368     if (m_pOptions->sDisplayFont.isEmpty())
1369     return;
1370     // Realize it.
1371     QFont font;
1372     if (!font.fromString(m_pOptions->sDisplayFont))
1373     return;
1374    
1375     // Full channel list update...
1376     QWidgetList wlist = m_pWorkspace->windowList();
1377     if (wlist.isEmpty())
1378     return;
1379    
1380     m_pWorkspace->setUpdatesEnabled(false);
1381     for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1382 capela 264 qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1383     if (pChannelStrip)
1384     pChannelStrip->setDisplayFont(font);
1385 capela 109 }
1386     m_pWorkspace->setUpdatesEnabled(true);
1387     }
1388    
1389    
1390 capela 267 // Update channel strips background effect.
1391     void qsamplerMainForm::updateDisplayEffect (void)
1392     {
1393     QPixmap pm;
1394     if (m_pOptions->bDisplayEffect)
1395     pm = QPixmap::fromMimeSource("displaybg1.png");
1396    
1397     // Full channel list update...
1398     QWidgetList wlist = m_pWorkspace->windowList();
1399     if (wlist.isEmpty())
1400     return;
1401    
1402     m_pWorkspace->setUpdatesEnabled(false);
1403     for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1404     qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1405     if (pChannelStrip)
1406     pChannelStrip->setDisplayBackground(pm);
1407     }
1408     m_pWorkspace->setUpdatesEnabled(true);
1409     }
1410    
1411    
1412 capela 119 // Force update of the channels maximum volume setting.
1413     void qsamplerMainForm::updateMaxVolume (void)
1414     {
1415     if (m_pOptions == NULL)
1416     return;
1417    
1418     // Full channel list update...
1419     QWidgetList wlist = m_pWorkspace->windowList();
1420     if (wlist.isEmpty())
1421     return;
1422    
1423     m_pWorkspace->setUpdatesEnabled(false);
1424     for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1425 capela 264 qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1426     if (pChannelStrip)
1427     pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
1428 capela 119 }
1429     m_pWorkspace->setUpdatesEnabled(true);
1430     }
1431    
1432    
1433 capela 109 //-------------------------------------------------------------------------
1434     // qsamplerMainForm -- Messages window form handlers.
1435    
1436     // Messages output methods.
1437     void qsamplerMainForm::appendMessages( const QString& s )
1438     {
1439     if (m_pMessages)
1440     m_pMessages->appendMessages(s);
1441    
1442     statusBar()->message(s, 3000);
1443     }
1444    
1445     void qsamplerMainForm::appendMessagesColor( const QString& s, const QString& c )
1446     {
1447     if (m_pMessages)
1448     m_pMessages->appendMessagesColor(s, c);
1449    
1450     statusBar()->message(s, 3000);
1451     }
1452    
1453     void qsamplerMainForm::appendMessagesText( const QString& s )
1454     {
1455     if (m_pMessages)
1456     m_pMessages->appendMessagesText(s);
1457     }
1458    
1459     void qsamplerMainForm::appendMessagesError( const QString& s )
1460     {
1461     if (m_pMessages)
1462     m_pMessages->show();
1463    
1464     appendMessagesColor(s.simplifyWhiteSpace(), "#ff0000");
1465    
1466     QMessageBox::critical(this, tr("Error"), s, tr("Cancel"));
1467     }
1468    
1469    
1470     // This is a special message format, just for client results.
1471     void qsamplerMainForm::appendMessagesClient( const QString& s )
1472     {
1473     if (m_pClient == NULL)
1474     return;
1475    
1476     appendMessagesColor(s + QString(": %1 (errno=%2)")
1477     .arg(::lscp_client_get_result(m_pClient))
1478     .arg(::lscp_client_get_errno(m_pClient)), "#996666");
1479     }
1480    
1481    
1482     // Force update of the messages font.
1483     void qsamplerMainForm::updateMessagesFont (void)
1484     {
1485     if (m_pOptions == NULL)
1486     return;
1487    
1488     if (m_pMessages && !m_pOptions->sMessagesFont.isEmpty()) {
1489     QFont font;
1490     if (font.fromString(m_pOptions->sMessagesFont))
1491     m_pMessages->setMessagesFont(font);
1492     }
1493     }
1494    
1495    
1496     // Update messages window line limit.
1497     void qsamplerMainForm::updateMessagesLimit (void)
1498     {
1499     if (m_pOptions == NULL)
1500     return;
1501    
1502     if (m_pMessages) {
1503     if (m_pOptions->bMessagesLimit)
1504     m_pMessages->setMessagesLimit(m_pOptions->iMessagesLimitLines);
1505     else
1506     m_pMessages->setMessagesLimit(0);
1507     }
1508     }
1509    
1510    
1511     // Enablement of the messages capture feature.
1512     void qsamplerMainForm::updateMessagesCapture (void)
1513     {
1514     if (m_pOptions == NULL)
1515     return;
1516    
1517     if (m_pMessages)
1518     m_pMessages->setCaptureEnabled(m_pOptions->bStdoutCapture);
1519     }
1520    
1521    
1522     //-------------------------------------------------------------------------
1523     // qsamplerMainForm -- MDI channel strip management.
1524    
1525     // The channel strip creation executive.
1526 capela 303 qsamplerChannelStrip *qsamplerMainForm::createChannelStrip ( qsamplerChannel *pChannel )
1527 capela 109 {
1528 capela 303 if (m_pClient == NULL || pChannel == NULL)
1529 capela 295 return NULL;
1530 capela 109
1531     // Prepare for auto-arrange?
1532 capela 264 qsamplerChannelStrip *pChannelStrip = NULL;
1533 capela 109 int y = 0;
1534     if (m_pOptions && m_pOptions->bAutoArrange) {
1535     QWidgetList wlist = m_pWorkspace->windowList();
1536     for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1537 capela 264 pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1538 capela 395 if (pChannelStrip) {
1539     // y += pChannelStrip->height() + pChannelStrip->parentWidget()->baseSize().height();
1540     y += pChannelStrip->parentWidget()->frameGeometry().height();
1541     }
1542 capela 109 }
1543     }
1544    
1545     // Add a new channel itema...
1546     WFlags wflags = Qt::WStyle_Customize | Qt::WStyle_Tool | Qt::WStyle_Title | Qt::WStyle_NoBorder;
1547 capela 264 pChannelStrip = new qsamplerChannelStrip(m_pWorkspace, 0, wflags);
1548 capela 303 if (pChannelStrip == NULL)
1549     return NULL;
1550    
1551     // Actual channel strip setup...
1552     pChannelStrip->setup(pChannel);
1553 capela 295 QObject::connect(pChannelStrip, SIGNAL(channelChanged(qsamplerChannelStrip *)), this, SLOT(channelStripChanged(qsamplerChannelStrip *)));
1554 capela 267 // Set some initial aesthetic options...
1555     if (m_pOptions) {
1556     // Background display effect...
1557     pChannelStrip->setDisplayEffect(m_pOptions->bDisplayEffect);
1558     // We'll need a display font.
1559     QFont font;
1560     if (font.fromString(m_pOptions->sDisplayFont))
1561     pChannelStrip->setDisplayFont(font);
1562     // Maximum allowed volume setting.
1563     pChannelStrip->setMaxVolume(m_pOptions->iMaxVolume);
1564     }
1565 capela 295
1566 capela 109 // Now we show up us to the world.
1567 capela 264 pChannelStrip->show();
1568 capela 109 // Only then, we'll auto-arrange...
1569     if (m_pOptions && m_pOptions->bAutoArrange) {
1570     int iWidth = m_pWorkspace->width();
1571     // int iHeight = pChannel->height() + pChannel->parentWidget()->baseSize().height();
1572 capela 264 int iHeight = pChannelStrip->parentWidget()->frameGeometry().height();
1573     pChannelStrip->parentWidget()->setGeometry(0, y, iWidth, iHeight);
1574 capela 109 }
1575 capela 400
1576     // This is pretty new, so we'll watch for it closely.
1577     channelStripChanged(pChannelStrip);
1578    
1579 capela 295 // Return our successful reference...
1580     return pChannelStrip;
1581 capela 109 }
1582    
1583    
1584     // Retrieve the active channel strip.
1585 capela 264 qsamplerChannelStrip *qsamplerMainForm::activeChannelStrip (void)
1586 capela 109 {
1587     return (qsamplerChannelStrip *) m_pWorkspace->activeWindow();
1588     }
1589    
1590    
1591     // Retrieve a channel strip by index.
1592 capela 264 qsamplerChannelStrip *qsamplerMainForm::channelStripAt ( int iChannel )
1593 capela 109 {
1594     QWidgetList wlist = m_pWorkspace->windowList();
1595     if (wlist.isEmpty())
1596 capela 395 return NULL;
1597 capela 109
1598     return (qsamplerChannelStrip *) wlist.at(iChannel);
1599     }
1600    
1601    
1602 capela 395 // Retrieve a channel strip by sampler channel id.
1603     qsamplerChannelStrip *qsamplerMainForm::channelStrip ( int iChannelID )
1604     {
1605     QWidgetList wlist = m_pWorkspace->windowList();
1606     if (wlist.isEmpty())
1607     return NULL;
1608    
1609     for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1610     qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1611     if (pChannelStrip) {
1612     qsamplerChannel *pChannel = pChannelStrip->channel();
1613     if (pChannel && pChannel->channelID() == iChannelID)
1614     return pChannelStrip;
1615     }
1616     }
1617    
1618     // Not found.
1619     return NULL;
1620     }
1621    
1622    
1623 capela 109 // Construct the windows menu.
1624     void qsamplerMainForm::channelsMenuAboutToShow (void)
1625     {
1626     channelsMenu->clear();
1627     channelsArrangeAction->addTo(channelsMenu);
1628     channelsAutoArrangeAction->addTo(channelsMenu);
1629    
1630     QWidgetList wlist = m_pWorkspace->windowList();
1631     if (!wlist.isEmpty()) {
1632     channelsMenu->insertSeparator();
1633     for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1634 capela 264 qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1635     if (pChannelStrip) {
1636     int iItemID = channelsMenu->insertItem(pChannelStrip->caption(), this, SLOT(channelsMenuActivated(int)));
1637     channelsMenu->setItemParameter(iItemID, iChannel);
1638     channelsMenu->setItemChecked(iItemID, activeChannelStrip() == pChannelStrip);
1639     }
1640 capela 109 }
1641     }
1642     }
1643    
1644    
1645     // Windows menu activation slot
1646     void qsamplerMainForm::channelsMenuActivated ( int iChannel )
1647     {
1648 capela 264 qsamplerChannelStrip *pChannelStrip = channelStripAt(iChannel);
1649     if (pChannelStrip)
1650     pChannelStrip->showNormal();
1651     pChannelStrip->setFocus();
1652 capela 109 }
1653    
1654    
1655     //-------------------------------------------------------------------------
1656     // qsamplerMainForm -- Timer stuff.
1657    
1658     // Set the pseudo-timer delay schedule.
1659     void qsamplerMainForm::startSchedule ( int iStartDelay )
1660     {
1661     m_iStartDelay = 1 + (iStartDelay * 1000);
1662     m_iTimerDelay = 0;
1663     }
1664    
1665     // Suspend the pseudo-timer delay schedule.
1666     void qsamplerMainForm::stopSchedule (void)
1667     {
1668     m_iStartDelay = 0;
1669     m_iTimerDelay = 0;
1670     }
1671    
1672     // Timer slot funtion.
1673     void qsamplerMainForm::timerSlot (void)
1674     {
1675     if (m_pOptions == NULL)
1676     return;
1677    
1678     // Is it the first shot on server start after a few delay?
1679     if (m_iTimerDelay < m_iStartDelay) {
1680     m_iTimerDelay += QSAMPLER_TIMER_MSECS;
1681     if (m_iTimerDelay >= m_iStartDelay) {
1682     // If we cannot start it now, maybe a lil'mo'later ;)
1683     if (!startClient()) {
1684     m_iStartDelay += m_iTimerDelay;
1685     m_iTimerDelay = 0;
1686     }
1687     }
1688     }
1689    
1690     // Refresh each channel usage, on each period...
1691 capela 400 if (m_pClient && (m_changedStrips.count() > 0 || m_pOptions->bAutoRefresh)) {
1692 capela 109 m_iTimerSlot += QSAMPLER_TIMER_MSECS;
1693 capela 296 if (m_iTimerSlot >= m_pOptions->iAutoRefreshTime && m_pWorkspace->isUpdatesEnabled()) {
1694 capela 109 m_iTimerSlot = 0;
1695 capela 400 // Update the channel information for each pending strip...
1696     for (qsamplerChannelStrip *pChannelStrip = m_changedStrips.first();
1697     pChannelStrip;
1698     pChannelStrip = m_changedStrips.next()) {
1699     // If successfull, remove from pending list...
1700     if (pChannelStrip->updateChannelInfo())
1701     m_changedStrips.remove(pChannelStrip);
1702     }
1703     // Update the channel stream usage for each strip...
1704 capela 109 QWidgetList wlist = m_pWorkspace->windowList();
1705     for (int iChannel = 0; iChannel < (int) wlist.count(); iChannel++) {
1706 capela 264 qsamplerChannelStrip *pChannelStrip = (qsamplerChannelStrip *) wlist.at(iChannel);
1707 capela 400 if (pChannelStrip && pChannelStrip->isVisible())
1708     pChannelStrip->updateChannelUsage();
1709 capela 109 }
1710     }
1711     }
1712    
1713     // Register the next timer slot.
1714     QTimer::singleShot(QSAMPLER_TIMER_MSECS, this, SLOT(timerSlot()));
1715     }
1716    
1717    
1718     //-------------------------------------------------------------------------
1719     // qsamplerMainForm -- Server stuff.
1720    
1721     // Start linuxsampler server...
1722     void qsamplerMainForm::startServer (void)
1723     {
1724     if (m_pOptions == NULL)
1725     return;
1726    
1727     // Aren't already a client, are we?
1728     if (!m_pOptions->bServerStart || m_pClient)
1729     return;
1730    
1731     // Is the server process instance still here?
1732     if (m_pServer) {
1733     switch (QMessageBox::warning(this, tr("Warning"),
1734     tr("Could not start the LinuxSampler server.\n\n"
1735     "Maybe it ss already started."),
1736     tr("Stop"), tr("Kill"), tr("Cancel"))) {
1737     case 0:
1738     m_pServer->tryTerminate();
1739     break;
1740     case 1:
1741     m_pServer->kill();
1742     break;
1743     }
1744     return;
1745     }
1746    
1747     // Reset our timer counters...
1748     stopSchedule();
1749    
1750     // OK. Let's build the startup process...
1751     m_pServer = new QProcess(this);
1752    
1753     // Setup stdout/stderr capture...
1754     //if (m_pOptions->bStdoutCapture) {
1755     m_pServer->setCommunication(QProcess::Stdout | QProcess::Stderr | QProcess::DupStderr);
1756     QObject::connect(m_pServer, SIGNAL(readyReadStdout()), this, SLOT(readServerStdout()));
1757     QObject::connect(m_pServer, SIGNAL(readyReadStderr()), this, SLOT(readServerStdout()));
1758     //}
1759     // The unforgiveable signal communication...
1760     QObject::connect(m_pServer, SIGNAL(processExited()), this, SLOT(processServerExit()));
1761    
1762     // Build process arguments...
1763     m_pServer->setArguments(QStringList::split(' ', m_pOptions->sServerCmdLine));
1764    
1765     appendMessages(tr("Server is starting..."));
1766     appendMessagesColor(m_pOptions->sServerCmdLine, "#990099");
1767    
1768     // Go jack, go...
1769     if (!m_pServer->start()) {
1770     appendMessagesError(tr("Could not start server.\n\nSorry."));
1771     processServerExit();
1772     return;
1773     }
1774    
1775     // Show startup results...
1776     appendMessages(tr("Server was started with PID=%1.").arg((long) m_pServer->processIdentifier()));
1777    
1778     // Reset (yet again) the timer counters,
1779     // but this time is deferred as the user opted.
1780     startSchedule(m_pOptions->iStartDelay);
1781     stabilizeForm();
1782     }
1783    
1784    
1785     // Stop linuxsampler server...
1786     void qsamplerMainForm::stopServer (void)
1787     {
1788     // Stop client code.
1789     stopClient();
1790    
1791     // And try to stop server.
1792     if (m_pServer) {
1793     appendMessages(tr("Server is stopping..."));
1794 capela 122 if (m_pServer->isRunning())
1795 capela 109 m_pServer->tryTerminate();
1796     }
1797    
1798 capela 122 // Give it some time to terminate gracefully and stabilize...
1799     QTime t;
1800     t.start();
1801     while (t.elapsed() < QSAMPLER_TIMER_MSECS)
1802     QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
1803    
1804 capela 109 // Do final processing anyway.
1805     processServerExit();
1806     }
1807    
1808    
1809     // Stdout handler...
1810     void qsamplerMainForm::readServerStdout (void)
1811     {
1812     if (m_pMessages)
1813     m_pMessages->appendStdoutBuffer(m_pServer->readStdout());
1814     }
1815    
1816    
1817     // Linuxsampler server cleanup.
1818     void qsamplerMainForm::processServerExit (void)
1819     {
1820     // Force client code cleanup.
1821     stopClient();
1822    
1823     // Flush anything that maybe pending...
1824     if (m_pMessages)
1825     m_pMessages->flushStdoutBuffer();
1826    
1827     if (m_pServer) {
1828     // Force final server shutdown...
1829     appendMessages(tr("Server was stopped with exit status %1.").arg(m_pServer->exitStatus()));
1830     if (!m_pServer->normalExit())
1831     m_pServer->kill();
1832     // Destroy it.
1833     delete m_pServer;
1834     m_pServer = NULL;
1835     }
1836    
1837     // Again, make status visible stable.
1838     stabilizeForm();
1839     }
1840    
1841    
1842     //-------------------------------------------------------------------------
1843     // qsamplerMainForm -- Client stuff.
1844    
1845     // The LSCP client callback procedure.
1846 capela 149 lscp_status_t qsampler_client_callback ( lscp_client_t */*pClient*/, lscp_event_t event, const char *pchData, int cchData, void *pvData )
1847 capela 109 {
1848 capela 149 qsamplerMainForm *pMainForm = (qsamplerMainForm *) pvData;
1849     if (pMainForm == NULL)
1850     return LSCP_FAILED;
1851    
1852     // ATTN: DO NOT EVER call any GUI code here,
1853 capela 145 // as this is run under some other thread context.
1854     // A custom event must be posted here...
1855 capela 149 QApplication::postEvent(pMainForm, new qsamplerCustomEvent(event, pchData, cchData));
1856 capela 109
1857     return LSCP_OK;
1858     }
1859    
1860    
1861     // Start our almighty client...
1862     bool qsamplerMainForm::startClient (void)
1863     {
1864     // Have it a setup?
1865     if (m_pOptions == NULL)
1866     return false;
1867    
1868     // Aren't we already started, are we?
1869     if (m_pClient)
1870     return true;
1871    
1872     // Log prepare here.
1873     appendMessages(tr("Client connecting..."));
1874    
1875     // Create the client handle...
1876     m_pClient = ::lscp_client_create(m_pOptions->sServerHost.latin1(), m_pOptions->iServerPort, qsampler_client_callback, this);
1877     if (m_pClient == NULL) {
1878     // Is this the first try?
1879     // maybe we need to start a local server...
1880     if ((m_pServer && m_pServer->isRunning()) || !m_pOptions->bServerStart)
1881     appendMessagesError(tr("Could not connect to server as client.\n\nSorry."));
1882     else
1883     startServer();
1884     // This is always a failure.
1885     stabilizeForm();
1886     return false;
1887     }
1888     // Just set receive timeout value, blindly.
1889     ::lscp_client_set_timeout(m_pClient, m_pOptions->iServerTimeout);
1890     appendMessages(tr("Client receive timeout is set to %1 msec.").arg(::lscp_client_get_timeout(m_pClient)));
1891    
1892     // We may stop scheduling around.
1893     stopSchedule();
1894    
1895     // We'll accept drops from now on...
1896     setAcceptDrops(true);
1897    
1898     // Log success here.
1899     appendMessages(tr("Client connected."));
1900    
1901 capela 428 // Hard-notify device configuration form,
1902     // if visible, that we're ready...
1903     if (m_pDeviceForm && m_pDeviceForm->isVisible())
1904     m_pDeviceForm->setClient(m_pClient);
1905    
1906 capela 109 // Is any session pending to be loaded?
1907     if (!m_pOptions->sSessionFile.isEmpty()) {
1908     // Just load the prabably startup session...
1909     if (loadSessionFile(m_pOptions->sSessionFile)) {
1910     m_pOptions->sSessionFile = QString::null;
1911     return true;
1912     }
1913     }
1914    
1915     // Make a new session
1916     return newSession();
1917     }
1918    
1919    
1920     // Stop client...
1921     void qsamplerMainForm::stopClient (void)
1922     {
1923     if (m_pClient == NULL)
1924     return;
1925    
1926 capela 428 // Hard-notify device configuration form,
1927     // if visible, that we're running out...
1928     if (m_pDeviceForm && m_pDeviceForm->isVisible())
1929     m_pDeviceForm->setClient(NULL);
1930    
1931 capela 109 // Log prepare here.
1932     appendMessages(tr("Client disconnecting..."));
1933    
1934     // Clear timer counters...
1935     stopSchedule();
1936    
1937     // We'll reject drops from now on...
1938     setAcceptDrops(false);
1939    
1940     // Force any channel strips around, but
1941     // but avoid removing the corresponding
1942     // channels from the back-end server.
1943     m_iDirtyCount = 0;
1944     closeSession(false);
1945    
1946     // Close us as a client...
1947     lscp_client_destroy(m_pClient);
1948     m_pClient = NULL;
1949    
1950     // Log final here.
1951     appendMessages(tr("Client disconnected."));
1952    
1953     // Make visible status.
1954     stabilizeForm();
1955     }
1956    
1957    
1958     // end of qsamplerMainForm.ui.h

  ViewVC Help
Powered by ViewVC