#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <Audio.h>
#include <AudioHdr.h>
#include <parse.h>
#include <convert.h>
static struct keyword_table Keywords[] = {
(char *)"encoding", K_ENCODING,
(char *)"rate", K_RATE,
(char *)"channels", K_CHANNELS,
(char *)"offset", K_OFFSET,
(char *)"format", K_FORMAT,
NULL, K_NULL,
};
keyword_type
do_lookup(
char *s,
struct keyword_table *kp)
{
struct keyword_table *tkp = NULL;
for (; kp && kp->name; kp++) {
if (strncmp(s, kp->name, strlen(s)) == 0) {
if (strlen(s) == strlen(kp->name)) {
return (kp->type);
} else {
if (tkp) {
return (K_AMBIG);
} else {
tkp = kp;
}
}
}
}
if (tkp) {
return (tkp->type);
} else {
return (K_NULL);
}
}
int
fileformat_parse(
char *val,
format_type& format)
{
if (strcasecmp(val, "sun") == 0) {
format = F_SUN;
} else if (strcasecmp(val, "raw") == 0) {
format = F_RAW;
} else if (strcasecmp(val, "aiff") == 0) {
Err(MGET("AIFF not yet supported\n"));
return (-1);
} else {
return (-1);
}
return (0);
}
int
audioformat_parse(
char *val,
AudioHdr& hdr)
{
if (strcasecmp(val, "dat") == 0) {
hdr.sample_rate = 48000;
hdr.channels = 2;
hdr.encoding = LINEAR;
hdr.samples_per_unit = 1;
hdr.bytes_per_unit = 2;
} else if (strcasecmp(val, "cd") == 0) {
hdr.sample_rate = 44100;
hdr.channels = 2;
hdr.encoding = LINEAR;
hdr.samples_per_unit = 1;
hdr.bytes_per_unit = 2;
} else if (strcasecmp(val, "voice") == 0) {
hdr.sample_rate = 8000;
hdr.channels = 1;
hdr.encoding = ULAW;
hdr.samples_per_unit = 1;
hdr.bytes_per_unit = 1;
} else {
return (-1);
}
return (0);
}
int
parse_format(
char *s,
AudioHdr& hdr,
format_type& format,
off_t& offset)
{
char *cp;
char *buf;
char *key;
char *val;
char *cp2;
offset = 0;
format = F_SUN;
if (!(s && *s))
return (0);
if (hdr.FormatParse(s) == AUDIO_SUCCESS) {
return (0);
}
buf = strdup(s);
for (cp = strtok(buf, ","); cp; cp = strtok(NULL, ",")) {
if (cp2 = strchr(cp, '=')) {
*cp2++ = '\0';
key = cp;
val = cp2;
switch (do_lookup(key, Keywords)) {
case K_ENCODING:
if (hdr.EncodingParse(val)) {
Err(MGET(
"invalid encoding option: %s\n"),
val);
goto parse_error;
}
break;
case K_RATE:
if (hdr.RateParse(val)) {
Err(MGET("invalid sample rate: %s\n"),
val);
goto parse_error;
}
break;
case K_CHANNELS:
if (hdr.ChannelParse(val)) {
Err(MGET(
"invalid channels option: %s\n"),
val);
goto parse_error;
}
break;
case K_FORMAT:
if (fileformat_parse(val, format) < 0) {
Err(MGET("unknown format: %s\n"), val);
goto parse_error;
}
break;
case K_OFFSET:
offset = (off_t)atoi(val);
break;
case K_AMBIG:
Err(MGET("ambiguous keyword: %s\n"), key);
goto parse_error;
case K_NULL:
Err(MGET("null keyword: =%s\n"), val);
goto parse_error;
default:
Err(MGET("invalid keyword: %s\n"), key);
goto parse_error;
}
} else {
val = cp;
if (hdr.EncodingParse(val) &&
(audioformat_parse(val, hdr) < 0) &&
(fileformat_parse(val, format) < 0)) {
if (!hdr.RateParse(val)) {
if (hdr.sample_rate < 1000) {
int x;
char y[10];
if (sscanf(val, " %lf %9s",
&x, y) != 1) {
Err(
MGET("ambiguous numeric option: %s\n"),
val);
goto parse_error;
}
}
} else if (hdr.ChannelParse(val)) {
Err(MGET("invalid option value: %s\n"),
val);
goto parse_error;
}
}
}
}
free(buf);
return (0);
parse_error:
free(buf);
return (-1);
}