#include "asterisk.h"
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <errno.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/frame.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/options.h"
Go to the source code of this file.
Defines | |
#define | ICES "/usr/bin/ices" |
#define | LOCAL_ICES "/usr/local/bin/ices" |
Functions | |
AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Encode and Stream via icecast and ices") | |
static int | ices_exec (struct ast_channel *chan, void *data) |
static int | icesencode (char *filename, int fd) |
static int | load_module (void) |
static int | unload_module (void) |
Variables | |
static char * | app = "ICES" |
static char * | descrip |
static char * | synopsis = "Encode and stream using 'ices'" |
Definition in file app_ices.c.
#define ICES "/usr/bin/ices" |
#define LOCAL_ICES "/usr/local/bin/ices" |
AST_MODULE_INFO_STANDARD | ( | ASTERISK_GPL_KEY | , | |
"Encode and Stream via icecast and ices" | ||||
) |
static int ices_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 102 of file app_ices.c.
References ast_channel::_state, ast_answer(), ast_config_AST_CONFIG_DIR, AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_frfree, ast_log(), ast_module_user_add, ast_module_user_remove, ast_read(), ast_set_read_format(), AST_STATE_UP, ast_stopstream(), ast_strlen_zero(), ast_waitfor(), ast_frame::data, ast_frame::datalen, errno, f, ast_frame::frametype, icesencode(), LOG_DEBUG, LOG_WARNING, and ast_channel::readformat.
Referenced by load_module().
00103 { 00104 int res=0; 00105 struct ast_module_user *u; 00106 int fds[2]; 00107 int ms = -1; 00108 int pid = -1; 00109 int flags; 00110 int oreadformat; 00111 struct timeval last; 00112 struct ast_frame *f; 00113 char filename[256]=""; 00114 char *c; 00115 00116 if (ast_strlen_zero(data)) { 00117 ast_log(LOG_WARNING, "ICES requires an argument (configfile.xml)\n"); 00118 return -1; 00119 } 00120 00121 u = ast_module_user_add(chan); 00122 00123 last = ast_tv(0, 0); 00124 00125 if (pipe(fds)) { 00126 ast_log(LOG_WARNING, "Unable to create pipe\n"); 00127 ast_module_user_remove(u); 00128 return -1; 00129 } 00130 flags = fcntl(fds[1], F_GETFL); 00131 fcntl(fds[1], F_SETFL, flags | O_NONBLOCK); 00132 00133 ast_stopstream(chan); 00134 00135 if (chan->_state != AST_STATE_UP) 00136 res = ast_answer(chan); 00137 00138 if (res) { 00139 close(fds[0]); 00140 close(fds[1]); 00141 ast_log(LOG_WARNING, "Answer failed!\n"); 00142 ast_module_user_remove(u); 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 ast_module_user_remove(u); 00153 return -1; 00154 } 00155 if (((char *)data)[0] == '/') 00156 ast_copy_string(filename, (char *) data, sizeof(filename)); 00157 else 00158 snprintf(filename, sizeof(filename), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, (char *)data); 00159 /* Placeholder for options */ 00160 c = strchr(filename, '|'); 00161 if (c) 00162 *c = '\0'; 00163 res = icesencode(filename, fds[0]); 00164 close(fds[0]); 00165 if (res >= 0) { 00166 pid = res; 00167 for (;;) { 00168 /* Wait for audio, and stream */ 00169 ms = ast_waitfor(chan, -1); 00170 if (ms < 0) { 00171 ast_log(LOG_DEBUG, "Hangup detected\n"); 00172 res = -1; 00173 break; 00174 } 00175 f = ast_read(chan); 00176 if (!f) { 00177 ast_log(LOG_DEBUG, "Null frame == hangup() detected\n"); 00178 res = -1; 00179 break; 00180 } 00181 if (f->frametype == AST_FRAME_VOICE) { 00182 res = write(fds[1], f->data, f->datalen); 00183 if (res < 0) { 00184 if (errno != EAGAIN) { 00185 ast_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno)); 00186 res = -1; 00187 ast_frfree(f); 00188 break; 00189 } 00190 } 00191 } 00192 ast_frfree(f); 00193 } 00194 } 00195 close(fds[1]); 00196 00197 if (pid > -1) 00198 kill(pid, SIGKILL); 00199 if (!res && oreadformat) 00200 ast_set_read_format(chan, oreadformat); 00201 00202 ast_module_user_remove(u); 00203 00204 return res; 00205 }
static int icesencode | ( | char * | filename, | |
int | fd | |||
) | [static] |
Definition at line 64 of file app_ices.c.
References ast_log(), ast_opt_high_priority, ast_set_priority(), ICES, LOCAL_ICES, and LOG_WARNING.
Referenced by ices_exec().
00065 { 00066 int res; 00067 int x; 00068 sigset_t fullset, oldset; 00069 00070 sigfillset(&fullset); 00071 pthread_sigmask(SIG_BLOCK, &fullset, &oldset); 00072 00073 res = fork(); 00074 if (res < 0) 00075 ast_log(LOG_WARNING, "Fork failed\n"); 00076 if (res) { 00077 pthread_sigmask(SIG_SETMASK, &oldset, NULL); 00078 return res; 00079 } 00080 00081 /* Stop ignoring PIPE */ 00082 signal(SIGPIPE, SIG_DFL); 00083 pthread_sigmask(SIG_UNBLOCK, &fullset, NULL); 00084 00085 if (ast_opt_high_priority) 00086 ast_set_priority(0); 00087 dup2(fd, STDIN_FILENO); 00088 for (x=STDERR_FILENO + 1;x<1024;x++) { 00089 if ((x != STDIN_FILENO) && (x != STDOUT_FILENO)) 00090 close(x); 00091 } 00092 /* Most commonly installed in /usr/local/bin */ 00093 execl(ICES, "ices", filename, (char *)NULL); 00094 /* But many places has it in /usr/bin */ 00095 execl(LOCAL_ICES, "ices", filename, (char *)NULL); 00096 /* As a last-ditch effort, try to use PATH */ 00097 execlp("ices", "ices", filename, (char *)NULL); 00098 ast_log(LOG_WARNING, "Execute of ices failed\n"); 00099 _exit(0); 00100 }
static int load_module | ( | void | ) | [static] |
Definition at line 218 of file app_ices.c.
References ast_register_application(), and ices_exec().
00219 { 00220 return ast_register_application(app, ices_exec, synopsis, descrip); 00221 }
static int unload_module | ( | void | ) | [static] |
Definition at line 207 of file app_ices.c.
References ast_module_user_hangup_all, and ast_unregister_application().
00208 { 00209 int res; 00210 00211 res = ast_unregister_application(app); 00212 00213 ast_module_user_hangup_all(); 00214 00215 return res; 00216 }
char* app = "ICES" [static] |
Definition at line 54 of file app_ices.c.
char* descrip [static] |
Initial value:
" ICES(config.xml) Streams to an icecast server using ices\n" "(available separately). A configuration file must be supplied\n" "for ices (see examples/asterisk-ices.conf). \n"
Definition at line 58 of file app_ices.c.
char* synopsis = "Encode and stream using 'ices'" [static] |
Definition at line 56 of file app_ices.c.