📄 miniphone.c
字号:
/* * Miniphone: A simple, command line telephone * * IAX Support for talking to Asterisk and other Gnophone clients * * Copyright (C) 1999, Linux Support Services, Inc. * * Mark Spencer <markster@linux-support.net> * * This program is free software, distributed under the terms of * the GNU General Public License */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <fcntl.h>#include <stdio.h>#include <errno.h>#include <sys/ioctl.h>#include <iax-client.h>#include <linux/soundcard.h>#include <errno.h>#include <sys/time.h>#include <sys/signal.h>#include <sys/time.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <gsm.h>#include <miniphone.h>#include <time.h>#include "busy.h"#include "dialtone.h"#include "answer.h"#include "ringtone.h"#include "ring10.h"#include "options.h"#define FRAME_SIZE 160static char callerid[80];struct peer { int time; gsm gsmin; gsm gsmout; struct iax_session *session; struct peer *next;};static char *audiodev = "/dev/dsp";static int audiofd = -1;static struct peer *peers;static int answered_call = 0;static struct peer *find_peer(struct iax_session *);static int audio_setup(char *);static void sighandler(int);static void parse_args(FILE *, unsigned char *);void do_iax_event(FILE *);void call(FILE *, char *);void answer_call(void);void reject_call(void);static void handle_event(FILE *, struct iax_event *e, struct peer *p);void parse_cmd(FILE *, int, char **);void issue_prompt(FILE *);void dump_array(FILE *, char **);struct sound { short *data; int datalen; int samplen; int silencelen; int repeat;};static int cursound = -1;static int sampsent = 0;static int offset = 0;static int silencelen = 0;static int nosound = 0;static int offhook = 0;static int ringing = 0;static int writeonly = 0;static struct iax_session *registry = NULL;static struct timeval regtime;#define TONE_NONE -1#define TONE_RINGTONE 0#define TONE_BUSY 1#define TONE_CONGEST 2#define TONE_RINGER 3#define TONE_ANSWER 4#define TONE_DIALTONE 5#define OUTPUT_NONE 0#define OUTPUT_SPEAKER 1#define OUTPUT_HANDSET 2#define OUTPUT_BOTH 3static struct sound sounds[] = { { ringtone, sizeof(ringtone)/2, 16000, 32000, 1 }, { busy, sizeof(busy)/2, 4000, 4000, 1 }, { busy, sizeof(busy)/2, 2000, 2000, 1 }, { ring10, sizeof(ring10)/2, 16000, 32000, 1 }, { answer, sizeof(answer)/2, 2200, 0, 0 }, { dialtone, sizeof(dialtone)/2, 8000, 0, 1 },};static char *help[] = {"Welcome to the miniphone telephony client, the commands are as follows:\n","Help\t\t-\tDisplays this screen.","Help <Command>\t-\tInqueries specific information on a command.","Dial <Number>\t-\tDials the number supplied in the first arguement","Status\t\t-\tLists the current sessions and their current status.","Quit\t\t-\tShuts down the client.","",0};static short silence[FRAME_SIZE];static struct peer *most_recent_answer;static struct iax_session *newcall = 0;static struct peer *find_peer(struct iax_session *session){ struct peer *cur = peers; while(cur) { if (cur->session == session) return cur; cur = cur->next; } return NULL;}static int audio_setup(char *dev){ int fd; int fmt = AFMT_S16_LE; int channels = 1; int speed = 8000; int fragsize = (40 << 16) | 6; if ( (fd = open(dev, O_RDWR | O_NONBLOCK)) < 0) { fprintf(stderr, "Unable to open audio device %s: %s\n", dev, strerror(errno)); return -1; } if (ioctl(fd, SNDCTL_DSP_SETFMT, &fmt) || (fmt != AFMT_S16_LE)) { fprintf(stderr, "Unable to set in signed linear format.\n"); return -1; } if (ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0)) { fprintf(stderr, "Unable to set full duplex operation.\n"); writeonly = 1; /* return -1; */ } if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) || (channels != 1)) { fprintf(stderr, "Unable to set to mono\n"); return -1; } if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) || (speed != 8000)) { fprintf(stderr, "Unable to set speed to 8000 hz\n"); return -1; } if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fragsize)) { fprintf(stderr, "Unable to set fragment size...\n"); return -1; } return fd;}static int send_sound(int soundfd){ /* Send FRAME_SIZE samples of whatever */ short myframe[FRAME_SIZE]; short *frame = NULL; int total = FRAME_SIZE; int amt=0; int res; int myoff; audio_buf_info abi; if (cursound > -1) { res = ioctl(soundfd, SNDCTL_DSP_GETOSPACE ,&abi); if (res) { fprintf(stderr,"Unable to read output space\n"); return -1; } /* Calculate how many samples we can send, max */ if (total > (abi.fragments * abi.fragsize / 2)) total = abi.fragments * abi.fragsize / 2; res = total; if (sampsent < sounds[cursound].samplen) { myoff=0; while(total) { amt = total; if (amt > (sounds[cursound].datalen - offset)) amt = sounds[cursound].datalen - offset; memcpy(myframe + myoff, sounds[cursound].data + offset, amt * 2); total -= amt; offset += amt; sampsent += amt; myoff += amt; if (offset >= sounds[cursound].datalen) offset = 0; } /* Set it up for silence */ if (sampsent >= sounds[cursound].samplen) silencelen = sounds[cursound].silencelen; frame = myframe; } else { if (silencelen > 0) { frame = silence; silencelen -= res; } else { if (sounds[cursound].repeat) { /* Start over */ sampsent = 0; offset = 0; } else { cursound = -1; nosound = 0; } } }#if 0 if (frame) printf("res is %d, frame[0] is %d\n", res, frame[0]);#endif res = write(soundfd, frame, res * 2); if (res > 0) return 0; return res; } return 0;}static int iax_regtimeout(int timeout){ if (timeout) { gettimeofday(®time, NULL); regtime.tv_sec += timeout; } else { regtime.tv_usec = 0; regtime.tv_sec = 0; } return 0;}static int check_iax_register(void){ int res; if (strlen(regpeer) && strlen(server)) { registry = iax_session_new(); res = iax_register(registry, server,regpeer,regsecret, refresh); if (res) { fprintf(stderr, "Failed registration: %s\n", iax_errstr); return -1; } iax_regtimeout(5 * refresh / 6); } else { iax_regtimeout(0); refresh = 60; } return 0;}static int check_iax_timeout(void){ struct timeval tv; int ms; if (!regtime.tv_usec || !regtime.tv_sec) return -1; gettimeofday(&tv, NULL); if ((tv.tv_usec >= regtime.tv_usec) && (tv.tv_sec >= regtime.tv_sec)) { check_iax_register(); /* Have it check again soon */ return 100; } ms = (regtime.tv_sec - tv.tv_sec) * 1000 + (regtime.tv_usec - tv.tv_usec) / 1000; return ms;}static int gentone(int sound, int uninterruptible){ cursound = sound; sampsent = 0; offset = 0; silencelen = 0; nosound = uninterruptible; printf("Sending tone %d\n", sound); return 0;}voidsighandler(int sig){ if(sig == SIGHUP) { puts("rehashing!"); } else if(sig == SIGINT) { static int prev = 0; int cur; if ( (cur = time(0))-prev <= 5) { printf("Terminating!\n"); exit(0); } else { prev = cur; printf("Press interrupt key again in the next %d seconds to really terminate\n", 5-(cur-prev)); } }}voidparse_args(FILE *f, unsigned char *cmd){ static char *argv[MAXARGS]; unsigned char *parse = cmd; int argc = 0, t = 0; // Don't mess with anything that doesn't exist... if(!*parse) return; bzero(argv, sizeof(argv)); while(*parse) { if(*parse < 33 || *parse > 128) { *parse = 0, t++; if(t > MAXARG) { fprintf(f, "Warning: Argument exceeds maximum argument size, command ignored!\n"); return; } } else if(t || !argc) { if(argc == MAXARGS) { fprintf(f, "Warning: Command ignored, too many arguments\n"); return; } argv[argc++] = parse; t = 0; } parse++; } if(argc) parse_cmd(f, argc, argv);}intmain(int argc, char *argv[]){ int port; int netfd; int c, h=0, m, regm; FILE *f; int fd = STDIN_FILENO; char rcmd[RBUFSIZE]; fd_set readfd; fd_set writefd; struct timeval timer; struct timeval *timerptr = NULL; gsm_frame fo; load_options(); if (!strlen(callerid)) gethostname(callerid, sizeof(callerid)); signal(SIGHUP, sighandler); signal(SIGINT, sighandler); if ( !(f = fdopen(fd, "w+"))) { fprintf(stderr, "Unable to create file on fd %d\n", fd); return -1; } if ( (audiofd = audio_setup(audiodev)) == -1) { fprintf(stderr, "Fatal error: failed to open sound device"); return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -