| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643 |
- /*
- ** Command & Conquer Generals Zero Hour(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: audplay.cpp **
- ** **
- ** Created by: 04/??/00 TR **
- ** **
- ** Description: <description> **
- ** **
- *****************************************************************************/
- /*****************************************************************************
- ** Includes **
- *****************************************************************************/
- #include <stdio.h>
- #include <string.h>
- #include <wpaudio/altypes.h>
- #include <wpaudio/Streamer.h>
- #include <wpaudio/StreamBuffering.h>
- #include <wpaudio/source.h>
- #include <wsys/file.h>
- #include <wpaudio/device.h>
- #include <wpaudio/channel.h>
- #include <wpaudio/thread.h>
- // 'assignment within condition expression'.
- #pragma warning(disable : 4706)
- DBG_DECLARE_TYPE ( AudioStreamer );
- /*****************************************************************************
- ** Externals **
- *****************************************************************************/
- /*****************************************************************************
- ** Defines **
- *****************************************************************************/
- #define AS_PLAYING 0x00000001
- #define AS_PAUSED 0x00000002
- #define AS_FILL 0x00000004 // service thread should fill this stream
- #define AS_NO_FILE_CLOSE 0x00000080 // file was not opened by us
- #define AS_OPEN 0x00000010 // we have a file to play
- #define AS_LOOPING 0x00000020 // seamlessly loop stream
- #define MIN_FRAME_SIZE (4*1024)
- /*****************************************************************************
- ** Private Types **
- *****************************************************************************/
- typedef struct AudioStreamerTag
- {
- ListNode nd;
- volatile int flags;
- AudioDevice *device;
- AudioChannel *channel;
- TimeStamp buffering;
- TimeStamp end_time_stamp;
- TimeStamp start_time_stamp;
- STM_STREAM *stream;
- STM_ACCESS *in;
- STM_ACCESS *out;
- AudioSample sample;
- AudioFormat format;
- File *file;
- Lock pause;
- Lock lock;
- int pending_bytes; // number of bytes submitted to audio playback
- int total_bytes;
- int data_start;
- int bytes_left;
- int frame_size;
-
- int stream_pos;
- int max_volume;
-
- char stream_name[80];
-
- #ifndef IG_FINAL_RELEASE
- char name[200];
- #endif
- DBG_TYPE()
- } AudioStreamer;
- /*****************************************************************************
- ** Private Data **
- *****************************************************************************/
- static AUD_Thread *thread = NULL;
- static ListHead streams;
- static int initialized = FALSE;
- /*****************************************************************************
- ** Public Data **
- *****************************************************************************/
- /*****************************************************************************
- ** Private Prototypes **
- *****************************************************************************/
- static int streamNextFrame ( AudioChannel *channel );
- static int streamSampleDone ( AudioChannel *channel );
- static int streamStop ( AudioChannel *channel );
- static void service_stream ( AudioStreamer *as );
- static AUD_ThreadCB service_streams;
- static int recalcBuffering ( AudioStreamer *as, TimeStamp buffering, AudioFormat *format );
- /*****************************************************************************
- ** Private Functions **
- *****************************************************************************/
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- static int streamNextFrame ( AudioChannel *channel )
- {
- AudioStreamer *as = (AudioStreamer*) channel->Data;
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- STM_AccessAdvance ( as->out, as->pending_bytes ); // mark these bytes as having been used
- as->stream_pos += as->pending_bytes;
- if ( as->stream_pos > as->total_bytes )
- {
- as->stream_pos %= as->total_bytes;
- }
- STM_AccessGetBlock ( as->out );
- if ( as->frame_size > as->out->Block.Bytes )
- {
- as->pending_bytes = as->out->Block.Bytes;
- }
- else
- {
- as->pending_bytes = as->frame_size;
- }
-
- channel->bytesInFrame = as->pending_bytes;
- channel->bytesRemaining = channel->bytesInFrame;
- channel->frameData = (char *) as->out->Block.Data;
- return vNO_ERROR;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- static int streamSampleDone ( AudioChannel *channel )
- {
- return streamStop ( channel );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- static int streamStop ( AudioChannel *channel )
- {
- AudioStreamer *as = (AudioStreamer*) channel->Data;
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- if ( as->flags & (AS_PLAYING|AS_PAUSED))
- {
- as->end_time_stamp = AudioGetTime();
- }
- FLAGS_CLEAR ( as->flags, AS_PLAYING | AS_PAUSED | AS_FILL );
- LockInit ( &as->pause );
- return vNO_ERROR;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- static int streamFill ( AudioStreamer *as, TimeStamp amount )
- {
- int bytes_to_fill;
- int transfered = 0; // initialize to prevent compiler warning
- int bytes;
- int result;
- int looping;
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- AUD_ThreadBeginCriticalSection ( thread );
- looping = ( as->flags & AS_LOOPING ) ;
- if ( amount )
- {
- bytes_to_fill = AudioFormatBytes ( &as->format, amount );
- }
- else
- {
- bytes_to_fill = (int) STM_AccessTotalBytes ( as->in );
- }
- while ( bytes_to_fill )
- {
- if ( (bytes = bytes_to_fill) > as->bytes_left )
- {
- bytes = as->bytes_left;
- }
- result = STM_AccessFileTransfer ( as->in, as->file, bytes, &transfered );
- as->bytes_left -= transfered;
- bytes_to_fill -= transfered;
- if ( as->bytes_left <= 0 || result == STM_EOF || result == STM_FAIL )
- {
- if ( looping )
- {
- // seek to start of stream and continue filling
- as->file->seek ( as->data_start, File::START );
- as->bytes_left = as->total_bytes;
- }
- else
- {
- FLAGS_CLEAR ( as->flags, AS_FILL );
- as->bytes_left = 0;
- bytes_to_fill = 0;
- }
- }
- }
- AUD_ThreadEndCriticalSection ( thread );
- return transfered;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- static void service_stream ( AudioStreamer *as )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- if ( ! (as->flags & AS_FILL ) )
- {
- return;
- }
- streamFill ( as, 0 );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- static int service_streams ( AUD_Thread *thread, void *data )
- {
- AudioStreamer *as;
- ListHead *list = (ListHead *) data;
- if ( list )
- {
- as = (AudioStreamer*) ListFirstItem ( list );
-
- while ( as )
- {
- service_stream ( as );
-
- as = (AudioStreamer*) ListNextItem ( &as->nd );
- }
- }
- return TRUE;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- static int recalcBuffering ( AudioStreamer *as, TimeStamp buffering, AudioFormat *format )
- {
- uint size;
- STM_STREAM *stm;
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- stm = as->stream;
- DBG_ASSERT ( stm );
- DBG_ASSERT ( format );
- size = (uint) AudioFormatBytes ( format, buffering );
- as->frame_size = AudioFormatBytes ( format, AudioChannelFrameTime ( as->channel )*2 );
- if ( as->frame_size < MIN_FRAME_SIZE )
- {
- as->frame_size = MIN_FRAME_SIZE;
- }
- if ( STM_StreamTotalBytes ( stm ) != size )
- {
- STM_SBUFFER *buffer;
- STM_StreamDestroyBuffers ( stm );
- buffer = STM_SBufferCreate ( size, 0 );
- if ( buffer )
- {
- STM_StreamAddSBuffer ( stm, buffer );
- }
- }
- return STM_StreamTotalBytes ( stm ) == size;
- }
- /*****************************************************************************
- ** Public Functions **
- *****************************************************************************/
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int AudioStreamerInit ( void )
- {
- ListInit ( &streams );
- thread = AUD_ThreadCreate ( "Streamer Thread", AUD_THREAD_PRI_HIGH, service_streams );
- if ( thread )
- {
- AUD_ThreadSetInterval ( thread, SECONDS(1) );
- AUD_ThreadSetData ( thread, &streams );
- }
- initialized = TRUE;
- return TRUE;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerDeinit ( void )
- {
- AudioStreamer *as;
- if ( !initialized )
- {
- return ;
- }
- msg_assert ( ListIsEmpty ( &streams), ("Not all streams were destroyed"));
- while ( as = (AudioStreamer*) ListFirstItem ( &streams ))
- {
- AudioStreamerStop ( as );
- AudioStreamerDestroy ( as );
- }
- if ( thread )
- {
- AUD_ThreadDestroy ( thread );
- thread = NULL;
- }
- initialized = FALSE;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- AudioStreamer* AudioStreamerCreate ( AudioDevice *dev, TimeStamp buffering )
- {
- AudioStreamer *as;
- if ( !dev || !initialized )
- {
- return NULL;
- }
- if ( buffering <=0 || buffering < SECONDS(7))
- {
- buffering = SECONDS(7);
- }
- ALLOC_STRUCT ( as, AudioStreamer );
- DBG_SET_TYPE ( as, AudioStreamer );
- ListNodeInit ( &as->nd );
- as->device = dev;
- as->channel = AudioDeviceReserveChannel ( dev, AUDIO_CHANNEL_TYPE_USER );
- as->buffering = buffering;
- AudioSampleInit ( &as->sample );
- AudioFormatInit ( &as->format );
- LockInit ( &as->pause );
- LockInit ( &as->lock );
- strcpy ( as->stream_name, "Audio Stream" );
- if ( !as->channel )
- {
- msg_assert ( FALSE, ("Unable to reserve channel for streamer"));
- goto error;
- }
- as->max_volume = AUDIO_VOLUME_MAX;
- as->channel->GroupAttribs = NULL;
- as->channel->SfxAttribs = NULL;
- as->channel->CompAttribs = NULL;
- as->channel->FadeAttribs = NULL;
- as->channel->Data = (void *) as;
- as->channel->CB_NextFrame = streamNextFrame;
- as->channel->CB_SampleDone = streamSampleDone;
- as->channel->CB_Stop = streamStop;
- as->stream = STM_StreamCreate ( );
- if ( !as->stream )
- {
- goto error;
- }
- AUD_ThreadBeginCriticalSection ( thread );
- ListNodeAppend ( &streams, &as->nd );
- AUD_ThreadEndCriticalSection ( thread );
- return as;
- error:
- AudioStreamerDestroy ( as );
- return NULL;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerDestroy ( AudioStreamer *as )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- msg_assert ( !(as->flags & AS_PLAYING), ("Trying to destroy as stream while is is still playing"));
- if ( ListNodeInList ( &as->nd ))
- {
- AUD_ThreadBeginCriticalSection ( thread );
- ListNodeRemove ( &as->nd );
- AUD_ThreadEndCriticalSection ( thread );
- }
- AudioStreamerClose ( as );
- if ( as->in )
- {
- STM_AccessRelease ( as->in );
- as->in = NULL;
- }
- if ( as->out )
- {
- STM_AccessRelease ( as->out );
- as->out = NULL;
- }
- if ( as->stream )
- {
- STM_StreamDestroy ( as->stream );
- }
- if ( as->channel )
- {
- AudioChannelRelease ( as->channel );
- }
- if ( as->file )
- {
- if ( ! (as->flags & AS_NO_FILE_CLOSE ))
- {
- as->file->close() ;
- }
- as->file = NULL;
- }
- DBG_INVALIDATE_TYPE ( as );
- MEM_Free ( as );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerSetAttribs ( AudioStreamer *as, AudioAttribs *attribs )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
-
- as->channel->GroupAttribs = attribs;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerSetFadeAttribs ( AudioStreamer *as, AudioAttribs *attribs )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
-
- as->channel->FadeAttribs = attribs;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int AudioStreamerOpen ( AudioStreamer *as, File *file)
- {
-
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- if ( Locked ( &as->lock ) || !file )
- {
- return FALSE;
- }
- AUD_ThreadBeginCriticalSection ( thread );
- AudioStreamerClose ( as );
- FLAGS_SET ( as->flags, AS_NO_FILE_CLOSE ); // we did not open this file so do not close it
- as->file = file;
- if ( !AudioFormatReadWaveFile ( as->file, &as->format, &as->total_bytes ))
- {
- goto error;
- }
- strncpy ( as->name, file->getName(), ArrayLen ( as->name ) );
- ArrayEnd ( as->name );
- AudioSampleSetName ( &as->sample, as->name );
- as->data_start = as->file->position();
- as->stream_pos = 0;
- FLAGS_SET ( as->flags, AS_OPEN );
- AUD_ThreadEndCriticalSection ( thread );
- return TRUE;
- error:
- if ( as->file )
- {
- as->file = NULL;
- }
- FLAGS_CLEAR ( as->flags, AS_OPEN );
- AUD_ThreadEndCriticalSection ( thread );
- return FALSE;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int AudioStreamerOpen ( AudioStreamer *as, const char *filename )
- {
- File *file;
- int opened;
- file = TheFileSystem->open ( (char *)filename, File::READ|File::BINARY );
- if ( !file )
- {
- return FALSE;
- }
- opened = AudioStreamerOpen ( as, file );
- if ( !opened )
- {
- file->close();
- return FALSE;
- }
- // we did open this file so automatically close when stream is closed
- FLAGS_CLEAR ( as->flags, AS_NO_FILE_CLOSE );
- return TRUE;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int AudioStreamerStart ( AudioStreamer *as )
- {
- TimeStamp time;
-
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- if ( Locked ( &as->lock ) || !(as->flags & AS_OPEN ))
- {
- return FALSE;
- }
- AUD_ThreadBeginCriticalSection ( thread );
- as->stream_pos = AudioFormatSeekToPos ( as->file, &as->format, as->stream_pos, as->data_start );
- as->bytes_left = as->total_bytes - as->stream_pos;
- if ( as->in )
- {
- STM_AccessRelease ( as->in );
- as->in = NULL;
- }
- if ( as->out )
- {
- STM_AccessRelease ( as->out );
- as->out = NULL;
- }
- if ( !recalcBuffering ( as, as->buffering, &as->format ) )
- {
- goto error;
- }
- STM_StreamReset ( as->stream);
- as->in = STM_StreamAcquireAccess ( as->stream, vSTM_ACCESS_ID_IN );
- as->out = STM_StreamAcquireAccess ( as->stream, vSTM_ACCESS_ID_OUT );
- if ( !as->in || !as->out )
- {
- goto error;
- }
- time = max ( AudioChannelBufferTime ( as->channel )*2, AUD_ThreadGetInterval(thread)*4);
- time = max ( time, (TimeStamp)SECONDS(4));
- if ( !streamFill ( as, time ))
- {
- goto error;
- }
- STM_AccessGetBlock ( as->out );
- as->sample.Data = (char *) as->out->Block.Data;
- as->sample.Bytes = AudioFormatBytes ( &as->format, AudioChannelFrameTime ( as->channel ));
- if ( as->sample.Bytes > as->out->Block.Bytes )
- {
- as->sample.Bytes = as->out->Block.Bytes ;
- }
- as->sample.Format = &as->format;
- as->pending_bytes = as->sample.Bytes;
- //AudioAttribsSetVolume ( &as->channel->ChannelAttribs, AUDIO_VOLUME_MAX );
- AudioChannelSetSample ( as->channel, &as->sample );
- FLAGS_SET ( as->flags, AS_PLAYING );
- if ( AudioChannelStart ( as->channel ) != vNO_ERROR )
- {
- FLAGS_CLEAR ( as->flags, AS_PLAYING );
- STM_AccessRelease ( as->in );
- as->in = NULL;
- STM_AccessRelease ( as->out );
- as->out = NULL;
- goto error;
- }
- as->start_time_stamp = AudioGetTime();
- as->end_time_stamp = as->start_time_stamp;
- FLAGS_SET ( as->flags, AS_FILL );
- AUD_ThreadEndCriticalSection ( thread );
- return TRUE;
- error:
- AUD_ThreadEndCriticalSection ( thread );
- return FALSE;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerStop ( AudioStreamer *as )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- if ( NotLocked ( &as->lock ) )
- {
- if ( as->channel )
- {
- AUD_ThreadBeginCriticalSection ( thread );
- AudioChannelStop ( as->channel );
- AUD_ThreadEndCriticalSection ( thread );
- }
- }
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerClose ( AudioStreamer *as )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- if ( NotLocked ( &as->lock ) )
- {
- AUD_ThreadBeginCriticalSection ( thread );
- AudioStreamerStop ( as );
- if ( as->file )
- {
- if ( ! (as->flags & AS_NO_FILE_CLOSE ))
- {
- as->file->close();
- }
- as->file = NULL;
- }
- FLAGS_CLEAR ( as->flags, AS_OPEN | AS_NO_FILE_CLOSE | AS_LOOPING ) ;
- AUD_ThreadEndCriticalSection ( thread );
- }
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerLock ( AudioStreamer *as )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- LockAcquire ( &as->lock );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerUnlock ( AudioStreamer *as )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- LockRelease ( &as->lock );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerPause ( AudioStreamer *as )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- if ( NotLocked ( &as->pause ))
- {
- if ( as->channel )
- {
- AUD_ThreadBeginCriticalSection ( thread );
- AudioChannelPause ( as->channel );
- if ( as->flags & AS_PLAYING )
- {
- FLAGS_SET ( as->flags, AS_PAUSED );
- FLAGS_CLEAR ( as->flags, AS_PLAYING );
- }
- AUD_ThreadEndCriticalSection ( thread );
- }
- }
- LockAcquire ( &as->pause );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerResume ( AudioStreamer *as )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- if ( Locked ( &as->pause ) )
- {
- LockRelease ( &as->pause );
- if ( NotLocked ( &as->pause ))
- {
- if ( as->channel )
- {
- AUD_ThreadBeginCriticalSection ( thread );
- if ( as->flags & AS_PAUSED )
- {
- FLAGS_CLEAR ( as->flags, AS_PAUSED );
- FLAGS_SET ( as->flags, AS_PLAYING );
- }
- AudioChannelResume ( as->channel );
- AUD_ThreadEndCriticalSection ( thread );
- }
- }
- }
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int AudioStreamerIsPlaying ( AudioStreamer *as )
- {
- DBG_ASSERT_TYPE ( as , AudioStreamer );
- return as->flags & AS_PLAYING ;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int AudioStreamerActive ( AudioStreamer *as )
- {
- DBG_ASSERT_TYPE ( as , AudioStreamer );
- return as->flags & (AS_PLAYING|AS_PAUSED) ;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerSetName ( AudioStreamer *as, const char *name )
- {
- DBG_ASSERT_TYPE ( as , AudioStreamer );
- strncpy ( as->stream_name, name, sizeof(as->stream_name));
- as->stream_name[ sizeof(as->stream_name) -1 ] = 0;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- const char *AudioStreamerName ( AudioStreamer *as )
- {
- DBG_ASSERT_TYPE ( as , AudioStreamer );
- return as->stream_name;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerFadeIn ( AudioStreamer *as )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- AudioAttribsAdjustVolume ( &as->channel->ChannelAttribs, as->max_volume );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerFadeOut ( AudioStreamer *as )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- AudioAttribsAdjustVolume ( &as->channel->ChannelAttribs, AUDIO_VOLUME_MIN );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int AudioStreamerIsFading ( AudioStreamer *as )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- return AudioStreamerIsPlaying ( as ) && !AudioAttribsVolumeAdjusted ( &as->channel->ChannelAttribs );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerWaitForFade ( AudioStreamer *as )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- TimeStamp time_out = AudioGetTime() + as->channel->ChannelAttribs.VolumeLevel.duration;
- while ( AudioStreamerIsFading ( as ) && (AudioGetTime() < time_out) )
- {
- //ServiceAllAudio (); TODO: trolfs
- break;
- }
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- TimeStamp AudioStreamerEndTimeStamp ( AudioStreamer *as )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- return as->end_time_stamp;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerStarve ( void )
- {
- AudioStreamer *as;
- if ( !initialized )
- {
- return;
- }
- as = (AudioStreamer*) ListFirstItem ( &streams );
-
- AUD_ThreadBeginCriticalSection ( thread );
- while ( as )
- {
- FLAGS_CLEAR ( as->flags, AS_FILL );
- as = (AudioStreamer*) ListNextItem ( &as->nd );
- }
- AUD_ThreadEndCriticalSection ( thread );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerStopAllStreams ( void )
- {
- AudioStreamer *as;
- if ( !initialized )
- {
- return;
- }
- AUD_ThreadBeginCriticalSection ( thread );
- as = (AudioStreamer*) ListFirstItem ( &streams );
- while ( as )
- {
- AudioStreamerStop ( as );
- as = (AudioStreamer*) ListNextItem ( &as->nd );
- }
- AUD_ThreadEndCriticalSection ( thread );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerCloseAllStreams ( void )
- {
- AudioStreamer *as;
- if ( !initialized )
- {
- return;
- }
- as = (AudioStreamer*) ListFirstItem ( &streams );
- while ( as )
- {
- AudioStreamerClose ( as );
- as = (AudioStreamer*) ListNextItem ( &as->nd );
- }
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerCloseAllStreamsUsingFile ( File *file )
- {
- AudioStreamer *as;
- if ( !initialized )
- {
- return;
- }
- as = (AudioStreamer*) ListFirstItem ( &streams );
- while ( as )
- {
- if ( as->file == file )
- {
- AudioStreamerClose ( as );
- }
- as = (AudioStreamer*) ListNextItem ( &as->nd );
- }
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerLockAllStreams ( void )
- {
- AudioStreamer *as;
- if ( !initialized )
- {
- return;
- }
- as = (AudioStreamer*) ListFirstItem ( &streams );
- while ( as )
- {
- AudioStreamerLock ( as );
- as = (AudioStreamer*) ListNextItem ( &as->nd );
- }
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerUnlockAllStreams ( void )
- {
- AudioStreamer *as;
- if ( !initialized )
- {
- return;
- }
- as = (AudioStreamer*) ListFirstItem ( &streams );
- while ( as )
- {
- AudioStreamerUnlock ( as );
- as = (AudioStreamer*) ListNextItem ( &as->nd );
- }
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerPauseAllStreams ( void )
- {
- AudioStreamer *as;
- if ( !initialized )
- {
- return;
- }
- as = (AudioStreamer*) ListFirstItem ( &streams );
- while ( as )
- {
- AudioStreamerPause ( as );
- as = (AudioStreamer*) ListNextItem ( &as->nd );
- }
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerResumeAllStreams ( void )
- {
- AudioStreamer *as;
- if ( !initialized )
- {
- return;
- }
- as = (AudioStreamer*) ListFirstItem ( &streams );
- while ( as )
- {
- AudioStreamerResume ( as );
- as = (AudioStreamer*) ListNextItem ( &as->nd );
- }
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerFadeOutAllStreams ( void )
- {
- AudioStreamer *as;
- if ( !initialized )
- {
- return;
- }
- as = (AudioStreamer*) ListFirstItem ( &streams );
- while ( as )
- {
- AudioStreamerFadeOut ( as );
- as = (AudioStreamer*) ListNextItem ( &as->nd );
- }
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerFadeInAllStreams ( void )
- {
- AudioStreamer *as;
- if ( !initialized )
- {
- return;
- }
- as = (AudioStreamer*) ListFirstItem ( &streams );
- while ( as )
- {
- AudioStreamerFadeIn ( as );
- as = (AudioStreamer*) ListNextItem ( &as->nd );
- }
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int AudioStreamerAllFaded ( void )
- {
- AudioStreamer *as;
- if ( !initialized )
- {
- return true;
- }
- as = (AudioStreamer*) ListFirstItem ( &streams );
- while ( as )
- {
- if ( AudioStreamerIsFading ( as ) )
- {
- return FALSE;
- }
- as = (AudioStreamer*) ListNextItem ( &as->nd );
- }
- return TRUE;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int AudioStreamerGetPosition ( AudioStreamer *as )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- return as->stream_pos;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerSetPosition ( AudioStreamer *as, int pos )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- int playing = AudioStreamerIsPlaying ( as );
- AudioStreamerStop ( as );
- as->stream_pos = pos;
- if ( playing )
- {
- AudioStreamerStart ( as );
- }
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- TimeStamp AudioStreamerGetTimePosition ( AudioStreamer *as )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- if ( as->flags & AS_OPEN )
- {
- return AudioFormatTime ( &as->format, as->stream_pos );
- }
- return 0;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerSetTimePosition ( AudioStreamer *as, TimeStamp time )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- if ( as->flags & AS_OPEN )
- {
- AudioStreamerSetPosition ( as, AudioFormatBytes ( &as->format, time ));
- }
- else
- {
- AudioStreamerSetPosition ( as, 0 );
- }
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerSetVolume ( AudioStreamer *as, int volume )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- AudioChannelSetVolume ( as->channel, volume );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int AudioStreamerGetVolume ( AudioStreamer *as )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- return AudioChannelGetVolume ( as->channel );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerSetMaxVolume ( AudioStreamer *as, int volume )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- if ( volume > AUDIO_VOLUME_MAX )
- {
- volume = AUDIO_VOLUME_MAX;
- }
- else if ( volume < AUDIO_VOLUME_MIN )
- {
- volume = AUDIO_VOLUME_MIN;
- }
- as->max_volume = volume;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int AudioStreamerGetMaxVolume ( AudioStreamer *as )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- return as->max_volume;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerSetLooping ( AudioStreamer *as, int loop )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
-
- AUD_ThreadBeginCriticalSection ( thread );
- if ( loop )
- {
- FLAGS_SET ( as->flags, AS_LOOPING );
- }
- else
- {
- FLAGS_CLEAR ( as->flags, AS_LOOPING );
- }
- AUD_ThreadEndCriticalSection ( thread );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int AudioStreamerIsLooping ( AudioStreamer *as )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- return as->flags & AS_LOOPING;
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- int AudioStreamerIsAudible ( AudioStreamer *as )
- {
- DBG_ASSERT_TYPE ( as, AudioStreamer );
- return AudioChannelIsAudible ( as->channel );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerSetPriority ( AudioStreamer *as, Int priority )
- {
- }
- #define vRANGE 15
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- static void streamDump ( AudioStreamer *as, int index, void (*print) ( char *text) )
- {
- int range = vRANGE;
- int in;
- int total;
- int percent;
- char buffer[200];
- uint out_pos;
- uint in_pos;
- if ( !as->stream )
- {
- sprintf ( buffer, "%02d: Invalid Stream\n", index);
- print ( buffer );
- return;
- }
- total = STM_StreamTotalBytes ( as->stream );
- in = 0;
- out_pos = 0;
- in_pos = 0;
- percent = 0;
- if ( total )
- {
- in = (STM_StreamTotalBytesIn ( as->stream )*range)/total;
- if ( as->out )
- {
- out_pos = (STM_AccessPosition ( as->out ) * range)/total;
- }
- if ( as->in )
- {
- in_pos = (STM_AccessPosition ( as->in ) * range)/total;
- }
- percent = (STM_StreamTotalBytesIn ( as->stream )*100)/total;
- }
- if ( out_pos == in_pos )
- {
- if ( in == 0)
- {
- if ( out_pos < vRANGE-1 )
- {
- in_pos = (out_pos + 1);
- }
- else
- {
- in_pos = 0;
- }
- }
- else
- {
- if ( out_pos > 0 )
- {
- in_pos = (out_pos - 1);
- }
- else
- {
- in_pos = vRANGE-1 ;
- }
- }
- }
- char gauge[vRANGE+1];
- uint i;
- for ( i =0; i < vRANGE; i++)
- {
- gauge[i] = ' ';
- }
- gauge[vRANGE] = 0;
- if ( out_pos > in_pos )
- {
- for ( i =out_pos+1; i < vRANGE; i++)
- gauge[i] = '*';
- for ( i =0; i < in_pos; i++)
- gauge[i] = '*';
- }
- else
- {
- for ( i =out_pos+1; i < in_pos; i++)
- gauge[i] = '*';
- }
- gauge[in_pos] = '>';
- gauge[out_pos] = '<';
- char name[sizeof(as->name)+1];
- char *ptr ;
- int seconds, minutes;
- strcpy ( name, as->name );
- ptr = strrchr ( name, '.' );
- if ( ptr )
- {
- *ptr = 0;
- }
- ptr = strrchr ( name, '\\' );
- if ( ptr )
- {
- strcpy ( name, ptr );
- }
- TimeStamp time = AudioFormatTime ( &as->format, as->total_bytes - as->stream_pos );
- minutes = (int) IN_MINUTES(time);
- time -= MINUTES(minutes);
- seconds = (int) IN_SECONDS(time);
- time -= SECONDS(seconds);
- time = (int) IN_MSECONDS(time);
- sprintf ( buffer, "%.12s %4d Kb %.31s \n", AudioStreamerName( as ), total/1024, name);
- print ( buffer );
- sprintf ( buffer, " Status: %s %s %s %d:%02d:%03d \n",
- as->flags & AS_PLAYING ? "Play " : (as->flags & AS_PAUSED ? "Paused" : "Stop ") ,
- as->flags & AS_FILL ? "Fill" : " ",
- Locked( &as->lock ) ? "Locked" : " ",
- minutes, seconds, time );
- print ( buffer );
- sprintf ( buffer, " Buffer: |%s| %3d %%\n", gauge, percent );
- print ( buffer );
- }
- /******************************************************************/
- /* */
- /* */
- /******************************************************************/
- void AudioStreamerDump ( void (*print) ( char *text ))
- {
- AudioStreamer *as;
- char buffer[200];
- char temp[100];
- int index = 0;
-
- if ( !initialized )
- {
- print ("\nAudio Streamer not initialized\n" );
- return ;
- }
- print ("\nAudio Streamer\n" );
- AudioServiceInfoDump ( AUD_ThreadServiceInfo (thread), temp );
- sprintf ( buffer, "service:%s\n", temp );
- print (buffer );
- as = (AudioStreamer*) ListFirstItem ( &streams );
- if ( as )
- {
- while ( as )
- {
- streamDump ( as , index++, print);
- as = (AudioStreamer*) ListNextItem ( &as->nd );
- }
- }
- else
- {
- print ("No streams created\n" );
- }
- }
|