app_nbscat.c
Go to the documentation of this file.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
00031
00032 #include "asterisk.h"
00033
00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328209 $")
00035
00036 #include <fcntl.h>
00037 #include <sys/time.h>
00038 #include <sys/socket.h>
00039 #include <signal.h>
00040
00041 #include "asterisk/lock.h"
00042 #include "asterisk/file.h"
00043 #include "asterisk/channel.h"
00044 #include "asterisk/frame.h"
00045 #include "asterisk/pbx.h"
00046 #include "asterisk/module.h"
00047 #include "asterisk/translate.h"
00048 #include "asterisk/app.h"
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 #define LOCAL_NBSCAT "/usr/local/bin/nbscat8k"
00064 #define NBSCAT "/usr/bin/nbscat8k"
00065
00066 #ifndef AF_LOCAL
00067 #define AF_LOCAL AF_UNIX
00068 #endif
00069
00070 static char *app = "NBScat";
00071
00072 static int NBScatplay(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 }
00080
00081 if (res) {
00082 return res;
00083 }
00084
00085 if (ast_opt_high_priority)
00086 ast_set_priority(0);
00087
00088 dup2(fd, STDOUT_FILENO);
00089 ast_close_fds_above_n(STDERR_FILENO);
00090
00091 execl(NBSCAT, "nbscat8k", "-d", (char *)NULL);
00092 execl(LOCAL_NBSCAT, "nbscat8k", "-d", (char *)NULL);
00093 fprintf(stderr, "Execute of nbscat8k failed\n");
00094 _exit(0);
00095 }
00096
00097 static int timed_read(int fd, void *data, int datalen)
00098 {
00099 int res;
00100 struct pollfd fds[1];
00101 fds[0].fd = fd;
00102 fds[0].events = POLLIN;
00103 res = ast_poll(fds, 1, 2000);
00104 if (res < 1) {
00105 ast_log(LOG_NOTICE, "Selected timed out/errored out with %d\n", res);
00106 return -1;
00107 }
00108 return read(fd, data, datalen);
00109
00110 }
00111
00112 static int NBScat_exec(struct ast_channel *chan, const char *data)
00113 {
00114 int res=0;
00115 int fds[2];
00116 int ms = -1;
00117 int pid = -1;
00118 int owriteformat;
00119 struct timeval next;
00120 struct ast_frame *f;
00121 struct myframe {
00122 struct ast_frame f;
00123 char offset[AST_FRIENDLY_OFFSET];
00124 short frdata[160];
00125 } myf;
00126
00127 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds)) {
00128 ast_log(LOG_WARNING, "Unable to create socketpair\n");
00129 return -1;
00130 }
00131
00132 ast_stopstream(chan);
00133
00134 owriteformat = chan->writeformat;
00135 res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
00136 if (res < 0) {
00137 ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
00138 return -1;
00139 }
00140
00141 res = NBScatplay(fds[1]);
00142
00143 next = ast_tvnow();
00144 next.tv_sec += 1;
00145 if (res >= 0) {
00146 pid = res;
00147
00148
00149 for (;;) {
00150 ms = ast_tvdiff_ms(next, ast_tvnow());
00151 if (ms <= 0) {
00152 res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata));
00153 if (res > 0) {
00154 myf.f.frametype = AST_FRAME_VOICE;
00155 myf.f.subclass.codec = AST_FORMAT_SLINEAR;
00156 myf.f.datalen = res;
00157 myf.f.samples = res / 2;
00158 myf.f.mallocd = 0;
00159 myf.f.offset = AST_FRIENDLY_OFFSET;
00160 myf.f.src = __PRETTY_FUNCTION__;
00161 myf.f.delivery.tv_sec = 0;
00162 myf.f.delivery.tv_usec = 0;
00163 myf.f.data.ptr = myf.frdata;
00164 if (ast_write(chan, &myf.f) < 0) {
00165 res = -1;
00166 break;
00167 }
00168 } else {
00169 ast_debug(1, "No more mp3\n");
00170 res = 0;
00171 break;
00172 }
00173 next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000));
00174 } else {
00175 ms = ast_waitfor(chan, ms);
00176 if (ms < 0) {
00177 ast_debug(1, "Hangup detected\n");
00178 res = -1;
00179 break;
00180 }
00181 if (ms) {
00182 f = ast_read(chan);
00183 if (!f) {
00184 ast_debug(1, "Null frame == hangup() detected\n");
00185 res = -1;
00186 break;
00187 }
00188 if (f->frametype == AST_FRAME_DTMF) {
00189 ast_debug(1, "User pressed a key\n");
00190 ast_frfree(f);
00191 res = 0;
00192 break;
00193 }
00194 ast_frfree(f);
00195 }
00196 }
00197 }
00198 }
00199 close(fds[0]);
00200 close(fds[1]);
00201
00202 if (pid > -1)
00203 kill(pid, SIGKILL);
00204 if (!res && owriteformat)
00205 ast_set_write_format(chan, owriteformat);
00206
00207 return res;
00208 }
00209
00210 static int unload_module(void)
00211 {
00212 return ast_unregister_application(app);
00213 }
00214
00215 static int load_module(void)
00216 {
00217 return ast_register_application_xml(app, NBScat_exec);
00218 }
00219
00220 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Silly NBS Stream Application");