Add experimental nbscat application
authorMark Spencer <markster@digium.com>
Sat, 20 Mar 2004 07:16:27 +0000 (07:16 +0000)
committerMark Spencer <markster@digium.com>
Sat, 20 Mar 2004 07:16:27 +0000 (07:16 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@2490 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/Makefile
apps/app_nbscat.c [new file with mode: 0755]
channels/chan_nbs.c

index 06d09a3..b8a82ea 100755 (executable)
@@ -25,7 +25,8 @@ APPS=app_dial.so app_playback.so app_voicemail.so app_directory.so app_mp3.so\
      app_waitforring.so app_privacy.so app_db.so app_chanisavail.so \
      app_enumlookup.so app_transfer.so app_setcidnum.so app_cdr.so \
      app_hasnewvoicemail.so app_sayunixtime.so app_cut.so app_read.so \
-     app_setcdruserfield.so app_random.so app_ices.so app_eval.so
+     app_setcdruserfield.so app_random.so app_ices.so app_eval.so \
+     app_nbscat.so
 
 ifneq (${OSARCH},Darwin)
 APPS+=app_intercom.so
diff --git a/apps/app_nbscat.c b/apps/app_nbscat.c
new file mode 100755 (executable)
index 0000000..e99d2f2
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * Asterisk -- A telephony toolkit for Linux.
+ *
+ * Silly application to play an NBScat file -- uses mpg123
+ * 
+ * Copyright (C) 1999, Mark Spencer
+ *
+ * Mark Spencer <markster@linux-support.net>
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License
+ */
+#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 <string.h>
+#include <stdio.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#define LOCAL_NBSCAT "/usr/local/bin/nbscat8k"
+#define NBSCAT "/usr/bin/nbscat8k"
+
+static char *tdesc = "Silly NBS Stream Application";
+
+static char *app = "NBScat";
+
+static char *synopsis = "Play an NBS local stream";
+
+static char *descrip = 
+"  NBScat: Executes nbscat to listen to the local NBS stream.\n"
+"Returns  -1  on\n hangup or 0 otherwise. User can exit by \n"
+"pressing any key\n.";
+
+STANDARD_LOCAL_USER;
+
+LOCAL_USER_DECL;
+
+static int NBScatplay(int fd)
+{
+       int res;
+       int x;
+       res = fork();
+       if (res < 0) 
+               ast_log(LOG_WARNING, "Fork failed\n");
+       if (res)
+               return res;
+       dup2(fd, STDOUT_FILENO);
+       for (x=0;x<256;x++) {
+               if (x != STDOUT_FILENO)
+                       close(x);
+       }
+       /* Most commonly installed in /usr/local/bin */
+       execl(NBSCAT, "nbscat8k", "-d", (char *)NULL);
+       execl(LOCAL_NBSCAT, "nbscat8k", "-d", (char *)NULL);
+       ast_log(LOG_WARNING, "Execute of nbscat8k failed\n");
+       return -1;
+}
+
+static int timed_read(int fd, void *data, int datalen)
+{
+       int res;
+       fd_set fds;
+       struct timeval tv = { 2, 0 };           /* Wait no more than 2 seconds */
+       FD_ZERO(&fds);
+       FD_SET(fd, &fds);
+       res = ast_select(fd + 1, &fds, NULL, NULL, &tv);
+       if (res < 1) {
+               ast_log(LOG_NOTICE, "Selected timed out/errored out with %d\n", res);
+               return -1;
+       }
+       return read(fd, data, datalen);
+       
+}
+
+static int NBScat_exec(struct ast_channel *chan, void *data)
+{
+       int res=0;
+       struct localuser *u;
+       int fds[2];
+       int ms = -1;
+       int pid = -1;
+       int owriteformat;
+       struct timeval last;
+       struct ast_frame *f;
+       struct myframe {
+               struct ast_frame f;
+               char offset[AST_FRIENDLY_OFFSET];
+               short frdata[160];
+       } myf;
+       last.tv_usec = 0;
+       last.tv_sec = 0;
+       if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds)) {
+               ast_log(LOG_WARNING, "Unable to create socketpair\n");
+               return -1;
+       }
+       LOCAL_USER_ADD(u);
+       ast_stopstream(chan);
+
+       owriteformat = chan->writeformat;
+       res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
+       if (res < 0) {
+               ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
+               return -1;
+       }
+       
+       res = NBScatplay(fds[1]);
+       /* Wait 1000 ms first */
+       ms = 1000;
+       if (res >= 0) {
+               pid = res;
+               /* Order is important -- there's almost always going to be NBScat...  we want to prioritize the
+                  user */
+               for (;;) {
+                       ms = ast_waitfor(chan, ms);
+                       if (ms < 0) {
+                               ast_log(LOG_DEBUG, "Hangup detected\n");
+                               res = -1;
+                               break;
+                       }
+                       if (ms) {
+                               f = ast_read(chan);
+                               if (!f) {
+                                       ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
+                                       res = -1;
+                                       break;
+                               }
+                               if (f->frametype == AST_FRAME_DTMF) {
+                                       ast_log(LOG_DEBUG, "User pressed a key\n");
+                                       ast_frfree(f);
+                                       res = 0;
+                                       break;
+                               }
+                               ast_frfree(f);
+                       } else  {
+                               res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata));
+                               if (res > 0) {
+                                       myf.f.frametype = AST_FRAME_VOICE;
+                                       myf.f.subclass = AST_FORMAT_SLINEAR;
+                                       myf.f.datalen = res;
+                                       myf.f.samples = res / 2;
+                                       myf.f.mallocd = 0;
+                                       myf.f.offset = AST_FRIENDLY_OFFSET;
+                                       myf.f.src = __PRETTY_FUNCTION__;
+                                       myf.f.data = myf.frdata;
+                                       if (ast_write(chan, &myf.f) < 0) {
+                                               res = -1;
+                                               break;
+                                       }
+                               } else {
+                                       ast_log(LOG_DEBUG, "No more NBScat\n");
+                                       res = 0;
+                                       break;
+                               }
+                               ms = res / 16;
+                       }
+               }
+       }
+       close(fds[0]);
+       close(fds[1]);
+       LOCAL_USER_REMOVE(u);
+       if (pid > -1)
+               kill(pid, SIGKILL);
+       if (!res && owriteformat)
+               ast_set_write_format(chan, owriteformat);
+       return res;
+}
+
+int unload_module(void)
+{
+       STANDARD_HANGUP_LOCALUSERS;
+       return ast_unregister_application(app);
+}
+
+int load_module(void)
+{
+       return ast_register_application(app, NBScat_exec, synopsis, descrip);
+}
+
+char *description(void)
+{
+       return tdesc;
+}
+
+int usecount(void)
+{
+       int res;
+       STANDARD_USECOUNT(res);
+       return res;
+}
+
+char *key()
+{
+       return ASTERISK_GPL_KEY;
+}
index cd40ce1..1960acb 100755 (executable)
@@ -149,7 +149,7 @@ static int nbs_hangup(struct ast_channel *ast)
        return 0;
 }
 
-static struct ast_frame  *nbs_read(struct ast_channel *ast)
+static struct ast_frame  *nbs_xread(struct ast_channel *ast)
 {
        struct nbs_pvt *p = ast->pvt->pvt;
        
@@ -209,7 +209,7 @@ static struct ast_channel *nbs_new(struct nbs_pvt *i, int state)
                tmp->pvt->pvt = i;
                tmp->pvt->call = nbs_call;
                tmp->pvt->hangup = nbs_hangup;
-               tmp->pvt->read = nbs_read;
+               tmp->pvt->read = nbs_xread;
                tmp->pvt->write = nbs_xwrite;
                strncpy(tmp->context, context, sizeof(tmp->context)-1);
                strncpy(tmp->exten, "s",  sizeof(tmp->exten) - 1);