19682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
29682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL - Simple DirectMedia Layer
39682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Copyright (C) 1997-2012 Sam Lantinga
49682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
59682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    This library is free software; you can redistribute it and/or
69682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    modify it under the terms of the GNU Library General Public
79682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    License as published by the Free Software Foundation; either
89682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    version 2 of the License, or (at your option) any later version.
99682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    This library is distributed in the hope that it will be useful,
119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    but WITHOUT ANY WARRANTY; without even the implied warranty of
129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Library General Public License for more details.
149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    You should have received a copy of the GNU Library General Public
169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    License along with this library; if not, write to the Free
179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Sam Lantinga
209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    slouken@devolution.com
219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_epocaudio.cpp
259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Epoc based SDL audio driver implementation
269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Markus Mertama
289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef SAVE_RCSID
319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic char rcsid =
329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall "@(#) $Id: SDL_epocaudio.c,v 0.0.0.0 2001/06/19 17:19:56 hercules Exp $";
339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <stdlib.h>
379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <stdio.h>
389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <string.h>
399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <errno.h>
409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <unistd.h>
419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <fcntl.h>
429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <signal.h>
439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <sys/time.h>
449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <sys/ioctl.h>
459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <sys/stat.h>
469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "epoc_sdl.h"
489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <e32hal.h>
509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallextern "C" {
539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_audio.h"
549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_error.h"
559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_audiomem.h"
569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_audio_c.h"
579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_timer.h"
589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_audiodev_c.h"
599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_epocaudio.h"
629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "streamplayer.h"
649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall//#define DEBUG_AUDIO
679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Audio driver functions */
709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int EPOC_OpenAudio(SDL_AudioDevice *thisdevice, SDL_AudioSpec *spec);
729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void EPOC_WaitAudio(SDL_AudioDevice *thisdevice);
739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void EPOC_PlayAudio(SDL_AudioDevice *thisdevice);
749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic Uint8 *EPOC_GetAudioBuf(SDL_AudioDevice *thisdevice);
759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void EPOC_CloseAudio(SDL_AudioDevice *thisdevice);
769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void EPOC_ThreadInit(SDL_AudioDevice *thisdevice);
779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int Audio_Available(void);
799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic SDL_AudioDevice *Audio_CreateDevice(int devindex);
809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void Audio_DeleteDevice(SDL_AudioDevice *device);
819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall//void sos_adump(SDL_AudioDevice* thisdevice, void* data, int len);
849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef __WINS__
869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define DODUMP
879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef DODUMP
909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallNONSHARABLE_CLASS(TDump)
919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	public:
939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	TInt Open();
949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	void Close();
959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	void Dump(const TDesC8& aDes);
969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	private:
979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		RFile iFile;
989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	RFs iFs;
999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	};
1009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallTInt TDump::Open()
1029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
1039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	TInt err = iFs.Connect();
1049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if(err == KErrNone)
1059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
1069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef __WINS__
1079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall_LIT(target, "C:\\sdlau.raw");
1089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else
1099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall_LIT(target, "E:\\sdlau.raw");
1109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
1119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		err = iFile.Replace(iFs, target, EFileWrite);
1129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
1139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return err;
1149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
1159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid TDump::Close()
1169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
1179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	iFile.Close();
1189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	iFs.Close();
1199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
1209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid TDump::Dump(const TDesC8& aDes)
1219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
1229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	iFile.Write(aDes);
1239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
1249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
1259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallNONSHARABLE_CLASS(CSimpleWait) : public CTimer
1289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
1299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	public:
1309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		void Wait(TTimeIntervalMicroSeconds32 aWait);
1319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		static CSimpleWait* NewL();
1329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	private:
1339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		CSimpleWait();
1349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		void RunL();
1359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	};
1369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallCSimpleWait* CSimpleWait::NewL()
1399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
1409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	CSimpleWait* wait = new (ELeave) CSimpleWait();
1419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	CleanupStack::PushL(wait);
1429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	wait->ConstructL();
1439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	CleanupStack::Pop();
1449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return wait;
1459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
1469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid CSimpleWait::Wait(TTimeIntervalMicroSeconds32 aWait)
1489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
1499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	After(aWait);
1509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	CActiveScheduler::Start();
1519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
1529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallCSimpleWait::CSimpleWait() : CTimer(CActive::EPriorityStandard)
1549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
1559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	CActiveScheduler::Add(this);
1569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
1579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid CSimpleWait::RunL()
1599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
1609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	CActiveScheduler::Stop();
1619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
1629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallconst TInt KAudioBuffers(2);
1649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallNONSHARABLE_CLASS(CEpocAudio) : public CBase, public MStreamObs, public MStreamProvider
1679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {
1689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    public:
1699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	static void* NewL(TInt BufferSize, TInt aFill);
1709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	inline static CEpocAudio& Current(SDL_AudioDevice* thisdevice);
1719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	static void Free(SDL_AudioDevice* thisdevice);
1739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	void Wait();
1759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	void Play();
1769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    //	void SetBuffer(const TDesC8& aBuffer);
1779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	void ThreadInitL(TAny* aDevice);
1789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	void Open(TInt iRate, TInt iChannels, TUint32 aType, TInt aBytes);
1799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	~CEpocAudio();
1809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	TUint8* Buffer();
1819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	TBool SetPause(TBool aPause);
1829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    #ifdef DODUMP
1839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	void Dump(const TDesC8& aBuf) {iDump.Dump(aBuf);}
1849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    #endif
1859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    private:
1869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	CEpocAudio(TInt aBufferSize);
1879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	void Complete(TInt aState, TInt aError);
1889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	TPtrC8 Data();
1899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	void ConstructL(TInt aFill);
1909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    private:
1919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	TInt iBufferSize;
1929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	CStreamPlayer* iPlayer;
1939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	TInt iBufferRate;
1949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	TInt iRate;
1959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	TInt iChannels;
1969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	TUint32 iType;
1979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	TInt iPosition;
1989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	TThreadId iTid;
1999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	TUint8* iAudioPtr;
2009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	TUint8* iBuffer;
2019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    //	TTimeIntervalMicroSeconds iStart;
2029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	TTime iStart;
2039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	TInt iTune;
2049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	CSimpleWait* iWait;
2059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    #ifdef DODUMP
2069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	TDump iDump;
2079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    #endif
2089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    };
2099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallinline CEpocAudio& CEpocAudio::Current(SDL_AudioDevice* thisdevice)
2119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
2129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return *static_cast<CEpocAudio*>((void*)thisdevice->hidden);
2139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
2149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
2169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallTBool EndSc(TAny*)
2189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
2199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	CActiveScheduler::Stop();
2209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
2219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallLOCAL_C void CleanScL()
2239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
2249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	CIdle* d = CIdle::NewLC(CActive:::EPriorityIdle);
2259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	d->Start(TCallBack(EndSc));
2269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	CActiveScheduler::Start();
2279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
2299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
2309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid CEpocAudio::Free(SDL_AudioDevice* thisdevice)
2329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
2339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CEpocAudio* ea = static_cast<CEpocAudio*>((void*)thisdevice->hidden);
2349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if(ea)
2359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	{
2369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		ASSERT(ea->iTid == RThread().Id());
2379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	delete ea;
2389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	thisdevice->hidden = NULL;
2399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	CActiveScheduler* as =  CActiveScheduler::Current();
2419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	ASSERT(as->StackDepth() == 0);
2429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	delete as;
2439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	CActiveScheduler::Install(NULL);
2449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    	}
2459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    ASSERT(thisdevice->hidden == NULL);
2469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
2479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallCEpocAudio::CEpocAudio(TInt aBufferSize) : iBufferSize(aBufferSize), iPosition(-1)
2499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
2509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
2519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid* CEpocAudio::NewL(TInt aBufferSize, TInt aFill)
2539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
2549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	CEpocAudio* eAudioLib = new (ELeave) CEpocAudio(aBufferSize);
2559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	CleanupStack::PushL(eAudioLib);
2569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	eAudioLib->ConstructL(aFill);
2579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	CleanupStack::Pop();
2589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return eAudioLib;
2599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
2609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid CEpocAudio::ConstructL(TInt aFill)
2629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
2639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	iBuffer = (TUint8*) User::AllocL(KAudioBuffers * iBufferSize);
2649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	memset(iBuffer, aFill, KAudioBuffers * iBufferSize);
2659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	iAudioPtr = iBuffer;
2669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
2679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallTBool CEpocAudio::SetPause(TBool aPause)
2709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
2719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if(aPause && iPosition >= 0)
2729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
2739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		iPosition = -1;
2749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if(iPlayer != NULL)
2759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			iPlayer->Stop();
2769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
2779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if(!aPause && iPosition < 0)
2789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
2799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		iPosition = 0;
2809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if(iPlayer != NULL)
2819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			iPlayer->Start();
2829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
2839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return iPosition < 0;
2849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
2859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid CEpocAudio::ThreadInitL(TAny* aDevice)
2879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
2889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	iTid = RThread().Id();
2899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	CActiveScheduler* as =  new (ELeave) CActiveScheduler();
2909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CActiveScheduler::Install(as);
2919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    EpocSdlEnv::AppendCleanupItem(TSdlCleanupItem((TSdlCleanupOperation)EPOC_CloseAudio, aDevice));
2939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    iWait = CSimpleWait::NewL();
2959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    iPlayer = new (ELeave) CStreamPlayer(*this, *this);
2979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    iPlayer->ConstructL();
2989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    iPlayer->OpenStream(iRate, iChannels, iType);
2999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    #ifdef DODUMP
3019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    User::LeaveIfError(iDump.Open());
3029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    #endif
3039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
3049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallTUint8* CEpocAudio::Buffer()
3089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
3099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	iStart.UniversalTime();
3109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall//	iStart = iPlayer->Position();
3119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return iAudioPtr;
3129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
3149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallCEpocAudio::~CEpocAudio()
3169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
3179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if(iWait != NULL)
3189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		iWait->Cancel();
3199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	delete iWait;
3209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if(iPlayer != NULL)
3219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		iPlayer->Close();
3229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	delete iPlayer;
3239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	delete iBuffer;
3249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
3259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid CEpocAudio::Complete(TInt aState, TInt aError)
3279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
3289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if(aState == MStreamObs::EClose)
3299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
3309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
3319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if(iPlayer->Closed())
3329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		return;
3339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	switch(aError)
3349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
3359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		case KErrUnderflow:
3369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		case KErrInUse:
3379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			iPlayer->Start();
3389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			break;
3399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		case KErrAbort:
3409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			iPlayer->Open();
3419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
3429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
3439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid sos_adump(SDL_AudioDevice* thisdevice, void* data, int len)
3469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
3479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef DODUMP
3489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const TPtrC8 buf((TUint8*)data, len);
3499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	CEpocAudio::Current(thisdevice).Dump(buf);
3509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
3519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
3529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallconst TInt KClip(256);
3549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallTPtrC8 CEpocAudio::Data()
3569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
3579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if(iPosition < 0)
3589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		return KNullDesC8();
3599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	TPtrC8 data(iAudioPtr + iPosition, KClip);
3619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef DODUMP
3639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	iDump.Dump(data);
3649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
3659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	iPosition += KClip;
3679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if(iPosition >= iBufferSize)
3689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
3699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*		if(iAudioPtr == iBuffer)
3719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			iAudioPtr = iBuffer + iBufferSize;
3729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		else
3739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			iAudioPtr = iBuffer;
3749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
3759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		iAudioPtr += iBufferSize;
3769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if((iAudioPtr - iBuffer) >= KAudioBuffers * iBufferSize)
3789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			iAudioPtr = iBuffer;
3799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		iPosition = -1;
3819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if(iWait->IsActive())
3829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			{
3839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			iWait->Cancel();
3849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			CActiveScheduler::Stop();
3859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
3869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
3879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return data;
3889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
3899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid CEpocAudio::Play()
3949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
3959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	iPosition = 0;
3969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
3979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid CEpocAudio::Wait()
3999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
4009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if(iPosition >= 0 /*&& iPlayer->Playing()*/)
4019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
4029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		const TInt64 bufMs = TInt64(iBufferSize - KClip) * TInt64(1000000);
4039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		const TInt64 specTime =  bufMs / TInt64(iRate * iChannels * 2);
4049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		iWait->After(specTime);
4059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		CActiveScheduler::Start();
4079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		TTime end;
4089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		end.UniversalTime();
4099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		const TTimeIntervalMicroSeconds delta = end.MicroSecondsFrom(iStart);
4109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall//		const TTimeIntervalMicroSeconds end = iPlayer->Position();
4139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		const TInt diff = specTime - delta.Int64();
4189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if(diff > 0 && diff < 200000)
4209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			{
4219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			User::After(diff);
4229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
4239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
4259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	else
4269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
4279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	User::After(10000);
4289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall//	iWait->Wait(10000); //just give some time...
4299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
4309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
4319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid CEpocAudio::Open(TInt aRate, TInt aChannels, TUint32 aType, TInt aBytes)
4339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
4349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	iRate = aRate;
4359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	iChannels = aChannels;
4369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	iType = aType;
4379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    iBufferRate = iRate * iChannels * aBytes; //1/x
4389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
4399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Audio driver bootstrap functions */
4429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallAudioBootStrap EPOCAudio_bootstrap = {
4449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	"epoc\0\0\0",
4459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	"EPOC streaming audio\0\0\0",
4469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Audio_Available,
4479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	Audio_CreateDevice
4489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall};
4499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic SDL_AudioDevice *Audio_CreateDevice(int /*devindex*/)
4529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
4539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_AudioDevice *thisdevice;
4549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Initialize all variables that we clean on shutdown */
4569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	thisdevice = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
4579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( thisdevice ) {
4589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		memset(thisdevice, 0, (sizeof *thisdevice));
4599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		thisdevice->hidden = NULL; /*(struct SDL_PrivateAudioData *)
4609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			 malloc((sizeof thisdevice->hidden)); */
4619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
4629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( (thisdevice == NULL) /*|| (thisdevice->hidden == NULL) */) {
4639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_OutOfMemory();
4649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ( thisdevice ) {
4659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			free(thisdevice);
4669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
4679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		return(0);
4689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
4699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall//	memset(thisdevice->hidden, 0, (sizeof *thisdevice->hidden));
4709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Set the function pointers */
4729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	thisdevice->OpenAudio = EPOC_OpenAudio;
4739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	thisdevice->WaitAudio = EPOC_WaitAudio;
4749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	thisdevice->PlayAudio = EPOC_PlayAudio;
4759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	thisdevice->GetAudioBuf = EPOC_GetAudioBuf;
4769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	thisdevice->CloseAudio = EPOC_CloseAudio;
4779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    thisdevice->ThreadInit = EPOC_ThreadInit;
4789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	thisdevice->free = Audio_DeleteDevice;
4799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return thisdevice;
4819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
4829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void Audio_DeleteDevice(SDL_AudioDevice *device)
4859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {
4869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	//free(device->hidden);
4879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	free(device);
4889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
4899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int Audio_Available(void)
4919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
4929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return(1); // Audio stream modules should be always there!
4939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
4949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int EPOC_OpenAudio(SDL_AudioDevice *thisdevice, SDL_AudioSpec *spec)
4979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
4989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_TRACE("SDL:EPOC_OpenAudio");
4999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	TUint32 type = KMMFFourCCCodePCM16;
5029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	TInt bytes = 2;
5039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	switch(spec->format)
5059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
5069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		case AUDIO_U16LSB:
5079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			type = KMMFFourCCCodePCMU16;
5089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			break;
5099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		case AUDIO_S16LSB:
5109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			type = KMMFFourCCCodePCM16;
5119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			break;
5129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		case AUDIO_U16MSB:
5139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			type = KMMFFourCCCodePCMU16B;
5149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			break;
5159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		case AUDIO_S16MSB:
5169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			type = KMMFFourCCCodePCM16B;
5179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			break;
5189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			//8 bit not supported!
5199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		case AUDIO_U8:
5209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		case AUDIO_S8:
5219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		default:
5229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			spec->format = AUDIO_S16LSB;
5239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		};
5249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if(spec->channels > 2)
5289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		spec->channels = 2;
5299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	spec->freq = CStreamPlayer::ClosestSupportedRate(spec->freq);
5319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Allocate mixing buffer */
5349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const TInt buflen = spec->size;// * bytes * spec->channels;
5359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall//	audiobuf = NULL;
5369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    TRAPD(err, thisdevice->hidden = static_cast<SDL_PrivateAudioData*>(CEpocAudio::NewL(buflen, spec->silence)));
5389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if(err != KErrNone)
5399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        return -1;
5409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	CEpocAudio::Current(thisdevice).Open(spec->freq, spec->channels, type, bytes);
5429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	CEpocAudio::Current(thisdevice).SetPause(ETrue);
5449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   // isSDLAudioPaused = 1;
5469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    thisdevice->enabled = 0; /* enable only after audio engine has been initialized!*/
5489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* We're ready to rock and roll. :-) */
5509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return(0);
5519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
5529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void EPOC_CloseAudio(SDL_AudioDevice* thisdevice)
5559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {
5569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef DEBUG_AUDIO
5579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_TRACE("Close audio\n");
5589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
5599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	CEpocAudio::Free(thisdevice);
5619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
5629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void EPOC_ThreadInit(SDL_AudioDevice *thisdevice)
5659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    {
5669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_TRACE("SDL:EPOC_ThreadInit");
5679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    CEpocAudio::Current(thisdevice).ThreadInitL(thisdevice);
5689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    RThread().SetPriority(EPriorityMore);
5699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    thisdevice->enabled = 1;
5709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
5719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* This function waits until it is possible to write a full sound buffer */
5739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void EPOC_WaitAudio(SDL_AudioDevice* thisdevice)
5749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
5759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef DEBUG_AUDIO
5769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_TRACE1("wait %d audio\n", CEpocAudio::AudioLib().StreamPlayer(KSfxChannel).SyncTime());
5779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    TInt tics = User::TickCount();
5789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
5799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	CEpocAudio::Current(thisdevice).Wait();
5819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef DEBUG_AUDIO
5839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    TInt ntics =  User::TickCount() - tics;
5849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_TRACE1("audio waited %d\n", ntics);
5859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_TRACE1("audio at %d\n", tics);
5869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
5879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
5889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void EPOC_PlayAudio(SDL_AudioDevice* thisdevice)
5929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
5939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 	if(CEpocAudio::Current(thisdevice).SetPause(SDL_GetAudioStatus() == SDL_AUDIO_PAUSED))
5949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 		SDL_Delay(500); //hold on the busy loop
5959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 	else
5969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 		CEpocAudio::Current(thisdevice).Play();
5979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef DEBUG_AUDIO
5999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_TRACE("buffer has audio data\n");
6009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
6019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef DEBUG_AUDIO
6049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_TRACE1("Wrote %d bytes of audio data\n", buflen);
6059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
6069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
6079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic Uint8 *EPOC_GetAudioBuf(SDL_AudioDevice* thisdevice)
6099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
6109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return CEpocAudio::Current(thisdevice).Buffer();
6119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
6129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
615