Silly application to play an MP3 file -- uses mpg123. More...
#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 | |
AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Silly MP3 Application") | |
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 char * | app = "MP3Player" |
Silly application to play an MP3 file -- uses mpg123.
Definition in file app_mp3.c.
#define LOCAL_MPG_123 "/usr/local/bin/mpg123" |
Definition at line 51 of file app_mp3.c.
Referenced by mp3play(), and spawn_mp3().
#define MPG_123 "/usr/bin/mpg123" |
Definition at line 52 of file app_mp3.c.
Referenced by mp3play(), and spawn_mp3().
AST_MODULE_INFO_STANDARD | ( | ASTERISK_GPL_KEY | , | |
"Silly MP3 Application" | ||||
) |
static int load_module | ( | void | ) | [static] |
Definition at line 254 of file app_mp3.c.
References ast_register_application_xml, and mp3_exec().
00255 { 00256 return ast_register_application_xml(app, mp3_exec); 00257 }
static int mp3_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 140 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, ast_frame::frametype, LOG_WARNING, mp3play(), ast_frame::offset, timed_read(), and ast_channel::writeformat.
Referenced by load_module().
00141 { 00142 int res=0; 00143 int fds[2]; 00144 int ms = -1; 00145 int pid = -1; 00146 int owriteformat; 00147 int timeout = 2000; 00148 struct timeval next; 00149 struct ast_frame *f; 00150 struct myframe { 00151 struct ast_frame f; 00152 char offset[AST_FRIENDLY_OFFSET]; 00153 short frdata[160]; 00154 } myf = { 00155 .f = { 0, }, 00156 }; 00157 00158 if (ast_strlen_zero(data)) { 00159 ast_log(LOG_WARNING, "MP3 Playback requires an argument (filename)\n"); 00160 return -1; 00161 } 00162 00163 if (pipe(fds)) { 00164 ast_log(LOG_WARNING, "Unable to create pipe\n"); 00165 return -1; 00166 } 00167 00168 ast_stopstream(chan); 00169 00170 owriteformat = chan->writeformat; 00171 res = ast_set_write_format(chan, AST_FORMAT_SLINEAR); 00172 if (res < 0) { 00173 ast_log(LOG_WARNING, "Unable to set write format to signed linear\n"); 00174 return -1; 00175 } 00176 00177 res = mp3play(data, fds[1]); 00178 if (!strncasecmp(data, "http://", 7)) { 00179 timeout = 10000; 00180 } 00181 /* Wait 1000 ms first */ 00182 next = ast_tvnow(); 00183 next.tv_sec += 1; 00184 if (res >= 0) { 00185 pid = res; 00186 /* Order is important -- there's almost always going to be mp3... we want to prioritize the 00187 user */ 00188 for (;;) { 00189 ms = ast_tvdiff_ms(next, ast_tvnow()); 00190 if (ms <= 0) { 00191 res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout); 00192 if (res > 0) { 00193 myf.f.frametype = AST_FRAME_VOICE; 00194 myf.f.subclass.codec = AST_FORMAT_SLINEAR; 00195 myf.f.datalen = res; 00196 myf.f.samples = res / 2; 00197 myf.f.mallocd = 0; 00198 myf.f.offset = AST_FRIENDLY_OFFSET; 00199 myf.f.src = __PRETTY_FUNCTION__; 00200 myf.f.delivery.tv_sec = 0; 00201 myf.f.delivery.tv_usec = 0; 00202 myf.f.data.ptr = myf.frdata; 00203 if (ast_write(chan, &myf.f) < 0) { 00204 res = -1; 00205 break; 00206 } 00207 } else { 00208 ast_debug(1, "No more mp3\n"); 00209 res = 0; 00210 break; 00211 } 00212 next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000)); 00213 } else { 00214 ms = ast_waitfor(chan, ms); 00215 if (ms < 0) { 00216 ast_debug(1, "Hangup detected\n"); 00217 res = -1; 00218 break; 00219 } 00220 if (ms) { 00221 f = ast_read(chan); 00222 if (!f) { 00223 ast_debug(1, "Null frame == hangup() detected\n"); 00224 res = -1; 00225 break; 00226 } 00227 if (f->frametype == AST_FRAME_DTMF) { 00228 ast_debug(1, "User pressed a key\n"); 00229 ast_frfree(f); 00230 res = 0; 00231 break; 00232 } 00233 ast_frfree(f); 00234 } 00235 } 00236 } 00237 } 00238 close(fds[0]); 00239 close(fds[1]); 00240 00241 if (pid > -1) 00242 kill(pid, SIGKILL); 00243 if (!res && owriteformat) 00244 ast_set_write_format(chan, owriteformat); 00245 00246 return res; 00247 }
static int mp3play | ( | const char * | filename, | |
int | fd | |||
) | [static] |
Definition at line 79 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().
00080 { 00081 int res; 00082 00083 res = ast_safe_fork(0); 00084 if (res < 0) 00085 ast_log(LOG_WARNING, "Fork failed\n"); 00086 if (res) { 00087 return res; 00088 } 00089 if (ast_opt_high_priority) 00090 ast_set_priority(0); 00091 00092 dup2(fd, STDOUT_FILENO); 00093 ast_close_fds_above_n(STDERR_FILENO); 00094 00095 /* Execute mpg123, but buffer if it's a net connection */ 00096 if (!strncasecmp(filename, "http://", 7)) { 00097 /* Most commonly installed in /usr/local/bin */ 00098 execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); 00099 /* But many places has it in /usr/bin */ 00100 execl(MPG_123, "mpg123", "-q", "-s", "-b", "1024","-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); 00101 /* As a last-ditch effort, try to use PATH */ 00102 execlp("mpg123", "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); 00103 } 00104 else if (strstr(filename, ".m3u")) { 00105 /* Most commonly installed in /usr/local/bin */ 00106 execl(LOCAL_MPG_123, "mpg123", "-q", "-z", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", "-@", filename, (char *)NULL); 00107 /* But many places has it in /usr/bin */ 00108 execl(MPG_123, "mpg123", "-q", "-z", "-s", "-b", "1024","-f", "8192", "--mono", "-r", "8000", "-@", filename, (char *)NULL); 00109 /* As a last-ditch effort, try to use PATH */ 00110 execlp("mpg123", "mpg123", "-q", "-z", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", "-@", filename, (char *)NULL); 00111 } 00112 else { 00113 /* Most commonly installed in /usr/local/bin */ 00114 execl(MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); 00115 /* But many places has it in /usr/bin */ 00116 execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); 00117 /* As a last-ditch effort, try to use PATH */ 00118 execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); 00119 } 00120 /* Can't use ast_log since FD's are closed */ 00121 fprintf(stderr, "Execute of mpg123 failed\n"); 00122 _exit(0); 00123 }
static int timed_read | ( | int | fd, | |
void * | data, | |||
int | datalen, | |||
int | timeout | |||
) | [static] |
Definition at line 125 of file app_mp3.c.
References ast_log(), ast_poll, and LOG_NOTICE.
Referenced by mp3_exec().
00126 { 00127 int res; 00128 struct pollfd fds[1]; 00129 fds[0].fd = fd; 00130 fds[0].events = POLLIN; 00131 res = ast_poll(fds, 1, timeout); 00132 if (res < 1) { 00133 ast_log(LOG_NOTICE, "Poll timed out/errored out with %d\n", res); 00134 return -1; 00135 } 00136 return read(fd, data, datalen); 00137 00138 }
static int unload_module | ( | void | ) | [static] |
Definition at line 249 of file app_mp3.c.
References ast_unregister_application().
00250 { 00251 return ast_unregister_application(app); 00252 }