staskobzar /
goagi
| 1 | package goagi |
||
| 2 | |||
| 3 | import ( |
||
| 4 | "fmt" |
||
| 5 | "regexp" |
||
| 6 | ) |
||
| 7 | |||
| 8 | // Command sends command as string to the AGI and returns response valus with |
||
| 9 | // text response |
||
| 10 | func (agi *AGI) Command(cmd string) (code int, result int, respStr string, err error) { |
||
| 11 | resp, err := agi.execute(cmd) |
||
| 12 | if err != nil { |
||
| 13 | return -1, -1, "", err |
||
| 14 | } |
||
| 15 | return resp.code, int(resp.result), resp.raw, nil |
||
| 16 | } |
||
| 17 | |||
| 18 | // Answer executes AGI command "ANSWER" |
||
| 19 | // Answers channel if not already in answer state. |
||
| 20 | func (agi *AGI) Answer() (bool, error) { |
||
| 21 | resp, err := agi.execute("ANSWER") |
||
| 22 | if err != nil { |
||
| 23 | return false, err |
||
| 24 | } |
||
| 25 | return resp.isOk(), nil |
||
| 26 | } |
||
| 27 | |||
| 28 | // AsyncAGIBreak Interrupts Async AGI |
||
| 29 | // Interrupts expected flow of Async AGI commands and returns control |
||
| 30 | // to previous source (typically, the PBX dialplan). |
||
| 31 | func (agi *AGI) AsyncAGIBreak() (bool, error) { |
||
| 32 | resp, err := agi.execute("ASYNCAGI BREAK") |
||
| 33 | if err != nil { |
||
| 34 | return false, err |
||
| 35 | } |
||
| 36 | // Asterisk res_agi always returns 200 result=0 |
||
| 37 | // but for the future try to check response. |
||
| 38 | return resp.isOk(), nil |
||
| 39 | } |
||
| 40 | |||
| 41 | // ChannelStatus returns status of the connected channel. |
||
| 42 | // |
||
| 43 | // If no channel name is given (empty line) then returns the status of the current channel. |
||
| 44 | // |
||
| 45 | //Return values: |
||
| 46 | // 0 - Channel is down and available. |
||
| 47 | // 1 - Channel is down, but reserved. |
||
| 48 | // 2 - Channel is off hook. |
||
| 49 | // 3 - Digits (or equivalent) have been dialed. |
||
| 50 | // 4 - Line is ringing. |
||
| 51 | // 5 - Remote end is ringing. |
||
| 52 | // 6 - Line is up. |
||
| 53 | // 7 - Line is busy. |
||
| 54 | func (agi *AGI) ChannelStatus(channel string) (int, error) { |
||
| 55 | resp, err := agi.execute("CHANNEL STATUS " + channel) |
||
| 56 | if err != nil { |
||
| 57 | return -1, err |
||
| 58 | } |
||
| 59 | if resp.result == -1 { |
||
| 60 | return -1, errorNew("No channel name matched the argument given.") |
||
| 61 | } |
||
| 62 | return int(resp.result), nil |
||
| 63 | } |
||
| 64 | |||
| 65 | // ControlStreamFile sends audio file on channel and allows the listener |
||
| 66 | // to control the stream. |
||
| 67 | // Send the given file, allowing playback to be controlled by the given digits, if any. |
||
| 68 | // Use double quotes for the digits if you wish none to be permitted. If offsetms |
||
| 69 | // is provided then the audio will seek to offsetms before play starts. |
||
| 70 | // Returns 0 if playback completes without a digit being pressed, or the ASCII numerical |
||
| 71 | // value of the digit if one was pressed, or -1 on error or if the channel was |
||
| 72 | // disconnected. |
||
| 73 | // Returns the position where playback was terminated as endpos. |
||
| 74 | // Example: |
||
| 75 | // agi.ControlStreamFile("prompt_en", "19", "3000", "#", "0", "#", "1600") |
||
| 76 | // agi.ControlStreamFile("prompt_en", "") |
||
| 77 | // agi.ControlStreamFile("prompt_en", "19", "", "", "", "#", "1600") |
||
| 78 | func (agi *AGI) ControlStreamFile(filename, digits string, args ...interface{}) (int32, error) { |
||
| 79 | cmd := "CONTROL STREAM FILE " + filename |
||
| 80 | if len(digits) > 0 { |
||
| 81 | cmd += " " + digits |
||
| 82 | } else { |
||
| 83 | cmd += " \"\"" |
||
| 84 | } |
||
| 85 | resp, err := agi.execute(cmd, args...) |
||
| 86 | if err != nil { |
||
| 87 | return 0, err |
||
| 88 | } |
||
| 89 | if resp.result == -1 { |
||
| 90 | return resp.result, errorNew("Error or channel disconnected.") |
||
| 91 | } |
||
| 92 | |||
| 93 | return resp.endpos, nil |
||
| 94 | } |
||
| 95 | |||
| 96 | // DatabaseDel deletes an entry in the Asterisk database for a given family and key. |
||
| 97 | // Returns status and error if fails. |
||
| 98 | func (agi *AGI) DatabaseDel(family, key string) (bool, error) { |
||
| 99 | resp, err := agi.execute("DATABASE DELETE", family, key) |
||
| 100 | if err != nil { |
||
| 101 | return false, err |
||
| 102 | } |
||
| 103 | ok := resp.code == 200 && resp.result == 1 |
||
| 104 | return ok, nil |
||
| 105 | } |
||
| 106 | |||
| 107 | // DatabaseDelTree deletes a family or specific keytree within a family in the Asterisk database. |
||
| 108 | func (agi *AGI) DatabaseDelTree(family, keytree string) (bool, error) { |
||
| 109 | resp, err := agi.execute("DATABASE DELTREE", family, keytree) |
||
| 110 | if err != nil { |
||
| 111 | return false, err |
||
| 112 | } |
||
| 113 | ok := resp.code == 200 && resp.result == 1 |
||
| 114 | return ok, nil |
||
| 115 | } |
||
| 116 | |||
| 117 | // DatabaseGet Retrieves an entry in the Asterisk database for a given family and key. |
||
| 118 | // Returns value as string or error if failed or value not set |
||
| 119 | func (agi *AGI) DatabaseGet(family, key string) (string, error) { |
||
| 120 | resp, err := agi.execute("DATABASE GET", family, key) |
||
| 121 | if err != nil { |
||
| 122 | return "", err |
||
| 123 | } |
||
| 124 | if resp.result == 0 { |
||
| 125 | return "", errorNew("Value not set.") |
||
| 126 | } |
||
| 127 | return resp.value, nil |
||
| 128 | } |
||
| 129 | |||
| 130 | // DatabasePut adds or updates an entry in the Asterisk database for |
||
| 131 | // a given family, key, and value. |
||
| 132 | func (agi *AGI) DatabasePut(family, key, val string) (bool, error) { |
||
| 133 | resp, err := agi.execute("DATABASE PUT", family, key, val) |
||
| 134 | if err != nil { |
||
| 135 | return false, err |
||
| 136 | } |
||
| 137 | ok := resp.code == 200 && resp.result == 1 |
||
| 138 | return ok, nil |
||
| 139 | } |
||
| 140 | |||
| 141 | // Exec executes application with given options. |
||
| 142 | func (agi *AGI) Exec(app, opts string) (int, error) { |
||
| 143 | opts = `"` + opts + `"` |
||
| 144 | resp, err := agi.execute("EXEC", app, opts) |
||
| 145 | if err != nil { |
||
| 146 | return -1, err |
||
| 147 | } |
||
| 148 | |||
| 149 | if resp.result == -2 { |
||
| 150 | return -2, errorNew("Could not find application " + app) |
||
| 151 | } |
||
| 152 | return int(resp.result), nil |
||
| 153 | } |
||
| 154 | |||
| 155 | // GetData Stream the given file, and receive DTMF data. |
||
| 156 | func (agi *AGI) GetData(file string, args ...interface{}) (digit string, timeout bool, err error) { |
||
| 157 | cmd := "GET DATA " + file |
||
| 158 | resp, err := agi.execute(cmd, args...) |
||
| 159 | if err != nil { |
||
| 160 | return "", false, err |
||
| 161 | } |
||
| 162 | re := regexp.MustCompile(`200 result=([\d*]+)`) |
||
| 163 | result := re.FindStringSubmatch(resp.raw) |
||
| 164 | |||
| 165 | if len(result) > 1 { |
||
| 166 | return result[1], false, nil |
||
| 167 | } |
||
| 168 | |||
| 169 | if resp.result < 0 { |
||
| 170 | return "", false, errorNew("Failed get data.") |
||
| 171 | } |
||
| 172 | timeout = resp.value == "timeout" |
||
| 173 | digit = "" //string(resp.result) |
||
| 174 | return |
||
| 175 | } |
||
| 176 | |||
| 177 | // GetFullVariable evaluates a channel expression |
||
| 178 | func (agi *AGI) GetFullVariable(name string, channel ...string) (string, error) { |
||
| 179 | cmd := "GET FULL VARIABLE " + name |
||
| 180 | var resp *agiResp |
||
| 181 | var err error |
||
| 182 | if len(channel) > 0 { |
||
| 183 | resp, err = agi.execute(cmd, channel[0]) |
||
| 184 | } else { |
||
| 185 | resp, err = agi.execute(cmd) |
||
| 186 | } |
||
| 187 | if err != nil { |
||
| 188 | return "", err |
||
| 189 | } |
||
| 190 | if resp.result == 0 { |
||
| 191 | return "", errorNew("Variable is not set.") |
||
| 192 | } |
||
| 193 | |||
| 194 | return resp.value, nil |
||
| 195 | } |
||
| 196 | |||
| 197 | // GetOption Stream file, prompt for DTMF, with timeout. |
||
| 198 | // Behaves similar to STREAM FILE but used with a timeout option. |
||
| 199 | // Returns digit pressed, offset and error |
||
| 200 | func (agi *AGI) GetOption(filename, digits string, timeout int32) (int, int32, error) { |
||
| 201 | cmd := "GET OPTION " + filename |
||
| 202 | resp, err := agi.execute(cmd, digits, timeout) |
||
| 203 | if err != nil { |
||
| 204 | return -1, 0, err |
||
| 205 | } |
||
| 206 | |||
| 207 | if resp.result == -1 { |
||
| 208 | return -1, 0, errorNew("Command failure") |
||
| 209 | } |
||
| 210 | |||
| 211 | if resp.result == 0 && resp.endpos == 0 { |
||
| 212 | return -1, 0, errorNew("Failure on open") |
||
| 213 | } |
||
| 214 | |||
| 215 | return int(resp.result), resp.endpos, nil |
||
| 216 | } |
||
| 217 | |||
| 218 | // GetVariable Gets a channel variable. |
||
| 219 | func (agi *AGI) GetVariable(name string) (string, error) { |
||
| 220 | resp, err := agi.execute("GET VARIABLE", name) |
||
| 221 | if err != nil { |
||
| 222 | return "", err |
||
| 223 | } |
||
| 224 | if resp.result == 0 { |
||
| 225 | return "", errorNew("Variable is not set.") |
||
| 226 | } |
||
| 227 | |||
| 228 | return resp.value, nil |
||
| 229 | } |
||
| 230 | |||
| 231 | // GetVariable Gets a channel variable. |
||
|
0 ignored issues
–
show
introduced
by
Loading history...
|
|||
| 232 | func (agi *AGI) GoSub(ctx, ext, prio, args string) (bool, error) { |
||
| 233 | resp, err := agi.execute("GOSUB", ctx, ext, prio, args) |
||
| 234 | if err != nil { |
||
| 235 | return false, err |
||
| 236 | } |
||
| 237 | if resp.result == -1 { |
||
| 238 | return false, errorNew("Failed Gosub") |
||
| 239 | } |
||
| 240 | if resp.result == 0 && resp.code == 100 { |
||
| 241 | chStr, chErr := agi.read() |
||
| 242 | select { |
||
| 243 | case str := <-chStr: |
||
| 244 | resp, err = parseResponse(str) |
||
| 245 | if err != nil { |
||
| 246 | return false, err |
||
| 247 | } |
||
| 248 | return resp.code == 200, nil |
||
| 249 | case err := <-chErr: |
||
| 250 | return false, err |
||
| 251 | } |
||
| 252 | } |
||
| 253 | return true, nil |
||
| 254 | } |
||
| 255 | |||
| 256 | // Hangup a channel. |
||
| 257 | // Hangs up the specified channel. If no channel name is given, hangs up the current channel |
||
| 258 | func (agi *AGI) Hangup(channel ...string) (bool, error) { |
||
| 259 | cmd := "HANGUP" |
||
| 260 | if len(channel) > 0 { |
||
| 261 | cmd += " " + channel[0] |
||
| 262 | } |
||
| 263 | resp, err := agi.execute(cmd) |
||
| 264 | if err != nil { |
||
| 265 | return false, err |
||
| 266 | } |
||
| 267 | if resp.result == -1 { |
||
| 268 | return false, errorNew("Failed hangup") |
||
| 269 | } |
||
| 270 | return true, nil |
||
| 271 | } |
||
| 272 | |||
| 273 | // Noop Does nothing. |
||
| 274 | func (agi *AGI) Noop() error { |
||
| 275 | _, err := agi.execute("NOOP") |
||
| 276 | return err |
||
| 277 | } |
||
| 278 | |||
| 279 | // ReceiveChar Receives one character from channels supporting it. |
||
| 280 | // Most channels do not support the reception of text. Returns the decimal value of |
||
| 281 | // the character if one is received, or 0 if the channel does not support text reception. |
||
| 282 | // timeout - The maximum time to wait for input in milliseconds, or 0 for infinite. Most channels |
||
| 283 | // Returns -1 only on error/hangup. |
||
| 284 | func (agi *AGI) ReceiveChar(timeout int32) (int, error) { |
||
| 285 | resp, err := agi.execute("RECEIVE CHAR", timeout) |
||
| 286 | if err != nil { |
||
| 287 | return -1, err |
||
| 288 | } |
||
| 289 | if resp.result == -1 { |
||
| 290 | return -1, errorNew("Channel error or hangup.") |
||
| 291 | } |
||
| 292 | if resp.result == 0 { |
||
| 293 | return -1, errorNew("Channel does not support text reception.") |
||
| 294 | } |
||
| 295 | return int(resp.result), nil |
||
| 296 | } |
||
| 297 | |||
| 298 | // ReceiveText Receives text from channels supporting it. |
||
| 299 | // timeout - The timeout to be the maximum time to wait for input in milliseconds, or 0 for infinite. |
||
| 300 | func (agi *AGI) ReceiveText(timeout int32) (string, error) { |
||
| 301 | resp, err := agi.execute("RECEIVE TEXT", timeout) |
||
| 302 | if err != nil { |
||
| 303 | return "", err |
||
| 304 | } |
||
| 305 | if resp.result == -1 { |
||
| 306 | return "", errorNew("Failure, hangup or timeout.") |
||
| 307 | } |
||
| 308 | return resp.value, nil |
||
| 309 | } |
||
| 310 | |||
| 311 | // RecordFile Record to a file until a given dtmf digit in the sequence is received. |
||
| 312 | // The format will specify what kind of file will be recorded. The timeout is the |
||
| 313 | // maximum record time in milliseconds, or -1 for no timeout. |
||
| 314 | // offset samples is optional, and, if provided, will seek to the offset without |
||
| 315 | // exceeding the end of the file. |
||
| 316 | // beep causes Asterisk to play a beep to the channel that is about to be recorded. |
||
| 317 | // silence is the number of seconds of silence allowed before the function returns |
||
| 318 | // despite the lack of dtmf digits or reaching timeout. |
||
| 319 | // silence is the number of seconds of silence that are permitted before the |
||
| 320 | // recording is terminated, regardless of the escape_digits or timeout arguments |
||
| 321 | func (agi *AGI) RecordFile(file, format, escDigits string, |
||
| 322 | timeout, offset int, beep bool, silence int) error { |
||
| 323 | |||
| 324 | cmd := "RECORD FILE" |
||
| 325 | cmd = fmt.Sprintf("%s %s %s %s", cmd, file, format, escDigits) |
||
| 326 | if beep { |
||
| 327 | cmd = fmt.Sprintf("%s BEEP", cmd) |
||
| 328 | } |
||
| 329 | if silence > 0 { |
||
| 330 | cmd = fmt.Sprintf("%s s=%d", cmd, silence) |
||
| 331 | } |
||
| 332 | resp, err := agi.execute(cmd) |
||
| 333 | if err != nil { |
||
| 334 | return err |
||
| 335 | } |
||
| 336 | if resp.result <= 0 { |
||
| 337 | return errorNew("Failed record file") |
||
| 338 | } |
||
| 339 | return nil |
||
| 340 | } |
||
| 341 | |||
| 342 | func (agi *AGI) say(cmd string, args ...interface{}) error { |
||
| 343 | resp, err := agi.execute("SAY "+cmd, args...) |
||
| 344 | if err != nil { |
||
| 345 | return err |
||
| 346 | } |
||
| 347 | if resp.result < 0 { |
||
| 348 | return errorNew("Failure") |
||
| 349 | } |
||
| 350 | return nil |
||
| 351 | } |
||
| 352 | |||
| 353 | // SayAlpha says a given character string, returning early if any of the given |
||
| 354 | // DTMF digits are received on the channel. |
||
| 355 | func (agi *AGI) SayAlpha(number, escDigits string) error { |
||
| 356 | return agi.say("ALPHA", number, escDigits) |
||
| 357 | } |
||
| 358 | |||
| 359 | // SayDate say a given date, returning early if any of the given DTMF digits |
||
| 360 | // are received on the channel |
||
| 361 | func (agi *AGI) SayDate(date, escDigits string) error { |
||
| 362 | return agi.say("DATE", date, escDigits) |
||
| 363 | } |
||
| 364 | |||
| 365 | // SayDatetime say a given time, returning early if any of the given DTMF |
||
| 366 | // digits are received on the channel |
||
| 367 | func (agi *AGI) SayDatetime(time, escDigits, format, timezone string) error { |
||
| 368 | return agi.say("DATETIME", time, escDigits, format, timezone) |
||
| 369 | } |
||
| 370 | |||
| 371 | // SayDigits say a given digit string, returning early if any of the given |
||
| 372 | // DTMF digits are received on the channel |
||
| 373 | func (agi *AGI) SayDigits(number, escDigits string) error { |
||
| 374 | return agi.say("DIGITS", number, escDigits) |
||
| 375 | } |
||
| 376 | |||
| 377 | // SayNumber say a given digit string, returning early if any of the given |
||
| 378 | // DTMF digits are received on the channel |
||
| 379 | func (agi *AGI) SayNumber(number, escDigits string) error { |
||
| 380 | return agi.say("NUMBER", number, escDigits) |
||
| 381 | } |
||
| 382 | |||
| 383 | // SayPhonetic say a given character string with phonetics, returning early |
||
| 384 | // if any of the given DTMF digits are received on the channel |
||
| 385 | func (agi *AGI) SayPhonetic(str, escDigits string) error { |
||
| 386 | return agi.say("PHONETIC", str, escDigits) |
||
| 387 | } |
||
| 388 | |||
| 389 | // SayTime say a given time, returning early if any of the given DTMF digits |
||
| 390 | // are received on the channel |
||
| 391 | func (agi *AGI) SayTime(time, escDigits string) error { |
||
| 392 | return agi.say("TIME", time, escDigits) |
||
| 393 | } |
||
| 394 | |||
| 395 | // SendImage Sends the given image on a channel. Most channels do not support |
||
| 396 | // the transmission of images. |
||
| 397 | func (agi *AGI) SendImage(image string) error { |
||
| 398 | resp, err := agi.execute("SEND IMAGE", image) |
||
| 399 | if err != nil { |
||
| 400 | return err |
||
| 401 | } |
||
| 402 | if resp.result < 0 { |
||
| 403 | return errorNew("Failure or hangup.") |
||
| 404 | } |
||
| 405 | return nil |
||
| 406 | } |
||
| 407 | |||
| 408 | // SendText Sends the given text on a channel. Most channels do not support |
||
| 409 | // the transmission of text. |
||
| 410 | func (agi *AGI) SendText(text string) error { |
||
| 411 | text = fmt.Sprintf("\"%s\"", text) |
||
| 412 | resp, err := agi.execute("SEND TEXT", text) |
||
| 413 | if err != nil { |
||
| 414 | return err |
||
| 415 | } |
||
| 416 | if resp.result < 0 { |
||
| 417 | return errorNew("Failure or hangup.") |
||
| 418 | } |
||
| 419 | return nil |
||
| 420 | } |
||
| 421 | |||
| 422 | // SetAutoHangup Cause the channel to automatically hangup at time seconds in the future. |
||
| 423 | // Setting to 0 will cause the autohangup feature to be disabled on this channel. |
||
| 424 | func (agi *AGI) SetAutoHangup(seconds int) error { |
||
| 425 | resp, err := agi.execute("SET AUTOHANGUP", seconds) |
||
| 426 | if err != nil { |
||
| 427 | return err |
||
| 428 | } |
||
| 429 | if resp.result != 0 { |
||
| 430 | return errorNew("Failure or hangup.") |
||
| 431 | } |
||
| 432 | return nil |
||
| 433 | } |
||
| 434 | |||
| 435 | // SetCallerid Changes the callerid of the current channel. |
||
| 436 | func (agi *AGI) SetCallerid(clid string) error { |
||
| 437 | resp, err := agi.execute("SET CALLERID", clid) |
||
| 438 | if err != nil { |
||
| 439 | return err |
||
| 440 | } |
||
| 441 | if resp.result != 1 { |
||
| 442 | return errorNew("Failure or hangup.") |
||
| 443 | } |
||
| 444 | return nil |
||
| 445 | } |
||
| 446 | |||
| 447 | // SetContext Sets the context for continuation upon exiting the application. |
||
| 448 | func (agi *AGI) SetContext(ctx string) error { |
||
| 449 | resp, err := agi.execute("SET CONTEXT", ctx) |
||
| 450 | if err != nil { |
||
| 451 | return err |
||
| 452 | } |
||
| 453 | if resp.result != 0 { |
||
| 454 | return errorNew("Failure or hangup.") |
||
| 455 | } |
||
| 456 | return nil |
||
| 457 | } |
||
| 458 | |||
| 459 | // SetExtension Changes the extension for continuation upon exiting the application. |
||
| 460 | func (agi *AGI) SetExtension(ext string) error { |
||
| 461 | resp, err := agi.execute("SET EXTENSION", ext) |
||
| 462 | if err != nil { |
||
| 463 | return err |
||
| 464 | } |
||
| 465 | if resp.result != 0 { |
||
| 466 | return errorNew("Failure or hangup.") |
||
| 467 | } |
||
| 468 | return nil |
||
| 469 | } |
||
| 470 | |||
| 471 | // SetMusic Enables/Disables the music on hold generator. If class is not specified, |
||
| 472 | // then the default music on hold class will be used. |
||
| 473 | // Parameters: opt is "on" or "off", and music class as string |
||
| 474 | func (agi *AGI) SetMusic(opt string, class ...string) error { |
||
| 475 | if opt != "on" && opt != "off" { |
||
| 476 | return errorNew("Invalid opt: '" + opt + "'. Must be 'on' or 'off'.") |
||
| 477 | } |
||
| 478 | |||
| 479 | if class != nil { |
||
| 480 | opt = fmt.Sprintf("%s %s", opt, class[0]) |
||
| 481 | } |
||
| 482 | |||
| 483 | resp, err := agi.execute("SET MUSIC", opt) |
||
| 484 | if err != nil { |
||
| 485 | return err |
||
| 486 | } |
||
| 487 | if resp.result != 0 { |
||
| 488 | return errorNew("Failure or hangup.") |
||
| 489 | } |
||
| 490 | return nil |
||
| 491 | } |
||
| 492 | |||
| 493 | // SetPriority Changes the priority for continuation upon exiting the application. |
||
| 494 | // The priority must be a valid priority or label. |
||
| 495 | func (agi *AGI) SetPriority(priority string) error { |
||
| 496 | resp, err := agi.execute("SET PRIORITY", priority) |
||
| 497 | if err != nil { |
||
| 498 | return err |
||
| 499 | } |
||
| 500 | if resp.result != 0 { |
||
| 501 | return errorNew("Failure or hangup.") |
||
| 502 | } |
||
| 503 | return nil |
||
| 504 | } |
||
| 505 | |||
| 506 | // SetVariable Sets a variable to the current channel. |
||
| 507 | func (agi *AGI) SetVariable(name, value string) error { |
||
| 508 | value = fmt.Sprintf("\"%s\"", value) |
||
| 509 | resp, err := agi.execute("SET VARIABLE", name, value) |
||
| 510 | if err != nil { |
||
| 511 | return err |
||
| 512 | } |
||
| 513 | if resp.result != 1 { |
||
| 514 | return errorNew("Failure or hangup.") |
||
| 515 | } |
||
| 516 | return nil |
||
| 517 | } |
||
| 518 | |||
| 519 | // StreamFile Send the given file, allowing playback to be interrupted by the given |
||
| 520 | // digits, if any. |
||
| 521 | func (agi *AGI) StreamFile(file, escDigits string, offset int) (int, error) { |
||
| 522 | resp, err := agi.execute("STREAM FILE", file, escDigits, offset) |
||
| 523 | if err != nil { |
||
| 524 | return -1, err |
||
| 525 | } |
||
| 526 | if resp.result == -1 { |
||
| 527 | return -1, errorNew("Failure or hangup.") |
||
| 528 | } |
||
| 529 | return int(resp.result), nil |
||
| 530 | } |
||
| 531 | |||
| 532 | // TDDMode Enable/Disable TDD transmission/reception on a channel. |
||
| 533 | // Modes: on, off, mate, tdd |
||
| 534 | func (agi *AGI) TDDMode(mode string) error { |
||
| 535 | resp, err := agi.execute("TDD MODE", mode) |
||
| 536 | if err != nil { |
||
| 537 | return err |
||
| 538 | } |
||
| 539 | if resp.result != 1 { |
||
| 540 | return errorNew("Failure or hangup.") |
||
| 541 | } |
||
| 542 | return nil |
||
| 543 | } |
||
| 544 | |||
| 545 | // Verbose Sends message to the console via verbose message system. |
||
| 546 | // level is the verbose level (1-4) |
||
| 547 | func (agi *AGI) Verbose(msg string, level ...int) error { |
||
| 548 | var err error |
||
| 549 | msg = fmt.Sprintf("\"%s\"", msg) |
||
| 550 | if level == nil { |
||
| 551 | _, err = agi.execute("VERBOSE", msg) |
||
| 552 | return err |
||
| 553 | } |
||
| 554 | |||
| 555 | lvl := level[0] |
||
| 556 | if lvl < 1 && lvl > 4 { |
||
| 557 | lvl = 1 |
||
| 558 | } |
||
| 559 | _, err = agi.execute("VERBOSE", msg, lvl) |
||
| 560 | return err |
||
| 561 | } |
||
| 562 | |||
| 563 | // WaitForDigit Waits up to timeout *milliseconds* for channel to receive a DTMF digit. |
||
| 564 | // Use -1 for the timeout value if you desire the call to block indefinitely. |
||
| 565 | // Return digit pressed as string or error |
||
| 566 | func (agi *AGI) WaitForDigit(timeout int) (string, error) { |
||
| 567 | resp, err := agi.execute("WAIT FOR DIGIT", timeout) |
||
| 568 | if err != nil { |
||
| 569 | return "", err |
||
| 570 | } |
||
| 571 | if resp.result == -1 { |
||
| 572 | return "", errorNew("Failed run command") |
||
| 573 | } |
||
| 574 | if resp.result == 0 { |
||
| 575 | return "", nil |
||
| 576 | } |
||
| 577 | return string(resp.result), nil |
||
| 578 | } |
||
| 579 |