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