AkStreamMgrModule.h 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. /*******************************************************************************
  2. The content of this file includes portions of the AUDIOKINETIC Wwise Technology
  3. released in source code form as part of the SDK installer package.
  4. Commercial License Usage
  5. Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology
  6. may use this file in accordance with the end user license agreement provided
  7. with the software or, alternatively, in accordance with the terms contained in a
  8. written agreement between you and Audiokinetic Inc.
  9. Apache License Usage
  10. Alternatively, this file may be used under the Apache License, Version 2.0 (the
  11. "Apache License"); you may not use this file except in compliance with the
  12. Apache License. You may obtain a copy of the Apache License at
  13. http://www.apache.org/licenses/LICENSE-2.0.
  14. Unless required by applicable law or agreed to in writing, software distributed
  15. under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
  16. OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for
  17. the specific language governing permissions and limitations under the License.
  18. Copyright (c) 2023 Audiokinetic Inc.
  19. *******************************************************************************/
  20. /// \file
  21. /// Audiokinetic's implementation-specific definitions and factory of
  22. /// overridable Stream Manager module.
  23. /// Contains the default Stream Manager's implementation-specific interfaces that altogether constitute
  24. /// the Low-Level I/O submodule. This submodule needs to be implemented by the game. All I/O requests
  25. /// generated by the Stream Manager end up to one of the I/O hooks defined herein.
  26. /// Read \ref streamingmanager_lowlevel to learn more about the Low-Level I/O.
  27. #ifndef _AK_STREAM_MGR_MODULE_H_
  28. #define _AK_STREAM_MGR_MODULE_H_
  29. #include <AK/SoundEngine/Common/IAkStreamMgr.h>
  30. #include <AK/Tools/Common/AkPlatformFuncs.h>
  31. class CAkFilePackage;
  32. /// \name Audiokinetic Stream Manager's implementation-specific definitions.
  33. //@{
  34. /// Stream Manager initialization settings.
  35. /// \sa
  36. /// - AK::IAkStreamMgr
  37. /// - AK::StreamMgr::Create()
  38. /// - \ref streamingmanager_settings
  39. struct AkStreamMgrSettings
  40. {
  41. };
  42. /// High-level IO devices initialization settings.
  43. /// \sa
  44. /// - AK::IAkStreamMgr
  45. /// - AK::StreamMgr::CreateDevice()
  46. /// - \ref streamingmanager_settings
  47. struct AkDeviceSettings
  48. {
  49. void * pIOMemory; ///< Pointer for I/O memory allocated by user.
  50. ///< Pass NULL if you want memory to be allocated via AK::MemoryMgr::Malign().
  51. ///< If specified, uIOMemorySize, uIOMemoryAlignment and ePoolAttributes are ignored.
  52. AkUInt32 uIOMemorySize; ///< Size of memory for I/O (for automatic streams). It is passed directly to AK::MemoryMgr::Malign(), after having been rounded down to a multiple of uGranularity.
  53. AkUInt32 uIOMemoryAlignment; ///< I/O memory alignment. It is passed directly to AK::MemoryMgr::Malign().
  54. AkUInt32 ePoolAttributes; ///< Attributes for I/O memory. Here, specify the allocation type (AkMemType_Device, and so on). It is passed directly to AK::MemoryMgr::Malign().
  55. AkUInt32 uGranularity; ///< I/O requests granularity (typical bytes/request).
  56. AkUInt32 uSchedulerTypeFlags; ///< Scheduler type flags.
  57. AkThreadProperties threadProperties; ///< Scheduler thread properties.
  58. AkReal32 fTargetAutoStmBufferLength; ///< Targetted automatic stream buffer length (ms). When a stream reaches that buffering, it stops being scheduled for I/O except if the scheduler is idle.
  59. AkUInt32 uMaxConcurrentIO; ///< Maximum number of transfers that can be sent simultaneously to the Low-Level I/O.
  60. bool bUseStreamCache; ///< If true, the device attempts to reuse I/O buffers that have already been streamed from disk. This is particularly useful when streaming small looping sounds. However, there is a small increase in CPU usage when allocating memory, and a slightly larger memory footprint in the StreamManager pool.
  61. AkUInt32 uMaxCachePinnedBytes; ///< Maximum number of bytes that can be "pinned" using AK::SoundEngine::PinEventInStreamCache() or AK::IAkStreamMgr::PinFileInCache()
  62. };
  63. /// \name Scheduler type flags.
  64. /// Requests to Low-Level IO are synchronous. The streaming device expects a blocking I/O hook at creation time (IAkIOHookBlocking interface, see CreateDevice()).
  65. /// Functions of this interface should return only when the transfer is complete.
  66. #define AK_SCHEDULER_BLOCKING (0x01)
  67. /// Requests to Low-Level IO are asynchronous, but posted one after the other, starting with streams that need data the most.
  68. /// The streaming device expects a deferred I/O hook at creation time (IAkIOHookDeferredBatch interface, see CreateDevice()).
  69. /// Up to AkDeviceSettings::uMaxConcurrentIO requests can be sent to the Low-Level I/O at the same time.
  70. #define AK_SCHEDULER_DEFERRED_LINED_UP (0x02)
  71. /// File descriptor. File identification for the low-level I/O.
  72. /// \sa
  73. /// - AK::StreamMgr::IAkLowLevelIOHook
  74. struct AkFileDesc
  75. {
  76. AkInt64 iFileSize; ///< File size in bytes
  77. AkUInt64 uSector; ///< Start sector (the sector size is specified by the low-level I/O)
  78. ///< \sa
  79. ///< - AK::StreamMgr::IAkFileLocationResolver::Open()
  80. ///< - AK::StreamMgr::IAkLowLevelIOHook::GetBlockSize()
  81. AkUInt32 uCustomParamSize; ///< Size of the custom parameter
  82. void * pCustomParam; ///< Custom parameter
  83. AkFileHandle hFile; ///< File handle/identifier
  84. AkDeviceID deviceID; ///< Device ID, obtained from CreateDevice() \sa AK::IAkStreamMgr::CreateDevice()
  85. CAkFilePackage* pPackage; ///< If this file is in a File Package, this will be the
  86. };
  87. /// Structure for synchronous transfers handshaking with the Low-Level I/O. Used with blocking I/O hooks.
  88. /// \sa AK::StreamMgr::IAkIOHookBlocking
  89. struct AkIOTransferInfo
  90. {
  91. AkUInt64 uFilePosition; ///< File offset where transfer should begin.
  92. AkUInt32 uBufferSize; ///< Size of the buffer in which the I/O hook can write to.
  93. AkUInt32 uRequestedSize; ///< Exact number of requested bytes for this transfer. Always equal to or smaller than uBufferSize.
  94. };
  95. struct AkAsyncIOTransferInfo;
  96. /// Callback function prototype definition used for asynchronous I/O transfers between the Stream Manager
  97. /// and the Low-Level IO. Used with deferred I/O hooks.
  98. /// Notes:
  99. /// - If you pass in_eResult of AK_Fail, all streams awaiting for this transfer are marked as invalid and will stop. An "IO error" notification is posted to the capture log.
  100. /// - If the transfer was cancelled by the Stream Manager while it was in the Low-Level IO, you must return AK_Success, whether
  101. /// you performed the operation or not. The Stream Manager knows that it was cancelled, so it will not try to use it after you call it back.
  102. /// \sa
  103. /// - AkAsyncIOTransferInfo
  104. /// - AK::StreamMgr::IAkIOHookDeferredBatch
  105. AK_CALLBACK( void, AkIOCallback )(
  106. AkAsyncIOTransferInfo * in_pTransferInfo, ///< Pointer to the AkAsyncIOTransferInfo structure that was passed to corresponding Read() or Write() call.
  107. AKRESULT in_eResult ///< Result of transfer: AK_Success or AK_Fail (streams waiting for this transfer become invalid).
  108. );
  109. /// Callback function prototype definition used for asynchronous I/O transfers between the Stream Manager
  110. /// and the Low-Level IO. Used with batch deferred I/O hooks.
  111. /// Notes:
  112. /// - in_peResult and in_ppTransferInfo must both contain in_uNumTransfers number of elements
  113. /// - For each in_peResult with a value of AK_Fail, all streams awaiting for the corresponding transfer are marked as invalid and will stop. An "IO error" notification is posted to the capture log.
  114. /// - If a given transfer was cancelled by the Stream Manager while it was in the Low-Level IO, you must return AK_Success for that result, whether
  115. /// you performed the operation or not. The Stream Manager knows that it was cancelled, so it will not try to use it after you call it back.
  116. /// - Note that one call to BatchRead, BatchWrite or BatchCancel does not have to result in one execution of the callback. The only requirement is that
  117. /// each element of in_ppTransferInfo passed in only has the IOCallback fired on it one time.
  118. /// \sa
  119. /// - AkAsyncIOTransferInfo
  120. /// - AK::StreamMgr::IAkIOHookDeferredBatch
  121. AK_CALLBACK(void, AkBatchIOCallback)(
  122. AkUInt32 in_uNumTransfers, ///< Number of transfers to process
  123. AkAsyncIOTransferInfo** in_ppTransferInfo, ///< List of pointers to AkAsyncIOTransferInfo structures that were previously passed in to BatchRead() or BatchWrite()
  124. AKRESULT* in_peResult ///< Array of results of each transfer: AK_Success or AK_Fail (streams waiting for this transfer become invalid).
  125. );
  126. /// Structure for asynchronous transfers handshaking with the Low-Level I/O. Extends AkIOTransferInfo.
  127. /// \sa
  128. /// - AK::StreamMgr::IAkIOHookDeferredBatch
  129. /// - AkIOTransferInfo
  130. /// - AkAIOCallback
  131. struct AkAsyncIOTransferInfo : public AkIOTransferInfo
  132. {
  133. void * pBuffer; ///< Buffer for data transfer.
  134. AkIOCallback pCallback; ///< Callback function used to notify the high-level device when the transfer is complete.
  135. void * pCookie; ///< Reserved. The I/O device uses this cookie to retrieve the owner of the transfer.
  136. void * pUserData; ///< Custom user data.
  137. };
  138. /// Low-Level I/O requests heuristics.
  139. /// Used for asynchronous read requests.
  140. /// \sa
  141. /// - AK::StreamMgr::IAkIOHookBlocking::Read()
  142. /// - AK::StreamMgr::IAkIOHookBlocking::Write()
  143. /// - AK::StreamMgr::IAkIOHookDeferredBatch::Read()
  144. /// - AK::StreamMgr::IAkIOHookDeferredBatch::Write()
  145. struct AkIoHeuristics
  146. {
  147. AkReal32 fDeadline; ///< Operation deadline (ms).
  148. AkPriority priority; ///< Operation priority (at the time it was scheduled and sent to the Low-Level I/O). Range is [AK_MIN_PRIORITY,AK_MAX_PRIORITY], inclusively.
  149. };
  150. //@}
  151. namespace AK
  152. {
  153. /// Audiokinetic Stream Manager's implementation-specific interfaces of the Low-Level IO submodule.
  154. namespace StreamMgr
  155. {
  156. /// Base interface for Low-Level I/O hooks. Defines common methods across both types of hooks.
  157. class IAkLowLevelIOHook
  158. {
  159. protected:
  160. /// Virtual destructor on interface to avoid warnings.
  161. virtual ~IAkLowLevelIOHook(){}
  162. public:
  163. /// Cleans up a file.
  164. /// \return AK_Success if the file was properly cleaned-up.
  165. virtual AKRESULT Close(
  166. AkFileDesc & in_fileDesc ///< File descriptor.
  167. ) = 0;
  168. /// Returns the block size for the file or its storage device.
  169. /// The block size is a constraint for clients
  170. /// of the Stream Manager: All reads, writes and position changes need to be a multiple of
  171. /// that size.
  172. /// \return
  173. /// The block size for a specific file or storage device.
  174. /// \remarks
  175. /// - Some files might be opened with flags that require I/O transfers to be a multiple
  176. /// of this size. The stream manager will query this function to resolve calls
  177. /// to IAk(Auto)Stream::GetBlockSize( ).
  178. /// - Also, AkFileDesc::uSector specifies a number of sectors in multiples of this value.
  179. /// - Files/IO devices that do not require byte alignment should return 1.
  180. /// - Whether file opening was deferred or not, GetBlockSize() is always called right
  181. /// after the first call to Open(), in the client's thread, and is never called again.
  182. /// \warning
  183. /// Returning 0 is not allowed and will likely make the Stream Manager crash.
  184. /// \sa
  185. /// - AK::StreamMgr::IAkFileLocationResolver::Open()
  186. /// - AK::StreamMgr::IAkIOHookBlocking::Read()
  187. /// - AK::StreamMgr::IAkIOHookBlocking::Write()
  188. /// - AK::StreamMgr::IAkIOHookDeferredBatch::Read()
  189. /// - AK::StreamMgr::IAkIOHookDeferredBatch::Write()
  190. virtual AkUInt32 GetBlockSize(
  191. AkFileDesc & in_fileDesc ///< File descriptor.
  192. ) = 0;
  193. /// Returns a description for the streaming device above this low-level hook.
  194. /// \remarks For profiling purposes only. The Release configuration of the
  195. /// Stream Manager never calls it.
  196. virtual void GetDeviceDesc(
  197. AkDeviceDesc & out_deviceDesc ///< Device description.
  198. ) = 0;
  199. /// Returns custom profiling data for the streaming device above this low-level hook.
  200. /// As opposed to GetDeviceDesc(), this is called at every monitoring frame.
  201. /// You may implement this function in order to display any value you find useful
  202. /// in the "Streaming Devices" tab of the Wwise profiler ("Custom Param" column).
  203. /// \remarks For profiling purposes only. The Release configuration of the
  204. /// Stream Manager never calls it.
  205. /// \return A 32-bit unsigned value to display in the Wwise profiler.
  206. virtual AkUInt32 GetDeviceData() = 0;
  207. };
  208. /// Interface for blocking low-level I/O transfers. Used by streaming devices created with the
  209. /// AK_SCHEDULER_BLOCKING flag.
  210. /// This is the simplest I/O hook. Calls to Read()/Write() must block until they are completed.
  211. /// The streaming device's I/O thread sends one transfer at a time.
  212. class IAkIOHookBlocking : public IAkLowLevelIOHook
  213. {
  214. protected:
  215. /// Virtual destructor on interface to avoid warnings.
  216. virtual ~IAkIOHookBlocking(){}
  217. public:
  218. /// Reads data from a file (synchronous).
  219. /// Read data from the file described by in_fileDesc, in address out_pBuffer and with size and position
  220. /// passed within io_transferInfo. When transfer is complete, return with the proper return code.
  221. /// \remarks
  222. /// File position passed in io_transferInfo takes the offset of this file relative
  223. /// to AkFileDesc::hFile (described with AkFileDesc::uSector). It is computed by the high-level
  224. /// device as "in_fileDesc.uSector * Block_Size + Stream_Position", where Block_Size is obtained
  225. /// via AK::StreamMgr::IAkLowLevelIOHook::GetBlockSize().
  226. /// \return
  227. /// - AK_Success: transfer was successful and out_pBuffer is filled with data.
  228. /// - AK_Fail: an error occured.
  229. virtual AKRESULT Read(
  230. AkFileDesc & in_fileDesc, ///< File descriptor.
  231. const AkIoHeuristics & in_heuristics, ///< Heuristics for this data transfer.
  232. void * out_pBuffer, ///< Buffer to be filled with data.
  233. AkIOTransferInfo & in_transferInfo ///< Synchronous data transfer info.
  234. ) = 0;
  235. /// Writes data to a file (synchronous).
  236. /// Write data to the file described by in_fileDesc, from address in_pData and with size and position
  237. /// passed within io_transferInfo. When transfer is complete, return with the proper return code.
  238. /// \remarks File position passed in io_transferInfo takes the offset of this file relative
  239. /// to AkFileDesc::hFile (described with AkFileDesc::uSector). It is computed by the high-level
  240. /// device as "in_fileDesc.uSector * Block_Size + Stream_Position", where Block_Size is obtained
  241. /// via AK::StreamMgr::IAkLowLevelIOHook::GetBlockSize().
  242. /// \return
  243. /// - AK_Success: transfer was successful.
  244. /// - AK_Fail: an error occured.
  245. virtual AKRESULT Write(
  246. AkFileDesc & in_fileDesc, ///< File descriptor.
  247. const AkIoHeuristics & in_heuristics, ///< Heuristics for this data transfer.
  248. void * in_pData, ///< Data to be written.
  249. AkIOTransferInfo & io_transferInfo ///< Synchronous data transfer info.
  250. ) = 0;
  251. };
  252. /// Interface for batched deferred low-level I/O transfers. Used by streaming devices created
  253. /// with the AK_SCHEDULER_DEFERRED_LINED_UP flag.
  254. /// This I/O transfer handshaking method is preferred when you want to hook I/O to your own
  255. /// I/O streaming technology, and you want to submit multiple I/O requests in one call, so as
  256. /// to allow for better opportunities for CPU and I/O performance.
  257. /// You may queue them into your own system, and even use the heuristics passed down to this
  258. /// level for your convenience. Note that the requests are always sent in the order that the
  259. /// Stream Manager considers to be the most appropriate. You may receive less than
  260. /// AkDeviceSettings::uMaxConcurrentIO at any given time. The number of concurrent transfers
  261. /// depends on the number of streams running in the high-level streaming device, and on its
  262. /// target buffering length and granularity. Your advantage at this level is to be aware of
  263. /// file placement, so you may try to re-order requests in order to minimize seeking on disk.
  264. /// Calls to BatchRead()/BatchWrite() should return as soon as possible. You need to call
  265. /// AkAsyncIOTransferInfo::pCallback for an individual item, or AkBatchIOCallback for a collection
  266. /// of items as soon as a transfer is completed.
  267. /// Cancel() is provided in order to inform you that the streaming device will flush this transfer
  268. /// upon completion. You may implement it or not. In all cases, you must call the callback.
  269. class IAkIOHookDeferredBatch : public IAkLowLevelIOHook
  270. {
  271. protected:
  272. /// Virtual destructor on interface to avoid warnings.
  273. virtual ~IAkIOHookDeferredBatch() {}
  274. public:
  275. struct BatchIoTransferItem
  276. {
  277. AkFileDesc* pFileDesc;
  278. AkIoHeuristics ioHeuristics;
  279. AkAsyncIOTransferInfo* pTransferInfo;
  280. };
  281. /// Reads multiple data from multiple files (asynchronous).
  282. /// \remarks
  283. /// - Queue up multiple read requests at once, using the provided array of in_pTransferItems. There will
  284. /// be in_uNumTransfers number of items in the array.
  285. /// - io_pDispatchResults will contain an in_uNumTransfers number of items in the array. Each item in
  286. /// io_pDispatchResults should be set to AK_Success if the corresponding Read was successfully dispatched,
  287. /// and set to AK_Failure otherwise. As well, the return value should be a cumulative result of the
  288. /// dispatches, where AK_Success indicates all requests were dispatched successfully, and
  289. /// io_pDispatchResults will not be investigated, whereas AK_Fail indicates at least one failure.
  290. /// - When a given Read, or some set of reads has completed - whether it was successful, cancelled,
  291. /// or failed - call in_pBatchIoCallback for the corresponding transfer. Pass in the list of
  292. /// AkAsyncIOTransferInfo objects to receive the callback, as well as a list of results for each transfer,
  293. /// e.g. AK_Success or some other AKRESULT. Do not call in_pBatchIoCallback for transfers that were not
  294. /// dispatched (as indicated by the corresponding value in io_pDispatchResults).
  295. /// - The pointer to each BatchIoTransferItem::pTransferInfo will be valid until the high-level
  296. /// device is notified through the callback. The array of in_pTransferItems will not be valid, though.
  297. /// - File position passed in each BatchIoTransferItem::pTransferInfo takes the offset of this file relative
  298. /// to AkFileDesc::hFile (described with AkFileDesc::uSector). It is computed by the high-level
  299. /// device as "pFileDesc->uSector * Block_Size + Stream_Position", where Block_Size is obtained
  300. /// via AK::StreamMgr::IAkLowLevelIOHook::GetBlockSize().
  301. ///
  302. /// \return
  303. /// - AK_Success: All I/O requests were successfully dispatched.
  304. /// in_pBatchIoCallback must be called for each read that completes.
  305. /// - AK_Fail: At least one failure occurred when dispatching reads.
  306. /// The values of io_pDispatchResults should indicate which operation failed to be dispatched.
  307. virtual AKRESULT BatchRead(
  308. AkUInt32 in_uNumTransfers, ///< Number of transfers to process
  309. BatchIoTransferItem* in_pTransferItems, ///< List of transfer items to process
  310. AkBatchIOCallback in_pBatchIoCallback, ///< Callback to execute to handle completion of multiple items simultaneously
  311. AKRESULT* io_pDispatchResults ///< Output result codes to indicate if a transfer was successfully dispatched
  312. ) = 0;
  313. /// Write multiple data to multiple files (asynchronous).
  314. /// \remarks
  315. /// - Queue up multiple write requests at once, using the provided array of in_pTransferItems. There will
  316. /// be in_uNumTransfers number of items in the array.
  317. /// - io_pDispatchResults will contain an in_uNumTransfers number of items in the array. Each item in
  318. /// io_pDispatchResults should be set to AK_Success if the corresponding write was successfully dispatched,
  319. /// and set to AK_Failure otherwise. As well, the return value should be a cumulative result of the
  320. /// dispatches, where AK_Success indicates all requests were dispatched successfully, and
  321. /// io_pDispatchResults will not be investigated, whereas AK_Fail indicates at least one failure.
  322. /// - When a given write, or some set of writes has completed - whether it was successful, cancelled,
  323. /// or failed - call in_pBatchIoCallback for the corresponding transfer. Pass in the list of
  324. /// AkAsyncIOTransferInfo objects to receive the callback, as well as a list of results for each transfer,
  325. /// e.g. AK_Success or some other AKRESULT. Do not call in_pBatchIoCallback for transfers that were not
  326. /// dispatched (as indicated by the corresponding value in io_pDispatchResults).
  327. /// - The pointer to each BatchIoTransferItem::pTransferInfo will be valid until the high-level
  328. /// device is notified through the callback. The array of in_pTransferItems will not be valid, though.
  329. /// - File position passed in each BatchIoTransferItem::pTransferInfo takes the offset of this file relative
  330. /// to AkFileDesc::hFile (described with AkFileDesc::uSector). It is computed by the high-level
  331. /// device as "pFileDesc->uSector * Block_Size + Stream_Position", where Block_Size is obtained
  332. /// via AK::StreamMgr::IAkLowLevelIOHook::GetBlockSize().
  333. ///
  334. /// \return
  335. /// - AK_Success: All I/O requests were successfully dispatched.
  336. /// in_pBatchIoCallback must be called for each write that completes.
  337. /// - AK_Fail: At least one failure occurred when dispatching writes.
  338. /// The values of io_pDispatchResults should indicate which operation failed to be dispatched.
  339. virtual AKRESULT BatchWrite(
  340. AkUInt32 in_uNumTransfers, ///< Number of transfers to process
  341. BatchIoTransferItem* in_pTransferItems, ///< List of transfer items to process
  342. AkBatchIOCallback in_pBatchIoCallback, ///< Callback to execute to handle completion of multiple items simultaneously
  343. AKRESULT* io_pDispatchResults ///< Output result codes to indicate if a transfer was successfully dispatched
  344. ) = 0;
  345. /// Notifies that a transfer request is cancelled. It will be flushed by the streaming device when completed.
  346. /// Cancellation is normal and happens regularly; for example, whenever a sound stops before the end
  347. /// or stops looping. It happens even more frequently when buffering (AkDeviceSettings::fTargetAutoStmBufferLength
  348. /// and AkDeviceSettings::uGranularity) is large and when you low-level IO hook accepts many concurrent requests
  349. /// at the same time.
  350. /// \remarks
  351. /// - Cancel() simply informs the Low-Level I/O that a specific transfer will be flushed upon reception.
  352. /// The Low-Level I/O may use this information to stop this transfer right away, or not (it is internally tagged
  353. /// by the high-level device as cancelled). Nevertheless, the callback function MUST be called for cancelled
  354. /// transfers to be resolved.
  355. /// - When calling the callback function of a cancelled transfer, pass it *AK_Success*. Passing AK_Fail
  356. /// to AkAsyncIOTransfer::pCallback has the effect of killing the stream once and for all. This is not
  357. /// what you want.
  358. /// - If io_bCancelAllTransfersForThisFile is set, you may cancel all transfers for this file at once.
  359. /// Leave io_bCancelAllTransfersForThisFile to true if you don't want to be called again. For example, if
  360. /// you don't do anything special in Cancel(), leave it to true. This will reduce the amount of useless calls.
  361. /// If you set it to false, Cancel() will be called again for each remaining pending transfer that need to be cancelled.
  362. /// - If io_bCancelAllTransfersForThisFile is not set, Cancel() is only called for a subset of pending
  363. /// transfers for this file. You must not set it to true, as Cancel() needs to be called explicitly for each transfer that should be cancelled.
  364. /// \warning
  365. /// - The calling thread holds the stream's lock. You may call the callback function directly from here
  366. /// (if you can guarantee that the I/O buffer will not be accessed in the meantime), but you must not wait here
  367. /// for another thread to call the callback function.
  368. /// - Likewise, if you resolve transfers with your own thread and use a lock to protect your transfers queue,
  369. /// be careful not to run into a deadlock. Cancel() can be executed by any thread. Thus, if you need to lock your queue
  370. /// in Cancel(), you must never hold this lock when calling back transfers, either from within Cancel() or from your
  371. /// worker thread's routine. Lock your list, dequeue the transfer if you can, unlock, and call pCallback if and only if
  372. /// the transfer was found and dequeued. On the other hand, if you choose not to do anything in Cancel(), the lock only protects
  373. /// your list between Read()/Write() and your worker thread's routine, and since the device I/O thread does not hold the
  374. /// stream's lock while calling Read()/Write(), your worker thread may therefore hold it while calling back transfers.
  375. /// - A race condition exists when cancelling all transfers (io_bCancelAllTransfersForThisFile is true) directly from within this hook.
  376. /// If you handle the io_bCancelAllTransfersForThisFile == true case, you need to defer calling the completion callback to later
  377. /// (from your usual I/O completion thread, for example). This will be fixed in a future version of Wwise.
  378. virtual void BatchCancel(
  379. AkUInt32 in_uNumTransfers, ///< Number of transfers to process
  380. BatchIoTransferItem* in_pTransferItems, ///< List of transfer items to process
  381. bool** io_ppbCancelAllTransfersForThisFile ///< Flag for each transfer indicating whether all transfers should be cancelled for this file (see notes in function description).
  382. ) = 0;
  383. };
  384. /// Interface for deferred low-level I/O transfers. Used by streaming devices created with the
  385. /// AK_SCHEDULER_DEFERRED_LINED_UP flag.
  386. /// This is an "adapter" interface to forward calls to IAkIOHookDeferredBatch, to maintain
  387. /// compatibility with existing implementations, as well as provide a simpler interface for new
  388. /// implementations.
  389. /// This I/O transfer handshaking method is preferred when you want to hook I/O to your own
  390. /// I/O streaming technology. You will receive up to AkDeviceSettings::uMaxConcurrentIO requests
  391. /// at the same time. You may queue them into your own system, and even use the heuristics passed
  392. /// down to this level for your convenience.
  393. /// Note that the requests are always sent in the order that the Stream Manager considers to be
  394. /// the most appropriate. You may receive less than AkDeviceSettings::uMaxConcurrentIO at any
  395. /// given time. The number of concurrent transfers depends on the number of streams running in
  396. /// the high-level streaming device, and on its target buffering length and granularity.
  397. /// Your advantage at this level is to be aware of file placement, so you may try to re-order
  398. /// requests in order to minimize seeking on disk.
  399. /// Calls to Read()/Write() should return as soon as possible. You need to call
  400. /// AkAsyncIOTransferInfo::pCallback as soon as a transfer is completed.
  401. /// Cancel() is provided in order to inform you that the streaming device will flush this transfer
  402. /// upon completion. You may implement it or not. In all cases, you must call the callback.
  403. class IAkIOHookDeferred : public IAkIOHookDeferredBatch
  404. {
  405. protected:
  406. /// Virtual destructor on interface to avoid warnings.
  407. virtual ~IAkIOHookDeferred(){}
  408. public:
  409. /// Reads data from a file (asynchronous).
  410. /// \remarks
  411. /// - Queue up your read request with address, size and file position specified in io_transferInfo.
  412. /// - When transfer is complete (whether it was successful, cancelled or failed), call
  413. /// AkAsyncIOTransferInfo::pCallback. However, if you return AK_Fail() from Read(), do not call
  414. /// AkAsyncIOTransferInfo::pCallback.
  415. /// - AkAsyncIOTransferInfo::pCookie must be passed to the callback function as-is. It must not
  416. /// be changed by the Low-Level I/O.
  417. /// - The reference to io_transferInfo will be valid until the high-level device is notified
  418. /// through the callback.
  419. /// - File position passed in io_transferInfo takes the offset of this file relative
  420. /// to AkFileDesc::hFile (described with AkFileDesc::uSector). It is computed by the high-level
  421. /// device as "in_fileDesc.uSector * Block_Size + Stream_Position", where Block_Size is obtained
  422. /// via AK::StreamMgr::IAkLowLevelIOHook::GetBlockSize().
  423. /// \return
  424. /// - AK_Success: An I/O request was successfully dispatched and is pending:
  425. /// AkAsyncIOTransferInfo::pCallback must be called when it completes.
  426. /// - AK_Fail: An error occurred, no I/O request was dispatched
  427. virtual AKRESULT Read(
  428. AkFileDesc & in_fileDesc, ///< File descriptor.
  429. const AkIoHeuristics & in_heuristics, ///< Heuristics for this data transfer.
  430. AkAsyncIOTransferInfo & io_transferInfo ///< Asynchronous data transfer info.
  431. ) = 0;
  432. /// Writes data to a file (asynchronous).
  433. /// \remarks
  434. /// - Queue up your write request with address, size and file position specified in io_transferInfo.
  435. /// - When transfer is complete (whether it was successful, cancelled or failed), call
  436. /// AkAsyncIOTransferInfo::pCallback. However, if you return AK_Fail() from Write(), do not call
  437. /// AkAsyncIOTransferInfo::pCallback.
  438. /// - AkAsyncIOTransferInfo::pCookie must be passed to the callback function as-is. It must not
  439. /// be changed by the Low-Level I/O.
  440. /// - The reference to io_transferInfo will be valid until the high-level device is notified
  441. /// through the callback.
  442. /// - File position passed in io_transferInfo takes the offset of this file relative
  443. /// to AkFileDesc::hFile (described with AkFileDesc::uSector). It is computed by the high-level
  444. /// device as "in_fileDesc.uSector * Block_Size + Stream_Position", where Block_Size is obtained
  445. /// via AK::StreamMgr::IAkLowLevelIOHook::GetBlockSize().
  446. /// \return
  447. /// - AK_Success: An I/O request was successfully processed and is pending:
  448. /// AkAsyncIOTransferInfo::pCallback must be called when it completes.
  449. /// - AK_Fail: an error occured.
  450. virtual AKRESULT Write(
  451. AkFileDesc & in_fileDesc, ///< File descriptor.
  452. const AkIoHeuristics & in_heuristics, ///< Heuristics for this data transfer.
  453. AkAsyncIOTransferInfo & io_transferInfo ///< Platform-specific asynchronous IO operation info.
  454. ) = 0;
  455. /// Notifies that a transfer request is cancelled. It will be flushed by the streaming device when completed.
  456. /// Cancellation is normal and happens regularly; for example, whenever a sound stops before the end
  457. /// or stops looping. It happens even more frequently when buffering (AkDeviceSettings::fTargetAutoStmBufferLength
  458. /// and AkDeviceSettings::uGranularity) is large and when you low-level IO hook accepts many concurrent requests
  459. /// at the same time.
  460. /// \remarks
  461. /// - Cancel() simply informs the Low-Level I/O that a specific transfer will be flushed upon reception.
  462. /// The Low-Level I/O may use this information to stop this transfer right away, or not (it is internally tagged
  463. /// by the high-level device as cancelled). Nevertheless, the callback function MUST be called for cancelled
  464. /// transfers to be resolved.
  465. /// - When calling the callback function of a cancelled transfer, pass it *AK_Success*. Passing AK_Fail
  466. /// to AkAsyncIOTransfer::pCallback has the effect of killing the stream once and for all. This is not
  467. /// what you want.
  468. /// - If io_bCancelAllTransfersForThisFile is set, you may cancel all transfers for this file at once.
  469. /// Leave io_bCancelAllTransfersForThisFile to true if you don't want to be called again. For example, if
  470. /// you don't do anything special in Cancel(), leave it to true. This will reduce the amount of useless calls.
  471. /// If you set it to false, Cancel() will be called again for each remaining pending transfer that need to be cancelled.
  472. /// - If io_bCancelAllTransfersForThisFile is not set, Cancel() is only called for a subset of pending
  473. /// transfers for this file. You must not set it to true, as Cancel() needs to be called explicitly for each transfer that should be cancelled.
  474. /// \warning
  475. /// - The calling thread holds the stream's lock. You may call the callback function directly from here
  476. /// (if you can guarantee that the I/O buffer will not be accessed in the meantime), but you must not wait here
  477. /// for another thread to call the callback function.
  478. /// - Likewise, if you resolve transfers with your own thread and use a lock to protect your transfers queue,
  479. /// be careful not to run into a deadlock. Cancel() can be executed by any thread. Thus, if you need to lock your queue
  480. /// in Cancel(), you must never hold this lock when calling back transfers, either from within Cancel() or from your
  481. /// worker thread's routine. Lock your list, dequeue the transfer if you can, unlock, and call pCallback if and only if
  482. /// the transfer was found and dequeued. On the other hand, if you choose not to do anything in Cancel(), the lock only protects
  483. /// your list between Read()/Write() and your worker thread's routine, and since the device I/O thread does not hold the
  484. /// stream's lock while calling Read()/Write(), your worker thread may therefore hold it while calling back transfers.
  485. /// - A race condition exists when cancelling all transfers (io_bCancelAllTransfersForThisFile is true) directly from within this hook.
  486. /// If you handle the io_bCancelAllTransfersForThisFile == true case, you need to defer calling the completion callback to later
  487. /// (from your usual I/O completion thread, for example). This will be fixed in a future version of Wwise.
  488. virtual void Cancel(
  489. AkFileDesc & in_fileDesc, ///< File descriptor.
  490. AkAsyncIOTransferInfo & io_transferInfo, ///< Transfer info to cancel.
  491. bool & io_bCancelAllTransfersForThisFile ///< Flag indicating whether all transfers should be cancelled for this file (see notes in function description).
  492. ) = 0;
  493. /// The following functions each provide "stub" implementations of IAkHookDeferredIOBatch operations, so as to forward calls to
  494. /// the existing single-transfer variants. The soundengine never calls IAkHookDeferred::Read et al, internally, and only
  495. /// ever calls IAkIOHookDeferredBatch::BatchRead et al.
  496. virtual AKRESULT BatchRead(
  497. AkUInt32 in_uNumTransfers, ///< Number of transfers to process
  498. BatchIoTransferItem* in_pTransferItems, ///< List of transfer items to process
  499. AkBatchIOCallback /*in_pBatchIoCallback*/,///< Callback to execute to handle completion of multiple items simultaneously
  500. AKRESULT* io_pDispatchResults ///< Output result codes to indicate if a transfer was successfully dispatched
  501. )
  502. {
  503. AKRESULT cumulativeResult = AK_Success;
  504. for (AkUInt32 i = 0; i < in_uNumTransfers; ++i)
  505. {
  506. BatchIoTransferItem ioTransferItem = in_pTransferItems[i];
  507. AKRESULT result = Read(*(ioTransferItem.pFileDesc), ioTransferItem.ioHeuristics, *(ioTransferItem.pTransferInfo));
  508. io_pDispatchResults[i] = result;
  509. cumulativeResult = result == AK_Success ? cumulativeResult : AK_Fail;
  510. }
  511. return cumulativeResult;
  512. }
  513. virtual AKRESULT BatchWrite(
  514. AkUInt32 in_uNumTransfers, ///< Number of transfers to process
  515. BatchIoTransferItem* in_pTransferItems, ///< List of transfer items to process
  516. AkBatchIOCallback /*in_pBatchIoCallback*/,///< Callback to execute to handle completion of multiple items simultaneously
  517. AKRESULT* io_pDispatchResults ///< Output result codes to indicate if a transfer was successfully dispatched
  518. )
  519. {
  520. AKRESULT cumulativeResult = AK_Success;
  521. for (AkUInt32 i = 0; i < in_uNumTransfers; ++i)
  522. {
  523. BatchIoTransferItem ioTransferItem = in_pTransferItems[i];
  524. AKRESULT result = Write(*(ioTransferItem.pFileDesc), ioTransferItem.ioHeuristics, *(ioTransferItem.pTransferInfo));
  525. io_pDispatchResults[i] = result;
  526. cumulativeResult = result == AK_Success ? cumulativeResult : AK_Fail;
  527. }
  528. return cumulativeResult;
  529. }
  530. virtual void BatchCancel(
  531. AkUInt32 in_uNumTransfers, ///< Number of transfers to process
  532. BatchIoTransferItem* in_pTransferItems, ///< List of transfer items to process
  533. bool** io_ppbCancelAllTransfersForThisFile ///< Flag for each transfer indicating whether all transfers should be cancelled for this file (see notes in function description).
  534. )
  535. {
  536. for (AkUInt32 i = 0; i < in_uNumTransfers; ++i)
  537. {
  538. BatchIoTransferItem ioTransferItem = in_pTransferItems[i];
  539. Cancel(*(ioTransferItem.pFileDesc), *(ioTransferItem.pTransferInfo), *(io_ppbCancelAllTransfersForThisFile[i]));
  540. }
  541. }
  542. };
  543. /// File location resolver interface. There is one and only one File Location Resolver that is
  544. /// registered to the Stream Manager (using AK::StreamMgr::SetFileLocationResolver()). Its purpose
  545. /// is to map a file name or ID to
  546. /// 1) a streaming device / I/O hook;
  547. /// 2) a valid file descriptor (AkFileDesc) usable by the I/O hook.
  548. /// When your Low-Level I/O submodule uses a single device, you should create a standalone I/O
  549. /// hook which implements one of the I/O hooks defined above (blocking or deferred), as well
  550. /// as the File Location Resolver. You then register this object to the Stream Manager as the
  551. /// File Location Resolver.
  552. /// If you wish to create multiple devices, then you should have a separate object that implements
  553. /// AK::StreamMgr::IAkFileLocationResolver and registers to the Stream Manager as such. This object
  554. /// will be used to dispatch the file open request to the appropriate device. The strategy you will
  555. /// use to select the correct device is up to you to implement. You may also implement a set of
  556. /// hooks that delegate opening to the next device when they can't find the file requested
  557. /// (like a chain of responsiblity pattern), although this will likely be less efficient.
  558. class IAkFileLocationResolver
  559. {
  560. protected:
  561. /// Virtual destructor on interface to avoid warnings.
  562. virtual ~IAkFileLocationResolver(){}
  563. public:
  564. /// Returns a file descriptor for a given file name (string).
  565. /// Performs the operations needed to make the file descriptor usable by
  566. /// the other methods of the interface (for e.g. ask the OS for a valid file handle).
  567. /// \return
  568. /// - AK_Success: A valid file descriptor is returned
  569. /// - AK_FileNotFound: File was not found.
  570. /// - AK_Fail: File could not be open for any other reason.
  571. /// \return
  572. /// - A file descriptor, that contains
  573. /// - an unique identifier to be used with functions of the low-level IO
  574. /// interface.
  575. /// - the total stream size in bytes.
  576. /// - the offset from the beginning of the file (in blocks).
  577. /// - a device ID, that was obtained through AK::StreamMgr::CreateDevice().
  578. /// - The updated io_bSyncOpen flag depending on the File Resolver's deferred opening policy.
  579. /// \remarks
  580. /// - The file descriptor is unique for each stream, and its address remains the same
  581. /// throughout its lifetime. In other words, the value of &in_fileDesc inside Read() or
  582. /// Close() is the same as &out_fileDesc in Open().
  583. /// - Open() is always called first in the client thread.
  584. /// - If io_bSyncOpen is true, file opening must be executed now. If it is false,
  585. /// the File Location Resolver may choose whether it wants open it now, or later
  586. /// from the streaming device's thread. If it wishes to open it now, then it must
  587. /// set io_bSyncOpen to true. Otherwise, it needs to do the following: leave
  588. /// io_bSyncOpen to false, clear out_fileDesc::iFileSize and out_fileDesc::uSector,
  589. /// and set out_fileDesc::deviceID to the streaming device's ID that will handle
  590. /// this file. By returning io_bSyncOpen as false, the Stream Manager will interpret
  591. /// this as a request for deferred file opening, and this function will called again
  592. /// from the streaming device's thread (this time, with this io_bSyncOpen set to true).
  593. /// - All members of out_fileDesc will be cleared upon first call to Open().
  594. /// \warning
  595. /// - It is illegal to return io_bSyncOpen as false if Open() was called with io_bSyncOpen
  596. /// set to true.
  597. /// - Deferred file opening requires allocations in the Stream Manager's small object pool.
  598. /// The File Location Resolver should always choose to open files synchronously if it is
  599. /// fast to do so.
  600. /// - Whether opening is deferred or not, GetBlockSize() is always called right after the
  601. /// first call to Open(), in the client's thread, and is never called again.
  602. /// \sa
  603. /// - GetBlockSize()
  604. /// - \ref streamingmanager_lowlevel_location
  605. virtual AKRESULT Open(
  606. const AkOSChar* in_pszFileName, ///< File name.
  607. AkOpenMode in_eOpenMode, ///< Open mode.
  608. AkFileSystemFlags * in_pFlags, ///< Special flags. Can pass NULL.
  609. bool & io_bSyncOpen, ///< If true, the file must be opened synchronously. Otherwise it is left at the File Location Resolver's discretion. Return false if Open needs to be deferred.
  610. AkFileDesc & io_fileDesc ///< Returned file descriptor.
  611. ) = 0;
  612. /// Returns a file descriptor for a given file ID.
  613. /// Performs the operations needed to make the file descriptor usable by
  614. /// the other methods of the interface (for e.g. ask the OS for a valid file handle).
  615. /// \return
  616. /// - AK_Success: A valid file descriptor is returned
  617. /// - AK_FileNotFound: File was not found.
  618. /// - AK_Fail: File could not be open for any other reason.
  619. /// \return
  620. /// - A file descriptor, that contains
  621. /// - an unique identifier to be used with functions of the low-level IO
  622. /// interface.
  623. /// - the total stream size in bytes.
  624. /// - the offset from the beginning of the file (in blocks).
  625. /// - a device ID, that was obtained through AK::StreamMgr::CreateDevice().
  626. /// - The updated io_bSyncOpen flag depending on the File Resolver's deferred opening policy.
  627. /// \remarks
  628. /// - Open() is always called first in the client thread.
  629. /// - If io_bSyncOpen is true, file opening must be executed now. If it is false,
  630. /// the File Location Resolver may choose whether it wants open it now, or later
  631. /// from the streaming device's thread. If it wishes to open it now, then it must
  632. /// set io_bSyncOpen to true. Otherwise, it needs to do the following: leave
  633. /// io_bSyncOpen to false, clear out_fileDesc::iFileSize and out_fileDesc::uSector,
  634. /// and set out_fileDesc::deviceID to the streaming device's ID that will handle
  635. /// this file. By returning io_bSyncOpen as false, the Stream Manager will interpret
  636. /// this as a request for deferred file opening, and this function will called again
  637. /// from the streaming device's thread (this time, with this io_bSyncOpen set to true).
  638. /// - All members of out_fileDesc will be cleared upon first call to Open().
  639. /// \warning
  640. /// - It is illegal to return io_bSyncOpen as false if Open() was called with io_bSyncOpen
  641. /// set to true.
  642. /// - Deferred file opening requires allocations in the Stream Manager's small object pool.
  643. /// The File Location Resolver should always choose to open files synchronously if it is
  644. /// fast to do so.
  645. /// - Whether opening is deferred or not, GetBlockSize() is always called right after the
  646. /// first call to Open(), in the client's thread, and is never called again.
  647. /// - GetBlockSize()
  648. /// - \ref streamingmanager_lowlevel_location
  649. virtual AKRESULT Open(
  650. AkFileID in_fileID, ///< File ID.
  651. AkOpenMode in_eOpenMode, ///< Open mode.
  652. AkFileSystemFlags * in_pFlags, ///< Special flags. Can pass NULL.
  653. bool & io_bSyncOpen, ///< If true, the file must be opened synchronously. Otherwise it is left at the File Location Resolver's discretion. Return false if Open needs to be deferred.
  654. AkFileDesc & io_fileDesc ///< Returned file descriptor.
  655. ) = 0;
  656. /// <summary>
  657. /// This function is called to provide information when file related errors occur. The base paths known by this Resolver should be returned in out_searchedPath.
  658. /// </summary>
  659. virtual AKRESULT OutputSearchedPaths(
  660. const AKRESULT& in_result, ///< Result of the open call
  661. const AkOSChar* in_pszFileName, ///< File name that was accessed
  662. AkFileSystemFlags* in_pFlags, ///< Special flags. Can be NULL.
  663. AkOpenMode in_eOpenMode, ///< File open mode (read, write, ...).
  664. AkOSChar* out_searchedPath, ///< Pre-allocated string buffer to be filled with all searched paths searched for the file.
  665. AkInt32 in_pathSize ///< The maximum size of the string
  666. ) { return AK_NotImplemented; };
  667. virtual AKRESULT OutputSearchedPaths(
  668. const AKRESULT& in_result, ///< Result of the open call
  669. const AkFileID in_fileID, ///< File ID that was accessed
  670. AkFileSystemFlags* in_pFlags, ///< Special flags. Can be NULL.
  671. AkOpenMode in_eOpenMode, ///< File open mode (read, write, ...).
  672. AkOSChar* out_searchedPath, ///< Pre-allocated string buffer to be filled with all searched paths searched for the file.
  673. AkInt32 in_pathSize ///< The maximum size of the string
  674. ) { return AK_NotImplemented; };
  675. };
  676. /// \name Audiokinetic implementation-specific Stream Manager factory.
  677. //@{
  678. /// Stream Manager factory.
  679. /// \remarks
  680. /// - In order for the Stream Manager to work properly, you also need to create
  681. /// at least one streaming device (and implement its I/O hook), and register the
  682. /// File Location Resolver with AK::StreamMgr::SetFileLocationResolver().
  683. /// - Use AK::StreamMgr::GetDefaultSettings(), then modify the settings you want,
  684. /// then feed this function with them.
  685. /// \sa
  686. /// - AK::IAkStreamMgr
  687. /// - AK::StreamMgr::SetFileLocationResolver()
  688. /// - AK::StreamMgr::GetDefaultSettings()
  689. AK_EXTERNAPIFUNC( IAkStreamMgr *, Create )(
  690. const AkStreamMgrSettings & in_settings ///< Stream manager initialization settings.
  691. );
  692. /// Get the default values for the Stream Manager's settings.
  693. /// \sa
  694. /// - AK::StreamMgr::Create()
  695. /// - AkStreamMgrSettings
  696. /// - \ref streamingmanager_settings
  697. AK_EXTERNAPIFUNC( void, GetDefaultSettings )(
  698. AkStreamMgrSettings & out_settings ///< Returned AkStreamMgrSettings structure with default values.
  699. );
  700. /// Get the one and only File Location Resolver registered to the Stream Manager.
  701. /// \sa
  702. /// - AK::StreamMgr::IAkFileLocationResolver
  703. /// - AK::StreamMgr::SetFileLocationResolver()
  704. AK_EXTERNAPIFUNC( IAkFileLocationResolver *, GetFileLocationResolver )();
  705. /// Register the one and only File Location Resolver to the Stream Manager.
  706. /// \sa
  707. /// - AK::StreamMgr::IAkFileLocationResolver
  708. AK_EXTERNAPIFUNC( void, SetFileLocationResolver )(
  709. IAkFileLocationResolver * in_pFileLocationResolver ///< Interface to your File Location Resolver
  710. );
  711. //@}
  712. /// \name Stream Manager: High-level I/O devices management.
  713. //@{
  714. /// Streaming device creation.
  715. /// Creates a high-level device, with specific settings.
  716. /// You need to provide the associated low-level I/O hook, implemented on your side.
  717. /// \return The device ID. AK_INVALID_DEVICE_ID if there was an error and it could not be created.
  718. /// \warning
  719. /// - This function is not thread-safe.
  720. /// - Use a blocking hook (IAkIOHookBlocking) with SCHEDULER_BLOCKING devices, and a
  721. /// deferred hook (IAkIOHookDeferredBatch) with SCHEDULER_DEFERRED_LINED_UP devices (these flags are
  722. /// specified in the device settings (AkDeviceSettings). The pointer to IAkLowLevelIOHook is
  723. /// statically cast internally into one of these hooks. Implementing the wrong (or no) interface
  724. /// will result into a crash.
  725. /// \remarks
  726. /// - You may use AK::StreamMgr::GetDefaultDeviceSettings() first to get default values for the
  727. /// settings, change those you want, then feed the structure to this function.
  728. /// - The returned device ID should be kept by the Low-Level IO, to assign it to file descriptors
  729. /// in AK::StreamMgr::IAkFileLocationResolver::Open().
  730. /// \sa
  731. /// - AK::StreamMgr::IAkLowLevelIOHook
  732. /// - AK::StreamMgr::GetDefaultDeviceSettings()
  733. /// - \ref streamingmanager_settings
  734. AK_EXTERNAPIFUNC( AkDeviceID, CreateDevice )(
  735. const AkDeviceSettings & in_settings, ///< Device settings.
  736. IAkLowLevelIOHook * in_pLowLevelHook ///< Associated low-level I/O hook. Pass either a IAkIOHookBlocking or a IAkIOHookDeferredBatch interface, consistent with the type of the scheduler.
  737. );
  738. /// Streaming device destruction.
  739. /// \return AK_Success if the device was successfully destroyed.
  740. /// \warning This function is not thread-safe. No stream should exist for that device when it is destroyed.
  741. AK_EXTERNAPIFUNC( AKRESULT, DestroyDevice )(
  742. AkDeviceID in_deviceID ///< Device ID of the device to destroy.
  743. );
  744. /// Execute pending I/O operations on all created I/O devices.
  745. /// This should only be called in single-threaded environments where an I/O device cannot spawn a thread.
  746. /// \return AK_Success when called from an appropriate environment, AK_NotCompatible otherwise.
  747. /// \sa
  748. /// - AK::StreamMgr::CreateDevice()
  749. AK_EXTERNAPIFUNC( AKRESULT, PerformIO )();
  750. /// Get the default values for the streaming device's settings. Recommended usage
  751. /// is to call this function first, then pass the settings to AK::StreamMgr::CreateDevice().
  752. /// \sa
  753. /// - AK::StreamMgr::CreateDevice()
  754. /// - AkDeviceSettings
  755. /// - \ref streamingmanager_settings
  756. AK_EXTERNAPIFUNC( void, GetDefaultDeviceSettings )(
  757. AkDeviceSettings & out_settings ///< Returned AkDeviceSettings structure with default values.
  758. );
  759. //@}
  760. /// \name Language management.
  761. //@{
  762. /// Set the current language once and only once, here. The language name is stored in a static buffer
  763. /// inside the Stream Manager. In order to resolve localized (language-specific) file location,
  764. /// AK::StreamMgr::IAkFileLocationResolver implementations query this string. They may use it to
  765. /// construct a file path (for e.g. SDK/samples/SoundEngine/Common/AkFileLocationBase.cpp), or to
  766. /// find a language-specific file within a look-up table (for e.g. SDK/samples/SoundEngine/Common/AkFilePackageLUT.cpp).
  767. /// Pass a valid null-terminated string, without a trailing slash or backslash. Empty strings are accepted.
  768. /// You may register for language changes (see RegisterToLanguageChangeNotification()).
  769. /// After changing the current language, all observers are notified.
  770. /// \return AK_Success if successful (if language string has less than AK_MAX_LANGUAGE_NAME_SIZE characters). AK_Fail otherwise.
  771. /// \warning Not multithread safe.
  772. /// \sa
  773. /// - AK::StreamMgr::GetCurrentLanguage()
  774. /// - AK::StreamMgr::AddLanguageChangeObserver()
  775. AK_EXTERNAPIFUNC( AKRESULT, SetCurrentLanguage )(
  776. const AkOSChar * in_pszLanguageName ///< Language name.
  777. );
  778. /// Get the current language. The language name is stored in a static buffer inside the Stream Manager,
  779. /// with AK::StreamMgr::SetCurrentLanguage(). In order to resolve localized (language-specific) file location,
  780. /// AK::StreamMgr::IAkFileLocationResolver implementations query this string. They may use it to
  781. /// construct a file path (for e.g. SDK/samples/SoundEngine/Common/AkFileLocationBase.cpp), or to
  782. /// find a language-specific file within a look-up table (for e.g. SDK/samples/SoundEngine/Common/AkFilePackageLUT.cpp).
  783. /// \return Current language.
  784. /// \sa AK::StreamMgr::SetCurrentLanguage()
  785. AK_EXTERNAPIFUNC( const AkOSChar *, GetCurrentLanguage )();
  786. /// Definition of handlers for language change notifications.
  787. /// Called after SetCurrentLanguage() is called.
  788. /// \warning Do not call AddLanguageChangeObserver or SetCurrentLanguage from within your handler.
  789. /// \warning Not multithread safe.
  790. /// \sa
  791. /// - AK::StreamMgr::SetCurrentLanguage()
  792. /// - AK::StreamMgr::AddLanguageChangeObserver()
  793. AK_CALLBACK( void, AkLanguageChangeHandler )(
  794. const AkOSChar * const in_pLanguageName,///< New language name.
  795. void * in_pCookie ///< Cookie that was passed to AddLanguageChangeObserver().
  796. );
  797. /// Register to language change notifications.
  798. /// \return AK_Success if successful, AK_Fail otherwise (no memory or no cookie).
  799. /// \warning Not multithread safe.
  800. /// \sa
  801. /// - AK::StreamMgr::SetCurrentLanguage()
  802. /// - AK::StreamMgr::RemoveLanguageChangeObserver()
  803. AK_EXTERNAPIFUNC( AKRESULT, AddLanguageChangeObserver )(
  804. AkLanguageChangeHandler in_handler, ///< Callback function.
  805. void * in_pCookie ///< Cookie, passed back to AkLanguageChangeHandler. Must set.
  806. );
  807. /// Unregister to language change notifications. Use the cookie you have passed to
  808. /// AddLanguageChangeObserver() to identify the observer.
  809. /// \warning Not multithread safe.
  810. /// \sa
  811. /// - AK::StreamMgr::SetCurrentLanguage()
  812. /// - AK::StreamMgr::AddLanguageChangeObserver()
  813. AK_EXTERNAPIFUNC( void, RemoveLanguageChangeObserver )(
  814. void * in_pCookie ///< Cookie that was passed to AddLanguageChangeObserver().
  815. );
  816. /// \name Stream Manager: Cache management.
  817. //@{
  818. /// Flush cache of all devices. This function has no effect for devices where
  819. /// AkDeviceSettings::bUseStreamCache was set to false (no caching).
  820. /// \sa
  821. /// - \ref streamingmanager_settings
  822. AK_EXTERNAPIFUNC( void, FlushAllCaches )();
  823. //@}
  824. }
  825. }
  826. #endif //_AK_STREAM_MGR_MODULE_H_