diff --git a/extras/Projucer/Builds/LinuxMakefile/Makefile b/extras/Projucer/Builds/LinuxMakefile/Makefile index c084a0b2b8..685e0c37b2 100644 --- a/extras/Projucer/Builds/LinuxMakefile/Makefile +++ b/extras/Projucer/Builds/LinuxMakefile/Makefile @@ -61,6 +61,7 @@ OBJECTS := \ $(JUCE_OBJDIR)/jucer_AutoUpdater_ca658dc2.o \ $(JUCE_OBJDIR)/jucer_CommandLine_f35de107.o \ $(JUCE_OBJDIR)/jucer_DocumentEditorComponent_695dff1d.o \ + $(JUCE_OBJDIR)/jucer_DownloadCompileEngineThread_8a38703f.o \ $(JUCE_OBJDIR)/jucer_GlobalPreferences_b0f1bd3d.o \ $(JUCE_OBJDIR)/jucer_Main_f8488f5b.o \ $(JUCE_OBJDIR)/jucer_MainWindow_1e163aeb.o \ @@ -154,6 +155,11 @@ $(JUCE_OBJDIR)/jucer_DocumentEditorComponent_695dff1d.o: ../../Source/Applicatio @echo "Compiling jucer_DocumentEditorComponent.cpp" @$(CXX) $(JUCE_CXXFLAGS) -o "$@" -c "$<" +$(JUCE_OBJDIR)/jucer_DownloadCompileEngineThread_8a38703f.o: ../../Source/Application/jucer_DownloadCompileEngineThread.cpp + -@mkdir -p $(JUCE_OBJDIR) + @echo "Compiling jucer_DownloadCompileEngineThread.cpp" + @$(CXX) $(JUCE_CXXFLAGS) -o "$@" -c "$<" + $(JUCE_OBJDIR)/jucer_GlobalPreferences_b0f1bd3d.o: ../../Source/Application/jucer_GlobalPreferences.cpp -@mkdir -p $(JUCE_OBJDIR) @echo "Compiling jucer_GlobalPreferences.cpp" diff --git a/extras/Projucer/Builds/MacOSX/Projucer.xcodeproj/project.pbxproj b/extras/Projucer/Builds/MacOSX/Projucer.xcodeproj/project.pbxproj index 22a8050bab..4933340f69 100644 --- a/extras/Projucer/Builds/MacOSX/Projucer.xcodeproj/project.pbxproj +++ b/extras/Projucer/Builds/MacOSX/Projucer.xcodeproj/project.pbxproj @@ -28,6 +28,7 @@ 6DD9DA1677A6CF789CDAB478 = {isa = PBXBuildFile; fileRef = 0D4D508C638BC74943B9976D; }; 954A036F5DDB375DB23FFB3E = {isa = PBXBuildFile; fileRef = 0400CB0E056A1D840304D2DE; }; 3EB3D569250C4BA4CA9AF578 = {isa = PBXBuildFile; fileRef = C7608A3967D9AB9481848F2B; }; + 636D21BF846031A6A1A7476A = {isa = PBXBuildFile; fileRef = 11EB44786085029106099D01; }; 3C3B0ED6C43FDA3AF76DEE2E = {isa = PBXBuildFile; fileRef = 84DE44680C9D37CDDCD127FF; }; 95B44E6C74B1DED31DBE37EB = {isa = PBXBuildFile; fileRef = 8C52A3DDA62A746AA7A68535; }; AA9D0B8E23F3D87A23DE9F8A = {isa = PBXBuildFile; fileRef = 9069981E414A631B036CC9AC; }; @@ -151,6 +152,7 @@ 11BB370E0CBA3B3548B1DDC7 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = pngtrans.c; path = "../../../../modules/juce_graphics/image_formats/pnglib/pngtrans.c"; sourceTree = "SOURCE_ROOT"; }; 11C55B714FE5D7CAFC35A0C7 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ImageEffectFilter.h"; path = "../../../../modules/juce_graphics/effects/juce_ImageEffectFilter.h"; sourceTree = "SOURCE_ROOT"; }; 11DC04468BC6023671017EBF = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_NewFileWizard.h"; path = "../../Source/Wizards/jucer_NewFileWizard.h"; sourceTree = "SOURCE_ROOT"; }; + 11EB44786085029106099D01 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "jucer_DownloadCompileEngineThread.cpp"; path = "../../Source/Application/jucer_DownloadCompileEngineThread.cpp"; sourceTree = "SOURCE_ROOT"; }; 1241F3A1FCDF100CD75D5E78 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_win32_DragAndDrop.cpp"; path = "../../../../modules/juce_gui_basics/native/juce_win32_DragAndDrop.cpp"; sourceTree = "SOURCE_ROOT"; }; 125CD8A5E5B57840F5154ACD = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Viewport.cpp"; path = "../../../../modules/juce_gui_basics/layout/juce_Viewport.cpp"; sourceTree = "SOURCE_ROOT"; }; 1268E54178897254E9A8B94C = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_TextLayout.cpp"; path = "../../../../modules/juce_graphics/fonts/juce_TextLayout.cpp"; sourceTree = "SOURCE_ROOT"; }; @@ -829,6 +831,7 @@ B67F3F40C568E6A0A85B13D9 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = jcphuff.c; path = "../../../../modules/juce_graphics/image_formats/jpglib/jcphuff.c"; sourceTree = "SOURCE_ROOT"; }; B6C40E843F7E8E7C4768B99E = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_GZIPDecompressorInputStream.cpp"; path = "../../../../modules/juce_core/zip/juce_GZIPDecompressorInputStream.cpp"; sourceTree = "SOURCE_ROOT"; }; B6D03F8491E288FD4BC31445 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ColourSelector.h"; path = "../../../../modules/juce_gui_extra/misc/juce_ColourSelector.h"; sourceTree = "SOURCE_ROOT"; }; + B7307A82D9EB1EDBA91EE43D = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_DownloadCompileEngineThread.h"; path = "../../Source/Application/jucer_DownloadCompileEngineThread.h"; sourceTree = "SOURCE_ROOT"; }; B741170E45D74F30B7D5CDDF = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_ComponentNameProperty.h"; path = "../../Source/ComponentEditor/components/jucer_ComponentNameProperty.h"; sourceTree = "SOURCE_ROOT"; }; B743DC50150100FFA2DE76AD = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_mac_Strings.mm"; path = "../../../../modules/juce_core/native/juce_mac_Strings.mm"; sourceTree = "SOURCE_ROOT"; }; B79595279502C1A11A4E8C36 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Point.h"; path = "../../../../modules/juce_graphics/geometry/juce_Point.h"; sourceTree = "SOURCE_ROOT"; }; @@ -1142,6 +1145,8 @@ 6E6140969908E7619F858740, C7608A3967D9AB9481848F2B, E65A820D34BF39478B7C5925, + 11EB44786085029106099D01, + B7307A82D9EB1EDBA91EE43D, 6AEF2E6130619AE550A5FCA7, D526C38D581425949BA0E4AC, 84DE44680C9D37CDDCD127FF, @@ -2461,6 +2466,7 @@ 6DD9DA1677A6CF789CDAB478, 954A036F5DDB375DB23FFB3E, 3EB3D569250C4BA4CA9AF578, + 636D21BF846031A6A1A7476A, 3C3B0ED6C43FDA3AF76DEE2E, 95B44E6C74B1DED31DBE37EB, AA9D0B8E23F3D87A23DE9F8A, diff --git a/extras/Projucer/Builds/VisualStudio2013/Projucer.vcxproj b/extras/Projucer/Builds/VisualStudio2013/Projucer.vcxproj index e94fdf1dae..e9024a2a15 100644 --- a/extras/Projucer/Builds/VisualStudio2013/Projucer.vcxproj +++ b/extras/Projucer/Builds/VisualStudio2013/Projucer.vcxproj @@ -135,6 +135,7 @@ + @@ -1326,6 +1327,7 @@ + diff --git a/extras/Projucer/Builds/VisualStudio2013/Projucer.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2013/Projucer.vcxproj.filters index f13c305315..15126bd95b 100644 --- a/extras/Projucer/Builds/VisualStudio2013/Projucer.vcxproj.filters +++ b/extras/Projucer/Builds/VisualStudio2013/Projucer.vcxproj.filters @@ -277,6 +277,9 @@ Projucer\Application + + Projucer\Application + Projucer\Application @@ -1665,6 +1668,9 @@ Projucer\Application + + Projucer\Application + Projucer\Application diff --git a/extras/Projucer/Builds/VisualStudio2015/Projucer.vcxproj b/extras/Projucer/Builds/VisualStudio2015/Projucer.vcxproj index e4468cf7c8..b751c309d7 100644 --- a/extras/Projucer/Builds/VisualStudio2015/Projucer.vcxproj +++ b/extras/Projucer/Builds/VisualStudio2015/Projucer.vcxproj @@ -135,6 +135,7 @@ + @@ -1326,6 +1327,7 @@ + diff --git a/extras/Projucer/Builds/VisualStudio2015/Projucer.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2015/Projucer.vcxproj.filters index 431d56d545..5a1800517f 100644 --- a/extras/Projucer/Builds/VisualStudio2015/Projucer.vcxproj.filters +++ b/extras/Projucer/Builds/VisualStudio2015/Projucer.vcxproj.filters @@ -277,6 +277,9 @@ Projucer\Application + + Projucer\Application + Projucer\Application @@ -1665,6 +1668,9 @@ Projucer\Application + + Projucer\Application + Projucer\Application diff --git a/extras/Projucer/Projucer.jucer b/extras/Projucer/Projucer.jucer index 672aed625f..2da2a1bcf3 100644 --- a/extras/Projucer/Projucer.jucer +++ b/extras/Projucer/Projucer.jucer @@ -112,6 +112,10 @@ resource="0" file="Source/Application/jucer_DocumentEditorComponent.cpp"/> + + in = url.createInputStream (false, nullptr, nullptr, + String(), timeoutMs, &responseHeaders, + &statusCode, 0); + + if (in == nullptr || statusCode != 200) + return Result::fail ("Download error: cannot establish connection"); + + MemoryOutputStream mo (dest, true); + + int64 size = in->getTotalLength(); + int64 bytesReceived = -1; + String msg("Downloading... (123)"); + + for (int64 pos = 0; pos < size; pos += bytesReceived) + { + setStatusMessage (msg.replace ("123", File::descriptionOfSizeInBytes (pos))); + + if (threadShouldExit()) + return Result::fail ("Download error: operation interrupted"); + + bytesReceived = mo.writeFromInputStream (*in, 8192); + + if (bytesReceived == 0) + return Result::fail ("Download error: lost connection"); + } + + return Result::ok(); +} + +Result DownloadCompileEngineThread::install (const MemoryBlock& data, File& targetFolder) +{ + MemoryInputStream input (data, false); + ZipFile zip (input); + + if (zip.getNumEntries() == 0) + return Result::fail ("Install error: downloaded file is corrupt"); + + if (threadShouldExit()) + return Result::fail ("Install error: operation interrupted"); + + return zip.uncompressTo (targetFolder); +} + +URL DownloadCompileEngineThread::getDownloadUrl() +{ + String urlStub ("http://assets.roli.com/juce/JUCECompileEngine_"); + + #if JUCE_MAC + urlStub << "osx_"; + #elif JUCE_WINDOWS + urlStub << "windows_"; + #else + jassertfalse + #endif + + return urlStub + ProjectInfo::versionString + ".zip"; +} + +File DownloadCompileEngineThread::getInstallFolder() +{ + return CompileEngineDLL::getVersionedUserAppSupportFolder(); +} + +bool DownloadCompileEngineThread::withError(const String& msg) +{ + AlertWindow::showMessageBox (AlertWindow::WarningIcon, + "Download and install", msg); + return false; +} diff --git a/extras/Projucer/Source/Application/jucer_DownloadCompileEngineThread.h b/extras/Projucer/Source/Application/jucer_DownloadCompileEngineThread.h new file mode 100644 index 0000000000..a1d5167a0e --- /dev/null +++ b/extras/Projucer/Source/Application/jucer_DownloadCompileEngineThread.h @@ -0,0 +1,57 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2015 - ROLI Ltd. + + Permission is granted to use this software under the terms of either: + a) the GPL v2 (or any later version) + b) the Affero GPL v3 + + Details of these licenses can be found at: www.gnu.org/licenses + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.juce.com for more information. + + ============================================================================== +*/ + +#ifndef JUCER_DOWNLOADCOMPILEENGINETHREAD_H_INCLUDED +#define JUCER_DOWNLOADCOMPILEENGINETHREAD_H_INCLUDED + +#include "jucer_Application.h" + + +//============================================================================== +class DownloadCompileEngineThread : public ThreadWithProgressWindow +{ +public: + static bool downloadAndInstall(); + +protected: + void run() override; + void threadComplete (bool userPressedCancel) override; + +private: + DownloadCompileEngineThread(); + + Result download (MemoryBlock& dest); + Result install (const MemoryBlock& data, File& targetFolder); + + static URL getDownloadUrl(); + static File getInstallFolder(); + static bool withError(const String& msg); + + Result result; + bool cancelledByUser; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DownloadCompileEngineThread) +}; + +#endif // JUCER_DOWNLOADCOMPILEENGINETHREAD_H_INCLUDED diff --git a/extras/Projucer/Source/Application/jucer_ProjucerLicenses.h b/extras/Projucer/Source/Application/jucer_ProjucerLicenses.h index 8902433a19..61bca0f7b7 100644 --- a/extras/Projucer/Source/Application/jucer_ProjucerLicenses.h +++ b/extras/Projucer/Source/Application/jucer_ProjucerLicenses.h @@ -101,6 +101,12 @@ struct ProjucerLicenses : private DeletedAtShutdown return isDLLPresent() && dll.projucer_hasLiveCodingLicence(); } + bool retryLoadDll() + { + dll.tryLoadDll(); + return dll.isLoaded(); + } + private: CompileEngineDLL dll; LoginCallback* userCallback = nullptr; diff --git a/extras/Projucer/Source/LiveBuildEngine/projucer_CompileEngineDLL.h b/extras/Projucer/Source/LiveBuildEngine/projucer_CompileEngineDLL.h index 2d4b909128..5f552bcf8f 100644 --- a/extras/Projucer/Source/LiveBuildEngine/projucer_CompileEngineDLL.h +++ b/extras/Projucer/Source/LiveBuildEngine/projucer_CompileEngineDLL.h @@ -29,14 +29,7 @@ struct CompileEngineDLL { CompileEngineDLL() { - File f = findDLLFile(); - - if (f != File() && dll.open (f.getLinkedTarget().getFullPathName())) - { - #define INIT_LIVE_DLL_FN(name, returnType, params) name = (name##_type) dll.getFunction (#name); - LIVE_DLL_FUNCTIONS (INIT_LIVE_DLL_FN); - #undef INIT_LIVE_DLL_FN - } + tryLoadDll(); } ~CompileEngineDLL() @@ -44,6 +37,22 @@ struct CompileEngineDLL shutdown(); } + void tryLoadDll() + { + // never load the dynamic lib multiple times + if (! isLoaded()) + { + File f = findDLLFile(); + + if (f != File() && dll.open (f.getLinkedTarget().getFullPathName())) + { + #define INIT_LIVE_DLL_FN(name, returnType, params) name = (name##_type) dll.getFunction (#name); + LIVE_DLL_FUNCTIONS (INIT_LIVE_DLL_FN); + #undef INIT_LIVE_DLL_FN + } + } + } + void initialise (CrashCallbackFunction crashFn, QuitCallbackFunction quitFn, bool setupSignals) { if (isLoaded()) @@ -87,80 +96,15 @@ struct CompileEngineDLL #endif } - static bool isDLLFile (const File& f) + static File getVersionedUserAppSupportFolder() { - return f.getFileName().equalsIgnoreCase (getDLLName()) && f.exists(); - } - - static File findDLLFile() - { - File appFile = File::getSpecialLocation (File::currentApplicationFile); + File userAppData (File::getSpecialLocation (File::userApplicationDataDirectory)); #if JUCE_MAC - // Look in the app bundle.. - for (DirectoryIterator i (appFile, true, "*", File::findFilesAndDirectories); i.next();) - if (isDLLFile (i.getFile())) - return i.getFile(); - - { - // Try in Application Support.. - File f = File ("~/Library/Application Support/Projucer").getChildFile (getDLLName()); - if (isDLLFile (f)) - return f; - - f = File ("/Library/Application Support/Projucer").getChildFile (getDLLName()); - if (isDLLFile (f)) - return f; - } - - #elif JUCE_WINDOWS - { - // Look in the application folder - File f = appFile.getParentDirectory().getChildFile (getDLLName()); - if (isDLLFile (f)) - return f; - } - #elif JUCE_LINUX - // TODO? - #else - #error + userAppData = userAppData.getChildFile ("Application Support"); #endif - { - // Look for a DLL in extras/Projucer/Builds - File f = appFile.getParentDirectory(); - - for (int i = 5; --i >= 0;) - { - if (f.getFileName().equalsIgnoreCase ("Builds") - && f.getParentDirectory().getFileName().equalsIgnoreCase ("Projucer")) - { - f = f.getSiblingFile (getDLLName()); - if (isDLLFile (f)) - return f; - - break; - } - - f = f.getParentDirectory(); - } - } - - // See if there's one in the same folder as the app... - File f = appFile.getSiblingFile (getDLLName()); - if (isDLLFile (f)) - return f; - - // Look in some common folders as a last resort.. - f = File::getSpecialLocation (File::userHomeDirectory).getChildFile (getDLLName()); - if (isDLLFile (f)) - return f; - - f = File::getSpecialLocation (File::userDocumentsDirectory).getChildFile (getDLLName()); - if (isDLLFile (f)) - return f; - - return File(); + return userAppData.getChildFile (String ("Projucer-") + ProjectInfo::versionString); } private: @@ -168,6 +112,61 @@ private: enum { requiredVersion = 1 }; + static File findDLLFile() + { + File dllFile; + + if (tryFindDLLFileInAppFolder(dllFile)) + return dllFile; + + #if JUCE_MAC + if (tryFindDLLFileInAppBundle(dllFile)) + return dllFile; + #endif + + if (tryFindDLLFileInAppConfigFolder(dllFile)) + return dllFile; + + return File(); + } + + #if JUCE_MAC + static bool tryFindDLLFileInAppBundle(File &outFile) + { + File currentExecFile (File::getSpecialLocation (File::currentExecutableFile)); + return tryFindDLLFileInFolder (currentExecFile.getParentDirectory(), outFile); + } + #endif + + static bool tryFindDLLFileInAppFolder(File &outFile) + { + File currentAppFile (File::getSpecialLocation (File::currentApplicationFile)); + return tryFindDLLFileInFolder (currentAppFile.getParentDirectory(), outFile); + } + + static bool tryFindDLLFileInAppConfigFolder(File &outFile) + { + File userAppDataFolder (getVersionedUserAppSupportFolder()); + return tryFindDLLFileInFolder (userAppDataFolder, outFile); + } + + static bool tryFindDLLFileInFolder(File folder, File& outFile) + { + File file = folder.getChildFile (getDLLName()); + if (isDLLFile (file)) + { + outFile = file; + return true; + } + + return false; + } + + static bool isDLLFile (const File& f) + { + return f.getFileName().equalsIgnoreCase (getDLLName()) && f.exists(); + } + static void setPropertyCallback (const char* key, const char* value) { if (String (key).isNotEmpty()) diff --git a/extras/Projucer/Source/Project/jucer_ProjectContentComponent.cpp b/extras/Projucer/Source/Project/jucer_ProjectContentComponent.cpp index 40a6642987..3cb634eeb3 100644 --- a/extras/Projucer/Source/Project/jucer_ProjectContentComponent.cpp +++ b/extras/Projucer/Source/Project/jucer_ProjectContentComponent.cpp @@ -27,6 +27,7 @@ #include "jucer_Module.h" #include "../Application/jucer_MainWindow.h" #include "../Application/jucer_Application.h" +#include "../Application/jucer_DownloadCompileEngineThread.h" #include "../Code Editor/jucer_SourceCodeEditor.h" #include "../Utility/jucer_FilePathPropertyComponent.h" #include "jucer_TreeItemTypes.h" @@ -330,6 +331,7 @@ void ProjectContentComponent::rebuildProjectTabs() resized(); } + //============================================================================== struct BuildTabComponent : public ConcertinaPanel { @@ -355,7 +357,8 @@ struct ProjucerDisabledComp : public Component, private Button::Listener { ProjucerDisabledComp (String message, bool loggedIn, bool showSubscribeButton, - bool showSignInButton, bool showSwitchAccountButton) + bool showSignInButton, bool showSwitchAccountButton, + bool showDownloadButton) : isLoggedIn (loggedIn) { infoLabel.setColour (Label::textColourId, findColour (mainBackgroundColourId).contrasting (0.7f)); @@ -383,6 +386,13 @@ struct ProjucerDisabledComp : public Component, addAndMakeVisible (*switchAccountButton); switchAccountButton->addListener (this); } + + if (showDownloadButton) + { + downloadButton = new TextButton (String ("Download live-build engine")); + addAndMakeVisible (*downloadButton); + downloadButton->addListener (this); + } } void resized() override @@ -417,6 +427,13 @@ struct ProjucerDisabledComp : public Component, { switchAccountButton->setSize (buttonWidth, buttonHeight); switchAccountButton->setCentrePosition (buttonCenterX, buttonCenterY); + buttonCenterY += itemDistance + buttonHeight; + } + + if (downloadButton.get() != nullptr) + { + downloadButton->setSize (buttonWidth, buttonHeight); + downloadButton->setCentrePosition (buttonCenterX, buttonCenterY); } } @@ -434,6 +451,26 @@ struct ProjucerDisabledComp : public Component, { ProjucerApplication::getApp().showLoginForm(); } + else if (btn == downloadButton.get()) + { + if (DownloadCompileEngineThread::downloadAndInstall()) + { + if (! ProjucerLicenses::getInstance()->retryLoadDll()) + { + AlertWindow::showMessageBox(AlertWindow::WarningIcon, + "Download and install", + "Loading the live-build engine failed"); + return; + } + + // async! + ProjucerApplication::getApp().showLoginForm(); + + // if sign in successful project tabs update, otherwise they were not + auto parent = findParentComponentOfClass(); + parent->rebuildProjectTabs(); + } + } } bool isLoggedIn; @@ -443,6 +480,7 @@ private: ScopedPointer subscribeButton; ScopedPointer signInButton; ScopedPointer switchAccountButton; + ScopedPointer downloadButton; }; struct EnableBuildComp : public Component @@ -476,11 +514,6 @@ struct EnableBuildComp : public Component //============================================================================== Component* ProjectContentComponent::createBuildTab (CompileEngineChildProcess* child) { - #if JUCE_LINUX - ignoreUnused (child); - return new ProjucerDisabledComp ("Linux support is still under development - " - "please check for updates at www.juce.com!", false, false, false, false); - #else if (child != nullptr) { child->crashHandler = [this] (const String& m) { this->handleCrash (m); }; @@ -489,31 +522,61 @@ Component* ProjectContentComponent::createBuildTab (CompileEngineChildProcess* c } jassert (project != nullptr); + + const auto osType = SystemStats::getOperatingSystemType(); + const bool isMac = (osType & SystemStats::MacOSX) != 0; + const bool isWin = (osType & SystemStats::Windows) != 0; + const bool isLinux = (osType & SystemStats::Linux) != 0; + + if (! isMac && ! isWin && ! isLinux) + return createDisabledBuildTabInfoOnly ( + "Live-build features are not supported on your system.\n\n" + "Please check supported platforms at www.juce.com!"); + + if (isLinux) + return createDisabledBuildTabInfoOnly ( + "Live-build features for Linux are under development.\n\n" + "Please check for updates at www.juce.com!"); + + if (isMac) + if (osType < SystemStats::MacOSX_10_9) + return createDisabledBuildTabInfoOnly ( + "Live-build features are available only on MacOSX 10.9 or higher."); + + if (isWin) + if (! SystemStats::isOperatingSystem64Bit() || osType < SystemStats::Windows8_0) + return createDisabledBuildTabInfoOnly ( + "Live-build features are available only on 64-Bit Windows 8 or higher."); + const auto& unlockStatus = *ProjucerLicenses::getInstance(); - if (unlockStatus.hasLiveCodingLicence()) - { - jassert (unlockStatus.isLoggedIn()); - jassert (unlockStatus.isDLLPresent()); - return new EnableBuildComp(); - } + if (! unlockStatus.hasLiveCodingLicence()) + return createDisabledBuildTabSubscribe(unlockStatus.isLoggedIn(), + unlockStatus.isDLLPresent()); - return createDisabledBuildTab(unlockStatus.isLoggedIn(), - unlockStatus.isDLLPresent()); - #endif + jassert (unlockStatus.isLoggedIn()); + jassert (unlockStatus.isDLLPresent()); + return new EnableBuildComp(); }; -//============================================================================== -Component* ProjectContentComponent::createDisabledBuildTab(bool loggedIn, bool dllPresent) { +Component* ProjectContentComponent::createDisabledBuildTabSubscribe(bool loggedIn, bool dllPresent) +{ bool showSubscribeButton = true; bool showSignInButton = dllPresent && ! loggedIn; bool showSwitchAccountButton = dllPresent && loggedIn; + bool showDownloadButton = ! dllPresent; return new ProjucerDisabledComp ( "Subscribe to JUCE Pro or Indie to use the Projucer's live-build features:", - loggedIn, showSubscribeButton, showSignInButton, showSwitchAccountButton); + loggedIn, showSubscribeButton, showSignInButton, showSwitchAccountButton, showDownloadButton); } +Component* ProjectContentComponent::createDisabledBuildTabInfoOnly(const char* message) +{ + return new ProjucerDisabledComp (message, false, false, false, false, false); +} + +//============================================================================== BuildTabComponent* findBuildTab (const TabbedComponent& tabs) { return dynamic_cast (tabs.getTabContentComponent (2)); @@ -1527,7 +1590,7 @@ void ProjectContentComponent::handleMissingSystemHeaders() createProjectTabs(); bool isLoggedIn = ProjucerLicenses::getInstance()->isLoggedIn(); - ProjucerDisabledComp* buildTab = new ProjucerDisabledComp (tabMessage, isLoggedIn, false, false, false); + ProjucerDisabledComp* buildTab = new ProjucerDisabledComp (tabMessage, isLoggedIn, false, false, false, false); treeViewTabs.addTab ("Build", Colours::transparentBlack, buildTab, true); showBuildTab(); diff --git a/extras/Projucer/Source/Project/jucer_ProjectContentComponent.h b/extras/Projucer/Source/Project/jucer_ProjectContentComponent.h index 534079f232..e5381fa444 100644 --- a/extras/Projucer/Source/Project/jucer_ProjectContentComponent.h +++ b/extras/Projucer/Source/Project/jucer_ProjectContentComponent.h @@ -154,7 +154,8 @@ private: void timerCallback() override; Component* createBuildTab (CompileEngineChildProcess*); - Component* createDisabledBuildTab (bool loggedIn, bool dllPresent); + Component* createDisabledBuildTabSubscribe (bool loggedIn, bool dllPresent); + Component* createDisabledBuildTabInfoOnly (const char* messsage); bool isContinuousRebuildEnabled() { return getAppSettings().getGlobalProperties().getBoolValue ("continuousRebuild", true); } void setContinuousRebuildEnabled (bool b) { getAppSettings().getGlobalProperties().setValue ("continuousRebuild", b); }