root / audio / spiceaudio.c @ 3e313753
History | View | Annotate | Download (8.3 kB)
1 | 3e313753 | Gerd Hoffmann | #include "hw/hw.h" |
---|---|---|---|
2 | 3e313753 | Gerd Hoffmann | #include "qemu-timer.h" |
3 | 3e313753 | Gerd Hoffmann | #include "ui/qemu-spice.h" |
4 | 3e313753 | Gerd Hoffmann | |
5 | 3e313753 | Gerd Hoffmann | #define AUDIO_CAP "spice" |
6 | 3e313753 | Gerd Hoffmann | #include "audio.h" |
7 | 3e313753 | Gerd Hoffmann | #include "audio_int.h" |
8 | 3e313753 | Gerd Hoffmann | |
9 | 3e313753 | Gerd Hoffmann | #define LINE_IN_SAMPLES 1024 |
10 | 3e313753 | Gerd Hoffmann | #define LINE_OUT_SAMPLES 1024 |
11 | 3e313753 | Gerd Hoffmann | |
12 | 3e313753 | Gerd Hoffmann | typedef struct SpiceRateCtl { |
13 | 3e313753 | Gerd Hoffmann | int64_t start_ticks; |
14 | 3e313753 | Gerd Hoffmann | int64_t bytes_sent; |
15 | 3e313753 | Gerd Hoffmann | } SpiceRateCtl; |
16 | 3e313753 | Gerd Hoffmann | |
17 | 3e313753 | Gerd Hoffmann | typedef struct SpiceVoiceOut { |
18 | 3e313753 | Gerd Hoffmann | HWVoiceOut hw; |
19 | 3e313753 | Gerd Hoffmann | SpicePlaybackInstance sin; |
20 | 3e313753 | Gerd Hoffmann | SpiceRateCtl rate; |
21 | 3e313753 | Gerd Hoffmann | int active;
|
22 | 3e313753 | Gerd Hoffmann | uint32_t *frame; |
23 | 3e313753 | Gerd Hoffmann | uint32_t *fpos; |
24 | 3e313753 | Gerd Hoffmann | uint32_t fsize; |
25 | 3e313753 | Gerd Hoffmann | } SpiceVoiceOut; |
26 | 3e313753 | Gerd Hoffmann | |
27 | 3e313753 | Gerd Hoffmann | typedef struct SpiceVoiceIn { |
28 | 3e313753 | Gerd Hoffmann | HWVoiceIn hw; |
29 | 3e313753 | Gerd Hoffmann | SpiceRecordInstance sin; |
30 | 3e313753 | Gerd Hoffmann | SpiceRateCtl rate; |
31 | 3e313753 | Gerd Hoffmann | int active;
|
32 | 3e313753 | Gerd Hoffmann | uint32_t samples[LINE_IN_SAMPLES]; |
33 | 3e313753 | Gerd Hoffmann | } SpiceVoiceIn; |
34 | 3e313753 | Gerd Hoffmann | |
35 | 3e313753 | Gerd Hoffmann | static const SpicePlaybackInterface playback_sif = { |
36 | 3e313753 | Gerd Hoffmann | .base.type = SPICE_INTERFACE_PLAYBACK, |
37 | 3e313753 | Gerd Hoffmann | .base.description = "playback",
|
38 | 3e313753 | Gerd Hoffmann | .base.major_version = SPICE_INTERFACE_PLAYBACK_MAJOR, |
39 | 3e313753 | Gerd Hoffmann | .base.minor_version = SPICE_INTERFACE_PLAYBACK_MINOR, |
40 | 3e313753 | Gerd Hoffmann | }; |
41 | 3e313753 | Gerd Hoffmann | |
42 | 3e313753 | Gerd Hoffmann | static const SpiceRecordInterface record_sif = { |
43 | 3e313753 | Gerd Hoffmann | .base.type = SPICE_INTERFACE_RECORD, |
44 | 3e313753 | Gerd Hoffmann | .base.description = "record",
|
45 | 3e313753 | Gerd Hoffmann | .base.major_version = SPICE_INTERFACE_RECORD_MAJOR, |
46 | 3e313753 | Gerd Hoffmann | .base.minor_version = SPICE_INTERFACE_RECORD_MINOR, |
47 | 3e313753 | Gerd Hoffmann | }; |
48 | 3e313753 | Gerd Hoffmann | |
49 | 3e313753 | Gerd Hoffmann | static void *spice_audio_init (void) |
50 | 3e313753 | Gerd Hoffmann | { |
51 | 3e313753 | Gerd Hoffmann | if (!using_spice) {
|
52 | 3e313753 | Gerd Hoffmann | return NULL; |
53 | 3e313753 | Gerd Hoffmann | } |
54 | 3e313753 | Gerd Hoffmann | return &spice_audio_init;
|
55 | 3e313753 | Gerd Hoffmann | } |
56 | 3e313753 | Gerd Hoffmann | |
57 | 3e313753 | Gerd Hoffmann | static void spice_audio_fini (void *opaque) |
58 | 3e313753 | Gerd Hoffmann | { |
59 | 3e313753 | Gerd Hoffmann | /* nothing */
|
60 | 3e313753 | Gerd Hoffmann | } |
61 | 3e313753 | Gerd Hoffmann | |
62 | 3e313753 | Gerd Hoffmann | static void rate_start (SpiceRateCtl *rate) |
63 | 3e313753 | Gerd Hoffmann | { |
64 | 3e313753 | Gerd Hoffmann | memset (rate, 0, sizeof (*rate)); |
65 | 3e313753 | Gerd Hoffmann | rate->start_ticks = qemu_get_clock (vm_clock); |
66 | 3e313753 | Gerd Hoffmann | } |
67 | 3e313753 | Gerd Hoffmann | |
68 | 3e313753 | Gerd Hoffmann | static int rate_get_samples (struct audio_pcm_info *info, SpiceRateCtl *rate) |
69 | 3e313753 | Gerd Hoffmann | { |
70 | 3e313753 | Gerd Hoffmann | int64_t now; |
71 | 3e313753 | Gerd Hoffmann | int64_t ticks; |
72 | 3e313753 | Gerd Hoffmann | int64_t bytes; |
73 | 3e313753 | Gerd Hoffmann | int64_t samples; |
74 | 3e313753 | Gerd Hoffmann | |
75 | 3e313753 | Gerd Hoffmann | now = qemu_get_clock (vm_clock); |
76 | 3e313753 | Gerd Hoffmann | ticks = now - rate->start_ticks; |
77 | 3e313753 | Gerd Hoffmann | bytes = muldiv64 (ticks, info->bytes_per_second, get_ticks_per_sec ()); |
78 | 3e313753 | Gerd Hoffmann | samples = (bytes - rate->bytes_sent) >> info->shift; |
79 | 3e313753 | Gerd Hoffmann | if (samples < 0 || samples > 65536) { |
80 | 3e313753 | Gerd Hoffmann | fprintf (stderr, "Resetting rate control (%" PRId64 " samples)\n", samples); |
81 | 3e313753 | Gerd Hoffmann | rate_start (rate); |
82 | 3e313753 | Gerd Hoffmann | samples = 0;
|
83 | 3e313753 | Gerd Hoffmann | } |
84 | 3e313753 | Gerd Hoffmann | rate->bytes_sent += samples << info->shift; |
85 | 3e313753 | Gerd Hoffmann | return samples;
|
86 | 3e313753 | Gerd Hoffmann | } |
87 | 3e313753 | Gerd Hoffmann | |
88 | 3e313753 | Gerd Hoffmann | /* playback */
|
89 | 3e313753 | Gerd Hoffmann | |
90 | 3e313753 | Gerd Hoffmann | static int line_out_init (HWVoiceOut *hw, struct audsettings *as) |
91 | 3e313753 | Gerd Hoffmann | { |
92 | 3e313753 | Gerd Hoffmann | SpiceVoiceOut *out = container_of (hw, SpiceVoiceOut, hw); |
93 | 3e313753 | Gerd Hoffmann | struct audsettings settings;
|
94 | 3e313753 | Gerd Hoffmann | |
95 | 3e313753 | Gerd Hoffmann | settings.freq = SPICE_INTERFACE_PLAYBACK_FREQ; |
96 | 3e313753 | Gerd Hoffmann | settings.nchannels = SPICE_INTERFACE_PLAYBACK_CHAN; |
97 | 3e313753 | Gerd Hoffmann | settings.fmt = AUD_FMT_S16; |
98 | 3e313753 | Gerd Hoffmann | settings.endianness = AUDIO_HOST_ENDIANNESS; |
99 | 3e313753 | Gerd Hoffmann | |
100 | 3e313753 | Gerd Hoffmann | audio_pcm_init_info (&hw->info, &settings); |
101 | 3e313753 | Gerd Hoffmann | hw->samples = LINE_OUT_SAMPLES; |
102 | 3e313753 | Gerd Hoffmann | out->active = 0;
|
103 | 3e313753 | Gerd Hoffmann | |
104 | 3e313753 | Gerd Hoffmann | out->sin.base.sif = &playback_sif.base; |
105 | 3e313753 | Gerd Hoffmann | qemu_spice_add_interface (&out->sin.base); |
106 | 3e313753 | Gerd Hoffmann | return 0; |
107 | 3e313753 | Gerd Hoffmann | } |
108 | 3e313753 | Gerd Hoffmann | |
109 | 3e313753 | Gerd Hoffmann | static void line_out_fini (HWVoiceOut *hw) |
110 | 3e313753 | Gerd Hoffmann | { |
111 | 3e313753 | Gerd Hoffmann | SpiceVoiceOut *out = container_of (hw, SpiceVoiceOut, hw); |
112 | 3e313753 | Gerd Hoffmann | |
113 | 3e313753 | Gerd Hoffmann | spice_server_remove_interface (&out->sin.base); |
114 | 3e313753 | Gerd Hoffmann | } |
115 | 3e313753 | Gerd Hoffmann | |
116 | 3e313753 | Gerd Hoffmann | static int line_out_run (HWVoiceOut *hw, int live) |
117 | 3e313753 | Gerd Hoffmann | { |
118 | 3e313753 | Gerd Hoffmann | SpiceVoiceOut *out = container_of (hw, SpiceVoiceOut, hw); |
119 | 3e313753 | Gerd Hoffmann | int rpos, decr;
|
120 | 3e313753 | Gerd Hoffmann | int samples;
|
121 | 3e313753 | Gerd Hoffmann | |
122 | 3e313753 | Gerd Hoffmann | if (!live) {
|
123 | 3e313753 | Gerd Hoffmann | return 0; |
124 | 3e313753 | Gerd Hoffmann | } |
125 | 3e313753 | Gerd Hoffmann | |
126 | 3e313753 | Gerd Hoffmann | decr = rate_get_samples (&hw->info, &out->rate); |
127 | 3e313753 | Gerd Hoffmann | decr = audio_MIN (live, decr); |
128 | 3e313753 | Gerd Hoffmann | |
129 | 3e313753 | Gerd Hoffmann | samples = decr; |
130 | 3e313753 | Gerd Hoffmann | rpos = hw->rpos; |
131 | 3e313753 | Gerd Hoffmann | while (samples) {
|
132 | 3e313753 | Gerd Hoffmann | int left_till_end_samples = hw->samples - rpos;
|
133 | 3e313753 | Gerd Hoffmann | int len = audio_MIN (samples, left_till_end_samples);
|
134 | 3e313753 | Gerd Hoffmann | |
135 | 3e313753 | Gerd Hoffmann | if (!out->frame) {
|
136 | 3e313753 | Gerd Hoffmann | spice_server_playback_get_buffer (&out->sin, &out->frame, &out->fsize); |
137 | 3e313753 | Gerd Hoffmann | out->fpos = out->frame; |
138 | 3e313753 | Gerd Hoffmann | } |
139 | 3e313753 | Gerd Hoffmann | if (out->frame) {
|
140 | 3e313753 | Gerd Hoffmann | len = audio_MIN (len, out->fsize); |
141 | 3e313753 | Gerd Hoffmann | hw->clip (out->fpos, hw->mix_buf + rpos, len); |
142 | 3e313753 | Gerd Hoffmann | out->fsize -= len; |
143 | 3e313753 | Gerd Hoffmann | out->fpos += len; |
144 | 3e313753 | Gerd Hoffmann | if (out->fsize == 0) { |
145 | 3e313753 | Gerd Hoffmann | spice_server_playback_put_samples (&out->sin, out->frame); |
146 | 3e313753 | Gerd Hoffmann | out->frame = out->fpos = NULL;
|
147 | 3e313753 | Gerd Hoffmann | } |
148 | 3e313753 | Gerd Hoffmann | } |
149 | 3e313753 | Gerd Hoffmann | rpos = (rpos + len) % hw->samples; |
150 | 3e313753 | Gerd Hoffmann | samples -= len; |
151 | 3e313753 | Gerd Hoffmann | } |
152 | 3e313753 | Gerd Hoffmann | hw->rpos = rpos; |
153 | 3e313753 | Gerd Hoffmann | return decr;
|
154 | 3e313753 | Gerd Hoffmann | } |
155 | 3e313753 | Gerd Hoffmann | |
156 | 3e313753 | Gerd Hoffmann | static int line_out_write (SWVoiceOut *sw, void *buf, int len) |
157 | 3e313753 | Gerd Hoffmann | { |
158 | 3e313753 | Gerd Hoffmann | return audio_pcm_sw_write (sw, buf, len);
|
159 | 3e313753 | Gerd Hoffmann | } |
160 | 3e313753 | Gerd Hoffmann | |
161 | 3e313753 | Gerd Hoffmann | static int line_out_ctl (HWVoiceOut *hw, int cmd, ...) |
162 | 3e313753 | Gerd Hoffmann | { |
163 | 3e313753 | Gerd Hoffmann | SpiceVoiceOut *out = container_of (hw, SpiceVoiceOut, hw); |
164 | 3e313753 | Gerd Hoffmann | |
165 | 3e313753 | Gerd Hoffmann | switch (cmd) {
|
166 | 3e313753 | Gerd Hoffmann | case VOICE_ENABLE:
|
167 | 3e313753 | Gerd Hoffmann | if (out->active) {
|
168 | 3e313753 | Gerd Hoffmann | break;
|
169 | 3e313753 | Gerd Hoffmann | } |
170 | 3e313753 | Gerd Hoffmann | out->active = 1;
|
171 | 3e313753 | Gerd Hoffmann | rate_start (&out->rate); |
172 | 3e313753 | Gerd Hoffmann | spice_server_playback_start (&out->sin); |
173 | 3e313753 | Gerd Hoffmann | break;
|
174 | 3e313753 | Gerd Hoffmann | case VOICE_DISABLE:
|
175 | 3e313753 | Gerd Hoffmann | if (!out->active) {
|
176 | 3e313753 | Gerd Hoffmann | break;
|
177 | 3e313753 | Gerd Hoffmann | } |
178 | 3e313753 | Gerd Hoffmann | out->active = 0;
|
179 | 3e313753 | Gerd Hoffmann | if (out->frame) {
|
180 | 3e313753 | Gerd Hoffmann | memset (out->fpos, 0, out->fsize << 2); |
181 | 3e313753 | Gerd Hoffmann | spice_server_playback_put_samples (&out->sin, out->frame); |
182 | 3e313753 | Gerd Hoffmann | out->frame = out->fpos = NULL;
|
183 | 3e313753 | Gerd Hoffmann | } |
184 | 3e313753 | Gerd Hoffmann | spice_server_playback_stop (&out->sin); |
185 | 3e313753 | Gerd Hoffmann | break;
|
186 | 3e313753 | Gerd Hoffmann | } |
187 | 3e313753 | Gerd Hoffmann | return 0; |
188 | 3e313753 | Gerd Hoffmann | } |
189 | 3e313753 | Gerd Hoffmann | |
190 | 3e313753 | Gerd Hoffmann | /* record */
|
191 | 3e313753 | Gerd Hoffmann | |
192 | 3e313753 | Gerd Hoffmann | static int line_in_init (HWVoiceIn *hw, struct audsettings *as) |
193 | 3e313753 | Gerd Hoffmann | { |
194 | 3e313753 | Gerd Hoffmann | SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw); |
195 | 3e313753 | Gerd Hoffmann | struct audsettings settings;
|
196 | 3e313753 | Gerd Hoffmann | |
197 | 3e313753 | Gerd Hoffmann | settings.freq = SPICE_INTERFACE_RECORD_FREQ; |
198 | 3e313753 | Gerd Hoffmann | settings.nchannels = SPICE_INTERFACE_RECORD_CHAN; |
199 | 3e313753 | Gerd Hoffmann | settings.fmt = AUD_FMT_S16; |
200 | 3e313753 | Gerd Hoffmann | settings.endianness = AUDIO_HOST_ENDIANNESS; |
201 | 3e313753 | Gerd Hoffmann | |
202 | 3e313753 | Gerd Hoffmann | audio_pcm_init_info (&hw->info, &settings); |
203 | 3e313753 | Gerd Hoffmann | hw->samples = LINE_IN_SAMPLES; |
204 | 3e313753 | Gerd Hoffmann | in->active = 0;
|
205 | 3e313753 | Gerd Hoffmann | |
206 | 3e313753 | Gerd Hoffmann | in->sin.base.sif = &record_sif.base; |
207 | 3e313753 | Gerd Hoffmann | qemu_spice_add_interface (&in->sin.base); |
208 | 3e313753 | Gerd Hoffmann | return 0; |
209 | 3e313753 | Gerd Hoffmann | } |
210 | 3e313753 | Gerd Hoffmann | |
211 | 3e313753 | Gerd Hoffmann | static void line_in_fini (HWVoiceIn *hw) |
212 | 3e313753 | Gerd Hoffmann | { |
213 | 3e313753 | Gerd Hoffmann | SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw); |
214 | 3e313753 | Gerd Hoffmann | |
215 | 3e313753 | Gerd Hoffmann | spice_server_remove_interface (&in->sin.base); |
216 | 3e313753 | Gerd Hoffmann | } |
217 | 3e313753 | Gerd Hoffmann | |
218 | 3e313753 | Gerd Hoffmann | static int line_in_run (HWVoiceIn *hw) |
219 | 3e313753 | Gerd Hoffmann | { |
220 | 3e313753 | Gerd Hoffmann | SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw); |
221 | 3e313753 | Gerd Hoffmann | int num_samples;
|
222 | 3e313753 | Gerd Hoffmann | int ready;
|
223 | 3e313753 | Gerd Hoffmann | int len[2]; |
224 | 3e313753 | Gerd Hoffmann | uint64_t delta_samp; |
225 | 3e313753 | Gerd Hoffmann | const uint32_t *samples;
|
226 | 3e313753 | Gerd Hoffmann | |
227 | 3e313753 | Gerd Hoffmann | if (!(num_samples = hw->samples - audio_pcm_hw_get_live_in (hw))) {
|
228 | 3e313753 | Gerd Hoffmann | return 0; |
229 | 3e313753 | Gerd Hoffmann | } |
230 | 3e313753 | Gerd Hoffmann | |
231 | 3e313753 | Gerd Hoffmann | delta_samp = rate_get_samples (&hw->info, &in->rate); |
232 | 3e313753 | Gerd Hoffmann | num_samples = audio_MIN (num_samples, delta_samp); |
233 | 3e313753 | Gerd Hoffmann | |
234 | 3e313753 | Gerd Hoffmann | ready = spice_server_record_get_samples (&in->sin, in->samples, num_samples); |
235 | 3e313753 | Gerd Hoffmann | samples = in->samples; |
236 | 3e313753 | Gerd Hoffmann | if (ready == 0) { |
237 | 3e313753 | Gerd Hoffmann | static const uint32_t silence[LINE_IN_SAMPLES]; |
238 | 3e313753 | Gerd Hoffmann | samples = silence; |
239 | 3e313753 | Gerd Hoffmann | ready = LINE_IN_SAMPLES; |
240 | 3e313753 | Gerd Hoffmann | } |
241 | 3e313753 | Gerd Hoffmann | |
242 | 3e313753 | Gerd Hoffmann | num_samples = audio_MIN (ready, num_samples); |
243 | 3e313753 | Gerd Hoffmann | |
244 | 3e313753 | Gerd Hoffmann | if (hw->wpos + num_samples > hw->samples) {
|
245 | 3e313753 | Gerd Hoffmann | len[0] = hw->samples - hw->wpos;
|
246 | 3e313753 | Gerd Hoffmann | len[1] = num_samples - len[0]; |
247 | 3e313753 | Gerd Hoffmann | } else {
|
248 | 3e313753 | Gerd Hoffmann | len[0] = num_samples;
|
249 | 3e313753 | Gerd Hoffmann | len[1] = 0; |
250 | 3e313753 | Gerd Hoffmann | } |
251 | 3e313753 | Gerd Hoffmann | |
252 | 3e313753 | Gerd Hoffmann | hw->conv (hw->conv_buf + hw->wpos, samples, len[0], &nominal_volume);
|
253 | 3e313753 | Gerd Hoffmann | |
254 | 3e313753 | Gerd Hoffmann | if (len[1]) { |
255 | 3e313753 | Gerd Hoffmann | hw->conv (hw->conv_buf, samples + len[0], len[1], |
256 | 3e313753 | Gerd Hoffmann | &nominal_volume); |
257 | 3e313753 | Gerd Hoffmann | } |
258 | 3e313753 | Gerd Hoffmann | |
259 | 3e313753 | Gerd Hoffmann | hw->wpos = (hw->wpos + num_samples) % hw->samples; |
260 | 3e313753 | Gerd Hoffmann | |
261 | 3e313753 | Gerd Hoffmann | return num_samples;
|
262 | 3e313753 | Gerd Hoffmann | } |
263 | 3e313753 | Gerd Hoffmann | |
264 | 3e313753 | Gerd Hoffmann | static int line_in_read (SWVoiceIn *sw, void *buf, int size) |
265 | 3e313753 | Gerd Hoffmann | { |
266 | 3e313753 | Gerd Hoffmann | return audio_pcm_sw_read (sw, buf, size);
|
267 | 3e313753 | Gerd Hoffmann | } |
268 | 3e313753 | Gerd Hoffmann | |
269 | 3e313753 | Gerd Hoffmann | static int line_in_ctl (HWVoiceIn *hw, int cmd, ...) |
270 | 3e313753 | Gerd Hoffmann | { |
271 | 3e313753 | Gerd Hoffmann | SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw); |
272 | 3e313753 | Gerd Hoffmann | |
273 | 3e313753 | Gerd Hoffmann | switch (cmd) {
|
274 | 3e313753 | Gerd Hoffmann | case VOICE_ENABLE:
|
275 | 3e313753 | Gerd Hoffmann | if (in->active) {
|
276 | 3e313753 | Gerd Hoffmann | break;
|
277 | 3e313753 | Gerd Hoffmann | } |
278 | 3e313753 | Gerd Hoffmann | in->active = 1;
|
279 | 3e313753 | Gerd Hoffmann | rate_start (&in->rate); |
280 | 3e313753 | Gerd Hoffmann | spice_server_record_start (&in->sin); |
281 | 3e313753 | Gerd Hoffmann | break;
|
282 | 3e313753 | Gerd Hoffmann | case VOICE_DISABLE:
|
283 | 3e313753 | Gerd Hoffmann | if (!in->active) {
|
284 | 3e313753 | Gerd Hoffmann | break;
|
285 | 3e313753 | Gerd Hoffmann | } |
286 | 3e313753 | Gerd Hoffmann | in->active = 0;
|
287 | 3e313753 | Gerd Hoffmann | spice_server_record_stop (&in->sin); |
288 | 3e313753 | Gerd Hoffmann | break;
|
289 | 3e313753 | Gerd Hoffmann | } |
290 | 3e313753 | Gerd Hoffmann | return 0; |
291 | 3e313753 | Gerd Hoffmann | } |
292 | 3e313753 | Gerd Hoffmann | |
293 | 3e313753 | Gerd Hoffmann | static struct audio_option audio_options[] = { |
294 | 3e313753 | Gerd Hoffmann | { /* end of list */ },
|
295 | 3e313753 | Gerd Hoffmann | }; |
296 | 3e313753 | Gerd Hoffmann | |
297 | 3e313753 | Gerd Hoffmann | static struct audio_pcm_ops audio_callbacks = { |
298 | 3e313753 | Gerd Hoffmann | .init_out = line_out_init, |
299 | 3e313753 | Gerd Hoffmann | .fini_out = line_out_fini, |
300 | 3e313753 | Gerd Hoffmann | .run_out = line_out_run, |
301 | 3e313753 | Gerd Hoffmann | .write = line_out_write, |
302 | 3e313753 | Gerd Hoffmann | .ctl_out = line_out_ctl, |
303 | 3e313753 | Gerd Hoffmann | |
304 | 3e313753 | Gerd Hoffmann | .init_in = line_in_init, |
305 | 3e313753 | Gerd Hoffmann | .fini_in = line_in_fini, |
306 | 3e313753 | Gerd Hoffmann | .run_in = line_in_run, |
307 | 3e313753 | Gerd Hoffmann | .read = line_in_read, |
308 | 3e313753 | Gerd Hoffmann | .ctl_in = line_in_ctl, |
309 | 3e313753 | Gerd Hoffmann | }; |
310 | 3e313753 | Gerd Hoffmann | |
311 | 3e313753 | Gerd Hoffmann | struct audio_driver spice_audio_driver = {
|
312 | 3e313753 | Gerd Hoffmann | .name = "spice",
|
313 | 3e313753 | Gerd Hoffmann | .descr = "spice audio driver",
|
314 | 3e313753 | Gerd Hoffmann | .options = audio_options, |
315 | 3e313753 | Gerd Hoffmann | .init = spice_audio_init, |
316 | 3e313753 | Gerd Hoffmann | .fini = spice_audio_fini, |
317 | 3e313753 | Gerd Hoffmann | .pcm_ops = &audio_callbacks, |
318 | 3e313753 | Gerd Hoffmann | .max_voices_out = 1,
|
319 | 3e313753 | Gerd Hoffmann | .max_voices_in = 1,
|
320 | 3e313753 | Gerd Hoffmann | .voice_size_out = sizeof (SpiceVoiceOut),
|
321 | 3e313753 | Gerd Hoffmann | .voice_size_in = sizeof (SpiceVoiceIn),
|
322 | 3e313753 | Gerd Hoffmann | }; |
323 | 3e313753 | Gerd Hoffmann | |
324 | 3e313753 | Gerd Hoffmann | void qemu_spice_audio_init (void) |
325 | 3e313753 | Gerd Hoffmann | { |
326 | 3e313753 | Gerd Hoffmann | spice_audio_driver.can_be_default = 1;
|
327 | 3e313753 | Gerd Hoffmann | } |