agi 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,239 @@
1
+ #
2
+ # File: asterisk_variables.rb
3
+ #
4
+ # 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
+ # == Overview
24
+ #
25
+
26
+ # Followings are the list of AGI variables
27
+ # -- agi >> agi_request
28
+ # -- agi >> agi_channel
29
+ # -- agi >> agi_language
30
+ # -- agi >> agi_type
31
+ # -- agi >> agi_uniqueid
32
+ # -- agi >> agi_callerid
33
+ # -- agi >> agi_dnid
34
+ # -- agi >> agi_rdnis
35
+ # -- agi >> agi_context
36
+ # -- agi >> agi_extension
37
+ # -- agi >> agi_priority
38
+ # -- agi >> agi_enhanced
39
+ # -- agi >> agi_accountcode
40
+
41
+
42
+ require 'agi/agi.rb'
43
+ require 'agi/error.rb'
44
+
45
+ class AGI
46
+ end
47
+
48
+ class AsteriskVariable < AGI
49
+
50
+ def initialize
51
+ env
52
+ end
53
+
54
+ protected
55
+ def env
56
+ if @asterisk_variable.nil?
57
+ @asterisk_variable = Hash.new
58
+ semaphore do
59
+ $stdin.each_line do | line |
60
+ line.strip!
61
+ break if line.nil? or line.size.zero? or line == "\n"
62
+ key, value = line.split(':')
63
+ value.strip! if not value.nil?
64
+ if ((not key.nil?) and (not key.to_s.size.zero?))
65
+ @asterisk_variable[key.to_s] = value
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ return @asterisk_variable
72
+ end
73
+
74
+ protected
75
+ def read_env(name)
76
+ if debug?
77
+ semaphore do
78
+ $stderr.puts " -- agi << Read asterisk variable '#{name}'"
79
+ $stderr.puts " -- agi >> Asterisk variable #{name} = #{env[name].to_s}"
80
+ end
81
+ end
82
+
83
+ return env[name]
84
+ end
85
+
86
+ public
87
+ def request
88
+ return read_env('agi_request')
89
+ end
90
+
91
+ public
92
+ def channel
93
+ return read_env('agi_channel')
94
+ end
95
+
96
+ public
97
+ def language
98
+ return read_env('agi_language')
99
+ end
100
+
101
+ public
102
+ def type
103
+ return read_env('agi_type')
104
+ end
105
+
106
+ public
107
+ def uniqueid
108
+ return read_env('agi_uniqueid')
109
+ end
110
+
111
+ public
112
+ def callerid
113
+ if @callerid.nil?
114
+ init_caller_variable
115
+ end
116
+
117
+ return @callerid
118
+ end
119
+
120
+ public
121
+ def dnid
122
+ return read_env('agi_dnid')
123
+ end
124
+
125
+ public
126
+ def rdnid
127
+ return read_env('agi_rdnid')
128
+ end
129
+
130
+ public
131
+ def context
132
+ return read_env('agi_context')
133
+ end
134
+
135
+ public
136
+ def extension
137
+ return read_env('agi_extension')
138
+ end
139
+
140
+ public
141
+ def priority
142
+ return read_env('agi_priority')
143
+ end
144
+
145
+ public
146
+ def enhanced
147
+ return read_env('agi_enhanced')
148
+ end
149
+
150
+ public
151
+ def accountcode
152
+ return read_env('agi_accountcode')
153
+ end
154
+
155
+ ####################################################################
156
+ #### additional methods generated from existing basic methods ####
157
+ ####################################################################
158
+
159
+ public
160
+ def calleridname
161
+ if @calleridname.nil?
162
+ init_caller_variable
163
+ end
164
+
165
+ return @calleridname
166
+ end
167
+
168
+ public
169
+ def calleridnumber
170
+ if @calleridnumber.nil?
171
+ init_caller_variable
172
+ end
173
+
174
+ return @calleridnumber
175
+ end
176
+
177
+ # following methods are not confirm that they are AGI variables
178
+ public
179
+ def callingpres
180
+ return read_env('agi_callingpres')
181
+ end
182
+
183
+ public
184
+ def callingani2
185
+ return read_env('agi_callingani2')
186
+ end
187
+
188
+ public
189
+ def callington
190
+ return read_env('agi_callington')
191
+ end
192
+
193
+ public
194
+ def callingtns
195
+ return read_env('agi_callingtns')
196
+ end
197
+
198
+ # asterisk-1.0.9 : agi_callerid (default value is 'unknown')
199
+ # asterisk-1.0.10 : agi_callerid (default value is 'unknown')
200
+ # asterisk-1.0.10 : agi_callerid, agi_calleridname (default value for both is 'unknown')
201
+ protected
202
+ def init_caller_variable
203
+ @callerid = read_env('agi_callerid').to_s.strip
204
+ if @callerid == "unknown"
205
+ @callerid = ""
206
+ @calleridname = ""
207
+ @calleridnumber = ""
208
+ elsif Regexp.new(/^\d+\d$/).match(@callerid)
209
+ @calleridname = ""
210
+ @calleridnumber = @callerid
211
+ else
212
+ @calleridname = read_env('agi_calleridname')
213
+ if @calleridname.nil? # for asterisk that don't have agi variable 'agi_calleridname'
214
+ name = Regexp.new(/\".+\"/).match(@callerid)
215
+ number = Regexp.new(/\<\d+\>/).match(@callerid)
216
+
217
+ if name.nil?
218
+ @calleridname = ""
219
+ else
220
+ name = name.to_s
221
+ name.gsub!(/\"/, '')
222
+ @calleridname = name.to_s.strip
223
+ end
224
+
225
+ if number.nil?
226
+ @calleridnumber = ""
227
+ else
228
+ number = number.to_s
229
+ number.sub!(/\</, '')
230
+ number.sub!(/\>/, '')
231
+ @calleridnumber = number.to_s.strip
232
+ end
233
+ else # for asterisk that have agi variable 'agi_calleridname'
234
+ @calleridnumber = @callerid
235
+ @callerid = "\"#{@calleridname}\" <#{@calleridnumber}>"
236
+ end
237
+ end
238
+ end
239
+ end
@@ -0,0 +1,908 @@
1
+ #
2
+ # File: command.rb
3
+ #
4
+ # 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 'agi/agi.rb'
39
+ require 'agi/return_status.rb'
40
+ require '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 " -- agi << #{cmd}" if debug?
838
+ $stdout.puts cmd
839
+ responses = $stdin.gets
840
+ $stderr.puts " -- 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
+
898
+ ############################################
899
+ ### More synthetic methods ###
900
+ ############################################
901
+
902
+ public
903
+ def jump_to(context, extension, priority)
904
+ set_context(context) if not context.nil?
905
+ set_extension(extension) if not extension.nil?
906
+ set_priority(priority) if not priority.nil?
907
+ end
908
+ end