integrity-nabaztag 0.0.0
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/Rakefile +13 -0
- data/VERSION +1 -0
- data/lib/integrity/notifier/config.haml +8 -0
- data/lib/integrity/notifier/nabaztag.rb +37 -0
- data/vendor/nabaztag-ruby/.gitignore +1 -0
- data/vendor/nabaztag-ruby/CHANGES +18 -0
- data/vendor/nabaztag-ruby/README +22 -0
- data/vendor/nabaztag-ruby/Rakefile +49 -0
- data/vendor/nabaztag-ruby/bin/nabaztag-say +97 -0
- data/vendor/nabaztag-ruby/lib/nabaztag.rb +160 -0
- data/vendor/nabaztag-ruby/lib/nabaztag/choreography.rb +119 -0
- data/vendor/nabaztag-ruby/lib/nabaztag/message.rb +75 -0
- data/vendor/nabaztag-ruby/lib/nabaztag/response.rb +78 -0
- data/vendor/nabaztag-ruby/sample/build.rb +35 -0
- data/vendor/nabaztag-ruby/sample/demo.rb +42 -0
- data/vendor/nabaztag-ruby/sample/interactive.rb +40 -0
- data/vendor/nabaztag-ruby/sample/speech.rb +39 -0
- data/vendor/nabaztag-ruby/setup.rb +1551 -0
- data/vendor/nabaztag-ruby/test/choreography_test.rb +42 -0
- data/vendor/nabaztag-ruby/test/message_test.rb +34 -0
- data/vendor/nabaztag-ruby/test/response_test.rb +32 -0
- metadata +75 -0
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
begin
|
2
|
+
require 'jeweler'
|
3
|
+
Jeweler::Tasks.new do |gemspec|
|
4
|
+
gemspec.name = "integrity-nabaztag"
|
5
|
+
gemspec.summary = "A Nabaztag notifier for integrity"
|
6
|
+
gemspec.description = "A Nabaztag notifier for integrity"
|
7
|
+
gemspec.email = "daniel@collectiveidea.com"
|
8
|
+
gemspec.homepage = "http://github.com/collectiveidea/integrity-nabaztag"
|
9
|
+
gemspec.authors = ["Daniel Morrison"]
|
10
|
+
end
|
11
|
+
rescue LoadError
|
12
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
13
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,8 @@
|
|
1
|
+
%p.normal
|
2
|
+
%label{ :for => "nabaztag_mac" } MAC Address
|
3
|
+
%input.text#nabaztag_mac{ :name => "notifiers[Nabaztag][mac]", :type => "text", :value => config["mac"] }
|
4
|
+
|
5
|
+
%p.normal
|
6
|
+
%label{ :for => "nabaztab_token" } Token
|
7
|
+
%input.text#nabaztab_token{ :name => "notifiers[Nabaztag][token]", :type => "text", :value => config["token"] }
|
8
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'integrity'
|
2
|
+
$:.unshift(File.dirname(__FILE__) + '/../../../vendor/nabaztag-ruby/lib')
|
3
|
+
require 'nabaztag'
|
4
|
+
|
5
|
+
module Integrity
|
6
|
+
class Notifier
|
7
|
+
class Nabaztag < Notifier::Base
|
8
|
+
attr_reader :config
|
9
|
+
|
10
|
+
def self.to_haml
|
11
|
+
File.read File.dirname(__FILE__) / "config.haml"
|
12
|
+
end
|
13
|
+
|
14
|
+
def deliver!
|
15
|
+
nabaztag.voice = 'US-Liberty'
|
16
|
+
nabaztag.say(message)
|
17
|
+
if commit.failed?
|
18
|
+
nabaztag.move_ears(10, 10)
|
19
|
+
else
|
20
|
+
nabaztag.move_ears(0, 0)
|
21
|
+
end
|
22
|
+
nabaztag.send
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def nabaztag
|
27
|
+
@nabaztag ||= ::Nabaztag.new(config['mac'], config['token'])
|
28
|
+
end
|
29
|
+
|
30
|
+
def message
|
31
|
+
"Build of #{commit.project.name} #{commit.successful? ? "was successful" : "failed"}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
register Nabaztag
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
pkg/Nabaztag-0.3.1.gem
|
@@ -0,0 +1,18 @@
|
|
1
|
+
= Changes
|
2
|
+
|
3
|
+
== 0.3.0
|
4
|
+
|
5
|
+
* Understands new XML responses from API
|
6
|
+
* Significant refactoring of response handling
|
7
|
+
|
8
|
+
== 0.2.0
|
9
|
+
|
10
|
+
* Version 2 API support
|
11
|
+
* Can speak French or English
|
12
|
+
* Added command-line utility, nabaztag-say
|
13
|
+
* Added gem
|
14
|
+
|
15
|
+
== 0.1
|
16
|
+
|
17
|
+
* Initial release
|
18
|
+
* Version 1 API only
|
@@ -0,0 +1,22 @@
|
|
1
|
+
= Nabaztag
|
2
|
+
|
3
|
+
== About
|
4
|
+
|
5
|
+
Nabaztag communication library for Ruby.
|
6
|
+
|
7
|
+
The Nabaztag is a small electronic rabbit with lights, motorised ears, and speech.
|
8
|
+
|
9
|
+
http://www.nabaztag.com/
|
10
|
+
|
11
|
+
== Copying
|
12
|
+
|
13
|
+
Copyright Revieworld Ltd. 2006
|
14
|
+
|
15
|
+
You may use, copy and redistribute this library under the same terms as Ruby itself
|
16
|
+
(http://www.ruby-lang.org/en/LICENSE.txt).
|
17
|
+
|
18
|
+
== Installation
|
19
|
+
|
20
|
+
To install (requires root/admin privileges):
|
21
|
+
|
22
|
+
# ruby setup.rb
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "rake/gempackagetask"
|
3
|
+
require "zlib"
|
4
|
+
require "rake/clean"
|
5
|
+
|
6
|
+
CLEAN.include("doc", "pkg")
|
7
|
+
|
8
|
+
SOURCES = FileList["lib/**/*.rb"]
|
9
|
+
|
10
|
+
spec = Gem::Specification.new do |s|
|
11
|
+
s.name = "Nabaztag"
|
12
|
+
s.version = "0.3.1"
|
13
|
+
s.author = "Paul Battley"
|
14
|
+
s.email = "paulbattley@reevoo.com"
|
15
|
+
s.summary = "Nabaztag communication library for Ruby."
|
16
|
+
s.files = SOURCES
|
17
|
+
s.require_path = "lib"
|
18
|
+
s.autorequire = "nabaztag"
|
19
|
+
s.has_rdoc = true
|
20
|
+
s.extra_rdoc_files = %w[README CHANGES]
|
21
|
+
s.executables << "nabaztag-say"
|
22
|
+
end
|
23
|
+
|
24
|
+
task :default => :package
|
25
|
+
|
26
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
27
|
+
pkg.need_tar_gz = true
|
28
|
+
end
|
29
|
+
|
30
|
+
task :package => %W[
|
31
|
+
pkg/#{spec.name}-#{spec.version}.gem
|
32
|
+
pkg/#{spec.name}-#{spec.version}.tar.gz
|
33
|
+
] do
|
34
|
+
puts "packaged version #{spec.version}"
|
35
|
+
end
|
36
|
+
|
37
|
+
file "doc" => SOURCES + spec.extra_rdoc_files do |t|
|
38
|
+
p t.prerequisites
|
39
|
+
rm_rf t.name
|
40
|
+
sh "rdoc #{t.prerequisites.join(" ")}"
|
41
|
+
end
|
42
|
+
|
43
|
+
task :tag do
|
44
|
+
unless (trunk = `svn info`[%r!URL: (.+/trunk)!, 1])
|
45
|
+
raise RuntimeError, "Couldn't determine trunk URL"
|
46
|
+
end
|
47
|
+
tag = trunk.sub(/trunk$/, "tags/#{spec.name.downcase}-#{spec.version}")
|
48
|
+
sh "svn cp #{trunk} #{tag} -m \"Automatically tagging version #{spec.version}\""
|
49
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'nabaztag'
|
4
|
+
require 'optparse'
|
5
|
+
load ENV['HOME'] + '/.nabaztag' rescue nil
|
6
|
+
|
7
|
+
OPTIONS = {
|
8
|
+
:mac => NABAZTAG_MAC,
|
9
|
+
:token => NABAZTAG_TOKEN,
|
10
|
+
}
|
11
|
+
|
12
|
+
class NabaztagSay
|
13
|
+
def list_voices
|
14
|
+
message = nabaztag.new_message
|
15
|
+
message.action = :get_voices
|
16
|
+
response = message.send
|
17
|
+
response.voices.each do |language, voices|
|
18
|
+
puts language
|
19
|
+
voices.sort.each do |v|
|
20
|
+
puts " #{v}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def nabaztag
|
26
|
+
@mabaztag ||= Nabaztag.new(OPTIONS[:mac], OPTIONS[:token])
|
27
|
+
end
|
28
|
+
|
29
|
+
def say!(sentence)
|
30
|
+
nabaztag.say!(sentence)
|
31
|
+
end
|
32
|
+
|
33
|
+
def voice=(v)
|
34
|
+
nabaztag.voice = v
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
n = NabaztagSay.new
|
39
|
+
|
40
|
+
ARGV.options do |o|
|
41
|
+
script_name = File.basename($0)
|
42
|
+
|
43
|
+
o.set_summary_indent(' ')
|
44
|
+
o.banner = "Usage: #{script_name} [OPTIONS] TEXT-TO-SAY"
|
45
|
+
o.define_head "Tell Nabaztag to say something."
|
46
|
+
o.separator ""
|
47
|
+
o.separator "If you create a file in your home directory called .nabaztag"
|
48
|
+
o.separator "containing the MAC and API token for your device, like this:"
|
49
|
+
o.separator " NABAZTAG_MAC = '00039XXXXXXX'"
|
50
|
+
o.separator " NABAZTAG_TOKEN = '1234XXXXXXXXXXX'"
|
51
|
+
o.separator "then you need not specify the MAC and token on the command line."
|
52
|
+
o.separator ""
|
53
|
+
o.separator "Options:"
|
54
|
+
|
55
|
+
begin
|
56
|
+
o.on(
|
57
|
+
"-m", "--mac=MAC", String,
|
58
|
+
"MAC address of device",
|
59
|
+
"Default is NABAZTAG_MAC in ~/.nabaztag"
|
60
|
+
) { |OPTIONS[:mac]| }
|
61
|
+
o.on(
|
62
|
+
"-t", "--token=TOKEN", String,
|
63
|
+
"API token",
|
64
|
+
"Default is NABAZTAG_TOKEN in ~/.nabaztag"
|
65
|
+
) { |OPTIONS[:token]| }
|
66
|
+
o.on(
|
67
|
+
"-v", "--voice=VOICE", String,
|
68
|
+
"Voice to use for speech"
|
69
|
+
) { |OPTIONS[:voice]| }
|
70
|
+
o.on(
|
71
|
+
"-l", "--list-voices",
|
72
|
+
"List available voices and exit"
|
73
|
+
) {
|
74
|
+
n.list_voices
|
75
|
+
exit
|
76
|
+
}
|
77
|
+
o.separator ""
|
78
|
+
o.on_tail("-h", "--help", "Show this help message.") { puts o; exit }
|
79
|
+
o.parse!
|
80
|
+
|
81
|
+
OPTIONS.each do |k,v|
|
82
|
+
if !v || v.empty?
|
83
|
+
raise RuntimeError, "Missing parameter #{v}"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
if ARGV.empty?
|
87
|
+
raise RuntimeError, "Nothing to say"
|
88
|
+
end
|
89
|
+
rescue StandardError => e
|
90
|
+
puts "Error: #{e.message}", ''
|
91
|
+
puts o
|
92
|
+
exit 1
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
n.voice = OPTIONS[:voice]
|
97
|
+
n.say!(ARGV.join(' '))
|
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'nabaztag/message'
|
2
|
+
require 'nabaztag/response'
|
3
|
+
require 'nabaztag/choreography'
|
4
|
+
|
5
|
+
#
|
6
|
+
# Nabaztag allows control of the text-to-speech, ear control, and choreography features of
|
7
|
+
# Nabaztag devices.
|
8
|
+
#
|
9
|
+
# To use this library, you need to know the MAC of the device (written on the base) and its
|
10
|
+
# API token. The token must be obtained from http://www.nabaztag.com/vl/FR/api_prefs.jsp .
|
11
|
+
#
|
12
|
+
# The API allows different commands to be dispatched simultaneously; in order to achieve this,
|
13
|
+
# this library queues commands until they are sent.
|
14
|
+
#
|
15
|
+
# E.g.
|
16
|
+
# nabaztag = Nabaztag.new(mac, token)
|
17
|
+
# nabaztag.say('bonjour') # Nothing sent yet
|
18
|
+
# nabaztag.move_ears(4, 4) # Still not sent
|
19
|
+
# nabaztag.send # Messages sent
|
20
|
+
#
|
21
|
+
# This also means that if two conflicting commands are issued without an intervening send,
|
22
|
+
# only the latter will be carried out.
|
23
|
+
#
|
24
|
+
# However, beware! The API doesn't seem to respond well if multiple commands are sent in
|
25
|
+
# a short period of time: it can become confused and send erroneous commands to the device.
|
26
|
+
#
|
27
|
+
# In addition, the choreography command does not seem to play well with other commands: if
|
28
|
+
# text-to-speech and choreography are sent in one request, only the speech will get through
|
29
|
+
# to the rabbit.
|
30
|
+
#
|
31
|
+
# With version 2 of the API, it is now possible to specify a voice for the message. The
|
32
|
+
# default is determined by the rabbit's language (claire22s for French; heather22k for
|
33
|
+
# English). The voice's language overrides that of the rabbit: i.e. a French rabbit will
|
34
|
+
# speak in English when told to use an English voice.
|
35
|
+
#
|
36
|
+
# The known voices are grouped by language in the Nabaztag::VOICES constant, but no attempt
|
37
|
+
# is made to validate against this list, as Violet may introduce additional voices in future.
|
38
|
+
#
|
39
|
+
class Nabaztag
|
40
|
+
|
41
|
+
class ServiceError < RuntimeError ; end
|
42
|
+
|
43
|
+
attr_reader :mac, :token, :message
|
44
|
+
attr_accessor :voice
|
45
|
+
|
46
|
+
#
|
47
|
+
# Create a new Nabaztag instance to communicate with the device with the given MAC address and
|
48
|
+
# service token (see class overview for explanation of token).
|
49
|
+
#
|
50
|
+
def initialize(mac, token)
|
51
|
+
@mac, @token = mac, token
|
52
|
+
@message = new_message
|
53
|
+
@ear_positions = [nil, nil]
|
54
|
+
end
|
55
|
+
|
56
|
+
#
|
57
|
+
# Send all pending messages
|
58
|
+
#
|
59
|
+
def send
|
60
|
+
@message.voice = voice
|
61
|
+
response = @message.send
|
62
|
+
@message = new_message
|
63
|
+
unless response.success?
|
64
|
+
raise ServiceError, response.raw
|
65
|
+
end
|
66
|
+
return response
|
67
|
+
end
|
68
|
+
|
69
|
+
#
|
70
|
+
# Send a message immediately to get the ear positions.
|
71
|
+
#
|
72
|
+
def ear_positions
|
73
|
+
ear_message = new_message
|
74
|
+
ear_message.ears = 'ok'
|
75
|
+
response = ear_message.send
|
76
|
+
return [response.left_ear, response.right_ear]
|
77
|
+
end
|
78
|
+
|
79
|
+
#
|
80
|
+
# Say text.
|
81
|
+
#
|
82
|
+
def say(text)
|
83
|
+
message.tts = text
|
84
|
+
nil
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# Say text immediately.
|
89
|
+
#
|
90
|
+
def say!(text)
|
91
|
+
say(text)
|
92
|
+
send
|
93
|
+
end
|
94
|
+
|
95
|
+
#
|
96
|
+
# Make the rabbit bark.
|
97
|
+
#
|
98
|
+
def bark
|
99
|
+
say('ouah ouah')
|
100
|
+
nil
|
101
|
+
end
|
102
|
+
|
103
|
+
#
|
104
|
+
# Bark immediately.
|
105
|
+
#
|
106
|
+
def bark!
|
107
|
+
bark
|
108
|
+
send
|
109
|
+
end
|
110
|
+
|
111
|
+
#
|
112
|
+
# Set the position of the left and right ears between 0 and 16. Use nil to avoid moving an ear.
|
113
|
+
# Note that these positions are not given in degrees, and that it is not possible to specify the
|
114
|
+
# direction of movement. For more precise ear control, use choreography instead.
|
115
|
+
#
|
116
|
+
def move_ears(left, right)
|
117
|
+
message.posleft = left if left
|
118
|
+
message.posright = right if right
|
119
|
+
nil
|
120
|
+
end
|
121
|
+
|
122
|
+
#
|
123
|
+
# Move ears immediately.
|
124
|
+
#
|
125
|
+
def move_ears!(left, right)
|
126
|
+
move_ears(left, right)
|
127
|
+
send
|
128
|
+
end
|
129
|
+
|
130
|
+
#
|
131
|
+
# Creates a new choreography message based on the actions instructed in the block. The commands
|
132
|
+
# are evaluated in the context of a new Choreography instance.
|
133
|
+
#
|
134
|
+
# E.g.
|
135
|
+
# nabaztag.choreography do
|
136
|
+
# together { led :middle, :green ; led :left, :red }
|
137
|
+
# led :right, :yellow
|
138
|
+
# together { led :left, :off ; led :right, :off}
|
139
|
+
# ...
|
140
|
+
# end
|
141
|
+
#
|
142
|
+
def choreography(title=nil, &blk)
|
143
|
+
message.chortitle = title
|
144
|
+
message.chor = Choreography.new(&blk).build
|
145
|
+
nil
|
146
|
+
end
|
147
|
+
|
148
|
+
#
|
149
|
+
# Creates choreography and sends it immediately.
|
150
|
+
#
|
151
|
+
def choreography!(title=nil, &blk)
|
152
|
+
choreography(title, &blk)
|
153
|
+
send
|
154
|
+
end
|
155
|
+
|
156
|
+
def new_message
|
157
|
+
return Message.new(mac, token)
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
class Nabaztag
|
2
|
+
|
3
|
+
#
|
4
|
+
# The Choreography class uses class methods to implement a simple DSL. These build API choreography
|
5
|
+
# messages based on instructions to move the ears and light the LEDs.
|
6
|
+
#
|
7
|
+
class Choreography
|
8
|
+
|
9
|
+
LED_COLORS = {
|
10
|
+
:red => [255, 0, 0],
|
11
|
+
:orange => [255, 127, 0],
|
12
|
+
:yellow => [255, 255, 0],
|
13
|
+
:green => [ 0, 255, 0],
|
14
|
+
:blue => [ 0, 0, 255],
|
15
|
+
:purple => [255, 0, 255],
|
16
|
+
:dim_red => [127, 0, 0],
|
17
|
+
:dim_orange => [127, 63, 0],
|
18
|
+
:dim_yellow => [127, 127, 0],
|
19
|
+
:dim_green => [ 0, 127, 0],
|
20
|
+
:dim_blue => [ 0, 0, 127],
|
21
|
+
:dim_purple => [127, 0, 127],
|
22
|
+
:off => [ 0, 0, 0]
|
23
|
+
}
|
24
|
+
EARS = {:left => [1], :right => [0], :both => [0,1]}
|
25
|
+
LEDS = {:bottom => 0, :left => 1, :middle => 2, :right => 3, :top => 4}
|
26
|
+
EAR_DIRECTIONS = {:forward => 0, :backward => 1}
|
27
|
+
|
28
|
+
def initialize(&blk)
|
29
|
+
@messages = []
|
30
|
+
@tempo = 10
|
31
|
+
@time_stamp = 0
|
32
|
+
instance_eval(&blk) if block_given?
|
33
|
+
end
|
34
|
+
|
35
|
+
def build
|
36
|
+
return (['%d' % @tempo] + @messages).join(',')
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# Set the tempo of the choreography in Hz (i.e. events per secod). The default is 10
|
41
|
+
# events per second.
|
42
|
+
#
|
43
|
+
def tempo(t)
|
44
|
+
@tempo = t
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# Move :left, :right, or :both ears to angle degrees (0-180) in direction
|
49
|
+
# :forward (default) or :backward.
|
50
|
+
#
|
51
|
+
def ear(which_ear, angle, direction=:forward)
|
52
|
+
direction_number = EAR_DIRECTIONS[direction]
|
53
|
+
EARS[which_ear].each do |ear_number|
|
54
|
+
append_message('motor', ear_number, angle, 0, direction_number)
|
55
|
+
end
|
56
|
+
advance
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# Change colour of an led (:top, :right:, middle, :left, :bottom) to a specified colour.
|
61
|
+
# The colour may be specified either as RGB values (0-255) or by using one of the named colours
|
62
|
+
# in LED_COLORS.
|
63
|
+
#
|
64
|
+
# E.g.
|
65
|
+
# led :middle, :red
|
66
|
+
# led :top, 0, 0, 255
|
67
|
+
# led :bottom, :off
|
68
|
+
#
|
69
|
+
def led(which_led, c1, c2=nil, c3=nil)
|
70
|
+
led_number = LEDS[which_led]
|
71
|
+
if (c1 && c2 && c3)
|
72
|
+
red, green, blue = c1, c2, c3
|
73
|
+
else
|
74
|
+
red, green, blue = LED_COLORS[c1]
|
75
|
+
end
|
76
|
+
append_message('led', led_number, red, green, blue)
|
77
|
+
advance
|
78
|
+
end
|
79
|
+
|
80
|
+
#
|
81
|
+
# Group several actions into a single chronological step via a block.
|
82
|
+
#
|
83
|
+
# E.g.
|
84
|
+
# event { led :top, :yellow ; ear :both, 0 }
|
85
|
+
#
|
86
|
+
def event(duration=1, &blk)
|
87
|
+
length(duration, &blk)
|
88
|
+
end
|
89
|
+
|
90
|
+
alias_method :together, :event
|
91
|
+
|
92
|
+
#
|
93
|
+
# Perform one or more actions for n chronological steps
|
94
|
+
#
|
95
|
+
# E.g.
|
96
|
+
# length 3 do
|
97
|
+
# led :top, :red ; led :middle, :yellow
|
98
|
+
# end
|
99
|
+
#
|
100
|
+
def length(duration, &blk)
|
101
|
+
old_in_event = @in_event
|
102
|
+
@in_event = true
|
103
|
+
yield
|
104
|
+
@in_event = old_in_event
|
105
|
+
advance duration
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def append_message(*params)
|
111
|
+
@messages << ("%d,%s,%d,%d,%d,%d" % ([@time_stamp] + params))
|
112
|
+
end
|
113
|
+
|
114
|
+
def advance(duration=1)
|
115
|
+
@time_stamp += duration unless @in_event
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
end
|