diff --git a/kivyblocks/version.py b/kivyblocks/version.py index 30b1088..28220e3 100644 --- a/kivyblocks/version.py +++ b/kivyblocks/version.py @@ -11,4 +11,6 @@ # move code using pyaudio to a independent module # __version__ = '0.2.13' # use json replace ujson because kivy-ios can not compile ujson -__version__ = '0.2.14' +# __version__ = '0.2.14' +# delete xcamera module +__version__ = '0.2.15' diff --git a/kivyblocks/xcamera/__init__.py b/kivyblocks/xcamera/__init__.py deleted file mode 100644 index 019bbb0..0000000 --- a/kivyblocks/xcamera/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -""" -Exposes `XCamera` directly in `xcamera` rather than `xcamera.xcamera`. -Also note this may break `pip` since all imports within `xcamera.py` would be -required at setup time. This is because `version.py` (same directory) is used -by the `setup.py` file. -Hence we're not exposing `XCamera` if `pip` is detected. -""" -import os - -project_dir = os.path.abspath( - os.path.join(__file__, os.pardir, os.pardir, os.pardir, os.pardir)) -using_pip = os.path.basename(project_dir).startswith('pip-') -# only exposes `XCamera` if not within `pip` ongoing install -if not using_pip: - from .xcamera import XCamera # noqa diff --git a/kivyblocks/xcamera/android_api.py b/kivyblocks/xcamera/android_api.py deleted file mode 100644 index 30a2aef..0000000 --- a/kivyblocks/xcamera/android_api.py +++ /dev/null @@ -1,85 +0,0 @@ -from kivy.logger import Logger - -from jnius import JavaException, PythonJavaClass, autoclass, java_method - -Camera = autoclass('android.hardware.Camera') -AndroidActivityInfo = autoclass('android.content.pm.ActivityInfo') -AndroidPythonActivity = autoclass('org.kivy.android.PythonActivity') -PORTRAIT = AndroidActivityInfo.SCREEN_ORIENTATION_PORTRAIT -LANDSCAPE = AndroidActivityInfo.SCREEN_ORIENTATION_LANDSCAPE - - -class ShutterCallback(PythonJavaClass): - __javainterfaces__ = ('android.hardware.Camera$ShutterCallback', ) - - @java_method('()V') - def onShutter(self): - # apparently, it is enough to have an empty shutter callback to play - # the standard shutter sound. If you pass None instead of shutter_cb - # below, the standard sound doesn't play O_o - pass - - -class PictureCallback(PythonJavaClass): - __javainterfaces__ = ('android.hardware.Camera$PictureCallback', ) - - def __init__(self, filename, on_success): - super(PictureCallback, self).__init__() - self.filename = filename - self.on_success = on_success - - @java_method('([BLandroid/hardware/Camera;)V') - def onPictureTaken(self, data, camera): - s = data.tostring() - with open(self.filename, 'wb') as f: - f.write(s) - Logger.info('xcamera: picture saved to %s', self.filename) - camera.startPreview() - self.on_success(self.filename) - - -class AutoFocusCallback(PythonJavaClass): - __javainterfaces__ = ('android.hardware.Camera$AutoFocusCallback', ) - - def __init__(self, filename, on_success): - super(AutoFocusCallback, self).__init__() - self.filename = filename - self.on_success = on_success - - @java_method('(ZLandroid/hardware/Camera;)V') - def onAutoFocus(self, success, camera): - if success: - Logger.info('xcamera: autofocus succeeded, taking picture...') - shutter_cb = ShutterCallback() - picture_cb = PictureCallback(self.filename, self.on_success) - camera.takePicture(shutter_cb, None, picture_cb) - else: - Logger.info('xcamera: autofocus failed') - - -def take_picture(camera_widget, filename, on_success): - # to call the android API, we need access to the underlying - # android.hardware.Camera instance. However, there is no official way to - # retrieve it from the camera widget, so we need to dig into internal - # attributes :-( This works at least on kivy 1.9.1, but it might break any - # time soon. - camera = camera_widget._camera._android_camera - params = camera.getParameters() - params.setFocusMode("auto") - camera.setParameters(params) - cb = AutoFocusCallback(filename, on_success) - Logger.info('xcamera: starting autofocus...') - try: - camera.autoFocus(cb) - except JavaException as e: - Logger.info('Error when calling autofocus: {}'.format(e)) - - -def set_orientation(value): - previous = get_orientation() - AndroidPythonActivity.mActivity.setRequestedOrientation(value) - return previous - - -def get_orientation(): - return AndroidPythonActivity.mActivity.getRequestedOrientation() diff --git a/kivyblocks/xcamera/data/icons.ttf b/kivyblocks/xcamera/data/icons.ttf deleted file mode 100644 index 1eae4aa..0000000 Binary files a/kivyblocks/xcamera/data/icons.ttf and /dev/null differ diff --git a/kivyblocks/xcamera/data/shutter.wav b/kivyblocks/xcamera/data/shutter.wav deleted file mode 100644 index 66d4380..0000000 Binary files a/kivyblocks/xcamera/data/shutter.wav and /dev/null differ diff --git a/kivyblocks/xcamera/main.py b/kivyblocks/xcamera/main.py deleted file mode 100644 index 35c094c..0000000 --- a/kivyblocks/xcamera/main.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python -from kivy.app import App -from kivy.lang import Builder - -kv = """ -#:import XCamera kivy_garden.xcamera.XCamera - -FloatLayout: - orientation: 'vertical' - - XCamera: - id: xcamera - on_picture_taken: app.picture_taken(*args) - - BoxLayout: - orientation: 'horizontal' - size_hint: 1, None - height: sp(50) - - Button: - text: 'Set landscape' - on_release: xcamera.force_landscape() - - Button: - text: 'Restore orientation' - on_release: xcamera.restore_orientation() -""" - - -class CameraApp(App): - def build(self): - return Builder.load_string(kv) - - def picture_taken(self, obj, filename): - print('Picture taken and saved to {}'.format(filename)) - - -def main(): - CameraApp().run() - - -if __name__ == '__main__': - main() diff --git a/kivyblocks/xcamera/platform_api.py b/kivyblocks/xcamera/platform_api.py deleted file mode 100644 index fa79f8f..0000000 --- a/kivyblocks/xcamera/platform_api.py +++ /dev/null @@ -1,37 +0,0 @@ -from kivy.utils import platform - - -def play_shutter(): - # bah, apparently we need to delay the import of kivy.core.audio, lese - # kivy cannot find a camera provider, at lease on linux. Maybe a - # gstreamer/pygame issue? - from kivy.core.audio import SoundLoader - sound = SoundLoader.load("data/shutter.wav") - sound.play() - - -if platform == 'android': - from .android_api import ( - LANDSCAPE, PORTRAIT, take_picture, set_orientation, get_orientation) - -else: - - # generic fallback for taking pictures. Probably not the best quality, - # they are meant mostly for testing - LANDSCAPE = 'landscape' - PORTRAIT = 'portrait' - - def take_picture(camera_widget, filename, on_success): - camera_widget.texture.save(filename, flipped=False) - play_shutter() - on_success(filename) - - def set_orientation(value): - previous = get_orientation() - print('FAKE orientation set to {}'.format(value)) - get_orientation.value = value - return previous - - def get_orientation(): - return get_orientation.value - get_orientation.value = PORTRAIT diff --git a/kivyblocks/xcamera/version.py b/kivyblocks/xcamera/version.py deleted file mode 100644 index 809d46f..0000000 --- a/kivyblocks/xcamera/version.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = '2020.0613' diff --git a/kivyblocks/xcamera/xcamera.kv b/kivyblocks/xcamera/xcamera.kv deleted file mode 100644 index 064d280..0000000 --- a/kivyblocks/xcamera/xcamera.kv +++ /dev/null @@ -1,41 +0,0 @@ -#:import xcamera kivyblocks.xcamera.xcamera - - - icon_color: (0, 0, 0, 1) - _down_color: xcamera.darker(self.icon_color) - icon_size: dp(50) - - canvas.before: - Color: - rgba: self.icon_color if self.state == 'normal' else self._down_color - Ellipse: - pos: self.pos - size: self.size - - size_hint: None, None - size: self.icon_size, self.icon_size - font_size: self.icon_size/2 - - -: - # \ue800 corresponds to the camera icon in the font - icon: u"[font=data/icons.ttf]\ue800[/font]" - icon_color: (0.13, 0.58, 0.95, 0.8) - icon_size: dp(70) - - id: camera - resolution: 640, 480 # 1920, 1080 - allow_stretch: True - - # Shoot button - XCameraIconButton: - id: shoot_button - markup: True - text: root.icon - icon_color: root.icon_color - icon_size: root.icon_size - on_release: root.shoot() - - # position - right: root.width - dp(10) - center_y: root.center_y diff --git a/kivyblocks/xcamera/xcamera.py b/kivyblocks/xcamera/xcamera.py deleted file mode 100644 index e350fc0..0000000 --- a/kivyblocks/xcamera/xcamera.py +++ /dev/null @@ -1,116 +0,0 @@ -import datetime -import os - -from kivy.clock import mainthread -from kivy.lang import Builder -from kivy.properties import ObjectProperty -from kivy.resources import resource_add_path -from kivy.uix.behaviors import ButtonBehavior -from kivy.uix.camera import Camera -from kivy.uix.label import Label -from kivy.utils import platform - -from .platform_api import LANDSCAPE, set_orientation, take_picture - -ROOT = os.path.dirname(os.path.abspath(__file__)) -resource_add_path(ROOT) - - -def darker(color, factor=0.5): - r, g, b, a = color - r *= factor - g *= factor - b *= factor - return r, g, b, a - - -def get_filename(): - return datetime.datetime.now().strftime('%Y-%m-%d %H.%M.%S.jpg') - - -def is_android(): - return platform == 'android' - - -def check_camera_permission(): - """ - Android runtime `CAMERA` permission check. - """ - if not is_android(): - return True - from android.permissions import Permission, check_permission - permission = Permission.CAMERA - return check_permission(permission) - - -def check_request_camera_permission(callback=None): - """ - Android runtime `CAMERA` permission check & request. - """ - had_permission = check_camera_permission() - if not had_permission: - from android.permissions import Permission, request_permissions - permissions = [Permission.CAMERA] - request_permissions(permissions, callback) - return had_permission - - -class XCameraIconButton(ButtonBehavior, Label): - pass - - -class XCamera(Camera): - directory = ObjectProperty(None) - _previous_orientation = None - __events__ = ('on_picture_taken', 'on_camera_ready') - - def __init__(self, **kwargs): - # Builder.load_file(os.path.join(ROOT, "xcamera.kv")) - super().__init__(**kwargs) - - def _on_index(self, *largs): - """ - Overrides `kivy.uix.camera.Camera._on_index()` to make sure - `camera.open()` is not called unless Android `CAMERA` permission is - granted, refs #5. - """ - @mainthread - def on_permissions_callback(permissions, grant_results): - """ - On camera permission callback calls parent `_on_index()` method. - """ - if all(grant_results): - self._on_index_dispatch(*largs) - if check_request_camera_permission(callback=on_permissions_callback): - self._on_index_dispatch(*largs) - - def _on_index_dispatch(self, *largs): - super()._on_index(*largs) - self.dispatch('on_camera_ready') - - def on_picture_taken(self, filename): - """ - This event is fired every time a picture has been taken. - """ - pass - - def on_camera_ready(self): - """ - Fired when the camera is ready. - """ - pass - - def shoot(self): - def on_success(filename): - self.dispatch('on_picture_taken', filename) - filename = get_filename() - if self.directory: - filename = os.path.join(self.directory, filename) - take_picture(self, filename, on_success) - - def force_landscape(self): - self._previous_orientation = set_orientation(LANDSCAPE) - - def restore_orientation(self): - if self._previous_orientation is not None: - set_orientation(self._previous_orientation)