/* * Monitor a Zaptel Channel * * Written by Mark Spencer * Based on previous works, designs, and architectures conceived and * written by Jim Dixon . * * Copyright (C) 2001 Jim Dixon / Zapata Telephony. * Copyright (C) 2001 Linux Support Services, Inc. * * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under thet erms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Primary Author: Mark Spencer * */ #include #include #include #include #include #include #include #include #include #ifdef STANDALONE_ZAPATA #include "zaptel.h" #include "tonezone.h" #else #include #include #endif #include #define BUFFERS 4 #define FRAG_SIZE 8 int audio_open(void) { int fd; int speed = 8000; int fmt = AFMT_S16_LE; int stereo = 0; int fragsize = (BUFFERS << 16) | (FRAG_SIZE); struct audio_buf_info ispace, ospace; fd = open("/dev/dsp", O_WRONLY); if (fd < 0) { fprintf(stderr, "Unable to open /dev/dsp: %s\n", strerror(errno)); return -1; } /* Step 1: Signed linear */ if (ioctl(fd, SNDCTL_DSP_SETFMT, &fmt) < 0) { fprintf(stderr, "ioctl(SETFMT) failed: %s\n", strerror(errno)); close(fd); return -1; } /* Step 2: Make non-stereo */ if (ioctl(fd, SNDCTL_DSP_STEREO, &stereo) < 0) { fprintf(stderr, "ioctl(STEREO) failed: %s\n", strerror(errno)); close(fd); return -1; } /* Step 3: Make 8000 Hz */ if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) < 0) { fprintf(stderr, "ioctl(SPEED) failed: %s\n", strerror(errno)); close(fd); return -1; } if (speed != 8000) fprintf(stderr, "Warning: Requested 8000 Hz, got %d\n", speed); if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fragsize)) { fprintf(stderr, "Sound card won't let me set fragment size to 10 64-byte buffers (%x)\n" "so sound may be choppy: %s.\n", fragsize, strerror(errno)); } bzero(&ispace, sizeof(ispace)); bzero(&ospace, sizeof(ospace)); if (ioctl(fd, SNDCTL_DSP_GETISPACE, &ispace)) { /* They don't support block size stuff, so just return but notify the user */ fprintf(stderr, "Sound card won't let me know the input buffering...\n"); } if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &ospace)) { /* They don't support block size stuff, so just return but notify the user */ fprintf(stderr, "Sound card won't let me know the output buffering...\n"); } fprintf(stderr, "New input space: %d of %d %d byte fragments (%d bytes left)\n", ispace.fragments, ispace.fragstotal, ispace.fragsize, ispace.bytes); fprintf(stderr, "New output space: %d of %d %d byte fragments (%d bytes left)\n", ospace.fragments, ospace.fragstotal, ospace.fragsize, ospace.bytes); return fd; } int pseudo_open(void) { int fd; int x = 1; fd = open("/dev/zap/pseudo", O_RDWR); if (fd < 0) { fprintf(stderr, "Unable to open pseudo channel: %s\n", strerror(errno)); return -1; } if (ioctl(fd, ZT_SETLINEAR, &x)) { fprintf(stderr, "Unable to set linear mode: %s\n", strerror(errno)); close(fd); return -1; } x = 240; if (ioctl(fd, ZT_SET_BLOCKSIZE, &x)) { fprintf(stderr, "unable to set sane block size: %s\n", strerror(errno)); close(fd); return -1; } return fd; } int main(int argc, char *argv[]) { int afd, pfd; char buf[8192]; int res; struct zt_confinfo zc; if ((argc < 2) || (atoi(argv[1]) < 1)) { fprintf(stderr, "Usage: ztmonitor \n"); exit(1); } /* Open audio */ if ((afd = audio_open()) < 0) exit(1); /* Open Pseudo device */ if ((pfd = pseudo_open()) < 0) exit(1); /* Conference them */ memset(&zc, 0, sizeof(zc)); zc.chan = 0; zc.confno = atoi(argv[1]); zc.confmode = ZT_CONF_MONITORBOTH; if (ioctl(pfd, ZT_SETCONF, &zc) < 0) { fprintf(stderr, "Unable to monitor: %s\n", strerror(errno)); exit(1); } /* Now, copy from pseudo to audio */ for (;;) { res = read(pfd, buf, sizeof(buf)); if (res < 1) break; write(afd, buf, res); } exit(0); }