from dial import DialManager, DialThread from hangup import HangUpThread from threading import Event import subprocess from queue import Queue class Phone: __instance = None @staticmethod def get_instance(): if Phone.__instance is None: Phone() return Phone.__instance def __init__(self): Phone.__instance = self self.queue = Queue() self.phone_held = Event() self.phone_hung_up = Event() self.processing_event = Event() # start phone as on hook self.phone_held.clear() self.phone_hung_up.set() self.processing_event.clear() self.dial_thread = DialThread(self) self.dial_thread.start() self.dial_manager = DialManager(self) self.hang_up_thread = HangUpThread(self) self.hang_up_thread.start() def wait_until_answered(self, timeout=None): return self.phone_held.wait(timeout) def wait_until_hung_up(self, timeout=None): return self.phone_hung_up.wait(timeout) def process_dial(self): try: dialed = self.queue.get(block=True, timeout=0.1) except: return response = self.dial_manager.dial(dialed) # If we matched a sequence, play out event if response is not None: self.processing_event.set() response.run() def clear_event(self): self.processing_event.clear() def run_until_hangup(self, command): process = subprocess.Popen(command) while process.poll() is None: if self.wait_until_hung_up(0.1): print("terminating process") process.terminate() process.kill() return False return True def run_many_until_hangup(self, commands): for command in commands: if not self.run_until_hangup(command): break