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