1 #ifndef lint
2 static char rcsid[] =
3 "$Id: encode_sun.c,v 1.3 1997/03/25 15:21:27 tommy Exp $";
4 #endif
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <fcntl.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <signal.h>
12 #include <err.h>
13 #include <arpa/inet.h>
14 
15 #include <sys/soundcard.h>
16 
17 #include "play.h"
18 #include "encode_sun.h"
19 
check_sunaudio(char * audio_file)20 sun_header_t *check_sunaudio(char *audio_file)
21 {
22     int fd;
23     static sun_header_t header;
24 
25     if ((fd = open(audio_file, O_RDONLY)) < 0) {
26 	warn("%s", audio_file);
27 	return (sun_header_t*)FAIL;
28     }
29     if (read(fd, &header, SUNAUDIO_HDR_SIZE) < 0) {
30 	warn("%s", audio_file);
31 	return NULL;
32     }
33 
34     header.magic = htonl(header.magic);
35     if (header.magic != SUNAUDIO_MAGIC)
36         return NULL;
37 
38     header.head_length = htonl(header.head_length);
39     if (header.head_length > SUNAUDIO_HDR_SIZE) {
40 	size_t infosize = header.head_length - SUNAUDIO_HDR_SIZE;
41 	if ((header.infop = malloc(infosize)) == NULL) {
42 	    warn("%s", "malloc");
43 	    return (sun_header_t*)FAIL;
44 	}
45 	if (read(fd, header.infop, infosize) < 0) {
46 	    warn("%s", audio_file);
47 	    return (sun_header_t*)FAIL;
48 	}
49     } else {
50 	header.infop = NULL;
51     }
52     close(fd);
53 
54     header.head_length = header.head_length;
55     header.data_length = htonl(header.data_length);
56     header.data_format = htonl(header.data_format);
57     header.sample_rate = htonl(header.sample_rate);
58     header.channels    = htonl(header.channels);
59     switch (header.data_format) {
60     case SUNAUDIO_ENCODING_MULAW_8:
61         header.data_format = AFMT_MU_LAW;
62         break;
63     case SUNAUDIO_ENCODING_LINEAR_8:
64     case SUNAUDIO_ENCODING_LINEAR_16:
65     case SUNAUDIO_ENCODING_LINEAR_24:
66     case SUNAUDIO_ENCODING_LINEAR_32:
67         header.data_format = AFMT_S16_LE;
68         break;
69     case SUNAUDIO_ENCODING_FLOAT:
70     case SUNAUDIO_ENCODING_DOUBLE:
71         header.data_format = AFMT_MU_LAW;
72         break;
73     default:
74 	warn("%s: Unknown format", header.data_format);
75 	return (sun_header_t*)FAIL;
76     }
77     return &header;
78 }
79 
print_sun_header(sun_header_t * headp)80 void print_sun_header(sun_header_t *headp)
81 {
82     printf("       magic = %d\n", headp->magic);
83     printf("headerlength = %d\n", headp->head_length);
84     printf(" data_length = %d\n", headp->data_length);
85     printf(" data_format = %d\n", headp->data_format);
86     printf(" sample_rate = %d\n", headp->sample_rate);
87     printf("    channels = %d\n", headp->channels);
88     if (headp->infop != NULL)
89 	printf("        info = %s\n", headp->infop);
90 }
91 
play_sunaudio(char * audio_file,sun_header_t * headp,arg_params_t * params)92 int play_sunaudio(char *audio_file, sun_header_t *headp, arg_params_t *params)
93 {
94     unsigned char *bufp;
95     int stat;
96     int devfd, filefd;
97     char *device;
98 
99     if (f_extra)
100 	print_sun_header(headp);
101 
102     if (params->device == NULL)
103 	device = DEV_DSP;
104     else
105 	device = params->device;
106 
107     if (headp->infop != NULL)
108         free(headp->infop);
109 
110     if (headp->data_length == SUNAUDIO_UNKNOWN_SIZE)
111         headp->data_length = 4096;
112 
113     if ((devfd = open(device, O_WRONLY)) < 0)
114 	err(1, "%s", device);
115 
116     if (f_hasdsp && ioctl(devfd, SNDCTL_DSP_SETFMT, &headp->data_format) < 0) {
117 	warn("%s", device);
118 	stat = FAIL; goto failplay0;
119     }
120     if ((filefd = open(audio_file, O_RDONLY)) < 0) {
121 	warn("%s", audio_file);
122 	stat = FAIL; goto failplay0;
123     }
124     if ((bufp = (char*)malloc(headp->data_length)) == NULL) {
125 	warn("%s", "malloc");
126 	stat = FAIL; goto failplay1;
127     }
128 
129     intr = FALSE;
130     signal(SIGINT, intr_play);
131 
132     if ((stat = read(filefd, bufp, headp->head_length)) < 0) {
133 	warn("%s", audio_file); goto failplay2;
134     }
135 
136     if (!intr && (stat = read(filefd, bufp, headp->data_length)) < 0) {
137 	warn("%s", audio_file); goto failplay2;
138     }
139     if (!intr && (stat = write(devfd, bufp, stat)) < 0) {
140 	warn("%s", audio_file); goto failplay2;
141     }
142 
143 failplay2:
144     free(bufp);
145 failplay1:
146     close(filefd);
147 failplay0:
148     close(devfd);
149 
150     return stat;
151 }
152