2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief Stream to an icecast server via ICES (see contrib/asterisk-ices.xml)
23 * \author Mark Spencer <markster@digium.com>
25 * \extref ICES - http://www.icecast.org/ices.php
27 * \ingroup applications
32 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
38 #include "asterisk/paths.h" /* use ast_config_AST_CONFIG_DIR */
39 #include "asterisk/lock.h"
40 #include "asterisk/file.h"
41 #include "asterisk/channel.h"
42 #include "asterisk/frame.h"
43 #include "asterisk/pbx.h"
44 #include "asterisk/module.h"
45 #include "asterisk/translate.h"
46 #include "asterisk/app.h"
48 #define ICES "/usr/bin/ices"
49 #define LOCAL_ICES "/usr/local/bin/ices"
51 static char *app
= "ICES";
53 static char *synopsis
= "Encode and stream using 'ices'";
55 static char *descrip
=
56 " ICES(config.xml) Streams to an icecast server using ices\n"
57 "(available separately). A configuration file must be supplied\n"
58 "for ices (see examples/asterisk-ices.conf). \n";
61 static int icesencode(char *filename
, int fd
)
65 res
= ast_safe_fork(0);
67 ast_log(LOG_WARNING
, "Fork failed\n");
72 if (ast_opt_high_priority
)
74 dup2(fd
, STDIN_FILENO
);
75 ast_close_fds_above_n(STDERR_FILENO
);
76 /* Most commonly installed in /usr/local/bin */
77 execl(ICES
, "ices", filename
, (char *)NULL
);
78 /* But many places has it in /usr/bin */
79 execl(LOCAL_ICES
, "ices", filename
, (char *)NULL
);
80 /* As a last-ditch effort, try to use PATH */
81 execlp("ices", "ices", filename
, (char *)NULL
);
82 ast_log(LOG_WARNING
, "Execute of ices failed\n");
86 static int ices_exec(struct ast_channel
*chan
, void *data
)
96 char filename
[256]="";
99 if (ast_strlen_zero(data
)) {
100 ast_log(LOG_WARNING
, "ICES requires an argument (configfile.xml)\n");
107 ast_log(LOG_WARNING
, "Unable to create pipe\n");
110 flags
= fcntl(fds
[1], F_GETFL
);
111 fcntl(fds
[1], F_SETFL
, flags
| O_NONBLOCK
);
113 ast_stopstream(chan
);
115 if (chan
->_state
!= AST_STATE_UP
)
116 res
= ast_answer(chan
);
121 ast_log(LOG_WARNING
, "Answer failed!\n");
125 oreadformat
= chan
->readformat
;
126 res
= ast_set_read_format(chan
, AST_FORMAT_SLINEAR
);
130 ast_log(LOG_WARNING
, "Unable to set write format to signed linear\n");
133 if (((char *)data
)[0] == '/')
134 ast_copy_string(filename
, (char *) data
, sizeof(filename
));
136 snprintf(filename
, sizeof(filename
), "%s/%s", ast_config_AST_CONFIG_DIR
, (char *)data
);
137 /* Placeholder for options */
138 c
= strchr(filename
, '|');
141 res
= icesencode(filename
, fds
[0]);
146 /* Wait for audio, and stream */
147 ms
= ast_waitfor(chan
, -1);
149 ast_debug(1, "Hangup detected\n");
155 ast_debug(1, "Null frame == hangup() detected\n");
159 if (f
->frametype
== AST_FRAME_VOICE
) {
160 res
= write(fds
[1], f
->data
.ptr
, f
->datalen
);
162 if (errno
!= EAGAIN
) {
163 ast_log(LOG_WARNING
, "Write failed to pipe: %s\n", strerror(errno
));
177 if (!res
&& oreadformat
)
178 ast_set_read_format(chan
, oreadformat
);
183 static int unload_module(void)
185 return ast_unregister_application(app
);
188 static int load_module(void)
190 return ast_register_application(app
, ices_exec
, synopsis
, descrip
);
193 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY
, "Encode and Stream via icecast and ices");