Wed Oct 14 15:02:01 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 <sys/capability.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 = "361d7bb937402d51e4658efb5b4d76e4" , .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 57 of file app_mp3.c.

Referenced by mp3play(), and spawn_mp3().

#define MPG_123   "/usr/bin/mpg123"

Definition at line 58 of file app_mp3.c.

Referenced by mp3play(), and spawn_mp3().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 273 of file app_mp3.c.

static void __unreg_module ( void   )  [static]

Definition at line 273 of file app_mp3.c.

static int load_module ( void   )  [static]

Definition at line 268 of file app_mp3.c.

References ast_register_application(), and mp3_exec().

00269 {
00270    return ast_register_application(app, mp3_exec, synopsis, descrip);
00271 }

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

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

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

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

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

00071 {
00072    int res;
00073    int x;
00074    sigset_t fullset, oldset;
00075 #ifdef HAVE_CAP
00076    cap_t cap;
00077 #endif
00078 
00079    sigfillset(&fullset);
00080    pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
00081 
00082    res = fork();
00083    if (res < 0) 
00084       ast_log(LOG_WARNING, "Fork failed\n");
00085    if (res) {
00086       pthread_sigmask(SIG_SETMASK, &oldset, NULL);
00087       return res;
00088    }
00089 #ifdef HAVE_CAP
00090    cap = cap_from_text("cap_net_admin-eip");
00091 
00092    if (cap_set_proc(cap)) {
00093       /* Careful with order! Logging cannot happen after we close FDs */
00094       ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
00095    }
00096    cap_free(cap);
00097 #endif
00098    if (ast_opt_high_priority)
00099       ast_set_priority(0);
00100    signal(SIGPIPE, SIG_DFL);
00101    pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
00102 
00103    dup2(fd, STDOUT_FILENO);
00104    for (x=STDERR_FILENO + 1;x<256;x++) {
00105       close(x);
00106    }
00107    /* Execute mpg123, but buffer if it's a net connection */
00108    if (!strncasecmp(filename, "http://", 7)) {
00109       /* Most commonly installed in /usr/local/bin */
00110        execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
00111       /* But many places has it in /usr/bin */
00112        execl(MPG_123, "mpg123", "-q", "-s", "-b", "1024","-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
00113       /* As a last-ditch effort, try to use PATH */
00114        execlp("mpg123", "mpg123", "-q", "-s", "-b", "1024",  "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
00115    }
00116    else {
00117       /* Most commonly installed in /usr/local/bin */
00118        execl(MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
00119       /* But many places has it in /usr/bin */
00120        execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
00121       /* As a last-ditch effort, try to use PATH */
00122        execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
00123    }
00124    ast_log(LOG_WARNING, "Execute of mpg123 failed\n");
00125    _exit(0);
00126 }

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

Definition at line 128 of file app_mp3.c.

References ast_log(), ast_poll, and LOG_NOTICE.

Referenced by mp3_exec(), and NBScat_exec().

00129 {
00130    int res;
00131    struct pollfd fds[1];
00132    fds[0].fd = fd;
00133    fds[0].events = POLLIN;
00134    res = ast_poll(fds, 1, timeout);
00135    if (res < 1) {
00136       ast_log(LOG_NOTICE, "Poll timed out/errored out with %d\n", res);
00137       return -1;
00138    }
00139    return read(fd, data, datalen);
00140    
00141 }

static int unload_module ( void   )  [static]

Definition at line 257 of file app_mp3.c.

References ast_module_user_hangup_all, and ast_unregister_application().

00258 {
00259    int res;
00260 
00261    res = ast_unregister_application(app);
00262 
00263    ast_module_user_hangup_all();
00264    
00265    return res;
00266 }


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

Definition at line 273 of file app_mp3.c.

char* app = "MP3Player" [static]

Definition at line 60 of file app_mp3.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

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

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

Definition at line 62 of file app_mp3.c.


Generated on Wed Oct 14 15:02:01 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7