/[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 454 - (hide annotations) (download) (as text)
Mon Mar 14 10:59:57 2005 UTC (13 years, 6 months ago) by capela
File MIME type: text/x-c++hdr
File size: 61667 byte(s)
New keep child windows always on top option; device icon retouching;

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

  ViewVC Help
Powered by ViewVC