Table of Contents

include/AK/SoundEngine/Common/AkStreamMgrModule.h

Go to the documentation of this file.
00001 /*******************************************************************************
00002 The content of this file includes portions of the AUDIOKINETIC Wwise Technology
00003 released in source code form as part of the SDK installer package.
00004 
00005 Commercial License Usage
00006 
00007 Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology
00008 may use this file in accordance with the end user license agreement provided 
00009 with the software or, alternatively, in accordance with the terms contained in a
00010 written agreement between you and Audiokinetic Inc.
00011 
00012 Apache License Usage
00013 
00014 Alternatively, this file may be used under the Apache License, Version 2.0 (the 
00015 "Apache License"); you may not use this file except in compliance with the 
00016 Apache License. You may obtain a copy of the Apache License at 
00017 http://www.apache.org/licenses/LICENSE-2.0.
00018 
00019 Unless required by applicable law or agreed to in writing, software distributed
00020 under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
00021 OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for
00022 the specific language governing permissions and limitations under the License.
00023 
00024   Version: <VERSION>  Build: <BUILDNUMBER>
00025   Copyright (c) <COPYRIGHTYEAR> Audiokinetic Inc.
00026 *******************************************************************************/
00027 
00028 /// \file 
00029 /// Audiokinetic's implementation-specific definitions and factory of 
00030 /// overridable Stream Manager module.
00031 /// Contains the default Stream Manager's implementation-specific interfaces that altogether constitute
00032 /// the Low-Level I/O submodule. This submodule needs to be implemented by the game. All I/O requests 
00033 /// generated by the Stream Manager end up to one of the I/O hooks defined herein.
00034 /// Read \ref streamingmanager_lowlevel to learn more about the Low-Level I/O.
00035 
00036 #ifndef _AK_STREAM_MGR_MODULE_H_
00037 #define _AK_STREAM_MGR_MODULE_H_
00038 
00039 #include <AK/SoundEngine/Common/IAkStreamMgr.h>
00040 #include <AK/Tools/Common/AkPlatformFuncs.h>
00041 
00042 /// \name Audiokinetic Stream Manager's implementation-specific definitions.
00043 //@{
00044 /// Stream Manager initialization settings.
00045 /// \sa 
00046 /// - AK::IAkStreamMgr
00047 /// - AK::StreamMgr::Create()
00048 /// - \ref streamingmanager_settings
00049 
00050 struct AkStreamMgrSettings
00051 {
00052     AkUInt32            uMemorySize;        ///< Size of memory pool for small objects of Stream Manager.
00053                                             ///< Small objects are the Stream Manager instance, devices, 
00054                                             ///< stream objects, user stream names, pending transfers, 
00055                                             ///< buffer records, pending open commands, and so on.
00056                                             ///< Ideally, this pool should never run out of memory, 
00057                                             ///< because it may cause undesired I/O transfer 
00058                                             ///< cancellation, and even major CPU spikes. I/O memory should 
00059                                             ///< be bound by the size of each device's I/O pool instead.
00060 };
00061 
00062 /// High-level IO devices initialization settings.
00063 /// \sa 
00064 /// - AK::IAkStreamMgr
00065 /// - AK::StreamMgr::CreateDevice()
00066 /// - \ref streamingmanager_settings
00067 struct AkDeviceSettings
00068 {
00069     void *              pIOMemory;                  ///< Pointer for I/O memory allocated by user. This is fed directly to AK::MemoryMgr::CreatePool().
00070                                                     ///< Pass NULL if you want memory to be allocated by the MemoryMgr via AK alloc hooks. 
00071                                                     ///< If specified, uIOMemorySize, uIOMemoryAlignment and ePoolAttributes are ignored.
00072     AkUInt32            uIOMemorySize;              ///< Size of memory pool for I/O (for automatic streams). It is passed directly to AK::MemoryMgr::CreatePool(), after having been rounded down to a multiple of uGranularity.
00073     AkUInt32            uIOMemoryAlignment;         ///< I/O memory pool alignment. It is passed directly to AK::MemoryMgr::CreatePool().
00074     AkMemPoolAttributes ePoolAttributes;            ///< Attributes for internal I/O memory pool. Note that these pools are always allocated internally as AkFixedSizeBlocksMode-style pools. Here, specify the block allocation type (AkMalloc, and so on). It is passed directly to AK::MemoryMgr::CreatePool().
00075     AkUInt32            uGranularity;               ///< I/O requests granularity (typical bytes/request).
00076     AkUInt32            uSchedulerTypeFlags;        ///< Scheduler type flags.
00077     AkThreadProperties  threadProperties;           ///< Scheduler thread properties.
00078     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.
00079     AkUInt32            uMaxConcurrentIO;           ///< Maximum number of transfers that can be sent simultaneously to the Low-Level I/O (applies to AK_SCHEDULER_DEFERRED_LINED_UP device only).
00080     bool                bUseStreamCache;            ///< If true the device attempts to reuse IO buffers that have already been streamed from disk. This is particularly useful when streaming small looping sounds. The drawback is a small CPU hit when allocating memory, and a slightly larger memory footprint in the StreamManager pool.                                                  
00081     AkUInt32            uMaxCachePinnedBytes;       ///< Maximum number of bytes that can be "pinned" using AK::SoundEngine::PinEventInStreamCache() or AK::IAkStreamMgr::PinFileInCache()
00082 };
00083 
00084 /// \name Scheduler type flags.
00085 
00086 /// Requests to Low-Level IO are synchronous. The streaming device expects a blocking I/O hook at creation time (IAkIOHookBlocking interface, see CreateDevice()). 
00087 /// Functions of this interface should return only when the transfer is complete.
00088 #define AK_SCHEDULER_BLOCKING          (0x01)
00089 /// Requests to Low-Level IO are asynchronous, but posted one after the other, starting with streams that need data the most. 
00090 /// The streaming device expects a deferred I/O hook at creation time (IAkIOHookDeferred interface, see CreateDevice()). 
00091 /// Up to AkDeviceSettings::uMaxConcurrentIO requests can be sent to the Low-Level I/O at the same time.
00092 #define AK_SCHEDULER_DEFERRED_LINED_UP (0x02)
00093 
00094 /// File descriptor. File identification for the low-level I/O.
00095 /// \sa
00096 /// - AK::StreamMgr::IAkLowLevelIOHook
00097 struct AkFileDesc
00098 {
00099     AkInt64             iFileSize;          ///< File size in bytes
00100     AkUInt32            uSector;            ///< Start sector (the sector size is specified by the low-level I/O)
00101                                             ///< \sa
00102                                             ///< - AK::StreamMgr::IAkFileLocationResolver::Open()
00103                                             ///< - AK::StreamMgr::IAkLowLevelIOHook::GetBlockSize()
00104     AkUInt32            uCustomParamSize;   ///< Size of the custom parameter
00105     void *              pCustomParam;       ///< Custom parameter
00106     AkFileHandle        hFile;              ///< File handle/identifier
00107     AkDeviceID          deviceID;           ///< Device ID, obtained from CreateDevice() \sa AK::IAkStreamMgr::CreateDevice()
00108 };
00109 
00110 /// Structure for synchronous transfers handshaking with the Low-Level I/O. Used with blocking I/O hooks.
00111 /// \sa AK::StreamMgr::IAkIOHookBlocking
00112 struct AkIOTransferInfo
00113 {
00114     AkUInt64        uFilePosition;      ///< File offset where transfer should begin.
00115     AkUInt32        uBufferSize;        ///< Size of the buffer in which the I/O hook can write to.
00116     AkUInt32        uRequestedSize;     ///< Exact number of requested bytes for this transfer. Always equal to or smaller than uBufferSize.
00117 };
00118 
00119 struct AkAsyncIOTransferInfo;
00120 /// Callback function prototype definition used for asynchronous I/O transfers between the Stream Manager
00121 /// and the Low-Level IO. Used with deferred I/O hooks.
00122 /// Notes:
00123 /// - If you return 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.
00124 /// - If the transfer was cancelled by the Stream Manager while it was in the Low-Level IO, you must return AK_Success, whether
00125 /// 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.
00126 /// \sa 
00127 /// - AkAsyncIOTransferInfo
00128 /// - AK::StreamMgr::IAkIOHookDeferred
00129 AK_CALLBACK( void, AkIOCallback )( 
00130     AkAsyncIOTransferInfo * in_pTransferInfo,   ///< Pointer to the AkAsyncIOTransferInfo structure that was passed to corresponding Read() or Write() call.
00131     AKRESULT        in_eResult          ///< Result of transfer: AK_Success or AK_Fail (streams waiting for this transfer become invalid).
00132     );
00133 
00134 /// Structure for asynchronous transfers handshaking with the Low-Level I/O. Extends AkIOTransferInfo.
00135 /// \sa 
00136 /// - AK::StreamMgr::IAkIOHookDeferred
00137 /// - AkIOTransferInfo
00138 /// - AkAIOCallback
00139 struct AkAsyncIOTransferInfo : public AkIOTransferInfo
00140 {
00141     void *          pBuffer;            ///< Buffer for data transfer.
00142     AkIOCallback    pCallback;          ///< Callback function used to notify the high-level device when the transfer is complete.
00143     void *          pCookie;            ///< Reserved. The I/O device uses this cookie to retrieve the owner of the transfer.
00144     void *          pUserData;          ///< Custom user data.
00145 };
00146 
00147 /// Low-Level I/O requests heuristics.
00148 /// Used for asynchronous read requests. 
00149 /// \sa 
00150 /// - AK::StreamMgr::IAkIOHookBlocking::Read()
00151 /// - AK::StreamMgr::IAkIOHookBlocking::Write()
00152 /// - AK::StreamMgr::IAkIOHookDeferred::Read()
00153 /// - AK::StreamMgr::IAkIOHookDeferred::Write()
00154 struct AkIoHeuristics
00155 {
00156     AkReal32        fDeadline;          ///< Operation deadline (ms). 
00157     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.
00158 };
00159 
00160 
00161 
00162 //@}
00163 
00164 namespace AK
00165 {
00166     // Audiokinetic Stream Manager's implementation-specific interfaces of the Low-Level IO submodule.
00167     namespace StreamMgr
00168     {
00169         /// Base interface for Low-Level I/O hooks. Defines common methods across both types of hooks.
00170         class IAkLowLevelIOHook
00171         {
00172         protected:
00173             /// Virtual destructor on interface to avoid warnings.
00174             virtual ~IAkLowLevelIOHook(){}
00175 
00176         public:
00177             /// Cleans up a file.
00178             /// \return AK_Success if the file was properly cleaned-up.
00179             virtual AKRESULT Close(
00180                 AkFileDesc &            in_fileDesc         ///< File descriptor.
00181                 ) = 0;
00182 
00183             /// Returns the block size for the file or its storage device. 
00184             /// The block size is a constraint for clients
00185             /// of the Stream Manager: All reads, writes and position changes need to be a multiple of
00186             /// that size.
00187             /// \return 
00188             /// The block size for a specific file or storage device.
00189             /// \remarks 
00190             /// - Some files might be opened with flags that require I/O transfers to be a multiple 
00191             /// of this size. The stream manager will query this function to resolve calls 
00192             /// to IAk(Auto)Stream::GetBlockSize( ).
00193             /// - Also, AkFileDesc::uSector specifies a number of sectors in multiples of this value.
00194             /// - Files/IO devices that do not require byte alignment should return 1.
00195             /// - Whether file opening was deferred or not, GetBlockSize() is always called right 
00196             /// after the first call to Open(), in the client's thread, and is never called again.
00197             /// \warning 
00198             /// Returning 0 is not allowed and will likely make the Stream Manager crash.
00199             /// \sa 
00200             /// - AK::StreamMgr::IAkFileLocationResolver::Open()
00201             /// - AK::StreamMgr::IAkIOHookBlocking::Read()
00202             /// - AK::StreamMgr::IAkIOHookBlocking::Write()
00203             /// - AK::StreamMgr::IAkIOHookDeferred::Read()
00204             /// - AK::StreamMgr::IAkIOHookDeferred::Write()
00205             virtual AkUInt32 GetBlockSize(
00206                 AkFileDesc &            in_fileDesc         ///< File descriptor.
00207                 ) = 0;
00208 
00209             /// Returns a description for the streaming device above this low-level hook.
00210             /// \remarks For profiling purposes only. The Release configuration of the 
00211             /// Stream Manager never calls it.
00212             virtual void GetDeviceDesc(
00213                 AkDeviceDesc &          out_deviceDesc      ///< Device description.
00214                 ) = 0;
00215 
00216             /// Returns custom profiling data for the streaming device above this low-level hook.
00217             /// As opposed to GetDeviceDesc(), this is called at every monitoring frame.
00218             /// You may implement this function in order to display any value you find useful 
00219             /// in the "Streaming Devices" tab of the Wwise profiler ("Custom Param" column).
00220             /// \remarks For profiling purposes only. The Release configuration of the 
00221             /// Stream Manager never calls it.
00222             /// \return A 32-bit unsigned value to display in the Wwise profiler.
00223             virtual AkUInt32 GetDeviceData() = 0;
00224         };
00225 
00226         /// Interface for blocking low-level I/O transfers. Used by streaming devices created with the
00227         /// AK_SCHEDULER_BLOCKING flag.
00228         /// This is the simplest I/O hook. Calls to Read()/Write() must block until they are completed.
00229         /// The streaming device's I/O thread sends one transfer at a time.
00230         class IAkIOHookBlocking : public IAkLowLevelIOHook
00231         {
00232         protected:
00233             /// Virtual destructor on interface to avoid warnings.
00234             virtual ~IAkIOHookBlocking(){}
00235 
00236         public:
00237 
00238             /// Reads data from a file (synchronous). 
00239             /// Read data from the file described by in_fileDesc, in address out_pBuffer and with size and position 
00240             /// passed within io_transferInfo. When transfer is complete, return with the proper return code.
00241             /// \remarks 
00242             /// File position passed in io_transferInfo takes the offset of this file relative 
00243             /// to AkFileDesc::hFile (described with AkFileDesc::uSector). It is computed by the high-level 
00244             /// device as "in_fileDesc.uSector * Block_Size + Stream_Position", where Block_Size is obtained 
00245             /// via AK::StreamMgr::IAkLowLevelIOHook::GetBlockSize(). 
00246             /// \return 
00247             ///     - AK_Success:   transfer was successful and out_pBuffer is filled with data.
00248             ///     - AK_Fail:      an error occured.
00249             virtual AKRESULT Read(
00250                 AkFileDesc &            in_fileDesc,        ///< File descriptor.
00251                 const AkIoHeuristics &  in_heuristics,      ///< Heuristics for this data transfer.
00252                 void *                  out_pBuffer,        ///< Buffer to be filled with data.
00253                 AkIOTransferInfo &      in_transferInfo     ///< Synchronous data transfer info. 
00254                 ) = 0;
00255 
00256             /// Writes data to a file (synchronous). 
00257             /// Write data to the file described by in_fileDesc, from address in_pData and with size and position 
00258             /// passed within io_transferInfo. When transfer is complete, return with the proper return code.
00259             /// \remarks File position passed in io_transferInfo takes the offset of this file relative 
00260             /// to AkFileDesc::hFile (described with AkFileDesc::uSector). It is computed by the high-level 
00261             /// device as "in_fileDesc.uSector * Block_Size + Stream_Position", where Block_Size is obtained 
00262             /// via AK::StreamMgr::IAkLowLevelIOHook::GetBlockSize(). 
00263             /// \return 
00264             ///     - AK_Success:   transfer was successful.
00265             ///     - AK_Fail:      an error occured.
00266             virtual AKRESULT Write(
00267                 AkFileDesc &            in_fileDesc,        ///< File descriptor.
00268                 const AkIoHeuristics &  in_heuristics,      ///< Heuristics for this data transfer.
00269                 void *                  in_pData,           ///< Data to be written.
00270                 AkIOTransferInfo &      io_transferInfo     ///< Synchronous data transfer info. 
00271                 ) = 0;
00272         };
00273 
00274         /// Interface for deferred low-level I/O transfers. Used by streaming devices created with the
00275         /// AK_SCHEDULER_DEFERRED_LINED_UP flag.
00276         /// This I/O transfer handshaking method is preferred when you want to hook I/O to your own
00277         /// I/O streaming technology. You will receive up to AkDeviceSettings::uMaxConcurrentIO requests
00278         /// at the same time. You may queue them into your own system, and even use the heuristics passed
00279         /// down to this level for your convenience. 
00280         /// Note that the requests are always sent in the order that the Stream Manager considers to be
00281         /// the most appropriate. You may receive less than AkDeviceSettings::uMaxConcurrentIO at any
00282         /// given time. The number of concurrent transfers depends on the number of streams running in 
00283         /// the high-level streaming device, and on its target buffering length and granularity.
00284         /// Your advantage at this level is to be aware of file placement, so you may try to re-order 
00285         /// requests in order to minimize seeking on disk. 
00286         /// Calls to Read()/Write() should return as soon as possible. You need to call 
00287         /// AkAsyncIOTransferInfo::pCallback as soon as a transfer is completed.
00288         /// Cancel() is provided in order to inform you that the streaming device will flush this transfer
00289         /// upon completion. You may implement it or not. In all cases, you must call the callback.
00290         class IAkIOHookDeferred : public IAkLowLevelIOHook
00291         {
00292         protected:
00293             /// Virtual destructor on interface to avoid warnings.
00294             virtual ~IAkIOHookDeferred(){}
00295 
00296         public:
00297 
00298             /// Reads data from a file (asynchronous).
00299             /// \remarks 
00300             /// - Queue up your read request with address, size and file position specified in io_transferInfo.
00301             /// - When transfer is complete (whether it was successful, cancelled or failed), call 
00302             /// AkAsyncIOTransferInfo::pCallback. However, if you return AK_Fail() from Read(), do not call
00303             /// AkAsyncIOTransferInfo::pCallback.
00304             /// - AkAsyncIOTransferInfo::pCookie must be passed to the callback function as-is. It must not
00305             /// be changed by the Low-Level I/O.
00306             /// - The reference to io_transferInfo will be valid until the high-level device is notified 
00307             /// through the callback.
00308             /// - File position passed in io_transferInfo takes the offset of this file relative 
00309             /// to AkFileDesc::hFile (described with AkFileDesc::uSector). It is computed by the high-level 
00310             /// device as "in_fileDesc.uSector * Block_Size + Stream_Position", where Block_Size is obtained 
00311             /// via AK::StreamMgr::IAkLowLevelIOHook::GetBlockSize(). 
00312             /// \return 
00313             ///     - AK_Success:    An I/O request was successfully processed and is pending: 
00314             ///                         AkAsyncIOTransferInfo::pCallback must be called when it completes.
00315             ///     - AK_Fail:        an error occured.
00316             virtual AKRESULT Read(
00317                 AkFileDesc &            in_fileDesc,        ///< File descriptor.
00318                 const AkIoHeuristics &  in_heuristics,      ///< Heuristics for this data transfer.
00319                 AkAsyncIOTransferInfo & io_transferInfo     ///< Asynchronous data transfer info.
00320                 ) = 0;
00321 
00322             /// Writes data to a file (asynchronous).
00323             /// \remarks 
00324             /// - Queue up your write request with address, size and file position specified in io_transferInfo.
00325             /// - When transfer is complete (whether it was successful, cancelled or failed), call 
00326             /// AkAsyncIOTransferInfo::pCallback. However, if you return AK_Fail() from Write(), do not call
00327             /// AkAsyncIOTransferInfo::pCallback.
00328             /// - AkAsyncIOTransferInfo::pCookie must be passed to the callback function as-is. It must not
00329             /// be changed by the Low-Level I/O.
00330             /// - The reference to io_transferInfo will be valid until the high-level device is notified 
00331             /// through the callback.
00332             /// - File position passed in io_transferInfo takes the offset of this file relative 
00333             /// to AkFileDesc::hFile (described with AkFileDesc::uSector). It is computed by the high-level 
00334             /// device as "in_fileDesc.uSector * Block_Size + Stream_Position", where Block_Size is obtained 
00335             /// via AK::StreamMgr::IAkLowLevelIOHook::GetBlockSize(). 
00336             /// \return 
00337             ///     - AK_Success:    An I/O request was successfully processed and is pending: 
00338             ///                         AkAsyncIOTransferInfo::pCallback must be called when it completes.
00339             ///     - AK_Fail:        an error occured.
00340             virtual AKRESULT Write(
00341                 AkFileDesc &            in_fileDesc,        ///< File descriptor.
00342                 const AkIoHeuristics &  in_heuristics,      ///< Heuristics for this data transfer.
00343                 AkAsyncIOTransferInfo & io_transferInfo     ///< Platform-specific asynchronous IO operation info.
00344                 ) = 0;
00345 
00346             /// Notifies that a transfer request is cancelled. It will be flushed by the streaming device when completed.
00347             /// Cancellation is normal and happens regularly; for example, whenever a sound stops before the end
00348             /// or stops looping. It happens even more frequently when buffering (AkDeviceSettings::fTargetAutoStmBufferLength 
00349             /// and AkDeviceSettings::uGranularity) is large and when you low-level IO hook accepts many concurrent requests
00350             /// at the same time.
00351             /// \remarks
00352             /// - Cancel() simply informs the Low-Level I/O that a specific transfer will be flushed upon reception. 
00353             /// The Low-Level I/O may use this information to stop this transfer right away, or not (it is internally tagged
00354             /// by the high-level device as cancelled). Nevertheless, the callback function MUST be called for cancelled 
00355             /// transfers to be resolved.
00356             /// - When calling the callback function of a cancelled transfer, pass it *AK_Success*. Passing AK_Fail 
00357             /// to AkAsyncIOTransfer::pCallback has the effect of killing the stream once and for all. This is not
00358             /// what you want.
00359             /// - If io_bCancelAllTransfersForThisFile is set, you may cancel all transfers for this file at once.
00360             /// Leave io_bCancelAllTransfersForThisFile to true if you don't want to be called again. For example, if
00361             /// you don't do anything special in Cancel(), leave it to true. This will reduce the amount of useless calls.
00362             /// If you set it to false, Cancel() will be called again for each remaining pending transfer that need to be cancelled. 
00363             /// - If io_bCancelAllTransfersForThisFile is not set, Cancel() is only called for a subset of pending 
00364             /// 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.
00365             /// \warning
00366             /// - The calling thread holds the stream's lock. You may call the callback function directly from here
00367             /// (if you can guarantee that the I/O buffer will not be accessed in the meantime), but you must not wait here 
00368             /// for another thread to call the callback function.
00369             /// - Likewise, if you resolve transfers with your own thread and use a lock to protect your transfers queue, 
00370             /// be careful not to run into a deadlock. Cancel() can be executed by any thread. Thus, if you need to lock your queue 
00371             /// in Cancel(), you must never hold this lock when calling back transfers, either from within Cancel() or from your 
00372             /// worker thread's routine. Lock your list, dequeue the transfer if you can, unlock, and call pCallback if and only if 
00373             /// the transfer was found and dequeued. On the other hand, if you choose not to do anything in Cancel(), the lock only protects 
00374             /// your list between Read()/Write() and your worker thread's routine, and since the device I/O thread does not hold the 
00375             /// stream's lock while calling Read()/Write(), your worker thread may therefore hold it while calling back transfers.
00376             /// - A race condition exists when cancelling all transfers (io_bCancelAllTransfersForThisFile is true) directly from within this hook. 
00377             /// If you handle the io_bCancelAllTransfersForThisFile == true case, you need to defer calling the completion callback to later 
00378             /// (from your usual I/O completion thread, for example). This will be fixed in a future version of Wwise.
00379             virtual void Cancel(
00380                 AkFileDesc &        in_fileDesc,            ///< File descriptor.
00381                 AkAsyncIOTransferInfo & io_transferInfo,    ///< Transfer info to cancel.
00382                 bool & io_bCancelAllTransfersForThisFile    ///< Flag indicating whether all transfers should be cancelled for this file (see notes in function description).
00383                 ) = 0;
00384         };
00385 
00386         /// File location resolver interface. There is one and only one File Location Resolver that is
00387         /// registered to the Stream Manager (using AK::StreamMgr::SetFileLocationResolver()). Its purpose
00388         /// is to map a file name or ID to 
00389         /// 1) a streaming device / I/O hook;
00390         /// 2) a valid file descriptor (AkFileDesc) usable by the I/O hook.
00391         /// When your Low-Level I/O submodule uses a single device, you should create a standalone I/O
00392         /// hook which implements one of the I/O hooks defined above (blocking or deferred), as well 
00393         /// as the File Location Resolver. You then register this object to the Stream Manager as the 
00394         /// File Location Resolver.
00395         /// If you wish to create multiple devices, then you should have a separate object that implements
00396         /// AK::StreamMgr::IAkFileLocationResolver and registers to the Stream Manager as such. This object
00397         /// will be used to dispatch the file open request to the appropriate device. The strategy you will 
00398         /// use to select the correct device is up to you to implement. You may also implement a set of
00399         /// hooks that delegate opening to the next device when they can't find the file requested 
00400         /// (like a chain of responsiblity pattern), although this will likely be less efficient.
00401         class IAkFileLocationResolver
00402         {
00403         protected:
00404             /// Virtual destructor on interface to avoid warnings.
00405             virtual ~IAkFileLocationResolver(){}
00406 
00407         public:
00408 
00409             /// Returns a file descriptor for a given file name (string).
00410             /// Performs the operations needed to make the file descriptor usable by
00411             /// the other methods of the interface (for e.g. ask the OS for a valid file handle).
00412             /// \return 
00413             ///     - AK_Success:       A valid file descriptor is returned
00414             ///     - AK_FileNotFound:  File was not found.
00415             ///     - AK_Fail:          File could not be open for any other reason.
00416             /// \return 
00417             ///     - A file descriptor, which contains 
00418             ///         - an unique identifier to be used with functions of the low-level IO 
00419             ///           interface.
00420             ///         - the total stream size in bytes.
00421             ///         - the offset from the beginning of the file (in blocks).
00422             ///         - a device ID, that was obtained through AK::StreamMgr::CreateDevice().
00423             ///     - The updated io_bSyncOpen flag depending on the File Resolver's deferred opening policy.
00424             /// \remarks
00425             ///     - The file descriptor is unique for each stream, and its address remains the same 
00426             ///     throughout its lifetime. In other words, the value of &in_fileDesc inside Read() or
00427             ///     Close() is the same as &out_fileDesc in Open().
00428             ///     - Open() is always called first in the client thread.
00429             ///     - If io_bSyncOpen is true, file opening must be executed now. If it is false,
00430             ///     the File Location Resolver may choose whether it wants open it now, or later
00431             ///     from the streaming device's thread. If it wishes to open it now, then it must
00432             ///     set io_bSyncOpen to true. Otherwise, it needs to do the following: leave 
00433             ///     io_bSyncOpen to false, clear out_fileDesc::iFileSize and out_fileDesc::uSector, 
00434             ///     and set out_fileDesc::deviceID to the streaming device's ID that will handle 
00435             ///     this file. By returning io_bSyncOpen as false, the Stream Manager will interpret
00436             ///     this as a request for deferred file opening, and this function will called again
00437             ///     from the streaming device's thread (this time, with this io_bSyncOpen set to true).
00438             ///     - All members of out_fileDesc will be cleared upon first call to Open().
00439             /// \warning
00440             ///     - It is illegal to return io_bSyncOpen as false if Open() was called with io_bSyncOpen
00441             ///     set to true.
00442             ///     - Deferred file opening requires allocations in the Stream Manager's small object pool.
00443             ///     The File Location Resolver should always choose to open files synchronously if it is 
00444             ///     fast to do so.
00445             ///     - Whether opening is deferred or not, GetBlockSize() is always called right after the
00446             ///     first call to Open(), in the client's thread, and is never called again.
00447             /// \sa 
00448             /// - GetBlockSize()
00449             /// - \ref streamingmanager_lowlevel_location
00450             virtual AKRESULT Open( 
00451                 const AkOSChar*         in_pszFileName,     ///< File name.
00452                 AkOpenMode              in_eOpenMode,       ///< Open mode.
00453                 AkFileSystemFlags *     in_pFlags,          ///< Special flags. Can pass NULL.
00454                 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.
00455                 AkFileDesc &            io_fileDesc         ///< Returned file descriptor.
00456                 ) = 0;
00457 
00458             /// Returns a file descriptor for a given file ID.
00459             /// Performs the operations needed to make the file descriptor usable by
00460             /// the other methods of the interface (for e.g. ask the OS for a valid file handle).
00461             /// \return 
00462             ///     - AK_Success:       A valid file descriptor is returned
00463             ///     - AK_FileNotFound:  File was not found.
00464             ///     - AK_Fail:          File could not be open for any other reason.
00465             /// \return 
00466             ///     - A file descriptor, which contains 
00467             ///         - an unique identifier to be used with functions of the low-level IO 
00468             ///           interface.
00469             ///         - the total stream size in bytes.
00470             ///         - the offset of the beginning of the file (in blocks). 
00471             ///         - a device ID, that was obtained through AK::StreamMgr::CreateDevice().
00472             ///     - A file descriptor, that contains 
00473             ///         - an unique identifier to be used with functions of the low-level IO 
00474             ///           interface.
00475             ///         - the total stream size in bytes.
00476             ///         - the offset from the beginning of the file (in blocks).
00477             ///         - a device ID, that was obtained through AK::StreamMgr::CreateDevice().
00478             ///     - The updated io_bSyncOpen flag depending on the File Resolver's deferred opening policy.
00479             /// \remarks
00480             ///     - Open() is always called first in the client thread.
00481             ///     - If io_bSyncOpen is true, file opening must be executed now. If it is false,
00482             ///     the File Location Resolver may choose whether it wants open it now, or later
00483             ///     from the streaming device's thread. If it wishes to open it now, then it must
00484             ///     set io_bSyncOpen to true. Otherwise, it needs to do the following: leave 
00485             ///     io_bSyncOpen to false, clear out_fileDesc::iFileSize and out_fileDesc::uSector, 
00486             ///     and set out_fileDesc::deviceID to the streaming device's ID that will handle 
00487             ///     this file. By returning io_bSyncOpen as false, the Stream Manager will interpret
00488             ///     this as a request for deferred file opening, and this function will called again
00489             ///     from the streaming device's thread (this time, with this io_bSyncOpen set to true).
00490             ///     - All members of out_fileDesc will be cleared upon first call to Open().
00491             /// \warning
00492             ///     - It is illegal to return io_bSyncOpen as false if Open() was called with io_bSyncOpen
00493             ///     set to true.
00494             ///     - Deferred file opening requires allocations in the Stream Manager's small object pool.
00495             ///     The File Location Resolver should always choose to open files synchronously if it is 
00496             ///     fast to do so.
00497             ///     - Whether opening is deferred or not, GetBlockSize() is always called right after the
00498             ///     first call to Open(), in the client's thread, and is never called again.
00499             /// - GetBlockSize()
00500             /// - \ref streamingmanager_lowlevel_location
00501             virtual AKRESULT Open( 
00502                 AkFileID                in_fileID,          ///< File ID.
00503                 AkOpenMode              in_eOpenMode,       ///< Open mode.
00504                 AkFileSystemFlags *     in_pFlags,          ///< Special flags. Can pass NULL.
00505                 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.
00506                 AkFileDesc &            io_fileDesc         ///< Returned file descriptor.
00507                 ) = 0;
00508         };
00509 
00510         /// \name Audiokinetic implementation-specific Stream Manager factory.
00511         //@{
00512         /// Stream Manager factory.
00513         /// \remarks 
00514         /// - In order for the Stream Manager to work properly, you also need to create 
00515         /// at least one streaming device (and implement its I/O hook), and register the 
00516         /// File Location Resolver with AK::StreamMgr::SetFileLocationResolver().
00517         /// - Use AK::StreamMgr::GetDefaultSettings(), then modify the settings you want,
00518         /// then feed this function with them.
00519         /// \sa 
00520         /// - AK::IAkStreamMgr
00521         /// - AK::StreamMgr::SetFileLocationResolver()
00522         /// - AK::StreamMgr::GetDefaultSettings()
00523         AK_EXTERNAPIFUNC( IAkStreamMgr *, Create )( 
00524             const AkStreamMgrSettings & in_settings     ///< Stream manager initialization settings.
00525             );
00526 
00527         /// Get the default values for the Stream Manager's settings.
00528         /// \sa 
00529         /// - AK::StreamMgr::Create()
00530         /// - AkStreamMgrSettings
00531         /// - \ref streamingmanager_settings
00532         AK_EXTERNAPIFUNC( void, GetDefaultSettings )(
00533             AkStreamMgrSettings &       out_settings    ///< Returned AkStreamMgrSettings structure with default values.
00534             );
00535 
00536         /// Get the one and only File Location Resolver registered to the Stream Manager.
00537         /// \sa
00538         /// - AK::StreamMgr::IAkFileLocationResolver
00539         /// - AK::StreamMgr::SetFileLocationResolver()
00540         AK_EXTERNAPIFUNC( IAkFileLocationResolver *, GetFileLocationResolver )();
00541 
00542         /// Register the one and only File Location Resolver to the Stream Manager.
00543         /// \sa 
00544         /// - AK::StreamMgr::IAkFileLocationResolver
00545         AK_EXTERNAPIFUNC( void, SetFileLocationResolver )(
00546             IAkFileLocationResolver *   in_pFileLocationResolver ///< Interface to your File Location Resolver
00547             );
00548 
00549         /// Get the Stream Manager's pool ID, created according to setting 
00550         /// AkStreamMgrSettings::uMemorySize. 
00551         /// \remarks This is the small objects pool, not one of the device ("Stream I/O") pools.
00552         /// \sa 
00553         /// - AkStreamMgrSettings
00554         /// - AK::StreamMgr::Create()
00555         AK_EXTERNAPIFUNC( AkMemPoolId, GetPoolID )();
00556 
00557         //@}
00558 
00559         /// \name Stream Manager: High-level I/O devices management.
00560         //@{
00561         /// Streaming device creation.
00562         /// Creates a high-level device, with specific settings. 
00563         /// You need to provide the associated low-level I/O hook, implemented on your side.
00564         /// \return The device ID. AK_INVALID_DEVICE_ID if there was an error and it could not be created.
00565         /// \warning 
00566         /// - This function is not thread-safe.
00567         /// - Use a blocking hook (IAkIOHookBlocking) with SCHEDULER_BLOCKING devices, and a 
00568         /// deferred hook (IAkIOHookDeferred) with SCHEDULER_DEFERRED_LINED_UP devices (these flags are
00569         /// specified in the device settings (AkDeviceSettings). The pointer to IAkLowLevelIOHook is
00570         /// statically cast internally into one of these hooks. Implementing the wrong (or no) interface
00571         /// will result into a crash.
00572         /// \remarks 
00573         /// - You may use AK::StreamMgr::GetDefaultDeviceSettings() first to get default values for the 
00574         /// settings, change those you want, then feed the structure to this function.
00575         /// - The returned device ID should be kept by the Low-Level IO, to assign it to file descriptors 
00576         /// in AK::StreamMgr::IAkFileLocationResolver::Open().
00577         /// \sa
00578         /// - AK::StreamMgr::IAkLowLevelIOHook
00579         /// - AK::StreamMgr::GetDefaultDeviceSettings()
00580         /// - \ref streamingmanager_settings
00581         AK_EXTERNAPIFUNC( AkDeviceID, CreateDevice )(
00582             const AkDeviceSettings &    in_settings,        ///< Device settings.
00583             IAkLowLevelIOHook *         in_pLowLevelHook    ///< Associated low-level I/O hook. Pass either a IAkIOHookBlocking or a IAkIOHookDeferred interface, consistent with the type of the scheduler.
00584             );
00585         /// Streaming device destruction.
00586         /// \return AK_Success if the device was successfully destroyed.
00587         /// \warning This function is not thread-safe. No stream should exist for that device when it is destroyed.
00588         AK_EXTERNAPIFUNC( AKRESULT, DestroyDevice )(
00589             AkDeviceID                  in_deviceID         ///< Device ID of the device to destroy.
00590             );
00591 
00592         /// Get the default values for the streaming device's settings. Recommended usage
00593         /// is to call this function first, then pass the settings to AK::StreamMgr::CreateDevice().
00594         /// \sa 
00595         /// - AK::StreamMgr::CreateDevice()
00596         /// - AkDeviceSettings
00597         /// - \ref streamingmanager_settings
00598         AK_EXTERNAPIFUNC( void, GetDefaultDeviceSettings )(
00599             AkDeviceSettings &          out_settings        ///< Returned AkDeviceSettings structure with default values.
00600             );
00601         //@}
00602 
00603         /// \name Language management.
00604         //@{
00605         /// Set the current language once and only once, here. The language name is stored in a static buffer 
00606         /// inside the Stream Manager. In order to resolve localized (language-specific) file location,
00607         /// AK::StreamMgr::IAkFileLocationResolver implementations query this string. They may use it to 
00608         /// construct a file path (for e.g. SDK/samples/SoundEngine/Common/AkFileLocationBase.cpp), or to
00609         /// find a language-specific file within a look-up table (for e.g. SDK/samples/SoundEngine/Common/AkFilePackageLUT.cpp).
00610         /// Pass a valid null-terminated string, without a trailing slash or backslash. Empty strings are accepted.
00611         /// You may register for language changes (see RegisterToLanguageChangeNotification()). 
00612         /// After changing the current language, all observers are notified.
00613         /// \return AK_Success if successful (if language string has less than AK_MAX_LANGUAGE_NAME_SIZE characters). AK_Fail otherwise.
00614         /// \warning Not multithread safe.
00615         /// \sa 
00616         /// - AK::StreamMgr::GetCurrentLanguage()
00617         /// - AK::StreamMgr::AddLanguageChangeObserver()
00618         AK_EXTERNAPIFUNC( AKRESULT, SetCurrentLanguage )(
00619             const AkOSChar *    in_pszLanguageName          ///< Language name.
00620             );
00621 
00622         /// Get the current language. The language name is stored in a static buffer inside the Stream Manager, 
00623         /// with AK::StreamMgr::SetCurrentLanguage(). In order to resolve localized (language-specific) file location,
00624         /// AK::StreamMgr::IAkFileLocationResolver implementations query this string. They may use it to 
00625         /// construct a file path (for e.g. SDK/samples/SoundEngine/Common/AkFileLocationBase.cpp), or to
00626         /// find a language-specific file within a look-up table (for e.g. SDK/samples/SoundEngine/Common/AkFilePackageLUT.cpp).
00627         /// \return Current language.
00628         /// \sa AK::StreamMgr::SetCurrentLanguage()
00629         AK_EXTERNAPIFUNC( const AkOSChar *, GetCurrentLanguage )();
00630 
00631         /// Definition of handlers for language change notifications.
00632         /// Called after SetCurrentLanguage() is called.
00633         /// \warning Do not call AddLanguageChangeObserver or SetCurrentLanguage from within your handler.
00634         /// \warning Not multithread safe.
00635         /// \sa 
00636         /// - AK::StreamMgr::SetCurrentLanguage()
00637         /// - AK::StreamMgr::AddLanguageChangeObserver()
00638         AK_CALLBACK( void, AkLanguageChangeHandler )( 
00639             const AkOSChar * const in_pLanguageName,///< New language name.
00640             void * in_pCookie                       ///< Cookie that was passed to AddLanguageChangeObserver().
00641             );
00642 
00643         /// Register to language change notifications.
00644         /// \return AK_Success if successful, AK_Fail otherwise (no memory or no cookie).
00645         /// \warning Not multithread safe.
00646         /// \sa 
00647         /// - AK::StreamMgr::SetCurrentLanguage()
00648         /// - AK::StreamMgr::RemoveLanguageChangeObserver()
00649         AK_EXTERNAPIFUNC( AKRESULT, AddLanguageChangeObserver )(
00650             AkLanguageChangeHandler in_handler, ///< Callback function.
00651             void * in_pCookie                   ///< Cookie, passed back to AkLanguageChangeHandler. Must set.
00652             );
00653 
00654         /// Unregister to language change notifications. Use the cookie you have passed to 
00655         /// AddLanguageChangeObserver() to identify the observer.
00656         /// \warning Not multithread safe.
00657         /// \sa 
00658         /// - AK::StreamMgr::SetCurrentLanguage()
00659         /// - AK::StreamMgr::AddLanguageChangeObserver()
00660         AK_EXTERNAPIFUNC( void, RemoveLanguageChangeObserver )(
00661             void * in_pCookie                   ///< Cookie that was passed to AddLanguageChangeObserver().
00662             );
00663 
00664         /// \name Stream Manager: Cache management.
00665         //@{
00666         /// Flush cache of all devices. This function has no effect for devices where
00667         /// AkDeviceSettings::bUseStreamCache was set to false (no caching).
00668         /// \sa
00669         /// - \ref streamingmanager_settings
00670         AK_EXTERNAPIFUNC( void, FlushAllCaches )();
00671         
00672         //@}
00673     }
00674 }
00675 
00676 #endif //_AK_STREAM_MGR_MODULE_H_