This makes pocketsphinx pick up way fewer false-positives of single
number-words as recognised sentences. It doesn't seem to make any
difference in anything else, but fewer false-positives is always nice.
They still need work of course, since I'm a programmer and not an
artist. The new icons of course are Kaylee's parasol, and anyone who
doesn't know that needs to watch Firefly.
Commands aren't stored in a special file anymore, and Kaylee never tries
to look at that file. Therefore, there's no need for the Config object
to keep that file's path, and so the path has been removed.
Added some blank lines and wrapped some long lines to be closer to PEP 8
compliance.
Improved docstrings in NumberParser class. Added docstrings for
undocumented code and removed a TODO message that no longer applies.
Now distributions created from setup.py put the systemd unit file in the
correct location for units provided by packages. It may then be enabled
and started by the user with systemctl.
Closes #11.
Next I need to make the setup.py script install it. It's meant to be a
user service (installed to /usr/lib/systemd/user/), since Kaylee
currently does not support being run outside of a normal user account.
Also, it would be really nice to make it possible to reload the service
once it has been started. This will require some changes to Kaylee to
support synchronously reloading configuration. I understand that you
aren't supposed to reload units asynchronously, and I *really* can't
trust Kaylee to reload succinctly since reloading configuration may
require contacting a remote server until #10 is implemented.
Configuration reloading may be a separate issue from the systemd unit
file, but I'd like to see it by version 0.2.
Apparently CMU thinks it's a good idea to release a new version of a
piece of software that breaks existing APIs without even changing the
version number. I find this idea to be highly dubious at best.
Nevertheless, I have updated Kaylee to support the latest version of
pocketsphinx.
Now we check a hash of the voice commands before writing the strings
file to reduce how much we write to the hard disk. In implementing
this, I realized that some code was being duplicated in an easily
fixable way, so I created a Hasher object that keeps track of the
hash.json file.
Resolves #6
Its control flow was confusing before; now it's much more
straightforward. We make a string representing classes of words, split
that by a regular expression for number words, then parse each number
and build up our return string and list. It works just as well as the
previous method, is a bit shorter, and I feel that it's clearer as well.
It wasn't actually guaranteed, it turns out. I was iterating over
dictionary keys, which is done in arbitrary order. The result was that
in different executions of the program, the corpus was generated
differently, so the hashes differed, and the language had to be updated.
Sorting the keys before adding them to the list of number-words fixed
the problem.
See commands.tmp for an example. It's pretty neat, but it could still
use some work. I thought of a really clever way to parse numbers, better
than the one I came up with last night, but since I have a working
implementation now I figure I'd better commit it.
We have a new bug which causes the dictionary to be updated every time the
program starts. I hope I didn't force that to happen last night or
something, but I have a vague feeling I did.
At the same time, I moved the logic to check if the language should be
updated into the new LanguageUpdater class. The README has been updated
to reflect the fact that you no longer need to do any of this manually
ever.
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.
Removed a bunch of print statements that looked like they were added for
debugging, then never removed.
Reorganized GStreamer pipeline code so that all configuration is done
when the pipeline is created.
The configuration file is now properly overridden by argument parsing.
This was accomplished by loading the config file, then treating the
specified options as a namespace for the ArgumentParser. This makes
things from the config file get overridden iff they were specified on
the command line (not simply from defaults set in the ArgumentParser).
Hashes are now stored in hash.json, not hash.yaml. Also, we use the XDG
configuration directory rather than assuming we should use ~/.config/.
Maybe I should also make use of XDG data and/or cache directories.
Mostly working for the options file now. Still some difficulty with
command-line arguments, though; they're overriding the config file even
when not specified. If I made them simply not get stored at all when
not specified, there would be further problems when a configuration file
is not present. Maybe I should make a whole new class to handle this.
Personally, I don't see a point to a switch that must be turned on to
make all other switches work at all. It's a confusing behaviour that
made me think I somehow broke the GUIs.
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.
This fork is called Kaylee, not Blather. Let's at least be consistent
with referring to the program as Kaylee, even if the code is still in
blather.py.
Removed QT interface, renamed interfaces to Kaylee
I'm a GTK man myself. I don't know if I have Python QT bindings
installed on any of my computers. It follows then that I would not
maintain the QT interface well, let alone use it at all. It has
therefore been removed to avoid having someone try to use it only to
find that it's broken.
Gotta keep that stuff up-to-date, yo. Pocketsphinx changed so it needs
GStreamer 1.0, and that required rewriting everything to use GObject
Introspection instead of the old, static Python bindings for GObject.