WwiseFileState.cpp 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855
  1. /*******************************************************************************
  2. The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
  3. Technology released in source code form as part of the game integration package.
  4. The content of this file may not be used without valid licenses to the
  5. AUDIOKINETIC Wwise Technology.
  6. Note that the use of the game engine is subject to the Unreal(R) Engine End User
  7. License Agreement at https://www.unrealengine.com/en-US/eula/unreal
  8. License Usage
  9. Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
  10. this file in accordance with the end user license agreement provided with the
  11. software or, alternatively, in accordance with the terms contained
  12. in a written agreement between you and Audiokinetic Inc.
  13. Copyright (c) 2023 Audiokinetic Inc.
  14. *******************************************************************************/
  15. #include "Wwise/WwiseFileState.h"
  16. #include "Wwise/Stats/AsyncStats.h"
  17. #include <inttypes.h>
  18. #include "Wwise/WwiseStreamableFileStateInfo.h"
  19. FWwiseFileState::~FWwiseFileState()
  20. {
  21. SCOPED_WWISEFILEHANDLER_EVENT_3(TEXT("FWwiseFileState::~FWwiseFileState"));
  22. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::~FWwiseFileState %p (dtor)"), this);
  23. UE_CLOG(FileStateExecutionQueue, LogWwiseFileHandler, Error, TEXT("Closing the File State without closing the execution queue."));
  24. if (LoadCount > 0)
  25. {
  26. UE_LOG(LogWwiseFileHandler, Error, TEXT("Deleting FWwiseFileState %p with LoadCount still active!"), this);
  27. }
  28. }
  29. void FWwiseFileState::IncrementCountAsync(EWwiseFileStateOperationOrigin InOperationOrigin,
  30. FIncrementCountCallback&& InCallback)
  31. {
  32. SCOPED_WWISEFILEHANDLER_EVENT_4(TEXT("FWwiseFileState::IncrementCountAsync"));
  33. if (UNLIKELY(!FileStateExecutionQueue))
  34. {
  35. UE_LOG(LogWwiseFileHandler, Error, TEXT("FWwiseFileState::IncrementCountAsync on a termed asset! Failing immediately!"));
  36. return InCallback(false);
  37. }
  38. FWwiseAsyncCycleCounter OpCycleCounter(GET_STATID(STAT_WwiseFileHandlerStateOperationLatency));
  39. ++OpenedInstances;
  40. AsyncOp(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileState::IncrementCountAsync Async"), [this, InOperationOrigin, OpCycleCounter = MoveTemp(OpCycleCounter), InCallback = MoveTemp(InCallback)]() mutable
  41. {
  42. INC_DWORD_STAT(STAT_WwiseFileHandlerStateOperationsBeingProcessed);
  43. UE_CLOG(CreationOpOrder == 0, LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::IncrementCountAsync %p %s %" PRIu32 ": Initial loading."), this, GetManagingTypeName(), GetShortId());
  44. const auto CurrentOpOrder = CreationOpOrder++;
  45. IncrementCount(InOperationOrigin, CurrentOpOrder, [OpCycleCounter = MoveTemp(OpCycleCounter), InCallback = MoveTemp(InCallback), CurrentOpOrder](bool bInResult) mutable
  46. {
  47. IncrementCountAsyncDone(MoveTemp(OpCycleCounter), MoveTemp(InCallback), bInResult);
  48. });
  49. });
  50. }
  51. void FWwiseFileState::IncrementCountAsyncDone(FWwiseAsyncCycleCounter&& InOpCycleCounter, FIncrementCountCallback&& InCallback, bool bInResult)
  52. {
  53. SCOPED_WWISEFILEHANDLER_EVENT_4(TEXT("FWwiseFileState::IncrementCountAsync Callback"));
  54. InOpCycleCounter.Stop();
  55. DEC_DWORD_STAT(STAT_WwiseFileHandlerStateOperationsBeingProcessed);
  56. InCallback(bInResult);
  57. }
  58. void FWwiseFileState::DecrementCountAsync(EWwiseFileStateOperationOrigin InOperationOrigin,
  59. FDeleteFileStateFunction&& InDeleteState, FDecrementCountCallback&& InCallback)
  60. {
  61. SCOPED_WWISEFILEHANDLER_EVENT_4(TEXT("FWwiseFileState::DecrementCountAsync"));
  62. if (UNLIKELY(!FileStateExecutionQueue))
  63. {
  64. UE_LOG(LogWwiseFileHandler, Error, TEXT("FWwiseFileState::DecrementCountAsync on a termed asset! Failing immediately!"));
  65. return InCallback();
  66. }
  67. FWwiseAsyncCycleCounter OpCycleCounter(GET_STATID(STAT_WwiseFileHandlerStateOperationLatency));
  68. AsyncOp(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileState::DecrementCountAsync Async"), [this, InOperationOrigin, OpCycleCounter = MoveTemp(OpCycleCounter), InDeleteState = MoveTemp(InDeleteState), InCallback = MoveTemp(InCallback)]() mutable
  69. {
  70. INC_DWORD_STAT(STAT_WwiseFileHandlerStateOperationsBeingProcessed);
  71. const auto CurrentOpOrder = CreationOpOrder++;
  72. DecrementCount(InOperationOrigin, CurrentOpOrder, MoveTemp(InDeleteState), [OpCycleCounter = MoveTemp(OpCycleCounter), InCallback = MoveTemp(InCallback), CurrentOpOrder]() mutable
  73. {
  74. DecrementCountAsyncDone(MoveTemp(OpCycleCounter), MoveTemp(InCallback));
  75. });
  76. });
  77. }
  78. void FWwiseFileState::DecrementCountAsyncDone(FWwiseAsyncCycleCounter&& InOpCycleCounter, FDecrementCountCallback&& InCallback)
  79. {
  80. SCOPED_WWISEFILEHANDLER_EVENT_4(TEXT("FWwiseFileState::DecrementCountAsyncDone Callback"));
  81. InOpCycleCounter.Stop();
  82. DEC_DWORD_STAT(STAT_WwiseFileHandlerStateOperationsBeingProcessed);
  83. InCallback();
  84. }
  85. bool FWwiseFileState::CanDelete() const
  86. {
  87. return OpenedInstances.load() == 0 && State == EState::Closed && LoadCount == 0;
  88. }
  89. FWwiseFileState::FWwiseFileState():
  90. LoadCount(0),
  91. StreamingCount(0),
  92. State(EState::Closed)
  93. {
  94. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::FWwiseFileState %p (ctor)"), this);
  95. }
  96. void FWwiseFileState::Term()
  97. {
  98. SCOPED_WWISEFILEHANDLER_EVENT_3(TEXT("FWwiseFileState::Term"));
  99. if (UNLIKELY(!FileStateExecutionQueue))
  100. {
  101. UE_LOG(LogWwiseFileHandler, Error, TEXT("FWwiseFileState::Term %p %s %" PRIu32 " already Term!"), this, GetManagingTypeName(), GetShortId());
  102. return;
  103. }
  104. if (UNLIKELY(OpenedInstances.load() > 0))
  105. {
  106. UE_LOG(LogWwiseFileHandler, Log, TEXT("FWwiseFileState::Term %p %s %" PRIu32 ": Terminating with active states. Waiting 10 loops before bailing out."), this, GetManagingTypeName(), GetShortId());
  107. for (int i = 0; OpenedInstances.load() > 0 && i < 10; ++i)
  108. {
  109. FileStateExecutionQueue->AsyncWait(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileState::Term Wait"), []{});
  110. }
  111. UE_CLOG(OpenedInstances.load() > 0, LogWwiseFileHandler, Error, TEXT("FWwiseFileState::Term %p %s %" PRIu32 ": Terminating with active states. This might cause a crash."), this, GetManagingTypeName(), GetShortId());
  112. }
  113. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::Term %p %s %" PRIu32 ": Terminating."), this, GetManagingTypeName(), GetShortId());
  114. UE_CLOG(!IsEngineExitRequested() && UNLIKELY(State != EState::Closed), LogWwiseFileHandler, Warning, TEXT("FWwiseFileState::Term %s State: Term unclosed file state %" PRIu32 ". Leaking."), GetManagingTypeName(), GetShortId());
  115. UE_CLOG(IsEngineExitRequested() && State != EState::Closed, LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::Term %s State: Term unclosed file state %" PRIu32 " at exit. Leaking."), GetManagingTypeName(), GetShortId());
  116. UE_CLOG(LoadCount != 0, LogWwiseFileHandler, Log, TEXT("FWwiseFileState::Term %p %s %" PRIu32 " when there are still %d load count"), this, GetManagingTypeName(), GetShortId(), LoadCount);
  117. FileStateExecutionQueue->CloseAndDelete(); FileStateExecutionQueue = nullptr;
  118. }
  119. void FWwiseFileState::IncrementCount(EWwiseFileStateOperationOrigin InOperationOrigin, int InCurrentOpOrder,
  120. FIncrementCountCallback&& InCallback)
  121. {
  122. check(FileStateExecutionQueue->IsRunningInThisThread());
  123. IncrementLoadCount(InOperationOrigin);
  124. IncrementCountOpen(InOperationOrigin, InCurrentOpOrder, MoveTemp(InCallback));
  125. }
  126. void FWwiseFileState::IncrementCountOpen(EWwiseFileStateOperationOrigin InOperationOrigin, int InCurrentOpOrder,
  127. FIncrementCountCallback&& InCallback)
  128. {
  129. SCOPED_WWISEFILEHANDLER_EVENT_F_3(TEXT("FWwiseFileState::IncrementCountOpen %s"), GetManagingTypeName());
  130. check(FileStateExecutionQueue->IsRunningInThisThread());
  131. if (IsBusy())
  132. {
  133. if (State == EState::Closing)
  134. {
  135. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::IncrementCountOpen %s %" PRIu32 ": Closing -> WillReopen"),
  136. GetManagingTypeName(), GetShortId());
  137. State = EState::WillReopen;
  138. }
  139. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::IncrementCountOpen %s %" PRIu32 ": Deferred."),
  140. GetManagingTypeName(), GetShortId());
  141. AsyncOpLater(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileState::IncrementCountOpen Busy"), [this, InOperationOrigin, InCurrentOpOrder, InCallback = MoveTemp(InCallback)]() mutable
  142. {
  143. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::IncrementCountOpen %s %" PRIu32 ": Retrying open"),
  144. GetManagingTypeName(), GetShortId());
  145. IncrementCountOpen(InOperationOrigin, InCurrentOpOrder, MoveTemp(InCallback)); // Call ourselves back
  146. });
  147. return;
  148. }
  149. if (State == EState::CanReopen)
  150. {
  151. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::IncrementCountOpen %s %" PRIu32 ": CanReopen -> Closed (post-close)"),
  152. GetManagingTypeName(), GetShortId());
  153. State = EState::Closed;
  154. }
  155. if (State == EState::Opening)
  156. {
  157. // We are currently opening asynchronously. We must wait for that operation to be initially done, so we can keep on processing this.
  158. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::IncrementCountOpen %s %" PRIu32 ": Waiting for deferred Opening file."),
  159. GetManagingTypeName(), GetShortId());
  160. AsyncOp(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileState::IncrementCountOpen Opening"), [this, InOperationOrigin, InCurrentOpOrder, InCallback = MoveTemp(InCallback)]() mutable
  161. {
  162. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::IncrementCountOpen %s %" PRIu32 ": Retrying open"),
  163. GetManagingTypeName(), GetShortId());
  164. IncrementCountOpen(InOperationOrigin, InCurrentOpOrder, MoveTemp(InCallback)); // Call ourselves back
  165. });
  166. return;
  167. }
  168. if (!CanOpenFile())
  169. {
  170. IncrementCountLoad(InOperationOrigin, InCurrentOpOrder, MoveTemp(InCallback)); // Continue
  171. return;
  172. }
  173. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::IncrementCountOpen %s %" PRIu32 ": Closed -> Opening"),
  174. GetManagingTypeName(), GetShortId());
  175. check(State == EState::Closed);
  176. State = EState::Opening;
  177. OpenFile([this, InOperationOrigin, InCurrentOpOrder, InCallback = MoveTemp(InCallback)]() mutable
  178. {
  179. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileState::IncrementCountOpen %s OpenFile"), GetManagingTypeName());
  180. IncrementCountLoad(InOperationOrigin, InCurrentOpOrder, MoveTemp(InCallback));
  181. });
  182. }
  183. void FWwiseFileState::IncrementCountLoad(EWwiseFileStateOperationOrigin InOperationOrigin, int InCurrentOpOrder,
  184. FIncrementCountCallback&& InCallback)
  185. {
  186. SCOPED_WWISEFILEHANDLER_EVENT_F_3(TEXT("FWwiseFileState::IncrementCountLoad %s"), GetManagingTypeName());
  187. check(FileStateExecutionQueue->IsRunningInThisThread());
  188. if (IsBusy())
  189. {
  190. if (State == EState::Unloading)
  191. {
  192. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::IncrementCountLoad %s %" PRIu32 ": Unloading -> WillReload"),
  193. GetManagingTypeName(), GetShortId());
  194. State = EState::WillReload;
  195. }
  196. else if (State == EState::Closing)
  197. {
  198. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::IncrementCountLoad %s %" PRIu32 ": Closing -> WillReopen"),
  199. GetManagingTypeName(), GetShortId());
  200. State = EState::WillReopen;
  201. }
  202. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::IncrementCountLoad %s %" PRIu32 ": Deferred."),
  203. GetManagingTypeName(), GetShortId());
  204. AsyncOpLater(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileState::IncrementCountLoad Busy"), [this, InOperationOrigin, InCurrentOpOrder, InCallback = MoveTemp(InCallback)]() mutable
  205. {
  206. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::IncrementCountLoad %s %" PRIu32 ": Retrying open"),
  207. GetManagingTypeName(), GetShortId());
  208. IncrementCountOpen(InOperationOrigin, InCurrentOpOrder, MoveTemp(InCallback)); // Restart the op from start
  209. });
  210. return;
  211. }
  212. if (State == EState::CanReload)
  213. {
  214. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::IncrementCountLoad %s %" PRIu32 ": CanReload -> Opened (post-unload)"),
  215. GetManagingTypeName(), GetShortId());
  216. State = EState::Opened;
  217. }
  218. if (State == EState::Loading)
  219. {
  220. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::IncrementCountLoad %s %" PRIu32 ": Waiting for deferred Loading file."),
  221. GetManagingTypeName(), GetShortId());
  222. AsyncOp(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileState::IncrementCountLoad Loading"), [this, InOperationOrigin, InCurrentOpOrder, InCallback = MoveTemp(InCallback)]() mutable
  223. {
  224. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::IncrementCountLoad %s %" PRIu32 ": Retrying load"),
  225. GetManagingTypeName(), GetShortId());
  226. IncrementCountLoad(InOperationOrigin, InCurrentOpOrder, MoveTemp(InCallback)); // Call ourselves back
  227. });
  228. return;
  229. }
  230. if (!CanLoadInSoundEngine())
  231. {
  232. IncrementCountDone(InOperationOrigin, InCurrentOpOrder, MoveTemp(InCallback)); // Continue
  233. return;
  234. }
  235. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::IncrementCountLoad %s %" PRIu32 ": Opened -> Loading"),
  236. GetManagingTypeName(), GetShortId());
  237. State = EState::Loading;
  238. LoadInSoundEngine([this, InOperationOrigin, InCurrentOpOrder, InCallback = MoveTemp(InCallback)]() mutable
  239. {
  240. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileState::IncrementCountLoad %s LoadInSoundEngine"), GetManagingTypeName());
  241. IncrementCountDone(InOperationOrigin, InCurrentOpOrder, MoveTemp(InCallback));
  242. });
  243. }
  244. void FWwiseFileState::IncrementCountDone(EWwiseFileStateOperationOrigin InOperationOrigin, int InCurrentOpOrder,
  245. FIncrementCountCallback&& InCallback)
  246. {
  247. SCOPED_WWISEFILEHANDLER_EVENT_F_3(TEXT("FWwiseFileState::IncrementCountDone %s"), GetManagingTypeName());
  248. check(FileStateExecutionQueue->IsRunningInThisThread());
  249. UE_CLOG(UNLIKELY(InCurrentOpOrder < DoneOpOrder), LogWwiseFileHandler, Error, TEXT("FWwiseFileState::IncrementCountDone %s %" PRIu32 ": CurrentOpOrder %d < DoneOpOrder %d"),
  250. GetManagingTypeName(), GetShortId(), InCurrentOpOrder, DoneOpOrder);
  251. if (UNLIKELY(IsBusy()))
  252. {
  253. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::IncrementCountDone %s %" PRIu32 ": Deferred."),
  254. GetManagingTypeName(), GetShortId());
  255. AsyncOpLater(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileState::IncrementCountDone Busy"), [this, InOperationOrigin, InCurrentOpOrder, InCallback = MoveTemp(InCallback)]() mutable
  256. {
  257. IncrementCountDone(InOperationOrigin, InCurrentOpOrder, MoveTemp(InCallback));
  258. });
  259. return;
  260. }
  261. ProcessLaterOpQueue();
  262. if (UNLIKELY(InCurrentOpOrder > DoneOpOrder))
  263. {
  264. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::IncrementCountDone %s %" PRIu32 ": Done incrementing. Out of Order callback. Waiting for our turn (remaining %d)."),
  265. GetManagingTypeName(), GetShortId(), InCurrentOpOrder-DoneOpOrder);
  266. AsyncOpLater(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileState::IncrementCountDone Async"), [this, InOperationOrigin, InCurrentOpOrder, InCallback = MoveTemp(InCallback)]() mutable
  267. {
  268. IncrementCountDone(InOperationOrigin, InCurrentOpOrder, MoveTemp(InCallback));
  269. });
  270. return;
  271. }
  272. ++DoneOpOrder;
  273. bool bResult;
  274. if (InOperationOrigin == EWwiseFileStateOperationOrigin::Streaming)
  275. {
  276. bResult = (State == EState::Loaded);
  277. if (UNLIKELY(!bResult))
  278. {
  279. UE_CLOG(CanLoadInSoundEngine(), LogWwiseFileHandler, Warning, TEXT("FWwiseFileState::IncrementCountDone %s %" PRIu32 ": Could not load file for streaming."),
  280. GetManagingTypeName(), GetShortId());
  281. UE_CLOG(!CanLoadInSoundEngine(), LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::IncrementCountDone %s %" PRIu32 ": Streaming request aborted before load done."),
  282. GetManagingTypeName(), GetShortId());
  283. }
  284. }
  285. else
  286. {
  287. bResult = (State == EState::Loaded)
  288. || (State == EState::Opened && !CanLoadInSoundEngine())
  289. || (State == EState::Closed && !CanOpenFile());
  290. if (UNLIKELY(!bResult))
  291. {
  292. UE_LOG(LogWwiseFileHandler, Warning, TEXT("FWwiseFileState::IncrementCountDone %s %" PRIu32 ": Could not open file for asset loading. [State:%d CanLoad:%s CanOpen:%s]"),
  293. GetManagingTypeName(), GetShortId(),
  294. (int)State, CanLoadInSoundEngine() ? TEXT("true"):TEXT("false"), CanOpenFile() ? TEXT("true"):TEXT("false"));
  295. }
  296. }
  297. UE_CLOG(LIKELY(bResult), LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::IncrementCountDone %s %" PRIu32 ": Done incrementing."),
  298. GetManagingTypeName(), GetShortId());
  299. {
  300. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileState::IncrementCountDone %s Callback"), GetManagingTypeName());
  301. InCallback(bResult);
  302. }
  303. }
  304. void FWwiseFileState::DecrementCount(EWwiseFileStateOperationOrigin InOperationOrigin, int InCurrentOpOrder,
  305. FDeleteFileStateFunction&& InDeleteState, FDecrementCountCallback&& InCallback)
  306. {
  307. check(FileStateExecutionQueue->IsRunningInThisThread());
  308. if (UNLIKELY(LoadCount == 0))
  309. {
  310. UE_LOG(LogWwiseFileHandler, Error, TEXT("FWwiseFileState::DecrementCount %s %" PRIu32 ": File State is already closed."), GetManagingTypeName(), GetShortId());
  311. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileState::DecrementCount %s Callback"), GetManagingTypeName());
  312. InCallback();
  313. return;
  314. }
  315. DecrementLoadCount(InOperationOrigin);
  316. DecrementCountUnload(InOperationOrigin, InCurrentOpOrder, MoveTemp(InDeleteState), MoveTemp(InCallback));
  317. }
  318. void FWwiseFileState::DecrementCountUnload(EWwiseFileStateOperationOrigin InOperationOrigin, int InCurrentOpOrder,
  319. FDeleteFileStateFunction&& InDeleteState, FDecrementCountCallback&& InCallback)
  320. {
  321. SCOPED_WWISEFILEHANDLER_EVENT_F_3(TEXT("FWwiseFileState::DecrementCountUnload %s"), GetManagingTypeName());
  322. check(FileStateExecutionQueue->IsRunningInThisThread());
  323. if (IsBusy())
  324. {
  325. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::DecrementCountUnload %s %" PRIu32 ": UnloadFromSoundEngine deferred."),
  326. GetManagingTypeName(), GetShortId());
  327. AsyncOpLater(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileState::DecrementCountUnload Busy"), [this, InOperationOrigin, InCurrentOpOrder, InDeleteState = MoveTemp(InDeleteState), InCallback = MoveTemp(InCallback)]() mutable
  328. {
  329. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::DecrementCountUnload %s %" PRIu32 ": Retrying unload"),
  330. GetManagingTypeName(), GetShortId());
  331. DecrementCountUnload(InOperationOrigin, InCurrentOpOrder, MoveTemp(InDeleteState), MoveTemp(InCallback)); // Call ourselves back
  332. });
  333. return;
  334. }
  335. if (!CanUnloadFromSoundEngine())
  336. {
  337. DecrementCountClose(InOperationOrigin, InCurrentOpOrder, MoveTemp(InDeleteState), MoveTemp(InCallback)); // Continue
  338. return;
  339. }
  340. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::DecrementCountUnload %s %" PRIu32 ": -> Unloading"),
  341. GetManagingTypeName(), GetShortId());
  342. State = EState::Unloading;
  343. UnloadFromSoundEngine([this, InOperationOrigin, InCurrentOpOrder, InDeleteState = MoveTemp(InDeleteState), InCallback = MoveTemp(InCallback)](EResult InDefer) mutable
  344. {
  345. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileState::DecrementCountUnload %s UnloadFromSoundEngine"), GetManagingTypeName());
  346. DecrementCountUnloadCallback(InOperationOrigin, InCurrentOpOrder, MoveTemp(InDeleteState), MoveTemp(InCallback), InDefer);
  347. });
  348. }
  349. void FWwiseFileState::DecrementCountUnloadCallback(EWwiseFileStateOperationOrigin InOperationOrigin, int InCurrentOpOrder,
  350. FDeleteFileStateFunction&& InDeleteState, FDecrementCountCallback&& InCallback, EResult InDefer)
  351. {
  352. SCOPED_WWISEFILEHANDLER_EVENT_F_3(TEXT("FWwiseFileState::DecrementCountUnloadCallback %s"), GetManagingTypeName());
  353. check(FileStateExecutionQueue->IsRunningInThisThread());
  354. if (LIKELY(InDefer == EResult::Done))
  355. {
  356. DecrementCountClose(InOperationOrigin, InCurrentOpOrder, MoveTemp(InDeleteState), MoveTemp(InCallback)); // Continue
  357. return;
  358. }
  359. UE_LOG(LogWwiseFileHandler, Verbose, TEXT("FWwiseFileState::DecrementCountUnloadCallback %s %" PRIu32 ": Processing deferred Unload."),
  360. GetManagingTypeName(), GetShortId());
  361. if (UNLIKELY(State == EState::WillReload))
  362. {
  363. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::DecrementCountUnloadCallback %s %" PRIu32 ": Another user needs this to be kept loaded."),
  364. GetManagingTypeName(), GetShortId());
  365. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::DecrementCountUnloadCallback %s %" PRIu32 ": WillReload -> Loaded"),
  366. GetManagingTypeName(), GetShortId());
  367. State = EState::Loaded;
  368. DecrementCountDone(InOperationOrigin, InCurrentOpOrder, MoveTemp(InDeleteState), MoveTemp(InCallback)); // Skip all
  369. }
  370. else if (UNLIKELY(State != EState::Unloading))
  371. {
  372. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::DecrementCountUnloadCallback %s %" PRIu32 ": State got changed. Not unloading anymore."),
  373. GetManagingTypeName(), GetShortId());
  374. DecrementCountClose(InOperationOrigin, InCurrentOpOrder, MoveTemp(InDeleteState), MoveTemp(InCallback)); // Continue
  375. }
  376. else
  377. {
  378. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::DecrementCountUnloadCallback %s %" PRIu32 ": Unloading -> Loaded (retry)"),
  379. GetManagingTypeName(), GetShortId());
  380. State = EState::Loaded;
  381. DecrementCountUnload(InOperationOrigin, InCurrentOpOrder, MoveTemp(InDeleteState), MoveTemp(InCallback)); // Call ourselves back
  382. }
  383. }
  384. void FWwiseFileState::DecrementCountClose(EWwiseFileStateOperationOrigin InOperationOrigin, int InCurrentOpOrder,
  385. FDeleteFileStateFunction&& InDeleteState, FDecrementCountCallback&& InCallback)
  386. {
  387. SCOPED_WWISEFILEHANDLER_EVENT_F_3(TEXT("FWwiseFileState::DecrementCountClose %s"), GetManagingTypeName());
  388. check(FileStateExecutionQueue->IsRunningInThisThread());
  389. if (IsBusy())
  390. {
  391. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::DecrementCountClose %s %" PRIu32 ": CloseFile deferred."),
  392. GetManagingTypeName(), GetShortId());
  393. AsyncOpLater(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileState::DecrementCountClose Busy"), [this, InOperationOrigin, InCurrentOpOrder, InDeleteState = MoveTemp(InDeleteState), InCallback = MoveTemp(InCallback)]() mutable
  394. {
  395. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::DecrementCountClose %s %" PRIu32 ": Retrying close"),
  396. GetManagingTypeName(), GetShortId());
  397. DecrementCountClose(InOperationOrigin, InCurrentOpOrder, MoveTemp(InDeleteState), MoveTemp(InCallback)); // Call ourselves back
  398. });
  399. return;
  400. }
  401. if (!CanCloseFile())
  402. {
  403. DecrementCountDone(InOperationOrigin, InCurrentOpOrder, MoveTemp(InDeleteState), MoveTemp(InCallback)); // Continue
  404. return;
  405. }
  406. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::DecrementCountClose %s %" PRIu32 ": -> Closing"),
  407. GetManagingTypeName(), GetShortId());
  408. State = EState::Closing;
  409. CloseFile([this, InOperationOrigin, InCurrentOpOrder, InDeleteState = MoveTemp(InDeleteState), InCallback = MoveTemp(InCallback)](EResult InDefer) mutable
  410. {
  411. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileState::DecrementCountClose %s CloseFile"), GetManagingTypeName());
  412. DecrementCountUnloadCallback(InOperationOrigin, InCurrentOpOrder, MoveTemp(InDeleteState), MoveTemp(InCallback), InDefer);
  413. });
  414. }
  415. void FWwiseFileState::DecrementCountCloseCallback(EWwiseFileStateOperationOrigin InOperationOrigin, int InCurrentOpOrder,
  416. FDeleteFileStateFunction&& InDeleteState, FDecrementCountCallback&& InCallback, EResult InDefer)
  417. {
  418. SCOPED_WWISEFILEHANDLER_EVENT_F_3(TEXT("FWwiseFileState::DecrementCountCloseCallback %s"), GetManagingTypeName());
  419. check(FileStateExecutionQueue->IsRunningInThisThread());
  420. if (LIKELY(InDefer == EResult::Done))
  421. {
  422. DecrementCountDone(InOperationOrigin, InCurrentOpOrder, MoveTemp(InDeleteState), MoveTemp(InCallback)); // Continue
  423. return;
  424. }
  425. UE_LOG(LogWwiseFileHandler, Verbose, TEXT("FWwiseFileState::DecrementCountCloseCallback %s %" PRIu32 ": Processing deferred Close."),
  426. GetManagingTypeName(), GetShortId());
  427. if (UNLIKELY(State == EState::WillReopen))
  428. {
  429. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::DecrementCountCloseCallback %s %" PRIu32 ": Another user needs this to be kept open."),
  430. GetManagingTypeName(), GetShortId());
  431. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::DecrementCountCloseCallback %s %" PRIu32 ": WillReopen -> Opened"),
  432. GetManagingTypeName(), GetShortId());
  433. State = EState::Opened;
  434. DecrementCountDone(InOperationOrigin, InCurrentOpOrder, MoveTemp(InDeleteState), MoveTemp(InCallback)); // Skip all
  435. }
  436. else if (UNLIKELY(State != EState::Closing))
  437. {
  438. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::DecrementCountCloseCallback %s %" PRIu32 ": State got changed. Not closing anymore."),
  439. GetManagingTypeName(), GetShortId());
  440. DecrementCountClose(InOperationOrigin, InCurrentOpOrder, MoveTemp(InDeleteState), MoveTemp(InCallback)); // Continue
  441. }
  442. else
  443. {
  444. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::DecrementCountCloseCallback %s %" PRIu32 ": Closing -> Opened (retry)"),
  445. GetManagingTypeName(), GetShortId());
  446. State = EState::Opened;
  447. DecrementCountClose(InOperationOrigin, InCurrentOpOrder, MoveTemp(InDeleteState), MoveTemp(InCallback)); // Call ourselves back
  448. }
  449. }
  450. void FWwiseFileState::DecrementCountDone(EWwiseFileStateOperationOrigin InOperationOrigin, int InCurrentOpOrder,
  451. FDeleteFileStateFunction&& InDeleteState, FDecrementCountCallback&& InCallback)
  452. {
  453. SCOPED_WWISEFILEHANDLER_EVENT_F_3(TEXT("FWwiseFileState::DecrementCountDone %s"), GetManagingTypeName());
  454. check(FileStateExecutionQueue->IsRunningInThisThread());
  455. UE_CLOG(UNLIKELY(InCurrentOpOrder < DoneOpOrder), LogWwiseFileHandler, Error, TEXT("FWwiseFileState::DecrementCountDone %s %" PRIu32 ": CurrentOpOrder %d < DoneOpOrder %d"),
  456. GetManagingTypeName(), GetShortId(), InCurrentOpOrder, DoneOpOrder);
  457. if (UNLIKELY(IsBusy()))
  458. {
  459. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::DecrementCountDone %s %" PRIu32 ": Deferred."),
  460. GetManagingTypeName(), GetShortId());
  461. AsyncOpLater(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileState::DecrementCountDone Busy"), [this, InOperationOrigin, InCurrentOpOrder, InDeleteState = MoveTemp(InDeleteState), InCallback = MoveTemp(InCallback)]() mutable
  462. {
  463. DecrementCountDone(InOperationOrigin, InCurrentOpOrder, MoveTemp(InDeleteState), MoveTemp(InCallback));
  464. });
  465. return;
  466. }
  467. ProcessLaterOpQueue();
  468. if (UNLIKELY(InCurrentOpOrder > DoneOpOrder))
  469. {
  470. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::DecrementCountDone %s %" PRIu32 ": Done decrementing. Out of Order callback. Waiting for our turn (remaining %d)."),
  471. GetManagingTypeName(), GetShortId(), InCurrentOpOrder-DoneOpOrder);
  472. AsyncOpLater(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileState::DecrementCountDone Async"), [this, InOperationOrigin, InCurrentOpOrder, InDeleteState = MoveTemp(InDeleteState), InCallback = MoveTemp(InCallback)]() mutable
  473. {
  474. DecrementCountDone(InOperationOrigin, InCurrentOpOrder, MoveTemp(InDeleteState), MoveTemp(InCallback));
  475. });
  476. return;
  477. }
  478. ++DoneOpOrder;
  479. --OpenedInstances;
  480. if (CanDelete())
  481. {
  482. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::DecrementCountDone %s %" PRIu32 ": Done decrementing. Deleting state."),
  483. GetManagingTypeName(), GetShortId());
  484. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileState::DecrementCountDone %s Delete"), GetManagingTypeName());
  485. InDeleteState(MoveTemp(InCallback));
  486. }
  487. else
  488. {
  489. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::DecrementCountDone %s %" PRIu32 ": Done decrementing."),
  490. GetManagingTypeName(), GetShortId());
  491. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileState::DecrementCountDone %s Callback"), GetManagingTypeName());
  492. InCallback();
  493. }
  494. }
  495. void FWwiseFileState::IncrementLoadCount(EWwiseFileStateOperationOrigin InOperationOrigin)
  496. {
  497. check(FileStateExecutionQueue->IsRunningInThisThread());
  498. const bool bIncrementStreamingCount = (InOperationOrigin == EWwiseFileStateOperationOrigin::Streaming);
  499. if (bIncrementStreamingCount) ++StreamingCount;
  500. ++LoadCount;
  501. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::IncrementLoadCount %s %" PRIu32 ": ++LoadCount %d %sStreamingCount %d"),
  502. GetManagingTypeName(), GetShortId(), LoadCount, bIncrementStreamingCount ? TEXT("++") : TEXT(""), StreamingCount);
  503. }
  504. bool FWwiseFileState::CanOpenFile() const
  505. {
  506. return State == EState::Closed && LoadCount > 0;
  507. }
  508. void FWwiseFileState::OpenFileSucceeded(FOpenFileCallback&& InCallback)
  509. {
  510. AsyncOp(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileState::OpenFileSucceeded"), [this, InCallback = MoveTemp(InCallback)]() mutable
  511. {
  512. if (UNLIKELY(State != EState::Opening))
  513. {
  514. UE_LOG(LogWwiseFileHandler, Error, TEXT("FWwiseFileState::OpenFileSucceeded: Succeeded opening %s %" PRIu32 " while not in Opening state"), GetManagingTypeName(), GetShortId());
  515. }
  516. else
  517. {
  518. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::OpenFileSucceeded %s %" PRIu32 ": Opening -> Opened"), GetManagingTypeName(), GetShortId());
  519. State = EState::Opened;
  520. }
  521. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileState::OpenFileSucceeded %s Callback"), GetManagingTypeName());
  522. InCallback();
  523. });
  524. }
  525. void FWwiseFileState::OpenFileFailed(FOpenFileCallback&& InCallback)
  526. {
  527. AsyncOp(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileState::OpenFileFailed"), [this, InCallback = MoveTemp(InCallback)]() mutable
  528. {
  529. INC_DWORD_STAT(STAT_WwiseFileHandlerTotalErrorCount);
  530. if (UNLIKELY(State != EState::Opening))
  531. {
  532. UE_LOG(LogWwiseFileHandler, Error, TEXT("FWwiseFileState::OpenFileFailed: Failed opening %s %" PRIu32 " while not in Opening state"), GetManagingTypeName(), GetShortId());
  533. }
  534. else
  535. {
  536. UE_LOG(LogWwiseFileHandler, Warning, TEXT("FWwiseFileState::OpenFileFailed %s %" PRIu32 ": Opening Failed -> Closed"), GetManagingTypeName(), GetShortId());
  537. State = EState::Closed;
  538. }
  539. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileState::OpenFileFailed %s Callback"), GetManagingTypeName());
  540. InCallback();
  541. });
  542. }
  543. bool FWwiseFileState::CanLoadInSoundEngine() const
  544. {
  545. return State == EState::Opened && (!IsStreamedState() || StreamingCount > 0);
  546. }
  547. void FWwiseFileState::LoadInSoundEngineSucceeded(FLoadInSoundEngineCallback&& InCallback)
  548. {
  549. AsyncOp(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileState::LoadInSoundEngineSucceeded"), [this, InCallback = MoveTemp(InCallback)]() mutable
  550. {
  551. if (UNLIKELY(State != EState::Loading))
  552. {
  553. UE_LOG(LogWwiseFileHandler, Error, TEXT("FWwiseFileState::LoadInSoundEngineSucceeded: Succeeded loading %s %" PRIu32 " while not in Loading state"), GetManagingTypeName(), GetShortId());
  554. }
  555. else
  556. {
  557. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::LoadInSoundEngineSucceeded %s %" PRIu32 ": Loading -> Loaded"), GetManagingTypeName(), GetShortId());
  558. State = EState::Loaded;
  559. }
  560. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileState::LoadInSoundEngineSucceeded %s Callback"), GetManagingTypeName());
  561. InCallback();
  562. });
  563. }
  564. void FWwiseFileState::LoadInSoundEngineFailed(FLoadInSoundEngineCallback&& InCallback)
  565. {
  566. AsyncOp(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileState::LoadInSoundEngineFailed"), [this, InCallback = MoveTemp(InCallback)]() mutable
  567. {
  568. INC_DWORD_STAT(STAT_WwiseFileHandlerTotalErrorCount);
  569. if (UNLIKELY(State != EState::Loading))
  570. {
  571. UE_LOG(LogWwiseFileHandler, Error, TEXT("FWwiseFileState::LoadInSoundEngineFailed: Failed loading %s %" PRIu32 " while not in Loading state"), GetManagingTypeName(), GetShortId());
  572. }
  573. else
  574. {
  575. UE_LOG(LogWwiseFileHandler, Warning, TEXT("FWwiseFileState::LoadInSoundEngineFailed %s %" PRIu32 ": Loading Failed -> Opened"), GetManagingTypeName(), GetShortId());
  576. State = EState::Opened;
  577. }
  578. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileState::LoadInSoundEngineFailed %s Callback"), GetManagingTypeName());
  579. InCallback();
  580. });
  581. }
  582. void FWwiseFileState::DecrementLoadCount(EWwiseFileStateOperationOrigin InOperationOrigin)
  583. {
  584. const bool bDecrementStreamingCount = (InOperationOrigin == EWwiseFileStateOperationOrigin::Streaming);
  585. if (bDecrementStreamingCount) --StreamingCount;
  586. --LoadCount;
  587. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::DecrementLoadCount %s %" PRIu32 ": --LoadCount %d %sStreamingCount %d"),
  588. GetManagingTypeName(), GetShortId(), LoadCount, bDecrementStreamingCount ? TEXT("--") : TEXT(""), StreamingCount);
  589. }
  590. bool FWwiseFileState::CanUnloadFromSoundEngine() const
  591. {
  592. return State == EState::Loaded && ((IsStreamedState() && StreamingCount == 0) || (!IsStreamedState() && LoadCount == 0));
  593. }
  594. void FWwiseFileState::UnloadFromSoundEngineDone(FUnloadFromSoundEngineCallback&& InCallback)
  595. {
  596. AsyncOp(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileState::UnloadFromSoundEngineDone"), [this, InCallback = MoveTemp(InCallback)]() mutable
  597. {
  598. if (UNLIKELY(State != EState::Unloading && State != EState::WillReload))
  599. {
  600. UE_LOG(LogWwiseFileHandler, Error, TEXT("FWwiseFileState::UnloadFromSoundEngineDone: Done unloading %s %" PRIu32 " while not in Unloading state"), GetManagingTypeName(), GetShortId());
  601. }
  602. else if (LIKELY(State == EState::Unloading))
  603. {
  604. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::UnloadFromSoundEngineDone %s %" PRIu32 ": Unloading -> Opened"), GetManagingTypeName(), GetShortId());
  605. State = EState::Opened;
  606. }
  607. else
  608. {
  609. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::UnloadFromSoundEngineDone %s %" PRIu32 ": WillReload -> CanReload"), GetManagingTypeName(), GetShortId());
  610. State = EState::CanReload;
  611. ProcessLaterOpQueue();
  612. }
  613. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileState::UnloadFromSoundEngineDone %s Callback"), GetManagingTypeName());
  614. InCallback(EResult::Done);
  615. });
  616. }
  617. void FWwiseFileState::UnloadFromSoundEngineToClosedFile(FUnloadFromSoundEngineCallback&& InCallback)
  618. {
  619. AsyncOp(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileState::UnloadFromSoundEngineToClosedFile"), [this, InCallback = MoveTemp(InCallback)]() mutable
  620. {
  621. if (UNLIKELY(State != EState::Unloading && State != EState::WillReload))
  622. {
  623. UE_LOG(LogWwiseFileHandler, Error, TEXT("FWwiseFileState::UnloadFromSoundEngineToClosedFile: Done unloading %s %" PRIu32 " while not in Unloading state"), GetManagingTypeName(), GetShortId());
  624. }
  625. else if (LIKELY(State == EState::Unloading))
  626. {
  627. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::UnloadFromSoundEngineToClosedFile %s %" PRIu32 ": Unloading -...-> Closed"), GetManagingTypeName(), GetShortId());
  628. State = EState::Closed;
  629. }
  630. else
  631. {
  632. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::UnloadFromSoundEngineToClosedFile %s %" PRIu32 ": WillReload -> CanReload -> CanReopen"), GetManagingTypeName(), GetShortId());
  633. State = EState::CanReopen;
  634. ProcessLaterOpQueue();
  635. }
  636. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileState::UnloadFromSoundEngineToClosedFile %s Callback"), GetManagingTypeName());
  637. InCallback(EResult::Done);
  638. });
  639. }
  640. void FWwiseFileState::UnloadFromSoundEngineDefer(FUnloadFromSoundEngineCallback&& InCallback)
  641. {
  642. AsyncOp(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileState::UnloadFromSoundEngineDefer"), [this, InCallback = MoveTemp(InCallback)]() mutable
  643. {
  644. if (UNLIKELY(State != EState::Unloading && State != EState::WillReload))
  645. {
  646. UE_LOG(LogWwiseFileHandler, Error, TEXT("FWwiseFileState::UnloadFromSoundEngineDefer %s %" PRIu32 ": Deferring unloading while not in Unloading state"), GetManagingTypeName(), GetShortId());
  647. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileState::UnloadFromSoundEngineDefer %s Callback"), GetManagingTypeName());
  648. InCallback(EResult::Done);
  649. return;
  650. }
  651. if (UNLIKELY(State == EState::WillReload))
  652. {
  653. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::UnloadFromSoundEngineDefer %s %" PRIu32 ": WillReload -> Loaded"), GetManagingTypeName(), GetShortId());
  654. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileState::UnloadFromSoundEngineDefer %s Callback"), GetManagingTypeName());
  655. State = EState::Loaded;
  656. InCallback(EResult::Done);
  657. return;
  658. }
  659. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::UnloadFromSoundEngineDefer %s %" PRIu32 ": Deferring Unload"), GetManagingTypeName(), GetShortId());
  660. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileState::UnloadFromSoundEngineDefer %s Callback"), GetManagingTypeName());
  661. InCallback(EResult::Deferred);
  662. });
  663. }
  664. bool FWwiseFileState::CanCloseFile() const
  665. {
  666. return State == EState::Opened && LoadCount == 0;
  667. }
  668. void FWwiseFileState::CloseFileDone(FCloseFileCallback&& InCallback)
  669. {
  670. AsyncOp(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileState::CloseFileDone"), [this, InCallback = MoveTemp(InCallback)]() mutable
  671. {
  672. if (UNLIKELY(State != EState::Closing && State != EState::WillReopen))
  673. {
  674. UE_LOG(LogWwiseFileHandler, Error, TEXT("FWwiseFileState::CloseFileDone %s %" PRIu32 ": Done closing while not in Closing state"), GetManagingTypeName(), GetShortId());
  675. }
  676. else if (LIKELY(State == EState::Closing))
  677. {
  678. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::CloseFileDone %s %" PRIu32 ": Closing -> Closed"), GetManagingTypeName(), GetShortId());
  679. State = EState::Closed;
  680. }
  681. else
  682. {
  683. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::CloseFileDone %s %" PRIu32 ": WillReopen -> CanReopen"), GetManagingTypeName(), GetShortId());
  684. State = EState::CanReopen;
  685. ProcessLaterOpQueue();
  686. }
  687. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileState::CloseFileDone %s Callback"), GetManagingTypeName());
  688. InCallback(EResult::Done);
  689. });
  690. }
  691. void FWwiseFileState::CloseFileDefer(FCloseFileCallback&& InCallback)
  692. {
  693. AsyncOp(WWISEFILEHANDLER_ASYNC_NAME("FWwiseFileState::CloseFileDone"), [this, InCallback = MoveTemp(InCallback)]() mutable
  694. {
  695. if (UNLIKELY(State != EState::Closing && State != EState::WillReopen))
  696. {
  697. UE_LOG(LogWwiseFileHandler, Error, TEXT("FWwiseFileState::CloseFileDefer %s %" PRIu32 ": Deferring closing while not in Closing state"), GetManagingTypeName(), GetShortId());
  698. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileState::CloseFileDefer %s Callback"), GetManagingTypeName());
  699. InCallback(EResult::Done);
  700. return;
  701. }
  702. if (UNLIKELY(State == EState::WillReopen))
  703. {
  704. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::CloseFileDefer %s %" PRIu32 ": WillReopen -> Opened"), GetManagingTypeName(), GetShortId());
  705. State = EState::Opened;
  706. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileState::CloseFileDefer %s Callback"), GetManagingTypeName());
  707. InCallback(EResult::Done);
  708. return;
  709. }
  710. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::CloseFileDefer %s %" PRIu32 ": Deferring Close"), GetManagingTypeName(), GetShortId());
  711. SCOPED_WWISEFILEHANDLER_EVENT_F_4(TEXT("FWwiseFileState::CloseFileDefer %s Callback"), GetManagingTypeName());
  712. InCallback(EResult::Deferred);
  713. });
  714. }
  715. bool FWwiseFileState::IsBusy() const
  716. {
  717. switch (State)
  718. {
  719. case EState::Opening:
  720. case EState::Loading:
  721. case EState::Unloading:
  722. case EState::Closing:
  723. case EState::WillReload:
  724. case EState::WillReopen:
  725. return true;
  726. default:
  727. return false;
  728. }
  729. }
  730. void FWwiseFileState::AsyncOp(const TCHAR* InDebugName, FBasicFunction&& Fct)
  731. {
  732. if (UNLIKELY(!FileStateExecutionQueue))
  733. {
  734. UE_LOG(LogWwiseFileHandler, Error, TEXT("FWwiseFileState::AsyncOp %s %" PRIu32 ": Doing async op on terminated state"), GetManagingTypeName(), GetShortId());
  735. return Fct();
  736. }
  737. FileStateExecutionQueue->Async(InDebugName, MoveTemp(Fct));
  738. }
  739. void FWwiseFileState::AsyncOpLater(const TCHAR* InDebugName, FBasicFunction&& Fct)
  740. {
  741. LaterOpQueue.Enqueue(FOpQueueItem(InDebugName, MoveTemp(Fct)));
  742. }
  743. void FWwiseFileState::ProcessLaterOpQueue()
  744. {
  745. int Count = 0;
  746. for (FOpQueueItem* Op; (Op = LaterOpQueue.Peek()) != nullptr; LaterOpQueue.Pop())
  747. {
  748. ++Count;
  749. #if ENABLE_NAMED_EVENTS
  750. AsyncOp(Op->DebugName, MoveTemp(Op->Function));
  751. #else
  752. AsyncOp(nullptr, MoveTemp(Op->Function));
  753. #endif
  754. }
  755. UE_CLOG(Count > 0, LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseFileState::ProcessLaterOpQueue %s %" PRIu32 ": Added back %d operations to be executed."), GetManagingTypeName(), GetShortId(), Count);
  756. }