]> Git Repo - qemu.git/blame - audio/wavcapture.c
Include qapi/error.h exactly where needed
[qemu.git] / audio / wavcapture.c
CommitLineData
6086a565 1#include "qemu/osdep.h"
87ecb68b 2#include "hw/hw.h"
83c9089e 3#include "monitor/monitor.h"
e688df6b 4#include "qapi/error.h"
d49b6836 5#include "qemu/error-report.h"
87ecb68b 6#include "audio.h"
8ead62cf
FB
7
8typedef struct {
b04df2a4 9 FILE *f;
8ead62cf 10 int bytes;
ec36b695
FB
11 char *path;
12 int freq;
13 int bits;
14 int nchannels;
15 CaptureVoiceOut *cap;
8ead62cf
FB
16} WAVState;
17
18/* VICE code: Store number as little endian. */
19static void le_store (uint8_t *buf, uint32_t val, int len)
20{
21 int i;
22 for (i = 0; i < len; i++) {
23 buf[i] = (uint8_t) (val & 0xff);
24 val >>= 8;
25 }
26}
27
ec36b695 28static void wav_notify (void *opaque, audcnotification_e cmd)
8ead62cf 29{
ec36b695
FB
30 (void) opaque;
31 (void) cmd;
32}
8ead62cf 33
ec36b695
FB
34static void wav_destroy (void *opaque)
35{
36 WAVState *wav = opaque;
37 uint8_t rlen[4];
38 uint8_t dlen[4];
39 uint32_t datalen = wav->bytes;
40 uint32_t rifflen = datalen + 36;
b04df2a4 41 Monitor *mon = cur_mon;
8ead62cf 42
e84a4fed
FB
43 if (wav->f) {
44 le_store (rlen, rifflen, 4);
45 le_store (dlen, datalen, 4);
f941aa25 46
b04df2a4
JQ
47 if (fseek (wav->f, 4, SEEK_SET)) {
48 monitor_printf (mon, "wav_destroy: rlen fseek failed\nReason: %s\n",
49 strerror (errno));
50 goto doclose;
51 }
52 if (fwrite (rlen, 4, 1, wav->f) != 1) {
53 monitor_printf (mon, "wav_destroy: rlen fwrite failed\nReason %s\n",
54 strerror (errno));
55 goto doclose;
56 }
57 if (fseek (wav->f, 32, SEEK_CUR)) {
58 monitor_printf (mon, "wav_destroy: dlen fseek failed\nReason %s\n",
59 strerror (errno));
60 goto doclose;
61 }
62 if (fwrite (dlen, 1, 4, wav->f) != 4) {
63 monitor_printf (mon, "wav_destroy: dlen fwrite failed\nReason %s\n",
64 strerror (errno));
65 goto doclose;
66 }
67 doclose:
68 if (fclose (wav->f)) {
69e99504 69 error_report("wav_destroy: fclose failed: %s", strerror(errno));
b04df2a4 70 }
8ead62cf 71 }
f941aa25 72
7267c094 73 g_free (wav->path);
8ead62cf
FB
74}
75
ec36b695 76static void wav_capture (void *opaque, void *buf, int size)
8ead62cf
FB
77{
78 WAVState *wav = opaque;
79
b04df2a4
JQ
80 if (fwrite (buf, size, 1, wav->f) != 1) {
81 monitor_printf (cur_mon, "wav_capture: fwrite error\nReason: %s",
82 strerror (errno));
83 }
8ead62cf
FB
84 wav->bytes += size;
85}
86
ec36b695
FB
87static void wav_capture_destroy (void *opaque)
88{
89 WAVState *wav = opaque;
90
91 AUD_del_capture (wav->cap, wav);
7bdfd907 92 g_free (wav);
ec36b695
FB
93}
94
95static void wav_capture_info (void *opaque)
96{
97 WAVState *wav = opaque;
98 char *path = wav->path;
99
b04df2a4
JQ
100 monitor_printf (cur_mon, "Capturing audio(%d,%d,%d) to %s: %d bytes\n",
101 wav->freq, wav->bits, wav->nchannels,
102 path ? path : "<not available>", wav->bytes);
ec36b695
FB
103}
104
105static struct capture_ops wav_capture_ops = {
106 .destroy = wav_capture_destroy,
107 .info = wav_capture_info
108};
109
110int wav_start_capture (CaptureState *s, const char *path, int freq,
111 int bits, int nchannels)
8ead62cf 112{
376253ec 113 Monitor *mon = cur_mon;
8ead62cf
FB
114 WAVState *wav;
115 uint8_t hdr[] = {
116 0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56,
117 0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
118 0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04,
119 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00
120 };
1ea879e5 121 struct audsettings as;
8ead62cf 122 struct audio_capture_ops ops;
ec36b695
FB
123 int stereo, bits16, shift;
124 CaptureVoiceOut *cap;
125
126 if (bits != 8 && bits != 16) {
b04df2a4 127 monitor_printf (mon, "incorrect bit count %d, must be 8 or 16\n", bits);
ec36b695
FB
128 return -1;
129 }
130
131 if (nchannels != 1 && nchannels != 2) {
b04df2a4
JQ
132 monitor_printf (mon, "incorrect channel count %d, must be 1 or 2\n",
133 nchannels);
ec36b695
FB
134 return -1;
135 }
8ead62cf 136
ec36b695
FB
137 stereo = nchannels == 2;
138 bits16 = bits == 16;
8ead62cf
FB
139
140 as.freq = freq;
141 as.nchannels = 1 << stereo;
142 as.fmt = bits16 ? AUD_FMT_S16 : AUD_FMT_U8;
d929eba5 143 as.endianness = 0;
8ead62cf 144
ec36b695
FB
145 ops.notify = wav_notify;
146 ops.capture = wav_capture;
147 ops.destroy = wav_destroy;
8ead62cf 148
7267c094 149 wav = g_malloc0 (sizeof (*wav));
8ead62cf
FB
150
151 shift = bits16 + stereo;
152 hdr[34] = bits16 ? 0x10 : 0x08;
153
154 le_store (hdr + 22, as.nchannels, 2);
155 le_store (hdr + 24, freq, 4);
156 le_store (hdr + 28, freq << shift, 4);
157 le_store (hdr + 32, 1 << shift, 2);
158
b04df2a4 159 wav->f = fopen (path, "wb");
8ead62cf 160 if (!wav->f) {
b04df2a4
JQ
161 monitor_printf (mon, "Failed to open wave file `%s'\nReason: %s\n",
162 path, strerror (errno));
7267c094 163 g_free (wav);
ec36b695 164 return -1;
8ead62cf
FB
165 }
166
7267c094 167 wav->path = g_strdup (path);
ec36b695
FB
168 wav->bits = bits;
169 wav->nchannels = nchannels;
170 wav->freq = freq;
171
b04df2a4
JQ
172 if (fwrite (hdr, sizeof (hdr), 1, wav->f) != 1) {
173 monitor_printf (mon, "Failed to write header\nReason: %s\n",
174 strerror (errno));
175 goto error_free;
176 }
ec36b695 177
1a7dafce 178 cap = AUD_add_capture (&as, &ops, wav);
ec36b695 179 if (!cap) {
b04df2a4
JQ
180 monitor_printf (mon, "Failed to add audio capture\n");
181 goto error_free;
ec36b695
FB
182 }
183
184 wav->cap = cap;
185 s->opaque = wav;
186 s->ops = wav_capture_ops;
187 return 0;
b04df2a4
JQ
188
189error_free:
190 g_free (wav->path);
191 if (fclose (wav->f)) {
192 monitor_printf (mon, "Failed to close wave file\nReason: %s\n",
193 strerror (errno));
194 }
195 g_free (wav);
196 return -1;
8ead62cf 197}
This page took 0.540386 seconds and 4 git commands to generate.