Revision 1d14ffa9 audio/ossaudio.c

b/audio/ossaudio.c
1 1
/*
2
 * QEMU OSS audio output driver
3
 * 
4
 * Copyright (c) 2003-2004 Vassili Karpov (malc)
5
 * 
2
 * QEMU OSS audio driver
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
......
25 25
#include <sys/types.h>
26 26
#include <sys/ioctl.h>
27 27
#include <sys/soundcard.h>
28
#include <assert.h>
29 28
#include "vl.h"
30 29

  
31
#include "audio/audio_int.h"
30
#define AUDIO_CAP "oss"
31
#include "audio_int.h"
32 32

  
33
typedef struct OSSVoice {
34
    HWVoice hw;
33
typedef struct OSSVoiceOut {
34
    HWVoiceOut hw;
35 35
    void *pcm_buf;
36 36
    int fd;
37 37
    int nfrags;
38 38
    int fragsize;
39 39
    int mmapped;
40 40
    int old_optr;
41
} OSSVoice;
42

  
43
#define dolog(...) AUD_log ("oss", __VA_ARGS__)
44
#ifdef DEBUG
45
#define ldebug(...) dolog (__VA_ARGS__)
46
#else
47
#define ldebug(...)
48
#endif
41
} OSSVoiceOut;
49 42

  
50
#define QC_OSS_FRAGSIZE "QEMU_OSS_FRAGSIZE"
51
#define QC_OSS_NFRAGS   "QEMU_OSS_NFRAGS"
52
#define QC_OSS_MMAP     "QEMU_OSS_MMAP"
53
#define QC_OSS_DEV      "QEMU_OSS_DEV"
54

  
55
#define errstr() strerror (errno)
43
typedef struct OSSVoiceIn {
44
    HWVoiceIn hw;
45
    void *pcm_buf;
46
    int fd;
47
    int nfrags;
48
    int fragsize;
49
    int old_optr;
50
} OSSVoiceIn;
56 51

  
57 52
static struct {
58 53
    int try_mmap;
59 54
    int nfrags;
60 55
    int fragsize;
61
    const char *dspname;
56
    const char *devpath_out;
57
    const char *devpath_in;
62 58
} conf = {
63 59
    .try_mmap = 0,
64 60
    .nfrags = 4,
65 61
    .fragsize = 4096,
66
    .dspname = "/dev/dsp"
62
    .devpath_out = "/dev/dsp",
63
    .devpath_in = "/dev/dsp"
67 64
};
68 65

  
69 66
struct oss_params {
......
74 71
    int fragsize;
75 72
};
76 73

  
77
static int oss_hw_write (SWVoice *sw, void *buf, int len)
74
static void GCC_FMT_ATTR (2, 3) oss_logerr (int err, const char *fmt, ...)
78 75
{
79
    return pcm_hw_write (sw, buf, len);
76
    va_list ap;
77

  
78
    AUD_vlog (AUDIO_CAP, fmt, ap);
79

  
80
    va_start (ap, fmt);
81
    AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err));
82
    va_end (ap);
80 83
}
81 84

  
82
static int AUD_to_ossfmt (audfmt_e fmt)
85
static void GCC_FMT_ATTR (3, 4) oss_logerr2 (
86
    int err,
87
    const char *typ,
88
    const char *fmt,
89
    ...
90
    )
91
{
92
    va_list ap;
93

  
94
    AUD_log (AUDIO_CAP, "Can not initialize %s\n", typ);
95

  
96
    va_start (ap, fmt);
97
    AUD_vlog (AUDIO_CAP, fmt, ap);
98
    va_end (ap);
99

  
100
    AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err));
101
}
102

  
103
static void oss_anal_close (int *fdp)
104
{
105
    int err = close (*fdp);
106
    if (err) {
107
        oss_logerr (errno, "Failed to close file(fd=%d)\n", *fdp);
108
    }
109
    *fdp = -1;
110
}
111

  
112
static int oss_write (SWVoiceOut *sw, void *buf, int len)
113
{
114
    return audio_pcm_sw_write (sw, buf, len);
115
}
116

  
117
static int aud_to_ossfmt (audfmt_e fmt)
83 118
{
84 119
    switch (fmt) {
85
    case AUD_FMT_S8: return AFMT_S8;
86
    case AUD_FMT_U8: return AFMT_U8;
87
    case AUD_FMT_S16: return AFMT_S16_LE;
88
    case AUD_FMT_U16: return AFMT_U16_LE;
120
    case AUD_FMT_S8:
121
        return AFMT_S8;
122

  
123
    case AUD_FMT_U8:
124
        return AFMT_U8;
125

  
126
    case AUD_FMT_S16:
127
        return AFMT_S16_LE;
128

  
129
    case AUD_FMT_U16:
130
        return AFMT_U16_LE;
131

  
89 132
    default:
90
        dolog ("Internal logic error: Bad audio format %d\nAborting\n", fmt);
91
        exit (EXIT_FAILURE);
133
        dolog ("Internal logic error: Bad audio format %d\n", fmt);
134
#ifdef DEBUG_AUDIO
135
        abort ();
136
#endif
137
        return AFMT_U8;
92 138
    }
93 139
}
94 140

  
95
static int oss_to_audfmt (int fmt)
141
static int oss_to_audfmt (int ossfmt, audfmt_e *fmt, int *endianness)
96 142
{
97
    switch (fmt) {
98
    case AFMT_S8: return AUD_FMT_S8;
99
    case AFMT_U8: return AUD_FMT_U8;
100
    case AFMT_S16_LE: return AUD_FMT_S16;
101
    case AFMT_U16_LE: return AUD_FMT_U16;
143
    switch (ossfmt) {
144
    case AFMT_S8:
145
        *endianness =0;
146
        *fmt = AUD_FMT_S8;
147
        break;
148

  
149
    case AFMT_U8:
150
        *endianness = 0;
151
        *fmt = AUD_FMT_U8;
152
        break;
153

  
154
    case AFMT_S16_LE:
155
        *endianness = 0;
156
        *fmt = AUD_FMT_S16;
157
        break;
158

  
159
    case AFMT_U16_LE:
160
        *endianness = 0;
161
        *fmt = AUD_FMT_U16;
162
        break;
163

  
164
    case AFMT_S16_BE:
165
        *endianness = 1;
166
        *fmt = AUD_FMT_S16;
167
        break;
168

  
169
    case AFMT_U16_BE:
170
        *endianness = 1;
171
        *fmt = AUD_FMT_U16;
172
        break;
173

  
102 174
    default:
103
        dolog ("Internal logic error: Unrecognized OSS audio format %d\n"
104
               "Aborting\n",
105
               fmt);
106
        exit (EXIT_FAILURE);
175
        dolog ("Unrecognized audio format %d\n", ossfmt);
176
        return -1;
107 177
    }
178

  
179
    return 0;
108 180
}
109 181

  
110
#ifdef DEBUG_PCM
111
static void oss_dump_pcm_info (struct oss_params *req, struct oss_params *obt)
182
#ifdef DEBUG_MISMATCHES
183
static void oss_dump_info (struct oss_params *req, struct oss_params *obt)
112 184
{
113 185
    dolog ("parameter | requested value | obtained value\n");
114 186
    dolog ("format    |      %10d |     %10d\n", req->fmt, obt->fmt);
115
    dolog ("channels  |      %10d |     %10d\n", req->nchannels, obt->nchannels);
187
    dolog ("channels  |      %10d |     %10d\n",
188
           req->nchannels, obt->nchannels);
116 189
    dolog ("frequency |      %10d |     %10d\n", req->freq, obt->freq);
117 190
    dolog ("nfrags    |      %10d |     %10d\n", req->nfrags, obt->nfrags);
118
    dolog ("fragsize  |      %10d |     %10d\n", req->fragsize, obt->fragsize);
191
    dolog ("fragsize  |      %10d |     %10d\n",
192
           req->fragsize, obt->fragsize);
119 193
}
120 194
#endif
121 195

  
122
static int oss_open (struct oss_params *req, struct oss_params *obt, int *pfd)
196
static int oss_open (int in, struct oss_params *req,
197
                     struct oss_params *obt, int *pfd)
123 198
{
124 199
    int fd;
125 200
    int mmmmssss;
126 201
    audio_buf_info abinfo;
127 202
    int fmt, freq, nchannels;
128
    const char *dspname = conf.dspname;
203
    const char *dspname = in ? conf.devpath_in : conf.devpath_out;
204
    const char *typ = in ? "ADC" : "DAC";
129 205

  
130
    fd = open (dspname, O_WRONLY | O_NONBLOCK);
206
    fd = open (dspname, (in ? O_RDONLY : O_WRONLY) | O_NONBLOCK);
131 207
    if (-1 == fd) {
132
        dolog ("Could not initialize audio hardware. Failed to open `%s':\n"
133
               "Reason:%s\n",
134
               dspname,
135
               errstr ());
208
        oss_logerr2 (errno, typ, "Failed to open `%s'\n", dspname);
136 209
        return -1;
137 210
    }
138 211

  
......
141 214
    fmt = req->fmt;
142 215

  
143 216
    if (ioctl (fd, SNDCTL_DSP_SAMPLESIZE, &fmt)) {
144
        dolog ("Could not initialize audio hardware\n"
145
               "Failed to set sample size\n"
146
               "Reason: %s\n",
147
               errstr ());
217
        oss_logerr2 (errno, typ, "Failed to set sample size %d\n", req->fmt);
148 218
        goto err;
149 219
    }
150 220

  
151 221
    if (ioctl (fd, SNDCTL_DSP_CHANNELS, &nchannels)) {
152
        dolog ("Could not initialize audio hardware\n"
153
               "Failed to set number of channels\n"
154
               "Reason: %s\n",
155
               errstr ());
222
        oss_logerr2 (errno, typ, "Failed to set number of channels %d\n",
223
                     req->nchannels);
156 224
        goto err;
157 225
    }
158 226

  
159 227
    if (ioctl (fd, SNDCTL_DSP_SPEED, &freq)) {
160
        dolog ("Could not initialize audio hardware\n"
161
               "Failed to set frequency\n"
162
               "Reason: %s\n",
163
               errstr ());
228
        oss_logerr2 (errno, typ, "Failed to set frequency %d\n", req->freq);
164 229
        goto err;
165 230
    }
166 231

  
167 232
    if (ioctl (fd, SNDCTL_DSP_NONBLOCK)) {
168
        dolog ("Could not initialize audio hardware\n"
169
               "Failed to set non-blocking mode\n"
170
               "Reason: %s\n",
171
               errstr ());
233
        oss_logerr2 (errno, typ, "Failed to set non-blocking mode\n");
172 234
        goto err;
173 235
    }
174 236

  
175 237
    mmmmssss = (req->nfrags << 16) | lsbindex (req->fragsize);
176 238
    if (ioctl (fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss)) {
177
        dolog ("Could not initialize audio hardware\n"
178
               "Failed to set buffer length (%d, %d)\n"
179
               "Reason:%s\n",
180
               conf.nfrags, conf.fragsize,
181
               errstr ());
239
        oss_logerr2 (errno, typ, "Failed to set buffer length (%d, %d)\n",
240
                     req->nfrags, req->fragsize);
182 241
        goto err;
183 242
    }
184 243

  
185
    if (ioctl (fd, SNDCTL_DSP_GETOSPACE, &abinfo)) {
186
        dolog ("Could not initialize audio hardware\n"
187
               "Failed to get buffer length\n"
188
               "Reason:%s\n",
189
               errstr ());
244
    if (ioctl (fd, in ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE, &abinfo)) {
245
        oss_logerr2 (errno, typ, "Failed to get buffer length\n");
190 246
        goto err;
191 247
    }
192 248

  
......
202 258
        (req->freq != obt->freq) ||
203 259
        (req->fragsize != obt->fragsize) ||
204 260
        (req->nfrags != obt->nfrags)) {
205
#ifdef DEBUG_PCM
261
#ifdef DEBUG_MISMATCHES
206 262
        dolog ("Audio parameters mismatch\n");
207
        oss_dump_pcm_info (req, obt);
263
        oss_dump_info (req, obt);
208 264
#endif
209 265
    }
210 266

  
211
#ifdef DEBUG_PCM
212
    oss_dump_pcm_info (req, obt);
267
#ifdef DEBUG
268
    oss_dump_info (req, obt);
213 269
#endif
214 270
    return 0;
215 271

  
216
err:
217
    close (fd);
272
 err:
273
    oss_anal_close (&fd);
218 274
    return -1;
219 275
}
220 276

  
221
static void oss_hw_run (HWVoice *hw)
277
static int oss_run_out (HWVoiceOut *hw)
222 278
{
223
    OSSVoice *oss = (OSSVoice *) hw;
279
    OSSVoiceOut *oss = (OSSVoiceOut *) hw;
224 280
    int err, rpos, live, decr;
225 281
    int samples;
226 282
    uint8_t *dst;
......
228 284
    struct audio_buf_info abinfo;
229 285
    struct count_info cntinfo;
230 286

  
231
    live = pcm_hw_get_live (hw);
232
    if (live <= 0)
233
        return;
287
    live = audio_pcm_hw_get_live_out (hw);
288
    if (!live) {
289
        return 0;
290
    }
234 291

  
235 292
    if (oss->mmapped) {
236 293
        int bytes;
237 294

  
238 295
        err = ioctl (oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo);
239 296
        if (err < 0) {
240
            dolog ("SNDCTL_DSP_GETOPTR failed\nReason: %s\n", errstr ());
241
            return;
297
            oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n");
298
            return 0;
242 299
        }
243 300

  
244 301
        if (cntinfo.ptr == oss->old_optr) {
245
            if (abs (hw->samples - live) < 64)
246
                dolog ("overrun\n");
247
            return;
302
            if (abs (hw->samples - live) < 64) {
303
                dolog ("warning: overrun\n");
304
            }
305
            return 0;
248 306
        }
249 307

  
250 308
        if (cntinfo.ptr > oss->old_optr) {
......
254 312
            bytes = hw->bufsize + cntinfo.ptr - oss->old_optr;
255 313
        }
256 314

  
257
        decr = audio_MIN (bytes >> hw->shift, live);
315
        decr = audio_MIN (bytes >> hw->info.shift, live);
258 316
    }
259 317
    else {
260 318
        err = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &abinfo);
261 319
        if (err < 0) {
262
            dolog ("SNDCTL_DSP_GETOSPACE failed\nReason: %s\n", errstr ());
263
            return;
320
            oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n");
321
            return 0;
322
        }
323

  
324
        if (abinfo.bytes < 0 || abinfo.bytes > hw->bufsize) {
325
            ldebug ("warning: invalid available size, size=%d bufsize=%d\n",
326
                    abinfo.bytes, hw->bufsize);
327
            return 0;
264 328
        }
265 329

  
266
        decr = audio_MIN (abinfo.bytes >> hw->shift, live);
267
        if (decr <= 0)
268
            return;
330
        decr = audio_MIN (abinfo.bytes >> hw->info.shift, live);
331
        if (!decr) {
332
            return 0;
333
        }
269 334
    }
270 335

  
271 336
    samples = decr;
......
274 339
        int left_till_end_samples = hw->samples - rpos;
275 340
        int convert_samples = audio_MIN (samples, left_till_end_samples);
276 341

  
277
        src = advance (hw->mix_buf, rpos * sizeof (st_sample_t));
278
        dst = advance (oss->pcm_buf, rpos << hw->shift);
342
        src = hw->mix_buf + rpos;
343
        dst = advance (oss->pcm_buf, rpos << hw->info.shift);
279 344

  
280 345
        hw->clip (dst, src, convert_samples);
281 346
        if (!oss->mmapped) {
282 347
            int written;
283 348

  
284
            written = write (oss->fd, dst, convert_samples << hw->shift);
349
            written = write (oss->fd, dst, convert_samples << hw->info.shift);
285 350
            /* XXX: follow errno recommendations ? */
286 351
            if (written == -1) {
287
                dolog ("Failed to write audio\nReason: %s\n", errstr ());
352
                oss_logerr (
353
                    errno,
354
                    "Failed to write %d bytes of audio data from %p\n",
355
                    convert_samples << hw->info.shift,
356
                    dst
357
                    );
288 358
                continue;
289 359
            }
290 360

  
291
            if (written != convert_samples << hw->shift) {
292
                int wsamples = written >> hw->shift;
293
                int wbytes = wsamples << hw->shift;
361
            if (written != convert_samples << hw->info.shift) {
362
                int wsamples = written >> hw->info.shift;
363
                int wbytes = wsamples << hw->info.shift;
294 364
                if (wbytes != written) {
295
                    dolog ("Unaligned write %d, %d\n", wbytes, written);
365
                    dolog ("warning: misaligned write %d (requested %d), "
366
                           "alignment %d\n",
367
                           wbytes, written, hw->info.align + 1);
296 368
                }
297
                memset (src, 0, wbytes);
298
                decr -= samples;
369
                mixeng_clear (src, wsamples);
370
                decr -= wsamples;
299 371
                rpos = (rpos + wsamples) % hw->samples;
300 372
                break;
301 373
            }
302 374
        }
303
        memset (src, 0, convert_samples * sizeof (st_sample_t));
375

  
376
        mixeng_clear (src, convert_samples);
304 377

  
305 378
        rpos = (rpos + convert_samples) % hw->samples;
306 379
        samples -= convert_samples;
......
309 382
        oss->old_optr = cntinfo.ptr;
310 383
    }
311 384

  
312
    pcm_hw_dec_live (hw, decr);
313 385
    hw->rpos = rpos;
386
    return decr;
314 387
}
315 388

  
316
static void oss_hw_fini (HWVoice *hw)
389
static void oss_fini_out (HWVoiceOut *hw)
317 390
{
318 391
    int err;
319
    OSSVoice *oss = (OSSVoice *) hw;
392
    OSSVoiceOut *oss = (OSSVoiceOut *) hw;
320 393

  
321
    ldebug ("oss_hw_fini\n");
322
    err = close (oss->fd);
323
    if (err) {
324
        dolog ("Failed to close OSS descriptor\nReason: %s\n", errstr ());
325
    }
326
    oss->fd = -1;
394
    ldebug ("oss_fini\n");
395
    oss_anal_close (&oss->fd);
327 396

  
328 397
    if (oss->pcm_buf) {
329 398
        if (oss->mmapped) {
330 399
            err = munmap (oss->pcm_buf, hw->bufsize);
331 400
            if (err) {
332
                dolog ("Failed to unmap OSS buffer\nReason: %s\n",
333
                       errstr ());
401
                oss_logerr (errno, "Failed to unmap buffer %p, size %d\n",
402
                            oss->pcm_buf, hw->bufsize);
334 403
            }
335 404
        }
336 405
        else {
......
340 409
    }
341 410
}
342 411

  
343
static int oss_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
412
static int oss_init_out (HWVoiceOut *hw, int freq, int nchannels, audfmt_e fmt)
344 413
{
345
    OSSVoice *oss = (OSSVoice *) hw;
414
    OSSVoiceOut *oss = (OSSVoiceOut *) hw;
346 415
    struct oss_params req, obt;
416
    int endianness;
417
    int err;
418
    int fd;
419
    audfmt_e effective_fmt;
347 420

  
348
    assert (!oss->fd);
349
    req.fmt = AUD_to_ossfmt (fmt);
421
    req.fmt = aud_to_ossfmt (fmt);
350 422
    req.freq = freq;
351 423
    req.nchannels = nchannels;
352 424
    req.fragsize = conf.fragsize;
353 425
    req.nfrags = conf.nfrags;
354 426

  
355
    if (oss_open (&req, &obt, &oss->fd))
427
    if (oss_open (0, &req, &obt, &fd)) {
356 428
        return -1;
429
    }
357 430

  
358
    hw->freq = obt.freq;
359
    hw->fmt = oss_to_audfmt (obt.fmt);
360
    hw->nchannels = obt.nchannels;
431
    err = oss_to_audfmt (obt.fmt, &effective_fmt, &endianness);
432
    if (err) {
433
        oss_anal_close (&fd);
434
        return -1;
435
    }
361 436

  
437
    audio_pcm_init_info (
438
        &hw->info,
439
        obt.freq,
440
        obt.nchannels,
441
        effective_fmt,
442
        audio_need_to_swap_endian (endianness)
443
        );
362 444
    oss->nfrags = obt.nfrags;
363 445
    oss->fragsize = obt.fragsize;
364 446
    hw->bufsize = obt.nfrags * obt.fragsize;
......
366 448
    oss->mmapped = 0;
367 449
    if (conf.try_mmap) {
368 450
        oss->pcm_buf = mmap (0, hw->bufsize, PROT_READ | PROT_WRITE,
369
                             MAP_SHARED, oss->fd, 0);
451
                             MAP_SHARED, fd, 0);
370 452
        if (oss->pcm_buf == MAP_FAILED) {
371
            dolog ("Failed to mmap OSS device\nReason: %s\n",
372
                   errstr ());
453
            oss_logerr (errno, "Failed to map %d bytes of DAC\n",
454
                        hw->bufsize);
373 455
        } else {
374 456
            int err;
375 457
            int trig = 0;
376
            if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
377
                dolog ("SNDCTL_DSP_SETTRIGGER 0 failed\nReason: %s\n",
378
                       errstr ());
458
            if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
459
                oss_logerr (errno, "SNDCTL_DSP_SETTRIGGER 0 failed\n");
379 460
            }
380 461
            else {
381 462
                trig = PCM_ENABLE_OUTPUT;
382
                if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
383
                    dolog ("SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
384
                           "Reason: %s\n", errstr ());
463
                if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
464
                    oss_logerr (
465
                        errno,
466
                        "SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
467
                        );
385 468
                }
386 469
                else {
387 470
                    oss->mmapped = 1;
......
391 474
            if (!oss->mmapped) {
392 475
                err = munmap (oss->pcm_buf, hw->bufsize);
393 476
                if (err) {
394
                    dolog ("Failed to unmap OSS device\nReason: %s\n",
395
                           errstr ());
477
                    oss_logerr (errno, "Failed to unmap buffer %p size %d\n",
478
                                oss->pcm_buf, hw->bufsize);
396 479
                }
397 480
            }
398 481
        }
......
401 484
    if (!oss->mmapped) {
402 485
        oss->pcm_buf = qemu_mallocz (hw->bufsize);
403 486
        if (!oss->pcm_buf) {
404
            close (oss->fd);
405
            oss->fd = -1;
487
            oss_anal_close (&fd);
406 488
            return -1;
407 489
        }
408 490
    }
409 491

  
492
    oss->fd = fd;
410 493
    return 0;
411 494
}
412 495

  
413
static int oss_hw_ctl (HWVoice *hw, int cmd, ...)
496
static int oss_ctl_out (HWVoiceOut *hw, int cmd, ...)
414 497
{
415 498
    int trig;
416
    OSSVoice *oss = (OSSVoice *) hw;
499
    OSSVoiceOut *oss = (OSSVoiceOut *) hw;
417 500

  
418
    if (!oss->mmapped)
501
    if (!oss->mmapped) {
419 502
        return 0;
503
    }
420 504

  
421 505
    switch (cmd) {
422 506
    case VOICE_ENABLE:
423 507
        ldebug ("enabling voice\n");
424
        pcm_hw_clear (hw, oss->pcm_buf, hw->samples);
508
        audio_pcm_info_clear_buf (&hw->info, oss->pcm_buf, hw->samples);
425 509
        trig = PCM_ENABLE_OUTPUT;
426 510
        if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
427
            dolog ("SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
428
                   "Reason: %s\n", errstr ());
511
            oss_logerr (
512
                errno,
513
                "SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
514
                );
429 515
            return -1;
430 516
        }
431 517
        break;
......
434 520
        ldebug ("disabling voice\n");
435 521
        trig = 0;
436 522
        if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
437
            dolog ("SNDCTL_DSP_SETTRIGGER 0 failed\nReason: %s\n",
438
                   errstr ());
523
            oss_logerr (errno, "SNDCTL_DSP_SETTRIGGER 0 failed\n");
439 524
            return -1;
440 525
        }
441 526
        break;
......
443 528
    return 0;
444 529
}
445 530

  
531
static int oss_init_in (HWVoiceIn *hw,
532
                        int freq, int nchannels, audfmt_e fmt)
533
{
534
    OSSVoiceIn *oss = (OSSVoiceIn *) hw;
535
    struct oss_params req, obt;
536
    int endianness;
537
    int err;
538
    int fd;
539
    audfmt_e effective_fmt;
540

  
541
    req.fmt = aud_to_ossfmt (fmt);
542
    req.freq = freq;
543
    req.nchannels = nchannels;
544
    req.fragsize = conf.fragsize;
545
    req.nfrags = conf.nfrags;
546
    if (oss_open (1, &req, &obt, &fd)) {
547
        return -1;
548
    }
549

  
550
    err = oss_to_audfmt (obt.fmt, &effective_fmt, &endianness);
551
    if (err) {
552
        oss_anal_close (&fd);
553
        return -1;
554
    }
555

  
556
    audio_pcm_init_info (
557
        &hw->info,
558
        obt.freq,
559
        obt.nchannels,
560
        effective_fmt,
561
        audio_need_to_swap_endian (endianness)
562
        );
563
    oss->nfrags = obt.nfrags;
564
    oss->fragsize = obt.fragsize;
565
    hw->bufsize = obt.nfrags * obt.fragsize;
566
    oss->pcm_buf = qemu_mallocz (hw->bufsize);
567
    if (!oss->pcm_buf) {
568
        oss_anal_close (&fd);
569
        return -1;
570
    }
571

  
572
    oss->fd = fd;
573
    return 0;
574
}
575

  
576
static void oss_fini_in (HWVoiceIn *hw)
577
{
578
    OSSVoiceIn *oss = (OSSVoiceIn *) hw;
579

  
580
    oss_anal_close (&oss->fd);
581

  
582
    if (oss->pcm_buf) {
583
        qemu_free (oss->pcm_buf);
584
        oss->pcm_buf = NULL;
585
    }
586
}
587

  
588
static int oss_run_in (HWVoiceIn *hw)
589
{
590
    OSSVoiceIn *oss = (OSSVoiceIn *) hw;
591
    int hwshift = hw->info.shift;
592
    int i;
593
    int live = audio_pcm_hw_get_live_in (hw);
594
    int dead = hw->samples - live;
595
    size_t read_samples = 0;
596
    struct {
597
        int add;
598
        int len;
599
    } bufs[2] = {
600
        { hw->wpos, 0 },
601
        { 0, 0 }
602
    };
603

  
604
    if (!dead) {
605
        return 0;
606
    }
607

  
608
    if (hw->wpos + dead > hw->samples) {
609
        bufs[0].len = (hw->samples - hw->wpos) << hwshift;
610
        bufs[1].len = (dead - (hw->samples - hw->wpos)) << hwshift;
611
    }
612
    else {
613
        bufs[0].len = dead << hwshift;
614
    }
615

  
616

  
617
    for (i = 0; i < 2; ++i) {
618
        ssize_t nread;
619

  
620
        if (bufs[i].len) {
621
            void *p = advance (oss->pcm_buf, bufs[i].add << hwshift);
622
            nread = read (oss->fd, p, bufs[i].len);
623

  
624
            if (nread > 0) {
625
                if (nread & hw->info.align) {
626
                    dolog ("warning: misaligned read %d (requested %d), "
627
                           "alignment %d\n", nread, bufs[i].add << hwshift,
628
                           hw->info.align + 1);
629
                }
630
                read_samples += nread >> hwshift;
631
                hw->conv (hw->conv_buf + bufs[i].add, p, nread >> hwshift,
632
                          &nominal_volume);
633
            }
634

  
635
            if (bufs[i].len - nread) {
636
                if (nread == -1) {
637
                    switch (errno) {
638
                    case EINTR:
639
                    case EAGAIN:
640
                        break;
641
                    default:
642
                        oss_logerr (
643
                            errno,
644
                            "Failed to read %d bytes of audio (to %p)\n",
645
                            bufs[i].len, p
646
                            );
647
                        break;
648
                    }
649
                }
650
                break;
651
            }
652
        }
653
    }
654

  
655
    hw->wpos = (hw->wpos + read_samples) % hw->samples;
656
    return read_samples;
657
}
658

  
659
static int oss_read (SWVoiceIn *sw, void *buf, int size)
660
{
661
    return audio_pcm_sw_read (sw, buf, size);
662
}
663

  
664
static int oss_ctl_in (HWVoiceIn *hw, int cmd, ...)
665
{
666
    (void) hw;
667
    (void) cmd;
668
    return 0;
669
}
670

  
446 671
static void *oss_audio_init (void)
447 672
{
448
    conf.fragsize = audio_get_conf_int (QC_OSS_FRAGSIZE, conf.fragsize);
449
    conf.nfrags = audio_get_conf_int (QC_OSS_NFRAGS, conf.nfrags);
450
    conf.try_mmap = audio_get_conf_int (QC_OSS_MMAP, conf.try_mmap);
451
    conf.dspname = audio_get_conf_str (QC_OSS_DEV, conf.dspname);
452 673
    return &conf;
453 674
}
454 675

  
455 676
static void oss_audio_fini (void *opaque)
456 677
{
678
    (void) opaque;
457 679
}
458 680

  
459
struct pcm_ops oss_pcm_ops = {
460
    oss_hw_init,
461
    oss_hw_fini,
462
    oss_hw_run,
463
    oss_hw_write,
464
    oss_hw_ctl
681
static struct audio_option oss_options[] = {
682
    {"FRAGSIZE", AUD_OPT_INT, &conf.fragsize,
683
     "Fragment size in bytes", NULL, 0},
684
    {"NFRAGS", AUD_OPT_INT, &conf.nfrags,
685
     "Number of fragments", NULL, 0},
686
    {"MMAP", AUD_OPT_BOOL, &conf.try_mmap,
687
     "Try using memory mapped access", NULL, 0},
688
    {"DAC_DEV", AUD_OPT_STR, &conf.devpath_out,
689
     "Path to DAC device", NULL, 0},
690
    {"ADC_DEV", AUD_OPT_STR, &conf.devpath_in,
691
     "Path to ADC device", NULL, 0},
692
    {NULL, 0, NULL, NULL, NULL, 0}
693
};
694

  
695
static struct audio_pcm_ops oss_pcm_ops = {
696
    oss_init_out,
697
    oss_fini_out,
698
    oss_run_out,
699
    oss_write,
700
    oss_ctl_out,
701

  
702
    oss_init_in,
703
    oss_fini_in,
704
    oss_run_in,
705
    oss_read,
706
    oss_ctl_in
465 707
};
466 708

  
467
struct audio_output_driver oss_output_driver = {
468
    "oss",
469
    oss_audio_init,
470
    oss_audio_fini,
471
    &oss_pcm_ops,
472
    1,
473
    INT_MAX,
474
    sizeof (OSSVoice)
709
struct audio_driver oss_audio_driver = {
710
    INIT_FIELD (name           = ) "oss",
711
    INIT_FIELD (descr          = ) "OSS http://www.opensound.com",
712
    INIT_FIELD (options        = ) oss_options,
713
    INIT_FIELD (init           = ) oss_audio_init,
714
    INIT_FIELD (fini           = ) oss_audio_fini,
715
    INIT_FIELD (pcm_ops        = ) &oss_pcm_ops,
716
    INIT_FIELD (can_be_default = ) 1,
717
    INIT_FIELD (max_voices_out = ) INT_MAX,
718
    INIT_FIELD (max_voices_in  = ) INT_MAX,
719
    INIT_FIELD (voice_size_out = ) sizeof (OSSVoiceOut),
720
    INIT_FIELD (voice_size_in  = ) sizeof (OSSVoiceIn)
475 721
};

Also available in: Unified diff