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

📄 winiphone.c

📁 IAX协议客户端源码
💻 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 *//* #define	PRINTCHUCK /* enable this to indicate chucked incomming packets */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <io.h>#include <conio.h>#include <stdio.h>#include <errno.h>#include <time.h>#include <process.h>#include <windows.h>#include <winsock.h>#include <mmsystem.h>#include <malloc.h>#include "gsm.h"#include "iax-client.h"#include "frame.h"#include "miniphone.h"struct peer {	int time;	gsm gsmin;	gsm gsmout;	struct iax_session *session;	struct peer *next;};static struct peer *peers;static int answered_call = 0;/* stuff for wave audio device */HWAVEOUT wout;HWAVEIN win;typedef struct whout {	WAVEHDR w;	short	data[160];	struct whout *next;} WHOUT;WHOUT *outqueue = NULL;/* parameters for audio in */#define	NWHIN 8				/* number of input buffer entries *//* NOTE the OUT_INTERVAL parameter *SHOULD* be more around 18 to 20 or so, since the packets shouldbe spaced by 20 milliseconds. However, in practice, especially in Windoze-95, setting it that highcaused underruns. 10 is just ever so slightly agressive, and the receiver has to chuck a packetevery now and then. Thats about the way it should be to be happy. */#define	OUT_INTERVAL 10		/* number of ms to wait before sending more data to peer *//* parameters for audio out */#define	OUT_DEPTH 12		/* number of outbut buffer entries */#define	OUT_PAUSE_THRESHOLD 2 /* number of active entries needed to start output (for smoothing) *//* audio input buffer headers */WAVEHDR whin[NWHIN];/* audio input buffers */char bufin[NWHIN][320];/* initialize the sequence variables for the audio in stuff */unsigned int whinserial = 1,nextwhin = 1;static struct peer *find_peer(struct iax_session *);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 **);static char *help[] = {"Welcome to the miniphone telephony client, the commands are as follows:\n","Help\t\t-\tDisplays this screen.","Call <Number>\t-\tDials the number supplied.","Answer\t\t-\tAnswers an Inbound call.","Reject\t\t-\tRejects an Inbound call.","Dump\t\t-\tDumps (disconnects) the current call.","Dtmf <Digit>\t-\tSends specified DTMF digit.","Status\t\t-\tLists the current sessions and their current status.","Quit\t\t-\tShuts down the client.","",0};static struct peer *most_recent_answer;static struct iax_session *newcall = 0;/* holder of the time, relative to startup in system ticks. See ourgettimeofday() implementation */time_t	startuptime;/* routine called at exit to shutdown audio I/O and close nicely.NOTE: If all this isnt done, the system doesnt not handle thiscleanly and has to be rebooted. What a pile of doo doo!! */void killem(void){	waveInStop(win);	waveInReset(win);	waveInClose(win); 	waveOutReset(wout);	waveOutClose(wout);	WSACleanup(); /* dont forget socket stuff too */	return;}/* Win-doze doenst have gettimeofday(). This sux. So, what we did isprovide some gettimeofday-like functionality that works for our purposes.In the main(), we take a sample of the system tick counter (into startuptime).This function returns the relative time since program startup, more or less,which is certainly good enough for our purposes. */void gettimeofday(struct timeval *tv, struct timezone *tz){	long l = startuptime + GetTickCount();	tv->tv_sec = l / 1000;	tv->tv_usec = (l % 1000) * 1000;	return;}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;}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;	memset(argv, 0, 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);}/* handle all network requests, and a pending scheduled event, if any */void service_network(int netfd, FILE *f){	fd_set readfd;	struct timeval dumbtimer;	/* set up a timer that falls-through */	dumbtimer.tv_sec = 0;	dumbtimer.tv_usec = 0;		for(;;) /* suck everything outa network stuff */		{			FD_ZERO(&readfd);			FD_SET(netfd, &readfd);			if (select(netfd + 1, &readfd, 0, 0, &dumbtimer) > 0)			{				if (FD_ISSET(netfd,&readfd))				{					do_iax_event(f);					(void) iax_time_to_next_event();				} else break;			} else break;		}		do_iax_event(f); /* do pending event if any */}intmain(int argc, char *argv[]){	int port;	int netfd; 	int c, i;	FILE *f;	char rcmd[RBUFSIZE];	gsm_frame fo;	WSADATA foop;	time_t	t;	WAVEFORMATEX wf;	WHOUT *wh,*wh1,*wh2;	unsigned long lastouttick = 0;	/* get time of day in milliseconds, offset by tick count (see our	   gettimeofday() implementation) */	time(&t);	startuptime = ((t % 86400) * 1000) - GetTickCount();	f = stdout;	_dup2(fileno(stdout),fileno(stderr));	/* start up the windoze-socket layer stuff */	if (WSAStartup(0x0101,&foop)) {		fprintf(stderr,"Fatal error: Falied to startup windows sockets\n");		return -1;	}	/* setup the format for opening audio channels */	wf.wFormatTag = WAVE_FORMAT_PCM;	wf.nChannels = 1;	wf.nSamplesPerSec = 8000;	wf.nAvgBytesPerSec = 16000;	wf.nBlockAlign = 2;	wf.wBitsPerSample = 16;	wf.cbSize = 0;	/* open the audio out channel */	if (waveOutOpen(&wout,0,&wf,0,0,CALLBACK_NULL) != MMSYSERR_NOERROR)		{			fprintf(stderr,"Fatal Error: Failed to open wave output device\n");			return -1;		}	/* open the audio in channel */	if (waveInOpen(&win,0,&wf,0,0,CALLBACK_NULL) != MMSYSERR_NOERROR)		{			fprintf(stderr,"Fatal Error: Failed to open wave input device\n");			waveOutReset(wout);			waveOutClose(wout);			return -1;		}	/* activate the exit handler */	atexit(killem);	/* initialize the audio in buffer structures */	memset(&whin,0,sizeof(whin));	if ( (port = iax_init(0) < 0)) {		fprintf(stderr, "Fatal error: failed to initialize iax with port %d\n", port);		return -1;	}	iax_set_formats(AST_FORMAT_GSM);	netfd = iax_get_fd();	fprintf(f, "Text Based Telephony Client.\n\n");	issue_prompt(f);	/* main tight loop */	while(1) {		/* service the network stuff */		service_network(netfd,f);		if (outqueue) /* if stuff in audio output queue, free it up if its available */		{			/* go through audio output queue */			for(wh = outqueue,wh1 = wh2 = NULL,i = 0; wh != NULL; wh = wh->next)			{				service_network(netfd,f); /* service network here for better performance */				/* if last one was removed from queue, zot it here */				if (i && wh1)				{ 					free(wh1);					wh1 = wh2;				}				i = 0; /* reset "last one removed" flag */				if (wh->w.dwFlags & WHDR_DONE) /* if this one is done */				{					/* prepare audio header */					if ((c = waveOutUnprepareHeader(wout,&wh->w,sizeof(WAVEHDR))) != MMSYSERR_NOERROR)					{ 						fprintf(stderr,"Cannot unprepare audio out header, error %d\n",c);						exit(255);					}					if (wh1 != NULL) /* if there was a last one */					{						wh1->next = wh->next;					} 					if (outqueue == wh) /* is first one, so set outqueue to next one */					{						outqueue = wh->next;					}					i = 1; /* set 'to free' flag */				}				wh2 = wh1;	/* save old,old wh pointer */				wh1 = wh; /* save the old wh pointer */			}		}		/* go through all audio in buffers, and prepare and queue ones that are currently idle */		for(i = 0; i < NWHIN; i++)		{			service_network(netfd,f); /* service network stuff here for better performance */			if (!(whin[i].dwFlags & WHDR_PREPARED)) /* if not prepared, do so */			{				/* setup this input buffer header */				memset(&whin[i],0,sizeof(WAVEHDR));				whin[i].lpData = bufin[i];				whin[i].dwBufferLength = 320;				whin[i].dwUser = whinserial++; /* set 'user data' to current serial number */				/* prepare the buffer */				if (waveInPrepareHeader(win,&whin[i],sizeof(WAVEHDR)))				{					fprintf(stderr,"Unable to prepare header for input\n");					return -1;				}				/* add it to device (queue) */				if (waveInAddBuffer(win,&whin[i],sizeof(WAVEHDR)))				{					fprintf(stderr,"Unable to prepare header for input\n");					return -1;				}			}			waveInStart(win); /* start it (if not already started) */		}				/* if key pressed, do command stuff */		if(_kbhit())		{				if ( ( fgets(&*rcmd, 256, stdin))) {					rcmd[strlen(rcmd)-1] = 0;					parse_args(f, &*rcmd);				} else fprintf(f, "Fatal error: failed to read data!\n");				issue_prompt(f);		}		/* do audio input stuff for buffers that have received data from audio in device already. Must			do them in serial number order (the order in which they were originally queued). */		if(answered_call) /* send audio only if call answered */		{			for(;;) /* loop until all are found */			{				for(i = 0; i < NWHIN; i++) /* find an available one that's the one we are looking for */				{					service_network(netfd,f); /* service network here for better performance */					/* if not time to send any more, dont */					if (GetTickCount() < (lastouttick + OUT_INTERVAL))					{						i = NWHIN; /* set to value that WILL exit loop */						break;					}					if ((whin[i].dwUser == nextwhin) && (whin[i].dwFlags & WHDR_DONE)) { /* if audio is ready */						/* must have read exactly 320 bytes */						if (whin[i].dwBytesRecorded != whin[i].dwBufferLength)						{							fprintf(stderr,"Short audio read, got %d bytes, expected %d bytes\n", whin[i].dwBytesRecorded,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -