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:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [master]
|
branches: [master, upgrade_p4a]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build_arm64_aar:
|
build_arm64_aar:
|
||||||
|
@ -16,20 +16,14 @@ jobs:
|
||||||
cp -r /root/.buildozer ~/.buildozer/
|
cp -r /root/.buildozer ~/.buildozer/
|
||||||
- name: setup
|
- name: setup
|
||||||
run: |
|
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]+\.?)+')
|
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 "NEXUS_SIGNING_KEYRING_FILE=$GITHUB_WORKSPACE/signing2.pgp" >> $GITHUB_ENV
|
||||||
echo "BUILD_VERSION=${B_VERSION}" >> $GITHUB_ENV
|
echo "BUILD_VERSION=${B_VERSION}" >> $GITHUB_ENV
|
||||||
export PATH=/usr/bin:$PATH
|
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/
|
wget -q 'https://dl.google.com/android/repository/android-ndk-r25b-linux.zip' -P ~/.buildozer/android/
|
||||||
tar -xf ~/.buildozer/android/crystax-ndk-10.3.2-linux-x86_64.tar.xz -C ~/.buildozer/android/
|
unzip ~/.buildozer/android/android-ndk-r25b-linux.zip -d ~/.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
|
|
||||||
mv buildozer.spec.arm64.ci buildozer.spec
|
mv buildozer.spec.arm64.ci buildozer.spec
|
||||||
chmod u+x ./build-release.sh
|
chmod u+x ./build-release.sh
|
||||||
- name: build release
|
- name: build release
|
||||||
|
@ -77,6 +71,7 @@ jobs:
|
||||||
echo "NEXUS_SIGNING_KEYRING_FILE=$GITHUB_WORKSPACE/signing2.pgp" >> $GITHUB_ENV
|
echo "NEXUS_SIGNING_KEYRING_FILE=$GITHUB_WORKSPACE/signing2.pgp" >> $GITHUB_ENV
|
||||||
export PATH=/usr/bin:$PATH
|
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/
|
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/
|
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
|
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
|
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/*.apk
|
||||||
p4a/*.aar
|
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'
|
version = '1.14.6'
|
||||||
url = 'https://pypi.python.org/packages/source/c/cffi/cffi-{version}.tar.gz'
|
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']
|
patches = ['disable-pkg-config.patch']
|
||||||
|
|
||||||
|
@ -43,16 +43,16 @@ class CffiRecipe(CompiledComponentsPythonRecipe):
|
||||||
self.ctx.get_site_packages_dir(),
|
self.ctx.get_site_packages_dir(),
|
||||||
env['BUILDLIB_PATH'],
|
env['BUILDLIB_PATH'],
|
||||||
])
|
])
|
||||||
if self.ctx.ndk == 'crystax':
|
# if self.ctx.ndk == 'crystax':
|
||||||
# only keeps major.minor (discards patch)
|
# # only keeps major.minor (discards patch)
|
||||||
python_version = self.ctx.python_recipe.version[0:3]
|
# python_version = self.ctx.python_recipe.version[0:3]
|
||||||
ndk_dir_python = os.path.join(self.ctx.ndk_dir, 'sources/python/', python_version)
|
# 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'] += ' -L{}'.format(os.path.join(ndk_dir_python, 'libs', arch.arch))
|
||||||
env['LDFLAGS'] += ' -lpython{}'.format(python_version)
|
# env['LDFLAGS'] += ' -lpython{}'.format(python_version)
|
||||||
# until `pythonforandroid/archs.py` gets merged upstream:
|
# # until `pythonforandroid/archs.py` gets merged upstream:
|
||||||
# https://github.com/kivy/python-for-android/pull/1250/files#diff-569e13021e33ced8b54385f55b49cbe6
|
# # https://github.com/kivy/python-for-android/pull/1250/files#diff-569e13021e33ced8b54385f55b49cbe6
|
||||||
env['CFLAGS'] += ' -I{}/include/python/'.format(ndk_dir_python)
|
# env['CFLAGS'] += ' -I{}/include/python/'.format(ndk_dir_python)
|
||||||
return env
|
# return env
|
||||||
|
|
||||||
|
|
||||||
recipe = CffiRecipe()
|
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