From fa0211261465c059f939d451eb95bc89f3d5209e Mon Sep 17 00:00:00 2001 From: ed Date: Thu, 15 Mar 2018 11:11:07 +0000 Subject: [PATCH] Projucer: Add PIPGenerator class --- extras/Projucer/Builds/LinuxMakefile/Makefile | 6 + .../MacOSX/Projucer.xcodeproj/project.pbxproj | 12 +- .../VisualStudio2013/Projucer_App.vcxproj | 5 + .../Projucer_App.vcxproj.filters | 12 + .../VisualStudio2015/Projucer_App.vcxproj | 5 + .../Projucer_App.vcxproj.filters | 12 + .../VisualStudio2017/Projucer_App.vcxproj | 5 + .../Projucer_App.vcxproj.filters | 12 + .../Projucer/JuceLibraryCode/BinaryData.cpp | 99 +++- extras/Projucer/JuceLibraryCode/BinaryData.h | 5 +- extras/Projucer/Projucer.jucer | 8 + .../BinaryData/Templates/jucer_PIPMain.cpp | 72 +++ .../Utility/Helpers/jucer_MiscUtilities.cpp | 94 ++++ .../Utility/Helpers/jucer_MiscUtilities.h | 11 + .../Source/Utility/Helpers/jucer_PresetIDs.h | 5 + .../Utility/PIPs/jucer_PIPGenerator.cpp | 531 ++++++++++++++++++ .../Source/Utility/PIPs/jucer_PIPGenerator.h | 84 +++ 17 files changed, 966 insertions(+), 12 deletions(-) create mode 100644 extras/Projucer/Source/BinaryData/Templates/jucer_PIPMain.cpp create mode 100644 extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.cpp create mode 100644 extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.h diff --git a/extras/Projucer/Builds/LinuxMakefile/Makefile b/extras/Projucer/Builds/LinuxMakefile/Makefile index 70594e8378..dc78ca052e 100644 --- a/extras/Projucer/Builds/LinuxMakefile/Makefile +++ b/extras/Projucer/Builds/LinuxMakefile/Makefile @@ -111,6 +111,7 @@ OBJECTS_APP := \ $(JUCE_OBJDIR)/jucer_CodeHelpers_1e797672.o \ $(JUCE_OBJDIR)/jucer_FileHelpers_54f12f83.o \ $(JUCE_OBJDIR)/jucer_MiscUtilities_31fc8dd8.o \ + $(JUCE_OBJDIR)/jucer_PIPGenerator_fd3402c7.o \ $(JUCE_OBJDIR)/jucer_DependencyPathPropertyComponent_5d68c773.o \ $(JUCE_OBJDIR)/jucer_Icons_d02d18f1.o \ $(JUCE_OBJDIR)/jucer_JucerTreeViewBase_9b9f2ff0.o \ @@ -353,6 +354,11 @@ $(JUCE_OBJDIR)/jucer_MiscUtilities_31fc8dd8.o: ../../Source/Utility/Helpers/juce @echo "Compiling jucer_MiscUtilities.cpp" $(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<" +$(JUCE_OBJDIR)/jucer_PIPGenerator_fd3402c7.o: ../../Source/Utility/PIPs/jucer_PIPGenerator.cpp + -$(V_AT)mkdir -p $(JUCE_OBJDIR) + @echo "Compiling jucer_PIPGenerator.cpp" + $(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<" + $(JUCE_OBJDIR)/jucer_DependencyPathPropertyComponent_5d68c773.o: ../../Source/Utility/UI/PropertyComponents/jucer_DependencyPathPropertyComponent.cpp -$(V_AT)mkdir -p $(JUCE_OBJDIR) @echo "Compiling jucer_DependencyPathPropertyComponent.cpp" diff --git a/extras/Projucer/Builds/MacOSX/Projucer.xcodeproj/project.pbxproj b/extras/Projucer/Builds/MacOSX/Projucer.xcodeproj/project.pbxproj index a56997ba29..5b1c63e843 100644 --- a/extras/Projucer/Builds/MacOSX/Projucer.xcodeproj/project.pbxproj +++ b/extras/Projucer/Builds/MacOSX/Projucer.xcodeproj/project.pbxproj @@ -67,6 +67,7 @@ 8BE478303CDF061B72F219E2 = {isa = PBXBuildFile; fileRef = F2E4998FB2C7221587A79F8B; }; BF913199032B4CE970E82AA3 = {isa = PBXBuildFile; fileRef = B403AF75EAF361ED74EE476E; }; 25EF9B3FECB4C9F0F522DCAA = {isa = PBXBuildFile; fileRef = 486E8D02DAD2A0BF54A901C0; }; + 638C7247B6DBA67EFE46E124 = {isa = PBXBuildFile; fileRef = 191330B20DAC08B890656EA0; }; 2BEC1197D981951D8A897F01 = {isa = PBXBuildFile; fileRef = D859E9EA11A71BD6E85DC649; }; D0E26EB54B0087C8BE3D541E = {isa = PBXBuildFile; fileRef = 846B2A670C5A19DE0039E11A; }; 468548FB21D264DC12321327 = {isa = PBXBuildFile; fileRef = 4D5F0CA8D1273144681A1D48; }; @@ -112,6 +113,7 @@ 16751E04B0F3737BDF52CEB4 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_HeaderComponent.h"; path = "../../Source/Project/UI/jucer_HeaderComponent.h"; sourceTree = "SOURCE_ROOT"; }; 169DD91232C070C4D6470B31 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_IconButton.h"; path = "../../Source/Utility/UI/jucer_IconButton.h"; sourceTree = "SOURCE_ROOT"; }; 182CB1F96890620A202C6524 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_SourceCodeRange.h"; path = "../../Source/LiveBuildEngine/jucer_SourceCodeRange.h"; sourceTree = "SOURCE_ROOT"; }; + 191330B20DAC08B890656EA0 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_PIPGenerator.cpp"; path = "../../Source/Utility/PIPs/jucer_PIPGenerator.cpp"; sourceTree = "SOURCE_ROOT"; }; 194457D806A26E793584AC0C = {isa = PBXFileReference; lastKnownFileType = file.svg; name = "huckleberry_icon.svg"; path = "../../Source/BinaryData/Icons/huckleberry_icon.svg"; sourceTree = "SOURCE_ROOT"; }; 1B0F18E1D96F727C062B05FA = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_ProjectContentComponent.cpp"; path = "../../Source/Project/UI/jucer_ProjectContentComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; 1B5BCD4899A9E295786EB642 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_OpenDocumentManager.h"; path = "../../Source/CodeEditor/jucer_OpenDocumentManager.h"; sourceTree = "SOURCE_ROOT"; }; @@ -151,6 +153,7 @@ 3BBFA655E129C2D817EA47C9 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_ErrorListComponent.h"; path = "../../Source/LiveBuildEngine/UI/jucer_ErrorListComponent.h"; sourceTree = "SOURCE_ROOT"; }; 3C95FA2AA91EBA19ADDD5C29 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_ProjectWizard_Animated.h"; path = "../../Source/Wizards/jucer_ProjectWizard_Animated.h"; sourceTree = "SOURCE_ROOT"; }; 3D6FD9C0065BF16568EC0AB7 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_SlidingPanelComponent.h"; path = "../../Source/Utility/UI/jucer_SlidingPanelComponent.h"; sourceTree = "SOURCE_ROOT"; }; + 3DC2ED15A9DFAAEF3D2ACDDF = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_PIPMain.cpp"; path = "../../Source/BinaryData/Templates/jucer_PIPMain.cpp"; sourceTree = "SOURCE_ROOT"; }; 3EA27F52A254912218F4DE94 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_ProjectBuildInfo.h"; path = "../../Source/LiveBuildEngine/jucer_ProjectBuildInfo.h"; sourceTree = "SOURCE_ROOT"; }; 3F7C5B53347A487C7FBD2223 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_OpenGLComponentTemplate.h"; path = "../../Source/BinaryData/Templates/jucer_OpenGLComponentTemplate.h"; sourceTree = "SOURCE_ROOT"; }; 3F8EC008960DBEB2A5D3C3F4 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_Headers.h"; path = "../../Source/Application/jucer_Headers.h"; sourceTree = "SOURCE_ROOT"; }; @@ -330,6 +333,7 @@ C607639897ED2538CBB860D0 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_OpenGLComponentSimpleTemplate.h"; path = "../../Source/BinaryData/Templates/jucer_OpenGLComponentSimpleTemplate.h"; sourceTree = "SOURCE_ROOT"; }; C7245390C6C44E89F7526CFC = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_NewComponentTemplate.h"; path = "../../Source/BinaryData/Templates/jucer_NewComponentTemplate.h"; sourceTree = "SOURCE_ROOT"; }; C736264708F3F68BA745BA29 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_FloatingToolWindow.h"; path = "../../Source/Application/Windows/jucer_FloatingToolWindow.h"; sourceTree = "SOURCE_ROOT"; }; + C76271530EB4458B6146D463 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_PIPGenerator.h"; path = "../../Source/Utility/PIPs/jucer_PIPGenerator.h"; sourceTree = "SOURCE_ROOT"; }; CC1C5F8E5DE34223FEC59673 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_AudioPluginFilterTemplate.h"; path = "../../Source/BinaryData/Templates/jucer_AudioPluginFilterTemplate.h"; sourceTree = "SOURCE_ROOT"; }; CCD62DB0A19A985A4B9D7F32 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_ProjectExport_Android.h"; path = "../../Source/ProjectSaving/jucer_ProjectExport_Android.h"; sourceTree = "SOURCE_ROOT"; }; CCEA34A55813C7C4E58254F5 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_BuildTabStatusComponent.h"; path = "../../Source/LiveBuildEngine/UI/jucer_BuildTabStatusComponent.h"; sourceTree = "SOURCE_ROOT"; }; @@ -470,7 +474,8 @@ 9E2B1506AC3FDB7863766D59, C607639897ED2538CBB860D0, 023B92AC0340305762412E90, - 3F7C5B53347A487C7FBD2223, ); name = Templates; sourceTree = ""; }; + 3F7C5B53347A487C7FBD2223, + 3DC2ED15A9DFAAEF3D2ACDDF, ); name = Templates; sourceTree = ""; }; A9399733CAA07BDAB958242C = {isa = PBXGroup; children = ( 8CF70DA9AB4725126B9F55BE, F0F189518721D46C0F94FD56, @@ -669,6 +674,9 @@ A6C4AE13FB409DE414094CFA, 6FD8DBC0FF42C87D8BEE2452, 00515BA4EC5A7D4DC078ED37, ); name = Helpers; sourceTree = ""; }; + 71AF6BA7575AF4EB0CB9F43C = {isa = PBXGroup; children = ( + 191330B20DAC08B890656EA0, + C76271530EB4458B6146D463, ); name = PIPs; sourceTree = ""; }; 15F56361B9CF3E0BE705E64D = {isa = PBXGroup; children = ( 9EB33734D0DBD0370AB1247B, D859E9EA11A71BD6E85DC649, @@ -689,6 +697,7 @@ 28D0199327887FFABF9C3F20, ); name = UI; sourceTree = ""; }; 2B1F885AA027E1A76A1C32E3 = {isa = PBXGroup; children = ( AA2CBF47682AE479C1A387BE, + 71AF6BA7575AF4EB0CB9F43C, DD068F16F341D15E150CE6F1, ); name = Utility; sourceTree = ""; }; 73BAA89A783BBDD79AA27964 = {isa = PBXGroup; children = ( A69024A225F2AC31F17B1314, @@ -965,6 +974,7 @@ 8BE478303CDF061B72F219E2, BF913199032B4CE970E82AA3, 25EF9B3FECB4C9F0F522DCAA, + 638C7247B6DBA67EFE46E124, 2BEC1197D981951D8A897F01, D0E26EB54B0087C8BE3D541E, 468548FB21D264DC12321327, diff --git a/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj b/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj index cd45931321..6145717563 100644 --- a/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj +++ b/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj @@ -194,6 +194,9 @@ true + + true + @@ -236,6 +239,7 @@ + @@ -1575,6 +1579,7 @@ + diff --git a/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj.filters index 4dd76c8c76..99b84ebf72 100644 --- a/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj.filters +++ b/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj.filters @@ -68,6 +68,9 @@ {A353D068-8C43-A573-8460-59B6BA167F83} + + {A4B9C07E-05B1-BCE9-E075-7E573FFD23B0} + {ACCBC32A-58D5-1EC6-FC4D-B3B32CB6588E} @@ -349,6 +352,9 @@ Projucer\BinaryData\Templates + + Projucer\BinaryData\Templates + Projucer\CodeEditor @@ -469,6 +475,9 @@ Projucer\Utility\Helpers + + Projucer\Utility\PIPs + Projucer\Utility\UI\PropertyComponents @@ -2232,6 +2241,9 @@ Projucer\Utility\Helpers + + Projucer\Utility\PIPs + Projucer\Utility\UI\PropertyComponents diff --git a/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj b/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj index 9d249843ab..aa88b69bd2 100644 --- a/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj +++ b/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj @@ -194,6 +194,9 @@ true + + true + @@ -236,6 +239,7 @@ + @@ -1575,6 +1579,7 @@ + diff --git a/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters index adce21cf4a..5b45bb18e7 100644 --- a/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters +++ b/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters @@ -68,6 +68,9 @@ {A353D068-8C43-A573-8460-59B6BA167F83} + + {A4B9C07E-05B1-BCE9-E075-7E573FFD23B0} + {ACCBC32A-58D5-1EC6-FC4D-B3B32CB6588E} @@ -349,6 +352,9 @@ Projucer\BinaryData\Templates + + Projucer\BinaryData\Templates + Projucer\CodeEditor @@ -469,6 +475,9 @@ Projucer\Utility\Helpers + + Projucer\Utility\PIPs + Projucer\Utility\UI\PropertyComponents @@ -2232,6 +2241,9 @@ Projucer\Utility\Helpers + + Projucer\Utility\PIPs + Projucer\Utility\UI\PropertyComponents diff --git a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj index 2d8c172c33..8db387c4fc 100644 --- a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj +++ b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj @@ -194,6 +194,9 @@ true + + true + @@ -236,6 +239,7 @@ + @@ -1575,6 +1579,7 @@ + diff --git a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters index e6fb7c50a2..4f8b4a0c32 100644 --- a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters +++ b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters @@ -68,6 +68,9 @@ {A353D068-8C43-A573-8460-59B6BA167F83} + + {A4B9C07E-05B1-BCE9-E075-7E573FFD23B0} + {ACCBC32A-58D5-1EC6-FC4D-B3B32CB6588E} @@ -349,6 +352,9 @@ Projucer\BinaryData\Templates + + Projucer\BinaryData\Templates + Projucer\CodeEditor @@ -469,6 +475,9 @@ Projucer\Utility\Helpers + + Projucer\Utility\PIPs + Projucer\Utility\UI\PropertyComponents @@ -2232,6 +2241,9 @@ Projucer\Utility\Helpers + + Projucer\Utility\PIPs + Projucer\Utility\UI\PropertyComponents diff --git a/extras/Projucer/JuceLibraryCode/BinaryData.cpp b/extras/Projucer/JuceLibraryCode/BinaryData.cpp index 669eec2f3d..616832c9a8 100644 --- a/extras/Projucer/JuceLibraryCode/BinaryData.cpp +++ b/extras/Projucer/JuceLibraryCode/BinaryData.cpp @@ -7051,8 +7051,85 @@ static const unsigned char temp_binary_data_51[] = const char* jucer_OpenGLComponentTemplate_h = (const char*) temp_binary_data_51; -//================== colourscheme_dark.xml ================== +//================== jucer_PIPMain.cpp ================== static const unsigned char temp_binary_data_52[] = +"/*\r\n" +" ==============================================================================\r\n" +"\r\n" +" This file was auto-generated and contains the startup code for a PIP.\r\n" +"\r\n" +" ==============================================================================\r\n" +"*/\r\n" +"\r\n" +"#include \"../JuceLibraryCode/JuceHeader.h\"\r\n" +"#include \"%%filename%%\"\r\n" +"\r\n" +"%%component_begin%%\r\n" +"class Application : public JUCEApplication\r\n" +"{\r\n" +"public:\r\n" +" //==============================================================================\r\n" +" Application() {}\r\n" +"\r\n" +" const String getApplicationName() override { return \"%%project_name%%\"; }\r\n" +" const String getApplicationVersion() override { return \"%%project_version%%\"; }\r\n" +"\r\n" +" void initialise (const String&) override { %%startup%% }\r\n" +" void shutdown() override { %%shutdown%% }\r\n" +"\r\n" +"private:\r\n" +" class MainWindow : public DocumentWindow\r\n" +" {\r\n" +" public:\r\n" +" MainWindow (const String& name, Component* c) : DocumentWindow (name,\r\n" +" Desktop::getInstance().getDefaultLookAndFeel()\r\n" +" .findColour (ResizableWindow::backgroundColourId),\r\n" +" DocumentWindow::allButtons)\r\n" +" {\r\n" +" setUsingNativeTitleBar (true);\r\n" +" setContentOwned (c, true);\r\n" +"\r\n" +" #if JUCE_ANDROID || JUCE_IOS\r\n" +" setFullScreen (true);\r\n" +" #else\r\n" +" setResizable (true, false);\r\n" +" setResizeLimits (300, 250, 10000, 10000);\r\n" +" centreWithSize (getWidth(), getHeight());\r\n" +" #endif\r\n" +"\r\n" +" setVisible (true);\r\n" +" }\r\n" +"\r\n" +" void closeButtonPressed() override\r\n" +" {\r\n" +" JUCEApplication::getInstance()->systemRequestedQuit();\r\n" +" }\r\n" +"\r\n" +" private:\r\n" +" JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainWindow)\r\n" +" };\r\n" +" ScopedPointer mainWindow;\r\n" +"};\r\n" +"\r\n" +"//==============================================================================\r\n" +"START_JUCE_APPLICATION (Application)\r\n" +"%%component_end%%\r\n" +"\r\n" +"%%audioprocessor_begin%%\r\n" +"//==============================================================================\r\n" +"AudioProcessor* JUCE_CALLTYPE createPluginFilter()\r\n" +"{\r\n" +" return new %%class_name%%();\r\n" +"}\r\n" +"%%audioprocessor_end%%\r\n" +"\r\n" +"%%console_begin%%\r\n" +"%%console_end%%\r\n"; + +const char* jucer_PIPMain_cpp = (const char*) temp_binary_data_52; + +//================== colourscheme_dark.xml ================== +static const unsigned char temp_binary_data_53[] = "\r\n" "\r\n" "\r\n" @@ -7077,10 +7154,10 @@ static const unsigned char temp_binary_data_52[] = " \r\n" "\r\n"; -const char* colourscheme_dark_xml = (const char*) temp_binary_data_52; +const char* colourscheme_dark_xml = (const char*) temp_binary_data_53; //================== colourscheme_light.xml ================== -static const unsigned char temp_binary_data_53[] = +static const unsigned char temp_binary_data_54[] = "\r\n" "\r\n" "\r\n" @@ -7105,10 +7182,10 @@ static const unsigned char temp_binary_data_53[] = " \r\n" "\r\n"; -const char* colourscheme_light_xml = (const char*) temp_binary_data_53; +const char* colourscheme_light_xml = (const char*) temp_binary_data_54; //================== offlinepage.html ================== -static const unsigned char temp_binary_data_54[] = +static const unsigned char temp_binary_data_55[] = "\n" " \n" " \n" @@ -7152,10 +7229,10 @@ static const unsigned char temp_binary_data_54[] = " \n" ""; -const char* offlinepage_html = (const char*) temp_binary_data_54; +const char* offlinepage_html = (const char*) temp_binary_data_55; //================== projucer_EULA.txt ================== -static const unsigned char temp_binary_data_55[] = +static const unsigned char temp_binary_data_56[] = "\r\n" "IMPORTANT NOTICE: PLEASE READ CAREFULLY BEFORE INSTALLING THE SOFTWARE:\r\n" "\r\n" @@ -7319,10 +7396,10 @@ static const unsigned char temp_binary_data_55[] = "\r\n" "10.6. Please note that this License, its subject matter and its formation, are governed by English law. You and we both agree to that the courts of England and Wales will have exclusive jurisdiction.\r\n"; -const char* projucer_EULA_txt = (const char*) temp_binary_data_55; +const char* projucer_EULA_txt = (const char*) temp_binary_data_56; //================== RecentFilesMenuTemplate.nib ================== -static const unsigned char temp_binary_data_56[] = +static const unsigned char temp_binary_data_57[] = { 98,112,108,105,115,116,48,48,212,0,1,0,2,0,3,0,4,0,5,0,6,1,53,1,54,88,36,118,101,114,115,105,111,110,88,36,111,98,106,101,99,116,115,89,36,97,114,99,104,105,118,101,114,84,36,116,111,112,18,0,1,134,160,175,16,74,0,7,0,8,0,31,0,35,0,36,0,42,0,46,0,50, 0,53,0,57,0,74,0,77,0,78,0,86,0,87,0,97,0,112,0,113,0,114,0,119,0,120,0,121,0,124,0,128,0,129,0,132,0,143,0,144,0,145,0,149,0,153,0,162,0,163,0,164,0,169,0,173,0,180,0,181,0,182,0,185,0,192,0,193,0,200,0,201,0,208,0,209,0,216,0,217,0,224,0,225,0,226, 0,229,0,230,0,232,0,249,1,11,1,29,1,30,1,31,1,32,1,33,1,34,1,35,1,36,1,37,1,38,1,39,1,40,1,41,1,42,1,43,1,44,1,47,1,50,85,36,110,117,108,108,219,0,9,0,10,0,11,0,12,0,13,0,14,0,15,0,16,0,17,0,18,0,19,0,20,0,21,0,22,0,23,0,24,0,25,0,26,0,27,0,28,0,29,0, @@ -7359,7 +7436,7 @@ static const unsigned char temp_binary_data_56[] = 7,157,7,159,7,161,7,163,7,165,7,167,7,169,7,171,7,173,7,175,7,177,7,179,7,181,7,190,7,192,7,225,7,227,7,229,7,231,7,233,7,235,7,237,7,239,7,241,7,243,7,245,7,247,7,249,7,251,7,253,7,255,8,2,8,5,8,8,8,11,8,14,8,17,8,20,8,23,8,26,8,29,8,32,8,35,8,38,8, 41,8,44,8,53,8,55,8,56,8,65,8,67,8,68,8,77,8,92,8,97,8,115,8,120,8,134,0,0,0,0,0,0,2,2,0,0,0,0,0,0,1,57,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,136,0,0 }; -const char* RecentFilesMenuTemplate_nib = (const char*) temp_binary_data_56; +const char* RecentFilesMenuTemplate_nib = (const char*) temp_binary_data_57; const char* getNamedResource (const char*, int&) throw(); @@ -7424,6 +7501,7 @@ const char* getNamedResource (const char* resourceNameUTF8, int& numBytes) throw case 0x6bdeb129: numBytes = 2174; return jucer_OpenGLComponentSimpleTemplate_h; case 0x7fbac252: numBytes = 1665; return jucer_OpenGLComponentTemplate_cpp; case 0x491fa0d7: numBytes = 1263; return jucer_OpenGLComponentTemplate_h; + case 0xf4ca9e9a: numBytes = 2446; return jucer_PIPMain_cpp; case 0x763d39dc: numBytes = 1050; return colourscheme_dark_xml; case 0xe8b08520: numBytes = 1050; return colourscheme_light_xml; case 0xf11580d8: numBytes = 1155; return offlinepage_html; @@ -7490,6 +7568,7 @@ const char* namedResourceList[] = "jucer_OpenGLComponentSimpleTemplate_h", "jucer_OpenGLComponentTemplate_cpp", "jucer_OpenGLComponentTemplate_h", + "jucer_PIPMain_cpp", "colourscheme_dark_xml", "colourscheme_light_xml", "offlinepage_html", diff --git a/extras/Projucer/JuceLibraryCode/BinaryData.h b/extras/Projucer/JuceLibraryCode/BinaryData.h index 069e80c241..911711796e 100644 --- a/extras/Projucer/JuceLibraryCode/BinaryData.h +++ b/extras/Projucer/JuceLibraryCode/BinaryData.h @@ -164,6 +164,9 @@ namespace BinaryData extern const char* jucer_OpenGLComponentTemplate_h; const int jucer_OpenGLComponentTemplate_hSize = 1263; + extern const char* jucer_PIPMain_cpp; + const int jucer_PIPMain_cppSize = 2446; + extern const char* colourscheme_dark_xml; const int colourscheme_dark_xmlSize = 1050; @@ -183,7 +186,7 @@ namespace BinaryData extern const char* namedResourceList[]; // Number of elements in the namedResourceList array. - const int namedResourceListSize = 57; + const int namedResourceListSize = 58; // If you provide the name of one of the binary resource variables above, this function will // return the corresponding data and its size (or a null pointer if the name isn't found). diff --git a/extras/Projucer/Projucer.jucer b/extras/Projucer/Projucer.jucer index 0ccd8d3744..b08f7cb8b0 100644 --- a/extras/Projucer/Projucer.jucer +++ b/extras/Projucer/Projucer.jucer @@ -246,6 +246,8 @@ resource="1" file="Source/BinaryData/Templates/jucer_OpenGLComponentTemplate.cpp"/> + @@ -618,6 +620,12 @@ + + + + systemRequestedQuit(); + } + + private: + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainWindow) + }; + ScopedPointer mainWindow; +}; + +//============================================================================== +START_JUCE_APPLICATION (Application) +%%component_end%% + +%%audioprocessor_begin%% +//============================================================================== +AudioProcessor* JUCE_CALLTYPE createPluginFilter() +{ + return new %%class_name%%(); +} +%%audioprocessor_end%% + +%%console_begin%% +%%console_end%% diff --git a/extras/Projucer/Source/Utility/Helpers/jucer_MiscUtilities.cpp b/extras/Projucer/Source/Utility/Helpers/jucer_MiscUtilities.cpp index 7584f9ee6b..225e604096 100644 --- a/extras/Projucer/Source/Utility/Helpers/jucer_MiscUtilities.cpp +++ b/extras/Projucer/Source/Utility/Helpers/jucer_MiscUtilities.cpp @@ -321,3 +321,97 @@ bool isJUCEModule (const String& moduleID) noexcept return juceModuleIds.contains (moduleID); } + +bool isValidExporterName (const String& exporterName) noexcept +{ + static StringArray validExporters = + { + "XCODE_MAC", + "XCODE_IPHONE", + "VS2013", + "VS2015", + "VS2017", + "LINUX_MAKE", + "ANDROIDSTUDIO", + "CODEBLOCKS_WINDOWS", + "CODEBLOCKS_LINUX" + }; + + return validExporters.contains (exporterName); +} + +String getTargetFolderForExporter (const String& exporterName) noexcept +{ + if (exporterName == "XCODE_MAC") return "MacOSX"; + if (exporterName == "XCODE_IPHONE") return "iOS"; + if (exporterName == "VS2017") return "VisualStudio2017"; + if (exporterName == "VS2015") return "VisualStudio2015"; + if (exporterName == "VS2013") return "MacOVisualStudio2015SX"; + if (exporterName == "LINUX_MAKE") return "LinuxMakefile"; + if (exporterName == "ANDROIDSTUDIO") return "Android"; + if (exporterName == "CODEBLOCKS_WINDOWS") return "CodeBlocksWindows"; + if (exporterName == "CODEBLOCKS_LINUX") return "CodeBlocksLinux"; + + return {}; +} + +StringArray getModulesRequiredForConsole() noexcept +{ + return { "juce_core", + "juce_data_structures", + "juce_events" + }; +} + +StringArray getModulesRequiredForComponent() noexcept +{ + return { "juce_core", + "juce_data_structures", + "juce_events", + "juce_graphics", + "juce_gui_basics" + }; +} + +StringArray getModulesRequiredForAudioProcessor() noexcept +{ + return { "juce_audio_basics", + "juce_audio_devices", + "juce_audio_formats", + "juce_audio_plugin_client", + "juce_audio_processors", + "juce_audio_utils", + "juce_core", + "juce_data_structures", + "juce_events", + "juce_graphics", + "juce_gui_basics", + "juce_gui_extra" + }; +} + +bool isPIPFile (const File& file) noexcept +{ + for (auto line : StringArray::fromLines (file.loadFileAsString())) + { + auto trimmedLine = trimCommentCharsFromStartOfLine (line); + + if (trimmedLine.startsWith ("BEGIN_JUCE_PIP_METADATA")) + return true; + } + + return false; +} + +File getJUCEExamplesDirectoryPathFromGlobal() noexcept +{ + return File (getAppSettings().getStoredPath (Ids::defaultJuceModulePath).toString()).getSiblingFile ("examples"); +} + +bool isValidJUCEExamplesDirectory (const File& directory) noexcept +{ + if (! directory.exists() || ! directory.isDirectory() || ! directory.containsSubDirectories()) + return false; + + return directory.getChildFile ("Resources").getChildFile ("juce_icon.png").existsAsFile(); +} diff --git a/extras/Projucer/Source/Utility/Helpers/jucer_MiscUtilities.h b/extras/Projucer/Source/Utility/Helpers/jucer_MiscUtilities.h index c7d8be4f3f..253e1618e2 100644 --- a/extras/Projucer/Source/Utility/Helpers/jucer_MiscUtilities.h +++ b/extras/Projucer/Source/Utility/Helpers/jucer_MiscUtilities.h @@ -59,6 +59,17 @@ void addPlistDictionaryKeyInt (XmlElement* xml, const String& key, int value); bool fileNeedsCppSyntaxHighlighting (const File& file); bool isJUCEModule (const String& moduleID) noexcept; +bool isValidExporterName (const String& exporterName) noexcept; +String getTargetFolderForExporter (const String& exporterName) noexcept; + +StringArray getModulesRequiredForConsole() noexcept; +StringArray getModulesRequiredForComponent() noexcept; +StringArray getModulesRequiredForAudioProcessor() noexcept; + +bool isPIPFile (const File&) noexcept; + +File getJUCEExamplesDirectoryPathFromGlobal() noexcept; +bool isValidJUCEExamplesDirectory (const File&) noexcept; //============================================================================== int indexOfLineStartingWith (const StringArray& lines, const String& text, int startIndex); diff --git a/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h b/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h index a76b7cff16..d3444f8e65 100644 --- a/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h +++ b/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h @@ -316,10 +316,15 @@ namespace Ids DECLARE_ID (pluginAAXCategory); DECLARE_ID (pluginAAXDisableBypass); DECLARE_ID (pluginAAXDisableMultiMono); + DECLARE_ID (exporters); + DECLARE_ID (website); + DECLARE_ID (mainClass); + DECLARE_ID (moduleFlags); const Identifier ID ("id"); const Identifier ID_uppercase ("ID"); const Identifier class_ ("class"); + const Identifier dependencies_ ("dependencies"); #undef DECLARE_ID } diff --git a/extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.cpp b/extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.cpp new file mode 100644 index 0000000000..797375e951 --- /dev/null +++ b/extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.cpp @@ -0,0 +1,531 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2017 - ROLI Ltd. + + JUCE is an open source library subject to commercial or open-source + licensing. + + By using JUCE, you agree to the terms of both the JUCE 5 End-User License + Agreement and JUCE 5 Privacy Policy (both updated and effective as of the + 27th April 2017). + + End User License Agreement: www.juce.com/juce-5-licence + Privacy Policy: www.juce.com/juce-5-privacy-policy + + Or: You may also use this code under the terms of the GPL v3 (see + www.gnu.org/licenses). + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +#include "../../Application/jucer_Headers.h" +#include "jucer_PIPGenerator.h" + +//============================================================================== +static String removeEnclosed (const String& input, const String& start, const String& end) +{ + auto startIndex = input.indexOf (start); + auto endIndex = input.indexOf (end) + end.length(); + + if (startIndex != -1 && endIndex != -1) + return input.replaceSection (startIndex, endIndex - startIndex, {}); + + return input; +} + +static void ensureSingleNewLineAfterIncludes (StringArray& lines) +{ + int lastIncludeIndex = -1; + + for (int i = 0; i < lines.size(); ++i) + { + if (lines[i].contains ("#include")) + lastIncludeIndex = i; + } + + if (lastIncludeIndex != -1) + { + auto index = lastIncludeIndex; + int numNewLines = 0; + + while (++index < lines.size() && lines[index].isEmpty()) + ++numNewLines; + + if (numNewLines > 1) + lines.removeRange (lastIncludeIndex + 1, numNewLines - 1); + } +} + +static String ensureCorrectWhitespace (const String& input) +{ + auto lines = StringArray::fromLines (input); + ensureSingleNewLineAfterIncludes (lines); + return joinLinesIntoSourceFile (lines); +} + +static bool isJUCEExample (const File& pipFile) +{ + int numLinesToTest = 10; // license should be at the top of the file so no need to + // check all lines + + for (auto line : StringArray::fromLines (pipFile.loadFileAsString())) + { + if (line.contains ("This file is part of the JUCE examples.")) + return true; + + --numLinesToTest; + } + + return false; +} + +//============================================================================== +PIPGenerator::PIPGenerator (const File& pip, const File& output) + : pipFile (pip), + metadata (parsePIPMetadata()) +{ + if (output != File()) + { + outputDirectory = output; + isTemp = false; + } + else + { + outputDirectory = File::getSpecialLocation (File::SpecialLocationType::tempDirectory).getChildFile ("PIPs"); + isTemp = true; + } + + outputDirectory = outputDirectory.getChildFile (metadata[Ids::name].toString()); + useLocalCopy = metadata[Ids::useLocalCopy].toString().isNotEmpty(); +} + +//============================================================================== +Result PIPGenerator::createJucerFile() +{ + ValueTree root (Ids::JUCERPROJECT); + + auto result = setProjectSettings (root); + + if (result != Result::ok()) + return result; + + addModules (root); + addExporters (root); + createFiles (root); + + if (! metadata[Ids::moduleFlags].toString().isEmpty()) + setModuleFlags (root); + + auto outputFile = outputDirectory.getChildFile (metadata[Ids::name].toString() + ".jucer"); + + ScopedPointer xml = root.createXml(); + + if (xml->writeToFile (outputFile, {})) + return Result::ok(); + else + return Result::fail ("Failed to create .jucer file in " + outputDirectory.getFullPathName()+ "."); +} + +bool PIPGenerator::createMainCpp() +{ + auto outputFile = outputDirectory.getChildFile ("Source").getChildFile ("Main.cpp"); + + if (! outputFile.existsAsFile() && (outputFile.create() != Result::ok())) + return false; + + outputFile.replaceWithText (getMainFileTextForType()); + + return true; +} + +//============================================================================== +var PIPGenerator::parsePIPMetadata (const StringArray& lines) +{ + auto* o = new DynamicObject(); + var result (o); + + for (auto& line : lines) + { + line = trimCommentCharsFromStartOfLine (line); + + auto colon = line.indexOfChar (':'); + + if (colon >= 0) + { + auto key = line.substring (0, colon).trim(); + auto value = line.substring (colon + 1).trim(); + + o->setProperty (key, value); + } + } + + return result; +} + +static String parseMetadataItem (const StringArray& lines, int& index) +{ + String result = lines[index++]; + + while (index < lines.size()) + { + auto continuationLine = trimCommentCharsFromStartOfLine (lines[index]); + + if (continuationLine.indexOfChar (':') != -1 || continuationLine.startsWith ("END_JUCE_PIP_METADATA")) + break; + + result += continuationLine; + ++index; + } + + return result; +} + +var PIPGenerator::parsePIPMetadata() +{ + StringArray lines; + pipFile.readLines (lines); + + for (int i = 0; i < lines.size(); ++i) + { + auto trimmedLine = trimCommentCharsFromStartOfLine (lines[i]); + + if (trimmedLine.startsWith ("BEGIN_JUCE_PIP_METADATA")) + { + StringArray desc; + auto j = i + 1; + + while (j < lines.size()) + { + if (trimCommentCharsFromStartOfLine (lines[j]).startsWith ("END_JUCE_PIP_METADATA")) + return parsePIPMetadata (desc); + + desc.add (parseMetadataItem (lines, j)); + } + } + } + + return {}; +} + +//============================================================================== +void PIPGenerator::addFileToTree (ValueTree& groupTree, const String& name, bool compile, const String& path) +{ + ValueTree file (Ids::FILE); + file.setProperty (Ids::ID, createAlphaNumericUID(), nullptr); + file.setProperty (Ids::name, name, nullptr); + file.setProperty (Ids::compile, compile, nullptr); + file.setProperty (Ids::resource, 0, nullptr); + file.setProperty (Ids::file, path, nullptr); + + groupTree.addChild (file, -1, nullptr); +} + +void PIPGenerator::createFiles (ValueTree& jucerTree) +{ + auto sourceDir = outputDirectory.getChildFile ("Source"); + + if (! sourceDir.exists()) + sourceDir.createDirectory(); + + if (useLocalCopy) + pipFile.copyFileTo (sourceDir.getChildFile (pipFile.getFileName())); + + ValueTree mainGroup (Ids::MAINGROUP); + mainGroup.setProperty (Ids::ID, createAlphaNumericUID(), nullptr); + mainGroup.setProperty (Ids::name, metadata[Ids::name], nullptr); + + ValueTree group (Ids::GROUP); + group.setProperty (Ids::ID, createGUID (sourceDir.getFullPathName() + "_guidpathsaltxhsdf"), nullptr); + group.setProperty (Ids::name, "Source", nullptr); + + addFileToTree (group, "Main.cpp", true, "Source/Main.cpp"); + addFileToTree (group, pipFile.getFileName(), false, useLocalCopy ? "Source/" + pipFile.getFileName() + : pipFile.getFullPathName()); + + mainGroup.addChild (group, -1, nullptr); + + if (useLocalCopy) + { + auto relativeFiles = replaceRelativeIncludesAndGetFilesToMove(); + + if (relativeFiles.size() > 0) + { + ValueTree resources (Ids::GROUP); + resources.setProperty (Ids::ID, createAlphaNumericUID(), nullptr); + resources.setProperty (Ids::name, "Resources", nullptr); + + for (auto& f : relativeFiles) + if (copyRelativeFileToLocalSourceDirectory (f)) + addFileToTree (resources, f.getFileName(), f.getFileExtension() == ".cpp", "Source/" + f.getFileName()); + + mainGroup.addChild (resources, -1, nullptr); + } + } + + jucerTree.addChild (mainGroup, 0, nullptr); +} + +ValueTree PIPGenerator::createModulePathChild (const String& moduleID) +{ + ValueTree modulePath (Ids::MODULEPATH); + + modulePath.setProperty (Ids::ID, moduleID, nullptr); + modulePath.setProperty (Ids::path, {}, nullptr); + + return modulePath; +} + +ValueTree PIPGenerator::createBuildConfigChild (bool isDebug) +{ + ValueTree child (Ids::CONFIGURATIONS); + + child.setProperty (Ids::name, isDebug ? "Debug" : "Release", nullptr); + child.setProperty (Ids::isDebug, isDebug ? 1 : 0, nullptr); + child.setProperty (Ids::optimisation, isDebug ? 1 : 3, nullptr); + child.setProperty (Ids::targetName, metadata[Ids::name], nullptr); + + return child; +} + +ValueTree PIPGenerator::createExporterChild (const String& exporterName) +{ + ValueTree exporter (exporterName); + + exporter.setProperty (Ids::targetFolder, "Builds/" + getTargetFolderForExporter (exporterName), nullptr); + + { + ValueTree configs (Ids::CONFIGURATIONS); + + configs.addChild (createBuildConfigChild (true), -1, nullptr); + configs.addChild (createBuildConfigChild (false), -1, nullptr); + + exporter.addChild (configs, -1, nullptr); + } + + { + ValueTree modulePaths (Ids::MODULEPATHS); + + auto modules = StringArray::fromTokens (metadata[Ids::dependencies_].toString(), ",", {}); + + for (auto m : modules) + { + m = m.trim(); + + if (isJUCEModule (m)) + modulePaths.addChild (createModulePathChild (m), -1, nullptr); + } + + exporter.addChild (modulePaths, -1, nullptr); + } + + return exporter; +} + +ValueTree PIPGenerator::createModuleChild (const String& moduleID) +{ + ValueTree module (Ids::MODULE); + + module.setProperty (Ids::ID, moduleID, nullptr); + module.setProperty (Ids::showAllCode, 1, nullptr); + module.setProperty (Ids::useLocalCopy, 0, nullptr); + module.setProperty (Ids::useGlobalPath, 1, nullptr); + + return module; +} + +void PIPGenerator::addExporters (ValueTree& jucerTree) +{ + ValueTree exportersTree (Ids::EXPORTFORMATS); + + auto exporters = StringArray::fromTokens (metadata[Ids::exporters].toString(), ",", {}); + + for (auto& e : exporters) + { + e = e.trim().toUpperCase(); + + if (isValidExporterName (e)) + exportersTree.addChild (createExporterChild (e), -1, nullptr); + } + + jucerTree.addChild (exportersTree, -1, nullptr); +} + +void PIPGenerator::addModules (ValueTree& jucerTree) +{ + ValueTree modulesTree (Ids::MODULES); + + auto modules = StringArray::fromTokens (metadata[Ids::dependencies_].toString(), ",", {}); + modules.trim(); + + auto projectType = metadata[Ids::type].toString(); + + if (projectType == "Console") + modules.mergeArray (getModulesRequiredForConsole()); + else if (projectType == "Component") + modules.mergeArray (getModulesRequiredForComponent()); + else if (projectType == "AudioProcessor") + modules.mergeArray (getModulesRequiredForAudioProcessor()); + + for (auto& m : modules) + { + m = m.trim(); + + if (isJUCEModule (m)) + modulesTree.addChild (createModuleChild (m), -1, nullptr); + } + + jucerTree.addChild (modulesTree, -1, nullptr); +} + +Result PIPGenerator::setProjectSettings (ValueTree& jucerTree) +{ + jucerTree.setProperty (Ids::name, metadata[Ids::name], nullptr); + jucerTree.setProperty (Ids::companyName, metadata[Ids::vendor], nullptr); + jucerTree.setProperty (Ids::version, metadata[Ids::version], nullptr); + jucerTree.setProperty (Ids::userNotes, metadata[Ids::description], nullptr); + jucerTree.setProperty (Ids::companyWebsite, metadata[Ids::website], nullptr); + + auto defines = metadata[Ids::defines].toString(); + + if (useLocalCopy && isJUCEExample (pipFile)) + { + auto examplesDirectory = getJUCEExamplesDirectoryPathFromGlobal(); + + if (isValidJUCEExamplesDirectory (examplesDirectory)) + { + defines += ((defines.isEmpty() ? "" : " ") + String ("PIP_JUCE_EXAMPLES_DIRECTORY=") + + examplesDirectory.getFullPathName()); + } + else + { + return Result::fail (String ("Invalid JUCE path. Set path to JUCE via ") + + (TargetOS::getThisOS() == TargetOS::osx ? "\"Projucer->Global Paths...\"" + : "\"File->Global Paths...\"") + + " menu item."); + } + } + + jucerTree.setProperty (Ids::defines, defines, nullptr); + + auto type = metadata[Ids::type].toString(); + + if (type == "Console") + { + jucerTree.setProperty (Ids::projectType, "consoleapp", nullptr); + } + else if (type == "Component") + { + jucerTree.setProperty (Ids::projectType, "guiapp", nullptr); + } + else if (type == "AudioProcessor") + { + jucerTree.setProperty (Ids::projectType, "audioplug", nullptr); + + jucerTree.setProperty (Ids::buildVST, false, nullptr); + jucerTree.setProperty (Ids::buildVST3, false, nullptr); + jucerTree.setProperty (Ids::buildAU, false, nullptr); + jucerTree.setProperty (Ids::buildAUv3, false, nullptr); + jucerTree.setProperty (Ids::buildRTAS, false, nullptr); + jucerTree.setProperty (Ids::buildAAX, false, nullptr); + jucerTree.setProperty (Ids::buildStandalone, true, nullptr); + } + + return Result::ok(); +} + +void PIPGenerator::setModuleFlags (ValueTree& jucerTree) +{ + ValueTree options ("JUCEOPTIONS"); + + for (auto& option : StringArray::fromTokens (metadata[Ids::moduleFlags].toString(), ",", {})) + { + auto name = option.upToFirstOccurrenceOf ("=", false, true).trim(); + auto value = option.fromFirstOccurrenceOf ("=", false, true).trim(); + + options.setProperty (name, (value == "1" ? 1 : 0), nullptr); + } + + jucerTree.addChild (options, -1, nullptr); +} + +String PIPGenerator::getMainFileTextForType() +{ + String mainTemplate (BinaryData::jucer_PIPMain_cpp); + + mainTemplate = mainTemplate.replace ("%%filename%%", useLocalCopy ? pipFile.getFileName() + : pipFile.getFullPathName()); + + auto type = metadata[Ids::type].toString(); + + if (type == "Console") + { + mainTemplate = removeEnclosed (mainTemplate, "%%component_begin%%", "%%component_end%%"); + mainTemplate = removeEnclosed (mainTemplate, "%%audioprocessor_begin%%", "%%audioprocessor_end%%"); + mainTemplate = mainTemplate.replace ("%%console_begin%%", {}).replace ("%%console_end%%", {}); + + return ensureCorrectWhitespace (mainTemplate); + } + else if (type == "Component") + { + mainTemplate = removeEnclosed (mainTemplate, "%%audioprocessor_begin%%", "%%audioprocessor_end%%"); + mainTemplate = removeEnclosed (mainTemplate, "%%console_begin%%", "%%console_end%%"); + mainTemplate = mainTemplate.replace ("%%component_begin%%", {}).replace ("%%component_end%%", {}); + + mainTemplate = mainTemplate.replace ("%%project_name%%", metadata[Ids::name].toString()); + mainTemplate = mainTemplate.replace ("%%project_version%%", metadata[Ids::version].toString()); + + return ensureCorrectWhitespace (mainTemplate.replace ("%%startup%%", "mainWindow = new MainWindow (" + metadata[Ids::name].toString().quoted() + + ", new " + metadata[Ids::mainClass].toString() + "());") + .replace ("%%shutdown%%", "mainWindow = nullptr;")); + } + else if (type == "AudioProcessor") + { + mainTemplate = removeEnclosed (mainTemplate, "%%component_begin%%", "%%component_end%%"); + mainTemplate = removeEnclosed (mainTemplate, "%%console_begin%%", "%%console_end%%"); + mainTemplate = mainTemplate.replace ("%%audioprocessor_begin%%", {}).replace ("%%audioprocessor_end%%", {}); + + return ensureCorrectWhitespace (mainTemplate.replace ("%%class_name%%", metadata[Ids::mainClass].toString())); + } + + return {}; +} + +//============================================================================== +Array PIPGenerator::replaceRelativeIncludesAndGetFilesToMove() +{ + StringArray lines; + pipFile.readLines (lines); + Array files; + + for (auto& line : lines) + { + if (line.contains ("#include") && ! line.contains ("JuceLibraryCode")) + { + auto path = line.fromFirstOccurrenceOf ("#include", false, false); + path = path.removeCharacters ("\"").trim(); + + auto file = pipFile.getParentDirectory().getChildFile (path); + files.add (file); + + line = line.replace (path, file.getFileName()); + } + } + + outputDirectory.getChildFile ("Source") + .getChildFile (pipFile.getFileName()) + .replaceWithText (joinLinesIntoSourceFile (lines)); + + return files; +} + +bool PIPGenerator::copyRelativeFileToLocalSourceDirectory (const File& fileToCopy) const noexcept +{ + return fileToCopy.copyFileTo (outputDirectory.getChildFile ("Source") + .getChildFile (fileToCopy.getFileName())); +} diff --git a/extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.h b/extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.h new file mode 100644 index 0000000000..d85769efa4 --- /dev/null +++ b/extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.h @@ -0,0 +1,84 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2017 - ROLI Ltd. + + JUCE is an open source library subject to commercial or open-source + licensing. + + By using JUCE, you agree to the terms of both the JUCE 5 End-User License + Agreement and JUCE 5 Privacy Policy (both updated and effective as of the + 27th April 2017). + + End User License Agreement: www.juce.com/juce-5-licence + Privacy Policy: www.juce.com/juce-5-privacy-policy + + Or: You may also use this code under the terms of the GPL v3 (see + www.gnu.org/licenses). + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +#pragma once + +#include "../Helpers/jucer_MiscUtilities.h" + +//============================================================================== +class PIPGenerator +{ +public: + PIPGenerator (const File& pipFile, const File& outputDirectory = {}); + + //============================================================================== + bool hasValidPIP() const noexcept { return ! metadata[Ids::name].toString().isEmpty(); } + File getJucerFile() noexcept { return outputDirectory.getChildFile (metadata[Ids::name].toString() + ".jucer"); } + + String getMainClassName() const noexcept { return metadata[Ids::mainClass]; } + + File getOutputDirectory() const noexcept { return outputDirectory; } + + //============================================================================== + Result createJucerFile(); + bool createMainCpp(); + +private: + //============================================================================== + var parsePIPMetadata (const StringArray& lines); + var parsePIPMetadata(); + + //============================================================================== + void addFileToTree (ValueTree& groupTree, const String& name, bool compile, const String& path); + void createFiles (ValueTree& jucerTree); + + ValueTree createModulePathChild (const String& moduleID); + ValueTree createBuildConfigChild (bool isDebug); + ValueTree createExporterChild (const String& exporterName); + ValueTree createModuleChild (const String& moduleID); + + void addExporters (ValueTree& jucerTree); + void addModules (ValueTree& jucerTree); + + Result setProjectSettings (ValueTree& jucerTree); + + void setModuleFlags (ValueTree& jucerTree); + + String getMainFileTextForType(); + + //============================================================================== + Array replaceRelativeIncludesAndGetFilesToMove(); + bool copyRelativeFileToLocalSourceDirectory (const File&) const noexcept; + + //============================================================================== + File pipFile, outputDirectory; + var metadata; + + bool isTemp = false; + bool useLocalCopy = false; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PIPGenerator) +};