| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307 |
- /*
- ** Command & Conquer Generals(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /*****************************************************************************
- ** **
- ** Westwood Studios Pacific. **
- ** **
- ** Confidential Information **
- ** Copyright (C) 2000 - All Rights Reserved **
- ** **
- ******************************************************************************
- ** **
- ** Project: Dune Emperor **
- ** **
- ** Module: <module> (<prefix>_) **
- ** **
- ** Version: $ID$ **
- ** **
- ** File name: audstrm.cpp **
- ** **
- ** Created by: 11/10/95 TR **
- ** **
- ** Description: <description> **
- ** **
- *****************************************************************************/
- /*****************************************************************************
- ** Includes **
- *****************************************************************************/
- #include <memory.h>
- #include <wpaudio/altypes.h>
- #include <wpaudio/list.h>
- #include <wpaudio/StreamBuffering.h>
- #include <wpaudio/memory.h>
- #include <wsys/file.h>
- // 'assignment within condition expression'.
- #pragma warning(disable : 4706)
- DBG_DECLARE_TYPE ( STM_SBUFFER )
- DBG_DECLARE_TYPE ( STM_ACCESS )
- DBG_DECLARE_TYPE ( STM_STREAM )
- /*****************************************************************************
- ** Externals **
- *****************************************************************************/
- /*****************************************************************************
- ** Defines **
- *****************************************************************************/
- /*****************************************************************************
- ** Private Types **
- *****************************************************************************/
- /*****************************************************************************
- ** Private Data **
- *****************************************************************************/
- /*****************************************************************************
- ** Public Data **
- *****************************************************************************/
- /*****************************************************************************
- ** Private Prototypes **
- *****************************************************************************/
- static STM_SBUFFER* STM_next_sbuffer ( STM_SBUFFER * sbuf );
- static void STM_stream_init ( STM_STREAM * stm );
- static void STM_stream_reset ( STM_STREAM * stm );
- static void STM_access_init ( STM_STREAM * stm, STM_ACCESS *access, int id );
- static void STM_access_reset ( STM_ACCESS *access, STM_SBUFFER *first );
- static void STM_access_return_to_start ( STM_ACCESS *access );
- static void STM_sbuffer_init ( STM_SBUFFER * buf );
- static void STM_sbuffer_reset( STM_SBUFFER *sbuf );
- /*****************************************************************************
- ** Private Functions **
- *****************************************************************************/
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- static STM_SBUFFER* STM_next_sbuffer ( STM_SBUFFER * sbuf )
- {
- STM_STREAM *stm;
- STM_SBUFFER *head;
- DBG_Function ("STM_next_sbuffer");
- DBG_ASSERT_TYPE ( sbuf, STM_SBUFFER );
- stm = sbuf->stream;
- head = (STM_SBUFFER *) &stm->buffer_list;
- sbuf = (STM_SBUFFER *)sbuf->nd.next;
- if ( sbuf == head )
- {
- sbuf = (STM_SBUFFER *)sbuf->nd.next;
- if (sbuf == head )
- {
- return NULL;
- }
- }
- return sbuf;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- static void STM_stream_init ( STM_STREAM * stm )
- {
- int i;
- /*DBG_Function ("STM_stream_init"); */
- DBG_SET_TYPE ( stm, STM_STREAM );
- ListInit ( &stm->buffer_list );
- LockInit ( &stm->ref );
- /* init access structs */
- for ( i = 0; i < vSTM_MAX_ACCESSORS; i++)
- {
- STM_access_init ( stm, &stm->access[i], i );
- }
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void STM_stream_reset( STM_STREAM* stm )
- {
- STM_SBUFFER *head,
- *first,
- *buf;
- DBG_Function ("STM_StreamReset");
- DBG_ASSERT_TYPE ( stm, STM_STREAM );
- head = (STM_SBUFFER *) &stm->buffer_list;
- if ( (first = (STM_SBUFFER *) head->nd.next) == head )
- {
- first = NULL;
- }
- if ( first ) /* there is at least one buffer */
- {
- int id = 0;
- buf = first;
- while ( buf != head )
- {
- STM_sbuffer_reset ( buf );
- buf->id = id++;
- buf = (STM_SBUFFER *) buf->nd.next;
- }
- }
- { /* reset the access interfaces */
- int i;
- for ( i = 0; i < vSTM_MAX_ACCESSORS; i++)
- {
- STM_access_reset ( &stm->access[i], first );
- }
- /* kick start the IN accessor */
- stm->access[vSTM_ACCESS_ID_IN].bytes_in += stm->bytes;
- }
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- static void STM_access_init ( STM_STREAM * stm, STM_ACCESS *access, int id )
- {
- DBG_Function ("STM_access_init");
- DBG_ASSERT_TYPE ( stm, STM_STREAM );
- DBG_SET_TYPE ( access, STM_ACCESS );
- access->stream = stm;
- DBG_CODE
- (
- LockInit ( &access->in_service ); /* we use the ref to stop nesting */
- )
- LockInit ( &access->ref );
- access->last_error = vNO_ERROR;
- access->id = id;
- access->mode = vSTM_ACCESS_MODE_UPDATE;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- static void STM_access_reset( STM_ACCESS *access, STM_SBUFFER *first )
- {
- DBG_Function ("STM_access_reset");
- DBG_ASSERT_TYPE ( access, STM_ACCESS );
- access->start_buffer = first;
- access->bytes_in = W_UINT_MAX -1000;
- access->bytes_out = access->bytes_in;
- access->position = 0;
- STM_access_return_to_start ( access );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- static void STM_access_return_to_start ( STM_ACCESS *access )
- {
- access->access_pos = 0;
- access->SBuffer = access->start_buffer;
- if ( access->start_buffer )
- {
- access->Block.Data = access->start_buffer->region[access->id].Data;
- }
- else
- {
- access->Block.Data = NULL;
- }
- access->Block.Bytes = 0;
- W_FlagsClear ( access->flags, mSTM_ACCESS_TOP_OF_START);
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- static void STM_sbuffer_init ( STM_SBUFFER *buf )
- {
- DBG_SET_TYPE ( buf, STM_SBUFFER );
- ListNodeInit ( &buf->nd );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- static void STM_sbuffer_reset( STM_SBUFFER *sbuf )
- {
- int i;
- DBG_Function ("STM_sbuffer_reset");
- DBG_ASSERT_TYPE ( sbuf, STM_SBUFFER );
- /* init access structs */
- for ( i = 0; i < vSTM_MAX_ACCESSORS; i++)
- {
- sbuf->region[i].Data = sbuf->data_region.Data;
- sbuf->region[i].Bytes = sbuf->data_region.Bytes;
- }
- }
- /*****************************************************************************
- ** Public Functions **
- *****************************************************************************/
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- STM_STREAM* STM_StreamCreate( void )
- {
- STM_STREAM *stm;
- DBG_Function ("STM_StreamCreate");
- MEM_ALLOC_STRUCT ( stm, STM_STREAM, mMEM_INTERNAL| vMEM_ANY );
- STM_stream_init ( stm );
- /* that was simple ;-) */
- return stm;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void STM_StreamDestroy( STM_STREAM* stm )
- {
- DBG_Function ("STM_StreamDestroy");
- DBG_ASSERT_TYPE ( stm, STM_STREAM );
- DBG_ASSERT ( ! (stm->flags & mSTM_STREAM_FAKE )); /* you can not destroy a fake stream */
- DBG_ASSERT ( !Locked ( &stm->ref) ); /* you are trying to destroy a stream that is still being accessed */
- STM_StreamDestroyBuffers ( stm );
- DBG_CODE
- (
- int i;
- for ( i = 0; i < vSTM_MAX_ACCESSORS; i++)
- {
- DBG_INVALIDATE_TYPE ( &stm->access[i] ); /* ensure that nobody tries to use an accessor after it is dead */
- }
- )
- DBG_INVALIDATE_TYPE ( stm );
- MEM_Free ( stm );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void STM_StreamDestroyBuffers( STM_STREAM* stm )
- {
- STM_SBUFFER *buf,
- *head;
- DBG_Function ("STM_StreamDestroy");
- DBG_ASSERT_TYPE ( stm, STM_STREAM );
- DBG_ASSERT ( !Locked ( &stm->ref) ); /* you are trying to destroy a stream that is still being accessed */
- head = (STM_SBUFFER *) &stm->buffer_list;
- while ( ( buf = (STM_SBUFFER *) head->nd.next) != head )
- {
- STM_SBufferRemove ( buf );
- STM_SBufferDestroy ( buf );
- }
- STM_StreamReset ( stm );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void STM_StreamReset( STM_STREAM* stm )
- {
- DBG_Function ("STM_StreamReset");
- DBG_ASSERT_TYPE ( stm, STM_STREAM );
- DBG_ASSERT ( !Locked ( &stm->ref )); /* you cannot reset the stream will it's in use */
- STM_stream_reset ( stm );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void STM_StreamAddSBuffer( STM_STREAM* stm, STM_SBUFFER *sbuf )
- {
- DBG_Function ("STM_StreamAddSBuffer");
- DBG_ASSERT_TYPE ( stm, STM_STREAM );
- DBG_ASSERT_TYPE ( sbuf, STM_SBUFFER );
- DBG_ASSERT ( !(ListNodeInList ( &sbuf->nd ))); /* buffer is already in a list */
- ListNodeAppend ( (ListNode *) &stm->buffer_list, &sbuf->nd );
- stm->buffers++;
- stm->bytes += sbuf->data_region.Bytes;
- sbuf->stream = stm;
- W_FlagsClear ( stm->flags, mSTM_STREAM_RESET_DONE ); /* make sure that a reset is performed again */
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int STM_StreamCreateSBuffers( STM_STREAM* stm, int num_buffers, int buf_size, int align )
- {
- int bcount = 0;
- STM_SBUFFER *buf;
- DBG_Function ("STM_StreamAddBuffers");
- DBG_ASSERT_TYPE ( stm, STM_STREAM );
- DBG_ASSERT ( num_buffers > 0 );
- DBG_ASSERT ( buf_size > 0 );
- DBG_ASSERT ( align >= 0 );
- while (num_buffers--)
- {
- if (! (buf = STM_SBufferCreate ( buf_size, align )))
- {
- break;
- }
- STM_StreamAddSBuffer ( stm, buf );
- bcount++;
- }
- return bcount;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- STM_ACCESS* STM_StreamAcquireAccess ( STM_STREAM *stm, int access_id )
- {
- STM_ACCESS *access;
- DBG_Function ("STM_StreamAcquireAccess");
- DBG_ASSERT_TYPE ( stm, STM_STREAM );
- DBG_ASSERT ( access_id >= 0); /* ilegal value */
- DBG_ASSERT ( access_id < vSTM_MAX_ACCESSORS ); /* legal values are vSTM_ACCESS_ID_OUT or vSTM_ACCESS_ID_IN */
- access = &stm->access[access_id];
- if ( Locked ( &access->ref ) ) /* someone has already acquired access */
- {
- DBGPRINTF (( "%s access to stream failed. Access already acquired.\n",access->id == vSTM_ACCESS_ID_IN ? "Write" : "Read" ));
- return NULL;
- }
-
- DBG_CODE
- (
- if ( !stm->buffers)
- {
- msg_assert ( FALSE, ( "Trying to acquire a stream with no buffers") );
- }
- ) /* you must add at least one buffer to a stream before you can use it */
- /* if this is the first time the stream has been acquired then perform a reset on the buffers */
- if ( !Locked ( &stm->ref ) )
- {
- STM_stream_reset ( stm );
- }
- LockAcquire ( &access->ref ); /* mark access interface as in use */
- LockAcquire ( &stm->ref ); /* mark stream as in use */
- return access;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- uint STM_StreamTotalBytesIn ( STM_STREAM *stm )
- {
- DBG_Function ("STM_StreamTotalBytesIn");
- DBG_ASSERT_TYPE ( stm, STM_STREAM );
- return STM_AccessTotalBytes (&stm->access[vSTM_ACCESS_ID_OUT]);
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- uint STM_StreamTotalBytesTillFull ( STM_STREAM *stm )
- {
- DBG_Function ("STM_StreamTotalBytesTillFull");
- DBG_ASSERT_TYPE ( stm, STM_STREAM );
- return STM_AccessTotalBytes (&stm->access[vSTM_ACCESS_ID_IN]);
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- uint STM_StreamTotalBytes ( STM_STREAM *stm )
- {
- DBG_Function ("STM_StreamTotalBytes");
- DBG_ASSERT_TYPE ( stm, STM_STREAM );
- return stm->bytes;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int STM_StreamFull ( STM_STREAM *stm )
- {
- DBG_Function ("STM_StreamFull");
- DBG_ASSERT_TYPE ( stm, STM_STREAM );
- return STM_StreamTotalBytesTillFull( stm ) == 0;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- STM_SBUFFER* STM_SBufferCreate( int bytes, int align )
- {
- STM_SBUFFER *buf;
- DBG_Function ("STM_SBufferCreate");
- DBG_ASSERT ( bytes > 0 );
- DBG_ASSERT ( align >= 0 );
- MEM_ALLOC_STRUCT ( buf, STM_SBUFFER, mMEM_INTERNAL | vMEM_ANY );
- DBG_SET_TYPE ( buf, STM_SBUFFER );
- STM_sbuffer_init ( buf );
- /* allocate the buffer, add space for alignment */
- buf->buffer_memory = (uint8 *) AudioMemAlloc ( bytes + ALIGN_UPBY(1,align));
- if ( !buf->buffer_memory )
- {
- goto error;
- }
- buf->align = align;
- buf->data_region.Data = ( uint8 *)ALIGN_UPBY ( buf->buffer_memory, align);
- buf->data_region.Bytes = bytes;
- return buf;
- error:
- if ( buf )
- {
- STM_SBufferDestroy ( buf );
- }
- return NULL;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void STM_SBufferDestroy( STM_SBUFFER *sbuf )
- {
- DBG_Function ("STM_SBufferDestroy");
- DBG_ASSERT_TYPE ( sbuf, STM_SBUFFER );
- DBG_ASSERT ( !ListNodeInList( &sbuf->nd )); /* you must remove the buffer from its stream */
- if ( sbuf->buffer_memory )
- {
- MEM_Free ( sbuf->buffer_memory );
- }
- DBG_INVALIDATE_TYPE ( sbuf );
- MEM_Free ( sbuf );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void STM_SBufferRemove( STM_SBUFFER *sbuf )
- {
- STM_STREAM *stm;
- DBG_Function ("STM_SBufferRemove");
- DBG_ASSERT_TYPE ( sbuf, STM_SBUFFER );
- DBG_ASSERT ( ListNodeInList ( &sbuf->nd )); /* buffer is not presently in a stream */
- DBG_ASSERT ( sbuf->stream != NULL ); /* bad data */
- DBG_ASSERT ( !Locked ( &sbuf->stream->ref)); /* stream is in use */
- ListNodeRemove ( &sbuf->nd );
- stm = sbuf->stream;
- sbuf->stream = NULL;
- stm->buffers--;
- stm->bytes -= sbuf->data_region.Bytes;
- DBG_ASSERT ( stm->bytes >= 0 ); /* somethings gone very wrong */
- DBG_ASSERT ( stm->buffers >= 0 ); /* somethings gone very wrong */
- W_FlagsClear ( stm->flags, mSTM_STREAM_RESET_DONE ); /* make sure that a reset is performed again */
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- STM_SBUFFER* STM_SBufferNext( STM_SBUFFER *sbuf )
- {
- DBG_Function ("STM_SBufferNext");
- DBG_ASSERT_TYPE ( sbuf, STM_SBUFFER );
- DBG_ASSERT ( sbuf->stream != NULL ); /* buffer is not currently in a stream */
- return STM_next_sbuffer ( sbuf );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void STM_AccessRelease ( STM_ACCESS *access )
- {
- DBG_Function ("STM_AccessRelease");
- DBG_ASSERT_TYPE ( access, STM_ACCESS );
- DBG_ASSERT ( Locked ( &access->ref ) ); /* already released, or was never acquired */
- LockRelease ( &access->ref );
- LockRelease ( &access->stream->ref );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int STM_AccessSetMode ( STM_ACCESS *access, int mode )
- {
- DBG_Function ("STM_AccessSetMode");
- DBG_ASSERT_TYPE ( access, STM_ACCESS );
- DBG_ASSERT ( mode >= 0 ); /* invalid mode */
- DBG_ASSERT ( mode < vSTM_ACCESS_MAX_MODES ); /* see vSTM_ACCESS_MODE_?? in wcore/stream.h */
- DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
- access->mode = mode;
- return vNO_ERROR;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int STM_AccessMode ( STM_ACCESS *access )
- {
- DBG_Function ("STM_AccessMode");
- DBG_ASSERT_TYPE ( access, STM_ACCESS );
- DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
- return access->mode;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int STM_AccessID ( STM_ACCESS *access )
- {
- DBG_Function ("STM_AccessID");
- DBG_ASSERT_TYPE ( access, STM_ACCESS );
- DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
- return access->id;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int STM_AccessTransfer( STM_ACCESS* access, void *data, int bytes )
- {
- int transfer,
- transfered = 0;
- uint8 *data8;
- DBG_Function ("STM_AccessTransfer");
- DBG_ASSERT_TYPE ( access, STM_ACCESS );
- DBG_ASSERT ( data != NULL );
- DBG_ASSERT ( bytes > 0);
- DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
- data8 = (uint8 *) data;
- STM_AccessGetBlock ( access );
- do
- {
- /* how much can we transfer this block */
- if ( (transfer = access->Block.Bytes) > bytes )
- {
- transfer = bytes;
- }
- if ( !transfer )
- {
- break; /* stream has been exhuasted */
- }
- /* do the transfer */
- switch ( access->id )
- {
- case vSTM_ACCESS_ID_IN:
- {
- memcpy ( access->Block.Data, data8, transfer );
- break;
- }
- case vSTM_ACCESS_ID_OUT:
- default: /* all accessor default to out */
- {
- memcpy ( data8, access->Block.Data, transfer );
- break;
- }
- }
- /* advance pointers */
- STM_AccessAdvance ( access, transfer );
- data8 += transfer;
- /* record work done */
- bytes -= transfer;
- transfered += transfer;
- } while ( bytes );
- return transfered;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int STM_AccessFileTransfer( STM_ACCESS* access, File *file, int bytes, int *transfered)
- {
- int transfer;
- DBG_Function ("STM_AccessFileTransfer");
- DBG_ASSERT_TYPE ( access, STM_ACCESS );
- DBG_ASSERT ( file != NULL );
- DBG_ASSERT ( bytes >= 0);
- DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
- STM_AccessGetBlock ( access );
- int dummy;
- if ( !transfered )
- {
- transfered = &dummy;
- }
- *transfered = 0;
- do
- {
- if ( (transfer = access->Block.Bytes) > bytes )
- {
- transfer = bytes;
- }
- if ( !transfer )
- {
- break; /* stream has been exhuasted */
- }
- switch ( access->id )
- {
- case vSTM_ACCESS_ID_IN:
- {
- transfer = file->read ( access->Block.Data, transfer );
- if ( transfer < 0 )
- {
- access->last_error = ERROR_CODE_FAIL;
- }
- break;
- }
- case vSTM_ACCESS_ID_OUT:
- default: /* all accessor default to out */
- {
- transfer = file->write ( access->Block.Data, transfer );
- if ( transfer < 0 )
- {
- access->last_error = ERROR_CODE_FAIL;
- }
- break;
- }
- }
- if ( !transfer )
- {
- return STM_EOF;
- }
- if ( transfer == -1 )
- {
- return STM_FAIL;
- }
- /* do the transfer */
- STM_AccessAdvance ( access, transfer );
- bytes -= transfer;
- *transfered += transfer;
- } while ( bytes );
- return STM_OK;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int STM_AccessGetError ( STM_ACCESS *access )
- {
- DBG_Function ("STM_AccessGetError");
- DBG_ASSERT_TYPE ( access, STM_ACCESS );
- DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
- return access->last_error;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int STM_AccessUpdate ( STM_ACCESS *access )
- {
- STM_SBUFFER *sbuf;
- int bytes_to_update;
- int bytes_updated;
- STM_ACCESS *up_stream_accessor;
- DBG_Function ("STM_AccessUpdate");
- DBG_ASSERT_TYPE ( access, STM_ACCESS );
- DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
- if ( (bytes_to_update = access->access_pos ) == 0)
- {
- return 0; /* no updating to perform */
- }
- /* first thing to do is to tell the up stream accessor that there is more
- buffer area avaiable for him to process */
- up_stream_accessor = STM_AccessUpStreamAccessor ( access );
- access->bytes_out += bytes_to_update; /* reduce our byte count accordingly */
- up_stream_accessor->bytes_in += bytes_to_update;
- /* now move our start buffer to its new posistion */
- sbuf = access->start_buffer ;
- DBG_ASSERT ( sbuf != NULL ); /* fubar */
- bytes_updated = bytes_to_update;
- do
- {
- STM_REGION *region;
- region = &sbuf->region[access->id];
- if ( region->Bytes <= bytes_to_update )
- {
- bytes_to_update -= region->Bytes;
- /* reset the current sbuffer region and move on to the next */
- region->Data = sbuf->data_region.Data; /* reset back to top of buffer */
- region->Bytes = sbuf->data_region.Bytes;
- sbuf = STM_next_sbuffer ( sbuf );
- }
- else
- {
- /* adjust start of data pointer and bytes accordingly */
- region->Data += bytes_to_update;
- region->Bytes -= bytes_to_update;
- bytes_to_update = 0; /* no more bytes to up date */
- }
- } while ( bytes_to_update );
- access->start_buffer = sbuf; /* update to new start buffer */
- STM_AccessReturnToStart ( access ); /* resycn access */
- return bytes_updated;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int STM_AccessAdvance ( STM_ACCESS *access, int bytes_to_advance )
- {
- int bytes_advanced = 0,
- bytes_available,
- advance;
- int total_bytes;
- int ok = TRUE;
- DBG_Function ("STM_AccessAdvance");
- DBG_ASSERT_TYPE ( access, STM_ACCESS );
- DBG_ASSERT ( bytes_to_advance >= 0);
- total_bytes = STM_AccessTotalBytes ( access );
- DBG_ASSERT ( access->access_pos <= total_bytes );
- DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
- if ( (bytes_available = total_bytes - access->access_pos ) == 0)
- {
- /* we are at the end of the data */
- access->Block.Bytes = 0;
- return 0;
- }
- DBG_ASSERT ( bytes_available >= 0 );
- if ( bytes_available < bytes_to_advance )
- {
- bytes_to_advance = bytes_available;
- }
- DBG_ASSERT ( access->SBuffer != NULL ); /* fubar */
- do
- {
- STM_REGION *buf_region;
- buf_region = &access->SBuffer->region[access->id];
- /* update block Bytes to real value */
- if ( access->flags & mSTM_ACCESS_TOP_OF_START )
- {
- access->Block.Bytes = bytes_available; /* this must be a valid range as total_bytes
- cannot be greater then the total stream bytes */
- }
- else
- {
- int actual_bytes =buf_region->Bytes - ( (uint) access->Block.Data - (uint) buf_region->Data );
- if ( actual_bytes < bytes_available )
- {
- access->Block.Bytes = actual_bytes;
- }
- else
- {
- access->Block.Bytes = bytes_available;
- }
- }
- /* advance access */
- if ( (advance = bytes_to_advance) == 0 )
- {
- break; /* we are done */
- }
- if ( advance >= access->Block.Bytes )
- {
- advance = access->Block.Bytes;
- /* move on to next buffer */
- access->SBuffer = STM_next_sbuffer ( access->SBuffer );
- if ( access->SBuffer == access->start_buffer )
- {
- /* this is a special case where we have come back round
- to the start buffer. This means that area we are interested in
- the area at the top of the buffer */
- W_FlagsSet ( access->flags, mSTM_ACCESS_TOP_OF_START);
- access->Block.Data = access->SBuffer->data_region.Data; /* this is the top of the buffer */
- }
- else
- {
- access->Block.Data = access->SBuffer->region[access->id].Data;
- }
- }
- else
- {
- access->Block.Data += advance;
- }
- bytes_to_advance -= advance;
- bytes_advanced += advance;
- bytes_available -= advance;
- } while ( ok );
- access->access_pos += bytes_advanced; /* update our position */
- access->position += bytes_advanced;
- if ( access->position >= STM_StreamTotalBytes(access->stream) )
- {
- access->position = access->position % STM_StreamTotalBytes ( access->stream );
- }
- if ( (access->access_pos )&& (STM_AccessMode ( access ) == vSTM_ACCESS_MODE_UPDATE) )
- {
- STM_AccessUpdate ( access );
- }
- return bytes_advanced;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void STM_AccessReturnToStart ( STM_ACCESS *access )
- {
- DBG_Function ("STM_AccessReturnToStart");
- DBG_ASSERT_TYPE ( access, STM_ACCESS );
- DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
- STM_access_return_to_start ( access );
- STM_AccessAdvance ( access, 0 ); /* make sure data block is valid */
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int STM_AccessNextBlock ( STM_ACCESS *access )
- {
- DBG_Function ("STM_AccessNextBlock");
- DBG_ASSERT_TYPE ( access, STM_ACCESS );
- DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
- STM_AccessGetBlock ( access );
- if ( access->Block.Bytes )
- {
- STM_AccessAdvance ( access, access->Block.Bytes );
- }
- return ERROR_CODE_FAIL;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int STM_AccessGetBlock ( STM_ACCESS *access )
- {
- DBG_Function ("STM_AccessGetBlock");
- DBG_ASSERT_TYPE ( access, STM_ACCESS );
- DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
- STM_AccessAdvance ( access, 0 ); /* kick start access */
- return access->Block.Bytes;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- uint STM_AccessTotalBytes ( STM_ACCESS *access )
- {
- uint total_bytes,
- bytes_in,
- bytes_out;
- DBG_Function ("STM_AccessTotalBytes");
- DBG_ASSERT_TYPE ( access, STM_ACCESS );
- bytes_in = access->bytes_in;
- bytes_out = access->bytes_out;
- if ( (bytes_in < bytes_out))
- {
- total_bytes = (W_UINT_MAX - bytes_out) +1 + bytes_in;
- }
- else
- {
- total_bytes = bytes_in - bytes_out;
- }
- return total_bytes;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- uint STM_AccessPosition ( STM_ACCESS *access )
- {
- DBG_ASSERT_TYPE ( access, STM_ACCESS );
- return access->position;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- STM_ACCESS* STM_AccessUpStreamAccessor ( STM_ACCESS *access )
- {
- int id;
- DBG_Function ("STM_AccessUpStreamAccessor");
- DBG_ASSERT_TYPE ( access, STM_ACCESS );
- DBG_ASSERT ( access->id >= 0 );
- DBG_ASSERT ( access->id < vSTM_MAX_ACCESSORS ); /* something has gone wrong. id should not be out of range */
- DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
- if ( (id = access->id + 1 ) == vSTM_MAX_ACCESSORS )
- {
- id = 0;
- }
- return &access->stream->access[id];
- }
- #ifdef _DEBUG
- #include <wpaudio/time.h>
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void STM_ProfileStart ( STM_PROFILE *pf )
- {
- DBG_Function ("STM_ProfileStart");
- DBG_ASSERT ( pf != NULL );
- pf->bytes = 0;
- pf->last_update = AudioGetTime ();
- pf->update_interval = SECONDS(3);
- W_FlagsSet ( pf->flags, mSTM_PROFILE_ACTIVE );
- pf->rate = 0;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void STM_ProfileStop ( STM_PROFILE *pf )
- {
- DBG_Function ("STM_ProfileStop");
- DBG_ASSERT ( pf != NULL );
- W_FlagsClear ( pf->flags, mSTM_PROFILE_ACTIVE );
- pf->rate = 0;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void STM_ProfileUpdate ( STM_PROFILE *pf, int bytes )
- {
- TimeStamp duration;
- DBG_Function ("STM_ProfileUpdate");
- DBG_ASSERT ( pf != NULL );
- if ( pf->flags & mSTM_PROFILE_ACTIVE )
- {
- duration = AudioGetTime() - pf->last_update;
- pf->bytes += bytes;
- if ( duration > pf->update_interval )
- {
- pf->rate = (int) ((pf->bytes * SECONDS(1)) / duration);
- pf->last_update = AudioGetTime ();
- pf->bytes = 0;
- }
- }
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int STM_ProfileResult ( STM_PROFILE *pf )
- {
- DBG_Function ("STM_ProfileResult");
- DBG_ASSERT ( pf != NULL );
- if ( pf->flags & mSTM_PROFILE_ACTIVE )
- {
- return pf->rate;
- }
- return 0;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int STM_ProfileActive ( STM_PROFILE *pf )
- {
- return pf->flags & mSTM_PROFILE_ACTIVE ;
- }
- #endif // _DEBUG
|