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 * \ingroup applications
30 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
41 #include "asterisk/lock.h"
42 #include "asterisk/file.h"
43 #include "asterisk/logger.h"
44 #include "asterisk/channel.h"
45 #include "asterisk/frame.h"
46 #include "asterisk/pbx.h"
47 #include "asterisk/module.h"
48 #include "asterisk/translate.h"
49 #include "asterisk/options.h"
51 #define ICES "/usr/bin/ices"
52 #define LOCAL_ICES "/usr/local/bin/ices"
54 static char *app
= "ICES";
56 static char *synopsis
= "Encode and stream using 'ices'";
58 static char *descrip
=
59 " ICES(config.xml) Streams to an icecast server using ices\n"
60 "(available separately). A configuration file must be supplied\n"
61 "for ices (see examples/asterisk-ices.conf). \n";
64 static int icesencode(char *filename
, int fd
)
70 ast_log(LOG_WARNING
, "Fork failed\n");
73 if (ast_opt_high_priority
)
75 dup2(fd
, STDIN_FILENO
);
76 for (x
=STDERR_FILENO
+ 1;x
<256;x
++) {
77 if ((x
!= STDIN_FILENO
) && (x
!= STDOUT_FILENO
))
80 /* Most commonly installed in /usr/local/bin */
81 execl(ICES
, "ices", filename
, (char *)NULL
);
82 /* But many places has it in /usr/bin */
83 execl(LOCAL_ICES
, "ices", filename
, (char *)NULL
);
84 /* As a last-ditch effort, try to use PATH */
85 execlp("ices", "ices", filename
, (char *)NULL
);
86 ast_log(LOG_WARNING
, "Execute of ices failed\n");
90 static int ices_exec(struct ast_channel
*chan
, void *data
)
93 struct ast_module_user
*u
;
101 char filename
[256]="";
104 if (ast_strlen_zero(data
)) {
105 ast_log(LOG_WARNING
, "ICES requires an argument (configfile.xml)\n");
109 u
= ast_module_user_add(chan
);
114 ast_log(LOG_WARNING
, "Unable to create pipe\n");
115 ast_module_user_remove(u
);
118 flags
= fcntl(fds
[1], F_GETFL
);
119 fcntl(fds
[1], F_SETFL
, flags
| O_NONBLOCK
);
121 ast_stopstream(chan
);
123 if (chan
->_state
!= AST_STATE_UP
)
124 res
= ast_answer(chan
);
129 ast_log(LOG_WARNING
, "Answer failed!\n");
130 ast_module_user_remove(u
);
134 oreadformat
= chan
->readformat
;
135 res
= ast_set_read_format(chan
, AST_FORMAT_SLINEAR
);
139 ast_log(LOG_WARNING
, "Unable to set write format to signed linear\n");
140 ast_module_user_remove(u
);
143 if (((char *)data
)[0] == '/')
144 ast_copy_string(filename
, (char *) data
, sizeof(filename
));
146 snprintf(filename
, sizeof(filename
), "%s/%s", (char *)ast_config_AST_CONFIG_DIR
, (char *)data
);
147 /* Placeholder for options */
148 c
= strchr(filename
, '|');
151 res
= icesencode(filename
, fds
[0]);
156 /* Wait for audio, and stream */
157 ms
= ast_waitfor(chan
, -1);
159 ast_log(LOG_DEBUG
, "Hangup detected\n");
165 ast_log(LOG_DEBUG
, "Null frame == hangup() detected\n");
169 if (f
->frametype
== AST_FRAME_VOICE
) {
170 res
= write(fds
[1], f
->data
, f
->datalen
);
172 if (errno
!= EAGAIN
) {
173 ast_log(LOG_WARNING
, "Write failed to pipe: %s\n", strerror(errno
));
187 if (!res
&& oreadformat
)
188 ast_set_read_format(chan
, oreadformat
);
190 ast_module_user_remove(u
);
195 static int unload_module(void)
199 res
= ast_unregister_application(app
);
201 ast_module_user_hangup_all();
206 static int load_module(void)
208 return ast_register_application(app
, ices_exec
, synopsis
, descrip
);
211 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY
, "Encode and Stream via icecast and ices");