1 //
2 //  FaustLiveApp.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 4005 4996)
10 # define WIN32_LEAN_AND_MEAN    // this is intended to solve the winsock API redefinitions
11 #else
12 # pragma GCC diagnostic ignored "-Wunused-parameter"
13 # pragma GCC diagnostic ignored "-Wunused-function"
14 #endif
15 
16 #include <QDir>
17 
18 #include "FLServerHttp.h"
19 #include "FLApp.h"
20 
21 #ifdef _WIN32
22 #include <shlobj.h>
23 #endif
24 
25 #include "FLSessionManager.h"
26 #include "FLInterfaceManager.h"
27 #include "FLWindow.h"
28 #include "FLComponentWindow.h"
29 #include "FLErrorWindow.h"
30 #include "FLMessageWindow.h"
31 #include "FLHelpWindow.h"
32 #include "FLPresentationWindow.h"
33 #include "utilities.h"
34 
35 #ifdef REMOTE
36 #include "faust/dsp/remote-dsp.h"
37 #include "FLRemoteDSPScanner.h"
38 #endif
39 
40 #include "FLSettings.h"
41 #include "FLWinSettings.h"
42 #include "FLPreferenceWindow.h"
43 #include "FJUI.h"
44 #include "QTDefs.h"
45 
46 
47 //----------------------CONSTRUCTOR/DESTRUCTOR---------------------------
FLApp(int & argc,char ** argv)48 FLApp::FLApp(int& argc, char** argv) : QApplication(argc, argv){
49 
50     //Create Current Session Folder
51     create_Session_Hierarchy();
52 
53     FLSettings::createInstance(fSessionFolder);
54     FLSessionManager::createInstance(fSessionFolder);
55 
56     //Connect drop on the HTML interface to the application action
57     FLServerHttp::createInstance(fHtmlFolder.toStdString());
58     connect(FLServerHttp::_Instance(), SIGNAL(compile(const char*, int)), this, SLOT(compile_HttpData(const char*, int)));
59 
60 #ifdef REMOTE
61     fDSPServer = createRemoteDSPServer(0, NULL);
62     fDSPServer->start(FLSettings::_Instance()->value("General/Network/RemoteServerPort", 5555).toInt());
63     //fDSPServer = NULL;
64 #endif
65     //Initializing screen parameters
66 #ifdef QTNEWPRIMARYSCREEN
67     QSize screenSize = QGuiApplication::primaryScreen()->geometry().size();
68 #else
69     QSize screenSize = QApplication::desktop()->screen(QApplication::desktop()->primaryScreen())->geometry().size();
70 #endif
71     fScreenWidth = screenSize.width();
72     fScreenHeight = screenSize.height();
73 
74     //Base Name of application's windows
75     fWindowBaseName = "FLW-";
76 
77     //Choose default style color
78     styleClicked(FLSettings::_Instance()->value("General/Style", "Default").toString());
79 
80 	//Initializing Recalling
81 	fRecalling = false;
82 
83 #ifndef __APPLE__
84     //For the application not to quit when the last window is closed
85 	connect(this, SIGNAL(lastWindowClosed()), this, SLOT(closeAllWindows()));
86 #else
87     setQuitOnLastWindowClosed(false);
88 #endif
89 
90 	fLastOpened = getenv("HOME");
91 
92     fMenuBar = new QMenuBar();
93 
94     //Initializing menu actions
95     fRecentFileAction = new QAction* [kMAXRECENT];
96     for (int i = 0; i < kMAXRECENT; i++) {
97         fRecentFileAction[i] = new QAction(NULL);
98         fRecentFileAction[i]->setVisible(false);
99         connect(fRecentFileAction[i], SIGNAL(triggered()), this, SLOT(open_Recent_File()));
100     }
101 
102     fRrecentSessionAction = new QAction* [kMAXRECENT];
103     fIrecentSessionAction = new QAction* [kMAXRECENT];
104 
105     for (int i = 0; i < kMAXRECENT; i++) {
106         fRrecentSessionAction[i] = new QAction(NULL);
107         fRrecentSessionAction[i]->setVisible(false);
108         connect(fRrecentSessionAction[i], SIGNAL(triggered()), this, SLOT(recall_Recent_Session()));
109 
110         fIrecentSessionAction[i] = new QAction(NULL);
111         fIrecentSessionAction[i]->setVisible(false);
112         connect(fIrecentSessionAction[i], SIGNAL(triggered()), this, SLOT(import_Recent_Session()));
113     }
114 
115     setup_Menu();
116 
117     recall_Recent_Files();
118     recall_Recent_Sessions();
119 
120     //Initializing OutPut Window
121     connect(FLErrorWindow::_Instance(), SIGNAL(closeAll()), this, SLOT(shut_AllWindows_FromWindow()));
122 
123     // Presentation Window Initialization
124     connect(FLPresentationWindow::_Instance(), SIGNAL(newWin()), this, SLOT(create_Empty_Window()));
125     connect(FLPresentationWindow::_Instance(), SIGNAL(openWin()), this, SLOT(open_New_Window()));
126     connect(FLPresentationWindow::_Instance(), SIGNAL(openSession()), this, SLOT(importSnapshotFromMenu()));
127     connect(FLPresentationWindow::_Instance(), SIGNAL(openPref()), this, SLOT(Preferences()));
128     connect(FLPresentationWindow::_Instance(), SIGNAL(openHelp()), FLHelpWindow::_Instance(), SLOT(show()));
129     connect(FLPresentationWindow::_Instance(), SIGNAL(openExample(const QString&)), this, SLOT(openExampleAction(const QString&)));
130 
131     //Initialiazing Remote HTTP Drop Server
132     launch_Server();
133 
134     //If no event opened a window half a second after the application was created, a initialized window is created
135     fInitTimer = new QTimer(this);
136     connect(fInitTimer, SIGNAL(timeout()), this, SLOT(init_Timer_Action()));
137     fInitTimer->start(500);
138 
139     QTimer* updateGuiTimer = new QTimer(this);
140     QObject::connect(updateGuiTimer, SIGNAL(timeout()), this, SLOT(updateGuis()));
141     updateGuiTimer->start(100);
142 }
143 
~FLApp()144 FLApp::~FLApp(){
145 
146     save_Recent_Files();
147     save_Recent_Sessions();
148 
149     for(int i=0; i<kMAXRECENT; i++){
150         delete fRecentFileAction[i];
151         delete fRrecentSessionAction[i];
152         delete fIrecentSessionAction[i];
153     }
154 
155     delete fAudioCreator;
156 
157     delete fRecentFileAction;
158     delete fRrecentSessionAction;
159     delete fIrecentSessionAction;
160     delete fMenuBar;
161 
162     delete fInitTimer;
163 
164     FLHelpWindow::deleteInstance();
165 
166     FLSettings::deleteInstance();
167 
168     FLSessionManager::deleteInstance();
169 
170     FLServerHttp::deleteInstance();
171 
172 #ifdef REMOTE
173     if (fDSPServer)
174         deleteRemoteDSPServer(fDSPServer);
175 #endif
176 }
177 
create_Session_Hierarchy()178 void FLApp::create_Session_Hierarchy()
179 {
180 	QString separationChar;
181 
182     // Initialization of current Session Path. NOTE: This path must not
183     // contain any whitespace, otherwise SVG generation is broken! -ag
184 #ifdef _WIN32
185     /* On Windows, we allow the user to set the FAUSTLIVE_SESSIONDIR
186        environment variable to specify an alternative directory name under
187        which the Faust session directory will be created. */
188     const char *sessiondir = getenv("FAUSTLIVE_SESSIONDIR");
189 	if (sessiondir) {
190 		fSessionFolder = sessiondir;
191         if (!QFileInfo(fSessionFolder).exists()) {
192             QDir direct(fSessionFolder);
193             direct.mkdir(fSessionFolder);
194         }
195     } else {
196 		fSessionFolder = QDir::homePath();
197 	}
198     fSessionFolder += "\\FaustLive-CurrentSession-";
199     separationChar = "\\";
200 #else
201     fSessionFolder = getenv("HOME");
202     fSessionFolder += "/.FaustLive-CurrentSession-";
203     separationChar = "/";
204 #endif
205 
206     fSessionFolder += APP_VERSION;
207     if (!QFileInfo(fSessionFolder).exists()) {
208         QDir direct(fSessionFolder);
209         direct.mkdir(fSessionFolder);
210     }
211 
212 /* ---- Resources that are contained in the QT binary (examples, documentation, libs, html files, etc)
213         need to be copied in the current session to really be manipulated */
214 
215     // Copy QT resources that where loaded at compilation with application.qrc
216     fExamplesFolder = fSessionFolder + separationChar  + "Examples";
217     if (!QFileInfo(fExamplesFolder).exists()) {
218         QDir direct(fExamplesFolder);
219         direct.mkdir(fExamplesFolder);
220     }
221 
222     QDir exDir(":/");
223 
224     if (exDir.cd("Examples")) {
225 
226         QFileInfoList children = exDir.entryInfoList(QDir::Files);
227         QFileInfoList::iterator it;
228 
229         for (it = children.begin(); it != children.end(); it++) {
230      		QString pathInSession = fExamplesFolder + separationChar + it->baseName() + "." + it->completeSuffix();
231             if (!QFileInfo(pathInSession).exists()) {
232 
233                 QFile file(it->absoluteFilePath());
234                 file.copy(pathInSession);
235 
236                 QFile newFile(pathInSession);
237                 newFile.setPermissions(QFile::ReadOwner);
238             }
239         }
240     }
241 
242     fLibsFolder = fSessionFolder + separationChar  + "Libs";
243     if (!QFileInfo(fLibsFolder).exists()){
244         QDir direct(fLibsFolder);
245         direct.mkdir(fLibsFolder);
246     }
247 
248     QDir libsDir(":/");
249 
250     if (libsDir.cd("Libs")) {
251 
252         QFileInfoList children = libsDir.entryInfoList(QDir::Files);
253         QFileInfoList::iterator it;
254 
255         for(it = children.begin(); it != children.end(); it++){
256 
257 			QString pathInSession = fLibsFolder + separationChar + it->baseName() + "." + it->completeSuffix();
258 
259             if (!QFileInfo(pathInSession).exists()) {
260                 QFile file(it->absoluteFilePath());
261                 file.copy(pathInSession);
262             }
263         }
264     }
265 
266     fHtmlFolder = fSessionFolder + separationChar  + "Html";
267     if(!QFileInfo(fHtmlFolder).exists()){
268         QDir direct(fHtmlFolder);
269         direct.mkdir(fHtmlFolder);
270     }
271 
272     QDir htmlDir(":/");
273 
274     if (htmlDir.cd("Html")) {
275         QFileInfoList children = htmlDir.entryInfoList(QDir::Files);
276 
277         QFileInfoList::iterator it;
278 
279         for (it = children.begin(); it != children.end(); it++) {
280 
281 			QString pathInSession = fHtmlFolder + separationChar + it->baseName() + "." + it->completeSuffix();
282 
283             if (!QFileInfo(pathInSession).exists()) {
284                 QFile file(it->absoluteFilePath());
285                 file.copy(pathInSession);
286             }
287         }
288     }
289 
290     fDocFolder = fSessionFolder + separationChar  + "Documentation";
291     if(!QFileInfo(fDocFolder).exists()){
292         QDir direct(fDocFolder);
293         direct.mkdir(fDocFolder);
294     }
295 
296     QDir docDir(":/");
297 
298     if (docDir.cd("Documentation")) {
299         QFileInfoList children = docDir.entryInfoList(QDir::Files);
300 
301         QFileInfoList::iterator it;
302 
303         for (it = children.begin(); it != children.end(); it++) {
304             QString pathInSession = fDocFolder + separationChar + it->baseName() + "." + it->completeSuffix();
305             if (!QFileInfo(pathInSession).exists()) {
306                 QFile file(it->absoluteFilePath());
307                 file.copy(pathInSession);
308             }
309         }
310     }
311 
312     QString factoryFolder = fSessionFolder + "/SHAFolder";
313     QDir shaFolder(factoryFolder);
314     shaFolder.mkdir(factoryFolder);
315 
316     QString tempPath = fSessionFolder + "/Temp";
317     QDir tempFolder(tempPath);
318     tempFolder.mkdir(tempPath);
319 
320     QString pathWindows = fSessionFolder + "/Windows";
321 
322     QDir windowsDir(pathWindows);
323     if(!windowsDir.exists())
324         windowsDir.mkdir(pathWindows);
325 
326     QString sched(":/usr/local/lib/faust/scheduler.ll");
327     if (QFileInfo(sched).exists()) {
328         QString newScheduler = fLibsFolder + "/scheduler.ll";
329         QFile f(sched);
330         f.copy(newScheduler);
331     }
332 }
333 
334 //-------- Build FaustLive Menu
create_FileMenu()335 QMenu* FLApp::create_FileMenu()
336 {
337    QMenu* fileMenu = new QMenu(tr("File"), 0);
338 
339     QAction* newAction = new QAction(tr("&New Default Window"), NULL);
340     newAction->setShortcut(tr("Ctrl+N"));
341     newAction->setToolTip(tr("Open a new empty file"));
342     connect(newAction, SIGNAL(triggered()), this, SLOT(create_Empty_Window()));
343 
344     QAction* openAction = new QAction(tr("&Open..."),NULL);
345     openAction->setShortcut(tr("Ctrl+O"));
346     openAction->setToolTip(tr("Open a DSP file"));
347     connect(openAction, SIGNAL(triggered()), this, SLOT(open_New_Window()));
348 
349     QAction* openRemoteAction = new QAction(tr("&Open remote DSP..."),NULL);
350     // openAction->setShortcut(tr("Ctrl+O"));
351     openRemoteAction->setToolTip(tr("Open a DSP file"));
352     connect(openRemoteAction, SIGNAL(triggered()), this, SLOT(open_Remote_Window()));
353 
354     //SESSION
355 
356     QAction* componentAction = new QAction(tr("New Component Creator"), fileMenu);
357     // componentAction->setShortcut(tr("Ctrl"));
358     componentAction->setToolTip(tr("Open a new window to create a 2 dsp component"));
359     connect(componentAction, SIGNAL(triggered()), this, SLOT(create_Component_Window()));
360 
361     QAction* takeSnapshotAction = new QAction(tr("&Take Snapshot"),NULL);
362     takeSnapshotAction->setShortcut(tr("Ctrl+S"));
363     takeSnapshotAction->setToolTip(tr("Save current state"));
364     connect(takeSnapshotAction, SIGNAL(triggered()), this, SLOT(take_Snapshot()));
365 
366     QAction* recallSnapshotAction = new QAction(tr("&Recall Snapshot..."),NULL);
367     recallSnapshotAction->setShortcut(tr("Ctrl+R"));
368     recallSnapshotAction->setToolTip(tr("Close all the opened window and open your snapshot"));
369     connect(recallSnapshotAction, SIGNAL(triggered()), this, SLOT(recallSnapshotFromMenu()));
370 
371     QAction* importSnapshotAction = new QAction(tr("&Import Snapshot..."),NULL);
372     importSnapshotAction->setShortcut(tr("Ctrl+I"));
373     importSnapshotAction->setToolTip(tr("Import your snapshot in the current session"));
374     connect(importSnapshotAction, SIGNAL(triggered()), this, SLOT(importSnapshotFromMenu()));
375 
376     //SHUT
377     QAction* shutAllAction = new QAction(tr("&Close All Windows"),NULL);
378     shutAllAction->setShortcut(tr("Ctrl+Alt+W"));
379     shutAllAction->setToolTip(tr("Close all the Windows"));
380     connect(shutAllAction, SIGNAL(triggered()), this, SLOT(shut_AllWindows_FromMenu()));
381 
382     fileMenu->addAction(newAction);
383     fileMenu->addSeparator();
384     fileMenu->addAction(openAction);
385     fileMenu->addAction(create_ExampleMenu()->menuAction());
386     fileMenu->addAction(create_RecentFileMenu()->menuAction());
387 #ifdef REMOTE
388     fileMenu->addAction(openRemoteAction);
389 #endif
390     fileMenu->addSeparator();
391     fileMenu->addAction(componentAction);
392     fileMenu->addSeparator();
393     fileMenu->addAction(takeSnapshotAction);
394     fileMenu->addSeparator();
395     fileMenu->addAction(recallSnapshotAction);
396     fileMenu->addAction(create_LoadSessionMenu(true)->menuAction());
397     fileMenu->addSeparator();
398     fileMenu->addAction(importSnapshotAction);
399     fileMenu->addAction(create_LoadSessionMenu(false)->menuAction());
400     fileMenu->addSeparator();
401     fileMenu->addAction(shutAllAction);
402 
403 //#ifndef __APPLE__
404     QAction* closeAllAction = new QAction(tr("&Quit FaustLive"),NULL);
405     closeAllAction->setShortcut(tr("Ctrl+Q"));
406     closeAllAction->setToolTip(tr("Close the application"));
407     connect(closeAllAction, SIGNAL(triggered()), this, SLOT(closeAllWindows()));
408 
409     fileMenu->addSeparator();
410     fileMenu->addAction(closeAllAction);
411 //#endif
412     return fileMenu;
413 }
414 
create_ExampleMenu()415 QMenu* FLApp::create_ExampleMenu()
416 {
417     QMenu* menuOpen_Example = new QMenu(tr("&Open Example"), NULL);
418     QDir examplesDir(":/");
419 
420     if (examplesDir.cd("Examples")) {
421 
422         QFileInfoList children = examplesDir.entryInfoList(QDir::Files | QDir::Drives | QDir::NoDotAndDotDot);
423         QFileInfoList::iterator it;
424         int i = 0;
425 
426         QAction** openExamples = new QAction* [children.size()];
427 
428         for (it = children.begin(); it != children.end(); it++) {
429             openExamples[i] = new QAction(it->baseName(), NULL);
430             openExamples[i]->setData(QVariant(it->absoluteFilePath()));
431             connect(openExamples[i], SIGNAL(triggered()), this, SLOT(open_Example_From_FileMenu()));
432             menuOpen_Example->addAction(openExamples[i]);
433             i++;
434         }
435     }
436 
437     return menuOpen_Example;
438 }
439 
create_RecentFileMenu()440 QMenu* FLApp::create_RecentFileMenu()
441 {
442     QMenu* openRecentAction = new QMenu(tr("&Open Recent File"), NULL);
443 
444     for (int i = 0; i < kMAXRECENT; i++) {
445         openRecentAction->addAction(fRecentFileAction[i]);
446     }
447 
448     return openRecentAction;
449 }
450 
451 //@param recallOrImport : true = Recall ||| false = Import
create_LoadSessionMenu(bool recallOrImport)452 QMenu* FLApp::create_LoadSessionMenu(bool recallOrImport)
453 {
454     QString menuName("");
455 
456     if (recallOrImport)
457         menuName = "Recall Recent Snapshot";
458     else
459         menuName = "Import Recent Snapshot";
460 
461     QMenu* loadRecentMenu = new QMenu( menuName, NULL);
462 
463     for(int i=0; i<kMAXRECENT; i++){
464 
465         if(recallOrImport)
466             loadRecentMenu->addAction(fRrecentSessionAction[i]);
467         else
468             loadRecentMenu->addAction(fIrecentSessionAction[i]);
469     }
470 
471     return loadRecentMenu;
472 }
473 
create_NavigateMenu()474 QMenu* FLApp::create_NavigateMenu()
475 {
476     QMenu* navigateMenu = new QMenu(tr("Navigate"), 0);
477     return navigateMenu;
478 }
479 
create_HelpMenu()480 QMenu* FLApp::create_HelpMenu()
481 {
482     QMenu* helpMenu = new QMenu(tr("Help"), 0);
483 
484     QAction* versionAction = new QAction(tr("&Version"), this);
485     versionAction->setToolTip(tr("Show the version of the libraries used"));
486     connect(versionAction, SIGNAL(triggered()), this, SLOT(version_Action()));
487 
488     QAction* openFLDoc = new QAction(tr("&Open FaustLive Documentation"), NULL);
489     openFLDoc->setToolTip(tr("Open FaustLive Documentation in appropriate application"));
490     connect(openFLDoc, SIGNAL(triggered()), this, SLOT(open_FL_doc()));
491 
492     QAction* openFDoc = new QAction(tr("&Open Faust Documentation"), NULL);
493     openFDoc->setToolTip(tr("Open Faust Documentation in appropriate application"));
494     connect(openFDoc, SIGNAL(triggered()), this, SLOT(open_F_doc()));
495 
496 //#ifndef __APPLE__
497 
498     QAction* aboutAction = new QAction(tr("&Help..."), NULL);
499     aboutAction->setToolTip(tr("Show the library's About Box"));
500     connect(aboutAction, SIGNAL(triggered()), FLHelpWindow::_Instance(), SLOT(show()));
501 
502     QAction* presentationAction = new QAction(tr("&About FaustLive"), NULL);
503     presentationAction->setToolTip(tr("Show the presentation Menu"));
504     connect(presentationAction, SIGNAL(triggered()), this, SLOT(show_presentation_Action()));
505 
506     QAction* preferencesAction = new QAction(tr("&Preferences"), NULL);
507     preferencesAction->setToolTip(tr("Set the preferences of the application"));
508     connect(preferencesAction, SIGNAL(triggered()), this, SLOT(Preferences()));
509 
510     helpMenu->addAction(aboutAction);
511     helpMenu->addAction(presentationAction);
512     helpMenu->addSeparator();
513     helpMenu->addAction(preferencesAction);
514     helpMenu->addSeparator();
515 //#endif
516     helpMenu->addAction(openFLDoc);
517     helpMenu->addAction(openFDoc);
518     helpMenu->addSeparator();
519     helpMenu->addAction(versionAction);
520 //#ifndef __APPLE__
521 
522     QAction* aboutQtAction = new QAction(tr("&About Qt"), NULL);
523     aboutQtAction->setToolTip(tr("Show the library's About Box"));
524     connect(aboutQtAction, SIGNAL(triggered()), this, SLOT(aboutQt()));
525 
526     helpMenu->addAction(aboutQtAction);
527 //#endif
528 
529     return helpMenu;
530 }
531 
setup_Menu()532 void FLApp::setup_Menu()
533 {
534     //---------------------Presentation MENU
535     connect(FLPreferenceWindow::_Instance(), SIGNAL(newStyle(const QString&)), this, SLOT(styleClicked(const QString&)));
536     connect(FLPreferenceWindow::_Instance(), SIGNAL(dropPortChange()), this, SLOT(changeDropPort()));
537 
538 #ifdef REMOTE
539     connect(FLPreferenceWindow::_Instance(), SIGNAL(remoteServerPortChanged()), this, SLOT(changeRemoteServerPort()));
540 #endif
541     fAudioCreator = AudioCreator::_Instance(NULL);
542 
543     //--------------------HELP Menu
544 #ifdef _WIN32
545     QString separationChar = "\\";
546 #else
547     QString separationChar = "/";
548 #endif
549 
550     fLibsFolder = fSessionFolder + separationChar  + "Libs";
551     QString testDSPPath = fSessionFolder + separationChar + "Examples" + separationChar + "TestLibs.dsp";
552     FLHelpWindow::createInstance(fLibsFolder, testDSPPath);
553     QMenu* fileMenu = create_FileMenu();
554 
555     //----------------MenuBar setups ---
556     fMenuBar->addMenu(fileMenu);
557     fMenuBar->addSeparator();
558     fNavigateMenu = create_NavigateMenu();
559     fMenuBar->addMenu(fNavigateMenu);
560     fMenuBar->addSeparator();
561     QMenu* helpMenu = create_HelpMenu();
562     fMenuBar->addMenu(helpMenu);
563 }
564 
565 //--Update all guis
updateGuis()566 void FLApp::updateGuis()
567 {
568     FLInterfaceManager::_Instance()->updateAllGuis();
569 }
570 
571 //--Starts the presentation menu if no windows are opened (session restoration or drop on icon that opens the application)
init_Timer_Action()572 void FLApp::init_Timer_Action()
573 {
574     fInitTimer->stop();
575     if (FLW_List.size() == 0){
576         if (!recall_CurrentSession()) {
577             show_presentation_Action();
578         }
579     }
580 }
581 
582 //--Print errors in errorWindow
errorPrinting(const QString & msg)583 void FLApp::errorPrinting(const QString& msg)
584 {
585     FLErrorWindow::_Instance()->print_Error(msg);
586 }
587 
588 //--------- OPERATIONS ON WINDOWS INDEXES
589 
get_currentIndexes()590 QList<int> FLApp::get_currentIndexes()
591 {
592     QList<int> currentIndexes;
593 
594     for (QList<FLWindow*>::iterator it = FLW_List.begin(); it != FLW_List.end(); it++) {
595         currentIndexes.push_back((*it)->get_indexWindow());
596     }
597     return currentIndexes;
598 }
599 
find_smallest_index(QList<int> currentIndexes)600 int FLApp::find_smallest_index(QList<int> currentIndexes)
601 {
602     QList<int>::iterator it;
603     bool found = true;
604     int i = 0;
605 
606     while(found && currentIndexes.size() != 0) {
607         i++;
608         for (it = currentIndexes.begin(); it != currentIndexes.end(); it++){
609             if (*it == i) {
610                 found = true;
611                 break;
612             } else {
613                 found = false;
614             }
615         }
616     }
617 
618     if (i == 0) {
619         i = 1;
620     }
621     return i;
622 }
623 
624 //Calculates the position of a new window to avoid overlapping
calculate_position(int index,int * x,int * y)625 void FLApp::calculate_position(int index, int* x, int* y)
626 {
627     int multiplCoef = index;
628     while(multiplCoef > 20) {
629         multiplCoef-=20;
630     }
631     *x = fScreenWidth/3 + multiplCoef*10;
632     *y = fScreenHeight/3 + multiplCoef*10;
633 }
634 
635 //---------GET WINDOW FROM ONE OF IT'S PARAMETER
636 
getActiveWin()637 FLWindow* FLApp::getActiveWin()
638 {
639     QList<FLWindow*>::iterator it;
640     for (it = FLW_List.begin(); it != FLW_List.end(); it++) {
641         if ((*it)->isActiveWindow()) {
642             return *it;
643         }
644     }
645     return NULL;
646 }
647 
648 //--------------------------------FILE-----------------------------
649 
createWindowFolder(const QString & sessionFolder,int index)650 QString FLApp::createWindowFolder(const QString& sessionFolder, int index)
651 {
652     QString path = sessionFolder + "/Windows/" + fWindowBaseName + QString::number(index);
653     QDir dir(path);
654     if (!dir.exists()) {
655         dir.mkdir(path);
656     }
657     return path;
658 }
659 
copyWindowFolder(const QString & sessionNewFolder,int newIndex,const QString & sessionFolder,int index,map<int,int> indexChanges)660 QString FLApp::copyWindowFolder(const QString& sessionNewFolder, int newIndex, const QString& sessionFolder, int index, map<int, int> indexChanges)
661 {
662     QString newPath = sessionNewFolder + "/Windows/" + fWindowBaseName + QString::number(newIndex);
663     QString oldPath = sessionFolder + "/Windows/" + fWindowBaseName + QString::number(index);
664     cpDir(oldPath, newPath);
665     QString jcPath = newPath + "/Connections.jc";
666     map<string, string> indexStringChanges;
667 
668     for(map<int, int>::iterator it = indexChanges.begin(); it!= indexChanges.end(); it++) {
669         string oldN = fWindowBaseName.toStdString() + QString::number(it->first).toStdString();
670         string newN = fWindowBaseName.toStdString() + QString::number(it->second).toStdString();
671         indexStringChanges[oldN] = newN;
672     }
673 
674     FJUI::update(jcPath.toStdString().c_str(), indexStringChanges);
675     return newPath;
676 }
677 
connectWindowSignals(FLWindow * win)678 void FLApp::connectWindowSignals(FLWindow* win)
679 {
680     connect(win, SIGNAL(drop(QList<QString>)), this, SLOT(drop_Action(QList<QString>)));
681     connect(win, SIGNAL(closeWin()), this, SLOT(close_Window_Action()));
682     connect(win, SIGNAL(shut_AllWindows()), this, SLOT(shut_AllWindows_FromWindow()));
683     connect(win, SIGNAL(duplicate_Action()), this, SLOT(duplicate_Window()));
684     connect(win, SIGNAL(windowNameChanged()), this, SLOT(updateNavigateText()));
685     connect(win, SIGNAL(audioPrefChange()), this, SLOT(audioPrefChanged()));
686 }
687 
688 //---------------NEW WINDOW
689 
690 //--General creation function
createWindow(int index,const QString & mySource,FLWinSettings * windowSettings,QString & error)691 FLWindow* FLApp::createWindow(int index, const QString& mySource, FLWinSettings* windowSettings, QString& error)
692 {
693     if (FLW_List.size() >= numberWindows) {
694         error = "You cannot open more windows. If you are not happy with this limit, feel free to contact us : research.grame@gmail.com ^^";
695         return NULL;
696     }
697 
698     int init = kNoInit;
699     QString source(mySource);
700 
701     //In case the source is empty, the effect is chosen by default
702     if (source.compare("") == 0) {
703         source = "process = !,!:0,0;";
704         if (QString::compare(FLSettings::_Instance()->value("General/Style", "Blue").toString(), "Blue") == 0 || QString::compare(FLSettings::_Instance()->value("General/Style", "Grey").toString(), "Grey") == 0) {
705             init = kInitWhite;
706         } else {
707             init = kInitBlue;
708         }
709     }
710 
711 // Menus have to be created to be passed to the window
712     QList<QMenu*> appMenus;
713     appMenus.push_back(create_FileMenu());
714     QMenu* navigateMenu = create_NavigateMenu();
715     appMenus.push_back(navigateMenu);
716     appMenus.push_back(create_HelpMenu());
717     FLWindow* win = new FLWindow(fWindowBaseName, index, fSessionFolder, windowSettings,appMenus);
718 
719 // Initialization of the window
720 // Some of its signals have to be connected to the application slots
721     if (win->init_Window(init, source, error)) {
722         FLW_List.push_back(win);
723         connectWindowSignals(win);
724         fNavigateMenus[win] = navigateMenu;
725         QString name = win->get_nameWindow();
726         name+=" : ";
727         name+= win->getName();
728         QAction* navigate = new QAction( name, NULL);
729         connect(navigate, SIGNAL(triggered()), this, SLOT(frontShow()));
730         fFrontWindow[navigate] = win;
731         updateNavigateMenus();
732         return win;
733     } else {
734         delete win;
735         delete windowSettings;
736         return NULL;
737     }
738 }
739 
740 //--Creation accessed from Menu
create_New_Window(const QString & source)741 void FLApp::create_New_Window(const QString& source)
742 {
743     QString error("");
744     //Choice of new Window's index
745     int val = find_smallest_index(get_currentIndexes());
746 
747     int x, y;
748     calculate_position(val, &x, &y);
749     QString windowPath = createWindowFolder(fSessionFolder, val);
750 
751     QString settingPath = windowPath + "/Settings.ini";
752     FLWinSettings* windowSettings = new FLWinSettings(val, settingPath, QSettings::IniFormat);
753     windowSettings->setValue("Position/x", x);
754     windowSettings->setValue("Position/y", y);
755 
756     FLWindow* win = createWindow(val, source, windowSettings, error);
757     if (!win) {
758         errorPrinting(error);
759     }
760 }
761 
762 //--Creation of Default Window from Menu
create_Empty_Window()763 void FLApp::create_Empty_Window()
764 {
765     create_New_Window("");
766 }
767 
768 //--------------NEW COMPONENT
769 
create_Component_Window()770 void FLApp::create_Component_Window()
771 {
772     FLComponentWindow* componentWindow = new FLComponentWindow();
773     connect(componentWindow, SIGNAL(newComponent(const QString&)), this, SLOT(create_New_Window(const QString&)));
774     connect(componentWindow, SIGNAL(deleteIt()), this, SLOT(deleteComponent()));
775     componentWindow->show();
776 }
777 
deleteComponent()778 void FLApp::deleteComponent()
779 {
780     FLComponentWindow* senderWindow = qobject_cast<FLComponentWindow*>(sender());
781     senderWindow->hide();
782     senderWindow->deleteLater();
783 }
784 
785 //--------------OPEN
786 
787 //--In the case of a DSP dropped on the Application's icon, this event is called
event(QEvent * ev)788 bool FLApp::event(QEvent *ev)
789 {
790     if (ev->type() == QEvent::FileOpen) {
791         QString fileName = static_cast<QFileOpenEvent *>(ev)->file();
792         if (fileName.indexOf(".tar") != -1) {
793             recall_Snapshot(fileName, true);
794         }
795         if (fileName.indexOf(".dsp") != -1) {
796             create_New_Window(fileName);
797         }
798         return true;
799     }
800 
801     return QApplication::event(ev);
802 }
803 
804 //--Open a dsp from disk
open_New_Window()805 void FLApp::open_New_Window()
806 {
807     // In case we are opening a new Window from the presentation Menu --> the application must not close : turning fRecalling to true is the trick
808     fRecalling = true;
809     FLWindow* win = getActiveWin();
810     QStringList fileNames = QFileDialog::getOpenFileNames(NULL, tr("Open one or several DSPs"), fLastOpened, tr("Files (*.dsp)"));
811     QStringList::iterator it;
812 
813     for (it = fileNames.begin(); it != fileNames.end(); it++) {
814 
815         if ((*it) != "") {
816 		    QString inter(*it);
817 			fLastOpened = QFileInfo(inter).absolutePath();
818             if (win != NULL && win->is_Default()) {
819                 win->update_Window(inter);
820             } else {
821                 create_New_Window(inter);
822             }
823         }
824     }
825 
826     fRecalling = false;
827 }
828 
829 //--------------OPEN EXAMPLE
830 
open_Example_From_FileMenu()831 void FLApp::open_Example_From_FileMenu()
832 {
833     QAction* action = qobject_cast<QAction*>(sender());
834     QString toto(action->data().toString());
835     open_Example_Action(toto);
836 }
837 
open_Example_Action(QString pathInQResource)838 void FLApp::open_Example_Action(QString pathInQResource)
839 {
840     QFileInfo toOpen(pathInQResource);
841     openExampleAction(toOpen.baseName());
842 }
843 
openExampleAction(const QString & exampleName)844 void FLApp::openExampleAction(const QString& exampleName)
845 {
846     QString pathInSession = fExamplesFolder + "/" + exampleName + ".dsp";
847     QString codeToCompile = pathToContent(pathInSession);
848     FLWindow* win = getActiveWin();
849 
850     if (win != NULL && win->is_Default()) {
851         win->update_Window(codeToCompile);
852     } else {
853         create_New_Window(codeToCompile);
854     }
855 }
856 
857 //-------------RECENT FILES MANAGEMENT
858 
save_Recent(QList<QString> & recents,const QString & pathToSettings)859 void FLApp::save_Recent(QList<QString>& recents, const QString& pathToSettings)
860 {
861     int index = 1;
862     for (QList<QString>::iterator it=recents.begin(); it!=recents.end(); it++) {
863 
864         if (index<kMAXRECENT+1) {
865             QString settingPath = pathToSettings + QString::number(index);
866             FLSettings::_Instance()->setValue(settingPath, *it);
867             index++;
868         } else
869             break;
870     }
871 }
872 
recall_Recent(QList<QString> & recents,const QString & pathToSettings)873 void FLApp::recall_Recent(QList<QString>& recents, const QString& pathToSettings)
874 {
875     for (int i = 1; i <= kMAXRECENT; i++) {
876         QString settingPath = pathToSettings + QString::number(i);
877         QString path = FLSettings::_Instance()->value(settingPath, "").toString();
878         recents.push_back(path);
879     }
880 }
881 
882 //--Save/Recall from file
save_Recent_Files()883 void FLApp::save_Recent_Files()
884 {
885     QString settingPath = "General/RecentFiles/";
886     save_Recent(fRecentFiles, settingPath);
887 }
888 
recall_Recent_Files()889 void FLApp::recall_Recent_Files()
890 {
891     QString settingPath = "General/RecentFiles/";
892     recall_Recent(fRecentFiles, settingPath);
893     update_Recent_File();
894 }
895 
896 //--Add new recent file
set_Current_File(const QString & path)897 void FLApp::set_Current_File(const QString& path)
898 {
899     fRecentFiles.removeOne(path);
900     fRecentFiles.push_front(path);
901     update_Recent_File();
902 }
903 
904 //--Visual Update
update_Recent_File()905 void FLApp::update_Recent_File()
906 {
907     int index = 0;
908     for (QList<QString>::iterator it = fRecentFiles.begin(); it != fRecentFiles.end(); it++) {
909 
910         if (index<kMAXRECENT) {
911             QString path = *it;
912             if (path != "") {
913                 QString text = tr("&%1 %2").arg(index+1).arg(QFileInfo(path).baseName());
914                 fRecentFileAction[index]->setText(text);
915                 fRecentFileAction[index]->setData(path);
916                 fRecentFileAction[index]->setVisible(true);
917                 index++;
918             }
919         }
920         else
921             break;
922     }
923 }
924 
open_Recent_File()925 void FLApp::open_Recent_File()
926 {
927     QAction* action = qobject_cast<QAction*>(sender());
928     QString toto(action->data().toString());
929     open_Recent_File(toto);
930 }
931 
932 //--Open a recent file
open_Recent_File(const QString & toto)933 void FLApp::open_Recent_File(const QString& toto)
934 {
935     FLWindow* win = getActiveWin();
936     if( win != NULL && win->is_Default())
937         win->update_Window(toto);
938     else
939         create_New_Window(toto);
940 }
941 
942 
943 //--------------OPEN Remote DSP
944 
945 /* Attempt never finished to scann remote machines and factory and open a remote instance (checkout FLRemoteDSPScanner)*/
open_Remote_Window()946 void FLApp::open_Remote_Window(){
947 //
948 //    FLRemoteDSPScanner* dspScanner = new FLRemoteDSPScanner();
949 //
950 //    if(dspScanner->exec()){
951 //        QString sha = dspScanner->shaKey();
952 //
953 //        printf("SHA KEY TO RECALL = %s\n", sha.toStdString().c_str());
954 ////        ---> ICI IL FAUT CONSTRUIRE LES SETTINGS DE LA W POUR POUVOIR LA CRÉER SEULEMENT À PARTIR DE LA CLÉ SHA DE SA REMOTE FACTORY
955 //    }
956 //
957 //    delete dspScanner;
958 }
959 
960 //--------------------------------SESSION
961 
962 //--------------RECENTLY OPENED
963 
964 //--Save/Recall from file
save_Recent_Sessions()965 void FLApp::save_Recent_Sessions()
966 {
967     QString settingPath = "General/RecentSessions/";
968     save_Recent(fRecentSessions, settingPath);
969 }
970 
recall_Recent_Sessions()971 void FLApp::recall_Recent_Sessions()
972 {
973     QString settingPath = "General/RecentSessions/";
974     recall_Recent(fRecentSessions, settingPath);
975     update_Recent_Session();
976 }
977 
978 //Add new recent session
set_Current_Session(const QString & path)979 void FLApp::set_Current_Session(const QString& path)
980 {
981     fRecentSessions.removeOne(path);
982     fRecentSessions.push_front(path);
983     update_Recent_Session();
984 }
985 
986 //Visual Update
update_Recent_Session()987 void FLApp::update_Recent_Session()
988 {
989     int index = 0;
990 
991     for (QList<QString>::iterator it = fRecentSessions.begin(); it != fRecentSessions.end(); it++){
992 
993         printf("Index = %i || Size = %i || Session = %s\n", index, fRecentSessions.size(), it->toStdString().c_str());
994 
995         if(index<kMAXRECENT){
996 
997             QString path = *it;
998 
999             if(path != ""){
1000                 QString text = tr("&%1 %2").arg(index+1).arg(QFileInfo(path).baseName());
1001 
1002                 fRrecentSessionAction[index]->setText(text);
1003                 fRrecentSessionAction[index]->setData(path);
1004                 fRrecentSessionAction[index]->setVisible(true);
1005 
1006                 fIrecentSessionAction[index]->setText(text);
1007                 fIrecentSessionAction[index]->setData(path);
1008                 fIrecentSessionAction[index]->setVisible(true);
1009 
1010                 index++;
1011             }
1012         }
1013         else
1014             break;
1015     }
1016 }
1017 
1018 //Recall or Import recent session
recall_Recent_Session()1019 void FLApp::recall_Recent_Session(){
1020 
1021     QAction* action = qobject_cast<QAction*>(sender());
1022     QString toto(action->data().toString());
1023     recall_Snapshot(toto, false);
1024 }
1025 
import_Recent_Session()1026 void FLApp::import_Recent_Session(){
1027 
1028     QAction* action = qobject_cast<QAction*>(sender());
1029     QString toto(action->data().toString());
1030     recall_Snapshot(toto, true);
1031 }
1032 
1033 //---------------CURRENT SESSION FUNCTIONS
1034 
1035 //Update Current Session Structure with current parameters of the windows
update_CurrentSession()1036 void FLApp::update_CurrentSession(){
1037 
1038     QList<FLWindow*>::iterator it;
1039 
1040     for (it = FLW_List.begin(); it != FLW_List.end(); it++)
1041         (*it)->saveWindow();
1042 }
1043 
1044 //---------------SAVE SNAPSHOT FUNCTIONS
1045 
1046 //Save the current State in SnapshotFolder.tar
1047 //It copies the hidden Session Folder and compresses it
take_Snapshot()1048 void FLApp::take_Snapshot(){
1049 
1050     QFileDialog* fileDialog = new QFileDialog;
1051 #ifdef QTNEWCONFIRMOVERWRITE
1052     fileDialog->setOption(QFileDialog::DontConfirmOverwrite, false);
1053 #else
1054     fileDialog->setConfirmOverwrite(true);
1055 #endif
1056 	QString filename;
1057 
1058 #ifndef _WIN32
1059     filename = fileDialog->getSaveFileName(NULL, "Take Snapshot", fLastOpened, tr("(*.tar)"));
1060 #else
1061 	filename = fileDialog->getSaveFileName(NULL, "Take Snapshot", fLastOpened);
1062 #endif
1063 
1064 
1065     //If no name is placed, nothing happens
1066     if(filename.compare("") != 0){
1067 
1068 		fLastOpened = QFileInfo(filename).absolutePath();
1069 
1070         display_CompilingProgress("Saving your snapshot...");
1071 
1072         int pos = filename.indexOf(".tar");
1073 
1074         set_Current_Session(filename);
1075 
1076         if(pos != -1)
1077             filename = filename.mid(0, pos);
1078 
1079         update_CurrentSession();
1080 
1081         FLSessionManager::_Instance()->createSnapshot(filename);
1082 
1083         StopProgressSlot();
1084     }
1085 
1086     delete fileDialog;
1087 }
1088 
1089 //---------------RESTORE SNAPSHOT FUNCTIONS
1090 
recallSnapshotFromMenu()1091 void FLApp::recallSnapshotFromMenu(){
1092 
1093 	QString fileName;
1094 #ifndef _WIN32
1095     fileName = QFileDialog::getOpenFileName(NULL, tr("Recall a Snapshot"), fLastOpened,tr("Files (*.tar)"));
1096 #else
1097 	fileName = QFileDialog::getExistingDirectory(NULL, tr("Recall a Snapshot"), fLastOpened, QFileDialog::ShowDirsOnly);
1098 #endif
1099 
1100     if(fileName != ""){
1101 		fLastOpened = QFileInfo(fileName).absolutePath();
1102         recall_Snapshot(fileName, false);
1103 	}
1104 }
1105 
importSnapshotFromMenu()1106 void FLApp::importSnapshotFromMenu(){
1107 
1108 	QString fileName;
1109 #ifndef _WIN32
1110     fileName = QFileDialog::getOpenFileName(NULL, tr("Import a Snapshot"), fLastOpened, tr("Files (*.tar)"));
1111 #else
1112 	fileName = QFileDialog::getExistingDirectory(NULL, tr("Import a Snapshot"), fLastOpened, QFileDialog::ShowDirsOnly);
1113 #endif
1114 
1115     if(fileName != ""){
1116         fLastOpened = QFileInfo(fileName).absolutePath();
1117         recall_Snapshot(fileName, true);
1118 	}
1119 }
1120 
1121 //----Recall or Import a Snapshot
1122 //@param : filename = snapshot that is loaded
1123 //@param : importOption = false for recalling | true for importing
recall_Snapshot(const QString & name,bool importOption)1124 void FLApp::recall_Snapshot(const QString& name, bool importOption){
1125 
1126     QString filename(name);
1127 
1128     display_CompilingProgress("Uploading your snapshot...");
1129 
1130 	fRecalling = true;
1131 
1132     set_Current_Session(filename);
1133 
1134     if(!importOption)
1135         shut_AllWindows_FromWindow();
1136 
1137     QString folderName = QFileInfo(filename).canonicalPath() + "/" + QFileInfo(filename).baseName();
1138 
1139     map<int, QString> restoredSources = FLSessionManager::_Instance()->snapshotRestoration(filename);
1140 
1141     map<int, int> indexChanges;
1142 
1143     QList<int> currentIndexes = get_currentIndexes();
1144 
1145 //    Creating mapping between saved index and new index
1146     for(map<int, QString>::iterator it = restoredSources.begin(); it != restoredSources.end(); it++){
1147 
1148         int indexValue;
1149 
1150         if(importOption)
1151             indexValue = find_smallest_index(currentIndexes);
1152         else
1153             indexValue = it->first;
1154 
1155         indexChanges[it->first] = indexValue;
1156         currentIndexes.push_back(indexValue);
1157     }
1158 
1159 //    Restore windows with new index
1160     for(map<int, int>::iterator it = indexChanges.begin(); it != indexChanges.end(); it++){
1161 
1162         QString windowPath = copyWindowFolder(fSessionFolder, it->second, folderName, it->first, indexChanges);
1163 
1164         QString settingPath = windowPath + "/Settings.ini";
1165         FLWinSettings* windowSettings = new FLWinSettings(it->second, settingPath, QSettings::IniFormat);
1166 
1167         QString error;
1168         if(!createWindow(it->second, restoredSources[it->first], windowSettings, error))
1169             errorPrinting(error);
1170     }
1171 
1172 #ifndef _WIN32
1173     deleteDirectoryAndContent(folderName);
1174 #endif
1175 
1176 	fRecalling = false;
1177 
1178     StopProgressSlot();
1179 }
1180 
1181 //--- Common function to the snapshots and the current session
restoreSession(map<int,QString> restoredSources)1182 void FLApp::restoreSession( map<int, QString> restoredSources){
1183 
1184     map<int, QString>::iterator it;
1185     for(it = restoredSources.begin(); it != restoredSources.end(); it++){
1186 
1187         QString windowPath = createWindowFolder(fSessionFolder, it->first);
1188 
1189         QString settingPath = windowPath + "/Settings.ini";
1190         FLWinSettings* windowSettings = new FLWinSettings(it->first, settingPath, QSettings::IniFormat);
1191 
1192         QString error;
1193         if(!createWindow(it->first, it->second, windowSettings, error))
1194             errorPrinting(error);
1195     }
1196 }
1197 
1198 //----Recall saved current session
recall_CurrentSession()1199 bool FLApp::recall_CurrentSession(){
1200 
1201     map<int, QString> restoredSources = FLSessionManager::_Instance()->currentSessionRestoration();
1202 
1203     if(restoredSources.size() == 0)
1204         return false;
1205 
1206 	fRecalling = true;
1207 
1208     display_CompilingProgress("Uploading your session...");
1209 
1210 	restoreSession(restoredSources);
1211 
1212 //  If no window could be recalled, it's considered that the audio driver could not be set.
1213 //  Then we go back to the default driver
1214     if(FLW_List.size() == 0){
1215 		fAudioCreator->reset_AudioArchitecture();
1216 
1217 	    fAudioCreator->visualSettingsToTempSettings();
1218 
1219 		restoreSession(restoredSources);
1220 		fAudioCreator->tempSettingsToSavedSettings();
1221 
1222 		QString msgToPrint = fAudioCreator->get_ArchiName();
1223 
1224 		if(FLW_List.size() == 0){
1225             msgToPrint += " could not be initialized.";
1226 		}
1227 		else{
1228 			msgToPrint += " started instead.";
1229 		}
1230 
1231 		errorPrinting(msgToPrint);
1232     }
1233 
1234 	StopProgressSlot();
1235 	fRecalling = false;
1236 
1237     return true;
1238 }
1239 
1240 //--------------CLOSE
1241 
1242 //Display progress Bar on FaustLive quit
display_Progress()1243 void FLApp::display_Progress(){
1244 
1245 //    Quit dialog is shown only if there are windows to save
1246     if(FLW_List.size() != 0){
1247 
1248 //        Stop showing the menu bar
1249         fMenuBar->setEnabled(false);
1250 
1251         QDialog* savingMessage = new QDialog();
1252         savingMessage->setWindowFlags(Qt::FramelessWindowHint);
1253 
1254         QLabel* tittle = new QLabel(tr("<h2>FAUSTLIVE</h2>"));
1255         tittle->setAlignment(Qt::AlignCenter);
1256         QLabel* text = new QLabel(tr("Saving your session..."), savingMessage);
1257         text->setAlignment(Qt::AlignCenter);
1258         fPBar = new QProgressBar(savingMessage);
1259         fPBar->setAlignment(Qt::AlignCenter);
1260         fPBar->setRange(0,100);
1261         fPBar->setValue(0);
1262 
1263         QVBoxLayout* layoutSave = new QVBoxLayout;
1264 
1265         layoutSave->addWidget(tittle);
1266         layoutSave->addWidget(new QLabel(tr("")));
1267         layoutSave->addWidget(text);
1268         layoutSave->addWidget(new QLabel(tr("")));
1269         layoutSave->addWidget(fPBar);
1270         savingMessage->setLayout(layoutSave);
1271 
1272         savingMessage->adjustSize();
1273         centerOnPrimaryScreen(savingMessage);
1274         savingMessage->show();
1275 
1276         fEndTimer = new QTimer(this);
1277         connect(fEndTimer, SIGNAL(timeout()), this, SLOT(update_ProgressBar()));
1278         fEndTimer->start(7);
1279     }
1280     else
1281         quit();
1282 }
1283 
1284 //Update of this progress bar
update_ProgressBar()1285 void FLApp::update_ProgressBar(){
1286 
1287     int value = fPBar->value();
1288     int maximum = fPBar->maximum();
1289 
1290     if (value < maximum){
1291         value ++;
1292         fPBar->setValue(value);
1293     }
1294 
1295     if(value >= maximum){
1296         this->quit();
1297     }
1298 }
1299 
1300 //Quit FaustLive
closeAllWindows()1301 void FLApp::closeAllWindows(){
1302 
1303 //This function is called when there are no more windows. In case of session recallin, the application can not be closed !!
1304     if(fRecalling)
1305     	   return;
1306 
1307     display_Progress();
1308 
1309     update_CurrentSession();
1310 
1311 // Windows have to be saved before being closed, otherwise the connections are not well saved
1312     QList<FLWindow*>::iterator it;
1313 
1314     for(it = FLW_List.begin(); it != FLW_List.end(); it++)
1315         (*it)->saveWindow();
1316 
1317     for(it = FLW_List.begin(); it != FLW_List.end(); it++){
1318 
1319         (*it)->closeWindow();
1320         (*it)->deleteLater();
1321     }
1322 
1323     FLW_List.clear();
1324 
1325     FLSessionManager::_Instance()->saveCurrentSources(fSessionFolder);
1326 }
1327 
1328 //Shut all Windows forcing to pass into closeEvent of the window
shut_AllWindows_FromMenu()1329 void FLApp::shut_AllWindows_FromMenu(){
1330 
1331     while(FLW_List.size() != 0 ){
1332         FLWindow* win = *(FLW_List.begin());
1333 		win->shut();
1334     }
1335 }
1336 
1337 //Shut all Windows already coming from closeEvent
shut_AllWindows_FromWindow()1338 void FLApp::shut_AllWindows_FromWindow(){
1339     while(FLW_List.size() != 0 ){
1340         FLWindow* win = *(FLW_List.begin());
1341 		common_shutAction(win);
1342     }
1343 }
1344 
1345 //Close from Window Action
close_Window_Action()1346 void FLApp::close_Window_Action(){
1347     FLWindow* win = (FLWindow*)QObject::sender();
1348     common_shutAction(win);
1349 }
1350 
1351 //Shut a specific window
common_shutAction(FLWindow * win)1352 void FLApp::common_shutAction(FLWindow* win){
1353 
1354     QString path = win->getPath();
1355     if(path != "")
1356         set_Current_File(path);
1357 
1358     win->shutWindow();
1359 
1360     QAction* action = fFrontWindow.key(win);
1361     fFrontWindow.remove(action);
1362     fNavigateMenus.remove(win);
1363     updateNavigateMenus();
1364 
1365     FLW_List.removeOne(win);
1366     win->deleteLater();
1367 }
1368 
1369 //--------------------------------Navigate---------------------------------
1370 
updateNavigateText()1371 void FLApp::updateNavigateText(){
1372 
1373     FLWindow* win = (FLWindow*)QObject::sender();
1374 
1375     QString name = win->get_nameWindow();
1376     name+=" : ";
1377     name+= win->getName();
1378 
1379     QAction* action = fFrontWindow.key(win);
1380     action->setText(name);
1381 
1382     updateNavigateMenus();
1383 }
1384 
updateNavigateMenus()1385 void FLApp::updateNavigateMenus(){
1386 
1387     fNavigateMenu->clear();
1388 
1389     for(QMap<FLWindow*, QMenu*>::iterator it = fNavigateMenus.begin(); it != fNavigateMenus.end(); it++){
1390 
1391         it.value()->clear();
1392 
1393         for(QMap<QAction*, FLWindow*>::iterator ite = fFrontWindow.begin(); ite != fFrontWindow.end() ; ite++){
1394             it.value()->addAction(ite.key());
1395             fNavigateMenu->addAction(ite.key());
1396         }
1397     }
1398 }
1399 
frontShow()1400 void FLApp::frontShow(){
1401 
1402     QAction* action = (QAction*)QObject::sender();
1403     fFrontWindow[action]->raise();
1404 }
1405 
1406 //--------------------------------Window----------------------------------------
1407 
1408 //Duplicate a specific window
duplicate(FLWindow * window)1409 void FLApp::duplicate(FLWindow* window){
1410 
1411     int val = find_smallest_index(get_currentIndexes());
1412 
1413     //Save then Copy the duplicated window's parameters
1414     window->saveWindow();
1415 
1416     map<int, int> indexChanges;
1417     indexChanges[window->get_indexWindow()] = val;
1418 
1419     QString windowPath = copyWindowFolder(fSessionFolder, val, fSessionFolder, window->get_indexWindow(), indexChanges);
1420 
1421     QString settingPath = windowPath + "/Settings.ini";
1422     FLWinSettings* windowSettings = new FLWinSettings(val, settingPath, QSettings::IniFormat);
1423 
1424     windowSettings->setValue("Position/x", windowSettings->value("Position/x", 0).toInt()+10);
1425     windowSettings->setValue("Position/y", windowSettings->value("Position/y", 0).toInt()+10);
1426 
1427     QString error("");
1428     if(!createWindow(val, window->get_source(), windowSettings, error))
1429         errorPrinting(error);
1430 }
1431 
1432 //Duplication window from Menu
duplicate_Window()1433 void FLApp::duplicate_Window(){
1434 
1435     FLWindow* win = (FLWindow*)QObject::sender();
1436 
1437     if(win != NULL)
1438         duplicate(win);
1439 }
1440 
1441 //---------------Drop
1442 
1443 //Drop of sources on a window
drop_Action(QList<QString> sources)1444 void FLApp::drop_Action(QList<QString> sources){
1445 
1446     QList<QString>::iterator it = sources.begin();
1447 
1448     while(it!=sources.end()){
1449         create_New_Window(*it);
1450         it++;
1451     }
1452 }
1453 
1454 //--------------------------------HELP----------------------------------------
1455 
1456 //Open Faust and FaustLive documentation
open_FL_doc()1457 void FLApp::open_FL_doc(){
1458 
1459     QString pathToOpen = fDocFolder + "/UserManual.pdf";
1460 
1461     QUrl url = QUrl::fromLocalFile(pathToOpen);
1462     bool b = QDesktopServices::openUrl(url);
1463 
1464     if (!b)
1465         errorPrinting("Impossible to open FaustLive documentation ! Make sure a file association is set up for .pdf.");
1466 }
1467 
open_F_doc()1468 void FLApp::open_F_doc(){
1469 
1470     QString pathToOpen = fDocFolder + "/faust-quick-reference.pdf";
1471 
1472     QUrl url = QUrl::fromLocalFile(pathToOpen);
1473     bool b = QDesktopServices::openUrl(url);
1474 
1475     if (!b)
1476         errorPrinting("Impossible to open Faust documentation ! Make sure a file association is set up for .pdf.");
1477 }
1478 
1479 #ifndef LLVM_VERSION
1480 // best guess
1481 #define LLVM_VERSION "3.x"
1482 #endif
1483 
1484 /* This window is not added to FaustLive. But it is supposed to contain the versions of all the librairies*/
version_Action()1485 void FLApp::version_Action(){
1486 
1487     QDialog* versionWindow = new QDialog;
1488 
1489     QVBoxLayout* layoutGeneral = new QVBoxLayout;
1490 
1491     QString text = "FAUSTLIVE Version ";
1492     text += VERSION;
1493 //    text += readFile(":/distVersion.txt");
1494 //    text += "- Build version ";
1495 //    text += readFile(":/buildVersion.txt");
1496     text += "\n\nBased on ";
1497     text += "\n - LLVM Compiler ";
1498     text += LLVM_VERSION;
1499 #ifdef ALSA
1500     text += "\n - ALSA ";
1501     text += "1.0";
1502 #endif
1503 #ifdef COREAUDIO
1504     text += "\n - CoreAudio API ";
1505     text += "4.0";
1506 #endif
1507 #ifdef JACK
1508     text += "\n - Jack 2";
1509 //    text += jack_get_version_string();
1510 #endif
1511 #ifdef NETJACK
1512     text += "\n - NetJack ";
1513     text += "2.1";
1514 #endif
1515 #ifdef PORTAUDIO
1516     text += "\n - PortAudio ";
1517     text += "v19";
1518 #endif
1519 
1520     QPlainTextEdit* versionText = new QPlainTextEdit(text, versionWindow);
1521 
1522     layoutGeneral->addWidget(versionText);
1523     versionWindow->setLayout(layoutGeneral);
1524     centerOnPrimaryScreen(versionWindow);
1525     versionWindow->exec();
1526 
1527     delete versionText;
1528     delete layoutGeneral;
1529     delete versionWindow;
1530 }
1531 
1532 //-------------------------------PRESENTATION WINDOW-----------------------------
1533 
show_presentation_Action()1534 void FLApp::show_presentation_Action(){
1535     FLPresentationWindow::_Instance()->show();
1536     FLPresentationWindow::_Instance()->raise();
1537 }
1538 
1539 //--------------------------------PREFERENCES---------------------------------------
1540 
1541 //Modification of application style
styleClicked(const QString & style)1542 void FLApp::styleClicked(const QString& style){
1543 
1544     QFile file;
1545     FLSettings::_Instance()->setValue("General/Style", style);
1546 
1547     QString styleFile = ":/Styles/" + style + ".qss";
1548     file.setFileName(styleFile);
1549 
1550     if(file.open(QIODevice::ReadOnly | QIODevice::Text))
1551     {
1552         QString styleSheet = QLatin1String(file.readAll());
1553 
1554         setStyleSheet(styleSheet);
1555         file.close();
1556     }
1557 }
1558 
1559 //Preference triggered from Menu
Preferences()1560 void FLApp::Preferences(){
1561     FLPreferenceWindow::_Instance()->exec();
1562     audioPrefChanged();
1563 }
1564 
audioPrefChanged()1565 void FLApp::audioPrefChanged(){
1566     if (fAudioCreator->didSettingChanged()) {
1567         fAudioCreator->visualSettingsToTempSettings();
1568         update_AudioArchitecture();
1569     }
1570 }
1571 
1572 //Update Audio Architecture of all opened windows
update_AudioArchitecture()1573 void FLApp::update_AudioArchitecture()
1574 {
1575     QList<FLWindow*>::iterator updateFailPointer, it;
1576 
1577     display_CompilingProgress("Updating Audio Architecture...");
1578 
1579     //Update all audio clients
1580     for (it = FLW_List.begin(); it != FLW_List.end(); it++) {
1581         (*it)->resetAudioDSPInterfaces();
1582     }
1583 
1584     fAudioCreator->tempSettingsToSavedSettings();
1585 
1586     StopProgressSlot();
1587 }
1588 
1589 /*
1590 void FLApp::update_AudioArchitecture(){
1591 
1592     QList<FLWindow*>::iterator updateFailPointer, it;
1593 
1594     bool updateSuccess = true;
1595     QString errorToPrint;
1596     QString error;
1597 
1598     display_CompilingProgress("Updating Audio Architecture...");
1599 
1600     //Save all audio clients
1601     for (it = FLW_List.begin(); it != FLW_List.end(); it++) {
1602         (*it)->saveWindow();
1603     }
1604 
1605     //Stop all audio clients
1606     for (it = FLW_List.begin(); it != FLW_List.end(); it++) {
1607         (*it)->stop_Audio();
1608         // Possibly delete MIDI interface
1609         (*it)->deleteMIDIInterface();
1610     }
1611 
1612     //Try to init new audio architecture
1613     for (it = FLW_List.begin(); it != FLW_List.end(); it++) {
1614         if (!(*it)->update_AudioArchitecture(error)) {
1615             updateSuccess = false;
1616             updateFailPointer = it;
1617             break;
1618         }
1619     }
1620 
1621     bool reinitSuccess = true;
1622 
1623     //If init failed, reinit old audio Architecture
1624     if (!updateSuccess) {
1625 
1626         errorPrinting(errorToPrint);
1627         errorPrinting(error);
1628 
1629 //        If some audio did start before the failure, they have to be stopped again
1630         for (it = FLW_List.begin(); it != updateFailPointer; it++) {
1631             (*it)->stop_Audio();
1632         }
1633 
1634 //        Switch back to previous architecture
1635         fAudioCreator->restoreSavedSettings();
1636 
1637         for (it = FLW_List.begin(); it != FLW_List.end(); it++) {
1638             if (!(*it)->update_AudioArchitecture(error)) {
1639                 reinitSuccess = false;
1640                 break;
1641             }
1642         }
1643 
1644 //        In case switch back fails, every window is closed
1645         if (!reinitSuccess) {
1646             shut_AllWindows_FromMenu();
1647 
1648             errorToPrint += fAudioCreator->get_ArchiName();
1649             errorToPrint = " could not be reinitialize";
1650 
1651             errorPrinting(errorToPrint);
1652             errorPrinting(error);
1653         } else {
1654             for (it = FLW_List.begin() ; it != FLW_List.end(); it++) {
1655                 (*it)->start_Audio();
1656             }
1657 
1658             errorToPrint = fAudioCreator->get_ArchiName();
1659             errorToPrint += " was reinitialized";
1660             errorPrinting(errorToPrint);
1661         }
1662 
1663     } else {
1664 
1665         for (it = FLW_List.begin() ; it != FLW_List.end(); it++) {
1666             (*it)->start_Audio();
1667             // Possibly restart MIDI interface
1668             (*it)->updateMIDIInterface();
1669         }
1670 
1671         fAudioCreator->tempSettingsToSavedSettings();
1672 
1673         //If there is no current window, it is strange to show that msg
1674         if (FLW_List.size() != 0) {
1675             errorToPrint = fAudioCreator->get_ArchiName() + " successfully started.";
1676             errorPrinting(errorToPrint);
1677         }
1678     }
1679 
1680     StopProgressSlot();
1681 }
1682 */
1683 
1684 //--------------------------LONG WAITING PROCESSES------------------------------
1685 
1686 //Display Messages like "Compiling..." / "Connection with server..."
display_CompilingProgress(const QString & msg)1687 void FLApp::display_CompilingProgress(const QString& msg){
1688     FLMessageWindow::_Instance()->displayMessage(msg);
1689     FLMessageWindow::_Instance()->show();
1690     FLMessageWindow::_Instance()->raise();
1691 }
1692 
1693 //Stop displaying the message
StopProgressSlot()1694 void FLApp::StopProgressSlot(){
1695     FLMessageWindow::_Instance()->hide();
1696 }
1697 
1698 //-----------------------FAUSTLIVE HTTP DROP SERVER ---------------------------
1699 
1700 /*For the needs of the Http drop server, the windows are identified by their http interface ports */
httpPortToWin(int port)1701 FLWindow* FLApp::httpPortToWin(int port){
1702 
1703     for(QList<FLWindow*>::iterator it = FLW_List.begin(); it != FLW_List.end(); it++){
1704         if ((*it)->get_Port() == port)
1705             return *it;
1706     }
1707     return NULL;
1708 }
1709 
1710 //Start FaustLive Server that wraps HTTP interface in a droppable environnement
launch_Server()1711 void FLApp::launch_Server(){
1712 
1713     bool returning = true;
1714     int i = 0;
1715     bool started = true;
1716 
1717     while(!FLServerHttp::_Instance()->start()){
1718 
1719         started = false;
1720         QString s("Server Could Not Start On Port ");
1721         s += QString::number(FLSettings::_Instance()->value("General/Network/HttpDropPort", 7777).toInt());
1722         errorPrinting(s);
1723         FLSettings::_Instance()->setValue("General/Network/HttpDropPort", FLSettings::_Instance()->value("General/Network/HttpDropPort", 7777).toInt()+1);
1724 
1725         if (i > 15){
1726             returning = false;
1727             break;
1728         } else {
1729             i++;
1730         }
1731     }
1732 
1733     if(!returning)
1734         errorPrinting("Server Did Not Start.\n Please Choose another port.");
1735 
1736 //    That way, it doesn't say it when it starts normally
1737     else if(!started){
1738         QString s("Server Started On Port ");
1739         s += QString::number(FLSettings::_Instance()->value("General/Network/HttpDropPort", 7777).toInt());
1740         errorPrinting(s);
1741     }
1742 }
1743 
1744 //Stop FaustLive Server
stop_Server()1745 void FLApp::stop_Server()
1746 {
1747     FLServerHttp::_Instance()->stop();
1748 }
1749 
1750 //Update when a file is dropped on HTTP interface (it has the same behavior as a drop in FaustLive window)
compile_HttpData(const char * data,int port)1751 void FLApp::compile_HttpData(const char* data, int port)
1752 {
1753     FLWindow* win;
1754     QString source(data);
1755     QString error("");
1756 
1757     bool success = false;
1758 
1759     if(port == 0){
1760 
1761         int val = find_smallest_index(get_currentIndexes());
1762 
1763         int x, y;
1764         calculate_position(val, &x, &y);
1765 
1766         QString windowPath = createWindowFolder(fSessionFolder, val);
1767 
1768         QString settingPath = windowPath + "/Settings.ini";
1769         FLWinSettings* windowSettings = new FLWinSettings(val, settingPath, QSettings::IniFormat);
1770         windowSettings->setValue("Position/x", x);
1771         windowSettings->setValue("Position/y", y);
1772         windowSettings->setValue("Http/Enabled", true);
1773 
1774         win = createWindow(val, source, windowSettings, error);
1775 
1776         if(win != NULL)
1777             success = true;
1778     } else {
1779         win = httpPortToWin(port);
1780 
1781         if(win->update_Window(source))
1782             success = true;
1783     }
1784 
1785 //The server has to know whether the compilation is successfull, to stop blocking the answer to its client
1786     if (success){
1787         string url = win->get_HttpUrl().toStdString();
1788         FLServerHttp::_Instance()->compileSuccessfull(url);
1789     } else {
1790         FLServerHttp::_Instance()->compileFailed(error.toStdString());
1791     }
1792 }
1793 
changeDropPort()1794 void FLApp::changeDropPort(){
1795     stop_Server();
1796     launch_Server();
1797 }
1798 
1799 //--------------------FAUSTLIVE REMOTE COMPILATION SERVER ------------------------
1800 #ifdef REMOTE
changeRemoteServerPort()1801 void FLApp::changeRemoteServerPort()
1802 {
1803     if (fDSPServer) {
1804         fDSPServer->stop();
1805         fDSPServer->start(FLSettings::_Instance()->value("General/Network/RemoteServerPort", 5555).toInt());
1806     }
1807 }
1808 #endif
1809 
1810