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: 196072 $")
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
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 #define path_BIN "/usr/bin/"
00068 #define path_LOCAL "/usr/local/bin/"
00069
00070 static char *app = "ICES";
00071
00072 static int icesencode(char *filename, int fd)
00073 {
00074 int res;
00075
00076 res = ast_safe_fork(0);
00077 if (res < 0)
00078 ast_log(LOG_WARNING, "Fork failed\n");
00079 if (res) {
00080 return res;
00081 }
00082
00083 if (ast_opt_high_priority)
00084 ast_set_priority(0);
00085 dup2(fd, STDIN_FILENO);
00086 ast_close_fds_above_n(STDERR_FILENO);
00087
00088
00089
00090
00091
00092 execl(path_LOCAL "ices2", "ices", filename, SENTINEL);
00093 execl(path_BIN "ices2", "ices", filename, SENTINEL);
00094 execlp("ices2", "ices", filename, SENTINEL);
00095
00096 ast_debug(1, "Couldn't find ices version 2, attempting to use ices version 1.");
00097
00098 execl(path_LOCAL "ices", "ices", filename, SENTINEL);
00099 execl(path_BIN "ices", "ices", filename, SENTINEL);
00100 execlp("ices", "ices", filename, SENTINEL);
00101
00102 ast_log(LOG_WARNING, "Execute of ices failed, could not find command.\n");
00103 close(fd);
00104 _exit(0);
00105 }
00106
00107 static int ices_exec(struct ast_channel *chan, const char *data)
00108 {
00109 int res = 0;
00110 int fds[2];
00111 int ms = -1;
00112 int pid = -1;
00113 int flags;
00114 int oreadformat;
00115 struct timeval last;
00116 struct ast_frame *f;
00117 char filename[256]="";
00118 char *c;
00119
00120 if (ast_strlen_zero(data)) {
00121 ast_log(LOG_WARNING, "ICES requires an argument (configfile.xml)\n");
00122 return -1;
00123 }
00124
00125 last = ast_tv(0, 0);
00126
00127 if (pipe(fds)) {
00128 ast_log(LOG_WARNING, "Unable to create pipe\n");
00129 return -1;
00130 }
00131 flags = fcntl(fds[1], F_GETFL);
00132 fcntl(fds[1], F_SETFL, flags | O_NONBLOCK);
00133
00134 ast_stopstream(chan);
00135
00136 if (chan->_state != AST_STATE_UP)
00137 res = ast_answer(chan);
00138
00139 if (res) {
00140 close(fds[0]);
00141 close(fds[1]);
00142 ast_log(LOG_WARNING, "Answer failed!\n");
00143 return -1;
00144 }
00145
00146 oreadformat = chan->readformat;
00147 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
00148 if (res < 0) {
00149 close(fds[0]);
00150 close(fds[1]);
00151 ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
00152 return -1;
00153 }
00154 if (((char *)data)[0] == '/')
00155 ast_copy_string(filename, (char *) data, sizeof(filename));
00156 else
00157 snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_CONFIG_DIR, (char *)data);
00158
00159 c = strchr(filename, '|');
00160 if (c)
00161 *c = '\0';
00162 res = icesencode(filename, fds[0]);
00163 if (res >= 0) {
00164 pid = res;
00165 for (;;) {
00166
00167 ms = ast_waitfor(chan, -1);
00168 if (ms < 0) {
00169 ast_debug(1, "Hangup detected\n");
00170 res = -1;
00171 break;
00172 }
00173 f = ast_read(chan);
00174 if (!f) {
00175 ast_debug(1, "Null frame == hangup() detected\n");
00176 res = -1;
00177 break;
00178 }
00179 if (f->frametype == AST_FRAME_VOICE) {
00180 res = write(fds[1], f->data.ptr, f->datalen);
00181 if (res < 0) {
00182 if (errno != EAGAIN) {
00183 ast_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno));
00184 res = -1;
00185 ast_frfree(f);
00186 break;
00187 }
00188 }
00189 }
00190 ast_frfree(f);
00191 }
00192 }
00193 close(fds[0]);
00194 close(fds[1]);
00195
00196 if (pid > -1)
00197 kill(pid, SIGKILL);
00198 if (!res && oreadformat)
00199 ast_set_read_format(chan, oreadformat);
00200
00201 return res;
00202 }
00203
00204 static int unload_module(void)
00205 {
00206 return ast_unregister_application(app);
00207 }
00208
00209 static int load_module(void)
00210 {
00211 return ast_register_application_xml(app, ices_exec);
00212 }
00213
00214 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Encode and Stream via icecast and ices");