james 0.1.0-universal-darwin-10 → 0.1.1-universal-darwin-10
Sign up to get free protection for your applications and to get access to all the features.
- data/aux/james/cli.rb +9 -1
- data/bin/james +5 -0
- data/lib/james.rb +4 -6
- data/lib/james/controller.rb +35 -38
- data/lib/james/dialog_api.rb +6 -2
- data/lib/james/inputs/audio.rb +4 -1
- data/lib/james/inputs/base.rb +9 -2
- data/lib/james/inputs/terminal.rb +15 -2
- data/lib/james/outputs/audio.rb +9 -3
- data/lib/james/outputs/terminal.rb +10 -0
- data/lib/james/visitor.rb +1 -8
- data/lib/james/visitors.rb +3 -7
- data/spec/lib/james/controller_spec.rb +3 -0
- data/spec/lib/james/dialog_spec.rb +0 -13
- data/spec/lib/james/inputs/audio_spec.rb +18 -0
- data/spec/lib/james/inputs/terminal_spec.rb +12 -0
- metadata +6 -3
- data/lib/james/timer.rb +0 -14
data/aux/james/cli.rb
CHANGED
@@ -5,6 +5,10 @@ module James
|
|
5
5
|
class CLI
|
6
6
|
|
7
7
|
def execute *patterns
|
8
|
+
silent = patterns.delete '-s'
|
9
|
+
silent_input = patterns.delete '-si'
|
10
|
+
silent_output = patterns.delete '-so'
|
11
|
+
|
8
12
|
dialogs = find_dialogs_for patterns
|
9
13
|
|
10
14
|
puts "James: I haven't found anything to talk about (No files found). Exiting." or exit!(1) if dialogs.empty?
|
@@ -12,7 +16,11 @@ module James
|
|
12
16
|
|
13
17
|
load_all dialogs
|
14
18
|
|
15
|
-
|
19
|
+
options = {}
|
20
|
+
options[:input] = Inputs::Terminal if silent || silent_input
|
21
|
+
options[:output] = Outputs::Terminal if silent || silent_output
|
22
|
+
|
23
|
+
James.listen options
|
16
24
|
end
|
17
25
|
def find_dialogs_for patterns
|
18
26
|
patterns = ["**/*_dialog{,ue}.rb"] if patterns.empty?
|
data/bin/james
CHANGED
data/lib/james.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
module James; end
|
2
2
|
|
3
|
-
# require File.expand_path '../james/timer', __FILE__
|
4
|
-
|
5
3
|
require File.expand_path '../james/state_api', __FILE__
|
6
4
|
require File.expand_path '../james/state_internals', __FILE__
|
7
5
|
|
@@ -35,18 +33,18 @@ module James
|
|
35
33
|
dialogs.each { |dialog| controller.add_dialog dialog }
|
36
34
|
end
|
37
35
|
|
38
|
-
# Start
|
36
|
+
# Start listening.
|
39
37
|
#
|
40
38
|
# Will not listen again if already listening.
|
41
39
|
#
|
42
|
-
def self.listen
|
43
|
-
controller.listen
|
40
|
+
def self.listen options
|
41
|
+
controller.listen options
|
44
42
|
end
|
45
43
|
|
46
44
|
# Controller instance.
|
47
45
|
#
|
48
46
|
def self.controller
|
49
|
-
|
47
|
+
Controller.instance
|
50
48
|
end
|
51
49
|
|
52
50
|
end
|
data/lib/james/controller.rb
CHANGED
@@ -2,21 +2,34 @@ module James
|
|
2
2
|
|
3
3
|
class Controller
|
4
4
|
|
5
|
-
attr_reader :visitor
|
5
|
+
attr_reader :visitor, :listening
|
6
|
+
|
7
|
+
# Singleton reader.
|
8
|
+
#
|
9
|
+
def self.instance
|
10
|
+
@controller ||= new
|
11
|
+
end
|
6
12
|
|
7
13
|
# This puts together the core dialog and the user
|
8
14
|
# ones that are hooked into it.
|
9
15
|
#
|
10
16
|
# TODO Rewrite this. Design needs some refactoring.
|
17
|
+
# Should the user visitor be created dynamically? (Probably yes.)
|
11
18
|
#
|
12
19
|
def initialize
|
13
|
-
@user_dialogs
|
14
|
-
|
15
|
-
|
20
|
+
@user_dialogs = Dialogs.new
|
21
|
+
@visitor = Visitors.new system_visitor, user_visitor
|
22
|
+
end
|
23
|
+
def system_visitor
|
24
|
+
Visitor.new CoreDialog.new.state_for(:awake)
|
25
|
+
end
|
26
|
+
def user_visitor
|
27
|
+
@user_dialogs.visitor
|
16
28
|
end
|
17
29
|
|
30
|
+
# MacRuby callback functions.
|
31
|
+
#
|
18
32
|
def applicationDidFinishLaunching notification
|
19
|
-
load_voices
|
20
33
|
start_output
|
21
34
|
start_input
|
22
35
|
end
|
@@ -24,12 +37,6 @@ module James
|
|
24
37
|
exit
|
25
38
|
end
|
26
39
|
|
27
|
-
# Load voices from yaml.
|
28
|
-
#
|
29
|
-
def load_voices
|
30
|
-
# TODO
|
31
|
-
end
|
32
|
-
|
33
40
|
# Add a dialog to the current system.
|
34
41
|
#
|
35
42
|
def add_dialog dialog
|
@@ -39,13 +46,13 @@ module James
|
|
39
46
|
# Start recognizing words.
|
40
47
|
#
|
41
48
|
def start_input
|
42
|
-
@input =
|
49
|
+
@input = @input_class.new self
|
43
50
|
@input.listen
|
44
51
|
end
|
45
52
|
# Start speaking.
|
46
53
|
#
|
47
54
|
def start_output
|
48
|
-
@output =
|
55
|
+
@output = @output_class.new @output_options
|
49
56
|
end
|
50
57
|
|
51
58
|
# Callback method from dialog.
|
@@ -62,38 +69,28 @@ module James
|
|
62
69
|
visitor.expects
|
63
70
|
end
|
64
71
|
|
65
|
-
|
72
|
+
# Start listening using the provided options.
|
73
|
+
#
|
74
|
+
# Options:
|
75
|
+
# * input # Inputs::Terminal or Inputs::Audio (default).
|
76
|
+
# * output # Outputs::Terminal or Outputs::Audio (default).
|
77
|
+
#
|
78
|
+
def listen options = {}
|
79
|
+
return if listening
|
80
|
+
|
81
|
+
@input_class = options[:input] || Inputs::Audio
|
82
|
+
@output_class = options[:output] || Outputs::Audio
|
83
|
+
|
84
|
+
@output_options ||= {}
|
85
|
+
@output_options[:voice] = options[:voice] || 'com.apple.speech.synthesis.voice.Alex'
|
86
|
+
|
66
87
|
app = NSApplication.sharedApplication
|
67
88
|
app.delegate = self
|
68
89
|
|
69
|
-
# window = NSWindow.alloc.initWithContentRect([100, 300, 300, 100],
|
70
|
-
# styleMask:NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask,
|
71
|
-
# backing:NSBackingStoreBuffered,
|
72
|
-
# defer:false)
|
73
|
-
# window.title = 'James Debug/Info'
|
74
|
-
# window.level = 3
|
75
|
-
# window.delegate = app.delegate
|
76
|
-
|
77
|
-
# @button = NSButton.alloc.initWithFrame([10, 10, 400, 10])
|
78
|
-
# @button.bezelStyle = 4
|
79
|
-
# @button.title = ''
|
80
|
-
# @button.target = app.delegate
|
81
|
-
# @button.action = 'say_hello:'
|
82
|
-
#
|
83
|
-
# window.contentView.addSubview(@button)
|
84
|
-
|
85
|
-
# window.display
|
86
|
-
# window.orderFrontRegardless
|
87
|
-
|
88
90
|
@listening = true
|
89
91
|
|
90
92
|
app.run
|
91
93
|
end
|
92
|
-
# If listen has been called, it is listening.
|
93
|
-
#
|
94
|
-
def listening?
|
95
|
-
!!@listening
|
96
|
-
end
|
97
94
|
|
98
95
|
end
|
99
96
|
|
data/lib/james/dialog_api.rb
CHANGED
@@ -2,7 +2,7 @@ module James
|
|
2
2
|
|
3
3
|
# A dialog can be instantiated in two ways:
|
4
4
|
#
|
5
|
-
# The simple way
|
5
|
+
# The simple way will directly add itself to James.
|
6
6
|
#
|
7
7
|
# James.use_dialog(optional_args_for_initialize) do
|
8
8
|
# # Your dialog.
|
@@ -10,12 +10,16 @@ module James
|
|
10
10
|
# end
|
11
11
|
#
|
12
12
|
# class MyDialog
|
13
|
+
#
|
13
14
|
# include James::Dialog
|
14
15
|
#
|
15
|
-
# # Your dialog.
|
16
|
+
# # Your dialog definition.
|
16
17
|
# #
|
18
|
+
#
|
17
19
|
# end
|
18
20
|
#
|
21
|
+
# # Tell James to use the dialog.
|
22
|
+
# #
|
19
23
|
# James.use MyDialog.new
|
20
24
|
#
|
21
25
|
module Dialog; end
|
data/lib/james/inputs/audio.rb
CHANGED
@@ -33,7 +33,10 @@ module James
|
|
33
33
|
end
|
34
34
|
def recognize_new_commands
|
35
35
|
possibilities = controller.expects
|
36
|
-
puts "Possibilities:\n
|
36
|
+
puts "Possibilities:\n"
|
37
|
+
possibilities.each_with_index do |possibility, index|
|
38
|
+
puts "#{index + 1}) #{possibility}"
|
39
|
+
end
|
37
40
|
@recognizer.setCommands possibilities
|
38
41
|
end
|
39
42
|
|
data/lib/james/inputs/base.rb
CHANGED
@@ -13,11 +13,18 @@ module James
|
|
13
13
|
# Call this method if you heard something in the subclass.
|
14
14
|
#
|
15
15
|
def heard command
|
16
|
-
# Call dialog.
|
17
|
-
#
|
18
16
|
controller.hear command
|
19
17
|
end
|
20
18
|
|
19
|
+
# Shows possible commands in the terminal.
|
20
|
+
#
|
21
|
+
def show_possibilities possibilities
|
22
|
+
puts "Possibilities:\n"
|
23
|
+
possibilities.each_with_index do |possibility, index|
|
24
|
+
puts "#{index + 1}) #{possibility}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
21
28
|
end
|
22
29
|
|
23
30
|
end
|
@@ -6,17 +6,30 @@ module James
|
|
6
6
|
#
|
7
7
|
class Terminal < Base
|
8
8
|
|
9
|
+
# Start listening to commands by the user.
|
10
|
+
#
|
9
11
|
def listen
|
10
12
|
sleep 2
|
11
13
|
loop do
|
12
14
|
possibilities = controller.expects
|
13
|
-
|
14
|
-
command =
|
15
|
+
show_possibilities possibilities
|
16
|
+
command = get_command
|
15
17
|
puts "I heard '#{command}'."
|
18
|
+
command = possibilities[command.to_i-1] unless command.to_i.zero?
|
16
19
|
heard command if possibilities.include? command
|
17
20
|
end
|
18
21
|
end
|
19
22
|
|
23
|
+
# Get the next command by the user.
|
24
|
+
#
|
25
|
+
def get_command
|
26
|
+
STDIN.gets.chop
|
27
|
+
rescue IOError
|
28
|
+
puts "Wait a second, please, Sir, I am busy."
|
29
|
+
sleep 1
|
30
|
+
retry
|
31
|
+
end
|
32
|
+
|
20
33
|
end
|
21
34
|
|
22
35
|
end
|
data/lib/james/outputs/audio.rb
CHANGED
@@ -4,11 +4,17 @@ module James
|
|
4
4
|
|
5
5
|
class Audio
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
# Create a new audio output.
|
8
|
+
#
|
9
|
+
# Options:
|
10
|
+
# * voice # Default is 'com.apple.speech.synthesis.voice.Alex'.
|
11
|
+
#
|
12
|
+
def initialize options = {}
|
13
|
+
@output = NSSpeechSynthesizer.alloc.initWithVoice options[:voice] || 'com.apple.speech.synthesis.voice.Alex'
|
10
14
|
end
|
11
15
|
|
16
|
+
# Say the given text out loud.
|
17
|
+
#
|
12
18
|
def say text
|
13
19
|
@output.startSpeakingString text
|
14
20
|
end
|
data/lib/james/visitor.rb
CHANGED
@@ -6,10 +6,6 @@ module James
|
|
6
6
|
# too much time passes without input.
|
7
7
|
#
|
8
8
|
# Note: A visitor should generally be very stupid.
|
9
|
-
# Note 2: We could call this Hearing, or Ear ;)
|
10
|
-
#
|
11
|
-
# TODO Add a timer which resets the state to the
|
12
|
-
# initial state.
|
13
9
|
#
|
14
10
|
class Visitor
|
15
11
|
|
@@ -18,17 +14,15 @@ module James
|
|
18
14
|
|
19
15
|
# Pass in an initial state to start from.
|
20
16
|
#
|
21
|
-
def initialize initial
|
17
|
+
def initialize initial
|
22
18
|
@current = initial
|
23
19
|
|
24
20
|
@initial = initial
|
25
|
-
# @timer = timer || Timer.new
|
26
21
|
end
|
27
22
|
|
28
23
|
# Resets the current state back to the initial.
|
29
24
|
#
|
30
25
|
def reset
|
31
|
-
# timer.stop
|
32
26
|
self.current = initial
|
33
27
|
end
|
34
28
|
|
@@ -59,7 +53,6 @@ module James
|
|
59
53
|
end
|
60
54
|
def hear phrase, &block
|
61
55
|
return unless hears? phrase
|
62
|
-
# timer.restart
|
63
56
|
exit_text = exit &block
|
64
57
|
transition phrase
|
65
58
|
check &block
|
data/lib/james/visitors.rb
CHANGED
@@ -22,10 +22,6 @@ module James
|
|
22
22
|
@visitors = visitors
|
23
23
|
end
|
24
24
|
|
25
|
-
def add_dialog dialog
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
25
|
# Hear tries all visitors in order
|
30
26
|
# until one hears a phrase he knows.
|
31
27
|
#
|
@@ -38,18 +34,18 @@ module James
|
|
38
34
|
visitor.hear phrase, &block and break
|
39
35
|
end
|
40
36
|
|
41
|
-
|
37
|
+
enumerator.each do |visitor|
|
42
38
|
visitor.reset
|
43
39
|
end
|
44
40
|
end
|
45
41
|
|
46
|
-
# Enter enters the first
|
42
|
+
# Enter enters the first visitor.
|
47
43
|
#
|
48
44
|
def enter
|
49
45
|
visitors.first.enter
|
50
46
|
end
|
51
47
|
|
52
|
-
# Simply returns the sum of what phrases all dialogs expect.
|
48
|
+
# Simply returns the sum of what phrases all dialogs do expect, front-to-back.
|
53
49
|
#
|
54
50
|
# Stops as soon as a visitor is not in a chainable state anymore.
|
55
51
|
#
|
@@ -7,6 +7,9 @@ require File.expand_path '../../../../lib/james/visitors', __FILE__
|
|
7
7
|
require File.expand_path '../../../../lib/james/visitor', __FILE__
|
8
8
|
require File.expand_path '../../../../lib/james/state_api', __FILE__
|
9
9
|
require File.expand_path '../../../../lib/james/dialogs', __FILE__
|
10
|
+
require File.expand_path '../../../../lib/james/inputs/base', __FILE__
|
11
|
+
require File.expand_path '../../../../lib/james/inputs/terminal', __FILE__
|
12
|
+
require File.expand_path '../../../../lib/james/inputs/audio', __FILE__
|
10
13
|
require File.expand_path '../../../../lib/james/controller', __FILE__
|
11
14
|
|
12
15
|
describe James::Controller do
|
@@ -9,10 +9,6 @@ require File.expand_path '../../../../lib/james/dialogs', __FILE__
|
|
9
9
|
|
10
10
|
describe James::Dialog do
|
11
11
|
|
12
|
-
it 'can haz merkin spellink' do
|
13
|
-
James::Dialog.should == James::Dialog
|
14
|
-
end
|
15
|
-
|
16
12
|
context 'units' do
|
17
13
|
let(:dialog) do
|
18
14
|
James.use_dialog do
|
@@ -89,15 +85,6 @@ describe James::Dialog do
|
|
89
85
|
end
|
90
86
|
end.to_not raise_error
|
91
87
|
end
|
92
|
-
it 'can haz merkin spellink' do
|
93
|
-
expect do
|
94
|
-
James.dialog do
|
95
|
-
|
96
|
-
hear 'something' => :some_state
|
97
|
-
|
98
|
-
end
|
99
|
-
end.to_not raise_error
|
100
|
-
end
|
101
88
|
end
|
102
89
|
|
103
90
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
require File.expand_path '../../../../../lib/james/inputs/base', __FILE__
|
4
|
+
require File.expand_path '../../../../../lib/james/inputs/audio', __FILE__
|
5
|
+
|
6
|
+
describe James::Inputs::Audio do
|
7
|
+
|
8
|
+
let(:input) { described_class.new }
|
9
|
+
|
10
|
+
describe 'speechRecognizer' do
|
11
|
+
it 'does something' do
|
12
|
+
sender = stub :sender
|
13
|
+
|
14
|
+
input.speechRecognizer sender
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
require File.expand_path '../../../../../lib/james/inputs/base', __FILE__
|
4
|
+
require File.expand_path '../../../../../lib/james/inputs/terminal', __FILE__
|
5
|
+
|
6
|
+
describe James::Inputs::Terminal do
|
7
|
+
|
8
|
+
let(:input) { described_class.new }
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
end
|
metadata
CHANGED
@@ -2,14 +2,14 @@
|
|
2
2
|
name: james
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.1.
|
5
|
+
version: 0.1.1
|
6
6
|
platform: universal-darwin-10
|
7
7
|
authors:
|
8
8
|
- Florian Hanke
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-05-
|
12
|
+
date: 2011-05-29 00:00:00 +10:00
|
13
13
|
default_executable: james
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -49,7 +49,6 @@ files:
|
|
49
49
|
- lib/james/outputs/terminal.rb
|
50
50
|
- lib/james/state_api.rb
|
51
51
|
- lib/james/state_internals.rb
|
52
|
-
- lib/james/timer.rb
|
53
52
|
- lib/james/visitor.rb
|
54
53
|
- lib/james/visitors.rb
|
55
54
|
- lib/james.rb
|
@@ -58,6 +57,8 @@ files:
|
|
58
57
|
- spec/integration/test_dialogue_spec.rb
|
59
58
|
- spec/lib/james/controller_spec.rb
|
60
59
|
- spec/lib/james/dialog_spec.rb
|
60
|
+
- spec/lib/james/inputs/audio_spec.rb
|
61
|
+
- spec/lib/james/inputs/terminal_spec.rb
|
61
62
|
- spec/lib/james/state_spec.rb
|
62
63
|
- spec/lib/james/visitor_spec.rb
|
63
64
|
- spec/lib/james/visitors_spec.rb
|
@@ -92,6 +93,8 @@ test_files:
|
|
92
93
|
- spec/integration/test_dialogue_spec.rb
|
93
94
|
- spec/lib/james/controller_spec.rb
|
94
95
|
- spec/lib/james/dialog_spec.rb
|
96
|
+
- spec/lib/james/inputs/audio_spec.rb
|
97
|
+
- spec/lib/james/inputs/terminal_spec.rb
|
95
98
|
- spec/lib/james/state_spec.rb
|
96
99
|
- spec/lib/james/visitor_spec.rb
|
97
100
|
- spec/lib/james/visitors_spec.rb
|