]> git.proxmox.com Git - mirror_qemu.git/blame - audio/wavcapture.c
Revert "vl: Fix to create migration object before block backends again"
[mirror_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;
8ead62cf 41
e84a4fed
FB
42 if (wav->f) {
43 le_store (rlen, rifflen, 4);
44 le_store (dlen, datalen, 4);
f941aa25 45
b04df2a4 46 if (fseek (wav->f, 4, SEEK_SET)) {
8beaac12
DDAG
47 error_report("wav_destroy: rlen fseek failed: %s",
48 strerror(errno));
b04df2a4
JQ
49 goto doclose;
50 }
51 if (fwrite (rlen, 4, 1, wav->f) != 1) {
8beaac12
DDAG
52 error_report("wav_destroy: rlen fwrite failed: %s",
53 strerror(errno));
b04df2a4
JQ
54 goto doclose;
55 }
56 if (fseek (wav->f, 32, SEEK_CUR)) {
8beaac12
DDAG
57 error_report("wav_destroy: dlen fseek failed: %s",
58 strerror(errno));
b04df2a4
JQ
59 goto doclose;
60 }
61 if (fwrite (dlen, 1, 4, wav->f) != 4) {
8beaac12
DDAG
62 error_report("wav_destroy: dlen fwrite failed: %s",
63 strerror(errno));
b04df2a4
JQ
64 goto doclose;
65 }
66 doclose:
67 if (fclose (wav->f)) {
69e99504 68 error_report("wav_destroy: fclose failed: %s", strerror(errno));
b04df2a4 69 }
8ead62cf 70 }
f941aa25 71
7267c094 72 g_free (wav->path);
8ead62cf
FB
73}
74
ec36b695 75static void wav_capture (void *opaque, void *buf, int size)
8ead62cf
FB
76{
77 WAVState *wav = opaque;
78
b04df2a4 79 if (fwrite (buf, size, 1, wav->f) != 1) {
8beaac12 80 error_report("wav_capture: fwrite error: %s", strerror(errno));
b04df2a4 81 }
8ead62cf
FB
82 wav->bytes += size;
83}
84
ec36b695
FB
85static void wav_capture_destroy (void *opaque)
86{
87 WAVState *wav = opaque;
88
89 AUD_del_capture (wav->cap, wav);
7bdfd907 90 g_free (wav);
ec36b695
FB
91}
92
93static void wav_capture_info (void *opaque)
94{
95 WAVState *wav = opaque;
96 char *path = wav->path;
97
b04df2a4
JQ
98 monitor_printf (cur_mon, "Capturing audio(%d,%d,%d) to %s: %d bytes\n",
99 wav->freq, wav->bits, wav->nchannels,
100 path ? path : "<not available>", wav->bytes);
ec36b695
FB
101}
102
103static struct capture_ops wav_capture_ops = {
104 .destroy = wav_capture_destroy,
105 .info = wav_capture_info
106};
107
108int wav_start_capture (CaptureState *s, const char *path, int freq,
109 int bits, int nchannels)
8ead62cf
FB
110{
111 WAVState *wav;
112 uint8_t hdr[] = {
113 0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56,
114 0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
115 0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04,
116 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00
117 };
1ea879e5 118 struct audsettings as;
8ead62cf 119 struct audio_capture_ops ops;
ec36b695
FB
120 int stereo, bits16, shift;
121 CaptureVoiceOut *cap;
122
123 if (bits != 8 && bits != 16) {
8beaac12 124 error_report("incorrect bit count %d, must be 8 or 16", bits);
ec36b695
FB
125 return -1;
126 }
127
128 if (nchannels != 1 && nchannels != 2) {
8beaac12
DDAG
129 error_report("incorrect channel count %d, must be 1 or 2",
130 nchannels);
ec36b695
FB
131 return -1;
132 }
8ead62cf 133
ec36b695
FB
134 stereo = nchannels == 2;
135 bits16 = bits == 16;
8ead62cf
FB
136
137 as.freq = freq;
138 as.nchannels = 1 << stereo;
85bc5852 139 as.fmt = bits16 ? AUDIO_FORMAT_S16 : AUDIO_FORMAT_U8;
d929eba5 140 as.endianness = 0;
8ead62cf 141
ec36b695
FB
142 ops.notify = wav_notify;
143 ops.capture = wav_capture;
144 ops.destroy = wav_destroy;
8ead62cf 145
7267c094 146 wav = g_malloc0 (sizeof (*wav));
8ead62cf
FB
147
148 shift = bits16 + stereo;
149 hdr[34] = bits16 ? 0x10 : 0x08;
150
151 le_store (hdr + 22, as.nchannels, 2);
152 le_store (hdr + 24, freq, 4);
153 le_store (hdr + 28, freq << shift, 4);
154 le_store (hdr + 32, 1 << shift, 2);
155
b04df2a4 156 wav->f = fopen (path, "wb");
8ead62cf 157 if (!wav->f) {
8beaac12
DDAG
158 error_report("Failed to open wave file `%s': %s",
159 path, strerror(errno));
7267c094 160 g_free (wav);
ec36b695 161 return -1;
8ead62cf
FB
162 }
163
7267c094 164 wav->path = g_strdup (path);
ec36b695
FB
165 wav->bits = bits;
166 wav->nchannels = nchannels;
167 wav->freq = freq;
168
b04df2a4 169 if (fwrite (hdr, sizeof (hdr), 1, wav->f) != 1) {
8beaac12 170 error_report("Failed to write header: %s", strerror(errno));
b04df2a4
JQ
171 goto error_free;
172 }
ec36b695 173
1a7dafce 174 cap = AUD_add_capture (&as, &ops, wav);
ec36b695 175 if (!cap) {
8beaac12 176 error_report("Failed to add audio capture");
b04df2a4 177 goto error_free;
ec36b695
FB
178 }
179
180 wav->cap = cap;
181 s->opaque = wav;
182 s->ops = wav_capture_ops;
183 return 0;
b04df2a4
JQ
184
185error_free:
186 g_free (wav->path);
187 if (fclose (wav->f)) {
8beaac12 188 error_report("Failed to close wave file: %s", strerror(errno));
b04df2a4
JQ
189 }
190 g_free (wav);
191 return -1;
8ead62cf 192}