from os.path import join from pyobjus import autoclass from pyobjus.dylib_manager import INCLUDE, load_framework from sbapp.plyer.facades import Audio from sbapp.plyer.platforms.macosx.storagepath import OSXStoragePath import threading load_framework(INCLUDE.Foundation) load_framework(INCLUDE.AVFoundation) AVAudioPlayer = autoclass("AVAudioPlayer") AVAudioRecorder = autoclass("AVAudioRecorder") AVAudioFormat = autoclass("AVAudioFormat") NSString = autoclass('NSString') NSURL = autoclass('NSURL') NSError = autoclass('NSError').alloc() class OSXAudio(Audio): def __init__(self, file_path=None): default_path = None super().__init__(file_path or default_path) self._recorder = None self._player = None self._current_file = None self._check_thread = None self._finished_callback = None self._loaded_path = None self.is_playing = False self.sound = None self.pa = None self.is_playing = False self.recorder = None self.should_record = False def _check_playback(self): while self._player and self._player.isPlaying: time.sleep(0.25) if self._finished_callback and callable(self._finished_callback): self._check_thread = None self._finished_callback(self) def _start(self): # Conversion of Python file path string to Objective-C NSString file_path_NSString = NSString.alloc() file_path_NSString = file_path_NSString.initWithUTF8String_( self._file_path ) # Definition of Objective-C NSURL object for the output record file # specified by NSString file path file_NSURL = NSURL.alloc() file_NSURL = file_NSURL.initWithString_(file_path_NSString) # Internal audio file format specification af = AVAudioFormat.alloc() af = af.initWithCommonFormat_sampleRate_channels_interleaved_( 1, 44100.0, 1, True ) # Audio recorder instance initialization with specified file NSURL # and audio file format self._recorder = AVAudioRecorder.alloc() self._recorder = self._recorder.initWithURL_format_error_( file_NSURL, af, NSError ) if not self._recorder: raise Exception(NSError.code, NSError.domain) self._recorder.record() # Setting the currently recorded file as current file # for using it as a parameter in audio player self._current_file = file_NSURL def _stop(self): if self._recorder: self._recorder.stop() self._recorder = None if self._player: self._player.stop() self._player = None def _play(self): # Conversion of Python file path string to Objective-C NSString file_path_NSString = NSString.alloc() file_path_NSString = file_path_NSString.initWithUTF8String_( self._file_path ) # Definition of Objective-C NSURL object for the output record file # specified by NSString file path file_NSURL = NSURL.alloc() file_NSURL = file_NSURL.initWithString_(file_path_NSString) self._current_file = file_NSURL # Audio player instance initialization with the file NSURL # of the last recorded audio file self._player = AVAudioPlayer.alloc() self._player = self._player.initWithContentsOfURL_error_( self._current_file, NSError ) if not self._player: raise Exception(NSError.code, NSError.domain) self._player.play() self._check_thread = threading.Thread(target=self._check_playback, daemon=True) self._check_thread.start() def reload(self): self._loaded_path = None def playing(self): return self.is_playing def instance(): return OSXAudio()