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 path_BIN "/usr/bin/"
52 #define path_LOCAL "/usr/local/bin/"
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 contrib/asterisk-ices.xml). \n";
63 static int icesencode(char *filename
, int fd
)
67 sigset_t fullset
, oldset
;
70 pthread_sigmask(SIG_BLOCK
, &fullset
, &oldset
);
74 ast_log(LOG_WARNING
, "Fork failed\n");
76 pthread_sigmask(SIG_SETMASK
, &oldset
, NULL
);
80 /* Stop ignoring PIPE */
81 signal(SIGPIPE
, SIG_DFL
);
82 pthread_sigmask(SIG_UNBLOCK
, &fullset
, NULL
);
84 if (ast_opt_high_priority
)
86 dup2(fd
, STDIN_FILENO
);
87 for (x
=STDERR_FILENO
+ 1;x
<1024;x
++) {
88 if ((x
!= STDIN_FILENO
) && (x
!= STDOUT_FILENO
))
92 /* Most commonly installed in /usr/local/bin
93 * But many places has it in /usr/bin
94 * As a last-ditch effort, try to use PATH
96 execl(path_LOCAL
"ices2", "ices", filename
, (char *)NULL
);
97 execl(path_BIN
"ices2", "ices", filename
, (char *)NULL
);
98 execlp("ices2", "ices", filename
, (char *)NULL
);
101 ast_log(LOG_DEBUG
, "Couldn't find ices version 2, attempting to use ices version 1.");
103 execl(path_LOCAL
"ices", "ices", filename
, (char *)NULL
);
104 execl(path_BIN
"ices", "ices", filename
, (char *)NULL
);
105 execlp("ices", "ices", filename
, (char *)NULL
);
107 ast_log(LOG_WARNING
, "Execute of ices failed, could not be found.\n");
112 static int ices_exec(struct ast_channel
*chan
, void *data
)
115 struct ast_module_user
*u
;
123 char filename
[256]="";
126 if (ast_strlen_zero(data
)) {
127 ast_log(LOG_WARNING
, "ICES requires an argument (configfile.xml)\n");
131 u
= ast_module_user_add(chan
);
136 ast_log(LOG_WARNING
, "Unable to create pipe\n");
137 ast_module_user_remove(u
);
140 flags
= fcntl(fds
[1], F_GETFL
);
141 fcntl(fds
[1], F_SETFL
, flags
| O_NONBLOCK
);
143 ast_stopstream(chan
);
145 if (chan
->_state
!= AST_STATE_UP
)
146 res
= ast_answer(chan
);
151 ast_log(LOG_WARNING
, "Answer failed!\n");
152 ast_module_user_remove(u
);
156 oreadformat
= chan
->readformat
;
157 res
= ast_set_read_format(chan
, AST_FORMAT_SLINEAR
);
161 ast_log(LOG_WARNING
, "Unable to set write format to signed linear\n");
162 ast_module_user_remove(u
);
165 if (((char *)data
)[0] == '/')
166 ast_copy_string(filename
, (char *) data
, sizeof(filename
));
168 snprintf(filename
, sizeof(filename
), "%s/%s", (char *)ast_config_AST_CONFIG_DIR
, (char *)data
);
169 /* Placeholder for options */
170 c
= strchr(filename
, '|');
173 res
= icesencode(filename
, fds
[0]);
177 /* Wait for audio, and stream */
178 ms
= ast_waitfor(chan
, -1);
180 ast_log(LOG_DEBUG
, "Hangup detected\n");
186 ast_log(LOG_DEBUG
, "Null frame == hangup() detected\n");
190 if (f
->frametype
== AST_FRAME_VOICE
) {
191 res
= write(fds
[1], f
->data
, f
->datalen
);
193 if (errno
!= EAGAIN
) {
194 ast_log(LOG_WARNING
, "Write failed to pipe: %s\n", strerror(errno
));
209 if (!res
&& oreadformat
)
210 ast_set_read_format(chan
, oreadformat
);
212 ast_module_user_remove(u
);
217 static int unload_module(void)
221 res
= ast_unregister_application(app
);
223 ast_module_user_hangup_all();
228 static int load_module(void)
230 return ast_register_application(app
, ices_exec
, synopsis
, descrip
);
233 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY
, "Encode and Stream via icecast and ices");