/[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 433 - (hide annotations) (download) (as text)
Wed Mar 9 16:44:04 2005 UTC (19 years, 1 month ago) by capela
File MIME type: text/x-c++hdr
File size: 61305 byte(s)
* Device configuration is now partially functional.

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

  ViewVC Help
Powered by ViewVC