teeveed: natural language interface for your media center
teeveed is a media center daeon you control with your voice. Right now, you talk to it with your smartphone's web browser. You tell teeveed to play a movie or an episode of a show you want to see that you have on your share, and it opens VLC for you.
Behind the scenes, teeveed runs an indexer to keep finding files fast. It runs a webserver so you can communicate with it, and it has a nice pleasent heads-up display, so you can see what it's doing.
Use the JavaFX entry point. Right now teeveed boots from
jar-bootstrap.rb
via JRuby's org.jruby.JarBootstrapMain
.
We need to use a JavaFX main to use JavaFX bundling tools
and eliminate dependence on
mvn com.zenjava:javafx-maven-plugin:2.0:fix-classpath
for deployment
Switch from JRuby-based JIT compiling to AOT compiling. teeveed boots really, really slowley, and that's because there's a lot of JIT happening when the jar is loaded. Maybe things would go faster if we pre-compiled teeveed (and its gems).
pg_trgm
extension! pg_trgm is one
of the ways we find similar-text matchesteeveed uses gem-maven-plugin instead of Bundler
to manage
requirements. See pom.xml
for more information.
git clone https://github.com/justjake/teeveed
or similar to get the sourcecd teeveed
, mvn initialize
will download and install the required rubygems
in teeveed/target/rubygems
source env.sh
will correct your $GEM_HOME
and $RUBY_LIB
environment variables
to point to the gems installed in teeveed/target/rubygems
and the teeveed sources.teeveed
(alias provided by env.sh) to start the daemon, or
cli
to start the Pry command line.If things feel too slow,
You should get drip in your ~/bin,
and then source drip.env.sh
before launching any of this ruby junk.
Drip'll put the spring back in your step!
The only reason we need Maven and the JDK is because (right now) teeveed isn't packaged as a JavaFX runtime app. Because the JavaFX runtime does some interesting native loading things, the simplest way is just to move the JavaFX libraries into the implicit system classpath.
I will get around to fixing this, but it's low priority for my own machines.
(sudo) mvn com.zenjava:javafx-maven-plugin:2.0:fix-classpath
This moves JavaFX onto the classpath so the JavaFX libraries are always loaded. THIS STEP IS ONLY REQUIRED ON USER-INTERFACE MACHINES
make a directory for all of the teeveed resources. I like ~/teeveed
.
teeveed-0.2.2.jar
and example.teeveed.conf.rb
into
your teeveed folder.teeveed.sh
into your ~/bin
or somewhere else on your path,
and modify $TEEVEED_HOME
in it to point to your teeveed folder.Change example.teeveed.conf.rb
so that it matches your setup.
Important things to change:
database
command to match the setup of your Postgres databaselibrary
command's path should be '/path/to/your/media'teeveed
instanceThe index is stored in a PostgeSQL database, which gets us nice
full-text-search for free. Indexing is performed by crawling each
library section on a specified schedule, and adding new items, and
removing old items based on a last_seen
timestamp.
At some point we should use the following algorithm when returning search results, so that we never return a file that doesn't exist:
# Array<Media> returned in ranked order from best to worst match
results = root.search(:title => "the good the bad the ugly", :sense => :watch)
results.each do |hit|
path = Pathname.new(root.path) + hit.relative_path
if not path.exist?
hit.delete!
next
end
path = path.realpath.to_s
return Result.new(hit, path)
end
User story: you sit down on the couch and say, "Ok tv. do we have the new Game of Thrones?"
User story: you want to quickly start music playing while in the kitchen. "Ok tv. Play songs by Royksopp"
We use Wit.ai to interpret user intents from plain
text. Intent behavior is defined in lib/teevee/daemon/intent_controller.rb
,
which performs dispatch based on intent type.
teeveed uses a simple JavaFX window to display user intents and matched entities on-screen. All intents are automatically displayed before they are handled, and the results of the handler (anything with a :friendly_name) function are displayed when the handler completes.