Sun Aug 6 15:03:53 2006

Asterisk developer's documentation


Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

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 "asterisk/options.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 48 of file app_mp3.c.

Referenced by mp3play(), and spawn_mp3().

#define MPG_123   "/usr/bin/mpg123"
 

Definition at line 49 of file app_mp3.c.

Referenced by mp3play(), and spawn_mp3().


Function Documentation

char* description void   ) 
 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 248 of file app_mp3.c.

References tdesc.

00249 {
00250    return tdesc;
00251 }

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 260 of file app_mp3.c.

References ASTERISK_GPL_KEY.

00261 {
00262    return ASTERISK_GPL_KEY;
00263 }

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 243 of file app_mp3.c.

References app, ast_register_application(), descrip, mp3_exec(), and synopsis.

00244 {
00245    return ast_register_application(app, mp3_exec, synopsis, descrip);
00246 }

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

Definition at line 118 of file app_mp3.c.

References AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree(), AST_FRIENDLY_OFFSET, ast_log(), ast_read(), ast_set_write_format(), ast_stopstream(), ast_strlen_zero(), ast_tvadd(), ast_waitfor(), ast_write(), ast_frame::frametype, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_DEBUG, LOG_WARNING, mp3play(), offset, timed_read(), and ast_channel::writeformat.

Referenced by load_module().

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

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

Definition at line 66 of file app_mp3.c.

References ast_log(), ast_set_priority(), LOCAL_MPG_123, LOG_WARNING, MPG_123, and option_highpriority.

Referenced by mp3_exec().

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

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

Definition at line 103 of file app_mp3.c.

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

Referenced by mp3_exec(), and NBScat_exec().

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

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 232 of file app_mp3.c.

References app, ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.

00233 {
00234    int res;
00235 
00236    res = ast_unregister_application(app);
00237 
00238    STANDARD_HANGUP_LOCALUSERS;
00239    
00240    return res;
00241 }

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 253 of file app_mp3.c.

References STANDARD_USECOUNT.

00254 {
00255    int res;
00256    STANDARD_USECOUNT(res);
00257    return res;
00258 }


Variable Documentation

char* app = "MP3Player" [static]
 

Definition at line 53 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.

LOCAL_USER_DECL
 

Definition at line 64 of file app_mp3.c.

STANDARD_LOCAL_USER
 

Definition at line 62 of file app_mp3.c.

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

Definition at line 55 of file app_mp3.c.

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

Definition at line 51 of file app_mp3.c.


Generated on Sun Aug 6 15:03:55 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.2