Thu Jul 9 13:40:46 2009

Asterisk developer's documentation


app_mp3.c File Reference

Silly application to play an MP3 file -- uses mpg123. More...

#include "asterisk.h"
#include <sys/time.h>
#include <signal.h>
#include <sys/capability.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"

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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, }
static char * app = "MP3Player"
static const struct ast_module_infoast_module_info = &__mod_info
static char * descrip
static char * synopsis = "Play an MP3 file or stream"


Detailed Description

Silly application to play an MP3 file -- uses mpg123.

Author:
Mark Spencer <markster@digium.com>

Definition in file app_mp3.c.


Define Documentation

#define LOCAL_MPG_123   "/usr/local/bin/mpg123"

Definition at line 50 of file app_mp3.c.

Referenced by mp3play(), and spawn_mp3().

#define MPG_123   "/usr/bin/mpg123"

Definition at line 51 of file app_mp3.c.

Referenced by mp3play(), and spawn_mp3().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 253 of file app_mp3.c.

static void __unreg_module ( void   )  [static]

Definition at line 253 of file app_mp3.c.

static int load_module ( void   )  [static]

Definition at line 248 of file app_mp3.c.

References ast_register_application, and mp3_exec().

00249 {
00250    return ast_register_application(app, mp3_exec, synopsis, descrip);
00251 }

static int mp3_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 136 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().

00137 {
00138    int res=0;
00139    int fds[2];
00140    int ms = -1;
00141    int pid = -1;
00142    int owriteformat;
00143    int timeout = 2000;
00144    struct timeval next;
00145    struct ast_frame *f;
00146    struct myframe {
00147       struct ast_frame f;
00148       char offset[AST_FRIENDLY_OFFSET];
00149       short frdata[160];
00150    } myf;
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((char *)data, fds[1]);
00172    if (!strncasecmp((char *)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 = 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 = 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 ( 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 #ifdef HAVE_CAP
00069    cap_t cap;
00070 #endif
00071 
00072    sigfillset(&fullset);
00073    pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
00074 
00075    res = fork();
00076    if (res < 0) 
00077       ast_log(LOG_WARNING, "Fork failed\n");
00078    if (res) {
00079       pthread_sigmask(SIG_SETMASK, &oldset, NULL);
00080       return res;
00081    }
00082 #ifdef HAVE_CAP
00083    cap = cap_from_text("cap_net_admin-eip");
00084 
00085    if (cap_set_proc(cap)) {
00086       /* Careful with order! Logging cannot happen after we close FDs */
00087       ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
00088    }
00089    cap_free(cap);
00090 #endif
00091    if (ast_opt_high_priority)
00092       ast_set_priority(0);
00093    signal(SIGPIPE, SIG_DFL);
00094    pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
00095 
00096    dup2(fd, STDOUT_FILENO);
00097    for (x=STDERR_FILENO + 1;x<256;x++) {
00098       close(x);
00099    }
00100    /* Execute mpg123, but buffer if it's a net connection */
00101    if (!strncasecmp(filename, "http://", 7)) {
00102       /* Most commonly installed in /usr/local/bin */
00103        execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
00104       /* But many places has it in /usr/bin */
00105        execl(MPG_123, "mpg123", "-q", "-s", "-b", "1024","-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
00106       /* As a last-ditch effort, try to use PATH */
00107        execlp("mpg123", "mpg123", "-q", "-s", "-b", "1024",  "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
00108    }
00109    else {
00110       /* Most commonly installed in /usr/local/bin */
00111        execl(MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
00112       /* But many places has it in /usr/bin */
00113        execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
00114       /* As a last-ditch effort, try to use PATH */
00115        execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
00116    }
00117    ast_log(LOG_WARNING, "Execute of mpg123 failed\n");
00118    _exit(0);
00119 }

static int timed_read ( int  fd,
void *  data,
int  datalen,
int  timeout 
) [static]

Definition at line 121 of file app_mp3.c.

References ast_log(), ast_poll, and LOG_NOTICE.

Referenced by mp3_exec(), and NBScat_exec().

00122 {
00123    int res;
00124    struct pollfd fds[1];
00125    fds[0].fd = fd;
00126    fds[0].events = POLLIN;
00127    res = ast_poll(fds, 1, timeout);
00128    if (res < 1) {
00129       ast_log(LOG_NOTICE, "Poll timed out/errored out with %d\n", res);
00130       return -1;
00131    }
00132    return read(fd, data, datalen);
00133    
00134 }

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 }


Variable Documentation

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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, } [static]

Definition at line 253 of file app_mp3.c.

char* app = "MP3Player" [static]

Definition at line 53 of file app_mp3.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 253 of file app_mp3.c.

char* descrip [static]

Initial value:

 
"  MP3Player(location): Executes mpg123 to play the given location,\n"
"which typically would be a filename or a URL. User can exit by pressing\n"
"any key on the dialpad, or by hanging up."

Definition at line 57 of file app_mp3.c.

char* synopsis = "Play an MP3 file or stream" [static]

Definition at line 55 of file app_mp3.c.


Generated on Thu Jul 9 13:40:46 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7