ruby-agi 0.0.3 → 1.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.
@@ -0,0 +1,897 @@
1
+ #
2
+ # File: command.rb
3
+ #
4
+ # ruby-agi: Ruby Language API for Asterisk
5
+ #
6
+ # Copyright (C) <2005> Mohammad Khan <info@beeplove.com>
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program; if not, write to the Free Software
20
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
+ #
22
+
23
+ # this would be the most used class
24
+
25
+ # most common arguements
26
+ # timeout: nil, zero, neative =forever,
27
+ # escape_digit, by default #, if nil passed as argument there will not have any escape
28
+ # escape_digits, by default #, if nil passed as argument there will not have any escape
29
+ # channel, current channel otherwise mentioned
30
+ # max_digit, maximum number of digits would be accepted from user, always 255 otherwise mentioned
31
+ # filename, name of file to be streamed, recoreds ..
32
+ # beep, always yes, otherwise passed false or nil as argument
33
+ # format, always gsm otherwise mentioned
34
+ # secs, all methods need time as an argument are passed as seconds
35
+
36
+ require 'sync'
37
+
38
+ require 'ruby-agi/agi.rb'
39
+ require 'ruby-agi/return_status.rb'
40
+ require 'ruby-agi/error.rb'
41
+
42
+ class AGI
43
+ end
44
+
45
+
46
+ class Command < AGI
47
+ def initialize
48
+ end
49
+
50
+ #
51
+ # Answers channel if not already in answer state.
52
+ #
53
+ # <b>Parameters</b>
54
+ # - none
55
+ #
56
+ # <b>Returns</b>
57
+ # - ReturnStatus object
58
+ #
59
+ # failure: 200 result=-1
60
+ # success: 200 result=0
61
+ # Command Reference: ANSWER
62
+ #
63
+ public
64
+ def answer
65
+ cmd = "ANSWER"
66
+ rs = exec_command(cmd)
67
+ raise CommandError, rs.to_s if rs.command_error?
68
+ return rs
69
+ end
70
+
71
+ #
72
+ # Cause the channel to automatically hangup at <time> seconds in the future.
73
+ # Of course it can be hungup before then as well.
74
+ # Setting to 0 will cause the autohangup feature to be disabled on this channel.
75
+ #
76
+ # <b>Parameters</b>
77
+ # - time : number of seconds, after this time period channel will be automatically hung up
78
+ #
79
+ # <b>Returns</b>
80
+ # - ReturnStatus object
81
+ #
82
+ # 200 result=0
83
+ # Command Reference: SET AUTOHANGUP <time>
84
+ #
85
+ public
86
+ def set_auto_hangup(secs=0)
87
+ cmd = "SET AUTOHANGUP #{secs.to_s}"
88
+ rs = exec_command(cmd)
89
+ raise CommandError, rs.to_s if rs.command_error?
90
+ return rs
91
+ end
92
+
93
+ #
94
+ # Returns the status of the specified channel.
95
+ # If no channel name is given the returns the status of the current channel.
96
+ #
97
+ # <b>Parameters</b>
98
+ # - channel : name of the channel.
99
+ #
100
+ # <b>Returns</b>
101
+ # - ReturnStatus object
102
+ #
103
+ # failure: 200 result=-1
104
+ # success: 200 result=<status>
105
+ # <status> values:
106
+ # 0 Channel is down and available
107
+ # 1 Channel is down, but reserved
108
+ # 2 Channel is off hook
109
+ # 3 Digits (or equivalent) have been dialed
110
+ # 4 Line is ringing
111
+ # 5 Remote end is ringing
112
+ # 6 Line is up
113
+ # 7 Line is busy
114
+ # Command Reference: CHANNEL STATUS [<channelname>]
115
+ #
116
+ public
117
+ def channel_status(channel=nil)
118
+ if channel.nil?
119
+ channel = ""
120
+ end
121
+
122
+ cmd = "CHANNEL STATUS #{channel.to_s}"
123
+ rs = exec_command(cmd)
124
+ raise CommandError, rs.to_s if rs.command_error?
125
+ return rs
126
+ end
127
+
128
+ #
129
+ # Executes <application> with given <options>.
130
+ # Applications are the functions you use to create a dial plan in extensions.conf.
131
+ #
132
+ # <b>Parameters</b>
133
+ # - application : Asterisk command of the application
134
+ # - options : options to be passed with the asterisk application
135
+ #
136
+ # <b>Returns</b>
137
+ # - ReturnStatus object
138
+ #
139
+ # failure: 200 result=-2
140
+ # success: 200 result=<ret>
141
+ # Command Reference: EXEC <application> <options>
142
+ #
143
+ public
144
+ def exec(application, options=nil)
145
+ if options.nil?
146
+ options = ""
147
+ end
148
+ cmd = "EXEC #{application.to_s} #{options.to_s}"
149
+ rs = exec_command(cmd)
150
+ raise CommandError, rs.to_s if rs.command_error?
151
+ return rs
152
+ end
153
+
154
+
155
+ #
156
+ # method to get digit(s)
157
+ # pressing '#' will always terminate the input process
158
+ #
159
+ # <b>Parameters</b>
160
+ # - filename : audio to be played before get as input
161
+ # - timeout : maximum allowed time in second(s) to receive each digit
162
+ # wait for ever if timeout is nil or negative or zero
163
+ # - max_digit: maximum number of digits to get as input
164
+ # wait for unlimited number of digits if max_digit is nil or negative or zero
165
+ # <b>Returns</b>
166
+ # - ReturnStatus object
167
+ #
168
+ # failure: 200 result=-1
169
+ # timeout: 200 result=<digits> (timeout)
170
+ # success: 200 result=<digits>
171
+ # <digits> is the digits pressed.
172
+ # Command Reference: GET DATA <file to be streamed> [timeout] [max digits]
173
+ #
174
+ public
175
+ def wait_for_digits(filename, timeout=nil, max_digit=nil)
176
+
177
+ timeout = sanitize_timeout(timeout)
178
+ max_digit = sanitize_max_digit(max_digit)
179
+
180
+ cmd = "GET DATA #{filename.to_s} #{timeout.to_s} #{max_digit.to_s}"
181
+
182
+ rs = exec_command(cmd)
183
+ raise CommandError, rs.to_s if rs.command_error?
184
+ return rs
185
+ end
186
+
187
+ #
188
+ # method to read a variable
189
+ #
190
+ # <b>Parameters</b>
191
+ # - name : name of the variable to read
192
+ #
193
+ # <b>Returns</b>
194
+ # - ReturnStatus object
195
+ #
196
+ # Does not work with global variables. Does not work with some variables that are generated by modules.
197
+ # failure or not set: 200 result=0
198
+ # success: 200 result=1 <value>
199
+ # Command Reference: GET VARIABLE <variablename>
200
+ #
201
+ public
202
+ def get_variable(name)
203
+ cmd = "GET VARIABLE #{name.to_s}"
204
+ rs = exec_command(cmd)
205
+ raise CommandError, rs.to_s if rs.command_error?
206
+ return rs
207
+ end
208
+
209
+ #
210
+ # method to hang up the specified channel.
211
+ # If no channel name is given, hangs up the current channel.
212
+ #
213
+ # <b>Parameters</b>
214
+ # - channel : name of the channel to hang up
215
+ # <b>Returns</b>
216
+ # - ReturnStatus object
217
+ #
218
+ # failure: 200 result=-1
219
+ # success: 200 result=1
220
+ # Command Reference: HANGUP [<channelname>]
221
+ #
222
+ public
223
+ def hangup(channel=nil)
224
+ if channel.nil?
225
+ channel = ""
226
+ end
227
+
228
+ cmd = "HANGUP #{channel.to_s}"
229
+ rs = exec_command(cmd)
230
+ raise CommandError, rs.to_s if rs.command_error?
231
+ return rs
232
+ end
233
+
234
+ #
235
+ # method that Does nothing !!
236
+ #
237
+ # <b>Parameters</b>
238
+ # - msg : message to pass this method
239
+ #
240
+ # <b>Returns</b>
241
+ # - ReturnStatus object
242
+ # success: 200 result=0
243
+ # Command Reference: Usage: NOOP
244
+ #
245
+ public
246
+ def noop(msg)
247
+ cmd = "NOOP #{msg.to_s}"
248
+ rs = exec_command(cmd)
249
+ raise CommandError, rs.to_s if rs.command_error?
250
+ return rs
251
+ end
252
+
253
+ #
254
+ # Receives a character of text on a channel, and discards any further characters after the first one waiting.
255
+ # Most channels do not support the reception of text. See Asterisk Text for details.
256
+ #
257
+ # <b>Parameters</b>
258
+ # - timeout : maximum time to wait for input in seconds
259
+ # negative or zero is not acceptable
260
+ #
261
+ # <b>Returns</b>
262
+ # - ReturnStatus object
263
+ #
264
+ # failure or hangup: 200 result=-1 (hangup)
265
+ # timeout: 200 result=<char> (timeout)
266
+ # success: 200 result=<char>
267
+ # <char> is the character received, or 0 if the channel does not support text reception.
268
+ # Command Reference: RECEIVE CHAR <timeout>
269
+ #
270
+ public
271
+ def receive_char(timeout)
272
+ timeout = sanitize_timeout(timeout)
273
+ raise(ArgumentError, "timeout need to be positive") if (timeout < 1)
274
+
275
+ cmd = "RECEIVE CHAR #{timeout.to_s}"
276
+ rs = exec_command(cmd)
277
+ raise CommandError, rs.to_s if rs.command_error?
278
+ return rs
279
+ end
280
+
281
+ #
282
+ # Receives a string text on a channel.
283
+ # Most channels do not support the reception of text.
284
+ #
285
+ # <b>Parameters</b>
286
+ # - timeout : time to wait for input in seconds
287
+ # negative or zero is not acceptable
288
+ #
289
+ # <b>Returns</b>
290
+ # - ReturnStatus object
291
+ #
292
+ # failure, hangup, or timeout: 200 result=-1
293
+ # success: 200 result=<text>
294
+ # <text> is the text received on the channel.
295
+ # Command Reference: RECEIVE TEXT <timeout>
296
+ #
297
+ public
298
+ def receive_text(timeout)
299
+ timeout = sanitize_timeout(timeout)
300
+ raise(ArgumentError, "timeout need to be positive") if (timeout < 1)
301
+
302
+ cmd = "RECEIVE TEXT #{timeout.to_s}"
303
+ rs = exec_command(cmd)
304
+ raise CommandError, rs.to_s if rs.command_error?
305
+ return rs
306
+ end
307
+
308
+ #
309
+ # Record to a file until <escape digits> are received as dtmf.
310
+ #
311
+ # <b>Parameters</b>
312
+ # - filename : location of the file where the audio file will be saved
313
+ # - format : specify what kind of file will be recorded.
314
+ # - escape_digits : digit(s) to be pressed to complete recording
315
+ # - timeout : maximum record time in seconds
316
+ # nil, negative or 0 for no timeout.
317
+ # - offset : [offset samples] is optional,
318
+ # and if provided will seek to the offset without exceeding the end of the file.
319
+ # - silence : number of seconds of silence allowed before the function returns
320
+ # despite the lack of dtmf digits or reaching timeout.
321
+ # Silence value must be preceeded by "s=" and is optional.
322
+ #
323
+ # <b>Returns</b>
324
+ # - ReturnStatus object
325
+ #
326
+ # failure to write: 200 result=-1 (writefile)
327
+ # failure on waitfor: 200 result=-1 (waitfor) endpos=<offset>
328
+ # hangup: 200 result=0 (hangup) endpos=<offset>
329
+ # interrrupted: 200 result=<digit> (dtmf) endpos=<offset>
330
+ # timeout: 200 result=0 (timeout) endpos=<offset>
331
+ # random error: 200 result=<error> (randomerror) endpos=<offset>
332
+ # <offset> is the end offset in the file being recorded.
333
+ # <digit> is the ascii code for the digit pressed.
334
+ # <error> ?????
335
+ #
336
+ # Command Reference: RECORD FILE <filename> <format> <escape digits> <timeout> [offset samples] [BEEP] [s=<silence>]
337
+ #
338
+ public
339
+ def record_file(filename, format='gsm', escape_digits='#', timeout=nil, beep=true)
340
+
341
+ format = sanitize_file_format(format)
342
+ escape_digits = sanitize_escape_digits(escape_digits)
343
+ timeout = sanitize_timeout(timeout)
344
+
345
+
346
+ if ((escape_digits == "X") and (timeout == -1))
347
+ raise(ArgumentError, "need at least one valid escape digit or timeout need te positive")
348
+ end
349
+
350
+ cmd = "RECORD FILE #{filename} #{format} #{escape_digits} #{timeout}"
351
+ cmd = "#{cmd} beep" if beep == true
352
+ rs = exec_command(cmd)
353
+ raise CommandError, rs.to_s if rs.command_error?
354
+ return rs
355
+ end
356
+
357
+
358
+ #
359
+ # Say a given digit string, returning early if any of the given DTMF digits are received on the channel.
360
+ #
361
+ # <b>Parameters</b>
362
+ # - number : number to announce
363
+ # - escape_digit : if digit pressed during playback, will return from announce
364
+ #
365
+ # <b>Returns</b>
366
+ # - ReturnStatus (object)
367
+ #
368
+ # failure: 200 result=-1
369
+ # success: 200 result=0
370
+ # digit pressed: 200 result=<digit>
371
+ # <digit> is the ascii code for the digit pressed.
372
+ #
373
+ # Command Reference: SAY DIGITS <number> <escape digits>
374
+ #
375
+ public
376
+ def say_digits(digit_string, escape_digits=nil)
377
+ escape_digits = sanitize_escape_digits(escape_digits)
378
+
379
+ cmd = "SAY DIGITS #{digit_string.to_s} #{escape_digits}"
380
+ rs = exec_command(cmd)
381
+ raise CommandError, rs.to_s if rs.command_error?
382
+ return rs
383
+ end
384
+
385
+ #
386
+ # Say a given number, returning early if any of the given DTMF digits are received on the channel.
387
+ #
388
+ # <b>Parameters</b>
389
+ # - number : number to announce
390
+ # - escape_digit : if pressed, return from program
391
+ #
392
+ # <b>Returns</b>
393
+ # - ReturnStatus object
394
+ #
395
+ # failure: 200 result=-1
396
+ # success: 200 result=0
397
+ # digit pressed: 200 result=<digit>
398
+ #<digit> is the ascii code for the digit pressed.
399
+ #
400
+ # Command Reference: SAY NUMBER <number> <escape digits>
401
+ #
402
+ public
403
+ def say_number(number, escape_digits=nil)
404
+ escape_digits = sanitize_escape_digits(escape_digits)
405
+ cmd = "SAY NUMBER #{number.to_s} #{escape_digits.to_s}"
406
+ rs = exec_command(cmd)
407
+ raise CommandError, rs.to_s if rs.command_error?
408
+ return rs
409
+ end
410
+
411
+ #
412
+ # Say a given character string with phonetics, returning early if any of the given DTMF digits are received on the channel.
413
+ #
414
+ # <b>Parameters</b>
415
+ # - string : character string to announce
416
+ # - escape_digit : digit to be pressed to escape from program
417
+ #
418
+ # <b>Returns</b>
419
+ # - ReturnStatus (object)
420
+ #
421
+ # failure: 200 result=-1
422
+ # success: 200 result=0
423
+ # digit pressed: 200 result=<digit>
424
+ # <digit> is the ascii code for the digit pressed.
425
+ #
426
+ # Command Reference: SAY PHONETIC <string> <escape digits>
427
+ #
428
+ public
429
+ def say_phonetic(string, escape_digits=nil)
430
+ escape_digits = sanitize_escape_digits(escape_digits)
431
+ cmd = "SAY PHONETIC #{string.to_s} #{escape_digits}"
432
+ rs = exec_command(cmd)
433
+ raise CommandError, rs.to_s if rs.command_error?
434
+ return rs
435
+ end
436
+
437
+ #
438
+ # Say a given time, returning early if any of the given DTMF digits are received on the channel.
439
+ #
440
+ # <b>Parameters</b>
441
+ # - time : number of seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC).
442
+ # - escape_digits : digit to be pressed to escape from the program
443
+ #
444
+ # <b>Returns</b>
445
+ # - ReturnStatus (object)
446
+ #
447
+ # failure: 200 result=-1
448
+ # success: 200 result=0
449
+ # digit pressed: 200 result=<digit>
450
+ # <digit> is the ascii code for the digit pressed.
451
+ #
452
+ # Command Reference: SAY TIME <time> <escape digits>
453
+ #
454
+ public
455
+ def say_time(time=Time.now.to_i, escape_digits='#')
456
+ escape_digits = sanitize_escape_digits(escape_digits)
457
+ cmd = "SAY TIME #{time.to_s} #{escape_digits.to_s}"
458
+ rs = exec_command(cmd)
459
+ raise CommandError, rs.to_s if rs.command_error?
460
+ return rs
461
+ end
462
+
463
+ #
464
+ # Sends the given image on a channel.
465
+ # Most channels do not support the transmission of images.
466
+ # Image names should not include extensions.
467
+ #
468
+ # <b>Parameters</b>
469
+ # - image : location of image
470
+ #
471
+ # <b>Returns</b>
472
+ # - ReturnStatus (object)
473
+ #
474
+ # failure: 200 result=-1
475
+ # success: 200 result=0
476
+ #
477
+ # Command Reference: SEND IMAGE <image>
478
+ #
479
+ public
480
+ def send_image(image)
481
+ cmd = "SEND IMAGE #{image.to_s}"
482
+ rs = exec_command(cmd)
483
+ raise CommandError, rs.to_s if rs.command_error?
484
+ return rs
485
+ end
486
+
487
+ #
488
+ # Sends the given text on a channel.
489
+ # Most channels do not support the transmission of text.
490
+ # Text consisting of greater than one word should be placed in quotes since the command only accepts a single argument.
491
+ #
492
+ # <b>Parameters</b>
493
+ # - text : text to be send
494
+ #
495
+ # <b>Returns</b>
496
+ # - ReturnStatus (object)
497
+ #
498
+ # failure: 200 result=-1
499
+ # success: 200 result=0
500
+ #
501
+ # Command Reference: SEND TEXT "<text to send>"
502
+ #
503
+ public
504
+ def send_text(text)
505
+ cmd = "SEND TEXT #{text.to_s}"
506
+ rs = exec_command(cmd)
507
+ raise CommandError, rs.to_s if rs.command_error?
508
+ return rs
509
+ end
510
+
511
+ #
512
+ # Changes the callerid of the current channel.
513
+ #
514
+ # <b>Parameters</b>
515
+ # - number : number to be set a callerid
516
+ #
517
+ # <b>Returns</b>
518
+ # - ReturnStatus (object)
519
+ #
520
+ # 200 result=1
521
+ #
522
+ # Command Reference: SET CALLERID <number>
523
+ #
524
+ public
525
+ def set_caller_id(number)
526
+ cmd = "SET CALLERID #{number.to_s}"
527
+ rs = exec_command(cmd)
528
+ raise CommandError, rs.to_s if rs.command_error?
529
+ return rs
530
+ end
531
+
532
+ #
533
+ # Sets the context for continuation upon exiting the application.
534
+ #
535
+ # <b>Parameters</b>
536
+ # - context : name of the context
537
+ #
538
+ # <b>Returns</b>
539
+ # - ReturnStatus object
540
+ #
541
+ # 200 result=0
542
+ # Note: no checking is done to verify that the context is valid.
543
+ # Specifying an invalid context will cause the call to drop
544
+ #
545
+ # Command Reference: SET CONTEXT <desired context>
546
+ #
547
+ public
548
+ def set_context(context)
549
+ cmd = "SET CONTEXT #{context.to_s}"
550
+ rs = exec_command(cmd)
551
+ raise CommandError, rs.to_s if rs.command_error?
552
+ return rs
553
+ end
554
+
555
+ #
556
+ # Changes the extension for continuation upon exiting the application.
557
+ #
558
+ # <b>Parameters</b>
559
+ # - extension: name or number of extension to be set
560
+ #
561
+ # <b>Returns</b>
562
+ # - ReturnStatus object
563
+ #
564
+ # 200 result=0
565
+ # Note: no checking is done to verify that the extension extists.
566
+ # If the extension does not exist, the PBX will attempt to move to the "i" (invalid) extension.
567
+ # If the invalid "i" extension does not exist, the call will drop
568
+ #
569
+ # Command Reference: SET EXTENSION <new extension>
570
+ #
571
+ public
572
+ def set_extension(extension)
573
+ cmd = "SET EXTENSION #{extension.to_s}"
574
+ rs = exec_command(cmd)
575
+ raise CommandError, rs.to_s if rs.command_error?
576
+ return rs
577
+ end
578
+
579
+ #
580
+ # Enables/Disables the music on hold generator.
581
+ #
582
+ # <b>Parameters</b>
583
+ # - mode : on or off
584
+ # - moh_class : name of the music on hold class
585
+ # 'default' for not provided or nil
586
+ #
587
+ # <b>Returns</b>
588
+ # - ReturnStatus object
589
+ #
590
+ # 200 result=0
591
+ # Command Reference: SET MUSIC <on|off> <class>
592
+ #
593
+ public
594
+ def set_music(mode=true, moh_class='default')
595
+ if ((mode == true) or (not (mode == 0)))
596
+ mode = 'ON'
597
+ else
598
+ mode = 'OFF'
599
+ end
600
+ cmd = "SET MUSIC #{mode.to_s} #{moh_class.to_s}"
601
+ rs = exec_command(cmd)
602
+ raise CommandError, rs.to_s if rs.command_error?
603
+ return rs
604
+ end
605
+
606
+ #
607
+ # Changes the priority for continuation upon exiting the application.
608
+ #
609
+ # <b>Parameters</b>
610
+ # - priority : number of priority
611
+ #
612
+ # <b>Returns</b>
613
+ # - ReturnStatus object
614
+ #
615
+ # 200 result=0
616
+ # Command Reference: SET PRIORITY <num>
617
+ #
618
+ public
619
+ def set_priority(priority)
620
+ cmd = "SET PRIORITY #{priority.to_s}"
621
+ rs = exec_command(cmd)
622
+ raise CommandError, rs.to_s if rs.command_error?
623
+ return rs
624
+ end
625
+
626
+ #
627
+ # set variable: Sets a channel variable
628
+ # These variables live in the channel Asterisk creates
629
+ # when you pickup a phone and as such they are both local
630
+ # and temporary. Variables created in one channel can not
631
+ # be accessed by another channel. When you hang up the phone,
632
+ # the channel is deleted and any variables in that channel are deleted as well.
633
+ #
634
+ # <b>Parameters</b>
635
+ # - variablename : name of the variable
636
+ # - value : value to be set for the variable
637
+ #
638
+ # <b>Returns</b>
639
+ # - ReturnStatus object
640
+ #
641
+ # 200 result=1
642
+ # Command Reference: SET VARIABLE <variablename> <value>
643
+ #
644
+ public
645
+ def set_variable(name, value)
646
+ cmd = "SET VARIABLE #{name.to_s} \"#{value.to_s}\""
647
+ rs = exec_command(cmd)
648
+ raise CommandError, rs.to_s if rs.command_error?
649
+ return rs
650
+ end
651
+
652
+
653
+ #
654
+ # stream file: Sends audio file on channel
655
+ # Send the given file, allowing playback to be interrupted by the given digits, if any.
656
+ # Use double quotes for the digits if you wish none to be permitted.
657
+ # If sample offset is provided then the audio will seek to sample offset before play starts.
658
+ # Remember, the file extension must not be included in the filename.
659
+ #
660
+ # <b>Parameters</b>
661
+ # - filename : location of the file to be played
662
+ # - escape_digit: digit to be pressed to escape from playback
663
+ #
664
+ # <b>Returns</b>
665
+ # - ReturnStatus object
666
+ #
667
+ # failure: 200 result=-1 endpos=<sample offset>
668
+ # failure on open: 200 result=0 endpos=0
669
+ # success: 200 result=0 endpos=<offset>
670
+ # digit pressed: 200 result=<digit> endpos=<offset>
671
+ # <offset> is the stream position streaming stopped. If it equals <sample offset> there was probably an error.
672
+ # <digit> is the ascii code for the digit pressed.
673
+ # Command Reference: STREAM FILE <filename> <escape digits> [sample offset]
674
+ #
675
+ public
676
+ def stream_file(filename, escape_digits='#')
677
+
678
+ escape_digits = sanitize_escape_digits(escape_digits)
679
+
680
+ cmd = "STREAM FILE #{filename.to_s} #{escape_digits}"
681
+ rs = exec_command(cmd)
682
+ raise CommandError, rs.to_s if rs.command_error?
683
+
684
+ return rs
685
+ end
686
+
687
+ #
688
+ # tdd mode: Activates TDD mode on channels supporting it, to enable communication with TDDs.
689
+ # Enable/Disable TDD transmission/reception on a channel.
690
+ # This function is currently (01July2005) only supported on Zap channels.
691
+ # As of 02July2005, this function never returns 0 (Not Capable).
692
+ # If it fails for any reason, -1 (Failure) will be returned, otherwise 1 (Success) will be returned.
693
+ # The capability for returning 0 if the channel is not capable of TDD MODE is a future plan.
694
+ #
695
+ # <b>Parameters</b>
696
+ # - mode : mode of the tdd to be set
697
+ # set tdd on if non-zero or 'true' specified
698
+ #
699
+ # <b>Returns</b>
700
+ # - ReturnStatus object
701
+ #
702
+ # failure: 200 result=-1
703
+ # not capable: 200 result=0
704
+ # success: 200 result=1
705
+ # Command Reference: TDD MODE <on|off|mate>
706
+ #
707
+ public
708
+ def tdd_mode(mode=true)
709
+ if ((mode == true) or ( not (mode == 1)))
710
+ mode = 'ON'
711
+ else
712
+ mode = 'OFF'
713
+ end
714
+ cmd = "TDD MODE #{mode.to_s}"
715
+ rs = exec_command(cmd)
716
+ raise CommandError, rs.to_s if rs.command_error?
717
+ return rs
718
+ end
719
+
720
+ #
721
+ # Sends <message> to the console via verbose message system.
722
+ # The Asterisk verbosity system works as follows.
723
+ # The Asterisk user gets to set the desired verbosity at startup time
724
+ # or later using the console 'set verbose' command.
725
+ # Messages are displayed on the console if their verbose level
726
+ # is less than or equal to desired verbosity set by the user.
727
+ # More important messages should have a low verbose level;
728
+ # less important messages should have a high verbose level.
729
+ #
730
+ # <b>Parameters</b>
731
+ # - message : message to be send as log
732
+ # - level : verbose level to be set
733
+ # [level] is the the verbose level (1-4)
734
+ # If you specify a verbose level less than 1 or greater than 4, the verbosity is 1.
735
+ # The default verbosity seems to be 0 (in 1.0.8),
736
+ # and supplying a 0 (zero) verbosity does work:
737
+ # the message will be displayed regardless of the console verbosity setting.
738
+ #
739
+ # <b>Returns</b>
740
+ # - ReturnStatus object
741
+ #
742
+ # 200 result=1
743
+ # Command Reference: VERBOSE <message> [level]
744
+ #
745
+ public
746
+ def verbose(message, level=3)
747
+ cmd = "VERBOSE \"#{message.to_s}\" #{level.to_s}"
748
+ rs = exec_command(cmd)
749
+ raise CommandError, rs.to_s if rs.command_error?
750
+ return rs
751
+ end
752
+
753
+ #
754
+ # wait for digit: Waits for a digit to be pressed
755
+ # Waits up to <timeout> milliseconds for channel to receive a DTMF digit.
756
+ #
757
+ # <b>Parameters</b>
758
+ # - timeout : maximum allow waiting time in seconds to get input
759
+ # nil, zero or negative would be considered as infinite wait time
760
+ #
761
+ # <b>Returns</b>
762
+ # - ReturnStatus object
763
+ #
764
+ # failure: 200 result=-1
765
+ # timeout: 200 result=0
766
+ # success: 200 result=<digit>
767
+ # <digit> is the ascii code for the digit received.
768
+ # Command Reference: WAIT FOR DIGIT <timeout>
769
+ #
770
+ public
771
+ def wait_for_digit(timeout=nil)
772
+ timeout = sanitize_timeout(timeout)
773
+
774
+ cmd = "WAIT FOR DIGIT #{timeout.to_s}"
775
+ rs = exec_command(cmd)
776
+ raise CommandError, rs.to_s if rs.command_error?
777
+ return rs
778
+ end
779
+
780
+ #
781
+ # method to dial out
782
+ #
783
+ # <b>Parameters</b>
784
+ # - telephone_number : telephone_number or extension to dial
785
+ # - protocol : protocol to be used to make this call
786
+ # - username : username to be used to make this call using the specified protocol
787
+ # - context : name of the context to be used for authentication
788
+ # - timeout : maximum allowed time in seconds to make this call
789
+ # - options : options to be passed in 'Dial' command
790
+ #
791
+ # <b>Returns</b>
792
+ # - ReturnStatus object
793
+ #
794
+ # Command Reference: Dial(type/identifier,timeout,options,URL)
795
+ #
796
+ def dial(telephone_number=nil, protocol=nil, username=nil, context='default', timeout=nil, options=nil)
797
+ dial_string = nil
798
+
799
+ if protocol == 'LOCAL'
800
+ return nil if (telephone_number.nil? or context.nil?)
801
+ dial_string = "LOCAL/#{telephone_number}@#{context}"
802
+ elsif protocol == 'IAX2'
803
+ return nil if (telephone_number.nil? or username.nil? or context.nil?)
804
+ telephone_number.strip!
805
+ dial_string = "IAX2/#{username}@#{context}/#{telephone_number}"
806
+ elsif protocol == 'SIP'
807
+ else
808
+ return nil
809
+ end
810
+
811
+ timeout.nil? ? dial_string += "|" : dial_string += "|#{timeout}"
812
+ options.nil? ? dial_string += "|" : dial_string += "|#{options}"
813
+ rs = exec('DIAL', dial_string)
814
+ return rs
815
+ end
816
+
817
+ ###### Process methods #######
818
+
819
+ public
820
+ def raw_command(cmd)
821
+ rs = exec_command(cmd)
822
+ raise CommandError, rs.to_s if rs.command_error?
823
+ return rs
824
+ end
825
+
826
+ #private
827
+ #def escape(str)
828
+ # rxp = Regexp.new(/\"/)
829
+ # return str.gsub(rxp, '\"')
830
+ #end
831
+
832
+ protected
833
+ def exec_command(cmd)
834
+ rs = nil
835
+ begin
836
+ semaphore do
837
+ $stderr.puts " -- ruby-agi << #{cmd}" if debug?
838
+ $stdout.puts cmd
839
+ responses = $stdin.gets
840
+ $stderr.puts " -- ruby-agi >> #{responses}" if debug?
841
+ rs = ReturnStatus.new(cmd, responses)
842
+
843
+ end
844
+
845
+ rescue Errno::EPIPE
846
+ raise HangupError, "Line hung up during command execution!!"
847
+ end
848
+
849
+ return rs
850
+ end
851
+
852
+ protected
853
+ def sanitize_escape_digits(digits)
854
+ if digits.nil?
855
+ digits = "#"
856
+ elsif digits.size == 0
857
+ digits = "X"
858
+ else
859
+ digits = digits.to_s
860
+ end
861
+
862
+ return digits
863
+ end
864
+
865
+ protected
866
+ def sanitize_timeout(timeout)
867
+ if timeout.nil? or timeout <= 0
868
+ timeout = -1
869
+ else
870
+ timeout = timeout * 1000
871
+ end
872
+
873
+ return timeout
874
+ end
875
+
876
+ protected
877
+ def sanitize_file_format(format)
878
+ if format.nil? or format.size == 0
879
+ format = "gsm"
880
+ else
881
+ format = format.to_s
882
+ end
883
+
884
+ return format
885
+ end
886
+
887
+ protected
888
+ def sanitize_max_digit(max_digit)
889
+ if ((max_digit.nil?) or (max_digit <= 0))
890
+ max_digit = ""
891
+ else
892
+ max_digit = max_digit.to_i
893
+ end
894
+
895
+ return max_digit
896
+ end
897
+ end