AkStreamMgrModule.h 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  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. /// \name Audiokinetic Stream Manager's implementation-specific definitions.
  32. //@{
  33. /// Stream Manager initialization settings.
  34. /// \sa
  35. /// - AK::IAkStreamMgr
  36. /// - AK::StreamMgr::Create()
  37. /// - \ref streamingmanager_settings
  38. struct AkStreamMgrSettings
  39. {
  40. };
  41. /// High-level IO devices initialization settings.
  42. /// \sa
  43. /// - AK::IAkStreamMgr
  44. /// - AK::StreamMgr::CreateDevice()
  45. /// - \ref streamingmanager_settings
  46. struct AkDeviceSettings
  47. {
  48. void * pIOMemory; ///< Pointer for I/O memory allocated by user.
  49. ///< Pass NULL if you want memory to be allocated via AK::MemoryMgr::Malign().
  50. ///< If specified, uIOMemorySize, uIOMemoryAlignment and ePoolAttributes are ignored.
  51. 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.
  52. AkUInt32 uIOMemoryAlignment; ///< I/O memory alignment. It is passed directly to AK::MemoryMgr::Malign().
  53. 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().
  54. AkUInt32 uGranularity; ///< I/O requests granularity (typical bytes/request).
  55. AkThreadProperties threadProperties; ///< Scheduler thread properties.
  56. 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.
  57. AkUInt32 uMaxConcurrentIO; ///< Maximum number of transfers that can be sent simultaneously to the Low-Level I/O.
  58. 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.
  59. AkUInt32 uMaxCachePinnedBytes; ///< Maximum number of bytes that can be "pinned" using AK::SoundEngine::PinEventInStreamCache() or AK::IAkStreamMgr::PinFileInCache()
  60. };
  61. /// File descriptor. File identification for the low-level I/O.
  62. /// \sa
  63. /// - AK::StreamMgr::IAkLowLevelIOHook
  64. /// - AK::StreamMgr::IAkLowLevelIOHook::BatchOpen
  65. /// - AK::StreamMgr::IAkLowLevelIOHook::Close
  66. struct AkFileDesc
  67. {
  68. AkInt64 iFileSize = 0; ///< File size in bytes
  69. AkUInt64 uSector = 0; ///< Start sector (the sector size is specified by the low-level I/O)
  70. ///< \sa
  71. ///< - AK::StreamMgr::IAkFileLocationResolver::Open()
  72. ///< - AK::StreamMgr::IAkLowLevelIOHook::GetBlockSize()
  73. AkFileHandle hFile = AkFileHandle(); ///< File handle/identifier
  74. AkDeviceID deviceID = AK_INVALID_DEVICE_ID; ///< Device ID, obtained from CreateDevice() \sa AK::IAkStreamMgr::CreateDevice()
  75. };
  76. /// Structure for synchronous transfers handshaking with the Low-Level I/O. Used with blocking I/O hooks.
  77. /// \sa AK::StreamMgr::IAkLowLevelIOHook
  78. struct AkIOTransferInfo
  79. {
  80. AkUInt64 uFilePosition; ///< File offset where transfer should begin.
  81. AkUInt32 uBufferSize; ///< Size of the buffer in which the I/O hook can write to.
  82. AkUInt32 uRequestedSize; ///< Exact number of requested bytes for this transfer. Always equal to or smaller than uBufferSize.
  83. };
  84. struct AkAsyncIOTransferInfo;
  85. /// Callback function prototype definition used for asynchronous I/O transfers between the Stream Manager and the Low-Level IO.
  86. /// Notes:
  87. /// - 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.
  88. /// - If the transfer was cancelled by the Stream Manager while it was in the Low-Level IO, you must return AK_Success, whether
  89. /// 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.
  90. /// \sa
  91. /// - AkAsyncIOTransferInfo
  92. /// - AK::StreamMgr::IAkLowLevelIOHook
  93. AK_CALLBACK( void, AkIOCallback )(
  94. AkAsyncIOTransferInfo * in_pTransferInfo, ///< Pointer to the AkAsyncIOTransferInfo structure that was passed to corresponding Read() or Write() call.
  95. AKRESULT in_eResult ///< Result of transfer: AK_Success or AK_Fail (streams waiting for this transfer become invalid).
  96. );
  97. /// Structure for asynchronous transfers handshaking with the Low-Level I/O. Extends AkIOTransferInfo.
  98. /// \sa
  99. /// - AK::StreamMgr::IAkLowLevelIOHook
  100. /// - AkIOTransferInfo
  101. /// - AkAIOCallback
  102. struct AkAsyncIOTransferInfo : public AkIOTransferInfo
  103. {
  104. void * pBuffer; ///< Buffer for data transfer.
  105. AkIOCallback pCallback; ///< Callback function used to notify the high-level device when the transfer is complete.
  106. void * pCookie; ///< Reserved. The I/O device uses this cookie to retrieve the owner of the transfer.
  107. void * pUserData; ///< Custom user data.
  108. };
  109. struct AkAsyncFileOpenData;
  110. /// Callback signature for the notification of completion of the asynchronous Open operation.
  111. /// \sa
  112. /// - AkAsyncFileOpenData
  113. /// - AK::StreamMgr::IAkLowLevelIOHook::BatchOpen
  114. AK_CALLBACK(void, AkFileOpenCallback)(
  115. AkAsyncFileOpenData * in_pOpenInfo, ///< Pointer to the AkAsyncFileOpenData structure that was passed to corresponding Open().
  116. AKRESULT in_eResult ///< Result of transfer: AK_Success or AK_Fail (streams waiting for this transfer become invalid).
  117. );
  118. /// Structure used by Low Level IO Hooks (IAkLowLevelIOHook) to pass and retreive information on files to be opened by the IO hook.
  119. /// Please refer to AK::StreamMgr::IAkLowLevelIOHook::BatchOpen for more information about the sementics of the Open operation.
  120. /// \sa
  121. /// - AkFileOpenData
  122. /// - AK::StreamMgr::IAkLowLevelIOHook::BatchOpen
  123. struct AkAsyncFileOpenData : public AkFileOpenData
  124. {
  125. ~AkAsyncFileOpenData();
  126. AkAsyncFileOpenData(const AkFileOpenData& in_copy)
  127. : pCallback(NULL)
  128. , pCookie(NULL)
  129. , pFileDesc(NULL)
  130. , pCustomData(NULL)
  131. , pszStreamName(NULL)
  132. {
  133. *(AkFileOpenData*)this = in_copy;
  134. }
  135. AkAsyncFileOpenData(const AkAsyncFileOpenData& in_copy)
  136. : pCallback(in_copy.pCallback)
  137. , pCookie(in_copy.pCookie)
  138. , pFileDesc(in_copy.pFileDesc)
  139. , pCustomData(NULL)
  140. , pszStreamName(NULL)
  141. {
  142. *(AkFileOpenData*)this = in_copy;
  143. }
  144. AkAsyncFileOpenData()
  145. : AkFileOpenData()
  146. , pCallback(NULL)
  147. , pCookie(NULL)
  148. , pFileDesc(NULL)
  149. , pCustomData(NULL)
  150. , pszStreamName(NULL)
  151. {}
  152. AkAsyncFileOpenData(const AkOSChar* in_pszFileName, AkOpenMode in_eOpenMode = AK_OpenModeRead, AkFileSystemFlags* in_pFlags = NULL)
  153. :AkFileOpenData(in_pszFileName, in_eOpenMode, in_pFlags)
  154. , pCallback(NULL)
  155. , pCookie(NULL)
  156. , pFileDesc(NULL)
  157. , pCustomData(NULL)
  158. , pszStreamName(NULL)
  159. {}
  160. AkAsyncFileOpenData(AkFileID in_idFile, AkOpenMode in_eOpenMode = AK_OpenModeRead, AkFileSystemFlags* in_pFlags = NULL)
  161. :AkFileOpenData(in_idFile, in_eOpenMode, in_pFlags)
  162. , pCallback(NULL)
  163. , pCookie(NULL)
  164. , pFileDesc(NULL)
  165. , pCustomData(NULL)
  166. , pszStreamName(NULL)
  167. {}
  168. ///< Functions used to manage optional stream name. The name will be used when sending stream information to the Wwise profiler.
  169. AKRESULT SetStreamName(const AkOSChar* in_pszStreamName);
  170. const AkOSChar* GetStreamName() const { return pszStreamName; }
  171. AkFileOpenCallback pCallback; ///< Callback function used to notify the high-level device when Open is done
  172. void* pCookie; ///< Reserved. Pass this unchanged to the callback function. The I/O device uses this cookie to retrieve the owner of the transfer.
  173. AkFileDesc* pFileDesc; ///< File Descriptor to fill once the Open operation is complete.
  174. void* pCustomData; ///< Convienience pointer for the IO hook implementer. Useful for additional data used in asynchronous implementations, for example.
  175. private:
  176. AkOSChar* pszStreamName; ///< Display name. If provided, this will be used to set the stream name, which is used for the profiler. This struct is not responsible for the memory.
  177. };
  178. /// Low-Level I/O requests heuristics.
  179. /// Used for asynchronous read requests.
  180. /// \sa
  181. /// - AK::StreamMgr::IAkLowLevelIOHook::BatchRead()
  182. /// - AK::StreamMgr::IAkLowLevelIOHook::BatchWrite()
  183. struct AkIoHeuristics
  184. {
  185. AkReal32 fDeadline; ///< Operation deadline (ms).
  186. 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.
  187. };
  188. //@}
  189. namespace AK
  190. {
  191. /// Audiokinetic Stream Manager's implementation-specific interfaces of the Low-Level IO submodule.
  192. namespace StreamMgr
  193. {
  194. /// Interface for batched deferred low-level I/O transfers.
  195. /// This I/O transfer handshaking method is preferred when you want to hook I/O to your own
  196. /// I/O streaming technology, and you want to submit multiple I/O requests in one call, so as
  197. /// to allow for better opportunities for CPU and I/O performance.
  198. /// All operations in this interface will be happening in the device's own thread, separate
  199. /// from the main audio thread. Also, it is assumed that all operations are asynchronous although
  200. /// immediate resolution is also supported.
  201. /// You may queue them into your own system, and even use the heuristics passed down to this
  202. /// level for your convenience. Note that the requests are always sent in the order that the
  203. /// Stream Manager considers to be the most appropriate. You may receive less than
  204. /// AkDeviceSettings::uMaxConcurrentIO at any given time. The number of concurrent transfers
  205. /// depends on the number of streams running in the high-level streaming device, and on its
  206. /// target buffering length and granularity. Your advantage at this level is to be aware of
  207. /// file placement, so you may try to re-order requests in order to minimize seeking on disk.
  208. /// Calls to BatchRead()/BatchWrite() should return as soon as possible. You need to call
  209. /// AkAsyncIOTransferInfo::pCallback for all individual items in a transfer batch.
  210. /// Cancel() is provided in order to inform you that the streaming device will flush this transfer
  211. /// upon completion. You may implement it or not. In all cases, you must call the callback.
  212. class IAkLowLevelIOHook
  213. {
  214. protected:
  215. /// Virtual destructor on interface to avoid warnings.
  216. virtual ~IAkLowLevelIOHook(){}
  217. public:
  218. /// Closes a file.
  219. /// The file descriptor should be deleted during this call.
  220. /// No other module should have a reference to it at this point.
  221. /// \return AK_Success if the file was properly cleaned-up.
  222. virtual AKRESULT Close(
  223. AkFileDesc * in_pFileDesc ///< File descriptor.
  224. ) = 0;
  225. /// Returns the block size for the file or its storage device.
  226. /// The block size is a constraint for clients
  227. /// of the Stream Manager: All reads, writes and position changes need to be a multiple of
  228. /// that size.
  229. /// \return
  230. /// The block size for a specific file or storage device.
  231. /// \remarks
  232. /// - Some files might be opened with flags that require I/O transfers to be a multiple
  233. /// of this size. The stream manager will query this function to resolve calls
  234. /// to IAk(Auto)Stream::GetBlockSize( ).
  235. /// - Also, AkFileDesc::uSector specifies a number of sectors in multiples of this value.
  236. /// - Files/IO devices that do not require byte alignment should return 1.
  237. /// - Whether file opening was deferred or not, GetBlockSize() is always called right
  238. /// after the first call to Open(), in the client's thread, and is never called again.
  239. /// \warning
  240. /// Returning 0 is not allowed and will likely make the Stream Manager crash.
  241. /// \sa
  242. /// - AK::StreamMgr::IAkLowLevelIOHook::BatchOpen()
  243. /// - AK::StreamMgr::IAkLowLevelIOHook::BatchRead()
  244. /// - AK::StreamMgr::IAkLowLevelIOHook::BatchWrite()
  245. virtual AkUInt32 GetBlockSize(
  246. AkFileDesc & in_fileDesc ///< File descriptor.
  247. ) = 0;
  248. /// Returns a description for the streaming device above this low-level hook.
  249. /// \remarks For profiling purposes only. The Release configuration of the
  250. /// Stream Manager never calls it.
  251. virtual void GetDeviceDesc(
  252. AkDeviceDesc & out_deviceDesc ///< Device description.
  253. ) = 0;
  254. /// Returns custom profiling data for the streaming device above this low-level hook.
  255. /// As opposed to GetDeviceDesc(), this is called at every monitoring frame.
  256. /// You may implement this function in order to display any value you find useful
  257. /// in the "Streaming Devices" tab of the Wwise profiler ("Custom Param" column).
  258. /// \remarks For profiling purposes only. The Release configuration of the
  259. /// Stream Manager never calls it.
  260. /// \return A 32-bit unsigned value to display in the Wwise profiler.
  261. virtual AkUInt32 GetDeviceData() = 0;
  262. struct BatchIoTransferItem
  263. {
  264. AkFileDesc* pFileDesc;
  265. AkIoHeuristics ioHeuristics;
  266. AkAsyncIOTransferInfo* pTransferInfo;
  267. };
  268. /// Request to open multiple files (asynchronous).
  269. /// \remarks
  270. /// - The pCallback within each AkAsyncFileOpenData must be called when completed.
  271. /// - It is possible to mix synchronous and asynchronous file opens, as long as all pCallbacks are eventually called.
  272. /// - When implementing this function, make sure to process all items even if one fails to be dispatched or to open.
  273. /// - Pointers in in_ppItems will stay valid until pCallback is called to signal the operation result.
  274. virtual void BatchOpen(
  275. AkUInt32 in_uNumFiles, ///< Number of transfers to process
  276. AkAsyncFileOpenData** in_ppItems ///< List of files to open. See remarks above.
  277. ) = 0;
  278. /// Reads multiple data from multiple files (asynchronous).
  279. /// \remarks
  280. /// - Queue up multiple read requests at once, using the provided array of in_pTransferItems. There will
  281. /// be in_uNumTransfers number of items in the array.
  282. /// - The pCallback within each BatchIoTransferItem::pTransferInfo must be called when completed.
  283. /// - The pointer to each BatchIoTransferItem::pTransferInfo will be valid until the high-level
  284. /// device is notified through the callback. However, the array of in_pTransferItems will not be valid.
  285. /// - File position passed in each BatchIoTransferItem::pTransferInfo takes the offset of this file relative
  286. /// to AkFileDesc::hFile (described with AkFileDesc::uSector). It is computed by the high-level
  287. /// device as "pFileDesc->uSector * Block_Size + Stream_Position", where Block_Size is obtained
  288. /// via AK::StreamMgr::IAkLowLevelIOHook::GetBlockSize().
  289. virtual void BatchRead(
  290. AkUInt32 in_uNumTransfers, ///< Number of transfers to process
  291. BatchIoTransferItem* in_pTransferItems ///< List of transfer items to process
  292. ) = 0;
  293. /// Write multiple data to multiple files (asynchronous).
  294. /// \remarks
  295. /// - Queue up multiple write requests at once, using the provided array of in_pTransferItems. There will
  296. /// be in_uNumTransfers number of items in the array.
  297. /// - The pCallback within each BatchIoTransferItem::pTransferInfo must be called when completed.
  298. /// - The pointer to each BatchIoTransferItem::pTransferInfo will be valid until the high-level
  299. /// device is notified through the callback. However, the array of in_pTransferItems will not be valid.
  300. /// - File position passed in each BatchIoTransferItem::pTransferInfo takes the offset of this file relative
  301. /// to AkFileDesc::hFile (described with AkFileDesc::uSector). It is computed by the high-level
  302. /// device as "pFileDesc->uSector * Block_Size + Stream_Position", where Block_Size is obtained
  303. /// via AK::StreamMgr::IAkLowLevelIOHook::GetBlockSize().
  304. virtual void BatchWrite(
  305. AkUInt32 in_uNumTransfers, ///< Number of transfers to process
  306. BatchIoTransferItem* in_pTransferItems ///< List of transfer items to process
  307. ) = 0;
  308. /// Notifies that a transfer request is cancelled. It will be flushed by the streaming device when completed.
  309. /// Cancellation is normal and happens regularly; for example, whenever a sound stops before the end
  310. /// or stops looping. It happens even more frequently when buffering (AkDeviceSettings::fTargetAutoStmBufferLength
  311. /// and AkDeviceSettings::uGranularity) is large and when you low-level IO hook accepts many concurrent requests
  312. /// at the same time.
  313. /// \remarks
  314. /// - BatchCancel() is an optional functionality that can be implemented as a no-op.
  315. /// - BatchCancel() simply informs the Low-Level I/O that a specific transfer will be flushed upon reception.
  316. /// The Low-Level I/O may use this information to stop this transfer right away, or not (it is internally tagged
  317. /// by the high-level device as cancelled). Nevertheless, the callback function MUST be called for cancelled
  318. /// transfers to be resolved.
  319. /// - When calling the callback function of a cancelled transfer, pass it *AK_Success*. Passing AK_Fail
  320. /// to AkAsyncIOTransfer::pCallback has the effect of killing the stream once and for all. This is not
  321. /// what you want.
  322. /// - If io_bCancelAllTransfersForThisFile is set, you may cancel all transfers for this file at once.
  323. /// Leave io_bCancelAllTransfersForThisFile to true if you don't want to be called again. For example, if
  324. /// you don't do anything special in BatchCancel(), leave it to true. This will reduce the amount of useless calls.
  325. /// If you set it to false, BatchCancel() will be called again for each remaining pending transfer that need to be cancelled.
  326. /// - If io_bCancelAllTransfersForThisFile is not set, BatchCancel() is only called for a subset of pending
  327. /// transfers for this file. You must not set it to true, as BatchCancel() needs to be called explicitly for each transfer that
  328. /// should be cancelled.
  329. /// \warning
  330. /// - The calling thread holds the stream's lock. You may call the callback function directly from here
  331. /// (if you can guarantee that the I/O buffer will not be accessed in the meantime), but you must not wait here
  332. /// for another thread to call the callback function.
  333. /// - Likewise, if you resolve transfers with your own thread and use a lock to protect your transfers queue,
  334. /// be careful not to run into a deadlock. BatchCancel() can be executed by any thread. Thus, if you need to lock your queue
  335. /// in BatchCancel(), you must never hold this lock when calling back transfers, either from within BatchCancel() or from your
  336. /// worker thread's routine. Lock your list, dequeue the transfer if you can, unlock, and call pCallback if and only if
  337. /// the transfer was found and dequeued. On the other hand, if you choose not to do anything in BatchCancel(), the lock only protects
  338. /// your list between Read()/Write() and your worker thread's routine, and since the device I/O thread does not hold the
  339. /// stream's lock while calling Read()/Write(), your worker thread may therefore hold it while calling back transfers.
  340. /// - A race condition exists when cancelling all transfers (io_bCancelAllTransfersForThisFile is true) directly from within this hook.
  341. /// If you handle the io_bCancelAllTransfersForThisFile == true case, you need to defer calling the completion callback to later
  342. /// (from your usual I/O completion thread, for example). This will be fixed in a future version of Wwise.
  343. virtual void BatchCancel(
  344. AkUInt32 in_uNumTransfers, ///< Number of transfers to process
  345. BatchIoTransferItem* in_pTransferItems, ///< List of transfer items to process
  346. bool** io_ppbCancelAllTransfersForThisFile ///< Flag for each transfer indicating whether all transfers should be cancelled for this file (see notes in function description).
  347. ) = 0;
  348. /// This function is called to provide information when file related errors occur. The base paths known by this IO hook should be returned in out_searchedPath.
  349. virtual AKRESULT OutputSearchedPaths(
  350. AKRESULT in_result, ///< Result of the open call
  351. const AkFileOpenData& in_FileOpen, ///< File name and flags passed to the Open call.
  352. AkOSChar* out_searchedPath, ///< Pre-allocated string buffer to be filled with all searched paths searched for the file.
  353. AkInt32 in_pathSize ///< The maximum size of the string
  354. ) { return AK_NotImplemented; };
  355. };
  356. /// File location resolver interface. There is one and only one File Location Resolver that is
  357. /// registered to the Stream Manager (using AK::StreamMgr::SetFileLocationResolver()). Its purpose
  358. /// is to resolve a file name or ID to a streaming device (I/O hook) that can handle the file.
  359. /// When your Low-Level I/O submodule uses a single device, you should create a standalone I/O
  360. /// hook which implements one of the I/O hooks defined above, as well
  361. /// as the File Location Resolver. You then register this object to the Stream Manager as the
  362. /// File Location Resolver.
  363. /// If you wish to create multiple devices, then you should have a separate object that implements
  364. /// AK::StreamMgr::IAkFileLocationResolver and registers to the Stream Manager as such. This object
  365. /// will be used to dispatch the file open request to the appropriate device. The strategy you will
  366. /// use to select the correct device is up to you to implement.
  367. /// There is a built-in mechanism of chaining devices through GetNextPreferredDevice().
  368. /// If a device can't open a file GetNextPreferredDevice will be called again to get the next
  369. /// device to check.
  370. class IAkFileLocationResolver
  371. {
  372. protected:
  373. /// Virtual destructor on interface to avoid warnings.
  374. virtual ~IAkFileLocationResolver(){}
  375. public:
  376. /// Determines which device to use to open a file.
  377. /// If your File Resolver only handles one device, return AK_NotImplemented and the StreamMgr will use the only device configured.
  378. /// If it handles multiple devices, you can base the decision on where to get the file on any kind of heuristic:
  379. /// file extension, file name, access rights, CodecID, etc.
  380. /// The order in which devices are searched is left to the implementer.
  381. /// This function will always be called first with io_idDevice = AK_INVALID_DEVICE_ID.
  382. /// \return
  383. /// - AK_Success if there is a device to delegate the Open() call to. io_idDevice should be set to the proper AkDeviceID (as returned by AK::StreamMgr::CreateDevice).
  384. /// - AK_FileNotFound if all devices have been exhausted.
  385. /// - AK_NotImplemented if there is only one device in the system and file resolution is trivial.
  386. /// \remark
  387. /// This can be called from multiple threads.
  388. /// Note that there is a
  389. virtual AKRESULT GetNextPreferredDevice(
  390. AkAsyncFileOpenData& in_FileOpen, ///< File name and flags passed to the Open call.
  391. AkDeviceID& io_idDevice ///< In: last device used. Out: next device to use to open the file
  392. )
  393. { return AK_NotImplemented; };
  394. };
  395. /// \name Audiokinetic implementation-specific Stream Manager factory.
  396. //@{
  397. /// Stream Manager factory.
  398. /// \remarks
  399. /// - In order for the Stream Manager to work properly, you also need to create
  400. /// at least one streaming device (and implement its I/O hook), and register the
  401. /// File Location Resolver with AK::StreamMgr::SetFileLocationResolver().
  402. /// - Use AK::StreamMgr::GetDefaultSettings(), then modify the settings you want,
  403. /// then feed this function with them.
  404. /// \sa
  405. /// - AK::IAkStreamMgr
  406. /// - AK::StreamMgr::SetFileLocationResolver()
  407. /// - AK::StreamMgr::GetDefaultSettings()
  408. AK_EXTERNAPIFUNC( IAkStreamMgr *, Create )(
  409. const AkStreamMgrSettings & in_settings ///< Stream manager initialization settings.
  410. );
  411. /// Get the default values for the Stream Manager's settings.
  412. /// \sa
  413. /// - AK::StreamMgr::Create()
  414. /// - AkStreamMgrSettings
  415. /// - \ref streamingmanager_settings
  416. AK_EXTERNAPIFUNC( void, GetDefaultSettings )(
  417. AkStreamMgrSettings & out_settings ///< Returned AkStreamMgrSettings structure with default values.
  418. );
  419. /// Get the one and only File Location Resolver registered to the Stream Manager.
  420. /// \sa
  421. /// - AK::StreamMgr::IAkFileLocationResolver
  422. /// - AK::StreamMgr::SetFileLocationResolver()
  423. AK_EXTERNAPIFUNC( IAkFileLocationResolver *, GetFileLocationResolver )();
  424. /// Register the one and only File Location Resolver to the Stream Manager.
  425. /// \sa
  426. /// - AK::StreamMgr::IAkFileLocationResolver
  427. AK_EXTERNAPIFUNC( void, SetFileLocationResolver )(
  428. IAkFileLocationResolver * in_pFileLocationResolver ///< Interface to your File Location Resolver
  429. );
  430. //@}
  431. /// \name Stream Manager: High-level I/O devices management.
  432. //@{
  433. /// Streaming device creation.
  434. /// Creates a high-level device, with specific settings.
  435. /// You need to provide the associated low-level I/O hook, implemented on your side.
  436. /// \return The device ID. AK_INVALID_DEVICE_ID if there was an error and it could not be created.
  437. /// \warning
  438. /// - This function is not thread-safe.
  439. /// \remarks
  440. /// - You may use AK::StreamMgr::GetDefaultDeviceSettings() first to get default values for the
  441. /// settings, change those you want, then feed the structure to this function.
  442. /// - The returned device ID should be kept by the Low-Level IO, to assign it to file descriptors
  443. /// in AK::StreamMgr::IAkLowLevelIOHook::BatchOpen().
  444. /// \return
  445. /// - AK_Success: Device was added to the system properly
  446. /// - AK_InsufficientMemory: Not enough memory to complete the operation
  447. /// - AK_InvalidParameter: One of the settings in AkDeviceSettings is out of range. Check asserts or debug console.
  448. /// \sa
  449. /// - AK::StreamMgr::IAkLowLevelIOHook
  450. /// - AK::StreamMgr::GetDefaultDeviceSettings()
  451. /// - \ref streamingmanager_settings
  452. AK_EXTERNAPIFUNC( AKRESULT, CreateDevice )(
  453. const AkDeviceSettings & in_settings, ///< Device settings.
  454. IAkLowLevelIOHook * in_pLowLevelHook, ///< Associated low-level I/O hook. Pass either a IAkLowLevelIOHook interface, consistent with the type of the scheduler.
  455. AkDeviceID& out_idDevice ///< Assigned unique device id to use in all other functions of this interface.
  456. );
  457. /// Streaming device destruction.
  458. /// \return AK_Success if the device was successfully destroyed.
  459. /// \warning This function is not thread-safe. No stream should exist for that device when it is destroyed.
  460. AK_EXTERNAPIFUNC( AKRESULT, DestroyDevice )(
  461. AkDeviceID in_deviceID ///< Device ID of the device to destroy.
  462. );
  463. /// Execute pending I/O operations on all created I/O devices.
  464. /// This should only be called in single-threaded environments where an I/O device cannot spawn a thread.
  465. /// \return AK_Success when called from an appropriate environment, AK_NotCompatible otherwise.
  466. /// \sa
  467. /// - AK::StreamMgr::CreateDevice()
  468. AK_EXTERNAPIFUNC( AKRESULT, PerformIO )();
  469. /// Get the default values for the streaming device's settings. Recommended usage
  470. /// is to call this function first, then pass the settings to AK::StreamMgr::CreateDevice().
  471. /// \sa
  472. /// - AK::StreamMgr::CreateDevice()
  473. /// - AkDeviceSettings
  474. /// - \ref streamingmanager_settings
  475. AK_EXTERNAPIFUNC( void, GetDefaultDeviceSettings )(
  476. AkDeviceSettings & out_settings ///< Returned AkDeviceSettings structure with default values.
  477. );
  478. //@}
  479. /// \name Language management.
  480. //@{
  481. /// Set the current language once and only once, here. The language name is stored in a static buffer
  482. /// inside the Stream Manager. In order to resolve localized (language-specific) file location,
  483. /// AK::StreamMgr::IAkFileLocationResolver implementations query this string. They may use it to
  484. /// construct a file path (for e.g. SDK/samples/SoundEngine/Common/AkFileLocationBase.cpp), or to
  485. /// find a language-specific file within a look-up table (for e.g. SDK/samples/SoundEngine/Common/AkFilePackageLUT.cpp).
  486. /// Pass a valid null-terminated string, without a trailing slash or backslash. Empty strings are accepted.
  487. /// You may register for language changes (see RegisterToLanguageChangeNotification()).
  488. /// After changing the current language, all observers are notified.
  489. /// \return AK_Success if successful (if language string has less than AK_MAX_LANGUAGE_NAME_SIZE characters). AK_Fail otherwise.
  490. /// \warning Not multithread safe.
  491. /// \sa
  492. /// - AK::StreamMgr::GetCurrentLanguage()
  493. /// - AK::StreamMgr::AddLanguageChangeObserver()
  494. AK_EXTERNAPIFUNC( AKRESULT, SetCurrentLanguage )(
  495. const AkOSChar * in_pszLanguageName ///< Language name.
  496. );
  497. /// Get the current language. The language name is stored in a static buffer inside the Stream Manager,
  498. /// with AK::StreamMgr::SetCurrentLanguage(). In order to resolve localized (language-specific) file location,
  499. /// AK::StreamMgr::IAkFileLocationResolver implementations query this string. They may use it to
  500. /// construct a file path (for e.g. SDK/samples/SoundEngine/Common/AkFileLocationBase.cpp), or to
  501. /// find a language-specific file within a look-up table (for e.g. SDK/samples/SoundEngine/Common/AkFilePackageLUT.cpp).
  502. /// \return Current language.
  503. /// \sa AK::StreamMgr::SetCurrentLanguage()
  504. AK_EXTERNAPIFUNC( const AkOSChar *, GetCurrentLanguage )();
  505. /// Definition of handlers for language change notifications.
  506. /// Called after SetCurrentLanguage() is called.
  507. /// \warning Do not call AddLanguageChangeObserver or SetCurrentLanguage from within your handler.
  508. /// \warning Not multithread safe.
  509. /// \sa
  510. /// - AK::StreamMgr::SetCurrentLanguage()
  511. /// - AK::StreamMgr::AddLanguageChangeObserver()
  512. AK_CALLBACK( void, AkLanguageChangeHandler )(
  513. const AkOSChar * const in_pLanguageName,///< New language name.
  514. void * in_pCookie ///< Cookie that was passed to AddLanguageChangeObserver().
  515. );
  516. /// Register to language change notifications.
  517. /// \return AK_Success if successful, AK_Fail otherwise (no memory or no cookie).
  518. /// \warning Not multithread safe.
  519. /// \sa
  520. /// - AK::StreamMgr::SetCurrentLanguage()
  521. /// - AK::StreamMgr::RemoveLanguageChangeObserver()
  522. AK_EXTERNAPIFUNC( AKRESULT, AddLanguageChangeObserver )(
  523. AkLanguageChangeHandler in_handler, ///< Callback function.
  524. void * in_pCookie ///< Cookie, passed back to AkLanguageChangeHandler. Must set.
  525. );
  526. /// Unregister to language change notifications. Use the cookie you have passed to
  527. /// AddLanguageChangeObserver() to identify the observer.
  528. /// \warning Not multithread safe.
  529. /// \sa
  530. /// - AK::StreamMgr::SetCurrentLanguage()
  531. /// - AK::StreamMgr::AddLanguageChangeObserver()
  532. AK_EXTERNAPIFUNC( void, RemoveLanguageChangeObserver )(
  533. void * in_pCookie ///< Cookie that was passed to AddLanguageChangeObserver().
  534. );
  535. /// \name Stream Manager: Cache management.
  536. //@{
  537. /// Flush cache of all devices. This function has no effect for devices where
  538. /// AkDeviceSettings::bUseStreamCache was set to false (no caching).
  539. /// \sa
  540. /// - \ref streamingmanager_settings
  541. AK_EXTERNAPIFUNC( void, FlushAllCaches )();
  542. //@}
  543. }
  544. }
  545. #endif //_AK_STREAM_MGR_MODULE_H_