forked from Kitt-AI/snowboy
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add wrapper around HotwordDetector class for Python to provide a simp…
…le interface for running detectors in a separate thread
- Loading branch information
Showing
1 changed file
with
92 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import snowboydecoder | ||
import threading | ||
import Queue | ||
|
||
|
||
class ThreadedDetector(threading.Thread): | ||
""" | ||
Wrapper class around detectors to run them in a separate thread | ||
and provide methods to pause, resume, and modify detection | ||
""" | ||
|
||
def __init__(self, models, **kwargs): | ||
""" | ||
Initialize Detectors object. **kwargs is for any __init__ keyword arguments to be passed into HotWordDetector | ||
__init__() method. | ||
""" | ||
threading.Thread.__init__(self) | ||
self.models = models | ||
self.init_kwargs = kwargs | ||
self.interrupted = True | ||
self.commands = Queue.Queue() | ||
self.vars_are_changed = True | ||
self.detectors = None # Initialize when thread is run in self.run() | ||
self.run_kwargs = None # Initialize when detectors start in self.start_recog() | ||
|
||
def initialize_detectors(self): | ||
""" | ||
Returns initialized Snowboy HotwordDetector objects | ||
""" | ||
self.detectors = snowboydecoder.HotwordDetector(self.models, **self.init_kwargs) | ||
|
||
def run(self): | ||
""" | ||
Runs in separate thread - waits on command to either run detectors or terminate thread from commands queue | ||
""" | ||
try: | ||
while True: | ||
command = self.commands.get(True) | ||
if command == "Start": | ||
self.interrupted = False | ||
if self.vars_are_changed: | ||
# If there is an existing detector object, terminate it | ||
if self.detectors is not None: | ||
self.detectors.terminate() | ||
self.initialize_detectors() | ||
self.vars_are_changed = False | ||
# Start detectors - blocks until interrupted by self.interrupted variable | ||
self.detectors.start(interrupt_check=lambda: self.interrupted, **self.run_kwargs) | ||
elif command == "Terminate": | ||
# Program ending - terminate thread | ||
break | ||
finally: | ||
if self.detectors is not None: | ||
self.detectors.terminate() | ||
|
||
def start_recog(self, **kwargs): | ||
""" | ||
Starts recognition in thread. Accepts kwargs to pass into the HotWordDetector.start() method, but | ||
does not accept interrupt_callback, as that is already set up. | ||
""" | ||
assert "interrupt_check" not in kwargs, \ | ||
"Cannot set interrupt_check argument. To interrupt detectors, use Detectors.stop_recog() instead" | ||
self.run_kwargs = kwargs | ||
self.commands.put("Start") | ||
|
||
def stop_recog(self): | ||
""" | ||
Halts recognition in thread. | ||
""" | ||
self.interrupted = True | ||
|
||
def terminate(self): | ||
""" | ||
Terminates recognition thread - called when program terminates | ||
""" | ||
self.stop_recog() | ||
self.commands.put("Terminate") | ||
|
||
def is_running(self): | ||
return not self.interrupted | ||
|
||
def change_models(self, models): | ||
if self.is_running(): | ||
print("Models will be changed after restarting detectors.") | ||
self.models = models | ||
self.vars_are_changed = True | ||
|
||
def change_sensitivity(self, sensitivity): | ||
if self.is_running(): | ||
print("Sensitivity will be changed after restarting detectors.") | ||
self.init_kwargs['sensitivity'] = sensitivity | ||
self.vars_are_changed = True |