From f9f0896bbbeb7ffc91e85903f660b195923e5ec2 Mon Sep 17 00:00:00 2001 From: ed Date: Fri, 12 Mar 2021 16:21:00 +0000 Subject: [PATCH 1/9] Tidied up URL and WebInputStream docs --- modules/juce_core/network/juce_URL.h | 244 ++++++++++-------- .../juce_core/network/juce_WebInputStream.h | 115 +++++---- 2 files changed, 206 insertions(+), 153 deletions(-) diff --git a/modules/juce_core/network/juce_URL.h b/modules/juce_core/network/juce_URL.h index 9a573a7ea0..2d03bd4bdf 100644 --- a/modules/juce_core/network/juce_URL.h +++ b/modules/juce_core/network/juce_URL.h @@ -30,7 +30,7 @@ class WebInputStream; Represents a URL and has a bunch of useful functions to manipulate it. This class can be used to launch URLs in browsers, and also to create - InputStreams that can read from remote http or ftp sources. + InputStreams that can read from remote HTTP or FTP sources. @tags{Core} */ @@ -42,24 +42,21 @@ public: URL(); /** Creates a URL from a string. + This will parse any embedded parameters after a '?' character and store them in the list (see getParameterNames etc). If you don't want this to happen, you can use createWithoutParsing(). */ URL (const String& url); - URL (const URL&) = default; - URL& operator= (const URL&) = default; - URL (URL&&) = default; - URL& operator= (URL&&) = default; - /** Creates URL referring to a local file on your disk using the file:// scheme. */ - explicit URL (File); + explicit URL (File localFile); /** Destructor. */ ~URL() = default; /** Compares two URLs. + All aspects of the URLs must be identical for them to match, including any parameters, upload files, etc. */ @@ -69,9 +66,11 @@ public: //============================================================================== /** Returns a string version of the URL. - If includeGetParameters is true and any parameters have been set with the - withParameter() method, then the string will have these appended on the - end and url-encoded. + @param includeGetParameters if this is true and any parameters have been set + with the withParameter() method, then the string + will have these appended on the end and URL-encoded. + + @see getQueryString */ String toString (bool includeGetParameters) const; @@ -82,26 +81,31 @@ public: bool isWellFormed() const; /** Returns just the domain part of the URL. - E.g. for "http://www.xyz.com/foobar", this will return "www.xyz.com". + + e.g. for "http://www.xyz.com/foobar", this will return "www.xyz.com". */ String getDomain() const; /** Returns the path part of the URL. - E.g. for "http://www.xyz.com/foo/bar?x=1", this will return "foo/bar". - If includeGetParameters is true and any parameters have been set with the - withParameter() method, then the string will have these appended on the - end and url-encoded. + e.g. for "http://www.xyz.com/foo/bar?x=1", this will return "foo/bar". + + @param includeGetParameters if this is true and any parameters have been set + with the withParameter() method, then the string + will have these appended on the end and URL-encoded. + + @see getQueryString */ String getSubPath (bool includeGetParameters = false) const; - /** If any parameters are set, returns these URL encoded, including the "?" - * prefix. + /** If any parameters are set, returns these URL-encoded, including the "?" + prefix. */ String getQueryString() const; /** Returns the scheme of the URL. - E.g. for "http://www.xyz.com/foobar", this will return "http". (It won't + + e.g. for "http://www.xyz.com/foobar", this will return "http" (it won't include the colon). */ String getScheme() const; @@ -110,19 +114,20 @@ public: bool isLocalFile() const; /** Returns the file path of the local file to which this URL refers to. + If the URL does not represent a local file URL (i.e. the URL's scheme is not 'file') then this method will assert. - This method also supports converting Android's content:// URLs to - local file paths. + This method also supports converting Android's content:// URLs to local file paths. @see isLocalFile */ File getLocalFile() const; - /** Returns the file name. For all but Android's content:// scheme, it will - simply return the last segment of the URL. - E.g. for "http://www.xyz.com/foo/bar.txt", this will return "bar.txt". + /** Returns the file name. + + For all but Android's content:// scheme, it will simply return the last segment of + the URL, e.g. for "http://www.xyz.com/foo/bar.txt", this will return "bar.txt". For Android's content:// scheme, it will attempt to resolve the filename located under the URL. @@ -130,36 +135,44 @@ public: String getFileName() const; /** Attempts to read a port number from the URL. + @returns the port number, or 0 if none is explicitly specified. */ int getPort() const; /** Returns a new version of this URL with a different domain and path. - E.g. if the URL is "http://www.xyz.com/foo?x=1" and you call this with + + e.g. if the URL is "http://www.xyz.com/foo?x=1" and you call this with "abc.com/zzz", it'll return "http://abc.com/zzz?x=1". + @see withNewSubPath */ URL withNewDomainAndPath (const String& newFullPath) const; /** Returns a new version of this URL with a different sub-path. - E.g. if the URL is "http://www.xyz.com/foo?x=1" and you call this with + + e.g. if the URL is "http://www.xyz.com/foo?x=1" and you call this with "bar", it'll return "http://www.xyz.com/bar?x=1". + @see withNewDomainAndPath */ URL withNewSubPath (const String& newPath) const; /** Attempts to return a URL which is the parent folder containing this URL. + If there isn't a parent, this method will just return a copy of this URL. */ URL getParentURL() const; /** Returns a new URL that refers to a sub-path relative to this one. - E.g. if the URL is "http://www.xyz.com/foo" and you call this with - "bar", it'll return "http://www.xyz.com/foo/bar". Note that there's no way for - this method to know whether the original URL is a file or directory, so it's - up to you to make sure it's a directory. It also won't attempt to be smart about - the content of the childPath string, so if this string is an absolute URL, it'll - still just get bolted onto the end of the path. + + e.g. if the URL is "http://www.xyz.com/foo" and you call this with "bar", + it'll return "http://www.xyz.com/foo/bar". + + Note that there's no way for this method to know whether the original URL is + a file or directory, so it's up to you to make sure it's a directory. It also + won't attempt to be smart about the content of the childPath string, so if this + string is an absolute URL, it'll still just get bolted onto the end of the path. @see File::getChildFile */ @@ -168,9 +181,10 @@ public: //============================================================================== /** Returns a copy of this URL, with a GET or POST parameter added to the end. - Any control characters in the value will be encoded. + Any control characters in the value will be URL-encoded. + e.g. calling "withParameter ("amount", "some fish") for the url "www.fish.com" - would produce a new url whose toString(true) method would return + would produce a new url whose `toString (true)` method would return "www.fish.com?amount=some+fish". @see getParameterNames, getParameterValues @@ -179,7 +193,9 @@ public: const String& parameterValue) const; /** Returns a copy of this URL, with a set of GET or POST parameters added. + This is a convenience method, equivalent to calling withParameter for each value. + @see withParameter */ URL withParameters (const StringPairArray& parametersToAdd) const; @@ -203,6 +219,7 @@ public: When performing a POST where one of your parameters is a binary file, this lets you specify the file content. + Note that the filename parameter should not be a full path, it's just the last part of the filename. @@ -215,7 +232,7 @@ public: /** Returns an array of the names of all the URL's parameters. - E.g. for the url "www.fish.com?type=haddock&amount=some+fish", this array would + e.g. for the url "www.fish.com?type=haddock&amount=some+fish", this array would contain two items: "type" and "amount". You can call getParameterValues() to get the corresponding value of each @@ -227,7 +244,7 @@ public: /** Returns an array of the values of all the URL's parameters. - E.g. for the url "www.fish.com?type=haddock&amount=some+fish", this array would + e.g. for the url "www.fish.com?type=haddock&amount=some+fish", this array would contain two items: "haddock" and "some fish". The values returned will have been cleaned up to remove any escape characters. @@ -275,7 +292,8 @@ public: //============================================================================== /** Tries to launch the system's default browser to open the URL. - Returns true if this seems to have worked. + + @returns true if this seems to have worked. */ bool launchInDefaultBrowser() const; @@ -312,32 +330,33 @@ public: If the URL represents a local file, then this method simply returns a FileInputStream. - @param doPostLikeRequest if true, the parameters added to this class will be transferred - via the HTTP headers which is typical for POST requests. Otherwise - the parameters will be added to the URL address. Additionally, - if the parameter httpRequestCmd is not specified (or empty) then this - parameter will determine which HTTP request command will be used - (POST or GET). - @param progressCallback if this is not a nullptr, it lets you supply a callback function - to keep track of the operation's progress. This can be useful - for lengthy POST operations, so that you can provide user feedback. + @param doPostLikeRequest if true, the parameters added to this class will be transferred + via the HTTP headers which is typical for POST requests. Otherwise + the parameters will be added to the URL address. Additionally, + if the parameter httpRequestCmd is not specified (or empty) then this + parameter will determine which HTTP request command will be used + (POST or GET). + @param progressCallback if this is not a nullptr, it lets you supply a callback function + to keep track of the operation's progress. This can be useful + for lengthy POST operations, so that you can provide user feedback. @param progressCallbackContext if a callback is specified, this value will be passed to - the function - @param extraHeaders if not empty, this string is appended onto the headers that - are used for the request. It must therefore be a valid set of HTML - header directives, separated by newlines. - @param connectionTimeOutMs if 0, this will use whatever default setting the OS chooses. If - a negative number, it will be infinite. Otherwise it specifies a - time in milliseconds. - @param responseHeaders if this is non-null, all the (key, value) pairs received as headers - in the response will be stored in this array - @param statusCode if this is non-null, it will get set to the http status code, if one - is known, or 0 if a code isn't available - @param numRedirectsToFollow specifies the number of redirects that will be followed before - returning a response (ignored for Android which follows up to 5 redirects) - @param httpRequestCmd Specify which HTTP Request to use. If this is empty, then doPostRequest - will determine the HTTP request. - @returns a valid input stream, or nullptr if there was an error trying to open it. + the function + @param extraHeaders if not empty, this string is appended onto the headers that + are used for the request. It must therefore be a valid set of HTML + header directives, separated by newlines. + @param connectionTimeOutMs if 0, this will use whatever default setting the OS chooses. If + a negative number, it will be infinite. Otherwise it specifies a + time in milliseconds. + @param responseHeaders if this is non-null, all the (key, value) pairs received as headers + in the response will be stored in this array + @param statusCode if this is non-null, it will get set to the http status code, if one + is known, or 0 if a code isn't available + @param numRedirectsToFollow specifies the number of redirects that will be followed before + returning a response (ignored for Android which follows up to 5 redirects) + @param httpRequestCmd Specify which HTTP Request to use. If this is empty, then doPostRequest + will determine the HTTP request. + + @returns a valid input stream, or nullptr if there was an error trying to open it. */ std::unique_ptr createInputStream (bool doPostLikeRequest, OpenStreamProgressCallback* progressCallback = nullptr, @@ -358,32 +377,38 @@ public: //============================================================================== /** Represents a download task. - Returned by downloadToFile to allow querying and controlling the download task. + + Returned by downloadToFile() to allow querying and controlling the download task. */ class JUCE_API DownloadTask { public: - /** Used to receive callbacks for download progress */ + /** Used to receive callbacks for download progress. */ struct JUCE_API Listener { virtual ~Listener(); /** Called when the download has finished. Be aware that this callback may - come on an arbitrary thread. */ + come on an arbitrary thread. + */ virtual void finished (URL::DownloadTask* task, bool success) = 0; /** Called periodically by the OS to indicate download progress. + Beware that this callback may come on an arbitrary thread. */ virtual void progress (URL::DownloadTask* task, int64 bytesDownloaded, int64 totalLength); }; /** Releases the resources of the download task, unregisters the listener - and cancels the download if necessary. */ + and cancels the download if necessary. + */ virtual ~DownloadTask(); - /** Returns the total length of the download task. This may return -1 if the length - was not returned by the server. */ + /** Returns the total length of the download task. + + This may return -1 if the length was not returned by the server. + */ int64 getTotalLength() const { return contentLength; } /** Returns the number of bytes that have been downloaded so far. */ @@ -393,7 +418,9 @@ public: bool isFinished() const { return finished; } /** Returns the status code of the server's response. + This will only be valid after the download has finished. + @see isFinished */ int statusCode() const { return httpCode; } @@ -449,9 +476,10 @@ public: Note that on some platforms (Android, for example) it's not permitted to do any network action from the message thread, so you must only call it from a background thread. - @param destData the memory block to append the new data to - @param usePostCommand whether to use a POST command to get the data (uses - a GET command if this is false) + @param destData the memory block to append the new data to. + @param usePostCommand whether to use a POST command to get the data (uses + a GET command if this is false). + @see readEntireTextStream, readEntireXmlStream */ bool readEntireBinaryStream (MemoryBlock& destData, @@ -467,8 +495,9 @@ public: Note that on some platforms (Android, for example) it's not permitted to do any network action from the message thread, so you must only call it from a background thread. - @param usePostCommand whether to use a POST command to get the data (uses - a GET command if this is false) + @param usePostCommand whether to use a POST command to get the data (uses + a GET command if this is false). + @see readEntireBinaryStream, readEntireXmlStream */ String readEntireTextStream (bool usePostCommand = false) const; @@ -481,8 +510,8 @@ public: Note that on some platforms (Android, for example) it's not permitted to do any network action from the message thread, so you must only call it from a background thread. - @param usePostCommand whether to use a POST command to get the data (uses - a GET command if this is false) + @param usePostCommand whether to use a POST command to get the data (uses + a GET command if this is false). @see readEntireBinaryStream, readEntireTextStream */ @@ -496,14 +525,14 @@ public: This is the opposite of removeEscapeChars(). - @param stringToAddEscapeCharsTo The string to escape. - @param isParameter If true then the string is going to be - used as a parameter, so it also encodes - '$' and ',' (which would otherwise be - legal in a URL. - @param roundBracketsAreLegal Technically round brackets are ok in URLs, - however, some servers (like AWS) also want - round brackets to be escaped. + @param stringToAddEscapeCharsTo the string to escape. + @param isParameter if true then the string is going to be + used as a parameter, so it also encodes + '$' and ',' (which would otherwise be + legal in a URL. + @param roundBracketsAreLegal technically round brackets are ok in URLs, + however, some servers (like AWS) also want + round brackets to be escaped. @see removeEscapeChars */ @@ -523,6 +552,7 @@ public: static String removeEscapeChars (const String& stringToRemoveEscapeCharsFrom); /** Returns a URL without attempting to remove any embedded parameters from the string. + This may be necessary if you need to create a request that involves both POST parameters and parameters which are embedded in the URL address itself. */ @@ -530,28 +560,7 @@ public: private: //============================================================================== - friend class WebInputStream; - - String url; - MemoryBlock postData; - StringArray parameterNames, parameterValues; - - static File fileFromFileSchemeURL (const URL&); - String getDomainInternal (bool) const; - - struct Upload : public ReferenceCountedObject - { - Upload (const String&, const String&, const String&, const File&, MemoryBlock*); - String parameterName, filename, mimeType; - File file; - std::unique_ptr data; - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Upload) - }; - - ReferenceCountedArray filesToUpload; - - #if JUCE_IOS + #if JUCE_IOS struct Bookmark : public ReferenceCountedObject { using Ptr = ReferenceCountedObjectPtr; @@ -566,7 +575,21 @@ private: friend void setURLBookmark (URL&, void*); friend void* getURLBookmark (URL&); - #endif + #endif + + //============================================================================== + struct Upload : public ReferenceCountedObject + { + Upload (const String&, const String&, const String&, const File&, MemoryBlock*); + String parameterName, filename, mimeType; + File file; + std::unique_ptr data; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Upload) + }; + + //============================================================================== + friend class WebInputStream; URL (const String&, int); void init(); @@ -574,6 +597,17 @@ private: void createHeadersAndPostData (String&, MemoryBlock&) const; URL withUpload (Upload*) const; + static File fileFromFileSchemeURL (const URL&); + String getDomainInternal (bool) const; + + //============================================================================== + String url; + MemoryBlock postData; + StringArray parameterNames, parameterValues; + + ReferenceCountedArray filesToUpload; + + //============================================================================== JUCE_LEAK_DETECTOR (URL) }; diff --git a/modules/juce_core/network/juce_WebInputStream.h b/modules/juce_core/network/juce_WebInputStream.h index b8d4a54af3..126fcecf68 100644 --- a/modules/juce_core/network/juce_WebInputStream.h +++ b/modules/juce_core/network/juce_WebInputStream.h @@ -25,35 +25,26 @@ namespace juce //============================================================================== /** - An InputStream which can be used to read from a given url. + An InputStream which can be used to read from a given URL. @tags{Core} */ -class JUCE_API WebInputStream : public InputStream +class JUCE_API WebInputStream : public InputStream { public: - /** Used to receive callbacks for data send progress */ - class JUCE_API Listener - { - public: - virtual ~Listener() = default; - - virtual bool postDataSendProgress (WebInputStream& /*request*/, int /*bytesSent*/, int /*totalBytes*/) { return true; } - }; - - /** Creates a new WebInputstream which can be used to read from a url. + /** Creates a new WebInputStream which can be used to read from a URL. - @param url The url that should be retrieved. This parameter may also contain - post data and/or parameters. + @param url The URL that should be retrieved. This parameter may also contain + POST data and/or parameters. @param usePost Specifies whether a GET or a POST command should be used. This parameter will also influence the way parameters are encoded. */ - WebInputStream (const URL& url, const bool usePost); + WebInputStream (const URL& url, bool usePost); + /** Destructor. */ ~WebInputStream() override; - - /** Add extra headers to http request + /** Add extra headers to the HTTP request. Returns a reference to itself so that several methods can be chained. @@ -63,65 +54,67 @@ class JUCE_API WebInputStream : public InputStream */ WebInputStream& withExtraHeaders (const String& extraHeaders); - /** Override the http command that is sent + /** Override the HTTP command that is sent. Returns a reference to itself so that several methods can be chained. Note that this command will not change the way parameters are sent. This must be specified in the constructor. - @param customRequestCommand this string is the custom http request command such - as POST or GET. + @param customRequestCommand this string is the custom http request command such + as POST or GET. */ WebInputStream& withCustomRequestCommand (const String& customRequestCommand); - /** Specify the connection time-out + /** Specify the connection time-out. Returns a reference to itself so that several methods can be chained. - @param timeoutInMs the number of milliseconds to wait until the connection - request is aborted. + @param timeoutInMs the number of milliseconds to wait until the connection + request is aborted. */ WebInputStream& withConnectionTimeout (int timeoutInMs); - /** Specify the number of redirects to be followed + /** Specify the number of redirects to be followed. Returns a reference to itself so that several methods can be chained. - @param numRedirects specifies the number of redirects that will be followed - before returning a response (ignored for Android which - follows up to 5 redirects) + @param numRedirects specifies the number of redirects that will be followed + before returning a response (ignored for Android which + follows up to 5 redirects) */ WebInputStream& withNumRedirectsToFollow (int numRedirects); - /** Returns a string array pair of the request headers */ - StringPairArray getRequestHeaders() const; - - /** Returns a string array pair of response headers - - If getResponseHeaders is called without an established connection, then - getResponseHeaders will call connect internally and block until connect - returns - either due to a successful connection or a connection - error. + //============================================================================== + /** Used to receive callbacks for POST data send progress. - @see connect + Pass one of these into the `connect()` method and its `postDataSendProgress()` + method will be called periodically with updates on POST data upload progress. */ - StringPairArray getResponseHeaders(); + class JUCE_API Listener + { + public: + /** Destructor. */ + virtual ~Listener() = default; - /** Returns the status code returned by the http server + /** This method will be called periodically with updates on POST data upload progress. - If getStatusCode is called without an established connection, then - getStatusCode will call connect internally and block until connect - returns - either due to a successful connection or a connection - error. + @param request the original request + @param bytesSent the number of bytes sent so far + @param totalByes the total number of bytes to send - @see connect - */ - int getStatusCode(); + @returns true to continue or false to cancel the upload + */ + virtual bool postDataSendProgress (WebInputStream& request, int bytesSent, int totalBytes) + { + ignoreUnused (request, bytesSent, totalBytes); + return true; + } + }; - /** Wait until the first byte is ready for reading + /** Wait until the first byte is ready for reading. - This method will attempt to connect to the url given in the constructor + This method will attempt to connect to the URL given in the constructor and block until the status code and all response headers have been received or an error has occurred. @@ -145,6 +138,31 @@ class JUCE_API WebInputStream : public InputStream /** Will cancel a blocking read and prevent any subsequent connection attempts. */ void cancel(); + /** Returns a StringArrayPair of the request headers. */ + StringPairArray getRequestHeaders() const; + + /** Returns a StringArrayPair of response headers. + + If getResponseHeaders is called without an established connection, then + getResponseHeaders will call connect internally and block until connect + returns - either due to a successful connection or a connection + error. + + @see connect + */ + StringPairArray getResponseHeaders(); + + /** Returns the status code returned by the HTTP server + + If getStatusCode is called without an established connection, then + getStatusCode will call connect internally and block until connect + returns - either due to a successful connection or a connection + error. + + @see connect + */ + int getStatusCode(); + //============================================================================== /** Returns the total number of bytes available for reading in this stream. @@ -181,6 +199,7 @@ class JUCE_API WebInputStream : public InputStream bool isExhausted() override; /** Returns the offset of the next byte that will be read from the stream. + @see setPosition */ int64 getPosition() override; From fa8c446d0cb3f6f956079afaa9e36cbb0f99b3ef Mon Sep 17 00:00:00 2001 From: ed Date: Fri, 12 Mar 2021 16:22:45 +0000 Subject: [PATCH 2/9] URL: Added InputStreamOptions and enable POST data to be sent with URL-encoded parameters. - Added a new URL::createInputStream() overload that takes an InputStreamOptions helper class to simplify stream creation. - Modified the internals of URL and WebInputStream so that parameters are only added to the request body when ParameterHandling is set to inPostData. This allows POST data to be added via URL::withPOSTData() and sent with URL-encoded parameters. --- .../juce_core/native/juce_android_Network.cpp | 20 +- .../juce_core/native/juce_curl_Network.cpp | 25 +-- .../juce_core/native/juce_linux_Network.cpp | 34 ++-- modules/juce_core/native/juce_mac_Network.mm | 16 +- .../juce_core/native/juce_win32_Network.cpp | 21 +- modules/juce_core/network/juce_URL.cpp | 175 +++++++++++++---- modules/juce_core/network/juce_URL.h | 185 ++++++++++++------ .../juce_core/network/juce_WebInputStream.cpp | 32 ++- .../juce_core/network/juce_WebInputStream.h | 8 +- 9 files changed, 353 insertions(+), 163 deletions(-) diff --git a/modules/juce_core/native/juce_android_Network.cpp b/modules/juce_core/native/juce_android_Network.cpp index 2ddd79f977..791c8dbbbc 100644 --- a/modules/juce_core/native/juce_android_Network.cpp +++ b/modules/juce_core/native/juce_android_Network.cpp @@ -324,12 +324,13 @@ class WebInputStream::Pimpl public: enum { contentStreamCacheSize = 1024 }; - Pimpl (WebInputStream&, const URL& urlToCopy, bool shouldBePost) + Pimpl (WebInputStream&, const URL& urlToCopy, bool isPOSTLike) : url (urlToCopy), isContentURL (urlToCopy.getScheme() == "content"), - isPost (shouldBePost), - httpRequest (isPost ? "POST" : "GET") - {} + addParametersToRequestBody (isPOSTLike), + httpRequest (isPOSTLike || url.hasPOSTData() ? "POST" : "GET") + { + } ~Pimpl() { @@ -373,14 +374,14 @@ public: } else { - String address = url.toString (! isPost); + String address = url.toString (! addParametersToRequestBody); if (! address.contains ("://")) address = "http://" + address; MemoryBlock postData; - if (isPost) - WebInputStream::createHeadersAndPostData (url, headers, postData); + if (url.hasPOSTData()) + WebInputStream::createHeadersAndPostData (url, headers, postData, addParametersToRequestBody); jbyteArray postDataArray = nullptr; @@ -406,7 +407,7 @@ public: stream = GlobalRef (LocalRef (env->CallStaticObjectMethod (HTTPStream, HTTPStream.createHTTPStream, javaString (address).get(), - (jboolean) isPost, + (jboolean) addParametersToRequestBody, postDataArray, javaString (headers).get(), (jint) timeOutMs, @@ -535,7 +536,8 @@ public: private: const URL url; - bool isContentURL, isPost, eofStreamReached = false; + const bool isContentURL, addParametersToRequestBody; + bool eofStreamReached = false; int numRedirectsToFollow = 5, timeOutMs = 0; String httpRequest, headers; StringPairArray responseHeaders; diff --git a/modules/juce_core/native/juce_curl_Network.cpp b/modules/juce_core/native/juce_curl_Network.cpp index 00d4283508..47e36e0135 100644 --- a/modules/juce_core/native/juce_curl_Network.cpp +++ b/modules/juce_core/native/juce_curl_Network.cpp @@ -110,9 +110,12 @@ private: class WebInputStream::Pimpl { public: - Pimpl (WebInputStream& ownerStream, const URL& urlToCopy, bool shouldUsePost) - : owner (ownerStream), url (urlToCopy), isPost (shouldUsePost), - httpRequest (isPost ? "POST" : "GET") + Pimpl (WebInputStream& ownerStream, const URL& urlToCopy, bool isPOSTLike) + : owner (ownerStream), + url (urlToCopy), + addParametersToRequestBody (isPOSTLike), + hasPOSTData (url.hasPOSTData()), + httpRequest (isPOSTLike || url.hasPOSTData() ? "POST" : "GET") { jassert (symbols); // Unable to load libcurl! @@ -220,7 +223,7 @@ public: //============================================================================== bool setOptions() { - auto address = url.toString (! isPost); + auto address = url.toString (! addParametersToRequestBody); curl_version_info_data* data = symbols->curl_version_info (CURLVERSION_NOW); jassert (data != nullptr); @@ -228,8 +231,8 @@ public: if (! requestHeaders.endsWithChar ('\n')) requestHeaders << "\r\n"; - if (isPost) - WebInputStream::createHeadersAndPostData (url, requestHeaders, headersAndPostData); + if (hasPOSTData) + WebInputStream::createHeadersAndPostData (url, requestHeaders, headersAndPostData, addParametersToRequestBody); if (! requestHeaders.endsWithChar ('\n')) requestHeaders << "\r\n"; @@ -244,7 +247,7 @@ public: && symbols->curl_easy_setopt (curl, CURLOPT_USERAGENT, userAgent.toRawUTF8()) == CURLE_OK && symbols->curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, (maxRedirects > 0 ? 1 : 0)) == CURLE_OK) { - if (isPost) + if (hasPOSTData) { if (symbols->curl_easy_setopt (curl, CURLOPT_READDATA, this) != CURLE_OK || symbols->curl_easy_setopt (curl, CURLOPT_READFUNCTION, StaticCurlRead) != CURLE_OK) @@ -256,7 +259,7 @@ public: } // handle special http request commands - bool hasSpecialRequestCmd = isPost ? (httpRequest != "POST") : (httpRequest != "GET"); + const auto hasSpecialRequestCmd = hasPOSTData ? (httpRequest != "POST") : (httpRequest != "GET"); if (hasSpecialRequestCmd) if (symbols->curl_easy_setopt (curl, CURLOPT_CUSTOMREQUEST, httpRequest.toRawUTF8()) != CURLE_OK) @@ -323,7 +326,7 @@ public: listener = webInputListener; - if (isPost) + if (hasPOSTData) postBuffer = &headersAndPostData; size_t lastPos = static_cast (-1); @@ -342,7 +345,7 @@ public: singleStep(); // call callbacks if this is a post request - if (isPost && listener != nullptr && lastPos != postPosition) + if (hasPOSTData && listener != nullptr && lastPos != postPosition) { lastPos = postPosition; @@ -613,7 +616,7 @@ public: // Options int timeOutMs = 0; int maxRedirects = 5; - const bool isPost; + const bool addParametersToRequestBody, hasPOSTData; String httpRequest; //============================================================================== diff --git a/modules/juce_core/native/juce_linux_Network.cpp b/modules/juce_core/native/juce_linux_Network.cpp index f323139114..a786baa89d 100644 --- a/modules/juce_core/native/juce_linux_Network.cpp +++ b/modules/juce_core/native/juce_linux_Network.cpp @@ -70,10 +70,13 @@ bool JUCE_CALLTYPE Process::openEmailWithAttachments (const String& /* targetEma class WebInputStream::Pimpl { public: - Pimpl (WebInputStream& pimplOwner, const URL& urlToCopy, bool shouldUsePost) - : owner (pimplOwner), url (urlToCopy), - isPost (shouldUsePost), httpRequestCmd (shouldUsePost ? "POST" : "GET") - {} + Pimpl (WebInputStream& pimplOwner, const URL& urlToCopy, bool isPOSTLike) + : owner (pimplOwner), + url (urlToCopy), + addParametersToRequestBody (isPOSTLike), + httpRequestCmd (isPOSTLike || url.hasPOSTData() ? "POST" : "GET") + { + } ~Pimpl() { @@ -127,7 +130,7 @@ public: return false; } - address = url.toString (! isPost); + address = url.toString (! addParametersToRequestBody); statusCode = createConnection (listener, numRedirectsToFollow); return statusCode != 0; @@ -256,7 +259,7 @@ private: MemoryBlock postData; int64 contentLength = -1, position = 0; bool finished = false; - const bool isPost; + const bool addParametersToRequestBody; int timeOutMs = 0; int numRedirectsToFollow = 5; String httpRequestCmd; @@ -285,8 +288,8 @@ private: { closeSocket (false); - if (isPost) - WebInputStream::createHeadersAndPostData (url, headers, postData); + if (url.hasPOSTData()) + WebInputStream::createHeadersAndPostData (url, headers, postData, addParametersToRequestBody); auto timeOutTime = Time::getMillisecondCounter(); @@ -367,8 +370,8 @@ private: freeaddrinfo (result); { - const MemoryBlock requestHeader (createRequestHeader (hostName, hostPort, proxyName, proxyPort, hostPath, - address, headers, postData, isPost, httpRequestCmd)); + const MemoryBlock requestHeader (createRequestHeader (hostName, hostPort, proxyName, proxyPort, hostPath, address, + headers, postData, httpRequestCmd)); if (! sendHeader (socketHandle, requestHeader, timeOutTime, owner, listener)) { @@ -474,7 +477,7 @@ private: const String& proxyName, int proxyPort, const String& hostPath, const String& originalURL, const String& userHeaders, const MemoryBlock& postData, - bool isPost, const String& httpRequestCmd) + const String& httpRequestCmd) { MemoryOutputStream header; @@ -488,15 +491,18 @@ private: "." JUCE_STRINGIFY(JUCE_BUILDNUMBER)); writeValueIfNotPresent (header, userHeaders, "Connection:", "close"); - if (isPost) - writeValueIfNotPresent (header, userHeaders, "Content-Length:", String ((int) postData.getSize())); + const auto postDataSize = postData.getSize(); + const auto hasPostData = postDataSize > 0; + + if (hasPostData) + writeValueIfNotPresent (header, userHeaders, "Content-Length:", String ((int) postDataSize)); if (userHeaders.isNotEmpty()) header << "\r\n" << userHeaders; header << "\r\n\r\n"; - if (isPost) + if (hasPostData) header << postData; return header.getMemoryBlock(); diff --git a/modules/juce_core/native/juce_mac_Network.mm b/modules/juce_core/native/juce_mac_Network.mm index a092a58398..3a77615c1a 100644 --- a/modules/juce_core/native/juce_mac_Network.mm +++ b/modules/juce_core/native/juce_mac_Network.mm @@ -943,9 +943,11 @@ JUCE_END_IGNORE_WARNINGS_GCC_LIKE class WebInputStream::Pimpl { public: - Pimpl (WebInputStream& pimplOwner, const URL& urlToUse, bool shouldBePost) - : owner (pimplOwner), url (urlToUse), isPost (shouldBePost), - httpRequestCmd (shouldBePost ? "POST" : "GET") + Pimpl (WebInputStream& pimplOwner, const URL& urlToUse, bool isPOSTLike) + : owner (pimplOwner), + url (urlToUse), + addParametersToRequestBody (isPOSTLike), + httpRequestCmd (isPOSTLike || url.hasPOSTData() ? "POST" : "GET") { } @@ -1089,7 +1091,7 @@ private: MemoryBlock postData; int64 position = 0; bool finished = false; - const bool isPost; + const bool addParametersToRequestBody; int timeOutMs = 0; int numRedirectsToFollow = 5; String httpRequestCmd; @@ -1101,7 +1103,7 @@ private: { jassert (connection == nullptr); - if (NSURL* nsURL = [NSURL URLWithString: juceStringToNS (url.toString (! isPost))]) + if (NSURL* nsURL = [NSURL URLWithString: juceStringToNS (url.toString (! addParametersToRequestBody))]) { if (NSMutableURLRequest* req = [NSMutableURLRequest requestWithURL: nsURL cachePolicy: NSURLRequestReloadIgnoringLocalCacheData @@ -1111,9 +1113,9 @@ private: { [req setHTTPMethod: httpMethod]; - if (isPost) + if (url.hasPOSTData()) { - WebInputStream::createHeadersAndPostData (url, headers, postData); + WebInputStream::createHeadersAndPostData (url, headers, postData, addParametersToRequestBody); if (postData.getSize() > 0) [req setHTTPBody: [NSData dataWithBytes: postData.getData() diff --git a/modules/juce_core/native/juce_win32_Network.cpp b/modules/juce_core/native/juce_win32_Network.cpp index c0289fc2fc..eb3a533bed 100644 --- a/modules/juce_core/native/juce_win32_Network.cpp +++ b/modules/juce_core/native/juce_win32_Network.cpp @@ -35,10 +35,13 @@ namespace juce class WebInputStream::Pimpl { public: - Pimpl (WebInputStream& pimplOwner, const URL& urlToCopy, bool shouldBePost) - : statusCode (0), owner (pimplOwner), url (urlToCopy), isPost (shouldBePost), - httpRequestCmd (isPost ? "POST" : "GET") - {} + Pimpl (WebInputStream& pimplOwner, const URL& urlToCopy, bool isPOSTLike) + : owner (pimplOwner), + url (urlToCopy), + addParametersToRequestBody (isPOSTLike), + httpRequestCmd (isPOSTLike || url.hasPOSTData() ? "POST" : "GET") + { + } ~Pimpl() { @@ -75,7 +78,7 @@ public: return false; } - String address = url.toString (! isPost); + auto address = url.toString (! addParametersToRequestBody); while (numRedirectsToFollow-- >= 0) { @@ -226,7 +229,7 @@ public: return true; } - int statusCode; + int statusCode = 0; private: //============================================================================== @@ -237,7 +240,7 @@ private: MemoryBlock postData; int64 position = 0; bool finished = false; - const bool isPost; + const bool addParametersToRequestBody; int timeOutMs = 0; String httpRequestCmd; int numRedirectsToFollow = 5; @@ -288,8 +291,8 @@ private: uc.lpszPassword = password; uc.dwPasswordLength = passwordNumChars; - if (isPost) - WebInputStream::createHeadersAndPostData (url, headers, postData); + if (url.hasPOSTData()) + WebInputStream::createHeadersAndPostData (url, headers, postData, addParametersToRequestBody); if (InternetCrackUrl (address.toWideCharPointer(), 0, 0, &uc)) openConnection (uc, sessionHandle, address, listener); diff --git a/modules/juce_core/network/juce_URL.cpp b/modules/juce_core/network/juce_URL.cpp index 36307db8d6..e9dd39ab83 100644 --- a/modules/juce_core/network/juce_URL.cpp +++ b/modules/juce_core/network/juce_URL.cpp @@ -377,6 +377,11 @@ String URL::getFileName() const } #endif +URL::ParameterHandling URL::toHandling (bool usePostData) +{ + return usePostData ? ParameterHandling::inPostData : ParameterHandling::inAddress; +} + File URL::fileFromFileSchemeURL (const URL& fileURL) { if (! fileURL.isLocalFile()) @@ -447,7 +452,9 @@ URL URL::getChildURL (const String& subPath) const return u; } -void URL::createHeadersAndPostData (String& headers, MemoryBlock& postDataToWrite) const +void URL::createHeadersAndPostData (String& headers, + MemoryBlock& postDataToWrite, + bool addParametersToBody) const { MemoryOutputStream data (postDataToWrite, false); @@ -491,8 +498,10 @@ void URL::createHeadersAndPostData (String& headers, MemoryBlock& postDataToWrit } else { - data << URLHelpers::getMangledParameters (*this) - << postData; + if (addParametersToBody) + data << URLHelpers::getMangledParameters (*this) << postData; + else + data << postData; // if the user-supplied headers didn't contain a content-type, add one now.. if (! headers.containsIgnoreCase ("Content-Type")) @@ -656,73 +665,127 @@ private: } }; #endif +//============================================================================== +template +static URL::InputStreamOptions with (URL::InputStreamOptions options, Member&& member, Item&& item) +{ + options.*member = std::forward (item); + return options; +} + +URL::InputStreamOptions::InputStreamOptions (ParameterHandling handling) : parameterHandling (handling) {} + +URL::InputStreamOptions URL::InputStreamOptions::withProgressCallback (std::function cb) const +{ + return with (*this, &InputStreamOptions::progressCallback, std::move (cb)); +} + +URL::InputStreamOptions URL::InputStreamOptions::withExtraHeaders (const String& headers) const +{ + return with (*this, &InputStreamOptions::extraHeaders, headers); +} + +URL::InputStreamOptions URL::InputStreamOptions::withConnectionTimeoutMs (int timeout) const +{ + return with (*this, &InputStreamOptions::connectionTimeOutMs, timeout); +} + +URL::InputStreamOptions URL::InputStreamOptions::withResponseHeaders (StringPairArray* headers) const +{ + return with (*this, &InputStreamOptions::responseHeaders, headers); +} + +URL::InputStreamOptions URL::InputStreamOptions::withStatusCode (int* status) const +{ + return with (*this, &InputStreamOptions::statusCode, status); +} + +URL::InputStreamOptions URL::InputStreamOptions::withNumRedirectsToFollow (int numRedirects) const +{ + return with (*this, &InputStreamOptions::numRedirectsToFollow, numRedirects); +} + +URL::InputStreamOptions URL::InputStreamOptions::withHttpRequestCmd (const String& cmd) const +{ + return with (*this, &InputStreamOptions::httpRequestCmd, cmd); +} //============================================================================== -std::unique_ptr URL::createInputStream (bool usePostCommand, - OpenStreamProgressCallback* progressCallback, - void* progressCallbackContext, - String headers, - int timeOutMs, - StringPairArray* responseHeaders, - int* statusCode, - int numRedirectsToFollow, - String httpRequestCmd) const +std::unique_ptr URL::createInputStream (const InputStreamOptions& options) const { if (isLocalFile()) { #if JUCE_IOS // We may need to refresh the embedded bookmark. - return std::make_unique> (const_cast(*this)); + return std::make_unique> (const_cast (*this)); #else return getLocalFile().createInputStream(); #endif } - auto wi = std::make_unique (*this, usePostCommand); + auto webInputStream = [&] + { + const auto usePost = options.getParameterHandling() == ParameterHandling::inPostData; + auto stream = std::make_unique (*this, usePost); + + auto extraHeaders = options.getExtraHeaders(); + + if (extraHeaders.isNotEmpty()) + stream->withExtraHeaders (extraHeaders); + + auto timeout = options.getConnectionTimeoutMs(); + + if (timeout != 0) + stream->withConnectionTimeout (timeout); + + auto requestCmd = options.getHttpRequestCmd(); + + if (requestCmd.isNotEmpty()) + stream->withCustomRequestCommand (requestCmd); + + stream->withNumRedirectsToFollow (options.getNumRedirectsToFollow()); + + return stream; + }(); struct ProgressCallbackCaller : public WebInputStream::Listener { - ProgressCallbackCaller (OpenStreamProgressCallback* progressCallbackToUse, void* progressCallbackContextToUse) - : callback (progressCallbackToUse), data (progressCallbackContextToUse) - {} + ProgressCallbackCaller (std::function progressCallbackToUse) + : callback (std::move (progressCallbackToUse)) + { + } bool postDataSendProgress (WebInputStream&, int bytesSent, int totalBytes) override { - return callback (data, bytesSent, totalBytes); + return callback (bytesSent, totalBytes); } - OpenStreamProgressCallback* callback; - void* const data; + std::function callback; }; - std::unique_ptr callbackCaller - (progressCallback != nullptr ? new ProgressCallbackCaller (progressCallback, progressCallbackContext) : nullptr); - - if (headers.isNotEmpty()) - wi->withExtraHeaders (headers); - - if (timeOutMs != 0) - wi->withConnectionTimeout (timeOutMs); - - if (httpRequestCmd.isNotEmpty()) - wi->withCustomRequestCommand (httpRequestCmd); + auto callbackCaller = [&options]() -> std::unique_ptr + { + if (auto progressCallback = options.getProgressCallback()) + return std::make_unique (progressCallback); - wi->withNumRedirectsToFollow (numRedirectsToFollow); + return {}; + }(); - bool success = wi->connect (callbackCaller.get()); + auto success = webInputStream->connect (callbackCaller.get()); - if (statusCode != nullptr) - *statusCode = wi->getStatusCode(); + if (auto* status = options.getStatusCode()) + *status = webInputStream->getStatusCode(); - if (responseHeaders != nullptr) - *responseHeaders = wi->getResponseHeaders(); + if (auto* responseHeaders = options.getResponseHeaders()) + *responseHeaders = webInputStream->getResponseHeaders(); - if (! success || wi->isError()) + if (! success || webInputStream->isError()) return nullptr; - // Older GCCs complain about binding unique_ptr&& to unique_ptr - // if we just `return wi` here. - return std::unique_ptr (std::move (wi)); + // std::move() needed here for older compilers + JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wredundant-move") + return std::move (webInputStream); + JUCE_END_IGNORE_WARNINGS_GCC_LIKE } #if JUCE_ANDROID @@ -752,7 +815,7 @@ std::unique_ptr URL::createOutputStream() const bool URL::readEntireBinaryStream (MemoryBlock& destData, bool usePostCommand) const { const std::unique_ptr in (isLocalFile() ? getLocalFile().createInputStream() - : createInputStream (usePostCommand)); + : createInputStream (InputStreamOptions (toHandling (usePostCommand)))); if (in != nullptr) { @@ -766,7 +829,7 @@ bool URL::readEntireBinaryStream (MemoryBlock& destData, bool usePostCommand) co String URL::readEntireTextStream (bool usePostCommand) const { const std::unique_ptr in (isLocalFile() ? getLocalFile().createInputStream() - : createInputStream (usePostCommand)); + : createInputStream (InputStreamOptions (toHandling (usePostCommand)))); if (in != nullptr) return in->readEntireStreamAsString(); @@ -911,4 +974,30 @@ bool URL::launchInDefaultBrowser() const return Process::openDocument (u, {}); } +//============================================================================== +std::unique_ptr URL::createInputStream (bool usePostCommand, + OpenStreamProgressCallback* cb, + void* context, + String headers, + int timeOutMs, + StringPairArray* responseHeaders, + int* statusCode, + int numRedirectsToFollow, + String httpRequestCmd) const +{ + std::function callback; + + if (cb != nullptr) + callback = [context, cb] (int sent, int total) { return cb (context, sent, total); }; + + return createInputStream (InputStreamOptions (toHandling (usePostCommand)) + .withProgressCallback (std::move (callback)) + .withExtraHeaders (headers) + .withConnectionTimeoutMs (timeOutMs) + .withResponseHeaders (responseHeaders) + .withStatusCode (statusCode) + .withNumRedirectsToFollow(numRedirectsToFollow) + .withHttpRequestCmd (httpRequestCmd)); +} + } // namespace juce diff --git a/modules/juce_core/network/juce_URL.h b/modules/juce_core/network/juce_URL.h index 2d03bd4bdf..293903a8b4 100644 --- a/modules/juce_core/network/juce_URL.h +++ b/modules/juce_core/network/juce_URL.h @@ -258,38 +258,33 @@ public: /** Returns a copy of this URL, with a block of data to send as the POST data. - If you're setting the POST data, be careful not to have any parameters set - as well, otherwise it'll all get thrown in together, and might not have the - desired effect. - If the URL already contains some POST data, this will replace it, rather than being appended to it. - This data will only be used if you specify a post operation when you call - createInputStream(). + If no HTTP command is set when calling createInputStream() to read from + this URL and some data has been set, it will do a POST request. */ URL withPOSTData (const String& postData) const; /** Returns a copy of this URL, with a block of data to send as the POST data. - If you're setting the POST data, be careful not to have any parameters set - as well, otherwise it'll all get thrown in together, and might not have the - desired effect. - If the URL already contains some POST data, this will replace it, rather than being appended to it. - This data will only be used if you specify a post operation when you call - createInputStream(). + If no HTTP command is set when calling createInputStream() to read from + this URL and some data has been set, it will do a POST request. */ URL withPOSTData (const MemoryBlock& postData) const; /** Returns the data that was set using withPOSTData(). */ String getPostData() const { return postData.toString(); } - /** Returns the data that was set using withPOSTData() as MemoryBlock. */ + /** Returns the data that was set using withPOSTData() as a MemoryBlock. */ const MemoryBlock& getPostDataAsMemoryBlock() const noexcept { return postData; } + /** Returns true if this URL has POST data set using withPOSTData(). */ + bool hasPOSTData() const noexcept { return postData.getSize() > 0; } + //============================================================================== /** Tries to launch the system's default browser to open the URL. @@ -308,13 +303,103 @@ public: */ static bool isProbablyAnEmailAddress (const String& possibleEmailAddress); - //============================================================================== - /** This callback function can be used by the createInputStream() method. + enum class ParameterHandling + { + inAddress, + inPostData + }; - It allows your app to receive progress updates during a lengthy POST operation. If you - want to continue the operation, this should return true, or false to abort. + //============================================================================== + /** Class used to create a set of options to pass to the createInputStream() method. + + You can chain together a series of calls to this class's methods to create + a set of whatever options you want to specify, e.g. + @code + if (auto inputStream = URL ("http://www.xyz.com/foobar") + .createInputStream (URL::InputStreamOptions (false).withConnectionTimeoutMs (1000) + .withNumRedirectsToFollow (0))) + { + ... + } + @endcode */ - using OpenStreamProgressCallback = bool (void* context, int bytesSent, int totalBytes); + class JUCE_API InputStreamOptions + { + public: + /** Constructor. + + If parameterHandling is ParameterHandling::inPostData and the URL contains some + POST data to send set via one of its withPOSTData() methods, the URL parameters + will be transferred via the request body data. Otherwise the parameters will + be added to the URL address. + */ + explicit InputStreamOptions (ParameterHandling parameterHandling); + + //============================================================================== + /** A callback function to keep track of the operation's progress. + + This can be useful for lengthy POST operations, so that you can provide user feedback. + */ + InputStreamOptions withProgressCallback (std::function progressCallback) const; + + /** A string that will be appended onto the headers that are used for the request. + + It must be a valid set of HTML header directives, separated by newlines. + */ + InputStreamOptions withExtraHeaders (const String& extraHeaders) const; + + /** Specifies a timeout for the request in milliseconds. + + If 0, this will use whatever default setting the OS chooses. If a negative + number, it will be infinite. + */ + InputStreamOptions withConnectionTimeoutMs (int connectionTimeoutMs) const; + + /** If this is non-null, all the (key, value) pairs received as headers + in the response will be stored in this array. + */ + InputStreamOptions withResponseHeaders (StringPairArray* responseHeaders) const; + + /** If this is non-null, it will get set to the http status code, if one + is known, or 0 if a code isn't available. + */ + InputStreamOptions withStatusCode (int* statusCode) const; + + /** Specifies the number of redirects that will be followed before returning a response. + + N.B. This will be ignored on Android which follows up to 5 redirects. + */ + InputStreamOptions withNumRedirectsToFollow (int numRedirectsToFollow) const; + + /** Specifies which HTTP request to use. + + If this is not set, then this will be determined by the value of `doPostLikeRequest` + or the presence of POST data set via URL::withPOSTData(). + */ + InputStreamOptions withHttpRequestCmd (const String& httpRequestCmd) const; + + //============================================================================== + ParameterHandling getParameterHandling() const noexcept { return parameterHandling; } + std::function getProgressCallback() const noexcept { return progressCallback; } + String getExtraHeaders() const noexcept { return extraHeaders; } + int getConnectionTimeoutMs() const noexcept { return connectionTimeOutMs; } + StringPairArray* getResponseHeaders() const noexcept { return responseHeaders; } + int* getStatusCode() const noexcept { return statusCode; } + int getNumRedirectsToFollow() const noexcept { return numRedirectsToFollow; } + String getHttpRequestCmd() const noexcept { return httpRequestCmd; } + + private: + //============================================================================== + const ParameterHandling parameterHandling; + + std::function progressCallback = nullptr; + String extraHeaders; + int connectionTimeOutMs = 0; + StringPairArray* responseHeaders = nullptr; + int* statusCode = nullptr; + int numRedirectsToFollow = 5; + String httpRequestCmd; + }; /** Attempts to open a stream that can read from this URL. @@ -330,43 +415,11 @@ public: If the URL represents a local file, then this method simply returns a FileInputStream. - @param doPostLikeRequest if true, the parameters added to this class will be transferred - via the HTTP headers which is typical for POST requests. Otherwise - the parameters will be added to the URL address. Additionally, - if the parameter httpRequestCmd is not specified (or empty) then this - parameter will determine which HTTP request command will be used - (POST or GET). - @param progressCallback if this is not a nullptr, it lets you supply a callback function - to keep track of the operation's progress. This can be useful - for lengthy POST operations, so that you can provide user feedback. - @param progressCallbackContext if a callback is specified, this value will be passed to - the function - @param extraHeaders if not empty, this string is appended onto the headers that - are used for the request. It must therefore be a valid set of HTML - header directives, separated by newlines. - @param connectionTimeOutMs if 0, this will use whatever default setting the OS chooses. If - a negative number, it will be infinite. Otherwise it specifies a - time in milliseconds. - @param responseHeaders if this is non-null, all the (key, value) pairs received as headers - in the response will be stored in this array - @param statusCode if this is non-null, it will get set to the http status code, if one - is known, or 0 if a code isn't available - @param numRedirectsToFollow specifies the number of redirects that will be followed before - returning a response (ignored for Android which follows up to 5 redirects) - @param httpRequestCmd Specify which HTTP Request to use. If this is empty, then doPostRequest - will determine the HTTP request. - - @returns a valid input stream, or nullptr if there was an error trying to open it. - */ - std::unique_ptr createInputStream (bool doPostLikeRequest, - OpenStreamProgressCallback* progressCallback = nullptr, - void* progressCallbackContext = nullptr, - String extraHeaders = {}, - int connectionTimeOutMs = 0, - StringPairArray* responseHeaders = nullptr, - int* statusCode = nullptr, - int numRedirectsToFollow = 5, - String httpRequestCmd = {}) const; + @param options a set of options that will be used when opening the stream. + + @returns a valid input stream, or nullptr if there was an error trying to open it. + */ + std::unique_ptr createInputStream (const InputStreamOptions& options) const; /** Attempts to open an output stream to a URL for writing @@ -558,6 +611,25 @@ public: */ static URL createWithoutParsing (const String& url); + //============================================================================== + using OpenStreamProgressCallback = bool (void* context, int bytesSent, int totalBytes); + + /** This method has been deprecated. + + New code should use the method which takes an InputStreamOptions argument instead. + + @see InputStreamOptions + */ + std::unique_ptr createInputStream (bool doPostLikeRequest, + OpenStreamProgressCallback* progressCallback = nullptr, + void* progressCallbackContext = nullptr, + String extraHeaders = {}, + int connectionTimeOutMs = 0, + StringPairArray* responseHeaders = nullptr, + int* statusCode = nullptr, + int numRedirectsToFollow = 5, + String httpRequestCmd = {}) const; + private: //============================================================================== #if JUCE_IOS @@ -594,9 +666,10 @@ private: URL (const String&, int); void init(); void addParameter (const String&, const String&); - void createHeadersAndPostData (String&, MemoryBlock&) const; + void createHeadersAndPostData (String&, MemoryBlock&, bool) const; URL withUpload (Upload*) const; + static ParameterHandling toHandling (bool); static File fileFromFileSchemeURL (const URL&); String getDomainInternal (bool) const; diff --git a/modules/juce_core/network/juce_WebInputStream.cpp b/modules/juce_core/network/juce_WebInputStream.cpp index 38eda1502d..5d6d3a04bf 100644 --- a/modules/juce_core/network/juce_WebInputStream.cpp +++ b/modules/juce_core/network/juce_WebInputStream.cpp @@ -24,13 +24,12 @@ namespace juce { WebInputStream::WebInputStream (const URL& url, const bool usePost) - : pimpl (new Pimpl (*this, url, usePost)), hasCalledConnect (false) + : pimpl (std::make_unique (*this, url, usePost)) { } WebInputStream::~WebInputStream() { - delete pimpl; } WebInputStream& WebInputStream::withExtraHeaders (const String& extra) { pimpl->withExtraHeaders (extra); return *this; } @@ -60,28 +59,41 @@ bool WebInputStream::connect (Listener* listener) StringPairArray WebInputStream::parseHttpHeaders (const String& headerData) { StringPairArray headerPairs; - StringArray headerLines = StringArray::fromLines (headerData); + auto headerLines = StringArray::fromLines (headerData); // ignore the first line as this is the status line for (int i = 1; i < headerLines.size(); ++i) { - const String& headersEntry = headerLines[i]; + const auto& headersEntry = headerLines[i]; if (headersEntry.isNotEmpty()) { - const String key (headersEntry.upToFirstOccurrenceOf (": ", false, false)); - const String value (headersEntry.fromFirstOccurrenceOf (": ", false, false)); - const String previousValue (headerPairs [key]); - headerPairs.set (key, previousValue.isEmpty() ? value : (previousValue + "," + value)); + const auto key = headersEntry.upToFirstOccurrenceOf (": ", false, false); + + auto value = [&headersEntry, &headerPairs, &key] + { + const auto currentValue = headersEntry.fromFirstOccurrenceOf (": ", false, false); + const auto previousValue = headerPairs [key]; + + if (previousValue.isNotEmpty()) + return previousValue + "," + currentValue; + + return currentValue; + }(); + + headerPairs.set (key, value); } } return headerPairs; } -void WebInputStream::createHeadersAndPostData (const URL& aURL, String& headers, MemoryBlock& data) +void WebInputStream::createHeadersAndPostData (const URL& aURL, + String& headers, + MemoryBlock& data, + bool addParametersToBody) { - aURL.createHeadersAndPostData (headers, data); + aURL.createHeadersAndPostData (headers, data, addParametersToBody); } } // namespace juce diff --git a/modules/juce_core/network/juce_WebInputStream.h b/modules/juce_core/network/juce_WebInputStream.h index 126fcecf68..f7cf04292a 100644 --- a/modules/juce_core/network/juce_WebInputStream.h +++ b/modules/juce_core/network/juce_WebInputStream.h @@ -220,14 +220,14 @@ class JUCE_API WebInputStream : public InputStream bool setPosition (int64 wantedPos) override; private: - static void createHeadersAndPostData (const URL&, String&, MemoryBlock&); - static StringPairArray parseHttpHeaders (const String& headerData); + static void createHeadersAndPostData (const URL&, String&, MemoryBlock&, bool); + static StringPairArray parseHttpHeaders (const String&); class Pimpl; friend class Pimpl; - Pimpl* const pimpl; - bool hasCalledConnect; + std::unique_ptr pimpl; + bool hasCalledConnect = false; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream) }; From 4ea3053b1c26d6815e47deba08b3d2b5f6538c1f Mon Sep 17 00:00:00 2001 From: ed Date: Fri, 12 Mar 2021 16:23:05 +0000 Subject: [PATCH 3/9] Projucer: Updated URL::createInputStream() code to use URL::InputStreamOptions --- .../UserAccount/jucer_LicenseQueryThread.h | 12 +++++++----- .../Source/Utility/Helpers/jucer_VersionInfo.cpp | 13 +++++++++---- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/extras/Projucer/Source/Application/UserAccount/jucer_LicenseQueryThread.h b/extras/Projucer/Source/Application/UserAccount/jucer_LicenseQueryThread.h index 3d88291257..14c7ee9b0e 100644 --- a/extras/Projucer/Source/Application/UserAccount/jucer_LicenseQueryThread.h +++ b/extras/Projucer/Source/Application/UserAccount/jucer_LicenseQueryThread.h @@ -309,9 +309,9 @@ private: static ErrorMessageAndType runTask (std::unique_ptr accountEnquiryTask, LicenseState& state) { const ErrorMessageAndType cancelledError ("Cancelled.", ErrorType::cancelled); - const String endpointURL = "https://api.juce.com/api/v1"; + const String endpointURL ("https://api.juce.com/api/v1"); - auto url = URL (endpointURL + accountEnquiryTask->getEndpointURLSuffix()); + URL url (endpointURL + accountEnquiryTask->getEndpointURLSuffix()); auto isPOST = accountEnquiryTask->isPOSTLikeRequest(); @@ -322,9 +322,11 @@ private: return cancelledError; int statusCode = 0; - auto urlStream = url.createInputStream (isPOST, nullptr, nullptr, - accountEnquiryTask->getExtraHeaders(), - 5000, nullptr, &statusCode); + auto urlStream = url.createInputStream (URL::InputStreamOptions (isPOST ? URL::ParameterHandling::inPostData + : URL::ParameterHandling::inAddress) + .withExtraHeaders (accountEnquiryTask->getExtraHeaders()) + .withConnectionTimeoutMs (5000) + .withStatusCode (&statusCode)); if (urlStream == nullptr) return { "Failed to connect to the web server.", ErrorType::connectionError }; diff --git a/extras/Projucer/Source/Utility/Helpers/jucer_VersionInfo.cpp b/extras/Projucer/Source/Utility/Helpers/jucer_VersionInfo.cpp index cbc5e74f9e..2b8eb5e3c5 100644 --- a/extras/Projucer/Source/Utility/Helpers/jucer_VersionInfo.cpp +++ b/extras/Projucer/Source/Utility/Helpers/jucer_VersionInfo.cpp @@ -48,9 +48,12 @@ std::unique_ptr VersionInfo::createInputStreamForAsset (const Asset URL downloadUrl (asset.url); StringPairArray responseHeaders; - return std::unique_ptr (downloadUrl.createInputStream (false, nullptr, nullptr, - "Accept: application/octet-stream", - 5000, &responseHeaders, &statusCode, 1)); + return std::unique_ptr (downloadUrl.createInputStream (URL::InputStreamOptions (URL::ParameterHandling::inAddress) + .withExtraHeaders ("Accept: application/octet-stream") + .withConnectionTimeoutMs (5000) + .withResponseHeaders (&responseHeaders) + .withStatusCode (&statusCode) + .withNumRedirectsToFollow (1))); } bool VersionInfo::isNewerVersionThanCurrent() @@ -76,7 +79,9 @@ bool VersionInfo::isNewerVersionThanCurrent() std::unique_ptr VersionInfo::fetch (const String& endpoint) { URL latestVersionURL ("https://api.github.com/repos/juce-framework/JUCE/releases/" + endpoint); - std::unique_ptr inStream (latestVersionURL.createInputStream (false, nullptr, nullptr, {}, 5000)); + + std::unique_ptr inStream (latestVersionURL.createInputStream (URL::InputStreamOptions (URL::ParameterHandling::inAddress) + .withConnectionTimeoutMs (5000))); if (inStream == nullptr) return nullptr; From 0e599bea06c19c38ad3e957a37bcff1a38ccd804 Mon Sep 17 00:00:00 2001 From: Tom Poole Date: Fri, 12 Mar 2021 16:58:39 +0000 Subject: [PATCH 4/9] Re-saved all projects --- .../DemoRunner/Builds/Android/app/CMakeLists.txt | 8 ++++++++ .../Android/app/src/main/assets/DemoUtilities.h | 2 +- .../Android/app/src/main/assets/WavefrontObjParser.h | 4 ++-- .../Builds/VisualStudio2015/DemoRunner_App.vcxproj | 8 ++++++++ .../VisualStudio2015/DemoRunner_App.vcxproj.filters | 12 ++++++++++++ .../Builds/VisualStudio2017/DemoRunner_App.vcxproj | 8 ++++++++ .../VisualStudio2017/DemoRunner_App.vcxproj.filters | 12 ++++++++++++ .../Builds/VisualStudio2019/DemoRunner_App.vcxproj | 8 ++++++++ .../VisualStudio2019/DemoRunner_App.vcxproj.filters | 12 ++++++++++++ examples/DemoRunner/Builds/iOS/Info-App.plist | 2 ++ .../Builds/Android/app/CMakeLists.txt | 8 ++++++++ .../AudioPerformanceTest_App.vcxproj | 8 ++++++++ .../AudioPerformanceTest_App.vcxproj.filters | 12 ++++++++++++ .../Builds/Android/app/CMakeLists.txt | 8 ++++++++ .../VisualStudio2015/AudioPluginHost_App.vcxproj | 8 ++++++++ .../AudioPluginHost_App.vcxproj.filters | 12 ++++++++++++ .../VisualStudio2017/AudioPluginHost_App.vcxproj | 8 ++++++++ .../AudioPluginHost_App.vcxproj.filters | 12 ++++++++++++ .../VisualStudio2019/AudioPluginHost_App.vcxproj | 8 ++++++++ .../AudioPluginHost_App.vcxproj.filters | 12 ++++++++++++ .../BinaryBuilder_ConsoleApp.vcxproj | 3 +++ .../BinaryBuilder_ConsoleApp.vcxproj.filters | 3 +++ .../Builds/Android/app/CMakeLists.txt | 8 ++++++++ .../VisualStudio2019/NetworkGraphicsDemo_App.vcxproj | 8 ++++++++ .../NetworkGraphicsDemo_App.vcxproj.filters | 12 ++++++++++++ .../Builds/VisualStudio2015/Projucer_App.vcxproj | 4 ++++ .../VisualStudio2015/Projucer_App.vcxproj.filters | 6 ++++++ .../Builds/VisualStudio2017/Projucer_App.vcxproj | 4 ++++ .../VisualStudio2017/Projucer_App.vcxproj.filters | 6 ++++++ .../Builds/VisualStudio2019/Projucer_App.vcxproj | 4 ++++ .../VisualStudio2019/Projucer_App.vcxproj.filters | 6 ++++++ .../UnitTestRunner_ConsoleApp.vcxproj | 8 ++++++++ .../UnitTestRunner_ConsoleApp.vcxproj.filters | 12 ++++++++++++ .../UnitTestRunner_ConsoleApp.vcxproj | 8 ++++++++ .../UnitTestRunner_ConsoleApp.vcxproj.filters | 12 ++++++++++++ .../WindowsDLL_StaticLibrary.vcxproj | 8 ++++++++ .../WindowsDLL_StaticLibrary.vcxproj.filters | 12 ++++++++++++ 37 files changed, 293 insertions(+), 3 deletions(-) diff --git a/examples/DemoRunner/Builds/Android/app/CMakeLists.txt b/examples/DemoRunner/Builds/Android/app/CMakeLists.txt index b517aa27b9..0e436f0458 100644 --- a/examples/DemoRunner/Builds/Android/app/CMakeLists.txt +++ b/examples/DemoRunner/Builds/Android/app/CMakeLists.txt @@ -611,6 +611,8 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h" "../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp" "../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.h" + "../../../../../modules/juce_audio_processors/utilities/juce_PluginHostType.cpp" + "../../../../../modules/juce_audio_processors/utilities/juce_PluginHostType.h" "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp" "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h" "../../../../../modules/juce_audio_processors/juce_audio_processors.cpp" @@ -908,6 +910,7 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_core/native/juce_posix_IPAddress.h" "../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp" "../../../../../modules/juce_core/native/juce_posix_SharedCode.h" + "../../../../../modules/juce_core/native/juce_wasm_SystemStats.cpp" "../../../../../modules/juce_core/native/juce_win32_ComSmartPtr.h" "../../../../../modules/juce_core/native/juce_win32_Files.cpp" "../../../../../modules/juce_core/native/juce_win32_Network.cpp" @@ -1576,6 +1579,7 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h" "../../../../../modules/juce_gui_basics/native/juce_win32_DragAndDrop.cpp" "../../../../../modules/juce_gui_basics/native/juce_win32_FileChooser.cpp" + "../../../../../modules/juce_gui_basics/native/juce_win32_ScopedThreadDPIAwarenessSetter.h" "../../../../../modules/juce_gui_basics/native/juce_win32_Windowing.cpp" "../../../../../modules/juce_gui_basics/positioning/juce_MarkerList.cpp" "../../../../../modules/juce_gui_basics/positioning/juce_MarkerList.h" @@ -2393,6 +2397,8 @@ set_source_files_properties("../../../../../modules/juce_audio_processors/utilit set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.h" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_PluginHostType.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_PluginHostType.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/juce_audio_processors.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) @@ -2690,6 +2696,7 @@ set_source_files_properties("../../../../../modules/juce_core/native/juce_osx_Ob set_source_files_properties("../../../../../modules/juce_core/native/juce_posix_IPAddress.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_core/native/juce_posix_SharedCode.h" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_core/native/juce_wasm_SystemStats.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_core/native/juce_win32_ComSmartPtr.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_core/native/juce_win32_Files.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_core/native/juce_win32_Network.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) @@ -3358,6 +3365,7 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_win32_DragAndDrop.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_win32_FileChooser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_win32_ScopedThreadDPIAwarenessSetter.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_win32_Windowing.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_gui_basics/positioning/juce_MarkerList.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_gui_basics/positioning/juce_MarkerList.h" PROPERTIES HEADER_FILE_ONLY TRUE) diff --git a/examples/DemoRunner/Builds/Android/app/src/main/assets/DemoUtilities.h b/examples/DemoRunner/Builds/Android/app/src/main/assets/DemoUtilities.h index 2901ac4df1..96cf595a87 100644 --- a/examples/DemoRunner/Builds/Android/app/src/main/assets/DemoUtilities.h +++ b/examples/DemoRunner/Builds/Android/app/src/main/assets/DemoUtilities.h @@ -59,7 +59,7 @@ inline File getExamplesDirectory() noexcept return mo.toString(); #elif defined PIP_JUCE_EXAMPLES_DIRECTORY_STRING - return File { PIP_JUCE_EXAMPLES_DIRECTORY_STRING }; + return File { CharPointer_UTF8 { PIP_JUCE_EXAMPLES_DIRECTORY_STRING } }; #else auto currentFile = File::getSpecialLocation (File::SpecialLocationType::currentApplicationFile); auto exampleDir = currentFile.getParentDirectory().getChildFile ("examples"); diff --git a/examples/DemoRunner/Builds/Android/app/src/main/assets/WavefrontObjParser.h b/examples/DemoRunner/Builds/Android/app/src/main/assets/WavefrontObjParser.h index 72c1db4415..396c9c7a6b 100644 --- a/examples/DemoRunner/Builds/Android/app/src/main/assets/WavefrontObjParser.h +++ b/examples/DemoRunner/Builds/Android/app/src/main/assets/WavefrontObjParser.h @@ -143,7 +143,7 @@ private: static float parseFloat (String::CharPointerType& t) { - t = t.findEndOfWhitespace(); + t.incrementToEndOfWhitespace(); return (float) CharacterFunctions::readDoubleValue (t); } @@ -211,7 +211,7 @@ private: { TripleIndex i; - t = t.findEndOfWhitespace(); + t.incrementToEndOfWhitespace(); i.vertexIndex = t.getIntValue32() - 1; t = findEndOfFaceToken (t); diff --git a/examples/DemoRunner/Builds/VisualStudio2015/DemoRunner_App.vcxproj b/examples/DemoRunner/Builds/VisualStudio2015/DemoRunner_App.vcxproj index 81be88b2a9..42d4eb6347 100644 --- a/examples/DemoRunner/Builds/VisualStudio2015/DemoRunner_App.vcxproj +++ b/examples/DemoRunner/Builds/VisualStudio2015/DemoRunner_App.vcxproj @@ -804,6 +804,9 @@ true + + true + true @@ -1191,6 +1194,9 @@ true + + true + true @@ -2812,6 +2818,7 @@ + @@ -3288,6 +3295,7 @@ + diff --git a/examples/DemoRunner/Builds/VisualStudio2015/DemoRunner_App.vcxproj.filters b/examples/DemoRunner/Builds/VisualStudio2015/DemoRunner_App.vcxproj.filters index 9310341a14..91f4733f31 100644 --- a/examples/DemoRunner/Builds/VisualStudio2015/DemoRunner_App.vcxproj.filters +++ b/examples/DemoRunner/Builds/VisualStudio2015/DemoRunner_App.vcxproj.filters @@ -1258,6 +1258,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -1678,6 +1681,9 @@ JUCE Modules\juce_core\native + + JUCE Modules\juce_core\native + JUCE Modules\juce_core\native @@ -4086,6 +4092,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -5514,6 +5523,9 @@ JUCE Modules\juce_gui_basics\native + + JUCE Modules\juce_gui_basics\native + JUCE Modules\juce_gui_basics\positioning diff --git a/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj b/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj index 4472b57236..70a185fa2f 100644 --- a/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj +++ b/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj @@ -804,6 +804,9 @@ true + + true + true @@ -1191,6 +1194,9 @@ true + + true + true @@ -2812,6 +2818,7 @@ + @@ -3288,6 +3295,7 @@ + diff --git a/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj.filters b/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj.filters index 62774310f5..093a0e4729 100644 --- a/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj.filters +++ b/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj.filters @@ -1258,6 +1258,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -1678,6 +1681,9 @@ JUCE Modules\juce_core\native + + JUCE Modules\juce_core\native + JUCE Modules\juce_core\native @@ -4086,6 +4092,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -5514,6 +5523,9 @@ JUCE Modules\juce_gui_basics\native + + JUCE Modules\juce_gui_basics\native + JUCE Modules\juce_gui_basics\positioning diff --git a/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj b/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj index cba3bf54d6..a6d952cfc5 100644 --- a/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj +++ b/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj @@ -804,6 +804,9 @@ true + + true + true @@ -1191,6 +1194,9 @@ true + + true + true @@ -2812,6 +2818,7 @@ + @@ -3288,6 +3295,7 @@ + diff --git a/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj.filters b/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj.filters index 4e0d0b75ca..8ffab8e72f 100644 --- a/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj.filters +++ b/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj.filters @@ -1258,6 +1258,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -1678,6 +1681,9 @@ JUCE Modules\juce_core\native + + JUCE Modules\juce_core\native + JUCE Modules\juce_core\native @@ -4086,6 +4092,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -5514,6 +5523,9 @@ JUCE Modules\juce_gui_basics\native + + JUCE Modules\juce_gui_basics\native + JUCE Modules\juce_gui_basics\positioning diff --git a/examples/DemoRunner/Builds/iOS/Info-App.plist b/examples/DemoRunner/Builds/iOS/Info-App.plist index 5e382c20f9..7b90f76664 100644 --- a/examples/DemoRunner/Builds/iOS/Info-App.plist +++ b/examples/DemoRunner/Builds/iOS/Info-App.plist @@ -41,6 +41,8 @@ UISupportsDocumentBrowser + UIRequiresFullScreen + UISupportedInterfaceOrientations UIInterfaceOrientationLandscapeLeft diff --git a/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt b/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt index 500841ffb1..f2ed2bd855 100644 --- a/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt +++ b/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt @@ -592,6 +592,8 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h" "../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp" "../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.h" + "../../../../../modules/juce_audio_processors/utilities/juce_PluginHostType.cpp" + "../../../../../modules/juce_audio_processors/utilities/juce_PluginHostType.h" "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp" "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h" "../../../../../modules/juce_audio_processors/juce_audio_processors.cpp" @@ -747,6 +749,7 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_core/native/juce_posix_IPAddress.h" "../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp" "../../../../../modules/juce_core/native/juce_posix_SharedCode.h" + "../../../../../modules/juce_core/native/juce_wasm_SystemStats.cpp" "../../../../../modules/juce_core/native/juce_win32_ComSmartPtr.h" "../../../../../modules/juce_core/native/juce_win32_Files.cpp" "../../../../../modules/juce_core/native/juce_win32_Network.cpp" @@ -1316,6 +1319,7 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h" "../../../../../modules/juce_gui_basics/native/juce_win32_DragAndDrop.cpp" "../../../../../modules/juce_gui_basics/native/juce_win32_FileChooser.cpp" + "../../../../../modules/juce_gui_basics/native/juce_win32_ScopedThreadDPIAwarenessSetter.h" "../../../../../modules/juce_gui_basics/native/juce_win32_Windowing.cpp" "../../../../../modules/juce_gui_basics/positioning/juce_MarkerList.cpp" "../../../../../modules/juce_gui_basics/positioning/juce_MarkerList.h" @@ -2031,6 +2035,8 @@ set_source_files_properties("../../../../../modules/juce_audio_processors/utilit set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.h" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_PluginHostType.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_PluginHostType.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/juce_audio_processors.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) @@ -2186,6 +2192,7 @@ set_source_files_properties("../../../../../modules/juce_core/native/juce_osx_Ob set_source_files_properties("../../../../../modules/juce_core/native/juce_posix_IPAddress.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_core/native/juce_posix_SharedCode.h" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_core/native/juce_wasm_SystemStats.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_core/native/juce_win32_ComSmartPtr.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_core/native/juce_win32_Files.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_core/native/juce_win32_Network.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) @@ -2755,6 +2762,7 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_win32_DragAndDrop.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_win32_FileChooser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_win32_ScopedThreadDPIAwarenessSetter.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_win32_Windowing.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_gui_basics/positioning/juce_MarkerList.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_gui_basics/positioning/juce_MarkerList.h" PROPERTIES HEADER_FILE_ONLY TRUE) diff --git a/extras/AudioPerformanceTest/Builds/VisualStudio2019/AudioPerformanceTest_App.vcxproj b/extras/AudioPerformanceTest/Builds/VisualStudio2019/AudioPerformanceTest_App.vcxproj index d63ea29585..53bc243d8e 100644 --- a/extras/AudioPerformanceTest/Builds/VisualStudio2019/AudioPerformanceTest_App.vcxproj +++ b/extras/AudioPerformanceTest/Builds/VisualStudio2019/AudioPerformanceTest_App.vcxproj @@ -785,6 +785,9 @@ true + + true + true @@ -977,6 +980,9 @@ true + + true + true @@ -2364,6 +2370,7 @@ + @@ -2713,6 +2720,7 @@ + diff --git a/extras/AudioPerformanceTest/Builds/VisualStudio2019/AudioPerformanceTest_App.vcxproj.filters b/extras/AudioPerformanceTest/Builds/VisualStudio2019/AudioPerformanceTest_App.vcxproj.filters index 37e04f009d..54dba429b7 100644 --- a/extras/AudioPerformanceTest/Builds/VisualStudio2019/AudioPerformanceTest_App.vcxproj.filters +++ b/extras/AudioPerformanceTest/Builds/VisualStudio2019/AudioPerformanceTest_App.vcxproj.filters @@ -1087,6 +1087,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -1312,6 +1315,9 @@ JUCE Modules\juce_core\native + + JUCE Modules\juce_core\native + JUCE Modules\juce_core\native @@ -3435,6 +3441,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -4482,6 +4491,9 @@ JUCE Modules\juce_gui_basics\native + + JUCE Modules\juce_gui_basics\native + JUCE Modules\juce_gui_basics\positioning diff --git a/extras/AudioPluginHost/Builds/Android/app/CMakeLists.txt b/extras/AudioPluginHost/Builds/Android/app/CMakeLists.txt index e837ae56a6..4ceca43894 100644 --- a/extras/AudioPluginHost/Builds/Android/app/CMakeLists.txt +++ b/extras/AudioPluginHost/Builds/Android/app/CMakeLists.txt @@ -609,6 +609,8 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h" "../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp" "../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.h" + "../../../../../modules/juce_audio_processors/utilities/juce_PluginHostType.cpp" + "../../../../../modules/juce_audio_processors/utilities/juce_PluginHostType.h" "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp" "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h" "../../../../../modules/juce_audio_processors/juce_audio_processors.cpp" @@ -764,6 +766,7 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_core/native/juce_posix_IPAddress.h" "../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp" "../../../../../modules/juce_core/native/juce_posix_SharedCode.h" + "../../../../../modules/juce_core/native/juce_wasm_SystemStats.cpp" "../../../../../modules/juce_core/native/juce_win32_ComSmartPtr.h" "../../../../../modules/juce_core/native/juce_win32_Files.cpp" "../../../../../modules/juce_core/native/juce_win32_Network.cpp" @@ -1432,6 +1435,7 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h" "../../../../../modules/juce_gui_basics/native/juce_win32_DragAndDrop.cpp" "../../../../../modules/juce_gui_basics/native/juce_win32_FileChooser.cpp" + "../../../../../modules/juce_gui_basics/native/juce_win32_ScopedThreadDPIAwarenessSetter.h" "../../../../../modules/juce_gui_basics/native/juce_win32_Windowing.cpp" "../../../../../modules/juce_gui_basics/positioning/juce_MarkerList.cpp" "../../../../../modules/juce_gui_basics/positioning/juce_MarkerList.h" @@ -2191,6 +2195,8 @@ set_source_files_properties("../../../../../modules/juce_audio_processors/utilit set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.h" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_PluginHostType.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_PluginHostType.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/juce_audio_processors.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) @@ -2346,6 +2352,7 @@ set_source_files_properties("../../../../../modules/juce_core/native/juce_osx_Ob set_source_files_properties("../../../../../modules/juce_core/native/juce_posix_IPAddress.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_core/native/juce_posix_SharedCode.h" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_core/native/juce_wasm_SystemStats.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_core/native/juce_win32_ComSmartPtr.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_core/native/juce_win32_Files.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_core/native/juce_win32_Network.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) @@ -3014,6 +3021,7 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_win32_DragAndDrop.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_win32_FileChooser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_win32_ScopedThreadDPIAwarenessSetter.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_win32_Windowing.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_gui_basics/positioning/juce_MarkerList.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_gui_basics/positioning/juce_MarkerList.h" PROPERTIES HEADER_FILE_ONLY TRUE) diff --git a/extras/AudioPluginHost/Builds/VisualStudio2015/AudioPluginHost_App.vcxproj b/extras/AudioPluginHost/Builds/VisualStudio2015/AudioPluginHost_App.vcxproj index d33b4862c0..0d97c9df3b 100644 --- a/extras/AudioPluginHost/Builds/VisualStudio2015/AudioPluginHost_App.vcxproj +++ b/extras/AudioPluginHost/Builds/VisualStudio2015/AudioPluginHost_App.vcxproj @@ -792,6 +792,9 @@ true + + true + true @@ -984,6 +987,9 @@ true + + true + true @@ -2539,6 +2545,7 @@ + @@ -2942,6 +2949,7 @@ + diff --git a/extras/AudioPluginHost/Builds/VisualStudio2015/AudioPluginHost_App.vcxproj.filters b/extras/AudioPluginHost/Builds/VisualStudio2015/AudioPluginHost_App.vcxproj.filters index 43d5b8eaec..86b0b58b2a 100644 --- a/extras/AudioPluginHost/Builds/VisualStudio2015/AudioPluginHost_App.vcxproj.filters +++ b/extras/AudioPluginHost/Builds/VisualStudio2015/AudioPluginHost_App.vcxproj.filters @@ -1156,6 +1156,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -1381,6 +1384,9 @@ JUCE Modules\juce_core\native + + JUCE Modules\juce_core\native + JUCE Modules\juce_core\native @@ -3699,6 +3705,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -4908,6 +4917,9 @@ JUCE Modules\juce_gui_basics\native + + JUCE Modules\juce_gui_basics\native + JUCE Modules\juce_gui_basics\positioning diff --git a/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj b/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj index df2b66ee56..6b7f5f6f70 100644 --- a/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj +++ b/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj @@ -792,6 +792,9 @@ true + + true + true @@ -984,6 +987,9 @@ true + + true + true @@ -2539,6 +2545,7 @@ + @@ -2942,6 +2949,7 @@ + diff --git a/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj.filters b/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj.filters index 767740f418..0b7d1a1733 100644 --- a/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj.filters +++ b/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj.filters @@ -1156,6 +1156,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -1381,6 +1384,9 @@ JUCE Modules\juce_core\native + + JUCE Modules\juce_core\native + JUCE Modules\juce_core\native @@ -3699,6 +3705,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -4908,6 +4917,9 @@ JUCE Modules\juce_gui_basics\native + + JUCE Modules\juce_gui_basics\native + JUCE Modules\juce_gui_basics\positioning diff --git a/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj b/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj index 4093313598..06f21e3e44 100644 --- a/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj +++ b/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj @@ -792,6 +792,9 @@ true + + true + true @@ -984,6 +987,9 @@ true + + true + true @@ -2539,6 +2545,7 @@ + @@ -2942,6 +2949,7 @@ + diff --git a/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj.filters b/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj.filters index 4eefc221fb..af9418dacb 100644 --- a/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj.filters +++ b/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj.filters @@ -1156,6 +1156,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -1381,6 +1384,9 @@ JUCE Modules\juce_core\native + + JUCE Modules\juce_core\native + JUCE Modules\juce_core\native @@ -3699,6 +3705,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -4908,6 +4917,9 @@ JUCE Modules\juce_gui_basics\native + + JUCE Modules\juce_gui_basics\native + JUCE Modules\juce_gui_basics\positioning diff --git a/extras/BinaryBuilder/Builds/VisualStudio2019/BinaryBuilder_ConsoleApp.vcxproj b/extras/BinaryBuilder/Builds/VisualStudio2019/BinaryBuilder_ConsoleApp.vcxproj index f646087ea8..f2f2193190 100644 --- a/extras/BinaryBuilder/Builds/VisualStudio2019/BinaryBuilder_ConsoleApp.vcxproj +++ b/extras/BinaryBuilder/Builds/VisualStudio2019/BinaryBuilder_ConsoleApp.vcxproj @@ -278,6 +278,9 @@ true + + true + true diff --git a/extras/BinaryBuilder/Builds/VisualStudio2019/BinaryBuilder_ConsoleApp.vcxproj.filters b/extras/BinaryBuilder/Builds/VisualStudio2019/BinaryBuilder_ConsoleApp.vcxproj.filters index 57ad38db1d..63ea3d1dfe 100644 --- a/extras/BinaryBuilder/Builds/VisualStudio2019/BinaryBuilder_ConsoleApp.vcxproj.filters +++ b/extras/BinaryBuilder/Builds/VisualStudio2019/BinaryBuilder_ConsoleApp.vcxproj.filters @@ -232,6 +232,9 @@ JUCE Modules\juce_core\native + + JUCE Modules\juce_core\native + JUCE Modules\juce_core\native diff --git a/extras/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt b/extras/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt index 86b95620d3..60a91c7158 100644 --- a/extras/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt +++ b/extras/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt @@ -596,6 +596,8 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h" "../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp" "../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.h" + "../../../../../modules/juce_audio_processors/utilities/juce_PluginHostType.cpp" + "../../../../../modules/juce_audio_processors/utilities/juce_PluginHostType.h" "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp" "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h" "../../../../../modules/juce_audio_processors/juce_audio_processors.cpp" @@ -751,6 +753,7 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_core/native/juce_posix_IPAddress.h" "../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp" "../../../../../modules/juce_core/native/juce_posix_SharedCode.h" + "../../../../../modules/juce_core/native/juce_wasm_SystemStats.cpp" "../../../../../modules/juce_core/native/juce_win32_ComSmartPtr.h" "../../../../../modules/juce_core/native/juce_win32_Files.cpp" "../../../../../modules/juce_core/native/juce_win32_Network.cpp" @@ -1335,6 +1338,7 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h" "../../../../../modules/juce_gui_basics/native/juce_win32_DragAndDrop.cpp" "../../../../../modules/juce_gui_basics/native/juce_win32_FileChooser.cpp" + "../../../../../modules/juce_gui_basics/native/juce_win32_ScopedThreadDPIAwarenessSetter.h" "../../../../../modules/juce_gui_basics/native/juce_win32_Windowing.cpp" "../../../../../modules/juce_gui_basics/positioning/juce_MarkerList.cpp" "../../../../../modules/juce_gui_basics/positioning/juce_MarkerList.h" @@ -2110,6 +2114,8 @@ set_source_files_properties("../../../../../modules/juce_audio_processors/utilit set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.h" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_PluginHostType.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_PluginHostType.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/juce_audio_processors.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) @@ -2265,6 +2271,7 @@ set_source_files_properties("../../../../../modules/juce_core/native/juce_osx_Ob set_source_files_properties("../../../../../modules/juce_core/native/juce_posix_IPAddress.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_core/native/juce_posix_SharedCode.h" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_core/native/juce_wasm_SystemStats.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_core/native/juce_win32_ComSmartPtr.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_core/native/juce_win32_Files.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_core/native/juce_win32_Network.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) @@ -2849,6 +2856,7 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_win32_DragAndDrop.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_win32_FileChooser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_win32_ScopedThreadDPIAwarenessSetter.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_win32_Windowing.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_gui_basics/positioning/juce_MarkerList.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_gui_basics/positioning/juce_MarkerList.h" PROPERTIES HEADER_FILE_ONLY TRUE) diff --git a/extras/NetworkGraphicsDemo/Builds/VisualStudio2019/NetworkGraphicsDemo_App.vcxproj b/extras/NetworkGraphicsDemo/Builds/VisualStudio2019/NetworkGraphicsDemo_App.vcxproj index ac4c11e106..a20959d6ea 100644 --- a/extras/NetworkGraphicsDemo/Builds/VisualStudio2019/NetworkGraphicsDemo_App.vcxproj +++ b/extras/NetworkGraphicsDemo/Builds/VisualStudio2019/NetworkGraphicsDemo_App.vcxproj @@ -785,6 +785,9 @@ true + + true + true @@ -977,6 +980,9 @@ true + + true + true @@ -2449,6 +2455,7 @@ + @@ -2805,6 +2812,7 @@ + diff --git a/extras/NetworkGraphicsDemo/Builds/VisualStudio2019/NetworkGraphicsDemo_App.vcxproj.filters b/extras/NetworkGraphicsDemo/Builds/VisualStudio2019/NetworkGraphicsDemo_App.vcxproj.filters index 51a8abb03d..a4d91089b1 100644 --- a/extras/NetworkGraphicsDemo/Builds/VisualStudio2019/NetworkGraphicsDemo_App.vcxproj.filters +++ b/extras/NetworkGraphicsDemo/Builds/VisualStudio2019/NetworkGraphicsDemo_App.vcxproj.filters @@ -1117,6 +1117,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -1342,6 +1345,9 @@ JUCE Modules\juce_core\native + + JUCE Modules\juce_core\native + JUCE Modules\juce_core\native @@ -3570,6 +3576,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -4638,6 +4647,9 @@ JUCE Modules\juce_gui_basics\native + + JUCE Modules\juce_gui_basics\native + JUCE Modules\juce_gui_basics\positioning diff --git a/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj b/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj index 435a780714..2047477d4a 100644 --- a/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj +++ b/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj @@ -405,6 +405,9 @@ true + + true + true @@ -2019,6 +2022,7 @@ + diff --git a/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters index f3263ed4bc..016406508f 100644 --- a/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters +++ b/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters @@ -700,6 +700,9 @@ JUCE Modules\juce_core\native + + JUCE Modules\juce_core\native + JUCE Modules\juce_core\native @@ -3465,6 +3468,9 @@ JUCE Modules\juce_gui_basics\native + + JUCE Modules\juce_gui_basics\native + JUCE Modules\juce_gui_basics\positioning diff --git a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj index 9cb7fd4217..1cd43ee1a0 100644 --- a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj +++ b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj @@ -405,6 +405,9 @@ true + + true + true @@ -2019,6 +2022,7 @@ + diff --git a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters index bab64ae06f..573ea91289 100644 --- a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters +++ b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters @@ -700,6 +700,9 @@ JUCE Modules\juce_core\native + + JUCE Modules\juce_core\native + JUCE Modules\juce_core\native @@ -3465,6 +3468,9 @@ JUCE Modules\juce_gui_basics\native + + JUCE Modules\juce_gui_basics\native + JUCE Modules\juce_gui_basics\positioning diff --git a/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj b/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj index 6874ef15f1..03794a6d4f 100644 --- a/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj +++ b/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj @@ -405,6 +405,9 @@ true + + true + true @@ -2019,6 +2022,7 @@ + diff --git a/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj.filters index 13a8a68509..d33dac599b 100644 --- a/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj.filters +++ b/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj.filters @@ -700,6 +700,9 @@ JUCE Modules\juce_core\native + + JUCE Modules\juce_core\native + JUCE Modules\juce_core\native @@ -3465,6 +3468,9 @@ JUCE Modules\juce_gui_basics\native + + JUCE Modules\juce_gui_basics\native + JUCE Modules\juce_gui_basics\positioning diff --git a/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj b/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj index e87d7fdc6a..25333783fd 100644 --- a/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj +++ b/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj @@ -801,6 +801,9 @@ true + + true + true @@ -1047,6 +1050,9 @@ true + + true + true @@ -2662,6 +2668,7 @@ + @@ -3090,6 +3097,7 @@ + diff --git a/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj.filters b/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj.filters index e68a1b4a03..d5abb36af3 100644 --- a/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj.filters +++ b/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj.filters @@ -1207,6 +1207,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -1486,6 +1489,9 @@ JUCE Modules\juce_core\native + + JUCE Modules\juce_core\native + JUCE Modules\juce_core\native @@ -3876,6 +3882,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -5160,6 +5169,9 @@ JUCE Modules\juce_gui_basics\native + + JUCE Modules\juce_gui_basics\native + JUCE Modules\juce_gui_basics\positioning diff --git a/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj b/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj index 6de8bb6cda..ba536f9190 100644 --- a/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj +++ b/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj @@ -801,6 +801,9 @@ true + + true + true @@ -1047,6 +1050,9 @@ true + + true + true @@ -2662,6 +2668,7 @@ + @@ -3090,6 +3097,7 @@ + diff --git a/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj.filters b/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj.filters index 256ff7f966..a5ea5989e4 100644 --- a/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj.filters +++ b/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj.filters @@ -1207,6 +1207,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -1486,6 +1489,9 @@ JUCE Modules\juce_core\native + + JUCE Modules\juce_core\native + JUCE Modules\juce_core\native @@ -3876,6 +3882,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -5160,6 +5169,9 @@ JUCE Modules\juce_gui_basics\native + + JUCE Modules\juce_gui_basics\native + JUCE Modules\juce_gui_basics\positioning diff --git a/extras/WindowsDLL/Builds/VisualStudio2019/WindowsDLL_StaticLibrary.vcxproj b/extras/WindowsDLL/Builds/VisualStudio2019/WindowsDLL_StaticLibrary.vcxproj index 82cbde056a..228f387ff2 100644 --- a/extras/WindowsDLL/Builds/VisualStudio2019/WindowsDLL_StaticLibrary.vcxproj +++ b/extras/WindowsDLL/Builds/VisualStudio2019/WindowsDLL_StaticLibrary.vcxproj @@ -784,6 +784,9 @@ true + + true + true @@ -976,6 +979,9 @@ true + + true + true @@ -2425,6 +2431,7 @@ + @@ -2781,6 +2788,7 @@ + diff --git a/extras/WindowsDLL/Builds/VisualStudio2019/WindowsDLL_StaticLibrary.vcxproj.filters b/extras/WindowsDLL/Builds/VisualStudio2019/WindowsDLL_StaticLibrary.vcxproj.filters index 74ed3bb9e2..c68416e0ff 100644 --- a/extras/WindowsDLL/Builds/VisualStudio2019/WindowsDLL_StaticLibrary.vcxproj.filters +++ b/extras/WindowsDLL/Builds/VisualStudio2019/WindowsDLL_StaticLibrary.vcxproj.filters @@ -1114,6 +1114,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -1339,6 +1342,9 @@ JUCE Modules\juce_core\native + + JUCE Modules\juce_core\native + JUCE Modules\juce_core\native @@ -3537,6 +3543,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -4605,6 +4614,9 @@ JUCE Modules\juce_gui_basics\native + + JUCE Modules\juce_gui_basics\native + JUCE Modules\juce_gui_basics\positioning From 717774b6483d1a231eabc1fef2bc316721d429f5 Mon Sep 17 00:00:00 2001 From: Tom Poole Date: Fri, 12 Mar 2021 18:02:23 +0000 Subject: [PATCH 5/9] VST3: Fixed the plug-in bundle path on aarch64 --- extras/Build/CMake/juce_runtime_arch_detection.cpp | 2 +- extras/Projucer/JuceLibraryCode/BinaryData.cpp | 4 ++-- extras/Projucer/JuceLibraryCode/BinaryData.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/extras/Build/CMake/juce_runtime_arch_detection.cpp b/extras/Build/CMake/juce_runtime_arch_detection.cpp index 7aea5fbbfe..900f13564f 100644 --- a/extras/Build/CMake/juce_runtime_arch_detection.cpp +++ b/extras/Build/CMake/juce_runtime_arch_detection.cpp @@ -1,7 +1,7 @@ #if defined(__arm__) || defined(__TARGET_ARCH_ARM) || defined(_M_ARM) || defined(_M_ARM64) || defined(__aarch64__) || defined(__ARM64__) #if defined(_M_ARM64) || defined(__aarch64__) || defined(__ARM64__) - #error JUCE_ARCH arm64 + #error JUCE_ARCH aarch64 #elif (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM == 8) || defined(__ARMv8__) || defined(__ARMv8_A__) #error JUCE_ARCH armv8l #elif (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM == 7) || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) || defined(_ARM_ARCH_7) || defined(__CORE_CORTEXA__) diff --git a/extras/Projucer/JuceLibraryCode/BinaryData.cpp b/extras/Projucer/JuceLibraryCode/BinaryData.cpp index 9cf3def10d..37466599ad 100644 --- a/extras/Projucer/JuceLibraryCode/BinaryData.cpp +++ b/extras/Projucer/JuceLibraryCode/BinaryData.cpp @@ -7488,7 +7488,7 @@ static const unsigned char temp_binary_data_61[] = "#if defined(__arm__) || defined(__TARGET_ARCH_ARM) || defined(_M_ARM) || defined(_M_ARM64) || defined(__aarch64__) || defined(__ARM64__)\r\n" "\r\n" " #if defined(_M_ARM64) || defined(__aarch64__) || defined(__ARM64__)\r\n" -" #error JUCE_ARCH arm64\r\n" +" #error JUCE_ARCH aarch64\r\n" " #elif (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM == 8) || defined(__ARMv8__) || defined(__ARMv8_A__)\r\n" " #error JUCE_ARCH armv8l\r\n" " #elif (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM == 7) || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) || defined(_ARM_ARCH_7) || defined(__CORE_CORTEX" @@ -7619,7 +7619,7 @@ const char* getNamedResource (const char* resourceNameUTF8, int& numBytes) case 0x0b16e320: numBytes = 517; return jucer_PIPTemplate_h; case 0x763d39dc: numBytes = 1050; return colourscheme_dark_xml; case 0xe8b08520: numBytes = 1050; return colourscheme_light_xml; - case 0x7c03d519: numBytes = 2127; return juce_runtime_arch_detection_cpp; + case 0x7c03d519: numBytes = 2129; return juce_runtime_arch_detection_cpp; default: break; } diff --git a/extras/Projucer/JuceLibraryCode/BinaryData.h b/extras/Projucer/JuceLibraryCode/BinaryData.h index dc4ddc8349..dfef6668ea 100644 --- a/extras/Projucer/JuceLibraryCode/BinaryData.h +++ b/extras/Projucer/JuceLibraryCode/BinaryData.h @@ -192,7 +192,7 @@ namespace BinaryData const int colourscheme_light_xmlSize = 1050; extern const char* juce_runtime_arch_detection_cpp; - const int juce_runtime_arch_detection_cppSize = 2127; + const int juce_runtime_arch_detection_cppSize = 2129; // Number of elements in the namedResourceList and originalFileNames arrays. const int namedResourceListSize = 62; From df06a471c0726a471dfdc1edf2db051b2e78e657 Mon Sep 17 00:00:00 2001 From: reuk Date: Thu, 11 Mar 2021 19:31:54 +0000 Subject: [PATCH 6/9] AudioProcessorPlayer: Support a greater variety of IO configurations Previously, the AudioProcessorPlayer would always match the AudioProcessor's bus configuration to the requested bus configuration, even if the processor did not explicitly support the requested configuration. Now, if the requested configuration has one or fewer input channels, the AudioProcessorPlayer will attempt to find a multi-input channel layout for which `checkBusesLayoutSupported` returns true, and will use such a layout if it exists. Otherwise, as a last resort, it will fall back to using the channel layout requested by the AudioProcessorPlayer. If the AudioProcessorPlayer has no input channels, but the wrapped processor is initialised with multiple input channels, each of these inputs will be fed with silence. If the AudioProcessorPlayer has a single input channel, but the wrapped processor is initialised with multiple input channels, each input channel will be fed with a copy of the AudioProcessorPlayer's mono input. --- .../Standalone/juce_StandaloneFilterWindow.h | 2 +- .../players/juce_AudioProcessorPlayer.cpp | 287 +++++++++++++++--- .../players/juce_AudioProcessorPlayer.h | 25 +- 3 files changed, 263 insertions(+), 51 deletions(-) diff --git a/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h b/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h index d78740f94c..3ec1bed66d 100644 --- a/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h +++ b/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h @@ -113,7 +113,7 @@ public: startTimer (500); } - virtual ~StandalonePluginHolder() override + ~StandalonePluginHolder() override { stopTimer(); diff --git a/modules/juce_audio_utils/players/juce_AudioProcessorPlayer.cpp b/modules/juce_audio_utils/players/juce_AudioProcessorPlayer.cpp index ec31b15f07..c6e27dd628 100644 --- a/modules/juce_audio_utils/players/juce_AudioProcessorPlayer.cpp +++ b/modules/juce_audio_utils/players/juce_AudioProcessorPlayer.cpp @@ -26,6 +26,102 @@ namespace juce { +template +struct ChannelInfo +{ + ChannelInfo() = default; + ChannelInfo (Value** dataIn, int numChannelsIn) + : data (dataIn), numChannels (numChannelsIn) {} + + Value** data = nullptr; + int numChannels = 0; +}; + +/** Sets up `channels` so that it contains channel pointers suitable for passing to + an AudioProcessor's processBlock. + + On return, `channels` will hold `max (processorIns, processorOuts)` entries. + The first `processorIns` entries will point to buffers holding input data. + Any entries after the first `processorIns` entries will point to zeroed buffers. + + In the case that the system only provides a single input channel, but the processor + has been initialised with multiple input channels, the system input will be copied + to all processor inputs. + + In the case that the system provides no input channels, but the processor has + been initialise with multiple input channels, the processor's input channels will + all be zeroed. + + @param ins the system inputs. + @param outs the system outputs. + @param numSamples the number of samples in the system buffers. + @param processorIns the number of input channels requested by the processor. + @param processorOuts the number of output channels requested by the processor. + @param tempBuffer temporary storage for inputs that don't have a corresponding output. + @param channels holds pointers to each of the processor's audio channels. +*/ +static void initialiseIoBuffers (ChannelInfo ins, + ChannelInfo outs, + const int numSamples, + int processorIns, + int processorOuts, + AudioBuffer& tempBuffer, + std::vector& channels) +{ + jassert ((int) channels.size() >= jmax (processorIns, processorOuts)); + + size_t totalNumChans = 0; + const auto numBytes = (size_t) numSamples * sizeof (float); + + const auto prepareInputChannel = [&] (int index) + { + if (ins.numChannels == 0) + zeromem (channels[totalNumChans], numBytes); + else + memcpy (channels[totalNumChans], ins.data[index % ins.numChannels], numBytes); + }; + + if (processorIns > processorOuts) + { + // If there aren't enough output channels for the number of + // inputs, we need to use some temporary extra ones (can't + // use the input data in case it gets written to). + jassert (tempBuffer.getNumChannels() >= processorIns - processorOuts); + jassert (tempBuffer.getNumSamples() >= numSamples); + + for (int i = 0; i < processorOuts; ++i) + { + channels[totalNumChans] = outs.data[i]; + prepareInputChannel (i); + ++totalNumChans; + } + + for (auto i = processorOuts; i < processorIns; ++i) + { + channels[totalNumChans] = tempBuffer.getWritePointer (i - outs.numChannels); + prepareInputChannel (i); + ++totalNumChans; + } + } + else + { + for (int i = 0; i < processorIns; ++i) + { + channels[totalNumChans] = outs.data[i]; + prepareInputChannel (i); + ++totalNumChans; + } + + for (auto i = processorIns; i < processorOuts; ++i) + { + channels[totalNumChans] = outs.data[i]; + zeromem (channels[totalNumChans], (size_t) numSamples * sizeof (float)); + ++totalNumChans; + } + } +} + +//============================================================================== AudioProcessorPlayer::AudioProcessorPlayer (bool doDoublePrecisionProcessing) : isDoublePrecision (doDoublePrecisionProcessing) { @@ -37,28 +133,64 @@ AudioProcessorPlayer::~AudioProcessorPlayer() } //============================================================================== +AudioProcessorPlayer::NumChannels AudioProcessorPlayer::findMostSuitableLayout (const AudioProcessor& proc) const +{ + std::vector layouts { deviceChannels }; + + if (deviceChannels.ins == 0 || deviceChannels.ins == 1) + { + layouts.emplace_back (defaultProcessorChannels.ins, deviceChannels.outs); + layouts.emplace_back (deviceChannels.outs, deviceChannels.outs); + } + + const auto it = std::find_if (layouts.begin(), layouts.end(), [&] (const NumChannels& chans) + { + return proc.checkBusesLayoutSupported (chans.toLayout()); + }); + + return it != std::end (layouts) ? *it : layouts[0]; +} + +void AudioProcessorPlayer::resizeChannels() +{ + const auto maxChannels = jmax (deviceChannels.ins, + deviceChannels.outs, + actualProcessorChannels.ins, + actualProcessorChannels.outs); + channels.resize ((size_t) maxChannels); + tempBuffer.setSize (maxChannels, blockSize); +} + void AudioProcessorPlayer::setProcessor (AudioProcessor* const processorToPlay) { if (processor != processorToPlay) { if (processorToPlay != nullptr && sampleRate > 0 && blockSize > 0) { - processorToPlay->setPlayConfigDetails (numInputChans, numOutputChans, sampleRate, blockSize); + defaultProcessorChannels = NumChannels { processorToPlay->getBusesLayout() }; + actualProcessorChannels = findMostSuitableLayout (*processorToPlay); + + processorToPlay->setPlayConfigDetails (actualProcessorChannels.ins, + actualProcessorChannels.outs, + sampleRate, + blockSize); - bool supportsDouble = processorToPlay->supportsDoublePrecisionProcessing() && isDoublePrecision; + auto supportsDouble = processorToPlay->supportsDoublePrecisionProcessing() && isDoublePrecision; processorToPlay->setProcessingPrecision (supportsDouble ? AudioProcessor::doublePrecision : AudioProcessor::singlePrecision); processorToPlay->prepareToPlay (sampleRate, blockSize); } - AudioProcessor* oldOne; + AudioProcessor* oldOne = nullptr; { const ScopedLock sl (lock); + oldOne = isPrepared ? processor : nullptr; processor = processorToPlay; isPrepared = true; + resizeChannels(); } if (oldOne != nullptr) @@ -76,7 +208,7 @@ void AudioProcessorPlayer::setDoublePrecisionProcessing (bool doublePrecision) { processor->releaseResources(); - bool supportsDouble = processor->supportsDoublePrecisionProcessing() && doublePrecision; + auto supportsDouble = processor->supportsDoublePrecisionProcessing() && doublePrecision; processor->setProcessingPrecision (supportsDouble ? AudioProcessor::doublePrecision : AudioProcessor::singlePrecision); @@ -103,53 +235,26 @@ void AudioProcessorPlayer::audioDeviceIOCallback (const float** const inputChann const int numOutputChannels, const int numSamples) { - // these should have been prepared by audioDeviceAboutToStart()... + // These should have been prepared by audioDeviceAboutToStart()... jassert (sampleRate > 0 && blockSize > 0); + // The processor should be prepared to deal with the same number of output channels + // as our output device. + jassert (processor == nullptr || numOutputChannels == actualProcessorChannels.outs); + incomingMidi.clear(); messageCollector.removeNextBlockOfMessages (incomingMidi, numSamples); - int totalNumChans = 0; - if (numInputChannels > numOutputChannels) - { - // if there aren't enough output channels for the number of - // inputs, we need to create some temporary extra ones (can't - // use the input data in case it gets written to) - tempBuffer.setSize (numInputChannels - numOutputChannels, numSamples, - false, false, true); + initialiseIoBuffers ({ inputChannelData, numInputChannels }, + { outputChannelData, numOutputChannels }, + numSamples, + actualProcessorChannels.ins, + actualProcessorChannels.outs, + tempBuffer, + channels); - for (int i = 0; i < numOutputChannels; ++i) - { - channels[totalNumChans] = outputChannelData[i]; - memcpy (channels[totalNumChans], inputChannelData[i], (size_t) numSamples * sizeof (float)); - ++totalNumChans; - } - - for (int i = numOutputChannels; i < numInputChannels; ++i) - { - channels[totalNumChans] = tempBuffer.getWritePointer (i - numOutputChannels); - memcpy (channels[totalNumChans], inputChannelData[i], (size_t) numSamples * sizeof (float)); - ++totalNumChans; - } - } - else - { - for (int i = 0; i < numInputChannels; ++i) - { - channels[totalNumChans] = outputChannelData[i]; - memcpy (channels[totalNumChans], inputChannelData[i], (size_t) numSamples * sizeof (float)); - ++totalNumChans; - } - - for (int i = numInputChannels; i < numOutputChannels; ++i) - { - channels[totalNumChans] = outputChannelData[i]; - zeromem (channels[totalNumChans], (size_t) numSamples * sizeof (float)); - ++totalNumChans; - } - } - - AudioBuffer buffer (channels, totalNumChans, numSamples); + const auto totalNumChannels = jmax (actualProcessorChannels.ins, actualProcessorChannels.outs); + AudioBuffer buffer (channels.data(), (int) totalNumChannels, numSamples); { const ScopedLock sl (lock); @@ -205,11 +310,11 @@ void AudioProcessorPlayer::audioDeviceAboutToStart (AudioIODevice* const device) sampleRate = newSampleRate; blockSize = newBlockSize; - numInputChans = numChansIn; - numOutputChans = numChansOut; + deviceChannels = { numChansIn, numChansOut }; + + resizeChannels(); messageCollector.reset (sampleRate); - channels.calloc (jmax (numChansIn, numChansOut) + 2); if (processor != nullptr) { @@ -240,4 +345,90 @@ void AudioProcessorPlayer::handleIncomingMidiMessage (MidiInput*, const MidiMess messageCollector.addMessageToQueue (message); } +//============================================================================== +//============================================================================== +#if JUCE_UNIT_TESTS + +struct AudioProcessorPlayerTests : public UnitTest +{ + AudioProcessorPlayerTests() + : UnitTest ("AudioProcessorPlayer", UnitTestCategories::audio) {} + + void runTest() override + { + struct Layout + { + int numIns, numOuts; + }; + + const Layout processorLayouts[] { Layout { 0, 0 }, + Layout { 1, 1 }, + Layout { 4, 4 }, + Layout { 4, 8 }, + Layout { 8, 4 } }; + + beginTest ("Buffers are prepared correctly for a variety of channel layouts"); + { + for (const auto& layout : processorLayouts) + { + for (const auto numSystemInputs : { 0, 1, layout.numIns }) + { + const int numSamples = 256; + const auto systemIns = getTestBuffer (numSystemInputs, numSamples); + auto systemOuts = getTestBuffer (layout.numOuts, numSamples); + AudioBuffer tempBuffer (jmax (layout.numIns, layout.numOuts), numSamples); + std::vector channels ((size_t) jmax (layout.numIns, layout.numOuts), nullptr); + + initialiseIoBuffers ({ systemIns.getArrayOfReadPointers(), systemIns.getNumChannels() }, + { systemOuts.getArrayOfWritePointers(), systemOuts.getNumChannels() }, + numSamples, + layout.numIns, + layout.numOuts, + tempBuffer, + channels); + + int channelIndex = 0; + + for (const auto& channel : channels) + { + const auto value = [&] + { + // Any channels past the number of inputs should be silent. + if (layout.numIns <= channelIndex) + return 0.0f; + + // If there's no input, all input channels should be silent. + if (numSystemInputs == 0) return 0.0f; + + // If there's one input, all input channels should copy from that input. + if (numSystemInputs == 1) return 1.0f; + + // Otherwise, each processor input should match the corresponding system input. + return (float) (channelIndex + 1); + }(); + + expect (FloatVectorOperations::findMinAndMax (channel, numSamples) == Range (value, value)); + + channelIndex += 1; + } + } + } + } + } + + static AudioBuffer getTestBuffer (int numChannels, int numSamples) + { + AudioBuffer result (numChannels, numSamples); + + for (int i = 0; i < result.getNumChannels(); ++i) + FloatVectorOperations::fill (result.getWritePointer (i), (float) i + 1, result.getNumSamples()); + + return result; + } +}; + +static AudioProcessorPlayerTests audioProcessorPlayerTests; + +#endif + } // namespace juce diff --git a/modules/juce_audio_utils/players/juce_AudioProcessorPlayer.h b/modules/juce_audio_utils/players/juce_AudioProcessorPlayer.h index 4458dd2ab5..b078518a79 100644 --- a/modules/juce_audio_utils/players/juce_AudioProcessorPlayer.h +++ b/modules/juce_audio_utils/players/juce_AudioProcessorPlayer.h @@ -101,6 +101,27 @@ public: void handleIncomingMidiMessage (MidiInput*, const MidiMessage&) override; private: + struct NumChannels + { + NumChannels() = default; + NumChannels (int numIns, int numOuts) : ins (numIns), outs (numOuts) {} + + explicit NumChannels (const AudioProcessor::BusesLayout& layout) + : ins (layout.getNumChannels (true, 0)), outs (layout.getNumChannels (false, 0)) {} + + AudioProcessor::BusesLayout toLayout() const + { + return { { AudioChannelSet::canonicalChannelSet (ins) }, + { AudioChannelSet::canonicalChannelSet (outs) } }; + } + + int ins = 0, outs = 0; + }; + + //============================================================================== + NumChannels findMostSuitableLayout (const AudioProcessor&) const; + void resizeChannels(); + //============================================================================== AudioProcessor* processor = nullptr; CriticalSection lock; @@ -108,8 +129,8 @@ private: int blockSize = 0; bool isPrepared = false, isDoublePrecision = false; - int numInputChans = 0, numOutputChans = 0; - HeapBlock channels; + NumChannels deviceChannels, defaultProcessorChannels, actualProcessorChannels; + std::vector channels; AudioBuffer tempBuffer; AudioBuffer conversionBuffer; From ad8f2013b58ea2848ac308ba2be4c3c593b2ff93 Mon Sep 17 00:00:00 2001 From: ed Date: Fri, 12 Mar 2021 14:44:54 +0000 Subject: [PATCH 7/9] AudioProcessorEditor: Set ComponentBoundsConstrainer stretchingTop/Left/Bottom/Right values when calling setBoundsForComponent() --- .../processors/juce_AudioProcessorEditor.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp b/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp index 7db87b2858..30249c0a53 100644 --- a/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp +++ b/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp @@ -146,10 +146,20 @@ void AudioProcessorEditor::attachResizableCornerComponent() void AudioProcessorEditor::setBoundsConstrained (Rectangle newBounds) { - if (constrainer != nullptr) - constrainer->setBoundsForComponent (this, newBounds, false, false, false, false); - else + if (constrainer == nullptr) + { setBounds (newBounds); + return; + } + + auto currentBounds = getBounds(); + + constrainer->setBoundsForComponent (this, + newBounds, + newBounds.getY() != currentBounds.getY() && newBounds.getBottom() == currentBounds.getBottom(), + newBounds.getX() != currentBounds.getX() && newBounds.getRight() == currentBounds.getRight(), + newBounds.getY() == currentBounds.getY() && newBounds.getBottom() != currentBounds.getBottom(), + newBounds.getX() == currentBounds.getX() && newBounds.getRight() != currentBounds.getRight()); } void AudioProcessorEditor::editorResized (bool wasResized) From db618477ff14d27c863986a04ec90979cb069e53 Mon Sep 17 00:00:00 2001 From: ed Date: Fri, 12 Mar 2021 17:17:39 +0000 Subject: [PATCH 8/9] Standalone: Respect AudioProcessorEditor resize limits --- .../Standalone/juce_StandaloneFilterWindow.h | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h b/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h index 3ec1bed66d..fc8d4e394b 100644 --- a/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h +++ b/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h @@ -819,10 +819,22 @@ private: #else if (editor != nullptr) { - auto rect = getSizeToContainEditor(); - - setSize (rect.getWidth(), - rect.getHeight() + (shouldShowNotification ? NotificationArea::height : 0)); + const int extraHeight = shouldShowNotification ? NotificationArea::height : 0; + const auto rect = getSizeToContainEditor(); + + if (auto* editorConstrainer = editor->getConstrainer()) + { + const auto borders = owner.getContentComponentBorder(); + const auto extraWindowWidth = borders.getLeftAndRight(); + const auto extraWindowHeight = extraHeight + borders.getTopAndBottom(); + + owner.setResizeLimits (editorConstrainer->getMinimumWidth() + extraWindowWidth, + editorConstrainer->getMinimumHeight() + extraWindowHeight, + editorConstrainer->getMaximumWidth() + extraWindowWidth, + editorConstrainer->getMaximumHeight() + extraWindowHeight); + } + + setSize (rect.getWidth(), rect.getHeight() + extraHeight); } #endif } From 7d71efe6e0ded444902b7902f18cf7b84ed63757 Mon Sep 17 00:00:00 2001 From: ed Date: Fri, 12 Mar 2021 17:44:34 +0000 Subject: [PATCH 9/9] Standalone: Use AudioProcessorEditor::setBoundsConstrained() when setting editor bounds --- .../Standalone/juce_StandaloneFilterWindow.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h b/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h index fc8d4e394b..40d8a60741 100644 --- a/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h +++ b/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h @@ -755,9 +755,9 @@ private: notification.setBounds (r.removeFromTop (NotificationArea::height)); if (editor != nullptr) - editor->setBounds (editor->getLocalArea (this, r.toFloat()) - .withPosition (r.getTopLeft().toFloat().transformedBy (editor->getTransform().inverted())) - .toNearestInt()); + editor->setBoundsConstrained (editor->getLocalArea (this, r.toFloat()) + .withPosition (r.getTopLeft().toFloat().transformedBy (editor->getTransform().inverted())) + .toNearestInt()); } private: