Mercurial > libervia-desktop-kivy
changeset 95:3e3c097b07b7
upload: added voice plugin (for Android)
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 27 Dec 2016 21:54:09 +0100 |
parents | b94967b7ebfd |
children | 641678ddc26c |
files | src/buildozer.spec src/cagou/plugins/plugin_upload_android_photo.py src/cagou/plugins/plugin_upload_android_video.py src/cagou/plugins/plugin_upload_voice.kv src/cagou/plugins/plugin_upload_voice.py |
diffstat | 5 files changed, 184 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/src/buildozer.spec Mon Dec 26 20:34:58 2016 +0100 +++ b/src/buildozer.spec Tue Dec 27 21:54:09 2016 +0100 @@ -74,7 +74,7 @@ fullscreen = 1 # (list) Permissions -android.permissions = INTERNET, ACCESS_NETWORK_STATE, VIBRATE +android.permissions = INTERNET, ACCESS_NETWORK_STATE, VIBRATE, RECORD_AUDIO # (int) Android API to use #android.api = 19
--- a/src/cagou/plugins/plugin_upload_android_photo.py Mon Dec 26 20:34:58 2016 +0100 +++ b/src/cagou/plugins/plugin_upload_android_photo.py Tue Dec 27 21:54:09 2016 +0100 @@ -25,8 +25,8 @@ import os import os.path import time -from plyer import camera if sys.platform == "android": + from plyer import camera from jnius import autoclass Environment = autoclass('android.os.Environment') else:
--- a/src/cagou/plugins/plugin_upload_android_video.py Mon Dec 26 20:34:58 2016 +0100 +++ b/src/cagou/plugins/plugin_upload_android_video.py Tue Dec 27 21:54:09 2016 +0100 @@ -25,8 +25,8 @@ import os import os.path import time -from plyer import camera if sys.platform == "android": + from plyer import camera from jnius import autoclass Environment = autoclass('android.os.Environment') else:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cagou/plugins/plugin_upload_voice.kv Tue Dec 27 21:54:09 2016 +0100 @@ -0,0 +1,71 @@ +# Cagou: desktop/mobile frontend for Salut à Toi XMPP client +# Copyright (C) 2016 Jérôme Poisson (goffi@goffi.org) + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +#:import _ sat.core.i18n._ +#:import IconButton cagou.core.common.IconButton + + +<VoiceRecorder>: + orientation: "vertical" + counter: counter + Label: + size_hint: 1, 0.4 + text_size: self.size + halign: 'center' + valign: 'top' + text: _(u"Push the microphone button to start the record, then push it again to stop it.\nWhen you are satisfied, click on the upload button") + Label: + id: counter + size_hint: 1, None + height: dp(60) + bold: True + font_size: sp(40) + text_size: self.size + text: u"{}:{:02}".format(root.time/60, root.time%60) + halign: 'center' + valign: 'middle' + BoxLayout: + size_hint: 1, None + height: dp(60) + Widget + IconButton: + source: app.expand("{media}/icons/muchoslava/png/") + ("micro_on_50.png" if root.recording else "micro_off_50.png") + allow_stretch: True + size_hint: None, None + size: dp(60), dp(60) + on_release: root.switchRecording() + IconButton: + opacity: 0 if root.recording or not root.time and not root.playing else 1 + source: app.expand("{media}/icons/muchoslava/png/") + ("stop_50.png" if root.playing else "play_50.png") + allow_stretch: True + size_hint: None, None + size: dp(60), dp(60) + on_release: root.playRecord() + Widget + Widget: + size_hint: 1, None + height: dp(50) + Button: + text: "upload" + size_hint: 1, None + height: dp(50) + on_release: root.callback(root.audio.file_path) + Button: + text: "cancel" + size_hint: 1, None + height: dp(50) + on_release: root.cancel_cb(root) + Widget
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cagou/plugins/plugin_upload_voice.py Tue Dec 27 21:54:09 2016 +0100 @@ -0,0 +1,110 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Cagou: desktop/mobile frontend for Salut à Toi XMPP client +# Copyright (C) 2016 Jérôme Poisson (goffi@goffi.org) + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +from sat.core import log as logging +log = logging.getLogger(__name__) +from sat.core.i18n import _ +from kivy.uix.boxlayout import BoxLayout +import sys +import time +from kivy.clock import Clock +if sys.platform == "android": + from kivy import properties + from plyer import audio + + +PLUGIN_INFO = { + "name": _(u"voice"), + "main": "VoiceRecorder", + "platforms": ["android"], + "description": _(u"upload a voice record"), +} + + +class VoiceRecorder(BoxLayout): + callback = properties.ObjectProperty() + cancel_cb = properties.ObjectProperty() + recording = properties.BooleanProperty(False) + playing = properties.BooleanProperty(False) + time = properties.NumericProperty(0) + + def __init__(self, **kwargs): + super(VoiceRecorder, self).__init__(**kwargs) + self._started_at = None + self._counter_timer = None + self._play_timer = None + self.record_time = None + self.audio = audio + self.audio.file_path = "/sdcard/cagou_record.3gp" + + def _updateTimer(self, dt): + self.time = int(time.time() - self._started_at) + + def switchRecording(self): + if self.playing: + self._stopPlaying() + if self.recording: + try: + audio.stop() + except Exception as e: + # an exception can happen if record is pressed + # repeatedly in a short time (not a normal use) + log.warning(u"Exception on stop: {}".format(e)) + self._counter_timer.cancel() + self.time = self.time + 1 + else: + audio.start() + self._started_at = time.time() + self.time = 0 + self._counter_timer = Clock.schedule_interval(self._updateTimer, 1) + + self.recording = not self.recording + + def _stopPlaying(self, dummy=None): + if self.record_time is None: + log.error("_stopPlaying should no be called when record_time is None") + return + audio.stop() + self.playing = False + self.time = self.record_time + if self._counter_timer is not None: + self._counter_timer.cancel() + + def playRecord(self): + if self.recording: + return + if self.playing: + self._stopPlaying() + else: + try: + audio.play() + except Exception as e: + # an exception can happen in the same situation + # as for audio.stop() above (i.e. bad record) + log.warning(u"Exception on play: {}".format(e)) + self.time = 0 + return + + self.playing = True + self.record_time = self.time + Clock.schedule_once(self._stopPlaying, self.time + 1) + self._started_at = time.time() + self.time = 0 + self._counter_timer = Clock.schedule_interval(self._updateTimer, 0.5)