Wed Jan 8 2020 09:49:39

Asterisk developer's documentation


app_controlplayback.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
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.
13  *
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.
17  */
18 
19 /*! \file
20  *
21  * \brief Trivial application to control playback of a sound file
22  *
23  * \author Mark Spencer <markster@digium.com>
24  *
25  * \ingroup applications
26  */
27 
28 /*** MODULEINFO
29  <support_level>core</support_level>
30  ***/
31 
32 #include "asterisk.h"
33 
34 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328209 $")
35 
36 #include "asterisk/pbx.h"
37 #include "asterisk/app.h"
38 #include "asterisk/module.h"
39 
40 /*** DOCUMENTATION
41  <application name="ControlPlayback" language="en_US">
42  <synopsis>
43  Play a file with fast forward and rewind.
44  </synopsis>
45  <syntax>
46  <parameter name="filename" required="true" />
47  <parameter name="skipms">
48  <para>This is number of milliseconds to skip when rewinding or
49  fast-forwarding.</para>
50  </parameter>
51  <parameter name="ff">
52  <para>Fast-forward when this DTMF digit is received. (defaults to <literal>#</literal>)</para>
53  </parameter>
54  <parameter name="rew">
55  <para>Rewind when this DTMF digit is received. (defaults to <literal>*</literal>)</para>
56  </parameter>
57  <parameter name="stop">
58  <para>Stop playback when this DTMF digit is received.</para>
59  </parameter>
60  <parameter name="pause">
61  <para>Pause playback when this DTMF digit is received.</para>
62  </parameter>
63  <parameter name="restart">
64  <para>Restart playback when this DTMF digit is received.</para>
65  </parameter>
66  <parameter name="options">
67  <optionlist>
68  <option name="o">
69  <argument name="time" required="true">
70  <para>Start at <replaceable>time</replaceable> ms from the
71  beginning of the file.</para>
72  </argument>
73  </option>
74  </optionlist>
75  </parameter>
76  </syntax>
77  <description>
78  <para>This application will play back the given <replaceable>filename</replaceable>.</para>
79  <para>It sets the following channel variables upon completion:</para>
80  <variablelist>
81  <variable name="CPLAYBACKSTATUS">
82  <para>Contains the status of the attempt as a text string</para>
83  <value name="SUCCESS" />
84  <value name="USERSTOPPED" />
85  <value name="ERROR" />
86  </variable>
87  <variable name="CPLAYBACKOFFSET">
88  <para>Contains the offset in ms into the file where playback
89  was at when it stopped. <literal>-1</literal> is end of file.</para>
90  </variable>
91  <variable name="CPLAYBACKSTOPKEY">
92  <para>If the playback is stopped by the user this variable contains
93  the key that was pressed.</para>
94  </variable>
95  </variablelist>
96  </description>
97  </application>
98  ***/
99 static const char app[] = "ControlPlayback";
100 
101 enum {
102  OPT_OFFSET = (1 << 1),
103 };
104 
105 enum {
107  /* must stay as the last entry ... */
109 };
110 
114 );
115 
116 static int is_on_phonepad(char key)
117 {
118  return key == 35 || key == 42 || (key >= 48 && key <= 57);
119 }
120 
121 static int is_argument(const char *haystack, int needle)
122 {
123  if (ast_strlen_zero(haystack))
124  return 0;
125 
126  if (strchr(haystack, needle))
127  return -1;
128 
129  return 0;
130 }
131 
132 static int controlplayback_exec(struct ast_channel *chan, const char *data)
133 {
134  int res = 0;
135  int skipms = 0;
136  long offsetms = 0;
137  char offsetbuf[20];
138  char stopkeybuf[2];
139  char *tmp;
140  struct ast_flags opts = { 0, };
141  char *opt_args[OPT_ARG_ARRAY_LEN];
143  AST_APP_ARG(filename);
144  AST_APP_ARG(skip);
145  AST_APP_ARG(fwd);
146  AST_APP_ARG(rev);
147  AST_APP_ARG(stop);
148  AST_APP_ARG(pause);
149  AST_APP_ARG(restart);
150  AST_APP_ARG(options);
151  );
152 
153  if (ast_strlen_zero(data)) {
154  ast_log(LOG_WARNING, "ControlPlayback requires an argument (filename)\n");
155  return -1;
156  }
157 
158  tmp = ast_strdupa(data);
160 
161  if (args.argc < 1) {
162  ast_log(LOG_WARNING, "ControlPlayback requires an argument (filename)\n");
163  return -1;
164  }
165 
166  skipms = args.skip ? (atoi(args.skip) ? atoi(args.skip) : 3000) : 3000;
167 
168  if (!args.fwd || !is_on_phonepad(*args.fwd)) {
169  char *digit = "#";
170  if (!is_argument(args.rev, *digit) && !is_argument(args.stop, *digit) && !is_argument(args.pause, *digit) && !is_argument(args.restart, *digit))
171  args.fwd = digit;
172  else
173  args.fwd = NULL;
174  }
175  if (!args.rev || !is_on_phonepad(*args.rev)) {
176  char *digit = "*";
177  if (!is_argument(args.fwd, *digit) && !is_argument(args.stop, *digit) && !is_argument(args.pause, *digit) && !is_argument(args.restart, *digit))
178  args.rev = digit;
179  else
180  args.rev = NULL;
181  }
182  ast_debug(1, "Forward key = %s, Rewind key = %s\n", args.fwd, args.rev);
183  if (args.stop && !is_on_phonepad(*args.stop))
184  args.stop = NULL;
185  if (args.pause && !is_on_phonepad(*args.pause))
186  args.pause = NULL;
187  if (args.restart && !is_on_phonepad(*args.restart))
188  args.restart = NULL;
189 
190  if (args.options) {
191  ast_app_parse_options(cpb_opts, &opts, opt_args, args.options);
192  if (ast_test_flag(&opts, OPT_OFFSET))
193  offsetms = atol(opt_args[OPT_ARG_OFFSET]);
194  }
195 
196  res = ast_control_streamfile(chan, args.filename, args.fwd, args.rev, args.stop, args.pause, args.restart, skipms, &offsetms);
197 
198  /* If we stopped on one of our stop keys, return 0 */
199  if (res > 0 && args.stop && strchr(args.stop, res)) {
200  pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "USERSTOPPED");
201  snprintf(stopkeybuf, sizeof(stopkeybuf), "%c", res);
202  pbx_builtin_setvar_helper(chan, "CPLAYBACKSTOPKEY", stopkeybuf);
203  res = 0;
204  } else {
205  if (res < 0) {
206  res = 0;
207  pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "ERROR");
208  } else
209  pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "SUCCESS");
210  }
211 
212  snprintf(offsetbuf, sizeof(offsetbuf), "%ld", offsetms);
213  pbx_builtin_setvar_helper(chan, "CPLAYBACKOFFSET", offsetbuf);
214 
215  return res;
216 }
217 
218 static int unload_module(void)
219 {
220  int res;
221  res = ast_unregister_application(app);
222  return res;
223 }
224 
225 static int load_module(void)
226 {
228 }
229 
230 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Control Playback Application");
Main Channel structure associated with a channel.
Definition: channel.h:742
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:396
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
Definition: app.h:732
Asterisk main include file. File version handling, generic pbx functions.
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
Definition: app.h:712
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)
Stream a file with fast forward, pause, reverse, restart.
Definition: app.c:683
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define LOG_WARNING
Definition: logger.h:144
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: app.c:2101
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
unsigned int stop
Definition: app_meetme.c:969
static int load_module(void)
#define END_OPTIONS
Definition: app.h:663
static int is_argument(const char *haystack, int needle)
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static int is_on_phonepad(char key)
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static int skipms
static struct @350 args
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
Structure used to handle boolean flags.
Definition: utils.h:200
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
Definition: pbx.c:10546
static int unload_module(void)
static struct ast_app_option cpb_opts[128]
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
static const char app[]
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
struct ast_channel * chan
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
Asterisk module definitions.
static int controlplayback_exec(struct ast_channel *chan, const char *data)
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
#define BEGIN_OPTIONS
Definition: app.h:662
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180