1 //
2 //  FLWindow.cpp
3 //
4 //  Created by Sarah Denoux on 12/04/13.
5 //  Copyright (c) 2013 __MyCompanyName__. All rights reserved.
6 //
7 
8 #if defined(_WIN32) && !defined(GCC)
9 # pragma warning (disable: 4100)
10 #else
11 # pragma GCC diagnostic ignored "-Wunused-parameter"
12 # pragma GCC diagnostic ignored "-Wunused-variable"
13 # pragma GCC diagnostic ignored "-Wunused-function"
14 #endif
15 
16 #include "faust/gui/QTUI.h"
17 #include "faust/gui/httpdUI.h"
18 #include "faust/gui/FUI.h"
19 #include "faust/gui/OSCUI.h"
20 
21 #if __APPLE__
22 #define __MACOSX_CORE__ 1
23 #endif
24 
25 #if __linux__
26 #define __LINUX_ALSA__ 1
27 #endif
28 
29 #if _WIN32
30 #define __WINDOWS_MM__ 1
31 #endif
32 
33 #include "faust/gui/MidiUI.h"
34 #include "faust/midi/RtMidi.cpp"
35 
36 #include "FLWindow.h"
37 #include "HTTPWindow.h"
38 #include "FLInterfaceManager.h"
39 #include "FLToolBar.h"
40 #include "FLServerHttp.h"
41 
42 #ifdef REMOTE
43 #include "FLStatusBar.h"
44 #endif
45 
46 #include "AudioCreator.h"
47 #include "AudioManager.h"
48 #include "utilities.h"
49 #include "FLSettings.h"
50 #include "FLWinSettings.h"
51 #include "FLSessionManager.h"
52 #include "FLExportManager.h"
53 #include "FLFileWatcher.h"
54 #include "FLErrorWindow.h"
55 #include "FLMessageWindow.h"
56 #include "QTDefs.h"
57 
58 #ifdef JACK
59 #include "JA_audioManager.h"
60 #include "JA_audioFader.h"
61 #endif
62 
63 #ifdef REMOTE
64 #include "faust/dsp/remote-dsp.h"
65 #endif
66 
67 #include "faust/dsp/poly-llvm-dsp.h"
68 
69 list<GUI*> GUI::fGuiList;
70 ztimedmap GUI::gTimedZoneMap;
71 
72 /****************************FaustLiveWindow IMPLEMENTATION***************************/
73 
74 //------------CONSTRUCTION WINDOW
75 //@param : baseName = Window name
76 //@param : index = Index of the window
77 //@param : home = current Session folder
78 //@param : windowSettings = parameters of the settings
79 //@param : appMenus = list of menus contained in the window
FLWindow(QString & baseName,int index,const QString & home,FLWinSettings * windowSettings,QList<QMenu * > appMenus)80 FLWindow::FLWindow(QString& baseName, int index, const QString& home, FLWinSettings* windowSettings, QList<QMenu*> appMenus)
81 {
82     connect(this, SIGNAL(audioError(const QString&)), this, SLOT(audioShutDown(const QString&)));
83 
84     fSettings = windowSettings;
85     fSettings->setValue("Release/Number", 0);
86 
87     // Enable Drag & Drop on window
88     setAcceptDrops(true);
89 
90     // Creating Window Name
91     fWindowIndex = index;
92     fWindowName = baseName +  QString::number(fWindowIndex);
93 
94     fIsDefault = false;
95     fAudioManagerStopped = false;
96 
97     // Initializing class members
98 
99     fHttpdWindow = NULL;
100     fHttpInterface = NULL;
101     fOscInterface = NULL;
102     fMIDIInterface = NULL;
103     fMIDIHandler = NULL;
104 
105     fInterface = NULL;
106     fRCInterface = NULL;
107     fCurrentDSP = NULL;
108 
109     fToolBar = NULL;
110 
111     // Creating Window Folder
112     fHome = home;
113 
114     // Creating Audio Manager
115     AudioCreator* creator = AudioCreator::_Instance(NULL);
116 
117     fAudioManager = creator->createAudioManager(FLWindow::audioShutDown, this);
118     fClientOpen = false;
119 
120     // Set Menu & ToolBar
121     fLastMigration = QDateTime::currentDateTime();
122     set_ToolBar();
123 #ifdef REMOTE
124     fStatusBar = NULL;
125     set_StatusBar();
126     connect(this, SIGNAL(remoteCnxLost(int)), this, SLOT(RemoteCallback(int)));
127 #endif
128     set_MenuBar(appMenus);
129 }
130 
~FLWindow()131 FLWindow::~FLWindow()
132 {
133     delete menuBar();
134 }
135 
136 //------------------------WINDOW ACTIONS
137 
138 //Show Window on front end with standard size
frontShow()139 void FLWindow::frontShow()
140 {
141     int x = fSettings->value("Position/x", 0).toInt();
142     int y = fSettings->value("Position/y", 0).toInt();
143     int w = fSettings->value("Size/w", 0).toInt();
144     int h = fSettings->value("Size/h", 0).toInt();
145     setGeometry(x, y, w, h);
146     if (w == 0 && h == 0) adjustSize();
147 
148     show();
149     raise();
150 
151     setMinimumSize(QSize(0, 0));
152 
153     // Bug in QT 5.6 : needed in oder to always see the windows on the screen...
154     resize(QSize(300, 400));
155 
156 #ifdef QT6
157     QSize screenSize = QGuiApplication::primaryScreen()->size();
158 #else
159     QSize screenSize = QApplication::desktop()->geometry().size();
160 #endif
161     setMaximumSize(screenSize);
162 }
163 
start_stop_watcher(bool on)164 void FLWindow::start_stop_watcher(bool on)
165 {
166     QVector<QString> dependencies = FLSessionManager::_Instance()->readDependencies(fSettings->value("SHA", "").toString());
167 
168 //--- Add possible wavfile to dependencies
169     if (fWavSource != "") {
170         dependencies.push_front(fWavSource);
171     }
172 
173     FLSessionManager::_Instance()->writeDependencies(dependencies, getSHA());
174 
175     if (fSettings->value("Path", "").toString() != "") {
176         dependencies.push_front(fSettings->value("Path", "").toString());
177     }
178 
179     if (on) {
180         fCreationDate = fCreationDate.currentDateTime();
181         FLFileWatcher::_Instance()->startWatcher(dependencies, this);
182     } else {
183         FLFileWatcher::_Instance()->stopWatcher(dependencies, this);
184     }
185 }
186 
187 //Initialization of User Interface + StartUp of Audio Client
188 //@param : init = if the window created is a default window.
189 //@param : error = in case init fails, the error is filled
init_Window(int init,const QString & source,QString & errorMsg)190 bool FLWindow::init_Window(int init, const QString& source, QString& errorMsg)
191 {
192     fSource = source;
193 
194 //---- If wav, sound2faust has to be executed
195     fWavSource = "";
196 
197     if (ifWavToString(fSource, fWavSource)) {
198         fSource = fWavSource;
199         fWavSource = source;
200     }
201 
202     FLMessageWindow::_Instance()->displayMessage("Compiling DSP...");
203     FLMessageWindow::_Instance()->show();
204     FLMessageWindow::_Instance()->raise();
205 
206     FLSessionManager* sessionManager = FLSessionManager::_Instance();
207     QPair<QString, void*> factorySetts = sessionManager->createFactory(source, fSettings, errorMsg);
208     FLMessageWindow::_Instance()->hide();
209 
210     if (!factorySetts.second) { // testing if the factory pointer is null (= the compilation failed)
211         return false;
212     }
213 
214     if (!init_audioClient(errorMsg)) {
215         return false;
216     }
217 
218     fCurrentDSP = sessionManager->createDSP(factorySetts, source, fSettings, remoteDSPCallback, this, errorMsg);
219     if (!fCurrentDSP) {
220         return false;
221     }
222 
223     if (init != kNoInit) {
224         fIsDefault = true;
225         print_initWindow(init);
226     }
227 
228     allocateInterfaces(fSettings->value("Name", "").toString());
229 
230     buildInterfaces(fCurrentDSP);
231 
232     if (setDSP(errorMsg)) {
233         start_Audio();
234         frontShow();
235         runInterfaces();
236         start_stop_watcher(true);
237         return true;
238     } else {
239         sessionManager->deleteDSPandFactory(fCurrentDSP);
240         deleteInterfaces();
241         fCurrentDSP = NULL;
242         return false;
243     }
244 }
245 
246 //--Transforms Wav file into faust string
ifWavToString(const QString & source,QString & newSource)247 bool FLWindow::ifWavToString(const QString& source, QString& newSource)
248 {
249     // --> à voir comment on gère, vu qu'on enregistre pas de fichier source "intermédiaire". Est-ce qu'on recalcule la waveform quand on demande d'éditer ??
250 
251     QString suffix = QFileInfo(source).completeSuffix();
252 
253     if (suffix == "wav" || suffix == "aif" || suffix == "aiff" || suffix == "aifc") {
254 
255         QString exeFile = "";
256         QString soundFileName = QFileInfo(source).baseName();
257         QString destinationFile = QFileInfo(source).absolutePath();
258         destinationFile += "/" ;
259         destinationFile += soundFileName;
260         QString waveFile = destinationFile;
261         waveFile += "_waveform.dsp";
262         destinationFile += ".dsp";
263         QString systemInstruct;
264 
265 		// figure out the right name for faust2sound depending of the OS
266 
267 #ifdef _WIN32
268         exeFile = "sound2faust.exe";
269 #endif
270 
271 #ifdef __linux__
272         if (QFileInfo("/usr/local/bin/sound2faust").exists()) {
273             exeFile = "/usr/local/bin/sound2faust";
274         } else {
275             exeFile = "./sound2faust";
276         }
277 #endif
278 
279 #ifdef __APPLE__
280         //        FLErrorWindow::_Instance()->print_Error(QCoreApplication::applicationDirPath());
281         exeFile = QCoreApplication::applicationDirPath() + "/sound2faust";
282         //        if(QCoreApplication::applicationDirPath().indexOf("Contents/MacOS") != -1)
283         //            exeFile = "./sound2faust";
284         //        else
285         //            exeFile = QCoreApplication::applicationDirPath() + "/FaustLive.app/Contents/MacOS/sound2faust";
286 #endif
287         systemInstruct += exeFile + " ";
288         systemInstruct += "\"" + source + "\"" + " -o " + waveFile;
289 
290         if (!QFileInfo(exeFile).exists()) {
291             FLErrorWindow::_Instance()->print_Error("ERROR : soundToFaust executable could not be found!");
292         }
293 
294         QString errorMsg("");
295         if (!executeInstruction(systemInstruct, errorMsg)) {
296             FLErrorWindow::_Instance()->print_Error(errorMsg);
297         }
298 
299         QString finalFileContent = "//The waveform was automatically generated in :\nimport(\"";
300         finalFileContent += soundFileName + "_waveform.dsp";
301         finalFileContent += "\");\n\n//It can accessed with :\n//";
302         finalFileContent += soundFileName + "_i" + " with i = [0, ..., n] and n the number of channels\n\n";
303         finalFileContent += "//The example played here is :\n//";
304         finalFileContent += soundFileName + " = (" + soundFileName + "_0, ..., " + soundFileName + "_n) : ((!,_), ..., (!,_));\n\n";
305         finalFileContent +="process = ";
306         finalFileContent += QFileInfo(source).baseName();
307         finalFileContent += ";";
308         finalFileContent += "\n\n//Also, rtables are created in " + soundFileName + "_waveform.dsp" + " and are named : \n//" + soundFileName + "_rtable_i";
309 
310         writeFile(destinationFile, finalFileContent);
311         newSource = destinationFile;
312         return true;
313     } else {
314         return false;
315     }
316 }
317 
selfUpdate()318 void FLWindow::selfUpdate()
319 {
320 //Avoiding the flicker when the source is saved - Mostly seeable on 10.9
321 //    if(QFileInfo(fSource).exists()){
322 //
323 //        QDateTime modifiedLast = QFileInfo(fSource).lastModified();
324 //        if(fCreationDate < modifiedLast)
325 //            update_Window(fSource);
326 //    }
327 //    else
328     QString wavform = fWavSource;
329     update_Window(fSource);
330     fWavSource = wavform;
331 }
332 
selfNameUpdate(const QString & oldSource,const QString & newSource)333 void FLWindow::selfNameUpdate(const QString& oldSource, const QString& newSource)
334 {
335  //    In case name update is concerning source
336     if (oldSource == fSource) {
337         QString wavform = fWavSource;
338         update_Window(newSource);
339         fWavSource = wavform;
340 //    In case name update concerns a dependency
341     } else {
342         QString errorMsg = "WARNING : "+ fWindowName+". " + oldSource + " has been renamed as " + newSource + ". The dependency might be broken ! ";
343         errorPrint(errorMsg);
344     }
345 }
346 
347 //Modification of the process in the window
348 //@param : source = source that reemplaces the current one
update_Window(const QString & source)349 bool FLWindow::update_Window(const QString& source)
350 {
351 
352 //    bool update = false;
353 //    bool update = true;
354 //Avoiding the flicker when the source is saved - Mostly seeable on 10.9
355 //FIND THE RIGHT CONDITION !!!!
356 //
357 //    if(QFileInfo(source).exists()){
358 //
359 //        QDateTime modifiedLast = QFileInfo(source).lastModified();
360 //        if(fSource != source || fCreationDate < modifiedLast)
361 //            update = true;
362 //    }
363 //    else
364 //        update = true;
365 //    ---- AVOIDs flicker but switch remote machine doesnt update && compilation options either!!!
366 //    printf("is update not true??? = %i\n", update); --> moved to selfUpdate !!
367 
368 //    if(update){
369 
370     float saveW = 0.0;
371     float saveH = 0.0;
372 
373     float newW = 0.0;
374     float newH = 0.0;
375 
376     if (fInterface) {
377         saveW = fInterface->minimumSizeHint().width();
378         saveH = fInterface->minimumSizeHint().height();
379     }
380 
381     start_stop_watcher(false);
382 
383     FLMessageWindow::_Instance()->displayMessage("Updating DSP...");
384     FLMessageWindow::_Instance()->show();
385     FLMessageWindow::_Instance()->raise();
386     hide();
387 
388     QString savedName = fSettings->value("Name", "").toString();
389     QString savedPath = fSettings->value("Path", "").toString();
390     QString savedSHA = fSettings->value("SHA", "").toString();
391 
392     saveWindow();
393     hide();
394 
395     QString errorMsg("");
396     FLSessionManager* sessionManager = FLSessionManager::_Instance();
397     QString sourceToCompile = source;
398     QString wavsource = "";
399 
400     if (ifWavToString(sourceToCompile, wavsource)) {
401         sourceToCompile = wavsource;
402         wavsource = source;
403     }
404 
405     QPair<QString, void*> factorySetts = sessionManager->createFactory(sourceToCompile, fSettings, errorMsg);
406     bool isUpdateSucessfull = factorySetts.second;
407 
408     if (isUpdateSucessfull) {
409 
410         //creating the new DSP instance
411         dsp* new_dsp = sessionManager->createDSP(factorySetts, source, fSettings, remoteDSPCallback, this, errorMsg);
412 
413         if (new_dsp) {
414 
415             QString newName = fSettings->value("Name", "").toString();
416 
417             if (fAudioManager->init_FadeAudio(errorMsg, newName.toStdString().c_str(), new_dsp)) {
418 
419                 fIsDefault = false;
420 
421                 recall_Window();
422 
423                 // Start crossfade and wait for its end
424                 fAudioManager->start_Fade();
425                 fAudioManager->wait_EndFade();
426 
427                 // Switch the current DSP as the dropped one
428                 dsp* old_dsp = fCurrentDSP;
429                 fCurrentDSP = new_dsp;
430 
431                 // Delete old dsp (and remove it from MIDI interface)
432                 FLSessionManager::_Instance()->deleteDSPandFactory(old_dsp);
433                 deleteInterfaces();
434 
435                 // Set the new interface & Recall the parameters of the window
436                 allocateInterfaces(newName);
437 
438                 buildInterfaces(new_dsp);
439 
440                 fSource = sourceToCompile;
441                 fWavSource = wavsource;
442 
443                 //Launch User Interface
444                 runInterfaces();
445             }
446         }
447     }
448 
449     start_stop_watcher(true);
450 
451     if (isUpdateSucessfull) {
452         emit windowNameChanged();
453     } else {
454         errorPrint(errorMsg);
455     }
456 
457     FLMessageWindow::_Instance()->hide();
458 
459     if (fInterface) {
460         newW = fInterface->minimumSizeHint().width();
461         newH = fInterface->minimumSizeHint().height();
462     }
463 
464 // 2 cases :
465 //    1- Updating with a new DSP --> adjusting Size to the new interface
466 //    2- Self Updating --> keeping the window as it is (could have been opened or shred)
467     if (newH != saveH || newW != saveW) {
468         adjustSize();
469     }
470 
471     show();
472     return isUpdateSucessfull;
473 }
474 
475 //Reaction to source deletion
source_Deleted()476 void FLWindow::source_Deleted()
477 {
478     QString msg = "Warning your file : " + fSource + " was deleted. You are now working on an internal copy of this file.";
479     fSource = FLSessionManager::_Instance()->contentOfShaSource(fSettings->value("SHA", "").toString());
480     fSettings->setValue("Path", "");
481     errorPrint(msg);
482 }
483 
484 //------------------------MENUS ACTIONS
485 
486 //Right-click
contextMenuEvent(QContextMenuEvent * ev)487 void FLWindow::contextMenuEvent(QContextMenuEvent* ev)
488 {
489     fWindowMenu->exec(ev->globalPos());
490 }
491 
492 //Menu Bar
set_MenuBar(QList<QMenu * > appMenus)493 void FLWindow::set_MenuBar(QList<QMenu*> appMenus)
494 {
495     //----------------FILE
496     QMenuBar *myMenuBar = new QMenuBar(NULL);
497     setMenuBar(myMenuBar);
498     QList<QMenu*>::iterator it = appMenus.begin();
499     myMenuBar->addMenu(*it);
500     myMenuBar->addSeparator();
501     it++;
502 
503     //-----------------Window
504     QAction* editAction = new QAction(tr("&Edit Faust Source"), this);
505     editAction->setShortcut(tr("Ctrl+E"));
506     editAction->setToolTip(tr("Edit the source"));
507     connect(editAction, SIGNAL(triggered()), this, SLOT(edit()));
508 
509     QAction* pasteAction = new QAction(tr("&Paste"),this);
510     pasteAction->setShortcut(tr("Ctrl+V"));
511     pasteAction->setToolTip(tr("Paste a DSP"));
512     connect(pasteAction, SIGNAL(triggered()), this, SLOT(paste()));
513 
514     QAction* duplicateAction = new QAction(tr("&Duplicate"),this);
515     duplicateAction->setShortcut(tr("Ctrl+D"));
516     duplicateAction->setToolTip(tr("Duplicate current DSP"));
517     connect(duplicateAction, SIGNAL(triggered()), this, SLOT(duplicate()));
518 
519     QAction* httpdViewAction = new QAction(tr("&View QRcode"),this);
520     httpdViewAction->setShortcut(tr("Ctrl+K"));
521     httpdViewAction->setToolTip(tr("Print the QRcode of TCP protocol"));
522     connect(httpdViewAction, SIGNAL(triggered()), this, SLOT(view_qrcode()));
523 
524     QAction* svgViewAction = new QAction(tr("&View SVG Diagram"),this);
525     svgViewAction->setShortcut(tr("Ctrl+G"));
526     svgViewAction->setToolTip(tr("Open the SVG Diagram in a browser"));
527     connect(svgViewAction, SIGNAL(triggered()), this, SLOT(view_svg()));
528 
529     QAction* exportAction = new QAction(tr("&Export As..."), this);
530     exportAction->setShortcut(tr("Ctrl+P"));
531     exportAction->setToolTip(tr("Export the DSP in whatever architecture you choose"));
532     connect(exportAction, SIGNAL(triggered()), this, SLOT(export_file()));
533 
534     QAction* shutAction = new QAction(tr("&Close Window"),this);
535     shutAction->setShortcut(tr("Ctrl+W"));
536     shutAction->setToolTip(tr("Close the current Window"));
537     connect(shutAction, SIGNAL(triggered()), this, SLOT(shut()));
538 
539     fWindowMenu = new QMenu(tr("&Window"), NULL);
540     fWindowMenu->addAction(editAction);
541     fWindowMenu->addAction(pasteAction);
542     fWindowMenu->addAction(duplicateAction);
543     fWindowMenu->addSeparator();
544     fWindowMenu->addAction(httpdViewAction);
545 
546     fWindowMenu->addAction(svgViewAction);
547     fWindowMenu->addSeparator();
548     fWindowMenu->addAction(exportAction);
549     fWindowMenu->addSeparator();
550     fWindowMenu->addAction(shutAction);
551 
552     myMenuBar->addMenu(fWindowMenu);
553     myMenuBar->addSeparator();
554 
555     while (it != appMenus.end()) {
556         myMenuBar->addMenu(*it);
557         myMenuBar->addSeparator();
558         it++;
559     }
560 }
561 
562 //----SLOTS
edit()563 void FLWindow::edit()
564 {
565     QString sourcePath = fSettings->value("Path", "").toString();
566     QString pathToOpen = sourcePath;
567 
568     if (sourcePath == "") {
569         pathToOpen = FLSessionManager::_Instance()->askForSourceSaving(FLSessionManager::_Instance()->contentOfShaSource(getSHA()));
570         // In case user has saved his file in a new location
571         if (pathToOpen != "" && pathToOpen != ".dsp") {
572             update_Window(pathToOpen);
573         } else {
574             return;
575         }
576     }
577 
578     FLSessionManager::_Instance()->updateFolderDate(fSettings->value("SHA", "").toString());
579 
580     QUrl url = QUrl::fromLocalFile(pathToOpen);
581     if (!QDesktopServices::openUrl(url)) {
582         errorPrint("Your DSP file could not be opened!\nMake sure you have a default application configured for DSP Files.");
583     }
584 }
585 
paste()586 void FLWindow::paste()
587 {
588     // Recuperation of Clipboard Content
589     const QClipboard *clipboard = QApplication::clipboard();
590     const QMimeData *mimeData = clipboard->mimeData();
591 
592     if (mimeData->hasText()) {
593         QString clipText = clipboard->text();
594         update_Window(clipText);
595     }
596 }
597 
duplicate()598 void FLWindow::duplicate()
599 {
600     emit duplicate_Action();
601 }
602 
view_qrcode()603 void FLWindow::view_qrcode()
604 {
605     fToolBar->switchHttp(true);
606     viewQRCode();
607 }
608 
view_svg()609 void FLWindow::view_svg()
610 {
611     QString svgPath = fHome + "/Windows/" + fWindowName;
612     QString errorMsg;
613     if (FLSessionManager::_Instance()->generateSVG(getSHA(), getPath(), svgPath, fWindowName, errorMsg)) {
614         QString pathToOpen = fHome + "/Windows/" + fWindowName + "/" + fWindowName + "-svg/process.svg";
615         QUrl url = QUrl::fromLocalFile(pathToOpen);
616         if (!QDesktopServices::openUrl(url)) {
617             errorPrint("Your SVG could not be opened!\nMake sure you have a default application configured for SVG Files.");
618         }
619     } else {
620         QString err = "Could not generate SVG diagram : " + errorMsg;
621         errorPrint(err);
622     }
623 }
624 
export_file()625 void FLWindow::export_file()
626 {
627     FLTargetChooser* targetDialog = FLTargetChooser::_Instance();
628     if (targetDialog->exec()) {
629         QString expandedCode = FLSessionManager::_Instance()->getExpandedVersion(fSettings, FLSessionManager::_Instance()->contentOfShaSource(getSHA()));
630         FLExportManager* exportDialog = FLExportManager::_Instance();
631         exportDialog->exportFile(getName(), expandedCode, targetDialog->platform(), targetDialog->architecture(), targetDialog->binOrSource());
632     }
633 }
634 
shut()635 void FLWindow::shut()
636 {
637     emit close();
638     // emit closeWin();
639 }
640 
641 //------------TOOLBAR RELATED ACTIONS
642 
643 //Set up of the Window ToolBar
set_ToolBar()644 void FLWindow::set_ToolBar()
645 {
646     fToolBar = new FLToolBar(fSettings, this);
647     addToolBar(Qt::TopToolBarArea, fToolBar);
648 
649     connect(fToolBar, SIGNAL(compilationOptionsChanged()), this, SLOT(modifiedOptions()));
650     connect(fToolBar, SIGNAL(generateNewAuxFiles()), this, SLOT(generateAuxFiles()));
651 //    connect(fToolBar, SIGNAL(execScript()), this, SLOT(scriptExecution()));
652     connect(fToolBar, SIGNAL(sizeGrowth()), this, SLOT(resizingBig()));
653     connect(fToolBar, SIGNAL(sizeReduction()), this, SLOT(resizingSmall()));
654 	connect(fToolBar, SIGNAL(switch_http(bool)), this, SLOT(switchHttp(bool)));
655 	connect(fToolBar, SIGNAL(oscPortChanged()), this, SLOT(updateOSCInterface()));
656 	connect(fToolBar, SIGNAL(switch_osc(bool)), this, SLOT(switchOsc(bool)));
657     connect(fToolBar, SIGNAL(switch_midi(bool)), this, SLOT(switchMIDI(bool)));
658     connect(fToolBar, SIGNAL(switch_poly(bool)), this, SLOT(switchPoly(bool)));
659 
660 #ifdef REMOTE
661     connect(fToolBar, SIGNAL(switch_release(bool)), this, SLOT(switchRelease(bool)));
662     connect(fToolBar, SIGNAL(switch_remotecontrol(bool)), this, SLOT(switchRemoteControl(bool)));
663 #endif
664 }
665 
666 //Set the windows options with current values
setWindowsOptions()667 void FLWindow::setWindowsOptions()
668 {
669     if (fHttpInterface) {
670         fSettings->setValue("Http/Port", fHttpInterface->getTCPPort());
671     }
672 
673 	if (fOscInterface) {
674         fSettings->setValue("Osc/InPort", QString::number(fOscInterface->getUDPPort()));
675         fSettings->setValue("Osc/OutPort", QString::number(fOscInterface->getUDPOut()));
676         fSettings->setValue("Osc/DestHost", fOscInterface->getDestAddress());
677         fSettings->setValue("Osc/ErrPort", QString::number(fOscInterface->getUDPErr()));
678     }
679 
680     fToolBar->syncVisualParams();
681 }
682 
683 //Reaction to the modifications of the ToolBar options
modifiedOptions()684 void FLWindow::modifiedOptions()
685 {
686     update_Window(fSource);
687 }
688 
689 //Reaction to the modification of outfile options
generateAuxFiles()690 void FLWindow::generateAuxFiles()
691 {
692 	QString errorMsg;
693 
694     if (!FLSessionManager::_Instance()->generateAuxFiles(getSHA(), getPath(), fSettings->value("AutomaticExport/Options", "").toString(), getSHA(), errorMsg)) {
695 		FLErrorWindow::_Instance()->print_Error(QString("Additional Compilation Step : ") + errorMsg);
696     }
697 }
698 
699 //Reaction to the resizing the toolbar
resizingSmall()700 void FLWindow::resizingSmall()
701 {
702 //  fSettings->setValue("Osc/DestHost", fOscInterface->getDestAddress());
703 //  setWindowsOptions();
704 
705     setMinimumSize(QSize(0, 0));
706     adjustSize();
707     addToolBar(Qt::TopToolBarArea, fToolBar);
708 }
709 
resizingBig()710 void FLWindow::resizingBig()
711 {
712     addToolBar(Qt::LeftToolBarArea, fToolBar);
713 
714     //    QSize winSize = fToolBar->geometry().size();
715     //    winSize += fToolBar->minimumSize();
716     //
717     //
718     //    QSize winMinSize = minimumSize();
719     //    winMinSize += fToolBar->geometry().size();
720 
721     // setGeometry(0,0,winSize.width(), winSize.height());
722     // setMinimumSize(winMinSize);
723     //
724     adjustSize();
725 }
726 
727 //------------STATUSBAR RELATED ACTIONS
728 
set_StatusBar()729 void FLWindow::set_StatusBar()
730 {
731 #ifdef REMOTE
732     fStatusBar = new FLStatusBar(fSettings, this);
733     connect(fStatusBar, SIGNAL(switchMachine()), this, SLOT(redirectSwitch()));
734     setStatusBar(fStatusBar);
735 #endif
736 }
737 
738 //Redirection machine switch
redirectSwitch()739 void FLWindow::redirectSwitch()
740 {
741 #ifdef REMOTE
742     if (!update_Window(fSource)) {
743         fStatusBar->remoteFailed();
744     }
745 #endif
746 }
747 
748 //------------ALLOCATION/DESALLOCATION OF INTERFACES
749 
disableOSCInterface()750 void FLWindow::disableOSCInterface()
751 {
752     fToolBar->switchOsc(false);
753 }
754 
switchOsc(bool on)755 void FLWindow::switchOsc(bool on)
756 {
757     if (on) {
758         updateOSCInterface();
759     } else {
760         deleteOscInterface();
761     }
762 }
763 
switchMIDI(bool)764 void FLWindow::switchMIDI(bool /*on*/)
765 {
766     switchPolyMIDI();
767 }
768 
switchPoly(bool)769 void FLWindow::switchPoly(bool /*on*/)
770 {
771     switchPolyMIDI();
772 }
773 
774 // We may want poly with or without MIDI, so redo everything
775 
resetAudioDSPInterfaces()776 bool FLWindow::resetAudioDSPInterfaces()
777 {
778     QString errorMsg;
779     FLSessionManager* sessionManager = FLSessionManager::_Instance();
780     QPair<QString, void*> factorySetts = sessionManager->createFactory(fSource, fSettings, errorMsg);
781 
782     float saveW = 0.0;
783     float saveH = 0.0;
784     float newW = 0.0;
785     float newH = 0.0;
786 
787     if (fInterface) {
788         saveW = fInterface->minimumSizeHint().width();
789         saveH = fInterface->minimumSizeHint().height();
790     }
791 
792     saveWindow();
793     hide();
794 
795     start_stop_watcher(false);
796     stop_Audio();
797 
798     sessionManager->deleteDSPandFactory(fCurrentDSP);
799     deleteInterfaces();
800 
801     fCurrentDSP = sessionManager->createDSP(factorySetts, fSource, fSettings, remoteDSPCallback, this, errorMsg);
802 
803     if (update_AudioArchitecture(errorMsg)) {
804 
805         allocateInterfaces(fSettings->value("Name", "").toString());
806 
807         buildInterfaces(fCurrentDSP);
808 
809         start_Audio();
810         runInterfaces();
811         start_stop_watcher(true);
812 
813         FLMessageWindow::_Instance()->hide();
814 
815         if (fInterface) {
816             newW = fInterface->minimumSizeHint().width();
817             newH = fInterface->minimumSizeHint().height();
818         }
819 
820         if (newH != saveH || newW != saveW) {
821             adjustSize();
822         }
823 
824         show();
825         return true;
826 
827     } else {
828         errorPrint(errorMsg);
829         return false;
830     }
831 }
832 
switchPolyMIDI()833 void FLWindow::switchPolyMIDI()
834 {
835     resetAudioDSPInterfaces();
836 }
837 
updateMIDIInterface()838 void FLWindow::updateMIDIInterface()
839 {
840     if (fSettings->value("MIDI/Enabled", FLSettings::_Instance()->value("General/Control/MIDIDefaultChecked", false)).toBool()) {
841         saveWindow();
842         deleteMIDIInterface();
843         allocateMIDIInterface();
844         fCurrentDSP->buildUserInterface(fMIDIInterface);
845         recall_Window();
846         fMIDIInterface->run();
847         FLInterfaceManager::_Instance()->registerGUI(fMIDIInterface);
848         setWindowsOptions();
849     }
850 }
851 
allocateMIDIInterface()852 void FLWindow::allocateMIDIInterface()
853 {
854 #ifdef JACK
855     JA_audioManager* manager = dynamic_cast<JA_audioManager*>(fAudioManager);
856     // Special case for JACK audio manager
857     if (manager) {
858         fMIDIHandler = manager->getAudioFader();
859     } else {
860         fMIDIHandler = new rt_midi(fWindowName.toStdString());
861     }
862 #else
863     fMIDIHandler = new rt_midi(fWindowName.toStdString());
864 #endif
865     fMIDIInterface = new MidiUI(fMIDIHandler);
866 }
867 
deleteMIDIInterface()868 void FLWindow::deleteMIDIInterface()
869 {
870     if (fMIDIInterface) {
871         FLInterfaceManager::_Instance()->unregisterGUI(fMIDIInterface);
872         delete fMIDIInterface;
873         fMIDIInterface = NULL;
874         // rt_midi handler has to be deallocated, JA_audioFader one is kept and deallocated JA_audioManager
875         if (dynamic_cast<rt_midi*>(fMIDIHandler)) {
876             delete fMIDIHandler;
877         }
878         fMIDIHandler = NULL;
879     }
880 }
881 
catch_OSCError(void * arg)882 void catch_OSCError(void* arg)
883 {
884     FLWindow* win = (FLWindow*)(arg);
885     win->errorPrint("Too many OSC interfaces are opened at the same time! A new connection could not start");
886     win->disableOSCInterface();
887 }
888 
889 //Allocation of Interfaces
allocateOscInterface()890 void FLWindow::allocateOscInterface()
891 {
892     int argc = 11;
893 
894 //---- Allocation for windows needs
895     char** argv = new char*[argc + 1];
896     argv[0] = (char*)(fWindowName.toStdString().c_str());
897     argv[1] = (char*)"-port";
898 
899     string inport = fSettings->value("Osc/InPort", "5510").toString().toStdString();
900     argv[2] = (char*) (inport.c_str());
901     argv[3] = (char*)"-xmit";
902     argv[4] = (char*)"1";
903     argv[5] = (char*)"-outport";
904     string outport = fSettings->value("Osc/OutPort", "5511").toString().toStdString();
905     argv[6] = (char*) (outport.c_str());
906     argv[7] = (char*)"-desthost";
907     string dest = fSettings->value("Osc/DestHost", "localhost").toString().toStdString();
908     argv[8] = (char*) (dest.c_str());
909     argv[9] = (char*)"-errport";
910     string errport = fSettings->value("Osc/ErrPort", "5512").toString().toStdString();
911     argv[10] = (char*) (errport.c_str());
912 
913     argv[argc] = 0; // NULL terminated argv
914 
915     fOscInterface = new OSCUI(argv[0], argc, argv, NULL, &catch_OSCError, this, false);
916     delete [] argv;
917 }
918 
deleteOscInterface()919 void FLWindow::deleteOscInterface()
920 {
921     if (fOscInterface) {
922         FLInterfaceManager::_Instance()->unregisterGUI(fOscInterface);
923         delete fOscInterface;
924         fOscInterface = NULL;
925     }
926 }
927 
updateOSCInterface()928 void FLWindow::updateOSCInterface()
929 {
930     saveWindow();
931     deleteOscInterface();
932     allocateOscInterface();
933     fCurrentDSP->buildUserInterface(fOscInterface);
934     recall_Window();
935     fOscInterface->run();
936     FLInterfaceManager::_Instance()->registerGUI(fOscInterface);
937     setWindowsOptions();
938 }
939 
940 //----4 STEP OF THE INTERFACES LIFE
941 
allocateInterfaces(const QString & nameEffect)942 bool FLWindow::allocateInterfaces(const QString& nameEffect)
943 {
944     QString intermediate = fWindowName + " : " + nameEffect;
945     setWindowTitle(intermediate);
946 
947     if (!fIsDefault) {
948         QScrollArea* sa = new QScrollArea(this);
949 
950         fInterface = new QTGUI(sa);
951         sa->setWidgetResizable(true);
952         sa->setWidget(fInterface);
953         sa->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
954         sa->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
955 
956         setCentralWidget(sa);
957         fInterface->installEventFilter(this);
958     }
959 
960     fRCInterface = new FUI;
961 
962     if (fSettings->value("Http/Enabled", FLSettings::_Instance()->value("General/Network/HttpDefaultChecked", false)).toBool()) {
963         allocateHttpInterface();
964     }
965 
966 	if (fSettings->value("Osc/Enabled", FLSettings::_Instance()->value("General/Network/OscDefaultChecked", false)).toBool()) {
967         allocateOscInterface();
968     }
969 
970     if (fSettings->value("MIDI/Enabled", FLSettings::_Instance()->value("General/Control/MIDIDefaultChecked", false)).toBool()) {
971         allocateMIDIInterface();
972     }
973 
974     return true;
975 }
976 
977 //Building QT Interface | Osc Interface | Parameter saving Interface | ToolBar
buildInterfaces(dsp * compiledDSP)978 void FLWindow::buildInterfaces(dsp* compiledDSP)
979 {
980     if (fInterface) {
981         compiledDSP->buildUserInterface(fInterface);
982     }
983 
984     if (fRCInterface) {
985         compiledDSP->buildUserInterface(fRCInterface);
986     }
987 
988     if (fHttpInterface) {
989         compiledDSP->buildUserInterface(fHttpInterface);
990     }
991 
992     if (fOscInterface) {
993         compiledDSP->buildUserInterface(fOscInterface);
994     }
995 
996     if (fMIDIInterface) {
997         compiledDSP->buildUserInterface(fMIDIInterface);
998     }
999 }
1000 
runInterfaces()1001 void FLWindow::runInterfaces()
1002 {
1003     if (fHttpInterface) {
1004         fHttpInterface->run();
1005         FLServerHttp::_Instance()->declareHttpInterface(fHttpInterface->getTCPPort(), getName().toStdString());
1006     }
1007 
1008     if (fOscInterface) {
1009         fOscInterface->run();
1010         FLInterfaceManager::_Instance()->registerGUI(fOscInterface);
1011     }
1012 
1013     if (fMIDIInterface) {
1014         fMIDIInterface->run();
1015         FLInterfaceManager::_Instance()->registerGUI(fMIDIInterface);
1016     }
1017 
1018     if (fInterface) {
1019         //fInterface->run();
1020         fInterface->installEventFilter(this);
1021         FLInterfaceManager::_Instance()->registerGUI(fInterface);
1022     }
1023 
1024     setWindowsOptions();
1025 }
1026 
1027 //Delete of QTinterface and of saving graphical interface
deleteInterfaces()1028 void FLWindow::deleteInterfaces()
1029 {
1030     if (fInterface) {
1031         FLInterfaceManager::_Instance()->unregisterGUI(fInterface);
1032         delete fInterface;
1033         fInterface = NULL;
1034     }
1035 
1036     deleteOscInterface();
1037     deleteHttpInterface();
1038     deleteMIDIInterface();
1039 
1040     delete fRCInterface;
1041     fRCInterface = NULL;
1042 }
1043 
1044 //------------DEFAULT WINDOW FUNCTIONS
1045 
1046 //Does window contain a default Faust process?
is_Default()1047 bool FLWindow::is_Default()
1048 {
1049     return fIsDefault;
1050 }
1051 
1052 //Artificial content of a default window
print_initWindow(int typeInit)1053 void FLWindow::print_initWindow(int typeInit)
1054 {
1055     QPixmap dropImage;
1056 
1057     if (typeInit == kInitBlue) {
1058         dropImage.load(":/Images/DropYourFaustLife_Blue.png");
1059     } else if(typeInit == kInitWhite) {
1060         dropImage.load(":/Images/DropYourFaustLife_White.png");
1061     }
1062 
1063     dropImage.scaledToHeight(10, Qt::SmoothTransformation);
1064     QLabel *image = new QLabel();
1065     // image->setMinimumSize (dropImage.width()*3, dropImage.height()*3);
1066 
1067     image->installEventFilter(this);
1068     image->setPixmap(dropImage);
1069     image->setAlignment(Qt::AlignCenter);
1070     setCentralWidget(image);
1071 }
1072 
1073 //------------------------CLOSING ACTIONS
1074 
1075 //Reaction to click an x button
closeEvent(QCloseEvent * event)1076 void FLWindow::closeEvent(QCloseEvent* event)
1077 {
1078     if (QApplication::keyboardModifiers() == Qt::AltModifier) {
1079         emit shut_AllWindows();
1080     } else {
1081         emit closeWin();
1082     }
1083 
1084 	event->accept();
1085 }
1086 
1087 //During the execution, when a window is shut, its associate folder has to be removed
shutWindow()1088 void FLWindow::shutWindow()
1089 {
1090     closeWindow();
1091     const QString winFolder = fHome + "/Windows/" + fWindowName;
1092     delete fSettings;
1093     deleteDirectoryAndContent(winFolder);
1094 }
1095 
1096 //Closing the window without removing its property for example when the application quits
closeWindow()1097 void FLWindow::closeWindow()
1098 {
1099     hide();
1100     start_stop_watcher(false);
1101     fSettings->sync();
1102 
1103     if (fClientOpen && fAudioManager) {
1104         fAudioManager->stop();
1105     }
1106 
1107     if (fHttpdWindow) {
1108         fHttpdWindow->deleteLater();
1109         fHttpdWindow = NULL;
1110     }
1111 
1112     FLSessionManager::_Instance()->deleteDSPandFactory(fCurrentDSP);
1113     deleteInterfaces();
1114 
1115 #ifdef REMOTE
1116     delete fStatusBar;
1117 #endif
1118 
1119     delete fAudioManager;
1120     delete fToolBar;
1121 
1122     blockSignals(true);
1123 }
1124 
1125 //------------------------DRAG AND DROP ACTIONS
1126 
1127 //Reaction to drop on the window
dropEvent(QDropEvent * event)1128 void FLWindow::dropEvent(QDropEvent* event)
1129 {
1130     //The widget was hidden from crossing of an object through the window
1131     this->centralWidget()->show();
1132 
1133     if (event->mimeData()->hasUrls()) {
1134 
1135         QList<QString> sourceList;
1136         QList<QUrl> urls = event->mimeData()->urls();
1137         QList<QUrl>::iterator i;
1138 
1139         for (i = urls.begin(); i != urls.end(); i++) {
1140 
1141             QString fileName;
1142 
1143             if (i->isLocalFile()) {
1144                 fileName = i->toLocalFile();
1145             } else {
1146                 fileName = i->toString();
1147             }
1148 
1149             if (i == urls.begin()) {
1150                 update_Window(fileName);
1151             } else {
1152                 sourceList.push_back(fileName);
1153             }
1154 
1155             event->accept();
1156         }
1157         emit drop(sourceList);
1158     } else if (event->mimeData()->hasText()) {
1159         event->accept();
1160         update_Window(event->mimeData()->text());
1161     }
1162 }
1163 
1164 //That way the drag movement is more visible : the central widget is hidden when an object is crossing the window and reset visible when the object leaves the window
dragEnterEvent(QDragEnterEvent * event)1165 void FLWindow::dragEnterEvent(QDragEnterEvent* event)
1166 {
1167     if (event->mimeData()->text() == fSource) {
1168         return;
1169     } else if (event->mimeData()->hasUrls() && *(event->mimeData()->urls().begin()) == fSource) {
1170         return;
1171     }
1172 
1173     if (event->mimeData()->hasFormat("text/uri-list") || event->mimeData()->hasFormat("text/plain")) {
1174 
1175         if (event->mimeData()->hasUrls()) {
1176             QList<QString> sourceList;
1177             QList<QUrl> urls = event->mimeData()->urls();
1178             QList<QUrl>::iterator i;
1179 
1180             for (i = urls.begin(); i != urls.end(); i++) {
1181                 QString suffix = QFileInfo(i->toString()).completeSuffix();
1182                 if (suffix == "dsp" || suffix == "wav" || suffix == "aif" || suffix == "aiff" || suffix == "aifc") {
1183                     centralWidget()->hide();
1184                     event->acceptProposedAction();
1185                 }
1186             }
1187 
1188         } else if (event->mimeData()->hasFormat("text/plain")) {
1189             centralWidget()->hide();
1190             event->acceptProposedAction();
1191         }
1192     }
1193 }
1194 
dragLeaveEvent(QDragLeaveEvent *)1195 void FLWindow::dragLeaveEvent(QDragLeaveEvent* /*event*/)
1196 {
1197     //setWindowFlags();
1198     centralWidget()->show();
1199 }
1200 
1201 //---Reversed DnD
pressEvent()1202 void FLWindow::pressEvent()
1203 {
1204     QDrag* reverseDrag = new QDrag(this);
1205     QMimeData* mimeData = new QMimeData;
1206     reverseDrag->setMimeData(mimeData);
1207     QPixmap fileIcon;
1208     fileIcon.load(":/Images/FileIcon.png");
1209     reverseDrag->setPixmap(fileIcon);
1210 
1211     if (QFileInfo(fSource).exists()) {
1212         QList<QUrl> listUrls;
1213         QUrl newURL(fSource);
1214         listUrls.push_back(newURL);
1215         mimeData->setUrls(listUrls);
1216     } else {
1217         mimeData->setText(fSource);
1218     }
1219 
1220     if (reverseDrag->exec(Qt::CopyAction) == Qt::CopyAction){}
1221 }
1222 
eventFilter(QObject * obj,QEvent * ev)1223 bool FLWindow::eventFilter(QObject* obj, QEvent* ev)
1224 {
1225     if (ev->type() == QEvent::MouseMove && QApplication::mouseButtons()==Qt::LeftButton) {
1226         pressEvent();
1227         return true;
1228     } else {
1229         return QMainWindow::eventFilter(obj, ev);
1230     }
1231 }
1232 
1233 //-------------------------AUDIO FUNCTIONS
1234 
1235 //Start/Stop of audio
stop_Audio()1236 void FLWindow::stop_Audio()
1237 {
1238 #ifdef REMOTE
1239 
1240     //    if (!fEffect->isLocal()) {
1241     //        remote_dsp* currentDSP = (remote_dsp*)fCurrentDSP;
1242     //        currentDSP->stop();
1243     //    }
1244 
1245 #endif
1246     if (fClientOpen) {
1247         fAudioManager->stop();
1248         fClientOpen = false;
1249     }
1250 }
1251 
start_Audio()1252 void FLWindow::start_Audio()
1253 {
1254     if (!fClientOpen) {
1255         recall_Window();
1256         fAudioManager->start();
1257         QString connectFile = fHome + "/Windows/" + fWindowName + "/Connections.jc";
1258         fAudioManager->connect_Audio(connectFile.toStdString());
1259         fClientOpen = true;
1260 
1261     #ifdef REMOTE
1262         //    if (!fEffect->isLocal()) {
1263         //        remote_dsp* currentDSP = (remote_dsp*)fCurrentDSP;
1264         //        currentDSP->start();
1265         //    }
1266     #endif
1267     }
1268 }
1269 
1270 //In case audio clients collapse, the architecture has to be changed
audioShutDown(const char * msg,void * arg)1271 void FLWindow::audioShutDown(const char* msg, void* arg)
1272 {
1273     ((FLWindow*)arg)->audioShutDown_redirect(msg);
1274 }
1275 
audioShutDown_redirect(const char * msg)1276 void FLWindow::audioShutDown_redirect(const char* msg)
1277 {
1278 // Redirect with SIGNAL TO SWITCH THREAD (leave audio thread to go to the window thread) + Copy char* for it might be destructed within audio driver before we have time to print it
1279     QString errorMsg(msg);
1280     emit audioError(errorMsg);
1281 }
1282 
audioShutDown(const QString & msg)1283 void FLWindow::audioShutDown(const QString& msg)
1284 {
1285     AudioCreator* creator = AudioCreator::_Instance(NULL);
1286     creator->reset_AudioArchitecture();
1287     errorPrint(msg);
1288     emit audioPrefChange();
1289 }
1290 
1291 //Switch of Audio architecture
update_AudioArchitecture(QString & error)1292 bool FLWindow::update_AudioArchitecture(QString& error)
1293 {
1294     AudioCreator* creator = AudioCreator::_Instance(NULL);
1295     delete fAudioManager;
1296     fAudioManager = creator->createAudioManager(FLWindow::audioShutDown, this);
1297     return (init_audioClient(error) && setDSP(error));
1298 }
1299 
1300 //Initialization of audio client reimplemented
init_audioClient(QString & error)1301 bool FLWindow::init_audioClient(QString& error)
1302 {
1303     int numberInputs = fSettings->value("InputNumber", 0).toInt();
1304     int numberOutputs = fSettings->value("OutputNumber", 0).toInt();
1305     bool midi = fSettings->value("MIDI/Enabled", FLSettings::_Instance()->value("General/Control/MIDIDefaultChecked", false)).toBool();
1306 
1307 	if (fAudioManager->initAudio(error,
1308                                 fWindowName.toStdString().c_str(),
1309                                 fSettings->value("Name", "").toString().toStdString().c_str(),
1310                                 numberInputs, numberOutputs, midi)) {
1311         update_AudioParams();
1312         return true;
1313     } else {
1314         return false;
1315     }
1316 }
1317 
update_AudioParams()1318 void FLWindow::update_AudioParams()
1319 {
1320     fSettings->setValue("SampleRate", fAudioManager->getSampleRate());
1321     fSettings->setValue("BufferSize", fAudioManager->getBufferSize());
1322 }
1323 
setDSP(QString & error)1324 bool FLWindow::setDSP(QString& error)
1325 {
1326     bool success = fAudioManager->setDSP(error, fCurrentDSP, fSettings->value("Name", "").toString().toStdString().c_str());
1327     update_AudioParams();
1328     return success;
1329 }
1330 
1331 //------------------------SAVING WINDOW ACTIONS
1332 
1333 //Read/Write window properties in saving file
saveWindow()1334 void FLWindow::saveWindow()
1335 {
1336     //Save the parameters of the actual interface
1337     fSettings->setValue("Position/x", this->geometry().x());
1338     fSettings->setValue("Position/y", this->geometry().y());
1339     fSettings->setValue("Size/w", this->geometry().width());
1340     fSettings->setValue("Size/h", this->geometry().height());
1341 
1342     //Graphical parameters//
1343     QString rcfilename = fHome + "/Windows/" + fWindowName + "/Graphics.rc";
1344     fRCInterface->saveState(rcfilename.toLatin1().data());
1345 
1346     //Audio Connections parameters
1347     QString connectFile = fHome + "/Windows/" + fWindowName + "/Connections.jc";
1348 
1349     fAudioManager->save_Connections(connectFile.toStdString());
1350 
1351     //Writing new settings in file (for infos to be synchronized)
1352     fSettings->sync();
1353  }
1354 
recall_Window()1355 void FLWindow::recall_Window()
1356 {
1357     //Graphical parameters//
1358     QString rcfilename = fHome + "/Windows/" + fWindowName + "/Graphics.rc";
1359 
1360     if (QFileInfo(rcfilename).exists()) {
1361         fRCInterface->recallState(rcfilename.toStdString().c_str());
1362     }
1363 }
1364 
1365 //------------------------ACCESSORS
1366 
get_nameWindow()1367 QString FLWindow::get_nameWindow()
1368 {
1369     return fWindowName;
1370 }
1371 
getSHA()1372 QString FLWindow::getSHA()
1373 {
1374     return fSettings->value("SHA", "").toString();
1375 }
1376 
getName()1377 QString FLWindow::getName()
1378 {
1379     return fSettings->value("Name", "").toString();
1380 }
1381 
getPath()1382 QString FLWindow::getPath(){
1383     return fSettings->value("Path", "").toString();
1384 }
1385 
get_indexWindow()1386 int FLWindow::get_indexWindow()
1387 {
1388     return fWindowIndex;
1389 }
1390 
get_source()1391 QString FLWindow::get_source()
1392 {
1393     return fSource;
1394 }
1395 
1396 //------------------------HTTPD
1397 
1398 //Calculation of screen position of the HTTP window, depending on its index
calculate_Coef()1399 int FLWindow::calculate_Coef()
1400 {
1401     int multiplCoef = fWindowIndex;
1402     while (multiplCoef > 20) {
1403         multiplCoef -= 20;
1404     }
1405     return multiplCoef;
1406 }
1407 
allocateHttpInterface()1408 void FLWindow::allocateHttpInterface()
1409 {
1410     QString windowTitle = fWindowName + ":" + getName();
1411     int argc = 3;
1412     char* argv[4];  // NULL terminated argv
1413 	char charport[20];
1414 	int port = 5510 + fWindowIndex;
1415 	sprintf(charport, "%d", port);
1416 
1417     argv[0] = (char*)(windowTitle.toStdString().c_str());
1418     argv[1] = (char*)"-port";
1419 	argv[2] = charport;
1420 
1421     argv[argc] = 0; // NULL terminated argv
1422 
1423     fHttpInterface = new httpdUI(getName().toStdString().c_str(), fCurrentDSP->getNumInputs(), fCurrentDSP->getNumOutputs(), 3, argv, false);
1424 }
1425 
deleteHttpInterface()1426 void FLWindow::deleteHttpInterface()
1427 {
1428     if (fHttpInterface) {
1429         FLServerHttp::_Instance()->removeHttpInterface(fHttpInterface->getTCPPort());
1430         delete fHttpInterface;
1431         fHttpInterface = NULL;
1432     }
1433 }
1434 
updateHttpInterface()1435 void FLWindow::updateHttpInterface()
1436 {
1437     saveWindow();
1438     deleteHttpInterface();
1439     allocateHttpInterface();
1440     fCurrentDSP->buildUserInterface(fHttpInterface);
1441     recall_Window();
1442     fHttpInterface->run();
1443     FLServerHttp::_Instance()->declareHttpInterface(fHttpInterface->getTCPPort(), getName().toStdString());
1444     setWindowsOptions();
1445 }
1446 
switchHttp(bool on)1447 void FLWindow::switchHttp(bool on)
1448 {
1449     if (on) {
1450         updateHttpInterface();
1451     } else {
1452         deleteHttpInterface();
1453     }
1454 }
1455 
viewQRCode()1456 void FLWindow::viewQRCode()
1457 {
1458     if (!fIsDefault) {
1459 
1460         if (!fHttpInterface) {
1461             fToolBar->switchHttp(true);
1462         }
1463 
1464         if (fHttpdWindow) {
1465             delete fHttpdWindow;
1466             fHttpdWindow = NULL;
1467         }
1468 
1469         fHttpdWindow = new HTTPWindow();
1470         connect(fHttpdWindow, SIGNAL(toPNG()), this, SLOT(exportToPNG()));
1471 
1472         if (fHttpdWindow) {
1473             int dropPort = FLSettings::_Instance()->value("General/Network/HttpDropPort", 7777).toInt();
1474             QString fullUrl = "http://" + searchLocalIP() + ":" + QString::number(dropPort) + "/" + QString::number(fHttpInterface->getTCPPort());
1475             fInterface->displayQRCode(fullUrl, fHttpdWindow);
1476             fHttpdWindow->move(calculate_Coef()*10, 0);
1477             QString windowTitle = fWindowName + ":" + fSettings->value("Name", "").toString().toStdString().c_str();
1478             fHttpdWindow->setWindowTitle(windowTitle);
1479             fHttpdWindow->raise();
1480             fHttpdWindow->show();
1481             fHttpdWindow->adjustSize();
1482         } else {
1483             errorPrint("Impossible to create QRCode window");
1484         }
1485     }
1486 }
1487 
exportToPNG()1488 void FLWindow::exportToPNG()
1489 {
1490     QFileDialog* fileDialog = new QFileDialog;
1491 #ifdef QTNEWCONFIRMOVERWRITE
1492     fileDialog->setOption(QFileDialog::DontConfirmOverwrite, false);
1493 #else
1494     fileDialog->setConfirmOverwrite(true);
1495 #endif
1496     QString filename;
1497     filename = fileDialog->getSaveFileName(NULL, "PNG Name", tr(""), tr("(*.png)"));
1498     QString errorMsg;
1499 
1500     if (!fInterface->toPNG(filename, errorMsg)) {
1501         errorPrint(errorMsg);
1502     }
1503 }
1504 
get_HttpUrl()1505 QString FLWindow::get_HttpUrl()
1506 {
1507     return (fHttpInterface) ? ("http://" + searchLocalIP() + ":" + QString::number(fHttpInterface->getTCPPort()) + "/") : "";
1508 }
1509 
1510 //Accessor to Http & Osc Port
get_Port()1511 int FLWindow::get_Port()
1512 {
1513     // If the interface is not enabled, it's not running on any port
1514     return (fHttpInterface) ? fHttpInterface->getTCPPort() : 0;
1515 }
1516 
1517 //Redirection of a received error
errorPrint(const QString & msg)1518 void FLWindow::errorPrint(const QString& msg)
1519 {
1520     FLErrorWindow::_Instance()->print_Error(msg);
1521 }
1522 
1523 #ifdef REMOTE
1524 //------------------REMOTE PROCESSING
1525 // We have to separate into 2 functions because the action cannot be done in the audio thread
1526 // that's why remoteDSPCallback has to send a signal, received in the graphical thread.
1527 
remoteDSPCallback(int error_code,void * arg)1528 int FLWindow::remoteDSPCallback(int error_code, void* arg)
1529 {
1530     FLWindow* errorWin = (FLWindow*) arg;
1531     errorWin->emit remoteCnxLost(error_code);
1532     return -1;
1533 }
1534 
RemoteCallback(int error_code)1535 void FLWindow::RemoteCallback(int error_code)
1536 {
1537     QDateTime currentTime(QDateTime::currentDateTime());
1538     if (fLastMigration.secsTo(currentTime) > 3) {
1539         if (error_code == ERROR_NETJACK_WRITE || error_code == ERROR_NETJACK_READ) {
1540             errorPrint("Remote Connection Error.\nSwitching back to local processing.");
1541             fStatusBar->setRemoteSettings("local processing", "127.0.0.1", 7777, "");
1542             redirectSwitch();
1543         }
1544     }
1545 
1546     fLastMigration = currentTime;
1547 }
1548 
1549 //----------------REMOTE CONTROL
1550 /*This is a never used attempt to implement remote control
1551  This is to checkout with Network/FLRemoteServer
1552  */
1553 
1554 //void FLWindow::switchRemoteControl(bool){
1555 //
1556 //    printf("");
1557 //
1558 //    Server::_Instance()->declareRemoteControl(fSettings->value("SHA", "").toString().toStdString(), getName().toStdString(), this);
1559 //}
1560 //
1561 //bool    FLWindow::createNJdspInstance(const string& name, const string& key, const string& celt, const string& ip, const string& port, const string& mtu, const string& latency){
1562 //
1563 //	Q_UNUSED(name);
1564 //	Q_UNUSED(key);
1565 //
1566 //    FLSettings::_Instance()->setValue("General/Audio/NetJackMaster/CV", celt.c_str());
1567 //    FLSettings::_Instance()->setValue("General/Audio/NetJackMaster/IP", ip.c_str());
1568 //    FLSettings::_Instance()->setValue("General/Audio/NetJackMaster/Port", port.c_str());
1569 //    FLSettings::_Instance()->setValue("General/Audio/NetJackMaster/MTU", mtu.c_str());
1570 //    FLSettings::_Instance()->setValue("General/Audio/NetJackMaster/Latency", latency.c_str());
1571 //
1572 //	return true;
1573 //}
1574 //
1575 //void FLWindow::stopNJdspAudio(const char* /*errorMsg*/){
1576 //
1577 //    printf("FLWindow::stopNJdspAudio\n");
1578 //
1579 //    fAudio->stop();
1580 //
1581 //    fAudioManager->start();
1582 //    fAudioManagerStopped = false;
1583 //
1584 //    errorPrint(errorMsg);
1585 //}
1586 
1587 //void* FLWindow::startAudioSlave(void* /*arg*/){
1588 //
1589 //    FLWindow * dspToStart = (FLWindow*) arg;
1590 //
1591 //    bool success = false;
1592 //
1593 //    if(Slave_DSP::fLocker.Lock()){
1594 //
1595 //        dspToStart->fAudio = new NJm_audioManager(NULL, NULL);
1596 //    connect(dspToStart->fAudio, SIGNAL(errorSignal(const char*)), dspToStart, SLOT(stopNJdspAudio(const char*)));
1597 //
1598 //        if (dspToStart->fAudio->init(dspToStart->getName().toStdString().c_str(), dspToStart->fCurrentDSP)) {
1599 //            if (!dspToStart->fAudio->start())
1600 //                printf("Start slave audio failed\n");
1601 //            else{
1602 //                printf("SLAVE WITH %i INPUTS || %i OUTPUTS\n", dspToStart->fCurrentDSP->getNumInputs(), dspToStart->fCurrentDSP->getNumOutputs());
1603 //                success = true;
1604 //            }
1605 //        }
1606 //        else
1607 //            printf("Init slave audio failed\n");
1608 //
1609 //        if(!success)
1610 //            deleteSlaveDSPInstance(dspToStart);
1611 
1612 //        Slave_DSP::fLocker.Unlock();
1613 //    }
1614 //    return NULL;
1615 //}
1616 //
1617 //bool FLWindow::startNJdspAudio(){
1618 //
1619 //    fAudioManager->stop();
1620 //    fAudioManagerStopped = true;
1621 //
1622 //    pthread_t myNewThread;
1623 //
1624 //    if(!pthread_create(&myNewThread, NULL, FLWindow::startAudioSlave, this)){
1625 //        return true;
1626 //    }
1627 //    else
1628 //        return false;
1629 //	return false;
1630 //}
1631 //
1632 //void FLWindow::cleanInactiveNJdspInstance(){
1633 //
1634 //    if(fAudio && !fAudio->is_connexion_active() && fAudioManagerStopped){
1635 //        fAudioManager->start();
1636 //        fAudioManagerStopped = false;
1637 //    }
1638 //
1639 //    printf("CLEAN INACTIVE\n");
1640 //}
1641 //
1642 //string FLWindow::json(){
1643 //    JSONUI json(fCurrentDSP->getNumInputs(), fCurrentDSP->getNumOutputs());
1644 //    fCurrentDSP->buildUserInterface(&json);
1645 //    string answer = json.JSON();
1646 //
1647 //    return answer;
1648 //}
1649 //
1650 //void FLWindow::switchRelease(bool on){
1651 //
1652 //    if(on){
1653 //        printf("SWITCH RELEASE\n");
1654 //        if(!FLSessionManager::_Instance()->addWinToServer(fSettings))
1655 //            FLErrorWindow::_Instance()->print_Error("Impossible to Publish Factory");
1656 ////        IL FAUT SWITCHER LA CHECKBOX SI ça NA PAS MARCHEE
1657 //    }
1658 //    else{
1659 //       FLSessionManager::_Instance()->deleteWinFromServer(fSettings);
1660 //    }
1661 //}
1662 #else
remoteDSPCallback(int error_code,void * arg)1663 int FLWindow::remoteDSPCallback(int error_code, void* arg)
1664 {
1665 	Q_UNUSED(error_code);
1666 	Q_UNUSED(arg);
1667     return -1;
1668 }
1669 #endif
1670 
1671 
1672 
1673 
1674 
1675 
1676 
1677 
1678 
1679