2012-10-31

No, I haven't been burning the oatmeal, but while doing some tests for a new project, I did write another network accessible wrapper to the espeak "text to speech" software. This time, I used the Ruby programming language and the webrick Ruby module which makes writing little web servers a snap.

For the longest time, I had a fairly negative opinion of the Ruby language. However, now that I've written some stuff with Ruby, I actually find the language quite pleasant. There are however, still a few drawbacks for me:

  • Rails. Since Ruby on Rails is arguably the flagship Ruby application, searching the web for solutions to ruby issues usually turns up a lot of Rails specific solutions.
  • The Gems package management system. Ruby libraries that are not part of the Ruby core or the Ruby standard library are usually distributed as a "Gem" and installed via the Gem package manager (that always seems to be at odds with my operating system)
  • Some other stuff because I'm a grump who doesn't like anything.

Actually, none of that is a problem with Ruby itself, so I should really just shut my pie hole. Alright, back to the applications.

What I wanted was a web page I could access with any browser and enter text for the host machine to speak, and a URL that I could hit with curl or wget in order to get the host machine to speak text that I send to it.

Oh wait! There is something I really don't like about ruby: the way multi-line comments are handled. blech! OK, rant over. (seriously, go look it up)

Enter the Ruby

#!/usr/bin/env ruby
require 'webrick'

#create the html of the 'index' page
@index_html="<html>
<head>
<title>Time Talky Thing</title>
</head>
<body>
<form target='iframe' action='/speak'>
<label for='string'>Text to Speak:</label><br>
<input type='text' name='text'><br>
<label for='delay_minutes'>Delay Minutes:</label><br>"
@index_html += "<select name='delay_minutes'>"
  (0..100).each do |i|
    @index_html += "<option>#{i}</option>"
  end
@index_html += "</select>"
    
@index_html+="<input type='submit' name='Submit'>
</form>
<iframe name='iframe'></iframe>
</body>
</html>"

#function to run when / is requested
def index (reqresp)
  resp['Content-Type'] = 'text/html'
  resp.body @index_html
end

#function to run when /speak is requested
def speak (reqresp)
  #get data from the request
  text req.query['text']
  delay req.query['delay_minutes'].to_i 60
  resp['Content-Type'] = 'text/plain'
  resp.body "OK"
  speak_stringtextdelay)
end

def speak_stringtextdelay )
  #build a command 
  cmd ""
  cmd += "sleep #{delay&& " if delay
  cmd += "espeak  -a150 -s150 -g7 -ven-us+f3  \"#{text}\"" if text
  #if there is a command, run it in a new thread
  unless cmd.empty?
    Thread.new do
      IO.popen(cmd)
    end
  end
end

# Initialize our WEBrick server
if $0 == __FILE__ 
  config = {:Port => 8000}
  server WEBrick::HTTPServer.new(config)
  #what urls do we need to mount?
  server.mount_proc('/'do |reqresp
    indexreqresp )
  end
  server.mount_proc('/speak'do |reqresp
    speakreqresp )
  end
  
  trap "INT" do 
    server.shutdown 
  end
  server.start
  
end

Code also available at: http://hoof.jezra.net/snip/o5
What's Happening? Run the code and point a browser at NAME_OF_MACHINE:8000 and you will be presented with a basic page with a form and an iframe. The form has the iframe as its "target" and the "/speak" url as its 'action'. This keeps things simple from an end users point of view since the page never needs to refresh.

If I don't want to use the form, I can simply send a command such as

curl HOSTNAME:8000/speak?text=check+the+oatmeal+jackass&delay_minutes=4

to tell me what to do in 4 minutes. ha!

The only downsides to this are:

  1. having to URLencode strings that need to be spoken
  2. the length limit of a GET request

Now I need to run this code on the NaNoBox (and install a speaker in the box).

sweet sauce, another internetted thing. Actually, it would be best to run this code on a computer in a toaster.

Comments
Name:
not required
Email:
not required (will not be displayed)
Website:
not required (will link your name to your site)
Comment:
required
Please do not post HTML code or bbcode unless you want it to show up as code in your post. (or if you are a blog spammer, in which case, you probably aren't reading this anyway).
Prove you are human by solving a math problem! I'm sorry, but due to an increase of blog spam, I've had to implement a CAPTCHA.
Problem:
3 minus 1
Answer:
required
subscribe
 
2016
2015
2014
2013
2012
2011
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008