WaapiClient.h (8465B)
1 /*---------------------------------------------------------------------------------------- 2 3 Copyright (c) 2023 AUDIOKINETIC Inc. 4 5 This file is licensed to use under the license available at: 6 https://github.com/audiokinetic/ReaWwise/blob/main/License.txt (the "License"). 7 You may not use this file except in compliance with the License. 8 9 Unless required by applicable law or agreed to in writing, software distributed 10 under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 11 CONDITIONS OF ANY KIND, either express or implied. See the License for the 12 specific language governing permissions and limitations under the License. 13 14 ----------------------------------------------------------------------------------------*/ 15 16 #pragma once 17 18 #include "AK/WwiseAuthoringAPI/AkAutobahn/AkJson.h" 19 #include "AK/WwiseAuthoringAPI/AkAutobahn/Client.h" 20 #include "Helpers/WaapiHelper.h" 21 #include "Model/Import.h" 22 #include "Model/Waapi.h" 23 #include "Model/Wwise.h" 24 25 #include <juce_core/juce_core.h> 26 #include <juce_events/juce_events.h> 27 28 namespace AK::WwiseTransfer 29 { 30 struct WaapiClientWatcherConfig 31 { 32 juce::String Ip; 33 int Port; 34 const int ConnectionMonitorDelay; 35 const int MinConnectionRetryDelay; 36 const int MaxConnectionRetryDelay; 37 }; 38 39 template <class Function, class Callback> 40 class AsyncJob 41 : public juce::ThreadPoolJob 42 { 43 public: 44 AsyncJob(const Function& function, const Callback& callback) 45 : function(function) 46 , callback(callback) 47 , juce::ThreadPoolJob("AsyncJob") 48 { 49 } 50 51 juce::ThreadPoolJob::JobStatus runJob() override 52 { 53 decltype(function()) response; 54 55 auto onExecute = [this, &response]() 56 { 57 response = function(); 58 59 return response.status || shouldExit(); 60 }; 61 62 WaapiHelper::executeWithRetry(onExecute); 63 64 auto onJobComplete = [callback = callback, response = std::move(response)] 65 { 66 callback(response); 67 }; 68 69 juce::MessageManager::callAsync(onJobComplete); 70 71 return juce::ThreadPoolJob::JobStatus::jobHasFinished; 72 } 73 74 private: 75 Callback callback; 76 Function function; 77 }; 78 79 class WaapiClient 80 : private WwiseAuthoringAPI::Client 81 { 82 public: 83 explicit WaapiClient(); 84 85 bool connect(const char* in_uri, unsigned int in_port, WwiseAuthoringAPI::disconnectHandler_t disconnectHandler = nullptr, int in_timeoutMs = -1); 86 bool subscribe(const char* in_uri, const WwiseAuthoringAPI::AkJson& in_options, WampEventCallback in_callback, uint64_t& out_subscriptionId, WwiseAuthoringAPI::AkJson& out_result, int in_timeoutMs = -1); 87 bool unsubscribe(const uint64_t& in_subscriptionId, WwiseAuthoringAPI::AkJson& out_result, int in_timeoutMs = -1); 88 bool isConnected() const; 89 void disconnect(); 90 bool call(const char* in_uri, const WwiseAuthoringAPI::AkJson& in_args, const WwiseAuthoringAPI::AkJson& in_options, WwiseAuthoringAPI::AkJson& out_result, int in_timeoutMs = -1); 91 bool call(const char* in_uri, const char* in_args, const char* in_options, std::string& out_result, int in_timeoutMs = -1); 92 93 Waapi::Response<Wwise::Version> getVersion(); 94 Waapi::Response<Waapi::ProjectInfo> getProjectInfo(); 95 Waapi::Response<Waapi::AdditionalProjectInfo> getAdditionalProjectInfo(); 96 Waapi::Response<Waapi::ObjectResponse> getSelectedObject(); 97 Waapi::Response<Waapi::ObjectResponseSet> pasteProperties(const Waapi::PastePropertiesRequest& pastePropertiesRequest); 98 Waapi::Response<Waapi::ObjectResponseSet> import(const std::vector<Waapi::ImportItemRequest>& importItemsRequest, Import::ContainerNameExistsOption containerNameExistsOption, const juce::String& objectLanguage); 99 Waapi::Response<Waapi::ObjectResponseSet> getObjectAncestorsAndDescendants(const juce::String& objectPath); 100 Waapi::Response<Waapi::ObjectResponseSet> getObjectAncestorsAndDescendantsLegacy(const juce::String& objectPath); 101 Waapi::Response<std::vector<juce::String>> getProjectLanguages(); 102 Waapi::Response<Waapi::ObjectResponse> getObject(const juce::String& objectPath); 103 104 bool selectObjects(const juce::String& selectObjectsCommand, const std::vector<juce::String>& objectPaths); 105 106 void beginUndoGroup(); 107 void cancelUndoGroup(); 108 void endUndoGroup(const juce::String& displayName); 109 110 template <typename Callback> 111 void getVersionAsync(const Callback& callback) 112 { 113 auto onJobExecute = [this]() 114 { 115 return getVersion(); 116 }; 117 118 threadPool.addJob(new AsyncJob(onJobExecute, callback), true); 119 } 120 121 template <typename Callback> 122 void getProjectInfoAsync(const Callback& callback) 123 { 124 auto onJobExecute = [this]() 125 { 126 return getProjectInfo(); 127 }; 128 129 threadPool.addJob(new AsyncJob(onJobExecute, callback), true); 130 } 131 132 template <typename Callback> 133 void getAdditionalProjectInfoAsync(const Callback& callback) 134 { 135 auto onJobExecute = [this]() 136 { 137 return getAdditionalProjectInfo(); 138 }; 139 140 threadPool.addJob(new AsyncJob(onJobExecute, callback), true); 141 } 142 143 template <typename Callback> 144 void getSelectedObjectAsync(const Callback& callback) 145 { 146 auto onJobExecute = [this]() 147 { 148 return getSelectedObject(); 149 }; 150 151 threadPool.addJob(new AsyncJob(onJobExecute, callback), true); 152 } 153 154 template <typename Callback> 155 void pastePropertiesAsync(const Waapi::PastePropertiesRequest& pastePropertiesRequest, const Callback& callback) 156 { 157 auto onJobExecute = [this, pastePropertiesRequest = pastePropertiesRequest]() 158 { 159 return pasteProperties(pastePropertiesRequest); 160 }; 161 162 threadPool.addJob(new AsyncJob(onJobExecute, callback), true); 163 } 164 165 template <typename Callback> 166 void getProjectLanguagesAsync(const Callback& callback) 167 { 168 auto onJobExecute = [this]() 169 { 170 return getProjectLanguages(); 171 }; 172 173 threadPool.addJob(new AsyncJob(onJobExecute, callback), true); 174 } 175 template <typename Callback> 176 void importAsync(const std::vector<Waapi::ImportItemRequest>& importItemsRequest, Import::ContainerNameExistsOption containerNameExistsOption, const juce::String& objectLanguage, const Callback& callback) 177 { 178 auto onJobExecute = [this, importItemsRequest = importItemsRequest, containerNameExistsOption = containerNameExistsOption, objectLanguage = objectLanguage]() 179 { 180 return import(importItemsRequest, containerNameExistsOption, objectLanguage); 181 }; 182 183 threadPool.addJob(new AsyncJob(onJobExecute, callback), true); 184 } 185 186 template <typename Callback> 187 void getObjectAncestorsAndDescendantsAsync(const juce::String& objectPath, Callback& callback) 188 { 189 auto onJobExecute = [objectPath, this]() 190 { 191 return getObjectAncestorsAndDescendants(objectPath); 192 }; 193 194 threadPool.addJob(new AsyncJob(onJobExecute, callback), true); 195 } 196 197 template <typename Callback> 198 void getObjectAncestorsAndDescendantsLegacyAsync(const juce::String& objectPath, Callback& callback) 199 { 200 auto onJobExecute = [objectPath, this]() 201 { 202 return getObjectAncestorsAndDescendantsLegacy(objectPath); 203 }; 204 205 threadPool.addJob(new AsyncJob(onJobExecute, callback), true); 206 } 207 208 template <typename Callback> 209 void getObjectAsync(const juce::String& objectPath, Callback& callback) 210 { 211 auto onJobExecute = [objectPath, this]() 212 { 213 return getObject(objectPath); 214 }; 215 216 threadPool.addJob(new AsyncJob(onJobExecute, callback), true); 217 } 218 219 private: 220 juce::ThreadPool threadPool; 221 }; 222 223 class WaapiClientWatcher 224 : private juce::Thread 225 { 226 public: 227 WaapiClientWatcher(juce::ValueTree applicationState, WaapiClient& waapiClient, WaapiClientWatcherConfig&& waapiClientWatcherConfig); 228 229 void start(); 230 void stop(); 231 void changeParameters(const juce::String& ip, int port); 232 233 private: 234 juce::ValueTree applicationState; 235 juce::CachedValue<juce::String> projectId; 236 juce::CachedValue<bool> waapiConnected; 237 juce::CachedValue<bool> wwiseObjectsChanged; 238 239 juce::ValueTree languages; 240 241 WaapiClientWatcherConfig waapiClientWatcherConfig; 242 WaapiClient& waapiClient; 243 244 int connectionRetryDelay; 245 246 uint64_t projectLoadedSubscriptionId{0}; 247 uint64_t projectPostClosedSubscriptionId{0}; 248 uint64_t objectCreatedEventSubscriptionId{0}; 249 uint64_t objectPostDeletedEventSubscriptionId{0}; 250 uint64_t objectNameChangedEventSubscriptionId{0}; 251 252 // protected by guiMutex except for on construction 253 std::mutex guiMutex; 254 bool shouldReconnect = false; 255 juce::String ip; 256 int port; 257 // 258 259 void run() override; 260 261 void setProjectId(const juce::String& projectId); 262 void setWaapiConnected(bool connected); 263 void setWwiseObjectsChanged(bool changed); 264 void disconnectFromWaapi(); 265 }; 266 } // namespace AK::WwiseTransfer