{* UltraStar Deluxe - Karaoke Game * * UltraStar Deluxe is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $URL$ * $Id$ *} unit UMediaPlugin; interface {$IFDEF FPC} {$MODE DELPHI } {$PACKENUM 4} (* use 4-byte enums *) {$PACKRECORDS C} (* C/C++-compatible record packing *) {$ELSE} {$MINENUMSIZE 4} (* use 4-byte enums *) {$ENDIF} uses ctypes; type PFileStream = Pointer; PThread = Pointer; PMutex = Pointer; PCond = Pointer; PMediaPluginCore = ^TMediaPluginCore; TMediaPluginCore = record version: cint; log: procedure(level: cint; msg: PChar; context: PChar); cdecl; ticksMillis: function(): cuint32; cdecl; fileOpen: function(utf8Filename: PAnsiChar; mode: cint): PFileStream; cdecl; fileClose: procedure(stream: PFileStream); cdecl; fileRead: function(stream: PFileStream; buf: PCuint8; size: cint): cint64; cdecl; fileWrite: function(stream: PFileStream; buf: PCuint8; size: cint): cint64; cdecl; fileSeek: function(stream: PFileStream; pos: cint64; whence: cint): cint64; cdecl; fileSize: function(stream: PFileStream): cint64; cdecl; threadCreate: function(func: Pointer; data: Pointer): PThread; cdecl; threadCurrentID: function(): cuint32; cdecl; threadGetID: function(thread: PThread): cuint32; cdecl; threadWait: procedure(thread: PThread; status: PCint); cdecl; threadSleep: procedure(millisecs: cuint32); cdecl; mutexCreate: function(): PMutex; cdecl; mutexDestroy: procedure(mutex: PMutex); cdecl; mutexLock: function(mutex: PMutex): cint; cdecl; mutexUnlock: function(mutex: PMutex): cint; cdecl; condCreate: function(): PCond; cdecl; condDestroy: procedure(cond: PCond); cdecl; condSignal: function(cond: PCond): cint; cdecl; condBroadcast: function(cond: PCond): cint; cdecl; condWait: function(cond: PCond; mutex: PMutex): cint; cdecl; condWaitTimeout: function(cond: PCond; mutex: PMutex; ms: cuint32): cint; cdecl; end; PAudioDecodeStream = Pointer; PAudioResampleStream = Pointer; PCAudioFormatInfo = ^TCAudioFormatInfo; TCAudioFormatInfo = record sampleRate: double; channels: cuint8; format: cint; end; PAudioDecoderInfo = ^TAudioDecoderInfo; TAudioDecoderInfo = record open: function(filename: PAnsiChar): PAudioDecodeStream; cdecl; close: procedure(stream: PAudioDecodeStream); cdecl; getLength: function(stream: PAudioDecodeStream): double; cdecl; getAudioFormatInfo: procedure(stream: PAudioDecodeStream; var info: TCAudioFormatInfo); cdecl; getPosition: function(stream: PAudioDecodeStream): double; cdecl; setPosition: procedure(stream: PAudioDecodeStream; time: double); cdecl; getLoop: function(stream: PAudioDecodeStream): cbool; cdecl; setLoop: procedure(stream: PAudioDecodeStream; enabled: cbool); cdecl; isEOF: function(stream: PAudioDecodeStream): cbool; cdecl; isError: function(stream: PAudioDecodeStream): cbool; cdecl; readData: function(stream: PAudioDecodeStream; buffer: PCUint8; bufferSize: cint): cint; cdecl; end; PAudioConverterInfo = ^TAudioConverterInfo; TAudioConverterInfo = record open: function(inputFormat: PCAudioFormatInfo; outputFormat: PCAudioFormatInfo): PAudioResampleStream; cdecl; close: procedure(stream: PAudioResampleStream); cdecl; convert: function(stream: PAudioResampleStream; input, output: PCuint8; numSamples: cint): cint; cdecl; end; PMediaPluginInfo = ^TMediaPluginInfo; TMediaPluginInfo = record version: cint; name: PAnsiChar; initialize: function(): cbool; cdecl; finalize: function(): cbool; cdecl; audioDecoder: PAudioDecoderInfo; audioConverter: PAudioConverterInfo; end; Plugin_register = function(core: PMediaPluginCore): PMediaPluginInfo; cdecl; function MediaPluginCore: PMediaPluginCore; implementation uses SDL, ULog; var MediaPluginCore_Instance: TMediaPluginCore; const DebugLogLevels: array[0 .. 5] of integer = ( LOG_LEVEL_DEBUG, LOG_LEVEL_INFO, LOG_LEVEL_STATUS, LOG_LEVEL_WARN, LOG_LEVEL_ERROR, LOG_LEVEL_CRITICAL ); function MediaPluginCore: PMediaPluginCore; begin Result := @MediaPluginCore_Instance; end; {* Misc *} procedure Core_log(level: cint; msg: PChar; context: PChar); cdecl; begin Log.LogMsg(msg, context, DebugLogLevels[level]); end; function Core_ticksMillis(): cuint32; cdecl; begin Result := SDL_GetTicks(); end; {* File *} function Core_fileOpen(utf8Filename: PChar; mode: cint): PFileStream; cdecl; begin end; procedure Core_fileClose(stream: PFileStream); cdecl; begin end; function Core_fileRead(stream: PFileStream; buf: PCuint8; size: cint): cint64; cdecl; begin end; function Core_fileWrite(stream: PFileStream; buf: PCuint8; size: cint): cint64; cdecl; begin end; function Core_fileSeek(stream: PFileStream; pos: cint64; whence: cint): cint64; cdecl; begin end; function Core_fileSize(stream: PFileStream): cint64; cdecl; begin end; {* Thread *} function Core_threadCreate(func: Pointer; data: Pointer): PThread; cdecl; begin Result := SDL_CreateThread(func, data); end; function Core_threadCurrentID(): cuint32; cdecl; begin Result := SDL_ThreadID(); end; function Core_threadGetID(thread: PThread): cuint32; cdecl; begin Result := SDL_GetThreadID(PSDL_Thread(thread)); end; procedure Core_threadWait(thread: PThread; status: PCint); cdecl; begin SDL_WaitThread(PSDL_Thread(thread), status^); end; procedure Core_threadSleep(millisecs: cuint32); cdecl; begin SDL_Delay(millisecs); end; {* Mutex *} function Core_mutexCreate(): PMutex; cdecl; begin Result := PMutex(SDL_CreateMutex()); end; procedure Core_mutexDestroy(mutex: PMutex); cdecl; begin SDL_DestroyMutex(PSDL_Mutex(mutex)); end; function Core_mutexLock(mutex: PMutex): cint; cdecl; begin Result := SDL_mutexP(PSDL_Mutex(mutex)); end; function Core_mutexUnlock(mutex: PMutex): cint; cdecl; begin Result := SDL_mutexV(PSDL_Mutex(mutex)); end; {* Condition *} function Core_condCreate(): PCond; cdecl; begin Result := PCond(SDL_CreateCond()); end; procedure Core_condDestroy(cond: PCond); cdecl; begin SDL_DestroyCond(PSDL_Cond(cond)); end; function Core_condSignal(cond: PCond): cint; cdecl; begin Result := SDL_CondSignal(PSDL_Cond(cond)); end; function Core_condBroadcast(cond: PCond): cint; cdecl; begin Result := SDL_CondBroadcast(PSDL_Cond(cond)); end; function Core_condWait(cond: PCond; mutex: PMutex): cint; cdecl; begin Result := SDL_CondWait(PSDL_Cond(cond), PSDL_Mutex(mutex)); end; function Core_condWaitTimeout(cond: PCond; mutex: PMutex; ms: cuint32): cint; cdecl; begin Result := SDL_CondWaitTimeout(PSDL_Cond(cond), PSDL_Mutex(mutex), ms); end; procedure InitializeMediaPluginCore; begin with MediaPluginCore_Instance do begin version := 0; log := Core_log; ticksMillis := Core_ticksMillis; fileOpen := Core_fileOpen; fileClose := Core_fileClose; fileRead := Core_fileRead; fileWrite := Core_fileWrite; fileSeek := Core_fileSeek; fileSize := Core_fileSize; threadCreate := Core_threadCreate; threadCurrentID := Core_threadCurrentID; threadGetID := Core_threadGetID; threadWait := Core_threadWait; threadSleep := Core_threadSleep; mutexCreate := Core_mutexCreate; mutexDestroy := Core_mutexDestroy; mutexLock := Core_mutexLock; mutexUnlock := Core_mutexUnlock; condCreate := Core_condCreate; condDestroy := Core_condDestroy; condSignal := Core_condSignal; condBroadcast := Core_condBroadcast; condWait := Core_condWait; condWaitTimeout := Core_condWaitTimeout; end; end; initialization InitializeMediaPluginCore; end.