#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 <sys/socket.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 | AF_LOCAL AF_UNIX |
#define | LOCAL_NBSCAT "/usr/local/bin/nbscat8k" |
#define | NBSCAT "/usr/bin/nbscat8k" |
Functions | |
AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Silly NBS Stream Application") | |
static int | load_module (void) |
static int | NBScat_exec (struct ast_channel *chan, void *data) |
static int | NBScatplay (int fd) |
static int | timed_read (int fd, void *data, int datalen) |
static int | unload_module (void) |
Variables | |
static char * | app = "NBScat" |
static char * | descrip |
static char * | synopsis = "Play an NBS local stream" |
Definition in file app_nbscat.c.
#define AF_LOCAL AF_UNIX |
Definition at line 55 of file app_nbscat.c.
#define LOCAL_NBSCAT "/usr/local/bin/nbscat8k" |
#define NBSCAT "/usr/bin/nbscat8k" |
AST_MODULE_INFO_STANDARD | ( | ASTERISK_GPL_KEY | , | |
"Silly NBS Stream Application" | ||||
) |
static int load_module | ( | void | ) | [static] |
Definition at line 232 of file app_nbscat.c.
References ast_register_application(), and NBScat_exec().
00233 { 00234 return ast_register_application(app, NBScat_exec, synopsis, descrip); 00235 }
static int NBScat_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 116 of file app_nbscat.c.
References AF_LOCAL, AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, ast_log(), ast_module_user_add, ast_module_user_remove, ast_read(), ast_set_write_format(), ast_stopstream(), ast_tvadd(), ast_waitfor(), ast_write(), f, LOG_DEBUG, LOG_WARNING, NBScatplay(), offset, timed_read(), and ast_channel::writeformat.
Referenced by load_module().
00117 { 00118 int res=0; 00119 struct ast_module_user *u; 00120 int fds[2]; 00121 int ms = -1; 00122 int pid = -1; 00123 int owriteformat; 00124 struct timeval next; 00125 struct ast_frame *f; 00126 struct myframe { 00127 struct ast_frame f; 00128 char offset[AST_FRIENDLY_OFFSET]; 00129 short frdata[160]; 00130 } myf; 00131 00132 u = ast_module_user_add(chan); 00133 00134 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds)) { 00135 ast_log(LOG_WARNING, "Unable to create socketpair\n"); 00136 ast_module_user_remove(u); 00137 return -1; 00138 } 00139 00140 ast_stopstream(chan); 00141 00142 owriteformat = chan->writeformat; 00143 res = ast_set_write_format(chan, AST_FORMAT_SLINEAR); 00144 if (res < 0) { 00145 ast_log(LOG_WARNING, "Unable to set write format to signed linear\n"); 00146 ast_module_user_remove(u); 00147 return -1; 00148 } 00149 00150 res = NBScatplay(fds[1]); 00151 /* Wait 1000 ms first */ 00152 next = ast_tvnow(); 00153 next.tv_sec += 1; 00154 if (res >= 0) { 00155 pid = res; 00156 /* Order is important -- there's almost always going to be mp3... we want to prioritize the 00157 user */ 00158 for (;;) { 00159 ms = ast_tvdiff_ms(next, ast_tvnow()); 00160 if (ms <= 0) { 00161 res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata)); 00162 if (res > 0) { 00163 myf.f.frametype = AST_FRAME_VOICE; 00164 myf.f.subclass = AST_FORMAT_SLINEAR; 00165 myf.f.datalen = res; 00166 myf.f.samples = res / 2; 00167 myf.f.mallocd = 0; 00168 myf.f.offset = AST_FRIENDLY_OFFSET; 00169 myf.f.src = __PRETTY_FUNCTION__; 00170 myf.f.delivery.tv_sec = 0; 00171 myf.f.delivery.tv_usec = 0; 00172 myf.f.data = myf.frdata; 00173 if (ast_write(chan, &myf.f) < 0) { 00174 res = -1; 00175 break; 00176 } 00177 } else { 00178 ast_log(LOG_DEBUG, "No more mp3\n"); 00179 res = 0; 00180 break; 00181 } 00182 next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000)); 00183 } else { 00184 ms = ast_waitfor(chan, ms); 00185 if (ms < 0) { 00186 ast_log(LOG_DEBUG, "Hangup detected\n"); 00187 res = -1; 00188 break; 00189 } 00190 if (ms) { 00191 f = ast_read(chan); 00192 if (!f) { 00193 ast_log(LOG_DEBUG, "Null frame == hangup() detected\n"); 00194 res = -1; 00195 break; 00196 } 00197 if (f->frametype == AST_FRAME_DTMF) { 00198 ast_log(LOG_DEBUG, "User pressed a key\n"); 00199 ast_frfree(f); 00200 res = 0; 00201 break; 00202 } 00203 ast_frfree(f); 00204 } 00205 } 00206 } 00207 } 00208 close(fds[0]); 00209 close(fds[1]); 00210 00211 if (pid > -1) 00212 kill(pid, SIGKILL); 00213 if (!res && owriteformat) 00214 ast_set_write_format(chan, owriteformat); 00215 00216 ast_module_user_remove(u); 00217 00218 return res; 00219 }
static int NBScatplay | ( | int | fd | ) | [static] |
Definition at line 67 of file app_nbscat.c.
References ast_log(), ast_opt_high_priority, ast_set_priority(), LOCAL_NBSCAT, LOG_WARNING, and NBSCAT.
Referenced by NBScat_exec().
00068 { 00069 int res; 00070 int x; 00071 sigset_t fullset, oldset; 00072 00073 sigfillset(&fullset); 00074 pthread_sigmask(SIG_BLOCK, &fullset, &oldset); 00075 00076 res = fork(); 00077 if (res < 0) 00078 ast_log(LOG_WARNING, "Fork failed\n"); 00079 if (res) { 00080 pthread_sigmask(SIG_SETMASK, &oldset, NULL); 00081 return res; 00082 } 00083 signal(SIGPIPE, SIG_DFL); 00084 pthread_sigmask(SIG_UNBLOCK, &fullset, NULL); 00085 00086 if (ast_opt_high_priority) 00087 ast_set_priority(0); 00088 00089 dup2(fd, STDOUT_FILENO); 00090 for (x = STDERR_FILENO + 1; x < 1024; x++) { 00091 if (x != STDOUT_FILENO) 00092 close(x); 00093 } 00094 /* Most commonly installed in /usr/local/bin */ 00095 execl(NBSCAT, "nbscat8k", "-d", (char *)NULL); 00096 execl(LOCAL_NBSCAT, "nbscat8k", "-d", (char *)NULL); 00097 ast_log(LOG_WARNING, "Execute of nbscat8k failed\n"); 00098 _exit(0); 00099 }
static int timed_read | ( | int | fd, | |
void * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 101 of file app_nbscat.c.
References ast_log(), pollfd::events, pollfd::fd, LOG_NOTICE, poll(), and POLLIN.
00102 { 00103 int res; 00104 struct pollfd fds[1]; 00105 fds[0].fd = fd; 00106 fds[0].events = POLLIN; 00107 res = poll(fds, 1, 2000); 00108 if (res < 1) { 00109 ast_log(LOG_NOTICE, "Selected timed out/errored out with %d\n", res); 00110 return -1; 00111 } 00112 return read(fd, data, datalen); 00113 00114 }
static int unload_module | ( | void | ) | [static] |
Definition at line 221 of file app_nbscat.c.
References ast_module_user_hangup_all, and ast_unregister_application().
00222 { 00223 int res; 00224 00225 res = ast_unregister_application(app); 00226 00227 ast_module_user_hangup_all(); 00228 00229 return res; 00230 }
char* app = "NBScat" [static] |
Definition at line 58 of file app_nbscat.c.
char* descrip [static] |
Initial value:
" NBScat: Executes nbscat to listen to the local NBS stream.\n" "User can exit by pressing any key\n."
Definition at line 62 of file app_nbscat.c.
char* synopsis = "Play an NBS local stream" [static] |
Definition at line 60 of file app_nbscat.c.