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_