2024-06-02 18:31:58 +02:00
|
|
|
import time
|
|
|
|
import threading
|
2022-09-16 18:07:57 +02:00
|
|
|
from jnius import autoclass
|
|
|
|
|
|
|
|
from plyer.facades.audio import Audio
|
|
|
|
|
|
|
|
# Recorder Classes
|
|
|
|
MediaRecorder = autoclass('android.media.MediaRecorder')
|
|
|
|
AudioSource = autoclass('android.media.MediaRecorder$AudioSource')
|
|
|
|
OutputFormat = autoclass('android.media.MediaRecorder$OutputFormat')
|
|
|
|
AudioEncoder = autoclass('android.media.MediaRecorder$AudioEncoder')
|
|
|
|
|
|
|
|
# Player Classes
|
|
|
|
MediaPlayer = autoclass('android.media.MediaPlayer')
|
|
|
|
|
|
|
|
|
|
|
|
class AndroidAudio(Audio):
|
|
|
|
'''Audio for android.
|
|
|
|
|
|
|
|
For recording audio we use MediaRecorder Android class.
|
|
|
|
For playing audio we use MediaPlayer Android class.
|
|
|
|
'''
|
|
|
|
|
|
|
|
def __init__(self, file_path=None):
|
2024-06-02 18:31:58 +02:00
|
|
|
default_path = None
|
2022-09-16 18:07:57 +02:00
|
|
|
super().__init__(file_path or default_path)
|
|
|
|
|
|
|
|
self._recorder = None
|
|
|
|
self._player = None
|
2024-06-02 18:31:58 +02:00
|
|
|
self._check_thread = None
|
|
|
|
self._finished_callback = None
|
2024-06-03 01:53:54 +02:00
|
|
|
self._format = "opus"
|
2024-06-04 02:55:13 +02:00
|
|
|
self.is_playing = False
|
2024-06-02 18:31:58 +02:00
|
|
|
|
|
|
|
def _check_playback(self):
|
|
|
|
while self._player and self._player.isPlaying():
|
|
|
|
time.sleep(0.25)
|
2024-06-04 02:55:13 +02:00
|
|
|
|
|
|
|
self.is_playing = False
|
2024-06-02 18:31:58 +02:00
|
|
|
|
|
|
|
if self._finished_callback and callable(self._finished_callback):
|
|
|
|
self._check_thread = None
|
|
|
|
self._finished_callback(self)
|
|
|
|
|
2022-09-16 18:07:57 +02:00
|
|
|
|
|
|
|
def _start(self):
|
|
|
|
self._recorder = MediaRecorder()
|
2024-06-03 01:53:54 +02:00
|
|
|
if self._format == "aac":
|
|
|
|
self._recorder.setAudioSource(AudioSource.DEFAULT)
|
|
|
|
self._recorder.setAudioSamplingRate(48000)
|
2024-06-04 02:55:13 +02:00
|
|
|
self._recorder.setAudioEncodingBitRate(64000)
|
2024-06-03 01:53:54 +02:00
|
|
|
self._recorder.setAudioChannels(1)
|
|
|
|
self._recorder.setOutputFormat(OutputFormat.MPEG_4)
|
|
|
|
self._recorder.setAudioEncoder(AudioEncoder.AAC)
|
|
|
|
|
|
|
|
else:
|
|
|
|
self._recorder.setAudioSource(AudioSource.DEFAULT)
|
|
|
|
self._recorder.setAudioSamplingRate(48000)
|
2024-06-04 02:55:13 +02:00
|
|
|
self._recorder.setAudioEncodingBitRate(16000)
|
2024-06-03 01:53:54 +02:00
|
|
|
self._recorder.setAudioChannels(1)
|
|
|
|
self._recorder.setOutputFormat(OutputFormat.OGG)
|
|
|
|
self._recorder.setAudioEncoder(AudioEncoder.OPUS)
|
|
|
|
|
2022-09-16 18:07:57 +02:00
|
|
|
self._recorder.setOutputFile(self.file_path)
|
|
|
|
|
|
|
|
self._recorder.prepare()
|
|
|
|
self._recorder.start()
|
|
|
|
|
|
|
|
def _stop(self):
|
|
|
|
if self._recorder:
|
|
|
|
self._recorder.stop()
|
|
|
|
self._recorder.release()
|
|
|
|
self._recorder = None
|
|
|
|
|
|
|
|
if self._player:
|
|
|
|
self._player.stop()
|
|
|
|
self._player.release()
|
|
|
|
self._player = None
|
|
|
|
|
2024-06-04 02:55:13 +02:00
|
|
|
self.is_playing = False
|
|
|
|
|
2022-09-16 18:07:57 +02:00
|
|
|
def _play(self):
|
|
|
|
self._player = MediaPlayer()
|
|
|
|
self._player.setDataSource(self.file_path)
|
|
|
|
self._player.prepare()
|
|
|
|
self._player.start()
|
2024-06-04 02:55:13 +02:00
|
|
|
self.is_playing = True
|
2022-09-16 18:07:57 +02:00
|
|
|
|
2024-06-02 18:31:58 +02:00
|
|
|
self._check_thread = threading.Thread(target=self._check_playback, daemon=True)
|
|
|
|
self._check_thread.start()
|
|
|
|
|
2024-06-03 13:20:41 +02:00
|
|
|
def reload(self):
|
|
|
|
self._stop()
|
2024-06-02 18:31:58 +02:00
|
|
|
|
2024-06-04 02:55:13 +02:00
|
|
|
def playing(self):
|
|
|
|
return self.is_playing
|
|
|
|
|
2022-09-16 18:07:57 +02:00
|
|
|
|
|
|
|
def instance():
|
|
|
|
return AndroidAudio()
|