~ubuntu-branches/ubuntu/trusty/libao/trusty

« back to all changes in this revision

Viewing changes to src/plugins/alsa/ao_alsa.c

  • Committer: Bazaar Package Importer
  • Author(s): John Francesco Ferlito
  • Date: 2010-04-11 11:04:30 UTC
  • mfrom: (5.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20100411110430-wldc1w7ll1j6c4yc
Tags: 1.0.0-4
Actually depend on libao.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
 *  ao_alsa.c
4
4
 *
5
5
 *      Copyright (C) Stan Seibert - July 2000, July 2001
 
6
 *      Modifications Copyright (C) Monty - January 2010
6
7
 *
7
8
 *  This file is part of libao, a cross-platform library.  See
8
9
 *  README for a history of this source code.
21
22
 *  along with GNU Make; see the file COPYING.  If not, write to
22
23
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23
24
 *
 
25
 *  Largely rewritten 2/18/2002 Kevin Cody Jr <kevinc@wuff.dhs.org>
 
26
 *
24
27
 */
25
28
 
 
29
#define ALSA_PCM_NEW_HW_PARAMS_API
 
30
#define ALSA_PCM_NEW_SW_PARAMS_API
 
31
 
26
32
#include <stdio.h>
27
33
#include <unistd.h>
28
34
#include <stdlib.h>
30
36
#include <sys/stat.h>
31
37
#include <string.h>
32
38
 
33
 
#include <sys/asoundlib.h>
 
39
#include <alsa/asoundlib.h>
34
40
#include <ao/ao.h>
35
41
#include <ao/plugin.h>
36
42
 
37
 
#define AO_ALSA_BUF_SIZE 32768
38
 
 
39
 
 
40
 
static char *ao_alsa_options[] = {"card","dev","buf_size"};
 
43
/* default 500 millisecond buffer */
 
44
#define AO_ALSA_BUFFER_TIME 500000
 
45
 
 
46
/* the period time is calculated if not given as an option */
 
47
#define AO_ALSA_PERIOD_TIME 0
 
48
 
 
49
/* number of samples between interrupts
 
50
 * supplying a period_time to ao overrides the use of this  */
 
51
#define AO_ALSA_SAMPLE_XFER 256
 
52
 
 
53
/* set mmap to default if enabled at compile time, otherwise, mmap isn't
 
54
   the default */
 
55
#ifdef USE_ALSA_MMIO
 
56
#define AO_ALSA_WRITEI snd_pcm_mmap_writei
 
57
#define AO_ALSA_ACCESS_MASK SND_PCM_ACCESS_MMAP_INTERLEAVED
 
58
#else
 
59
#define AO_ALSA_WRITEI snd_pcm_writei
 
60
#define AO_ALSA_ACCESS_MASK SND_PCM_ACCESS_RW_INTERLEAVED
 
61
#endif
 
62
 
 
63
typedef snd_pcm_sframes_t ao_alsa_writei_t(snd_pcm_t *pcm, const void *buffer,
 
64
                                                snd_pcm_uframes_t size);
 
65
 
 
66
static char *ao_alsa_options[] = {
 
67
        "dev",
 
68
        "buffer_time",
 
69
        "period_time",
 
70
        "use_mmap",
 
71
        "matrix",
 
72
        "verbose",
 
73
        "quiet",
 
74
        "debug"
 
75
};
 
76
 
 
77
 
41
78
static ao_info ao_alsa_info =
42
79
{
43
80
        AO_TYPE_LIVE,
44
81
        "Advanced Linux Sound Architecture (ALSA) output",
45
 
        "alsa05",
46
 
        "Stan Seibert <volsung@asu.edu>",
47
 
        "Outputs to the Advanced Linux Sound Architecture version 0.5.x.",
 
82
        "alsa",
 
83
        "Bill Currie <bill@taniwha.org>/Kevin Cody, Jr. <kevinc@wuff.dhs.org>",
 
84
        "Outputs to the Advanced Linux Sound Architecture version 0.9/1.x",
48
85
        AO_FMT_NATIVE,
49
 
        34,
 
86
        35,
50
87
        ao_alsa_options,
51
 
        3
 
88
        8
52
89
};
53
90
 
 
91
 
54
92
typedef struct ao_alsa_internal
55
93
{
56
94
        snd_pcm_t *pcm_handle;
57
 
        char *buf;
58
 
        int buf_size;
59
 
        int buf_end;
60
 
        int card;
61
 
        int dev;
 
95
        unsigned int buffer_time;
 
96
        unsigned int period_time;
 
97
        snd_pcm_uframes_t period_size;
 
98
        int sample_size;
 
99
        snd_pcm_format_t bitformat;
 
100
        char *dev;
 
101
        ao_alsa_writei_t * writei;
 
102
        snd_pcm_access_t access_mask;
62
103
} ao_alsa_internal;
63
104
 
64
105
 
 
106
/* determine if parameters are requires for this particular plugin */
65
107
int ao_plugin_test()
66
108
{
67
109
        snd_pcm_t *handle;
 
110
        int err;
68
111
 
69
 
        if (snd_pcm_open(&handle, 0, 0, 
70
 
                         SND_PCM_OPEN_PLAYBACK | SND_PCM_OPEN_NONBLOCK) != 0)
 
112
        /* Use nonblock flag when testing to avoid getting stuck if the device
 
113
           is in use. Try several devices, as 'default' usually means 'stereo only'. */
 
114
        err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK,
 
115
                           SND_PCM_NONBLOCK);
 
116
        if (err != 0)
71
117
                return 0; /* Cannot use this plugin with default parameters */
72
118
        else {
73
119
                snd_pcm_close(handle);
76
122
}
77
123
 
78
124
 
 
125
/* return the address of the driver info structure */
79
126
ao_info *ao_plugin_driver_info(void)
80
127
{
81
128
        return &ao_alsa_info;
82
129
}
83
130
 
84
131
 
 
132
/* initialize internal data structures */
85
133
int ao_plugin_device_init(ao_device *device)
86
134
{
87
135
        ao_alsa_internal *internal;
88
136
 
89
 
        internal = (ao_alsa_internal *) malloc(sizeof(ao_alsa_internal));
90
 
 
91
 
        if (internal == NULL)   
92
 
                return 0; /* Could not initialize device memory */
93
 
        
94
 
        internal->buf_size = AO_ALSA_BUF_SIZE;
95
 
        internal->card = 0;
96
 
        internal->dev = 0;
97
 
        
 
137
        internal = (ao_alsa_internal *) calloc(1,sizeof(ao_alsa_internal));
 
138
 
 
139
        if (internal == NULL)
 
140
                return 0;
 
141
 
 
142
        internal->buffer_time = AO_ALSA_BUFFER_TIME;
 
143
        internal->period_time = AO_ALSA_PERIOD_TIME;
 
144
        internal->writei = AO_ALSA_WRITEI;
 
145
        internal->access_mask = AO_ALSA_ACCESS_MASK;
 
146
 
98
147
        device->internal = internal;
 
148
        device->output_matrix = strdup("L,R,BL,BR,C,LFE,SL,SR");
 
149
        device->output_matrix_order = AO_OUTPUT_MATRIX_FIXED;
99
150
 
100
 
        return 1; /* Memory alloc successful */
 
151
        return 1;
101
152
}
102
153
 
103
154
 
 
155
/* pass application parameters regarding the sound device */
104
156
int ao_plugin_set_option(ao_device *device, const char *key, const char *value)
105
157
{
106
158
        ao_alsa_internal *internal = (ao_alsa_internal *) device->internal;
107
 
        if (!strcmp(key, "card"))
108
 
                internal->card = atoi(value);
109
 
        else if (!strcmp(key, "dev"))
110
 
                internal->dev = atoi(value);
111
 
        else if (!strcmp(key, "buf_size"))
112
 
                internal->buf_size = atoi(value);
113
 
 
114
 
        return 1;
115
 
}
116
 
 
 
159
 
 
160
        if (!strcmp(key, "dev")) {
 
161
                if (internal->dev)
 
162
                        free (internal->dev);
 
163
                if (!(internal->dev = strdup(value)))
 
164
                        return 0;
 
165
        }
 
166
        else if (!strcmp(key, "buffer_time"))
 
167
                internal->buffer_time = atoi(value) * 1000;
 
168
        else if (!strcmp(key, "period_time"))
 
169
                internal->period_time = atoi(value);
 
170
        else if (!strcmp(key,"use_mmap")) {
 
171
                if(!strcmp(value,"yes") || !strcmp(value,"y") || 
 
172
                        !strcmp(value,"true") || !strcmp(value,"t") ||
 
173
                        !strcmp(value,"1"))
 
174
                {
 
175
                        internal->writei = snd_pcm_mmap_writei;
 
176
                        internal->access_mask = SND_PCM_ACCESS_MMAP_INTERLEAVED;
 
177
                }
 
178
                else {
 
179
                        internal->writei = snd_pcm_writei;
 
180
                        internal->access_mask = SND_PCM_ACCESS_RW_INTERLEAVED;
 
181
                }
 
182
        }
 
183
 
 
184
        return 1;
 
185
}
 
186
 
 
187
 
 
188
/* determine the alsa bitformat for a given bitwidth and endianness */
 
189
static inline int alsa_get_sample_bitformat(int bitwidth, int bigendian, ao_device *device)
 
190
{
 
191
        int ret;
 
192
 
 
193
        switch (bitwidth) {
 
194
        case 8  : ret = SND_PCM_FORMAT_S8;
 
195
                  break;
 
196
        case 16 : ret = SND_PCM_FORMAT_S16;
 
197
                  break;
 
198
        case 24 : ret = SND_PCM_FORMAT_S24;
 
199
                  break;
 
200
        case 32 : ret = SND_PCM_FORMAT_S32;
 
201
                  break;
 
202
        default : aerror("invalid bitwidth %d\n", bitwidth);
 
203
                  return -1;
 
204
        }
 
205
 
 
206
        return ret;
 
207
}
 
208
 
 
209
/* setup alsa data format and buffer geometry */
 
210
static inline int alsa_set_hwparams(ao_device *device,
 
211
                                    ao_sample_format *format)
 
212
{
 
213
        ao_alsa_internal *internal  = (ao_alsa_internal *) device->internal;
 
214
        snd_pcm_hw_params_t   *params;
 
215
        int err;
 
216
        unsigned int rate = format->rate;
 
217
 
 
218
        /* allocate the hardware parameter structure */
 
219
        snd_pcm_hw_params_alloca(&params);
 
220
 
 
221
        /* fetch all possible hardware parameters */
 
222
        err = snd_pcm_hw_params_any(internal->pcm_handle, params);
 
223
        if (err < 0){
 
224
          adebug("snd_pcm_hw_params_any() failed.\n"
 
225
                 "        Device exists but no matching hardware?\n");
 
226
          return err;
 
227
        }
 
228
 
 
229
        /* set the access type */
 
230
        err = snd_pcm_hw_params_set_access(internal->pcm_handle,
 
231
                        params, internal->access_mask);
 
232
        if (err < 0){
 
233
          adebug("snd_pcm_hw_params_set_access() failed.\n");
 
234
          return err;
 
235
        }
 
236
 
 
237
        /* set the sample bitformat */
 
238
        err = snd_pcm_hw_params_set_format(internal->pcm_handle,
 
239
                        params, internal->bitformat);
 
240
        if (err < 0){
 
241
          adebug("snd_pcm_hw_params_set_format() failed.\n");
 
242
          return err;
 
243
        }
 
244
 
 
245
        /* set the number of channels */
 
246
        err = snd_pcm_hw_params_set_channels(internal->pcm_handle,
 
247
                        params, (unsigned int)device->output_channels);
 
248
        if (err < 0){
 
249
          adebug("snd_pcm_hw_params_set_channels() failed.\n");
 
250
          return err;
 
251
        }
 
252
 
 
253
        /* save the sample size in bytes for posterity */
 
254
        internal->sample_size = format->bits * device->output_channels / 8;
 
255
 
 
256
        /* set the sample rate */
 
257
        err = snd_pcm_hw_params_set_rate_near(internal->pcm_handle,
 
258
                        params, &rate, 0);
 
259
        if (err < 0){
 
260
          adebug("snd_pcm_hw_params_set_rate_near() failed.\n");
 
261
          return err;
 
262
        }
 
263
        if (rate > 1.05 * format->rate || rate < 0.95 * format->rate) {
 
264
          awarn("sample rate %i not supported "
 
265
                "by the hardware, using %u\n", format->rate, rate);
 
266
        }
 
267
 
 
268
        /* set the length of the hardware sample buffer in microseconds */
 
269
        err = snd_pcm_hw_params_set_buffer_time_near(internal->pcm_handle,
 
270
                        params, &(internal->buffer_time), 0);
 
271
        if (err < 0){
 
272
          adebug("snd_pcm_hw_params_set_buffer_time_near() failed.\n");
 
273
          return err;
 
274
        }
 
275
 
 
276
        /* calculate a period time of one half sample time */
 
277
        if ((internal->period_time == 0) && (rate > 0))
 
278
                internal->period_time =
 
279
                        1000000 * AO_ALSA_SAMPLE_XFER / rate;
 
280
 
 
281
        /* set the time per hardware sample transfer */
 
282
        err = snd_pcm_hw_params_set_period_time_near(internal->pcm_handle,
 
283
                        params, &(internal->period_time), 0);
 
284
        if (err < 0){
 
285
          adebug("snd_pcm_hw_params_set_period_time_near() failed.\n");
 
286
          return err;
 
287
        }
 
288
 
 
289
        /* commit the params structure to the hardware via ALSA */
 
290
        err = snd_pcm_hw_params(internal->pcm_handle, params);
 
291
        if (err < 0){
 
292
          adebug("snd_pcm_hw_params() failed.\n");
 
293
          return err;
 
294
        }
 
295
 
 
296
        /* save the period size in frames for posterity */
 
297
        err = snd_pcm_hw_params_get_period_size(params,
 
298
                                                &(internal->period_size), 0);
 
299
        if (err < 0){
 
300
          adebug("snd_pcm_hw_params_get_period_size() failed.\n");
 
301
          return err;
 
302
        }
 
303
 
 
304
        return 1;
 
305
}
 
306
 
 
307
 
 
308
/* setup alsa data transfer behavior */
 
309
static inline int alsa_set_swparams(ao_device *device)
 
310
{
 
311
        ao_alsa_internal *internal  = (ao_alsa_internal *) device->internal;
 
312
        snd_pcm_sw_params_t   *params;
 
313
        int err;
 
314
 
 
315
        /* allocate the software parameter structure */
 
316
        snd_pcm_sw_params_alloca(&params);
 
317
 
 
318
        /* fetch the current software parameters */
 
319
        err = snd_pcm_sw_params_current(internal->pcm_handle, params);
 
320
        if (err < 0){
 
321
          adebug("snd_pcm_sw_params_current() failed.\n");
 
322
          return err;
 
323
        }
 
324
 
 
325
        /* allow transfers to start when there is one period */
 
326
        err = snd_pcm_sw_params_set_start_threshold(internal->pcm_handle,
 
327
                        params, internal->period_size);
 
328
        if (err < 0){
 
329
          adebug("snd_pcm_sw_params_set_start_threshold() failed.\n");
 
330
          return err;
 
331
        }
 
332
 
 
333
        /* require a minimum of one full transfer in the buffer */
 
334
        err = snd_pcm_sw_params_set_avail_min(internal->pcm_handle, params,
 
335
                        internal->period_size);
 
336
        if (err < 0){
 
337
          adebug("snd_pcm_sw_params_set_avail_min() failed.\n");
 
338
          return err;
 
339
        }
 
340
 
 
341
        /* do not align transfers; this is obsolete/deprecated in ALSA
 
342
           1.x where the transfer alignemnt is always 1 (except for
 
343
           buggy drivers like VIA 82xx which still demand aligned
 
344
           transfers regardless of setting, in violation of the ALSA
 
345
           API docs) */
 
346
        err = snd_pcm_sw_params_set_xfer_align(internal->pcm_handle, params, 1);
 
347
        if (err < 0){
 
348
          adebug("snd_pcm_sw_params_set_xfer_align() failed.\n");
 
349
          return err;
 
350
        }
 
351
 
 
352
        /* force a work-ahead silence buffer; this is a fix, again for
 
353
           VIA 82xx, where non-MMIO transfers will buffer into
 
354
           period-size transfers, but the last transfer is usually
 
355
           undersized and playback falls off the end of the submitted
 
356
           data. */
 
357
        {
 
358
          snd_pcm_uframes_t boundary;
 
359
          err = snd_pcm_sw_params_get_boundary(params,&boundary);
 
360
          if (err < 0){
 
361
            adebug("snd_pcm_sw_params_get_boundary() failed.\n");
 
362
            return err;
 
363
          }
 
364
          err = snd_pcm_sw_params_set_silence_size(internal->pcm_handle, params, boundary);
 
365
          if (err < 0){
 
366
            adebug("snd_pcm_sw_params_set_silence_size() failed.\n");
 
367
            return err;
 
368
          }
 
369
        }
 
370
 
 
371
        /* commit the params structure to ALSA */
 
372
        err = snd_pcm_sw_params(internal->pcm_handle, params);
 
373
        if (err < 0){
 
374
          adebug("snd_pcm_sw_params() failed.\n");
 
375
          return err;
 
376
        }
 
377
 
 
378
        return 1;
 
379
}
 
380
 
 
381
 
 
382
/* Devices declared in the alsa configuration will usually open
 
383
   without error, even if there's no underlying hardware to support
 
384
   them, eg, opening a 5.1 surround device on setero hardware.  The
 
385
   device won't 'fail' until there's an attempt to configure it. */
 
386
 
 
387
static inline int alsa_test_open(ao_device *device,
 
388
                                 char *dev,
 
389
                                 ao_sample_format *format)
 
390
{
 
391
  ao_alsa_internal *internal  = (ao_alsa_internal *) device->internal;
 
392
  snd_pcm_hw_params_t   *params;
 
393
  int err;
 
394
 
 
395
  adebug("Trying to open ALSA device '%s'\n",dev);
 
396
 
 
397
  err = snd_pcm_open(&(internal->pcm_handle), dev,
 
398
                     SND_PCM_STREAM_PLAYBACK, 0);
 
399
 
 
400
  if(err){
 
401
    adebug("Unable to open ALSA device '%s'\n",dev);
 
402
    return err;
 
403
  }
 
404
 
 
405
  /* this is a hack and fragile if the exact device detection code
 
406
     flow changes!  Nevertheless, this is a useful warning for users.
 
407
     Never fail silently if we can help it! */
 
408
  if(!strcasecmp(dev,"default")){
 
409
    /* default device */
 
410
    if(device->output_channels>2){
 
411
      awarn("ALSA 'default' device plays only channels 0,1.\n");
 
412
      device->output_channels=2;
 
413
    }
 
414
  }
 
415
 
 
416
  /* try to set up hw params */
 
417
  err = alsa_set_hwparams(device,format);
 
418
  if(err<0){
 
419
    adebug("Unable to open ALSA device '%s'\n",dev);
 
420
    snd_pcm_close(internal->pcm_handle);
 
421
    internal->pcm_handle = NULL;
 
422
    return err;
 
423
  }
 
424
 
 
425
  /* try to set up sw params */
 
426
  err = alsa_set_swparams(device);
 
427
  if(err<0){
 
428
    adebug("Unable to open ALSA device '%s'\n",dev);
 
429
    snd_pcm_close(internal->pcm_handle);
 
430
    internal->pcm_handle = NULL;
 
431
    return err;
 
432
  }
 
433
 
 
434
  /* success! */
 
435
  return 0;
 
436
}
 
437
 
 
438
/* prepare the audio device for playback */
117
439
int ao_plugin_open(ao_device *device, ao_sample_format *format)
118
440
{
119
 
        ao_alsa_internal *internal = (ao_alsa_internal *) device->internal;
120
 
 
121
 
        snd_pcm_channel_params_t param;
 
441
        ao_alsa_internal *internal  = (ao_alsa_internal *) device->internal;
122
442
        int err;
123
443
 
124
 
        memset(&param, 0, sizeof(param));
125
 
 
126
 
        param.channel = SND_PCM_CHANNEL_PLAYBACK;
127
 
        param.mode = SND_PCM_MODE_BLOCK;
128
 
 
129
 
        param.format.interleave = 1;
130
 
 
131
 
        switch (format->bits) {
132
 
        case 8  : param.format.format = SND_PCM_SFMT_S8;
133
 
                  break;
134
 
        case 16 : param.format.format = 
135
 
                    device->client_byte_format == AO_FMT_BIG ?
136
 
                    SND_PCM_SFMT_S16_BE : SND_PCM_SFMT_S16_LE;
137
 
                  device->driver_byte_format = device->client_byte_format;
138
 
                  break;
139
 
        default : return 0;
140
 
        }
141
 
 
142
 
        if (format->channels == 1 || format->channels == 2)
143
 
                param.format.voices = format->channels;
144
 
        else
145
 
                return 0;
146
 
 
147
 
        /* Finish filling in the parameter structure */
148
 
        param.format.rate = format->rate;
149
 
 
150
 
        param.start_mode = SND_PCM_START_FULL;
151
 
        
152
 
        param.stop_mode = SND_PCM_STOP_STOP;
153
 
 
154
 
        param.buf.block.frag_size = internal->buf_size;
155
 
        param.buf.block.frags_min = 1;
156
 
        param.buf.block.frags_max = 8;
157
 
 
158
 
        internal->buf = malloc(internal->buf_size);
159
 
        internal->buf_end = 0;
160
 
        if (internal->buf == NULL)
161
 
          return 0;  /* Could not alloc swap buffer */
162
 
 
 
444
        /* Get the ALSA bitformat first to make sure it's valid */
 
445
        err = alsa_get_sample_bitformat(format->bits,
 
446
                                        device->client_byte_format == AO_FMT_BIG,device);
 
447
        if (err < 0){
 
448
          aerror("Invalid byte format\n");
 
449
          return 0;
 
450
        }
 
451
 
 
452
        internal->bitformat = err;
163
453
 
164
454
        /* Open the ALSA device */
165
 
        err = snd_pcm_open(&(internal->pcm_handle), 
166
 
                           internal->card, 
167
 
                           internal->dev,
168
 
                           SND_PCM_OPEN_PLAYBACK | SND_PCM_OPEN_NONBLOCK);
169
 
        if (err < 0) {
170
 
                free(internal->buf);
171
 
                return 0;
172
 
        }
173
 
 
174
 
        err = snd_pcm_channel_params(internal->pcm_handle, &param);
175
 
 
176
 
        if (err < 0) {
177
 
                snd_pcm_close(internal->pcm_handle);
178
 
                free(internal->buf);
179
 
                return 0;
180
 
        }
181
 
 
182
 
        snd_pcm_nonblock_mode(internal->pcm_handle, 0);
183
 
        snd_pcm_channel_prepare(internal->pcm_handle, 
184
 
                                SND_PCM_CHANNEL_PLAYBACK);
 
455
        err=0;
 
456
        if(!internal->dev){
 
457
          char *tmp=NULL;
 
458
          /* we don't try just 'default' as it's a plug device that
 
459
             will accept any number of channels but usually plays back
 
460
             everything as stereo. */
 
461
          switch(device->output_channels){
 
462
          default:
 
463
          case 8:
 
464
          case 7:
 
465
            err = alsa_test_open(device, tmp="surround71", format);
 
466
            break;
 
467
          case 4:
 
468
          case 3:
 
469
            err = alsa_test_open(device, tmp="surround40", format);
 
470
            if(err==0)break;
 
471
          case 6:
 
472
          case 5:
 
473
            err = alsa_test_open(device, tmp="surround51", format);
 
474
          case 1:
 
475
          case 2:
 
476
            break;
 
477
          }
 
478
 
 
479
          if(err){
 
480
            awarn("Unable to open surround playback.  Trying default device...\n");
 
481
            tmp=NULL;
 
482
          }
 
483
 
 
484
          if(!tmp)
 
485
            err = alsa_test_open(device, tmp="default", format);
 
486
 
 
487
          internal->dev=strdup(tmp);
 
488
 
 
489
        }else
 
490
          err = alsa_test_open(device, internal->dev, format);
 
491
 
 
492
        if (err < 0) {
 
493
          aerror("Unable to open ALSA device '%s' for playback => %s\n",
 
494
                 internal->dev, snd_strerror(err));
 
495
          return 0;
 
496
        }
 
497
 
 
498
        adebug("Using ALSA device '%s'\n",internal->dev);
 
499
 
 
500
        /* alsa's endinness will be the same as the application's */
 
501
        if (format->bits > 8)
 
502
                device->driver_byte_format = device->client_byte_format;
 
503
 
 
504
        if(strcasecmp(internal->dev,"default")){
 
505
          if(strncasecmp(internal->dev,"surround",8)){
 
506
            if(device->output_channels>2 && device->verbose>=0){
 
507
              awarn("No way to determine hardware %d channel mapping of\n"
 
508
                    "ALSA device '%s'.\n",device->output_channels, internal->dev);
 
509
              if(device->inter_matrix){
 
510
                free(device->inter_matrix);
 
511
                device->inter_matrix=NULL;
 
512
              }
 
513
            }
 
514
          }
 
515
        }
185
516
 
186
517
        return 1;
187
518
}
188
519
 
189
520
 
190
 
int _alsa_write_buffer(ao_alsa_internal *s)
 
521
/* recover from an alsa exception */
 
522
static inline int alsa_error_recovery(ao_alsa_internal *internal, int err, ao_device *device)
191
523
{
192
 
        snd_pcm_channel_status_t status;
193
 
        snd_pcm_t *pcm_handle = s->pcm_handle;
194
 
        int len = s->buf_end;
195
 
        ssize_t written, snd_pcm_write_ret;
196
 
 
197
 
        s->buf_end = 0;
198
 
 
199
 
        snd_pcm_write_ret = written = 0;
200
 
        while ((snd_pcm_write_ret >= 0) && (written < len)) {
201
 
                while ((snd_pcm_write_ret = snd_pcm_write(pcm_handle, s->buf, len)) == -EINTR)
202
 
                        ;
203
 
                if (snd_pcm_write_ret > 0)
204
 
                        written += snd_pcm_write_ret;
205
 
        }
206
 
 
207
 
        memset(&status, 0, sizeof(status));
208
 
        if (snd_pcm_channel_status(pcm_handle, &status) < 0) {
209
 
                fprintf(stderr, "ALSA: could not get channel status\n");
210
 
                return 0;
211
 
        }       
212
 
        if (status.underrun) {
213
 
                /* fprintf(stderr, "ALSA: underrun. resetting channel\n"); */
214
 
                snd_pcm_channel_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
215
 
                snd_pcm_playback_prepare(pcm_handle);
216
 
                snd_pcm_write(pcm_handle, s->buf, len);
217
 
                if (snd_pcm_channel_status(pcm_handle, &status) < 0) {
218
 
                        fprintf(stderr, "ALSA: could not get channel status. giving up\n");
219
 
                        return 0;
 
524
        if (err == -EPIPE) {
 
525
                /* FIXME: underrun length detection */
 
526
                adebug("underrun, restarting...\n");
 
527
                /* output buffer underrun */
 
528
                err = snd_pcm_prepare(internal->pcm_handle);
 
529
                if (err < 0)
 
530
                        return err;
 
531
        } else if (err == -ESTRPIPE) {
 
532
                /* application was suspended, wait until suspend flag clears */
 
533
                while ((err = snd_pcm_resume(internal->pcm_handle)) == -EAGAIN)
 
534
                        sleep (1);
 
535
 
 
536
                if (err < 0) {
 
537
                        /* unable to wake up pcm device, restart it */
 
538
                        err = snd_pcm_prepare(internal->pcm_handle);
 
539
                        if (err < 0)
 
540
                                return err;
220
541
                }
221
 
                if (status.underrun) {
222
 
                        fprintf(stderr, "ALSA: write error. giving up\n");
223
 
                                        return 0;
224
 
                }               
 
542
                return 0;
225
543
        }
226
544
 
227
 
        return 1;
228
 
}       
229
 
 
230
 
 
 
545
        /* error isn't recoverable */
 
546
        return err;
 
547
}
 
548
 
 
549
 
 
550
/* play num_bytes of audio data */
231
551
int ao_plugin_play(ao_device *device, const char *output_samples, 
232
552
                uint_32 num_bytes)
233
553
{
234
554
        ao_alsa_internal *internal = (ao_alsa_internal *) device->internal;
235
 
        
236
 
        int packed = 0;
237
 
        int copy_len;
238
 
        char *samples = (char *) output_samples;
239
 
        int ok = 1;
240
 
 
241
 
        while (packed < num_bytes && ok) {
242
 
                /* Pack the buffer */
243
 
                if (num_bytes-packed < internal->buf_size - internal->buf_end)
244
 
                        copy_len = num_bytes - packed;
245
 
                else
246
 
                        copy_len = internal->buf_size - internal->buf_end;
247
 
 
248
 
                memcpy(internal->buf + internal->buf_end, samples + packed, 
249
 
                       copy_len); 
250
 
                packed += copy_len;
251
 
                internal->buf_end += copy_len;
252
 
 
253
 
                if(internal->buf_end == internal->buf_size)
254
 
                        ok = _alsa_write_buffer(internal);
 
555
        uint_32 len = num_bytes / internal->sample_size;
 
556
        char *ptr = (char *) output_samples;
 
557
        int err;
 
558
 
 
559
        /* the entire buffer might not transfer at once */
 
560
        while (len > 0) {
 
561
                /* try to write the entire buffer at once */
 
562
                err = internal->writei(internal->pcm_handle, ptr, len);
 
563
 
 
564
                /* no data transferred or interrupt signal */
 
565
                if (err == -EAGAIN || err == -EINTR) {
 
566
                        continue;
 
567
                }
 
568
 
 
569
                if (err < 0) {
 
570
                        /* this might be an error, or an exception */
 
571
                  err = alsa_error_recovery(internal, err, device);
 
572
                        if (err < 0) {
 
573
                                aerror("write error: %s\n",
 
574
                                       snd_strerror(err));
 
575
                                return 0;
 
576
                        }else /* recovered, continue */
 
577
                          continue;
 
578
                }
 
579
 
 
580
                /* decrement the sample counter */
 
581
                len -= err;
 
582
 
 
583
                /* adjust the start pointer */
 
584
                ptr += err * internal->sample_size;
255
585
        }
256
586
 
257
 
        return ok;
 
587
        return 1;
258
588
}
259
589
 
260
590
 
 
591
/* close the audio device */
261
592
int ao_plugin_close(ao_device *device)
262
593
{
263
 
        ao_alsa_internal *internal = (ao_alsa_internal *) device->internal;
264
 
        int result;
265
 
 
266
 
        /* Clear buffer */
267
 
        result = _alsa_write_buffer(internal);
268
 
        snd_pcm_close(internal->pcm_handle);
269
 
        free(internal->buf);
270
 
 
271
 
        return result;
 
594
        ao_alsa_internal *internal;
 
595
 
 
596
        if (device) {
 
597
          if ((internal = (ao_alsa_internal *) device->internal)) {
 
598
            if (internal->pcm_handle) {
 
599
              snd_pcm_drain(internal->pcm_handle);
 
600
              snd_pcm_close(internal->pcm_handle);
 
601
              internal->pcm_handle=NULL;
 
602
            } 
 
603
          } else
 
604
            awarn("ao_plugin_close called with uninitialized ao_device->internal\n");
 
605
        } else
 
606
          awarn("ao_plugin_close called with uninitialized ao_device\n");
 
607
 
 
608
        return 1;
272
609
}
273
610
 
274
611
 
 
612
/* free the internal data structures */
275
613
void ao_plugin_device_clear(ao_device *device)
276
614
{
277
 
        ao_alsa_internal *internal = (ao_alsa_internal *) device->internal;
278
 
 
279
 
        free(internal);
 
615
        ao_alsa_internal *internal;
 
616
 
 
617
        if (device) {
 
618
          if ((internal = (ao_alsa_internal *) device->internal)) {
 
619
            if (internal->dev)
 
620
              free (internal->dev);
 
621
            else
 
622
              awarn("ao_plugin_device_clear called with uninitialized ao_device->internal->dev\n");
 
623
 
 
624
            free(device->internal);
 
625
          } else
 
626
            awarn("ao_plugin_device_clear called with uninitialized ao_device->internal\n");
 
627
        } else
 
628
          awarn("ao_plugin_device_clear called with uninitialized ao_device\n");
280
629
}
 
630