Thu Apr 28 2011 16:56:51

Asterisk developer's documentation


app_mp3.c File Reference

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

#include "asterisk.h"
#include <sys/time.h>
#include <signal.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/frame.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/app.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

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
__MODULE_INFO_SECTION 
__mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Silly MP3 Application" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, }
static char * app = "MP3Player"
static struct ast_module_infoast_module_info = &__mod_info

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

Referenced by mp3play().

#define MPG_123   "/usr/bin/mpg123"

Definition at line 45 of file app_mp3.c.

Referenced by mp3play().


Function Documentation

static void __reg_module ( void  ) [static]

Definition at line 239 of file app_mp3.c.

static void __unreg_module ( void  ) [static]

Definition at line 239 of file app_mp3.c.

static int load_module ( void  ) [static]

Definition at line 234 of file app_mp3.c.

References ast_register_application_xml, and mp3_exec().

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

Definition at line 120 of file app_mp3.c.

References ast_debug, AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, ast_log(), 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, ast_frame::frametype, LOG_WARNING, mp3play(), ast_frame::offset, timed_read(), and ast_channel::writeformat.

Referenced by load_module().

{
   int res=0;
   int fds[2];
   int ms = -1;
   int pid = -1;
   int owriteformat;
   int timeout = 2000;
   struct timeval next;
   struct ast_frame *f;
   struct myframe {
      struct ast_frame f;
      char offset[AST_FRIENDLY_OFFSET];
      short frdata[160];
   } myf = {
      .f = { 0, },
   };

   if (ast_strlen_zero(data)) {
      ast_log(LOG_WARNING, "MP3 Playback requires an argument (filename)\n");
      return -1;
   }

   if (pipe(fds)) {
      ast_log(LOG_WARNING, "Unable to create pipe\n");
      return -1;
   }
   
   ast_stopstream(chan);

   owriteformat = chan->writeformat;
   res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
   if (res < 0) {
      ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
      return -1;
   }
   
   res = mp3play((char *)data, fds[1]);
   if (!strncasecmp((char *)data, "http://", 7)) {
      timeout = 10000;
   }
   /* Wait 1000 ms first */
   next = ast_tvnow();
   next.tv_sec += 1;
   if (res >= 0) {
      pid = res;
      /* Order is important -- there's almost always going to be mp3...  we want to prioritize the
         user */
      for (;;) {
         ms = ast_tvdiff_ms(next, ast_tvnow());
         if (ms <= 0) {
            res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout);
            if (res > 0) {
               myf.f.frametype = AST_FRAME_VOICE;
               myf.f.subclass = AST_FORMAT_SLINEAR;
               myf.f.datalen = res;
               myf.f.samples = res / 2;
               myf.f.mallocd = 0;
               myf.f.offset = AST_FRIENDLY_OFFSET;
               myf.f.src = __PRETTY_FUNCTION__;
               myf.f.delivery.tv_sec = 0;
               myf.f.delivery.tv_usec = 0;
               myf.f.data.ptr = myf.frdata;
               if (ast_write(chan, &myf.f) < 0) {
                  res = -1;
                  break;
               }
            } else {
               ast_debug(1, "No more mp3\n");
               res = 0;
               break;
            }
            next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000));
         } else {
            ms = ast_waitfor(chan, ms);
            if (ms < 0) {
               ast_debug(1, "Hangup detected\n");
               res = -1;
               break;
            }
            if (ms) {
               f = ast_read(chan);
               if (!f) {
                  ast_debug(1, "Null frame == hangup() detected\n");
                  res = -1;
                  break;
               }
               if (f->frametype == AST_FRAME_DTMF) {
                  ast_debug(1, "User pressed a key\n");
                  ast_frfree(f);
                  res = 0;
                  break;
               }
               ast_frfree(f);
            } 
         }
      }
   }
   close(fds[0]);
   close(fds[1]);
   
   if (pid > -1)
      kill(pid, SIGKILL);
   if (!res && owriteformat)
      ast_set_write_format(chan, owriteformat);
   
   return res;
}
static int mp3play ( char *  filename,
int  fd 
) [static]

Definition at line 67 of file app_mp3.c.

References ast_close_fds_above_n(), ast_log(), ast_opt_high_priority, ast_safe_fork(), ast_set_priority(), LOCAL_MPG_123, LOG_WARNING, and MPG_123.

Referenced by mp3_exec().

{
   int res;

   res = ast_safe_fork(0);
   if (res < 0) 
      ast_log(LOG_WARNING, "Fork failed\n");
   if (res) {
      return res;
   }
   if (ast_opt_high_priority)
      ast_set_priority(0);

   dup2(fd, STDOUT_FILENO);
   ast_close_fds_above_n(STDERR_FILENO);

   /* Execute mpg123, but buffer if it's a net connection */
   if (!strncasecmp(filename, "http://", 7)) {
      /* Most commonly installed in /usr/local/bin */
       execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
      /* But many places has it in /usr/bin */
       execl(MPG_123, "mpg123", "-q", "-s", "-b", "1024","-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
      /* As a last-ditch effort, try to use PATH */
       execlp("mpg123", "mpg123", "-q", "-s", "-b", "1024",  "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
   }
   else {
      /* Most commonly installed in /usr/local/bin */
       execl(MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
      /* But many places has it in /usr/bin */
       execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
      /* As a last-ditch effort, try to use PATH */
       execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
   }
   /* Can't use ast_log since FD's are closed */
   fprintf(stderr, "Execute of mpg123 failed\n");
   _exit(0);
}
static int timed_read ( int  fd,
void *  data,
int  datalen,
int  timeout 
) [static]

Definition at line 105 of file app_mp3.c.

References ast_log(), ast_poll, and LOG_NOTICE.

Referenced by mp3_exec().

{
   int res;
   struct pollfd fds[1];
   fds[0].fd = fd;
   fds[0].events = POLLIN;
   res = ast_poll(fds, 1, timeout);
   if (res < 1) {
      ast_log(LOG_NOTICE, "Poll timed out/errored out with %d\n", res);
      return -1;
   }
   return read(fd, data, datalen);
   
}
static int unload_module ( void  ) [static]

Definition at line 229 of file app_mp3.c.

References ast_unregister_application().


Variable Documentation

struct ast_module_info __MODULE_INFO_SECTION __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Silly MP3 Application" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } [static]

Definition at line 239 of file app_mp3.c.

char* app = "MP3Player" [static]

Definition at line 65 of file app_mp3.c.

Definition at line 239 of file app_mp3.c.