2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief Trivial application to control playback of a sound file
23 * \author Mark Spencer <markster@digium.com>
25 * \ingroup applications
30 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
32 #include "asterisk/pbx.h"
33 #include "asterisk/app.h"
34 #include "asterisk/module.h"
36 static const char *app
= "ControlPlayback";
38 static const char *synopsis
= "Play a file with fast forward and rewind";
40 static const char *descrip
=
41 " ControlPlayback(file[,skipms[,ff[,rew[,stop[,pause[,restart,options]]]]]]]):\n"
42 "This application will play back the given filename. By default, the '*' key\n"
43 "can be used to rewind, and the '#' key can be used to fast-forward.\n"
45 " skipms - This is number of milliseconds to skip when rewinding or\n"
47 " ff - Fast-forward when this DTMF digit is received.\n"
48 " rew - Rewind when this DTMF digit is received.\n"
49 " stop - Stop playback when this DTMF digit is received.\n"
50 " pause - Pause playback when this DTMF digit is received.\n"
51 " restart - Restart playback when this DTMF digit is received.\n"
53 " o(#) - Start at # ms from the beginning of the file.\n"
54 "This application sets the following channel variables upon completion:\n"
55 " CPLAYBACKSTATUS - This variable contains the status of the attempt as a text\n"
56 " string, one of: SUCCESS | USERSTOPPED | ERROR\n"
57 " CPLAYBACKOFFSET - This contains the offset in ms into the file where\n"
58 " playback was at when it stopped. -1 is end of file.\n"
59 " CPLAYBACKSTOPKEY - If the playback is stopped by the user this variable contains\n"
60 " the key that was pressed.\n";
63 OPT_OFFSET
= (1 << 1),
68 /* must stay as the last entry ... */
72 AST_APP_OPTIONS(cpb_opts
, BEGIN_OPTIONS
73 AST_APP_OPTION_ARG('o', OPT_OFFSET
, OPT_ARG_OFFSET
),
77 static int is_on_phonepad(char key
)
79 return key
== 35 || key
== 42 || (key
>= 48 && key
<= 57);
82 static int is_argument(const char *haystack
, int needle
)
84 if (ast_strlen_zero(haystack
))
87 if (strchr(haystack
, needle
))
93 static int controlplayback_exec(struct ast_channel
*chan
, void *data
)
101 struct ast_flags opts
= { 0, };
102 char *opt_args
[OPT_ARG_ARRAY_LEN
];
103 AST_DECLARE_APP_ARGS(args
,
104 AST_APP_ARG(filename
);
110 AST_APP_ARG(restart
);
111 AST_APP_ARG(options
);
114 if (ast_strlen_zero(data
)) {
115 ast_log(LOG_WARNING
, "ControlPlayback requires an argument (filename)\n");
119 tmp
= ast_strdupa(data
);
120 AST_STANDARD_APP_ARGS(args
, tmp
);
123 ast_log(LOG_WARNING
, "ControlPlayback requires an argument (filename)\n");
127 skipms
= args
.skip
? (atoi(args
.skip
) ? atoi(args
.skip
) : 3000) : 3000;
129 if (!args
.fwd
|| !is_on_phonepad(*args
.fwd
)) {
131 if (!is_argument(args
.rev
, *digit
) && !is_argument(args
.stop
, *digit
) && !is_argument(args
.pause
, *digit
) && !is_argument(args
.restart
, *digit
))
136 if (!args
.rev
|| !is_on_phonepad(*args
.rev
)) {
138 if (!is_argument(args
.fwd
, *digit
) && !is_argument(args
.stop
, *digit
) && !is_argument(args
.pause
, *digit
) && !is_argument(args
.restart
, *digit
))
143 ast_log(LOG_WARNING
, "args.fwd = %s, args.rew = %s\n", args
.fwd
, args
.rev
);
144 if (args
.stop
&& !is_on_phonepad(*args
.stop
))
146 if (args
.pause
&& !is_on_phonepad(*args
.pause
))
148 if (args
.restart
&& !is_on_phonepad(*args
.restart
))
152 ast_app_parse_options(cpb_opts
, &opts
, opt_args
, args
.options
);
153 if (ast_test_flag(&opts
, OPT_OFFSET
))
154 offsetms
= atol(opt_args
[OPT_ARG_OFFSET
]);
157 res
= ast_control_streamfile(chan
, args
.filename
, args
.fwd
, args
.rev
, args
.stop
, args
.pause
, args
.restart
, skipms
, &offsetms
);
159 /* If we stopped on one of our stop keys, return 0 */
160 if (res
> 0 && args
.stop
&& strchr(args
.stop
, res
)) {
161 pbx_builtin_setvar_helper(chan
, "CPLAYBACKSTATUS", "USERSTOPPED");
162 snprintf(stopkeybuf
, sizeof(stopkeybuf
), "%c", res
);
163 pbx_builtin_setvar_helper(chan
, "CPLAYBACKSTOPKEY", stopkeybuf
);
168 pbx_builtin_setvar_helper(chan
, "CPLAYBACKSTATUS", "ERROR");
170 pbx_builtin_setvar_helper(chan
, "CPLAYBACKSTATUS", "SUCCESS");
173 snprintf(offsetbuf
, sizeof(offsetbuf
), "%ld", offsetms
);
174 pbx_builtin_setvar_helper(chan
, "CPLAYBACKOFFSET", offsetbuf
);
179 static int unload_module(void)
182 res
= ast_unregister_application(app
);
186 static int load_module(void)
188 return ast_register_application(app
, controlplayback_exec
, synopsis
, descrip
);
191 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY
, "Control Playback Application");