qcmd 0.1.15 → 0.1.16.pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- @code = parse(expression)
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?(Action)
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 < Action
3
- # cue commands work differently
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
@@ -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
 
@@ -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
@@ -1,5 +1,5 @@
1
1
  module Qcmd
2
- VERSION = "0.1.15"
2
+ VERSION = "0.1.16.pre"
3
3
 
4
4
  class << self
5
5
  def installed_version
@@ -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
@@ -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: false
4
+ prerelease: true
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 15
9
- version: 0.1.15
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-03 00:00:00 -04:00
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
- - 0
199
- version: "0"
199
+ - 1
200
+ - 3
201
+ - 1
202
+ version: 1.3.1
200
203
  requirements: []
201
204
 
202
205
  rubyforge_project: