#include "asterisk.h"
#include <sys/time.h>
#include <signal.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/frame.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/app.h"
Go to the source code of this file.
Defines | |
#define | LOCAL_MPG_123 "/usr/local/bin/mpg123" |
#define | MPG_123 "/usr/bin/mpg123" |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static int | load_module (void) |
static int | mp3_exec (struct ast_channel *chan, const char *data) |
static int | mp3play (const char *filename, int fd) |
static int | timed_read (int fd, void *data, int datalen, int timeout) |
static int | unload_module (void) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Silly MP3 Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } |
static char * | app = "MP3Player" |
static struct ast_module_info * | ast_module_info = &__mod_info |
Definition in file app_mp3.c.
#define LOCAL_MPG_123 "/usr/local/bin/mpg123" |
#define MPG_123 "/usr/bin/mpg123" |
static int load_module | ( | void | ) | [static] |
Definition at line 248 of file app_mp3.c.
References ast_register_application_xml, and mp3_exec().
00249 { 00250 return ast_register_application_xml(app, mp3_exec); 00251 }
static int mp3_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 134 of file app_mp3.c.
References ast_debug, AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, ast_log(), ast_read(), ast_samp2tv(), ast_set_write_format(), ast_stopstream(), ast_strlen_zero(), ast_tvadd(), ast_tvdiff_ms(), ast_tvnow(), ast_waitfor(), ast_write(), f, LOG_WARNING, mp3play(), ast_frame::offset, timed_read(), and ast_channel::writeformat.
Referenced by load_module().
00135 { 00136 int res=0; 00137 int fds[2]; 00138 int ms = -1; 00139 int pid = -1; 00140 int owriteformat; 00141 int timeout = 2000; 00142 struct timeval next; 00143 struct ast_frame *f; 00144 struct myframe { 00145 struct ast_frame f; 00146 char offset[AST_FRIENDLY_OFFSET]; 00147 short frdata[160]; 00148 } myf = { 00149 .f = { 0, }, 00150 }; 00151 00152 if (ast_strlen_zero(data)) { 00153 ast_log(LOG_WARNING, "MP3 Playback requires an argument (filename)\n"); 00154 return -1; 00155 } 00156 00157 if (pipe(fds)) { 00158 ast_log(LOG_WARNING, "Unable to create pipe\n"); 00159 return -1; 00160 } 00161 00162 ast_stopstream(chan); 00163 00164 owriteformat = chan->writeformat; 00165 res = ast_set_write_format(chan, AST_FORMAT_SLINEAR); 00166 if (res < 0) { 00167 ast_log(LOG_WARNING, "Unable to set write format to signed linear\n"); 00168 return -1; 00169 } 00170 00171 res = mp3play(data, fds[1]); 00172 if (!strncasecmp(data, "http://", 7)) { 00173 timeout = 10000; 00174 } 00175 /* Wait 1000 ms first */ 00176 next = ast_tvnow(); 00177 next.tv_sec += 1; 00178 if (res >= 0) { 00179 pid = res; 00180 /* Order is important -- there's almost always going to be mp3... we want to prioritize the 00181 user */ 00182 for (;;) { 00183 ms = ast_tvdiff_ms(next, ast_tvnow()); 00184 if (ms <= 0) { 00185 res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout); 00186 if (res > 0) { 00187 myf.f.frametype = AST_FRAME_VOICE; 00188 myf.f.subclass.codec = AST_FORMAT_SLINEAR; 00189 myf.f.datalen = res; 00190 myf.f.samples = res / 2; 00191 myf.f.mallocd = 0; 00192 myf.f.offset = AST_FRIENDLY_OFFSET; 00193 myf.f.src = __PRETTY_FUNCTION__; 00194 myf.f.delivery.tv_sec = 0; 00195 myf.f.delivery.tv_usec = 0; 00196 myf.f.data.ptr = myf.frdata; 00197 if (ast_write(chan, &myf.f) < 0) { 00198 res = -1; 00199 break; 00200 } 00201 } else { 00202 ast_debug(1, "No more mp3\n"); 00203 res = 0; 00204 break; 00205 } 00206 next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000)); 00207 } else { 00208 ms = ast_waitfor(chan, ms); 00209 if (ms < 0) { 00210 ast_debug(1, "Hangup detected\n"); 00211 res = -1; 00212 break; 00213 } 00214 if (ms) { 00215 f = ast_read(chan); 00216 if (!f) { 00217 ast_debug(1, "Null frame == hangup() detected\n"); 00218 res = -1; 00219 break; 00220 } 00221 if (f->frametype == AST_FRAME_DTMF) { 00222 ast_debug(1, "User pressed a key\n"); 00223 ast_frfree(f); 00224 res = 0; 00225 break; 00226 } 00227 ast_frfree(f); 00228 } 00229 } 00230 } 00231 } 00232 close(fds[0]); 00233 close(fds[1]); 00234 00235 if (pid > -1) 00236 kill(pid, SIGKILL); 00237 if (!res && owriteformat) 00238 ast_set_write_format(chan, owriteformat); 00239 00240 return res; 00241 }
static int mp3play | ( | const char * | filename, | |
int | fd | |||
) | [static] |
Definition at line 73 of file app_mp3.c.
References ast_close_fds_above_n(), ast_log(), ast_opt_high_priority, ast_safe_fork(), ast_set_priority(), LOCAL_MPG_123, LOG_WARNING, and MPG_123.
Referenced by mp3_exec().
00074 { 00075 int res; 00076 00077 res = ast_safe_fork(0); 00078 if (res < 0) 00079 ast_log(LOG_WARNING, "Fork failed\n"); 00080 if (res) { 00081 return res; 00082 } 00083 if (ast_opt_high_priority) 00084 ast_set_priority(0); 00085 00086 dup2(fd, STDOUT_FILENO); 00087 ast_close_fds_above_n(STDERR_FILENO); 00088 00089 /* Execute mpg123, but buffer if it's a net connection */ 00090 if (!strncasecmp(filename, "http://", 7)) { 00091 /* Most commonly installed in /usr/local/bin */ 00092 execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); 00093 /* But many places has it in /usr/bin */ 00094 execl(MPG_123, "mpg123", "-q", "-s", "-b", "1024","-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); 00095 /* As a last-ditch effort, try to use PATH */ 00096 execlp("mpg123", "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); 00097 } 00098 else if (strstr(filename, ".m3u")) { 00099 /* Most commonly installed in /usr/local/bin */ 00100 execl(LOCAL_MPG_123, "mpg123", "-q", "-z", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", "-@", filename, (char *)NULL); 00101 /* But many places has it in /usr/bin */ 00102 execl(MPG_123, "mpg123", "-q", "-z", "-s", "-b", "1024","-f", "8192", "--mono", "-r", "8000", "-@", filename, (char *)NULL); 00103 /* As a last-ditch effort, try to use PATH */ 00104 execlp("mpg123", "mpg123", "-q", "-z", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", "-@", filename, (char *)NULL); 00105 } 00106 else { 00107 /* Most commonly installed in /usr/local/bin */ 00108 execl(MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); 00109 /* But many places has it in /usr/bin */ 00110 execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); 00111 /* As a last-ditch effort, try to use PATH */ 00112 execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); 00113 } 00114 /* Can't use ast_log since FD's are closed */ 00115 fprintf(stderr, "Execute of mpg123 failed\n"); 00116 _exit(0); 00117 }
static int timed_read | ( | int | fd, | |
void * | data, | |||
int | datalen, | |||
int | timeout | |||
) | [static] |
Definition at line 119 of file app_mp3.c.
References ast_log(), ast_poll, and LOG_NOTICE.
Referenced by mp3_exec(), and NBScat_exec().
00120 { 00121 int res; 00122 struct pollfd fds[1]; 00123 fds[0].fd = fd; 00124 fds[0].events = POLLIN; 00125 res = ast_poll(fds, 1, timeout); 00126 if (res < 1) { 00127 ast_log(LOG_NOTICE, "Poll timed out/errored out with %d\n", res); 00128 return -1; 00129 } 00130 return read(fd, data, datalen); 00131 00132 }
static int unload_module | ( | void | ) | [static] |
Definition at line 243 of file app_mp3.c.
References ast_unregister_application().
00244 { 00245 return ast_unregister_application(app); 00246 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Silly MP3 Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static] |
struct ast_module_info* ast_module_info = &__mod_info [static] |