Revision 1d14ffa9

b/Changelog
1
version 0.7.3:
2

  
3
  - Mac OS X cocoa improvements (Mike Kronenberg)
4
  - DirectSound driver (malc)
5
  - new audio options: '-soundhw' and 'audio-help' (malc)
6
  - ES1370 PCI audio device (malc)
7
   
1 8
version 0.7.2:
2 9
  
3 10
  - x86_64 fixes (Win2000 and Linux 2.6 boot in 32 bit)
b/Makefile.target
262 262
VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o
263 263
VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o
264 264

  
265
SOUND_HW = sb16.o
265
SOUND_HW = sb16.o es1370.o
266 266
AUDIODRV = audio.o noaudio.o wavaudio.o
267 267
ifdef CONFIG_SDL
268 268
AUDIODRV += sdlaudio.o
......
270 270
ifdef CONFIG_OSS
271 271
AUDIODRV += ossaudio.o
272 272
endif
273

  
274
pc.o: DEFINES := -DUSE_SB16 $(DEFINES)
275

  
276
ifdef CONFIG_ADLIB
277
SOUND_HW += fmopl.o adlib.o
273
ifdef CONFIG_COREAUDIO
274
AUDIODRV += coreaudio.o
275
endif
276
ifdef CONFIG_ALSA
277
AUDIODRV += alsaaudio.o
278
LIBS += -lasound
279
endif
280
ifdef CONFIG_DSOUND
281
AUDIODRV += dsoundaudio.o
282
LIBS += -lole32 -ldxguid
278 283
endif
279

  
280 284
ifdef CONFIG_FMOD
281 285
AUDIODRV += fmodaudio.o
282 286
audio.o fmodaudio.o: DEFINES := -I$(CONFIG_FMOD_INC) $(DEFINES)
283 287
LIBS += $(CONFIG_FMOD_LIB)
284 288
endif
289
ifdef CONFIG_ADLIB
290
SOUND_HW += fmopl.o adlib.o
291
endif
285 292

  
286 293
ifeq ($(TARGET_BASE_ARCH), i386)
287 294
# Hardware support
288 295
VL_OBJS+= ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
289 296
VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o
290 297
VL_OBJS+= cirrus_vga.o mixeng.o apic.o parallel.o
298
DEFINES += -DHAS_AUDIO
291 299
endif
292 300
ifeq ($(TARGET_BASE_ARCH), ppc)
293 301
VL_OBJS+= ppc.o ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
294 302
VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
295 303
VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o mixeng.o
304
DEFINES += -DHAS_AUDIO
296 305
endif
297 306
ifeq ($(TARGET_ARCH), mips)
298 307
VL_OBJS+= mips_r4k.o dma.o vga.o serial.o ne2000.o i8254.o i8259.o
......
317 326
endif
318 327
ifdef CONFIG_COCOA
319 328
VL_OBJS+=cocoa.o
320
COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa
329
COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa -framework IOKit
330
ifdef CONFIG_COREAUDIO
331
COCOA_LIBS+=-framework CoreAudio
332
endif
321 333
endif
322 334
ifdef CONFIG_SLIRP
323 335
DEFINES+=-I$(SRC_PATH)/slirp
......
349 361
VL_LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/ia64.ld
350 362
endif
351 363

  
364
ifdef CONFIG_WIN32
365
SDL_LIBS := $(filter-out -mwindows, $(SDL_LIBS)) -mconsole
366
endif
367

  
352 368
$(QEMU_SYSTEM): $(VL_OBJS) libqemu.a
353 369
	$(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS)
354 370

  
......
364 380
depend: $(SRCS)
365 381
	$(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend
366 382

  
383
vldepend: $(VL_OBJS:.o=.c)
384
	$(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend
385

  
367 386
# libqemu 
368 387

  
369 388
libqemu.a: $(LIBOBJS)
......
415 434
op_helper.o: op_helper_mem.c
416 435
endif
417 436

  
418
mixeng.o: mixeng.c mixeng.h mixeng_template.h
419

  
420 437
%.o: %.c
421 438
	$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
422 439

  
......
434 451
ifneq ($(wildcard .depend),)
435 452
include .depend
436 453
endif
454

  
455
ifeq (0, 1)
456
audio.o sdlaudio.o dsoundaudio.o ossaudio.o wavaudio.o noaudio.o \
457
fmodaudio.o alsaaudio.o mixeng.o: \
458
CFLAGS := $(CFLAGS) -Wall -Werror -W -Wsign-compare
459
endif
b/audio/alsaaudio.c
1
/*
2
 * QEMU ALSA audio driver
3
 *
4
 * Copyright (c) 2005 Vassili Karpov (malc)
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include <alsa/asoundlib.h>
25
#include "vl.h"
26

  
27
#define AUDIO_CAP "alsa"
28
#include "audio_int.h"
29

  
30
typedef struct ALSAVoiceOut {
31
    HWVoiceOut hw;
32
    void *pcm_buf;
33
    snd_pcm_t *handle;
34
    int can_pause;
35
    int was_enabled;
36
} ALSAVoiceOut;
37

  
38
typedef struct ALSAVoiceIn {
39
    HWVoiceIn hw;
40
    snd_pcm_t *handle;
41
    void *pcm_buf;
42
    int can_pause;
43
} ALSAVoiceIn;
44

  
45
static struct {
46
    int size_in_usec_in;
47
    int size_in_usec_out;
48
    const char *pcm_name_in;
49
    const char *pcm_name_out;
50
    unsigned int buffer_size_in;
51
    unsigned int period_size_in;
52
    unsigned int buffer_size_out;
53
    unsigned int period_size_out;
54
    unsigned int threshold;
55

  
56
    int buffer_size_in_overriden;
57
    int period_size_in_overriden;
58

  
59
    int buffer_size_out_overriden;
60
    int period_size_out_overriden;
61
} conf = {
62
#ifdef HIGH_LATENCY
63
    .size_in_usec_in = 1,
64
    .size_in_usec_out = 1,
65
#endif
66
    .pcm_name_out = "hw:0,0",
67
    .pcm_name_in = "hw:0,0",
68
#ifdef HIGH_LATENCY
69
    .buffer_size_in = 400000,
70
    .period_size_in = 400000 / 4,
71
    .buffer_size_out = 400000,
72
    .period_size_out = 400000 / 4,
73
#else
74
#define DEFAULT_BUFFER_SIZE 1024
75
#define DEFAULT_PERIOD_SIZE 256
76
    .buffer_size_in = DEFAULT_BUFFER_SIZE,
77
    .period_size_in = DEFAULT_PERIOD_SIZE,
78
    .buffer_size_out = DEFAULT_BUFFER_SIZE,
79
    .period_size_out = DEFAULT_PERIOD_SIZE,
80
    .buffer_size_in_overriden = 0,
81
    .buffer_size_out_overriden = 0,
82
    .period_size_in_overriden = 0,
83
    .period_size_out_overriden = 0,
84
#endif
85
    .threshold = 0
86
};
87

  
88
struct alsa_params_req {
89
    int freq;
90
    audfmt_e fmt;
91
    int nchannels;
92
    unsigned int buffer_size;
93
    unsigned int period_size;
94
};
95

  
96
struct alsa_params_obt {
97
    int freq;
98
    audfmt_e fmt;
99
    int nchannels;
100
    int can_pause;
101
    snd_pcm_uframes_t buffer_size;
102
};
103

  
104
static void GCC_FMT_ATTR (2, 3) alsa_logerr (int err, const char *fmt, ...)
105
{
106
    va_list ap;
107

  
108
    va_start (ap, fmt);
109
    AUD_vlog (AUDIO_CAP, fmt, ap);
110
    va_end (ap);
111

  
112
    AUD_log (AUDIO_CAP, "Reason: %s\n", snd_strerror (err));
113
}
114

  
115
static void GCC_FMT_ATTR (3, 4) alsa_logerr2 (
116
    int err,
117
    const char *typ,
118
    const char *fmt,
119
    ...
120
    )
121
{
122
    va_list ap;
123

  
124
    AUD_log (AUDIO_CAP, "Can not initialize %s\n", typ);
125

  
126
    va_start (ap, fmt);
127
    AUD_vlog (AUDIO_CAP, fmt, ap);
128
    va_end (ap);
129

  
130
    AUD_log (AUDIO_CAP, "Reason: %s\n", snd_strerror (err));
131
}
132

  
133
static void alsa_anal_close (snd_pcm_t **handlep)
134
{
135
    int err = snd_pcm_close (*handlep);
136
    if (err) {
137
        alsa_logerr (err, "Failed to close PCM handle %p\n", *handlep);
138
    }
139
    *handlep = NULL;
140
}
141

  
142
static int alsa_write (SWVoiceOut *sw, void *buf, int len)
143
{
144
    return audio_pcm_sw_write (sw, buf, len);
145
}
146

  
147
static int aud_to_alsafmt (audfmt_e fmt)
148
{
149
    switch (fmt) {
150
    case AUD_FMT_S8:
151
        return SND_PCM_FORMAT_S8;
152

  
153
    case AUD_FMT_U8:
154
        return SND_PCM_FORMAT_U8;
155

  
156
    case AUD_FMT_S16:
157
        return SND_PCM_FORMAT_S16_LE;
158

  
159
    case AUD_FMT_U16:
160
        return SND_PCM_FORMAT_U16_LE;
161

  
162
    default:
163
        dolog ("Internal logic error: Bad audio format %d\n", fmt);
164
#ifdef DEBUG_AUDIO
165
        abort ();
166
#endif
167
        return SND_PCM_FORMAT_U8;
168
    }
169
}
170

  
171
static int alsa_to_audfmt (int alsafmt, audfmt_e *fmt, int *endianness)
172
{
173
    switch (alsafmt) {
174
    case SND_PCM_FORMAT_S8:
175
        *endianness = 0;
176
        *fmt = AUD_FMT_S8;
177
        break;
178

  
179
    case SND_PCM_FORMAT_U8:
180
        *endianness = 0;
181
        *fmt = AUD_FMT_U8;
182
        break;
183

  
184
    case SND_PCM_FORMAT_S16_LE:
185
        *endianness = 0;
186
        *fmt = AUD_FMT_S16;
187
        break;
188

  
189
    case SND_PCM_FORMAT_U16_LE:
190
        *endianness = 0;
191
        *fmt = AUD_FMT_U16;
192
        break;
193

  
194
    case SND_PCM_FORMAT_S16_BE:
195
        *endianness = 1;
196
        *fmt = AUD_FMT_S16;
197
        break;
198

  
199
    case SND_PCM_FORMAT_U16_BE:
200
        *endianness = 1;
201
        *fmt = AUD_FMT_U16;
202
        break;
203

  
204
    default:
205
        dolog ("Unrecognized audio format %d\n", alsafmt);
206
        return -1;
207
    }
208

  
209
    return 0;
210
}
211

  
212
#ifdef DEBUG_MISMATCHES
213
static void alsa_dump_info (struct alsa_params_req *req,
214
                            struct alsa_params_obt *obt)
215
{
216
    dolog ("parameter | requested value | obtained value\n");
217
    dolog ("format    |      %10d |     %10d\n", req->fmt, obt->fmt);
218
    dolog ("channels  |      %10d |     %10d\n",
219
           req->nchannels, obt->nchannels);
220
    dolog ("frequency |      %10d |     %10d\n", req->freq, obt->freq);
221
    dolog ("============================================\n");
222
    dolog ("requested: buffer size %d period size %d\n",
223
           req->buffer_size, req->period_size);
224
    dolog ("obtained: buffer size %ld\n", obt->buffer_size);
225
}
226
#endif
227

  
228
static void alsa_set_threshold (snd_pcm_t *handle, snd_pcm_uframes_t threshold)
229
{
230
    int err;
231
    snd_pcm_sw_params_t *sw_params;
232

  
233
    snd_pcm_sw_params_alloca (&sw_params);
234

  
235
    err = snd_pcm_sw_params_current (handle, sw_params);
236
    if (err < 0) {
237
        dolog ("Can not fully initialize DAC\n");
238
        alsa_logerr (err, "Failed to get current software parameters\n");
239
        return;
240
    }
241

  
242
    err = snd_pcm_sw_params_set_start_threshold (handle, sw_params, threshold);
243
    if (err < 0) {
244
        dolog ("Can not fully initialize DAC\n");
245
        alsa_logerr (err, "Failed to set software threshold to %ld\n",
246
                     threshold);
247
        return;
248
    }
249

  
250
    err = snd_pcm_sw_params (handle, sw_params);
251
    if (err < 0) {
252
        dolog ("Can not fully initialize DAC\n");
253
        alsa_logerr (err, "Failed to set software parameters\n");
254
        return;
255
    }
256
}
257

  
258
static int alsa_open (int in, struct alsa_params_req *req,
259
                      struct alsa_params_obt *obt, snd_pcm_t **handlep)
260
{
261
    snd_pcm_t *handle;
262
    snd_pcm_hw_params_t *hw_params;
263
    int err, freq, nchannels;
264
    const char *pcm_name = in ? conf.pcm_name_in : conf.pcm_name_out;
265
    unsigned int period_size, buffer_size;
266
    snd_pcm_uframes_t obt_buffer_size;
267
    const char *typ = in ? "ADC" : "DAC";
268

  
269
    freq = req->freq;
270
    period_size = req->period_size;
271
    buffer_size = req->buffer_size;
272
    nchannels = req->nchannels;
273

  
274
    snd_pcm_hw_params_alloca (&hw_params);
275

  
276
    err = snd_pcm_open (
277
        &handle,
278
        pcm_name,
279
        in ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
280
        SND_PCM_NONBLOCK
281
        );
282
    if (err < 0) {
283
        alsa_logerr2 (err, typ, "Failed to open `%s':\n", pcm_name);
284
        return -1;
285
    }
286

  
287
    err = snd_pcm_hw_params_any (handle, hw_params);
288
    if (err < 0) {
289
        alsa_logerr2 (err, typ, "Failed to initialize hardware parameters\n");
290
        goto err;
291
    }
292

  
293
    err = snd_pcm_hw_params_set_access (
294
        handle,
295
        hw_params,
296
        SND_PCM_ACCESS_RW_INTERLEAVED
297
        );
298
    if (err < 0) {
299
        alsa_logerr2 (err, typ, "Failed to set access type\n");
300
        goto err;
301
    }
302

  
303
    err = snd_pcm_hw_params_set_format (handle, hw_params, req->fmt);
304
    if (err < 0) {
305
        alsa_logerr2 (err, typ, "Failed to set format %d\n", req->fmt);
306
        goto err;
307
    }
308

  
309
    err = snd_pcm_hw_params_set_rate_near (handle, hw_params, &freq, 0);
310
    if (err < 0) {
311
        alsa_logerr2 (err, typ, "Failed to set frequency %d\n", req->freq);
312
        goto err;
313
    }
314

  
315
    err = snd_pcm_hw_params_set_channels_near (
316
        handle,
317
        hw_params,
318
        &nchannels
319
        );
320
    if (err < 0) {
321
        alsa_logerr2 (err, typ, "Failed to set number of channels %d\n",
322
                      req->nchannels);
323
        goto err;
324
    }
325

  
326
    if (nchannels != 1 && nchannels != 2) {
327
        alsa_logerr2 (err, typ,
328
                      "Can not handle obtained number of channels %d\n",
329
                      nchannels);
330
        goto err;
331
    }
332

  
333
    if (!((in && conf.size_in_usec_in) || (!in && conf.size_in_usec_out))) {
334
        if (!buffer_size) {
335
            buffer_size = DEFAULT_BUFFER_SIZE;
336
            period_size= DEFAULT_PERIOD_SIZE;
337
        }
338
    }
339

  
340
    if (buffer_size) {
341
        if ((in && conf.size_in_usec_in) || (!in && conf.size_in_usec_out)) {
342
            if (period_size) {
343
                err = snd_pcm_hw_params_set_period_time_near (
344
                    handle,
345
                    hw_params,
346
                    &period_size,
347
                    0);
348
                if (err < 0) {
349
                    alsa_logerr2 (err, typ,
350
                                  "Failed to set period time %d\n",
351
                                  req->period_size);
352
                    goto err;
353
                }
354
            }
355

  
356
            err = snd_pcm_hw_params_set_buffer_time_near (
357
                handle,
358
                hw_params,
359
                &buffer_size,
360
                0);
361

  
362
            if (err < 0) {
363
                alsa_logerr2 (err, typ,
364
                              "Failed to set buffer time %d\n",
365
                              req->buffer_size);
366
                goto err;
367
            }
368
        }
369
        else {
370
            int dir;
371
            snd_pcm_uframes_t minval;
372

  
373
            if (period_size) {
374
                minval = period_size;
375
                dir = 0;
376

  
377
                err = snd_pcm_hw_params_get_period_size_min (
378
                    hw_params,
379
                    &minval,
380
                    &dir
381
                    );
382
                if (err < 0) {
383
                    alsa_logerr (
384
                        err,
385
                        "Can not get minmal period size for %s\n",
386
                        typ
387
                        );
388
                }
389
                else {
390
                    if (period_size < minval) {
391
                        if ((in && conf.period_size_in_overriden)
392
                            || (!in && conf.period_size_out_overriden)) {
393
                            dolog ("%s period size(%d) is less "
394
                                   "than minmal period size(%ld)\n",
395
                                   typ,
396
                                   period_size,
397
                                   minval);
398
                        }
399
                        period_size = minval;
400
                    }
401
                }
402

  
403
                err = snd_pcm_hw_params_set_period_size (
404
                    handle,
405
                    hw_params,
406
                    period_size,
407
                    0
408
                    );
409
                if (err < 0) {
410
                    alsa_logerr2 (err, typ, "Failed to set period size %d\n",
411
                                  req->period_size);
412
                    goto err;
413
                }
414
            }
415

  
416
            minval = buffer_size;
417
            err = snd_pcm_hw_params_get_buffer_size_min (
418
                hw_params,
419
                &minval
420
                );
421
            if (err < 0) {
422
                alsa_logerr (err, "Can not get minmal buffer size for %s\n",
423
                             typ);
424
            }
425
            else {
426
                if (buffer_size < minval) {
427
                    if ((in && conf.buffer_size_in_overriden)
428
                        || (!in && conf.buffer_size_out_overriden)) {
429
                        dolog (
430
                            "%s buffer size(%d) is less "
431
                            "than minimal buffer size(%ld)\n",
432
                            typ,
433
                            buffer_size,
434
                            minval
435
                            );
436
                    }
437
                    buffer_size = minval;
438
                }
439
            }
440

  
441
            err = snd_pcm_hw_params_set_buffer_size (
442
                handle,
443
                hw_params,
444
                buffer_size
445
                );
446
            if (err < 0) {
447
                alsa_logerr2 (err, typ, "Failed to set buffer size %d\n",
448
                              req->buffer_size);
449
                goto err;
450
            }
451
        }
452
    }
453
    else {
454
        dolog ("warning: buffer size is not set\n");
455
    }
456

  
457
    err = snd_pcm_hw_params (handle, hw_params);
458
    if (err < 0) {
459
        alsa_logerr2 (err, typ, "Failed to apply audio parameters\n");
460
        goto err;
461
    }
462

  
463
    err = snd_pcm_hw_params_get_buffer_size (hw_params, &obt_buffer_size);
464
    if (err < 0) {
465
        alsa_logerr2 (err, typ, "Failed to get buffer size\n");
466
        goto err;
467
    }
468

  
469
    err = snd_pcm_prepare (handle);
470
    if (err < 0) {
471
        alsa_logerr2 (err, typ, "Can not prepare handle %p\n", handle);
472
        goto err;
473
    }
474

  
475
    obt->can_pause = snd_pcm_hw_params_can_pause (hw_params);
476
    if (obt->can_pause < 0) {
477
        alsa_logerr (err, "Can not get pause capability for %s\n", typ);
478
        obt->can_pause = 0;
479
    }
480

  
481
    if (!in && conf.threshold) {
482
        snd_pcm_uframes_t threshold;
483
        int bytes_per_sec;
484

  
485
        bytes_per_sec = freq
486
            << (nchannels == 2)
487
            << (req->fmt == AUD_FMT_S16 || req->fmt == AUD_FMT_U16);
488

  
489
        threshold = (conf.threshold * bytes_per_sec) / 1000;
490
        alsa_set_threshold (handle, threshold);
491
    }
492

  
493
    obt->fmt = req->fmt;
494
    obt->nchannels = nchannels;
495
    obt->freq = freq;
496
    obt->buffer_size = snd_pcm_frames_to_bytes (handle, obt_buffer_size);
497
    *handlep = handle;
498

  
499
    if (obt->fmt != req->fmt ||
500
        obt->nchannels != req->nchannels ||
501
        obt->freq != req->freq) {
502
#ifdef DEBUG_MISMATCHES
503
        dolog ("Audio paramters mismatch for %s\n", typ);
504
        alsa_dump_info (req, obt);
505
#endif
506
    }
507

  
508
#ifdef DEBUG
509
    alsa_dump_info (req, obt);
510
#endif
511
    return 0;
512

  
513
 err:
514
    alsa_anal_close (&handle);
515
    return -1;
516
}
517

  
518
static int alsa_recover (snd_pcm_t *handle)
519
{
520
    int err = snd_pcm_prepare (handle);
521
    if (err < 0) {
522
        alsa_logerr (err, "Failed to prepare handle %p\n", handle);
523
        return -1;
524
    }
525
    return 0;
526
}
527

  
528
static int alsa_run_out (HWVoiceOut *hw)
529
{
530
    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
531
    int rpos, live, decr;
532
    int samples;
533
    uint8_t *dst;
534
    st_sample_t *src;
535
    snd_pcm_sframes_t avail;
536

  
537
    live = audio_pcm_hw_get_live_out (hw);
538
    if (!live) {
539
        return 0;
540
    }
541

  
542
    avail = snd_pcm_avail_update (alsa->handle);
543
    if (avail < 0) {
544
        if (avail == -EPIPE) {
545
            if (!alsa_recover (alsa->handle)) {
546
                avail = snd_pcm_avail_update (alsa->handle);
547
                if (avail >= 0) {
548
                    goto ok;
549
                }
550
            }
551
        }
552

  
553
        alsa_logerr (avail, "Can not get amount free space\n");
554
        return 0;
555
    }
556

  
557
 ok:
558
    decr = audio_MIN (live, avail);
559
    samples = decr;
560
    rpos = hw->rpos;
561
    while (samples) {
562
        int left_till_end_samples = hw->samples - rpos;
563
        int convert_samples = audio_MIN (samples, left_till_end_samples);
564
        snd_pcm_sframes_t written;
565

  
566
        src = hw->mix_buf + rpos;
567
        dst = advance (alsa->pcm_buf, rpos << hw->info.shift);
568

  
569
        hw->clip (dst, src, convert_samples);
570

  
571
    again:
572
        written = snd_pcm_writei (alsa->handle, dst, convert_samples);
573

  
574
        if (written < 0) {
575
            switch (written) {
576
            case -EPIPE:
577
                if (!alsa_recover (alsa->handle)) {
578
                    goto again;
579
                }
580
                dolog (
581
                    "Failed to write %d frames to %p, handle %p not prepared\n",
582
                    convert_samples,
583
                    dst,
584
                    alsa->handle
585
                    );
586
                goto exit;
587

  
588
            case -EAGAIN:
589
                goto again;
590

  
591
            default:
592
                alsa_logerr (written, "Failed to write %d frames to %p\n",
593
                             convert_samples, dst);
594
                goto exit;
595
            }
596
        }
597

  
598
        mixeng_clear (src, written);
599
        rpos = (rpos + written) % hw->samples;
600
        samples -= written;
601
    }
602

  
603
 exit:
604
    hw->rpos = rpos;
605
    return decr;
606
}
607

  
608
static void alsa_fini_out (HWVoiceOut *hw)
609
{
610
    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
611

  
612
    ldebug ("alsa_fini\n");
613
    alsa_anal_close (&alsa->handle);
614

  
615
    if (alsa->pcm_buf) {
616
        qemu_free (alsa->pcm_buf);
617
        alsa->pcm_buf = NULL;
618
    }
619
}
620

  
621
static int alsa_init_out (HWVoiceOut *hw, int freq, int nchannels, audfmt_e fmt)
622
{
623
    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
624
    struct alsa_params_req req;
625
    struct alsa_params_obt obt;
626
    audfmt_e effective_fmt;
627
    int endianness;
628
    int err;
629
    snd_pcm_t *handle;
630

  
631
    req.fmt = aud_to_alsafmt (fmt);
632
    req.freq = freq;
633
    req.nchannels = nchannels;
634
    req.period_size = conf.period_size_out;
635
    req.buffer_size = conf.buffer_size_out;
636

  
637
    if (alsa_open (0, &req, &obt, &handle)) {
638
        return -1;
639
    }
640

  
641
    err = alsa_to_audfmt (obt.fmt, &effective_fmt, &endianness);
642
    if (err) {
643
        alsa_anal_close (&handle);
644
        return -1;
645
    }
646

  
647
    audio_pcm_init_info (
648
        &hw->info,
649
        obt.freq,
650
        obt.nchannels,
651
        effective_fmt,
652
        audio_need_to_swap_endian (endianness)
653
        );
654
    alsa->can_pause = obt.can_pause;
655
    hw->bufsize = obt.buffer_size;
656

  
657
    alsa->pcm_buf = qemu_mallocz (hw->bufsize);
658
    if (!alsa->pcm_buf) {
659
        alsa_anal_close (&handle);
660
        return -1;
661
    }
662

  
663
    alsa->handle = handle;
664
    alsa->was_enabled = 0;
665
    return 0;
666
}
667

  
668
static int alsa_ctl_out (HWVoiceOut *hw, int cmd, ...)
669
{
670
    int err;
671
    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
672

  
673
    switch (cmd) {
674
    case VOICE_ENABLE:
675
        ldebug ("enabling voice\n");
676
        audio_pcm_info_clear_buf (&hw->info, alsa->pcm_buf, hw->samples);
677
        if (alsa->can_pause) {
678
            /* Why this was_enabled madness is needed at all?? */
679
            if (alsa->was_enabled) {
680
                err = snd_pcm_pause (alsa->handle, 0);
681
                if (err < 0) {
682
                    alsa_logerr (err, "Failed to resume playing\n");
683
                    /* not fatal really */
684
                }
685
            }
686
            else {
687
                alsa->was_enabled = 1;
688
            }
689
        }
690
        break;
691

  
692
    case VOICE_DISABLE:
693
        ldebug ("disabling voice\n");
694
        if (alsa->can_pause) {
695
            err = snd_pcm_pause (alsa->handle, 1);
696
            if (err < 0) {
697
                alsa_logerr (err, "Failed to stop playing\n");
698
                /* not fatal really */
699
            }
700
        }
701
        break;
702
    }
703
    return 0;
704
}
705

  
706
static int alsa_init_in (HWVoiceIn *hw,
707
                        int freq, int nchannels, audfmt_e fmt)
708
{
709
    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
710
    struct alsa_params_req req;
711
    struct alsa_params_obt obt;
712
    int endianness;
713
    int err;
714
    audfmt_e effective_fmt;
715
    snd_pcm_t *handle;
716

  
717
    req.fmt = aud_to_alsafmt (fmt);
718
    req.freq = freq;
719
    req.nchannels = nchannels;
720
    req.period_size = conf.period_size_in;
721
    req.buffer_size = conf.buffer_size_in;
722

  
723
    if (alsa_open (1, &req, &obt, &handle)) {
724
        return -1;
725
    }
726

  
727
    err = alsa_to_audfmt (obt.fmt, &effective_fmt, &endianness);
728
    if (err) {
729
        alsa_anal_close (&handle);
730
        return -1;
731
    }
732

  
733
    audio_pcm_init_info (
734
        &hw->info,
735
        obt.freq,
736
        obt.nchannels,
737
        effective_fmt,
738
        audio_need_to_swap_endian (endianness)
739
        );
740
    alsa->can_pause = obt.can_pause;
741
    hw->bufsize = obt.buffer_size;
742
    alsa->pcm_buf = qemu_mallocz (hw->bufsize);
743
    if (!alsa->pcm_buf) {
744
        alsa_anal_close (&handle);
745
        return -1;
746
    }
747

  
748
    alsa->handle = handle;
749
    return 0;
750
}
751

  
752
static void alsa_fini_in (HWVoiceIn *hw)
753
{
754
    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
755

  
756
    alsa_anal_close (&alsa->handle);
757

  
758
    if (alsa->pcm_buf) {
759
        qemu_free (alsa->pcm_buf);
760
        alsa->pcm_buf = NULL;
761
    }
762
}
763

  
764
static int alsa_run_in (HWVoiceIn *hw)
765
{
766
    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
767
    int hwshift = hw->info.shift;
768
    int i;
769
    int live = audio_pcm_hw_get_live_in (hw);
770
    int dead = hw->samples - live;
771
    struct {
772
        int add;
773
        int len;
774
    } bufs[2] = {
775
        { hw->wpos, 0 },
776
        { 0, 0 }
777
    };
778

  
779
    snd_pcm_uframes_t read_samples = 0;
780

  
781
    if (!dead) {
782
        return 0;
783
    }
784

  
785
    if (hw->wpos + dead > hw->samples) {
786
        bufs[0].len = (hw->samples - hw->wpos);
787
        bufs[1].len = (dead - (hw->samples - hw->wpos));
788
    }
789
    else {
790
        bufs[0].len = dead;
791
    }
792

  
793

  
794
    for (i = 0; i < 2; ++i) {
795
        void *src;
796
        st_sample_t *dst;
797
        snd_pcm_sframes_t nread;
798
        snd_pcm_uframes_t len;
799

  
800
        len = bufs[i].len;
801

  
802
        src = advance (alsa->pcm_buf, bufs[i].add << hwshift);
803
        dst = hw->conv_buf + bufs[i].add;
804

  
805
        while (len) {
806
            nread = snd_pcm_readi (alsa->handle, src, len);
807

  
808
            if (nread < 0) {
809
                switch (nread) {
810
                case -EPIPE:
811
                    if (!alsa_recover (alsa->handle)) {
812
                        continue;
813
                    }
814
                    dolog (
815
                        "Failed to read %ld frames from %p, "
816
                        "handle %p not prepared\n",
817
                        len,
818
                        src,
819
                        alsa->handle
820
                        );
821
                    goto exit;
822

  
823
                case -EAGAIN:
824
                    continue;
825

  
826
                default:
827
                    alsa_logerr (
828
                        nread,
829
                        "Failed to read %ld frames from %p\n",
830
                        len,
831
                        src
832
                        );
833
                    goto exit;
834
                }
835
            }
836

  
837
            hw->conv (dst, src, nread, &nominal_volume);
838

  
839
            src = advance (src, nread << hwshift);
840
            dst += nread;
841

  
842
            read_samples += nread;
843
            len -= nread;
844
        }
845
    }
846

  
847
 exit:
848
    hw->wpos = (hw->wpos + read_samples) % hw->samples;
849
    return read_samples;
850
}
851

  
852
static int alsa_read (SWVoiceIn *sw, void *buf, int size)
853
{
854
    return audio_pcm_sw_read (sw, buf, size);
855
}
856

  
857
static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...)
858
{
859
    (void) hw;
860
    (void) cmd;
861
    return 0;
862
}
863

  
864
static void *alsa_audio_init (void)
865
{
866
    return &conf;
867
}
868

  
869
static void alsa_audio_fini (void *opaque)
870
{
871
    (void) opaque;
872
}
873

  
874
static struct audio_option alsa_options[] = {
875
    {"DAC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_out,
876
     "DAC period/buffer size in microseconds (otherwise in frames)", NULL, 0},
877
    {"DAC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_out,
878
     "DAC period size", &conf.period_size_out_overriden, 0},
879
    {"DAC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_out,
880
     "DAC buffer size", &conf.buffer_size_out_overriden, 0},
881

  
882
    {"ADC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_in,
883
     "ADC period/buffer size in microseconds (otherwise in frames)", NULL, 0},
884
    {"ADC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_in,
885
     "ADC period size", &conf.period_size_in_overriden, 0},
886
    {"ADC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_in,
887
     "ADC buffer size", &conf.buffer_size_in_overriden, 0},
888

  
889
    {"THRESHOLD", AUD_OPT_INT, &conf.threshold,
890
     "(undocumented)", NULL, 0},
891

  
892
    {"DAC_DEV", AUD_OPT_STR, &conf.pcm_name_out,
893
     "DAC device name (for instance dmix)", NULL, 0},
894

  
895
    {"ADC_DEV", AUD_OPT_STR, &conf.pcm_name_in,
896
     "ADC device name", NULL, 0},
897
    {NULL, 0, NULL, NULL, NULL, 0}
898
};
899

  
900
static struct audio_pcm_ops alsa_pcm_ops = {
901
    alsa_init_out,
902
    alsa_fini_out,
903
    alsa_run_out,
904
    alsa_write,
905
    alsa_ctl_out,
906

  
907
    alsa_init_in,
908
    alsa_fini_in,
909
    alsa_run_in,
910
    alsa_read,
911
    alsa_ctl_in
912
};
913

  
914
struct audio_driver alsa_audio_driver = {
915
    INIT_FIELD (name           = ) "alsa",
916
    INIT_FIELD (descr          = ) "ALSA http://www.alsa-project.org",
917
    INIT_FIELD (options        = ) alsa_options,
918
    INIT_FIELD (init           = ) alsa_audio_init,
919
    INIT_FIELD (fini           = ) alsa_audio_fini,
920
    INIT_FIELD (pcm_ops        = ) &alsa_pcm_ops,
921
    INIT_FIELD (can_be_default = ) 1,
922
    INIT_FIELD (max_voices_out = ) INT_MAX,
923
    INIT_FIELD (max_voices_in  = ) INT_MAX,
924
    INIT_FIELD (voice_size_out = ) sizeof (ALSAVoiceOut),
925
    INIT_FIELD (voice_size_in  = ) sizeof (ALSAVoiceIn)
926
};
b/audio/audio.c
1 1
/*
2 2
 * QEMU Audio subsystem
3
 * 
4
 * Copyright (c) 2003-2004 Vassili Karpov (malc)
5
 * 
3
 *
4
 * Copyright (c) 2003-2005 Vassili Karpov (malc)
5
 *
6 6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 7
 * of this software and associated documentation files (the "Software"), to deal
8 8
 * in the Software without restriction, including without limitation the rights
......
21 21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 22
 * THE SOFTWARE.
23 23
 */
24
#include <assert.h>
25 24
#include "vl.h"
26 25

  
27
#define USE_WAV_AUDIO
26
#define AUDIO_CAP "audio"
27
#include "audio_int.h"
28 28

  
29
#include "audio/audio_int.h"
29
static void audio_pcm_hw_fini_in (HWVoiceIn *hw);
30
static void audio_pcm_hw_fini_out (HWVoiceOut *hw);
30 31

  
31
#define dolog(...) AUD_log ("audio", __VA_ARGS__)
32
#ifdef DEBUG
33
#define ldebug(...) dolog (__VA_ARGS__)
34
#else
35
#define ldebug(...)
36
#endif
32
static LIST_HEAD (hw_in_listhead, HWVoiceIn) hw_head_in;
33
static LIST_HEAD (hw_out_listhead, HWVoiceOut) hw_head_out;
37 34

  
38
#define QC_AUDIO_DRV    "QEMU_AUDIO_DRV"
39
#define QC_VOICES       "QEMU_VOICES"
40
#define QC_FIXED_FORMAT "QEMU_FIXED_FORMAT"
41
#define QC_FIXED_FREQ   "QEMU_FIXED_FREQ"
35
/* #define DEBUG_PLIVE */
36
/* #define DEBUG_LIVE */
37
/* #define DEBUG_OUT */
42 38

  
43
static HWVoice *hw_voices;
39
static struct audio_driver *drvtab[] = {
40
#ifdef CONFIG_OSS
41
    &oss_audio_driver,
42
#endif
43
#ifdef CONFIG_ALSA
44
    &alsa_audio_driver,
45
#endif
46
#ifdef CONFIG_COREAUDIO
47
    &coreaudio_audio_driver,
48
#endif
49
#ifdef CONFIG_DSOUND
50
    &dsound_audio_driver,
51
#endif
52
#ifdef CONFIG_FMOD
53
    &fmod_audio_driver,
54
#endif
55
#ifdef CONFIG_SDL
56
    &sdl_audio_driver,
57
#endif
58
    &no_audio_driver,
59
    &wav_audio_driver
60
};
44 61

  
45 62
AudioState audio_state = {
63
    /* Out */
64
    1,                          /* use fixed settings */
65
    44100,                      /* fixed frequency */
66
    2,                          /* fixed channels */
67
    AUD_FMT_S16,                /* fixed format */
68
    1,                          /* number of hw voices */
69
    1,                          /* greedy */
70

  
71
    /* In */
46 72
    1,                          /* use fixed settings */
47 73
    44100,                      /* fixed frequency */
48 74
    2,                          /* fixed channels */
49 75
    AUD_FMT_S16,                /* fixed format */
50 76
    1,                          /* number of hw voices */
51
    -1                          /* voice size */
77
    1,                          /* greedy */
78

  
79
    NULL,                       /* driver opaque */
80
    NULL,                       /* driver */
81

  
82
    NULL,                       /* timer handle */
83
    { 0 },                      /* period */
84
    0                           /* plive */
85
};
86

  
87
volume_t nominal_volume = {
88
    0,
89
#ifdef FLOAT_MIXENG
90
    1.0,
91
    1.0
92
#else
93
    UINT_MAX,
94
    UINT_MAX
95
#endif
52 96
};
53 97

  
54 98
/* http://www.df.lth.se/~john_e/gems/gem002d.html */
......
68 112
    return popcount ((u&-u)-1);
69 113
}
70 114

  
71
int audio_get_conf_int (const char *key, int defval)
115
#ifdef AUDIO_IS_FLAWLESS_AND_NO_CHECKS_ARE_REQURIED
116
#error No its not
117
#else
118
int audio_bug (const char *funcname, int cond)
72 119
{
73
    int val = defval;
74
    char *strval;
75

  
76
    strval = getenv (key);
77
    if (strval) {
78
        val = atoi (strval);
120
    if (cond) {
121
        static int shown;
122

  
123
        AUD_log (NULL, "Error a bug that was just triggered in %s\n", funcname);
124
        if (!shown) {
125
            shown = 1;
126
            AUD_log (NULL, "Save all your work and restart without audio\n");
127
            AUD_log (NULL, "Please send bug report to malc@pulsesoft.com\n");
128
            AUD_log (NULL, "I am sorry\n");
129
        }
130
        AUD_log (NULL, "Context:\n");
131

  
132
#if defined AUDIO_BREAKPOINT_ON_BUG
133
#  if defined HOST_I386
134
#    if defined __GNUC__
135
        __asm__ ("int3");
136
#    elif defined _MSC_VER
137
        _asm _emit 0xcc;
138
#    else
139
        abort ();
140
#    endif
141
#  else
142
        abort ();
143
#  endif
144
#endif
79 145
    }
80 146

  
81
    return val;
147
    return cond;
82 148
}
149
#endif
83 150

  
84
const char *audio_get_conf_str (const char *key, const char *defval)
151
static char *audio_alloc_prefix (const char *s)
85 152
{
86
    const char *val = getenv (key);
87
    if (!val)
88
        return defval;
89
    else
90
        return val;
91
}
153
    const char qemu_prefix[] = "QEMU_";
154
    size_t len;
155
    char *r;
92 156

  
93
void AUD_log (const char *cap, const char *fmt, ...)
94
{
95
    va_list ap;
96
    fprintf (stderr, "%s: ", cap);
97
    va_start (ap, fmt);
98
    vfprintf (stderr, fmt, ap);
99
    va_end (ap);
100
}
157
    if (!s) {
158
        return NULL;
159
    }
101 160

  
102
/*
103
 * Soft Voice
104
 */
105
void pcm_sw_free_resources (SWVoice *sw)
106
{
107
    if (sw->buf) qemu_free (sw->buf);
108
    if (sw->rate) st_rate_stop (sw->rate);
109
    sw->buf = NULL;
110
    sw->rate = NULL;
111
}
161
    len = strlen (s);
162
    r = qemu_malloc (len + sizeof (qemu_prefix));
112 163

  
113
int pcm_sw_alloc_resources (SWVoice *sw)
114
{
115
    sw->buf = qemu_mallocz (sw->hw->samples * sizeof (st_sample_t));
116
    if (!sw->buf)
117
        return -1;
164
    if (r) {
165
        size_t i;
166
        char *u = r + sizeof (qemu_prefix) - 1;
118 167

  
119
    sw->rate = st_rate_start (sw->freq, sw->hw->freq);
120
    if (!sw->rate) {
121
        qemu_free (sw->buf);
122
        sw->buf = NULL;
123
        return -1;
168
        strcpy (r, qemu_prefix);
169
        strcat (r, s);
170

  
171
        for (i = 0; i < len; ++i) {
172
            u[i] = toupper (u[i]);
173
        }
124 174
    }
125
    return 0;
175
    return r;
126 176
}
127 177

  
128
void pcm_sw_fini (SWVoice *sw)
178
const char *audio_audfmt_to_string (audfmt_e fmt)
129 179
{
130
    pcm_sw_free_resources (sw);
131
}
180
    switch (fmt) {
181
    case AUD_FMT_U8:
182
        return "U8";
132 183

  
133
int pcm_sw_init (SWVoice *sw, HWVoice *hw, int freq,
134
                 int nchannels, audfmt_e fmt)
135
{
136
    int bits = 8, sign = 0;
184
    case AUD_FMT_U16:
185
        return "U16";
137 186

  
138
    switch (fmt) {
139 187
    case AUD_FMT_S8:
140
        sign = 1;
141
    case AUD_FMT_U8:
142
        break;
188
        return "S8";
143 189

  
144 190
    case AUD_FMT_S16:
145
        sign = 1;
146
    case AUD_FMT_U16:
147
        bits = 16;
148
        break;
191
        return "S16";
149 192
    }
150 193

  
151
    sw->hw = hw;
152
    sw->freq = freq;
153
    sw->fmt = fmt;
154
    sw->nchannels = nchannels;
155
    sw->shift = (nchannels == 2) + (bits == 16);
156
    sw->align = (1 << sw->shift) - 1;
157
    sw->left = 0;
158
    sw->pos = 0;
159
    sw->wpos = 0;
160
    sw->live = 0;
161
    sw->ratio = (sw->hw->freq * ((int64_t) INT_MAX)) / sw->freq;
162
    sw->bytes_per_second = sw->freq << sw->shift;
163
    sw->conv = mixeng_conv[nchannels == 2][sign][bits == 16];
164

  
165
    pcm_sw_free_resources (sw);
166
    return pcm_sw_alloc_resources (sw);
167
}
168

  
169
/* Hard voice */
170
void pcm_hw_free_resources (HWVoice *hw)
171
{
172
    if (hw->mix_buf)
173
        qemu_free (hw->mix_buf);
174
    hw->mix_buf = NULL;
194
    dolog ("Bogus audfmt %d returning S16\n", fmt);
195
    return "S16";
175 196
}
176 197

  
177
int pcm_hw_alloc_resources (HWVoice *hw)
198
audfmt_e audio_string_to_audfmt (const char *s, audfmt_e defval, int *defaultp)
178 199
{
179
    hw->mix_buf = qemu_mallocz (hw->samples * sizeof (st_sample_t));
180
    if (!hw->mix_buf)
181
        return -1;
182
    return 0;
200
    if (!strcasecmp (s, "u8")) {
201
        *defaultp = 0;
202
        return AUD_FMT_U8;
203
    }
204
    else if (!strcasecmp (s, "u16")) {
205
        *defaultp = 0;
206
        return AUD_FMT_U16;
207
    }
208
    else if (!strcasecmp (s, "s8")) {
209
        *defaultp = 0;
210
        return AUD_FMT_S8;
211
    }
212
    else if (!strcasecmp (s, "s16")) {
213
        *defaultp = 0;
214
        return AUD_FMT_S16;
215
    }
216
    else {
217
        dolog ("Bogus audio format `%s' using %s\n",
218
               s, audio_audfmt_to_string (defval));
219
        *defaultp = 1;
220
        return defval;
221
    }
183 222
}
184 223

  
185
void pcm_hw_fini (HWVoice *hw)
224
static audfmt_e audio_get_conf_fmt (const char *envname,
225
                                    audfmt_e defval,
226
                                    int *defaultp)
186 227
{
187
    if (hw->active) {
188
        ldebug ("pcm_hw_fini: %d %d %d\n", hw->freq, hw->nchannels, hw->fmt);
189
        pcm_hw_free_resources (hw);
190
        hw->pcm_ops->fini (hw);
191
        memset (hw, 0, audio_state.drv->voice_size);
228
    const char *var = getenv (envname);
229
    if (!var) {
230
        *defaultp = 1;
231
        return defval;
192 232
    }
233
    return audio_string_to_audfmt (var, defval, defaultp);
193 234
}
194 235

  
195
void pcm_hw_gc (HWVoice *hw)
236
static int audio_get_conf_int (const char *key, int defval, int *defaultp)
196 237
{
197
    if (hw->nb_voices)
198
        return;
238
    int val;
239
    char *strval;
199 240

  
200
    pcm_hw_fini (hw);
241
    strval = getenv (key);
242
    if (strval) {
243
        *defaultp = 0;
244
        val = atoi (strval);
245
        return val;
246
    }
247
    else {
248
        *defaultp = 1;
249
        return defval;
250
    }
201 251
}
202 252

  
203
int pcm_hw_get_live (HWVoice *hw)
253
static const char *audio_get_conf_str (const char *key,
254
                                       const char *defval,
255
                                       int *defaultp)
204 256
{
205
    int i, alive = 0, live = hw->samples;
206

  
207
    for (i = 0; i < hw->nb_voices; i++) {
208
        if (hw->pvoice[i]->live) {
209
            live = audio_MIN (hw->pvoice[i]->live, live);
210
            alive += 1;
211
        }
257
    const char *val = getenv (key);
258
    if (!val) {
259
        *defaultp = 1;
260
        return defval;
261
    }
262
    else {
263
        *defaultp = 0;
264
        return val;
212 265
    }
213

  
214
    if (alive)
215
        return live;
216
    else
217
        return -1;
218 266
}
219 267

  
220
int pcm_hw_get_live2 (HWVoice *hw, int *nb_active)
268
void AUD_log (const char *cap, const char *fmt, ...)
221 269
{
222
    int i, alive = 0, live = hw->samples;
223

  
224
    *nb_active = 0;
225
    for (i = 0; i < hw->nb_voices; i++) {
226
        if (hw->pvoice[i]->live) {
227
            if (hw->pvoice[i]->live < live) {
228
                *nb_active = hw->pvoice[i]->active != 0;
229
                live = hw->pvoice[i]->live;
230
            }
231
            alive += 1;
232
        }
270
    va_list ap;
271
    if (cap) {
272
        fprintf (stderr, "%s: ", cap);
233 273
    }
234

  
235
    if (alive)
236
        return live;
237
    else
238
        return -1;
274
    va_start (ap, fmt);
275
    vfprintf (stderr, fmt, ap);
276
    va_end (ap);
239 277
}
240 278

  
241
void pcm_hw_dec_live (HWVoice *hw, int decr)
279
void AUD_vlog (const char *cap, const char *fmt, va_list ap)
242 280
{
243
    int i;
244

  
245
    for (i = 0; i < hw->nb_voices; i++) {
246
        if (hw->pvoice[i]->live) {
247
            hw->pvoice[i]->live -= decr;
248
        }
281
    if (cap) {
282
        fprintf (stderr, "%s: ", cap);
249 283
    }
284
    vfprintf (stderr, fmt, ap);
250 285
}
251 286

  
252
void pcm_hw_clear (HWVoice *hw, void *buf, int len)
287
static void audio_print_options (const char *prefix,
288
                                 struct audio_option *opt)
253 289
{
254
    if (!len)
290
    char *uprefix;
291

  
292
    if (!prefix) {
293
        dolog ("No prefix specified\n");
294
        return;
295
    }
296

  
297
    if (!opt) {
298
        dolog ("No options\n");
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff