Squashed commit of the following:

commit 236d02a237fd018880c090b91aa5cf0f2271d382
Merge: 02076e7 a97cd68
Author: baidwwy <313738139@qq.com>
Date:   Mon Mar 22 09:52:28 2021 +0800

    Merge branch 'master' of https://gitee.com/GGELUA/GGELUA into pr_1

    # Conflicts:
    #	source/app/ggelua/main.c
    #	source/lib/ggelua/main.c

commit 02076e7f0e
Author: chenxu <chenxu_unix@163.com>
Date:   Sun Mar 21 22:50:46 2021 +0800

    Android 版本打桩
This commit is contained in:
baidwwy 2021-03-22 10:59:14 +08:00
parent 9a3a6f5309
commit 898779aca9
86 changed files with 12764 additions and 55 deletions

6
.gitignore vendored
View File

@ -1,2 +1,8 @@
dependent/library
.vs
.gradle
.idea
.externalNativeBuild
build
Obj
Bin

View File

@ -1,7 +1,7 @@
--[[
@Author : baidwwy
@Date : 2021-02-08 15:51:46
@LastEditTime : 2021-03-10 10:00:01
@LastEditTime : 2021-03-22 10:31:13
--]]
io.stdout:setvbuf('no',0)
local gge = package.loadlib("ggelua", "luaopen_ggelua")()
@ -12,8 +12,9 @@ local tt = os.clock()
local runpath = getrunpath()
local curpath = getcurpath()--arg[1]
local luafolder = arg[2] or 'lua'
local exetype = arg[3] or 'ggelua.exe'
print(runpath,curpath,luafolder,exetype)
local buildtype = arg[3] or 'ggelua.exe'
print(runpath,curpath,luafolder,buildtype)
package.cpath = ("?.dll;lib/?.dll;!/?.dll;!/lib/?.dll"):gsub('!',runpath)
local lfs = require("lfs")
local cjson = require("cjson.safe")
@ -127,34 +128,44 @@ print('-------------------------------------------------------------')
data = cmsgpack.pack(data)
(runpath.."/lua54.dll","lua54.dll")
(runpath.."/ggelua.dll","ggelua.dll")
if not (runpath.."/"..exetype,"ggelua.exe") then
error('写出失败!')
end
--print(string.packsize("<I4I4I4"))
local file<close> = io.open("ggelua.exe","r+b")
if file then
if file:seek('end',-12) then
local glue = file:read(12)
if glue and #glue==12 then
local sig,s1,s2 = string.unpack("<I4I4I4",glue)
if sig==0x20454747 then
file:seek('end',-(12+s1+s2))
if buildtype == 'android' then
local file<close> = io.open(runpath.."/script.dump","w+b")
if file then
file:write(core)
file:write(data)
file:write(string.pack("<I4I4I4",0x20454747,#core,#data))
else
goto 失败
end
else
(runpath.."/lua54.dll","lua54.dll")
(runpath.."/ggelua.dll","ggelua.dll")
if not (runpath.."/"..buildtype,"ggelua.exe") then
error('写出失败!')
end
--print(string.packsize("<I4I4I4"))
local file<close> = io.open("ggelua.exe","r+b")
if file then
if file:seek('end',-12) then
local glue = file:read(12)
if glue and #glue==12 then
local sig,s1,s2 = string.unpack("<I4I4I4",glue)
if sig==0x20454747 then
file:seek('end',-(12+s1+s2))
end
file:seek('cur')--没有这句,会有奇怪的数据
file:write(core)
file:write(data)
file:write(string.pack("<I4I4I4",0x20454747,#core,#data))
else
goto 失败
end
file:seek('cur')--没有这句,会有奇怪的数据
file:write(core)
file:write(data)
file:write(string.pack("<I4I4I4",0x20454747,#core,#data))
else
goto 失败
end
else
goto 失败
end
else
goto 失败
end
print('编译完成\n用时:'..os.clock()-tt..'')

View File

@ -13,6 +13,12 @@ local function _检查输入内容(self,c,v)
if not c then
return false
end
--密码模式任意输入
if self._模式&self. == self. then
return true
end
if c>=48 and c<=57 then
return self._模式&self.==self.
elseif c>=65 and c<=90 then--大字字母
@ -209,6 +215,7 @@ function GUI输入:_显示(...)
self._选中精灵:(_x+self._显示偏移,_y)
self._文本精灵:(_x+self._显示偏移,_y)
:()
if self._光标可见 then
_x = _x+self._光标偏移
self._光标精灵:(_x,_y)
@ -297,6 +304,7 @@ function GUI输入:置数值(v)
end
function GUI输入:插入文本(str,p,)
if type(str)=='string' then
--检查输入
local t = {}
@ -375,7 +383,7 @@ function GUI输入:置焦点(v)
if self._输入焦点 ~= v then
self._输入焦点 = v
if v then
if _当前输入焦点 then
if _当前输入焦点 and _当前输入焦点 ~= self then
_当前输入焦点:(false)
end
self._光标可见 = true
@ -386,6 +394,16 @@ function GUI输入:置焦点(v)
self:()
--self:_子消息事件('失去输入焦点')
end
local platform = SDL.GetPlatform()
if platform == 'Android' or platform == 'iOS' then
if v then
SDL.StartTextInput()
else
SDL.StopTextInput()
end
end
end
return self
end
@ -478,6 +496,8 @@ function GUI输入:_消息事件(msg)
if v.clicks==2 then--双击全选
self:()
end
else
self:(false)
end
end
elseif v.type==SDL._移动 then--拖选

View File

@ -0,0 +1,133 @@
-- @作者: baidwwy
-- @邮箱: 313738139@qq.com
-- @创建时间: 2015-11-13 10:12:10
-- @最后修改来自: baidwwy
-- @Last Modified time: 2019-07-19 20:14:10
--==========================================================================================
local PushClient = package.loaded.PushClient or require("HPS/PushClient")
local PullClient = class("PullClient",PushClient)
PullClient._hp = false
PullClient._数据事件 = false
PullClient._准备事件 = false
PullClient._连接事件 = false
PullClient._发送事件 = false
PullClient._断开事件 = false
PullClient. = false
PullClient. = false
PullClient. = false
PullClient. = false
PullClient. = false
local hp_buffer = require "ghpsocket.buffer"
function PullClient:PullClient()
self._hp = require "ghpsocket.pullclient"(self)
self._sendbuf = hp_buffer(14138, 1024 * 1024, 9527)
self._recbuf = hp_buffer(14138, 1024 * 1024, 9527)
local psd = {77,11,22,33,44,55,66,77,88,99,00,69}
self._sendbuf:SetCode(psd)
self._recbuf:SetCode(psd)
end
function PullClient:连接(lpszRemoteAddress,usPort,bAsyncConnect,lpszBindAddress,usLocalPort)--地址,端口,异步
self._info = {
ishead = true,
len = self._recbuf:GetHeaderLen()
}
return self._hp:Start(lpszRemoteAddress,usPort,bAsyncConnect,lpszBindAddress,usLocalPort)
end
function PullClient:发送(...)
--添加数据
self._sendbuf:Reset()
local arg = {...}
for i,v in ipairs(arg) do
if type(v) == 'number' then
self._sendbuf:AddNumber(v)
else
self._sendbuf:AddString(tostring(v))
end
end
self._sendbuf:Finish()
self._hp:Send(self._sendbuf)
end
function PullClient:取连接ID()
return self._hp:GetConnectionID()
end
--准备连接通知
function PullClient:OnPrepareConnect(dwConnID,socket)
if self._准备事件 then
ggexpcall(self._准备事件,self,dwConnID,socket)
elseif self. then
ggexpcall(self.,self,dwConnID,socket)
end
return 0
end
function PullClient:OnConnect(dwConnID)
if self._连接事件 then
ggexpcall(self._连接事件,self,dwConnID)
elseif self. then
ggexpcall(self.,self,dwConnID)
end
return 0
end
--已发送数据通知
function PullClient:OnSend(dwConnID,iLength)
if self._发送事件 then
ggexpcall(self._发送事件,self,dwConnID,iLength)
elseif self. then
ggexpcall(self.,self,dwConnID,iLength)
end
return 1
end
function PullClient:OnReceivePull(dwConnID, iLength)
local required = self._info.len
local remain = iLength
while remain >= required do
remain = remain -required --剩余数据长度
local FR_OK = self._hp:Fetch(self._recbuf,required)
if FR_OK == 0 then
if self._info.ishead then--是否是包头
required = self._recbuf:CheckHeader() --获取包体长度
if required == 0 then --非法数据
self:()
break
end
else
if self. then
ggexpcall(self.,self, dwConnID, unpack(self._recbuf:GetData()))
elseif self._数据事件 and self._数据事件 then
ggexpcall(self._数据事件, dwConnID, unpack(self._recbuf:GetData()))
end
required = self._recbuf:GetHeaderLen()--获取包头长度
end
self._info.ishead = not self._info.ishead
self._info.len = required
else
break
end
end
return 0
end
function PullClient:OnReceivePack(dwConnID, Data)
print("PACK:",#Data)
end
function PullClient:OnClose(dwConnID,enOperation,iErrorCode)
if self._断开事件 then
ggexpcall(self._断开事件 ,self ,dwConnID,enOperation ,iErrorCode)
elseif self. then
ggexpcall(self. ,self ,dwConnID,enOperation ,iErrorCode)
end
return 0
end
return PullClient

View File

@ -717,6 +717,10 @@ function main()
local t = GetEvent(e)
local win = _wins[t.windowID]
if win then
if t.type==0x400 or t.type==0x401 or t.type==0x402 or t.type==0x403 then--鼠标事件
t.x = t.x / win.scale
t.y = t.y / win.scale
end
win:_Event(e,t)
if win:_Event(t.type,unpack(t)) then
return true

View File

@ -25,6 +25,8 @@ function SDL图像:SDL图像(a,b,c,d)
end
elseif ggetype(a) == 'SDL_Surface' then
self._sf = a
elseif ggetype(a) == 'SDL_RWops' then
self._sf = assert(IMG.LoadARGB8888_RW(a), GetError(),2)
-- elseif ggetype(a) == 'SDL_PixelFormat' then
end
if self._sf then

View File

@ -1,7 +1,7 @@
--[[
@Author : baidwwy
@Date : 2021-02-11 11:49:09
@LastEditTime : 2021-03-14 22:38:09
@LastEditTime : 2021-03-22 10:15:57
--]]
local _ENV = require("SDL")
TTF = require("gsdl2.ttf")
@ -14,10 +14,16 @@ function SDL文字:SDL文字(file,size,aliasing,w)
self._anti = aliasing ~=false --抗锯齿
self._w = w --折行宽度
self._size = size or 14
if GetPlatform()=='Windows' then
--Windows Mac OS X Linux iOS Android
local platform = GetPlatform()
if platform =='Windows' then
local rp = os.getenv("SystemRoot")..'/Fonts/'
self._font = assert(TTF.OpenFontIndex(file and rp..file or rp..'simsun.ttc', self._size), GetError(),2)
elseif platform == 'Android' then
self._font = assert(TTF.OpenFontIndex(file or 'simsun.ttc', self._size), GetError(),2)
end
if self._font then
_ttfs[self] = self._font
self:(255,255,255)
@ -149,11 +155,15 @@ function SDL文字:取标志()
end
function SDL文字:置颜色(r,g,b,a)
self._t = nil
self._a = a
self._r = r
self._g = g
self._b = b
if self._r ~= r or self._g ~= g or self._b ~= b or self._a ~= a then
self._t = nil
self._a = a
self._r = r
self._g = g
self._b = b
end
return self
end

View File

@ -98,8 +98,9 @@ end
function SDL渲染:渲染结束()
if self._rd then
if self._tg then
self._tg = nil
self._rd:SetRenderTarget()
self._rd:RenderCopy(self._tg:());
self._tg = nil
end
self._rd:RenderPresent()
else

View File

@ -1,7 +1,7 @@
--[[
@Author : GGELUA
@Date : 2020-11-27 10:05:41
@LastEditTime : 2021-02-25 03:57:31
@LastEditTime : 2021-03-22 10:19:10
--]]
require("GGE")
@ -10,6 +10,32 @@ local SDL = require("SDL")
local SDL窗口 = class('SDL窗口',"SDL渲染")
--移动平台设置设计分辨率
function set_design_resolution_size(win_w, win_h)
local mode = SDL.GetCurrentDisplayMode(0)
if nil == mode then
print("获取窗口模式失败")
return
end
--计算缩放比
local rate = mode.w / mode.h
local drate = win_w / win_h
local scale = 1
if rate > drate then
win_w = math.floor(win_h * mode.w / mode.h)
scale = drate
else
win_h = math.floor(win_w * mode.h / mode.w)
scale = rate
end
return win_w, win_h, scale
end
function SDL窗口:SDL窗口(t)
for k,v in pairs(t) do
if not self[k] then
@ -17,6 +43,13 @@ function SDL窗口:SDL窗口(t)
end
end
--Windows Mac OS X Linux iOS Android
local platform = SDL.GetPlatform()
if platform == 'Android' or platform == 'iOS' then
t. = true
t., t., t.scale = set_design_resolution_size(t., t.)
end
self. = t. or "GGELUA Game Engine"
self. = self.
self. = t. or 800
@ -27,6 +60,7 @@ function SDL窗口:SDL窗口(t)
self.2 = self.//2
self.x = 0
self.y = 0
self.scale = t.scale or 1
--SetHint('SDL_RENDER_DRIVER',"opengl")
--SetHint("SDL_RENDER_DIRECT3D_THREADSAFE","1")--线程安全

View File

@ -24,6 +24,8 @@ local function _载入纹理(rd,a,b,c,d,e)
return assert(rd:CreateTextureFromSurface(a,b or TEXTUREACCESS_STREAMING), GetError(),2)
elseif ggetype(a) == 'SDL图像' and a:() then
return assert(rd:CreateTextureFromSurface(a:(),b or TEXTUREACCESS_STREAMING), GetError(),2)
elseif ggetype(a) == 'SDL_RWops' then
return assert(rd:LoadTexture_RW(a, c or TEXTUREACCESS_STREAMING), GetError(),2)
elseif a~= nil then
error('未知模式',3)
end

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,609 @@
/* ========================================================================================== */
/* FMOD Ex - C++ header file. Copyright (c), Firelight Technologies Pty, Ltd. 2004-2016. */
/* */
/* Use this header in conjunction with fmod.h (which contains all the constants / callbacks) */
/* to develop using C++ classes. */
/* ========================================================================================== */
#ifndef _FMOD_HPP
#define _FMOD_HPP
#include "fmod.h"
/*
Constant and defines
*/
/*
FMOD Namespace
*/
namespace FMOD
{
class System;
class Sound;
class Channel;
class ChannelGroup;
class SoundGroup;
class Reverb;
class DSP;
class DSPConnection;
class Geometry;
/*
FMOD global system functions (optional).
*/
inline FMOD_RESULT Memory_Initialize(void *poolmem, int poollen, FMOD_MEMORY_ALLOCCALLBACK useralloc, FMOD_MEMORY_REALLOCCALLBACK userrealloc, FMOD_MEMORY_FREECALLBACK userfree, FMOD_MEMORY_TYPE memtypeflags = FMOD_MEMORY_ALL) { return FMOD_Memory_Initialize(poolmem, poollen, useralloc, userrealloc, userfree, memtypeflags); }
inline FMOD_RESULT Memory_GetStats (int *currentalloced, int *maxalloced, bool blocking = true) { return FMOD_Memory_GetStats(currentalloced, maxalloced, blocking); }
inline FMOD_RESULT Debug_SetLevel(FMOD_DEBUGLEVEL level) { return FMOD_Debug_SetLevel(level); }
inline FMOD_RESULT Debug_GetLevel(FMOD_DEBUGLEVEL *level) { return FMOD_Debug_GetLevel(level); }
inline FMOD_RESULT File_SetDiskBusy(int busy) { return FMOD_File_SetDiskBusy(busy); }
inline FMOD_RESULT File_GetDiskBusy(int *busy) { return FMOD_File_GetDiskBusy(busy); }
/*
FMOD System factory functions.
*/
inline FMOD_RESULT System_Create(System **system) { return FMOD_System_Create((FMOD_SYSTEM **)system); }
/*
'System' API
*/
class System
{
private:
System(); /* Constructor made private so user cannot statically instance a System class.
System_Create must be used. */
public:
FMOD_RESULT F_API release ();
// Pre-init functions.
FMOD_RESULT F_API setOutput (FMOD_OUTPUTTYPE output);
FMOD_RESULT F_API getOutput (FMOD_OUTPUTTYPE *output);
FMOD_RESULT F_API getNumDrivers (int *numdrivers);
FMOD_RESULT F_API getDriverInfo (int id, char *name, int namelen, FMOD_GUID *guid);
FMOD_RESULT F_API getDriverInfoW (int id, short *name, int namelen, FMOD_GUID *guid);
FMOD_RESULT F_API getDriverCaps (int id, FMOD_CAPS *caps, int *controlpaneloutputrate, FMOD_SPEAKERMODE *controlpanelspeakermode);
FMOD_RESULT F_API setDriver (int driver);
FMOD_RESULT F_API getDriver (int *driver);
FMOD_RESULT F_API setHardwareChannels (int numhardwarechannels);
FMOD_RESULT F_API setSoftwareChannels (int numsoftwarechannels);
FMOD_RESULT F_API getSoftwareChannels (int *numsoftwarechannels);
FMOD_RESULT F_API setSoftwareFormat (int samplerate, FMOD_SOUND_FORMAT format, int numoutputchannels, int maxinputchannels, FMOD_DSP_RESAMPLER resamplemethod);
FMOD_RESULT F_API getSoftwareFormat (int *samplerate, FMOD_SOUND_FORMAT *format, int *numoutputchannels, int *maxinputchannels, FMOD_DSP_RESAMPLER *resamplemethod, int *bits);
FMOD_RESULT F_API setDSPBufferSize (unsigned int bufferlength, int numbuffers);
FMOD_RESULT F_API getDSPBufferSize (unsigned int *bufferlength, int *numbuffers);
FMOD_RESULT F_API setFileSystem (FMOD_FILE_OPENCALLBACK useropen, FMOD_FILE_CLOSECALLBACK userclose, FMOD_FILE_READCALLBACK userread, FMOD_FILE_SEEKCALLBACK userseek, FMOD_FILE_ASYNCREADCALLBACK userasyncread, FMOD_FILE_ASYNCCANCELCALLBACK userasynccancel, int blockalign);
FMOD_RESULT F_API attachFileSystem (FMOD_FILE_OPENCALLBACK useropen, FMOD_FILE_CLOSECALLBACK userclose, FMOD_FILE_READCALLBACK userread, FMOD_FILE_SEEKCALLBACK userseek);
FMOD_RESULT F_API setAdvancedSettings (FMOD_ADVANCEDSETTINGS *settings);
FMOD_RESULT F_API getAdvancedSettings (FMOD_ADVANCEDSETTINGS *settings);
FMOD_RESULT F_API setSpeakerMode (FMOD_SPEAKERMODE speakermode);
FMOD_RESULT F_API getSpeakerMode (FMOD_SPEAKERMODE *speakermode);
FMOD_RESULT F_API setCallback (FMOD_SYSTEM_CALLBACK callback);
// Plug-in support
FMOD_RESULT F_API setPluginPath (const char *path);
FMOD_RESULT F_API loadPlugin (const char *filename, unsigned int *handle, unsigned int priority = 0);
FMOD_RESULT F_API unloadPlugin (unsigned int handle);
FMOD_RESULT F_API getNumPlugins (FMOD_PLUGINTYPE plugintype, int *numplugins);
FMOD_RESULT F_API getPluginHandle (FMOD_PLUGINTYPE plugintype, int index, unsigned int *handle);
FMOD_RESULT F_API getPluginInfo (unsigned int handle, FMOD_PLUGINTYPE *plugintype, char *name, int namelen, unsigned int *version);
FMOD_RESULT F_API setOutputByPlugin (unsigned int handle);
FMOD_RESULT F_API getOutputByPlugin (unsigned int *handle);
FMOD_RESULT F_API createDSPByPlugin (unsigned int handle, DSP **dsp);
FMOD_RESULT F_API registerCodec (FMOD_CODEC_DESCRIPTION *description, unsigned int *handle, unsigned int priority = 0);
FMOD_RESULT F_API registerDSP (FMOD_DSP_DESCRIPTION *description, unsigned int *handle);
// Init/Close
FMOD_RESULT F_API init (int maxchannels, FMOD_INITFLAGS flags, void *extradriverdata);
FMOD_RESULT F_API close ();
// General post-init system functions
FMOD_RESULT F_API update (); /* IMPORTANT! CALL THIS ONCE PER FRAME! */
FMOD_RESULT F_API set3DSettings (float dopplerscale, float distancefactor, float rolloffscale);
FMOD_RESULT F_API get3DSettings (float *dopplerscale, float *distancefactor, float *rolloffscale);
FMOD_RESULT F_API set3DNumListeners (int numlisteners);
FMOD_RESULT F_API get3DNumListeners (int *numlisteners);
FMOD_RESULT F_API set3DListenerAttributes(int listener, const FMOD_VECTOR *pos, const FMOD_VECTOR *vel, const FMOD_VECTOR *forward, const FMOD_VECTOR *up);
FMOD_RESULT F_API get3DListenerAttributes(int listener, FMOD_VECTOR *pos, FMOD_VECTOR *vel, FMOD_VECTOR *forward, FMOD_VECTOR *up);
FMOD_RESULT F_API set3DRolloffCallback (FMOD_3D_ROLLOFFCALLBACK callback);
FMOD_RESULT F_API set3DSpeakerPosition (FMOD_SPEAKER speaker, float x, float y, bool active);
FMOD_RESULT F_API get3DSpeakerPosition (FMOD_SPEAKER speaker, float *x, float *y, bool *active);
FMOD_RESULT F_API setStreamBufferSize (unsigned int filebuffersize, FMOD_TIMEUNIT filebuffersizetype);
FMOD_RESULT F_API getStreamBufferSize (unsigned int *filebuffersize, FMOD_TIMEUNIT *filebuffersizetype);
// System information functions.
FMOD_RESULT F_API getVersion (unsigned int *version);
FMOD_RESULT F_API getOutputHandle (void **handle);
FMOD_RESULT F_API getChannelsPlaying (int *channels);
FMOD_RESULT F_API getHardwareChannels (int *numhardwarechannels);
FMOD_RESULT F_API getCPUUsage (float *dsp, float *stream, float *geometry, float *update, float *total);
FMOD_RESULT F_API getSoundRAM (int *currentalloced, int *maxalloced, int *total);
FMOD_RESULT F_API getNumCDROMDrives (int *numdrives);
FMOD_RESULT F_API getCDROMDriveName (int drive, char *drivename, int drivenamelen, char *scsiname, int scsinamelen, char *devicename, int devicenamelen);
FMOD_RESULT F_API getSpectrum (float *spectrumarray, int numvalues, int channeloffset, FMOD_DSP_FFT_WINDOW windowtype);
FMOD_RESULT F_API getWaveData (float *wavearray, int numvalues, int channeloffset);
// Sound/DSP/Channel/FX creation and retrieval.
FMOD_RESULT F_API createSound (const char *name_or_data, FMOD_MODE mode, FMOD_CREATESOUNDEXINFO *exinfo, Sound **sound);
FMOD_RESULT F_API createStream (const char *name_or_data, FMOD_MODE mode, FMOD_CREATESOUNDEXINFO *exinfo, Sound **sound);
FMOD_RESULT F_API createDSP (FMOD_DSP_DESCRIPTION *description, DSP **dsp);
FMOD_RESULT F_API createDSPByType (FMOD_DSP_TYPE type, DSP **dsp);
FMOD_RESULT F_API createChannelGroup (const char *name, ChannelGroup **channelgroup);
FMOD_RESULT F_API createSoundGroup (const char *name, SoundGroup **soundgroup);
FMOD_RESULT F_API createReverb (Reverb **reverb);
FMOD_RESULT F_API playSound (FMOD_CHANNELINDEX channelid, Sound *sound, bool paused, Channel **channel);
FMOD_RESULT F_API playDSP (FMOD_CHANNELINDEX channelid, DSP *dsp, bool paused, Channel **channel);
FMOD_RESULT F_API getChannel (int channelid, Channel **channel);
FMOD_RESULT F_API getMasterChannelGroup (ChannelGroup **channelgroup);
FMOD_RESULT F_API getMasterSoundGroup (SoundGroup **soundgroup);
// Reverb API
FMOD_RESULT F_API setReverbProperties (const FMOD_REVERB_PROPERTIES *prop);
FMOD_RESULT F_API getReverbProperties (FMOD_REVERB_PROPERTIES *prop);
FMOD_RESULT F_API setReverbAmbientProperties(FMOD_REVERB_PROPERTIES *prop);
FMOD_RESULT F_API getReverbAmbientProperties(FMOD_REVERB_PROPERTIES *prop);
// System level DSP access.
FMOD_RESULT F_API getDSPHead (DSP **dsp);
FMOD_RESULT F_API addDSP (DSP *dsp, DSPConnection **connection);
FMOD_RESULT F_API lockDSP ();
FMOD_RESULT F_API unlockDSP ();
FMOD_RESULT F_API getDSPClock (unsigned int *hi, unsigned int *lo);
// Recording API.
FMOD_RESULT F_API getRecordNumDrivers (int *numdrivers);
FMOD_RESULT F_API getRecordDriverInfo (int id, char *name, int namelen, FMOD_GUID *guid);
FMOD_RESULT F_API getRecordDriverInfoW (int id, short *name, int namelen, FMOD_GUID *guid);
FMOD_RESULT F_API getRecordDriverCaps (int id, FMOD_CAPS *caps, int *minfrequency, int *maxfrequency);
FMOD_RESULT F_API getRecordPosition (int id, unsigned int *position);
FMOD_RESULT F_API recordStart (int id, Sound *sound, bool loop);
FMOD_RESULT F_API recordStop (int id);
FMOD_RESULT F_API isRecording (int id, bool *recording);
// Geometry API.
FMOD_RESULT F_API createGeometry (int maxpolygons, int maxvertices, Geometry **geometry);
FMOD_RESULT F_API setGeometrySettings (float maxworldsize);
FMOD_RESULT F_API getGeometrySettings (float *maxworldsize);
FMOD_RESULT F_API loadGeometry (const void *data, int datasize, Geometry **geometry);
FMOD_RESULT F_API getGeometryOcclusion (const FMOD_VECTOR *listener, const FMOD_VECTOR *source, float *direct, float *reverb);
// Network functions.
FMOD_RESULT F_API setNetworkProxy (const char *proxy);
FMOD_RESULT F_API getNetworkProxy (char *proxy, int proxylen);
FMOD_RESULT F_API setNetworkTimeout (int timeout);
FMOD_RESULT F_API getNetworkTimeout (int *timeout);
// Userdata set/get.
FMOD_RESULT F_API setUserData (void *userdata);
FMOD_RESULT F_API getUserData (void **userdata);
FMOD_RESULT F_API getMemoryInfo (unsigned int memorybits, unsigned int event_memorybits, unsigned int *memoryused, FMOD_MEMORY_USAGE_DETAILS *memoryused_details);
};
/*
'Sound' API
*/
class Sound
{
private:
Sound(); /* Constructor made private so user cannot statically instance a Sound class.
Appropriate Sound creation or retrieval function must be used. */
public:
FMOD_RESULT F_API release ();
FMOD_RESULT F_API getSystemObject (System **system);
// Standard sound manipulation functions.
FMOD_RESULT F_API lock (unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2);
FMOD_RESULT F_API unlock (void *ptr1, void *ptr2, unsigned int len1, unsigned int len2);
FMOD_RESULT F_API setDefaults (float frequency, float volume, float pan, int priority);
FMOD_RESULT F_API getDefaults (float *frequency, float *volume, float *pan, int *priority);
FMOD_RESULT F_API setVariations (float frequencyvar, float volumevar, float panvar);
FMOD_RESULT F_API getVariations (float *frequencyvar, float *volumevar, float *panvar);
FMOD_RESULT F_API set3DMinMaxDistance (float min, float max);
FMOD_RESULT F_API get3DMinMaxDistance (float *min, float *max);
FMOD_RESULT F_API set3DConeSettings (float insideconeangle, float outsideconeangle, float outsidevolume);
FMOD_RESULT F_API get3DConeSettings (float *insideconeangle, float *outsideconeangle, float *outsidevolume);
FMOD_RESULT F_API set3DCustomRolloff (FMOD_VECTOR *points, int numpoints);
FMOD_RESULT F_API get3DCustomRolloff (FMOD_VECTOR **points, int *numpoints);
FMOD_RESULT F_API setSubSound (int index, Sound *subsound);
FMOD_RESULT F_API getSubSound (int index, Sound **subsound);
FMOD_RESULT F_API getSubSoundParent (Sound **parentsound);
FMOD_RESULT F_API setSubSoundSentence (int *subsoundlist, int numsubsounds);
FMOD_RESULT F_API getName (char *name, int namelen);
FMOD_RESULT F_API getLength (unsigned int *length, FMOD_TIMEUNIT lengthtype);
FMOD_RESULT F_API getFormat (FMOD_SOUND_TYPE *type, FMOD_SOUND_FORMAT *format, int *channels, int *bits);
FMOD_RESULT F_API getNumSubSounds (int *numsubsounds);
FMOD_RESULT F_API getNumTags (int *numtags, int *numtagsupdated);
FMOD_RESULT F_API getTag (const char *name, int index, FMOD_TAG *tag);
FMOD_RESULT F_API getOpenState (FMOD_OPENSTATE *openstate, unsigned int *percentbuffered, bool *starving, bool *diskbusy);
FMOD_RESULT F_API readData (void *buffer, unsigned int lenbytes, unsigned int *read);
FMOD_RESULT F_API seekData (unsigned int pcm);
FMOD_RESULT F_API setSoundGroup (SoundGroup *soundgroup);
FMOD_RESULT F_API getSoundGroup (SoundGroup **soundgroup);
// Synchronization point API. These points can come from markers embedded in wav files, and can also generate channel callbacks.
FMOD_RESULT F_API getNumSyncPoints (int *numsyncpoints);
FMOD_RESULT F_API getSyncPoint (int index, FMOD_SYNCPOINT **point);
FMOD_RESULT F_API getSyncPointInfo (FMOD_SYNCPOINT *point, char *name, int namelen, unsigned int *offset, FMOD_TIMEUNIT offsettype);
FMOD_RESULT F_API addSyncPoint (unsigned int offset, FMOD_TIMEUNIT offsettype, const char *name, FMOD_SYNCPOINT **point);
FMOD_RESULT F_API deleteSyncPoint (FMOD_SYNCPOINT *point);
// Functions also in Channel class but here they are the 'default' to save having to change it in Channel all the time.
FMOD_RESULT F_API setMode (FMOD_MODE mode);
FMOD_RESULT F_API getMode (FMOD_MODE *mode);
FMOD_RESULT F_API setLoopCount (int loopcount);
FMOD_RESULT F_API getLoopCount (int *loopcount);
FMOD_RESULT F_API setLoopPoints (unsigned int loopstart, FMOD_TIMEUNIT loopstarttype, unsigned int loopend, FMOD_TIMEUNIT loopendtype);
FMOD_RESULT F_API getLoopPoints (unsigned int *loopstart, FMOD_TIMEUNIT loopstarttype, unsigned int *loopend, FMOD_TIMEUNIT loopendtype);
// For MOD/S3M/XM/IT/MID sequenced formats only.
FMOD_RESULT F_API getMusicNumChannels (int *numchannels);
FMOD_RESULT F_API setMusicChannelVolume (int channel, float volume);
FMOD_RESULT F_API getMusicChannelVolume (int channel, float *volume);
FMOD_RESULT F_API setMusicSpeed (float speed);
FMOD_RESULT F_API getMusicSpeed (float *speed);
// Userdata set/get.
FMOD_RESULT F_API setUserData (void *userdata);
FMOD_RESULT F_API getUserData (void **userdata);
FMOD_RESULT F_API getMemoryInfo (unsigned int memorybits, unsigned int event_memorybits, unsigned int *memoryused, FMOD_MEMORY_USAGE_DETAILS *memoryused_details);
};
/*
'Channel' API.
*/
class Channel
{
private:
Channel(); /* Constructor made private so user cannot statically instance a Channel class.
Appropriate Channel creation or retrieval function must be used. */
public:
FMOD_RESULT F_API getSystemObject (System **system);
FMOD_RESULT F_API stop ();
FMOD_RESULT F_API setPaused (bool paused);
FMOD_RESULT F_API getPaused (bool *paused);
FMOD_RESULT F_API setVolume (float volume);
FMOD_RESULT F_API getVolume (float *volume);
FMOD_RESULT F_API setFrequency (float frequency);
FMOD_RESULT F_API getFrequency (float *frequency);
FMOD_RESULT F_API setPan (float pan);
FMOD_RESULT F_API getPan (float *pan);
FMOD_RESULT F_API setDelay (FMOD_DELAYTYPE delaytype, unsigned int delayhi, unsigned int delaylo);
FMOD_RESULT F_API getDelay (FMOD_DELAYTYPE delaytype, unsigned int *delayhi, unsigned int *delaylo);
FMOD_RESULT F_API setSpeakerMix (float frontleft, float frontright, float center, float lfe, float backleft, float backright, float sideleft, float sideright);
FMOD_RESULT F_API getSpeakerMix (float *frontleft, float *frontright, float *center, float *lfe, float *backleft, float *backright, float *sideleft, float *sideright);
FMOD_RESULT F_API setSpeakerLevels (FMOD_SPEAKER speaker, float *levels, int numlevels);
FMOD_RESULT F_API getSpeakerLevels (FMOD_SPEAKER speaker, float *levels, int numlevels);
FMOD_RESULT F_API setInputChannelMix (float *levels, int numlevels);
FMOD_RESULT F_API getInputChannelMix (float *levels, int numlevels);
FMOD_RESULT F_API setMute (bool mute);
FMOD_RESULT F_API getMute (bool *mute);
FMOD_RESULT F_API setPriority (int priority);
FMOD_RESULT F_API getPriority (int *priority);
FMOD_RESULT F_API setPosition (unsigned int position, FMOD_TIMEUNIT postype);
FMOD_RESULT F_API getPosition (unsigned int *position, FMOD_TIMEUNIT postype);
FMOD_RESULT F_API setReverbProperties (const FMOD_REVERB_CHANNELPROPERTIES *prop);
FMOD_RESULT F_API getReverbProperties (FMOD_REVERB_CHANNELPROPERTIES *prop);
FMOD_RESULT F_API setLowPassGain (float gain);
FMOD_RESULT F_API getLowPassGain (float *gain);
FMOD_RESULT F_API setChannelGroup (ChannelGroup *channelgroup);
FMOD_RESULT F_API getChannelGroup (ChannelGroup **channelgroup);
FMOD_RESULT F_API setCallback (FMOD_CHANNEL_CALLBACK callback);
// 3D functionality.
FMOD_RESULT F_API set3DAttributes (const FMOD_VECTOR *pos, const FMOD_VECTOR *vel);
FMOD_RESULT F_API get3DAttributes (FMOD_VECTOR *pos, FMOD_VECTOR *vel);
FMOD_RESULT F_API set3DMinMaxDistance (float mindistance, float maxdistance);
FMOD_RESULT F_API get3DMinMaxDistance (float *mindistance, float *maxdistance);
FMOD_RESULT F_API set3DConeSettings (float insideconeangle, float outsideconeangle, float outsidevolume);
FMOD_RESULT F_API get3DConeSettings (float *insideconeangle, float *outsideconeangle, float *outsidevolume);
FMOD_RESULT F_API set3DConeOrientation (FMOD_VECTOR *orientation);
FMOD_RESULT F_API get3DConeOrientation (FMOD_VECTOR *orientation);
FMOD_RESULT F_API set3DCustomRolloff (FMOD_VECTOR *points, int numpoints);
FMOD_RESULT F_API get3DCustomRolloff (FMOD_VECTOR **points, int *numpoints);
FMOD_RESULT F_API set3DOcclusion (float directocclusion, float reverbocclusion);
FMOD_RESULT F_API get3DOcclusion (float *directocclusion, float *reverbocclusion);
FMOD_RESULT F_API set3DSpread (float angle);
FMOD_RESULT F_API get3DSpread (float *angle);
FMOD_RESULT F_API set3DPanLevel (float level);
FMOD_RESULT F_API get3DPanLevel (float *level);
FMOD_RESULT F_API set3DDopplerLevel (float level);
FMOD_RESULT F_API get3DDopplerLevel (float *level);
FMOD_RESULT F_API set3DDistanceFilter (bool custom, float customLevel, float centerFreq);
FMOD_RESULT F_API get3DDistanceFilter (bool *custom, float *customLevel, float *centerFreq);
// DSP functionality only for channels playing sounds created with FMOD_SOFTWARE.
FMOD_RESULT F_API getDSPHead (DSP **dsp);
FMOD_RESULT F_API addDSP (DSP *dsp, DSPConnection **connection);
// Information only functions.
FMOD_RESULT F_API isPlaying (bool *isplaying);
FMOD_RESULT F_API isVirtual (bool *isvirtual);
FMOD_RESULT F_API getAudibility (float *audibility);
FMOD_RESULT F_API getCurrentSound (Sound **sound);
FMOD_RESULT F_API getSpectrum (float *spectrumarray, int numvalues, int channeloffset, FMOD_DSP_FFT_WINDOW windowtype);
FMOD_RESULT F_API getWaveData (float *wavearray, int numvalues, int channeloffset);
FMOD_RESULT F_API getIndex (int *index);
// Functions also found in Sound class but here they can be set per channel.
FMOD_RESULT F_API setMode (FMOD_MODE mode);
FMOD_RESULT F_API getMode (FMOD_MODE *mode);
FMOD_RESULT F_API setLoopCount (int loopcount);
FMOD_RESULT F_API getLoopCount (int *loopcount);
FMOD_RESULT F_API setLoopPoints (unsigned int loopstart, FMOD_TIMEUNIT loopstarttype, unsigned int loopend, FMOD_TIMEUNIT loopendtype);
FMOD_RESULT F_API getLoopPoints (unsigned int *loopstart, FMOD_TIMEUNIT loopstarttype, unsigned int *loopend, FMOD_TIMEUNIT loopendtype);
// Userdata set/get.
FMOD_RESULT F_API setUserData (void *userdata);
FMOD_RESULT F_API getUserData (void **userdata);
FMOD_RESULT F_API getMemoryInfo (unsigned int memorybits, unsigned int event_memorybits, unsigned int *memoryused, FMOD_MEMORY_USAGE_DETAILS *memoryused_details);
};
/*
'ChannelGroup' API
*/
class ChannelGroup
{
private:
ChannelGroup(); /* Constructor made private so user cannot statically instance a ChannelGroup class.
Appropriate ChannelGroup creation or retrieval function must be used. */
public:
FMOD_RESULT F_API release ();
FMOD_RESULT F_API getSystemObject (System **system);
// Channelgroup scale values. (changes attributes relative to the channels, doesn't overwrite them)
FMOD_RESULT F_API setVolume (float volume);
FMOD_RESULT F_API getVolume (float *volume);
FMOD_RESULT F_API setPitch (float pitch);
FMOD_RESULT F_API getPitch (float *pitch);
FMOD_RESULT F_API set3DOcclusion (float directocclusion, float reverbocclusion);
FMOD_RESULT F_API get3DOcclusion (float *directocclusion, float *reverbocclusion);
FMOD_RESULT F_API setPaused (bool paused);
FMOD_RESULT F_API getPaused (bool *paused);
FMOD_RESULT F_API setMute (bool mute);
FMOD_RESULT F_API getMute (bool *mute);
// Channelgroup override values. (recursively overwrites whatever settings the channels had)
FMOD_RESULT F_API stop ();
FMOD_RESULT F_API overrideVolume (float volume);
FMOD_RESULT F_API overrideFrequency (float frequency);
FMOD_RESULT F_API overridePan (float pan);
FMOD_RESULT F_API overrideReverbProperties(const FMOD_REVERB_CHANNELPROPERTIES *prop);
FMOD_RESULT F_API override3DAttributes (const FMOD_VECTOR *pos, const FMOD_VECTOR *vel);
FMOD_RESULT F_API overrideSpeakerMix (float frontleft, float frontright, float center, float lfe, float backleft, float backright, float sideleft, float sideright);
// Nested channel groups.
FMOD_RESULT F_API addGroup (ChannelGroup *group);
FMOD_RESULT F_API getNumGroups (int *numgroups);
FMOD_RESULT F_API getGroup (int index, ChannelGroup **group);
FMOD_RESULT F_API getParentGroup (ChannelGroup **group);
// DSP functionality only for channel groups playing sounds created with FMOD_SOFTWARE.
FMOD_RESULT F_API getDSPHead (DSP **dsp);
FMOD_RESULT F_API addDSP (DSP *dsp, DSPConnection **connection);
// Information only functions.
FMOD_RESULT F_API getName (char *name, int namelen);
FMOD_RESULT F_API getNumChannels (int *numchannels);
FMOD_RESULT F_API getChannel (int index, Channel **channel);
FMOD_RESULT F_API getSpectrum (float *spectrumarray, int numvalues, int channeloffset, FMOD_DSP_FFT_WINDOW windowtype);
FMOD_RESULT F_API getWaveData (float *wavearray, int numvalues, int channeloffset);
// Userdata set/get.
FMOD_RESULT F_API setUserData (void *userdata);
FMOD_RESULT F_API getUserData (void **userdata);
FMOD_RESULT F_API getMemoryInfo (unsigned int memorybits, unsigned int event_memorybits, unsigned int *memoryused, FMOD_MEMORY_USAGE_DETAILS *memoryused_details);
};
/*
'SoundGroup' API
*/
class SoundGroup
{
private:
SoundGroup(); /* Constructor made private so user cannot statically instance a SoundGroup class.
Appropriate SoundGroup creation or retrieval function must be used. */
public:
FMOD_RESULT F_API release ();
FMOD_RESULT F_API getSystemObject (System **system);
// SoundGroup control functions.
FMOD_RESULT F_API setMaxAudible (int maxaudible);
FMOD_RESULT F_API getMaxAudible (int *maxaudible);
FMOD_RESULT F_API setMaxAudibleBehavior (FMOD_SOUNDGROUP_BEHAVIOR behavior);
FMOD_RESULT F_API getMaxAudibleBehavior (FMOD_SOUNDGROUP_BEHAVIOR *behavior);
FMOD_RESULT F_API setMuteFadeSpeed (float speed);
FMOD_RESULT F_API getMuteFadeSpeed (float *speed);
FMOD_RESULT F_API setVolume (float volume);
FMOD_RESULT F_API getVolume (float *volume);
FMOD_RESULT F_API stop ();
// Information only functions.
FMOD_RESULT F_API getName (char *name, int namelen);
FMOD_RESULT F_API getNumSounds (int *numsounds);
FMOD_RESULT F_API getSound (int index, Sound **sound);
FMOD_RESULT F_API getNumPlaying (int *numplaying);
// Userdata set/get.
FMOD_RESULT F_API setUserData (void *userdata);
FMOD_RESULT F_API getUserData (void **userdata);
FMOD_RESULT F_API getMemoryInfo (unsigned int memorybits, unsigned int event_memorybits, unsigned int *memoryused, FMOD_MEMORY_USAGE_DETAILS *memoryused_details);
};
/*
'DSP' API
*/
class DSP
{
private:
DSP(); /* Constructor made private so user cannot statically instance a DSP class.
Appropriate DSP creation or retrieval function must be used. */
public:
FMOD_RESULT F_API release ();
FMOD_RESULT F_API getSystemObject (System **system);
// Connection / disconnection / input and output enumeration.
FMOD_RESULT F_API addInput (DSP *target, DSPConnection **connection);
FMOD_RESULT F_API disconnectFrom (DSP *target);
FMOD_RESULT F_API disconnectAll (bool inputs, bool outputs);
FMOD_RESULT F_API remove ();
FMOD_RESULT F_API getNumInputs (int *numinputs);
FMOD_RESULT F_API getNumOutputs (int *numoutputs);
FMOD_RESULT F_API getInput (int index, DSP **input, DSPConnection **inputconnection);
FMOD_RESULT F_API getOutput (int index, DSP **output, DSPConnection **outputconnection);
// DSP unit control.
FMOD_RESULT F_API setActive (bool active);
FMOD_RESULT F_API getActive (bool *active);
FMOD_RESULT F_API setBypass (bool bypass);
FMOD_RESULT F_API getBypass (bool *bypass);
FMOD_RESULT F_API setSpeakerActive (FMOD_SPEAKER speaker, bool active);
FMOD_RESULT F_API getSpeakerActive (FMOD_SPEAKER speaker, bool *active);
FMOD_RESULT F_API reset ();
// DSP parameter control.
FMOD_RESULT F_API setParameter (int index, float value);
FMOD_RESULT F_API getParameter (int index, float *value, char *valuestr, int valuestrlen);
FMOD_RESULT F_API getNumParameters (int *numparams);
FMOD_RESULT F_API getParameterInfo (int index, char *name, char *label, char *description, int descriptionlen, float *min, float *max);
FMOD_RESULT F_API showConfigDialog (void *hwnd, bool show);
// DSP attributes.
FMOD_RESULT F_API getInfo (char *name, unsigned int *version, int *channels, int *configwidth, int *configheight);
FMOD_RESULT F_API getType (FMOD_DSP_TYPE *type);
FMOD_RESULT F_API setDefaults (float frequency, float volume, float pan, int priority);
FMOD_RESULT F_API getDefaults (float *frequency, float *volume, float *pan, int *priority);
// Userdata set/get.
FMOD_RESULT F_API setUserData (void *userdata);
FMOD_RESULT F_API getUserData (void **userdata);
FMOD_RESULT F_API getMemoryInfo (unsigned int memorybits, unsigned int event_memorybits, unsigned int *memoryused, FMOD_MEMORY_USAGE_DETAILS *memoryused_details);
};
/*
'DSPConnection' API
*/
class DSPConnection
{
private:
DSPConnection(); /* Constructor made private so user cannot statically instance a DSPConnection class.
Appropriate DSPConnection creation or retrieval function must be used. */
public:
FMOD_RESULT F_API getInput (DSP **input);
FMOD_RESULT F_API getOutput (DSP **output);
FMOD_RESULT F_API setMix (float volume);
FMOD_RESULT F_API getMix (float *volume);
FMOD_RESULT F_API setLevels (FMOD_SPEAKER speaker, float *levels, int numlevels);
FMOD_RESULT F_API getLevels (FMOD_SPEAKER speaker, float *levels, int numlevels);
// Userdata set/get.
FMOD_RESULT F_API setUserData (void *userdata);
FMOD_RESULT F_API getUserData (void **userdata);
FMOD_RESULT F_API getMemoryInfo (unsigned int memorybits, unsigned int event_memorybits, unsigned int *memoryused, FMOD_MEMORY_USAGE_DETAILS *memoryused_details);
};
/*
'Geometry' API
*/
class Geometry
{
private:
Geometry(); /* Constructor made private so user cannot statically instance a Geometry class.
Appropriate Geometry creation or retrieval function must be used. */
public:
FMOD_RESULT F_API release ();
// Polygon manipulation.
FMOD_RESULT F_API addPolygon (float directocclusion, float reverbocclusion, bool doublesided, int numvertices, const FMOD_VECTOR *vertices, int *polygonindex);
FMOD_RESULT F_API getNumPolygons (int *numpolygons);
FMOD_RESULT F_API getMaxPolygons (int *maxpolygons, int *maxvertices);
FMOD_RESULT F_API getPolygonNumVertices (int index, int *numvertices);
FMOD_RESULT F_API setPolygonVertex (int index, int vertexindex, const FMOD_VECTOR *vertex);
FMOD_RESULT F_API getPolygonVertex (int index, int vertexindex, FMOD_VECTOR *vertex);
FMOD_RESULT F_API setPolygonAttributes (int index, float directocclusion, float reverbocclusion, bool doublesided);
FMOD_RESULT F_API getPolygonAttributes (int index, float *directocclusion, float *reverbocclusion, bool *doublesided);
// Object manipulation.
FMOD_RESULT F_API setActive (bool active);
FMOD_RESULT F_API getActive (bool *active);
FMOD_RESULT F_API setRotation (const FMOD_VECTOR *forward, const FMOD_VECTOR *up);
FMOD_RESULT F_API getRotation (FMOD_VECTOR *forward, FMOD_VECTOR *up);
FMOD_RESULT F_API setPosition (const FMOD_VECTOR *position);
FMOD_RESULT F_API getPosition (FMOD_VECTOR *position);
FMOD_RESULT F_API setScale (const FMOD_VECTOR *scale);
FMOD_RESULT F_API getScale (FMOD_VECTOR *scale);
FMOD_RESULT F_API save (void *data, int *datasize);
// Userdata set/get.
FMOD_RESULT F_API setUserData (void *userdata);
FMOD_RESULT F_API getUserData (void **userdata);
FMOD_RESULT F_API getMemoryInfo (unsigned int memorybits, unsigned int event_memorybits, unsigned int *memoryused, FMOD_MEMORY_USAGE_DETAILS *memoryused_details);
};
/*
'Reverb' API
*/
class Reverb
{
private:
Reverb(); /* Constructor made private so user cannot statically instance a Reverb class.
Appropriate Reverb creation or retrieval function must be used. */
public:
FMOD_RESULT F_API release ();
// Reverb manipulation.
FMOD_RESULT F_API set3DAttributes (const FMOD_VECTOR *position, float mindistance, float maxdistance);
FMOD_RESULT F_API get3DAttributes (FMOD_VECTOR *position, float *mindistance,float *maxdistance);
FMOD_RESULT F_API setProperties (const FMOD_REVERB_PROPERTIES *properties);
FMOD_RESULT F_API getProperties (FMOD_REVERB_PROPERTIES *properties);
FMOD_RESULT F_API setActive (bool active);
FMOD_RESULT F_API getActive (bool *active);
// Userdata set/get.
FMOD_RESULT F_API setUserData (void *userdata);
FMOD_RESULT F_API getUserData (void **userdata);
FMOD_RESULT F_API getMemoryInfo (unsigned int memorybits, unsigned int event_memorybits, unsigned int *memoryused, FMOD_MEMORY_USAGE_DETAILS *memoryused_details);
};
}
#endif

View File

@ -0,0 +1,159 @@
/* ==================================================================================================== */
/* FMOD Ex - codec development header file. Copyright (c), Firelight Technologies Pty, Ltd. 2004-2016. */
/* */
/* Use this header if you are wanting to develop your own file format plugin to use with */
/* FMOD's codec system. With this header you can make your own fileformat plugin that FMOD */
/* can register and use. See the documentation and examples on how to make a working plugin. */
/* */
/* ==================================================================================================== */
#ifndef _FMOD_CODEC_H
#define _FMOD_CODEC_H
typedef struct FMOD_CODEC_STATE FMOD_CODEC_STATE;
typedef struct FMOD_CODEC_WAVEFORMAT FMOD_CODEC_WAVEFORMAT;
/*
Codec callbacks
*/
typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_OPENCALLBACK) (FMOD_CODEC_STATE *codec_state, FMOD_MODE usermode, FMOD_CREATESOUNDEXINFO *userexinfo);
typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_CLOSECALLBACK) (FMOD_CODEC_STATE *codec_state);
typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_READCALLBACK) (FMOD_CODEC_STATE *codec_state, void *buffer, unsigned int sizebytes, unsigned int *bytesread);
typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_GETLENGTHCALLBACK) (FMOD_CODEC_STATE *codec_state, unsigned int *length, FMOD_TIMEUNIT lengthtype);
typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_SETPOSITIONCALLBACK) (FMOD_CODEC_STATE *codec_state, int subsound, unsigned int position, FMOD_TIMEUNIT postype);
typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_GETPOSITIONCALLBACK) (FMOD_CODEC_STATE *codec_state, unsigned int *position, FMOD_TIMEUNIT postype);
typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_SOUNDCREATECALLBACK) (FMOD_CODEC_STATE *codec_state, int subsound, FMOD_SOUND *sound);
typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_METADATACALLBACK) (FMOD_CODEC_STATE *codec_state, FMOD_TAGTYPE tagtype, char *name, void *data, unsigned int datalen, FMOD_TAGDATATYPE datatype, int unique);
typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_GETWAVEFORMAT) (FMOD_CODEC_STATE *codec_state, int index, FMOD_CODEC_WAVEFORMAT *waveformat);
/*
[STRUCTURE]
[
[DESCRIPTION]
When creating a codec, declare one of these and provide the relevant callbacks and name for FMOD to use when it opens and reads a file.
[REMARKS]
Members marked with [in] mean the variable can be written to. The user can set the value.
Members marked with [out] mean the variable is modified by FMOD and is for reading purposes only. Do not change this value.
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
FMOD_CODEC_STATE
]
*/
typedef struct FMOD_CODEC_DESCRIPTION
{
const char *name; /* [in] Name of the codec. */
unsigned int version; /* [in] Plugin writer's version number. */
int defaultasstream; /* [in] Tells FMOD to open the file as a stream when calling System::createSound, and not a static sample. Should normally be 0 (FALSE), because generally the user wants to decode the file into memory when using System::createSound. Mainly used for formats that decode for a very long time, or could use large amounts of memory when decoded. Usually sequenced formats such as mod/s3m/xm/it/midi fall into this category. It is mainly to stop users that don't know what they're doing from getting FMOD_ERR_MEMORY returned from createSound when they should have in fact called System::createStream or used FMOD_CREATESTREAM in System::createSound. */
FMOD_TIMEUNIT timeunits; /* [in] When setposition codec is called, only these time formats will be passed to the codec. Use bitwise OR to accumulate different types. */
FMOD_CODEC_OPENCALLBACK open; /* [in] Open callback for the codec for when FMOD tries to open a sound using this codec. */
FMOD_CODEC_CLOSECALLBACK close; /* [in] Close callback for the codec for when FMOD tries to close a sound using this codec. */
FMOD_CODEC_READCALLBACK read; /* [in] Read callback for the codec for when FMOD tries to read some data from the file to the destination format (specified in the open callback). */
FMOD_CODEC_GETLENGTHCALLBACK getlength; /* [in] Callback to return the length of the song in whatever format required when Sound::getLength is called. */
FMOD_CODEC_SETPOSITIONCALLBACK setposition; /* [in] Seek callback for the codec for when FMOD tries to seek within the file with Channel::setPosition. */
FMOD_CODEC_GETPOSITIONCALLBACK getposition; /* [in] Tell callback for the codec for when FMOD tries to get the current position within the with Channel::getPosition. */
FMOD_CODEC_SOUNDCREATECALLBACK soundcreate; /* [in] Sound creation callback for the codec when FMOD finishes creating the sound. (So the codec can set more parameters for the related created sound, ie loop points/mode or 3D attributes etc). */
FMOD_CODEC_GETWAVEFORMAT getwaveformat; /* [in] Callback to tell FMOD about the waveformat of a particular subsound. This is to save memory, rather than saving 1000 FMOD_CODEC_WAVEFORMAT structures in the codec, the codec might have a more optimal way of storing this information. */
} FMOD_CODEC_DESCRIPTION;
/*
[STRUCTURE]
[
[DESCRIPTION]
Set these values marked 'in' to tell fmod what sort of sound to create.
The format, channels and frequency tell FMOD what sort of hardware buffer to create when you initialize your code. So if you wrote an MP3 codec that decoded to stereo 16bit integer PCM, you would specify FMOD_SOUND_FORMAT_PCM16, and channels would be equal to 2.
Members marked as 'out' are set by fmod. Do not modify these. Simply specify 0 for these values when declaring the structure, FMOD will fill in the values for you after creation with the correct function pointers.
[REMARKS]
Members marked with [in] mean the variable can be written to. The user can set the value.
Members marked with [out] mean the variable is modified by FMOD and is for reading purposes only. Do not change this value.
An FMOD file might be from disk, memory or network, however the file may be opened by the user.
'numsubsounds' should be 0 if the file is a normal single sound stream or sound. Examples of this would be .WAV, .WMA, .MP3, .AIFF.
'numsubsounds' should be 1+ if the file is a container format, and does not contain wav data itself. Examples of these types would be CDDA (multiple CD tracks), FSB (contains multiple sounds), MIDI/MOD/S3M/XM/IT (contain instruments).
The arrays of format, channel, frequency, length and blockalign should point to arrays of information based on how many subsounds are in the format. If the number of subsounds is 0 then it should point to 1 of each attribute, the same as if the number of subsounds was 1. If subsounds was 100 for example, each pointer should point to an array of 100 of each attribute.
When a sound has 1 or more subsounds, you must play the individual sounds specified by first obtaining the subsound with Sound::getSubSound.
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
FMOD_SOUND_FORMAT
FMOD_FILE_READCALLBACK
FMOD_FILE_SEEKCALLBACK
FMOD_CODEC_METADATACALLBACK
Sound::getSubSound
Sound::getNumSubSounds
]
*/
struct FMOD_CODEC_WAVEFORMAT
{
char name[256]; /* [in] Name of sound.*/
FMOD_SOUND_FORMAT format; /* [in] Format for (decompressed) codec output, ie FMOD_SOUND_FORMAT_PCM8, FMOD_SOUND_FORMAT_PCM16.*/
int channels; /* [in] Number of channels used by codec, ie mono = 1, stereo = 2. */
int frequency; /* [in] Default frequency in hz of the codec, ie 44100. */
unsigned int lengthbytes; /* [in] Length in bytes of the source data. */
unsigned int lengthpcm; /* [in] Length in decompressed, PCM samples of the file, ie length in seconds * frequency. Used for Sound::getLength and for memory allocation of static decompressed sample data. */
int blockalign; /* [in] Blockalign in decompressed, PCM samples of the optimal decode chunk size for this format. The codec read callback will be called in multiples of this value. */
int loopstart; /* [in] Loopstart in decompressed, PCM samples of file. */
int loopend; /* [in] Loopend in decompressed, PCM samples of file. */
FMOD_MODE mode; /* [in] Mode to determine whether the sound should by default load as looping, non looping, 2d or 3d. */
unsigned int channelmask; /* [in] Microsoft speaker channel mask, as defined for WAVEFORMATEXTENSIBLE and is found in ksmedia.h. Leave at 0 to play in natural speaker order. */
};
/*
[STRUCTURE]
[
[DESCRIPTION]
Codec plugin structure that is passed into each callback.
Set these numsubsounds and waveformat members when called in FMOD_CODEC_OPENCALLBACK to tell fmod what sort of sound to create.
The format, channels and frequency tell FMOD what sort of hardware buffer to create when you initialize your code. So if you wrote an MP3 codec that decoded to stereo 16bit integer PCM, you would specify FMOD_SOUND_FORMAT_PCM16, and channels would be equal to 2.
[REMARKS]
Members marked with [in] mean the variable can be written to. The user can set the value.
Members marked with [out] mean the variable is modified by FMOD and is for reading purposes only. Do not change this value.
An FMOD file might be from disk, memory or internet, however the file may be opened by the user.
'numsubsounds' should be 0 if the file is a normal single sound stream or sound. Examples of this would be .WAV, .WMA, .MP3, .AIFF.
'numsubsounds' should be 1+ if the file is a container format, and does not contain wav data itself. Examples of these types would be CDDA (multiple CD tracks), FSB (contains multiple sounds), DLS (contain instruments).
The arrays of format, channel, frequency, length and blockalign should point to arrays of information based on how many subsounds are in the format. If the number of subsounds is 0 then it should point to 1 of each attribute, the same as if the number of subsounds was 1. If subsounds was 100 for example, each pointer should point to an array of 100 of each attribute.
When a sound has 1 or more subsounds, you must play the individual sounds specified by first obtaining the subsound with Sound::getSubSound.
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
FMOD_SOUND_FORMAT
FMOD_FILE_READCALLBACK
FMOD_FILE_SEEKCALLBACK
FMOD_CODEC_METADATACALLBACK
Sound::getSubSound
Sound::getNumSubSounds
]
*/
struct FMOD_CODEC_STATE
{
int numsubsounds; /* [in] Number of 'subsounds' in this sound. Anything other than 0 makes it a 'container' format (ie CDDA/DLS/FSB etc which contain 1 or more su bsounds). For most normal, single sound codec such as WAV/AIFF/MP3, this should be 0 as they are not a container for subsounds, they are the sound by itself. */
FMOD_CODEC_WAVEFORMAT *waveformat; /* [in] Pointer to an array of format structures containing information about each sample. Can be 0 or NULL if FMOD_CODEC_GETWAVEFORMAT callback is preferred. The number of entries here must equal the number of subsounds defined in the subsound parameter. If numsubsounds = 0 then there should be 1 instance of this structure. */
void *plugindata; /* [in] Plugin writer created data the codec author wants to attach to this object. */
void *filehandle; /* [out] This will return an internal FMOD file handle to use with the callbacks provided. */
unsigned int filesize; /* [out] This will contain the size of the file in bytes. */
FMOD_FILE_READCALLBACK fileread; /* [out] This will return a callable FMOD file function to use from codec. */
FMOD_FILE_SEEKCALLBACK fileseek; /* [out] This will return a callable FMOD file function to use from codec. */
FMOD_CODEC_METADATACALLBACK metadata; /* [out] This will return a callable FMOD metadata function to use from codec. */
};
#endif

View File

@ -0,0 +1,746 @@
/* ========================================================================================== */
/* FMOD Ex - DSP header file. Copyright (c), Firelight Technologies Pty, Ltd. 2004-2016. */
/* */
/* Use this header if you are interested in delving deeper into the FMOD software mixing / */
/* DSP engine. In this header you can find parameter structures for FMOD system reigstered */
/* DSP effects and generators. */
/* Also use this header if you are wanting to develop your own DSP plugin to use with FMOD's */
/* dsp system. With this header you can make your own DSP plugin that FMOD can */
/* register and use. See the documentation and examples on how to make a working plugin. */
/* */
/* ========================================================================================== */
#ifndef _FMOD_DSP_H
#define _FMOD_DSP_H
typedef struct FMOD_DSP_STATE FMOD_DSP_STATE;
/*
DSP callbacks
*/
typedef FMOD_RESULT (F_CALLBACK *FMOD_DSP_CREATECALLBACK) (FMOD_DSP_STATE *dsp_state);
typedef FMOD_RESULT (F_CALLBACK *FMOD_DSP_RELEASECALLBACK) (FMOD_DSP_STATE *dsp_state);
typedef FMOD_RESULT (F_CALLBACK *FMOD_DSP_RESETCALLBACK) (FMOD_DSP_STATE *dsp_state);
typedef FMOD_RESULT (F_CALLBACK *FMOD_DSP_READCALLBACK) (FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int outchannels);
typedef FMOD_RESULT (F_CALLBACK *FMOD_DSP_SETPOSITIONCALLBACK)(FMOD_DSP_STATE *dsp_state, unsigned int pos);
typedef FMOD_RESULT (F_CALLBACK *FMOD_DSP_SETPARAMCALLBACK) (FMOD_DSP_STATE *dsp_state, int index, float value);
typedef FMOD_RESULT (F_CALLBACK *FMOD_DSP_GETPARAMCALLBACK) (FMOD_DSP_STATE *dsp_state, int index, float *value, char *valuestr);
typedef FMOD_RESULT (F_CALLBACK *FMOD_DSP_DIALOGCALLBACK) (FMOD_DSP_STATE *dsp_state, void *hwnd, int show);
/*
[ENUM]
[
[DESCRIPTION]
These definitions can be used for creating FMOD defined special effects or DSP units.
[REMARKS]
To get them to be active, first create the unit, then add it somewhere into the DSP network, either at the front of the network near the soundcard unit to affect the global output (by using System::getDSPHead), or on a single channel (using Channel::getDSPHead).
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
System::createDSPByType
]
*/
typedef enum
{
FMOD_DSP_TYPE_UNKNOWN, /* This unit was created via a non FMOD plugin so has an unknown purpose. */
FMOD_DSP_TYPE_MIXER, /* This unit does nothing but take inputs and mix them together then feed the result to the soundcard unit. */
FMOD_DSP_TYPE_OSCILLATOR, /* This unit generates sine/square/saw/triangle or noise tones. */
FMOD_DSP_TYPE_LOWPASS, /* This unit filters sound using a high quality, resonant lowpass filter algorithm but consumes more CPU time. */
FMOD_DSP_TYPE_ITLOWPASS, /* This unit filters sound using a resonant lowpass filter algorithm that is used in Impulse Tracker, but with limited cutoff range (0 to 8060hz). */
FMOD_DSP_TYPE_HIGHPASS, /* This unit filters sound using a resonant highpass filter algorithm. */
FMOD_DSP_TYPE_ECHO, /* This unit produces an echo on the sound and fades out at the desired rate. */
FMOD_DSP_TYPE_FLANGE, /* This unit produces a flange effect on the sound. */
FMOD_DSP_TYPE_DISTORTION, /* This unit distorts the sound. */
FMOD_DSP_TYPE_NORMALIZE, /* This unit normalizes or amplifies the sound to a certain level. */
FMOD_DSP_TYPE_PARAMEQ, /* This unit attenuates or amplifies a selected frequency range. */
FMOD_DSP_TYPE_PITCHSHIFT, /* This unit bends the pitch of a sound without changing the speed of playback. */
FMOD_DSP_TYPE_CHORUS, /* This unit produces a chorus effect on the sound. */
FMOD_DSP_TYPE_VSTPLUGIN, /* This unit allows the use of Steinberg VST plugins */
FMOD_DSP_TYPE_WINAMPPLUGIN, /* This unit allows the use of Nullsoft Winamp plugins */
FMOD_DSP_TYPE_ITECHO, /* This unit produces an echo on the sound and fades out at the desired rate as is used in Impulse Tracker. */
FMOD_DSP_TYPE_COMPRESSOR, /* This unit implements dynamic compression (linked multichannel, wideband) */
FMOD_DSP_TYPE_SFXREVERB, /* This unit implements SFX reverb */
FMOD_DSP_TYPE_LOWPASS_SIMPLE, /* This unit filters sound using a simple lowpass with no resonance, but has flexible cutoff and is fast. */
FMOD_DSP_TYPE_DELAY, /* This unit produces different delays on individual channels of the sound. */
FMOD_DSP_TYPE_TREMOLO, /* This unit produces a tremolo / chopper effect on the sound. */
FMOD_DSP_TYPE_LADSPAPLUGIN, /* This unit allows the use of LADSPA standard plugins. */
FMOD_DSP_TYPE_HIGHPASS_SIMPLE, /* This unit filters sound using a simple highpass with no resonance, but has flexible cutoff and is fast. */
FMOD_DSP_TYPE_HARDWARE = 1000, /* Offset that platform specific FMOD_HARDWARE DSPs will start at. */
FMOD_DSP_TYPE_FORCEINT = 65536 /* Makes sure this enum is signed 32bit. */
} FMOD_DSP_TYPE;
/*
[STRUCTURE]
[
[DESCRIPTION]
Structure to define a parameter for a DSP unit.
[REMARKS]
Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only. Do not change this value.
Members marked with [w] mean the variable can be written to. The user can set the value.
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
System::createDSP
DSP::setParameter
]
*/
typedef struct FMOD_DSP_PARAMETERDESC
{
float min; /* [w] Minimum value of the parameter (ie 100.0). */
float max; /* [w] Maximum value of the parameter (ie 22050.0). */
float defaultval; /* [w] Default value of parameter. */
char name[16]; /* [w] Name of the parameter to be displayed (ie "Cutoff frequency"). */
char label[16]; /* [w] Short string to be put next to value to denote the unit type (ie "hz"). */
const char *description; /* [w] Description of the parameter to be displayed as a help item / tooltip for this parameter. */
} FMOD_DSP_PARAMETERDESC;
/*
[STRUCTURE]
[
[DESCRIPTION]
When creating a DSP unit, declare one of these and provide the relevant callbacks and name for FMOD to use when it creates and uses a DSP unit of this type.
[REMARKS]
Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only. Do not change this value.
Members marked with [w] mean the variable can be written to. The user can set the value.
IMPORTANT: The 'paramdesc' member should point to static memory, as FMOD references the data internally using the pointer provided. Do not store these parameter description structures on the stack, or in heap memory that is freed while FMOD is using it.
There are 2 different ways to change a parameter in this architecture.
One is to use DSP::setParameter / DSP::getParameter. This is platform independant and is dynamic, so new unknown plugins can have their parameters enumerated and used.
The other is to use DSP::showConfigDialog. This is platform specific and requires a GUI, and will display a dialog box to configure the plugin.
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
System::createDSP
FMOD_DSP_STATE
]
*/
typedef struct FMOD_DSP_DESCRIPTION
{
char name[32]; /* [w] Name of the unit to be displayed in the network. */
unsigned int version; /* [w] Plugin writer's version number. */
int channels; /* [w] Number of channels. Use 0 to process whatever number of channels is currently in the network. >0 would be mostly used if the unit is a unit that only generates sound. */
FMOD_DSP_CREATECALLBACK create; /* [w] Create callback. This is called when DSP unit is created. Can be null. */
FMOD_DSP_RELEASECALLBACK release; /* [w] Release callback. This is called just before the unit is freed so the user can do any cleanup needed for the unit. Can be null. */
FMOD_DSP_RESETCALLBACK reset; /* [w] Reset callback. This is called by the user to reset any history buffers that may need resetting for a filter, when it is to be used or re-used for the first time to its initial clean state. Use to avoid clicks or artifacts. */
FMOD_DSP_READCALLBACK read; /* [w] Read callback. Processing is done here. Can be null. */
FMOD_DSP_SETPOSITIONCALLBACK setposition; /* [w] Set position callback. This is called if the unit wants to update its position info but not process data, or reset a cursor position internally if it is reading data from a certain source. Can be null. */
int numparameters; /* [w] Number of parameters used in this filter. The user finds this with DSP::getNumParameters */
FMOD_DSP_PARAMETERDESC *paramdesc; /* [w] Variable number of parameter structures. */
FMOD_DSP_SETPARAMCALLBACK setparameter; /* [w] This is called when the user calls DSP::setParameter. Can be null. */
FMOD_DSP_GETPARAMCALLBACK getparameter; /* [w] This is called when the user calls DSP::getParameter. Can be null. */
FMOD_DSP_DIALOGCALLBACK config; /* [w] This is called when the user calls DSP::showConfigDialog. Can be used to display a dialog to configure the filter. Can be null. */
int configwidth; /* [w] Width of config dialog graphic if there is one. 0 otherwise.*/
int configheight; /* [w] Height of config dialog graphic if there is one. 0 otherwise.*/
void *userdata; /* [w] Optional. Specify 0 to ignore. This is user data to be attached to the DSP unit during creation. Access via DSP::getUserData. */
} FMOD_DSP_DESCRIPTION;
/*
[STRUCTURE]
[
[DESCRIPTION]
DSP plugin structure that is passed into each callback.
[REMARKS]
Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only. Do not change this value.
Members marked with [w] mean the variable can be written to. The user can set the value.
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
FMOD_DSP_DESCRIPTION
]
*/
struct FMOD_DSP_STATE
{
FMOD_DSP *instance; /* [r] Handle to the DSP hand the user created. Not to be modified. C++ users cast to FMOD::DSP to use. */
void *plugindata; /* [w] Plugin writer created data the output author wants to attach to this object. */
unsigned short speakermask; /* [w] Specifies which speakers the DSP effect is active on */
};
/*
===================================================================================================
FMOD built in effect parameters.
Use DSP::setParameter with these enums for the 'index' parameter.
===================================================================================================
*/
/*
[ENUM]
[
[DESCRIPTION]
Parameter types for the FMOD_DSP_TYPE_OSCILLATOR filter.
[REMARKS]
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
DSP::setParameter
DSP::getParameter
FMOD_DSP_TYPE
]
*/
typedef enum
{
FMOD_DSP_OSCILLATOR_TYPE, /* Waveform type. 0 = sine. 1 = square. 2 = sawup. 3 = sawdown. 4 = triangle. 5 = noise. */
FMOD_DSP_OSCILLATOR_RATE /* Frequency of the sinewave in hz. 1.0 to 22000.0. Default = 220.0. */
} FMOD_DSP_OSCILLATOR;
/*
[ENUM]
[
[DESCRIPTION]
Parameter types for the FMOD_DSP_TYPE_LOWPASS filter.
[REMARKS]
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
DSP::setParameter
DSP::getParameter
FMOD_DSP_TYPE
]
*/
typedef enum
{
FMOD_DSP_LOWPASS_CUTOFF, /* Lowpass cutoff frequency in hz. 10.0 to 22000.0. Default = 5000.0. */
FMOD_DSP_LOWPASS_RESONANCE /* Lowpass resonance Q value. 1.0 to 10.0. Default = 1.0. */
} FMOD_DSP_LOWPASS;
/*
[ENUM]
[
[DESCRIPTION]
Parameter types for the FMOD_DSP_TYPE_ITLOWPASS filter.
This is different to the default FMOD_DSP_TYPE_ITLOWPASS filter in that it uses a different quality algorithm and is
the filter used to produce the correct sounding playback in .IT files.
FMOD Ex's .IT playback uses this filter.
[REMARKS]
Note! This filter actually has a limited cutoff frequency below the specified maximum, due to its limited design,
so for a more open range filter use FMOD_DSP_LOWPASS or if you don't mind not having resonance,
FMOD_DSP_LOWPASS_SIMPLE.
The effective maximum cutoff is about 8060hz.
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
DSP::setParameter
DSP::getParameter
FMOD_DSP_TYPE
]
*/
typedef enum
{
FMOD_DSP_ITLOWPASS_CUTOFF, /* Lowpass cutoff frequency in hz. 1.0 to 22000.0. Default = 5000.0/ */
FMOD_DSP_ITLOWPASS_RESONANCE /* Lowpass resonance Q value. 0.0 to 127.0. Default = 1.0. */
} FMOD_DSP_ITLOWPASS;
/*
[ENUM]
[
[DESCRIPTION]
Parameter types for the FMOD_DSP_TYPE_HIGHPASS filter.
[REMARKS]
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
DSP::setParameter
DSP::getParameter
FMOD_DSP_TYPE
]
*/
typedef enum
{
FMOD_DSP_HIGHPASS_CUTOFF, /* Highpass cutoff frequency in hz. 1.0 to output 22000.0. Default = 5000.0. */
FMOD_DSP_HIGHPASS_RESONANCE /* Highpass resonance Q value. 1.0 to 10.0. Default = 1.0. */
} FMOD_DSP_HIGHPASS;
/*
[ENUM]
[
[DESCRIPTION]
Parameter types for the FMOD_DSP_TYPE_ECHO filter.
[REMARKS]
Note. Every time the delay is changed, the plugin re-allocates the echo buffer. This means the echo will dissapear at that time while it refills its new buffer.
Larger echo delays result in larger amounts of memory allocated.
'<i>maxchannels</i>' also dictates the amount of memory allocated. By default, the maxchannels value is 0. If FMOD is set to stereo, the echo unit will allocate enough memory for 2 channels. If it is 5.1, it will allocate enough memory for a 6 channel echo, etc.
If the echo effect is only ever applied to the global mix (ie it was added with System::addDSP), then 0 is the value to set as it will be enough to handle all speaker modes.
When the echo is added to a channel (ie Channel::addDSP) then the channel count that comes in could be anything from 1 to 8 possibly. It is only in this case where you might want to increase the channel count above the output's channel count.
If a channel echo is set to a lower number than the sound's channel count that is coming in, it will not echo the sound.
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
DSP::setParameter
DSP::getParameter
FMOD_DSP_TYPE
]
*/
typedef enum
{
FMOD_DSP_ECHO_DELAY, /* Echo delay in ms. 10 to 5000. Default = 500. */
FMOD_DSP_ECHO_DECAYRATIO, /* Echo decay per delay. 0 to 1. 1.0 = No decay, 0.0 = total decay (ie simple 1 line delay). Default = 0.5. */
FMOD_DSP_ECHO_MAXCHANNELS, /* Maximum channels supported. 0 to 16. 0 = same as fmod's default output polyphony, 1 = mono, 2 = stereo etc. See remarks for more. Default = 0. It is suggested to leave at 0! */
FMOD_DSP_ECHO_DRYMIX, /* Volume of original signal to pass to output. 0.0 to 1.0. Default = 1.0. */
FMOD_DSP_ECHO_WETMIX /* Volume of echo signal to pass to output. 0.0 to 1.0. Default = 1.0. */
} FMOD_DSP_ECHO;
/*
[ENUM]
[
[DESCRIPTION]
Parameter types for the FMOD_DSP_TYPE_DELAY filter.
[REMARKS]
Note. Every time MaxDelay is changed, the plugin re-allocates the delay buffer. This means the delay will dissapear at that time while it refills its new buffer.
A larger MaxDelay results in larger amounts of memory allocated.
Channel delays above MaxDelay will be clipped to MaxDelay and the delay buffer will not be resized.
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
DSP::setParameter
DSP::getParameter
FMOD_DSP_TYPE
]
*/
typedef enum
{
FMOD_DSP_DELAY_CH0, /* Channel #0 Delay in ms. 0 to 10000. Default = 0. */
FMOD_DSP_DELAY_CH1, /* Channel #1 Delay in ms. 0 to 10000. Default = 0. */
FMOD_DSP_DELAY_CH2, /* Channel #2 Delay in ms. 0 to 10000. Default = 0. */
FMOD_DSP_DELAY_CH3, /* Channel #3 Delay in ms. 0 to 10000. Default = 0. */
FMOD_DSP_DELAY_CH4, /* Channel #4 Delay in ms. 0 to 10000. Default = 0. */
FMOD_DSP_DELAY_CH5, /* Channel #5 Delay in ms. 0 to 10000. Default = 0. */
FMOD_DSP_DELAY_CH6, /* Channel #6 Delay in ms. 0 to 10000. Default = 0. */
FMOD_DSP_DELAY_CH7, /* Channel #7 Delay in ms. 0 to 10000. Default = 0. */
FMOD_DSP_DELAY_CH8, /* Channel #8 Delay in ms. 0 to 10000. Default = 0. */
FMOD_DSP_DELAY_CH9, /* Channel #9 Delay in ms. 0 to 10000. Default = 0. */
FMOD_DSP_DELAY_CH10, /* Channel #10 Delay in ms. 0 to 10000. Default = 0. */
FMOD_DSP_DELAY_CH11, /* Channel #11 Delay in ms. 0 to 10000. Default = 0. */
FMOD_DSP_DELAY_CH12, /* Channel #12 Delay in ms. 0 to 10000. Default = 0. */
FMOD_DSP_DELAY_CH13, /* Channel #13 Delay in ms. 0 to 10000. Default = 0. */
FMOD_DSP_DELAY_CH14, /* Channel #14 Delay in ms. 0 to 10000. Default = 0. */
FMOD_DSP_DELAY_CH15, /* Channel #15 Delay in ms. 0 to 10000. Default = 0. */
FMOD_DSP_DELAY_MAXDELAY /* Maximum delay in ms. 0 to 10000. Default = 10. */
} FMOD_DSP_DELAY;
/*
[ENUM]
[
[DESCRIPTION]
Parameter types for the FMOD_DSP_TYPE_FLANGE filter.
[REMARKS]
Flange is an effect where the signal is played twice at the same time, and one copy slides back and forth creating a whooshing or flanging effect.
As there are 2 copies of the same signal, by default each signal is given 50% mix, so that the total is not louder than the original unaffected signal.
Flange depth is a percentage of a 10ms shift from the original signal. Anything above 10ms is not considered flange because to the ear it begins to 'echo' so 10ms is the highest value possible.
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
DSP::setParameter
DSP::getParameter
FMOD_DSP_TYPE
]
*/
typedef enum
{
FMOD_DSP_FLANGE_DRYMIX, /* Volume of original signal to pass to output. 0.0 to 1.0. Default = 0.45. */
FMOD_DSP_FLANGE_WETMIX, /* Volume of flange signal to pass to output. 0.0 to 1.0. Default = 0.55. */
FMOD_DSP_FLANGE_DEPTH, /* Flange depth (percentage of 40ms delay). 0.01 to 1.0. Default = 1.0. */
FMOD_DSP_FLANGE_RATE /* Flange speed in hz. 0.0 to 20.0. Default = 0.1. */
} FMOD_DSP_FLANGE;
/*
[ENUM]
[
[DESCRIPTION]
Parameter types for the FMOD_DSP_TYPE_TREMOLO filter.
[REMARKS]
The tremolo effect varies the amplitude of a sound. Depending on the settings, this unit can produce a tremolo, chopper or auto-pan effect.
The shape of the LFO (low freq. oscillator) can morphed between sine, triangle and sawtooth waves using the FMOD_DSP_TREMOLO_SHAPE and FMOD_DSP_TREMOLO_SKEW parameters.
FMOD_DSP_TREMOLO_DUTY and FMOD_DSP_TREMOLO_SQUARE are useful for a chopper-type effect where the first controls the on-time duration and second controls the flatness of the envelope.
FMOD_DSP_TREMOLO_SPREAD varies the LFO phase between channels to get an auto-pan effect. This works best with a sine shape LFO.
The LFO can be synchronized using the FMOD_DSP_TREMOLO_PHASE parameter which sets its instantaneous phase.
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
DSP::setParameter
DSP::getParameter
FMOD_DSP_TYPE
]
*/
typedef enum
{
FMOD_DSP_TREMOLO_FREQUENCY, /* LFO frequency in Hz. 0.1 to 20. Default = 4. */
FMOD_DSP_TREMOLO_DEPTH, /* Tremolo depth. 0 to 1. Default = 0. */
FMOD_DSP_TREMOLO_SHAPE, /* LFO shape morph between triangle and sine. 0 to 1. Default = 0. */
FMOD_DSP_TREMOLO_SKEW, /* Time-skewing of LFO cycle. -1 to 1. Default = 0. */
FMOD_DSP_TREMOLO_DUTY, /* LFO on-time. 0 to 1. Default = 0.5. */
FMOD_DSP_TREMOLO_SQUARE, /* Flatness of the LFO shape. 0 to 1. Default = 0. */
FMOD_DSP_TREMOLO_PHASE, /* Instantaneous LFO phase. 0 to 1. Default = 0. */
FMOD_DSP_TREMOLO_SPREAD /* Rotation / auto-pan effect. -1 to 1. Default = 0. */
} FMOD_DSP_TREMOLO;
/*
[ENUM]
[
[DESCRIPTION]
Parameter types for the FMOD_DSP_TYPE_DISTORTION filter.
[REMARKS]
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
DSP::setParameter
DSP::getParameter
FMOD_DSP_TYPE
]
*/
typedef enum
{
FMOD_DSP_DISTORTION_LEVEL /* Distortion value. 0.0 to 1.0. Default = 0.5. */
} FMOD_DSP_DISTORTION;
/*
[ENUM]
[
[DESCRIPTION]
Parameter types for the FMOD_DSP_TYPE_NORMALIZE filter.
[REMARKS]
Normalize amplifies the sound based on the maximum peaks within the signal.
For example if the maximum peaks in the signal were 50% of the bandwidth, it would scale the whole sound by 2.
The lower threshold value makes the normalizer ignores peaks below a certain point, to avoid over-amplification if a loud signal suddenly came in, and also to avoid amplifying to maximum things like background hiss.
Because FMOD is a realtime audio processor, it doesn't have the luxury of knowing the peak for the whole sound (ie it can't see into the future), so it has to process data as it comes in.
To avoid very sudden changes in volume level based on small samples of new data, fmod fades towards the desired amplification which makes for smooth gain control. The fadetime parameter can control this.
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
DSP::setParameter
DSP::getParameter
FMOD_DSP_TYPE
]
*/
typedef enum
{
FMOD_DSP_NORMALIZE_FADETIME, /* Time to ramp the silence to full in ms. 0.0 to 20000.0. Default = 5000.0. */
FMOD_DSP_NORMALIZE_THRESHHOLD, /* Lower volume range threshold to ignore. 0.0 to 1.0. Default = 0.1. Raise higher to stop amplification of very quiet signals. */
FMOD_DSP_NORMALIZE_MAXAMP /* Maximum amplification allowed. 1.0 to 100000.0. Default = 20.0. 1.0 = no amplifaction, higher values allow more boost. */
} FMOD_DSP_NORMALIZE;
/*
[ENUM]
[
[DESCRIPTION]
Parameter types for the FMOD_DSP_TYPE_PARAMEQ filter.
[REMARKS]
Parametric EQ is a bandpass filter that attenuates or amplifies a selected frequency and its neighbouring frequencies.
To create a multi-band EQ create multiple FMOD_DSP_TYPE_PARAMEQ units and set each unit to different frequencies, for example 1000hz, 2000hz, 4000hz, 8000hz, 16000hz with a range of 1 octave each.
When a frequency has its gain set to 1.0, the sound will be unaffected and represents the original signal exactly.
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
DSP::setParameter
DSP::getParameter
FMOD_DSP_TYPE
]
*/
typedef enum
{
FMOD_DSP_PARAMEQ_CENTER, /* Frequency center. 20.0 to 22000.0. Default = 8000.0. */
FMOD_DSP_PARAMEQ_BANDWIDTH, /* Octave range around the center frequency to filter. 0.2 to 5.0. Default = 1.0. */
FMOD_DSP_PARAMEQ_GAIN /* Frequency Gain. 0.05 to 3.0. Default = 1.0. */
} FMOD_DSP_PARAMEQ;
/*
[ENUM]
[
[DESCRIPTION]
Parameter types for the FMOD_DSP_TYPE_PITCHSHIFT filter.
[REMARKS]
This pitch shifting unit can be used to change the pitch of a sound without speeding it up or slowing it down.
It can also be used for time stretching or scaling, for example if the pitch was doubled, and the frequency of the sound was halved, the pitch of the sound would sound correct but it would be twice as slow.
<b>Warning!</b> This filter is very computationally expensive! Similar to a vocoder, it requires several overlapping FFT and IFFT's to produce smooth output, and can require around 440mhz for 1 stereo 48khz signal using the default settings.
Reducing the signal to mono will half the cpu usage.
Reducing this will lower audio quality, but what settings to use are largely dependant on the sound being played. A noisy polyphonic signal will need higher fft size compared to a speaking voice for example.
This pitch shifter is based on the pitch shifter code at http://www.dspdimension.com, written by Stephan M. Bernsee.
The original code is COPYRIGHT 1999-2003 Stephan M. Bernsee <smb@dspdimension.com>.
'<i>maxchannels</i>' dictates the amount of memory allocated. By default, the maxchannels value is 0. If FMOD is set to stereo, the pitch shift unit will allocate enough memory for 2 channels. If it is 5.1, it will allocate enough memory for a 6 channel pitch shift, etc.
If the pitch shift effect is only ever applied to the global mix (ie it was added with System::addDSP), then 0 is the value to set as it will be enough to handle all speaker modes.
When the pitch shift is added to a channel (ie Channel::addDSP) then the channel count that comes in could be anything from 1 to 8 possibly. It is only in this case where you might want to increase the channel count above the output's channel count.
If a channel pitch shift is set to a lower number than the sound's channel count that is coming in, it will not pitch shift the sound.
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
DSP::setParameter
DSP::getParameter
FMOD_DSP_TYPE
]
*/
typedef enum
{
FMOD_DSP_PITCHSHIFT_PITCH, /* Pitch value. 0.5 to 2.0. Default = 1.0. 0.5 = one octave down, 2.0 = one octave up. 1.0 does not change the pitch. */
FMOD_DSP_PITCHSHIFT_FFTSIZE, /* FFT window size. 256, 512, 1024, 2048, 4096. Default = 1024. Increase this to reduce 'smearing'. This effect is a warbling sound similar to when an mp3 is encoded at very low bitrates. */
FMOD_DSP_PITCHSHIFT_OVERLAP, /* Removed. Do not use. FMOD now uses 4 overlaps and cannot be changed. */
FMOD_DSP_PITCHSHIFT_MAXCHANNELS /* Maximum channels supported. 0 to 16. 0 = same as fmod's default output polyphony, 1 = mono, 2 = stereo etc. See remarks for more. Default = 0. It is suggested to leave at 0! */
} FMOD_DSP_PITCHSHIFT;
/*
[ENUM]
[
[DESCRIPTION]
Parameter types for the FMOD_DSP_TYPE_CHORUS filter.
[REMARKS]
Chrous is an effect where the sound is more 'spacious' due to 1 to 3 versions of the sound being played along side the original signal but with the pitch of each copy modulating on a sine wave.
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
DSP::setParameter
DSP::getParameter
FMOD_DSP_TYPE
]
*/
typedef enum
{
FMOD_DSP_CHORUS_DRYMIX, /* Volume of original signal to pass to output. 0.0 to 1.0. Default = 0.5. */
FMOD_DSP_CHORUS_WETMIX1, /* Volume of 1st chorus tap. 0.0 to 1.0. Default = 0.5. */
FMOD_DSP_CHORUS_WETMIX2, /* Volume of 2nd chorus tap. This tap is 90 degrees out of phase of the first tap. 0.0 to 1.0. Default = 0.5. */
FMOD_DSP_CHORUS_WETMIX3, /* Volume of 3rd chorus tap. This tap is 90 degrees out of phase of the second tap. 0.0 to 1.0. Default = 0.5. */
FMOD_DSP_CHORUS_DELAY, /* Chorus delay in ms. 0.1 to 100.0. Default = 40.0 ms. */
FMOD_DSP_CHORUS_RATE, /* Chorus modulation rate in hz. 0.0 to 20.0. Default = 0.8 hz. */
FMOD_DSP_CHORUS_DEPTH /* Chorus modulation depth. 0.0 to 1.0. Default = 0.03. */
} FMOD_DSP_CHORUS;
/*
[ENUM]
[
[DESCRIPTION]
Parameter types for the FMOD_DSP_TYPE_ITECHO filter.
This is effectively a software based echo filter that emulates the DirectX DMO echo effect. Impulse tracker files can support this, and FMOD will produce the effect on ANY platform, not just those that support DirectX effects!
[REMARKS]
Note. Every time the delay is changed, the plugin re-allocates the echo buffer. This means the echo will dissapear at that time while it refills its new buffer.
Larger echo delays result in larger amounts of memory allocated.
As this is a stereo filter made mainly for IT playback, it is targeted for stereo signals.
With mono signals only the FMOD_DSP_ITECHO_LEFTDELAY is used.
For multichannel signals (>2) there will be no echo on those channels.
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
DSP::SetParameter
DSP::GetParameter
FMOD_DSP_TYPE
System::addDSP
]
*/
typedef enum
{
FMOD_DSP_ITECHO_WETDRYMIX, /* Ratio of wet (processed) signal to dry (unprocessed) signal. Must be in the range from 0.0 through 100.0 (all wet). The default value is 50. */
FMOD_DSP_ITECHO_FEEDBACK, /* Percentage of output fed back into input, in the range from 0.0 through 100.0. The default value is 50. */
FMOD_DSP_ITECHO_LEFTDELAY, /* Delay for left channel, in milliseconds, in the range from 1.0 through 2000.0. The default value is 500 ms. */
FMOD_DSP_ITECHO_RIGHTDELAY, /* Delay for right channel, in milliseconds, in the range from 1.0 through 2000.0. The default value is 500 ms. */
FMOD_DSP_ITECHO_PANDELAY /* Value that specifies whether to swap left and right delays with each successive echo. The default value is zero, meaning no swap. Possible values are defined as 0.0 (equivalent to FALSE) and 1.0 (equivalent to TRUE). CURRENTLY NOT SUPPORTED. */
} FMOD_DSP_ITECHO;
/*
[ENUM]
[
[DESCRIPTION]
Parameter types for the FMOD_DSP_TYPE_COMPRESSOR unit.
This is a simple linked multichannel software limiter that is uniform across the whole spectrum.
[REMARKS]
The limiter is not guaranteed to catch every peak above the threshold level,
because it cannot apply gain reduction instantaneously - the time delay is
determined by the attack time. However setting the attack time too short will
distort the sound, so it is a compromise. High level peaks can be avoided by
using a short attack time - but not too short, and setting the threshold a few
decibels below the critical level.
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
DSP::SetParameter
DSP::GetParameter
FMOD_DSP_TYPE
System::addDSP
]
*/
typedef enum
{
FMOD_DSP_COMPRESSOR_THRESHOLD, /* Threshold level (dB) in the range from -60 through 0. The default value is 0. */
FMOD_DSP_COMPRESSOR_ATTACK, /* Gain reduction attack time (milliseconds), in the range from 10 through 200. The default value is 50. */
FMOD_DSP_COMPRESSOR_RELEASE, /* Gain reduction release time (milliseconds), in the range from 20 through 1000. The default value is 50. */
FMOD_DSP_COMPRESSOR_GAINMAKEUP /* Make-up gain (dB) applied after limiting, in the range from 0 through 30. The default value is 0. */
} FMOD_DSP_COMPRESSOR;
/*
[ENUM]
[
[DESCRIPTION]
Parameter types for the FMOD_DSP_TYPE_SFXREVERB unit.
[REMARKS]
This is a high quality I3DL2 based reverb.
On top of the I3DL2 property set, "Dry Level" is also included to allow the dry mix to be changed.
These properties can be set with presets in FMOD_REVERB_PRESETS.
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
DSP::SetParameter
DSP::GetParameter
FMOD_DSP_TYPE
System::addDSP
FMOD_REVERB_PRESETS
]
*/
typedef enum
{
FMOD_DSP_SFXREVERB_DRYLEVEL, /* Dry Level : Mix level of dry signal in output in mB. Ranges from -10000.0 to 0.0. Default is 0. */
FMOD_DSP_SFXREVERB_ROOM, /* Room : Room effect level at low frequencies in mB. Ranges from -10000.0 to 0.0. Default is -10000.0. */
FMOD_DSP_SFXREVERB_ROOMHF, /* Room HF : Room effect high-frequency level re. low frequency level in mB. Ranges from -10000.0 to 0.0. Default is 0.0. */
FMOD_DSP_SFXREVERB_DECAYTIME, /* Decay Time : Reverberation decay time at low-frequencies in seconds. Ranges from 0.1 to 20.0. Default is 1.0. */
FMOD_DSP_SFXREVERB_DECAYHFRATIO, /* Decay HF Ratio : High-frequency to low-frequency decay time ratio. Ranges from 0.1 to 2.0. Default is 0.5. */
FMOD_DSP_SFXREVERB_REFLECTIONSLEVEL, /* Reflections : Early reflections level relative to room effect in mB. Ranges from -10000.0 to 1000.0. Default is -10000.0. */
FMOD_DSP_SFXREVERB_REFLECTIONSDELAY, /* Reflect Delay : Delay time of first reflection in seconds. Ranges from 0.0 to 0.3. Default is 0.02. */
FMOD_DSP_SFXREVERB_REVERBLEVEL, /* Reverb : Late reverberation level relative to room effect in mB. Ranges from -10000.0 to 2000.0. Default is 0.0. */
FMOD_DSP_SFXREVERB_REVERBDELAY, /* Reverb Delay : Late reverberation delay time relative to first reflection in seconds. Ranges from 0.0 to 0.1. Default is 0.04. */
FMOD_DSP_SFXREVERB_DIFFUSION, /* Diffusion : Reverberation diffusion (echo density) in percent. Ranges from 0.0 to 100.0. Default is 100.0. */
FMOD_DSP_SFXREVERB_DENSITY, /* Density : Reverberation density (modal density) in percent. Ranges from 0.0 to 100.0. Default is 100.0. */
FMOD_DSP_SFXREVERB_HFREFERENCE, /* HF Reference : Reference high frequency in Hz. Ranges from 20.0 to 20000.0. Default is 5000.0. */
FMOD_DSP_SFXREVERB_ROOMLF, /* Room LF : Room effect low-frequency level in mB. Ranges from -10000.0 to 0.0. Default is 0.0. */
FMOD_DSP_SFXREVERB_LFREFERENCE /* LF Reference : Reference low-frequency in Hz. Ranges from 20.0 to 1000.0. Default is 250.0. */
} FMOD_DSP_SFXREVERB;
/*
[ENUM]
[
[DESCRIPTION]
Parameter types for the FMOD_DSP_TYPE_LOWPASS_SIMPLE filter.
This is a very simple low pass filter, based on two single-pole RC time-constant modules.
The emphasis is on speed rather than accuracy, so this should not be used for task requiring critical filtering.
[REMARKS]
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
DSP::setParameter
DSP::getParameter
FMOD_DSP_TYPE
]
*/
typedef enum
{
FMOD_DSP_LOWPASS_SIMPLE_CUTOFF /* Lowpass cutoff frequency in hz. 10.0 to 22000.0. Default = 5000.0 */
} FMOD_DSP_LOWPASS_SIMPLE;
/*
[ENUM]
[
[DESCRIPTION]
Parameter types for the FMOD_DSP_TYPE_HIGHPASS_SIMPLE filter.
This is a very simple single-order high pass filter.
The emphasis is on speed rather than accuracy, so this should not be used for task requiring critical filtering.
[REMARKS]
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
DSP::setParameter
DSP::getParameter
FMOD_DSP_TYPE
]
*/
typedef enum
{
FMOD_DSP_HIGHPASS_SIMPLE_CUTOFF /* Highpass cutoff frequency in hz. 10.0 to 22000.0. Default = 1000.0 */
} FMOD_DSP_HIGHPASS_SIMPLE;
#endif

View File

@ -0,0 +1,123 @@
/* ============================================================================================== */
/* FMOD Ex - Error string header file. Copyright (c), Firelight Technologies Pty, Ltd. 2004-2016. */
/* */
/* Use this header if you want to store or display a string version / english explanation of */
/* the FMOD error codes. */
/* */
/* ============================================================================================== */
#ifndef _FMOD_ERRORS_H
#define _FMOD_ERRORS_H
#include "fmod.h"
#ifdef __GNUC__
static const char *FMOD_ErrorString(FMOD_RESULT errcode) __attribute__((unused));
#endif
static const char *FMOD_ErrorString(FMOD_RESULT errcode)
{
switch (errcode)
{
case FMOD_ERR_ALREADYLOCKED: return "Tried to call lock a second time before unlock was called. ";
case FMOD_ERR_BADCOMMAND: return "Tried to call a function on a data type that does not allow this type of functionality (ie calling Sound::lock on a streaming sound). ";
case FMOD_ERR_CDDA_DRIVERS: return "Neither NTSCSI nor ASPI could be initialised. ";
case FMOD_ERR_CDDA_INIT: return "An error occurred while initialising the CDDA subsystem. ";
case FMOD_ERR_CDDA_INVALID_DEVICE: return "Couldn't find the specified device. ";
case FMOD_ERR_CDDA_NOAUDIO: return "No audio tracks on the specified disc. ";
case FMOD_ERR_CDDA_NODEVICES: return "No CD/DVD devices were found. ";
case FMOD_ERR_CDDA_NODISC: return "No disc present in the specified drive. ";
case FMOD_ERR_CDDA_READ: return "A CDDA read error occurred. ";
case FMOD_ERR_CHANNEL_ALLOC: return "Error trying to allocate a channel. ";
case FMOD_ERR_CHANNEL_STOLEN: return "The specified channel has been reused to play another sound. ";
case FMOD_ERR_COM: return "A Win32 COM related error occured. COM failed to initialize or a QueryInterface failed meaning a Windows codec or driver was not installed properly. ";
case FMOD_ERR_DMA: return "DMA Failure. See debug output for more information. ";
case FMOD_ERR_DSP_CONNECTION: return "DSP connection error. Connection possibly caused a cyclic dependancy. Or tried to connect a tree too many units deep (more than 128). ";
case FMOD_ERR_DSP_FORMAT: return "DSP Format error. A DSP unit may have attempted to connect to this network with the wrong format. ";
case FMOD_ERR_DSP_NOTFOUND: return "DSP connection error. Couldn't find the DSP unit specified. ";
case FMOD_ERR_DSP_RUNNING: return "DSP error. Cannot perform this operation while the network is in the middle of running. This will most likely happen if a connection or disconnection is attempted in a DSP callback. ";
case FMOD_ERR_DSP_TOOMANYCONNECTIONS: return "DSP connection error. The unit being connected to or disconnected should only have 1 input or output. ";
case FMOD_ERR_EVENT_ALREADY_LOADED: return "The specified project or bank has already been loaded. Having multiple copies of the same project loaded simultaneously is forbidden. ";
case FMOD_ERR_EVENT_FAILED: return "An Event failed to be retrieved, most likely due to 'just fail' being specified as the max playbacks behavior. ";
case FMOD_ERR_EVENT_GUIDCONFLICT: return "An event with the same GUID already exists. ";
case FMOD_ERR_EVENT_INFOONLY: return "Can't execute this command on an EVENT_INFOONLY event. ";
case FMOD_ERR_EVENT_INTERNAL: return "An error occured that wasn't supposed to. See debug log for reason. ";
case FMOD_ERR_EVENT_MAXSTREAMS: return "Event failed because 'Max streams' was hit when FMOD_EVENT_INIT_FAIL_ON_MAXSTREAMS was specified. ";
case FMOD_ERR_EVENT_MISMATCH: return "FSB mismatches the FEV it was compiled with, the stream/sample mode it was meant to be created with was different, or the FEV was built for a different platform. ";
case FMOD_ERR_EVENT_NAMECONFLICT: return "A category with the same name already exists. ";
case FMOD_ERR_EVENT_NEEDSSIMPLE: return "Tried to call a function on a complex event that's only supported by simple events. ";
case FMOD_ERR_EVENT_NOTFOUND: return "The requested event, event group, event category or event property could not be found. ";
case FMOD_ERR_FILE_BAD: return "Error loading file. ";
case FMOD_ERR_FILE_COULDNOTSEEK: return "Couldn't perform seek operation. This is a limitation of the medium (ie netstreams) or the file format. ";
case FMOD_ERR_FILE_DISKEJECTED: return "Media was ejected while reading. ";
case FMOD_ERR_FILE_EOF: return "End of file unexpectedly reached while trying to read essential data (truncated data?). ";
case FMOD_ERR_FILE_NOTFOUND: return "File not found. ";
case FMOD_ERR_FILE_UNWANTED: return "Unwanted file access occured. ";
case FMOD_ERR_FORMAT: return "Unsupported file or audio format. ";
case FMOD_ERR_HTTP: return "A HTTP error occurred. This is a catch-all for HTTP errors not listed elsewhere. ";
case FMOD_ERR_HTTP_ACCESS: return "The specified resource requires authentication or is forbidden. ";
case FMOD_ERR_HTTP_PROXY_AUTH: return "Proxy authentication is required to access the specified resource. ";
case FMOD_ERR_HTTP_SERVER_ERROR: return "A HTTP server error occurred. ";
case FMOD_ERR_HTTP_TIMEOUT: return "The HTTP request timed out. ";
case FMOD_ERR_INITIALIZATION: return "FMOD was not initialized correctly to support this function. ";
case FMOD_ERR_INITIALIZED: return "Cannot call this command after System::init. ";
case FMOD_ERR_INTERNAL: return "An error occured that wasn't supposed to. Contact support. ";
case FMOD_ERR_INVALID_ADDRESS: return "On Xbox 360, this memory address passed to FMOD must be physical, (ie allocated with XPhysicalAlloc.) ";
case FMOD_ERR_INVALID_FLOAT: return "Value passed in was a NaN, Inf or denormalized float. ";
case FMOD_ERR_INVALID_HANDLE: return "An invalid object handle was used. ";
case FMOD_ERR_INVALID_PARAM: return "An invalid parameter was passed to this function. ";
case FMOD_ERR_INVALID_POSITION: return "An invalid seek position was passed to this function. ";
case FMOD_ERR_INVALID_SPEAKER: return "An invalid speaker was passed to this function based on the current speaker mode. ";
case FMOD_ERR_INVALID_SYNCPOINT: return "The syncpoint did not come from this sound handle. ";
case FMOD_ERR_INVALID_VECTOR: return "The vectors passed in are not unit length, or perpendicular. ";
case FMOD_ERR_MAXAUDIBLE: return "Reached maximum audible playback count for this sound's soundgroup. ";
case FMOD_ERR_MEMORY: return "Not enough memory or resources. ";
case FMOD_ERR_MEMORY_CANTPOINT: return "Can't use FMOD_OPENMEMORY_POINT on non PCM source data, or non mp3/xma/adpcm data if FMOD_CREATECOMPRESSEDSAMPLE was used. ";
case FMOD_ERR_MEMORY_SRAM: return "Not enough memory or resources on console sound ram. ";
case FMOD_ERR_MUSIC_NOCALLBACK: return "The music callback is required, but it has not been set. ";
case FMOD_ERR_MUSIC_NOTFOUND: return "The requested music entity could not be found. ";
case FMOD_ERR_MUSIC_UNINITIALIZED: return "Music system is not initialized probably because no music data is loaded. ";
case FMOD_ERR_NEEDS2D: return "Tried to call a command on a 3d sound when the command was meant for 2d sound. ";
case FMOD_ERR_NEEDS3D: return "Tried to call a command on a 2d sound when the command was meant for 3d sound. ";
case FMOD_ERR_NEEDSHARDWARE: return "Tried to use a feature that requires hardware support. (ie trying to play a GCADPCM compressed sound in software on Wii). ";
case FMOD_ERR_NEEDSSOFTWARE: return "Tried to use a feature that requires the software engine. Software engine has either been turned off, or command was executed on a hardware channel which does not support this feature. ";
case FMOD_ERR_NET_CONNECT: return "Couldn't connect to the specified host. ";
case FMOD_ERR_NET_SOCKET_ERROR: return "A socket error occurred. This is a catch-all for socket-related errors not listed elsewhere. ";
case FMOD_ERR_NET_URL: return "The specified URL couldn't be resolved. ";
case FMOD_ERR_NET_WOULD_BLOCK: return "Operation on a non-blocking socket could not complete immediately. ";
case FMOD_ERR_NOTREADY: return "Operation could not be performed because specified sound/DSP connection is not ready. ";
case FMOD_ERR_OUTPUT_ALLOCATED: return "Error initializing output device, but more specifically, the output device is already in use and cannot be reused. ";
case FMOD_ERR_OUTPUT_CREATEBUFFER: return "Error creating hardware sound buffer. ";
case FMOD_ERR_OUTPUT_DRIVERCALL: return "A call to a standard soundcard driver failed, which could possibly mean a bug in the driver or resources were missing or exhausted. ";
case FMOD_ERR_OUTPUT_ENUMERATION: return "Error enumerating the available driver list. List may be inconsistent due to a recent device addition or removal. ";
case FMOD_ERR_OUTPUT_FORMAT: return "Soundcard does not support the minimum features needed for this soundsystem (16bit stereo output). ";
case FMOD_ERR_OUTPUT_INIT: return "Error initializing output device. ";
case FMOD_ERR_OUTPUT_NOHARDWARE: return "FMOD_HARDWARE was specified but the sound card does not have the resources necessary to play it. ";
case FMOD_ERR_OUTPUT_NOSOFTWARE: return "Attempted to create a software sound but no software channels were specified in System::init. ";
case FMOD_ERR_PAN: return "Panning only works with mono or stereo sound sources. ";
case FMOD_ERR_PLUGIN: return "An unspecified error has been returned from a 3rd party plugin. ";
case FMOD_ERR_PLUGIN_INSTANCES: return "The number of allowed instances of a plugin has been exceeded. ";
case FMOD_ERR_PLUGIN_MISSING: return "A requested output, dsp unit type or codec was not available. ";
case FMOD_ERR_PLUGIN_RESOURCE: return "A resource that the plugin requires cannot be found. (ie the DLS file for MIDI playback or other DLLs that it needs to load) ";
case FMOD_ERR_PRELOADED: return "The specified sound is still in use by the event system, call EventSystem::unloadFSB before trying to release it. ";
case FMOD_ERR_PROGRAMMERSOUND: return "The specified sound is still in use by the event system, wait for the event which is using it finish with it. ";
case FMOD_ERR_RECORD: return "An error occured trying to initialize the recording device. ";
case FMOD_ERR_REVERB_INSTANCE: return "Specified instance in FMOD_REVERB_PROPERTIES couldn't be set. Most likely because it is an invalid instance number or the reverb doesnt exist. ";
case FMOD_ERR_SUBSOUNDS: return "The error occured because the sound referenced contains subsounds when it shouldn't have, or it doesn't contain subsounds when it should have. The operation may also not be able to be performed on a parent sound, or a parent sound was played without setting up a sentence first. ";
case FMOD_ERR_SUBSOUND_ALLOCATED: return "This subsound is already being used by another sound, you cannot have more than one parent to a sound. Null out the other parent's entry first. ";
case FMOD_ERR_SUBSOUND_CANTMOVE: return "Shared subsounds cannot be replaced or moved from their parent stream, such as when the parent stream is an FSB file. ";
case FMOD_ERR_SUBSOUND_MODE: return "The subsound's mode bits do not match with the parent sound's mode bits. See documentation for function that it was called with. ";
case FMOD_ERR_TAGNOTFOUND: return "The specified tag could not be found or there are no tags. ";
case FMOD_ERR_TOOMANYCHANNELS: return "The sound created exceeds the allowable input channel count. This can be increased using the maxinputchannels parameter in System::setSoftwareFormat. ";
case FMOD_ERR_UNIMPLEMENTED: return "Something in FMOD hasn't been implemented when it should be! contact support! ";
case FMOD_ERR_UNINITIALIZED: return "This command failed because System::init or System::setDriver was not called. ";
case FMOD_ERR_UNSUPPORTED: return "A command issued was not supported by this object. Possibly a plugin without certain callbacks specified. ";
case FMOD_ERR_UPDATE: return "An error caused by System::update occured. ";
case FMOD_ERR_VERSION: return "The version number of this file format is not supported. ";
case FMOD_OK: return "No errors.";
default : return "Unknown error.";
};
}
#endif

View File

@ -0,0 +1,201 @@
/* ============================================================================================= */
/* FMOD Ex - Memory info header file. Copyright (c), Firelight Technologies Pty, Ltd. 2008-2016. */
/* */
/* Use this header if you are interested in getting detailed information on FMOD's memory */
/* usage. See the documentation for more details. */
/* */
/* ============================================================================================= */
#ifndef _FMOD_MEMORYINFO_H
#define _FMOD_MEMORYINFO_H
/*
[STRUCTURE]
[
[DESCRIPTION]
Structure to be filled with detailed memory usage information of an FMOD object
[REMARKS]
Every public FMOD class has a getMemoryInfo function which can be used to get detailed information on what memory resources are associated with the object in question.
On return from getMemoryInfo, each member of this structure will hold the amount of memory used for its type in bytes.
Members marked with [in] mean the user sets the value before passing it to the function.
Members marked with [out] mean FMOD sets the value to be used after the function exits.
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
System::getMemoryInfo
EventSystem::getMemoryInfo
FMOD_MEMBITS
FMOD_EVENT_MEMBITS
]
*/
typedef struct FMOD_MEMORY_USAGE_DETAILS
{
unsigned int other; /* [out] Memory not accounted for by other types */
unsigned int string; /* [out] String data */
unsigned int system; /* [out] System object and various internals */
unsigned int plugins; /* [out] Plugin objects and internals */
unsigned int output; /* [out] Output module object and internals */
unsigned int channel; /* [out] Channel related memory */
unsigned int channelgroup; /* [out] ChannelGroup objects and internals */
unsigned int codec; /* [out] Codecs allocated for streaming */
unsigned int file; /* [out] File buffers and structures */
unsigned int sound; /* [out] Sound objects and internals */
unsigned int secondaryram; /* [out] Sound data stored in secondary RAM */
unsigned int soundgroup; /* [out] SoundGroup objects and internals */
unsigned int streambuffer; /* [out] Stream buffer memory */
unsigned int dspconnection; /* [out] DSPConnection objects and internals */
unsigned int dsp; /* [out] DSP implementation objects */
unsigned int dspcodec; /* [out] Realtime file format decoding DSP objects */
unsigned int profile; /* [out] Profiler memory footprint. */
unsigned int recordbuffer; /* [out] Buffer used to store recorded data from microphone */
unsigned int reverb; /* [out] Reverb implementation objects */
unsigned int reverbchannelprops; /* [out] Reverb channel properties structs */
unsigned int geometry; /* [out] Geometry objects and internals */
unsigned int syncpoint; /* [out] Sync point memory. */
unsigned int eventsystem; /* [out] EventSystem and various internals */
unsigned int musicsystem; /* [out] MusicSystem and various internals */
unsigned int fev; /* [out] Definition of objects contained in all loaded projects e.g. events, groups, categories */
unsigned int memoryfsb; /* [out] Data loaded with preloadFSB */
unsigned int eventproject; /* [out] EventProject objects and internals */
unsigned int eventgroupi; /* [out] EventGroup objects and internals */
unsigned int soundbankclass; /* [out] Objects used to manage wave banks */
unsigned int soundbanklist; /* [out] Data used to manage lists of wave bank usage */
unsigned int streaminstance; /* [out] Stream objects and internals */
unsigned int sounddefclass; /* [out] Sound definition objects */
unsigned int sounddefdefclass; /* [out] Sound definition static data objects */
unsigned int sounddefpool; /* [out] Sound definition pool data */
unsigned int reverbdef; /* [out] Reverb definition objects */
unsigned int eventreverb; /* [out] Reverb objects */
unsigned int userproperty; /* [out] User property objects */
unsigned int eventinstance; /* [out] Event instance base objects */
unsigned int eventinstance_complex; /* [out] Complex event instance objects */
unsigned int eventinstance_simple; /* [out] Simple event instance objects */
unsigned int eventinstance_layer; /* [out] Event layer instance objects */
unsigned int eventinstance_sound; /* [out] Event sound instance objects */
unsigned int eventenvelope; /* [out] Event envelope objects */
unsigned int eventenvelopedef; /* [out] Event envelope definition objects */
unsigned int eventparameter; /* [out] Event parameter objects */
unsigned int eventcategory; /* [out] Event category objects */
unsigned int eventenvelopepoint; /* [out] Event envelope point objects */
unsigned int eventinstancepool; /* [out] Event instance pool memory */
} FMOD_MEMORY_USAGE_DETAILS;
/*
[DEFINE]
[
[NAME]
FMOD_MEMBITS
[DESCRIPTION]
Bitfield used to request specific memory usage information from the getMemoryInfo function of every public FMOD Ex class.
Use with the "memorybits" parameter of getMemoryInfo to get information on FMOD Ex memory usage.
[REMARKS]
Every public FMOD class has a getMemoryInfo function which can be used to get detailed information on what memory resources are associated with the object in question.
The FMOD_MEMBITS defines can be OR'd together to specify precisely what memory usage you'd like to get information on. See System::getMemoryInfo for an example.
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
FMOD_EVENT_MEMBITS
System::getMemoryInfo
]
*/
#define FMOD_MEMBITS_OTHER 0x00000001 /* Memory not accounted for by other types */
#define FMOD_MEMBITS_STRING 0x00000002 /* String data */
#define FMOD_MEMBITS_SYSTEM 0x00000004 /* System object and various internals */
#define FMOD_MEMBITS_PLUGINS 0x00000008 /* Plugin objects and internals */
#define FMOD_MEMBITS_OUTPUT 0x00000010 /* Output module object and internals */
#define FMOD_MEMBITS_CHANNEL 0x00000020 /* Channel related memory */
#define FMOD_MEMBITS_CHANNELGROUP 0x00000040 /* ChannelGroup objects and internals */
#define FMOD_MEMBITS_CODEC 0x00000080 /* Codecs allocated for streaming */
#define FMOD_MEMBITS_FILE 0x00000100 /* Codecs allocated for streaming */
#define FMOD_MEMBITS_SOUND 0x00000200 /* Sound objects and internals */
#define FMOD_MEMBITS_SOUND_SECONDARYRAM 0x00000400 /* Sound data stored in secondary RAM */
#define FMOD_MEMBITS_SOUNDGROUP 0x00000800 /* SoundGroup objects and internals */
#define FMOD_MEMBITS_STREAMBUFFER 0x00001000 /* Stream buffer memory */
#define FMOD_MEMBITS_DSPCONNECTION 0x00002000 /* DSPConnection objects and internals */
#define FMOD_MEMBITS_DSP 0x00004000 /* DSP implementation objects */
#define FMOD_MEMBITS_DSPCODEC 0x00008000 /* Realtime file format decoding DSP objects */
#define FMOD_MEMBITS_PROFILE 0x00010000 /* Profiler memory footprint. */
#define FMOD_MEMBITS_RECORDBUFFER 0x00020000 /* Buffer used to store recorded data from microphone */
#define FMOD_MEMBITS_REVERB 0x00040000 /* Reverb implementation objects */
#define FMOD_MEMBITS_REVERBCHANNELPROPS 0x00080000 /* Reverb channel properties structs */
#define FMOD_MEMBITS_GEOMETRY 0x00100000 /* Geometry objects and internals */
#define FMOD_MEMBITS_SYNCPOINT 0x00200000 /* Sync point memory. */
#define FMOD_MEMBITS_ALL 0xffffffff /* All memory used by FMOD Ex */
/* [DEFINE_END] */
/*
[DEFINE]
[
[NAME]
FMOD_EVENT_MEMBITS
[DESCRIPTION]
Bitfield used to request specific memory usage information from the getMemoryInfo function of every public FMOD Event System class.
Use with the "event_memorybits" parameter of getMemoryInfo to get information on FMOD Event System memory usage.
[REMARKS]
Every public FMOD Event System class has a getMemoryInfo function which can be used to get detailed information on what memory resources are associated with the object in question.
The FMOD_EVENT_MEMBITS defines can be OR'd together to specify precisely what memory usage you'd like to get information on. See EventSystem::getMemoryInfo for an example.
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
FMOD_MEMBITS
System::getMemoryInfo
]
*/
#define FMOD_EVENT_MEMBITS_EVENTSYSTEM 0x00000001 /* EventSystem and various internals */
#define FMOD_EVENT_MEMBITS_MUSICSYSTEM 0x00000002 /* MusicSystem and various internals */
#define FMOD_EVENT_MEMBITS_FEV 0x00000004 /* Definition of objects contained in all loaded projects e.g. events, groups, categories */
#define FMOD_EVENT_MEMBITS_MEMORYFSB 0x00000008 /* Data loaded with preloadFSB */
#define FMOD_EVENT_MEMBITS_EVENTPROJECT 0x00000010 /* EventProject objects and internals */
#define FMOD_EVENT_MEMBITS_EVENTGROUPI 0x00000020 /* EventGroup objects and internals */
#define FMOD_EVENT_MEMBITS_SOUNDBANKCLASS 0x00000040 /* Objects used to manage wave banks */
#define FMOD_EVENT_MEMBITS_SOUNDBANKLIST 0x00000080 /* Data used to manage lists of wave bank usage */
#define FMOD_EVENT_MEMBITS_STREAMINSTANCE 0x00000100 /* Stream objects and internals */
#define FMOD_EVENT_MEMBITS_SOUNDDEFCLASS 0x00000200 /* Sound definition objects */
#define FMOD_EVENT_MEMBITS_SOUNDDEFDEFCLASS 0x00000400 /* Sound definition static data objects */
#define FMOD_EVENT_MEMBITS_SOUNDDEFPOOL 0x00000800 /* Sound definition pool data */
#define FMOD_EVENT_MEMBITS_REVERBDEF 0x00001000 /* Reverb definition objects */
#define FMOD_EVENT_MEMBITS_EVENTREVERB 0x00002000 /* Reverb objects */
#define FMOD_EVENT_MEMBITS_USERPROPERTY 0x00004000 /* User property objects */
#define FMOD_EVENT_MEMBITS_EVENTINSTANCE 0x00008000 /* Event instance base objects */
#define FMOD_EVENT_MEMBITS_EVENTINSTANCE_COMPLEX 0x00010000 /* Complex event instance objects */
#define FMOD_EVENT_MEMBITS_EVENTINSTANCE_SIMPLE 0x00020000 /* Simple event instance objects */
#define FMOD_EVENT_MEMBITS_EVENTINSTANCE_LAYER 0x00040000 /* Event layer instance objects */
#define FMOD_EVENT_MEMBITS_EVENTINSTANCE_SOUND 0x00080000 /* Event sound instance objects */
#define FMOD_EVENT_MEMBITS_EVENTENVELOPE 0x00100000 /* Event envelope objects */
#define FMOD_EVENT_MEMBITS_EVENTENVELOPEDEF 0x00200000 /* Event envelope definition objects */
#define FMOD_EVENT_MEMBITS_EVENTPARAMETER 0x00400000 /* Event parameter objects */
#define FMOD_EVENT_MEMBITS_EVENTCATEGORY 0x00800000 /* Event category objects */
#define FMOD_EVENT_MEMBITS_EVENTENVELOPEPOINT 0x01000000 /* Event envelope point object+s */
#define FMOD_EVENT_MEMBITS_EVENTINSTANCEPOOL 0x02000000 /* Event instance pool data */
#define FMOD_EVENT_MEMBITS_ALL 0xffffffff /* All memory used by FMOD Event System */
/* All event instance memory */
#define FMOD_EVENT_MEMBITS_EVENTINSTANCE_GROUP (FMOD_EVENT_MEMBITS_EVENTINSTANCE | \
FMOD_EVENT_MEMBITS_EVENTINSTANCE_COMPLEX | \
FMOD_EVENT_MEMBITS_EVENTINSTANCE_SIMPLE | \
FMOD_EVENT_MEMBITS_EVENTINSTANCE_LAYER | \
FMOD_EVENT_MEMBITS_EVENTINSTANCE_SOUND)
/* All sound definition memory */
#define FMOD_EVENT_MEMBITS_SOUNDDEF_GROUP (FMOD_EVENT_MEMBITS_SOUNDDEFCLASS | \
FMOD_EVENT_MEMBITS_SOUNDDEFDEFCLASS | \
FMOD_EVENT_MEMBITS_SOUNDDEFPOOL)
/* [DEFINE_END] */
#endif

View File

@ -0,0 +1,93 @@
/* ==================================================================================================== */
/* FMOD Ex - output development header file. Copyright (c), Firelight Technologies Pty, Ltd. 2004-2016. */
/* */
/* Use this header if you are wanting to develop your own output plugin to use with */
/* FMOD's output system. With this header you can make your own output plugin that FMOD */
/* can register and use. See the documentation and examples on how to make a working plugin. */
/* */
/* ==================================================================================================== */
#ifndef _FMOD_OUTPUT_H
#define _FMOD_OUTPUT_H
#include "fmod.h"
typedef struct FMOD_OUTPUT_STATE FMOD_OUTPUT_STATE;
/*
Output callbacks
*/
typedef FMOD_RESULT (F_CALLBACK *FMOD_OUTPUT_GETNUMDRIVERSCALLBACK)(FMOD_OUTPUT_STATE *output_state, int *numdrivers);
typedef FMOD_RESULT (F_CALLBACK *FMOD_OUTPUT_GETDRIVERNAMECALLBACK)(FMOD_OUTPUT_STATE *output_state, int id, char *name, int namelen);
typedef FMOD_RESULT (F_CALLBACK *FMOD_OUTPUT_GETDRIVERCAPSCALLBACK)(FMOD_OUTPUT_STATE *output_state, int id, FMOD_CAPS *caps);
typedef FMOD_RESULT (F_CALLBACK *FMOD_OUTPUT_INITCALLBACK) (FMOD_OUTPUT_STATE *output_state, int selecteddriver, FMOD_INITFLAGS flags, int *outputrate, int outputchannels, FMOD_SOUND_FORMAT *outputformat, int dspbufferlength, int dspnumbuffers, void *extradriverdata);
typedef FMOD_RESULT (F_CALLBACK *FMOD_OUTPUT_CLOSECALLBACK) (FMOD_OUTPUT_STATE *output_state);
typedef FMOD_RESULT (F_CALLBACK *FMOD_OUTPUT_UPDATECALLBACK) (FMOD_OUTPUT_STATE *output_state);
typedef FMOD_RESULT (F_CALLBACK *FMOD_OUTPUT_GETHANDLECALLBACK) (FMOD_OUTPUT_STATE *output_state, void **handle);
typedef FMOD_RESULT (F_CALLBACK *FMOD_OUTPUT_GETPOSITIONCALLBACK) (FMOD_OUTPUT_STATE *output_state, unsigned int *pcm);
typedef FMOD_RESULT (F_CALLBACK *FMOD_OUTPUT_LOCKCALLBACK) (FMOD_OUTPUT_STATE *output_state, unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2);
typedef FMOD_RESULT (F_CALLBACK *FMOD_OUTPUT_UNLOCKCALLBACK) (FMOD_OUTPUT_STATE *output_state, void *ptr1, void *ptr2, unsigned int len1, unsigned int len2);
typedef FMOD_RESULT (F_CALLBACK *FMOD_OUTPUT_READFROMMIXER) (FMOD_OUTPUT_STATE *output_state, void *buffer, unsigned int length);
/*
[STRUCTURE]
[
[DESCRIPTION]
When creating an output, declare one of these and provide the relevant callbacks and name for FMOD to use when it opens and reads a file of this type.
[REMARKS]
Members marked with [in] mean the variable can be written to. The user can set the value.
Members marked with [out] mean the variable is modified by FMOD and is for reading purposes only. Do not change this value.
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
FMOD_OUTPUT_STATE
]
*/
typedef struct FMOD_OUTPUT_DESCRIPTION
{
const char *name; /* [in] Name of the output. */
unsigned int version; /* [in] Plugin writer's version number. */
int polling; /* [in] If TRUE (non zero), this tells FMOD to start a thread and call getposition / lock / unlock for feeding data. If 0, the output is probably callback based, so all the plugin needs to do is call readfrommixer to the appropriate pointer. */
FMOD_OUTPUT_GETNUMDRIVERSCALLBACK getnumdrivers; /* [in] For sound device enumeration. This callback is to give System::getNumDrivers somthing to return. */
FMOD_OUTPUT_GETDRIVERNAMECALLBACK getdrivername; /* [in] For sound device enumeration. This callback is to give System::getDriverName somthing to return. */
FMOD_OUTPUT_GETDRIVERCAPSCALLBACK getdrivercaps; /* [in] For sound device enumeration. This callback is to give System::getDriverCaps somthing to return. */
FMOD_OUTPUT_INITCALLBACK init; /* [in] Initialization function for the output device. This is called from System::init. */
FMOD_OUTPUT_CLOSECALLBACK close; /* [in] Cleanup / close down function for the output device. This is called from System::close. */
FMOD_OUTPUT_UPDATECALLBACK update; /* [in] Update function that is called once a frame by the user. This is called from System::update. */
FMOD_OUTPUT_GETHANDLECALLBACK gethandle; /* [in] This is called from System::getOutputHandle. This is just to return a pointer to the internal system device object that the system may be using.*/
FMOD_OUTPUT_GETPOSITIONCALLBACK getposition; /* [in] This is called from the FMOD software mixer thread if 'polling' = true. This returns a position value in samples so that FMOD knows where and when to fill its buffer. */
FMOD_OUTPUT_LOCKCALLBACK lock; /* [in] This is called from the FMOD software mixer thread if 'polling' = true. This function provides a pointer to data that FMOD can write to when software mixing. */
FMOD_OUTPUT_UNLOCKCALLBACK unlock; /* [in] This is called from the FMOD software mixer thread if 'polling' = true. This optional function accepts the data that has been mixed and copies it or does whatever it needs to before sending it to the hardware. */
} FMOD_OUTPUT_DESCRIPTION;
/*
[STRUCTURE]
[
[DESCRIPTION]
Output plugin structure that is passed into each callback.
[REMARKS]
Members marked with [in] mean the variable can be written to. The user can set the value.
Members marked with [out] mean the variable is modified by FMOD and is for reading purposes only. Do not change this value.
[PLATFORMS]
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
[SEE_ALSO]
FMOD_OUTPUT_DESCRIPTION
]
*/
struct FMOD_OUTPUT_STATE
{
void *plugindata; /* [in] Plugin writer created data the output author wants to attach to this object. */
FMOD_OUTPUT_READFROMMIXER readfrommixer; /* [out] Function to update mixer and write the result to the provided pointer. Used from callback based output only. Polling based output uses lock/unlock/getposition. */
};
#endif

View File

@ -0,0 +1,16 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := fmod
LOCAL_MODULE_FILENAME := libfmod
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libfmod.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../inc
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := fmodL
LOCAL_MODULE_FILENAME := libfmodL
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libfmodL.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../inc
include $(PREBUILT_SHARED_LIBRARY)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,123 @@
def buildAsLibrary = project.hasProperty('BUILD_AS_LIBRARY');
def buildAsApplication = !buildAsLibrary
if (buildAsApplication) {
apply plugin: 'com.android.application'
}
else {
apply plugin: 'com.android.library'
}
android {
compileSdkVersion 28
defaultConfig {
if (buildAsApplication) {
applicationId "org.ggelua.demo"
}
minSdkVersion 21
targetSdkVersion 28
versionCode 1
versionName "1.0"
externalNativeBuild {
ndkBuild {
arguments "APP_PLATFORM=android-21"
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86' , 'x86_64'
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
if (!project.hasProperty('EXCLUDE_NATIVE_LIBS')) {
sourceSets.main {
jniLibs.srcDir 'libs'
}
externalNativeBuild {
ndkBuild {
path 'jni/Android.mk'
}
}
}
lintOptions {
abortOnError false
}
if (buildAsLibrary) {
libraryVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith(".aar")) {
def fileName = "org.libsdl.app.aar";
output.outputFile = new File(outputFile.parent, fileName);
}
}
}
}
}
android.applicationVariants.all { variant ->
// delete previous files first
delete "${buildDir}/intermediates/merged_assets/${variant.name}"
variant.mergeAssets.doLast {
def sourceDir = "${buildDir}/../../../.."
def buildType = it.buildType.name
copy {
from "${sourceDir}/GGELUA/Release64/Test/data"
into "${outputDir}/data"
}
if (buildType == "release") {
copy {
from "${sourceDir}/GGELUA/Release64/Test/pvf.script"
into outputDir
}
} else {
copy {
from "${sourceDir}/GGELUA/Release64/lua"
into "${outputDir}/lua"
}
copy {
from "${sourceDir}/GGELUA/Release64/ggelua.lua"
into outputDir
}
copy {
from "${sourceDir}/GGELUA/Release64/main.lua"
into outputDir
}
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
}
task buildLua(type: Exec, description: '编译lua脚本'){
def sourceDir = "${buildDir}/../../../../GGELUA/Release64"
workingDir sourceDir
def myCommond = [
"${sourceDir}/lua.exe", "${sourceDir}/build.lua",
'${sourceDir}',
"${sourceDir}/Test",
"${sourceDir}/Test/pvf.script",
'android'
]
commandLine myCommond
}
android.applicationVariants.all {
//release还是debug版本
def buildType = it.buildType.name
if (buildType == "release") {
preBuild.dependsOn buildLua
}
}

View File

@ -0,0 +1,15 @@
LOCAL_PATH := $(call my-dir)
MYLOCAL_PATH := $(LOCAL_PATH)
#include $(call all-subdir-makefiles)
include $(call all-makefiles-under, $(MYLOCAL_PATH)/../../../../dependent)
include $(call all-makefiles-under, $(MYLOCAL_PATH)/../../../../source/lib)
include $(call all-makefiles-under, $(MYLOCAL_PATH)/../../../../source)
include $(call all-makefiles-under, $(MYLOCAL_PATH))
$(call import-add-path, $(MYLOCAL_PATH)/../../../../dependent)
$(call import-add-path, $(MYLOCAL_PATH)/../../../../source)
$(call import-module, fmod/api/lib/android)
$(call import-module, HP-Socket/Linux/project/android-ndk/jni)

View File

@ -0,0 +1,13 @@
# Uncomment this if you're using STL in your project
# You can find more information here:
# https://developer.android.com/ndk/guides/cpp-support
APP_STL := c++_shared
APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
#APP_CPPFLAGS := -frtti -std=c++11 -fsigned-char
#APP_LDFLAGS := -latomic
# Min runtime API level
APP_PLATFORM=android-21

View File

@ -0,0 +1,20 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
DEPENDENT_LIB_PATH := $(LOCAL_PATH)/../../../../../dependent
SRC_PATH := $(DEPENDENT_LIB_PATH)/SQLite3MultipleCiphers
LOCAL_MODULE:= sqlite3mc
LOCAL_MODULE_FILENAME := sqlite3mc
LOCAL_SRC_FILES:= $(SRC_PATH)/src/sqlite3mc.c
LOCAL_CFLAGS += -D"HAVE_CIPHER_AES_128_CBC=0" -D"HAVE_CIPHER_AES_256_CBC=0" -D"HAVE_CIPHER_SQLCIPHER=0"
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(BUILD_STATIC_LIBRARY)

View File

@ -0,0 +1,57 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := SDLmain
BASE_LIB_PATH := $(LOCAL_PATH)/../../../../../dependent
SRC_PATH := $(LOCAL_PATH)/../../../../../src
SDL_PATH := $(BASE_LIB_PATH)/SDL
SDL_IMAGE_PATH := $(BASE_LIB_PATH)/SDL_image
SDL_MIXER_PATH := $(BASE_LIB_PATH)/lib/SDL_mixer
SDL_TTF_PATH := $(BASE_LIB_PATH)/lib/SDL_ttf
GGE_LIB_PATH := $(LOCAL_PATH)/../../../../../source
LUA_PATH := $(GGE_LIB_PATH)/lua
LOCAL_C_INCLUDES += $(LUA_PATH)
LOCAL_C_INCLUDES := $(SDL_PATH)/include \
$(SDL_IMAGE_PATH) \
$(SDL_MIXER_PATH) \
$(SDL_TTF_PATH) \
$(SRC_PATH) \
$(LUA_PATH)
# Add your application source files here...
LOCAL_SRC_FILES := main.c \
init.c
LOCAL_SHARED_LIBRARIES := SDL2 \
SDL2_image \
SDL2_mixer \
SDL2_ttf \
lua
LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 -llog
include $(BUILD_SHARED_LIBRARY)
#$(call import-add-path, $(LOCAL_PATH)/../../../../../dependent)
#$(call import-add-path, $(LOCAL_PATH)/../../../../../source)
#$(call import-module, SDL)
#$(call import-module, SDL_image)
#$(call import-module, SDL_mixer)
#$(call import-module, SDL_ttf)
#$(call import-module, lua)
#$(call import-module, fmod/api/lib/android)
#$(call import-module, HP-Socket/Linux/project/android-ndk/jni)
#$(call import-module, lib/cjson)
#$(call import-module, lib/gastar)
#$(call import-module, lib/ggelua)
#$(call import-module, lib/ghpsocket)
#$(call import-module, lib/gip)
#$(call import-module, lib/gsdl2)
#$(call import-module, lib/gxy)
#$(call import-module, lib/lsqlite3)
#$(call import-module, lib/socket)

View File

@ -0,0 +1,173 @@
#include "init.h"
int gge_searcher(lua_State *L) {
lua_getfield(L, lua_upvalueindex(1), "searchpath");//package.searchpath
lua_rotate(L,-2,-1);
lua_getfield(L, lua_upvalueindex(1), "path");//package.path
lua_call(L,2,-1);
if (lua_isstring(L,1)){
luaL_loadfile(L, lua_tostring(L,1));
lua_rotate(L,-2,-1);
return 2;
}else{
lua_remove(L,-2);
}
return 1;
}
int gge_getscript(lua_State *L) {
// Utf8_Ansi(L);
lua_getfield(L, lua_upvalueindex(1), "searchpath");//package.searchpath
lua_rotate(L,-2,-1);
lua_getfield(L, lua_upvalueindex(1), "path");//package.path
lua_call(L,2,-1);
if (lua_isstring(L,1)){
size_t nr;
luaL_Buffer b;
FILE *f = fopen(lua_tostring(L,-1), "r");
luaL_buffinit(L, &b);
do { /* read file in chunks of LUAL_BUFFERSIZE bytes */
char *p = luaL_prepbuffer(&b);
nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f);
luaL_addsize(&b, nr);
} while (nr == LUAL_BUFFERSIZE);
luaL_pushresult(&b); /* close buffer */
fclose(f);
return 1;
}
return 0;
}
#include "SDL.h"
static const char *getnextfilename (char **path, char *end) {
char *sep;
char *name = *path;
if (name == end)
return NULL; /* no more names */
else if (*name == '\0') { /* from previous iteration? */
*name = *LUA_PATH_SEP; /* restore separator */
name++; /* skip it */
}
sep = strchr(name, *LUA_PATH_SEP); /* find next separator */
if (sep == NULL) /* separator not found? */
sep = end; /* name goes until the end */
*sep = '\0'; /* finish file name */
*path = sep; /* will start next search from here */
return name;
}
int gge_require(lua_State* L) {
const char *module = lua_tostring(L, 1);
Sint64 size = 0;
char *chunk = NULL;
SDL_RWops * ops = NULL;
const char *search = NULL, *filename = NULL;
char *pathname = NULL, *endpathname = NULL;
lua_getglobal(L, LUA_LOADLIBNAME); // push "package"
lua_getfield(L, -1, "path"); // push "package.path"
lua_remove(L, -2); // remove "package"
search = luaL_checkstring(L, -1);
lua_pop(L, 2);
if (strchr(module, '.') != NULL)
module = luaL_gsub(L, module, ".", LUA_DIRSEP); /* replace it by 'dirsep' */
luaL_Buffer buff;
luaL_buffinit(L, &buff);
luaL_addgsub(&buff, search, LUA_PATH_MARK, module);
luaL_addchar(&buff, '\0');
pathname = luaL_buffaddr(&buff); /* writable list of file names */
endpathname = pathname + luaL_bufflen(&buff) - 1;
while ((filename = getnextfilename(&pathname, endpathname)) != NULL) {
ops = SDL_RWFromFile(filename, "rb");
if (ops) {
break;
}
}
if (ops) { //文件打开成功
size = SDL_RWsize(ops);
chunk = malloc(size + 1);
SDL_RWread(ops, chunk, size, size + 1);
chunk[size] = 0;
SDL_RWclose(ops);
luaL_loadbuffer(L, chunk, size, module);
free(chunk);
}
return 1;
}
void gge_addLoader(lua_State *L, int (*FUNC)(lua_State* L)){
lua_getglobal(L, LUA_LOADLIBNAME); // push "package"
lua_getfield(L, -1, "searchers"); // push "package.loaders"
lua_remove(L, -2); // remove "package"
// Count the number of entries in package.loaders.
// Table is now at index -2, since 'nil' is right on top of it.
// lua_next pushes a key and a value onto the stack.
int numLoaders = 0;
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
lua_pop(L, 1);
numLoaders++;
}
lua_pushinteger(L, numLoaders + 1);
lua_pushcfunction(L, FUNC);
lua_rawset(L, -3); // Table is still on the stack. Get rid of it now.
lua_pop(L, 1);
}
int gge_init (lua_State *L) {
const char *path = luaL_checkstring(L, -1);
lua_pop(L, 1);
lua_getglobal(L,LUA_LOADLIBNAME);
lua_getfield(L, -1, "searchers");
lua_pushvalue(L,-2);
lua_pushcclosure(L, gge_searcher,1);
lua_seti(L, -2, 2);
lua_pop(L,1);
// GetRunPath(L);
lua_pushstring(L, ".");
luaL_gsub(L,"?.lua;lua/?.lua;!/lua/?.lua;script/?.lua;!/script/?.lua;!/lua/?/?.lua;lua/?/?.lua",LUA_EXEC_DIR,lua_tostring(L,-1));
lua_setfield(L,-3,"path");
char cpath[1024] = {0};
sprintf(cpath, "?.so;lib/?.so;!/?.so;!/lib/?.so;%s/lib?.so", path);
luaL_gsub(L, cpath, LUA_EXEC_DIR, lua_tostring(L,-1));
lua_setfield(L,-3,"cpath");
lua_pop(L,2);
gge_addLoader(L, gge_require);
return 0;
}

View File

@ -0,0 +1,10 @@
#ifndef init_h
#define init_h
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
int Utf8_Ansi(lua_State *L);
int GetRunPath (lua_State *L);
int gge_init (lua_State *L);
int gge_getscript(lua_State *L);
#endif

View File

@ -0,0 +1,130 @@
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "SDL.h"
#include "SDL_main.h"
#include "SDL_stdinc.h"
#include "SDL_mutex.h"
#include "SDL_messagebox.h"
#include "platform.h"
#include "init.h"
struct INFO {
unsigned int signal;
unsigned int coresize;
unsigned int packsize;
};
char* ggelua = NULL;
char* ggepack = NULL;
struct INFO info = { 0,0,0 };
static int GGE_Load(lua_State* L)
{
SDL_RWops *ops = SDL_RWFromFile("ggelua.lua", "r");
if (ops) {
info.coresize = SDL_RWsize(ops);
info.packsize = 0;
ggelua = (char*)SDL_malloc(info.coresize);
SDL_RWread(ops, ggelua, info.coresize, 1);
SDL_RWclose(ops);
}
return 0;
}
static int GGE_Error(lua_State* L) {
lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);//LOADED
if (lua_getfield(L, -1, "SDL") != LUA_TTABLE) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "error", lua_tostring(L, -3), NULL);
}
else {
printf("%s\n", lua_tostring(L, -3));
}
return 0;
}
int main(int argc, char *argv[])
{
lua_State* L = luaL_newstate();
luaL_openlibs(L);
lua_newtable(L);
lua_createtable(L, argc, 0);
for (int i = 1; i < argc; i++) {
lua_pushstring(L, argv[i]);
lua_seti(L, -2, i);
}
lua_setfield(L, -2, "arg");//gge.arg
#ifdef _CONSOLE
lua_pushboolean(L, 1);
#else
lua_pushboolean(L, 0);
#endif
lua_setfield(L, -2, "isconsole"); //gge.isconsole
lua_pushboolean(L, ggepack == NULL);
lua_setfield(L, -2, "isdebug"); //gge.isdebug
lua_pushstring(L, "main");
lua_setfield(L, -2, "entry"); //gge.entry
lua_pushboolean(L, 1);
lua_setfield(L, -2, "ismain"); //gge.ismain
lua_createtable(L, 6, 0);
lua_pushinteger(L, GGE_TARGET_PLATFORM);
lua_setfield(L, -2, "platform"); //gge.sys.platform
lua_pushinteger(L, GGE_PLATFORM_IOS);
lua_setfield(L, -2, "GGE_PLATFORM_IOS"); //gge.sys.GGE_PLATFORM_IOS
lua_pushinteger(L, GGE_PLATFORM_ANDROID);
lua_setfield(L, -2, "GGE_PLATFORM_ANDROID"); //gge.sys.GGE_PLATFORM_ANDROID
lua_pushinteger(L, GGE_PLATFORM_WIN32);
lua_setfield(L, -2, "GGE_PLATFORM_WIN32"); //gge.sys.GGE_PLATFORM_WIN32
lua_pushinteger(L, GGE_PLATFORM_LINUX);
lua_setfield(L, -2, "GGE_PLATFORM_LINUX"); //gge.sys.GGE_PLATFORM_LINUX
lua_pushinteger(L, GGE_PLATFORM_MAC);
lua_setfield(L, -2, "GGE_PLATFORM_MAC"); //gge.sys.GGE_PLATFORM_MAC
lua_setfield(L, -2, "sys");//gge.sys
lua_pushvalue(L, -1);
lua_setfield(L, LUA_REGISTRYINDEX, "_ggelua");
lua_setglobal(L, "gge");
SDL_mutex** extra = (SDL_mutex**)lua_getextraspace(L);//线程锁
SDL_mutex* mutex = SDL_CreateMutex();
*extra = mutex;
(argc == 2) ? lua_pushstring(L, argv[1]) : lua_pushstring(L, "");
gge_init(L);
lua_pushcfunction(L, GGE_Load);//读取脚本
lua_pushstring(L, argv[0]);
lua_call(L, 1, 0);
if (ggelua) {
lua_pushlstring(L, ggelua, info.coresize);
lua_setfield(L, LUA_REGISTRYINDEX, "ggelua.lua");
if (ggepack) {
lua_pushlstring(L, ggepack, info.packsize);
lua_setfield(L, LUA_REGISTRYINDEX, "ggepack");
}
SDL_LockMutex(mutex);//ggelua.delay解锁
if (luaL_loadbuffer(L, ggelua, info.coresize, "ggelua.lua") == LUA_OK) {
lua_pushstring(L, "main");
if (ggepack)//打包的脚本数据
lua_pushlstring(L, ggepack, info.packsize);
else
lua_pushnil(L);
if (lua_pcall(L, 2, 0, 0) != LUA_OK) {
GGE_Error(L);
}
}
else
GGE_Error(L);
SDL_free(ggelua);
}
SDL_DestroyMutex(mutex);
lua_close(L);
if (ggepack)
SDL_free(ggepack);
return 0;
}

View File

@ -0,0 +1,65 @@
#ifndef _PLATFORMCONFIG_H
#define GGE_PLATFORM_UNKNOWN 0
#define GGE_PLATFORM_IOS 1
#define GGE_PLATFORM_ANDROID 2
#define GGE_PLATFORM_WIN32 3
#define GGE_PLATFORM_LINUX 4
#define GGE_PLATFORM_MAC 5
// Determine target platform by compile environment macro.
#define GGE_TARGET_PLATFORM GGE_PLATFORM_UNKNOWN
// Apple: Mac and iOS
#if defined(__APPLE__) && !defined(ANDROID) // exclude android for binding generator.
#include <TargetConditionals.h>
#if TARGET_OS_IPHONE // TARGET_OS_IPHONE includes TARGET_OS_IOS TARGET_OS_TV and TARGET_OS_WATCH. see TargetConditionals.h
#undef GGE_TARGET_PLATFORM
#define GGE_TARGET_PLATFORM GGE_PLATFORM_IOS
#elif TARGET_OS_MAC
#undef GGE_TARGET_PLATFORM
#define GGE_TARGET_PLATFORM GGE_PLATFORM_MAC
#endif
#endif
// android
#if defined(ANDROID)
#undef GGE_TARGET_PLATFORM
#define GGE_TARGET_PLATFORM GGE_PLATFORM_ANDROID
#endif
// win32
#if defined(_WIN32) && defined(_WINDOWS)
#undef GGE_TARGET_PLATFORM
#define GGE_TARGET_PLATFORM GGE_PLATFORM_WIN32
#endif
// linux
#if defined(LINUX) && !defined(__APPLE__)
#undef GGE_TARGET_PLATFORM
#define GGE_TARGET_PLATFORM GGE_PLATFORM_LINUX
#endif
//////////////////////////////////////////////////////////////////////////
// post configure
//////////////////////////////////////////////////////////////////////////
// check user set platform
#if ! GGE_TARGET_PLATFORM
#error "Cannot recognize the target platform; are you targeting an unsupported platform?"
#endif
#if (GGE_TARGET_PLATFORM == GGE_PLATFORM_WIN32)
#ifndef __MINGW32__
#pragma warning (disable:4127)
#endif
#endif // GGE_PLATFORM_WIN32
#if ((GGE_TARGET_PLATFORM == GGE_PLATFORM_ANDROID) || (GGE_TARGET_PLATFORM == GGE_PLATFORM_IOS))
#define GGE_PLATFORM_MOBILE
#else
#define GGE_PLATFORM_PC
#endif
#endif // !_PLATFORMCONFIG_H

View File

@ -0,0 +1,29 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
DEPENDENT_LIB_PATH := $(LOCAL_PATH)/../../../../../dependent
SRC_PATH := $(DEPENDENT_LIB_PATH)/zlib
LOCAL_MODULE:= zlib
LOCAL_SRC_FILES:= $(SRC_PATH)/adler32.c \
$(SRC_PATH)/compress.c \
$(SRC_PATH)/crc32.c \
$(SRC_PATH)/deflate.c \
$(SRC_PATH)/gzclose.c \
$(SRC_PATH)/gzlib.c \
$(SRC_PATH)/gzread.c \
$(SRC_PATH)/gzwrite.c \
$(SRC_PATH)/infback.c \
$(SRC_PATH)/inflate.c \
$(SRC_PATH)/inftrees.c \
$(SRC_PATH)/inffast.c \
$(SRC_PATH)/trees.c \
$(SRC_PATH)/uncompr.c \
$(SRC_PATH)/zutil.c
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(BUILD_STATIC_LIBRARY)

Binary file not shown.

17
project/android/app/proguard-rules.pro vendored Normal file
View File

@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in [sdk]/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Replace com.test.game with the identifier of your game below, e.g.
com.gamemaker.game
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.libsdl.app"
android:versionCode="1"
android:versionName="1.0"
android:installLocation="auto">
<!-- OpenGL ES 2.0 -->
<uses-feature android:glEsVersion="0x00020000" />
<!-- Touchscreen support -->
<uses-feature
android:name="android.hardware.touchscreen"
android:required="false" />
<!-- Game controller support -->
<uses-feature
android:name="android.hardware.bluetooth"
android:required="false" />
<uses-feature
android:name="android.hardware.gamepad"
android:required="false" />
<uses-feature
android:name="android.hardware.usb.host"
android:required="false" />
<!-- External mouse input events -->
<uses-feature
android:name="android.hardware.type.pc"
android:required="false" />
<!-- Audio recording support -->
<!-- if you want to capture audio, uncomment this. -->
<!-- <uses-feature
android:name="android.hardware.microphone"
android:required="false" /> -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- Allow writing to external storage -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- Allow access to Bluetooth devices -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<!-- Allow access to the vibrator -->
<uses-permission android:name="android.permission.VIBRATE" />
<!-- if you want to capture audio, uncomment this. -->
<!-- <uses-permission android:name="android.permission.RECORD_AUDIO" /> -->
<!-- Create a Java class extending SDLActivity and place it in a
directory under app/src/main/java matching the package, e.g. app/src/main/java/com/gamemaker/game/MyGame.java
then replace "SDLActivity" with the name of your class (e.g. "MyGame")
in the XML below.
An example Java class can be found in README-android.md
-->
<application android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:allowBackup="true"
android:usesCleartextTraffic="true"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:hardwareAccelerated="true" >
<!-- Example of setting SDL hints from AndroidManifest.xml:
<meta-data android:name="SDL_ENV.SDL_ACCELEROMETER_AS_JOYSTICK" android:value="0"/>
-->
<activity android:name="SDLActivity"
android:label="@string/app_name"
android:screenOrientation="landscape"
android:alwaysRetainTaskState="true"
android:launchMode="singleInstance"
android:configChanges="layoutDirection|locale|orientation|uiMode|screenLayout|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!-- Drop file event -->
<!--
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
-->
</activity>
</application>
</manifest>

View File

@ -0,0 +1,22 @@
package org.libsdl.app;
import android.hardware.usb.UsbDevice;
interface HIDDevice
{
public int getId();
public int getVendorId();
public int getProductId();
public String getSerialNumber();
public int getVersion();
public String getManufacturerName();
public String getProductName();
public UsbDevice getDevice();
public boolean open();
public int sendFeatureReport(byte[] report);
public int sendOutputReport(byte[] report);
public boolean getFeatureReport(byte[] report);
public void setFrozen(boolean frozen);
public void close();
public void shutdown();
}

View File

@ -0,0 +1,650 @@
package org.libsdl.app;
import android.content.Context;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothGattService;
import android.hardware.usb.UsbDevice;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.os.*;
//import com.android.internal.util.HexDump;
import java.lang.Runnable;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.UUID;
class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDevice {
private static final String TAG = "hidapi";
private HIDDeviceManager mManager;
private BluetoothDevice mDevice;
private int mDeviceId;
private BluetoothGatt mGatt;
private boolean mIsRegistered = false;
private boolean mIsConnected = false;
private boolean mIsChromebook = false;
private boolean mIsReconnecting = false;
private boolean mFrozen = false;
private LinkedList<GattOperation> mOperations;
GattOperation mCurrentOperation = null;
private Handler mHandler;
private static final int TRANSPORT_AUTO = 0;
private static final int TRANSPORT_BREDR = 1;
private static final int TRANSPORT_LE = 2;
private static final int CHROMEBOOK_CONNECTION_CHECK_INTERVAL = 10000;
static public final UUID steamControllerService = UUID.fromString("100F6C32-1735-4313-B402-38567131E5F3");
static public final UUID inputCharacteristic = UUID.fromString("100F6C33-1735-4313-B402-38567131E5F3");
static public final UUID reportCharacteristic = UUID.fromString("100F6C34-1735-4313-B402-38567131E5F3");
static private final byte[] enterValveMode = new byte[] { (byte)0xC0, (byte)0x87, 0x03, 0x08, 0x07, 0x00 };
static class GattOperation {
private enum Operation {
CHR_READ,
CHR_WRITE,
ENABLE_NOTIFICATION
}
Operation mOp;
UUID mUuid;
byte[] mValue;
BluetoothGatt mGatt;
boolean mResult = true;
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid) {
mGatt = gatt;
mOp = operation;
mUuid = uuid;
}
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid, byte[] value) {
mGatt = gatt;
mOp = operation;
mUuid = uuid;
mValue = value;
}
public void run() {
// This is executed in main thread
BluetoothGattCharacteristic chr;
switch (mOp) {
case CHR_READ:
chr = getCharacteristic(mUuid);
//Log.v(TAG, "Reading characteristic " + chr.getUuid());
if (!mGatt.readCharacteristic(chr)) {
Log.e(TAG, "Unable to read characteristic " + mUuid.toString());
mResult = false;
break;
}
mResult = true;
break;
case CHR_WRITE:
chr = getCharacteristic(mUuid);
//Log.v(TAG, "Writing characteristic " + chr.getUuid() + " value=" + HexDump.toHexString(value));
chr.setValue(mValue);
if (!mGatt.writeCharacteristic(chr)) {
Log.e(TAG, "Unable to write characteristic " + mUuid.toString());
mResult = false;
break;
}
mResult = true;
break;
case ENABLE_NOTIFICATION:
chr = getCharacteristic(mUuid);
//Log.v(TAG, "Writing descriptor of " + chr.getUuid());
if (chr != null) {
BluetoothGattDescriptor cccd = chr.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
if (cccd != null) {
int properties = chr.getProperties();
byte[] value;
if ((properties & BluetoothGattCharacteristic.PROPERTY_NOTIFY) == BluetoothGattCharacteristic.PROPERTY_NOTIFY) {
value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE;
} else if ((properties & BluetoothGattCharacteristic.PROPERTY_INDICATE) == BluetoothGattCharacteristic.PROPERTY_INDICATE) {
value = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE;
} else {
Log.e(TAG, "Unable to start notifications on input characteristic");
mResult = false;
return;
}
mGatt.setCharacteristicNotification(chr, true);
cccd.setValue(value);
if (!mGatt.writeDescriptor(cccd)) {
Log.e(TAG, "Unable to write descriptor " + mUuid.toString());
mResult = false;
return;
}
mResult = true;
}
}
}
}
public boolean finish() {
return mResult;
}
private BluetoothGattCharacteristic getCharacteristic(UUID uuid) {
BluetoothGattService valveService = mGatt.getService(steamControllerService);
if (valveService == null)
return null;
return valveService.getCharacteristic(uuid);
}
static public GattOperation readCharacteristic(BluetoothGatt gatt, UUID uuid) {
return new GattOperation(gatt, Operation.CHR_READ, uuid);
}
static public GattOperation writeCharacteristic(BluetoothGatt gatt, UUID uuid, byte[] value) {
return new GattOperation(gatt, Operation.CHR_WRITE, uuid, value);
}
static public GattOperation enableNotification(BluetoothGatt gatt, UUID uuid) {
return new GattOperation(gatt, Operation.ENABLE_NOTIFICATION, uuid);
}
}
public HIDDeviceBLESteamController(HIDDeviceManager manager, BluetoothDevice device) {
mManager = manager;
mDevice = device;
mDeviceId = mManager.getDeviceIDForIdentifier(getIdentifier());
mIsRegistered = false;
mIsChromebook = mManager.getContext().getPackageManager().hasSystemFeature("org.chromium.arc.device_management");
mOperations = new LinkedList<GattOperation>();
mHandler = new Handler(Looper.getMainLooper());
mGatt = connectGatt();
// final HIDDeviceBLESteamController finalThis = this;
// mHandler.postDelayed(new Runnable() {
// @Override
// public void run() {
// finalThis.checkConnectionForChromebookIssue();
// }
// }, CHROMEBOOK_CONNECTION_CHECK_INTERVAL);
}
public String getIdentifier() {
return String.format("SteamController.%s", mDevice.getAddress());
}
public BluetoothGatt getGatt() {
return mGatt;
}
// Because on Chromebooks we show up as a dual-mode device, it will attempt to connect TRANSPORT_AUTO, which will use TRANSPORT_BREDR instead
// of TRANSPORT_LE. Let's force ourselves to connect low energy.
private BluetoothGatt connectGatt(boolean managed) {
if (Build.VERSION.SDK_INT >= 23) {
try {
return mDevice.connectGatt(mManager.getContext(), managed, this, TRANSPORT_LE);
} catch (Exception e) {
return mDevice.connectGatt(mManager.getContext(), managed, this);
}
} else {
return mDevice.connectGatt(mManager.getContext(), managed, this);
}
}
private BluetoothGatt connectGatt() {
return connectGatt(false);
}
protected int getConnectionState() {
Context context = mManager.getContext();
if (context == null) {
// We are lacking any context to get our Bluetooth information. We'll just assume disconnected.
return BluetoothProfile.STATE_DISCONNECTED;
}
BluetoothManager btManager = (BluetoothManager)context.getSystemService(Context.BLUETOOTH_SERVICE);
if (btManager == null) {
// This device doesn't support Bluetooth. We should never be here, because how did
// we instantiate a device to start with?
return BluetoothProfile.STATE_DISCONNECTED;
}
return btManager.getConnectionState(mDevice, BluetoothProfile.GATT);
}
public void reconnect() {
if (getConnectionState() != BluetoothProfile.STATE_CONNECTED) {
mGatt.disconnect();
mGatt = connectGatt();
}
}
protected void checkConnectionForChromebookIssue() {
if (!mIsChromebook) {
// We only do this on Chromebooks, because otherwise it's really annoying to just attempt
// over and over.
return;
}
int connectionState = getConnectionState();
switch (connectionState) {
case BluetoothProfile.STATE_CONNECTED:
if (!mIsConnected) {
// We are in the Bad Chromebook Place. We can force a disconnect
// to try to recover.
Log.v(TAG, "Chromebook: We are in a very bad state; the controller shows as connected in the underlying Bluetooth layer, but we never received a callback. Forcing a reconnect.");
mIsReconnecting = true;
mGatt.disconnect();
mGatt = connectGatt(false);
break;
}
else if (!isRegistered()) {
if (mGatt.getServices().size() > 0) {
Log.v(TAG, "Chromebook: We are connected to a controller, but never got our registration. Trying to recover.");
probeService(this);
}
else {
Log.v(TAG, "Chromebook: We are connected to a controller, but never discovered services. Trying to recover.");
mIsReconnecting = true;
mGatt.disconnect();
mGatt = connectGatt(false);
break;
}
}
else {
Log.v(TAG, "Chromebook: We are connected, and registered. Everything's good!");
return;
}
break;
case BluetoothProfile.STATE_DISCONNECTED:
Log.v(TAG, "Chromebook: We have either been disconnected, or the Chromebook BtGatt.ContextMap bug has bitten us. Attempting a disconnect/reconnect, but we may not be able to recover.");
mIsReconnecting = true;
mGatt.disconnect();
mGatt = connectGatt(false);
break;
case BluetoothProfile.STATE_CONNECTING:
Log.v(TAG, "Chromebook: We're still trying to connect. Waiting a bit longer.");
break;
}
final HIDDeviceBLESteamController finalThis = this;
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
finalThis.checkConnectionForChromebookIssue();
}
}, CHROMEBOOK_CONNECTION_CHECK_INTERVAL);
}
private boolean isRegistered() {
return mIsRegistered;
}
private void setRegistered() {
mIsRegistered = true;
}
private boolean probeService(HIDDeviceBLESteamController controller) {
if (isRegistered()) {
return true;
}
if (!mIsConnected) {
return false;
}
Log.v(TAG, "probeService controller=" + controller);
for (BluetoothGattService service : mGatt.getServices()) {
if (service.getUuid().equals(steamControllerService)) {
Log.v(TAG, "Found Valve steam controller service " + service.getUuid());
for (BluetoothGattCharacteristic chr : service.getCharacteristics()) {
if (chr.getUuid().equals(inputCharacteristic)) {
Log.v(TAG, "Found input characteristic");
// Start notifications
BluetoothGattDescriptor cccd = chr.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
if (cccd != null) {
enableNotification(chr.getUuid());
}
}
}
return true;
}
}
if ((mGatt.getServices().size() == 0) && mIsChromebook && !mIsReconnecting) {
Log.e(TAG, "Chromebook: Discovered services were empty; this almost certainly means the BtGatt.ContextMap bug has bitten us.");
mIsConnected = false;
mIsReconnecting = true;
mGatt.disconnect();
mGatt = connectGatt(false);
}
return false;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////
private void finishCurrentGattOperation() {
GattOperation op = null;
synchronized (mOperations) {
if (mCurrentOperation != null) {
op = mCurrentOperation;
mCurrentOperation = null;
}
}
if (op != null) {
boolean result = op.finish(); // TODO: Maybe in main thread as well?
// Our operation failed, let's add it back to the beginning of our queue.
if (!result) {
mOperations.addFirst(op);
}
}
executeNextGattOperation();
}
private void executeNextGattOperation() {
synchronized (mOperations) {
if (mCurrentOperation != null)
return;
if (mOperations.isEmpty())
return;
mCurrentOperation = mOperations.removeFirst();
}
// Run in main thread
mHandler.post(new Runnable() {
@Override
public void run() {
synchronized (mOperations) {
if (mCurrentOperation == null) {
Log.e(TAG, "Current operation null in executor?");
return;
}
mCurrentOperation.run();
// now wait for the GATT callback and when it comes, finish this operation
}
}
});
}
private void queueGattOperation(GattOperation op) {
synchronized (mOperations) {
mOperations.add(op);
}
executeNextGattOperation();
}
private void enableNotification(UUID chrUuid) {
GattOperation op = HIDDeviceBLESteamController.GattOperation.enableNotification(mGatt, chrUuid);
queueGattOperation(op);
}
public void writeCharacteristic(UUID uuid, byte[] value) {
GattOperation op = HIDDeviceBLESteamController.GattOperation.writeCharacteristic(mGatt, uuid, value);
queueGattOperation(op);
}
public void readCharacteristic(UUID uuid) {
GattOperation op = HIDDeviceBLESteamController.GattOperation.readCharacteristic(mGatt, uuid);
queueGattOperation(op);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
////////////// BluetoothGattCallback overridden methods
//////////////////////////////////////////////////////////////////////////////////////////////////////
public void onConnectionStateChange(BluetoothGatt g, int status, int newState) {
//Log.v(TAG, "onConnectionStateChange status=" + status + " newState=" + newState);
mIsReconnecting = false;
if (newState == 2) {
mIsConnected = true;
// Run directly, without GattOperation
if (!isRegistered()) {
mHandler.post(new Runnable() {
@Override
public void run() {
mGatt.discoverServices();
}
});
}
}
else if (newState == 0) {
mIsConnected = false;
}
// Disconnection is handled in SteamLink using the ACTION_ACL_DISCONNECTED Intent.
}
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
//Log.v(TAG, "onServicesDiscovered status=" + status);
if (status == 0) {
if (gatt.getServices().size() == 0) {
Log.v(TAG, "onServicesDiscovered returned zero services; something has gone horribly wrong down in Android's Bluetooth stack.");
mIsReconnecting = true;
mIsConnected = false;
gatt.disconnect();
mGatt = connectGatt(false);
}
else {
probeService(this);
}
}
}
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
//Log.v(TAG, "onCharacteristicRead status=" + status + " uuid=" + characteristic.getUuid());
if (characteristic.getUuid().equals(reportCharacteristic) && !mFrozen) {
mManager.HIDDeviceFeatureReport(getId(), characteristic.getValue());
}
finishCurrentGattOperation();
}
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
//Log.v(TAG, "onCharacteristicWrite status=" + status + " uuid=" + characteristic.getUuid());
if (characteristic.getUuid().equals(reportCharacteristic)) {
// Only register controller with the native side once it has been fully configured
if (!isRegistered()) {
Log.v(TAG, "Registering Steam Controller with ID: " + getId());
mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0);
setRegistered();
}
}
finishCurrentGattOperation();
}
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
// Enable this for verbose logging of controller input reports
//Log.v(TAG, "onCharacteristicChanged uuid=" + characteristic.getUuid() + " data=" + HexDump.dumpHexString(characteristic.getValue()));
if (characteristic.getUuid().equals(inputCharacteristic) && !mFrozen) {
mManager.HIDDeviceInputReport(getId(), characteristic.getValue());
}
}
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
//Log.v(TAG, "onDescriptorRead status=" + status);
}
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
BluetoothGattCharacteristic chr = descriptor.getCharacteristic();
//Log.v(TAG, "onDescriptorWrite status=" + status + " uuid=" + chr.getUuid() + " descriptor=" + descriptor.getUuid());
if (chr.getUuid().equals(inputCharacteristic)) {
boolean hasWrittenInputDescriptor = true;
BluetoothGattCharacteristic reportChr = chr.getService().getCharacteristic(reportCharacteristic);
if (reportChr != null) {
Log.v(TAG, "Writing report characteristic to enter valve mode");
reportChr.setValue(enterValveMode);
gatt.writeCharacteristic(reportChr);
}
}
finishCurrentGattOperation();
}
public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
//Log.v(TAG, "onReliableWriteCompleted status=" + status);
}
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
//Log.v(TAG, "onReadRemoteRssi status=" + status);
}
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
//Log.v(TAG, "onMtuChanged status=" + status);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
//////// Public API
//////////////////////////////////////////////////////////////////////////////////////////////////////
@Override
public int getId() {
return mDeviceId;
}
@Override
public int getVendorId() {
// Valve Corporation
final int VALVE_USB_VID = 0x28DE;
return VALVE_USB_VID;
}
@Override
public int getProductId() {
// We don't have an easy way to query from the Bluetooth device, but we know what it is
final int D0G_BLE2_PID = 0x1106;
return D0G_BLE2_PID;
}
@Override
public String getSerialNumber() {
// This will be read later via feature report by Steam
return "12345";
}
@Override
public int getVersion() {
return 0;
}
@Override
public String getManufacturerName() {
return "Valve Corporation";
}
@Override
public String getProductName() {
return "Steam Controller";
}
@Override
public UsbDevice getDevice() {
return null;
}
@Override
public boolean open() {
return true;
}
@Override
public int sendFeatureReport(byte[] report) {
if (!isRegistered()) {
Log.e(TAG, "Attempted sendFeatureReport before Steam Controller is registered!");
if (mIsConnected) {
probeService(this);
}
return -1;
}
// We need to skip the first byte, as that doesn't go over the air
byte[] actual_report = Arrays.copyOfRange(report, 1, report.length - 1);
//Log.v(TAG, "sendFeatureReport " + HexDump.dumpHexString(actual_report));
writeCharacteristic(reportCharacteristic, actual_report);
return report.length;
}
@Override
public int sendOutputReport(byte[] report) {
if (!isRegistered()) {
Log.e(TAG, "Attempted sendOutputReport before Steam Controller is registered!");
if (mIsConnected) {
probeService(this);
}
return -1;
}
//Log.v(TAG, "sendFeatureReport " + HexDump.dumpHexString(report));
writeCharacteristic(reportCharacteristic, report);
return report.length;
}
@Override
public boolean getFeatureReport(byte[] report) {
if (!isRegistered()) {
Log.e(TAG, "Attempted getFeatureReport before Steam Controller is registered!");
if (mIsConnected) {
probeService(this);
}
return false;
}
//Log.v(TAG, "getFeatureReport");
readCharacteristic(reportCharacteristic);
return true;
}
@Override
public void close() {
}
@Override
public void setFrozen(boolean frozen) {
mFrozen = frozen;
}
@Override
public void shutdown() {
close();
BluetoothGatt g = mGatt;
if (g != null) {
g.disconnect();
g.close();
mGatt = null;
}
mManager = null;
mIsRegistered = false;
mIsConnected = false;
mOperations.clear();
}
}

View File

@ -0,0 +1,678 @@
package org.libsdl.app;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.util.Log;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.hardware.usb.*;
import android.os.Handler;
import android.os.Looper;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
public class HIDDeviceManager {
private static final String TAG = "hidapi";
private static final String ACTION_USB_PERMISSION = "org.libsdl.app.USB_PERMISSION";
private static HIDDeviceManager sManager;
private static int sManagerRefCount = 0;
public static HIDDeviceManager acquire(Context context) {
if (sManagerRefCount == 0) {
sManager = new HIDDeviceManager(context);
}
++sManagerRefCount;
return sManager;
}
public static void release(HIDDeviceManager manager) {
if (manager == sManager) {
--sManagerRefCount;
if (sManagerRefCount == 0) {
sManager.close();
sManager = null;
}
}
}
private Context mContext;
private HashMap<Integer, HIDDevice> mDevicesById = new HashMap<Integer, HIDDevice>();
private HashMap<BluetoothDevice, HIDDeviceBLESteamController> mBluetoothDevices = new HashMap<BluetoothDevice, HIDDeviceBLESteamController>();
private int mNextDeviceId = 0;
private SharedPreferences mSharedPreferences = null;
private boolean mIsChromebook = false;
private UsbManager mUsbManager;
private Handler mHandler;
private BluetoothManager mBluetoothManager;
private List<BluetoothDevice> mLastBluetoothDevices;
private final BroadcastReceiver mUsbBroadcast = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
handleUsbDeviceAttached(usbDevice);
} else if (action.equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
handleUsbDeviceDetached(usbDevice);
} else if (action.equals(HIDDeviceManager.ACTION_USB_PERMISSION)) {
UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
handleUsbDevicePermission(usbDevice, intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false));
}
}
};
private final BroadcastReceiver mBluetoothBroadcast = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// Bluetooth device was connected. If it was a Steam Controller, handle it
if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.d(TAG, "Bluetooth device connected: " + device);
if (isSteamController(device)) {
connectBluetoothDevice(device);
}
}
// Bluetooth device was disconnected, remove from controller manager (if any)
if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.d(TAG, "Bluetooth device disconnected: " + device);
disconnectBluetoothDevice(device);
}
}
};
private HIDDeviceManager(final Context context) {
mContext = context;
// Make sure we have the HIDAPI library loaded with the native functions
try {
SDL.loadLibrary("hidapi");
} catch (Throwable e) {
Log.w(TAG, "Couldn't load hidapi: " + e.toString());
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setCancelable(false);
builder.setTitle("SDL HIDAPI Error");
builder.setMessage("Please report the following error to the SDL maintainers: " + e.getMessage());
builder.setNegativeButton("Quit", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
try {
// If our context is an activity, exit rather than crashing when we can't
// call our native functions.
Activity activity = (Activity)context;
activity.finish();
}
catch (ClassCastException cce) {
// Context wasn't an activity, there's nothing we can do. Give up and return.
}
}
});
builder.show();
return;
}
HIDDeviceRegisterCallback();
mSharedPreferences = mContext.getSharedPreferences("hidapi", Context.MODE_PRIVATE);
mIsChromebook = mContext.getPackageManager().hasSystemFeature("org.chromium.arc.device_management");
// if (shouldClear) {
// SharedPreferences.Editor spedit = mSharedPreferences.edit();
// spedit.clear();
// spedit.commit();
// }
// else
{
mNextDeviceId = mSharedPreferences.getInt("next_device_id", 0);
}
initializeUSB();
initializeBluetooth();
}
public Context getContext() {
return mContext;
}
public int getDeviceIDForIdentifier(String identifier) {
SharedPreferences.Editor spedit = mSharedPreferences.edit();
int result = mSharedPreferences.getInt(identifier, 0);
if (result == 0) {
result = mNextDeviceId++;
spedit.putInt("next_device_id", mNextDeviceId);
}
spedit.putInt(identifier, result);
spedit.commit();
return result;
}
private void initializeUSB() {
mUsbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);
/*
// Logging
for (UsbDevice device : mUsbManager.getDeviceList().values()) {
Log.i(TAG,"Path: " + device.getDeviceName());
Log.i(TAG,"Manufacturer: " + device.getManufacturerName());
Log.i(TAG,"Product: " + device.getProductName());
Log.i(TAG,"ID: " + device.getDeviceId());
Log.i(TAG,"Class: " + device.getDeviceClass());
Log.i(TAG,"Protocol: " + device.getDeviceProtocol());
Log.i(TAG,"Vendor ID " + device.getVendorId());
Log.i(TAG,"Product ID: " + device.getProductId());
Log.i(TAG,"Interface count: " + device.getInterfaceCount());
Log.i(TAG,"---------------------------------------");
// Get interface details
for (int index = 0; index < device.getInterfaceCount(); index++) {
UsbInterface mUsbInterface = device.getInterface(index);
Log.i(TAG," ***** *****");
Log.i(TAG," Interface index: " + index);
Log.i(TAG," Interface ID: " + mUsbInterface.getId());
Log.i(TAG," Interface class: " + mUsbInterface.getInterfaceClass());
Log.i(TAG," Interface subclass: " + mUsbInterface.getInterfaceSubclass());
Log.i(TAG," Interface protocol: " + mUsbInterface.getInterfaceProtocol());
Log.i(TAG," Endpoint count: " + mUsbInterface.getEndpointCount());
// Get endpoint details
for (int epi = 0; epi < mUsbInterface.getEndpointCount(); epi++)
{
UsbEndpoint mEndpoint = mUsbInterface.getEndpoint(epi);
Log.i(TAG," ++++ ++++ ++++");
Log.i(TAG," Endpoint index: " + epi);
Log.i(TAG," Attributes: " + mEndpoint.getAttributes());
Log.i(TAG," Direction: " + mEndpoint.getDirection());
Log.i(TAG," Number: " + mEndpoint.getEndpointNumber());
Log.i(TAG," Interval: " + mEndpoint.getInterval());
Log.i(TAG," Packet size: " + mEndpoint.getMaxPacketSize());
Log.i(TAG," Type: " + mEndpoint.getType());
}
}
}
Log.i(TAG," No more devices connected.");
*/
// Register for USB broadcasts and permission completions
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
filter.addAction(HIDDeviceManager.ACTION_USB_PERMISSION);
mContext.registerReceiver(mUsbBroadcast, filter);
for (UsbDevice usbDevice : mUsbManager.getDeviceList().values()) {
handleUsbDeviceAttached(usbDevice);
}
}
UsbManager getUSBManager() {
return mUsbManager;
}
private void shutdownUSB() {
try {
mContext.unregisterReceiver(mUsbBroadcast);
} catch (Exception e) {
// We may not have registered, that's okay
}
}
private boolean isHIDDeviceInterface(UsbDevice usbDevice, UsbInterface usbInterface) {
if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_HID) {
return true;
}
if (isXbox360Controller(usbDevice, usbInterface) || isXboxOneController(usbDevice, usbInterface)) {
return true;
}
return false;
}
private boolean isXbox360Controller(UsbDevice usbDevice, UsbInterface usbInterface) {
final int XB360_IFACE_SUBCLASS = 93;
final int XB360_IFACE_PROTOCOL = 1; // Wired
final int XB360W_IFACE_PROTOCOL = 129; // Wireless
final int[] SUPPORTED_VENDORS = {
0x0079, // GPD Win 2
0x044f, // Thrustmaster
0x045e, // Microsoft
0x046d, // Logitech
0x056e, // Elecom
0x06a3, // Saitek
0x0738, // Mad Catz
0x07ff, // Mad Catz
0x0e6f, // PDP
0x0f0d, // Hori
0x1038, // SteelSeries
0x11c9, // Nacon
0x12ab, // Unknown
0x1430, // RedOctane
0x146b, // BigBen
0x1532, // Razer Sabertooth
0x15e4, // Numark
0x162e, // Joytech
0x1689, // Razer Onza
0x1bad, // Harmonix
0x24c6, // PowerA
};
if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_VENDOR_SPEC &&
usbInterface.getInterfaceSubclass() == XB360_IFACE_SUBCLASS &&
(usbInterface.getInterfaceProtocol() == XB360_IFACE_PROTOCOL ||
usbInterface.getInterfaceProtocol() == XB360W_IFACE_PROTOCOL)) {
int vendor_id = usbDevice.getVendorId();
for (int supportedVid : SUPPORTED_VENDORS) {
if (vendor_id == supportedVid) {
return true;
}
}
}
return false;
}
private boolean isXboxOneController(UsbDevice usbDevice, UsbInterface usbInterface) {
final int XB1_IFACE_SUBCLASS = 71;
final int XB1_IFACE_PROTOCOL = 208;
final int[] SUPPORTED_VENDORS = {
0x045e, // Microsoft
0x0738, // Mad Catz
0x0e6f, // PDP
0x0f0d, // Hori
0x1532, // Razer Wildcat
0x24c6, // PowerA
0x2e24, // Hyperkin
};
if (usbInterface.getId() == 0 &&
usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_VENDOR_SPEC &&
usbInterface.getInterfaceSubclass() == XB1_IFACE_SUBCLASS &&
usbInterface.getInterfaceProtocol() == XB1_IFACE_PROTOCOL) {
int vendor_id = usbDevice.getVendorId();
for (int supportedVid : SUPPORTED_VENDORS) {
if (vendor_id == supportedVid) {
return true;
}
}
}
return false;
}
private void handleUsbDeviceAttached(UsbDevice usbDevice) {
connectHIDDeviceUSB(usbDevice);
}
private void handleUsbDeviceDetached(UsbDevice usbDevice) {
List<Integer> devices = new ArrayList<Integer>();
for (HIDDevice device : mDevicesById.values()) {
if (usbDevice.equals(device.getDevice())) {
devices.add(device.getId());
}
}
for (int id : devices) {
HIDDevice device = mDevicesById.get(id);
mDevicesById.remove(id);
device.shutdown();
HIDDeviceDisconnected(id);
}
}
private void handleUsbDevicePermission(UsbDevice usbDevice, boolean permission_granted) {
for (HIDDevice device : mDevicesById.values()) {
if (usbDevice.equals(device.getDevice())) {
boolean opened = false;
if (permission_granted) {
opened = device.open();
}
HIDDeviceOpenResult(device.getId(), opened);
}
}
}
private void connectHIDDeviceUSB(UsbDevice usbDevice) {
synchronized (this) {
int interface_mask = 0;
for (int interface_index = 0; interface_index < usbDevice.getInterfaceCount(); interface_index++) {
UsbInterface usbInterface = usbDevice.getInterface(interface_index);
if (isHIDDeviceInterface(usbDevice, usbInterface)) {
// Check to see if we've already added this interface
// This happens with the Xbox Series X controller which has a duplicate interface 0, which is inactive
int interface_id = usbInterface.getId();
if ((interface_mask & (1 << interface_id)) != 0) {
continue;
}
interface_mask |= (1 << interface_id);
HIDDeviceUSB device = new HIDDeviceUSB(this, usbDevice, interface_index);
int id = device.getId();
mDevicesById.put(id, device);
HIDDeviceConnected(id, device.getIdentifier(), device.getVendorId(), device.getProductId(), device.getSerialNumber(), device.getVersion(), device.getManufacturerName(), device.getProductName(), usbInterface.getId(), usbInterface.getInterfaceClass(), usbInterface.getInterfaceSubclass(), usbInterface.getInterfaceProtocol());
}
}
}
}
private void initializeBluetooth() {
Log.d(TAG, "Initializing Bluetooth");
if (mContext.getPackageManager().checkPermission(android.Manifest.permission.BLUETOOTH, mContext.getPackageName()) != PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "Couldn't initialize Bluetooth, missing android.permission.BLUETOOTH");
return;
}
// Find bonded bluetooth controllers and create SteamControllers for them
mBluetoothManager = (BluetoothManager)mContext.getSystemService(Context.BLUETOOTH_SERVICE);
if (mBluetoothManager == null) {
// This device doesn't support Bluetooth.
return;
}
BluetoothAdapter btAdapter = mBluetoothManager.getAdapter();
if (btAdapter == null) {
// This device has Bluetooth support in the codebase, but has no available adapters.
return;
}
// Get our bonded devices.
for (BluetoothDevice device : btAdapter.getBondedDevices()) {
Log.d(TAG, "Bluetooth device available: " + device);
if (isSteamController(device)) {
connectBluetoothDevice(device);
}
}
// NOTE: These don't work on Chromebooks, to my undying dismay.
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
mContext.registerReceiver(mBluetoothBroadcast, filter);
if (mIsChromebook) {
mHandler = new Handler(Looper.getMainLooper());
mLastBluetoothDevices = new ArrayList<BluetoothDevice>();
// final HIDDeviceManager finalThis = this;
// mHandler.postDelayed(new Runnable() {
// @Override
// public void run() {
// finalThis.chromebookConnectionHandler();
// }
// }, 5000);
}
}
private void shutdownBluetooth() {
try {
mContext.unregisterReceiver(mBluetoothBroadcast);
} catch (Exception e) {
// We may not have registered, that's okay
}
}
// Chromebooks do not pass along ACTION_ACL_CONNECTED / ACTION_ACL_DISCONNECTED properly.
// This function provides a sort of dummy version of that, watching for changes in the
// connected devices and attempting to add controllers as things change.
public void chromebookConnectionHandler() {
if (!mIsChromebook) {
return;
}
ArrayList<BluetoothDevice> disconnected = new ArrayList<BluetoothDevice>();
ArrayList<BluetoothDevice> connected = new ArrayList<BluetoothDevice>();
List<BluetoothDevice> currentConnected = mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT);
for (BluetoothDevice bluetoothDevice : currentConnected) {
if (!mLastBluetoothDevices.contains(bluetoothDevice)) {
connected.add(bluetoothDevice);
}
}
for (BluetoothDevice bluetoothDevice : mLastBluetoothDevices) {
if (!currentConnected.contains(bluetoothDevice)) {
disconnected.add(bluetoothDevice);
}
}
mLastBluetoothDevices = currentConnected;
for (BluetoothDevice bluetoothDevice : disconnected) {
disconnectBluetoothDevice(bluetoothDevice);
}
for (BluetoothDevice bluetoothDevice : connected) {
connectBluetoothDevice(bluetoothDevice);
}
final HIDDeviceManager finalThis = this;
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
finalThis.chromebookConnectionHandler();
}
}, 10000);
}
public boolean connectBluetoothDevice(BluetoothDevice bluetoothDevice) {
Log.v(TAG, "connectBluetoothDevice device=" + bluetoothDevice);
synchronized (this) {
if (mBluetoothDevices.containsKey(bluetoothDevice)) {
Log.v(TAG, "Steam controller with address " + bluetoothDevice + " already exists, attempting reconnect");
HIDDeviceBLESteamController device = mBluetoothDevices.get(bluetoothDevice);
device.reconnect();
return false;
}
HIDDeviceBLESteamController device = new HIDDeviceBLESteamController(this, bluetoothDevice);
int id = device.getId();
mBluetoothDevices.put(bluetoothDevice, device);
mDevicesById.put(id, device);
// The Steam Controller will mark itself connected once initialization is complete
}
return true;
}
public void disconnectBluetoothDevice(BluetoothDevice bluetoothDevice) {
synchronized (this) {
HIDDeviceBLESteamController device = mBluetoothDevices.get(bluetoothDevice);
if (device == null)
return;
int id = device.getId();
mBluetoothDevices.remove(bluetoothDevice);
mDevicesById.remove(id);
device.shutdown();
HIDDeviceDisconnected(id);
}
}
public boolean isSteamController(BluetoothDevice bluetoothDevice) {
// Sanity check. If you pass in a null device, by definition it is never a Steam Controller.
if (bluetoothDevice == null) {
return false;
}
// If the device has no local name, we really don't want to try an equality check against it.
if (bluetoothDevice.getName() == null) {
return false;
}
return bluetoothDevice.getName().equals("SteamController") && ((bluetoothDevice.getType() & BluetoothDevice.DEVICE_TYPE_LE) != 0);
}
private void close() {
shutdownUSB();
shutdownBluetooth();
synchronized (this) {
for (HIDDevice device : mDevicesById.values()) {
device.shutdown();
}
mDevicesById.clear();
mBluetoothDevices.clear();
HIDDeviceReleaseCallback();
}
}
public void setFrozen(boolean frozen) {
synchronized (this) {
for (HIDDevice device : mDevicesById.values()) {
device.setFrozen(frozen);
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////
private HIDDevice getDevice(int id) {
synchronized (this) {
HIDDevice result = mDevicesById.get(id);
if (result == null) {
Log.v(TAG, "No device for id: " + id);
Log.v(TAG, "Available devices: " + mDevicesById.keySet());
}
return result;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
////////// JNI interface functions
//////////////////////////////////////////////////////////////////////////////////////////////////////
public boolean openDevice(int deviceID) {
Log.v(TAG, "openDevice deviceID=" + deviceID);
HIDDevice device = getDevice(deviceID);
if (device == null) {
HIDDeviceDisconnected(deviceID);
return false;
}
// Look to see if this is a USB device and we have permission to access it
UsbDevice usbDevice = device.getDevice();
if (usbDevice != null && !mUsbManager.hasPermission(usbDevice)) {
HIDDeviceOpenPending(deviceID);
try {
mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, new Intent(HIDDeviceManager.ACTION_USB_PERMISSION), 0));
} catch (Exception e) {
Log.v(TAG, "Couldn't request permission for USB device " + usbDevice);
HIDDeviceOpenResult(deviceID, false);
}
return false;
}
try {
return device.open();
} catch (Exception e) {
Log.e(TAG, "Got exception: " + Log.getStackTraceString(e));
}
return false;
}
public int sendOutputReport(int deviceID, byte[] report) {
try {
//Log.v(TAG, "sendOutputReport deviceID=" + deviceID + " length=" + report.length);
HIDDevice device;
device = getDevice(deviceID);
if (device == null) {
HIDDeviceDisconnected(deviceID);
return -1;
}
return device.sendOutputReport(report);
} catch (Exception e) {
Log.e(TAG, "Got exception: " + Log.getStackTraceString(e));
}
return -1;
}
public int sendFeatureReport(int deviceID, byte[] report) {
try {
//Log.v(TAG, "sendFeatureReport deviceID=" + deviceID + " length=" + report.length);
HIDDevice device;
device = getDevice(deviceID);
if (device == null) {
HIDDeviceDisconnected(deviceID);
return -1;
}
return device.sendFeatureReport(report);
} catch (Exception e) {
Log.e(TAG, "Got exception: " + Log.getStackTraceString(e));
}
return -1;
}
public boolean getFeatureReport(int deviceID, byte[] report) {
try {
//Log.v(TAG, "getFeatureReport deviceID=" + deviceID);
HIDDevice device;
device = getDevice(deviceID);
if (device == null) {
HIDDeviceDisconnected(deviceID);
return false;
}
return device.getFeatureReport(report);
} catch (Exception e) {
Log.e(TAG, "Got exception: " + Log.getStackTraceString(e));
}
return false;
}
public void closeDevice(int deviceID) {
try {
Log.v(TAG, "closeDevice deviceID=" + deviceID);
HIDDevice device;
device = getDevice(deviceID);
if (device == null) {
HIDDeviceDisconnected(deviceID);
return;
}
device.close();
} catch (Exception e) {
Log.e(TAG, "Got exception: " + Log.getStackTraceString(e));
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////// Native methods
//////////////////////////////////////////////////////////////////////////////////////////////////////
private native void HIDDeviceRegisterCallback();
private native void HIDDeviceReleaseCallback();
native void HIDDeviceConnected(int deviceID, String identifier, int vendorId, int productId, String serial_number, int release_number, String manufacturer_string, String product_string, int interface_number, int interface_class, int interface_subclass, int interface_protocol);
native void HIDDeviceOpenPending(int deviceID);
native void HIDDeviceOpenResult(int deviceID, boolean opened);
native void HIDDeviceDisconnected(int deviceID);
native void HIDDeviceInputReport(int deviceID, byte[] report);
native void HIDDeviceFeatureReport(int deviceID, byte[] report);
}

View File

@ -0,0 +1,309 @@
package org.libsdl.app;
import android.hardware.usb.*;
import android.os.Build;
import android.util.Log;
import java.util.Arrays;
class HIDDeviceUSB implements HIDDevice {
private static final String TAG = "hidapi";
protected HIDDeviceManager mManager;
protected UsbDevice mDevice;
protected int mInterfaceIndex;
protected int mInterface;
protected int mDeviceId;
protected UsbDeviceConnection mConnection;
protected UsbEndpoint mInputEndpoint;
protected UsbEndpoint mOutputEndpoint;
protected InputThread mInputThread;
protected boolean mRunning;
protected boolean mFrozen;
public HIDDeviceUSB(HIDDeviceManager manager, UsbDevice usbDevice, int interface_index) {
mManager = manager;
mDevice = usbDevice;
mInterfaceIndex = interface_index;
mInterface = mDevice.getInterface(mInterfaceIndex).getId();
mDeviceId = manager.getDeviceIDForIdentifier(getIdentifier());
mRunning = false;
}
public String getIdentifier() {
return String.format("%s/%x/%x/%d", mDevice.getDeviceName(), mDevice.getVendorId(), mDevice.getProductId(), mInterfaceIndex);
}
@Override
public int getId() {
return mDeviceId;
}
@Override
public int getVendorId() {
return mDevice.getVendorId();
}
@Override
public int getProductId() {
return mDevice.getProductId();
}
@Override
public String getSerialNumber() {
String result = null;
if (Build.VERSION.SDK_INT >= 21) {
try {
result = mDevice.getSerialNumber();
}
catch (SecurityException exception) {
//Log.w(TAG, "App permissions mean we cannot get serial number for device " + getDeviceName() + " message: " + exception.getMessage());
}
}
if (result == null) {
result = "";
}
return result;
}
@Override
public int getVersion() {
return 0;
}
@Override
public String getManufacturerName() {
String result = null;
if (Build.VERSION.SDK_INT >= 21) {
result = mDevice.getManufacturerName();
}
if (result == null) {
result = String.format("%x", getVendorId());
}
return result;
}
@Override
public String getProductName() {
String result = null;
if (Build.VERSION.SDK_INT >= 21) {
result = mDevice.getProductName();
}
if (result == null) {
result = String.format("%x", getProductId());
}
return result;
}
@Override
public UsbDevice getDevice() {
return mDevice;
}
public String getDeviceName() {
return getManufacturerName() + " " + getProductName() + "(0x" + String.format("%x", getVendorId()) + "/0x" + String.format("%x", getProductId()) + ")";
}
@Override
public boolean open() {
mConnection = mManager.getUSBManager().openDevice(mDevice);
if (mConnection == null) {
Log.w(TAG, "Unable to open USB device " + getDeviceName());
return false;
}
// Force claim our interface
UsbInterface iface = mDevice.getInterface(mInterfaceIndex);
if (!mConnection.claimInterface(iface, true)) {
Log.w(TAG, "Failed to claim interfaces on USB device " + getDeviceName());
close();
return false;
}
// Find the endpoints
for (int j = 0; j < iface.getEndpointCount(); j++) {
UsbEndpoint endpt = iface.getEndpoint(j);
switch (endpt.getDirection()) {
case UsbConstants.USB_DIR_IN:
if (mInputEndpoint == null) {
mInputEndpoint = endpt;
}
break;
case UsbConstants.USB_DIR_OUT:
if (mOutputEndpoint == null) {
mOutputEndpoint = endpt;
}
break;
}
}
// Make sure the required endpoints were present
if (mInputEndpoint == null || mOutputEndpoint == null) {
Log.w(TAG, "Missing required endpoint on USB device " + getDeviceName());
close();
return false;
}
// Start listening for input
mRunning = true;
mInputThread = new InputThread();
mInputThread.start();
return true;
}
@Override
public int sendFeatureReport(byte[] report) {
int res = -1;
int offset = 0;
int length = report.length;
boolean skipped_report_id = false;
byte report_number = report[0];
if (report_number == 0x0) {
++offset;
--length;
skipped_report_id = true;
}
res = mConnection.controlTransfer(
UsbConstants.USB_TYPE_CLASS | 0x01 /*RECIPIENT_INTERFACE*/ | UsbConstants.USB_DIR_OUT,
0x09/*HID set_report*/,
(3/*HID feature*/ << 8) | report_number,
mInterface,
report, offset, length,
1000/*timeout millis*/);
if (res < 0) {
Log.w(TAG, "sendFeatureReport() returned " + res + " on device " + getDeviceName());
return -1;
}
if (skipped_report_id) {
++length;
}
return length;
}
@Override
public int sendOutputReport(byte[] report) {
int r = mConnection.bulkTransfer(mOutputEndpoint, report, report.length, 1000);
if (r != report.length) {
Log.w(TAG, "sendOutputReport() returned " + r + " on device " + getDeviceName());
}
return r;
}
@Override
public boolean getFeatureReport(byte[] report) {
int res = -1;
int offset = 0;
int length = report.length;
boolean skipped_report_id = false;
byte report_number = report[0];
if (report_number == 0x0) {
/* Offset the return buffer by 1, so that the report ID
will remain in byte 0. */
++offset;
--length;
skipped_report_id = true;
}
res = mConnection.controlTransfer(
UsbConstants.USB_TYPE_CLASS | 0x01 /*RECIPIENT_INTERFACE*/ | UsbConstants.USB_DIR_IN,
0x01/*HID get_report*/,
(3/*HID feature*/ << 8) | report_number,
mInterface,
report, offset, length,
1000/*timeout millis*/);
if (res < 0) {
Log.w(TAG, "getFeatureReport() returned " + res + " on device " + getDeviceName());
return false;
}
if (skipped_report_id) {
++res;
++length;
}
byte[] data;
if (res == length) {
data = report;
} else {
data = Arrays.copyOfRange(report, 0, res);
}
mManager.HIDDeviceFeatureReport(mDeviceId, data);
return true;
}
@Override
public void close() {
mRunning = false;
if (mInputThread != null) {
while (mInputThread.isAlive()) {
mInputThread.interrupt();
try {
mInputThread.join();
} catch (InterruptedException e) {
// Keep trying until we're done
}
}
mInputThread = null;
}
if (mConnection != null) {
UsbInterface iface = mDevice.getInterface(mInterfaceIndex);
mConnection.releaseInterface(iface);
mConnection.close();
mConnection = null;
}
}
@Override
public void shutdown() {
close();
mManager = null;
}
@Override
public void setFrozen(boolean frozen) {
mFrozen = frozen;
}
protected class InputThread extends Thread {
@Override
public void run() {
int packetSize = mInputEndpoint.getMaxPacketSize();
byte[] packet = new byte[packetSize];
while (mRunning) {
int r;
try
{
r = mConnection.bulkTransfer(mInputEndpoint, packet, packetSize, 1000);
}
catch (Exception e)
{
Log.v(TAG, "Exception in UsbDeviceConnection bulktransfer: " + e);
break;
}
if (r < 0) {
// Could be a timeout or an I/O error
}
if (r > 0) {
byte[] data;
if (r == packetSize) {
data = packet;
} else {
data = Arrays.copyOfRange(packet, 0, r);
}
if (!mFrozen) {
mManager.HIDDeviceInputReport(mDeviceId, data);
}
}
}
}
}
}

View File

@ -0,0 +1,85 @@
package org.libsdl.app;
import android.content.Context;
import java.lang.Class;
import java.lang.reflect.Method;
/**
SDL library initialization
*/
public class SDL {
// This function should be called first and sets up the native code
// so it can call into the Java classes
public static void setupJNI() {
SDLActivity.nativeSetupJNI();
SDLAudioManager.nativeSetupJNI();
SDLControllerManager.nativeSetupJNI();
}
// This function should be called each time the activity is started
public static void initialize() {
setContext(null);
SDLActivity.initialize();
SDLAudioManager.initialize();
SDLControllerManager.initialize();
}
// This function stores the current activity (SDL or not)
public static void setContext(Context context) {
mContext = context;
}
public static Context getContext() {
return mContext;
}
public static void loadLibrary(String libraryName) throws UnsatisfiedLinkError, SecurityException, NullPointerException {
if (libraryName == null) {
throw new NullPointerException("No library name provided.");
}
try {
// Let's see if we have ReLinker available in the project. This is necessary for
// some projects that have huge numbers of local libraries bundled, and thus may
// trip a bug in Android's native library loader which ReLinker works around. (If
// loadLibrary works properly, ReLinker will simply use the normal Android method
// internally.)
//
// To use ReLinker, just add it as a dependency. For more information, see
// https://github.com/KeepSafe/ReLinker for ReLinker's repository.
//
Class<?> relinkClass = mContext.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker");
Class<?> relinkListenerClass = mContext.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker$LoadListener");
Class<?> contextClass = mContext.getClassLoader().loadClass("android.content.Context");
Class<?> stringClass = mContext.getClassLoader().loadClass("java.lang.String");
// Get a 'force' instance of the ReLinker, so we can ensure libraries are reinstalled if
// they've changed during updates.
Method forceMethod = relinkClass.getDeclaredMethod("force");
Object relinkInstance = forceMethod.invoke(null);
Class<?> relinkInstanceClass = relinkInstance.getClass();
// Actually load the library!
Method loadMethod = relinkInstanceClass.getDeclaredMethod("loadLibrary", contextClass, stringClass, stringClass, relinkListenerClass);
loadMethod.invoke(relinkInstance, mContext, libraryName, null, null);
}
catch (final Throwable e) {
// Fall back
try {
System.loadLibrary(libraryName);
}
catch (final UnsatisfiedLinkError ule) {
throw ule;
}
catch (final SecurityException se) {
throw se;
}
}
}
protected static Context mContext;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,390 @@
package org.libsdl.app;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.os.Build;
import android.util.Log;
public class SDLAudioManager
{
protected static final String TAG = "SDLAudio";
protected static AudioTrack mAudioTrack;
protected static AudioRecord mAudioRecord;
public static void initialize() {
mAudioTrack = null;
mAudioRecord = null;
}
// Audio
protected static String getAudioFormatString(int audioFormat) {
switch (audioFormat) {
case AudioFormat.ENCODING_PCM_8BIT:
return "8-bit";
case AudioFormat.ENCODING_PCM_16BIT:
return "16-bit";
case AudioFormat.ENCODING_PCM_FLOAT:
return "float";
default:
return Integer.toString(audioFormat);
}
}
protected static int[] open(boolean isCapture, int sampleRate, int audioFormat, int desiredChannels, int desiredFrames) {
int channelConfig;
int sampleSize;
int frameSize;
Log.v(TAG, "Opening " + (isCapture ? "capture" : "playback") + ", requested " + desiredFrames + " frames of " + desiredChannels + " channel " + getAudioFormatString(audioFormat) + " audio at " + sampleRate + " Hz");
/* On older devices let's use known good settings */
if (Build.VERSION.SDK_INT < 21) {
if (desiredChannels > 2) {
desiredChannels = 2;
}
if (sampleRate < 8000) {
sampleRate = 8000;
} else if (sampleRate > 48000) {
sampleRate = 48000;
}
}
if (audioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
int minSDKVersion = (isCapture ? 23 : 21);
if (Build.VERSION.SDK_INT < minSDKVersion) {
audioFormat = AudioFormat.ENCODING_PCM_16BIT;
}
}
switch (audioFormat)
{
case AudioFormat.ENCODING_PCM_8BIT:
sampleSize = 1;
break;
case AudioFormat.ENCODING_PCM_16BIT:
sampleSize = 2;
break;
case AudioFormat.ENCODING_PCM_FLOAT:
sampleSize = 4;
break;
default:
Log.v(TAG, "Requested format " + audioFormat + ", getting ENCODING_PCM_16BIT");
audioFormat = AudioFormat.ENCODING_PCM_16BIT;
sampleSize = 2;
break;
}
if (isCapture) {
switch (desiredChannels) {
case 1:
channelConfig = AudioFormat.CHANNEL_IN_MONO;
break;
case 2:
channelConfig = AudioFormat.CHANNEL_IN_STEREO;
break;
default:
Log.v(TAG, "Requested " + desiredChannels + " channels, getting stereo");
desiredChannels = 2;
channelConfig = AudioFormat.CHANNEL_IN_STEREO;
break;
}
} else {
switch (desiredChannels) {
case 1:
channelConfig = AudioFormat.CHANNEL_OUT_MONO;
break;
case 2:
channelConfig = AudioFormat.CHANNEL_OUT_STEREO;
break;
case 3:
channelConfig = AudioFormat.CHANNEL_OUT_STEREO | AudioFormat.CHANNEL_OUT_FRONT_CENTER;
break;
case 4:
channelConfig = AudioFormat.CHANNEL_OUT_QUAD;
break;
case 5:
channelConfig = AudioFormat.CHANNEL_OUT_QUAD | AudioFormat.CHANNEL_OUT_FRONT_CENTER;
break;
case 6:
channelConfig = AudioFormat.CHANNEL_OUT_5POINT1;
break;
case 7:
channelConfig = AudioFormat.CHANNEL_OUT_5POINT1 | AudioFormat.CHANNEL_OUT_BACK_CENTER;
break;
case 8:
if (Build.VERSION.SDK_INT >= 23) {
channelConfig = AudioFormat.CHANNEL_OUT_7POINT1_SURROUND;
} else {
Log.v(TAG, "Requested " + desiredChannels + " channels, getting 5.1 surround");
desiredChannels = 6;
channelConfig = AudioFormat.CHANNEL_OUT_5POINT1;
}
break;
default:
Log.v(TAG, "Requested " + desiredChannels + " channels, getting stereo");
desiredChannels = 2;
channelConfig = AudioFormat.CHANNEL_OUT_STEREO;
break;
}
/*
Log.v(TAG, "Speaker configuration (and order of channels):");
if ((channelConfig & 0x00000004) != 0) {
Log.v(TAG, " CHANNEL_OUT_FRONT_LEFT");
}
if ((channelConfig & 0x00000008) != 0) {
Log.v(TAG, " CHANNEL_OUT_FRONT_RIGHT");
}
if ((channelConfig & 0x00000010) != 0) {
Log.v(TAG, " CHANNEL_OUT_FRONT_CENTER");
}
if ((channelConfig & 0x00000020) != 0) {
Log.v(TAG, " CHANNEL_OUT_LOW_FREQUENCY");
}
if ((channelConfig & 0x00000040) != 0) {
Log.v(TAG, " CHANNEL_OUT_BACK_LEFT");
}
if ((channelConfig & 0x00000080) != 0) {
Log.v(TAG, " CHANNEL_OUT_BACK_RIGHT");
}
if ((channelConfig & 0x00000100) != 0) {
Log.v(TAG, " CHANNEL_OUT_FRONT_LEFT_OF_CENTER");
}
if ((channelConfig & 0x00000200) != 0) {
Log.v(TAG, " CHANNEL_OUT_FRONT_RIGHT_OF_CENTER");
}
if ((channelConfig & 0x00000400) != 0) {
Log.v(TAG, " CHANNEL_OUT_BACK_CENTER");
}
if ((channelConfig & 0x00000800) != 0) {
Log.v(TAG, " CHANNEL_OUT_SIDE_LEFT");
}
if ((channelConfig & 0x00001000) != 0) {
Log.v(TAG, " CHANNEL_OUT_SIDE_RIGHT");
}
*/
}
frameSize = (sampleSize * desiredChannels);
// Let the user pick a larger buffer if they really want -- but ye
// gods they probably shouldn't, the minimums are horrifyingly high
// latency already
int minBufferSize;
if (isCapture) {
minBufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
} else {
minBufferSize = AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat);
}
desiredFrames = Math.max(desiredFrames, (minBufferSize + frameSize - 1) / frameSize);
int[] results = new int[4];
if (isCapture) {
if (mAudioRecord == null) {
mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, sampleRate,
channelConfig, audioFormat, desiredFrames * frameSize);
// see notes about AudioTrack state in audioOpen(), above. Probably also applies here.
if (mAudioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
Log.e(TAG, "Failed during initialization of AudioRecord");
mAudioRecord.release();
mAudioRecord = null;
return null;
}
mAudioRecord.startRecording();
}
results[0] = mAudioRecord.getSampleRate();
results[1] = mAudioRecord.getAudioFormat();
results[2] = mAudioRecord.getChannelCount();
} else {
if (mAudioTrack == null) {
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM);
// Instantiating AudioTrack can "succeed" without an exception and the track may still be invalid
// Ref: https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/media/java/android/media/AudioTrack.java
// Ref: http://developer.android.com/reference/android/media/AudioTrack.html#getState()
if (mAudioTrack.getState() != AudioTrack.STATE_INITIALIZED) {
/* Try again, with safer values */
Log.e(TAG, "Failed during initialization of Audio Track");
mAudioTrack.release();
mAudioTrack = null;
return null;
}
mAudioTrack.play();
}
results[0] = mAudioTrack.getSampleRate();
results[1] = mAudioTrack.getAudioFormat();
results[2] = mAudioTrack.getChannelCount();
}
results[3] = desiredFrames;
Log.v(TAG, "Opening " + (isCapture ? "capture" : "playback") + ", got " + results[3] + " frames of " + results[2] + " channel " + getAudioFormatString(results[1]) + " audio at " + results[0] + " Hz");
return results;
}
/**
* This method is called by SDL using JNI.
*/
public static int[] audioOpen(int sampleRate, int audioFormat, int desiredChannels, int desiredFrames) {
return open(false, sampleRate, audioFormat, desiredChannels, desiredFrames);
}
/**
* This method is called by SDL using JNI.
*/
public static void audioWriteFloatBuffer(float[] buffer) {
if (mAudioTrack == null) {
Log.e(TAG, "Attempted to make audio call with uninitialized audio!");
return;
}
for (int i = 0; i < buffer.length;) {
int result = mAudioTrack.write(buffer, i, buffer.length - i, AudioTrack.WRITE_BLOCKING);
if (result > 0) {
i += result;
} else if (result == 0) {
try {
Thread.sleep(1);
} catch(InterruptedException e) {
// Nom nom
}
} else {
Log.w(TAG, "SDL audio: error return from write(float)");
return;
}
}
}
/**
* This method is called by SDL using JNI.
*/
public static void audioWriteShortBuffer(short[] buffer) {
if (mAudioTrack == null) {
Log.e(TAG, "Attempted to make audio call with uninitialized audio!");
return;
}
for (int i = 0; i < buffer.length;) {
int result = mAudioTrack.write(buffer, i, buffer.length - i);
if (result > 0) {
i += result;
} else if (result == 0) {
try {
Thread.sleep(1);
} catch(InterruptedException e) {
// Nom nom
}
} else {
Log.w(TAG, "SDL audio: error return from write(short)");
return;
}
}
}
/**
* This method is called by SDL using JNI.
*/
public static void audioWriteByteBuffer(byte[] buffer) {
if (mAudioTrack == null) {
Log.e(TAG, "Attempted to make audio call with uninitialized audio!");
return;
}
for (int i = 0; i < buffer.length; ) {
int result = mAudioTrack.write(buffer, i, buffer.length - i);
if (result > 0) {
i += result;
} else if (result == 0) {
try {
Thread.sleep(1);
} catch(InterruptedException e) {
// Nom nom
}
} else {
Log.w(TAG, "SDL audio: error return from write(byte)");
return;
}
}
}
/**
* This method is called by SDL using JNI.
*/
public static int[] captureOpen(int sampleRate, int audioFormat, int desiredChannels, int desiredFrames) {
return open(true, sampleRate, audioFormat, desiredChannels, desiredFrames);
}
/** This method is called by SDL using JNI. */
public static int captureReadFloatBuffer(float[] buffer, boolean blocking) {
return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);
}
/** This method is called by SDL using JNI. */
public static int captureReadShortBuffer(short[] buffer, boolean blocking) {
if (Build.VERSION.SDK_INT < 23) {
return mAudioRecord.read(buffer, 0, buffer.length);
} else {
return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);
}
}
/** This method is called by SDL using JNI. */
public static int captureReadByteBuffer(byte[] buffer, boolean blocking) {
if (Build.VERSION.SDK_INT < 23) {
return mAudioRecord.read(buffer, 0, buffer.length);
} else {
return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);
}
}
/** This method is called by SDL using JNI. */
public static void audioClose() {
if (mAudioTrack != null) {
mAudioTrack.stop();
mAudioTrack.release();
mAudioTrack = null;
}
}
/** This method is called by SDL using JNI. */
public static void captureClose() {
if (mAudioRecord != null) {
mAudioRecord.stop();
mAudioRecord.release();
mAudioRecord = null;
}
}
/** This method is called by SDL using JNI. */
public static void audioSetThreadPriority(boolean iscapture, int device_id) {
try {
/* Set thread name */
if (iscapture) {
Thread.currentThread().setName("SDLAudioC" + device_id);
} else {
Thread.currentThread().setName("SDLAudioP" + device_id);
}
/* Set thread priority */
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO);
} catch (Exception e) {
Log.v(TAG, "modify thread properties failed " + e.toString());
}
}
public static native int nativeSetupJNI();
}

View File

@ -0,0 +1,792 @@
package org.libsdl.app;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import android.content.Context;
import android.os.Build;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.util.Log;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
public class SDLControllerManager
{
public static native int nativeSetupJNI();
public static native int nativeAddJoystick(int device_id, String name, String desc,
int vendor_id, int product_id,
boolean is_accelerometer, int button_mask,
int naxes, int nhats, int nballs);
public static native int nativeRemoveJoystick(int device_id);
public static native int nativeAddHaptic(int device_id, String name);
public static native int nativeRemoveHaptic(int device_id);
public static native int onNativePadDown(int device_id, int keycode);
public static native int onNativePadUp(int device_id, int keycode);
public static native void onNativeJoy(int device_id, int axis,
float value);
public static native void onNativeHat(int device_id, int hat_id,
int x, int y);
protected static SDLJoystickHandler mJoystickHandler;
protected static SDLHapticHandler mHapticHandler;
private static final String TAG = "SDLControllerManager";
public static void initialize() {
if (mJoystickHandler == null) {
if (Build.VERSION.SDK_INT >= 19) {
mJoystickHandler = new SDLJoystickHandler_API19();
} else {
mJoystickHandler = new SDLJoystickHandler_API16();
}
}
if (mHapticHandler == null) {
if (Build.VERSION.SDK_INT >= 26) {
mHapticHandler = new SDLHapticHandler_API26();
} else {
mHapticHandler = new SDLHapticHandler();
}
}
}
// Joystick glue code, just a series of stubs that redirect to the SDLJoystickHandler instance
public static boolean handleJoystickMotionEvent(MotionEvent event) {
return mJoystickHandler.handleMotionEvent(event);
}
/**
* This method is called by SDL using JNI.
*/
public static void pollInputDevices() {
mJoystickHandler.pollInputDevices();
}
/**
* This method is called by SDL using JNI.
*/
public static void pollHapticDevices() {
mHapticHandler.pollHapticDevices();
}
/**
* This method is called by SDL using JNI.
*/
public static void hapticRun(int device_id, float intensity, int length) {
mHapticHandler.run(device_id, intensity, length);
}
/**
* This method is called by SDL using JNI.
*/
public static void hapticStop(int device_id)
{
mHapticHandler.stop(device_id);
}
// Check if a given device is considered a possible SDL joystick
public static boolean isDeviceSDLJoystick(int deviceId) {
InputDevice device = InputDevice.getDevice(deviceId);
// We cannot use InputDevice.isVirtual before API 16, so let's accept
// only nonnegative device ids (VIRTUAL_KEYBOARD equals -1)
if ((device == null) || (deviceId < 0)) {
return false;
}
int sources = device.getSources();
/* This is called for every button press, so let's not spam the logs */
/*
if ((sources & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
Log.v(TAG, "Input device " + device.getName() + " has class joystick.");
}
if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD) {
Log.v(TAG, "Input device " + device.getName() + " is a dpad.");
}
if ((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) {
Log.v(TAG, "Input device " + device.getName() + " is a gamepad.");
}
*/
return ((sources & InputDevice.SOURCE_CLASS_JOYSTICK) != 0 ||
((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD) ||
((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD)
);
}
}
class SDLJoystickHandler {
/**
* Handles given MotionEvent.
* @param event the event to be handled.
* @return if given event was processed.
*/
public boolean handleMotionEvent(MotionEvent event) {
return false;
}
/**
* Handles adding and removing of input devices.
*/
public void pollInputDevices() {
}
}
/* Actual joystick functionality available for API >= 12 devices */
class SDLJoystickHandler_API16 extends SDLJoystickHandler {
static class SDLJoystick {
public int device_id;
public String name;
public String desc;
public ArrayList<InputDevice.MotionRange> axes;
public ArrayList<InputDevice.MotionRange> hats;
}
static class RangeComparator implements Comparator<InputDevice.MotionRange> {
@Override
public int compare(InputDevice.MotionRange arg0, InputDevice.MotionRange arg1) {
// Some controllers, like the Moga Pro 2, return AXIS_GAS (22) for right trigger and AXIS_BRAKE (23) for left trigger - swap them so they're sorted in the right order for SDL
int arg0Axis = arg0.getAxis();
int arg1Axis = arg1.getAxis();
if (arg0Axis == MotionEvent.AXIS_GAS) {
arg0Axis = MotionEvent.AXIS_BRAKE;
} else if (arg0Axis == MotionEvent.AXIS_BRAKE) {
arg0Axis = MotionEvent.AXIS_GAS;
}
if (arg1Axis == MotionEvent.AXIS_GAS) {
arg1Axis = MotionEvent.AXIS_BRAKE;
} else if (arg1Axis == MotionEvent.AXIS_BRAKE) {
arg1Axis = MotionEvent.AXIS_GAS;
}
return arg0Axis - arg1Axis;
}
}
private final ArrayList<SDLJoystick> mJoysticks;
public SDLJoystickHandler_API16() {
mJoysticks = new ArrayList<SDLJoystick>();
}
@Override
public void pollInputDevices() {
int[] deviceIds = InputDevice.getDeviceIds();
for (int device_id : deviceIds) {
if (SDLControllerManager.isDeviceSDLJoystick(device_id)) {
SDLJoystick joystick = getJoystick(device_id);
if (joystick == null) {
InputDevice joystickDevice = InputDevice.getDevice(device_id);
joystick = new SDLJoystick();
joystick.device_id = device_id;
joystick.name = joystickDevice.getName();
joystick.desc = getJoystickDescriptor(joystickDevice);
joystick.axes = new ArrayList<InputDevice.MotionRange>();
joystick.hats = new ArrayList<InputDevice.MotionRange>();
List<InputDevice.MotionRange> ranges = joystickDevice.getMotionRanges();
Collections.sort(ranges, new RangeComparator());
for (InputDevice.MotionRange range : ranges) {
if ((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) {
joystick.hats.add(range);
} else {
joystick.axes.add(range);
}
}
}
mJoysticks.add(joystick);
SDLControllerManager.nativeAddJoystick(joystick.device_id, joystick.name, joystick.desc,
getVendorId(joystickDevice), getProductId(joystickDevice), false,
getButtonMask(joystickDevice), joystick.axes.size(), joystick.hats.size()/2, 0);
}
}
}
/* Check removed devices */
ArrayList<Integer> removedDevices = null;
for (SDLJoystick joystick : mJoysticks) {
int device_id = joystick.device_id;
int i;
for (i = 0; i < deviceIds.length; i++) {
if (device_id == deviceIds[i]) break;
}
if (i == deviceIds.length) {
if (removedDevices == null) {
removedDevices = new ArrayList<Integer>();
}
removedDevices.add(device_id);
}
}
if (removedDevices != null) {
for (int device_id : removedDevices) {
SDLControllerManager.nativeRemoveJoystick(device_id);
for (int i = 0; i < mJoysticks.size(); i++) {
if (mJoysticks.get(i).device_id == device_id) {
mJoysticks.remove(i);
break;
}
}
}
}
}
protected SDLJoystick getJoystick(int device_id) {
for (SDLJoystick joystick : mJoysticks) {
if (joystick.device_id == device_id) {
return joystick;
}
}
return null;
}
@Override
public boolean handleMotionEvent(MotionEvent event) {
if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) != 0) {
int actionPointerIndex = event.getActionIndex();
int action = event.getActionMasked();
if (action == MotionEvent.ACTION_MOVE) {
SDLJoystick joystick = getJoystick(event.getDeviceId());
if (joystick != null) {
for (int i = 0; i < joystick.axes.size(); i++) {
InputDevice.MotionRange range = joystick.axes.get(i);
/* Normalize the value to -1...1 */
float value = (event.getAxisValue(range.getAxis(), actionPointerIndex) - range.getMin()) / range.getRange() * 2.0f - 1.0f;
SDLControllerManager.onNativeJoy(joystick.device_id, i, value);
}
for (int i = 0; i < joystick.hats.size() / 2; i++) {
int hatX = Math.round(event.getAxisValue(joystick.hats.get(2 * i).getAxis(), actionPointerIndex));
int hatY = Math.round(event.getAxisValue(joystick.hats.get(2 * i + 1).getAxis(), actionPointerIndex));
SDLControllerManager.onNativeHat(joystick.device_id, i, hatX, hatY);
}
}
}
}
return true;
}
public String getJoystickDescriptor(InputDevice joystickDevice) {
String desc = joystickDevice.getDescriptor();
if (desc != null && !desc.isEmpty()) {
return desc;
}
return joystickDevice.getName();
}
public int getProductId(InputDevice joystickDevice) {
return 0;
}
public int getVendorId(InputDevice joystickDevice) {
return 0;
}
public int getButtonMask(InputDevice joystickDevice) {
return -1;
}
}
class SDLJoystickHandler_API19 extends SDLJoystickHandler_API16 {
@Override
public int getProductId(InputDevice joystickDevice) {
return joystickDevice.getProductId();
}
@Override
public int getVendorId(InputDevice joystickDevice) {
return joystickDevice.getVendorId();
}
@Override
public int getButtonMask(InputDevice joystickDevice) {
int button_mask = 0;
int[] keys = new int[] {
KeyEvent.KEYCODE_BUTTON_A,
KeyEvent.KEYCODE_BUTTON_B,
KeyEvent.KEYCODE_BUTTON_X,
KeyEvent.KEYCODE_BUTTON_Y,
KeyEvent.KEYCODE_BACK,
KeyEvent.KEYCODE_BUTTON_MODE,
KeyEvent.KEYCODE_BUTTON_START,
KeyEvent.KEYCODE_BUTTON_THUMBL,
KeyEvent.KEYCODE_BUTTON_THUMBR,
KeyEvent.KEYCODE_BUTTON_L1,
KeyEvent.KEYCODE_BUTTON_R1,
KeyEvent.KEYCODE_DPAD_UP,
KeyEvent.KEYCODE_DPAD_DOWN,
KeyEvent.KEYCODE_DPAD_LEFT,
KeyEvent.KEYCODE_DPAD_RIGHT,
KeyEvent.KEYCODE_BUTTON_SELECT,
KeyEvent.KEYCODE_DPAD_CENTER,
// These don't map into any SDL controller buttons directly
KeyEvent.KEYCODE_BUTTON_L2,
KeyEvent.KEYCODE_BUTTON_R2,
KeyEvent.KEYCODE_BUTTON_C,
KeyEvent.KEYCODE_BUTTON_Z,
KeyEvent.KEYCODE_BUTTON_1,
KeyEvent.KEYCODE_BUTTON_2,
KeyEvent.KEYCODE_BUTTON_3,
KeyEvent.KEYCODE_BUTTON_4,
KeyEvent.KEYCODE_BUTTON_5,
KeyEvent.KEYCODE_BUTTON_6,
KeyEvent.KEYCODE_BUTTON_7,
KeyEvent.KEYCODE_BUTTON_8,
KeyEvent.KEYCODE_BUTTON_9,
KeyEvent.KEYCODE_BUTTON_10,
KeyEvent.KEYCODE_BUTTON_11,
KeyEvent.KEYCODE_BUTTON_12,
KeyEvent.KEYCODE_BUTTON_13,
KeyEvent.KEYCODE_BUTTON_14,
KeyEvent.KEYCODE_BUTTON_15,
KeyEvent.KEYCODE_BUTTON_16,
};
int[] masks = new int[] {
(1 << 0), // A -> A
(1 << 1), // B -> B
(1 << 2), // X -> X
(1 << 3), // Y -> Y
(1 << 4), // BACK -> BACK
(1 << 5), // MODE -> GUIDE
(1 << 6), // START -> START
(1 << 7), // THUMBL -> LEFTSTICK
(1 << 8), // THUMBR -> RIGHTSTICK
(1 << 9), // L1 -> LEFTSHOULDER
(1 << 10), // R1 -> RIGHTSHOULDER
(1 << 11), // DPAD_UP -> DPAD_UP
(1 << 12), // DPAD_DOWN -> DPAD_DOWN
(1 << 13), // DPAD_LEFT -> DPAD_LEFT
(1 << 14), // DPAD_RIGHT -> DPAD_RIGHT
(1 << 4), // SELECT -> BACK
(1 << 0), // DPAD_CENTER -> A
(1 << 15), // L2 -> ??
(1 << 16), // R2 -> ??
(1 << 17), // C -> ??
(1 << 18), // Z -> ??
(1 << 20), // 1 -> ??
(1 << 21), // 2 -> ??
(1 << 22), // 3 -> ??
(1 << 23), // 4 -> ??
(1 << 24), // 5 -> ??
(1 << 25), // 6 -> ??
(1 << 26), // 7 -> ??
(1 << 27), // 8 -> ??
(1 << 28), // 9 -> ??
(1 << 29), // 10 -> ??
(1 << 30), // 11 -> ??
(1 << 31), // 12 -> ??
// We're out of room...
0xFFFFFFFF, // 13 -> ??
0xFFFFFFFF, // 14 -> ??
0xFFFFFFFF, // 15 -> ??
0xFFFFFFFF, // 16 -> ??
};
boolean[] has_keys = joystickDevice.hasKeys(keys);
for (int i = 0; i < keys.length; ++i) {
if (has_keys[i]) {
button_mask |= masks[i];
}
}
return button_mask;
}
}
class SDLHapticHandler_API26 extends SDLHapticHandler {
@Override
public void run(int device_id, float intensity, int length) {
SDLHaptic haptic = getHaptic(device_id);
if (haptic != null) {
Log.d("SDL", "Rtest: Vibe with intensity " + intensity + " for " + length);
if (intensity == 0.0f) {
stop(device_id);
return;
}
int vibeValue = Math.round(intensity * 255);
if (vibeValue > 255) {
vibeValue = 255;
}
if (vibeValue < 1) {
stop(device_id);
return;
}
try {
haptic.vib.vibrate(VibrationEffect.createOneShot(length, vibeValue));
}
catch (Exception e) {
// Fall back to the generic method, which uses DEFAULT_AMPLITUDE, but works even if
// something went horribly wrong with the Android 8.0 APIs.
haptic.vib.vibrate(length);
}
}
}
}
class SDLHapticHandler {
static class SDLHaptic {
public int device_id;
public String name;
public Vibrator vib;
}
private final ArrayList<SDLHaptic> mHaptics;
public SDLHapticHandler() {
mHaptics = new ArrayList<SDLHaptic>();
}
public void run(int device_id, float intensity, int length) {
SDLHaptic haptic = getHaptic(device_id);
if (haptic != null) {
haptic.vib.vibrate(length);
}
}
public void stop(int device_id) {
SDLHaptic haptic = getHaptic(device_id);
if (haptic != null) {
haptic.vib.cancel();
}
}
public void pollHapticDevices() {
final int deviceId_VIBRATOR_SERVICE = 999999;
boolean hasVibratorService = false;
int[] deviceIds = InputDevice.getDeviceIds();
// It helps processing the device ids in reverse order
// For example, in the case of the XBox 360 wireless dongle,
// so the first controller seen by SDL matches what the receiver
// considers to be the first controller
for (int i = deviceIds.length - 1; i > -1; i--) {
SDLHaptic haptic = getHaptic(deviceIds[i]);
if (haptic == null) {
InputDevice device = InputDevice.getDevice(deviceIds[i]);
Vibrator vib = device.getVibrator();
if (vib.hasVibrator()) {
haptic = new SDLHaptic();
haptic.device_id = deviceIds[i];
haptic.name = device.getName();
haptic.vib = vib;
mHaptics.add(haptic);
SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name);
}
}
}
/* Check VIBRATOR_SERVICE */
Vibrator vib = (Vibrator) SDL.getContext().getSystemService(Context.VIBRATOR_SERVICE);
if (vib != null) {
hasVibratorService = vib.hasVibrator();
if (hasVibratorService) {
SDLHaptic haptic = getHaptic(deviceId_VIBRATOR_SERVICE);
if (haptic == null) {
haptic = new SDLHaptic();
haptic.device_id = deviceId_VIBRATOR_SERVICE;
haptic.name = "VIBRATOR_SERVICE";
haptic.vib = vib;
mHaptics.add(haptic);
SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name);
}
}
}
/* Check removed devices */
ArrayList<Integer> removedDevices = null;
for (SDLHaptic haptic : mHaptics) {
int device_id = haptic.device_id;
int i;
for (i = 0; i < deviceIds.length; i++) {
if (device_id == deviceIds[i]) break;
}
if (device_id != deviceId_VIBRATOR_SERVICE || !hasVibratorService) {
if (i == deviceIds.length) {
if (removedDevices == null) {
removedDevices = new ArrayList<Integer>();
}
removedDevices.add(device_id);
}
} // else: don't remove the vibrator if it is still present
}
if (removedDevices != null) {
for (int device_id : removedDevices) {
SDLControllerManager.nativeRemoveHaptic(device_id);
for (int i = 0; i < mHaptics.size(); i++) {
if (mHaptics.get(i).device_id == device_id) {
mHaptics.remove(i);
break;
}
}
}
}
}
protected SDLHaptic getHaptic(int device_id) {
for (SDLHaptic haptic : mHaptics) {
if (haptic.device_id == device_id) {
return haptic;
}
}
return null;
}
}
class SDLGenericMotionListener_API12 implements View.OnGenericMotionListener {
// Generic Motion (mouse hover, joystick...) events go here
@Override
public boolean onGenericMotion(View v, MotionEvent event) {
float x, y;
int action;
switch ( event.getSource() ) {
case InputDevice.SOURCE_JOYSTICK:
case InputDevice.SOURCE_GAMEPAD:
case InputDevice.SOURCE_DPAD:
return SDLControllerManager.handleJoystickMotionEvent(event);
case InputDevice.SOURCE_MOUSE:
action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_SCROLL:
x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0);
y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0);
SDLActivity.onNativeMouse(0, action, x, y, false);
return true;
case MotionEvent.ACTION_HOVER_MOVE:
x = event.getX(0);
y = event.getY(0);
SDLActivity.onNativeMouse(0, action, x, y, false);
return true;
default:
break;
}
break;
default:
break;
}
// Event was not managed
return false;
}
public boolean supportsRelativeMouse() {
return false;
}
public boolean inRelativeMode() {
return false;
}
public boolean setRelativeMouseEnabled(boolean enabled) {
return false;
}
public void reclaimRelativeMouseModeIfNeeded()
{
}
public float getEventX(MotionEvent event) {
return event.getX(0);
}
public float getEventY(MotionEvent event) {
return event.getY(0);
}
}
class SDLGenericMotionListener_API24 extends SDLGenericMotionListener_API12 {
// Generic Motion (mouse hover, joystick...) events go here
private boolean mRelativeModeEnabled;
@Override
public boolean onGenericMotion(View v, MotionEvent event) {
// Handle relative mouse mode
if (mRelativeModeEnabled) {
if (event.getSource() == InputDevice.SOURCE_MOUSE) {
int action = event.getActionMasked();
if (action == MotionEvent.ACTION_HOVER_MOVE) {
float x = event.getAxisValue(MotionEvent.AXIS_RELATIVE_X);
float y = event.getAxisValue(MotionEvent.AXIS_RELATIVE_Y);
SDLActivity.onNativeMouse(0, action, x, y, true);
return true;
}
}
}
// Event was not managed, call SDLGenericMotionListener_API12 method
return super.onGenericMotion(v, event);
}
@Override
public boolean supportsRelativeMouse() {
return true;
}
@Override
public boolean inRelativeMode() {
return mRelativeModeEnabled;
}
@Override
public boolean setRelativeMouseEnabled(boolean enabled) {
mRelativeModeEnabled = enabled;
return true;
}
@Override
public float getEventX(MotionEvent event) {
if (mRelativeModeEnabled) {
return event.getAxisValue(MotionEvent.AXIS_RELATIVE_X);
} else {
return event.getX(0);
}
}
@Override
public float getEventY(MotionEvent event) {
if (mRelativeModeEnabled) {
return event.getAxisValue(MotionEvent.AXIS_RELATIVE_Y);
} else {
return event.getY(0);
}
}
}
class SDLGenericMotionListener_API26 extends SDLGenericMotionListener_API24 {
// Generic Motion (mouse hover, joystick...) events go here
private boolean mRelativeModeEnabled;
@Override
public boolean onGenericMotion(View v, MotionEvent event) {
float x, y;
int action;
switch ( event.getSource() ) {
case InputDevice.SOURCE_JOYSTICK:
case InputDevice.SOURCE_GAMEPAD:
case InputDevice.SOURCE_DPAD:
return SDLControllerManager.handleJoystickMotionEvent(event);
case InputDevice.SOURCE_MOUSE:
// DeX desktop mouse cursor is a separate non-standard input type.
case InputDevice.SOURCE_MOUSE | InputDevice.SOURCE_TOUCHSCREEN:
action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_SCROLL:
x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0);
y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0);
SDLActivity.onNativeMouse(0, action, x, y, false);
return true;
case MotionEvent.ACTION_HOVER_MOVE:
x = event.getX(0);
y = event.getY(0);
SDLActivity.onNativeMouse(0, action, x, y, false);
return true;
default:
break;
}
break;
case InputDevice.SOURCE_MOUSE_RELATIVE:
action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_SCROLL:
x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0);
y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0);
SDLActivity.onNativeMouse(0, action, x, y, false);
return true;
case MotionEvent.ACTION_HOVER_MOVE:
x = event.getX(0);
y = event.getY(0);
SDLActivity.onNativeMouse(0, action, x, y, true);
return true;
default:
break;
}
break;
default:
break;
}
// Event was not managed
return false;
}
@Override
public boolean supportsRelativeMouse() {
return (!SDLActivity.isDeXMode() || (Build.VERSION.SDK_INT >= 27));
}
@Override
public boolean inRelativeMode() {
return mRelativeModeEnabled;
}
@Override
public boolean setRelativeMouseEnabled(boolean enabled) {
if (!SDLActivity.isDeXMode() || (Build.VERSION.SDK_INT >= 27)) {
if (enabled) {
SDLActivity.getContentView().requestPointerCapture();
} else {
SDLActivity.getContentView().releasePointerCapture();
}
mRelativeModeEnabled = enabled;
return true;
} else {
return false;
}
}
@Override
public void reclaimRelativeMouseModeIfNeeded()
{
if (mRelativeModeEnabled && !SDLActivity.isDeXMode()) {
SDLActivity.getContentView().requestPointerCapture();
}
}
@Override
public float getEventX(MotionEvent event) {
// Relative mouse in capture mode will only have relative for X/Y
return event.getX(0);
}
@Override
public float getEventY(MotionEvent event) {
// Relative mouse in capture mode will only have relative for X/Y
return event.getY(0);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
</resources>

View File

@ -0,0 +1,3 @@
<resources>
<string name="app_name">ggelua</string>
</resources>

View File

@ -0,0 +1,8 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
<!-- Customize your theme here. -->
</style>
</resources>

View File

@ -0,0 +1,25 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
google()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

View File

@ -0,0 +1,17 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx4096m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

Binary file not shown.

View File

@ -0,0 +1,6 @@
#Sat Mar 13 13:13:15 CST 2021
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip

160
project/android/gradlew vendored Normal file
View File

@ -0,0 +1,160 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

90
project/android/gradlew.bat vendored Normal file
View File

@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -0,0 +1,8 @@
## This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
#Sat Feb 27 14:08:58 CST 2021
sdk.dir=D\:\\Env\\Android\\Android-SDK

View File

@ -0,0 +1 @@
include ':app'

View File

@ -0,0 +1,29 @@
# Save the local path
LUA_LOCAL_PATH := $(call my-dir)
# Restore local path
LOCAL_PATH := $(LUA_LOCAL_PATH)
include $(CLEAR_VARS)
LOCAL_MODULE := cjson
#LOCAL_MODULE_FILENAME := cjson
GGE_LIB_PATH := $(LOCAL_PATH)/../../../../../GGELUA
LUA_PATH := $(GGE_LIB_PATH)/luadll
LOCAL_C_INCLUDES += $(LUA_PATH)
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_SRC_FILES := fpconv.c \
lua_cjson.c \
strbuf.c
LOCAL_SHARED_LIBRARIES := lua
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_C_INCLUDES)
LOCAL_CFLAGS += -fPIC -DLUA_USE_DLOPEN -DLUA_USE_POSIX
include $(BUILD_SHARED_LIBRARY)

View File

@ -0,0 +1,26 @@
# Save the local path
LUA_LOCAL_PATH := $(call my-dir)
# Restore local path
LOCAL_PATH := $(LUA_LOCAL_PATH)
include $(CLEAR_VARS)
LOCAL_MODULE := gastar
GGE_LIB_PATH := $(LOCAL_PATH)/../../../../../GGELUA
LUA_PATH := $(GGE_LIB_PATH)/luadll
LOCAL_C_INCLUDES += $(LUA_PATH)
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_SRC_FILES := Astart.cpp \
lua.cpp
LOCAL_SHARED_LIBRARIES := lua
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_C_INCLUDES)
LOCAL_CFLAGS += -fPIC -DLUA_USE_DLOPEN -DLUA_USE_POSIX
include $(BUILD_SHARED_LIBRARY)

View File

@ -0,0 +1,31 @@
# Save the local path
LUA_LOCAL_PATH := $(call my-dir)
# Restore local path
LOCAL_PATH := $(LUA_LOCAL_PATH)
include $(CLEAR_VARS)
LOCAL_MODULE := ggelua
GGE_LIB_PATH := $(LOCAL_PATH)/../../../source
LUA_PATH := $(GGE_LIB_PATH)/lua
LOCAL_C_INCLUDES += $(LUA_PATH)
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_SRC_FILES := cprint.c \
hash.c \
lbase64.c \
lfs.c \
lua_cmsgpack.c \
lua_zlib.c \
luuid.c \
main.c \
md5.c
LOCAL_SHARED_LIBRARIES := lua SDL2 zlib iconv
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_C_INCLUDES)
LOCAL_CFLAGS += -fPIC -DLUA_USE_DLOPEN -DLUA_USE_POSIX
include $(BUILD_SHARED_LIBRARY)

View File

@ -19,7 +19,7 @@ unsigned int g_tohash(const char *path)
//x86 - 32 bits - Registers
unsigned int eax, ebx, ecx, edx, edi, esi;
unsigned __int64 num = 0;
unsigned long long num = 0;
unsigned int v;
int i;

View File

@ -1,4 +1,4 @@
#include "lua.h"
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include <stdio.h>
@ -6,28 +6,26 @@
#ifdef _WIN32
#include <objbase.h>
#else
#include <uuid/uuid.h>
//#include <uuid/uuid.h>
#endif
static int
luuid(lua_State *L){
luuid(lua_State* L) {
char buf[40];
#ifdef _WIN32
GUID guid = {0};
GUID guid = { 0 };
CoCreateGuid(&guid);
sprintf(buf,"%.8X%.4X%.4X%.8X%.8X",guid.Data1,guid.Data2,guid.Data3,((unsigned int*)(guid.Data4))[0],((unsigned int*)(guid.Data4))[1]);
sprintf(buf, "%.8X%.4X%.4X%.8X%.8X", guid.Data1, guid.Data2, guid.Data3, ((unsigned int*)(guid.Data4))[0], ((unsigned int*)(guid.Data4))[1]);
#else
uuid_t guid;
uuid_generate(guid);
sprintf(buf,"%.8X%.8X%.8X%.8X",((unsigned int*)(guid))[0],((unsigned int*)(guid))[1],((unsigned int*)(guid))[2],((unsigned int*)(guid))[3]);
// uuid_t guid;
// uuid_generate(guid);
// sprintf(buf,"%.8X%.8X%.8X%.8X",((unsigned int*)(guid))[0],((unsigned int*)(guid))[1],((unsigned int*)(guid))[2],((unsigned int*)(guid))[3]);
#endif
lua_pushstring(L,buf);
lua_pushstring(L, buf);
return 1;
}
LUALIB_API int luaopen_uuid(lua_State *L){
LUALIB_API int luaopen_uuid(lua_State* L) {
lua_pushcfunction(L, luuid);
return 1;
}

View File

@ -1,4 +1,3 @@
#include <Windows.h>
#include "luaopen.h"
#include "SDL_clipboard.h"
#include "SDL_filesystem.h"
@ -10,6 +9,9 @@
#include "SDL_thread.h"
#include "SDL_timer.h"
#ifdef __WIN32__
#include <Windows.h>
#endif
static int LUA_ANSI2UTF8(lua_State *L){
const char* str = luaL_checkstring(L,1);
@ -251,4 +253,4 @@ LUALIB_API int luaopen_ggelua(lua_State *L) {
luaL_getsubtable(L, LUA_REGISTRYINDEX, "_ggelua");
luaL_setfuncs(L, fun_list, 0);
return 1;//fun_list
}
}

View File

@ -0,0 +1,43 @@
# Save the local path
LUA_LOCAL_PATH := $(call my-dir)
# Restore local path
LOCAL_PATH := $(LUA_LOCAL_PATH)
include $(CLEAR_VARS)
LOCAL_MODULE := ghpsocket
DEPENDENT_LIB_PATH := $(LOCAL_PATH)/../../../dependent
GGE_LIB_PATH := $(LOCAL_PATH)/../../../source
LUA_PATH := $(GGE_LIB_PATH)/lua
SDL_PATH := $(DEPENDENT_LIB_PATH)/SDL
HPSOCKET_PATH := $(DEPENDENT_LIB_PATH)/HP-Socket/Linux/include/hpsocket
LOCAL_C_INCLUDES := $(SDL_PATH)/include
LOCAL_C_INCLUDES += $(LUA_PATH)
LOCAL_C_INCLUDES += $(HPSOCKET_PATH)
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_SRC_FILES := common.cpp \
HP_HttpClient.cpp \
HP_PackAgent.cpp \
HP_PackClient.cpp \
HP_PackServer.cpp \
HP_PushClient.cpp \
HP_UdpNode.cpp \
HP_Buffer.cpp \
HP_PullClient.cpp \
HP_PullAgent.cpp
LOCAL_SHARED_LIBRARIES := lua SDL2 zlib
LOCAL_STATIC_LIBRARIES := hpsocket_a
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_C_INCLUDES)
LOCAL_CFLAGS += -fPIC -DLUA_USE_DLOPEN -DLUA_USE_POSIX
LOCAL_CXXFLAGS := -DHAVE_PTHREADS
include $(BUILD_SHARED_LIBRARY)

View File

@ -0,0 +1,286 @@
#include "HP_Buffer.h"
#include "lua.hpp"
HP_Buffer::HP_Buffer(int flag, int len, int max_seq)
{
m_flag = flag;
m_buflen = len;
m_bodylen = len - sizeof(HP_Header);
m_data = new unsigned char[len];
memset(m_data, 0, len);
m_head = (HP_Header*)m_data;
m_wint = (int*)(m_data + sizeof(HP_Header));
m_rint = (int*)m_data;
m_code = NULL;
m_maxseq = max_seq;
m_seq = 0;
}
HP_Buffer::~HP_Buffer(void)
{
delete m_data;
}
void HP_Buffer::Reset() {
m_i = 0;
m_len = sizeof(HP_Header);
m_lock = false;
memset(m_data, 0, m_buflen);
}
bool HP_Buffer::AddNumber(int v) {
if (m_len + sizeof(int) < m_bodylen && !m_lock)
{
m_wint[m_i++] = v;
m_len += sizeof(int);
return true;
}
return false;
}
bool HP_Buffer::AddString(const char* v, int len) {
if (m_len + len < m_bodylen && !m_lock)
{
memcpy(m_data + m_len, v, len);
m_len += len;
m_lock = true;
return true;
}
return false;
}
void HP_Buffer::Finish() {
m_head->flag = m_flag;
m_head->seq = m_seq;
m_head->len = m_len - this->GetHeaderLen();
m_head->qty = m_i;
m_seq++;
m_lock = true;
if (m_code)
{
unsigned char* data = m_data + this->GetHeaderLen();
int k = 0;
for (int i = 0; i < m_head->len; i++)
{
data[i] ^= m_code[k++];
if (k >= m_codelen)
{
k = 0;
}
}
}
if (m_seq > m_maxseq)
{
m_seq = 1;
}
}
unsigned int HP_Buffer::GetHeaderLen() {
return sizeof(HP_Header) - 4; //第四位是整数个数
}
unsigned int HP_Buffer::CheckHeader() {
if (m_head->flag == m_flag)
{
m_len = m_head->len;
return m_len;
}
return 0;
}
unsigned char* HP_Buffer::GetPtr() {
return m_data;
}
unsigned int HP_Buffer::GetLen() {
return m_len;
}
void HP_Buffer::SetCode(int* psd, int len)
{
if (m_code)
{
delete[]m_code;
m_code = NULL;
}
m_code = new int[len];
memset(m_code, 0, sizeof(int) * len);
memcpy(m_code, psd, sizeof(int) * len);
m_codelen = len;
}
void HP_Buffer::SetComp(bool v) {
m_comp = v;
}
static int Reset(lua_State* L)
{
HP_Buffer* ud = *(HP_Buffer**)luaL_checkudata(L, 1, "HP_Buffer");
ud->Reset();
return 0;
}
static int AddNumber(lua_State* L)
{
HP_Buffer* ud = *(HP_Buffer**)luaL_checkudata(L, 1, "HP_Buffer");
ud->AddNumber(luaL_checkinteger(L, 2));
return 0;
}
static int AddString(lua_State* L)
{
HP_Buffer* ud = *(HP_Buffer**)luaL_checkudata(L, 1, "HP_Buffer");
size_t len = 0;
const char* v = luaL_checklstring(L, 2, &len);
char* buff = (char*)malloc(len + 1);
memset(buff, 0, len + 1);
memcpy(buff, v, len);
//const char* v = luaL_checkstring(L, 2);
ud->AddString(v, len);
return 0;
}
static int Finish(lua_State* L)
{
HP_Buffer* ud = *(HP_Buffer**)luaL_checkudata(L, 1, "HP_Buffer");
ud->Finish();
return 0;
}
static int GetHeaderLen(lua_State* L)
{
HP_Buffer* ud = *(HP_Buffer**)luaL_checkudata(L, 1, "HP_Buffer");
int ret = ud->GetHeaderLen();
lua_pushinteger(L, ret);
return 1;
}
static int CheckHeader(lua_State* L)
{
HP_Buffer* ud = *(HP_Buffer**)luaL_checkudata(L, 1, "HP_Buffer");
int ret = ud->CheckHeader();
lua_pushinteger(L, ret);
return 1;
}
static int SetCode(lua_State* L)
{
HP_Buffer* ud = *(HP_Buffer**)luaL_checkudata(L, 1, "HP_Buffer");
size_t len = 0;
if (!lua_istable(L, 2))
{
luaL_error(L, "passwd isn't a table");
return 0;
}
int pwd[1024] = { 0 };
int codelen = 0;
/* 表放在索引 't' 处 */
lua_pushnil(L); /* 第一个键 */
while (lua_next(L, 2) != 0) {
int index = luaL_checkinteger(L, -2);
int value = luaL_checkinteger(L, -1);
pwd[index - 1] = value;
codelen++;
lua_pop(L, 1);
}
ud->SetCode(pwd, codelen);
return 0;
}
static int GetData(lua_State* L)
{
HP_Buffer* ud = *(HP_Buffer**)luaL_checkudata(L, 1, "HP_Buffer");
//数据解密
if (ud->m_code)
{
unsigned char* data = ud->m_data;
int k = 0;
for (int i = 0; i < ud->m_len; i++)
{
data[i] ^= ud->m_code[k++];
if (k >= ud->m_codelen)
{
k = 0;
}
}
}
lua_newtable(L);//创建一个表格,放在栈顶
ud->m_qty = ud->m_rint[0];
int stroff = (ud->m_qty + 1) * sizeof(int);
if (stroff < ud->m_bodylen)
{
for (int i = 0; i < ud->m_qty; i++)
{
lua_pushinteger(L, ud->m_rint[i + 1]);
lua_seti(L, -2, i + 1);
}
if (ud->m_len - stroff > 0)
{
//lua_pushlstring(L, (const char*)ud->m_data + stroff, ud->m_len - stroff);
lua_pushstring(L, (const char*)ud->m_data + stroff);
lua_seti(L, -2, ud->m_qty + 1);
}
}
return 1;
}
static int Creat_HP_Buffer(lua_State* L) {
int flag = luaL_checkinteger(L, 1);
int len = luaL_checkinteger(L, 2);
int maxseq = luaL_checkinteger(L, 3);
HP_Buffer* p = new HP_Buffer(flag, len, maxseq);
HP_Buffer** ud = (HP_Buffer**)lua_newuserdata(L, sizeof(HP_Buffer*));
*ud = p;
luaL_setmetatable(L, "HP_Buffer");
return 1;
}
static int Destroy_HP_Buffer(lua_State* L) {
HP_Buffer* ud = *(HP_Buffer**)luaL_checkudata(L, 1, "HP_Buffer");
delete ud;
return 0;
}
#ifdef _WIN32
extern "C"
#endif // _WIN32
LUALIB_API
int luaopen_ghpsocket_buffer(lua_State * L)
{
luaL_Reg methods[] = {
{"Reset",Reset},
{"AddNumber",AddNumber},
{"AddString",AddString},
{"Finish",Finish},
{"GetHeaderLen",GetHeaderLen},
{"CheckHeader",CheckHeader},
{"SetCode",SetCode},
{"GetData",GetData},
{NULL, NULL},
};
setvbuf(stdout, NULL, _IONBF, 0);
luaL_newmetatable(L, "HP_Buffer");
luaL_newlib(L, methods);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, Destroy_HP_Buffer);
lua_setfield(L, -2, "__gc");
lua_pop(L, 1);
lua_pushcfunction(L, Creat_HP_Buffer);
return 1;
}

View File

@ -0,0 +1,44 @@
#pragma once
#include "common.h"
struct HP_Header
{
//0包头1序号2长度3数量
int flag; //标识
int seq; //序号
int len; //长度
int qty; //数量
};
class HP_Buffer
{
public:
HP_Buffer(int flag, int len, int max_seq);
~HP_Buffer(void);
void Reset();
bool AddNumber(int v);
bool AddString(const char* v, int len);
void Finish();
unsigned int GetHeaderLen();
unsigned int CheckHeader();
unsigned char* GetPtr();
unsigned int GetLen();
void SetCode(int* psd, int len);
void SetComp(bool v);
int m_flag;
int m_seq;
int m_len;
int m_qty;
int m_maxseq;
unsigned int m_bodylen;
unsigned int m_buflen;
unsigned char* m_data;
HP_Header* m_head;
int* m_wint;
int* m_rint;
bool m_lock;
int m_i;
int* m_code;
int m_codelen;
bool m_comp;
};

View File

@ -0,0 +1,561 @@
#include "HP_PullAgent.h"
#include "HP_Buffer.h"
EnHandleResult HP_PullAgent::OnPrepareConnect(ITcpAgent* pSender, CONNID dwConnID, SOCKET socket)
{
GetCallBack("OnPrepareConnect");
lua_pushinteger(L, dwConnID);
lua_pushinteger(L, socket);
lua_call(L, 3, 1);
return GetResult();
}
EnHandleResult HP_PullAgent::OnConnect(ITcpAgent* pSender, CONNID dwConnID)
{
GetCallBack("OnConnect");
lua_pushinteger(L, dwConnID);
lua_call(L, 2, 1);
return GetResult();
}
EnHandleResult HP_PullAgent::OnReceive(ITcpAgent* pSender, CONNID dwConnID, int iLength)
{
GetCallBack("OnReceivePack");
lua_pushinteger(L, dwConnID);
lua_pushinteger(L, iLength);
lua_call(L, 3, 1);
return GetResult();
}
EnHandleResult HP_PullAgent::OnReceive(ITcpAgent* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
{
GetCallBack("OnReceive");
lua_pushinteger(L, dwConnID);
lua_pushlstring(L, (const char*)pData, iLength);
lua_call(L, 3, 1);
return GetResult();
}
EnHandleResult HP_PullAgent::OnSend(ITcpAgent* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
{
GetCallBack("OnSend");
lua_pushinteger(L, dwConnID);
//lua_pushlightuserdata(L,(void*)pData);
lua_pushinteger(L, iLength);
lua_call(L, 3, 1);
return GetResult();
}
EnHandleResult HP_PullAgent::OnShutdown(ITcpAgent* pSender)
{
GetCallBack("OnShutdown");
lua_call(L, 1, 1);
return GetResult();
}
EnHandleResult HP_PullAgent::OnClose(ITcpAgent* pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode)
{
GetCallBack("OnClose");
lua_pushinteger(L, dwConnID);
switch (enOperation) {
CASE(SO_UNKNOWN)
CASE(SO_ACCEPT)
CASE(SO_CONNECT)
CASE(SO_SEND)
CASE(SO_RECEIVE)
CASE(SO_CLOSE)
}
lua_pushinteger(L, iErrorCode);
lua_call(L, 4, 1);
return GetResult();
}
static BOOL luaL_optboolean(lua_State* L, int arg, BOOL def) {
if (lua_isnoneornil(L, arg)) {
return def;
}
return lua_toboolean(L, arg);
}
static ITcpPullAgent* GetAgent(lua_State* L) {
HP_PullAgent* p = *(HP_PullAgent**)luaL_checkudata(L, 1, "HP_PullAgent");
return p->m_Agent;
}
//IPullSocket
static int Fetch(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
HP_Buffer* p = *(HP_Buffer**)luaL_checkudata(L, 3, "HP_Buffert");
Agent->Fetch((DWORD)luaL_checkinteger(L, 2), p->GetPtr(), (int)luaL_checkinteger(L, 4));
return 0;
}
static int Peek(lua_State* L) {
//virtual EnFetchResult Peek (CONNID dwConnID, BYTE* pData, int iLength) = 0;
ITcpPullAgent* Agent = GetAgent(L);
HP_Buffer* p = *(HP_Buffer**)luaL_checkudata(L, 3, "HP_Buffert");
Agent->Peek((USHORT)luaL_checkinteger(L, 2), p->GetPtr(), (int)luaL_checkinteger(L, 4));
return 0;
}
//ITcpAgent
static int SendSmallFile(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
lua_pushboolean(L, Agent->SendSmallFile(luaL_checkinteger(L, 2), luaL_checkstring(L, 3),
(LPWSABUF)luaL_optlstring(L, 4, nullptr, NULL),
(LPWSABUF)luaL_optlstring(L, 5, nullptr, NULL)));
return 1;
}
static int SetSocketBufferSize(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
Agent->SetSocketBufferSize((DWORD)luaL_checkinteger(L, 2));
return 0;
}
static int SetKeepAliveTime(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
Agent->SetKeepAliveTime((DWORD)luaL_checkinteger(L, 2));
return 0;
}
static int SetKeepAliveInterval(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
Agent->SetKeepAliveInterval((DWORD)luaL_checkinteger(L, 2));
return 0;
}
static int GetSocketBufferSize(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
lua_pushinteger(L, Agent->GetSocketBufferSize());
return 1;
}
static int GetKeepAliveTime(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
lua_pushinteger(L, Agent->GetKeepAliveTime());
return 1;
}
static int GetKeepAliveInterval(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
lua_pushinteger(L, Agent->GetKeepAliveInterval());
return 1;
}
//IAgent
static int Start(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
BOOL r = Agent->Start(luaL_optstring(L, 2, nullptr), luaL_optboolean(L, 3, FALSE));
lua_pushboolean(L, r);
return 1;
}
static int Connect(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
CONNID ConnID;
BOOL r = Agent->Connect(luaL_checkstring(L, 2), (USHORT)luaL_checkinteger(L, 3), &ConnID, nullptr, (USHORT)luaL_optinteger(L, 4, 0), luaL_optstring(L, 5, nullptr));
lua_pushboolean(L, r);
lua_pushinteger(L, ConnID);
return 2;
}
static int GetRemoteHost(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
luaL_Buffer b;
char* p = luaL_buffinitsize(L, &b, LUAL_BUFFERSIZE);
int len = LUAL_BUFFERSIZE;
USHORT port;
if (Agent->GetRemoteHost(luaL_checkinteger(L, 2), p, len, port)) {
luaL_pushresultsize(&b, len - 1);
lua_pushinteger(L, port);
return 2;
}
return 0;
}
//IComplexSocket
static int Stop(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
lua_pushboolean(L, Agent->Stop());
return 1;
}
static int Send(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
size_t len;
BYTE* buf = (BYTE*)luaL_checklstring(L, 3, &len);
lua_pushboolean(L, Agent->Send(luaL_checkinteger(L, 2), buf, (int)len, (int)luaL_optinteger(L, 4, 0)));
return 1;
}
//static int SendPackets(lua_State* L){
// ITcpPullAgent* Agent = GetAgent(L);
//
// return 0;
//}
static int PauseReceive(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
lua_pushboolean(L, Agent->PauseReceive(luaL_checkinteger(L, 2), luaL_optboolean(L, 3, TRUE)));
return 1;
}
static int Disconnect(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
lua_pushboolean(L, Agent->Disconnect(luaL_checkinteger(L, 2), luaL_optboolean(L, 3, TRUE)));
return 1;
}
static int DisconnectLongConnections(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
lua_pushboolean(L, Agent->DisconnectLongConnections((DWORD)luaL_checkinteger(L, 2), luaL_optboolean(L, 3, TRUE)));
return 1;
}
static int DisconnectSilenceConnections(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
lua_pushboolean(L, Agent->DisconnectSilenceConnections((DWORD)luaL_checkinteger(L, 2), luaL_optboolean(L, 3, TRUE)));
return 1;
}
static int Wait(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
lua_pushboolean(L, Agent->Wait((DWORD)luaL_optinteger(L, 2, INFINITE)));
return 1;
}
//static int SetConnectionExtra(lua_State* L){
// ITcpPullAgent* Agent = GetAgent(L);
//
// return 0;
//}
//static int GetConnectionExtra(lua_State* L){
// ITcpPullAgent* Agent = GetAgent(L);
//
// return 0;
//}
static int IsSecure(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
lua_pushboolean(L, Agent->IsSecure());
return 1;
}
static int HasStarted(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
lua_pushboolean(L, Agent->HasStarted());
return 1;
}
static int GetState(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
switch (Agent->GetState()) {
CASE(SS_STARTING)
CASE(SS_STARTED)
CASE(SS_STOPPING)
CASE(SS_STOPPED)
}
return 1;
}
static int GetConnectionCount(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
lua_pushinteger(L, Agent->GetConnectionCount());
return 1;
}
static int GetAllConnectionIDs(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
DWORD num = Agent->GetConnectionCount();
CONNID* id = new CONNID[num];
lua_createtable(L, num, 0);
if (Agent->GetAllConnectionIDs(id, num)) {
for (DWORD i = 0; i < num; i++) {
lua_pushinteger(L, id[i]);
lua_seti(L, -2, i + 1);
}
}
delete[]id;
return 1;
}
static int GetConnectPeriod(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
DWORD v;
Agent->GetConnectPeriod(luaL_checkinteger(L, 2), v);
lua_pushinteger(L, v);
return 1;
}
static int GetSilencePeriod(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
DWORD v;
Agent->GetSilencePeriod(luaL_checkinteger(L, 2), v);
lua_pushinteger(L, v);
return 1;
}
static int GetLocalAddress(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
luaL_Buffer b;
char* p = luaL_buffinitsize(L, &b, LUAL_BUFFERSIZE);
int len = LUAL_BUFFERSIZE;
USHORT port;
if (Agent->GetLocalAddress(luaL_checkinteger(L, 2), p, len, port)) {
luaL_pushresultsize(&b, len - 1);
lua_pushinteger(L, port);
return 2;
}
return 0;
}
static int GetRemoteAddress(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
luaL_Buffer b;
char* p = luaL_buffinitsize(L, &b, LUAL_BUFFERSIZE);
int len = LUAL_BUFFERSIZE;
USHORT port;
if (Agent->GetRemoteAddress(luaL_checkinteger(L, 2), p, len, port)) {
luaL_pushresultsize(&b, len - 1);
lua_pushinteger(L, port);
return 2;
}
return 0;
}
static int GetLastError(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
switch (Agent->GetLastError()) {
CASE(SE_OK)
CASE(SE_ILLEGAL_STATE)
CASE(SE_INVALID_PARAM)
CASE(SE_SOCKET_CREATE)
CASE(SE_SOCKET_BIND)
CASE(SE_SOCKET_PREPARE)
CASE(SE_SOCKET_LISTEN)
CASE(SE_CP_CREATE)
CASE(SE_WORKER_THREAD_CREATE)
CASE(SE_DETECT_THREAD_CREATE)
CASE(SE_SOCKE_ATTACH_TO_CP)
CASE(SE_CONNECT_SERVER)
CASE(SE_NETWORK)
CASE(SE_DATA_PROC)
CASE(SE_DATA_SEND)
CASE(SE_SSL_ENV_NOT_READY)
}
return 1;
}
static int GetLastErrorDesc(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
lua_pushstring(L, Agent->GetLastErrorDesc());
return 1;
}
static int GetPendingDataLength(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
int v;
Agent->GetPendingDataLength(luaL_checkinteger(L, 2), v);
lua_pushinteger(L, v);
return 1;
}
static int IsPauseReceive(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
BOOL v;
Agent->GetPendingDataLength(luaL_checkinteger(L, 2), v);
lua_pushboolean(L, v);
return 1;
}
static int IsConnected(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
lua_pushboolean(L, Agent->IsConnected(luaL_checkinteger(L, 2)));
return 1;
}
static int SetReuseAddressPolicy(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
static const char* const opts[] = { "RAP_NONE", "RAP_ADDR_ONLY", "RAP_ADDR_AND_PORT", NULL };
Agent->SetReuseAddressPolicy(EnReuseAddressPolicy(luaL_checkoption(L, 2, "RAP_NONE", opts)));
return 0;
}
static int SetSendPolicy(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
static const char* const opts[] = { "SP_PACK", "SP_SAFE", "SP_DIRECT", NULL };
Agent->SetSendPolicy(EnSendPolicy(luaL_checkoption(L, 2, "SP_PACK", opts)));
return 0;
}
static int SetOnSendSyncPolicy(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
static const char* const opts[] = { "OSSP_NONE", "OSSP_CLOSE", "OSSP_RECEIVE", NULL };
Agent->SetOnSendSyncPolicy(EnOnSendSyncPolicy(luaL_checkoption(L, 2, "OSSP_NONE", opts)));
return 0;
}
static int SetMaxConnectionCount(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
Agent->SetMaxConnectionCount((DWORD)luaL_checkinteger(L, 2));
return 0;
}
static int SetFreeSocketObjLockTime(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
Agent->SetFreeSocketObjLockTime((DWORD)luaL_checkinteger(L, 2));
return 0;
}
static int SetFreeSocketObjPool(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
Agent->SetFreeSocketObjPool((DWORD)luaL_checkinteger(L, 2));
return 0;
}
static int SetFreeBufferObjPool(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
Agent->SetFreeBufferObjPool((DWORD)luaL_checkinteger(L, 2));
return 0;
}
static int SetFreeSocketObjHold(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
Agent->SetFreeSocketObjHold((DWORD)luaL_checkinteger(L, 2));
return 0;
}
static int SetFreeBufferObjHold(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
Agent->SetFreeBufferObjHold((DWORD)luaL_checkinteger(L, 2));
return 0;
}
static int SetWorkerThreadCount(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
Agent->SetWorkerThreadCount((DWORD)luaL_checkinteger(L, 2));
return 0;
}
static int SetMarkSilence(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
Agent->SetMarkSilence(lua_toboolean(L, 2));
return 0;
}
static int GetReuseAddressPolicy(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
switch (Agent->GetReuseAddressPolicy()) {
CASE(RAP_NONE)
CASE(RAP_ADDR_ONLY)
CASE(RAP_ADDR_AND_PORT)
}
return 1;
}
static int GetSendPolicy(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
switch (Agent->GetSendPolicy()) {
CASE(SP_PACK)
CASE(SP_SAFE)
CASE(SP_DIRECT)
}
return 1;
}
static int GetOnSendSyncPolicy(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
switch (Agent->GetOnSendSyncPolicy()) {
CASE(OSSP_NONE)
CASE(OSSP_CLOSE)
CASE(OSSP_RECEIVE)
}
return 1;
}
static int GetMaxConnectionCount(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
lua_pushinteger(L, Agent->GetMaxConnectionCount());
return 1;
}
static int GetFreeSocketObjLockTime(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
lua_pushinteger(L, Agent->GetFreeSocketObjLockTime());
return 1;
}
static int GetFreeSocketObjPool(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
lua_pushinteger(L, Agent->GetFreeSocketObjPool());
return 1;
}
static int GetFreeBufferObjPool(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
lua_pushinteger(L, Agent->GetFreeBufferObjPool());
return 1;
}
static int GetFreeSocketObjHold(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
lua_pushinteger(L, Agent->GetFreeSocketObjHold());
return 1;
}
static int GetFreeBufferObjHold(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
lua_pushinteger(L, Agent->GetFreeBufferObjHold());
return 1;
}
static int GetWorkerThreadCount(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
lua_pushinteger(L, Agent->GetWorkerThreadCount());
return 1;
}
static int IsMarkSilence(lua_State* L) {
ITcpPullAgent* Agent = GetAgent(L);
lua_pushboolean(L, Agent->IsMarkSilence());
return 1;
}
static int Creat_HP_PullAgent(lua_State* L) {
HP_PullAgent* p = new HP_PullAgent(L);
HP_PullAgent** ud = (HP_PullAgent**)lua_newuserdata(L, sizeof(HP_PullAgent*));
*ud = p;
luaL_setmetatable(L, "HP_PullAgent");
return 1;
}
static int Destroy_HP_PullAgent(lua_State* L) {
HP_PullAgent* ud = *(HP_PullAgent**)luaL_checkudata(L, 1, "HP_PullAgent");
ud->m_Agent->Stop();
delete ud;
return 0;
}
#ifdef _WIN32
extern "C"
#endif // _WIN32
LUALIB_API
int luaopen_ghpsocket_pullagent(lua_State * L)
{
luaL_Reg methods[] = {
{"Fetch",Fetch},
{"Peek",Peek},
{"SendSmallFile",SendSmallFile},
{"SetSocketBufferSize",SetSocketBufferSize},
{"SetKeepAliveTime",SetKeepAliveTime},
{"SetKeepAliveInterval",SetKeepAliveInterval},
{"GetSocketBufferSize",GetSocketBufferSize},
{"GetKeepAliveTime",GetKeepAliveTime},
{"GetKeepAliveInterval",GetKeepAliveInterval},
{"Start",Start},
{"Connect",Connect},
{"GetRemoteHost",GetRemoteHost},
{"Stop",Stop},
{"Send",Send},
//{"SendPackets",SendPackets},
{"PauseReceive",PauseReceive},
{"Disconnect",Disconnect},
{"DisconnectLongConnections",DisconnectLongConnections},
{"DisconnectSilenceConnections",DisconnectSilenceConnections},
{"Wait",Wait},
//{"SetConnectionExtra",SetConnectionExtra},
//{"GetConnectionExtra",GetConnectionExtra},
{"IsSecure",IsSecure},
{"HasStarted",HasStarted},
{"GetState",GetState},
{"GetConnectionCount",GetConnectionCount},
{"GetAllConnectionIDs",GetAllConnectionIDs},
{"GetConnectPeriod",GetConnectPeriod},
{"GetSilencePeriod",GetSilencePeriod},
{"GetLocalAddress",GetLocalAddress},
{"GetRemoteAddress",GetRemoteAddress},
{"GetLastError",GetLastError},
{"GetLastErrorDesc",GetLastErrorDesc},
{"GetPendingDataLength",GetPendingDataLength},
{"IsPauseReceive",IsPauseReceive},
{"IsConnected",IsConnected},
{"SetReuseAddressPolicy",SetReuseAddressPolicy},
{"SetSendPolicy",SetSendPolicy},
{"SetOnSendSyncPolicy",SetOnSendSyncPolicy},
{"SetMaxConnectionCount",SetMaxConnectionCount},
{"SetFreeSocketObjLockTime",SetFreeSocketObjLockTime},
{"SetFreeSocketObjPool",SetFreeSocketObjPool},
{"SetFreeBufferObjPool",SetFreeBufferObjPool},
{"SetFreeSocketObjHold",SetFreeSocketObjHold},
{"SetFreeBufferObjHold",SetFreeBufferObjHold},
{"SetWorkerThreadCount",SetWorkerThreadCount},
{"SetMarkSilence",SetMarkSilence},
{"GetReuseAddressPolicy",GetReuseAddressPolicy},
{"GetSendPolicy",GetSendPolicy},
{"GetOnSendSyncPolicy",GetOnSendSyncPolicy},
{"GetMaxConnectionCount",GetMaxConnectionCount},
{"GetFreeSocketObjLockTime",GetFreeSocketObjLockTime},
{"GetFreeSocketObjPool",GetFreeSocketObjPool},
{"GetFreeBufferObjPool",GetFreeBufferObjPool},
{"GetFreeSocketObjHold",GetFreeSocketObjHold},
{"GetFreeBufferObjHold",GetFreeBufferObjHold},
{"GetWorkerThreadCount",GetWorkerThreadCount},
{"IsMarkSilence",IsMarkSilence},
{NULL, NULL},
};
luaL_newmetatable(L, "HP_PullAgent");
luaL_newlib(L, methods);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, Destroy_HP_PullAgent);
lua_setfield(L, -2, "__gc");
lua_pop(L, 1);
lua_pushcfunction(L, Creat_HP_PullAgent);
return 1;
}

View File

@ -1,2 +1,24 @@
#pragma once
#include "common.h"
#pragma once
#include "common.h"
class HP_PullAgent : public HP_Base, public CTcpPullAgentListener
{
public:
HP_PullAgent(lua_State* L) :HP_Base(L) {
m_Agent = HP_Create_TcpPullAgent(this);
};
~HP_PullAgent() {
HP_Destroy_TcpPullAgent(m_Agent);
};
virtual EnHandleResult OnPrepareConnect(ITcpAgent* pSender, CONNID dwConnID, SOCKET socket);
virtual EnHandleResult OnConnect(ITcpAgent* pSender, CONNID dwConnID);
//virtual EnHandleResult OnHandShake(ITcpAgent* pSender, CONNID dwConnID);
virtual EnHandleResult OnReceive(ITcpAgent* pSender, CONNID dwConnID, int iLength);
virtual EnHandleResult OnReceive(ITcpAgent* pSender, CONNID dwConnID, const BYTE* pData, int iLength);
virtual EnHandleResult OnSend(ITcpAgent* pSender, CONNID dwConnID, const BYTE* pData, int iLength);
virtual EnHandleResult OnShutdown(ITcpAgent* pSender);
virtual EnHandleResult OnClose(ITcpAgent* pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode);
ITcpPullAgent* m_Agent;
};

View File

@ -0,0 +1,421 @@
#include "HP_PullClient.h"
#include "HP_Buffer.h"
EnHandleResult HP_PullClient::OnPrepareConnect(ITcpClient* pSender, CONNID dwConnID, SOCKET socket)
{
GetCallBack("OnPrepareConnect");
lua_pushinteger(L, dwConnID);
lua_pushinteger(L, socket);
lua_call(L, 3, 1);
return GetResult();
}
EnHandleResult HP_PullClient::OnConnect(ITcpClient* pSender, CONNID dwConnID)
{
GetCallBack("OnConnect");
lua_pushinteger(L, dwConnID);
lua_call(L, 2, 1);
return GetResult();
}
EnHandleResult HP_PullClient::OnReceive(ITcpClient* pSender, CONNID dwConnID, int iLength)
{
GetCallBack("OnReceivePull");
lua_pushinteger(L, dwConnID);
lua_pushinteger(L, iLength);
lua_call(L, 3, 1);
return GetResult();
}
EnHandleResult HP_PullClient::OnReceive(ITcpClient* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
{
GetCallBack("OnReceive");
lua_pushinteger(L, dwConnID);
lua_pushlstring(L, (const char*)pData, iLength);
lua_call(L, 3, 1);
return GetResult();
}
EnHandleResult HP_PullClient::OnSend(ITcpClient* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
{
GetCallBack("OnSend");
lua_pushinteger(L, dwConnID);
//lua_pushlightuserdata(L,(void*)pData);
lua_pushinteger(L, iLength);
lua_call(L, 3, 1);
return GetResult();
}
EnHandleResult HP_PullClient::OnClose(ITcpClient* pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode)
{
GetCallBack("OnClose");
lua_pushinteger(L, dwConnID);
switch (enOperation) {
CASE(SO_UNKNOWN)
CASE(SO_ACCEPT)
CASE(SO_CONNECT)
CASE(SO_SEND)
CASE(SO_RECEIVE)
CASE(SO_CLOSE)
}
lua_pushinteger(L, iErrorCode);
lua_call(L, 4, 1);
return GetResult();
}
static BOOL luaL_optboolean(lua_State* L, int arg, BOOL def) {
if (lua_isnoneornil(L, arg)) {
return def;
}
return lua_toboolean(L, arg);
}
static ITcpPullClient* GetPullClient(lua_State* L) {
lua_getuservalue(L, 1);
ITcpPullClient* p = (ITcpPullClient*)lua_topointer(L, -1);
lua_pop(L, 1);
return p;
}
//ITcpClient
int SendSmallFile(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
lua_pushboolean(L, cli->SendSmallFile(luaL_checkstring(L, 2),
(LPWSABUF)luaL_optlstring(L, 3, nullptr, NULL),
(LPWSABUF)luaL_optlstring(L, 4, nullptr, NULL)));
return 1;
}
int SetSocketBufferSize(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
cli->SetSocketBufferSize((DWORD)luaL_checkinteger(L, 2));
return 0;
}
int SetKeepAliveTime(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
cli->SetKeepAliveTime((DWORD)luaL_checkinteger(L, 2));
return 0;
}
int SetKeepAliveInterval(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
cli->SetKeepAliveInterval((DWORD)luaL_checkinteger(L, 2));
return 0;
}
int GetSocketBufferSize(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
lua_pushinteger(L, cli->GetSocketBufferSize());
return 1;
}
int GetKeepAliveTime(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
lua_pushinteger(L, cli->GetKeepAliveTime());
return 1;
}
int GetKeepAliveInterval(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
lua_pushinteger(L, cli->GetKeepAliveInterval());
return 1;
}
//IClient
int Start(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
BOOL r = cli->Start(luaL_checkstring(L, 2), (USHORT)luaL_checkinteger(L, 3), luaL_optboolean(L, 4, FALSE),
luaL_optstring(L, 5, nullptr), (USHORT)luaL_optinteger(L, 6, 0U));
lua_pushboolean(L, r);
return 1;
}
int Stop(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
HP_mutex* mutex = *(HP_mutex**)lua_getextraspace(L);
HP_UnlockMutex(mutex);
BOOL r = cli->Stop();
HP_LockMutex(mutex);
lua_pushboolean(L, r);
return 1;
}
//int Send(lua_State* L) {
// ITcpPullClient* cli = GetPullClient(L);
// size_t len;
// BYTE* buf = (BYTE*)luaL_checklstring(L, 2, &len);
// lua_pushboolean(L, cli->Send(buf, (int)len, (int)luaL_optinteger(L, 3, 0)));
// return 1;
//}
//int SendPackets(lua_State* L){
// ITcpPullClient* cli = GetPullClient(L);
//
// return 0;
//}
int PauseReceive(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
lua_pushboolean(L, cli->PauseReceive());
return 1;
}
int Wait(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
lua_pushboolean(L, cli->Wait((DWORD)luaL_optinteger(L, 2, INFINITE)));
return 1;
}
//int SetExtra(lua_State* L){
// ITcpPullClient* cli = GetPullClient(L);
//
// return 0;
//}
//int GetExtra(lua_State* L){
// ITcpPullClient* cli = GetPullClient(L);
//
// return 0;
//}
int IsSecure(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
lua_pushboolean(L, cli->IsSecure());
return 1;
}
int HasStarted(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
lua_pushboolean(L, cli->HasStarted());
return 1;
}
int GetState(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
switch (cli->GetState()) {
CASE(SS_STARTING)
CASE(SS_STARTED)
CASE(SS_STOPPING)
CASE(SS_STOPPED)
}
return 1;
}
int GetLastError(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
switch (cli->GetLastError()) {
CASE(SE_OK)
CASE(SE_ILLEGAL_STATE)
CASE(SE_INVALID_PARAM)
CASE(SE_SOCKET_CREATE)
CASE(SE_SOCKET_BIND)
CASE(SE_SOCKET_PREPARE)
CASE(SE_SOCKET_LISTEN)
CASE(SE_CP_CREATE)
CASE(SE_WORKER_THREAD_CREATE)
CASE(SE_DETECT_THREAD_CREATE)
CASE(SE_SOCKE_ATTACH_TO_CP)
CASE(SE_CONNECT_SERVER)
CASE(SE_NETWORK)
CASE(SE_DATA_PROC)
CASE(SE_DATA_SEND)
CASE(SE_SSL_ENV_NOT_READY)
}
return 1;
}
int GetLastErrorDesc(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
lua_pushstring(L, cli->GetLastErrorDesc());
return 1;
}
int GetConnectionID(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
lua_pushinteger(L, cli->GetConnectionID());
return 1;
}
int GetLocalAddress(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
luaL_Buffer b;
char* p = luaL_buffinitsize(L, &b, LUAL_BUFFERSIZE);
int len = LUAL_BUFFERSIZE;
USHORT port;
if (cli->GetLocalAddress(p, len, port)) {
luaL_pushresultsize(&b, len - 1);
lua_pushinteger(L, port);
return 2;
}
return 0;
}
int GetRemoteHost(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
luaL_Buffer b;
char* p = luaL_buffinitsize(L, &b, LUAL_BUFFERSIZE);
int len = LUAL_BUFFERSIZE;
USHORT port;
if (cli->GetRemoteHost(p, len, port)) {
luaL_pushresultsize(&b, len - 1);
lua_pushinteger(L, port);
return 2;
}
return 0;
}
int GetPendingDataLength(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
int v;
cli->GetPendingDataLength(v);
lua_pushinteger(L, v);
return 1;
}
int IsPauseReceive(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
BOOL v;
cli->IsPauseReceive(v);
lua_pushboolean(L, v);
return 1;
}
int IsConnected(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
lua_pushboolean(L, cli->IsConnected());
return 1;
}
int SetReuseAddressPolicy(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
static const char* const opts[] = { "RAP_NONE", "RAP_ADDR_ONLY", "RAP_ADDR_AND_PORT", NULL };
//static const int optsnum[] = {RAP_NONE, RAP_ADDR_ONLY, RAP_ADDR_AND_PORT,};
cli->SetReuseAddressPolicy(EnReuseAddressPolicy(luaL_checkoption(L, 2, "RAP_NONE", opts)));
return 0;
}
int SetFreeBufferPoolSize(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
cli->SetFreeBufferPoolSize((DWORD)luaL_checkinteger(L, 2));
return 0;
}
int SetFreeBufferPoolHold(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
cli->SetFreeBufferPoolHold((DWORD)luaL_checkinteger(L, 2));
return 0;
}
int GetReuseAddressPolicy(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
switch (cli->GetReuseAddressPolicy()) {
CASE(RAP_NONE)
CASE(RAP_ADDR_ONLY)
CASE(RAP_ADDR_AND_PORT)
}
return 1;
}
int GetFreeBufferPoolSize(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
lua_pushinteger(L, cli->GetFreeBufferPoolSize());
return 1;
}
int GetFreeBufferPoolHold(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
lua_pushinteger(L, cli->GetFreeBufferPoolHold());
return 1;
}
static int Send(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
HP_Buffer* p = *(HP_Buffer**)luaL_checkudata(L, 2, "HP_Buffer");
lua_pushboolean(L, cli->Send(p->GetPtr(), p->GetLen(), 0));
return 1;
}
static int Fetch(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
HP_Buffer* p = *(HP_Buffer**)luaL_checkudata(L, 2, "HP_Buffer");
int len = luaL_checkinteger(L, 3);
lua_pushinteger(L, cli->Fetch(p->GetPtr(), len));
p->m_len = len;
p->m_bodylen = len;
return 1;
}
static int Peek(lua_State* L) {
ITcpPullClient* cli = GetPullClient(L);
HP_Buffer* p = *(HP_Buffer**)luaL_checkudata(L, 2, "HP_Buffer");
int len = luaL_checkinteger(L, 3);
lua_pushinteger(L, cli->Peek(p->GetPtr(), len));
return 1;
}
static int Creat_HP_PullClient(lua_State* L) {
HP_PullClient* p = new HP_PullClient(L);
HP_PullClient** ud = (HP_PullClient**)lua_newuserdata(L, sizeof(HP_PullClient*));
*ud = p;
lua_pushlightuserdata(L, (ITcpPullClient*)p->m_Client);
lua_setuservalue(L, -2);
luaL_setmetatable(L, "HP_PullClient");
return 1;
}
static int Destroy_HP_PullClient(lua_State* L) {
HP_PullClient* ud = *(HP_PullClient**)luaL_checkudata(L, 1, "HP_PullClient");
ud->m_Client->Stop();
delete ud;
return 0;
}
#ifdef _WIN32
extern "C"
#endif // _WIN32
LUALIB_API
int luaopen_ghpsocket_pullclient(lua_State * L)
{
luaL_Reg methods[] = {
{"Fetch",Fetch},
{"Peek",Peek},
{"SendSmallFile",SendSmallFile},
{"SetSocketBufferSize",SetSocketBufferSize},
{"SetKeepAliveTime",SetKeepAliveTime},
{"SetKeepAliveInterval",SetKeepAliveInterval},
{"GetSocketBufferSize",GetSocketBufferSize},
{"GetKeepAliveTime",GetKeepAliveTime},
{"GetKeepAliveInterval",GetKeepAliveInterval},
{"Start",Start},
{"Stop",Stop},
{"Send",Send},
//{"SendPackets",SendPackets},
{"PauseReceive",PauseReceive},
{"Wait",Wait},
//{"SetExtra",SetExtra},
//{"GetExtra",GetExtra},
{"IsSecure",IsSecure},
{"HasStarted",HasStarted},
{"GetState",GetState},
{"GetLastError",GetLastError},
{"GetLastErrorDesc",GetLastErrorDesc},
{"GetConnectionID",GetConnectionID},
{"GetLocalAddress",GetLocalAddress},
{"GetRemoteHost",GetRemoteHost},
{"GetPendingDataLength",GetPendingDataLength},
{"IsPauseReceive",IsPauseReceive},
{"IsConnected",IsConnected},
{"SetReuseAddressPolicy",SetReuseAddressPolicy},
{"SetFreeBufferPoolSize",SetFreeBufferPoolSize},
{"SetFreeBufferPoolHold",SetFreeBufferPoolHold},
{"GetReuseAddressPolicy",GetReuseAddressPolicy},
{"GetFreeBufferPoolSize",GetFreeBufferPoolSize},
{"GetFreeBufferPoolHold",GetFreeBufferPoolHold},
{NULL, NULL},
};
//setvbuf(stdout, NULL, _IONBF, 0);
luaL_newmetatable(L, "HP_PullClient");
luaL_newlib(L, methods);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, Destroy_HP_PullClient);
lua_setfield(L, -2, "__gc");
lua_pop(L, 1);
lua_pushcfunction(L, Creat_HP_PullClient);
return 1;
}

View File

@ -1,2 +1,24 @@
#pragma once
#include "common.h"
#pragma once
#include "common.h"
class HP_PullClient : public HP_Base, public CTcpPullClientListener
{
public:
HP_PullClient(lua_State* L) :HP_Base(L) {
m_Client = HP_Create_TcpPullClient(this);
};
~HP_PullClient() {
HP_Destroy_TcpPullClient(m_Client);
};
virtual EnHandleResult OnPrepareConnect(ITcpClient* pSender, CONNID dwConnID, SOCKET socket);
virtual EnHandleResult OnConnect(ITcpClient* pSender, CONNID dwConnID);
//virtual EnHandleResult OnHandShake(ITcpClient* pSender, CONNID dwConnID);
virtual EnHandleResult OnReceive(ITcpClient* pSender, CONNID dwConnID, int iLength);
virtual EnHandleResult OnReceive(ITcpClient* pSender, CONNID dwConnID, const BYTE* pData, int iLength);
virtual EnHandleResult OnSend(ITcpClient* pSender, CONNID dwConnID, const BYTE* pData, int iLength);
virtual EnHandleResult OnClose(ITcpClient* pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode);
ITcpPullClient* m_Client;
};

View File

@ -1,2 +1,40 @@
#pragma once
#include "common.h"
#pragma once
#include "common.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
int SendSmallFile(lua_State* L);
int SetSocketBufferSize(lua_State* L);
int SetKeepAliveTime(lua_State* L);
int SetKeepAliveInterval(lua_State* L);
int GetSocketBufferSize(lua_State* L);
int GetKeepAliveTime(lua_State* L);
int GetKeepAliveInterval(lua_State* L);
int Start(lua_State* L);
int Stop(lua_State* L);
int Send(lua_State* L);
int SendPackets(lua_State* L);
int PauseReceive(lua_State* L);
int Wait(lua_State* L);
int SetExtra(lua_State* L);
int GetExtra(lua_State* L);
int IsSecure(lua_State* L);
int HasStarted(lua_State* L);
int GetState(lua_State* L);
int HP_GetLastError(lua_State* L);
int GetLastErrorDesc(lua_State* L);
int GetConnectionID(lua_State* L);
int GetLocalAddress(lua_State* L);
int GetRemoteHost(lua_State* L);
int GetPendingDataLength(lua_State* L);
int IsPauseReceive(lua_State* L);
int IsConnected(lua_State* L);
int SetReuseAddressPolicy(lua_State* L);
int SetFreeBufferPoolSize(lua_State* L);
int SetFreeBufferPoolHold(lua_State* L);
int GetReuseAddressPolicy(lua_State* L);
int GetFreeBufferPoolSize(lua_State* L);
int GetFreeBufferPoolHold(lua_State* L);
#ifdef __cplusplus
}
#endif // __cplusplus

28
source/lib/gip/Android.mk Normal file
View File

@ -0,0 +1,28 @@
# Save the local path
LUA_LOCAL_PATH := $(call my-dir)
# Restore local path
LOCAL_PATH := $(LUA_LOCAL_PATH)
include $(CLEAR_VARS)
LOCAL_MODULE := gip
#LOCAL_MODULE_FILENAME := gip
GGE_LIB_PATH := $(LOCAL_PATH)/../../../../../GGELUA
LUA_PATH := $(GGE_LIB_PATH)/luadll
LOCAL_C_INCLUDES += $(LUA_PATH)
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_SRC_FILES := lua.c \
ip2region.c
LOCAL_SHARED_LIBRARIES := lua
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_C_INCLUDES)
LOCAL_CFLAGS += -fPIC -DLUA_USE_DLOPEN -DLUA_USE_POSIX
include $(BUILD_SHARED_LIBRARY)

View File

@ -0,0 +1,78 @@
# Save the local path
LUA_LOCAL_PATH := $(call my-dir)
# Restore local path
LOCAL_PATH := $(LUA_LOCAL_PATH)
include $(CLEAR_VARS)
LOCAL_MODULE := gsdl2
DEPENDENT_LIB_PATH := $(LOCAL_PATH)/../../../dependent
GGE_LIB_PATH := $(LOCAL_PATH)/../../../source
LUA_PATH := $(GGE_LIB_PATH)/lua
SDL_PATH := $(DEPENDENT_LIB_PATH)/SDL
IMAGE_PATH := $(BASE_LIB_PATH)/SDL_image
MIXER_PATH := $(BASE_LIB_PATH)/SDL_mixer
TTF_PATH := $(BASE_LIB_PATH)/SDL_ttf
LOCAL_C_INCLUDES := $(SDL_PATH)/include
LOCAL_C_INCLUDES += $(SDL_PATH)/src
LOCAL_C_INCLUDES += $(IMAGE_PATH)
LOCAL_C_INCLUDES += $(MIXER_PATH)
LOCAL_C_INCLUDES += $(TTF_PATH)
LOCAL_C_INCLUDES += $(LUA_PATH)
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_SRC_FILES := audio.c \
blendmode.c \
clipboard.c \
cpuinfo.c \
error.c \
events.c \
filesystem.c \
gamecontroller.c \
gesture.c \
gge.c \
haptic.c \
hints.c \
joystick.c \
keyboard.c \
locale.c \
log.c \
messagebox.c \
metal.c \
misc.c \
mouse.c \
mutex.c \
opengl.c \
pixels.c \
platform.c \
power.c \
rect.c \
renderer.c \
rwops.c \
sdl_image.c \
sdl_mixer.c \
sdl_net.c \
sdl_ttf.c \
sdl.c \
sensor.c \
shape.c \
stdinc.c \
surface.c \
system.c \
syswm.c \
thread.c \
timer.c \
touch.c \
version.c \
video.c
LOCAL_SHARED_LIBRARIES := lua SDL2 SDL2_image SDL2_ttf SDL2_mixer zlib
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_C_INCLUDES)
LOCAL_CFLAGS += -fPIC -DLUA_USE_DLOPEN -DLUA_USE_POSIX
include $(BUILD_SHARED_LIBRARY)

View File

@ -11,11 +11,13 @@ static int LUA_GetWindowWMInfo(lua_State* L)
lua_pushinteger(L, info.subsystem);
lua_setfield(L, -2, "subsystem");
lua_createtable(L, 0, 3);
#if defined(SDL_VIDEO_DRIVER_WINDOWS)
lua_pushinteger(L, (lua_Integer)info.info.win.window);
lua_setfield(L, -2, "window");
lua_pushinteger(L, (lua_Integer)info.info.win.hdc);
lua_setfield(L, -2, "hdc");
lua_pushinteger(L, (lua_Integer)info.info.win.hinstance);
#endif
lua_setfield(L, -2, "hinstance");
lua_setfield(L, -2, "info");
return 1;

View File

@ -0,0 +1,28 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= lsqlite3
#LOCAL_MODULE_FILENAME := lsqlite3
LOCAL_SRC_FILES:= lsqlite3.c
DEPENDENT_LIB_PATH := $(LOCAL_PATH)/../../../dependent
GGE_LIB_PATH := $(LOCAL_PATH)/../../../source
LUA_PATH := $(GGE_LIB_PATH)/lua
SDL_PATH := $(DEPENDENT_LIB_PATH)/SDL
SQLITE3MC_PATH := $(DEPENDENT_LIB_PATH)/SQLite3MultipleCiphers/src
LOCAL_C_INCLUDES := $(SQLITE3MC_PATH)
LOCAL_C_INCLUDES += $(LUA_PATH)
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_SHARED_LIBRARIES := lua
LOCAL_STATIC_LIBRARIES := sqlite3mc
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
include $(BUILD_SHARED_LIBRARY)

55
source/lua/Android.mk Normal file
View File

@ -0,0 +1,55 @@
# Save the local path
LUA_LOCAL_PATH := $(call my-dir)
# Restore local path
LOCAL_PATH := $(LUA_LOCAL_PATH)
include $(CLEAR_VARS)
LOCAL_MODULE := lua
#LOCAL_MODULE_FILENAME := lua
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_SRC_FILES := lapi.c \
lauxlib.c \
lbaselib.c \
lcode.c \
lcorolib.c \
lctype.c \
ldblib.c \
ldebug.c \
ldo.c \
ldump.c \
lfunc.c \
lgc.c \
linit.c \
liolib.c \
llex.c \
lmathlib.c \
lmem.c \
loadlib.c \
lobject.c \
lopcodes.c \
loslib.c \
lparser.c \
lstate.c \
lstring.c \
lstrlib.c \
ltable.c \
ltablib.c \
ltm.c \
lundump.c \
lutf8lib.c \
lvm.c \
lzio.c
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_C_INCLUDES)
LOCAL_CFLAGS += -fPIC -DLUA_USE_POSIX -DLUA_UCID -DLUA_COMPAT_MATHLIB -DLUA_USE_DLOPEN
LOCAL_CFLAGS += -D"lua_getlocaledecpoint()='.'"
LOCAL_LDFLAGS += -lm
include $(BUILD_SHARED_LIBRARY)