/******************************************************************************* The content of this file includes portions of the AUDIOKINETIC Wwise Technology released in source code form as part of the SDK installer package. Commercial License Usage Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology may use this file in accordance with the end user license agreement provided with the software or, alternatively, in accordance with the terms contained in a written agreement between you and Audiokinetic Inc. Apache License Usage Alternatively, this file may be used under the Apache License, Version 2.0 (the "Apache License"); you may not use this file except in compliance with the Apache License. You may obtain a copy of the Apache License at http://www.apache.org/licenses/LICENSE-2.0. Unless required by applicable law or agreed to in writing, software distributed under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for the specific language governing permissions and limitations under the License. Copyright (c) 2023 Audiokinetic Inc. *******************************************************************************/ /// \file /// Audiokinetic's implementation-specific definitions and factory of /// overridable Stream Manager module. /// Contains the default Stream Manager's implementation-specific interfaces that altogether constitute /// the Low-Level I/O submodule. This submodule needs to be implemented by the game. All I/O requests /// generated by the Stream Manager end up to one of the I/O hooks defined herein. /// Read \ref streamingmanager_lowlevel to learn more about the Low-Level I/O. #ifndef _AK_STREAM_MGR_MODULE_H_ #define _AK_STREAM_MGR_MODULE_H_ #include #include /// \name Audiokinetic Stream Manager's implementation-specific definitions. //@{ /// Stream Manager initialization settings. /// \sa /// - AK::IAkStreamMgr /// - AK::StreamMgr::Create() /// - \ref streamingmanager_settings struct AkStreamMgrSettings { }; /// High-level IO devices initialization settings. /// \sa /// - AK::IAkStreamMgr /// - AK::StreamMgr::CreateDevice() /// - \ref streamingmanager_settings struct AkDeviceSettings { void * pIOMemory; ///< Pointer for I/O memory allocated by user. ///< Pass NULL if you want memory to be allocated via AK::MemoryMgr::Malign(). ///< If specified, uIOMemorySize, uIOMemoryAlignment and ePoolAttributes are ignored. 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. AkUInt32 uIOMemoryAlignment; ///< I/O memory alignment. It is passed directly to AK::MemoryMgr::Malign(). 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(). AkUInt32 uGranularity; ///< I/O requests granularity (typical bytes/request). AkThreadProperties threadProperties; ///< Scheduler thread properties. 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. AkUInt32 uMaxConcurrentIO; ///< Maximum number of transfers that can be sent simultaneously to the Low-Level I/O. 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. AkUInt32 uMaxCachePinnedBytes; ///< Maximum number of bytes that can be "pinned" using AK::SoundEngine::PinEventInStreamCache() or AK::IAkStreamMgr::PinFileInCache() }; /// File descriptor. File identification for the low-level I/O. /// \sa /// - AK::StreamMgr::IAkLowLevelIOHook /// - AK::StreamMgr::IAkLowLevelIOHook::BatchOpen /// - AK::StreamMgr::IAkLowLevelIOHook::Close struct AkFileDesc { AkInt64 iFileSize = 0; ///< File size in bytes AkUInt64 uSector = 0; ///< Start sector (the sector size is specified by the low-level I/O) ///< \sa ///< - AK::StreamMgr::IAkFileLocationResolver::Open() ///< - AK::StreamMgr::IAkLowLevelIOHook::GetBlockSize() AkFileHandle hFile = AkFileHandle(); ///< File handle/identifier AkDeviceID deviceID = AK_INVALID_DEVICE_ID; ///< Device ID, obtained from CreateDevice() \sa AK::IAkStreamMgr::CreateDevice() }; /// Structure for synchronous transfers handshaking with the Low-Level I/O. Used with blocking I/O hooks. /// \sa AK::StreamMgr::IAkLowLevelIOHook struct AkIOTransferInfo { AkUInt64 uFilePosition; ///< File offset where transfer should begin. AkUInt32 uBufferSize; ///< Size of the buffer in which the I/O hook can write to. AkUInt32 uRequestedSize; ///< Exact number of requested bytes for this transfer. Always equal to or smaller than uBufferSize. }; struct AkAsyncIOTransferInfo; /// Callback function prototype definition used for asynchronous I/O transfers between the Stream Manager and the Low-Level IO. /// Notes: /// - 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. /// - If the transfer was cancelled by the Stream Manager while it was in the Low-Level IO, you must return AK_Success, whether /// 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. /// \sa /// - AkAsyncIOTransferInfo /// - AK::StreamMgr::IAkLowLevelIOHook AK_CALLBACK( void, AkIOCallback )( AkAsyncIOTransferInfo * in_pTransferInfo, ///< Pointer to the AkAsyncIOTransferInfo structure that was passed to corresponding Read() or Write() call. AKRESULT in_eResult ///< Result of transfer: AK_Success or AK_Fail (streams waiting for this transfer become invalid). ); /// Structure for asynchronous transfers handshaking with the Low-Level I/O. Extends AkIOTransferInfo. /// \sa /// - AK::StreamMgr::IAkLowLevelIOHook /// - AkIOTransferInfo /// - AkAIOCallback struct AkAsyncIOTransferInfo : public AkIOTransferInfo { void * pBuffer; ///< Buffer for data transfer. AkIOCallback pCallback; ///< Callback function used to notify the high-level device when the transfer is complete. void * pCookie; ///< Reserved. The I/O device uses this cookie to retrieve the owner of the transfer. void * pUserData; ///< Custom user data. }; struct AkAsyncFileOpenData; /// Callback signature for the notification of completion of the asynchronous Open operation. /// \sa /// - AkAsyncFileOpenData /// - AK::StreamMgr::IAkLowLevelIOHook::BatchOpen AK_CALLBACK(void, AkFileOpenCallback)( AkAsyncFileOpenData * in_pOpenInfo, ///< Pointer to the AkAsyncFileOpenData structure that was passed to corresponding Open(). AKRESULT in_eResult ///< Result of transfer: AK_Success or AK_Fail (streams waiting for this transfer become invalid). ); /// Structure used by Low Level IO Hooks (IAkLowLevelIOHook) to pass and retreive information on files to be opened by the IO hook. /// Please refer to AK::StreamMgr::IAkLowLevelIOHook::BatchOpen for more information about the sementics of the Open operation. /// \sa /// - AkFileOpenData /// - AK::StreamMgr::IAkLowLevelIOHook::BatchOpen struct AkAsyncFileOpenData : public AkFileOpenData { ~AkAsyncFileOpenData(); AkAsyncFileOpenData(const AkFileOpenData& in_copy) : pCallback(NULL) , pCookie(NULL) , pFileDesc(NULL) , pCustomData(NULL) , pszStreamName(NULL) { *(AkFileOpenData*)this = in_copy; } AkAsyncFileOpenData(const AkAsyncFileOpenData& in_copy) : pCallback(in_copy.pCallback) , pCookie(in_copy.pCookie) , pFileDesc(in_copy.pFileDesc) , pCustomData(NULL) , pszStreamName(NULL) { *(AkFileOpenData*)this = in_copy; } AkAsyncFileOpenData() : AkFileOpenData() , pCallback(NULL) , pCookie(NULL) , pFileDesc(NULL) , pCustomData(NULL) , pszStreamName(NULL) {} AkAsyncFileOpenData(const AkOSChar* in_pszFileName, AkOpenMode in_eOpenMode = AK_OpenModeRead, AkFileSystemFlags* in_pFlags = NULL) :AkFileOpenData(in_pszFileName, in_eOpenMode, in_pFlags) , pCallback(NULL) , pCookie(NULL) , pFileDesc(NULL) , pCustomData(NULL) , pszStreamName(NULL) {} AkAsyncFileOpenData(AkFileID in_idFile, AkOpenMode in_eOpenMode = AK_OpenModeRead, AkFileSystemFlags* in_pFlags = NULL) :AkFileOpenData(in_idFile, in_eOpenMode, in_pFlags) , pCallback(NULL) , pCookie(NULL) , pFileDesc(NULL) , pCustomData(NULL) , pszStreamName(NULL) {} ///< Functions used to manage optional stream name. The name will be used when sending stream information to the Wwise profiler. AKRESULT SetStreamName(const AkOSChar* in_pszStreamName); const AkOSChar* GetStreamName() const { return pszStreamName; } AkFileOpenCallback pCallback; ///< Callback function used to notify the high-level device when Open is done void* pCookie; ///< Reserved. Pass this unchanged to the callback function. The I/O device uses this cookie to retrieve the owner of the transfer. AkFileDesc* pFileDesc; ///< File Descriptor to fill once the Open operation is complete. void* pCustomData; ///< Convienience pointer for the IO hook implementer. Useful for additional data used in asynchronous implementations, for example. private: 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. }; /// Low-Level I/O requests heuristics. /// Used for asynchronous read requests. /// \sa /// - AK::StreamMgr::IAkLowLevelIOHook::BatchRead() /// - AK::StreamMgr::IAkLowLevelIOHook::BatchWrite() struct AkIoHeuristics { AkReal32 fDeadline; ///< Operation deadline (ms). 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. }; //@} namespace AK { /// Audiokinetic Stream Manager's implementation-specific interfaces of the Low-Level IO submodule. namespace StreamMgr { /// Interface for batched deferred low-level I/O transfers. /// This I/O transfer handshaking method is preferred when you want to hook I/O to your own /// I/O streaming technology, and you want to submit multiple I/O requests in one call, so as /// to allow for better opportunities for CPU and I/O performance. /// All operations in this interface will be happening in the device's own thread, separate /// from the main audio thread. Also, it is assumed that all operations are asynchronous although /// immediate resolution is also supported. /// You may queue them into your own system, and even use the heuristics passed down to this /// level for your convenience. Note that the requests are always sent in the order that the /// Stream Manager considers to be the most appropriate. You may receive less than /// AkDeviceSettings::uMaxConcurrentIO at any given time. The number of concurrent transfers /// depends on the number of streams running in the high-level streaming device, and on its /// target buffering length and granularity. Your advantage at this level is to be aware of /// file placement, so you may try to re-order requests in order to minimize seeking on disk. /// Calls to BatchRead()/BatchWrite() should return as soon as possible. You need to call /// AkAsyncIOTransferInfo::pCallback for all individual items in a transfer batch. /// Cancel() is provided in order to inform you that the streaming device will flush this transfer /// upon completion. You may implement it or not. In all cases, you must call the callback. class IAkLowLevelIOHook { protected: /// Virtual destructor on interface to avoid warnings. virtual ~IAkLowLevelIOHook(){} public: /// Closes a file. /// The file descriptor should be deleted during this call. /// No other module should have a reference to it at this point. /// \return AK_Success if the file was properly cleaned-up. virtual AKRESULT Close( AkFileDesc * in_pFileDesc ///< File descriptor. ) = 0; /// Returns the block size for the file or its storage device. /// The block size is a constraint for clients /// of the Stream Manager: All reads, writes and position changes need to be a multiple of /// that size. /// \return /// The block size for a specific file or storage device. /// \remarks /// - Some files might be opened with flags that require I/O transfers to be a multiple /// of this size. The stream manager will query this function to resolve calls /// to IAk(Auto)Stream::GetBlockSize( ). /// - Also, AkFileDesc::uSector specifies a number of sectors in multiples of this value. /// - Files/IO devices that do not require byte alignment should return 1. /// - Whether file opening was deferred or not, GetBlockSize() is always called right /// after the first call to Open(), in the client's thread, and is never called again. /// \warning /// Returning 0 is not allowed and will likely make the Stream Manager crash. /// \sa /// - AK::StreamMgr::IAkLowLevelIOHook::BatchOpen() /// - AK::StreamMgr::IAkLowLevelIOHook::BatchRead() /// - AK::StreamMgr::IAkLowLevelIOHook::BatchWrite() virtual AkUInt32 GetBlockSize( AkFileDesc & in_fileDesc ///< File descriptor. ) = 0; /// Returns a description for the streaming device above this low-level hook. /// \remarks For profiling purposes only. The Release configuration of the /// Stream Manager never calls it. virtual void GetDeviceDesc( AkDeviceDesc & out_deviceDesc ///< Device description. ) = 0; /// Returns custom profiling data for the streaming device above this low-level hook. /// As opposed to GetDeviceDesc(), this is called at every monitoring frame. /// You may implement this function in order to display any value you find useful /// in the "Streaming Devices" tab of the Wwise profiler ("Custom Param" column). /// \remarks For profiling purposes only. The Release configuration of the /// Stream Manager never calls it. /// \return A 32-bit unsigned value to display in the Wwise profiler. virtual AkUInt32 GetDeviceData() = 0; struct BatchIoTransferItem { AkFileDesc* pFileDesc; AkIoHeuristics ioHeuristics; AkAsyncIOTransferInfo* pTransferInfo; }; /// Request to open multiple files (asynchronous). /// \remarks /// - The pCallback within each AkAsyncFileOpenData must be called when completed. /// - It is possible to mix synchronous and asynchronous file opens, as long as all pCallbacks are eventually called. /// - When implementing this function, make sure to process all items even if one fails to be dispatched or to open. /// - Pointers in in_ppItems will stay valid until pCallback is called to signal the operation result. virtual void BatchOpen( AkUInt32 in_uNumFiles, ///< Number of transfers to process AkAsyncFileOpenData** in_ppItems ///< List of files to open. See remarks above. ) = 0; /// Reads multiple data from multiple files (asynchronous). /// \remarks /// - Queue up multiple read requests at once, using the provided array of in_pTransferItems. There will /// be in_uNumTransfers number of items in the array. /// - The pCallback within each BatchIoTransferItem::pTransferInfo must be called when completed. /// - The pointer to each BatchIoTransferItem::pTransferInfo will be valid until the high-level /// device is notified through the callback. However, the array of in_pTransferItems will not be valid. /// - File position passed in each BatchIoTransferItem::pTransferInfo takes the offset of this file relative /// to AkFileDesc::hFile (described with AkFileDesc::uSector). It is computed by the high-level /// device as "pFileDesc->uSector * Block_Size + Stream_Position", where Block_Size is obtained /// via AK::StreamMgr::IAkLowLevelIOHook::GetBlockSize(). virtual void BatchRead( AkUInt32 in_uNumTransfers, ///< Number of transfers to process BatchIoTransferItem* in_pTransferItems ///< List of transfer items to process ) = 0; /// Write multiple data to multiple files (asynchronous). /// \remarks /// - Queue up multiple write requests at once, using the provided array of in_pTransferItems. There will /// be in_uNumTransfers number of items in the array. /// - The pCallback within each BatchIoTransferItem::pTransferInfo must be called when completed. /// - The pointer to each BatchIoTransferItem::pTransferInfo will be valid until the high-level /// device is notified through the callback. However, the array of in_pTransferItems will not be valid. /// - File position passed in each BatchIoTransferItem::pTransferInfo takes the offset of this file relative /// to AkFileDesc::hFile (described with AkFileDesc::uSector). It is computed by the high-level /// device as "pFileDesc->uSector * Block_Size + Stream_Position", where Block_Size is obtained /// via AK::StreamMgr::IAkLowLevelIOHook::GetBlockSize(). virtual void BatchWrite( AkUInt32 in_uNumTransfers, ///< Number of transfers to process BatchIoTransferItem* in_pTransferItems ///< List of transfer items to process ) = 0; /// Notifies that a transfer request is cancelled. It will be flushed by the streaming device when completed. /// Cancellation is normal and happens regularly; for example, whenever a sound stops before the end /// or stops looping. It happens even more frequently when buffering (AkDeviceSettings::fTargetAutoStmBufferLength /// and AkDeviceSettings::uGranularity) is large and when you low-level IO hook accepts many concurrent requests /// at the same time. /// \remarks /// - BatchCancel() is an optional functionality that can be implemented as a no-op. /// - BatchCancel() simply informs the Low-Level I/O that a specific transfer will be flushed upon reception. /// The Low-Level I/O may use this information to stop this transfer right away, or not (it is internally tagged /// by the high-level device as cancelled). Nevertheless, the callback function MUST be called for cancelled /// transfers to be resolved. /// - When calling the callback function of a cancelled transfer, pass it *AK_Success*. Passing AK_Fail /// to AkAsyncIOTransfer::pCallback has the effect of killing the stream once and for all. This is not /// what you want. /// - If io_bCancelAllTransfersForThisFile is set, you may cancel all transfers for this file at once. /// Leave io_bCancelAllTransfersForThisFile to true if you don't want to be called again. For example, if /// you don't do anything special in BatchCancel(), leave it to true. This will reduce the amount of useless calls. /// If you set it to false, BatchCancel() will be called again for each remaining pending transfer that need to be cancelled. /// - If io_bCancelAllTransfersForThisFile is not set, BatchCancel() is only called for a subset of pending /// transfers for this file. You must not set it to true, as BatchCancel() needs to be called explicitly for each transfer that /// should be cancelled. /// \warning /// - The calling thread holds the stream's lock. You may call the callback function directly from here /// (if you can guarantee that the I/O buffer will not be accessed in the meantime), but you must not wait here /// for another thread to call the callback function. /// - Likewise, if you resolve transfers with your own thread and use a lock to protect your transfers queue, /// be careful not to run into a deadlock. BatchCancel() can be executed by any thread. Thus, if you need to lock your queue /// in BatchCancel(), you must never hold this lock when calling back transfers, either from within BatchCancel() or from your /// worker thread's routine. Lock your list, dequeue the transfer if you can, unlock, and call pCallback if and only if /// the transfer was found and dequeued. On the other hand, if you choose not to do anything in BatchCancel(), the lock only protects /// your list between Read()/Write() and your worker thread's routine, and since the device I/O thread does not hold the /// stream's lock while calling Read()/Write(), your worker thread may therefore hold it while calling back transfers. /// - A race condition exists when cancelling all transfers (io_bCancelAllTransfersForThisFile is true) directly from within this hook. /// If you handle the io_bCancelAllTransfersForThisFile == true case, you need to defer calling the completion callback to later /// (from your usual I/O completion thread, for example). This will be fixed in a future version of Wwise. virtual void BatchCancel( AkUInt32 in_uNumTransfers, ///< Number of transfers to process BatchIoTransferItem* in_pTransferItems, ///< List of transfer items to process bool** io_ppbCancelAllTransfersForThisFile ///< Flag for each transfer indicating whether all transfers should be cancelled for this file (see notes in function description). ) = 0; /// 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. virtual AKRESULT OutputSearchedPaths( AKRESULT in_result, ///< Result of the open call const AkFileOpenData& in_FileOpen, ///< File name and flags passed to the Open call. AkOSChar* out_searchedPath, ///< Pre-allocated string buffer to be filled with all searched paths searched for the file. AkInt32 in_pathSize ///< The maximum size of the string ) { return AK_NotImplemented; }; }; /// File location resolver interface. There is one and only one File Location Resolver that is /// registered to the Stream Manager (using AK::StreamMgr::SetFileLocationResolver()). Its purpose /// is to resolve a file name or ID to a streaming device (I/O hook) that can handle the file. /// When your Low-Level I/O submodule uses a single device, you should create a standalone I/O /// hook which implements one of the I/O hooks defined above, as well /// as the File Location Resolver. You then register this object to the Stream Manager as the /// File Location Resolver. /// If you wish to create multiple devices, then you should have a separate object that implements /// AK::StreamMgr::IAkFileLocationResolver and registers to the Stream Manager as such. This object /// will be used to dispatch the file open request to the appropriate device. The strategy you will /// use to select the correct device is up to you to implement. /// There is a built-in mechanism of chaining devices through GetNextPreferredDevice(). /// If a device can't open a file GetNextPreferredDevice will be called again to get the next /// device to check. class IAkFileLocationResolver { protected: /// Virtual destructor on interface to avoid warnings. virtual ~IAkFileLocationResolver(){} public: /// Determines which device to use to open a file. /// If your File Resolver only handles one device, return AK_NotImplemented and the StreamMgr will use the only device configured. /// If it handles multiple devices, you can base the decision on where to get the file on any kind of heuristic: /// file extension, file name, access rights, CodecID, etc. /// The order in which devices are searched is left to the implementer. /// This function will always be called first with io_idDevice = AK_INVALID_DEVICE_ID. /// \return /// - 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). /// - AK_FileNotFound if all devices have been exhausted. /// - AK_NotImplemented if there is only one device in the system and file resolution is trivial. /// \remark /// This can be called from multiple threads. /// Note that there is a virtual AKRESULT GetNextPreferredDevice( AkAsyncFileOpenData& in_FileOpen, ///< File name and flags passed to the Open call. AkDeviceID& io_idDevice ///< In: last device used. Out: next device to use to open the file ) { return AK_NotImplemented; }; }; /// \name Audiokinetic implementation-specific Stream Manager factory. //@{ /// Stream Manager factory. /// \remarks /// - In order for the Stream Manager to work properly, you also need to create /// at least one streaming device (and implement its I/O hook), and register the /// File Location Resolver with AK::StreamMgr::SetFileLocationResolver(). /// - Use AK::StreamMgr::GetDefaultSettings(), then modify the settings you want, /// then feed this function with them. /// \sa /// - AK::IAkStreamMgr /// - AK::StreamMgr::SetFileLocationResolver() /// - AK::StreamMgr::GetDefaultSettings() AK_EXTERNAPIFUNC( IAkStreamMgr *, Create )( const AkStreamMgrSettings & in_settings ///< Stream manager initialization settings. ); /// Get the default values for the Stream Manager's settings. /// \sa /// - AK::StreamMgr::Create() /// - AkStreamMgrSettings /// - \ref streamingmanager_settings AK_EXTERNAPIFUNC( void, GetDefaultSettings )( AkStreamMgrSettings & out_settings ///< Returned AkStreamMgrSettings structure with default values. ); /// Get the one and only File Location Resolver registered to the Stream Manager. /// \sa /// - AK::StreamMgr::IAkFileLocationResolver /// - AK::StreamMgr::SetFileLocationResolver() AK_EXTERNAPIFUNC( IAkFileLocationResolver *, GetFileLocationResolver )(); /// Register the one and only File Location Resolver to the Stream Manager. /// \sa /// - AK::StreamMgr::IAkFileLocationResolver AK_EXTERNAPIFUNC( void, SetFileLocationResolver )( IAkFileLocationResolver * in_pFileLocationResolver ///< Interface to your File Location Resolver ); //@} /// \name Stream Manager: High-level I/O devices management. //@{ /// Streaming device creation. /// Creates a high-level device, with specific settings. /// You need to provide the associated low-level I/O hook, implemented on your side. /// \return The device ID. AK_INVALID_DEVICE_ID if there was an error and it could not be created. /// \warning /// - This function is not thread-safe. /// \remarks /// - You may use AK::StreamMgr::GetDefaultDeviceSettings() first to get default values for the /// settings, change those you want, then feed the structure to this function. /// - The returned device ID should be kept by the Low-Level IO, to assign it to file descriptors /// in AK::StreamMgr::IAkLowLevelIOHook::BatchOpen(). /// \return /// - AK_Success: Device was added to the system properly /// - AK_InsufficientMemory: Not enough memory to complete the operation /// - AK_InvalidParameter: One of the settings in AkDeviceSettings is out of range. Check asserts or debug console. /// \sa /// - AK::StreamMgr::IAkLowLevelIOHook /// - AK::StreamMgr::GetDefaultDeviceSettings() /// - \ref streamingmanager_settings AK_EXTERNAPIFUNC( AKRESULT, CreateDevice )( const AkDeviceSettings & in_settings, ///< Device settings. IAkLowLevelIOHook * in_pLowLevelHook, ///< Associated low-level I/O hook. Pass either a IAkLowLevelIOHook interface, consistent with the type of the scheduler. AkDeviceID& out_idDevice ///< Assigned unique device id to use in all other functions of this interface. ); /// Streaming device destruction. /// \return AK_Success if the device was successfully destroyed. /// \warning This function is not thread-safe. No stream should exist for that device when it is destroyed. AK_EXTERNAPIFUNC( AKRESULT, DestroyDevice )( AkDeviceID in_deviceID ///< Device ID of the device to destroy. ); /// Execute pending I/O operations on all created I/O devices. /// This should only be called in single-threaded environments where an I/O device cannot spawn a thread. /// \return AK_Success when called from an appropriate environment, AK_NotCompatible otherwise. /// \sa /// - AK::StreamMgr::CreateDevice() AK_EXTERNAPIFUNC( AKRESULT, PerformIO )(); /// Get the default values for the streaming device's settings. Recommended usage /// is to call this function first, then pass the settings to AK::StreamMgr::CreateDevice(). /// \sa /// - AK::StreamMgr::CreateDevice() /// - AkDeviceSettings /// - \ref streamingmanager_settings AK_EXTERNAPIFUNC( void, GetDefaultDeviceSettings )( AkDeviceSettings & out_settings ///< Returned AkDeviceSettings structure with default values. ); //@} /// \name Language management. //@{ /// Set the current language once and only once, here. The language name is stored in a static buffer /// inside the Stream Manager. In order to resolve localized (language-specific) file location, /// AK::StreamMgr::IAkFileLocationResolver implementations query this string. They may use it to /// construct a file path (for e.g. SDK/samples/SoundEngine/Common/AkFileLocationBase.cpp), or to /// find a language-specific file within a look-up table (for e.g. SDK/samples/SoundEngine/Common/AkFilePackageLUT.cpp). /// Pass a valid null-terminated string, without a trailing slash or backslash. Empty strings are accepted. /// You may register for language changes (see RegisterToLanguageChangeNotification()). /// After changing the current language, all observers are notified. /// \return AK_Success if successful (if language string has less than AK_MAX_LANGUAGE_NAME_SIZE characters). AK_Fail otherwise. /// \warning Not multithread safe. /// \sa /// - AK::StreamMgr::GetCurrentLanguage() /// - AK::StreamMgr::AddLanguageChangeObserver() AK_EXTERNAPIFUNC( AKRESULT, SetCurrentLanguage )( const AkOSChar * in_pszLanguageName ///< Language name. ); /// Get the current language. The language name is stored in a static buffer inside the Stream Manager, /// with AK::StreamMgr::SetCurrentLanguage(). In order to resolve localized (language-specific) file location, /// AK::StreamMgr::IAkFileLocationResolver implementations query this string. They may use it to /// construct a file path (for e.g. SDK/samples/SoundEngine/Common/AkFileLocationBase.cpp), or to /// find a language-specific file within a look-up table (for e.g. SDK/samples/SoundEngine/Common/AkFilePackageLUT.cpp). /// \return Current language. /// \sa AK::StreamMgr::SetCurrentLanguage() AK_EXTERNAPIFUNC( const AkOSChar *, GetCurrentLanguage )(); /// Definition of handlers for language change notifications. /// Called after SetCurrentLanguage() is called. /// \warning Do not call AddLanguageChangeObserver or SetCurrentLanguage from within your handler. /// \warning Not multithread safe. /// \sa /// - AK::StreamMgr::SetCurrentLanguage() /// - AK::StreamMgr::AddLanguageChangeObserver() AK_CALLBACK( void, AkLanguageChangeHandler )( const AkOSChar * const in_pLanguageName,///< New language name. void * in_pCookie ///< Cookie that was passed to AddLanguageChangeObserver(). ); /// Register to language change notifications. /// \return AK_Success if successful, AK_Fail otherwise (no memory or no cookie). /// \warning Not multithread safe. /// \sa /// - AK::StreamMgr::SetCurrentLanguage() /// - AK::StreamMgr::RemoveLanguageChangeObserver() AK_EXTERNAPIFUNC( AKRESULT, AddLanguageChangeObserver )( AkLanguageChangeHandler in_handler, ///< Callback function. void * in_pCookie ///< Cookie, passed back to AkLanguageChangeHandler. Must set. ); /// Unregister to language change notifications. Use the cookie you have passed to /// AddLanguageChangeObserver() to identify the observer. /// \warning Not multithread safe. /// \sa /// - AK::StreamMgr::SetCurrentLanguage() /// - AK::StreamMgr::AddLanguageChangeObserver() AK_EXTERNAPIFUNC( void, RemoveLanguageChangeObserver )( void * in_pCookie ///< Cookie that was passed to AddLanguageChangeObserver(). ); /// \name Stream Manager: Cache management. //@{ /// Flush cache of all devices. This function has no effect for devices where /// AkDeviceSettings::bUseStreamCache was set to false (no caching). /// \sa /// - \ref streamingmanager_settings AK_EXTERNAPIFUNC( void, FlushAllCaches )(); //@} } } #endif //_AK_STREAM_MGR_MODULE_H_