Explorar el Código

Update language automatically on startup

We now have a hash.yaml file which contains a SHA256 hash of
sentences.corpus.  If this differs from the hash the file calculated
when Kaylee sarts, the language is updated and the new hash is stored in
hash.yaml.
Clara Hobbs hace 8 años
padre
commit
900a3d8d2f
Se han modificado 2 ficheros con 70 adiciones y 28 borrados
  1. 66
    24
      blather.py
  2. 4
    4
      recognizer.py

+ 66
- 24
blather.py Ver fichero

@@ -5,16 +5,18 @@
5 5
 # Copyright 2013 Jezra
6 6
 # Copyright 2015 Clayton G. Hobbs
7 7
 
8
+from __future__ import print_function
8 9
 import sys
9 10
 import signal
10
-from gi.repository import GObject
11
+import hashlib
11 12
 import os.path
12 13
 import subprocess
13 14
 from optparse import OptionParser
15
+from gi.repository import GObject
14 16
 try:
15 17
     import yaml
16 18
 except:
17
-    print "YAML is not supported. ~/.config/blather/options.yaml will not function"
19
+    print("YAML is not supported; unable to use config file")
18 20
 
19 21
 from recognizer import Recognizer
20 22
 
@@ -25,8 +27,9 @@ command_file = os.path.join(conf_dir, "commands.conf")
25 27
 strings_file = os.path.join(conf_dir, "sentences.corpus")
26 28
 history_file = os.path.join(conf_dir, "blather.history")
27 29
 opt_file = os.path.join(conf_dir, "options.yaml")
28
-lang_file = os.path.join(lang_dir,'lm')
29
-dic_file = os.path.join(lang_dir,'dic')
30
+hash_file = os.path.join(conf_dir, "hash.yaml")
31
+lang_file = os.path.join(lang_dir, 'lm')
32
+dic_file = os.path.join(lang_dir, 'dic')
30 33
 # Make the lang_dir if it doesn't exist
31 34
 if not os.path.exists(lang_dir):
32 35
     os.makedirs(lang_dir)
@@ -34,7 +37,6 @@ if not os.path.exists(lang_dir):
34 37
 class Blather:
35 38
 
36 39
     def __init__(self, opts):
37
-        # Import the recognizer so Gst doesn't clobber our -h
38 40
         self.ui = None
39 41
         self.options = {}
40 42
         ui_continuous_listen = False
@@ -48,8 +50,8 @@ class Blather:
48 50
         # Load the options file
49 51
         self.load_options()
50 52
 
51
-        # Merge the opts
52
-        for k,v in opts.__dict__.items():
53
+        # Merge the options with the ones provided by command-line arguments
54
+        for k, v in opts.__dict__.items():
53 55
             if (not k in self.options) or opts.override:
54 56
                 self.options[k] = v
55 57
 
@@ -59,7 +61,7 @@ class Blather:
59 61
             elif self.options['interface'] == "gt":
60 62
                 from gtktrayui import UI
61 63
             else:
62
-                print "no GUI defined"
64
+                print("no GUI defined")
63 65
                 sys.exit()
64 66
 
65 67
             self.ui = UI(args, self.options['continuous'])
@@ -76,47 +78,51 @@ class Blather:
76 78
         if self.options['history']:
77 79
             self.history = []
78 80
 
81
+        # Update the language if necessary
82
+        self.update_language()
83
+
79 84
         # Create the recognizer
80 85
         try:
81 86
             self.recognizer = Recognizer(lang_file, dic_file, self.options['microphone'])
82
-        except Exception, e:
83
-            #no recognizer? bummer
84
-            print 'error making recognizer'
87
+        except Exception as e:
88
+            # No recognizer? bummer
89
+            print('error making recognizer')
85 90
             sys.exit()
86 91
 
87 92
         self.recognizer.connect('finished', self.recognizer_finished)
88 93
 
89
-        print "Using Options: ", self.options
94
+        print("Using Options: ", self.options)
90 95
 
91 96
     def read_commands(self):
92 97
         # Read the commands file
93 98
         file_lines = open(command_file)
94 99
         strings = open(strings_file, "w")
95 100
         for line in file_lines:
96
-            print line
101
+            print(line)
97 102
             # Trim the white spaces
98 103
             line = line.strip()
99 104
             # If the line has length and the first char isn't a hash
100 105
             if len(line) and line[0]!="#":
101 106
                 # This is a parsible line
102
-                (key,value) = line.split(":",1)
103
-                print key, value
107
+                (key, value) = line.split(":", 1)
108
+                print(key, value)
104 109
                 self.commands[key.strip().lower()] = value.strip()
105 110
                 strings.write( key.strip()+"\n")
106 111
         # Close the strings file
107 112
         strings.close()
108 113
 
109 114
     def load_options(self):
115
+        """If possible, load options from the options.yaml file"""
110 116
         # Is there an opt file?
111 117
         try:
112 118
             opt_fh = open(opt_file)
113 119
             text = opt_fh.read()
114 120
             self.options = yaml.load(text)
115 121
         except:
122
+            # Do nothing if the options file cannot be loaded
116 123
             pass
117 124
 
118
-
119
-    def log_history(self,text):
125
+    def log_history(self, text):
120 126
         if self.options['history']:
121 127
             self.history.append(text)
122 128
             if len(self.history) > self.options['history']:
@@ -130,9 +136,45 @@ class Blather:
130 136
             # Close the file
131 137
             hfile.close()
132 138
 
139
+    def update_language(self):
140
+        """Update the language if its hash has changed"""
141
+        try:
142
+            # Load the stored hash from the hash file
143
+            try:
144
+                with open(hash_file, 'r') as f:
145
+                    text = f.read()
146
+                    hashes = yaml.load(text)
147
+                stored_hash = hashes['language']
148
+            except (IOError, KeyError, TypeError):
149
+                # No stored hash
150
+                stored_hash = ''
151
+
152
+            # Calculate the hash the language file has right now
153
+            hasher = hashlib.sha256()
154
+            with open(strings_file, 'rb') as sfile:
155
+                buf = sfile.read()
156
+                hasher.update(buf)
157
+            new_hash = hasher.hexdigest()
158
+
159
+            # If the hashes differ
160
+            if stored_hash != new_hash:
161
+                # Update the language
162
+                # FIXME: Do this with Python, not Bash
163
+                self.run_command('./language_updater.sh')
164
+                # Store the new hash
165
+                new_hashes = {'language': new_hash}
166
+                with open(hash_file, 'w') as f:
167
+                    f.write(yaml.dump(new_hashes))
168
+        except Exception as e:
169
+            # Do nothing if the hash file cannot be loaded
170
+            # FIXME: This is kind of bad; maybe YAML should be mandatory.
171
+            print('error updating language')
172
+            print(e)
173
+            pass
174
+
133 175
     def run_command(self, cmd):
134
-        '''Print the command, then run it'''
135
-        print cmd
176
+        """Print the command, then run it"""
177
+        print(cmd)
136 178
         subprocess.call(cmd, shell=True)
137 179
 
138 180
     def recognizer_finished(self, recognizer, text):
@@ -154,7 +196,7 @@ class Blather:
154 196
             # Run the invalid_sentence_command if there is an invalid sentence command
155 197
             if self.options['invalid_sentence_command']:
156 198
                 subprocess.call(self.options['invalid_sentence_command'], shell=True)
157
-            print "no matching command %s" % t
199
+            print("no matching command {0}".format(t))
158 200
         # If there is a UI and we are not continuous listen
159 201
         if self.ui:
160 202
             if not self.continuous_listen:
@@ -173,7 +215,7 @@ class Blather:
173 215
         sys.exit()
174 216
 
175 217
     def process_command(self, UI, command):
176
-        print command
218
+        print(command)
177 219
         if command == "listen":
178 220
             self.recognizer.listen()
179 221
         elif command == "stop":
@@ -187,9 +229,9 @@ class Blather:
187 229
         elif command == "quit":
188 230
             self.quit()
189 231
 
190
-    def load_resource(self,string):
232
+    def load_resource(self, string):
191 233
         local_data = os.path.join(os.path.dirname(__file__), 'data')
192
-        paths = ["/usr/share/blather/","/usr/local/share/blather", local_data]
234
+        paths = ["/usr/share/blather/", "/usr/local/share/blather", local_data]
193 235
         for path in paths:
194 236
             resource = os.path.join(path, string)
195 237
             if os.path.exists( resource ):
@@ -247,7 +289,7 @@ if __name__ == "__main__":
247 289
     try:
248 290
         main_loop.run()
249 291
     except:
250
-        print "time to quit"
292
+        print("time to quit")
251 293
         main_loop.quit()
252 294
         sys.exit()
253 295
 

+ 4
- 4
recognizer.py Ver fichero

@@ -32,9 +32,9 @@ class Recognizer(GObject.GObject):
32 32
         cmd = audio_src+' ! audioconvert ! audioresample ! pocketsphinx name=asr ! appsink sync=false'
33 33
         try:
34 34
             self.pipeline=Gst.parse_launch( cmd )
35
-        except Exception, e:
36
-            print e.message
37
-            print "You may need to install gstreamer1.0-pocketsphinx"
35
+        except Exception as e:
36
+            print(e.message)
37
+            print("You may need to install gstreamer1.0-pocketsphinx")
38 38
             raise e
39 39
 
40 40
         bus = self.pipeline.get_bus()
@@ -63,4 +63,4 @@ class Recognizer(GObject.GObject):
63 63
         # If we have a final command, send it for processing
64 64
         command = msg_struct.get_string('hypothesis')
65 65
         if command != '' and msg_struct.get_boolean('final')[1]:
66
-	    self.emit("finished", command)
66
+            self.emit("finished", command)

Loading…
Cancelar
Guardar