fc5dcf20a906478253fbd9d97e82abcfd80ae65c
[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 LOCAL_USER_DECL;
70
71 static int playback_exec(struct ast_channel *chan, void *data)
72 {
73         int res = 0;
74         struct localuser *u;
75         char *tmp;
76         int option_skip=0;
77         int option_noanswer = 0;
78         int priority_jump = 0;
79
80         AST_DECLARE_APP_ARGS(args,
81                 AST_APP_ARG(filenames);
82                 AST_APP_ARG(options);
83         );
84         
85         if (ast_strlen_zero(data)) {
86                 ast_log(LOG_WARNING, "Playback requires an argument (filename)\n");
87                 return -1;
88         }
89
90         if (!(tmp = ast_strdupa(data)))
91                 return -1;      
92
93         LOCAL_USER_ADD(u);
94         AST_STANDARD_APP_ARGS(args, tmp);
95
96         if (args.options) {
97                 if (strcasestr(args.options, "skip"))
98                         option_skip = 1;
99                 if (strcasestr(args.options, "noanswer"))
100                         option_noanswer = 1;
101                 if (strchr(args.options, 'j'))
102                         priority_jump = 1;
103         }
104         
105         if (chan->_state != AST_STATE_UP) {
106                 if (option_skip) {
107                         /* At the user's option, skip if the line is not up */
108                         LOCAL_USER_REMOVE(u);
109                         return 0;
110                 } else if (!option_noanswer)
111                         /* Otherwise answer unless we're supposed to send this while on-hook */
112                         res = ast_answer(chan);
113         }
114         if (!res) {
115                 int mres = 0;
116                 char *front;
117
118                 ast_stopstream(chan);
119                 while (!res && (front = strsep(&tmp, "&"))) {
120                         res = ast_streamfile(chan, front, chan->language);
121                         if (!res) { 
122                                 res = ast_waitstream(chan, ""); 
123                                 ast_stopstream(chan);
124                         } else {
125                                 ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data);
126                                 if (priority_jump || ast_opt_priority_jumping)
127                                         ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
128                                 res = 0;
129                                 mres = 1;
130                         }
131                 }
132                 pbx_builtin_setvar_helper(chan, "PLAYBACKSTATUS", mres ? "FAILED" : "SUCCESS");
133         }
134         LOCAL_USER_REMOVE(u);
135         return res;
136 }
137
138 static int unload_module(void *mod)
139 {
140         int res;
141
142         res = ast_unregister_application(app);
143
144         STANDARD_HANGUP_LOCALUSERS;
145
146         return res;     
147 }
148
149 static int load_module(void *mod)
150 {
151         return ast_register_application(app, playback_exec, synopsis, descrip);
152 }
153
154 static const char *description(void)
155 {
156         return tdesc;
157 }
158
159 static const char *key(void)
160 {
161         return ASTERISK_GPL_KEY;
162 }
163
164 STD_MOD1;