From 194f9ae0647d46171a8e21888cbd18c716547785 Mon Sep 17 00:00:00 2001 From: James Laird-Wah Date: Wed, 19 Aug 2015 11:59:39 +1000 Subject: [PATCH 01/16] S60v3: initial commit GUI, keyboard, sound all work; keyboard is almost completely unresponsive when sound is playing though. --- projects/.gitignore | 5 + projects/Makefile | 27 +- projects/Makefile.S60 | 39 ++ projects/bld.inf | 2 + projects/lgpt.pkg | 36 ++ projects/lgpt.rss | 9 + projects/s60/makemmp.pl | 31 ++ projects/s60/mmpheader | 53 ++ sources/Adapters/S60/S60Main.cpp | 26 + sources/Adapters/S60/System/S60System.cpp | 153 ++++++ sources/Adapters/S60/System/S60System.h | 31 ++ sources/Adapters/SDL/GUI/SDLEventManager.cpp | 24 +- sources/Adapters/SDL/GUI/SDLGUIWindowImp.cpp | 14 +- sources/Resources/lgpt_icon.svg | 526 +++++++++++++++++++ 14 files changed, 961 insertions(+), 15 deletions(-) create mode 100644 projects/.gitignore create mode 100644 projects/Makefile.S60 create mode 100644 projects/bld.inf create mode 100644 projects/lgpt.pkg create mode 100644 projects/lgpt.rss create mode 100644 projects/s60/makemmp.pl create mode 100644 projects/s60/mmpheader create mode 100644 sources/Adapters/S60/S60Main.cpp create mode 100644 sources/Adapters/S60/System/S60System.cpp create mode 100644 sources/Adapters/S60/System/S60System.h create mode 100644 sources/Resources/lgpt_icon.svg diff --git a/projects/.gitignore b/projects/.gitignore new file mode 100644 index 00000000..ebafed02 --- /dev/null +++ b/projects/.gitignore @@ -0,0 +1,5 @@ +lgpt.mmp +lgpt.GCCE +lgpt.mif +lgpt.sis +lgpt.mbm diff --git a/projects/Makefile b/projects/Makefile index 59768b2b..3fb1511a 100644 --- a/projects/Makefile +++ b/projects/Makefile @@ -4,9 +4,9 @@ .SUFFIXES: #--------------------------------------------------------------------------------- -PLATFORM:= RASPI +PLATFORM:= S60 -include $(PWD)/Makefile.$(PLATFORM) +include Makefile.$(PLATFORM) #--------------------------------------------------------------------------------- # options for FXE @@ -179,6 +179,16 @@ COMMONDIRS := ../sources/System/Console \ ../sources/Externals/Soundfont \ ../sources/Externals/TinyXML +S60DIRS := ../sources/Adapters/Unix/FileSystem \ + ../sources/System/Process \ + ../sources/Adapters/SDL/Audio \ + ../sources/Adapters/Dummy/Midi \ + ../sources/Adapters/Unix/Process \ + ../sources/Adapters/SDL/GUI \ + ../sources/Adapters/SDL/Timer \ + ../sources/Adapters/S60/System \ + ../sources/Adapters/S60 + #--------------------------------------------------------------------------------- # files definition #--------------------------------------------------------------------------------- @@ -299,6 +309,19 @@ GP2XFILES := GPSDLMain.o \ SDLTimer.o \ GUIFactory.o SDLEventManager.o SDLGUIWindowImp.o +S60FILES := UnixFileSystem.o \ + DummyMidi.o \ + SDLAudio.o \ + Process.o \ + SDLAudioDriver.o \ + UnixProcess.o \ + SDLTimer.o \ + GUIFactory.o \ + SDLEventManager.o \ + SDLGUIWindowImp.o \ + S60Main.o \ + S60System.o + CAANOOFILES := CAANOOSDLMain.o \ UnixFileSystem.o \ CAANOOMidiService.o \ diff --git a/projects/Makefile.S60 b/projects/Makefile.S60 new file mode 100644 index 00000000..a1538536 --- /dev/null +++ b/projects/Makefile.S60 @@ -0,0 +1,39 @@ +PWD = ${shell pwd} + +ICONSRC = ..\sources\Resources\lgpt_icon.svg + +all: lgpt.sis + +run: lgpt.sis + runonphone -s lgpt.sis lgpt.exe + +lgpt.sis: $(EPOCROOT)/epoc32/build/$(PWD)/lgpt/gcce/urel/lgpt.exe lgpt.pkg lgpt.mif + makesis "-d$(EPOCROOT)" lgpt.pkg + +$(EPOCROOT)/epoc32/build/$(PWD)/lgpt/gcce/urel/lgpt.exe: lgpt.gcce $(SRCS) $(EPOCROOT)/epoc32/release/armv5/urel/sdl.lib + +make -f lgpt.gcce UREL + +lgpt.mif: $(ICONSRC) + mifconv lgpt.mif $(ICONSRC) + +lgpt.mmp: s60/mmpheader + +perl s60/makemmp.pl "$(OFILES)" "$(SOURCES)" $< > $@ + +lgpt.gcce: lgpt.mmp + bldmake bldfiles + makmake lgpt.mmp gcce + +clean: clean-S60 + +clean-S60: lgpt.gcce + make -f lgpt.gcce CLEAN + del lgpt.gcce + del lgpt.mmp + del lgpt.mif + del lgpt.sis + +mrproper: clean + rm -rf $(EPOCROOT)/epoc32/build$(PWD) + +$(EPOCROOT)/epoc32/build/$(PWD)/gcce.make: bld.inf lgpt.mmp + bldmake bldfiles diff --git a/projects/bld.inf b/projects/bld.inf new file mode 100644 index 00000000..300ef388 --- /dev/null +++ b/projects/bld.inf @@ -0,0 +1,2 @@ +prj_mmpfiles +lgpt.mmp diff --git a/projects/lgpt.pkg b/projects/lgpt.pkg new file mode 100644 index 00000000..5b40518b --- /dev/null +++ b/projects/lgpt.pkg @@ -0,0 +1,36 @@ +&EN + +; standard SIS file header +#{"LGPT"},(0xA0102033),1,0,0 + +;Localised Vendor name +%{"Vendor-EN"} + +;Unique Vendor name +:"Vendor" + +[0x101F7961], 0, 0, 0, {"S60v3"} +[0x1028315F], 0, 0, 0, {"S60v5"} + +;Files to install +"\epoc32\release\gcce\urel\lgpt.exe" - "!:\sys\bin\lgpt.exe" +"\epoc32\data\z\private\10003a3f\import\apps\lgpt.rsc" - "!:\private\10003a3f\import\apps\lgpt.rsc" +"\epoc32\data\z\resource\apps\lgpt_loc.rsc" - "!:\resource\apps\lgpt_loc.rsc" +"lgpt.mif" - "!:\resource\apps\lgpt.mif" + +; For getting meaningful stacktraces with fdb from FShell +"\epoc32\release\gcce\urel\lgpt.exe.map" - "e:\lgpt.exe.map" + +; Demo song include +"lgpt10k\samples\tunedbell.wav" - "e:\lgpt\lgpt10k\samples\tunedbell.wav" +"lgpt10k\samples\triangle.wav" - "e:\lgpt\lgpt10k\samples\triangle.wav" +"lgpt10k\samples\square.wav" - "e:\lgpt\lgpt10k\samples\square.wav" +"lgpt10k\samples\Snaredrum.wav" - "e:\lgpt\lgpt10k\samples\Snaredrum.wav" +"lgpt10k\samples\sinus.wav" - "e:\lgpt\lgpt10k\samples\sinus.wav" +"lgpt10k\samples\sawtooth.wav" - "e:\lgpt\lgpt10k\samples\sawtooth.wav" +"lgpt10k\samples\rezobass.wav" - "e:\lgpt\lgpt10k\samples\rezobass.wav" +"lgpt10k\samples\Hihat.wav" - "e:\lgpt\lgpt10k\samples\Hihat.wav" +"lgpt10k\samples\Downramp.wav" - "e:\lgpt\lgpt10k\samples\Downramp.wav" +"lgpt10k\samples\Bassdrum.wav" - "e:\lgpt\lgpt10k\samples\Bassdrum.wav" +"lgpt10k\samples\accordion.wav" - "e:\lgpt\lgpt10k\samples\accordion.wav" +"lgpt10k\lgptsav.dat" - "e:\lgpt\lgpt10k\lgptsav.dat" diff --git a/projects/lgpt.rss b/projects/lgpt.rss new file mode 100644 index 00000000..929723ba --- /dev/null +++ b/projects/lgpt.rss @@ -0,0 +1,9 @@ +#include + +UID2 KUidAppRegistrationResourceFile +UID3 0xA0102034 + +RESOURCE APP_REGISTRATION_INFO { + app_file="lgpt"; + localisable_resource_file="\\resource\\apps\\lgpt_loc"; +} diff --git a/projects/s60/makemmp.pl b/projects/s60/makemmp.pl new file mode 100644 index 00000000..22cc4530 --- /dev/null +++ b/projects/s60/makemmp.pl @@ -0,0 +1,31 @@ +@files = split /\s+/, $ARGV[0]; +@searchdirs = split /\s+/, $ARGV[1]; +map { s/\.o$// } @files; + +open IN, "<$ARGV[2]" || die; +for () { print }; + +for $dir (@searchdirs) { + print "userinclude $dir\n"; +} + +%seen = (); + +for $dir (@searchdirs) { + next if $dir =~ /^\s*$/; + print "sourcepath $dir\n"; + for $file (@files) { + if (-e "$dir/$file.cpp") { + print "source $file.cpp\n"; + $seen{$file} = 1; + } + if (-e "$dir/$file.c") { + print "source $file.c\n"; + $seen{$file} = 1; + } + } +} + +for (@files) { + die "Did not find source for $_.o!" unless $seen{$_}; +} diff --git a/projects/s60/mmpheader b/projects/s60/mmpheader new file mode 100644 index 00000000..ddce3f0a --- /dev/null +++ b/projects/s60/mmpheader @@ -0,0 +1,53 @@ +target lgpt.exe +targettype exe +uid 0x100039ce 0xa0102034 +vendorid 0 + +epocstacksize 0xA000 +epocheapsize 0x100000 0x4000000 + +start resource lgpt.rss +targetpath \private\10003a3f\import\apps +end +start resource lgpt_loc.rss +targetpath \resource\apps +lang SC +end + +macro SYMBIAN +macro WITH_SDL +macro WITH_ZLIB +macro WITH_PERSONAL_DIR +macro CPP_MEMORY + +systeminclude \epoc32\include\stdapis +systeminclude \epoc32\include\stdapis\stlport +systeminclude \epoc32\include\stdapis\stlport\stl +systeminclude \epoc32\include\stdapis\glib-2.0 +systeminclude \epoc32\include +systeminclude \epoc32\include\SDL + +library libc.lib +library libm.lib +library libpthread.lib +library libstdcpp.lib +staticlibrary sdl.lib +library apgrfx.lib +library apparc.lib +library avkon.lib +library bitgdi.lib +library cone.lib +library eikcore.lib +library euser.lib +library fbscli.lib +library hal.lib +library mediaclientaudiostream.lib +library ws32.lib +library centralrepository.lib +library remconcoreapi.lib +library remconinterfacebase.lib + +capability ReadUserData WriteUserData UserEnvironment NetworkServices + +userinclude ../sources +userinclude ../sources/System/System diff --git a/sources/Adapters/S60/S60Main.cpp b/sources/Adapters/S60/S60Main.cpp new file mode 100644 index 00000000..a266cf2a --- /dev/null +++ b/sources/Adapters/S60/S60Main.cpp @@ -0,0 +1,26 @@ +#include "Application/Application.h" +#include "Adapters/S60/System/S60System.h" +#include "Foundation/T_Singleton.h" +#include +#include +#include "Adapters/SDL/GUI/SDLGUIWindowImp.h" +#include "Application/Persistency/PersistencyService.h" +#include "Adapters/SDL/GUI/SDLGUIWindowImp.h" + +int main(int argc,char *argv[]) +{ + S60System::Boot(argc,argv) ; + + SDLCreateWindowParams params ; + params.title="littlegptracker" ; + params.cacheFonts_=true ; + params.framebuffer_=false ; + + Application::GetInstance()->Init(params) ; + + S60System::MainLoop() ; + S60System::Shutdown() ; +} + + + diff --git a/sources/Adapters/S60/System/S60System.cpp b/sources/Adapters/S60/System/S60System.cpp new file mode 100644 index 00000000..a6c59916 --- /dev/null +++ b/sources/Adapters/S60/System/S60System.cpp @@ -0,0 +1,153 @@ +#include "S60System.h" +#include "Adapters/Unix/FileSystem/UnixFileSystem.h" +#include "Adapters/SDL/GUI/GUIFactory.h" +#include "Adapters/SDL/GUI/SDLGUIWindowImp.h" +#include "Adapters/SDL/GUI/SDLEventManager.h" +#include "Adapters/Unix/Process/UnixProcess.h" +#include "Adapters/SDL/Audio/SDLAudio.h" +#include "Adapters/Dummy/Midi/DummyMidi.h" +#include "Externals/TinyXML/tinyxml.h" +#include "Application/Model/Config.h" +#include "Application/Controllers/ControlRoom.h" +#include "Application/Player/SyncMaster.h" +#include "Application/Commands/NodeList.h" +#include "Adapters/SDL/Timer/SDLTimer.h" +#include "System/Console/Logger.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define Time E32Time +#include + +EventManager *S60System::eventManager_ = NULL ; + +int S60System::MainLoop() { + eventManager_->InstallMappings() ; + eventManager_->MainLoop() ; +} ; + +void S60System::Boot(int argc,char **argv) { + + // Install System + System::Install(new S60System()) ; + + // Install FileSystem + FileSystem::Install(new UnixFileSystem()) ; + Config::GetInstance()->ProcessArguments(argc,argv) ; + + // XXX debug to SD card + unlink("e:/lgpt.log"); + Path logPath("e:\\lgpt.log"); + FileLogger *fileLogger=new FileLogger(logPath); + if(fileLogger->Init().Succeeded()) + { + Trace::GetInstance()->SetLogger(*fileLogger); + } + + // Install GUI Factory + I_GUIWindowFactory::Install(new GUIFactory()) ; + + // Install Timers + TimerService::GetInstance()->Install(new SDLTimerService()) ; + + // Install Sound + AudioSettings hints ; + hints.bufferSize_=1024 ; + hints.preBufferCount_=8 ; + Audio::Install(new SDLAudio(hints)) ; + // Install Midi + MidiService::Install(new DummyMidi()) ; + + // Install Threads + SysProcessFactory::Install(new UnixProcessFactory()) ; + + // XXX this conflicts with the SDLEventManager + if ( SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0 ) { + return; + } + Path::SetAlias("root","e:/lgpt") ; + Path::SetAlias("bin","e:/lgpt") ; + + SDL_EnableUNICODE(1); + + atexit(SDL_Quit); + + eventManager_=I_GUIWindowFactory::GetInstance()->GetEventManager() ; + eventManager_->Init() ; + + // defaults suitable for qwertyphones eg. E63 + eventManager_->MapAppButton("q", APP_BUTTON_A); + eventManager_->MapAppButton("a", APP_BUTTON_B); + eventManager_->MapAppButton("left", APP_BUTTON_LEFT); + eventManager_->MapAppButton("right", APP_BUTTON_RIGHT); + eventManager_->MapAppButton("up", APP_BUTTON_UP); + eventManager_->MapAppButton("down", APP_BUTTON_DOWN); + eventManager_->MapAppButton("home", APP_BUTTON_L); // green call key + eventManager_->MapAppButton("space", APP_BUTTON_R); // left softkey + eventManager_->MapAppButton("escape", APP_BUTTON_START); // right softkey +} ; + +void S60System::Shutdown() { + delete Audio::GetInstance() ; + exit(0); +} ; + +static int secbase; + +unsigned long S60System::GetClock() { + struct timeval tp; + + gettimeofday(&tp, NULL); + if (!secbase) + { + secbase = tp.tv_sec; + return long(tp.tv_usec/1000.0); + } + return long((tp.tv_sec - secbase)*1000 + tp.tv_usec/1000.0); +} + +int S60System::GetBatteryLevel() { + return -1; +} ; + +void S60System::Sleep(int millisec) { + User::After(millisec*1000); +} + +void *S60System::Malloc(unsigned size) { + void *ptr=malloc(size) ; + return ptr ; +} + +void S60System::Free(void *ptr) { + free(ptr) ; +} + +//extern "C" void *gpmemset(void *s1,unsigned char val,int n) ; + +void S60System::Memset(void *addr,char val,int size) +{ + memset(addr,val,size) ; +} ; + +void *S60System::Memcpy(void *s1, const void *s2, int n) +{ + return memcpy(s1,s2,n); +} + +void S60System::PostQuitMessage() +{ + Trace::Log("S60", "PostQuitMessage called"); + SDLEventManager::GetInstance()->PostQuitMessage() ; +} + +unsigned int S60System::GetMemoryUsage() +{ + return 0; +} diff --git a/sources/Adapters/S60/System/S60System.h b/sources/Adapters/S60/System/S60System.h new file mode 100644 index 00000000..7b5052d4 --- /dev/null +++ b/sources/Adapters/S60/System/S60System.h @@ -0,0 +1,31 @@ +#ifndef _S60_SYSTEM_H_ +#define _S60_SYSTEM_H_ + +#include "System/System/System.h" +#include "UIFramework/SimpleBaseClasses/EventManager.h" +#include + +class S60System: public System { +public: + static void Boot(int argc,char **argv) ; + static void Shutdown() ; + static int MainLoop() ; + +public: // System implementation + virtual unsigned long GetClock() ; + virtual int GetBatteryLevel() ; + virtual void Sleep(int millisec); + virtual void *Malloc(unsigned size) ; + virtual void Free(void *) ; + virtual void Memset(void *addr,char val,int size) ; + virtual void *Memcpy(void *s1, const void *s2, int n) ; + virtual void PostQuitMessage() ; + virtual unsigned int GetMemoryUsage() ; + +private: + static bool invert_ ; + static int lastBattLevel_ ; + static unsigned int lastBeatCount_ ; + static EventManager *eventManager_; +} ; +#endif diff --git a/sources/Adapters/SDL/GUI/SDLEventManager.cpp b/sources/Adapters/SDL/GUI/SDLEventManager.cpp index a598715d..99b9da09 100644 --- a/sources/Adapters/SDL/GUI/SDLEventManager.cpp +++ b/sources/Adapters/SDL/GUI/SDLEventManager.cpp @@ -20,6 +20,7 @@ bool SDLEventManager::Init() { EventManager::Init() ; +#ifndef SYMBIAN if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_JOYSTICK|SDL_INIT_TIMER) < 0 ) { return false; @@ -34,22 +35,15 @@ bool SDLEventManager::Init() int joyCount=SDL_NumJoysticks() ; joyCount=(joyCount>MAX_JOY_COUNT)?MAX_JOY_COUNT:joyCount ; - - keyboardCS_=new KeyboardControllerSource("keyboard") ; - const char *dumpIt=Config::GetInstance()->GetValue("DUMPEVENT") ; - if ((dumpIt)&&(!strcmp(dumpIt,"YES"))) - { - dumpEvent_=true ; - } - - for (int i=0;iGetValue("DUMPEVENT") ; + if ((dumpIt)&&(!strcmp(dumpIt,"YES"))) + { + dumpEvent_=true ; + } + for (int i=0;iw; + int screenHeight = modes[0]->h; + windowed_ = false; + #elif defined(PLATFORM_GP2X) int screenWidth = 320; int screenHeight = 240; #elif defined(PLATFORM_PSP) @@ -82,6 +89,9 @@ SDLGUIWindowImp::SDLGUIWindowImp(GUICreateWindowParams &p) Trace::Log("DISPLAY","Using driver %s. Screen (%d,%d) Bpp:%d",driverName,screenWidth,screenHeight,bitDepth_); bool fullscreen=false ; + #ifdef SYMBIAN + fullscreen=true; + #endif const char *fullscreenValue=Config::GetInstance()->GetValue("FULLSCREEN") ; if ((fullscreenValue)&&(!strcmp(fullscreenValue,"YES"))) diff --git a/sources/Resources/lgpt_icon.svg b/sources/Resources/lgpt_icon.svg new file mode 100644 index 00000000..45054df7 --- /dev/null +++ b/sources/Resources/lgpt_icon.svg @@ -0,0 +1,526 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From ec0371ffe7c5274e8d0d0d82bde4b261d4e80f2b Mon Sep 17 00:00:00 2001 From: James Laird-Wah Date: Wed, 19 Aug 2015 12:01:13 +1000 Subject: [PATCH 02/16] Unix adapter compatibility fixes - use dirent.h instead of sys/dir.h - use anonymous, unshared semaphores If I understand the code right, these should be independent both between UnixSysSemaphore instances and between processes. Anyway, named semaphores aren't present on S60. --- sources/Adapters/Unix/FileSystem/UnixFileSystem.cpp | 2 +- sources/Adapters/Unix/Process/UnixProcess.cpp | 9 ++++----- sources/Adapters/Unix/Process/UnixProcess.h | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/sources/Adapters/Unix/FileSystem/UnixFileSystem.cpp b/sources/Adapters/Unix/FileSystem/UnixFileSystem.cpp index e1c678d9..ff7b9f22 100644 --- a/sources/Adapters/Unix/FileSystem/UnixFileSystem.cpp +++ b/sources/Adapters/Unix/FileSystem/UnixFileSystem.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/sources/Adapters/Unix/Process/UnixProcess.cpp b/sources/Adapters/Unix/Process/UnixProcess.cpp index 9912ded5..6bb85d0b 100644 --- a/sources/Adapters/Unix/Process/UnixProcess.cpp +++ b/sources/Adapters/Unix/Process/UnixProcess.cpp @@ -22,16 +22,15 @@ SysSemaphore *UnixProcessFactory::CreateNewSemaphore(int initialcount, int maxco } ; UnixSysSemaphore::UnixSysSemaphore(int initialcount,int maxcount) { - sem_=sem_open("n0ssemaphore",O_CREAT,S_IRUSR|S_IWUSR , 0 ); + sem_init(&sem_, 0, initialcount); } ; UnixSysSemaphore::~UnixSysSemaphore() { - sem_close(sem_) ; - sem_unlink("n0ssemaphore") ; + sem_destroy(&sem_); } ; SysSemaphoreResult UnixSysSemaphore::Wait() { - sem_wait(sem_) ; + sem_wait(&sem_) ; return SSR_NO_ERROR ; } ; @@ -44,6 +43,6 @@ SysSemaphoreResult UnixSysSemaphore::WaitTimeout(unsigned long timeout) { } ; SysSemaphoreResult UnixSysSemaphore::Post() { - sem_post(sem_) ; + sem_post(&sem_) ; return SSR_NO_ERROR ; } ; diff --git a/sources/Adapters/Unix/Process/UnixProcess.h b/sources/Adapters/Unix/Process/UnixProcess.h index f69181e3..0f446615 100644 --- a/sources/Adapters/Unix/Process/UnixProcess.h +++ b/sources/Adapters/Unix/Process/UnixProcess.h @@ -19,6 +19,6 @@ class UnixSysSemaphore:public SysSemaphore { virtual SysSemaphoreResult WaitTimeout(unsigned long) ; virtual SysSemaphoreResult Post() ; private: - sem_t *sem_ ; + sem_t sem_; } ; #endif From b11822d4f6233036c52eddb9d4eb04a4935ecb4b Mon Sep 17 00:00:00 2001 From: James Laird-Wah Date: Wed, 19 Aug 2015 12:05:13 +1000 Subject: [PATCH 03/16] NOTFORMERGE - S60 hack: avoid mixer mutex crash Presumably not initialised on the platform. Need to fix. --- sources/Application/AppWindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sources/Application/AppWindow.cpp b/sources/Application/AppWindow.cpp index faa12a20..97405248 100644 --- a/sources/Application/AppWindow.cpp +++ b/sources/Application/AppWindow.cpp @@ -408,7 +408,7 @@ bool AppWindow::onEvent(GUIEvent &event) { unsigned short v=1<Lock() ; + //sm->Lock() ; switch(event.GetType()) { @@ -441,7 +441,7 @@ bool AppWindow::onEvent(GUIEvent &event) { default: break ; } - sm->Unlock() ; + //sm->Unlock() ; if (_shouldQuit) { onQuitApp() ; From e0d87ca3d938ed4780c8fcf9a43165c89b74f12a Mon Sep 17 00:00:00 2001 From: James Laird-Wah Date: Wed, 19 Aug 2015 12:10:03 +1000 Subject: [PATCH 04/16] lgpt.pkg: fix UID --- projects/lgpt.pkg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/lgpt.pkg b/projects/lgpt.pkg index 5b40518b..a42d830c 100644 --- a/projects/lgpt.pkg +++ b/projects/lgpt.pkg @@ -1,7 +1,7 @@ &EN ; standard SIS file header -#{"LGPT"},(0xA0102033),1,0,0 +#{"LGPT"},(0xA0102034),1,0,0 ;Localised Vendor name %{"Vendor-EN"} From aa3bdd9c0f818c29bce1cd1feff65ca371949363 Mon Sep 17 00:00:00 2001 From: James Laird-Wah Date: Wed, 19 Aug 2015 12:19:42 +1000 Subject: [PATCH 05/16] Ensure CRLF line endings used on lgpt.pkg Otherwise makesis bombs with a verification error. --- .gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..b6ecd427 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +lgpt.pkg text eol=crlf From 23129c434edf1d7b1f8ee66bd0d87c2aa60ab1de Mon Sep 17 00:00:00 2001 From: James Laird-Wah Date: Wed, 19 Aug 2015 12:21:44 +1000 Subject: [PATCH 06/16] Move root & bin dir to c:/data/lgpt Somewhat more consistent with the S60 standard. Note that the .pkg file at this point expects to find the `lgpt10k` demo song directory in 'projects' at build time (this is very useful for testing). --- projects/lgpt.pkg | 24 +++++++++++------------ sources/Adapters/S60/System/S60System.cpp | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/projects/lgpt.pkg b/projects/lgpt.pkg index a42d830c..f5b75364 100644 --- a/projects/lgpt.pkg +++ b/projects/lgpt.pkg @@ -22,15 +22,15 @@ "\epoc32\release\gcce\urel\lgpt.exe.map" - "e:\lgpt.exe.map" ; Demo song include -"lgpt10k\samples\tunedbell.wav" - "e:\lgpt\lgpt10k\samples\tunedbell.wav" -"lgpt10k\samples\triangle.wav" - "e:\lgpt\lgpt10k\samples\triangle.wav" -"lgpt10k\samples\square.wav" - "e:\lgpt\lgpt10k\samples\square.wav" -"lgpt10k\samples\Snaredrum.wav" - "e:\lgpt\lgpt10k\samples\Snaredrum.wav" -"lgpt10k\samples\sinus.wav" - "e:\lgpt\lgpt10k\samples\sinus.wav" -"lgpt10k\samples\sawtooth.wav" - "e:\lgpt\lgpt10k\samples\sawtooth.wav" -"lgpt10k\samples\rezobass.wav" - "e:\lgpt\lgpt10k\samples\rezobass.wav" -"lgpt10k\samples\Hihat.wav" - "e:\lgpt\lgpt10k\samples\Hihat.wav" -"lgpt10k\samples\Downramp.wav" - "e:\lgpt\lgpt10k\samples\Downramp.wav" -"lgpt10k\samples\Bassdrum.wav" - "e:\lgpt\lgpt10k\samples\Bassdrum.wav" -"lgpt10k\samples\accordion.wav" - "e:\lgpt\lgpt10k\samples\accordion.wav" -"lgpt10k\lgptsav.dat" - "e:\lgpt\lgpt10k\lgptsav.dat" +"lgpt10k\samples\tunedbell.wav" - "c:\data\lgpt\lgpt10k\samples\tunedbell.wav" +"lgpt10k\samples\triangle.wav" - "c:\data\lgpt\lgpt10k\samples\triangle.wav" +"lgpt10k\samples\square.wav" - "c:\data\lgpt\lgpt10k\samples\square.wav" +"lgpt10k\samples\Snaredrum.wav" - "c:\data\lgpt\lgpt10k\samples\Snaredrum.wav" +"lgpt10k\samples\sinus.wav" - "c:\data\lgpt\lgpt10k\samples\sinus.wav" +"lgpt10k\samples\sawtooth.wav" - "c:\data\lgpt\lgpt10k\samples\sawtooth.wav" +"lgpt10k\samples\rezobass.wav" - "c:\data\lgpt\lgpt10k\samples\rezobass.wav" +"lgpt10k\samples\Hihat.wav" - "c:\data\lgpt\lgpt10k\samples\Hihat.wav" +"lgpt10k\samples\Downramp.wav" - "c:\data\lgpt\lgpt10k\samples\Downramp.wav" +"lgpt10k\samples\Bassdrum.wav" - "c:\data\lgpt\lgpt10k\samples\Bassdrum.wav" +"lgpt10k\samples\accordion.wav" - "c:\data\lgpt\lgpt10k\samples\accordion.wav" +"lgpt10k\lgptsav.dat" - "c:\data\lgpt\lgpt10k\lgptsav.dat" diff --git a/sources/Adapters/S60/System/S60System.cpp b/sources/Adapters/S60/System/S60System.cpp index a6c59916..e0b70d4e 100644 --- a/sources/Adapters/S60/System/S60System.cpp +++ b/sources/Adapters/S60/System/S60System.cpp @@ -71,8 +71,8 @@ void S60System::Boot(int argc,char **argv) { if ( SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0 ) { return; } - Path::SetAlias("root","e:/lgpt") ; - Path::SetAlias("bin","e:/lgpt") ; + Path::SetAlias("root","c:/data/lgpt") ; + Path::SetAlias("bin","c:/data/lgpt") ; SDL_EnableUNICODE(1); From 0be071350d4d69f8ab34ec2258e5bbc476249fb2 Mon Sep 17 00:00:00 2001 From: James Laird-Wah Date: Wed, 19 Aug 2015 12:32:11 +1000 Subject: [PATCH 07/16] S60: remove unneeded capabilities. --- projects/s60/mmpheader | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/s60/mmpheader b/projects/s60/mmpheader index ddce3f0a..a83506de 100644 --- a/projects/s60/mmpheader +++ b/projects/s60/mmpheader @@ -47,7 +47,7 @@ library centralrepository.lib library remconcoreapi.lib library remconinterfacebase.lib -capability ReadUserData WriteUserData UserEnvironment NetworkServices +capability ReadUserData WriteUserData userinclude ../sources userinclude ../sources/System/System From 0b80b263794ffabf53b5e8f373fa49fe2e5591ea Mon Sep 17 00:00:00 2001 From: James Laird-Wah Date: Wed, 19 Aug 2015 12:38:00 +1000 Subject: [PATCH 08/16] S60: add some notes on the port --- README.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000..d60a0400 --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +# LittleGPTracker +This is a fork of m-.-n's LGPT for Symbian (S60v3) devices. Built and tested on a Nokia E63 (S60v3 FP1). + +At present, everything works - except the keyboard becomes unresponsive when audio is running. To be fixed. + +## Runtime dependencies +You need the Open C/C++ libraries installed; these come with the Qt installer, amongst other places. The separate SIS files are also available in the Open C/C++ plugin (see below). + +## Compile dependencies +You need: + +- an S60 SDK matching your phone (v3, v3 FP1, v3 FP2) - these are not backwards compatible but somewhat forwards +- a suitable version of the GCCE compiler +- the Open C/C++ plug-in +- SDL-S60v3 from here: http://repo.or.cz/w/SDL.s60v3.git + +Unfortunately the Nokia site with the SDKs and tools is now gone. Most of the necessary files can be found here: +http://n8delight.blogspot.com.au/2014/05/for-developers-re-up-of-symbian.html +I also found a copy of Open C/C++ on 4shared (look for s60_open_c_cpp_plug_in_v1_7_en). +The Qt SDK 1.1.x includes compiler, SDK and plug-ins all together, which are suitable for FP2 and above. This can be found here: +ftp://ftp.informatik.hu-berlin.de/pub/Mirrors/ftp.troll.no/QT/qtsdk/ + +To build: +- Install the SDK, which will add it to your PATH or give you a startup link to do so (QtSDK does this). +- Install the compiler, put its bin directory on your PATH +- Install Open C/C++ over the SDK +- `cd SDL-s60v3\symbian`; `bldmake bldfiles`; `abld build gcce` + This installs the resulting files *into the SDK tree* (eek). +- cd LittleGPTracker\projects; make + Assuming the platform is set to S60, this should give you `lgpt.sis` which you can install. + +### Notes +There is a "make run" target which will use `runonphone.exe` (available in the QtSDK, amongst other places). You need the App TRK installed and running on your phone. + +I had to patch a few bits of the FP1 SDK to get the compiler to work! +Notably, I had to replace macros defining `va_list`, `va_start`, `va_end` etc. using `__builtin_va_{list,start,end}`. + +If you use a newer SDK than your phone you might get lucky, or you might not. The FP2/QtSDK built the project nicely, but it refused to run on my phone with "Feature not supported". + +There's a debugger `fdb` in the FShell project at http://fshell.sf.net which can give you stack traces; use `fdb -m e:\` to point it at `lgpt.exe.map` with all the symbols. From ca68de148462ccfda5a3530d6ab8ec9628f8df8e Mon Sep 17 00:00:00 2001 From: James Laird-Wah Date: Wed, 19 Aug 2015 22:34:51 +1000 Subject: [PATCH 09/16] S60: add DevSound audio driver Currently: a) crashes on exit, and b) doesn't appear to improve audio latency - still around 300ms on my test phone. Does not suffer from the UI trouble that the SDL one does. --- projects/Makefile | 5 +- projects/s60/mmpheader | 3 +- sources/Adapters/S60/S60Audio.cpp | 31 ++++++++ sources/Adapters/S60/S60Audio.h | 16 ++++ sources/Adapters/S60/S60AudioDriver.cpp | 91 +++++++++++++++++++++++ sources/Adapters/S60/S60AudioDriver.h | 55 ++++++++++++++ sources/Adapters/S60/System/S60System.cpp | 6 +- 7 files changed, 199 insertions(+), 8 deletions(-) create mode 100644 sources/Adapters/S60/S60Audio.cpp create mode 100644 sources/Adapters/S60/S60Audio.h create mode 100644 sources/Adapters/S60/S60AudioDriver.cpp create mode 100644 sources/Adapters/S60/S60AudioDriver.h diff --git a/projects/Makefile b/projects/Makefile index 3fb1511a..00c6d798 100644 --- a/projects/Makefile +++ b/projects/Makefile @@ -181,7 +181,6 @@ COMMONDIRS := ../sources/System/Console \ S60DIRS := ../sources/Adapters/Unix/FileSystem \ ../sources/System/Process \ - ../sources/Adapters/SDL/Audio \ ../sources/Adapters/Dummy/Midi \ ../sources/Adapters/Unix/Process \ ../sources/Adapters/SDL/GUI \ @@ -311,9 +310,9 @@ GP2XFILES := GPSDLMain.o \ S60FILES := UnixFileSystem.o \ DummyMidi.o \ - SDLAudio.o \ + S60Audio.o \ + S60AudioDriver.o \ Process.o \ - SDLAudioDriver.o \ UnixProcess.o \ SDLTimer.o \ GUIFactory.o \ diff --git a/projects/s60/mmpheader b/projects/s60/mmpheader index a83506de..15093957 100644 --- a/projects/s60/mmpheader +++ b/projects/s60/mmpheader @@ -42,12 +42,13 @@ library euser.lib library fbscli.lib library hal.lib library mediaclientaudiostream.lib +library mmfdevsound.lib library ws32.lib library centralrepository.lib library remconcoreapi.lib library remconinterfacebase.lib -capability ReadUserData WriteUserData +capability ReadUserData WriteUserData MultimediaDD userinclude ../sources userinclude ../sources/System/System diff --git a/sources/Adapters/S60/S60Audio.cpp b/sources/Adapters/S60/S60Audio.cpp new file mode 100644 index 00000000..178ec6c3 --- /dev/null +++ b/sources/Adapters/S60/S60Audio.cpp @@ -0,0 +1,31 @@ +#include "S60Audio.h" +#include "S60AudioDriver.h" +#include "Services/Audio/AudioOutDriver.h" +#include "System/Console/Trace.h" + +S60Audio::S60Audio(AudioSettings &settings):Audio(settings), + sampleRate_(44100) +{ +} + +S60Audio::~S60Audio() { +} + +void S60Audio::Init() { + S60AudioDriver *drv=new S60AudioDriver(settings_) ; + AudioOutDriver *out=new AudioOutDriver(*drv) ; + Insert(out) ; + sampleRate_=drv->GetSampleRate() ; +} ; + +void S60Audio::Close() { + IteratorPtrit(GetIterator()) ; + for (it->Begin();!it->IsDone();it->Next()) { + AudioOut ¤t=it->CurrentItem() ; + current.Close() ; + } +} ; + +int S60Audio::GetSampleRate() { + return sampleRate_ ; +} ; diff --git a/sources/Adapters/S60/S60Audio.h b/sources/Adapters/S60/S60Audio.h new file mode 100644 index 00000000..7ba49561 --- /dev/null +++ b/sources/Adapters/S60/S60Audio.h @@ -0,0 +1,16 @@ +#ifndef _S60AUDIO_H_ +#define _S60AUDIO_H_ + +#include "Services/Audio/Audio.h" + +class S60Audio: public Audio { +public: + S60Audio(AudioSettings &settings) ; + ~S60Audio() ; + virtual void Init() ; + virtual void Close() ; + virtual int GetSampleRate() ; +private: + int sampleRate_ ; +}; +#endif diff --git a/sources/Adapters/S60/S60AudioDriver.cpp b/sources/Adapters/S60/S60AudioDriver.cpp new file mode 100644 index 00000000..312364f6 --- /dev/null +++ b/sources/Adapters/S60/S60AudioDriver.cpp @@ -0,0 +1,91 @@ +#include "S60AudioDriver.h" +#include +#include "System/Console/Trace.h" +#include "System/System/System.h" +#include "Services/Midi/MidiService.h" +#include + +S60AudioDriver::S60AudioDriver(AudioSettings &settings):AudioDriver(settings) { +} + +S60AudioDriver::~S60AudioDriver() { +} + +bool S60AudioDriver::InitDriver() { + return true; +} + +void S60AudioDriver::CloseDriver() { + +} ; + +bool S60AudioDriver::StartDriver() { + streamTime_=0 ; + thread_=new S60AudioDriverThread(this) ; + thread_->Start() ; + return true ; +} ; + +void S60AudioDriver::StopDriver() { +} ; + +double S60AudioDriver::GetStreamTime() { + return streamTime_ ; +} ; + +bool S60AudioDriverThread::Execute() { + CActiveScheduler* activeScheduler = new (ELeave) CActiveScheduler; + CleanupStack::PushL(activeScheduler); + CActiveScheduler::Install(activeScheduler); + dev = CMMFDevSound::NewL(); + dev->InitializeL(*this, KMMFFourCCCodePCM16, EMMFStatePlaying); + CActiveScheduler::Start(); + CleanupStack::PopAndDestroy(activeScheduler); + return true; +} + +void S60AudioDriverThread::RequestTermination() { +} + +void S60AudioDriverThread::InitializeComplete(TInt aError) { + TInt err; + TMMFPrioritySettings pri; + pri.iPref = EMdaPriorityPreferenceTimeAndQuality; + pri.iPriority = EMdaPriorityMax; + TRAP(err, dev->SetPrioritySettings(pri)); + TMMFCapabilities caps = dev->Config(); + caps.iChannels = EMMFStereo; + caps.iEncoding = EMMFSoundEncoding16BitPCM; + caps.iRate = EMMFSampleRate44100Hz; + caps.iBufferSize = 0; + TRAP(err, dev->SetConfigL(caps)); + TRAP(err, dev->PlayInitL()); +} ; + +void S60AudioDriver::FillBuffer(CMMFBuffer *aBuffer, FILE *fp) { + CMMFDataBuffer *buf = static_cast(aBuffer); + TDes8 &output = buf->Data(); + AudioBufferData *abd = &(pool_[poolPlayPosition_]); + if (!abd->size_) { + OnNewBufferNeeded(); + while (!abd->size_); // XXX spinning! + } + output.Copy((TUint8*)abd->buffer_, abd->size_); + streamTime_ += abd->size_ / (2*44100); + SAFE_FREE(pool_[poolPlayPosition_].buffer_); + poolPlayPosition_=(poolPlayPosition_+1)%SOUND_BUFFER_COUNT; + output.SetLength(abd->size_); + + onAudioBufferTick(); + OnNewBufferNeeded(); +} + +void S60AudioDriverThread::BufferToBeFilled(CMMFBuffer *aBuffer) { + driver->FillBuffer(aBuffer, fp); + dev->EmptyBuffers(); + TInt err; + TRAP(err, dev->PlayData()); +} + +void S60AudioDriverThread::PlayError(TInt aError) { +} diff --git a/sources/Adapters/S60/S60AudioDriver.h b/sources/Adapters/S60/S60AudioDriver.h new file mode 100644 index 00000000..298fa26f --- /dev/null +++ b/sources/Adapters/S60/S60AudioDriver.h @@ -0,0 +1,55 @@ +#ifndef _S60_SOUND_H_ +#define _S60_SOUND_H_ + +#include "Services/Audio/AudioDriver.h" +#include "System/Process/Process.h" +#include "Foundation/T_Stack.h" +#define Time E32Time +#include +#undef Time + +#include // XXX + +class S60AudioDriver; + +class S60AudioDriverThread: public SysThread, MDevSoundObserver { +public: + S60AudioDriverThread(S60AudioDriver *driver) : driver(driver) {}; + virtual ~S60AudioDriverThread() {} ; + virtual bool Execute() ; + void RequestTermination() ; + +public: // From MDevSoundObserver + void InitializeComplete(TInt aError); + void ToneFinished(TInt aError) {}; + void BufferToBeFilled(CMMFBuffer* aBuffer); + void PlayError(TInt aError); + void BufferToBeEmptied(CMMFBuffer *aBuffer) {}; + void RecordError(TInt aError) {}; + void ConvertError(TInt aError) {}; + void DeviceMessage(TUid aMessageType, const TDesC8 &aMsg) {}; + +private: + CMMFDevSound *dev; + S60AudioDriver *driver; +} ; + +class S60AudioDriver: public AudioDriver { +public: + S60AudioDriver(AudioSettings &settings) ; + ~S60AudioDriver() ; + // Audio implementation + virtual bool InitDriver() ; + virtual void CloseDriver(); + virtual bool StartDriver() ; + virtual void StopDriver(); + virtual int GetPlayedBufferPercentage() { return 0 ;} ; + virtual int GetSampleRate() { return 44100; } ; + virtual bool Interlaced() { return true ; } ; + virtual double GetStreamTime() ; + + void FillBuffer(CMMFBuffer *aBuffer, FILE *fp); +private: + double streamTime_ ; +} ; +#endif diff --git a/sources/Adapters/S60/System/S60System.cpp b/sources/Adapters/S60/System/S60System.cpp index e0b70d4e..ae67cdca 100644 --- a/sources/Adapters/S60/System/S60System.cpp +++ b/sources/Adapters/S60/System/S60System.cpp @@ -4,7 +4,7 @@ #include "Adapters/SDL/GUI/SDLGUIWindowImp.h" #include "Adapters/SDL/GUI/SDLEventManager.h" #include "Adapters/Unix/Process/UnixProcess.h" -#include "Adapters/SDL/Audio/SDLAudio.h" +#include "Adapters/S60/S60Audio.h" #include "Adapters/Dummy/Midi/DummyMidi.h" #include "Externals/TinyXML/tinyxml.h" #include "Application/Model/Config.h" @@ -58,9 +58,7 @@ void S60System::Boot(int argc,char **argv) { // Install Sound AudioSettings hints ; - hints.bufferSize_=1024 ; - hints.preBufferCount_=8 ; - Audio::Install(new SDLAudio(hints)) ; + Audio::Install(new S60Audio(hints)) ; // Install Midi MidiService::Install(new DummyMidi()) ; From 883e8eb7b02014996c92ac05b3642e6c2382e528 Mon Sep 17 00:00:00 2001 From: James Laird-Wah Date: Wed, 19 Aug 2015 23:44:16 +1000 Subject: [PATCH 10/16] S60: fix SVG icon pixelation --- sources/Resources/lgpt_icon.svg | 619 +++++--------------------------- 1 file changed, 94 insertions(+), 525 deletions(-) diff --git a/sources/Resources/lgpt_icon.svg b/sources/Resources/lgpt_icon.svg index 45054df7..ef544d08 100644 --- a/sources/Resources/lgpt_icon.svg +++ b/sources/Resources/lgpt_icon.svg @@ -1,526 +1,95 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + From c8afea7e44b3591d0fba91d476e0b5df2fa63baa Mon Sep 17 00:00:00 2001 From: James Laird-Wah Date: Thu, 20 Aug 2015 00:13:52 +1000 Subject: [PATCH 11/16] S60: fix DevSound commit --- sources/Adapters/S60/S60AudioDriver.cpp | 15 ++++++++++----- sources/Adapters/S60/S60AudioDriver.h | 16 ++++++++-------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/sources/Adapters/S60/S60AudioDriver.cpp b/sources/Adapters/S60/S60AudioDriver.cpp index 312364f6..ed51067a 100644 --- a/sources/Adapters/S60/S60AudioDriver.cpp +++ b/sources/Adapters/S60/S60AudioDriver.cpp @@ -20,7 +20,6 @@ void S60AudioDriver::CloseDriver() { } ; bool S60AudioDriver::StartDriver() { - streamTime_=0 ; thread_=new S60AudioDriverThread(this) ; thread_->Start() ; return true ; @@ -29,8 +28,14 @@ bool S60AudioDriver::StartDriver() { void S60AudioDriver::StopDriver() { } ; +double S60AudioDriverThread::GetStreamTime() { + return streamTime_; +} + double S60AudioDriver::GetStreamTime() { - return streamTime_ ; + if (!thread_) + return 0; + return thread_->GetStreamTime() ; } ; bool S60AudioDriverThread::Execute() { @@ -62,7 +67,7 @@ void S60AudioDriverThread::InitializeComplete(TInt aError) { TRAP(err, dev->PlayInitL()); } ; -void S60AudioDriver::FillBuffer(CMMFBuffer *aBuffer, FILE *fp) { +void S60AudioDriver::FillBuffer(CMMFBuffer *aBuffer) { CMMFDataBuffer *buf = static_cast(aBuffer); TDes8 &output = buf->Data(); AudioBufferData *abd = &(pool_[poolPlayPosition_]); @@ -71,7 +76,6 @@ void S60AudioDriver::FillBuffer(CMMFBuffer *aBuffer, FILE *fp) { while (!abd->size_); // XXX spinning! } output.Copy((TUint8*)abd->buffer_, abd->size_); - streamTime_ += abd->size_ / (2*44100); SAFE_FREE(pool_[poolPlayPosition_].buffer_); poolPlayPosition_=(poolPlayPosition_+1)%SOUND_BUFFER_COUNT; output.SetLength(abd->size_); @@ -81,10 +85,11 @@ void S60AudioDriver::FillBuffer(CMMFBuffer *aBuffer, FILE *fp) { } void S60AudioDriverThread::BufferToBeFilled(CMMFBuffer *aBuffer) { - driver->FillBuffer(aBuffer, fp); + driver->FillBuffer(aBuffer); dev->EmptyBuffers(); TInt err; TRAP(err, dev->PlayData()); + streamTime_ = dev->SamplesPlayed() / 44100; } void S60AudioDriverThread::PlayError(TInt aError) { diff --git a/sources/Adapters/S60/S60AudioDriver.h b/sources/Adapters/S60/S60AudioDriver.h index 298fa26f..599ed324 100644 --- a/sources/Adapters/S60/S60AudioDriver.h +++ b/sources/Adapters/S60/S60AudioDriver.h @@ -8,16 +8,15 @@ #include #undef Time -#include // XXX - class S60AudioDriver; class S60AudioDriverThread: public SysThread, MDevSoundObserver { public: - S60AudioDriverThread(S60AudioDriver *driver) : driver(driver) {}; - virtual ~S60AudioDriverThread() {} ; - virtual bool Execute() ; - void RequestTermination() ; + S60AudioDriverThread(S60AudioDriver *driver) : driver(driver) {}; + virtual ~S60AudioDriverThread() {} ; + virtual bool Execute() ; + void RequestTermination() ; + double GetStreamTime() ; public: // From MDevSoundObserver void InitializeComplete(TInt aError); @@ -32,6 +31,7 @@ class S60AudioDriverThread: public SysThread, MDevSoundObserver { private: CMMFDevSound *dev; S60AudioDriver *driver; + double streamTime_ ; } ; class S60AudioDriver: public AudioDriver { @@ -48,8 +48,8 @@ class S60AudioDriver: public AudioDriver { virtual bool Interlaced() { return true ; } ; virtual double GetStreamTime() ; - void FillBuffer(CMMFBuffer *aBuffer, FILE *fp); + void FillBuffer(CMMFBuffer *aBuffer); private: - double streamTime_ ; + S60AudioDriverThread * thread_ ; } ; #endif From fb5e29d20fb3a265f18c1cdfa58aea249a6702e5 Mon Sep 17 00:00:00 2001 From: James Laird-Wah Date: Thu, 20 Aug 2015 15:21:59 +1000 Subject: [PATCH 12/16] S60: take a better stab at an icon Still has some bleed around the edge but at least it's not horrible. --- sources/Resources/lgpt_icon.svg | 103 +++----------------------------- 1 file changed, 9 insertions(+), 94 deletions(-) diff --git a/sources/Resources/lgpt_icon.svg b/sources/Resources/lgpt_icon.svg index ef544d08..8e17a565 100644 --- a/sources/Resources/lgpt_icon.svg +++ b/sources/Resources/lgpt_icon.svg @@ -1,95 +1,10 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - + + + + + + + + + From 93d11e7d4813e0edf74f8c4a7e9d8cf560290534 Mon Sep 17 00:00:00 2001 From: James Laird-Wah Date: Thu, 20 Aug 2015 15:22:52 +1000 Subject: [PATCH 13/16] S60: thread priority & naming --- sources/Adapters/S60/S60AudioDriver.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sources/Adapters/S60/S60AudioDriver.cpp b/sources/Adapters/S60/S60AudioDriver.cpp index ed51067a..0141c25c 100644 --- a/sources/Adapters/S60/S60AudioDriver.cpp +++ b/sources/Adapters/S60/S60AudioDriver.cpp @@ -39,6 +39,14 @@ double S60AudioDriver::GetStreamTime() { } ; bool S60AudioDriverThread::Execute() { + _LIT(KThreadName,"lgpt_audio_thread"); + TPtrC threadname(KThreadName); + User::RenameThread(threadname); + + RProcess cur_process; + cur_process.SetPriority(EPriorityHigh); + RThread cur_thread; + cur_thread.SetPriority(EPriorityAbsoluteHigh); CActiveScheduler* activeScheduler = new (ELeave) CActiveScheduler; CleanupStack::PushL(activeScheduler); CActiveScheduler::Install(activeScheduler); From 24536d908f2bf8a533b18bd1a1c4d20a88d27b73 Mon Sep 17 00:00:00 2001 From: James Laird-Wah Date: Thu, 20 Aug 2015 15:24:04 +1000 Subject: [PATCH 14/16] S60: push smaller audio chunks into driver --- sources/Adapters/S60/S60AudioDriver.cpp | 28 ++++++++++++++++--------- sources/Adapters/S60/S60AudioDriver.h | 3 ++- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/sources/Adapters/S60/S60AudioDriver.cpp b/sources/Adapters/S60/S60AudioDriver.cpp index 0141c25c..41ae1ec7 100644 --- a/sources/Adapters/S60/S60AudioDriver.cpp +++ b/sources/Adapters/S60/S60AudioDriver.cpp @@ -75,21 +75,29 @@ void S60AudioDriverThread::InitializeComplete(TInt aError) { TRAP(err, dev->PlayInitL()); } ; -void S60AudioDriver::FillBuffer(CMMFBuffer *aBuffer) { +int S60AudioDriver::FillBuffer(CMMFBuffer *aBuffer) { CMMFDataBuffer *buf = static_cast(aBuffer); TDes8 &output = buf->Data(); AudioBufferData *abd = &(pool_[poolPlayPosition_]); if (!abd->size_) { OnNewBufferNeeded(); - while (!abd->size_); // XXX spinning! + while (!abd->size_) + User::After(1000); } - output.Copy((TUint8*)abd->buffer_, abd->size_); - SAFE_FREE(pool_[poolPlayPosition_].buffer_); - poolPlayPosition_=(poolPlayPosition_+1)%SOUND_BUFFER_COUNT; - output.SetLength(abd->size_); - - onAudioBufferTick(); - OnNewBufferNeeded(); + int nplayed = abd->size_ - bufpos_; + if (nplayed > 200*4) + nplayed = 200*4; + output.Copy((TUint8*)abd->buffer_ + bufpos_, nplayed); + bufpos_ += nplayed; + if (bufpos_ >= abd->size_) { + bufpos_ = 0; + SAFE_FREE(pool_[poolPlayPosition_].buffer_); + poolPlayPosition_=(poolPlayPosition_+1)%SOUND_BUFFER_COUNT; + onAudioBufferTick(); + OnNewBufferNeeded(); + } + output.SetLength(nplayed); + return nplayed / 4; } void S60AudioDriverThread::BufferToBeFilled(CMMFBuffer *aBuffer) { @@ -97,7 +105,7 @@ void S60AudioDriverThread::BufferToBeFilled(CMMFBuffer *aBuffer) { dev->EmptyBuffers(); TInt err; TRAP(err, dev->PlayData()); - streamTime_ = dev->SamplesPlayed() / 44100; + streamTime_ = dev->SamplesPlayed() / 44100.; } void S60AudioDriverThread::PlayError(TInt aError) { diff --git a/sources/Adapters/S60/S60AudioDriver.h b/sources/Adapters/S60/S60AudioDriver.h index 599ed324..b9b867bb 100644 --- a/sources/Adapters/S60/S60AudioDriver.h +++ b/sources/Adapters/S60/S60AudioDriver.h @@ -32,6 +32,7 @@ class S60AudioDriverThread: public SysThread, MDevSoundObserver { CMMFDevSound *dev; S60AudioDriver *driver; double streamTime_ ; + int bufpos_; } ; class S60AudioDriver: public AudioDriver { @@ -48,7 +49,7 @@ class S60AudioDriver: public AudioDriver { virtual bool Interlaced() { return true ; } ; virtual double GetStreamTime() ; - void FillBuffer(CMMFBuffer *aBuffer); + int FillBuffer(CMMFBuffer *aBuffer); private: S60AudioDriverThread * thread_ ; } ; From 27c0dcc208359d3d2a613e8c3e97c80f55badc76 Mon Sep 17 00:00:00 2001 From: James Laird-Wah Date: Thu, 20 Aug 2015 15:24:41 +1000 Subject: [PATCH 15/16] S60: start sandbagging to keep latency down Depending on the driver, there is little or no control about the output buffer size. This adds up to several hundred milliseconds on my test phone (Nokia E63). This patch adds a delay before submitting samples for playing. If the system's output counter is too far behind the submitted samples, it waits until it isn't. This allows some measure of control over the invisible buffers. Of course, this introduces a magic value for the lag tolerance. Setting it too low causes glitches. These tend to be evenly periodic - so maybe rejigging things to submit (say) precisely 256 samples a throw would allow pushing this further. --- sources/Adapters/S60/S60AudioDriver.cpp | 14 ++++++++++++-- sources/Adapters/S60/S60AudioDriver.h | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/sources/Adapters/S60/S60AudioDriver.cpp b/sources/Adapters/S60/S60AudioDriver.cpp index 41ae1ec7..f54d64ae 100644 --- a/sources/Adapters/S60/S60AudioDriver.cpp +++ b/sources/Adapters/S60/S60AudioDriver.cpp @@ -72,6 +72,7 @@ void S60AudioDriverThread::InitializeComplete(TInt aError) { caps.iRate = EMMFSampleRate44100Hz; caps.iBufferSize = 0; TRAP(err, dev->SetConfigL(caps)); + samples_pushed = 0; TRAP(err, dev->PlayInitL()); } ; @@ -101,8 +102,17 @@ int S60AudioDriver::FillBuffer(CMMFBuffer *aBuffer) { } void S60AudioDriverThread::BufferToBeFilled(CMMFBuffer *aBuffer) { - driver->FillBuffer(aBuffer); - dev->EmptyBuffers(); + samples_pushed += driver->FillBuffer(aBuffer); + + // This is a filthy hack to reduce the amount of buffering (which we can't control) supplied by the OS. + // Once the output sample comes up, we start sandbagging to let that buffer drain. + // This is a terrible magic number. + if (dev->SamplesPlayed()) { + while (dev->SamplesPlayed() < (samples_pushed - 10000)) { + User::After(1); + } + } + TInt err; TRAP(err, dev->PlayData()); streamTime_ = dev->SamplesPlayed() / 44100.; diff --git a/sources/Adapters/S60/S60AudioDriver.h b/sources/Adapters/S60/S60AudioDriver.h index b9b867bb..a5d591e6 100644 --- a/sources/Adapters/S60/S60AudioDriver.h +++ b/sources/Adapters/S60/S60AudioDriver.h @@ -32,6 +32,7 @@ class S60AudioDriverThread: public SysThread, MDevSoundObserver { CMMFDevSound *dev; S60AudioDriver *driver; double streamTime_ ; + int samples_pushed; int bufpos_; } ; From 0cf5f1d1e39f7d9ac2e6de25ab30654e49bbb7fb Mon Sep 17 00:00:00 2001 From: James Laird-Wah Date: Sun, 23 Aug 2015 00:06:21 +1000 Subject: [PATCH 16/16] S60: Sound working well. --- projects/s60/mmpheader | 2 +- sources/Adapters/S60/S60AudioDriver.cpp | 72 +++++++++++++---------- sources/Adapters/S60/S60AudioDriver.h | 17 ++++-- sources/Adapters/S60/System/S60System.cpp | 26 ++++---- 4 files changed, 66 insertions(+), 51 deletions(-) diff --git a/projects/s60/mmpheader b/projects/s60/mmpheader index 15093957..26785652 100644 --- a/projects/s60/mmpheader +++ b/projects/s60/mmpheader @@ -48,7 +48,7 @@ library centralrepository.lib library remconcoreapi.lib library remconinterfacebase.lib -capability ReadUserData WriteUserData MultimediaDD +capability ReadUserData WriteUserData userinclude ../sources userinclude ../sources/System/System diff --git a/sources/Adapters/S60/S60AudioDriver.cpp b/sources/Adapters/S60/S60AudioDriver.cpp index f54d64ae..d019de93 100644 --- a/sources/Adapters/S60/S60AudioDriver.cpp +++ b/sources/Adapters/S60/S60AudioDriver.cpp @@ -2,10 +2,16 @@ #include #include "System/Console/Trace.h" #include "System/System/System.h" -#include "Services/Midi/MidiService.h" +#include "Application/Model/Config.h" #include -S60AudioDriver::S60AudioDriver(AudioSettings &settings):AudioDriver(settings) { +S60AudioDriver::S60AudioDriver(AudioSettings &settings): + AudioDriver(settings), buffersize_(settings.bufferSize_){ + const char *delta = Config::GetInstance()->GetValue("S60SANDBAGDELTA"); + if (delta) + sandbagdelta_ = atoi(delta); + else + sandbagdelta_ = 11500; // works reliably on Nokia E63 w/ fw 500.x } S60AudioDriver::~S60AudioDriver() { @@ -13,19 +19,19 @@ S60AudioDriver::~S60AudioDriver() { bool S60AudioDriver::InitDriver() { return true; -} +} void S60AudioDriver::CloseDriver() { - } ; bool S60AudioDriver::StartDriver() { - thread_=new S60AudioDriverThread(this) ; + thread_=new S60AudioDriverThread(this, bufferSize_, sandbagdelta_) ; thread_->Start() ; return true ; -} ; +} ; void S60AudioDriver::StopDriver() { + thread_->RequestTermination(); } ; double S60AudioDriverThread::GetStreamTime() { @@ -58,6 +64,7 @@ bool S60AudioDriverThread::Execute() { } void S60AudioDriverThread::RequestTermination() { + terminating = true; } void S60AudioDriverThread::InitializeComplete(TInt aError) { @@ -70,52 +77,53 @@ void S60AudioDriverThread::InitializeComplete(TInt aError) { caps.iChannels = EMMFStereo; caps.iEncoding = EMMFSoundEncoding16BitPCM; caps.iRate = EMMFSampleRate44100Hz; - caps.iBufferSize = 0; + caps.iBufferSize = buffersize_; TRAP(err, dev->SetConfigL(caps)); samples_pushed = 0; TRAP(err, dev->PlayInitL()); -} ; +} ; int S60AudioDriver::FillBuffer(CMMFBuffer *aBuffer) { - CMMFDataBuffer *buf = static_cast(aBuffer); - TDes8 &output = buf->Data(); AudioBufferData *abd = &(pool_[poolPlayPosition_]); - if (!abd->size_) { - OnNewBufferNeeded(); - while (!abd->size_) - User::After(1000); - } - int nplayed = abd->size_ - bufpos_; - if (nplayed > 200*4) - nplayed = 200*4; - output.Copy((TUint8*)abd->buffer_ + bufpos_, nplayed); - bufpos_ += nplayed; - if (bufpos_ >= abd->size_) { - bufpos_ = 0; - SAFE_FREE(pool_[poolPlayPosition_].buffer_); - poolPlayPosition_=(poolPlayPosition_+1)%SOUND_BUFFER_COUNT; - onAudioBufferTick(); + if (!abd->size_) OnNewBufferNeeded(); - } - output.SetLength(nplayed); - return nplayed / 4; + + CMMFDataBuffer *buf = static_cast(aBuffer); + TDes8 &output = buf->Data(); + output.Copy((TUint8*)abd->buffer_, abd->size_); + return abd->size_ / 4; +} + +void S60AudioDriver::NextBuffer() { + SAFE_FREE(pool_[poolPlayPosition_].buffer_); + poolPlayPosition_=(poolPlayPosition_+1)%SOUND_BUFFER_COUNT; + onAudioBufferTick(); + OnNewBufferNeeded(); } void S60AudioDriverThread::BufferToBeFilled(CMMFBuffer *aBuffer) { + if (terminating) { + dev->Stop(); + CActiveScheduler::Stop(); + return; + } + samples_pushed += driver->FillBuffer(aBuffer); // This is a filthy hack to reduce the amount of buffering (which we can't control) supplied by the OS. - // Once the output sample comes up, we start sandbagging to let that buffer drain. + // Once the output sample counter comes up, we start sandbagging to let that buffer drain. // This is a terrible magic number. - if (dev->SamplesPlayed()) { - while (dev->SamplesPlayed() < (samples_pushed - 10000)) { - User::After(1); + if (sandbagdelta_ && dev->SamplesPlayed()) { + while (dev->SamplesPlayed() < (samples_pushed - sandbagdelta_)) { + User::After(100); } } TInt err; TRAP(err, dev->PlayData()); + User::After(100); // yield streamTime_ = dev->SamplesPlayed() / 44100.; + driver->NextBuffer(); } void S60AudioDriverThread::PlayError(TInt aError) { diff --git a/sources/Adapters/S60/S60AudioDriver.h b/sources/Adapters/S60/S60AudioDriver.h index a5d591e6..bca11252 100644 --- a/sources/Adapters/S60/S60AudioDriver.h +++ b/sources/Adapters/S60/S60AudioDriver.h @@ -12,7 +12,11 @@ class S60AudioDriver; class S60AudioDriverThread: public SysThread, MDevSoundObserver { public: - S60AudioDriverThread(S60AudioDriver *driver) : driver(driver) {}; + S60AudioDriverThread(S60AudioDriver *driver, int buffersize, int sandbagdelta) + : driver(driver), + terminating(false), + buffersize_(buffersize), + sandbagdelta_(sandbagdelta) {}; virtual ~S60AudioDriverThread() {} ; virtual bool Execute() ; void RequestTermination() ; @@ -33,7 +37,8 @@ class S60AudioDriverThread: public SysThread, MDevSoundObserver { S60AudioDriver *driver; double streamTime_ ; int samples_pushed; - int bufpos_; + bool terminating; + int buffersize_, sandbagdelta_; } ; class S60AudioDriver: public AudioDriver { @@ -41,17 +46,19 @@ class S60AudioDriver: public AudioDriver { S60AudioDriver(AudioSettings &settings) ; ~S60AudioDriver() ; // Audio implementation - virtual bool InitDriver() ; + virtual bool InitDriver() ; virtual void CloseDriver(); - virtual bool StartDriver() ; + virtual bool StartDriver() ; virtual void StopDriver(); virtual int GetPlayedBufferPercentage() { return 0 ;} ; - virtual int GetSampleRate() { return 44100; } ; + virtual int GetSampleRate() { return 44100; } ; virtual bool Interlaced() { return true ; } ; virtual double GetStreamTime() ; int FillBuffer(CMMFBuffer *aBuffer); + void NextBuffer(); private: S60AudioDriverThread * thread_ ; + int buffersize_, sandbagdelta_; } ; #endif diff --git a/sources/Adapters/S60/System/S60System.cpp b/sources/Adapters/S60/System/S60System.cpp index ae67cdca..b66f5aae 100644 --- a/sources/Adapters/S60/System/S60System.cpp +++ b/sources/Adapters/S60/System/S60System.cpp @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #define Time E32Time @@ -33,12 +33,13 @@ int S60System::MainLoop() { } ; void S60System::Boot(int argc,char **argv) { - // Install System System::Install(new S60System()) ; // Install FileSystem FileSystem::Install(new UnixFileSystem()) ; + Path::SetAlias("root","c:/data/lgpt") ; + Path::SetAlias("bin","c:/data/lgpt") ; Config::GetInstance()->ProcessArguments(argc,argv) ; // XXX debug to SD card @@ -47,7 +48,7 @@ void S60System::Boot(int argc,char **argv) { FileLogger *fileLogger=new FileLogger(logPath); if(fileLogger->Init().Succeeded()) { - Trace::GetInstance()->SetLogger(*fileLogger); + Trace::GetInstance()->SetLogger(*fileLogger); } // Install GUI Factory @@ -58,6 +59,8 @@ void S60System::Boot(int argc,char **argv) { // Install Sound AudioSettings hints ; + hints.bufferSize_=0 ; // let OS autosize (ignored on many) + hints.preBufferCount_=0 ; // does nothing Audio::Install(new S60Audio(hints)) ; // Install Midi MidiService::Install(new DummyMidi()) ; @@ -65,12 +68,9 @@ void S60System::Boot(int argc,char **argv) { // Install Threads SysProcessFactory::Install(new UnixProcessFactory()) ; - // XXX this conflicts with the SDLEventManager - if ( SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0 ) { + if ( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0 ) { return; } - Path::SetAlias("root","c:/data/lgpt") ; - Path::SetAlias("bin","c:/data/lgpt") ; SDL_EnableUNICODE(1); @@ -96,12 +96,12 @@ void S60System::Shutdown() { exit(0); } ; -static int secbase; +static int secbase; unsigned long S60System::GetClock() { struct timeval tp; - gettimeofday(&tp, NULL); + gettimeofday(&tp, NULL); if (!secbase) { secbase = tp.tv_sec; @@ -125,11 +125,11 @@ void *S60System::Malloc(unsigned size) { void S60System::Free(void *ptr) { free(ptr) ; -} +} //extern "C" void *gpmemset(void *s1,unsigned char val,int n) ; -void S60System::Memset(void *addr,char val,int size) +void S60System::Memset(void *addr,char val,int size) { memset(addr,val,size) ; } ; @@ -139,13 +139,13 @@ void *S60System::Memcpy(void *s1, const void *s2, int n) return memcpy(s1,s2,n); } -void S60System::PostQuitMessage() +void S60System::PostQuitMessage() { Trace::Log("S60", "PostQuitMessage called"); SDLEventManager::GetInstance()->PostQuitMessage() ; } -unsigned int S60System::GetMemoryUsage() +unsigned int S60System::GetMemoryUsage() { return 0; }