8c08c8dbc377359557889f42c1844798414b97cf
[src/app-framework-binder.git] / plugins / audio / audio-alsa.c
1 #include "audio-api.h"
2 #include "audio-alsa.h"
3
4 PUBLIC unsigned char _alsa_init (const char *name, audioCtxHandleT *ctx) {
5
6     snd_pcm_t *dev;
7     snd_pcm_hw_params_t *params;
8     int num;
9
10     if (snd_pcm_open (&dev, name, SND_PCM_STREAM_PLAYBACK, 0) < 0)
11         return 0;
12
13     snd_pcm_hw_params_malloc (&params);
14     snd_pcm_hw_params_any (dev, params);
15     snd_pcm_hw_params_set_access (dev, params, SND_PCM_ACCESS_RW_INTERLEAVED);
16     snd_pcm_hw_params_set_format (dev, params, SND_PCM_FORMAT_S16_LE);
17     snd_pcm_hw_params_set_rate_near (dev, params, &ctx->rate, 0);
18     snd_pcm_hw_params_set_channels (dev, params, ctx->channels);
19     if (snd_pcm_hw_params (dev, params) < 0) {
20         snd_pcm_hw_params_free (params);
21         return 0;
22     }
23     snd_pcm_prepare (dev);
24     
25     /* allocate the global array if it hasn't been done */
26     if (!dev_ctx) {
27         dev_ctx = (dev_ctx_T**) malloc (sizeof(dev_ctx_T));
28         dev_ctx[0] = (dev_ctx_T*) malloc (sizeof(dev_ctx_T));
29         dev_ctx[0]->name = NULL;
30         dev_ctx[0]->dev = NULL;
31     }
32
33     /* is a card with similar name already opened ? */
34     for (num = 0; num < (sizeof(dev_ctx)/sizeof(dev_ctx_T)); num++) {
35         if (dev_ctx[num]->name &&
36            !strcmp (dev_ctx[num]->name, name))
37             return 0;
38     }
39     num++;
40
41     /* it's not... let us add it to the global array */
42     dev_ctx[num] = (dev_ctx_T*) malloc (sizeof(dev_ctx_T));
43     dev_ctx[num]->name = strdup (name);
44     dev_ctx[num]->dev = dev;
45     dev_ctx[num]->params = params;
46
47     return 1;
48 }
49
50 PUBLIC void _alsa_free (const char *name) {
51
52     int num;
53
54     for (num = 0; num < (sizeof(dev_ctx)/sizeof(dev_ctx_T)); num++) {
55         if (dev_ctx[num]->name &&
56            !strcmp (dev_ctx[num]->name, name)) {
57             snd_pcm_close (dev_ctx[num]->dev);
58             snd_pcm_hw_params_free (dev_ctx[num]->params);
59             free (dev_ctx[num]->name);
60             dev_ctx[num]->name = NULL;
61             dev_ctx[num]->dev = NULL;
62             free(dev_ctx[num]);
63             return;
64         }
65     }
66 }
67
68 PUBLIC void _alsa_play (unsigned int num, void *buf, int len) {
69
70     if (!dev_ctx || !dev_ctx[num])
71         return;
72
73     int16_t *cbuf = (int16_t *)buf;
74     int frames = len / 2;
75     int res;
76
77     if ((res = snd_pcm_writei (dev_ctx[num]->dev, cbuf, frames)) != frames) {
78         snd_pcm_recover (dev_ctx[num]->dev, res, 0);
79         snd_pcm_prepare (dev_ctx[num]->dev);
80     }
81     /* snd_pcm_drain (dev_ctx[num]->dev); */
82 }