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