#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 | path_BIN "/usr/bin/" |
#define | path_LOCAL "/usr/local/bin/" |
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 path_BIN "/usr/bin/" |
#define path_LOCAL "/usr/local/bin/" |
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 112 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(), errno, f, icesencode(), LOG_DEBUG, LOG_WARNING, and ast_channel::readformat.
Referenced by load_module().
00113 { 00114 int res=0; 00115 struct ast_module_user *u; 00116 int fds[2]; 00117 int ms = -1; 00118 int pid = -1; 00119 int flags; 00120 int oreadformat; 00121 struct timeval last; 00122 struct ast_frame *f; 00123 char filename[256]=""; 00124 char *c; 00125 00126 if (ast_strlen_zero(data)) { 00127 ast_log(LOG_WARNING, "ICES requires an argument (configfile.xml)\n"); 00128 return -1; 00129 } 00130 00131 u = ast_module_user_add(chan); 00132 00133 last = ast_tv(0, 0); 00134 00135 if (pipe(fds)) { 00136 ast_log(LOG_WARNING, "Unable to create pipe\n"); 00137 ast_module_user_remove(u); 00138 return -1; 00139 } 00140 flags = fcntl(fds[1], F_GETFL); 00141 fcntl(fds[1], F_SETFL, flags | O_NONBLOCK); 00142 00143 ast_stopstream(chan); 00144 00145 if (chan->_state != AST_STATE_UP) 00146 res = ast_answer(chan); 00147 00148 if (res) { 00149 close(fds[0]); 00150 close(fds[1]); 00151 ast_log(LOG_WARNING, "Answer failed!\n"); 00152 ast_module_user_remove(u); 00153 return -1; 00154 } 00155 00156 oreadformat = chan->readformat; 00157 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); 00158 if (res < 0) { 00159 close(fds[0]); 00160 close(fds[1]); 00161 ast_log(LOG_WARNING, "Unable to set write format to signed linear\n"); 00162 ast_module_user_remove(u); 00163 return -1; 00164 } 00165 if (((char *)data)[0] == '/') 00166 ast_copy_string(filename, (char *) data, sizeof(filename)); 00167 else 00168 snprintf(filename, sizeof(filename), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, (char *)data); 00169 /* Placeholder for options */ 00170 c = strchr(filename, '|'); 00171 if (c) 00172 *c = '\0'; 00173 res = icesencode(filename, fds[0]); 00174 if (res >= 0) { 00175 pid = res; 00176 for (;;) { 00177 /* Wait for audio, and stream */ 00178 ms = ast_waitfor(chan, -1); 00179 if (ms < 0) { 00180 ast_log(LOG_DEBUG, "Hangup detected\n"); 00181 res = -1; 00182 break; 00183 } 00184 f = ast_read(chan); 00185 if (!f) { 00186 ast_log(LOG_DEBUG, "Null frame == hangup() detected\n"); 00187 res = -1; 00188 break; 00189 } 00190 if (f->frametype == AST_FRAME_VOICE) { 00191 res = write(fds[1], f->data, f->datalen); 00192 if (res < 0) { 00193 if (errno != EAGAIN) { 00194 ast_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno)); 00195 res = -1; 00196 ast_frfree(f); 00197 break; 00198 } 00199 } 00200 } 00201 ast_frfree(f); 00202 } 00203 } 00204 close(fds[0]); 00205 close(fds[1]); 00206 00207 if (pid > -1) 00208 kill(pid, SIGKILL); 00209 if (!res && oreadformat) 00210 ast_set_read_format(chan, oreadformat); 00211 00212 ast_module_user_remove(u); 00213 00214 return res; 00215 }
static int icesencode | ( | char * | filename, | |
int | fd | |||
) | [static] |
Definition at line 63 of file app_ices.c.
References ast_log(), ast_opt_high_priority, ast_set_priority(), LOG_DEBUG, LOG_WARNING, option_debug, path_BIN, and path_LOCAL.
Referenced by ices_exec().
00064 { 00065 int res; 00066 int x; 00067 sigset_t fullset, oldset; 00068 00069 sigfillset(&fullset); 00070 pthread_sigmask(SIG_BLOCK, &fullset, &oldset); 00071 00072 res = fork(); 00073 if (res < 0) 00074 ast_log(LOG_WARNING, "Fork failed\n"); 00075 if (res) { 00076 pthread_sigmask(SIG_SETMASK, &oldset, NULL); 00077 return res; 00078 } 00079 00080 /* Stop ignoring PIPE */ 00081 signal(SIGPIPE, SIG_DFL); 00082 pthread_sigmask(SIG_UNBLOCK, &fullset, NULL); 00083 00084 if (ast_opt_high_priority) 00085 ast_set_priority(0); 00086 dup2(fd, STDIN_FILENO); 00087 for (x=STDERR_FILENO + 1;x<1024;x++) { 00088 if ((x != STDIN_FILENO) && (x != STDOUT_FILENO)) 00089 close(x); 00090 } 00091 00092 /* Most commonly installed in /usr/local/bin 00093 * But many places has it in /usr/bin 00094 * As a last-ditch effort, try to use PATH 00095 */ 00096 execl(path_LOCAL "ices2", "ices", filename, (char *)NULL); 00097 execl(path_BIN "ices2", "ices", filename, (char *)NULL); 00098 execlp("ices2", "ices", filename, (char *)NULL); 00099 00100 if (option_debug) 00101 ast_log(LOG_DEBUG, "Couldn't find ices version 2, attempting to use ices version 1."); 00102 00103 execl(path_LOCAL "ices", "ices", filename, (char *)NULL); 00104 execl(path_BIN "ices", "ices", filename, (char *)NULL); 00105 execlp("ices", "ices", filename, (char *)NULL); 00106 00107 ast_log(LOG_WARNING, "Execute of ices failed, could not be found.\n"); 00108 close(fd); 00109 _exit(0); 00110 }
static int load_module | ( | void | ) | [static] |
Definition at line 228 of file app_ices.c.
References ast_register_application(), and ices_exec().
00229 { 00230 return ast_register_application(app, ices_exec, synopsis, descrip); 00231 }
static int unload_module | ( | void | ) | [static] |
Definition at line 217 of file app_ices.c.
References ast_module_user_hangup_all, and ast_unregister_application().
00218 { 00219 int res; 00220 00221 res = ast_unregister_application(app); 00222 00223 ast_module_user_hangup_all(); 00224 00225 return res; 00226 }
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 contrib/asterisk-ices.xml). \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.