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: 356573 $")
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 struct ast_format 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 ast_format_clear(&owriteformat);
00128 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds)) {
00129 ast_log(LOG_WARNING, "Unable to create socketpair\n");
00130 return -1;
00131 }
00132
00133 ast_stopstream(chan);
00134
00135 ast_format_copy(&owriteformat, ast_channel_writeformat(chan));
00136 res = ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR);
00137 if (res < 0) {
00138 ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
00139 return -1;
00140 }
00141
00142 res = NBScatplay(fds[1]);
00143
00144 next = ast_tvnow();
00145 next.tv_sec += 1;
00146 if (res >= 0) {
00147 pid = res;
00148
00149
00150 for (;;) {
00151 ms = ast_tvdiff_ms(next, ast_tvnow());
00152 if (ms <= 0) {
00153 res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata));
00154 if (res > 0) {
00155 myf.f.frametype = AST_FRAME_VOICE;
00156 ast_format_set(&myf.f.subclass.format, AST_FORMAT_SLINEAR, 0);
00157 myf.f.datalen = res;
00158 myf.f.samples = res / 2;
00159 myf.f.mallocd = 0;
00160 myf.f.offset = AST_FRIENDLY_OFFSET;
00161 myf.f.src = __PRETTY_FUNCTION__;
00162 myf.f.delivery.tv_sec = 0;
00163 myf.f.delivery.tv_usec = 0;
00164 myf.f.data.ptr = myf.frdata;
00165 if (ast_write(chan, &myf.f) < 0) {
00166 res = -1;
00167 break;
00168 }
00169 } else {
00170 ast_debug(1, "No more mp3\n");
00171 res = 0;
00172 break;
00173 }
00174 next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000));
00175 } else {
00176 ms = ast_waitfor(chan, ms);
00177 if (ms < 0) {
00178 ast_debug(1, "Hangup detected\n");
00179 res = -1;
00180 break;
00181 }
00182 if (ms) {
00183 f = ast_read(chan);
00184 if (!f) {
00185 ast_debug(1, "Null frame == hangup() detected\n");
00186 res = -1;
00187 break;
00188 }
00189 if (f->frametype == AST_FRAME_DTMF) {
00190 ast_debug(1, "User pressed a key\n");
00191 ast_frfree(f);
00192 res = 0;
00193 break;
00194 }
00195 ast_frfree(f);
00196 }
00197 }
00198 }
00199 }
00200 close(fds[0]);
00201 close(fds[1]);
00202
00203 if (pid > -1)
00204 kill(pid, SIGKILL);
00205 if (!res && owriteformat.id)
00206 ast_set_write_format(chan, &owriteformat);
00207
00208 return res;
00209 }
00210
00211 static int unload_module(void)
00212 {
00213 return ast_unregister_application(app);
00214 }
00215
00216 static int load_module(void)
00217 {
00218 return ast_register_application_xml(app, NBScat_exec);
00219 }
00220
00221 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Silly NBS Stream Application");