summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/app_controlplayback.c49
-rw-r--r--apps/app_voicemail.c2
-rw-r--r--include/asterisk/app.h10
-rw-r--r--main/app.c32
-rw-r--r--res/res_agi.c2
5 files changed, 76 insertions, 19 deletions
diff --git a/apps/app_controlplayback.c b/apps/app_controlplayback.c
index 8a5a845cd..73a800479 100644
--- a/apps/app_controlplayback.c
+++ b/apps/app_controlplayback.c
@@ -61,11 +61,29 @@ static const char *descrip =
" pause - Pause playback when this DTMF digit is received.\n"
" restart - Restart playback when this DTMF digit is received.\n"
"Options:\n"
-" j - Jump to priority n+101 if the requested file is not found.\n"
-"This application sets the following channel variable upon completion:\n"
+" j - Jump to priority n+101 if the requested file is not found.\n"
+" o(#) - Start at # ms from the beginning of the file.\n"
+"This application sets the following channel variables upon completion:\n"
" CPLAYBACKSTATUS - This variable contains the status of the attempt as a text\n"
-" string, one of: SUCCESS | USERSTOPPED | ERROR\n";
-
+" string, one of: SUCCESS | USERSTOPPED | ERROR\n"
+" CPLAYBACKOFFSET - This contains the offset in ms into the file where\n"
+" playback was at when it stopped. -1 is end of file.\n";
+
+enum {
+ OPT_JUMP = (1 << 0),
+ OPT_OFFSET = (1 << 1),
+};
+
+enum {
+ OPT_ARG_OFFSET = 0,
+ /* must stay as the last entry ... */
+ OPT_ARG_ARRAY_LEN,
+};
+
+AST_APP_OPTIONS(cpb_opts, BEGIN_OPTIONS
+ AST_APP_OPTION('j', OPT_JUMP),
+ AST_APP_OPTION_ARG('o', OPT_OFFSET, OPT_ARG_OFFSET),
+END_OPTIONS );
static int is_on_phonepad(char key)
{
@@ -74,12 +92,14 @@ static int is_on_phonepad(char key)
static int controlplayback_exec(struct ast_channel *chan, void *data)
{
- int res = 0, priority_jump = 0;
+ int res = 0;
int skipms = 0;
+ long offsetms = 0;
+ char offsetbuf[20];
struct ast_module_user *u;
char *tmp;
int argc;
- char *argv[8];
+ char *argv[8] = { NULL, };
enum arg_ids {
arg_file = 0,
arg_skip = 1,
@@ -90,7 +110,9 @@ static int controlplayback_exec(struct ast_channel *chan, void *data)
arg_restart = 6,
options = 7,
};
-
+ struct ast_flags opts = { 0, };
+ char *opt_args[OPT_ARG_ARRAY_LEN];
+
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "ControlPlayback requires an argument (filename)\n");
return -1;
@@ -99,7 +121,6 @@ static int controlplayback_exec(struct ast_channel *chan, void *data)
u = ast_module_user_add(chan);
tmp = ast_strdupa(data);
- memset(argv, 0, sizeof(argv));
argc = ast_app_separate_args(tmp, '|', argv, sizeof(argv) / sizeof(argv[0]));
@@ -125,11 +146,12 @@ static int controlplayback_exec(struct ast_channel *chan, void *data)
argv[arg_restart] = NULL;
if (argv[options]) {
- if (strchr(argv[options], 'j'))
- priority_jump = 1;
+ ast_app_parse_options(cpb_opts, &opts, opt_args, argv[options]);
+ if (ast_test_flag(&opts, OPT_OFFSET))
+ offsetms = atol(opt_args[OPT_ARG_OFFSET]);
}
- res = ast_control_streamfile(chan, argv[arg_file], argv[arg_fwd], argv[arg_rev], argv[arg_stop], argv[arg_pause], argv[arg_restart], skipms);
+ res = ast_control_streamfile(chan, argv[arg_file], argv[arg_fwd], argv[arg_rev], argv[arg_stop], argv[arg_pause], argv[arg_restart], skipms, &offsetms);
/* If we stopped on one of our stop keys, return 0 */
if (argv[arg_stop] && strchr(argv[arg_stop], res)) {
@@ -137,7 +159,7 @@ static int controlplayback_exec(struct ast_channel *chan, void *data)
pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "USERSTOPPED");
} else {
if (res < 0) {
- if (priority_jump || ast_opt_priority_jumping) {
+ if (ast_test_flag(&opts, OPT_JUMP) || ast_opt_priority_jumping) {
if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101)) {
ast_log(LOG_WARNING, "ControlPlayback tried to jump to priority n+101 as requested, but priority didn't exist\n");
}
@@ -148,6 +170,9 @@ static int controlplayback_exec(struct ast_channel *chan, void *data)
pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "SUCCESS");
}
+ snprintf(offsetbuf, sizeof(offsetbuf), "%ld", offsetms);
+ pbx_builtin_setvar_helper(chan, "CPLAYBACKOFFSET", offsetbuf);
+
ast_module_user_remove(u);
return res;
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index 14a99d8ba..01f07d722 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -4363,7 +4363,7 @@ static int wait_file2(struct ast_channel *chan, struct vm_state *vms, char *file
static int wait_file(struct ast_channel *chan, struct vm_state *vms, char *file)
{
- return ast_control_streamfile(chan, file, "#", "*", "1456789", "0", "2", skipms);
+ return ast_control_streamfile(chan, file, "#", "*", "1456789", "0", "2", skipms, NULL);
}
static int play_message_category(struct ast_channel *chan, const char *category)
diff --git a/include/asterisk/app.h b/include/asterisk/app.h
index c60219b85..77e77bfb0 100644
--- a/include/asterisk/app.h
+++ b/include/asterisk/app.h
@@ -163,8 +163,14 @@ int ast_dtmf_stream(struct ast_channel *chan, struct ast_channel *peer, const ch
/*! Stream a filename (or file descriptor) as a generator. */
int ast_linear_stream(struct ast_channel *chan, const char *filename, int fd, int allowoverride);
-/*! Stream a file with fast forward, pause, reverse, restart. */
-int ast_control_streamfile(struct ast_channel *chan, const char *file, const char *fwd, const char *rev, const char *stop, const char *pause, const char *restart, int skipms);
+/*!
+ * \brief Stream a file with fast forward, pause, reverse, restart.
+ * \param offsetms Before calling this function, set this to be the number
+ * of ms to start from the beginning of the file. When the function
+ * returns, it will be the number of ms from the beginning where the
+ * playback stopped. Pass NULL if you don't care.
+ */
+int ast_control_streamfile(struct ast_channel *chan, const char *file, const char *fwd, const char *rev, const char *stop, const char *pause, const char *restart, int skipms, long *offsetms);
/*! Play a stream and wait for a digit, returning the digit that was pressed */
int ast_play_and_wait(struct ast_channel *chan, const char *fn);
diff --git a/main/app.c b/main/app.c
index b3fd264f1..22a29218e 100644
--- a/main/app.c
+++ b/main/app.c
@@ -395,13 +395,17 @@ int ast_linear_stream(struct ast_channel *chan, const char *filename, int fd, in
int ast_control_streamfile(struct ast_channel *chan, const char *file,
const char *fwd, const char *rev,
const char *stop, const char *pause,
- const char *restart, int skipms)
+ const char *restart, int skipms, long *offsetms)
{
char *breaks = NULL;
char *end = NULL;
int blen = 2;
int res;
long pause_restart_point = 0;
+ long offset = 0;
+
+ if (offsetms)
+ offset = *offsetms * 8; /* XXX Assumes 8kHz */
if (stop)
blen += strlen(stop);
@@ -440,9 +444,18 @@ int ast_control_streamfile(struct ast_channel *chan, const char *file,
ast_seekstream(chan->stream, pause_restart_point, SEEK_SET);
pause_restart_point = 0;
}
- else if (end) {
- ast_seekstream(chan->stream, 0, SEEK_END);
+ else if (end || offset < 0) {
+ if (offset == -8)
+ offset = 0;
+ ast_verbose(VERBOSE_PREFIX_3 "ControlPlayback seek to offset %ld from end\n", offset);
+
+ ast_seekstream(chan->stream, offset, SEEK_END);
end = NULL;
+ offset = 0;
+ } else if (offset) {
+ ast_verbose(VERBOSE_PREFIX_3 "ControlPlayback seek to offset %ld\n", offset);
+ ast_seekstream(chan->stream, offset, SEEK_SET);
+ offset = 0;
};
res = ast_waitstream_fr(chan, breaks, fwd, rev, skipms);
}
@@ -482,6 +495,19 @@ int ast_control_streamfile(struct ast_channel *chan, const char *file,
break;
}
+ if (pause_restart_point) {
+ offset = pause_restart_point;
+ } else {
+ if (chan->stream) {
+ offset = ast_tellstream(chan->stream);
+ } else {
+ offset = -8; /* indicate end of file */
+ }
+ }
+
+ if (offsetms)
+ *offsetms = offset / 8; /* samples --> ms ... XXX Assumes 8 kHz */
+
ast_stopstream(chan);
return res;
diff --git a/res/res_agi.c b/res/res_agi.c
index 46a26a4c9..5d58de4b0 100644
--- a/res/res_agi.c
+++ b/res/res_agi.c
@@ -551,7 +551,7 @@ static int handle_controlstreamfile(struct ast_channel *chan, AGI *agi, int argc
else
pause = NULL;
- res = ast_control_streamfile(chan, argv[3], fwd, rev, stop, pause, NULL, skipms);
+ res = ast_control_streamfile(chan, argv[3], fwd, rev, stop, pause, NULL, skipms, NULL);
fdprintf(agi->fd, "200 result=%d\n", res);