Fri May 26 01:46:03 2006

Asterisk developer's documentation


app_mp3.c File Reference

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

#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include "asterisk.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 dependency graph for app_mp3.c:

Go to the source code of this file.

Defines

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

Functions

char * description (void)
 Provides a description of the module.
char * key ()
 Returns the ASTERISK_GPL_KEY.
int load_module (void)
 Initialize the module.
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)
int unload_module (void)
 Cleanup all module structures, sockets, etc.
int usecount (void)
 Provides a usecount.

Variables

static char * app = "MP3Player"
static char * descrip
 LOCAL_USER_DECL
 STANDARD_LOCAL_USER
static char * synopsis = "Play an MP3 file or stream"
static char * tdesc = "Silly MP3 Application"


Detailed Description

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

Definition in file app_mp3.c.


Define Documentation

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

Definition at line 47 of file app_mp3.c.

#define MPG_123   "/usr/bin/mpg123"
 

Definition at line 48 of file app_mp3.c.


Function Documentation

char* description void   ) 
 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 245 of file app_mp3.c.

00246 {
00247    return tdesc;
00248 }

char* key void   ) 
 

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

 char *key(void) {
         return ASTERISK_GPL_KEY;
 }

Returns:
ASTERISK_GPL_KEY

Definition at line 257 of file app_mp3.c.

References ASTERISK_GPL_KEY.

00258 {
00259    return ASTERISK_GPL_KEY;
00260 }

int load_module void   ) 
 

Initialize the module.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
int Always 0.

Definition at line 240 of file app_mp3.c.

References ast_register_application(), and mp3_exec().

00241 {
00242    return ast_register_application(app, mp3_exec, synopsis, descrip);
00243 }

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

Definition at line 115 of file app_mp3.c.

References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_set_write_format(), ast_stopstream(), ast_strlen_zero(), ast_write(), LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_WARNING, mp3play(), offset, timed_read(), and ast_channel::writeformat.

Referenced by load_module().

00116 {
00117    int res=0;
00118    struct localuser *u;
00119    int fds[2];
00120    int ms = -1;
00121    int pid = -1;
00122    int owriteformat;
00123    int timeout = 2000;
00124    struct timeval next;
00125    struct ast_frame *f;
00126    struct myframe {
00127       struct ast_frame f;
00128       char offset[AST_FRIENDLY_OFFSET];
00129       short frdata[160];
00130    } myf;
00131    
00132    if (ast_strlen_zero(data)) {
00133       ast_log(LOG_WARNING, "MP3 Playback requires an argument (filename)\n");
00134       return -1;
00135    }
00136 
00137    LOCAL_USER_ADD(u);
00138 
00139    if (pipe(fds)) {
00140       ast_log(LOG_WARNING, "Unable to create pipe\n");
00141       LOCAL_USER_REMOVE(u);
00142       return -1;
00143    }
00144    
00145    ast_stopstream(chan);
00146 
00147    owriteformat = chan->writeformat;
00148    res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
00149    if (res < 0) {
00150       ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
00151       LOCAL_USER_REMOVE(u);
00152       return -1;
00153    }
00154    
00155    res = mp3play((char *)data, fds[1]);
00156    if (!strncasecmp((char *)data, "http://", 7)) {
00157       timeout = 10000;
00158    }
00159    /* Wait 1000 ms first */
00160    next = ast_tvnow();
00161    next.tv_sec += 1;
00162    if (res >= 0) {
00163       pid = res;
00164       /* Order is important -- there's almost always going to be mp3...  we want to prioritize the
00165          user */
00166       for (;;) {
00167          ms = ast_tvdiff_ms(next, ast_tvnow());
00168          if (ms <= 0) {
00169             res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout);
00170             if (res > 0) {
00171                myf.f.frametype = AST_FRAME_VOICE;
00172                myf.f.subclass = AST_FORMAT_SLINEAR;
00173                myf.f.datalen = res;
00174                myf.f.samples = res / 2;
00175                myf.f.mallocd = 0;
00176                myf.f.offset = AST_FRIENDLY_OFFSET;
00177                myf.f.src = __PRETTY_FUNCTION__;
00178                myf.f.delivery.tv_sec = 0;
00179                myf.f.delivery.tv_usec = 0;
00180                myf.f.data = myf.frdata;
00181                if (ast_write(chan, &myf.f) < 0) {
00182                   res = -1;
00183                   break;
00184                }
00185             } else {
00186                ast_log(LOG_DEBUG, "No more mp3\n");
00187                res = 0;
00188                break;
00189             }
00190             next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000));
00191          } else {
00192             ms = ast_waitfor(chan, ms);
00193             if (ms < 0) {
00194                ast_log(LOG_DEBUG, "Hangup detected\n");
00195                res = -1;
00196                break;
00197             }
00198             if (ms) {
00199                f = ast_read(chan);
00200                if (!f) {
00201                   ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
00202                   res = -1;
00203                   break;
00204                }
00205                if (f->frametype == AST_FRAME_DTMF) {
00206                   ast_log(LOG_DEBUG, "User pressed a key\n");
00207                   ast_frfree(f);
00208                   res = 0;
00209                   break;
00210                }
00211                ast_frfree(f);
00212             } 
00213          }
00214       }
00215    }
00216    close(fds[0]);
00217    close(fds[1]);
00218    
00219    if (pid > -1)
00220       kill(pid, SIGKILL);
00221    if (!res && owriteformat)
00222       ast_set_write_format(chan, owriteformat);
00223 
00224    LOCAL_USER_REMOVE(u);
00225    
00226    return res;
00227 }

static int mp3play char *  filename,
int  fd
[static]
 

Definition at line 65 of file app_mp3.c.

References ast_log(), and LOG_WARNING.

Referenced by mp3_exec().

00066 {
00067    int res;
00068    int x;
00069    res = fork();
00070    if (res < 0) 
00071       ast_log(LOG_WARNING, "Fork failed\n");
00072    if (res)
00073       return res;
00074    dup2(fd, STDOUT_FILENO);
00075    for (x=0;x<256;x++) {
00076       if (x != STDOUT_FILENO)
00077          close(x);
00078    }
00079    /* Execute mpg123, but buffer if it's a net connection */
00080    if (!strncasecmp(filename, "http://", 7)) {
00081       /* Most commonly installed in /usr/local/bin */
00082        execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
00083       /* But many places has it in /usr/bin */
00084        execl(MPG_123, "mpg123", "-q", "-s", "-b", "1024","-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
00085       /* As a last-ditch effort, try to use PATH */
00086        execlp("mpg123", "mpg123", "-q", "-s", "-b", "1024",  "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
00087    }
00088    else {
00089       /* Most commonly installed in /usr/local/bin */
00090        execl(MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
00091       /* But many places has it in /usr/bin */
00092        execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
00093       /* As a last-ditch effort, try to use PATH */
00094        execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
00095    }
00096    ast_log(LOG_WARNING, "Execute of mpg123 failed\n");
00097    return -1;
00098 }

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

Definition at line 100 of file app_mp3.c.

References ast_log(), pollfd::events, pollfd::fd, LOG_NOTICE, poll(), and POLLIN.

Referenced by mp3_exec(), and NBScat_exec().

00101 {
00102    int res;
00103    struct pollfd fds[1];
00104    fds[0].fd = fd;
00105    fds[0].events = POLLIN;
00106    res = poll(fds, 1, timeout);
00107    if (res < 1) {
00108       ast_log(LOG_NOTICE, "Poll timed out/errored out with %d\n", res);
00109       return -1;
00110    }
00111    return read(fd, data, datalen);
00112    
00113 }

int unload_module void   ) 
 

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
Zero on success, or non-zero on error.

Definition at line 229 of file app_mp3.c.

References ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.

00230 {
00231    int res;
00232 
00233    res = ast_unregister_application(app);
00234 
00235    STANDARD_HANGUP_LOCALUSERS;
00236    
00237    return res;
00238 }

int usecount void   ) 
 

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
The module's usecount.

Definition at line 250 of file app_mp3.c.

References STANDARD_USECOUNT.

00251 {
00252    int res;
00253    STANDARD_USECOUNT(res);
00254    return res;
00255 }


Variable Documentation

char* app = "MP3Player" [static]
 

Definition at line 52 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 56 of file app_mp3.c.

LOCAL_USER_DECL
 

Definition at line 63 of file app_mp3.c.

STANDARD_LOCAL_USER
 

Definition at line 61 of file app_mp3.c.

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

Definition at line 54 of file app_mp3.c.

char* tdesc = "Silly MP3 Application" [static]
 

Definition at line 50 of file app_mp3.c.


Generated on Fri May 26 01:46:04 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.6