• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2007 The Android Open Source Project
3  *
4  * Audio output device.
5  */
6 #include "Common.h"
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <alsa/asoundlib.h>
12 
13 #include <fcntl.h>
14 #include <sys/ioctl.h>
15 #include <linux/input.h>
16 
17 
18 /*
19  * Input event device state.
20  */
21 typedef struct AudioState {
22     snd_pcm_t *handle;
23 } AudioState;
24 
25 /*
26  * Set some stuff up.
27  */
configureInitialState(const char * pathName,AudioState * audioState)28 static int configureInitialState(const char* pathName, AudioState* audioState)
29 {
30 #if BUILD_SIM_WITHOUT_AUDIO
31     return 0;
32 #else
33     audioState->handle = NULL;
34 
35     snd_pcm_open(&audioState->handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
36 
37     if (audioState->handle) {
38         snd_pcm_hw_params_t *params;
39         snd_pcm_hw_params_malloc(&params);
40         snd_pcm_hw_params_any(audioState->handle, params);
41         snd_pcm_hw_params_set_access(audioState->handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
42         snd_pcm_hw_params_set_format(audioState->handle, params, SND_PCM_FORMAT_S16_LE);
43         unsigned int rate = 44100;
44         snd_pcm_hw_params_set_rate_near(audioState->handle, params, &rate, NULL);
45         snd_pcm_hw_params_set_channels(audioState->handle, params, 2);
46         snd_pcm_hw_params(audioState->handle, params);
47         snd_pcm_hw_params_free(params);
48     } else {
49         wsLog("Couldn't open audio hardware, faking it\n");
50     }
51 
52     return 0;
53 #endif
54 }
55 
56 /*
57  * Write audio data.
58  */
writeAudio(FakeDev * dev,int fd,const void * buf,size_t count)59 static ssize_t writeAudio(FakeDev* dev, int fd, const void* buf, size_t count)
60 {
61 #if BUILD_SIM_WITHOUT_AUDIO
62     return 0;
63 #else
64     AudioState *state = (AudioState*)dev->state;
65     if (state->handle != NULL) {
66         snd_pcm_writei(state->handle, buf, count / 4);
67         return count;
68     }
69 
70     // fake timing
71     usleep(count * 10000 / (441 * 4));
72     return count;
73 #endif
74 }
75 
76 /*
77  * Handle event ioctls.
78  */
ioctlAudio(FakeDev * dev,int fd,int request,void * argp)79 static int ioctlAudio(FakeDev* dev, int fd, int request, void* argp)
80 {
81     return -1;
82 }
83 
84 /*
85  * Free up our state before closing down the fake descriptor.
86  */
closeAudio(FakeDev * dev,int fd)87 static int closeAudio(FakeDev* dev, int fd)
88 {
89 #if BUILD_SIM_WITHOUT_AUDIO
90     return 0;
91 #else
92     AudioState *state = (AudioState*)dev->state;
93     snd_pcm_close(state->handle);
94     free(state);
95     dev->state = NULL;
96     return 0;
97 #endif
98 }
99 
100 /*
101  * Open an audio output device.
102  */
wsOpenDevAudio(const char * pathName,int flags)103 FakeDev* wsOpenDevAudio(const char* pathName, int flags)
104 {
105     FakeDev* newDev = wsCreateFakeDev(pathName);
106     if (newDev != NULL) {
107         newDev->write = writeAudio;
108         newDev->ioctl = ioctlAudio;
109         newDev->close = closeAudio;
110 
111         AudioState* eventState = calloc(1, sizeof(AudioState));
112 
113         if (configureInitialState(pathName, eventState) != 0) {
114             free(eventState);
115             return NULL;
116         }
117         newDev->state = eventState;
118     }
119 
120     return newDev;
121 }
122