diff --git a/extras/Projucer/Source/Application/jucer_Application.h b/extras/Projucer/Source/Application/jucer_Application.h index ff04448406..6c76389a2f 100644 --- a/extras/Projucer/Source/Application/jucer_Application.h +++ b/extras/Projucer/Source/Application/jucer_Application.h @@ -107,6 +107,8 @@ public: void licenseStateChanged (const LicenseState&) override; void doLogout(); + bool isPaidOrGPL() const { return licenseController == nullptr || licenseController->getState().isPaidOrGPL(); } + //============================================================================== ProjucerLookAndFeel lookAndFeel; diff --git a/extras/Projucer/Source/Project Saving/jucer_ProjectSaver.h b/extras/Projucer/Source/Project Saving/jucer_ProjectSaver.h index aadfd29ea5..6545d81206 100644 --- a/extras/Projucer/Source/Project Saving/jucer_ProjectSaver.h +++ b/extras/Projucer/Source/Project Saving/jucer_ProjectSaver.h @@ -369,8 +369,32 @@ private: << "//==============================================================================" << newLine << "// [BEGIN_USER_CODE_SECTION]" << newLine << userContent - << "// [END_USER_CODE_SECTION]" << newLine + << "// [END_USER_CODE_SECTION]" << newLine; + + out << newLine + << "//==============================================================================" << newLine + << "/*" << newLine + << " ==============================================================================" << newLine << newLine + << " In accordance with the terms of the JUCE 5 End-Use License Agreement, the" << newLine + << " JUCE Code in SECTION A cannot be removed, changed or otherwise rendered" << newLine + << " ineffective unless you have a JUCE Indie or Pro license, or are using JUCE" << newLine + << " under the GPL v3 license." << newLine + << newLine + << " End User License Agreement: www.juce.com/juce-5-licence" << newLine + << " ==============================================================================" << newLine + << "*/" << newLine + << newLine + << "// BEGIN SECTION A" << newLine + << newLine + << "#define JUCE_DISPLAY_SPLASH_SCREEN " << (project.shouldDisplaySplashScreen().getValue() ? "1" : "0") << newLine + << "#define JUCE_REPORT_APP_USAGE " << (project.shouldReportAppUsage().getValue() ? "1" : "0") << newLine + << newLine + << "// END SECTION A" << newLine + << newLine + << "#define JUCE_USE_DARK_SPLASH_SCREEN " << (project.splashScreenColour().toString() == "Dark" ? "1" : "0") << newLine; + + out << newLine << "//==============================================================================" << newLine; const int longestName = findLongestModuleName (modules); diff --git a/extras/Projucer/Source/Project/jucer_Project.cpp b/extras/Projucer/Source/Project/jucer_Project.cpp index 46d14c8ab1..713b58cb62 100644 --- a/extras/Projucer/Source/Project/jucer_Project.cpp +++ b/extras/Projucer/Source/Project/jucer_Project.cpp @@ -110,6 +110,19 @@ void Project::setMissingDefaultValues() if (getDocumentTitle().isEmpty()) setTitle ("JUCE Project"); + { + auto defaultSplashScreenAndReporting = ! ProjucerApplication::getApp().isPaidOrGPL(); + + if (shouldDisplaySplashScreen() == var() || defaultSplashScreenAndReporting) + shouldDisplaySplashScreen() = defaultSplashScreenAndReporting; + + if (shouldReportAppUsage() == var() || defaultSplashScreenAndReporting) + shouldReportAppUsage() = defaultSplashScreenAndReporting; + } + + if (splashScreenColour() == var()) + splashScreenColour() = "Dark"; + if (! projectRoot.hasProperty (Ids::projectType)) getProjectTypeValue() = ProjectType_GUIApp::getTypeName(); @@ -555,6 +568,55 @@ void Project::createPropertyEditors (PropertyListBuilder& props) props.add (new TextPropertyComponent (getCompanyEmail(), "Company E-mail", 256, false), "Your company e-mail, which will be added to the properties of the binary where possible"); + { + const String licenseRequiredTagline ("Required for closed source applications without an Indie or Pro JUCE license"); + const String licenseRequiredInfo ("In accordance with the terms of the JUCE 5 End-Use License Agreement (www.juce.com/juce-5-licence), " + "this option can only be disabled for closed source applications if you have a JUCE Indie or Pro " + "license, or are using JUCE under the GPL v3 license."); + + StringPairArray description; + description.set ("Report JUCE app usage", "This option controls the collection of usage data from users of this JUCE application."); + description.set ("Display the JUCE splash screen", "This option controls the display of the standard JUCE splash screen."); + + if (ProjucerApplication::getApp().isPaidOrGPL()) + { + props.add (new BooleanPropertyComponent (shouldReportAppUsage(), "Report JUCE app usage", licenseRequiredTagline), + description["Report JUCE app usage"] + " " + licenseRequiredInfo); + + props.add (new BooleanPropertyComponent (shouldDisplaySplashScreen(), "Display the JUCE splash screen", licenseRequiredTagline), + description["Display the JUCE splash screen"] + " " + licenseRequiredInfo); + } + else + { + StringArray options; + Array vars; + + options.add (licenseRequiredTagline); + vars.add (var()); + + props.add (new ChoicePropertyComponent (Value(), "Report JUCE app usage", options, vars), + description["Report JUCE app usage"] + " " + licenseRequiredInfo); + + props.add (new ChoicePropertyComponent (Value(), "Display the JUCE splash screen", options, vars), + description["Display the JUCE splash screen"] + " " + licenseRequiredInfo); + } + } + + { + StringArray splashScreenColours; + + splashScreenColours.add ("Dark"); + splashScreenColours.add ("Light"); + + Array splashScreenCodes; + + for (auto& splashScreenColour : splashScreenColours) + splashScreenCodes.add (splashScreenColour); + + props.add (new ChoicePropertyComponent (splashScreenColour(), "Splash screen colour", splashScreenColours, splashScreenCodes), + "Choose the colour of the JUCE splash screen."); + } + { StringArray projectTypeNames; Array projectTypeCodes; diff --git a/extras/Projucer/Source/Project/jucer_Project.h b/extras/Projucer/Source/Project/jucer_Project.h index 661afaaa61..64bde467d9 100644 --- a/extras/Projucer/Source/Project/jucer_Project.h +++ b/extras/Projucer/Source/Project/jucer_Project.h @@ -94,6 +94,10 @@ public: Value getCompanyWebsite() { return getProjectValue (Ids::companyWebsite); } Value getCompanyEmail() { return getProjectValue (Ids::companyEmail); } + Value shouldDisplaySplashScreen() { return getProjectValue (Ids::displaySplashScreen); } + Value shouldReportAppUsage() { return getProjectValue (Ids::reportAppUsage); } + Value splashScreenColour() { return getProjectValue (Ids::splashScreenColour); } + //============================================================================== Value getProjectValue (const Identifier& name) { return projectRoot.getPropertyAsValue (name, getUndoManagerFor (projectRoot)); } var getProjectVar (const Identifier& name) const { return projectRoot.getProperty (name); } diff --git a/extras/Projucer/Source/Utility/jucer_PresetIDs.h b/extras/Projucer/Source/Utility/jucer_PresetIDs.h index 16d9641710..0f67b0a9ec 100644 --- a/extras/Projucer/Source/Utility/jucer_PresetIDs.h +++ b/extras/Projucer/Source/Utility/jucer_PresetIDs.h @@ -43,6 +43,9 @@ namespace Ids DECLARE_ID (companyName); DECLARE_ID (companyWebsite); DECLARE_ID (companyEmail); + DECLARE_ID (displaySplashScreen); + DECLARE_ID (reportAppUsage); + DECLARE_ID (splashScreenColour); DECLARE_ID (position); DECLARE_ID (source); DECLARE_ID (width); diff --git a/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp b/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp index 344d8c4e82..a1bd1f5f81 100644 --- a/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp +++ b/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp @@ -36,6 +36,8 @@ AudioProcessorEditor::AudioProcessorEditor (AudioProcessor* p) noexcept : proce AudioProcessorEditor::~AudioProcessorEditor() { + splashScreen.deleteAndZero(); + // if this fails, then the wrapper hasn't called editorBeingDeleted() on the // filter for some reason.. jassert (processor.getActiveEditor() != this); @@ -47,6 +49,23 @@ int AudioProcessorEditor::getControlParameterIndex (Component&) { return -1; } void AudioProcessorEditor::initialise() { + /* + ========================================================================== + In accordance with the terms of the JUCE 5 End-Use License Agreement, the + JUCE Code in SECTION A cannot be removed, changed or otherwise rendered + ineffective unless you have a JUCE Indie or Pro license, or are using + JUCE under the GPL v3 license. + + End User License Agreement: www.juce.com/juce-5-licence + ========================================================================== + */ + + // BEGIN SECTION A + + splashScreen = new JUCESplashScreen (*this); + + // END SECTION A + resizable = false; attachConstrainer (&defaultConstrainer); diff --git a/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.h b/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.h index cb768a582a..77f94a6d0a 100644 --- a/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.h +++ b/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.h @@ -167,6 +167,7 @@ private: bool resizable; ComponentBoundsConstrainer defaultConstrainer; ComponentBoundsConstrainer* constrainer; + Component::SafePointer splashScreen; JUCE_DECLARE_NON_COPYABLE (AudioProcessorEditor) }; diff --git a/modules/juce_core/juce_core.h b/modules/juce_core/juce_core.h index d1d49bd860..2c440146a7 100644 --- a/modules/juce_core/juce_core.h +++ b/modules/juce_core/juce_core.h @@ -287,7 +287,6 @@ extern JUCE_API void JUCE_CALLTYPE logAssertion (const char* file, int line) noe #include "misc/juce_RuntimePermissions.h" #include "misc/juce_Uuid.h" #include "misc/juce_WindowsRegistry.h" -#include "system/juce_SystemStats.h" #include "threads/juce_ChildProcess.h" #include "threads/juce_DynamicLibrary.h" #include "threads/juce_HighResolutionTimer.h" @@ -308,6 +307,7 @@ extern JUCE_API void JUCE_CALLTYPE logAssertion (const char* file, int line) noe #include "network/juce_Socket.h" #include "network/juce_URL.h" #include "network/juce_WebInputStream.h" +#include "system/juce_SystemStats.h" #include "time/juce_PerformanceCounter.h" #include "unit_tests/juce_UnitTest.h" #include "xml/juce_XmlDocument.h" diff --git a/modules/juce_core/system/juce_SystemStats.cpp b/modules/juce_core/system/juce_SystemStats.cpp index 72c37b755e..b610828b8c 100644 --- a/modules/juce_core/system/juce_SystemStats.cpp +++ b/modules/juce_core/system/juce_SystemStats.cpp @@ -63,6 +63,30 @@ String SystemStats::getJUCEVersion() static JuceVersionPrinter juceVersionPrinter; #endif +StringArray SystemStats::getDeviceIdentifiers() +{ + StringArray ids; + + #if JUCE_WINDOWS + File f (File::getSpecialLocation (File::windowsSystemDirectory)); + #else + File f ("~"); + #endif + if (auto num = f.getFileIdentifier()) + { + ids.add (String::toHexString ((int64) num)); + } + else + { + Array addresses; + MACAddress::findAllAddresses (addresses); + for (auto& address : addresses) + ids.add (address.toString()); + } + + jassert (ids.size() > 0); // Failed to create any IDs! + return ids; +} //============================================================================== struct CPUInformation diff --git a/modules/juce_core/system/juce_SystemStats.h b/modules/juce_core/system/juce_SystemStats.h index cdc79b48a0..2ed6ff0072 100644 --- a/modules/juce_core/system/juce_SystemStats.h +++ b/modules/juce_core/system/juce_SystemStats.h @@ -137,6 +137,13 @@ public: */ static String getDeviceDescription(); + /** This method calculates some IDs to uniquely identify the device. + + The first choice for an ID is a filesystem ID for the user's home folder or + windows directory. If that fails then this function returns the MAC addresses. + */ + static StringArray getDeviceIdentifiers(); + //============================================================================== // CPU and memory information.. diff --git a/modules/juce_gui_basics/juce_gui_basics.cpp b/modules/juce_gui_basics/juce_gui_basics.cpp index 3beb851b11..4ebda0f2f8 100644 --- a/modules/juce_gui_basics/juce_gui_basics.cpp +++ b/modules/juce_gui_basics/juce_gui_basics.cpp @@ -253,6 +253,7 @@ extern bool juce_areThereAnyAlwaysOnTopWindows(); #include "application/juce_Application.cpp" #include "misc/juce_BubbleComponent.cpp" #include "misc/juce_DropShadower.cpp" +#include "misc/juce_JUCESplashScreen.cpp" // these classes are C++11-only #if JUCE_COMPILER_SUPPORTS_INITIALIZER_LISTS && JUCE_COMPILER_SUPPORTS_LAMBDAS diff --git a/modules/juce_gui_basics/juce_gui_basics.h b/modules/juce_gui_basics/juce_gui_basics.h index dbcdc05922..a89594a3fc 100644 --- a/modules/juce_gui_basics/juce_gui_basics.h +++ b/modules/juce_gui_basics/juce_gui_basics.h @@ -245,6 +245,7 @@ class FlexBox; #include "widgets/juce_ToolbarItemPalette.h" #include "buttons/juce_ToolbarButton.h" #include "misc/juce_DropShadower.h" +#include "misc/juce_JUCESplashScreen.h" #include "widgets/juce_TreeView.h" #include "windows/juce_TopLevelWindow.h" #include "windows/juce_AlertWindow.h" diff --git a/modules/juce_gui_basics/misc/juce_JUCESplashScreen.cpp b/modules/juce_gui_basics/misc/juce_JUCESplashScreen.cpp new file mode 100644 index 0000000000..469e6b117d --- /dev/null +++ b/modules/juce_gui_basics/misc/juce_JUCESplashScreen.cpp @@ -0,0 +1,345 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2017 - 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. + + ============================================================================== +*/ + +/* + ============================================================================== + + In accordance with the terms of the JUCE 5 End-Use License Agreement, the + JUCE Code in SECTION A cannot be removed, changed or otherwise rendered + ineffective unless you have a JUCE Indie or Pro license, or are using JUCE + under the GPL v3 license. + + End User License Agreement: www.juce.com/juce-5-licence + ============================================================================== +*/ + +// BEGIN SECTION A + +#if ! defined (JUCE_REPORT_APP_USAGE) + #define JUCE_REPORT_APP_USAGE 1 +#endif + +#if ! defined (JUCE_DISPLAY_SPLASH_SCREEN) + #define JUCE_DISPLAY_SPLASH_SCREEN 1 +#endif + +#if ! defined (JUCE_USE_DARK_SPLASH_SCREEN) + #define JUCE_USE_DARK_SPLASH_SCREEN 1 +#endif + +static const int millisecondsToDisplaySplash = 2000, splashScreenFadeOutTime = 2000; +static const int splashScreenLogoWidth = 123, splashScreenLogoHeight = 63; +static uint32 splashDisplayTime = 0; +static bool appUsageReported = false; + + +Rectangle getLogoArea (Rectangle parentRect) +{ + return parentRect.reduced (6.0f) + .removeFromRight ((float) splashScreenLogoWidth) + .removeFromBottom ((float) splashScreenLogoHeight); +} + +//============================================================================== +struct ReportingThread; + +struct ReportingThreadContainer : public ChangeListener, + public DeletedAtShutdown +{ + void sendReport (String, String&, StringPairArray&); + void changeListenerCallback (ChangeBroadcaster*) override; + + ScopedPointer reportingThread; + + juce_DeclareSingleton_SingleThreaded_Minimal (ReportingThreadContainer) +}; + +juce_ImplementSingleton_SingleThreaded (ReportingThreadContainer); + +//============================================================================== +struct ReportingThread : public Thread, + private ChangeBroadcaster +{ + ReportingThread (ReportingThreadContainer& container, + String& address, + String& userAgent, + StringPairArray& parameters) + : Thread ("JUCE app usage reporting"), + threadContainer (container), + headers ("User-Agent: " + userAgent) + { + StringArray postData; + + for (auto& key : parameters.getAllKeys()) + if (parameters[key].isNotEmpty()) + postData.add (key + "=" + URL::addEscapeChars (parameters[key], true)); + + url = URL (address).withPOSTData (postData.joinIntoString ("&")); + + addChangeListener (&threadContainer); + } + + ~ReportingThread() + { + removeChangeListener (&threadContainer); + + if (webStream != nullptr) + webStream->cancel(); + + stopThread (2000); + } + + void run() override + { + webStream = new WebInputStream (url, true); + webStream->withExtraHeaders (headers); + webStream->connect (nullptr); + + sendChangeMessage(); + } + +private: + ReportingThreadContainer& threadContainer; + URL url; + String headers; + ScopedPointer webStream; +}; + +//============================================================================== +void ReportingThreadContainer::sendReport (String address, String& userAgent, StringPairArray& parameters) +{ + reportingThread = new ReportingThread (*this, address, userAgent, parameters); + + reportingThread->startThread(); +} + +void ReportingThreadContainer::changeListenerCallback (ChangeBroadcaster*) +{ + reportingThread = nullptr; +} + +//============================================================================== +JUCESplashScreen::JUCESplashScreen (Component& parent) +{ + ignoreUnused (parent); + + #if JUCE_REPORT_APP_USAGE + if (! appUsageReported) + { + const ScopedTryLock appUsageReportingLock (appUsageReporting); + + if (appUsageReportingLock.isLocked() && ! appUsageReported) + { + const auto deviceDescription = SystemStats::getDeviceDescription(); + const auto deviceString = SystemStats::getDeviceIdentifiers().joinIntoString (":"); + const auto deviceIdentifier = String::toHexString (deviceString.hashCode64()); + const auto osName = SystemStats::getOperatingSystemName(); + + StringPairArray data; + + data.set ("v", "1"); + data.set ("tid", "UA-19759318-3"); + data.set ("cid", deviceIdentifier); + data.set ("t", "event"); + data.set ("ec", "info"); + data.set ("ea", "appStarted"); + + data.set ("cd1", SystemStats::getJUCEVersion()); + data.set ("cd2", osName); + data.set ("cd3", deviceDescription); + data.set ("cd4", deviceIdentifier); + + String appType, appName, appVersion, appManufacturer; + + #if defined(JucePlugin_Name) + appType = "Plugin"; + appName = JucePlugin_Name; + appVersion = JucePlugin_VersionString; + appManufacturer = JucePlugin_Manufacturer; + #else + if (JUCEApplicationBase::isStandaloneApp()) + { + appType = "Application"; + + if (auto* app = JUCEApplicationBase::getInstance()) + { + appName = app->getApplicationName(); + appVersion = app->getApplicationVersion(); + } + } + else + { + appType = "Library"; + } + #endif + + data.set ("cd5", appType); + data.set ("cd6", appName); + data.set ("cd7", appVersion); + data.set ("cd8", appManufacturer); + + data.set ("an", appName); + data.set ("av", appVersion); + + auto agentCPUVendor = SystemStats::getCpuVendor(); + + if (agentCPUVendor.isEmpty()) + agentCPUVendor = "CPU"; + + auto agentOSName = osName.replaceCharacter ('.', '_') + .replace ("iOS", "iPhone OS"); + #if JUCE_IOS + agentOSName << " like Mac OS X"; + #endif + + String userAgent; + userAgent << "Mozilla/5.0 (" + << deviceDescription << ";" + << agentCPUVendor << " " << agentOSName << ";" + << SystemStats::getDisplayLanguage() << ")"; + + ReportingThreadContainer::getInstance()->sendReport ("https://www.google-analytics.com/collect", userAgent, data); + + appUsageReported = true; + } + } + #endif + + #if JUCE_DISPLAY_SPLASH_SCREEN + if (splashDisplayTime == 0 + || Time::getMillisecondCounter() < splashDisplayTime + (uint32) millisecondsToDisplaySplash) + { + const char* svgData = R"JUCESPLASHSCREEN( + + + + + + + + + + " + R"JUCESPLASHSCREEN( + + + + + + + + + + + + + + + + )JUCESPLASHSCREEN"; + + ScopedPointer svgXml (XmlDocument::parse (svgData)); + content = Drawable::createFromSVG (*svgXml); + + setAlwaysOnTop (true); + parent.addAndMakeVisible (this); + } + else + #endif + { + startTimer (1); + } +} + +JUCESplashScreen::~JUCESplashScreen() +{ + if (auto* p = getParentComponent()) + p->removeChildComponent (this); +} + +void JUCESplashScreen::paint (Graphics& g) +{ + auto r = getLocalBounds().toFloat(); + Point bottomRight (0.9f * r.getWidth(), + 0.9f * r.getHeight()); + + ColourGradient cg (Colour (0x00000000), Line (0.0f, r.getHeight(), r.getWidth(), 0.0f).findNearestPointTo (bottomRight), + Colour (0xff000000), bottomRight, false); + cg.addColour (0.25f, Colour (0x10000000)); + cg.addColour (0.50f, Colour (0x30000000)); + cg.addColour (0.75f, Colour (0x70000000)); + g.setFillType (cg); + g.fillAll(); + + content->drawWithin (g, getLogoArea (r), RectanglePlacement::centred, 1.0f); + + if (splashDisplayTime == 0) + splashDisplayTime = Time::getMillisecondCounter(); + + if (! isTimerRunning()) + startTimer (millisecondsToDisplaySplash); +} + +void JUCESplashScreen::timerCallback() +{ + if (isVisible() && ! hasStartedFading) + { + hasStartedFading = true; + fader.animateComponent (this, getBounds(), 0.0f, splashScreenFadeOutTime, false, 0, 0); + } + + if (hasStartedFading && ! fader.isAnimating()) + delete this; +} + +void JUCESplashScreen::parentSizeChanged() +{ + if (auto* p = getParentComponent()) + setBounds (p->getLocalBounds().removeFromBottom (splashScreenLogoHeight * 3) + .removeFromRight (splashScreenLogoWidth * 3)); +} + +void JUCESplashScreen::parentHierarchyChanged() +{ + toFront (false); +} + +bool JUCESplashScreen::hitTest (int x, int y) +{ + return getLogoArea (getLocalBounds().toFloat()).contains ((float) x, (float) y); +} + +void JUCESplashScreen::mouseUp (const MouseEvent&) +{ + URL juceWebsite ("https://juce.com"); + juceWebsite.launchInDefaultBrowser(); +} + +// END SECTION A diff --git a/modules/juce_gui_basics/misc/juce_JUCESplashScreen.h b/modules/juce_gui_basics/misc/juce_JUCESplashScreen.h new file mode 100644 index 0000000000..267c0ae38c --- /dev/null +++ b/modules/juce_gui_basics/misc/juce_JUCESplashScreen.h @@ -0,0 +1,68 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2017 - 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. + + ============================================================================== +*/ + +/* + ============================================================================== + + In accordance with the terms of the JUCE 5 End-Use License Agreement, the + JUCE Code in SECTION A cannot be removed, changed or otherwise rendered + ineffective unless you have a JUCE Indie or Pro license, or are using JUCE + under the GPL v3 license. + + End User License Agreement: www.juce.com/juce-5-licence + ============================================================================== +*/ + +// BEGIN SECTION A + +#pragma once + +/** + The standard JUCE splash screen component. +*/ +class JUCE_API JUCESplashScreen : public Component, + private Timer, + private DeletedAtShutdown +{ +public: + JUCESplashScreen (Component& parentToAddTo); + ~JUCESplashScreen(); + +private: + void paint (Graphics&) override; + void timerCallback() override; + void parentSizeChanged() override; + void parentHierarchyChanged() override; + bool hitTest (int, int) override; + void mouseUp (const MouseEvent&) override; + + ScopedPointer content; + CriticalSection appUsageReporting; + ComponentAnimator fader; + bool hasStartedFading = false; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JUCESplashScreen) +}; + +// END SECTION A diff --git a/modules/juce_gui_basics/windows/juce_ResizableWindow.cpp b/modules/juce_gui_basics/windows/juce_ResizableWindow.cpp index 341acaa6ec..ddafb4059a 100644 --- a/modules/juce_gui_basics/windows/juce_ResizableWindow.cpp +++ b/modules/juce_gui_basics/windows/juce_ResizableWindow.cpp @@ -23,31 +23,13 @@ */ ResizableWindow::ResizableWindow (const String& name, bool shouldAddToDesktop) - : TopLevelWindow (name, shouldAddToDesktop), - ownsContentComponent (false), - resizeToFitContent (false), - fullscreen (false), - canDrag (true), - dragStarted (false), - constrainer (nullptr) - #if JUCE_DEBUG - , hasBeenResized (false) - #endif + : TopLevelWindow (name, shouldAddToDesktop) { initialise (shouldAddToDesktop); } ResizableWindow::ResizableWindow (const String& name, Colour bkgnd, bool shouldAddToDesktop) - : TopLevelWindow (name, shouldAddToDesktop), - ownsContentComponent (false), - resizeToFitContent (false), - fullscreen (false), - canDrag (true), - dragStarted (false), - constrainer (nullptr) - #if JUCE_DEBUG - , hasBeenResized (false) - #endif + : TopLevelWindow (name, shouldAddToDesktop) { setBackgroundColour (bkgnd); @@ -56,6 +38,8 @@ ResizableWindow::ResizableWindow (const String& name, Colour bkgnd, bool shouldA ResizableWindow::~ResizableWindow() { + splashScreen.deleteAndZero(); + // Don't delete or remove the resizer components yourself! They're managed by the // ResizableWindow, and you should leave them alone! You may have deleted them // accidentally by careless use of deleteAllChildren()..? @@ -73,6 +57,25 @@ ResizableWindow::~ResizableWindow() void ResizableWindow::initialise (const bool shouldAddToDesktop) { + /* + ========================================================================== + In accordance with the terms of the JUCE 5 End-Use License Agreement, the + JUCE Code in SECTION A cannot be removed, changed or otherwise rendered + ineffective unless you have a JUCE Indie or Pro license, or are using + JUCE under the GPL v3 license. + + End User License Agreement: www.juce.com/juce-5-licence + ========================================================================== + */ + + // BEGIN SECTION A + + #if ! JucePlugin_Build_Standalone + splashScreen = new JUCESplashScreen (*this); + #endif + + // END SECTION A + defaultConstrainer.setMinimumOnscreenAmounts (0x10000, 16, 24, 16); lastNonFullScreenPos.setBounds (50, 50, 256, 256); diff --git a/modules/juce_gui_basics/windows/juce_ResizableWindow.h b/modules/juce_gui_basics/windows/juce_ResizableWindow.h index b0b683a780..b9ea1291c3 100644 --- a/modules/juce_gui_basics/windows/juce_ResizableWindow.h +++ b/modules/juce_gui_basics/windows/juce_ResizableWindow.h @@ -380,14 +380,14 @@ protected: private: //============================================================================== - Component::SafePointer contentComponent; - bool ownsContentComponent, resizeToFitContent, fullscreen, canDrag, dragStarted; + Component::SafePointer contentComponent, splashScreen; + bool ownsContentComponent = false, resizeToFitContent = false, fullscreen = false, canDrag = true, dragStarted = false; ComponentDragger dragger; Rectangle lastNonFullScreenPos; ComponentBoundsConstrainer defaultConstrainer; - ComponentBoundsConstrainer* constrainer; + ComponentBoundsConstrainer* constrainer = nullptr; #if JUCE_DEBUG - bool hasBeenResized; + bool hasBeenResized = false; #endif void initialise (bool addToDesktop); diff --git a/modules/juce_tracktion_marketplace/marketplace/juce_OnlineUnlockStatus.cpp b/modules/juce_tracktion_marketplace/marketplace/juce_OnlineUnlockStatus.cpp index 8298ffde2a..872eaa5330 100644 --- a/modules/juce_tracktion_marketplace/marketplace/juce_OnlineUnlockStatus.cpp +++ b/modules/juce_tracktion_marketplace/marketplace/juce_OnlineUnlockStatus.cpp @@ -310,22 +310,11 @@ void OnlineUnlockStatus::MachineIDUtilities::addMACAddressesToList (StringArray& StringArray OnlineUnlockStatus::MachineIDUtilities::getLocalMachineIDs() { - StringArray ids; + auto identifiers = SystemStats::getDeviceIdentifiers(); + for (auto& identifier : identifiers) + identifier = getEncodedIDString (identifier); - // First choice for an ID number is a filesystem ID for the user's home - // folder or windows directory. - #if JUCE_WINDOWS - MachineIDUtilities::addFileIDToList (ids, File::getSpecialLocation (File::windowsSystemDirectory)); - #else - MachineIDUtilities::addFileIDToList (ids, File ("~")); - #endif - - // ..if that fails, use the MAC addresses.. - if (ids.size() == 0) - MachineIDUtilities::addMACAddressesToList (ids); - - jassert (ids.size() > 0); // failed to create any IDs! - return ids; + return identifiers; } StringArray OnlineUnlockStatus::getLocalMachineIDs()