Wed Jan 8 2020 09:49:54

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"

Go to the source code of this file.

Macros

#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, const char *data)
 
static int mp3play (const 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_LOAD_ORDER , .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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
 
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 marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
Note
Add feature to play local M3U playlist file Vincent Li mchun.nosp@m..li@.nosp@m.gmail.nosp@m..com

Definition in file app_mp3.c.

Macro Definition Documentation

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

Definition at line 51 of file app_mp3.c.

Referenced by mp3play().

#define MPG_123   "/usr/bin/mpg123"

Definition at line 52 of file app_mp3.c.

Referenced by mp3play().

Function Documentation

static void __reg_module ( void  )
static

Definition at line 259 of file app_mp3.c.

static void __unreg_module ( void  )
static

Definition at line 259 of file app_mp3.c.

static int load_module ( void  )
static

Definition at line 254 of file app_mp3.c.

References ast_register_application_xml, and mp3_exec().

255 {
257 }
static char * app
Definition: app_mp3.c:77
static int mp3_exec(struct ast_channel *chan, const char *data)
Definition: app_mp3.c:140
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
static int mp3_exec ( struct ast_channel chan,
const char *  data 
)
static

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

141 {
142  int res=0;
143  int fds[2];
144  int ms = -1;
145  int pid = -1;
146  int owriteformat;
147  int timeout = 2000;
148  struct timeval next;
149  struct ast_frame *f;
150  struct myframe {
151  struct ast_frame f;
153  short frdata[160];
154  } myf = {
155  .f = { 0, },
156  };
157 
158  if (ast_strlen_zero(data)) {
159  ast_log(LOG_WARNING, "MP3 Playback requires an argument (filename)\n");
160  return -1;
161  }
162 
163  if (pipe(fds)) {
164  ast_log(LOG_WARNING, "Unable to create pipe\n");
165  return -1;
166  }
167 
168  ast_stopstream(chan);
169 
170  owriteformat = chan->writeformat;
172  if (res < 0) {
173  ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
174  return -1;
175  }
176 
177  res = mp3play(data, fds[1]);
178  if (!strncasecmp(data, "http://", 7)) {
179  timeout = 10000;
180  }
181  /* Wait 1000 ms first */
182  next = ast_tvnow();
183  next.tv_sec += 1;
184  if (res >= 0) {
185  pid = res;
186  /* Order is important -- there's almost always going to be mp3... we want to prioritize the
187  user */
188  for (;;) {
189  ms = ast_tvdiff_ms(next, ast_tvnow());
190  if (ms <= 0) {
191  res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout);
192  if (res > 0) {
193  myf.f.frametype = AST_FRAME_VOICE;
194  myf.f.subclass.codec = AST_FORMAT_SLINEAR;
195  myf.f.datalen = res;
196  myf.f.samples = res / 2;
197  myf.f.mallocd = 0;
198  myf.f.offset = AST_FRIENDLY_OFFSET;
199  myf.f.src = __PRETTY_FUNCTION__;
200  myf.f.delivery.tv_sec = 0;
201  myf.f.delivery.tv_usec = 0;
202  myf.f.data.ptr = myf.frdata;
203  if (ast_write(chan, &myf.f) < 0) {
204  res = -1;
205  break;
206  }
207  } else {
208  ast_debug(1, "No more mp3\n");
209  res = 0;
210  break;
211  }
212  next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000));
213  } else {
214  ms = ast_waitfor(chan, ms);
215  if (ms < 0) {
216  ast_debug(1, "Hangup detected\n");
217  res = -1;
218  break;
219  }
220  if (ms) {
221  f = ast_read(chan);
222  if (!f) {
223  ast_debug(1, "Null frame == hangup() detected\n");
224  res = -1;
225  break;
226  }
227  if (f->frametype == AST_FRAME_DTMF) {
228  ast_debug(1, "User pressed a key\n");
229  ast_frfree(f);
230  res = 0;
231  break;
232  }
233  ast_frfree(f);
234  }
235  }
236  }
237  }
238  close(fds[0]);
239  close(fds[1]);
240 
241  if (pid > -1)
242  kill(pid, SIGKILL);
243  if (!res && owriteformat)
244  ast_set_write_format(chan, owriteformat);
245 
246  return res;
247 }
int offset
Definition: frame.h:156
format_t writeformat
Definition: channel.h:854
#define LOG_WARNING
Definition: logger.h:144
static int timed_read(int fd, void *data, int datalen, int timeout)
Definition: app_mp3.c:125
#define AST_FRAME_DTMF
Definition: frame.h:128
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:90
int ast_set_write_format(struct ast_channel *chan, format_t format)
Sets write format on channel chan Set write format for channel to whichever component of &quot;format&quot; is ...
Definition: channel.c:5307
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define AST_FRIENDLY_OFFSET
Offset into a frame&#39;s data buffer.
Definition: frame.h:204
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:191
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: utils.c:1587
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static struct ast_format f[]
Definition: format_g726.c:181
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:4916
static int mp3play(const char *filename, int fd)
Definition: app_mp3.c:79
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
struct ast_frame * next
Definition: frame.h:164
Data structure associated with a single frame of data.
Definition: frame.h:142
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
union ast_frame::@172 data
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:128
static int mp3play ( const char *  filename,
int  fd 
)
static

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

80 {
81  int res;
82 
83  res = ast_safe_fork(0);
84  if (res < 0)
85  ast_log(LOG_WARNING, "Fork failed\n");
86  if (res) {
87  return res;
88  }
91 
92  dup2(fd, STDOUT_FILENO);
93  ast_close_fds_above_n(STDERR_FILENO);
94 
95  /* Execute mpg123, but buffer if it's a net connection */
96  if (!strncasecmp(filename, "http://", 7)) {
97  /* Most commonly installed in /usr/local/bin */
98  execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
99  /* But many places has it in /usr/bin */
100  execl(MPG_123, "mpg123", "-q", "-s", "-b", "1024","-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
101  /* As a last-ditch effort, try to use PATH */
102  execlp("mpg123", "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
103  }
104  else if (strstr(filename, ".m3u")) {
105  /* Most commonly installed in /usr/local/bin */
106  execl(LOCAL_MPG_123, "mpg123", "-q", "-z", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", "-@", filename, (char *)NULL);
107  /* But many places has it in /usr/bin */
108  execl(MPG_123, "mpg123", "-q", "-z", "-s", "-b", "1024","-f", "8192", "--mono", "-r", "8000", "-@", filename, (char *)NULL);
109  /* As a last-ditch effort, try to use PATH */
110  execlp("mpg123", "mpg123", "-q", "-z", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", "-@", filename, (char *)NULL);
111  }
112  else {
113  /* Most commonly installed in /usr/local/bin */
114  execl(MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
115  /* But many places has it in /usr/bin */
116  execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
117  /* As a last-ditch effort, try to use PATH */
118  execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
119  }
120  /* Can't use ast_log since FD's are closed */
121  fprintf(stderr, "Execute of mpg123 failed\n");
122  _exit(0);
123 }
int ast_safe_fork(int stop_reaper)
Common routine to safely fork without a chance of a signal handler firing badly in the child...
Definition: app.c:2242
#define LOG_WARNING
Definition: logger.h:144
int ast_set_priority(int)
We set ourselves to a high priority, that we might pre-empt everything else. If your PBX has heavy ac...
Definition: asterisk.c:1650
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
void ast_close_fds_above_n(int n)
Common routine for child processes, to close all fds prior to exec(2)
Definition: app.c:2237
#define LOCAL_MPG_123
Definition: app_mp3.c:51
#define MPG_123
Definition: app_mp3.c:52
#define ast_opt_high_priority
Definition: options.h:108
static int timed_read ( int  fd,
void *  data,
int  datalen,
int  timeout 
)
static

Definition at line 125 of file app_mp3.c.

References ast_log(), ast_poll, and LOG_NOTICE.

Referenced by mp3_exec().

126 {
127  int res;
128  struct pollfd fds[1];
129  fds[0].fd = fd;
130  fds[0].events = POLLIN;
131  res = ast_poll(fds, 1, timeout);
132  if (res < 1) {
133  ast_log(LOG_NOTICE, "Poll timed out/errored out with %d\n", res);
134  return -1;
135  }
136  return read(fd, data, datalen);
137 
138 }
#define ast_poll(a, b, c)
Definition: poll-compat.h:88
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
static int unload_module ( void  )
static

Definition at line 249 of file app_mp3.c.

References ast_unregister_application().

250 {
252 }
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
static char * app
Definition: app_mp3.c:77

Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static

Definition at line 259 of file app_mp3.c.

char* app = "MP3Player"
static

Definition at line 77 of file app_mp3.c.

Definition at line 259 of file app_mp3.c.