Add a function, CHANNELS(), which retrieves a list of all active channels.
[asterisk-bristuff.git] / apps / app_ices.c
blob7a4c9f18fce17529dd95cf928ccff1527f83711f
1 /*
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.
19 /*! \file
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
30 #include "asterisk.h"
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
34 #include <signal.h>
35 #include <fcntl.h>
36 #include <sys/time.h>
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)
63 int res;
65 res = ast_safe_fork(0);
66 if (res < 0)
67 ast_log(LOG_WARNING, "Fork failed\n");
68 if (res) {
69 return res;
72 if (ast_opt_high_priority)
73 ast_set_priority(0);
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");
83 _exit(0);
86 static int ices_exec(struct ast_channel *chan, void *data)
88 int res = 0;
89 int fds[2];
90 int ms = -1;
91 int pid = -1;
92 int flags;
93 int oreadformat;
94 struct timeval last;
95 struct ast_frame *f;
96 char filename[256]="";
97 char *c;
99 if (ast_strlen_zero(data)) {
100 ast_log(LOG_WARNING, "ICES requires an argument (configfile.xml)\n");
101 return -1;
104 last = ast_tv(0, 0);
106 if (pipe(fds)) {
107 ast_log(LOG_WARNING, "Unable to create pipe\n");
108 return -1;
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);
118 if (res) {
119 close(fds[0]);
120 close(fds[1]);
121 ast_log(LOG_WARNING, "Answer failed!\n");
122 return -1;
125 oreadformat = chan->readformat;
126 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
127 if (res < 0) {
128 close(fds[0]);
129 close(fds[1]);
130 ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
131 return -1;
133 if (((char *)data)[0] == '/')
134 ast_copy_string(filename, (char *) data, sizeof(filename));
135 else
136 snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_CONFIG_DIR, (char *)data);
137 /* Placeholder for options */
138 c = strchr(filename, '|');
139 if (c)
140 *c = '\0';
141 res = icesencode(filename, fds[0]);
142 close(fds[0]);
143 if (res >= 0) {
144 pid = res;
145 for (;;) {
146 /* Wait for audio, and stream */
147 ms = ast_waitfor(chan, -1);
148 if (ms < 0) {
149 ast_debug(1, "Hangup detected\n");
150 res = -1;
151 break;
153 f = ast_read(chan);
154 if (!f) {
155 ast_debug(1, "Null frame == hangup() detected\n");
156 res = -1;
157 break;
159 if (f->frametype == AST_FRAME_VOICE) {
160 res = write(fds[1], f->data.ptr, f->datalen);
161 if (res < 0) {
162 if (errno != EAGAIN) {
163 ast_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno));
164 res = -1;
165 ast_frfree(f);
166 break;
170 ast_frfree(f);
173 close(fds[1]);
175 if (pid > -1)
176 kill(pid, SIGKILL);
177 if (!res && oreadformat)
178 ast_set_read_format(chan, oreadformat);
180 return res;
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");