#include "asterisk.h"
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/frame.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/options.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 | AST_MODFLAG_BUILDSUM, .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 = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, } |
static char * | app = "MP3Player" |
static const 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 250 of file app_mp3.c.
References ast_register_application(), and mp3_exec().
00251 { 00252 return ast_register_application(app, mp3_exec, synopsis, descrip); 00253 }
static int mp3_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 125 of file app_mp3.c.
References AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, ast_log(), ast_module_user_add, ast_module_user_remove, 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_DEBUG, LOG_WARNING, mp3play(), offset, timed_read(), and ast_channel::writeformat.
Referenced by load_module().
00126 { 00127 int res=0; 00128 struct ast_module_user *u; 00129 int fds[2]; 00130 int ms = -1; 00131 int pid = -1; 00132 int owriteformat; 00133 int timeout = 2000; 00134 struct timeval next; 00135 struct ast_frame *f; 00136 struct myframe { 00137 struct ast_frame f; 00138 char offset[AST_FRIENDLY_OFFSET]; 00139 short frdata[160]; 00140 } myf; 00141 00142 if (ast_strlen_zero(data)) { 00143 ast_log(LOG_WARNING, "MP3 Playback requires an argument (filename)\n"); 00144 return -1; 00145 } 00146 00147 u = ast_module_user_add(chan); 00148 00149 if (pipe(fds)) { 00150 ast_log(LOG_WARNING, "Unable to create pipe\n"); 00151 ast_module_user_remove(u); 00152 return -1; 00153 } 00154 00155 ast_stopstream(chan); 00156 00157 owriteformat = chan->writeformat; 00158 res = ast_set_write_format(chan, AST_FORMAT_SLINEAR); 00159 if (res < 0) { 00160 ast_log(LOG_WARNING, "Unable to set write format to signed linear\n"); 00161 ast_module_user_remove(u); 00162 return -1; 00163 } 00164 00165 res = mp3play((char *)data, fds[1]); 00166 if (!strncasecmp((char *)data, "http://", 7)) { 00167 timeout = 10000; 00168 } 00169 /* Wait 1000 ms first */ 00170 next = ast_tvnow(); 00171 next.tv_sec += 1; 00172 if (res >= 0) { 00173 pid = res; 00174 /* Order is important -- there's almost always going to be mp3... we want to prioritize the 00175 user */ 00176 for (;;) { 00177 ms = ast_tvdiff_ms(next, ast_tvnow()); 00178 if (ms <= 0) { 00179 res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout); 00180 if (res > 0) { 00181 myf.f.frametype = AST_FRAME_VOICE; 00182 myf.f.subclass = AST_FORMAT_SLINEAR; 00183 myf.f.datalen = res; 00184 myf.f.samples = res / 2; 00185 myf.f.mallocd = 0; 00186 myf.f.offset = AST_FRIENDLY_OFFSET; 00187 myf.f.src = __PRETTY_FUNCTION__; 00188 myf.f.delivery.tv_sec = 0; 00189 myf.f.delivery.tv_usec = 0; 00190 myf.f.data = myf.frdata; 00191 if (ast_write(chan, &myf.f) < 0) { 00192 res = -1; 00193 break; 00194 } 00195 } else { 00196 ast_log(LOG_DEBUG, "No more mp3\n"); 00197 res = 0; 00198 break; 00199 } 00200 next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000)); 00201 } else { 00202 ms = ast_waitfor(chan, ms); 00203 if (ms < 0) { 00204 ast_log(LOG_DEBUG, "Hangup detected\n"); 00205 res = -1; 00206 break; 00207 } 00208 if (ms) { 00209 f = ast_read(chan); 00210 if (!f) { 00211 ast_log(LOG_DEBUG, "Null frame == hangup() detected\n"); 00212 res = -1; 00213 break; 00214 } 00215 if (f->frametype == AST_FRAME_DTMF) { 00216 ast_log(LOG_DEBUG, "User pressed a key\n"); 00217 ast_frfree(f); 00218 res = 0; 00219 break; 00220 } 00221 ast_frfree(f); 00222 } 00223 } 00224 } 00225 } 00226 close(fds[0]); 00227 close(fds[1]); 00228 00229 if (pid > -1) 00230 kill(pid, SIGKILL); 00231 if (!res && owriteformat) 00232 ast_set_write_format(chan, owriteformat); 00233 00234 ast_module_user_remove(u); 00235 00236 return res; 00237 }
static int mp3play | ( | char * | filename, | |
int | fd | |||
) | [static] |
Definition at line 63 of file app_mp3.c.
References ast_log(), ast_opt_high_priority, ast_set_priority(), LOCAL_MPG_123, LOG_WARNING, and MPG_123.
Referenced by mp3_exec().
00064 { 00065 int res; 00066 int x; 00067 sigset_t fullset, oldset; 00068 00069 sigfillset(&fullset); 00070 pthread_sigmask(SIG_BLOCK, &fullset, &oldset); 00071 00072 res = fork(); 00073 if (res < 0) 00074 ast_log(LOG_WARNING, "Fork failed\n"); 00075 if (res) { 00076 pthread_sigmask(SIG_SETMASK, &oldset, NULL); 00077 return res; 00078 } 00079 if (ast_opt_high_priority) 00080 ast_set_priority(0); 00081 signal(SIGPIPE, SIG_DFL); 00082 pthread_sigmask(SIG_UNBLOCK, &fullset, NULL); 00083 00084 dup2(fd, STDOUT_FILENO); 00085 for (x=STDERR_FILENO + 1;x<256;x++) { 00086 if (x != STDOUT_FILENO) 00087 close(x); 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 { 00099 /* Most commonly installed in /usr/local/bin */ 00100 execl(MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); 00101 /* But many places has it in /usr/bin */ 00102 execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); 00103 /* As a last-ditch effort, try to use PATH */ 00104 execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); 00105 } 00106 ast_log(LOG_WARNING, "Execute of mpg123 failed\n"); 00107 _exit(0); 00108 }
static int timed_read | ( | int | fd, | |
void * | data, | |||
int | datalen, | |||
int | timeout | |||
) | [static] |
Definition at line 110 of file app_mp3.c.
References ast_log(), pollfd::events, pollfd::fd, LOG_NOTICE, poll(), and POLLIN.
Referenced by mp3_exec(), and NBScat_exec().
00111 { 00112 int res; 00113 struct pollfd fds[1]; 00114 fds[0].fd = fd; 00115 fds[0].events = POLLIN; 00116 res = poll(fds, 1, timeout); 00117 if (res < 1) { 00118 ast_log(LOG_NOTICE, "Poll timed out/errored out with %d\n", res); 00119 return -1; 00120 } 00121 return read(fd, data, datalen); 00122 00123 }
static int unload_module | ( | void | ) | [static] |
Definition at line 239 of file app_mp3.c.
References ast_module_user_hangup_all, and ast_unregister_application().
00240 { 00241 int res; 00242 00243 res = ast_unregister_application(app); 00244 00245 ast_module_user_hangup_all(); 00246 00247 return res; 00248 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .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 = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, } [static] |
const struct ast_module_info* ast_module_info = &__mod_info [static] |
char* descrip [static] |