38 #include <sys/types.h>
51 #define LOCAL_MPG_123 "/usr/local/bin/mpg123"
52 #define MPG_123 "/usr/bin/mpg123"
80 static char *app =
"MP3Player";
82 static int mp3play(
const char *filename,
unsigned int sampling_rate,
int fd)
85 char sampling_rate_str[8];
89 ast_log(LOG_WARNING,
"Fork failed\n");
93 if (ast_opt_high_priority)
96 dup2(fd, STDOUT_FILENO);
99 snprintf(sampling_rate_str, 8,
"%u", sampling_rate);
102 if (!strncasecmp(filename,
"http://", 7) && strstr(filename,
".m3u")) {
103 char buffer_size_str[8];
104 snprintf(buffer_size_str, 8,
"%u", (
int) 0.5*2*sampling_rate/1000);
106 execl(LOCAL_MPG_123,
"mpg123",
"-e",
"s16",
"-q",
"-s",
"-b", buffer_size_str,
"-f",
"8192",
"--mono",
"-r", sampling_rate_str,
"-@", filename, (
char *)NULL);
108 execl(MPG_123,
"mpg123",
"-e",
"s16",
"-q",
"-s",
"-b", buffer_size_str,
"-f",
"8192",
"--mono",
"-r", sampling_rate_str,
"-@", filename, (
char *)NULL);
110 execlp(
"mpg123",
"mpg123",
"-e",
"s16",
"-q",
"-s",
"-b", buffer_size_str,
"-f",
"8192",
"--mono",
"-r", sampling_rate_str,
"-@", filename, (
char *)NULL);
112 else if (!strncasecmp(filename,
"http://", 7)) {
113 char buffer_size_str[8];
114 snprintf(buffer_size_str, 8,
"%u", 6*2*sampling_rate/1000);
116 execl(LOCAL_MPG_123,
"mpg123",
"-e",
"s16",
"-q",
"-s",
"-b", buffer_size_str,
"-f",
"8192",
"--mono",
"-r", sampling_rate_str, filename, (
char *)NULL);
118 execl(MPG_123,
"mpg123",
"-e",
"s16",
"-q",
"-s",
"-b", buffer_size_str,
"-f",
"8192",
"--mono",
"-r", sampling_rate_str, filename, (
char *)NULL);
120 execlp(
"mpg123",
"mpg123",
"-e",
"s16",
"-q",
"-s",
"-b", buffer_size_str,
"-f",
"8192",
"--mono",
"-r", sampling_rate_str, filename, (
char *)NULL);
122 else if (strstr(filename,
".m3u")) {
124 execl(LOCAL_MPG_123,
"mpg123",
"-e",
"s16",
"-q",
"-z",
"-s",
"-f",
"8192",
"--mono",
"-r", sampling_rate_str,
"-@", filename, (
char *)NULL);
126 execl(MPG_123,
"mpg123",
"-e",
"s16",
"-q",
"-z",
"-s",
"-f",
"8192",
"--mono",
"-r", sampling_rate_str,
"-@", filename, (
char *)NULL);
128 execlp(
"mpg123",
"mpg123",
"-e",
"s16",
"-q",
"-z",
"-s",
"-f",
"8192",
"--mono",
"-r", sampling_rate_str,
"-@", filename, (
char *)NULL);
132 execl(MPG_123,
"mpg123",
"-e",
"s16",
"-q",
"-s",
"-f",
"8192",
"--mono",
"-r", sampling_rate_str, filename, (
char *)NULL);
134 execl(LOCAL_MPG_123,
"mpg123",
"-e",
"s16",
"-q",
"-s",
"-f",
"8192",
"--mono",
"-r", sampling_rate_str, filename, (
char *)NULL);
136 execlp(
"mpg123",
"mpg123",
"-e",
"s16",
"-q",
"-s",
"-f",
"8192",
"--mono",
"-r", sampling_rate_str, filename, (
char *)NULL);
139 fprintf(stderr,
"Execute of mpg123 failed\n");
143 static int timed_read(
int fd,
void *data,
int datalen,
int timeout,
int pid)
147 struct pollfd fds[1];
149 fds[0].events = POLLIN;
150 for (i = 0; i < timeout; i++) {
151 res = ast_poll(fds, 1, 1000);
154 }
else if (res == 0) {
157 if (errno == ESRCH) {
161 ast_log(LOG_NOTICE,
"error polling mpg123: %s\n", strerror(errno));
167 ast_log(LOG_NOTICE,
"Poll timed out.\n");
171 return read(fd, data, datalen);
175 static int mp3_exec(
struct ast_channel *chan,
const char *data)
194 unsigned int sampling_rate;
197 if (ast_strlen_zero(data)) {
198 ast_log(LOG_WARNING,
"MP3 Playback requires an argument (filename)\n");
203 ast_log(LOG_WARNING,
"Unable to create pipe\n");
213 owriteformat =
ao2_bump(ast_channel_writeformat(chan));
216 ast_log(LOG_WARNING,
"Unable to set write format to signed linear\n");
221 myf.f.subclass.format = write_format;
224 myf.f.src = __PRETTY_FUNCTION__;
225 myf.f.delivery.tv_sec = 0;
226 myf.f.delivery.tv_usec = 0;
227 myf.f.data.ptr = myf.frdata;
229 res = mp3play(data, sampling_rate, fds[1]);
230 if (!strncasecmp(data,
"http://", 7)) {
243 res = timed_read(fds[0], myf.frdata,
sizeof(myf.frdata), timeout, pid);
246 myf.f.samples = res / 2;
255 if (!strncasecmp(data,
"https://", 8)) {
256 ast_log(LOG_WARNING,
"%s() does not support HTTPS streams. Use HTTP instead.\n", app);
258 ast_log(LOG_WARNING,
"MP3 stream '%s' is broken or nonexistent\n", data);
274 ast_debug(1,
"Null frame == hangup() detected\n");
294 if (!res && owriteformat)
302 static int unload_module(
void)
307 static int load_module(
void)
312 AST_MODULE_INFO_STANDARD_EXTENDED(
ASTERISK_GPL_KEY,
"Silly MP3 Application");
Main Channel structure associated with a channel.
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
Support for translation of data formats. translate.c.
void ast_close_fds_above_n(int n)
Common routine for child processes, to close all fds prior to exec(2)
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
int ast_unregister_application(const char *app)
Unregister an application.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
General Asterisk PBX channel definitions.
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
Asterisk internal frame definitions.
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 ...
#define ast_debug(level,...)
Log a DEBUG message.
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
Core PBX routines and definitions.
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...
int ast_safe_fork(int stop_reaper)
Common routine to safely fork without a chance of a signal handler firing badly in the child...
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
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.
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Data structure associated with a single frame of data.
enum ast_frame_type frametype
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
int ast_stopstream(struct ast_channel *c)
Stops a stream.
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.