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(¶ms);
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