#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, void *data) |
static int | mp3play (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_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } |
static char * | app = "MP3Player" |
static struct ast_module_info * | ast_module_info = &__mod_info |
static char * | descrip |
static char * | synopsis = "Play an MP3 file or stream" |
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 224 of file app_mp3.c.
References ast_register_application, and mp3_exec().
00225 { 00226 return ast_register_application(app, mp3_exec, synopsis, descrip); 00227 }
static int mp3_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 110 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(), chan, f, LOG_WARNING, mp3play(), ast_frame::offset, timed_read(), and ast_channel::writeformat.
Referenced by load_module().
00111 { 00112 int res=0; 00113 int fds[2]; 00114 int ms = -1; 00115 int pid = -1; 00116 int owriteformat; 00117 int timeout = 2000; 00118 struct timeval next; 00119 struct ast_frame *f; 00120 struct myframe { 00121 struct ast_frame f; 00122 char offset[AST_FRIENDLY_OFFSET]; 00123 short frdata[160]; 00124 } myf = { 00125 .f = { 0, }, 00126 }; 00127 00128 if (ast_strlen_zero(data)) { 00129 ast_log(LOG_WARNING, "MP3 Playback requires an argument (filename)\n"); 00130 return -1; 00131 } 00132 00133 if (pipe(fds)) { 00134 ast_log(LOG_WARNING, "Unable to create pipe\n"); 00135 return -1; 00136 } 00137 00138 ast_stopstream(chan); 00139 00140 owriteformat = chan->writeformat; 00141 res = ast_set_write_format(chan, AST_FORMAT_SLINEAR); 00142 if (res < 0) { 00143 ast_log(LOG_WARNING, "Unable to set write format to signed linear\n"); 00144 return -1; 00145 } 00146 00147 res = mp3play((char *)data, fds[1]); 00148 if (!strncasecmp((char *)data, "http://", 7)) { 00149 timeout = 10000; 00150 } 00151 /* Wait 1000 ms first */ 00152 next = ast_tvnow(); 00153 next.tv_sec += 1; 00154 if (res >= 0) { 00155 pid = res; 00156 /* Order is important -- there's almost always going to be mp3... we want to prioritize the 00157 user */ 00158 for (;;) { 00159 ms = ast_tvdiff_ms(next, ast_tvnow()); 00160 if (ms <= 0) { 00161 res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout); 00162 if (res > 0) { 00163 myf.f.frametype = AST_FRAME_VOICE; 00164 myf.f.subclass = AST_FORMAT_SLINEAR; 00165 myf.f.datalen = res; 00166 myf.f.samples = res / 2; 00167 myf.f.mallocd = 0; 00168 myf.f.offset = AST_FRIENDLY_OFFSET; 00169 myf.f.src = __PRETTY_FUNCTION__; 00170 myf.f.delivery.tv_sec = 0; 00171 myf.f.delivery.tv_usec = 0; 00172 myf.f.data.ptr = myf.frdata; 00173 if (ast_write(chan, &myf.f) < 0) { 00174 res = -1; 00175 break; 00176 } 00177 } else { 00178 ast_debug(1, "No more mp3\n"); 00179 res = 0; 00180 break; 00181 } 00182 next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000)); 00183 } else { 00184 ms = ast_waitfor(chan, ms); 00185 if (ms < 0) { 00186 ast_debug(1, "Hangup detected\n"); 00187 res = -1; 00188 break; 00189 } 00190 if (ms) { 00191 f = ast_read(chan); 00192 if (!f) { 00193 ast_debug(1, "Null frame == hangup() detected\n"); 00194 res = -1; 00195 break; 00196 } 00197 if (f->frametype == AST_FRAME_DTMF) { 00198 ast_debug(1, "User pressed a key\n"); 00199 ast_frfree(f); 00200 res = 0; 00201 break; 00202 } 00203 ast_frfree(f); 00204 } 00205 } 00206 } 00207 } 00208 close(fds[0]); 00209 close(fds[1]); 00210 00211 if (pid > -1) 00212 kill(pid, SIGKILL); 00213 if (!res && owriteformat) 00214 ast_set_write_format(chan, owriteformat); 00215 00216 return res; 00217 }
static int mp3play | ( | char * | filename, | |
int | fd | |||
) | [static] |
Definition at line 57 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().
00058 { 00059 int res; 00060 00061 res = ast_safe_fork(0); 00062 if (res < 0) 00063 ast_log(LOG_WARNING, "Fork failed\n"); 00064 if (res) { 00065 return res; 00066 } 00067 if (ast_opt_high_priority) 00068 ast_set_priority(0); 00069 00070 dup2(fd, STDOUT_FILENO); 00071 ast_close_fds_above_n(STDERR_FILENO); 00072 00073 /* Execute mpg123, but buffer if it's a net connection */ 00074 if (!strncasecmp(filename, "http://", 7)) { 00075 /* Most commonly installed in /usr/local/bin */ 00076 execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); 00077 /* But many places has it in /usr/bin */ 00078 execl(MPG_123, "mpg123", "-q", "-s", "-b", "1024","-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); 00079 /* As a last-ditch effort, try to use PATH */ 00080 execlp("mpg123", "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); 00081 } 00082 else { 00083 /* Most commonly installed in /usr/local/bin */ 00084 execl(MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); 00085 /* But many places has it in /usr/bin */ 00086 execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); 00087 /* As a last-ditch effort, try to use PATH */ 00088 execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); 00089 } 00090 /* Can't use ast_log since FD's are closed */ 00091 fprintf(stderr, "Execute of mpg123 failed\n"); 00092 _exit(0); 00093 }
static int timed_read | ( | int | fd, | |
void * | data, | |||
int | datalen, | |||
int | timeout | |||
) | [static] |
Definition at line 95 of file app_mp3.c.
References ast_log(), ast_poll, and LOG_NOTICE.
Referenced by mp3_exec(), and NBScat_exec().
00096 { 00097 int res; 00098 struct pollfd fds[1]; 00099 fds[0].fd = fd; 00100 fds[0].events = POLLIN; 00101 res = ast_poll(fds, 1, timeout); 00102 if (res < 1) { 00103 ast_log(LOG_NOTICE, "Poll timed out/errored out with %d\n", res); 00104 return -1; 00105 } 00106 return read(fd, data, datalen); 00107 00108 }
static int unload_module | ( | void | ) | [static] |
Definition at line 219 of file app_mp3.c.
References ast_unregister_application().
00220 { 00221 return ast_unregister_application(app); 00222 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } [static] |
struct ast_module_info* ast_module_info = &__mod_info [static] |
char* descrip [static] |