⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 miniphone.c

📁 ppciaxclient softphone
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * 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 160

static 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    3

static 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(&regtime, 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;
}

void
sighandler(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));
		}
	}
}

void
parse_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);
}

int
main(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 + -