james 0.1.0-universal-darwin-10 → 0.1.1-universal-darwin-10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|