punchblock 0.4.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.
Files changed (94) hide show
  1. data/.document +5 -0
  2. data/.gitignore +12 -0
  3. data/.rspec +3 -0
  4. data/Gemfile +2 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.markdown +31 -0
  7. data/Rakefile +23 -0
  8. data/assets/ozone/ask-1.0.xsd +56 -0
  9. data/assets/ozone/conference-1.0.xsd +17 -0
  10. data/assets/ozone/ozone-1.0.xsd +127 -0
  11. data/assets/ozone/say-1.0.xsd +24 -0
  12. data/assets/ozone/transfer-1.0.xsd +32 -0
  13. data/bin/punchblock-console +125 -0
  14. data/lib/punchblock/command/accept.rb +30 -0
  15. data/lib/punchblock/command/answer.rb +30 -0
  16. data/lib/punchblock/command/dial.rb +88 -0
  17. data/lib/punchblock/command/hangup.rb +25 -0
  18. data/lib/punchblock/command/join.rb +81 -0
  19. data/lib/punchblock/command/mute.rb +7 -0
  20. data/lib/punchblock/command/redirect.rb +49 -0
  21. data/lib/punchblock/command/reject.rb +61 -0
  22. data/lib/punchblock/command/unjoin.rb +50 -0
  23. data/lib/punchblock/command/unmute.rb +7 -0
  24. data/lib/punchblock/command.rb +16 -0
  25. data/lib/punchblock/command_node.rb +46 -0
  26. data/lib/punchblock/component/input.rb +320 -0
  27. data/lib/punchblock/component/output.rb +449 -0
  28. data/lib/punchblock/component/record.rb +216 -0
  29. data/lib/punchblock/component/tropo/ask.rb +197 -0
  30. data/lib/punchblock/component/tropo/conference.rb +328 -0
  31. data/lib/punchblock/component/tropo/say.rb +113 -0
  32. data/lib/punchblock/component/tropo/transfer.rb +178 -0
  33. data/lib/punchblock/component/tropo.rb +12 -0
  34. data/lib/punchblock/component.rb +73 -0
  35. data/lib/punchblock/connection.rb +209 -0
  36. data/lib/punchblock/core_ext/blather/stanza/presence.rb +11 -0
  37. data/lib/punchblock/core_ext/blather/stanza.rb +26 -0
  38. data/lib/punchblock/dsl.rb +46 -0
  39. data/lib/punchblock/event/answered.rb +7 -0
  40. data/lib/punchblock/event/complete.rb +65 -0
  41. data/lib/punchblock/event/dtmf.rb +19 -0
  42. data/lib/punchblock/event/end.rb +15 -0
  43. data/lib/punchblock/event/info.rb +15 -0
  44. data/lib/punchblock/event/joined.rb +50 -0
  45. data/lib/punchblock/event/offer.rb +29 -0
  46. data/lib/punchblock/event/ringing.rb +7 -0
  47. data/lib/punchblock/event/unjoined.rb +50 -0
  48. data/lib/punchblock/event.rb +16 -0
  49. data/lib/punchblock/generic_connection.rb +18 -0
  50. data/lib/punchblock/has_headers.rb +34 -0
  51. data/lib/punchblock/header.rb +47 -0
  52. data/lib/punchblock/media_container.rb +39 -0
  53. data/lib/punchblock/media_node.rb +17 -0
  54. data/lib/punchblock/protocol_error.rb +16 -0
  55. data/lib/punchblock/rayo_node.rb +88 -0
  56. data/lib/punchblock/ref.rb +26 -0
  57. data/lib/punchblock/version.rb +3 -0
  58. data/lib/punchblock.rb +42 -0
  59. data/log/.gitkeep +0 -0
  60. data/punchblock.gemspec +42 -0
  61. data/spec/punchblock/command/accept_spec.rb +13 -0
  62. data/spec/punchblock/command/answer_spec.rb +13 -0
  63. data/spec/punchblock/command/dial_spec.rb +54 -0
  64. data/spec/punchblock/command/hangup_spec.rb +13 -0
  65. data/spec/punchblock/command/join_spec.rb +21 -0
  66. data/spec/punchblock/command/mute_spec.rb +11 -0
  67. data/spec/punchblock/command/redirect_spec.rb +19 -0
  68. data/spec/punchblock/command/reject_spec.rb +43 -0
  69. data/spec/punchblock/command/unjoin_spec.rb +19 -0
  70. data/spec/punchblock/command/unmute_spec.rb +11 -0
  71. data/spec/punchblock/command_node_spec.rb +80 -0
  72. data/spec/punchblock/component/input_spec.rb +188 -0
  73. data/spec/punchblock/component/output_spec.rb +531 -0
  74. data/spec/punchblock/component/record_spec.rb +235 -0
  75. data/spec/punchblock/component/tropo/ask_spec.rb +183 -0
  76. data/spec/punchblock/component/tropo/conference_spec.rb +360 -0
  77. data/spec/punchblock/component/tropo/say_spec.rb +171 -0
  78. data/spec/punchblock/component/tropo/transfer_spec.rb +153 -0
  79. data/spec/punchblock/component_spec.rb +126 -0
  80. data/spec/punchblock/connection_spec.rb +194 -0
  81. data/spec/punchblock/event/answered_spec.rb +23 -0
  82. data/spec/punchblock/event/complete_spec.rb +80 -0
  83. data/spec/punchblock/event/dtmf_spec.rb +24 -0
  84. data/spec/punchblock/event/end_spec.rb +30 -0
  85. data/spec/punchblock/event/info_spec.rb +30 -0
  86. data/spec/punchblock/event/joined_spec.rb +32 -0
  87. data/spec/punchblock/event/offer_spec.rb +35 -0
  88. data/spec/punchblock/event/ringing_spec.rb +23 -0
  89. data/spec/punchblock/event/unjoined_spec.rb +32 -0
  90. data/spec/punchblock/header_spec.rb +44 -0
  91. data/spec/punchblock/protocol_error_spec.rb +9 -0
  92. data/spec/punchblock/ref_spec.rb +21 -0
  93. data/spec/spec_helper.rb +43 -0
  94. metadata +353 -0
@@ -0,0 +1,449 @@
1
+ module Punchblock
2
+ module Component
3
+ class Output < ComponentNode
4
+ register :output, :output
5
+
6
+ include MediaContainer
7
+
8
+ ##
9
+ # Creates an Rayo Output command
10
+ #
11
+ # @param [Hash] options
12
+ # @option options [String, Optional] :text to speak back
13
+ # @option options [String, Optional] :voice with which to render TTS
14
+ # @option options [String, Optional] :ssml document to render TTS
15
+ #
16
+ # @return [Command::Output] an Rayo "output" command
17
+ #
18
+ # @example
19
+ # output :text => 'Hello brown cow.'
20
+ #
21
+ # returns:
22
+ # <output xmlns="urn:xmpp:tropo:output:1">Hello brown cow.</output>
23
+ #
24
+ def self.new(options = {})
25
+ super().tap do |new_node|
26
+ case options
27
+ when Hash
28
+ new_node.voice = options.delete(:voice) if options[:voice]
29
+ new_node.ssml = options.delete(:ssml) if options[:ssml]
30
+ new_node << options.delete(:text) if options[:text]
31
+ options.each_pair { |k,v| new_node.send :"#{k}=", v }
32
+ when Nokogiri::XML::Element
33
+ new_node.inherit options
34
+ end
35
+ end
36
+ end
37
+
38
+ ##
39
+ # @return [String] the TTS voice to use
40
+ #
41
+ def interrupt_on
42
+ read_attr :'interrupt-on', :to_sym
43
+ end
44
+
45
+ ##
46
+ # @param [String] voice to use when rendering TTS
47
+ #
48
+ def interrupt_on=(other)
49
+ write_attr :'interrupt-on', other
50
+ end
51
+
52
+ ##
53
+ # @return [String] the TTS voice to use
54
+ #
55
+ def start_offset
56
+ read_attr :'start-offset', :to_i
57
+ end
58
+
59
+ ##
60
+ # @param [String] voice to use when rendering TTS
61
+ #
62
+ def start_offset=(other)
63
+ write_attr :'start-offset', other
64
+ end
65
+
66
+ ##
67
+ # @return [String] the TTS voice to use
68
+ #
69
+ def start_paused
70
+ read_attr(:'start-paused') == 'true'
71
+ end
72
+
73
+ ##
74
+ # @param [String] voice to use when rendering TTS
75
+ #
76
+ def start_paused=(other)
77
+ write_attr :'start-paused', other.to_s
78
+ end
79
+
80
+ ##
81
+ # @return [String] the TTS voice to use
82
+ #
83
+ def repeat_interval
84
+ read_attr :'repeat-interval', :to_i
85
+ end
86
+
87
+ ##
88
+ # @param [String] voice to use when rendering TTS
89
+ #
90
+ def repeat_interval=(other)
91
+ write_attr :'repeat-interval', other
92
+ end
93
+
94
+ ##
95
+ # @return [String] the TTS voice to use
96
+ #
97
+ def repeat_times
98
+ read_attr :'repeat-times', :to_i
99
+ end
100
+
101
+ ##
102
+ # @param [String] voice to use when rendering TTS
103
+ #
104
+ def repeat_times=(other)
105
+ write_attr :'repeat-times', other
106
+ end
107
+
108
+ ##
109
+ # @return [String] the TTS voice to use
110
+ #
111
+ def max_time
112
+ read_attr(:'max-time').to_i
113
+ end
114
+
115
+ ##
116
+ # @param [String] voice to use when rendering TTS
117
+ #
118
+ def max_time=(other)
119
+ write_attr :'max-time', other
120
+ end
121
+
122
+ state_machine :state do
123
+ event :paused do
124
+ transition :executing => :paused
125
+ end
126
+
127
+ event :resumed do
128
+ transition :paused => :executing
129
+ end
130
+ end
131
+
132
+ # Pauses a running Output
133
+ #
134
+ # @return [Command::Output::Pause] an Rayo pause message for the current Output
135
+ #
136
+ # @example
137
+ # output_obj.pause_action.to_xml
138
+ #
139
+ # returns:
140
+ # <pause xmlns="urn:xmpp:tropo:output:1"/>
141
+ def pause_action
142
+ Pause.new :component_id => component_id, :call_id => call_id
143
+ end
144
+
145
+ ##
146
+ # Sends an Rayo pause message for the current Output
147
+ #
148
+ def pause!
149
+ raise InvalidActionError, "Cannot pause a Output that is not executing" unless executing?
150
+ pause_action.tap do |action|
151
+ result = write_action action
152
+ paused! if result
153
+ end
154
+ end
155
+
156
+ ##
157
+ # Create an Rayo resume message for the current Output
158
+ #
159
+ # @return [Command::Output::Resume] an Rayo resume message
160
+ #
161
+ # @example
162
+ # output_obj.resume_action.to_xml
163
+ #
164
+ # returns:
165
+ # <resume xmlns="urn:xmpp:tropo:output:1"/>
166
+ def resume_action
167
+ Resume.new :component_id => component_id, :call_id => call_id
168
+ end
169
+
170
+ ##
171
+ # Sends an Rayo resume message for the current Output
172
+ #
173
+ def resume!
174
+ raise InvalidActionError, "Cannot resume a Output that is not paused." unless paused?
175
+ resume_action.tap do |action|
176
+ result = write_action action
177
+ resumed! if result
178
+ end
179
+ end
180
+
181
+ class Pause < CommandNode # :nodoc:
182
+ register :pause, :output
183
+ end
184
+
185
+ class Resume < CommandNode # :nodoc:
186
+ register :resume, :output
187
+ end
188
+
189
+ ##
190
+ # Creates an Rayo seek message for the current Output
191
+ #
192
+ # @return [Command::Output::Seek] a Rayo seek message
193
+ #
194
+ # @example
195
+ # output_obj.seek_action.to_xml
196
+ #
197
+ # returns:
198
+ # <seek xmlns="urn:xmpp:rayo:output:1"/>
199
+ def seek_action(options = {})
200
+ Seek.new({ :component_id => component_id, :call_id => call_id }.merge(options)).tap do |s|
201
+ s.original_component = self
202
+ end
203
+ end
204
+
205
+ ##
206
+ # Sends a Rayo seek message for the current Output
207
+ #
208
+ def seek!(options = {})
209
+ raise InvalidActionError, "Cannot seek an Output that is already seeking." if seeking?
210
+ seek_action(options).tap do |action|
211
+ write_action action
212
+ end
213
+ end
214
+
215
+ state_machine :seek_status, :initial => :not_seeking do
216
+ event :seeking do
217
+ transition :not_seeking => :seeking
218
+ end
219
+
220
+ event :stopped_seeking do
221
+ transition :seeking => :not_seeking
222
+ end
223
+ end
224
+
225
+ class Seek < CommandNode # :nodoc:
226
+ register :seek, :output
227
+
228
+ def self.new(options = {})
229
+ super.tap do |new_node|
230
+ new_node.direction = options[:direction]
231
+ new_node.amount = options[:amount]
232
+ end
233
+ end
234
+
235
+ def direction=(other)
236
+ write_attr :direction, other
237
+ end
238
+
239
+ def amount=(other)
240
+ write_attr :amount, other
241
+ end
242
+
243
+ def request!
244
+ source.seeking!
245
+ super
246
+ end
247
+
248
+ def execute!
249
+ source.stopped_seeking!
250
+ super
251
+ end
252
+ end
253
+
254
+ ##
255
+ # Creates an Rayo speed up message for the current Output
256
+ #
257
+ # @return [Command::Output::SpeedUp] a Rayo speed up message
258
+ #
259
+ # @example
260
+ # output_obj.speed_up_action.to_xml
261
+ #
262
+ # returns:
263
+ # <speed-up xmlns="urn:xmpp:rayo:output:1"/>
264
+ def speed_up_action
265
+ SpeedUp.new(:component_id => component_id, :call_id => call_id).tap do |s|
266
+ s.original_component = self
267
+ end
268
+ end
269
+
270
+ ##
271
+ # Sends a Rayo speed up message for the current Output
272
+ #
273
+ def speed_up!
274
+ raise InvalidActionError, "Cannot speed up an Output that is already speeding." unless not_speeding?
275
+ speed_up_action.tap do |action|
276
+ write_action action
277
+ end
278
+ end
279
+
280
+ ##
281
+ # Creates an Rayo slow down message for the current Output
282
+ #
283
+ # @return [Command::Output::SlowDown] a Rayo slow down message
284
+ #
285
+ # @example
286
+ # output_obj.slow_down_action.to_xml
287
+ #
288
+ # returns:
289
+ # <speed-down xmlns="urn:xmpp:rayo:output:1"/>
290
+ def slow_down_action
291
+ SlowDown.new(:component_id => component_id, :call_id => call_id).tap do |s|
292
+ s.original_component = self
293
+ end
294
+ end
295
+
296
+ ##
297
+ # Sends a Rayo slow down message for the current Output
298
+ #
299
+ def slow_down!
300
+ raise InvalidActionError, "Cannot slow down an Output that is already speeding." unless not_speeding?
301
+ slow_down_action.tap do |action|
302
+ write_action action
303
+ end
304
+ end
305
+
306
+ state_machine :speed_status, :initial => :not_speeding do
307
+ event :speeding_up do
308
+ transition :not_speeding => :speeding_up
309
+ end
310
+
311
+ event :slowing_down do
312
+ transition :not_speeding => :slowing_down
313
+ end
314
+
315
+ event :stopped_speeding do
316
+ transition [:speeding_up, :slowing_down] => :not_speeding
317
+ end
318
+ end
319
+
320
+ class SpeedUp < CommandNode # :nodoc:
321
+ register :'speed-up', :output
322
+
323
+ def request!
324
+ source.speeding_up!
325
+ super
326
+ end
327
+
328
+ def execute!
329
+ source.stopped_speeding!
330
+ super
331
+ end
332
+ end
333
+
334
+ class SlowDown < CommandNode # :nodoc:
335
+ register :'speed-down', :output
336
+
337
+ def request!
338
+ source.slowing_down!
339
+ super
340
+ end
341
+
342
+ def execute!
343
+ source.stopped_speeding!
344
+ super
345
+ end
346
+ end
347
+
348
+ ##
349
+ # Creates an Rayo volume up message for the current Output
350
+ #
351
+ # @return [Command::Output::VolumeUp] a Rayo volume up message
352
+ #
353
+ # @example
354
+ # output_obj.volume_up_action.to_xml
355
+ #
356
+ # returns:
357
+ # <volume-up xmlns="urn:xmpp:rayo:output:1"/>
358
+ def volume_up_action
359
+ VolumeUp.new(:component_id => component_id, :call_id => call_id).tap do |s|
360
+ s.original_component = self
361
+ end
362
+ end
363
+
364
+ ##
365
+ # Sends a Rayo volume up message for the current Output
366
+ #
367
+ def volume_up!
368
+ raise InvalidActionError, "Cannot volume up an Output that is already voluming." unless not_voluming?
369
+ volume_up_action.tap do |action|
370
+ write_action action
371
+ end
372
+ end
373
+
374
+ ##
375
+ # Creates an Rayo volume down message for the current Output
376
+ #
377
+ # @return [Command::Output::VolumeDown] a Rayo volume down message
378
+ #
379
+ # @example
380
+ # output_obj.volume_down_action.to_xml
381
+ #
382
+ # returns:
383
+ # <volume-down xmlns="urn:xmpp:rayo:output:1"/>
384
+ def volume_down_action
385
+ VolumeDown.new(:component_id => component_id, :call_id => call_id).tap do |s|
386
+ s.original_component = self
387
+ end
388
+ end
389
+
390
+ ##
391
+ # Sends a Rayo volume down message for the current Output
392
+ #
393
+ def volume_down!
394
+ raise InvalidActionError, "Cannot volume down an Output that is already voluming." unless not_voluming?
395
+ volume_down_action.tap do |action|
396
+ write_action action
397
+ end
398
+ end
399
+
400
+ state_machine :volume_status, :initial => :not_voluming do
401
+ event :voluming_up do
402
+ transition :not_voluming => :voluming_up
403
+ end
404
+
405
+ event :voluming_down do
406
+ transition :not_voluming => :voluming_down
407
+ end
408
+
409
+ event :stopped_voluming do
410
+ transition [:voluming_up, :voluming_down] => :not_voluming
411
+ end
412
+ end
413
+
414
+ class VolumeUp < CommandNode # :nodoc:
415
+ register :'volume-up', :output
416
+
417
+ def request!
418
+ source.voluming_up!
419
+ super
420
+ end
421
+
422
+ def execute!
423
+ source.stopped_voluming!
424
+ super
425
+ end
426
+ end
427
+
428
+ class VolumeDown < CommandNode # :nodoc:
429
+ register :'volume-down', :output
430
+
431
+ def request!
432
+ source.voluming_down!
433
+ super
434
+ end
435
+
436
+ def execute!
437
+ source.stopped_voluming!
438
+ super
439
+ end
440
+ end
441
+
442
+ class Complete
443
+ class Success < Event::Complete::Reason
444
+ register :success, :output_complete
445
+ end
446
+ end
447
+ end # Output
448
+ end # Command
449
+ end # Punchblock
@@ -0,0 +1,216 @@
1
+ module Punchblock
2
+ module Component
3
+ class Record < ComponentNode
4
+ register :record, :record
5
+
6
+ ##
7
+ # Creates an Rayo Record command
8
+ #
9
+ # @param [Hash] options
10
+ # @option options [String, Optional] :text to speak back
11
+ # @option options [String, Optional] :voice with which to render TTS
12
+ # @option options [String, Optional] :ssml document to render TTS
13
+ #
14
+ # @return [Command::Record] an Rayo "record" command
15
+ #
16
+ # @example
17
+ # record :text => 'Hello brown cow.'
18
+ #
19
+ # returns:
20
+ # <record xmlns="urn:xmpp:rayo:record:1">Hello brown cow.</record>
21
+ #
22
+ def self.new(options = {})
23
+ super().tap do |new_node|
24
+ options.each_pair { |k,v| new_node.send :"#{k}=", v }
25
+ end
26
+ end
27
+
28
+ ##
29
+ # @return [String] the codec to use for recording
30
+ #
31
+ def final_timeout
32
+ read_attr :'final-timeout', :to_i
33
+ end
34
+
35
+ ##
36
+ # @param [String] codec to use for recording
37
+ #
38
+ def final_timeout=(timeout)
39
+ write_attr :'final-timeout', timeout
40
+ end
41
+
42
+ ##
43
+ # @return [String] the codec to use for recording
44
+ #
45
+ def format
46
+ read_attr :format
47
+ end
48
+
49
+ ##
50
+ # @param [String] codec to use for recording
51
+ #
52
+ def format=(format)
53
+ write_attr :format, format
54
+ end
55
+
56
+ ##
57
+ # @return [String] the codec to use for recording
58
+ #
59
+ def initial_timeout
60
+ read_attr :'initial-timeout', :to_i
61
+ end
62
+
63
+ ##
64
+ # @param [String] codec to use for recording
65
+ #
66
+ def initial_timeout=(timeout)
67
+ write_attr :'initial-timeout', timeout
68
+ end
69
+
70
+ ##
71
+ # @return [String] the codec to use for recording
72
+ #
73
+ def max_duration
74
+ read_attr :'max-duration', :to_i
75
+ end
76
+
77
+ ##
78
+ # @param [String] codec to use for recording
79
+ #
80
+ def max_duration=(other)
81
+ write_attr :'max-duration', other
82
+ end
83
+
84
+ ##
85
+ # @return [String] the codec to use for recording
86
+ #
87
+ def start_beep
88
+ read_attr(:'start-beep') == 'true'
89
+ end
90
+
91
+ ##
92
+ # @param [String] codec to use for recording
93
+ #
94
+ def start_beep=(sb)
95
+ write_attr :'start-beep', sb
96
+ end
97
+
98
+ ##
99
+ # @return [String] the codec to use for recording
100
+ #
101
+ def stop_beep
102
+ read_attr(:'stop-beep') == 'true'
103
+ end
104
+
105
+ ##
106
+ # @param [String] codec to use for recording
107
+ #
108
+ def stop_beep=(sb)
109
+ write_attr :'stop-beep', sb
110
+ end
111
+
112
+ ##
113
+ # @return [String] the codec to use for recording
114
+ #
115
+ def start_paused
116
+ read_attr(:'start-paused') == 'true'
117
+ end
118
+
119
+ ##
120
+ # @param [String] codec to use for recording
121
+ #
122
+ def start_paused=(other)
123
+ write_attr :'start-paused', other
124
+ end
125
+
126
+ def inspect_attributes # :nodoc:
127
+ [:final_timeout, :format, :initial_timeout, :max_duration, :start_beep, :start_paused, :stop_beep] + super
128
+ end
129
+
130
+ state_machine :state do
131
+ event :paused do
132
+ transition :executing => :paused
133
+ end
134
+
135
+ event :resumed do
136
+ transition :paused => :executing
137
+ end
138
+ end
139
+
140
+ # Pauses a running Record
141
+ #
142
+ # @return [Command::Record::Pause] an Rayo pause message for the current Record
143
+ #
144
+ # @example
145
+ # record_obj.pause_action.to_xml
146
+ #
147
+ # returns:
148
+ # <pause xmlns="urn:xmpp:rayo:record:1"/>
149
+ def pause_action
150
+ Pause.new :component_id => component_id, :call_id => call_id
151
+ end
152
+
153
+ ##
154
+ # Sends an Rayo pause message for the current Record
155
+ #
156
+ def pause!
157
+ raise InvalidActionError, "Cannot pause a Record that is not executing" unless executing?
158
+ pause_action.tap do |action|
159
+ result = write_action action
160
+ paused! if result
161
+ end
162
+ end
163
+
164
+ ##
165
+ # Create an Rayo resume message for the current Record
166
+ #
167
+ # @return [Command::Record::Resume] an Rayo resume message
168
+ #
169
+ # @example
170
+ # record_obj.resume_action.to_xml
171
+ #
172
+ # returns:
173
+ # <resume xmlns="urn:xmpp:rayo:record:1"/>
174
+ def resume_action
175
+ Resume.new :component_id => component_id, :call_id => call_id
176
+ end
177
+
178
+ ##
179
+ # Sends an Rayo resume message for the current Record
180
+ #
181
+ def resume!
182
+ raise InvalidActionError, "Cannot resume a Record that is not paused." unless paused?
183
+ resume_action.tap do |action|
184
+ result = write_action action
185
+ resumed! if result
186
+ end
187
+ end
188
+
189
+ class Pause < CommandNode # :nodoc:
190
+ register :pause, :record
191
+ end
192
+
193
+ class Resume < CommandNode # :nodoc:
194
+ register :resume, :record
195
+ end
196
+
197
+ class Recording < Event
198
+ register :recording, :record_complete
199
+
200
+ def uri
201
+ read_attr :uri
202
+ end
203
+
204
+ def inspect_attributes # :nodoc:
205
+ [:uri] + super
206
+ end
207
+ end
208
+
209
+ class Complete
210
+ class Success < Event::Complete::Reason
211
+ register :success, :record_complete
212
+ end
213
+ end
214
+ end # Record
215
+ end # Command
216
+ end # Punchblock