diff options
author | Jonathan Rose <jrose@digium.com> | 2014-04-17 21:57:36 +0000 |
---|---|---|
committer | Jonathan Rose <jrose@digium.com> | 2014-04-17 21:57:36 +0000 |
commit | a8742e327f8de3866526a653977c0eae58d85d40 (patch) | |
tree | 02464cf2984c6beb6efe2864e252b33aefab899c /main/app.c | |
parent | c3497aa2bbfcf2e78d479a9d586b0320ba2b7cb0 (diff) |
ARI: Add tones playback resource
Adds a tones URI type to the playback resource. The tone can be specified by
name (from indications.conf) or by a tone pattern. In addition, tonezone can
be specified in the URI (by appending ;tonezone=<zone>). Tones must be
stopped manually in order for a stasis control to move on from playback of
the tone. Tones may be paused, resumed, restarted, and stopped. They may
not be rewound or fast forwarded (tones can't be controlled in a way that
lets you skip around from note to note and pausing and resuming will also
restart the tone from the beginning). Tests are currently in development
for this feature (https://reviewboard.asterisk.org/r/3428/).
(closes issue ASTERISK-23433)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3427/
........
Merged revisions 412535 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@412536 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/app.c')
-rw-r--r-- | main/app.c | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/main/app.c b/main/app.c index b6c988258..f7bb0048c 100644 --- a/main/app.c +++ b/main/app.c @@ -1070,6 +1070,143 @@ int ast_control_streamfile_lang(struct ast_channel *chan, const char *file, return control_streamfile(chan, file, fwd, rev, stop, suspend, restart, skipms, offsetms, lang, NULL); } +enum control_tone_frame_response_result { + CONTROL_TONE_RESPONSE_FAILED = -1, + CONTROL_TONE_RESPONSE_NORMAL = 0, + CONTROL_TONE_RESPONSE_FINISHED = 1, +}; + +static enum control_tone_frame_response_result control_tone_frame_response(struct ast_channel *chan, struct ast_frame *fr, struct ast_tone_zone_sound *ts, const char *tone, int *paused) +{ + switch (fr->subclass.integer) { + case AST_CONTROL_STREAM_STOP: + ast_playtones_stop(chan); + return CONTROL_TONE_RESPONSE_FINISHED; + case AST_CONTROL_STREAM_SUSPEND: + if (*paused) { + *paused = 0; + if (ast_playtones_start(chan, 0, ts ? ts->data : tone, 0)) { + return CONTROL_TONE_RESPONSE_FAILED; + } + } else { + *paused = 1; + ast_playtones_stop(chan); + } + return CONTROL_TONE_RESPONSE_NORMAL; + case AST_CONTROL_STREAM_RESTART: + ast_playtones_stop(chan); + if (ast_playtones_start(chan, 0, ts ? ts->data : tone, 0)) { + return CONTROL_TONE_RESPONSE_FAILED; + } + return CONTROL_TONE_RESPONSE_NORMAL; + case AST_CONTROL_STREAM_REVERSE: + ast_log(LOG_NOTICE, "Media control operation 'reverse' not supported for media type 'tone'\n"); + return CONTROL_TONE_RESPONSE_NORMAL; + case AST_CONTROL_STREAM_FORWARD: + ast_log(LOG_NOTICE, "Media control operation 'forward' not supported for media type 'tone'\n"); + return CONTROL_TONE_RESPONSE_NORMAL; + case AST_CONTROL_HANGUP: + case AST_CONTROL_BUSY: + case AST_CONTROL_CONGESTION: + return CONTROL_TONE_RESPONSE_FINISHED; + } + + return CONTROL_TONE_RESPONSE_NORMAL; +} + +static int parse_tone_uri(char *tone_parser, + const char **tone_indication, + const char **tone_zone) +{ + *tone_indication = strsep(&tone_parser, ";"); + + if (ast_strlen_zero(tone_parser)) { + /* Only the indication is included */ + return 0; + } + + if (!(strncmp(tone_parser, "tonezone=", 9))) { + *tone_zone = tone_parser + 9; + } else { + ast_log(LOG_ERROR, "Unexpected Tone URI component: %s\n", tone_parser); + return -1; + } + + return 0; +} + +int ast_control_tone(struct ast_channel *chan, const char *tone) +{ + struct ast_tone_zone *zone = NULL; + struct ast_tone_zone_sound *ts; + int paused = 0; + int res; + + const char *tone_indication = NULL; + const char *tone_zone = NULL; + char *tone_uri_parser; + + if (ast_strlen_zero(tone)) { + return -1; + } + + tone_uri_parser = ast_strdupa(tone); + + if (parse_tone_uri(tone_uri_parser, &tone_indication, &tone_zone)) { + return -1; + } + + if (tone_zone) { + zone = ast_get_indication_zone(tone_zone); + } + + ts = ast_get_indication_tone(zone ? zone : ast_channel_zone(chan), tone_indication); + + if (ast_playtones_start(chan, 0, ts ? ts->data : tone_indication, 0)) { + return -1; + } + + for (;;) { + struct ast_frame *fr; + int res; + + if (ast_waitfor(chan, -1) < 0) { + res = -1; + break; + } + + fr = ast_read_noaudio(chan); + + if (!fr) { + res = -1; + break; + } + + if (fr->frametype != AST_FRAME_CONTROL) { + continue; + } + + res = control_tone_frame_response(chan, fr, ts, tone_indication, &paused); + if (res == CONTROL_TONE_RESPONSE_FINISHED) { + res = 0; + break; + } else if (res == CONTROL_TONE_RESPONSE_FAILED) { + res = -1; + break; + } + } + + if (ts) { + ast_tone_zone_sound_unref(ts); + } + + if (zone) { + ast_tone_zone_unref(zone); + } + + return res; +} + int ast_play_and_wait(struct ast_channel *chan, const char *fn) { int d = 0; |