Sat Aug 6 00:39:35 2011

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

static void __unreg_module ( void   )  [static]

Definition at line 275 of file app_mp3.c.

static int load_module ( void   )  [static]

Definition at line 270 of file app_mp3.c.

References ast_register_application(), and mp3_exec().

00271 {
00272    return ast_register_application(app, mp3_exec, synopsis, descrip);
00273 }

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

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

References ast_module_user_hangup_all, and ast_unregister_application().

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


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 275 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 275 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 Sat Aug 6 00:39:35 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7