remove lots of useless checks of the result of ast_strdupa
[asterisk/asterisk.git] / apps / app_playback.c
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 playback a sound file
22  *
23  * \author Mark Spencer <markster@digium.com>
24  * 
25  * \ingroup applications
26  */
27  
28 #include <string.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31
32 #include "asterisk.h"
33
34 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
35
36 #include "asterisk/lock.h"
37 #include "asterisk/file.h"
38 #include "asterisk/logger.h"
39 #include "asterisk/channel.h"
40 #include "asterisk/pbx.h"
41 #include "asterisk/module.h"
42 #include "asterisk/translate.h"
43 #include "asterisk/utils.h"
44 #include "asterisk/options.h"
45 #include "asterisk/app.h"
46
47 static char *tdesc = "Sound File Playback Application";
48
49 static char *app = "Playback";
50
51 static char *synopsis = "Play a file";
52
53 static char *descrip = 
54 "  Playback(filename[&filename2...][|option]):  Plays back given filenames (do not put\n"
55 "extension). Options may also be included following a pipe symbol. The 'skip'\n"
56 "option causes the playback of the message to be skipped if the channel\n"
57 "is not in the 'up' state (i.e. it hasn't been  answered  yet). If 'skip' is \n"
58 "specified, the application will return immediately should the channel not be\n"
59 "off hook.  Otherwise, unless 'noanswer' is specified, the channel will\n"
60 "be answered before the sound is played. Not all channels support playing\n"
61 "messages while still on hook. If 'j' is specified, the application\n"
62 "will jump to priority n+101 if present when a file specified to be played\n"
63 "does not exist.\n"
64 "This application sets the following channel variable upon completion:\n"
65 " PLAYBACKSTATUS    The status of the playback attempt as a text string, one of\n"
66 "               SUCCESS | FAILED\n"
67 ;
68
69 STANDARD_LOCAL_USER;
70
71 LOCAL_USER_DECL;
72
73 static int playback_exec(struct ast_channel *chan, void *data)
74 {
75         int res = 0;
76         struct localuser *u;
77         char *tmp;
78         int option_skip=0;
79         int option_noanswer = 0;
80         int priority_jump = 0;
81
82         AST_DECLARE_APP_ARGS(args,
83                 AST_APP_ARG(filenames);
84                 AST_APP_ARG(options);
85         );
86         
87         if (ast_strlen_zero(data)) {
88                 ast_log(LOG_WARNING, "Playback requires an argument (filename)\n");
89                 return -1;
90         }
91
92         tmp = ast_strdupa(data);
93
94         LOCAL_USER_ADD(u);
95         AST_STANDARD_APP_ARGS(args, tmp);
96
97         if (args.options) {
98                 if (strcasestr(args.options, "skip"))
99                         option_skip = 1;
100                 if (strcasestr(args.options, "noanswer"))
101                         option_noanswer = 1;
102                 if (strchr(args.options, 'j'))
103                         priority_jump = 1;
104         }
105         
106         if (chan->_state != AST_STATE_UP) {
107                 if (option_skip) {
108                         /* At the user's option, skip if the line is not up */
109                         LOCAL_USER_REMOVE(u);
110                         return 0;
111                 } else if (!option_noanswer)
112                         /* Otherwise answer unless we're supposed to send this while on-hook */
113                         res = ast_answer(chan);
114         }
115         if (!res) {
116                 int mres = 0;
117                 char *front;
118
119                 ast_stopstream(chan);
120                 while (!res && (front = strsep(&tmp, "&"))) {
121                         res = ast_streamfile(chan, front, chan->language);
122                         if (!res) { 
123                                 res = ast_waitstream(chan, ""); 
124                                 ast_stopstream(chan);
125                         } else {
126                                 ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data);
127                                 if (priority_jump || ast_opt_priority_jumping)
128                                         ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
129                                 res = 0;
130                                 mres = 1;
131                         }
132                 }
133                 pbx_builtin_setvar_helper(chan, "PLAYBACKSTATUS", mres ? "FAILED" : "SUCCESS");
134         }
135         LOCAL_USER_REMOVE(u);
136         return res;
137 }
138
139 int unload_module(void)
140 {
141         int res;
142
143         res = ast_unregister_application(app);
144
145         STANDARD_HANGUP_LOCALUSERS;
146
147         return res;     
148 }
149
150 int load_module(void)
151 {
152         return ast_register_application(app, playback_exec, synopsis, descrip);
153 }
154
155 char *description(void)
156 {
157         return tdesc;
158 }
159
160 int usecount(void)
161 {
162         int res;
163         STANDARD_USECOUNT(res);
164         return res;
165 }
166
167 char *key()
168 {
169         return ASTERISK_GPL_KEY;
170 }