From 25ebc8fe8b34939507d741636a11816cb4f11db2 Mon Sep 17 00:00:00 2001 From: "Clayton G. Hobbs" Date: Sun, 27 Dec 2015 14:40:53 -0500 Subject: Moved paths to Config class Paths of important files and directories are part of the program's configuration, no? We're making better use of XDG paths now. Only configuration-y things go in $XDG_CONFIG_HOME now, with cache-y and data-y things going in the appropriate places instead of just being crammed in with configuration. --- blather.py | 43 ++++++++++++---------------------------- config.py | 56 +++++++++++++++++++++++++++++++++++++++++++---------- language_updater.sh | 13 +++++++------ recognizer.py | 10 ++++++---- 4 files changed, 71 insertions(+), 51 deletions(-) diff --git a/blather.py b/blather.py index 7cfe276..a90afe3 100755 --- a/blather.py +++ b/blather.py @@ -17,19 +17,6 @@ import json from recognizer import Recognizer from config import Config -# Where are the files? -conf_dir = os.path.expanduser(os.path.join(GLib.get_user_config_dir(), - "blather")) -lang_dir = os.path.join(conf_dir, "language") -command_file = os.path.join(conf_dir, "commands.conf") -strings_file = os.path.join(conf_dir, "sentences.corpus") -history_file = os.path.join(conf_dir, "blather.history") -hash_file = os.path.join(conf_dir, "hash.json") -lang_file = os.path.join(lang_dir, 'lm') -dic_file = os.path.join(lang_dir, 'dic') -# Make the lang_dir if it doesn't exist -if not os.path.exists(lang_dir): - os.makedirs(lang_dir) class Blather: @@ -41,13 +28,13 @@ class Blather: self.commands = {} - # Read the commands - self.read_commands() - - # Load the options file + # Load configuration self.config = Config() self.options = vars(self.config.options) + # Read the commands + self.read_commands() + if self.options['interface'] != None: if self.options['interface'] == "g": from gtkui import UI @@ -75,24 +62,18 @@ class Blather: self.update_language() # Create the recognizer - try: - self.recognizer = Recognizer(lang_file, dic_file, self.options['microphone']) - except Exception as e: - # No recognizer? bummer - print('error making recognizer') - sys.exit() - + self.recognizer = Recognizer(self.config) self.recognizer.connect('finished', self.recognizer_finished) def read_commands(self): # Read the commands file - file_lines = open(command_file) - strings = open(strings_file, "w") + file_lines = open(self.config.command_file) + strings = open(self.config.strings_file, "w") for line in file_lines: # Trim the white spaces line = line.strip() # If the line has length and the first char isn't a hash - if len(line) and line[0]!="#": + if len(line) and line[0] != "#": # This is a parsible line (key, value) = line.split(":", 1) self.commands[key.strip().lower()] = value.strip() @@ -108,7 +89,7 @@ class Blather: self.history.pop(0) # Open and truncate the blather history file - hfile = open(history_file, "w") + hfile = open(self.config.history_file, "w") for line in self.history: hfile.write(line + "\n") # Close the file @@ -118,7 +99,7 @@ class Blather: """Update the language if its hash has changed""" # Load the stored hash from the hash file try: - with open(hash_file, 'r') as f: + with open(self.config.hash_file, 'r') as f: hashes = json.load(f) stored_hash = hashes['language'] except (IOError, KeyError, TypeError): @@ -127,7 +108,7 @@ class Blather: # Calculate the hash the language file has right now hasher = hashlib.sha256() - with open(strings_file, 'rb') as sfile: + with open(self.config.strings_file, 'rb') as sfile: buf = sfile.read() hasher.update(buf) new_hash = hasher.hexdigest() @@ -139,7 +120,7 @@ class Blather: self.run_command('./language_updater.sh') # Store the new hash new_hashes = {'language': new_hash} - with open(hash_file, 'w') as f: + with open(self.config.hash_file, 'w') as f: json.dump(new_hashes, f) def run_command(self, cmd): diff --git a/config.py b/config.py index 21b4ec2..482e929 100644 --- a/config.py +++ b/config.py @@ -10,11 +10,34 @@ from argparse import ArgumentParser, Namespace from gi.repository import GLib class Config: - conf_dir = os.path.expanduser(os.path.join(GLib.get_user_config_dir(), - "blather")) + """Keep track of the configuration of Kaylee""" + # Name of the program, for later use + program_name = "kaylee" + + # Directories + conf_dir = os.path.join(GLib.get_user_config_dir(), program_name) + cache_dir = os.path.join(GLib.get_user_cache_dir(), program_name) + data_dir = os.path.join(GLib.get_user_data_dir(), program_name) + + # Configuration files + command_file = os.path.join(conf_dir, "commands.conf") opt_file = os.path.join(conf_dir, "options.json") + # Cache files + history_file = os.path.join(cache_dir, program_name + "history") + hash_file = os.path.join(cache_dir, "hash.json") + + # Data files + strings_file = os.path.join(data_dir, "sentences.corpus") + lang_file = os.path.join(data_dir, 'lm') + dic_file = os.path.join(data_dir, 'dic') + def __init__(self): + # Ensure necessary directories exist + self._make_dir(self.conf_dir) + self._make_dir(self.cache_dir) + self._make_dir(self.data_dir) + # Set up the argument parser self.parser = ArgumentParser() self.parser.add_argument("-i", "--interface", type=str, @@ -24,16 +47,16 @@ class Config: self.parser.add_argument("-c", "--continuous", action="store_true", dest="continuous", default=False, - help="starts interface with 'continuous' listen enabled") + help="Start interface with 'continuous' listen enabled") self.parser.add_argument("-p", "--pass-words", action="store_true", dest="pass_words", default=False, - help="passes the recognized words as arguments to the shell" + + help="Pass the recognized words as arguments to the shell" + " command") self.parser.add_argument("-H", "--history", type=int, action="store", dest="history", - help="number of commands to store in history file") + help="Number of commands to store in history file") self.parser.add_argument("-m", "--microphone", type=int, action="store", dest="microphone", default=None, @@ -41,16 +64,29 @@ class Config: self.parser.add_argument("--valid-sentence-command", type=str, dest="valid_sentence_command", action='store', - help="command to run when a valid sentence is detected") + help="Command to run when a valid sentence is detected") self.parser.add_argument("--invalid-sentence-command", type=str, dest="invalid_sentence_command", action='store', - help="command to run when an invalid sentence is detected") + help="Command to run when an invalid sentence is detected") # Read the configuration file - with open(self.opt_file, 'r') as f: - self.options = json.load(f) - self.options = Namespace(**self.options) + self._read_options_file() # Parse command-line arguments, overriding config file as appropriate self.args = self.parser.parse_args(namespace=self.options) + print(self.args) + print(self.options) + + def _make_dir(self, directory): + if not os.path.exists(directory): + os.makedirs(directory) + + def _read_options_file(self): + try: + with open(self.opt_file, 'r') as f: + self.options = json.load(f) + self.options = Namespace(**self.options) + except FileNotFoundError: + # Make an empty options namespace + self.options = Namespace() diff --git a/language_updater.sh b/language_updater.sh index ec5c868..5a2c232 100755 --- a/language_updater.sh +++ b/language_updater.sh @@ -1,10 +1,11 @@ #!/bin/bash -blatherdir=~/.config/blather -sentences=$blatherdir/sentences.corpus +blatherdir=~/.config/kaylee +blatherdatadir=~/.local/share/kaylee +blathercachedir=~/.cache/kaylee +sentences=$blatherdatadir/sentences.corpus sourcefile=$blatherdir/commands.conf -langdir=$blatherdir/language -tempfile=$blatherdir/url.txt +tempfile=$blathercachedir/url.txt lmtoolurl=http://www.speech.cs.cmu.edu/cgi-bin/tools/lmtool/run cd $blatherdir @@ -25,7 +26,7 @@ curl -C - -O $(cat $tempfile).dic curl -C - -O $(cat $tempfile).lm # mv em to the right name/place -mv *.dic $langdir/dic -mv *.lm $langdir/lm +mv *.dic $blatherdatadir/dic +mv *.lm $blatherdatadir/lm rm $tempfile diff --git a/recognizer.py b/recognizer.py index ac970a0..3d6f4bf 100755 --- a/recognizer.py +++ b/recognizer.py @@ -18,11 +18,13 @@ class Recognizer(GObject.GObject): 'finished' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, (GObject.TYPE_STRING,)) } - def __init__(self, language_file, dictionary_file, src=None): + def __init__(self, config): GObject.GObject.__init__(self) self.commands = {} + + src = config.options.microphone if src: - audio_src = 'alsasrc device="hw:%d,0"' % (src) + audio_src = 'alsasrc device="hw:{0},0"'.format(src) else: audio_src = 'autoaudiosrc' @@ -31,8 +33,8 @@ class Recognizer(GObject.GObject): audio_src + ' ! audioconvert' + ' ! audioresample' + - ' ! pocketsphinx lm=' + language_file + ' dict=' + - dictionary_file + ' configured=true' + + ' ! pocketsphinx lm=' + config.lang_file + ' dict=' + + config.dic_file + ' configured=true' + ' ! appsink sync=false' ) try: -- cgit 1.4.1