Thu Feb 5 16:25:55 2009

Asterisk developer's documentation


app_mp3.c File Reference

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

#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_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 255 of file app_mp3.c.

static void __unreg_module ( void   )  [static]

Definition at line 255 of file app_mp3.c.

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 }


Variable Documentation

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]

Definition at line 255 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 255 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 Feb 5 16:25:55 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7