~ubuntu-branches/ubuntu/natty/libsdl1.2/natty

« back to all changes in this revision

Viewing changes to src/audio/symbian/SDL_epocaudio.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2007-12-05 20:29:43 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20071205202943-ryogi07hodn5cdif
Tags: 1.2.12-1ubuntu1
* Merge with Debian; remaining changes:
  - Remove svgalib support.
  - Prefer libgl1-mesa-dev build-dependency over xlibmesa-gl-dev.
  - Build for lpia as for i386.
* Link using -Wl,-Bsymbolic-functions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    SDL - Simple DirectMedia Layer
 
3
    Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
 
4
 
 
5
    This library is free software; you can redistribute it and/or
 
6
    modify it under the terms of the GNU Library General Public
 
7
    License as published by the Free Software Foundation; either
 
8
    version 2 of the License, or (at your option) any later version.
 
9
 
 
10
    This library is distributed in the hope that it will be useful,
 
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
    Library General Public License for more details.
 
14
 
 
15
    You should have received a copy of the GNU Library General Public
 
16
    License along with this library; if not, write to the Free
 
17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 
 
19
    Sam Lantinga
 
20
    slouken@devolution.com
 
21
*/
 
22
 
 
23
/*
 
24
    SDL_epocaudio.cpp
 
25
    Epoc based SDL audio driver implementation
 
26
    
 
27
    Markus Mertama
 
28
*/
 
29
 
 
30
#ifdef SAVE_RCSID
 
31
static char rcsid =
 
32
 "@(#) $Id: SDL_epocaudio.c,v 0.0.0.0 2001/06/19 17:19:56 hercules Exp $";
 
33
#endif
 
34
 
 
35
 
 
36
#include <stdlib.h>
 
37
#include <stdio.h>
 
38
#include <string.h>
 
39
#include <errno.h>
 
40
#include <unistd.h>
 
41
#include <fcntl.h>
 
42
#include <signal.h>
 
43
#include <sys/time.h>
 
44
#include <sys/ioctl.h>
 
45
#include <sys/stat.h>
 
46
 
 
47
#include "epoc_sdl.h"
 
48
 
 
49
#include <e32hal.h>
 
50
 
 
51
 
 
52
extern "C" {
 
53
#include "SDL_audio.h"
 
54
#include "SDL_error.h"
 
55
#include "SDL_audiomem.h"
 
56
#include "SDL_audio_c.h"
 
57
#include "SDL_timer.h"
 
58
#include "SDL_audiodev_c.h"
 
59
}
 
60
 
 
61
#include "SDL_epocaudio.h"
 
62
 
 
63
#include "streamplayer.h"
 
64
 
 
65
 
 
66
//#define DEBUG_AUDIO
 
67
 
 
68
 
 
69
/* Audio driver functions */
 
70
 
 
71
static int EPOC_OpenAudio(SDL_AudioDevice *thisdevice, SDL_AudioSpec *spec);
 
72
static void EPOC_WaitAudio(SDL_AudioDevice *thisdevice);
 
73
static void EPOC_PlayAudio(SDL_AudioDevice *thisdevice);
 
74
static Uint8 *EPOC_GetAudioBuf(SDL_AudioDevice *thisdevice);
 
75
static void EPOC_CloseAudio(SDL_AudioDevice *thisdevice);
 
76
static void EPOC_ThreadInit(SDL_AudioDevice *thisdevice);
 
77
 
 
78
static int Audio_Available(void);
 
79
static SDL_AudioDevice *Audio_CreateDevice(int devindex);
 
80
static void Audio_DeleteDevice(SDL_AudioDevice *device);
 
81
 
 
82
 
 
83
//void sos_adump(SDL_AudioDevice* thisdevice, void* data, int len);
 
84
 
 
85
#ifdef __WINS__
 
86
#define DODUMP
 
87
#endif
 
88
 
 
89
#ifdef DODUMP
 
90
NONSHARABLE_CLASS(TDump)
 
91
        {
 
92
        public:
 
93
        TInt Open();
 
94
        void Close();
 
95
        void Dump(const TDesC8& aDes);
 
96
        private:
 
97
                RFile iFile;
 
98
        RFs iFs; 
 
99
        };
 
100
        
 
101
TInt TDump::Open()
 
102
        {
 
103
        TInt err = iFs.Connect();
 
104
        if(err == KErrNone)
 
105
                {
 
106
#ifdef __WINS__
 
107
_LIT(target, "C:\\sdlau.raw");
 
108
#else
 
109
_LIT(target, "E:\\sdlau.raw");
 
110
#endif 
 
111
                err = iFile.Replace(iFs, target, EFileWrite);
 
112
                }
 
113
        return err;
 
114
        }
 
115
void TDump::Close()
 
116
        {
 
117
        iFile.Close();
 
118
        iFs.Close();
 
119
        }
 
120
void TDump::Dump(const TDesC8& aDes)
 
121
        {
 
122
        iFile.Write(aDes);
 
123
        }
 
124
#endif
 
125
 
 
126
 
 
127
NONSHARABLE_CLASS(CSimpleWait) : public CTimer
 
128
        {
 
129
        public:
 
130
                void Wait(TTimeIntervalMicroSeconds32 aWait);
 
131
                static CSimpleWait* NewL();
 
132
        private:
 
133
                CSimpleWait();
 
134
                void RunL();
 
135
        };
 
136
 
 
137
 
 
138
CSimpleWait* CSimpleWait::NewL()
 
139
        {
 
140
        CSimpleWait* wait = new (ELeave) CSimpleWait();
 
141
        CleanupStack::PushL(wait);
 
142
        wait->ConstructL();
 
143
        CleanupStack::Pop();
 
144
        return wait;
 
145
        }
 
146
 
 
147
void CSimpleWait::Wait(TTimeIntervalMicroSeconds32 aWait)
 
148
        {
 
149
        After(aWait);
 
150
        CActiveScheduler::Start();
 
151
        }
 
152
        
 
153
CSimpleWait::CSimpleWait() : CTimer(CActive::EPriorityStandard) 
 
154
        {
 
155
        CActiveScheduler::Add(this);
 
156
        }
 
157
 
 
158
void CSimpleWait::RunL()
 
159
        {
 
160
        CActiveScheduler::Stop();
 
161
        }
 
162
 
 
163
const TInt KAudioBuffers(2);
 
164
        
 
165
 
 
166
NONSHARABLE_CLASS(CEpocAudio) : public CBase, public MStreamObs, public MStreamProvider
 
167
    {
 
168
    public:
 
169
        static void* NewL(TInt BufferSize, TInt aFill);
 
170
        inline static CEpocAudio& Current(SDL_AudioDevice* thisdevice);
 
171
        
 
172
        static void Free(SDL_AudioDevice* thisdevice);
 
173
                
 
174
        void Wait();
 
175
        void Play();
 
176
    //  void SetBuffer(const TDesC8& aBuffer);
 
177
        void ThreadInitL(TAny* aDevice);
 
178
        void Open(TInt iRate, TInt iChannels, TUint32 aType, TInt aBytes);
 
179
        ~CEpocAudio();
 
180
        TUint8* Buffer();
 
181
        TBool SetPause(TBool aPause);
 
182
    #ifdef DODUMP
 
183
        void Dump(const TDesC8& aBuf) {iDump.Dump(aBuf);}
 
184
    #endif
 
185
    private:
 
186
        CEpocAudio(TInt aBufferSize);
 
187
        void Complete(TInt aState, TInt aError);
 
188
        TPtrC8 Data();
 
189
        void ConstructL(TInt aFill);
 
190
    private:
 
191
        TInt iBufferSize;
 
192
        CStreamPlayer* iPlayer;
 
193
        TInt iBufferRate;
 
194
        TInt iRate;
 
195
        TInt iChannels;
 
196
        TUint32 iType;
 
197
        TInt iPosition;
 
198
        TThreadId iTid;
 
199
        TUint8* iAudioPtr;
 
200
        TUint8* iBuffer;
 
201
    //  TTimeIntervalMicroSeconds iStart;
 
202
        TTime iStart;
 
203
        TInt iTune;
 
204
        CSimpleWait* iWait;
 
205
    #ifdef DODUMP
 
206
        TDump iDump;
 
207
    #endif
 
208
    };
 
209
 
 
210
inline CEpocAudio& CEpocAudio::Current(SDL_AudioDevice* thisdevice)
 
211
        {
 
212
        return *static_cast<CEpocAudio*>((void*)thisdevice->hidden);
 
213
        }
 
214
        
 
215
/*
 
216
 
 
217
TBool EndSc(TAny*)
 
218
        {       
 
219
        CActiveScheduler::Stop();
 
220
        }
 
221
        
 
222
LOCAL_C void CleanScL()
 
223
        {
 
224
        CIdle* d = CIdle::NewLC(CActive:::EPriorityIdle);
 
225
        d->Start(TCallBack(EndSc));
 
226
        CActiveScheduler::Start();
 
227
        
 
228
        }
 
229
*/
 
230
        
 
231
void CEpocAudio::Free(SDL_AudioDevice* thisdevice)
 
232
        {
 
233
    CEpocAudio* ea = static_cast<CEpocAudio*>((void*)thisdevice->hidden);
 
234
    if(ea)
 
235
        {
 
236
                ASSERT(ea->iTid == RThread().Id());
 
237
        delete ea;
 
238
        thisdevice->hidden = NULL;      
 
239
   
 
240
        CActiveScheduler* as =  CActiveScheduler::Current();
 
241
        ASSERT(as->StackDepth() == 0);          
 
242
        delete as;
 
243
        CActiveScheduler::Install(NULL);
 
244
        }
 
245
    ASSERT(thisdevice->hidden == NULL);
 
246
        }
 
247
        
 
248
CEpocAudio::CEpocAudio(TInt aBufferSize) : iBufferSize(aBufferSize), iPosition(-1) 
 
249
        {
 
250
        }
 
251
 
 
252
void* CEpocAudio::NewL(TInt aBufferSize, TInt aFill)
 
253
        {
 
254
        CEpocAudio* eAudioLib = new (ELeave) CEpocAudio(aBufferSize);
 
255
        CleanupStack::PushL(eAudioLib);
 
256
        eAudioLib->ConstructL(aFill);
 
257
        CleanupStack::Pop();
 
258
        return eAudioLib;
 
259
        }
 
260
        
 
261
void CEpocAudio::ConstructL(TInt aFill)
 
262
        {
 
263
        iBuffer = (TUint8*) User::AllocL(KAudioBuffers * iBufferSize);
 
264
        memset(iBuffer, aFill, KAudioBuffers * iBufferSize);
 
265
        iAudioPtr = iBuffer;
 
266
        }
 
267
 
 
268
 
 
269
TBool CEpocAudio::SetPause(TBool aPause)
 
270
        {
 
271
        if(aPause && iPosition >= 0)
 
272
                {
 
273
                iPosition = -1;
 
274
                if(iPlayer != NULL)
 
275
                        iPlayer->Stop();
 
276
                }
 
277
        if(!aPause && iPosition < 0)
 
278
                {
 
279
                iPosition = 0;
 
280
                if(iPlayer != NULL)
 
281
                        iPlayer->Start();
 
282
                }
 
283
        return iPosition < 0;
 
284
        }
 
285
        
 
286
void CEpocAudio::ThreadInitL(TAny* aDevice)
 
287
        {
 
288
        iTid = RThread().Id(); 
 
289
        CActiveScheduler* as =  new (ELeave) CActiveScheduler();
 
290
    CActiveScheduler::Install(as);
 
291
    
 
292
    EpocSdlEnv::AppendCleanupItem(TSdlCleanupItem((TSdlCleanupOperation)EPOC_CloseAudio, aDevice));
 
293
   
 
294
    iWait = CSimpleWait::NewL();
 
295
   
 
296
    iPlayer = new (ELeave) CStreamPlayer(*this, *this);
 
297
    iPlayer->ConstructL();      
 
298
    iPlayer->OpenStream(iRate, iChannels, iType);
 
299
    
 
300
    #ifdef DODUMP
 
301
    User::LeaveIfError(iDump.Open());
 
302
    #endif
 
303
        }
 
304
        
 
305
        
 
306
        
 
307
TUint8* CEpocAudio::Buffer()
 
308
        {
 
309
        iStart.UniversalTime();
 
310
//      iStart = iPlayer->Position();           
 
311
        return iAudioPtr;
 
312
 
 
313
        }
 
314
        
 
315
CEpocAudio::~CEpocAudio()
 
316
        {
 
317
        if(iWait != NULL)
 
318
                iWait->Cancel();
 
319
        delete iWait; 
 
320
        if(iPlayer != NULL)
 
321
                iPlayer->Close();
 
322
        delete iPlayer;
 
323
        delete iBuffer;
 
324
        }
 
325
        
 
326
void CEpocAudio::Complete(TInt aState, TInt aError)
 
327
        {
 
328
        if(aState == MStreamObs::EClose)
 
329
                {
 
330
                }
 
331
        if(iPlayer->Closed())
 
332
                return;
 
333
        switch(aError)
 
334
                {
 
335
                case KErrUnderflow:
 
336
                case KErrInUse:
 
337
                        iPlayer->Start();
 
338
                        break;
 
339
                case KErrAbort:
 
340
                        iPlayer->Open();
 
341
                }
 
342
        }
 
343
        
 
344
 
 
345
void sos_adump(SDL_AudioDevice* thisdevice, void* data, int len)
 
346
        {
 
347
#ifdef DODUMP
 
348
        const TPtrC8 buf((TUint8*)data, len);
 
349
        CEpocAudio::Current(thisdevice).Dump(buf);
 
350
#endif
 
351
        }
 
352
 
 
353
const TInt KClip(256);
 
354
        
 
355
TPtrC8 CEpocAudio::Data()
 
356
        {
 
357
        if(iPosition < 0)
 
358
                return KNullDesC8();
 
359
        
 
360
        TPtrC8 data(iAudioPtr + iPosition, KClip);
 
361
        
 
362
#ifdef DODUMP
 
363
        iDump.Dump(data);
 
364
#endif
 
365
        
 
366
        iPosition += KClip;
 
367
        if(iPosition >= iBufferSize) 
 
368
                {
 
369
                
 
370
/*              if(iAudioPtr == iBuffer)
 
371
                        iAudioPtr = iBuffer + iBufferSize;
 
372
                else
 
373
                        iAudioPtr = iBuffer;
 
374
*/              
 
375
                iAudioPtr += iBufferSize;
 
376
                
 
377
                if((iAudioPtr - iBuffer) >= KAudioBuffers * iBufferSize)
 
378
                        iAudioPtr = iBuffer;
 
379
                
 
380
                iPosition = -1;
 
381
                if(iWait->IsActive())
 
382
                        {
 
383
                        iWait->Cancel();
 
384
                        CActiveScheduler::Stop();
 
385
                        }
 
386
                }
 
387
        return data;
 
388
        }
 
389
                
 
390
 
 
391
 
 
392
        
 
393
void CEpocAudio::Play()
 
394
        {
 
395
        iPosition = 0;
 
396
        }
 
397
 
 
398
void CEpocAudio::Wait()
 
399
        {
 
400
        if(iPosition >= 0 /*&& iPlayer->Playing()*/)
 
401
                {
 
402
                const TInt64 bufMs = TInt64(iBufferSize - KClip) * TInt64(1000000);
 
403
                const TInt64 specTime =  bufMs / TInt64(iRate * iChannels * 2);
 
404
                iWait->After(specTime);
 
405
                
 
406
                CActiveScheduler::Start();
 
407
                TTime end;
 
408
                end.UniversalTime();
 
409
                const TTimeIntervalMicroSeconds delta = end.MicroSecondsFrom(iStart);
 
410
        
 
411
        
 
412
//              const TTimeIntervalMicroSeconds end = iPlayer->Position();
 
413
                
 
414
                
 
415
        
 
416
                
 
417
                const TInt diff = specTime - delta.Int64();
 
418
                
 
419
                if(diff > 0 && diff < 200000)
 
420
                        {
 
421
                        User::After(diff);
 
422
                        }
 
423
                
 
424
                }
 
425
        else
 
426
                {
 
427
        User::After(10000); 
 
428
//      iWait->Wait(10000); //just give some time...    
 
429
                }       
 
430
        }
 
431
        
 
432
void CEpocAudio::Open(TInt aRate, TInt aChannels, TUint32 aType, TInt aBytes)   
 
433
        {
 
434
        iRate = aRate;
 
435
        iChannels = aChannels;
 
436
        iType = aType;
 
437
    iBufferRate = iRate * iChannels * aBytes; //1/x
 
438
        }
 
439
        
 
440
 
 
441
/* Audio driver bootstrap functions */
 
442
 
 
443
AudioBootStrap EPOCAudio_bootstrap = {
 
444
        "epoc\0\0\0",
 
445
        "EPOC streaming audio\0\0\0",
 
446
        Audio_Available,
 
447
        Audio_CreateDevice
 
448
};
 
449
 
 
450
 
 
451
static SDL_AudioDevice *Audio_CreateDevice(int /*devindex*/)
 
452
{
 
453
        SDL_AudioDevice *thisdevice;
 
454
 
 
455
        /* Initialize all variables that we clean on shutdown */
 
456
        thisdevice = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
 
457
        if ( thisdevice ) {
 
458
                memset(thisdevice, 0, (sizeof *thisdevice));
 
459
                thisdevice->hidden = NULL; /*(struct SDL_PrivateAudioData *)
 
460
                         malloc((sizeof thisdevice->hidden)); */
 
461
        }
 
462
        if ( (thisdevice == NULL) /*|| (thisdevice->hidden == NULL) */) {
 
463
                SDL_OutOfMemory();
 
464
                if ( thisdevice ) {
 
465
                        free(thisdevice);
 
466
                }
 
467
                return(0);
 
468
        }
 
469
//      memset(thisdevice->hidden, 0, (sizeof *thisdevice->hidden));
 
470
 
 
471
        /* Set the function pointers */
 
472
        thisdevice->OpenAudio = EPOC_OpenAudio;
 
473
        thisdevice->WaitAudio = EPOC_WaitAudio;
 
474
        thisdevice->PlayAudio = EPOC_PlayAudio;
 
475
        thisdevice->GetAudioBuf = EPOC_GetAudioBuf;
 
476
        thisdevice->CloseAudio = EPOC_CloseAudio;
 
477
    thisdevice->ThreadInit = EPOC_ThreadInit;
 
478
        thisdevice->free = Audio_DeleteDevice;
 
479
 
 
480
        return thisdevice;
 
481
}
 
482
 
 
483
 
 
484
static void Audio_DeleteDevice(SDL_AudioDevice *device)
 
485
    {
 
486
        //free(device->hidden);
 
487
        free(device);
 
488
    }
 
489
 
 
490
static int Audio_Available(void)
 
491
{
 
492
        return(1); // Audio stream modules should be always there!
 
493
}
 
494
 
 
495
 
 
496
static int EPOC_OpenAudio(SDL_AudioDevice *thisdevice, SDL_AudioSpec *spec)
 
497
{
 
498
        SDL_TRACE("SDL:EPOC_OpenAudio");
 
499
 
 
500
        
 
501
        TUint32 type = KMMFFourCCCodePCM16;
 
502
        TInt bytes = 2;
 
503
        
 
504
        switch(spec->format)
 
505
                {
 
506
                case AUDIO_U16LSB: 
 
507
                        type = KMMFFourCCCodePCMU16; 
 
508
                        break;
 
509
                case AUDIO_S16LSB: 
 
510
                        type = KMMFFourCCCodePCM16; 
 
511
                        break;
 
512
                case AUDIO_U16MSB: 
 
513
                        type = KMMFFourCCCodePCMU16B; 
 
514
                        break;
 
515
                case AUDIO_S16MSB: 
 
516
                        type = KMMFFourCCCodePCM16B; 
 
517
                        break; 
 
518
                        //8 bit not supported!
 
519
                case AUDIO_U8: 
 
520
                case AUDIO_S8:
 
521
                default:
 
522
                        spec->format = AUDIO_S16LSB;
 
523
                };
 
524
        
 
525
 
 
526
        
 
527
        if(spec->channels > 2)
 
528
                spec->channels = 2;
 
529
        
 
530
        spec->freq = CStreamPlayer::ClosestSupportedRate(spec->freq);
 
531
        
 
532
 
 
533
        /* Allocate mixing buffer */
 
534
        const TInt buflen = spec->size;// * bytes * spec->channels;
 
535
//      audiobuf = NULL;
 
536
    
 
537
    TRAPD(err, thisdevice->hidden = static_cast<SDL_PrivateAudioData*>(CEpocAudio::NewL(buflen, spec->silence)));
 
538
    if(err != KErrNone)
 
539
        return -1;
 
540
 
 
541
        CEpocAudio::Current(thisdevice).Open(spec->freq, spec->channels, type, bytes);
 
542
        
 
543
        CEpocAudio::Current(thisdevice).SetPause(ETrue);
 
544
        
 
545
   // isSDLAudioPaused = 1;
 
546
 
 
547
    thisdevice->enabled = 0; /* enable only after audio engine has been initialized!*/
 
548
 
 
549
        /* We're ready to rock and roll. :-) */
 
550
        return(0);
 
551
}
 
552
 
 
553
 
 
554
static void EPOC_CloseAudio(SDL_AudioDevice* thisdevice)
 
555
    {
 
556
#ifdef DEBUG_AUDIO
 
557
    SDL_TRACE("Close audio\n");
 
558
#endif
 
559
 
 
560
        CEpocAudio::Free(thisdevice);
 
561
        }
 
562
 
 
563
 
 
564
static void EPOC_ThreadInit(SDL_AudioDevice *thisdevice)
 
565
    {
 
566
        SDL_TRACE("SDL:EPOC_ThreadInit");
 
567
    CEpocAudio::Current(thisdevice).ThreadInitL(thisdevice);
 
568
    RThread().SetPriority(EPriorityMore);
 
569
    thisdevice->enabled = 1;
 
570
    }
 
571
 
 
572
/* This function waits until it is possible to write a full sound buffer */
 
573
static void EPOC_WaitAudio(SDL_AudioDevice* thisdevice)
 
574
{
 
575
#ifdef DEBUG_AUDIO
 
576
    SDL_TRACE1("wait %d audio\n", CEpocAudio::AudioLib().StreamPlayer(KSfxChannel).SyncTime());
 
577
    TInt tics = User::TickCount();
 
578
#endif
 
579
 
 
580
        CEpocAudio::Current(thisdevice).Wait();
 
581
 
 
582
#ifdef DEBUG_AUDIO
 
583
    TInt ntics =  User::TickCount() - tics;
 
584
    SDL_TRACE1("audio waited %d\n", ntics);
 
585
    SDL_TRACE1("audio at %d\n", tics);
 
586
#endif
 
587
}
 
588
 
 
589
 
 
590
 
 
591
static void EPOC_PlayAudio(SDL_AudioDevice* thisdevice)
 
592
        {
 
593
        if(CEpocAudio::Current(thisdevice).SetPause(SDL_GetAudioStatus() == SDL_AUDIO_PAUSED))
 
594
                SDL_Delay(500); //hold on the busy loop
 
595
        else
 
596
                CEpocAudio::Current(thisdevice).Play();
 
597
 
 
598
#ifdef DEBUG_AUDIO
 
599
    SDL_TRACE("buffer has audio data\n");
 
600
#endif
 
601
 
 
602
        
 
603
#ifdef DEBUG_AUDIO
 
604
        SDL_TRACE1("Wrote %d bytes of audio data\n", buflen);
 
605
#endif
 
606
}
 
607
 
 
608
static Uint8 *EPOC_GetAudioBuf(SDL_AudioDevice* thisdevice)
 
609
        {
 
610
        return CEpocAudio::Current(thisdevice).Buffer();
 
611
        }
 
612
 
 
613
 
 
614