Upgrade p4a #19
3445 changed files with 456206 additions and 3803 deletions
17
.github/workflows/deploy.yml
vendored
17
.github/workflows/deploy.yml
vendored
|
@ -2,7 +2,7 @@ name: Publish Assets
|
|||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
branches: [master, upgrade_p4a]
|
||||
|
||||
jobs:
|
||||
build_arm64_aar:
|
||||
|
@ -16,20 +16,14 @@ jobs:
|
|||
cp -r /root/.buildozer ~/.buildozer/
|
||||
- name: setup
|
||||
run: |
|
||||
apt update
|
||||
apt install libssl-dev zip unzip openjdk-11-jdk -y
|
||||
export B_VERSION=$(cat $GITHUB_WORKSPACE/src/main/python/main.py | grep --color=never -oP '([0-9]+\.?)+')
|
||||
echo "NEXUS_SIGNING_KEYRING_FILE=$GITHUB_WORKSPACE/signing2.pgp" >> $GITHUB_ENV
|
||||
echo "BUILD_VERSION=${B_VERSION}" >> $GITHUB_ENV
|
||||
export PATH=/usr/bin:$PATH
|
||||
wget -q 'https://eu.crystax.net/download/crystax-ndk-10.3.2-linux-x86_64.tar.xz' -P ~/.buildozer/android/
|
||||
tar -xf ~/.buildozer/android/crystax-ndk-10.3.2-linux-x86_64.tar.xz -C ~/.buildozer/android/
|
||||
rm -rf ~/.buildozer/android/crystax-ndk-10.3.2/platforms/android-9
|
||||
ln -s ~/.buildozer/android/crystax-ndk-10.3.2/platforms/android-21 ~/.buildozer/android/crystax-ndk-10.3.2/platforms/android-9
|
||||
cp -f $GITHUB_WORKSPACE/scripts/build-target-python.sh ~/.buildozer/android/crystax-ndk-10.3.2/build/tools/build-target-python.sh
|
||||
cp -f $GITHUB_WORKSPACE/scripts/mangled-glibc-syscalls__arm64.h ~/.buildozer/android/crystax-ndk-10.3.2/platforms/android-21/arch-arm64/usr/include/crystax/bionic/libc/include/sys/mangled-glibc-syscalls.h
|
||||
cp -f $GITHUB_WORKSPACE/scripts/build-binary.mk ~/.buildozer/android/crystax-ndk-10.3.2/build/core/build-binary.mk
|
||||
rm -rf ~/.buildozer/android/crystax-ndk-10.3.2/sources/sqlite
|
||||
cp -Rf $GITHUB_WORKSPACE/scripts/crystax-sources/sqlite ~/.buildozer/android/crystax-ndk-10.3.2/sources/sqlite
|
||||
rm ~/.buildozer/android/crystax-ndk-10.3.2-linux-x86_64.tar.xz
|
||||
wget -q 'https://dl.google.com/android/repository/android-ndk-r25b-linux.zip' -P ~/.buildozer/android/
|
||||
unzip ~/.buildozer/android/android-ndk-r25b-linux.zip -d ~/.buildozer/android/
|
||||
mv buildozer.spec.arm64.ci buildozer.spec
|
||||
chmod u+x ./build-release.sh
|
||||
- name: build release
|
||||
|
@ -77,6 +71,7 @@ jobs:
|
|||
echo "NEXUS_SIGNING_KEYRING_FILE=$GITHUB_WORKSPACE/signing2.pgp" >> $GITHUB_ENV
|
||||
export PATH=/usr/bin:$PATH
|
||||
wget -q 'https://eu.crystax.net/download/crystax-ndk-10.3.2-linux-x86_64.tar.xz' -P ~/.buildozer/android/
|
||||
unzip ~/
|
||||
tar -xf ~/.buildozer/android/crystax-ndk-10.3.2-linux-x86_64.tar.xz -C ~/.buildozer/android/
|
||||
rm -rf ~/.buildozer/android/crystax-ndk-10.3.2/platforms/android-9
|
||||
ln -s ~/.buildozer/android/crystax-ndk-10.3.2/platforms/android-21 ~/.buildozer/android/crystax-ndk-10.3.2/platforms/android-9
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -19,3 +19,4 @@ p4a/pythonforandroid/bootstraps/lbry/build/templates/google-services.json
|
|||
|
||||
p4a/*.apk
|
||||
p4a/*.aar
|
||||
venv
|
0
MovedRecipes/__init__.py
Normal file
0
MovedRecipes/__init__.py
Normal file
257
MovedRecipes/android/__init__.py
Normal file
257
MovedRecipes/android/__init__.py
Normal file
|
@ -0,0 +1,257 @@
|
|||
from pythonforandroid.recipe import CythonRecipe, IncludedFilesBehaviour
|
||||
from pythonforandroid.util import current_directory
|
||||
from pythonforandroid import logger
|
||||
|
||||
from os.path import join
|
||||
|
||||
|
||||
class AndroidRecipe(IncludedFilesBehaviour, CythonRecipe):
|
||||
# name = 'android'
|
||||
version = None
|
||||
url = None
|
||||
|
||||
src_filename = 'src'
|
||||
|
||||
depends = [('sdl2', 'genericndkbuild'), 'pyjnius']
|
||||
|
||||
config_env = {}
|
||||
|
||||
def get_recipe_env(self, arch):
|
||||
env = super().get_recipe_env(arch)
|
||||
env.update(self.config_env)
|
||||
return env
|
||||
|
||||
def prebuild_arch(self, arch):
|
||||
super().prebuild_arch(arch)
|
||||
ctx_bootstrap = self.ctx.bootstrap.name
|
||||
|
||||
# define macros for Cython, C, Python
|
||||
tpxi = 'DEF {} = {}\n'
|
||||
th = '#define {} {}\n'
|
||||
tpy = '{} = {}\n'
|
||||
|
||||
# make sure bootstrap name is in unicode
|
||||
if isinstance(ctx_bootstrap, bytes):
|
||||
ctx_bootstrap = ctx_bootstrap.decode('utf-8')
|
||||
bootstrap = bootstrap_name = ctx_bootstrap
|
||||
is_lbry = bootstrap_name in ('lbry',)
|
||||
is_sdl2 = (bootstrap_name == "sdl2")
|
||||
if bootstrap_name in ["sdl2", "webview", "service_only", "service_library", "lbry"]:
|
||||
java_ns = u'org.kivy.android'
|
||||
jni_ns = u'org/kivy/android'
|
||||
else:
|
||||
logger.error((
|
||||
'unsupported bootstrap for android recipe: {}'
|
||||
''.format(bootstrap_name)
|
||||
))
|
||||
exit(1)
|
||||
|
||||
config = {
|
||||
'BOOTSTRAP': bootstrap,
|
||||
'IS_SDL2': int(is_sdl2),
|
||||
'PY2': 0,
|
||||
'JAVA_NAMESPACE': java_ns,
|
||||
'JNI_NAMESPACE': jni_ns,
|
||||
'ACTIVITY_CLASS_NAME': self.ctx.activity_class_name,
|
||||
'ACTIVITY_CLASS_NAMESPACE': self.ctx.activity_class_name.replace('.', '/'),
|
||||
'SERVICE_CLASS_NAME': self.ctx.service_class_name,
|
||||
}
|
||||
|
||||
# create config files for Cython, C and Python
|
||||
with (
|
||||
current_directory(self.get_build_dir(arch.arch))), (
|
||||
open(join('android', 'config.pxi'), 'w')) as fpxi, (
|
||||
open(join('android', 'config.h'), 'w')) as fh, (
|
||||
open(join('android', 'config.py'), 'w')) as fpy:
|
||||
|
||||
for key, value in config.items():
|
||||
fpxi.write(tpxi.format(key, repr(value)))
|
||||
fpy.write(tpy.format(key, repr(value)))
|
||||
|
||||
fh.write(th.format(
|
||||
key,
|
||||
value if isinstance(value, int) else '"{}"'.format(value)
|
||||
))
|
||||
self.config_env[key] = str(value)
|
||||
|
||||
if is_sdl2:
|
||||
fh.write('JNIEnv *SDL_AndroidGetJNIEnv(void);\n')
|
||||
fh.write(
|
||||
'#define SDL_ANDROID_GetJNIEnv SDL_AndroidGetJNIEnv\n'
|
||||
)
|
||||
else:
|
||||
fh.write('JNIEnv *WebView_AndroidGetJNIEnv(void);\n')
|
||||
fh.write(
|
||||
'#define SDL_ANDROID_GetJNIEnv WebView_AndroidGetJNIEnv\n'
|
||||
)
|
||||
|
||||
|
||||
recipe = AndroidRecipe()
|
||||
|
||||
'''
|
||||
from pythonforandroid.recipe import CythonRecipe, IncludedFilesBehaviour
|
||||
from pythonforandroid.util import current_directory
|
||||
from pythonforandroid.patching import will_build
|
||||
from pythonforandroid import logger
|
||||
|
||||
from os.path import join
|
||||
|
||||
|
||||
class AndroidRecipe(IncludedFilesBehaviour, CythonRecipe):
|
||||
# name = 'android'
|
||||
version = None
|
||||
url = None
|
||||
|
||||
src_filename = 'src'
|
||||
|
||||
depends = [('pygame', 'sdl2', 'genericndkbuild'), ('python2', 'python3crystax')]
|
||||
|
||||
config_env = {}
|
||||
|
||||
def get_recipe_env(self, arch):
|
||||
env = super(AndroidRecipe, self).get_recipe_env(arch)
|
||||
env.update(self.config_env)
|
||||
return env
|
||||
|
||||
def prebuild_arch(self, arch):
|
||||
super(AndroidRecipe, self).prebuild_arch(arch)
|
||||
|
||||
tpxi = 'DEF {} = {}\n'
|
||||
th = '#define {} {}\n'
|
||||
tpy = '{} = {}\n'
|
||||
|
||||
bootstrap = bootstrap_name = self.ctx.bootstrap.name
|
||||
is_sdl2 = bootstrap_name in ('sdl2', 'sdl2python3', 'sdl2_gradle')
|
||||
is_pygame = bootstrap_name in ('pygame',)
|
||||
is_webview = bootstrap_name in ('webview',)
|
||||
is_lbry = bootstrap_name in ('lbry',)
|
||||
|
||||
if is_sdl2 or is_webview or is_lbry:
|
||||
if is_sdl2:
|
||||
bootstrap = 'sdl2'
|
||||
java_ns = 'org.kivy.android'
|
||||
jni_ns = 'org/kivy/android'
|
||||
elif is_pygame:
|
||||
java_ns = 'org.renpy.android'
|
||||
jni_ns = 'org/renpy/android'
|
||||
else:
|
||||
logger.error('unsupported bootstrap for android recipe: {}'.format(bootstrap_name))
|
||||
exit(1)
|
||||
|
||||
config = {
|
||||
'BOOTSTRAP': bootstrap,
|
||||
'IS_SDL2': int(is_sdl2),
|
||||
'IS_PYGAME': int(is_pygame),
|
||||
'PY2': int(will_build('python2')(self)),
|
||||
'JAVA_NAMESPACE': java_ns,
|
||||
'JNI_NAMESPACE': jni_ns,
|
||||
}
|
||||
|
||||
with current_directory(self.get_build_dir(arch.arch)):
|
||||
with open(join('android', 'config.pxi'), 'w') as fpxi:
|
||||
with open(join('android', 'config.h'), 'w') as fh:
|
||||
with open(join('android', 'config.py'), 'w') as fpy:
|
||||
for key, value in config.items():
|
||||
fpxi.write(tpxi.format(key, repr(value)))
|
||||
fpy.write(tpy.format(key, repr(value)))
|
||||
fh.write(th.format(key, value if isinstance(value, int)
|
||||
else '"{}"'.format(value)))
|
||||
self.config_env[key] = str(value)
|
||||
|
||||
if is_sdl2:
|
||||
fh.write('JNIEnv *SDL_AndroidGetJNIEnv(void);\n')
|
||||
fh.write('#define SDL_ANDROID_GetJNIEnv SDL_AndroidGetJNIEnv\n')
|
||||
elif is_pygame:
|
||||
fh.write('JNIEnv *SDL_ANDROID_GetJNIEnv(void);\n')
|
||||
|
||||
|
||||
recipe = AndroidRecipe()
|
||||
'''
|
||||
|
||||
'''
|
||||
from pythonforandroid.recipe import CythonRecipe, Recipe, IncludedFilesBehaviour
|
||||
from pythonforandroid.util import current_directory
|
||||
from pythonforandroid.patching import will_build
|
||||
from pythonforandroid import logger
|
||||
|
||||
from os.path import join
|
||||
|
||||
|
||||
class AndroidRecipe(IncludedFilesBehaviour, CythonRecipe):
|
||||
# name = 'android'
|
||||
version = None
|
||||
url = None
|
||||
|
||||
src_filename = 'src'
|
||||
|
||||
depends = [('pygame', 'sdl2', 'genericndkbuild'), ('python2', 'python3crystax')]
|
||||
|
||||
call_hostpython_via_targetpython = False
|
||||
|
||||
config_env = {}
|
||||
|
||||
def get_recipe_env(self, arch):
|
||||
env = super(AndroidRecipe, self).get_recipe_env(arch)
|
||||
env.update(self.config_env)
|
||||
|
||||
target_python = Recipe.get_recipe('python2', self.ctx).get_build_dir(arch.arch)
|
||||
env['PYTHON_ROOT'] = join(target_python, 'python-install')
|
||||
env['CFLAGS'] += ' -I' + env['PYTHON_ROOT'] + '/include/python2.7'
|
||||
env['LDFLAGS'] += ' -L' + env['PYTHON_ROOT'] + '/lib' + ' -lpython2.7'
|
||||
|
||||
return env
|
||||
|
||||
def prebuild_arch(self, arch):
|
||||
super(AndroidRecipe, self).prebuild_arch(arch)
|
||||
|
||||
tpxi = 'DEF {} = {}\n'
|
||||
th = '#define {} {}\n'
|
||||
tpy = '{} = {}\n'
|
||||
|
||||
bootstrap = bootstrap_name = self.ctx.bootstrap.name
|
||||
is_sdl2 = bootstrap_name in ('sdl2', 'sdl2python3')
|
||||
is_pygame = bootstrap_name in ('pygame',)
|
||||
is_webview = bootstrap_name in ('webview')
|
||||
is_lbry = bootstrap_name in ('lbry')
|
||||
|
||||
if is_sdl2 or is_webview or is_lbry:
|
||||
if is_sdl2:
|
||||
bootstrap = 'sdl2'
|
||||
java_ns = 'org.kivy.android'
|
||||
jni_ns = 'org/kivy/android'
|
||||
elif is_pygame:
|
||||
java_ns = 'org.renpy.android'
|
||||
jni_ns = 'org/renpy/android'
|
||||
else:
|
||||
logger.error('unsupported bootstrap for android recipe: {}'.format(bootstrap_name))
|
||||
exit(1)
|
||||
|
||||
config = {
|
||||
'BOOTSTRAP': bootstrap,
|
||||
'IS_SDL2': int(is_sdl2),
|
||||
'IS_PYGAME': int(is_pygame),
|
||||
'PY2': int(will_build('python2')(self)),
|
||||
'JAVA_NAMESPACE': java_ns,
|
||||
'JNI_NAMESPACE': jni_ns,
|
||||
}
|
||||
|
||||
with current_directory(self.get_build_dir(arch.arch)):
|
||||
with open(join('android', 'config.pxi'), 'w') as fpxi:
|
||||
with open(join('android', 'config.h'), 'w') as fh:
|
||||
with open(join('android', 'config.py'), 'w') as fpy:
|
||||
for key, value in config.items():
|
||||
fpxi.write(tpxi.format(key, repr(value)))
|
||||
fpy.write(tpy.format(key, repr(value)))
|
||||
fh.write(th.format(key, value if isinstance(value, int)
|
||||
else '"{}"'.format(value)))
|
||||
self.config_env[key] = str(value)
|
||||
|
||||
if is_sdl2:
|
||||
fh.write('JNIEnv *SDL_AndroidGetJNIEnv(void);\n')
|
||||
fh.write('#define SDL_ANDROID_GetJNIEnv SDL_AndroidGetJNIEnv\n')
|
||||
elif is_pygame:
|
||||
fh.write('JNIEnv *SDL_ANDROID_GetJNIEnv(void);\n')
|
||||
|
||||
|
||||
recipe = AndroidRecipe()
|
||||
'''
|
0
MovedRecipes/android/src/__init__.py
Normal file
0
MovedRecipes/android/src/__init__.py
Normal file
8
MovedRecipes/android/src/android/__init__.py
Normal file
8
MovedRecipes/android/src/android/__init__.py
Normal file
|
@ -0,0 +1,8 @@
|
|||
'''
|
||||
Android module
|
||||
==============
|
||||
|
||||
'''
|
||||
|
||||
# legacy import
|
||||
from android._android import *
|
385
MovedRecipes/android/src/android/_android.pyx
Normal file
385
MovedRecipes/android/src/android/_android.pyx
Normal file
|
@ -0,0 +1,385 @@
|
|||
# Android-specific python services.
|
||||
|
||||
include "config.pxi"
|
||||
|
||||
IF BOOTSTRAP == 'pygame':
|
||||
cdef extern int SDL_ANDROID_CheckPause()
|
||||
cdef extern void SDL_ANDROID_WaitForResume() nogil
|
||||
cdef extern void SDL_ANDROID_MapKey(int scancode, int keysym)
|
||||
|
||||
def check_pause():
|
||||
return SDL_ANDROID_CheckPause()
|
||||
|
||||
def wait_for_resume():
|
||||
android_accelerometer_enable(False)
|
||||
SDL_ANDROID_WaitForResume()
|
||||
android_accelerometer_enable(accelerometer_enabled)
|
||||
|
||||
def map_key(scancode, keysym):
|
||||
SDL_ANDROID_MapKey(scancode, keysym)
|
||||
|
||||
# Android keycodes.
|
||||
KEYCODE_UNKNOWN = 0
|
||||
KEYCODE_SOFT_LEFT = 1
|
||||
KEYCODE_SOFT_RIGHT = 2
|
||||
KEYCODE_HOME = 3
|
||||
KEYCODE_BACK = 4
|
||||
KEYCODE_CALL = 5
|
||||
KEYCODE_ENDCALL = 6
|
||||
KEYCODE_0 = 7
|
||||
KEYCODE_1 = 8
|
||||
KEYCODE_2 = 9
|
||||
KEYCODE_3 = 10
|
||||
KEYCODE_4 = 11
|
||||
KEYCODE_5 = 12
|
||||
KEYCODE_6 = 13
|
||||
KEYCODE_7 = 14
|
||||
KEYCODE_8 = 15
|
||||
KEYCODE_9 = 16
|
||||
KEYCODE_STAR = 17
|
||||
KEYCODE_POUND = 18
|
||||
KEYCODE_DPAD_UP = 19
|
||||
KEYCODE_DPAD_DOWN = 20
|
||||
KEYCODE_DPAD_LEFT = 21
|
||||
KEYCODE_DPAD_RIGHT = 22
|
||||
KEYCODE_DPAD_CENTER = 23
|
||||
KEYCODE_VOLUME_UP = 24
|
||||
KEYCODE_VOLUME_DOWN = 25
|
||||
KEYCODE_POWER = 26
|
||||
KEYCODE_CAMERA = 27
|
||||
KEYCODE_CLEAR = 28
|
||||
KEYCODE_A = 29
|
||||
KEYCODE_B = 30
|
||||
KEYCODE_C = 31
|
||||
KEYCODE_D = 32
|
||||
KEYCODE_E = 33
|
||||
KEYCODE_F = 34
|
||||
KEYCODE_G = 35
|
||||
KEYCODE_H = 36
|
||||
KEYCODE_I = 37
|
||||
KEYCODE_J = 38
|
||||
KEYCODE_K = 39
|
||||
KEYCODE_L = 40
|
||||
KEYCODE_M = 41
|
||||
KEYCODE_N = 42
|
||||
KEYCODE_O = 43
|
||||
KEYCODE_P = 44
|
||||
KEYCODE_Q = 45
|
||||
KEYCODE_R = 46
|
||||
KEYCODE_S = 47
|
||||
KEYCODE_T = 48
|
||||
KEYCODE_U = 49
|
||||
KEYCODE_V = 50
|
||||
KEYCODE_W = 51
|
||||
KEYCODE_X = 52
|
||||
KEYCODE_Y = 53
|
||||
KEYCODE_Z = 54
|
||||
KEYCODE_COMMA = 55
|
||||
KEYCODE_PERIOD = 56
|
||||
KEYCODE_ALT_LEFT = 57
|
||||
KEYCODE_ALT_RIGHT = 58
|
||||
KEYCODE_SHIFT_LEFT = 59
|
||||
KEYCODE_SHIFT_RIGHT = 60
|
||||
KEYCODE_TAB = 61
|
||||
KEYCODE_SPACE = 62
|
||||
KEYCODE_SYM = 63
|
||||
KEYCODE_EXPLORER = 64
|
||||
KEYCODE_ENVELOPE = 65
|
||||
KEYCODE_ENTER = 66
|
||||
KEYCODE_DEL = 67
|
||||
KEYCODE_GRAVE = 68
|
||||
KEYCODE_MINUS = 69
|
||||
KEYCODE_EQUALS = 70
|
||||
KEYCODE_LEFT_BRACKET = 71
|
||||
KEYCODE_RIGHT_BRACKET = 72
|
||||
KEYCODE_BACKSLASH = 73
|
||||
KEYCODE_SEMICOLON = 74
|
||||
KEYCODE_APOSTROPHE = 75
|
||||
KEYCODE_SLASH = 76
|
||||
KEYCODE_AT = 77
|
||||
KEYCODE_NUM = 78
|
||||
KEYCODE_HEADSETHOOK = 79
|
||||
KEYCODE_FOCUS = 80
|
||||
KEYCODE_PLUS = 81
|
||||
KEYCODE_MENU = 82
|
||||
KEYCODE_NOTIFICATION = 83
|
||||
KEYCODE_SEARCH = 84
|
||||
KEYCODE_MEDIA_PLAY_PAUSE= 85
|
||||
KEYCODE_MEDIA_STOP = 86
|
||||
KEYCODE_MEDIA_NEXT = 87
|
||||
KEYCODE_MEDIA_PREVIOUS = 88
|
||||
KEYCODE_MEDIA_REWIND = 89
|
||||
KEYCODE_MEDIA_FAST_FORWARD = 90
|
||||
KEYCODE_MUTE = 91
|
||||
|
||||
# Vibration support.
|
||||
cdef extern void android_vibrate(double)
|
||||
|
||||
def vibrate(s):
|
||||
android_vibrate(s)
|
||||
|
||||
# Accelerometer support.
|
||||
cdef extern void android_accelerometer_enable(int)
|
||||
cdef extern void android_accelerometer_reading(float *)
|
||||
|
||||
accelerometer_enabled = False
|
||||
|
||||
def accelerometer_enable(p):
|
||||
global accelerometer_enabled
|
||||
|
||||
android_accelerometer_enable(p)
|
||||
|
||||
accelerometer_enabled = p
|
||||
|
||||
def accelerometer_reading():
|
||||
cdef float rv[3]
|
||||
android_accelerometer_reading(rv)
|
||||
|
||||
return (rv[0], rv[1], rv[2])
|
||||
|
||||
# Wifi reading support
|
||||
cdef extern void android_wifi_scanner_enable()
|
||||
cdef extern char * android_wifi_scan()
|
||||
|
||||
def wifi_scanner_enable():
|
||||
android_wifi_scanner_enable()
|
||||
|
||||
def wifi_scan():
|
||||
cdef char * reading
|
||||
reading = android_wifi_scan()
|
||||
|
||||
reading_list = []
|
||||
|
||||
for line in filter(lambda l: l, reading.split('\n')):
|
||||
[ssid, mac, level] = line.split('\t')
|
||||
reading_list.append((ssid.strip(), mac.upper().strip(), int(level)))
|
||||
|
||||
return reading_list
|
||||
|
||||
# DisplayMetrics information.
|
||||
cdef extern int android_get_dpi()
|
||||
|
||||
def get_dpi():
|
||||
return android_get_dpi()
|
||||
|
||||
|
||||
# Soft keyboard.
|
||||
cdef extern void android_show_keyboard(int)
|
||||
cdef extern void android_hide_keyboard()
|
||||
|
||||
|
||||
from jnius import autoclass, PythonJavaClass, java_method, cast
|
||||
|
||||
# API versions
|
||||
api_version = autoclass('android.os.Build$VERSION').SDK_INT
|
||||
version_codes = autoclass('android.os.Build$VERSION_CODES')
|
||||
|
||||
|
||||
python_act = autoclass(JAVA_NAMESPACE + '.PythonActivity')
|
||||
Rect = autoclass('android.graphics.Rect')
|
||||
mActivity = python_act.mActivity
|
||||
if mActivity:
|
||||
# PyGame backend already has the listener so adding
|
||||
# one here leads to a crash/too much cpu usage.
|
||||
# SDL2 now does noe need the listener so there is
|
||||
# no point adding a processor intensive layout listenere here.
|
||||
height = 0
|
||||
def get_keyboard_height():
|
||||
rctx = Rect()
|
||||
mActivity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rctx)
|
||||
# NOTE top should always be zero
|
||||
rctx.top = 0
|
||||
height = mActivity.getWindowManager().getDefaultDisplay().getHeight() - (rctx.bottom - rctx.top)
|
||||
return height
|
||||
else:
|
||||
def get_keyboard_height():
|
||||
return 0
|
||||
|
||||
# Flags for input_type, for requesting a particular type of keyboard
|
||||
#android FLAGS
|
||||
TYPE_CLASS_DATETIME = 4
|
||||
TYPE_CLASS_NUMBER = 2
|
||||
TYPE_NUMBER_VARIATION_NORMAL = 0
|
||||
TYPE_NUMBER_VARIATION_PASSWORD = 16
|
||||
TYPE_CLASS_TEXT = 1
|
||||
TYPE_TEXT_FLAG_AUTO_COMPLETE = 65536
|
||||
TYPE_TEXT_FLAG_AUTO_CORRECT = 32768
|
||||
TYPE_TEXT_FLAG_NO_SUGGESTIONS = 524288
|
||||
TYPE_TEXT_VARIATION_EMAIL_ADDRESS = 32
|
||||
TYPE_TEXT_VARIATION_NORMAL = 0
|
||||
TYPE_TEXT_VARIATION_PASSWORD = 128
|
||||
TYPE_TEXT_VARIATION_POSTAL_ADDRESS = 112
|
||||
TYPE_TEXT_VARIATION_URI = 16
|
||||
TYPE_CLASS_PHONE = 3
|
||||
|
||||
IF BOOTSTRAP == 'sdl2':
|
||||
def remove_presplash():
|
||||
# Remove android presplash in SDL2 bootstrap.
|
||||
mActivity.removeLoadingScreen()
|
||||
|
||||
def show_keyboard(target, input_type):
|
||||
if input_type == 'text':
|
||||
_input_type = TYPE_CLASS_TEXT
|
||||
elif input_type == 'number':
|
||||
_input_type = TYPE_CLASS_NUMBER
|
||||
elif input_type == 'url':
|
||||
_input_type = \
|
||||
TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_URI
|
||||
elif input_type == 'mail':
|
||||
_input_type = \
|
||||
TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_EMAIL_ADDRESS
|
||||
elif input_type == 'datetime':
|
||||
_input_type = TYPE_CLASS_DATETIME
|
||||
elif input_type == 'tel':
|
||||
_input_type = TYPE_CLASS_PHONE
|
||||
elif input_type == 'address':
|
||||
_input_type = TYPE_TEXT_VARIATION_POSTAL_ADDRESS
|
||||
|
||||
if hasattr(target, 'password') and target.password:
|
||||
if _input_type == TYPE_CLASS_TEXT:
|
||||
_input_type |= TYPE_TEXT_VARIATION_PASSWORD
|
||||
elif _input_type == TYPE_CLASS_NUMBER:
|
||||
_input_type |= TYPE_NUMBER_VARIATION_PASSWORD
|
||||
|
||||
if hasattr(target, 'keyboard_suggestions') and not target.keyboard_suggestions:
|
||||
if _input_type == TYPE_CLASS_TEXT:
|
||||
_input_type = TYPE_CLASS_TEXT | \
|
||||
TYPE_TEXT_FLAG_NO_SUGGESTIONS
|
||||
|
||||
android_show_keyboard(_input_type)
|
||||
|
||||
def hide_keyboard():
|
||||
android_hide_keyboard()
|
||||
|
||||
# Build info.
|
||||
cdef extern char* BUILD_MANUFACTURER
|
||||
cdef extern char* BUILD_MODEL
|
||||
cdef extern char* BUILD_PRODUCT
|
||||
cdef extern char* BUILD_VERSION_RELEASE
|
||||
|
||||
cdef extern void android_get_buildinfo()
|
||||
|
||||
class BuildInfo:
|
||||
MANUFACTURER = None
|
||||
MODEL = None
|
||||
PRODUCT = None
|
||||
VERSION_RELEASE = None
|
||||
|
||||
def get_buildinfo():
|
||||
android_get_buildinfo()
|
||||
binfo = BuildInfo()
|
||||
binfo.MANUFACTURER = BUILD_MANUFACTURER
|
||||
binfo.MODEL = BUILD_MODEL
|
||||
binfo.PRODUCT = BUILD_PRODUCT
|
||||
binfo.VERSION_RELEASE = BUILD_VERSION_RELEASE
|
||||
return binfo
|
||||
|
||||
IF IS_PYGAME:
|
||||
# Activate input - required to receive input events.
|
||||
cdef extern void android_activate_input()
|
||||
|
||||
def init():
|
||||
android_activate_input()
|
||||
|
||||
# Action send
|
||||
cdef extern void android_action_send(char*, char*, char*, char*, char*)
|
||||
def action_send(mimetype, filename=None, subject=None, text=None,
|
||||
chooser_title=None):
|
||||
cdef char *j_mimetype = <bytes>mimetype
|
||||
cdef char *j_filename = NULL
|
||||
cdef char *j_subject = NULL
|
||||
cdef char *j_text = NULL
|
||||
cdef char *j_chooser_title = NULL
|
||||
if filename is not None:
|
||||
j_filename = <bytes>filename
|
||||
if subject is not None:
|
||||
j_subject = <bytes>subject
|
||||
if text is not None:
|
||||
j_text = <bytes>text
|
||||
if chooser_title is not None:
|
||||
j_chooser_title = <bytes>chooser_title
|
||||
android_action_send(j_mimetype, j_filename, j_subject, j_text,
|
||||
j_chooser_title)
|
||||
|
||||
cdef extern int android_checkstop()
|
||||
cdef extern void android_ackstop()
|
||||
|
||||
def check_stop():
|
||||
return android_checkstop()
|
||||
|
||||
def ack_stop():
|
||||
android_ackstop()
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# URL Opening.
|
||||
def open_url(url):
|
||||
Intent = autoclass('android.content.Intent')
|
||||
Uri = autoclass('android.net.Uri')
|
||||
browserIntent = Intent()
|
||||
browserIntent.setAction(Intent.ACTION_VIEW)
|
||||
browserIntent.setData(Uri.parse(url))
|
||||
currentActivity = cast('android.app.Activity', mActivity)
|
||||
currentActivity.startActivity(browserIntent)
|
||||
return True
|
||||
|
||||
# Web browser support.
|
||||
class AndroidBrowser(object):
|
||||
def open(self, url, new=0, autoraise=True):
|
||||
return open_url(url)
|
||||
def open_new(self, url):
|
||||
return open_url(url)
|
||||
def open_new_tab(self, url):
|
||||
return open_url(url)
|
||||
|
||||
import webbrowser
|
||||
webbrowser.register('android', AndroidBrowser, None, -1)
|
||||
|
||||
cdef extern void android_start_service(char *, char *, char *)
|
||||
def start_service(title=None, description=None, arg=None):
|
||||
cdef char *j_title = NULL
|
||||
cdef char *j_description = NULL
|
||||
if title is not None:
|
||||
j_title = <bytes>title
|
||||
if description is not None:
|
||||
j_description = <bytes>description
|
||||
if arg is not None:
|
||||
j_arg = <bytes>arg
|
||||
android_start_service(j_title, j_description, j_arg)
|
||||
|
||||
cdef extern void android_stop_service()
|
||||
def stop_service():
|
||||
android_stop_service()
|
||||
|
||||
class AndroidService(object):
|
||||
'''Android service class.
|
||||
Run ``service/main.py`` from application directory as a service.
|
||||
|
||||
:Parameters:
|
||||
`title`: str, default to 'Python service'
|
||||
Notification title.
|
||||
|
||||
`description`: str, default to 'Kivy Python service started'
|
||||
Notification text.
|
||||
'''
|
||||
|
||||
def __init__(self, title='Python service',
|
||||
description='Kivy Python service started'):
|
||||
self.title = title
|
||||
self.description = description
|
||||
|
||||
def start(self, arg=''):
|
||||
'''Start the service.
|
||||
|
||||
:Parameters:
|
||||
`arg`: str, default to ''
|
||||
Argument to pass to a service,
|
||||
through environment variable ``PYTHON_SERVICE_ARGUMENT``.
|
||||
'''
|
||||
start_service(self.title, self.description, arg)
|
||||
|
||||
def stop(self):
|
||||
'''Stop the service.
|
||||
'''
|
||||
stop_service()
|
||||
|
||||
|
81
MovedRecipes/android/src/android/_android_billing.pyx
Normal file
81
MovedRecipes/android/src/android/_android_billing.pyx
Normal file
|
@ -0,0 +1,81 @@
|
|||
# -------------------------------------------------------------------
|
||||
# Billing
|
||||
cdef extern void android_billing_service_start()
|
||||
cdef extern void android_billing_service_stop()
|
||||
cdef extern void android_billing_buy(char *sku)
|
||||
cdef extern char *android_billing_get_purchased_items()
|
||||
cdef extern char *android_billing_get_pending_message()
|
||||
|
||||
class BillingService(object):
|
||||
|
||||
BILLING_ACTION_SUPPORTED = 'billingsupported'
|
||||
BILLING_ACTION_ITEMSCHANGED = 'itemschanged'
|
||||
|
||||
BILLING_TYPE_INAPP = 'inapp'
|
||||
BILLING_TYPE_SUBSCRIPTION = 'subs'
|
||||
|
||||
def __init__(self, callback):
|
||||
super(BillingService, self).__init__()
|
||||
self.callback = callback
|
||||
self.purchased_items = None
|
||||
android_billing_service_start()
|
||||
|
||||
def _stop(self):
|
||||
android_billing_service_stop()
|
||||
|
||||
def buy(self, sku):
|
||||
cdef char *j_sku = <bytes>sku
|
||||
android_billing_buy(j_sku)
|
||||
|
||||
def get_purchased_items(self):
|
||||
cdef char *items = NULL
|
||||
cdef bytes pitem
|
||||
items = android_billing_get_purchased_items()
|
||||
if items == NULL:
|
||||
return []
|
||||
pitems = items
|
||||
ret = {}
|
||||
for item in pitems.split('\n'):
|
||||
if not item:
|
||||
continue
|
||||
sku, qt = item.split(',')
|
||||
ret[sku] = {'qt': int(qt)}
|
||||
return ret
|
||||
|
||||
def check(self, *largs):
|
||||
cdef char *message
|
||||
cdef bytes pymessage
|
||||
|
||||
while True:
|
||||
message = android_billing_get_pending_message()
|
||||
if message == NULL:
|
||||
break
|
||||
pymessage = <bytes>message
|
||||
self._handle_message(pymessage)
|
||||
|
||||
if self.purchased_items is None:
|
||||
self._check_new_items()
|
||||
|
||||
def _handle_message(self, message):
|
||||
action, data = message.split('|', 1)
|
||||
#print "HANDLE MESSAGE-----", (action, data)
|
||||
|
||||
if action == 'billingSupported':
|
||||
tp, value = data.split('|')
|
||||
value = True if value == '1' else False
|
||||
self.callback(BillingService.BILLING_ACTION_SUPPORTED, tp, value)
|
||||
|
||||
elif action == 'requestPurchaseResponse':
|
||||
self._check_new_items()
|
||||
|
||||
elif action == 'purchaseStateChange':
|
||||
self._check_new_items()
|
||||
|
||||
elif action == 'restoreTransaction':
|
||||
self._check_new_items()
|
||||
|
||||
def _check_new_items(self):
|
||||
items = self.get_purchased_items()
|
||||
if self.purchased_items != items:
|
||||
self.purchased_items = items
|
||||
self.callback(BillingService.BILLING_ACTION_ITEMSCHANGED, self.purchased_items)
|
120
MovedRecipes/android/src/android/_android_billing_jni.c
Normal file
120
MovedRecipes/android/src/android/_android_billing_jni.c
Normal file
|
@ -0,0 +1,120 @@
|
|||
#include <jni.h>
|
||||
#include <stdio.h>
|
||||
#include <android/log.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define aassert(x) { if (!x) { __android_log_print(ANDROID_LOG_ERROR, "android_jni", "Assertion failed. %s:%d", __FILE__, __LINE__); abort(); }}
|
||||
#define PUSH_FRAME { (*env)->PushLocalFrame(env, 16); }
|
||||
#define POP_FRAME { (*env)->PopLocalFrame(env, NULL); }
|
||||
|
||||
void android_billing_service_start() {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, JNI_NAMESPACE "/PythonActivity");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "billingServiceStart", "()V");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
PUSH_FRAME;
|
||||
(*env)->CallStaticVoidMethod(env, cls, mid);
|
||||
POP_FRAME;
|
||||
}
|
||||
|
||||
void android_billing_service_stop() {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, JNI_NAMESPACE "/PythonActivity");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "billingServiceStop", "()V");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
PUSH_FRAME;
|
||||
(*env)->CallStaticVoidMethod(env, cls, mid);
|
||||
POP_FRAME;
|
||||
}
|
||||
|
||||
void android_billing_buy(char *sku) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, JNI_NAMESPACE "/PythonActivity");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "billingBuy", "(Ljava/lang/String;)V");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
PUSH_FRAME;
|
||||
|
||||
(*env)->CallStaticVoidMethod(
|
||||
env, cls, mid,
|
||||
(*env)->NewStringUTF(env, sku)
|
||||
);
|
||||
|
||||
POP_FRAME;
|
||||
}
|
||||
|
||||
char *android_billing_get_purchased_items() {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
jobject jreading;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, JNI_NAMESPACE "/PythonActivity");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "billingGetPurchasedItems", "()Ljava/lang/String;");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
PUSH_FRAME;
|
||||
jreading = (*env)->CallStaticObjectMethod(env, cls, mid);
|
||||
const char * reading = (*env)->GetStringUTFChars(env, jreading, 0);
|
||||
POP_FRAME;
|
||||
|
||||
return reading;
|
||||
}
|
||||
|
||||
char *android_billing_get_pending_message() {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
jobject jreading;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, JNI_NAMESPACE "/PythonActivity");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "billingGetPendingMessage", "()Ljava/lang/String;");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
PUSH_FRAME;
|
||||
jreading = (*env)->CallStaticObjectMethod(env, cls, mid);
|
||||
const char * reading = (*env)->GetStringUTFChars(env, jreading, 0);
|
||||
POP_FRAME;
|
||||
|
||||
return reading;
|
||||
}
|
||||
|
358
MovedRecipes/android/src/android/_android_jni.c
Normal file
358
MovedRecipes/android/src/android/_android_jni.c
Normal file
|
@ -0,0 +1,358 @@
|
|||
#include <jni.h>
|
||||
#include <stdio.h>
|
||||
#include <android/log.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define aassert(x) { if (!x) { __android_log_print(ANDROID_LOG_ERROR, "android_jni", "Assertion failed. %s:%d", __FILE__, __LINE__); abort(); }}
|
||||
#define PUSH_FRAME { (*env)->PushLocalFrame(env, 16); }
|
||||
#define POP_FRAME { (*env)->PopLocalFrame(env, NULL); }
|
||||
|
||||
void android_vibrate(double seconds) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/Hardware");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "vibrate", "(D)V");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
(*env)->CallStaticVoidMethod(
|
||||
env, cls, mid,
|
||||
(jdouble) seconds);
|
||||
}
|
||||
|
||||
void android_accelerometer_enable(int enable) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/Hardware");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "accelerometerEnable", "(Z)V");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
(*env)->CallStaticVoidMethod(
|
||||
env, cls, mid,
|
||||
(jboolean) enable);
|
||||
}
|
||||
|
||||
void android_wifi_scanner_enable(void){
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/Hardware");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "enableWifiScanner", "()V");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
(*env)->CallStaticVoidMethod(env, cls, mid);
|
||||
}
|
||||
|
||||
|
||||
char * android_wifi_scan() {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
jobject jreading;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/Hardware");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "scanWifi", "()Ljava/lang/String;");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
PUSH_FRAME;
|
||||
jreading = (*env)->CallStaticObjectMethod(env, cls, mid);
|
||||
const char * reading = (*env)->GetStringUTFChars(env, jreading, 0);
|
||||
POP_FRAME;
|
||||
|
||||
return reading;
|
||||
}
|
||||
|
||||
void android_accelerometer_reading(float *values) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
jobject jvalues;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/Hardware");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "accelerometerReading", "()[F");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
PUSH_FRAME;
|
||||
|
||||
jvalues = (*env)->CallStaticObjectMethod(env, cls, mid);
|
||||
(*env)->GetFloatArrayRegion(env, jvalues, 0, 3, values);
|
||||
|
||||
POP_FRAME;
|
||||
}
|
||||
|
||||
int android_get_dpi(void) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/Hardware");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "getDPI", "()I");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
return (*env)->CallStaticIntMethod(env, cls, mid);
|
||||
}
|
||||
|
||||
void android_show_keyboard(int input_type) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/Hardware");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "showKeyboard", "(I)V");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
(*env)->CallStaticVoidMethod(env, cls, mid, (jint) input_type);
|
||||
}
|
||||
|
||||
void android_hide_keyboard(void) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/Hardware");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "hideKeyboard", "()V");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
(*env)->CallStaticVoidMethod(env, cls, mid);
|
||||
}
|
||||
|
||||
char* BUILD_MANUFACTURER = NULL;
|
||||
char* BUILD_MODEL = NULL;
|
||||
char* BUILD_PRODUCT = NULL;
|
||||
char* BUILD_VERSION_RELEASE = NULL;
|
||||
|
||||
void android_get_buildinfo() {
|
||||
static JNIEnv *env = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
jclass *cls = NULL;
|
||||
jfieldID fid;
|
||||
jstring sval;
|
||||
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
|
||||
cls = (*env)->FindClass(env, "android/os/Build");
|
||||
|
||||
fid = (*env)->GetStaticFieldID(env, cls, "MANUFACTURER", "Ljava/lang/String;");
|
||||
sval = (jstring) (*env)->GetStaticObjectField(env, cls, fid);
|
||||
BUILD_MANUFACTURER = (*env)->GetStringUTFChars(env, sval, 0);
|
||||
|
||||
fid = (*env)->GetStaticFieldID(env, cls, "MODEL", "Ljava/lang/String;");
|
||||
sval = (jstring) (*env)->GetStaticObjectField(env, cls, fid);
|
||||
BUILD_MODEL = (*env)->GetStringUTFChars(env, sval, 0);
|
||||
|
||||
fid = (*env)->GetStaticFieldID(env, cls, "PRODUCT", "Ljava/lang/String;");
|
||||
sval = (jstring) (*env)->GetStaticObjectField(env, cls, fid);
|
||||
BUILD_PRODUCT = (*env)->GetStringUTFChars(env, sval, 0);
|
||||
|
||||
cls = (*env)->FindClass(env, "android/os/Build$VERSION");
|
||||
|
||||
fid = (*env)->GetStaticFieldID(env, cls, "RELEASE", "Ljava/lang/String;");
|
||||
sval = (jstring) (*env)->GetStaticObjectField(env, cls, fid);
|
||||
BUILD_VERSION_RELEASE = (*env)->GetStringUTFChars(env, sval, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#if IS_PYGAME
|
||||
void android_activate_input(void) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/SDLSurfaceView");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "activateInput", "()V");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
(*env)->CallStaticVoidMethod(env, cls, mid);
|
||||
}
|
||||
|
||||
int android_checkstop(void) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/SDLSurfaceView");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "checkStop", "()I");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
return (*env)->CallStaticIntMethod(env, cls, mid);
|
||||
}
|
||||
|
||||
void android_ackstop(void) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/SDLSurfaceView");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "ackStop", "()I");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
(*env)->CallStaticIntMethod(env, cls, mid);
|
||||
}
|
||||
|
||||
void android_action_send(char *mimeType, char *filename, char *subject, char *text, char *chooser_title) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/Action");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "send",
|
||||
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
jstring j_mimeType = (*env)->NewStringUTF(env, mimeType);
|
||||
jstring j_filename = NULL;
|
||||
jstring j_subject = NULL;
|
||||
jstring j_text = NULL;
|
||||
jstring j_chooser_title = NULL;
|
||||
if ( filename != NULL )
|
||||
j_filename = (*env)->NewStringUTF(env, filename);
|
||||
if ( subject != NULL )
|
||||
j_subject = (*env)->NewStringUTF(env, subject);
|
||||
if ( text != NULL )
|
||||
j_text = (*env)->NewStringUTF(env, text);
|
||||
if ( chooser_title != NULL )
|
||||
j_chooser_title = (*env)->NewStringUTF(env, text);
|
||||
|
||||
(*env)->CallStaticVoidMethod(
|
||||
env, cls, mid,
|
||||
j_mimeType, j_filename, j_subject, j_text,
|
||||
j_chooser_title);
|
||||
}
|
||||
|
||||
void android_open_url(char *url) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/SDLSurfaceView");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "openUrl", "(Ljava/lang/String;)V");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
PUSH_FRAME;
|
||||
|
||||
(*env)->CallStaticVoidMethod(
|
||||
env, cls, mid,
|
||||
(*env)->NewStringUTF(env, url)
|
||||
);
|
||||
|
||||
POP_FRAME;
|
||||
}
|
||||
#endif // IS_PYGAME
|
||||
|
||||
void android_start_service(char *title, char *description, char *arg) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, JNI_NAMESPACE "/PythonActivity");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "start_service",
|
||||
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
jstring j_title = NULL;
|
||||
jstring j_description = NULL;
|
||||
jstring j_arg = NULL;
|
||||
if ( title != 0 )
|
||||
j_title = (*env)->NewStringUTF(env, title);
|
||||
if ( description != 0 )
|
||||
j_description = (*env)->NewStringUTF(env, description);
|
||||
if ( arg != 0 )
|
||||
j_arg = (*env)->NewStringUTF(env, arg);
|
||||
|
||||
(*env)->CallStaticVoidMethod(env, cls, mid, j_title, j_description, j_arg);
|
||||
}
|
||||
|
||||
void android_stop_service() {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
cls = (*env)->FindClass(env, JNI_NAMESPACE "/PythonActivity");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "stop_service", "()V");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
(*env)->CallStaticVoidMethod(env, cls, mid);
|
||||
}
|
125
MovedRecipes/android/src/android/_android_sound.pyx
Normal file
125
MovedRecipes/android/src/android/_android_sound.pyx
Normal file
|
@ -0,0 +1,125 @@
|
|||
cdef extern void android_sound_queue(int, char *, char *, long long, long long)
|
||||
cdef extern void android_sound_play(int, char *, char *, long long, long long)
|
||||
cdef extern void android_sound_stop(int)
|
||||
cdef extern void android_sound_seek(int, float)
|
||||
cdef extern void android_sound_dequeue(int)
|
||||
cdef extern void android_sound_playing_name(int, char *, int)
|
||||
cdef extern void android_sound_pause(int)
|
||||
cdef extern void android_sound_unpause(int)
|
||||
|
||||
cdef extern void android_sound_set_volume(int, float)
|
||||
cdef extern void android_sound_set_secondary_volume(int, float)
|
||||
cdef extern void android_sound_set_pan(int, float)
|
||||
|
||||
cdef extern int android_sound_queue_depth(int)
|
||||
cdef extern int android_sound_get_pos(int)
|
||||
cdef extern int android_sound_get_length(int)
|
||||
|
||||
channels = set()
|
||||
volumes = { }
|
||||
|
||||
def queue(channel, file, name, fadein=0, tight=False):
|
||||
|
||||
channels.add(channel)
|
||||
|
||||
real_fn = file.name
|
||||
base = getattr(file, "base", -1)
|
||||
length = getattr(file, "length", -1)
|
||||
|
||||
android_sound_queue(channel, name, real_fn, base, length)
|
||||
|
||||
def play(channel, file, name, paused=False, fadein=0, tight=False):
|
||||
|
||||
channels.add(channel)
|
||||
|
||||
real_fn = file.name
|
||||
base = getattr(file, "base", -1)
|
||||
length = getattr(file, "length", -1)
|
||||
|
||||
android_sound_play(channel, name, real_fn, base, length)
|
||||
|
||||
def seek(channel, position):
|
||||
android_sound_seek(channel, position)
|
||||
|
||||
def stop(channel):
|
||||
android_sound_stop(channel)
|
||||
|
||||
def dequeue(channel, even_tight=False):
|
||||
android_sound_dequeue(channel)
|
||||
|
||||
def queue_depth(channel):
|
||||
return android_sound_queue_depth(channel)
|
||||
|
||||
def playing_name(channel):
|
||||
cdef char buf[1024]
|
||||
|
||||
android_sound_playing_name(channel, buf, 1024)
|
||||
|
||||
rv = buf
|
||||
if not len(rv):
|
||||
return None
|
||||
return rv
|
||||
|
||||
def pause(channel):
|
||||
android_sound_pause(channel)
|
||||
return
|
||||
|
||||
def unpause(channel):
|
||||
android_sound_unpause(channel)
|
||||
return
|
||||
|
||||
def unpause_all():
|
||||
for i in channels:
|
||||
unpause(i)
|
||||
|
||||
def pause_all():
|
||||
for i in channels:
|
||||
pause(i)
|
||||
|
||||
def fadeout(channel, ms):
|
||||
stop(channel)
|
||||
|
||||
def busy(channel):
|
||||
return playing_name(channel) != None
|
||||
|
||||
def get_pos(channel):
|
||||
return android_sound_get_pos(channel)
|
||||
|
||||
def get_length(channel):
|
||||
return android_sound_get_length(channel)
|
||||
|
||||
def set_volume(channel, volume):
|
||||
android_sound_set_volume(channel, volume)
|
||||
volumes[channel] = volume
|
||||
|
||||
def set_secondary_volume(channel, volume):
|
||||
android_sound_set_secondary_volume(channel, volume)
|
||||
|
||||
def set_pan(channel, pan):
|
||||
android_sound_set_pan(channel, pan)
|
||||
|
||||
def set_end_event(channel, event):
|
||||
return
|
||||
|
||||
def get_volume(channel):
|
||||
return volumes.get(channel, 1.0)
|
||||
|
||||
def init(freq, stereo, samples, status=False):
|
||||
return
|
||||
|
||||
def quit():
|
||||
for i in channels:
|
||||
stop(i)
|
||||
|
||||
def periodic():
|
||||
return
|
||||
|
||||
def alloc_event(surf):
|
||||
return
|
||||
|
||||
def refresh_event():
|
||||
return
|
||||
|
||||
def check_version(version):
|
||||
return
|
||||
|
308
MovedRecipes/android/src/android/_android_sound_jni.c
Normal file
308
MovedRecipes/android/src/android/_android_sound_jni.c
Normal file
|
@ -0,0 +1,308 @@
|
|||
#include <jni.h>
|
||||
#include <stdio.h>
|
||||
#include <android/log.h>
|
||||
#include <string.h>
|
||||
|
||||
JNIEnv *SDL_ANDROID_GetJNIEnv();
|
||||
|
||||
#define aassert(x) { if (!x) { __android_log_print(ANDROID_LOG_ERROR, "android_sound_jni", "Assertion failed. %s:%d", __FILE__, __LINE__); abort(); }}
|
||||
#define PUSH_FRAME { (*env)->PushLocalFrame(env, 16); }
|
||||
#define POP_FRAME { (*env)->PopLocalFrame(env, NULL); }
|
||||
|
||||
|
||||
void android_sound_queue(int channel, char *filename, char *real_fn, long long base, long long length) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/RenPySound");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "queue", "(ILjava/lang/String;Ljava/lang/String;JJ)V");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
PUSH_FRAME;
|
||||
|
||||
(*env)->CallStaticVoidMethod(
|
||||
env, cls, mid,
|
||||
channel,
|
||||
(*env)->NewStringUTF(env, filename),
|
||||
(*env)->NewStringUTF(env, real_fn),
|
||||
(jlong) base,
|
||||
(jlong) length);
|
||||
|
||||
POP_FRAME;
|
||||
}
|
||||
|
||||
void android_sound_play(int channel, char *filename, char *real_fn, long long base, long long length) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/RenPySound");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "play", "(ILjava/lang/String;Ljava/lang/String;JJ)V");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
PUSH_FRAME;
|
||||
|
||||
(*env)->CallStaticVoidMethod(
|
||||
env, cls, mid,
|
||||
channel,
|
||||
(*env)->NewStringUTF(env, filename),
|
||||
(*env)->NewStringUTF(env, real_fn),
|
||||
(jlong) base,
|
||||
(jlong) length);
|
||||
|
||||
POP_FRAME;
|
||||
}
|
||||
|
||||
void android_sound_seek(int channel, float position){
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/RenPySound");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "seek", "(IF)V");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
(*env)->CallStaticVoidMethod(
|
||||
env, cls, mid,
|
||||
channel,
|
||||
(jfloat) position);
|
||||
}
|
||||
|
||||
void android_sound_stop(int channel) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/RenPySound");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "stop", "(I)V");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
(*env)->CallStaticVoidMethod(
|
||||
env, cls, mid,
|
||||
channel);
|
||||
}
|
||||
|
||||
void android_sound_dequeue(int channel) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/RenPySound");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "dequeue", "(I)V");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
(*env)->CallStaticVoidMethod(
|
||||
env, cls, mid,
|
||||
channel);
|
||||
}
|
||||
|
||||
int android_sound_queue_depth(int channel) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/RenPySound");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "queue_depth", "(I)I");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
(*env)->CallStaticIntMethod(
|
||||
env, cls, mid,
|
||||
channel);
|
||||
}
|
||||
|
||||
void android_sound_playing_name(int channel, char *buf, int buflen) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
jobject s = NULL;
|
||||
char *jbuf;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/RenPySound");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "playing_name", "(I)Ljava/lang/String;");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
PUSH_FRAME;
|
||||
|
||||
s = (*env)->CallStaticObjectMethod(
|
||||
env, cls, mid,
|
||||
channel);
|
||||
|
||||
jbuf = (*env)->GetStringUTFChars(env, s, NULL);
|
||||
strncpy(buf, jbuf, buflen);
|
||||
(*env)->ReleaseStringUTFChars(env, s, jbuf);
|
||||
|
||||
POP_FRAME;
|
||||
}
|
||||
|
||||
void android_sound_set_volume(int channel, float value) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/RenPySound");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "set_volume", "(IF)V");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
(*env)->CallStaticVoidMethod(
|
||||
env, cls, mid,
|
||||
channel,
|
||||
(jfloat) value);
|
||||
}
|
||||
|
||||
void android_sound_set_secondary_volume(int channel, float value) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/RenPySound");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "set_secondary_volume", "(IF)V");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
(*env)->CallStaticVoidMethod(
|
||||
env, cls, mid,
|
||||
channel,
|
||||
(jfloat) value);
|
||||
}
|
||||
|
||||
void android_sound_set_pan(int channel, float value) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/RenPySound");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "set_pan", "(IF)V");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
(*env)->CallStaticVoidMethod(
|
||||
env, cls, mid,
|
||||
channel,
|
||||
(jfloat) value);
|
||||
}
|
||||
|
||||
void android_sound_pause(int channel) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/RenPySound");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "pause", "(I)V");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
(*env)->CallStaticVoidMethod(
|
||||
env, cls, mid,
|
||||
channel);
|
||||
}
|
||||
|
||||
void android_sound_unpause(int channel) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/RenPySound");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "unpause", "(I)V");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
(*env)->CallStaticVoidMethod(
|
||||
env, cls, mid,
|
||||
channel);
|
||||
}
|
||||
|
||||
int android_sound_get_pos(int channel) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/RenPySound");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "get_pos", "(I)I");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
return (*env)->CallStaticIntMethod(
|
||||
env, cls, mid,
|
||||
channel);
|
||||
}
|
||||
|
||||
int android_sound_get_length(int channel) {
|
||||
static JNIEnv *env = NULL;
|
||||
static jclass *cls = NULL;
|
||||
static jmethodID mid = NULL;
|
||||
|
||||
if (env == NULL) {
|
||||
env = SDL_ANDROID_GetJNIEnv();
|
||||
aassert(env);
|
||||
cls = (*env)->FindClass(env, "org/renpy/android/RenPySound");
|
||||
aassert(cls);
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "get_length", "(I)I");
|
||||
aassert(mid);
|
||||
}
|
||||
|
||||
return (*env)->CallStaticIntMethod(
|
||||
env, cls, mid,
|
||||
channel);
|
||||
}
|
61
MovedRecipes/android/src/android/activity.py
Normal file
61
MovedRecipes/android/src/android/activity.py
Normal file
|
@ -0,0 +1,61 @@
|
|||
from jnius import PythonJavaClass, java_method, autoclass, cast
|
||||
from android.config import JAVA_NAMESPACE, JNI_NAMESPACE
|
||||
|
||||
_activity = autoclass(JAVA_NAMESPACE + '.PythonActivity').mActivity
|
||||
|
||||
_callbacks = {
|
||||
'on_new_intent': [],
|
||||
'on_activity_result': [] }
|
||||
|
||||
class NewIntentListener(PythonJavaClass):
|
||||
__javainterfaces__ = [JNI_NAMESPACE + '/PythonActivity$NewIntentListener']
|
||||
__javacontext__ = 'app'
|
||||
|
||||
def __init__(self, callback, **kwargs):
|
||||
super(NewIntentListener, self).__init__(**kwargs)
|
||||
self.callback = callback
|
||||
|
||||
@java_method('(Landroid/content/Intent;)V')
|
||||
def onNewIntent(self, intent):
|
||||
self.callback(intent)
|
||||
|
||||
|
||||
class ActivityResultListener(PythonJavaClass):
|
||||
__javainterfaces__ = [JNI_NAMESPACE + '/PythonActivity$ActivityResultListener']
|
||||
__javacontext__ = 'app'
|
||||
|
||||
def __init__(self, callback):
|
||||
super(ActivityResultListener, self).__init__()
|
||||
self.callback = callback
|
||||
|
||||
@java_method('(IILandroid/content/Intent;)V')
|
||||
def onActivityResult(self, requestCode, resultCode, intent):
|
||||
self.callback(requestCode, resultCode, intent)
|
||||
|
||||
|
||||
def bind(**kwargs):
|
||||
for event, callback in kwargs.items():
|
||||
if event not in _callbacks:
|
||||
raise Exception('Unknown {!r} event'.format(event))
|
||||
elif event == 'on_new_intent':
|
||||
listener = NewIntentListener(callback)
|
||||
_activity.registerNewIntentListener(listener)
|
||||
_callbacks[event].append(listener)
|
||||
elif event == 'on_activity_result':
|
||||
listener = ActivityResultListener(callback)
|
||||
_activity.registerActivityResultListener(listener)
|
||||
_callbacks[event].append(listener)
|
||||
|
||||
def unbind(**kwargs):
|
||||
for event, callback in kwargs.items():
|
||||
if event not in _callbacks:
|
||||
raise Exception('Unknown {!r} event'.format(event))
|
||||
else:
|
||||
for listener in _callbacks[event][:]:
|
||||
if listener.callback == callback:
|
||||
_callbacks[event].remove(listener)
|
||||
if event == 'on_new_intent':
|
||||
_activity.unregisterNewIntentListener(listener)
|
||||
elif event == 'on_activity_result':
|
||||
_activity.unregisterActivityResultListener(listener)
|
||||
|
7
MovedRecipes/android/src/android/billing.py
Normal file
7
MovedRecipes/android/src/android/billing.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
'''
|
||||
Android Billing API
|
||||
===================
|
||||
|
||||
'''
|
||||
|
||||
from android._android_billing import *
|
79
MovedRecipes/android/src/android/broadcast.py
Normal file
79
MovedRecipes/android/src/android/broadcast.py
Normal file
|
@ -0,0 +1,79 @@
|
|||
# -------------------------------------------------------------------
|
||||
# Broadcast receiver bridge
|
||||
|
||||
from jnius import autoclass, PythonJavaClass, java_method
|
||||
from android.config import JAVA_NAMESPACE, JNI_NAMESPACE
|
||||
|
||||
|
||||
class BroadcastReceiver(object):
|
||||
|
||||
class Callback(PythonJavaClass):
|
||||
__javainterfaces__ = [JNI_NAMESPACE + '/GenericBroadcastReceiverCallback']
|
||||
__javacontext__ = 'app'
|
||||
|
||||
def __init__(self, callback, *args, **kwargs):
|
||||
self.callback = callback
|
||||
PythonJavaClass.__init__(self, *args, **kwargs)
|
||||
|
||||
@java_method('(Landroid/content/Context;Landroid/content/Intent;)V')
|
||||
def onReceive(self, context, intent):
|
||||
self.callback(context, intent)
|
||||
|
||||
def __init__(self, callback, actions=None, categories=None):
|
||||
super(BroadcastReceiver, self).__init__()
|
||||
self.callback = callback
|
||||
|
||||
if not actions and not categories:
|
||||
raise Exception('You need to define at least actions or categories')
|
||||
|
||||
def _expand_partial_name(partial_name):
|
||||
if '.' in partial_name:
|
||||
return partial_name # Its actually a full dotted name
|
||||
else:
|
||||
name = 'ACTION_{}'.format(partial_name.upper())
|
||||
if not hasattr(Intent, name):
|
||||
raise Exception('The intent {} doesnt exist'.format(name))
|
||||
return getattr(Intent, name)
|
||||
|
||||
# resolve actions/categories first
|
||||
Intent = autoclass('android.content.Intent')
|
||||
resolved_actions = [_expand_partial_name(x) for x in actions or []]
|
||||
resolved_categories = [_expand_partial_name(x) for x in categories or []]
|
||||
|
||||
# resolve android API
|
||||
GenericBroadcastReceiver = autoclass(JAVA_NAMESPACE + '.GenericBroadcastReceiver')
|
||||
IntentFilter = autoclass('android.content.IntentFilter')
|
||||
HandlerThread = autoclass('android.os.HandlerThread')
|
||||
|
||||
# create a thread for handling events from the receiver
|
||||
self.handlerthread = HandlerThread('handlerthread')
|
||||
|
||||
# create a listener
|
||||
self.listener = BroadcastReceiver.Callback(self.callback)
|
||||
self.receiver = GenericBroadcastReceiver(self.listener)
|
||||
self.receiver_filter = IntentFilter()
|
||||
for x in resolved_actions:
|
||||
self.receiver_filter.addAction(x)
|
||||
for x in resolved_categories:
|
||||
self.receiver_filter.addCategory(x)
|
||||
|
||||
def start(self):
|
||||
Handler = autoclass('android.os.Handler')
|
||||
self.handlerthread.start()
|
||||
self.handler = Handler(self.handlerthread.getLooper())
|
||||
self.context.registerReceiver(self.receiver, self.receiver_filter, None,
|
||||
self.handler)
|
||||
|
||||
def stop(self):
|
||||
self.context.unregisterReceiver(self.receiver)
|
||||
self.handlerthread.quit()
|
||||
|
||||
@property
|
||||
def context(self):
|
||||
from os import environ
|
||||
if 'PYTHON_SERVICE_ARGUMENT' in environ:
|
||||
PythonService = autoclass(JAVA_NAMESPACE + '.PythonService')
|
||||
return PythonService.mService
|
||||
PythonActivity = autoclass(JAVA_NAMESPACE + '.PythonActivity')
|
||||
return PythonActivity.mActivity
|
||||
|
309
MovedRecipes/android/src/android/mixer.py
Normal file
309
MovedRecipes/android/src/android/mixer.py
Normal file
|
@ -0,0 +1,309 @@
|
|||
# This module is, as much a possible, a clone of the pygame
|
||||
# mixer api.
|
||||
|
||||
import android._android_sound as sound
|
||||
import time
|
||||
import threading
|
||||
import os
|
||||
|
||||
condition = threading.Condition()
|
||||
|
||||
def periodic():
|
||||
for i in range(0, num_channels):
|
||||
if i in channels:
|
||||
channels[i].periodic()
|
||||
|
||||
num_channels = 8
|
||||
reserved_channels = 0
|
||||
|
||||
def init(frequency=22050, size=-16, channels=2, buffer=4096):
|
||||
return None
|
||||
|
||||
def pre_init(frequency=22050, size=-16, channels=2, buffersize=4096):
|
||||
return None
|
||||
|
||||
def quit():
|
||||
stop()
|
||||
return None
|
||||
|
||||
def stop():
|
||||
for i in range(0, num_channels):
|
||||
sound.stop(i)
|
||||
|
||||
def pause():
|
||||
for i in range(0, num_channels):
|
||||
sound.pause(i)
|
||||
|
||||
def unpause():
|
||||
for i in range(0, num_channels):
|
||||
sound.unpause(i)
|
||||
|
||||
def get_busy():
|
||||
for i in range(0, num_channels):
|
||||
if sound.busy(i):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def fadeout(time):
|
||||
# Fadeout doesn't work - it just immediately stops playback.
|
||||
stop()
|
||||
|
||||
|
||||
# A map from channel number to Channel object.
|
||||
channels = { }
|
||||
|
||||
def set_num_channels(count):
|
||||
global num_channels
|
||||
num_channels = count
|
||||
|
||||
def get_num_channels(count):
|
||||
return num_channels
|
||||
|
||||
def set_reserved(count):
|
||||
global reserved_channels
|
||||
reserved_channels = count
|
||||
|
||||
def find_channel(force=False):
|
||||
|
||||
busy = [ ]
|
||||
|
||||
for i in range(reserved_channels, num_channels):
|
||||
c = Channel(i)
|
||||
|
||||
if not c.get_busy():
|
||||
return c
|
||||
|
||||
busy.append(c)
|
||||
|
||||
if not force:
|
||||
return None
|
||||
|
||||
return min(busy, key=lambda x : x.play_time)
|
||||
|
||||
class ChannelImpl(object):
|
||||
|
||||
def __init__(self, id):
|
||||
self.id = id
|
||||
self.loop = None
|
||||
self.queued = None
|
||||
|
||||
self.play_time = time.time()
|
||||
|
||||
def periodic(self):
|
||||
qd = sound.queue_depth(self.id)
|
||||
|
||||
if qd < 2:
|
||||
self.queued = None
|
||||
|
||||
if self.loop is not None and sound.queue_depth(self.id) < 2:
|
||||
self.queue(self.loop, loops=1)
|
||||
|
||||
|
||||
def play(self, s, loops=0, maxtime=0, fade_ms=0):
|
||||
if loops:
|
||||
self.loop = s
|
||||
|
||||
sound.play(self.id, s.file, s.serial)
|
||||
|
||||
self.play_time = time.time()
|
||||
|
||||
with condition:
|
||||
condition.notify()
|
||||
|
||||
def seek(self, position):
|
||||
sound.seek(self.id, position)
|
||||
|
||||
def stop(self):
|
||||
self.loop = None
|
||||
sound.stop(self.id)
|
||||
|
||||
def pause(self):
|
||||
sound.pause(self.id)
|
||||
|
||||
def unpause(self):
|
||||
sound.pause(self.id)
|
||||
|
||||
def fadeout(self, time):
|
||||
# No fadeout
|
||||
self.stop()
|
||||
|
||||
def set_volume(self, left, right=None):
|
||||
sound.set_volume(self.id, left)
|
||||
|
||||
def get_volume(self):
|
||||
return sound.get_volume(self.id)
|
||||
|
||||
def get_busy(self):
|
||||
return sound.busy(self.id)
|
||||
|
||||
def get_sound(self):
|
||||
is_busy = sound.busy(self.id)
|
||||
if not is_busy:
|
||||
return
|
||||
serial = sound.playing_name(self.id)
|
||||
if not serial:
|
||||
return
|
||||
return sounds.get(serial, None)
|
||||
|
||||
def queue(self, s):
|
||||
self.loop = None
|
||||
self.queued = s
|
||||
|
||||
sound.queue(self.id, s.what, s.serial)
|
||||
|
||||
with condition:
|
||||
condition.notify()
|
||||
|
||||
def get_queue(self):
|
||||
return self.queued
|
||||
|
||||
def get_pos(self):
|
||||
return sound.get_pos(self.id)/1000.
|
||||
|
||||
def get_length(self):
|
||||
return sound.get_length(self.id)/1000.
|
||||
|
||||
|
||||
def Channel(n):
|
||||
"""
|
||||
Gets the channel with the given number.
|
||||
"""
|
||||
|
||||
rv = channels.get(n, None)
|
||||
if rv is None:
|
||||
rv = ChannelImpl(n)
|
||||
channels[n] = rv
|
||||
|
||||
return rv
|
||||
|
||||
|
||||
sound_serial = 0
|
||||
sounds = { }
|
||||
|
||||
class Sound(object):
|
||||
|
||||
def __init__(self, what):
|
||||
|
||||
# Doesn't support buffers.
|
||||
|
||||
global sound_serial
|
||||
|
||||
self._channel = None
|
||||
self._volume = 1.
|
||||
self.serial = str(sound_serial)
|
||||
sound_serial += 1
|
||||
|
||||
if isinstance(what, file):
|
||||
self.file = what
|
||||
else:
|
||||
self.file = file(os.path.abspath(what), "rb")
|
||||
|
||||
sounds[self.serial] = self
|
||||
|
||||
def play(self, loops=0, maxtime=0, fade_ms=0):
|
||||
# avoid new play if the sound is already playing
|
||||
# -> same behavior as standard pygame.
|
||||
if self._channel is not None:
|
||||
if self._channel.get_sound() is self:
|
||||
return
|
||||
self._channel = channel = find_channel(True)
|
||||
channel.set_volume(self._volume)
|
||||
channel.play(self, loops=loops)
|
||||
return channel
|
||||
|
||||
|
||||
def stop(self):
|
||||
for i in range(0, num_channels):
|
||||
if Channel(i).get_sound() is self:
|
||||
Channel(i).stop()
|
||||
|
||||
def fadeout(self, time):
|
||||
self.stop()
|
||||
|
||||
def set_volume(self, left, right=None):
|
||||
self._volume = left
|
||||
if self._channel:
|
||||
if self._channel.get_sound() is self:
|
||||
self._channel.set_volume(self._volume)
|
||||
|
||||
def get_volume(self):
|
||||
return self._volume
|
||||
|
||||
def get_num_channels(self):
|
||||
rv = 0
|
||||
|
||||
for i in range(0, num_channels):
|
||||
if Channel(i).get_sound() is self:
|
||||
rv += 1
|
||||
|
||||
return rv
|
||||
|
||||
def get_length(self):
|
||||
return 1.0
|
||||
|
||||
music_channel = Channel(256)
|
||||
music_sound = None
|
||||
|
||||
class music(object):
|
||||
|
||||
@staticmethod
|
||||
def load(filename):
|
||||
|
||||
music_channel.stop()
|
||||
|
||||
global music_sound
|
||||
music_sound = Sound(filename)
|
||||
|
||||
@staticmethod
|
||||
def play(loops=0, start=0.0):
|
||||
# No start.
|
||||
|
||||
music_channel.play(music_sound, loops=loops)
|
||||
|
||||
@staticmethod
|
||||
def rewind():
|
||||
music_channel.play(music_sound)
|
||||
|
||||
@staticmethod
|
||||
def seek(position):
|
||||
music_channel.seek(position)
|
||||
|
||||
@staticmethod
|
||||
def stop():
|
||||
music_channel.stop()
|
||||
|
||||
@staticmethod
|
||||
def pause():
|
||||
music_channel.pause()
|
||||
|
||||
@staticmethod
|
||||
def unpause():
|
||||
music_channel.unpause()
|
||||
|
||||
@staticmethod
|
||||
def fadeout(time):
|
||||
music_channel.fadeout(time)
|
||||
|
||||
@staticmethod
|
||||
def set_volume(value):
|
||||
music_channel.set_volume(value)
|
||||
|
||||
@staticmethod
|
||||
def get_volume():
|
||||
return music_channel.get_volume()
|
||||
|
||||
@staticmethod
|
||||
def get_busy():
|
||||
return music_channel.get_busy()
|
||||
|
||||
@staticmethod
|
||||
def get_pos():
|
||||
return music_channel.get_pos()
|
||||
|
||||
@staticmethod
|
||||
def queue(filename):
|
||||
return music_channel.queue(Sound(filename))
|
||||
|
||||
|
||||
|
48
MovedRecipes/android/src/android/runnable.py
Normal file
48
MovedRecipes/android/src/android/runnable.py
Normal file
|
@ -0,0 +1,48 @@
|
|||
'''
|
||||
Runnable
|
||||
========
|
||||
|
||||
'''
|
||||
|
||||
from jnius import PythonJavaClass, java_method, autoclass
|
||||
from android.config import JAVA_NAMESPACE
|
||||
|
||||
# reference to the activity
|
||||
_PythonActivity = autoclass(JAVA_NAMESPACE + '.PythonActivity')
|
||||
|
||||
|
||||
class Runnable(PythonJavaClass):
|
||||
'''Wrapper around Java Runnable class. This class can be used to schedule a
|
||||
call of a Python function into the PythonActivity thread.
|
||||
'''
|
||||
|
||||
__javainterfaces__ = ['java/lang/Runnable']
|
||||
__runnables__ = []
|
||||
|
||||
def __init__(self, func):
|
||||
super(Runnable, self).__init__()
|
||||
self.func = func
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
Runnable.__runnables__.append(self)
|
||||
_PythonActivity.mActivity.runOnUiThread(self)
|
||||
|
||||
@java_method('()V')
|
||||
def run(self):
|
||||
try:
|
||||
self.func(*self.args, **self.kwargs)
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
Runnable.__runnables__.remove(self)
|
||||
|
||||
def run_on_ui_thread(f):
|
||||
'''Decorator to create automatically a :class:`Runnable` object with the
|
||||
function. The function will be delayed and call into the Activity thread.
|
||||
'''
|
||||
def f2(*args, **kwargs):
|
||||
Runnable(f)(*args, **kwargs)
|
||||
return f2
|
34
MovedRecipes/android/src/setup.py
Executable file
34
MovedRecipes/android/src/setup.py
Executable file
|
@ -0,0 +1,34 @@
|
|||
from distutils.core import setup, Extension
|
||||
import os
|
||||
|
||||
library_dirs = ['libs/' + os.environ['ARCH']]
|
||||
lib_dict = {
|
||||
'pygame': ['sdl'],
|
||||
'sdl2': ['SDL2', 'SDL2_image', 'SDL2_mixer', 'SDL2_ttf']
|
||||
}
|
||||
sdl_libs = lib_dict[os.environ['BOOTSTRAP']] if os.environ['BOOTSTRAP'] == 'sdl2' else []
|
||||
|
||||
renpy_sound = Extension('android._android_sound',
|
||||
['android/_android_sound.c', 'android/_android_sound_jni.c', ],
|
||||
libraries=sdl_libs + ['log'],
|
||||
library_dirs=library_dirs)
|
||||
|
||||
modules = [Extension('android._android',
|
||||
['android/_android.c', 'android/_android_jni.c'],
|
||||
libraries=sdl_libs + ['log'],
|
||||
library_dirs=library_dirs),
|
||||
Extension('android._android_billing',
|
||||
['android/_android_billing.c', 'android/_android_billing_jni.c'],
|
||||
libraries=['log'],
|
||||
library_dirs=library_dirs)]
|
||||
|
||||
if int(os.environ['IS_PYGAME']):
|
||||
modules.append(renpy_sound)
|
||||
|
||||
|
||||
setup(name='android',
|
||||
version='1.0',
|
||||
packages=['android'],
|
||||
package_dir={'android': 'android'},
|
||||
ext_modules=modules
|
||||
)
|
|
@ -8,7 +8,7 @@ class CffiRecipe(CompiledComponentsPythonRecipe):
|
|||
version = '1.14.6'
|
||||
url = 'https://pypi.python.org/packages/source/c/cffi/cffi-{version}.tar.gz'
|
||||
|
||||
depends = [('python2', 'python3crystax'), 'setuptools', 'pycparser', 'libffi']
|
||||
depends = [('python2', 'python3'), 'setuptools', 'pycparser', 'libffi']
|
||||
|
||||
patches = ['disable-pkg-config.patch']
|
||||
|
||||
|
@ -43,16 +43,16 @@ class CffiRecipe(CompiledComponentsPythonRecipe):
|
|||
self.ctx.get_site_packages_dir(),
|
||||
env['BUILDLIB_PATH'],
|
||||
])
|
||||
if self.ctx.ndk == 'crystax':
|
||||
# only keeps major.minor (discards patch)
|
||||
python_version = self.ctx.python_recipe.version[0:3]
|
||||
ndk_dir_python = os.path.join(self.ctx.ndk_dir, 'sources/python/', python_version)
|
||||
env['LDFLAGS'] += ' -L{}'.format(os.path.join(ndk_dir_python, 'libs', arch.arch))
|
||||
env['LDFLAGS'] += ' -lpython{}'.format(python_version)
|
||||
# until `pythonforandroid/archs.py` gets merged upstream:
|
||||
# https://github.com/kivy/python-for-android/pull/1250/files#diff-569e13021e33ced8b54385f55b49cbe6
|
||||
env['CFLAGS'] += ' -I{}/include/python/'.format(ndk_dir_python)
|
||||
return env
|
||||
# if self.ctx.ndk == 'crystax':
|
||||
# # only keeps major.minor (discards patch)
|
||||
# python_version = self.ctx.python_recipe.version[0:3]
|
||||
# ndk_dir_python = os.path.join(self.ctx.ndk_dir, 'sources/python/', python_version)
|
||||
# env['LDFLAGS'] += ' -L{}'.format(os.path.join(ndk_dir_python, 'libs', arch.arch))
|
||||
# env['LDFLAGS'] += ' -lpython{}'.format(python_version)
|
||||
# # until `pythonforandroid/archs.py` gets merged upstream:
|
||||
# # https://github.com/kivy/python-for-android/pull/1250/files#diff-569e13021e33ced8b54385f55b49cbe6
|
||||
# env['CFLAGS'] += ' -I{}/include/python/'.format(ndk_dir_python)
|
||||
# return env
|
||||
|
||||
|
||||
recipe = CffiRecipe()
|
74
MovedRecipes/coincurve/__init__.py
Normal file
74
MovedRecipes/coincurve/__init__.py
Normal file
|
@ -0,0 +1,74 @@
|
|||
import os
|
||||
from pythonforandroid.recipe import PythonRecipe, CompiledComponentsPythonRecipe
|
||||
|
||||
|
||||
class CoincurveRecipe(CompiledComponentsPythonRecipe):
|
||||
# version = '15.0.0'
|
||||
# url = 'https://github.com/ofek/coincurve/archive/{version}.tar.gz'
|
||||
# call_hostpython_via_targetpython = False
|
||||
# depends = ['setuptools',
|
||||
# 'libffi', 'cffi', 'libsecp256k1']
|
||||
# patches = [
|
||||
# "cross_compile.patch", "drop_setup_requires.patch",
|
||||
# "find_lib.patch", "no-download.patch", "setup.py.patch"]
|
||||
#
|
||||
# def get_recipe_env(self, arch=None, with_flags_in_cc=True):
|
||||
# env = super().get_recipe_env(arch, with_flags_in_cc)
|
||||
# # sets linker to use the correct gcc (cross compiler)
|
||||
# env['LDSHARED'] = env['CC'] + ' -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions'
|
||||
# libsecp256k1 = self.get_recipe('libsecp256k1', self.ctx)
|
||||
# libsecp256k1_dir = libsecp256k1.get_build_dir(arch.arch)
|
||||
# env['LDFLAGS'] += ' -L{}'.format(os.path.join(libsecp256k1_dir, '.libs'))
|
||||
# env['CFLAGS'] += ' -I' + os.path.join(libsecp256k1_dir, 'include')
|
||||
# # only keeps major.minor (discards patch)
|
||||
# python_version = self.ctx.python_recipe.version[0:3]
|
||||
# # required additional library and path for Crystax
|
||||
# if self.ctx.ndk == 'crystax':
|
||||
# ndk_dir_python = os.path.join(self.ctx.ndk_dir, 'sources/python/', python_version)
|
||||
# env['LDFLAGS'] += ' -L{}'.format(os.path.join(ndk_dir_python, 'libs', arch.arch))
|
||||
# env['LDFLAGS'] += ' -lpython{}'.format(python_version)
|
||||
# # until `pythonforandroid/archs.py` gets merged upstream:
|
||||
# # https://github.com/kivy/python-for-android/pull/1250/files#diff-569e13021e33ced8b54385f55b49cbe6
|
||||
# env['CFLAGS'] += ' -I{}/include/python/'.format(ndk_dir_python)
|
||||
# else:
|
||||
# env['PYTHON_ROOT'] = self.ctx.get_python_install_dir(arch.arch)
|
||||
# env['CFLAGS'] += ' -I' + env['PYTHON_ROOT'] + '/include/python{}'.format(python_version)
|
||||
# env['LDFLAGS'] += " -lpython{}".format(python_version)
|
||||
# env['LDFLAGS'] += " -lsecp256k1"
|
||||
# return env
|
||||
version = 'v15.0.1'
|
||||
url = 'https://github.com/ofek/coincurve/archive/refs/tags/v15.0.1.tar.gz'
|
||||
call_hostpython_via_targetpython = False
|
||||
depends = [('python2', 'python3'), 'setuptools',
|
||||
'libffi', 'cffi', 'libsecp256k1']
|
||||
patches = [
|
||||
"cross_compile.patch", "drop_setup_requires.patch",
|
||||
"find_lib.patch", "no-download.patch", "setup.py.patch"]
|
||||
|
||||
def get_recipe_env(self, arch=None, with_flags_in_cc=True):
|
||||
env = super().get_recipe_env(arch, with_flags_in_cc)
|
||||
# sets linker to use the correct gcc (cross compiler)
|
||||
env['LDSHARED'] = env['CC'] + ' -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions'
|
||||
libsecp256k1 = self.get_recipe('libsecp256k1', self.ctx)
|
||||
libsecp256k1_dir = libsecp256k1.get_build_dir(arch.arch)
|
||||
env['LDFLAGS'] += ' -L{}'.format(os.path.join(libsecp256k1_dir, '.libs'))
|
||||
env['CFLAGS'] += ' -I' + os.path.join(libsecp256k1_dir, 'include')
|
||||
# only keeps major.minor (discards patch)
|
||||
python_version = self.ctx.python_recipe.version[0:3]
|
||||
# required additional library and path for Crystax
|
||||
# if self.ctx.ndk == 'crystax':
|
||||
# ndk_dir_python = os.path.join(self.ctx.ndk_dir, 'sources/python/', python_version)
|
||||
# env['LDFLAGS'] += ' -L{}'.format(os.path.join(ndk_dir_python, 'libs', arch.arch))
|
||||
# env['LDFLAGS'] += ' -lpython{}m'.format(python_version)
|
||||
# # until `pythonforandroid/archs.py` gets merged upstream:
|
||||
# # https://github.com/kivy/python-for-android/pull/1250/files#diff-569e13021e33ced8b54385f55b49cbe6
|
||||
# env['CFLAGS'] += ' -I{}/include/python/'.format(ndk_dir_python)
|
||||
# else:
|
||||
env['PYTHON_ROOT'] = self.ctx.get_python_install_dir(arch.arch)
|
||||
env['CFLAGS'] += ' -I' + env['PYTHON_ROOT'] + '/include/python{}'.format(python_version)
|
||||
env['LDFLAGS'] += " -lpython{}".format(python_version)
|
||||
env['LDFLAGS'] += " -lsecp256k1"
|
||||
return env
|
||||
|
||||
|
||||
recipe = CoincurveRecipe()
|
12
MovedRecipes/coincurve/cross_compile.patch
Normal file
12
MovedRecipes/coincurve/cross_compile.patch
Normal file
|
@ -0,0 +1,12 @@
|
|||
diff --git a/setup.py b/setup.py
|
||||
index c224fb2..bf925bd 100644
|
||||
--- a/setup.py
|
||||
+++ b/setup.py
|
||||
@@ -182,6 +182,7 @@ class build_clib(_build_clib):
|
||||
'--disable-dependency-tracking',
|
||||
'--with-pic',
|
||||
'--enable-module-recovery',
|
||||
+ "--host=%s" % os.environ['TOOLCHAIN_PREFIX'],
|
||||
'--disable-jni',
|
||||
'--prefix',
|
||||
os.path.abspath(self.build_clib),
|
12
MovedRecipes/coincurve/drop_setup_requires.patch
Normal file
12
MovedRecipes/coincurve/drop_setup_requires.patch
Normal file
|
@ -0,0 +1,12 @@
|
|||
diff --git a/setup.py b/setup.py
|
||||
index c224fb2..466e789 100644
|
||||
--- a/setup.py
|
||||
+++ b/setup.py
|
||||
@@ -250,7 +250,6 @@ else:
|
||||
def has_c_libraries(self):
|
||||
return not has_system_lib()
|
||||
setup_kwargs = dict(
|
||||
- setup_requires=['cffi>=1.3.0', 'pytest-runner>=2.6.2'],
|
||||
ext_package='coincurve',
|
||||
cffi_modules=['_cffi_build/build.py:ffi'],
|
||||
cmdclass={
|
13
MovedRecipes/coincurve/find_lib.patch
Normal file
13
MovedRecipes/coincurve/find_lib.patch
Normal file
|
@ -0,0 +1,13 @@
|
|||
diff --git a/setup_support.py b/setup_support.py
|
||||
index e7a4f2e..72f0c4d 100644
|
||||
--- a/setup_support.py
|
||||
+++ b/setup_support.py
|
||||
@@ -68,6 +69,8 @@ def build_flags(library, type_, path):
|
||||
|
||||
|
||||
def _find_lib():
|
||||
+ # we're picking up the recipe one
|
||||
+ return True
|
||||
from cffi import FFI
|
||||
ffi = FFI()
|
||||
try:
|
13
MovedRecipes/coincurve/no-download.patch
Normal file
13
MovedRecipes/coincurve/no-download.patch
Normal file
|
@ -0,0 +1,13 @@
|
|||
diff --git a/setup.py b/setup.py
|
||||
index c224fb2..d5f6d1a 100644
|
||||
--- a/setup.py
|
||||
+++ b/setup.py
|
||||
@@ -51,6 +51,8 @@ if [int(i) for i in setuptools_version.split('.', 2)[:2]] < [3, 3]:
|
||||
|
||||
|
||||
def download_library(command):
|
||||
+ # we will use the custom libsecp256k1 recipe
|
||||
+ return
|
||||
if command.dry_run:
|
||||
return
|
||||
libdir = absolute('libsecp256k1')
|
0
MovedRecipes/python3crystax/libffi/__init__.py
Normal file
0
MovedRecipes/python3crystax/libffi/__init__.py
Normal file
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue