/* $Id: misc.c,v 1.5 1999/03/10 07:58:03 boyns Exp $ */
/*
* Copyright (C) 1993-99 Mark R. Boyns <boyns@doit.org>
*
* This file is part of rplay.
*
* rplay is free software; you can redistribute it and/or modify
* it under the terms 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.
*
* rplay 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 rplay; see the file COPYING. If not, write to the
* Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "rplayd.h"
#include <string.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef ultrix
#include <fcntl.h>
#else
#include <sys/fcntl.h>
#endif
#include <sys/param.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <math.h>
#include "sound.h"
#include "timer.h"
#ifdef __STDC__
char *
sys_err_str(int error)
#else
char *
sys_err_str(error)
int error;
#endif
{
#ifdef HAVE_STRERROR
return (char *) strerror(error);
#else
extern char *sys_errlist[];
return sys_errlist[error];
#endif
}
#ifdef __STDC__
int
udp_socket(int port)
#else
int
udp_socket(port)
int port;
#endif
{
int fd;
struct sockaddr_in s;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
{
report(REPORT_ERROR, "socket: %s\n", sys_err_str(errno));
done(1);
}
s.sin_family = AF_INET;
s.sin_port = htons(port);
s.sin_addr.s_addr = INADDR_ANY;
if (bind(fd, (struct sockaddr *) &s, sizeof(s)) < 0)
{
report(REPORT_ERROR, "bind: %s\n", sys_err_str(errno));
done(1);
}
return fd;
}
#ifdef __STDC__
int
tcp_socket(int port)
#else
int
tcp_socket(port)
int port;
#endif
{
int fd;
struct sockaddr_in s;
int on = 1;
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0)
{
report(REPORT_ERROR, "socket: %s\n", sys_err_str(errno));
done(1);
}
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)) < 0)
{
report(REPORT_ERROR, "setsockopt: SO_REUSEADDR: %s\n", sys_err_str(errno));
done(1);
}
s.sin_family = AF_INET;
s.sin_port = htons(port);
s.sin_addr.s_addr = INADDR_ANY;
if (bind(fd, (struct sockaddr *) &s, sizeof(s)) < 0)
{
report(REPORT_ERROR, "bind: %s\n", sys_err_str(errno));
done(1);
}
if (listen(fd, 5) < 0)
{
report(REPORT_ERROR, "listen: %s\n", sys_err_str(errno));
done(1);
}
return fd;
}
/*
* make a file descriptor non-blocking
*/
#ifdef __STDC__
void
fd_nonblock(int fd)
#else
void
fd_nonblock(fd)
int fd;
#endif
{
int flags;
flags = fcntl(fd, F_GETFL, 0);
if (flags < 0)
{
report(REPORT_ERROR, "fd_nonblock: F_GETFL fcntl: %s\n", sys_err_str(errno));
done(1);
}
#ifdef linux
flags |= O_NONBLOCK;
#else
flags |= FNDELAY;
#endif
if (fcntl(fd, F_SETFL, flags) < 0)
{
report(REPORT_ERROR, "fd_nonblock: F_SETFL fcntl: %s\n", sys_err_str(errno));
done(1);
}
}
/*
* make a file descriptor blocking
*/
#ifdef __STDC__
void
fd_block(int fd)
#else
void
fd_block(fd)
int fd;
#endif
{
int flags;
flags = fcntl(fd, F_GETFL, 0);
if (flags < 0)
{
report(REPORT_ERROR, "fd_block: F_GETFL fcntl: %s\n", sys_err_str(errno));
done(1);
}
#ifdef linux
flags &= ~O_NONBLOCK;
#else
flags &= ~FNDELAY;
#endif
if (fcntl(fd, F_SETFL, flags) < 0)
{
report(REPORT_ERROR, "fd_block: F_SETFL fcntl: %s\n", sys_err_str(errno));
done(1);
}
}
#ifdef __STDC__
int
modified(char *filename, time_t since)
#else
int
modified(filename, since)
char *filename;
time_t since;
#endif
{
struct stat st;
if (stat(filename, &st) < 0)
{
report(REPORT_ERROR, "%s: %s\n", filename, sys_err_str(errno));
return 0;
}
return ((time_t) st.st_mtime > since) ? 1 : 0;
}
#ifdef __STDC__
char *
time2string(time_t t)
#else
char *
time2string(t)
time_t t;
#endif
{
static char buf[64];
int days, hours, mins, secs;
days = t / (60 * 60 * 24);
t %= (60 * 60 * 24);
hours = t / (60 * 60);
t %= (60 * 60);
mins = t / 60;
t %= 60;
secs = t;
buf[0] = '\0';
if (days > 0)
{
SNPRINTF(SIZE(buf, sizeof(buf)), "%d+", days);
}
SNPRINTF(SIZE(buf + strlen(buf), sizeof(buf) - strlen(buf)), "%02d:%02d:%02d", hours, mins, secs);
return buf;
}
#ifdef __STDC__
char *
audio_format_to_string(int format)
#else
char *
audio_format_to_string(format)
int format;
#endif
{
switch (format)
{
case RPLAY_FORMAT_ULAW:
return "ulaw";
case RPLAY_FORMAT_LINEAR_8:
return "linear-8";
case RPLAY_FORMAT_ULINEAR_8:
return "ulinear-8";
case RPLAY_FORMAT_LINEAR_16:
return "linear-16";
case RPLAY_FORMAT_ULINEAR_16:
return "ulinear-16";
case RPLAY_FORMAT_G721:
return "g721";
case RPLAY_FORMAT_G723_3:
return "g723-3";
case RPLAY_FORMAT_G723_5:
return "g723-5";
case RPLAY_FORMAT_GSM:
return "gsm";
default:
return "unknown";
}
}
#ifdef __STDC__
int
string_to_audio_format(char *string)
#else
int
string_to_audio_format(string)
char *string;
#endif
{
if (strcmp(string, "ulaw") == 0
|| strcmp(string, "u_law") == 0
|| strcmp(string, "u-law") == 0)
{
return RPLAY_FORMAT_ULAW;
}
else if (strcmp(string, "linear-16") == 0
|| strcmp(string, "linear_16") == 0
|| strcmp(string, "linear16") == 0)
{
return RPLAY_FORMAT_LINEAR_16;
}
else if (strcmp(string, "ulinear-16") == 0
|| strcmp(string, "ulinear_16") == 0
|| strcmp(string, "ulinear16") == 0)
{
return RPLAY_FORMAT_ULINEAR_16;
}
else if (strcmp(string, "linear-8") == 0
|| strcmp(string, "linear_8") == 0
|| strcmp(string, "linear8") == 0)
{
return RPLAY_FORMAT_LINEAR_8;
}
else if (strcmp(string, "ulinear-8") == 0
|| strcmp(string, "ulinear_8") == 0
|| strcmp(string, "ulinear8") == 0)
{
return RPLAY_FORMAT_ULINEAR_8;
}
else if (strcmp(string, "g721") == 0)
{
return RPLAY_FORMAT_G721;
}
else if (strcmp(string, "g723-3") == 0
|| strcmp(string, "g723_3") == 0)
{
return RPLAY_FORMAT_G723_3;
}
else if (strcmp(string, "g723-5") == 0
|| strcmp(string, "g723_5") == 0)
{
return RPLAY_FORMAT_G723_5;
}
else if (strcmp(string, "gsm") == 0
|| strcmp(string, "GSM") == 0)
{
return RPLAY_FORMAT_GSM;
}
else
{
return RPLAY_FORMAT_NONE;
}
}
#ifdef __STDC__
char *
byte_order_to_string(int byte_order)
#else
char *
byte_order_to_string(byte_order)
int byte_order;
#endif
{
switch (byte_order)
{
case RPLAY_BIG_ENDIAN:
return "big-endian";
case RPLAY_LITTLE_ENDIAN:
return "little-endian";
default:
return "unknown";
}
}
#ifdef __STDC__
int
string_to_byte_order(char *string)
#else
int
string_to_byte_order(string)
char *string;
#endif
{
if (strcmp(string, "big-endian") == 0
|| strcmp(string, "big") == 0)
{
return RPLAY_BIG_ENDIAN;
}
else if (strcmp(string, "little-endian") == 0
|| strcmp(string, "little") == 0)
{
return RPLAY_LITTLE_ENDIAN;
}
else
{
return 0;
}
}
#ifdef __STDC__
char *
storage_to_string(int storage)
#else
char *
storage_to_string(storage)
int storage;
#endif
{
switch (storage)
{
case SOUND_STORAGE_NONE:
return "none";
case SOUND_STORAGE_DISK:
return "disk";
case SOUND_STORAGE_MEMORY:
return "memory";
default:
return "unknown";
}
}
#ifdef __STDC__
int
string_to_storage(char *string)
#else
int
string_to_storage(string)
char *string;
#endif
{
if (strcmp(string, "none") == 0)
{
return SOUND_STORAGE_NONE;
}
else if (strcmp(string, "disk") == 0)
{
return SOUND_STORAGE_DISK;
}
else if (strcmp(string, "memory") == 0)
{
return SOUND_STORAGE_MEMORY;
}
else
{
return SOUND_STORAGE_NULL;
}
}
#ifdef __STDC__
char *
input_to_string(int input)
#else
char *
input_to_string(input)
int input;
#endif
{
switch (input)
{
case SOUND_FILE:
return "file";
case SOUND_FLOW:
return "flow";
#ifdef HAVE_CDROM
case SOUND_CDROM:
return "cdrom";
#endif /* HAVE_CDROM */
case SOUND_VIRTUAL:
return "virtual";
default:
return "unknown";
}
}
#ifdef __STDC__
int
string_to_input(char *string)
#else
int
string_to_input(string)
char *string;
#endif
{
if (strcmp(string, "file") == 0)
{
return SOUND_FILE;
}
else if (strcmp(string, "flow") == 0)
{
return SOUND_FLOW;
}
else
{
return 0;
}
}
#ifdef __STDC__
char *
audio_port_to_string(int port)
#else
char *
audio_port_to_string(port)
int port;
#endif
{
static char string[128];
int n;
string[0] = '\0';
if (BIT(port, RPLAY_AUDIO_PORT_NONE))
{
strncat(string, "none,", sizeof(string) - strlen(string));
}
if (BIT(port, RPLAY_AUDIO_PORT_SPEAKER))
{
strncat(string, "speaker,", sizeof(string) - strlen(string));
}
if (BIT(port, RPLAY_AUDIO_PORT_HEADPHONE))
{
strncat(string, "headphone,", sizeof(string) - strlen(string));
}
if (BIT(port, RPLAY_AUDIO_PORT_LINEOUT))
{
strncat(string, "lineout,", sizeof(string) - strlen(string));
}
string[strlen(string) - 1] = '\0';
return string;
}
unsigned short
little_short(p)
char *p;
{
return (((unsigned long) (((unsigned char *) p)[1])) << 8) |
((unsigned long) (((unsigned char *) p)[0]));
}
unsigned short
big_short(p)
char *p;
{
return (((unsigned long) (((unsigned char *) p)[0])) << 8) |
((unsigned long) (((unsigned char *) p)[1]));
}
unsigned long
little_long(p)
char *p;
{
return (((unsigned long) (((unsigned char *) p)[3])) << 24) |
(((unsigned long) (((unsigned char *) p)[2])) << 16) |
(((unsigned long) (((unsigned char *) p)[1])) << 8) |
((unsigned long) (((unsigned char *) p)[0]));
}
unsigned long
big_long(p)
char *p;
{
return (((unsigned long) (((unsigned char *) p)[0])) << 24) |
(((unsigned long) (((unsigned char *) p)[1])) << 16) |
(((unsigned long) (((unsigned char *) p)[2])) << 8) |
((unsigned long) (((unsigned char *) p)[3]));
}
/*
* C O N V E R T F R O M I E E E E X T E N D E D
*/
/*
* Copyright (C) 1988-1991 Apple Computer, Inc.
* All rights reserved.
*
* Machine-independent I/O routines for IEEE floating-point numbers.
*
* NaN's and infinities are converted to HUGE_VAL or HUGE, which
* happens to be infinity on IEEE machines. Unfortunately, it is
* impossible to preserve NaN's in a machine-independent way.
* Infinities are, however, preserved on IEEE machines.
*
* These routines have been tested on the following machines:
* Apple Macintosh, MPW 3.1 C compiler
* Apple Macintosh, THINK C compiler
* Silicon Graphics IRIS, MIPS compiler
* Cray X/MP and Y/MP
* Digital Equipment VAX
*
*
* Implemented by Malcolm Slaney and Ken Turkowski.
*
* Malcolm Slaney contributions during 1988-1990 include big- and little-
* endian file I/O, conversion to and from Motorola's extended 80-bit
* floating-point format, and conversions to and from IEEE single-
* precision floating-point format.
*
* In 1991, Ken Turkowski implemented the conversions to and from
* IEEE double-precision format, added more precision to the extended
* conversions, and accommodated conversions involving +/- infinity,
* NaN's, and denormalized numbers.
*/
#ifndef HUGE_VAL
#define HUGE_VAL HUGE
#endif /*HUGE_VAL */
#define UnsignedToFloat(u) (((double)((long)(u - 2147483647L - 1))) + 2147483648.0)
/****************************************************************
* Extended precision IEEE floating-point conversion routine.
****************************************************************/
double
ConvertFromIeeeExtended(bytes)
unsigned char *bytes; /* LCN */
{
double f;
int expon;
unsigned long hiMant, loMant;
expon = ((bytes[0] & 0x7F) << 8) | (bytes[1] & 0xFF);
hiMant = ((unsigned long) (bytes[2] & 0xFF) << 24)
| ((unsigned long) (bytes[3] & 0xFF) << 16)
| ((unsigned long) (bytes[4] & 0xFF) << 8)
| ((unsigned long) (bytes[5] & 0xFF));
loMant = ((unsigned long) (bytes[6] & 0xFF) << 24)
| ((unsigned long) (bytes[7] & 0xFF) << 16)
| ((unsigned long) (bytes[8] & 0xFF) << 8)
| ((unsigned long) (bytes[9] & 0xFF));
if (expon == 0 && hiMant == 0 && loMant == 0)
{
f = 0;
}
else
{
if (expon == 0x7FFF)
{ /* Infinity or NaN */
f = HUGE_VAL;
}
else
{
expon -= 16383;
f = ldexp(UnsignedToFloat(hiMant), expon -= 31);
f += ldexp(UnsignedToFloat(loMant), expon -= 32);
}
}
if (bytes[0] & 0x80)
return -f;
else
return f;
}