1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-04 17:49:45 +02:00
2010-01-24 09:19:39 +00:00

162 lines
3.6 KiB
C

/*
**********************************************************************
* File io.c
**********************************************************************
*
* Non blocking input routine
* Works by puttng the terminal in CBREAK mode and using the FIONREAD
* ioctl call to determine the number of characters in the input queue
*/
#include "stdio.h"
#include "io.h"
#include <sys/types.h>
#include <sys/time.h>
#include <signal.h>
#include <sgtty.h>
#include "cext.h"
int IOinputfd; /* input file descriptor (usually 0) */
int IOnochar; /* Value to be returned by IOgetchar()
where there is no input to be had */
static struct sgttyb IOoldmodes, IOcurrentmodes;
/* Initial and current tty modes */
/*
* IOsetup(inputfd)
* Args:
* inputfd - input file descriptor (should be zero for standard input)
* Returns:
* 0 - if all goes well
* -1 - if an ioctl fails (also calls perror)
* Side Effects:
* Puts the terminal in CBREAK mode - before process termination
* IOcleanup() should be called to restore old terminal modes
* Catch's interrupts (if they are not already being caught) and
* calls IOcleanup before exiting
*
*/
#define ERROR(s) return (perror(s), -1)
IOsetup(inputfd)
{
static IOdiegracefully();
int (*interrupt_handler)();
IOinputfd = inputfd;
IOnochar = NOCHAR;
if(ioctl(IOinputfd, TIOCGETP, &IOoldmodes) < 0)
ERROR("IOsetup");
IOcurrentmodes = IOoldmodes;
IOcurrentmodes.sg_flags |= CBREAK;
IOcurrentmodes.sg_flags &= ~ECHO;
if(ioctl(IOinputfd, TIOCSETP, &IOcurrentmodes))
ERROR("IOsetup-2");
if( (interrupt_handler = signal(SIGINT, IOdiegracefully)) != 0)
signal(SIGINT, interrupt_handler);
return 0;
}
static
IOdiegracefully()
{
write(2, "\nBye\n", 5);
IOcleanup();
EXIT(2);
}
/*
* IOcleanup()
* Returns:
* 0 - if all goes well
* -1 - if an ioctl fails (also calls perror)
* Side Effects:
* Restores initial terminal modes
*/
IOcleanup()
{
if(ioctl(IOinputfd, TIOCSETP, &IOoldmodes) < 0)
ERROR("IOclean");
return 0;
}
/*
* IOgetchar()
* Returns:
* A character off the input queue if there is one,
* IOnochar if there is no character waiting to be read,
* -1 if an ioctl fails (shouldn't happen if IOsetup went OK)
*/
#ifndef UNIX_MACH
IOgetchar()
{
int n;
char c;
if(ioctl(IOinputfd, FIONREAD, &n) < 0)
ERROR("IOgetchar");
if(n <= 0)
return IOnochar;
switch(read(IOinputfd, &c, 1)) {
case 1:
return c;
case 0:
return EOF;
default:
ERROR("IOgetchar-read");
}
}
#ifdef IOGETCHAR2
IOgetchar2()
{
int nfds, readfds = 1 << IOinputfd;
char c;
static struct timeval zero;
if(IOinputfd < 0 || IOinputfd >= 32) {
printf("IOgetchar2: bad IOinputfd (%d)%s\n", IOinputfd,
IOinputfd == -1 ? "Did you call IOsetup(fd)?" : "");
}
nfds = select(32, &readfds, 0, 0, &zero);
if(nfds > 0) {
switch(read(IOinputfd, &c, 1)) {
case 0:
return EOF;
case 1:
return c;
default:
printf("IOgetchar2: read failed!\n");
return NOCHAR;
}
}
else if(nfds < 0)
printf("IOgetchar2: select failed!\n");
return NOCHAR;
}
#endif
/*
* IOwaitchar()
* Returns:
* A character off the input queue. Waits if necessary.
*/
int IOwaitchar()
{
char c;
if (read(IOinputfd, &c, 1) == 1) return c;
else return EOF;
}
#endif /* not UNIX_MACH */