00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "asterisk.h"
00031
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 135059 $")
00033
00034 #include <signal.h>
00035 #include <fcntl.h>
00036 #include <sys/time.h>
00037
00038 #include "asterisk/paths.h"
00039 #include "asterisk/lock.h"
00040 #include "asterisk/file.h"
00041 #include "asterisk/channel.h"
00042 #include "asterisk/frame.h"
00043 #include "asterisk/pbx.h"
00044 #include "asterisk/module.h"
00045 #include "asterisk/translate.h"
00046 #include "asterisk/app.h"
00047
00048 #define path_BIN "/usr/bin/"
00049 #define path_LOCAL "/usr/local/bin/"
00050
00051 static char *app = "ICES";
00052
00053 static char *synopsis = "Encode and stream using 'ices'";
00054
00055 static char *descrip =
00056 " ICES(config.xml) Streams to an icecast server using ices\n"
00057 "(available separately). A configuration file must be supplied\n"
00058 "for ices (see contrib/asterisk-ices.xml). \n"
00059 "\n"
00060 "- ICES version 2 cient and server required.\n";
00061
00062
00063 static int icesencode(char *filename, int fd)
00064 {
00065 int res;
00066
00067 res = ast_safe_fork(0);
00068 if (res < 0)
00069 ast_log(LOG_WARNING, "Fork failed\n");
00070 if (res) {
00071 return res;
00072 }
00073
00074 if (ast_opt_high_priority)
00075 ast_set_priority(0);
00076 dup2(fd, STDIN_FILENO);
00077 ast_close_fds_above_n(STDERR_FILENO);
00078
00079
00080
00081
00082
00083 execl(path_LOCAL "ices2", "ices", filename, SENTINEL);
00084 execl(path_BIN "ices2", "ices", filename, SENTINEL);
00085 execlp("ices2", "ices", filename, SENTINEL);
00086
00087 ast_debug(1, "Couldn't find ices version 2, attempting to use ices version 1.");
00088
00089 execl(path_LOCAL "ices", "ices", filename, SENTINEL);
00090 execl(path_BIN "ices", "ices", filename, SENTINEL);
00091 execlp("ices", "ices", filename, SENTINEL);
00092
00093 ast_log(LOG_WARNING, "Execute of ices failed, could not find command.\n");
00094 close(fd);
00095 _exit(0);
00096 }
00097
00098 static int ices_exec(struct ast_channel *chan, void *data)
00099 {
00100 int res = 0;
00101 int fds[2];
00102 int ms = -1;
00103 int pid = -1;
00104 int flags;
00105 int oreadformat;
00106 struct timeval last;
00107 struct ast_frame *f;
00108 char filename[256]="";
00109 char *c;
00110
00111 if (ast_strlen_zero(data)) {
00112 ast_log(LOG_WARNING, "ICES requires an argument (configfile.xml)\n");
00113 return -1;
00114 }
00115
00116 last = ast_tv(0, 0);
00117
00118 if (pipe(fds)) {
00119 ast_log(LOG_WARNING, "Unable to create pipe\n");
00120 return -1;
00121 }
00122 flags = fcntl(fds[1], F_GETFL);
00123 fcntl(fds[1], F_SETFL, flags | O_NONBLOCK);
00124
00125 ast_stopstream(chan);
00126
00127 if (chan->_state != AST_STATE_UP)
00128 res = ast_answer(chan);
00129
00130 if (res) {
00131 close(fds[0]);
00132 close(fds[1]);
00133 ast_log(LOG_WARNING, "Answer failed!\n");
00134 return -1;
00135 }
00136
00137 oreadformat = chan->readformat;
00138 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
00139 if (res < 0) {
00140 close(fds[0]);
00141 close(fds[1]);
00142 ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
00143 return -1;
00144 }
00145 if (((char *)data)[0] == '/')
00146 ast_copy_string(filename, (char *) data, sizeof(filename));
00147 else
00148 snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_CONFIG_DIR, (char *)data);
00149
00150 c = strchr(filename, '|');
00151 if (c)
00152 *c = '\0';
00153 res = icesencode(filename, fds[0]);
00154 if (res >= 0) {
00155 pid = res;
00156 for (;;) {
00157
00158 ms = ast_waitfor(chan, -1);
00159 if (ms < 0) {
00160 ast_debug(1, "Hangup detected\n");
00161 res = -1;
00162 break;
00163 }
00164 f = ast_read(chan);
00165 if (!f) {
00166 ast_debug(1, "Null frame == hangup() detected\n");
00167 res = -1;
00168 break;
00169 }
00170 if (f->frametype == AST_FRAME_VOICE) {
00171 res = write(fds[1], f->data.ptr, f->datalen);
00172 if (res < 0) {
00173 if (errno != EAGAIN) {
00174 ast_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno));
00175 res = -1;
00176 ast_frfree(f);
00177 break;
00178 }
00179 }
00180 }
00181 ast_frfree(f);
00182 }
00183 }
00184 close(fds[0]);
00185 close(fds[1]);
00186
00187 if (pid > -1)
00188 kill(pid, SIGKILL);
00189 if (!res && oreadformat)
00190 ast_set_read_format(chan, oreadformat);
00191
00192 return res;
00193 }
00194
00195 static int unload_module(void)
00196 {
00197 return ast_unregister_application(app);
00198 }
00199
00200 static int load_module(void)
00201 {
00202 return ast_register_application(app, ices_exec, synopsis, descrip);
00203 }
00204
00205 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Encode and Stream via icecast and ices");