qcmd 0.1.15 → 0.1.16.pre
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/lib/qcmd/actions/base_action.rb +72 -8
- data/lib/qcmd/actions/cue_action.rb +7 -2
- data/lib/qcmd/aliases.rb +3 -1
- data/lib/qcmd/commands.rb +22 -0
- data/lib/qcmd/version.rb +1 -1
- data/spec/unit/action_spec.rb +67 -0
- data/spec/unit/parser_spec.rb +5 -0
- metadata +10 -7
@@ -1,6 +1,7 @@
|
|
1
1
|
module Qcmd
|
2
2
|
class BaseAction
|
3
3
|
attr_reader :code
|
4
|
+
attr_accessor :modification
|
4
5
|
|
5
6
|
# initialize and evaluate in one shot
|
6
7
|
def self.evaluate action_input
|
@@ -24,7 +25,7 @@ module Qcmd
|
|
24
25
|
expression = Qcmd::Parser.parse(expression)
|
25
26
|
end
|
26
27
|
|
27
|
-
|
28
|
+
parse(expression)
|
28
29
|
end
|
29
30
|
|
30
31
|
def evaluate
|
@@ -32,7 +33,7 @@ module Qcmd
|
|
32
33
|
nil
|
33
34
|
else
|
34
35
|
@code = code.map do |token|
|
35
|
-
if token.is_a?(
|
36
|
+
if token.is_a?(BaseAction)
|
36
37
|
Qcmd.debug "[Action evaluate] evaluating nested action: #{ token.code.inspect }"
|
37
38
|
token.evaluate
|
38
39
|
else
|
@@ -42,17 +43,22 @@ module Qcmd
|
|
42
43
|
|
43
44
|
Qcmd.debug "[Action evaluate] evaluating code: #{ code.inspect }"
|
44
45
|
|
45
|
-
send_message
|
46
|
+
response = send_message
|
47
|
+
if modification
|
48
|
+
modification.call(response)
|
49
|
+
else
|
50
|
+
response
|
51
|
+
end
|
46
52
|
end
|
47
53
|
end
|
48
54
|
|
55
|
+
# convert nested arrays into new actions
|
49
56
|
def parse(expression)
|
50
|
-
# unwrap nested arrays
|
51
57
|
if expression.size == 1 && expression[0].is_a?(Array)
|
52
58
|
expression = expression[0]
|
53
59
|
end
|
54
60
|
|
55
|
-
expression.map do |token|
|
61
|
+
@code = expression.map do |token|
|
56
62
|
if token.is_a?(Array)
|
57
63
|
if [:cue, :cue_id].include?(token.first)
|
58
64
|
Qcmd.debug "nested cue action detected in #{ expression.inspect }"
|
@@ -66,6 +72,31 @@ module Qcmd
|
|
66
72
|
end.tap {|exp|
|
67
73
|
Qcmd.debug "[Action parse] returning: #{ exp.inspect }"
|
68
74
|
}
|
75
|
+
|
76
|
+
# if there's a trailing modifier command, replace it with an action that will
|
77
|
+
# return a value that can be modified.
|
78
|
+
if tm = trailing_modifier
|
79
|
+
Qcmd.debug "[Action parse] found trailing modifier: #{ tm.inspect }"
|
80
|
+
|
81
|
+
mod_type = tm[0]
|
82
|
+
mod_value = tm[2].to_f
|
83
|
+
|
84
|
+
# clone this action without the final arg
|
85
|
+
new_action = self.class.new(@code[0, @code.size - 1])
|
86
|
+
|
87
|
+
Qcmd.debug "[Action parse] creating modification proc: value.send(:#{ mod_type }, #{ mod_value })"
|
88
|
+
new_action.modification = Proc.new {|value|
|
89
|
+
Qcmd.debug "[Action parse] executing modification proc: #{ value }.send(:#{ mod_type }, #{ mod_value })"
|
90
|
+
if value.respond_to?(mod_type)
|
91
|
+
value.send mod_type, mod_value
|
92
|
+
else
|
93
|
+
Qcmd.log :warning, "The command `#{ new_action.code.join(' ') }` returned a value of type #{ value.class.to_s } which does not understand the #{ mod_type } modifier."
|
94
|
+
value
|
95
|
+
end
|
96
|
+
}
|
97
|
+
|
98
|
+
code[code.size - 1] = new_action
|
99
|
+
end
|
69
100
|
end
|
70
101
|
|
71
102
|
# the default command builder
|
@@ -97,14 +128,47 @@ module Qcmd
|
|
97
128
|
|
98
129
|
private
|
99
130
|
|
131
|
+
# is the last argument to the osc command a modifier?
|
132
|
+
# returns nil or [modifier, matcher, matched_value]
|
133
|
+
def trailing_modifier
|
134
|
+
if osc_arguments && !osc_arguments.last.is_a?(BaseAction)
|
135
|
+
modifier = modifiers.find {|(_, matcher)|
|
136
|
+
matcher =~ osc_arguments.last.to_s
|
137
|
+
}
|
138
|
+
|
139
|
+
if modifier
|
140
|
+
modifier + [$1]
|
141
|
+
else
|
142
|
+
nil
|
143
|
+
end
|
144
|
+
else
|
145
|
+
nil
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def number_matcher
|
150
|
+
# matches 1.9, .9, or 1
|
151
|
+
"(?: [0-9]+ \. [0-9]+ | \. [0-9]+ | [0-9]+ )"
|
152
|
+
end
|
153
|
+
|
154
|
+
def modifiers
|
155
|
+
[
|
156
|
+
[:+, /^\+\+(#{ number_matcher })/x],
|
157
|
+
[:-, /--(#{ number_matcher })/x],
|
158
|
+
[:/, /\/\/(#{ number_matcher })/x],
|
159
|
+
[:*, /\*\*(#{ number_matcher })/x]
|
160
|
+
]
|
161
|
+
end
|
162
|
+
|
163
|
+
def modifier_matchers
|
164
|
+
modifiers.map(&:last)
|
165
|
+
end
|
166
|
+
|
100
167
|
def send_message
|
101
168
|
responses = []
|
102
169
|
|
103
170
|
Qcmd.debug "[Action send_message] send #{ osc_message.encode }"
|
104
171
|
Qcmd.context.qlab.send(osc_message) do |response|
|
105
|
-
# puts "response to: #{ osc_message.inspect }"
|
106
|
-
# puts response.inspect
|
107
|
-
|
108
172
|
responses << QLab::Reply.new(response)
|
109
173
|
end
|
110
174
|
|
@@ -1,6 +1,11 @@
|
|
1
1
|
module Qcmd
|
2
|
-
class CueAction <
|
3
|
-
# cue commands
|
2
|
+
class CueAction < BaseAction
|
3
|
+
# cue commands should be in the form:
|
4
|
+
#
|
5
|
+
# [$id_field, $identifier, $command[, $arguments]]
|
6
|
+
#
|
7
|
+
# where arguments are optional.
|
8
|
+
|
4
9
|
def command
|
5
10
|
code[2]
|
6
11
|
end
|
data/lib/qcmd/aliases.rb
CHANGED
@@ -3,7 +3,7 @@ module Qcmd
|
|
3
3
|
def self.defaults
|
4
4
|
@defaults ||= {
|
5
5
|
'n' => 'cue $1 name $2',
|
6
|
-
# zero-out cue_number
|
6
|
+
# zero-out sliders for cue_number
|
7
7
|
'zero-out' => '(log-silent)' +
|
8
8
|
(1..48).map {|n| "(cue $1 sliderLevel #{n} 0)"}.join(' ') +
|
9
9
|
'(log-noisy) (echo "set slider levels for cue $1 to all zeros")',
|
@@ -11,6 +11,8 @@ module Qcmd
|
|
11
11
|
'copy-sliders' => '(log-silent)' +
|
12
12
|
(1..48).map {|n| "(cue $2 sliderLevel #{n} (cue $1 sliderLevel #{n}))"}.join(' ') +
|
13
13
|
'(log-noisy) (echo "copied slider levels from cue $1 to cue $2")',
|
14
|
+
'boost' => '(cue $1 sliderLevel $2 ++$3)',
|
15
|
+
'drop' => '(cue $1 sliderLevel $2 --$3)'
|
14
16
|
}.merge(copy_cue_actions)
|
15
17
|
end
|
16
18
|
|
data/lib/qcmd/commands.rb
CHANGED
@@ -281,16 +281,38 @@ sleep NUMBER
|
|
281
281
|
|
282
282
|
Will start cue number 3, then stop it two seconds later.
|
283
283
|
|
284
|
+
|
284
285
|
log-silent, log-noisy
|
285
286
|
|
286
287
|
Turn off output, turn it back on, respectively.
|
287
288
|
|
289
|
+
|
288
290
|
log-debug, log-info
|
289
291
|
|
290
292
|
Set output "level" to debug or info, respectively. Debug will tell you
|
291
293
|
everything qcmd is doing, in great detail. It's really just for development
|
292
294
|
purposes.
|
293
295
|
|
296
|
+
|
297
|
+
--, ++, //, **
|
298
|
+
|
299
|
+
These are modifiers can be used with a number on cue specific commands to
|
300
|
+
drop, raise, divide, or multiply the given value by the given amount,
|
301
|
+
respectively. For example, instead of using:
|
302
|
+
|
303
|
+
cue 1 sliderLevel 1 0
|
304
|
+
|
305
|
+
to set the value of volume slider 1 on cue 1 to 0 absolute, you can use:
|
306
|
+
|
307
|
+
cue 1 sliderLevel 1 ++0.2
|
308
|
+
|
309
|
+
to raise the current value of slider 1 on cue 1 by 0.2. To lower it by 0.2
|
310
|
+
you'd use "--0.2". The same for ** and //.
|
311
|
+
|
312
|
+
This is handy if you know you want to adjust the value of the cue setting by
|
313
|
+
a small amount but you don't know what the value is at the moment.
|
314
|
+
|
315
|
+
|
294
316
|
]
|
295
317
|
end
|
296
318
|
end
|
data/lib/qcmd/version.rb
CHANGED
data/spec/unit/action_spec.rb
CHANGED
@@ -10,6 +10,12 @@ class DeadHandler
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
+
def stubbed_modified_action modifier
|
14
|
+
action = Qcmd::CueAction.new ''
|
15
|
+
action.stub(:code) { [:cue, 1, :sliderLevel, 0, modifier] }
|
16
|
+
action
|
17
|
+
end
|
18
|
+
|
13
19
|
describe Qcmd::Action do
|
14
20
|
before do
|
15
21
|
Qcmd.context = Qcmd::Context.new
|
@@ -78,6 +84,67 @@ describe Qcmd::Action do
|
|
78
84
|
action = Qcmd::CueAction.new 'cue 1 name (cue 2 name)'
|
79
85
|
action.code[3].should be_an_instance_of(Qcmd::CueAction)
|
80
86
|
end
|
87
|
+
|
88
|
+
describe 'modifiers' do
|
89
|
+
describe 'positive' do
|
90
|
+
it 'should match int' do
|
91
|
+
action = stubbed_modified_action :'++1'
|
92
|
+
found = action.send(:trailing_modifier)
|
93
|
+
|
94
|
+
found.should_not be_nil
|
95
|
+
found.first.should eql(:+)
|
96
|
+
found.last.should eql('1')
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should match float' do
|
100
|
+
action = stubbed_modified_action :'++1.2'
|
101
|
+
found = action.send(:trailing_modifier)
|
102
|
+
|
103
|
+
found.should_not be_nil
|
104
|
+
found.first.should eql(:+)
|
105
|
+
found.last.should eql('1.2')
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should match bare float' do
|
109
|
+
action = stubbed_modified_action :'++.2'
|
110
|
+
found = action.send(:trailing_modifier)
|
111
|
+
|
112
|
+
found.should_not be_nil
|
113
|
+
found.first.should eql(:+)
|
114
|
+
found.last.should eql('.2')
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
describe 'negative' do
|
120
|
+
it 'should match int' do
|
121
|
+
action = stubbed_modified_action :'--1'
|
122
|
+
found = action.send(:trailing_modifier)
|
123
|
+
|
124
|
+
found.should_not be_nil
|
125
|
+
found.first.should eql(:-)
|
126
|
+
found.last.should eql('1')
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should match float' do
|
130
|
+
action = stubbed_modified_action :'--1.2'
|
131
|
+
found = action.send(:trailing_modifier)
|
132
|
+
|
133
|
+
found.should_not be_nil
|
134
|
+
found.first.should eql(:-)
|
135
|
+
found.last.should eql('1.2')
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'should match bare float' do
|
139
|
+
action = stubbed_modified_action :'--.2'
|
140
|
+
found = action.send(:trailing_modifier)
|
141
|
+
|
142
|
+
found.should_not be_nil
|
143
|
+
found.first.should eql(:-)
|
144
|
+
found.last.should eql('.2')
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
81
148
|
end
|
82
149
|
|
83
150
|
end
|
data/spec/unit/parser_spec.rb
CHANGED
@@ -26,6 +26,11 @@ describe Qcmd::Parser do
|
|
26
26
|
tokens.should eql([:cue, :'1.11.0'])
|
27
27
|
end
|
28
28
|
|
29
|
+
it 'should parse modifiers as symbols' do
|
30
|
+
tokens = Qcmd::Parser.parse 'cue number ++1 --1'
|
31
|
+
tokens.should eql([:cue, :number, :'++1', :'--1'])
|
32
|
+
end
|
33
|
+
|
29
34
|
it "should parse nested quotes" do
|
30
35
|
tokens = Qcmd::Parser.parse 'go "word word" 10 -12.3 "life \"is good\" yeah"'
|
31
36
|
tokens.should eql([:go, 'word word', 10, -12.3, 'life "is good" yeah'])
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: qcmd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
4
|
+
prerelease: true
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
|
8
|
+
- 16
|
9
|
+
- pre
|
10
|
+
version: 0.1.16.pre
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Adam Bachman
|
@@ -14,7 +15,7 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date: 2013-06-
|
18
|
+
date: 2013-06-05 00:00:00 -04:00
|
18
19
|
default_executable:
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
@@ -192,11 +193,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
192
193
|
version: "0"
|
193
194
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
194
195
|
requirements:
|
195
|
-
- - "
|
196
|
+
- - ">"
|
196
197
|
- !ruby/object:Gem::Version
|
197
198
|
segments:
|
198
|
-
-
|
199
|
-
|
199
|
+
- 1
|
200
|
+
- 3
|
201
|
+
- 1
|
202
|
+
version: 1.3.1
|
200
203
|
requirements: []
|
201
204
|
|
202
205
|
rubyforge_project:
|