Somewhat fancy voice command recognition software
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

blather.py 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #!/usr/bin/env python3
  2. # This is part of Kaylee
  3. # -- this code is licensed GPLv3
  4. # Copyright 2013 Jezra
  5. # Copyright 2015 Clayton G. Hobbs
  6. from __future__ import print_function
  7. import sys
  8. import signal
  9. import hashlib
  10. import os.path
  11. import subprocess
  12. from gi.repository import GObject, GLib
  13. import json
  14. from recognizer import Recognizer
  15. from config import Config
  16. from languageupdater import LanguageUpdater
  17. class Blather:
  18. def __init__(self):
  19. self.ui = None
  20. self.options = {}
  21. ui_continuous_listen = False
  22. self.continuous_listen = False
  23. self.commands = {}
  24. # Load configuration
  25. self.config = Config()
  26. self.options = vars(self.config.options)
  27. # Read the commands
  28. self.read_commands()
  29. if self.options['interface']:
  30. if self.options['interface'] == "g":
  31. from gtkui import UI
  32. elif self.options['interface'] == "gt":
  33. from gtktrayui import UI
  34. else:
  35. print("no GUI defined")
  36. sys.exit()
  37. self.ui = UI(self.options, self.options['continuous'])
  38. self.ui.connect("command", self.process_command)
  39. # Can we load the icon resource?
  40. icon = self.load_resource("icon.png")
  41. if icon:
  42. self.ui.set_icon_active_asset(icon)
  43. # Can we load the icon_inactive resource?
  44. icon_inactive = self.load_resource("icon_inactive.png")
  45. if icon_inactive:
  46. self.ui.set_icon_inactive_asset(icon_inactive)
  47. if self.options['history']:
  48. self.history = []
  49. # Update the language if necessary
  50. self.language_updater = LanguageUpdater(self.config)
  51. self.language_updater.update_language_if_changed()
  52. # Create the recognizer
  53. self.recognizer = Recognizer(self.config)
  54. self.recognizer.connect('finished', self.recognizer_finished)
  55. def read_commands(self):
  56. # Read the commands file
  57. file_lines = open(self.config.command_file)
  58. strings = open(self.config.strings_file, "w")
  59. for line in file_lines:
  60. # Trim the white spaces
  61. line = line.strip()
  62. # If the line has length and the first char isn't a hash
  63. if len(line) and line[0] != "#":
  64. # This is a parsible line
  65. (key, value) = line.split(":", 1)
  66. self.commands[key.strip().lower()] = value.strip()
  67. strings.write(key.strip() + "\n")
  68. # Close the strings file
  69. strings.close()
  70. def log_history(self, text):
  71. if self.options['history']:
  72. self.history.append(text)
  73. if len(self.history) > self.options['history']:
  74. # Pop off the first item
  75. self.history.pop(0)
  76. # Open and truncate the blather history file
  77. hfile = open(self.config.history_file, "w")
  78. for line in self.history:
  79. hfile.write(line + "\n")
  80. # Close the file
  81. hfile.close()
  82. def run_command(self, cmd):
  83. """Print the command, then run it"""
  84. print(cmd)
  85. subprocess.call(cmd, shell=True)
  86. def recognizer_finished(self, recognizer, text):
  87. t = text.lower()
  88. # Is there a matching command?
  89. if t in self.commands:
  90. # Run the valid_sentence_command if there is a valid sentence command
  91. if self.options['valid_sentence_command']:
  92. subprocess.call(self.options['valid_sentence_command'], shell=True)
  93. cmd = self.commands[t]
  94. # Should we be passing words?
  95. if self.options['pass_words']:
  96. cmd += " " + t
  97. self.run_command(cmd)
  98. else:
  99. self.run_command(cmd)
  100. self.log_history(text)
  101. else:
  102. # Run the invalid_sentence_command if there is an invalid sentence command
  103. if self.options['invalid_sentence_command']:
  104. subprocess.call(self.options['invalid_sentence_command'], shell=True)
  105. print("no matching command {0}".format(t))
  106. # If there is a UI and we are not continuous listen
  107. if self.ui:
  108. if not self.continuous_listen:
  109. # Stop listening
  110. self.recognizer.pause()
  111. # Let the UI know that there is a finish
  112. self.ui.finished(t)
  113. def run(self):
  114. if self.ui:
  115. self.ui.run()
  116. else:
  117. blather.recognizer.listen()
  118. def quit(self):
  119. sys.exit()
  120. def process_command(self, UI, command):
  121. print(command)
  122. if command == "listen":
  123. self.recognizer.listen()
  124. elif command == "stop":
  125. self.recognizer.pause()
  126. elif command == "continuous_listen":
  127. self.continuous_listen = True
  128. self.recognizer.listen()
  129. elif command == "continuous_stop":
  130. self.continuous_listen = False
  131. self.recognizer.pause()
  132. elif command == "quit":
  133. self.quit()
  134. def load_resource(self, string):
  135. local_data = os.path.join(os.path.dirname(__file__), 'data')
  136. paths = ["/usr/share/blather/", "/usr/local/share/blather", local_data]
  137. for path in paths:
  138. resource = os.path.join(path, string)
  139. if os.path.exists(resource):
  140. return resource
  141. # If we get this far, no resource was found
  142. return False
  143. if __name__ == "__main__":
  144. # Make our blather object
  145. blather = Blather()
  146. # Init gobject threads
  147. GObject.threads_init()
  148. # We want a main loop
  149. main_loop = GObject.MainLoop()
  150. # Handle sigint
  151. signal.signal(signal.SIGINT, signal.SIG_DFL)
  152. # Run the blather
  153. blather.run()
  154. # Start the main loop
  155. try:
  156. main_loop.run()
  157. except:
  158. print("time to quit")
  159. main_loop.quit()
  160. sys.exit()