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 <esd.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 int fd;
23 int sourceId;
24 int esdVol;
25 int streamType;
26 } AudioState;
27
28 /*
29 * Set some stuff up.
30 */
configureInitialState(const char * pathName,AudioState * audioState)31 static int configureInitialState(const char* pathName, AudioState* audioState)
32 {
33 #if BUILD_SIM_WITHOUT_AUDIO
34 return 0;
35 #else
36 esd_player_info_t *pi;
37 audioState->fd = -1;
38 audioState->sourceId = -1;
39 audioState->esdVol = -1;
40 audioState->streamType = 0;
41
42 int format = ESD_BITS16 | ESD_STEREO | ESD_STREAM | ESD_PLAY;
43 char namestring[] = "Android Audio XXXXXXXX";
44 sprintf(namestring,"Android Audio %08x", (unsigned int)audioState);
45 int esd_fd = esd_play_stream_fallback(format, 44100, NULL, namestring);
46 if (esd_fd > 0) {
47 // find the source_id for this stream
48 int mix = esd_open_sound(NULL);
49 if (mix > 0) {
50 esd_info_t *info = esd_get_all_info(mix);
51
52 if (info) {
53 for(pi = info->player_list; pi; pi = pi->next) {
54 if(strcmp(pi->name, namestring) == 0) {
55 audioState->sourceId = pi->source_id;
56 break;
57 }
58 }
59 esd_free_all_info(info);
60 }
61 esd_close(mix);
62 }
63 audioState->fd = esd_fd;
64 return 0;
65 }
66 printf("Couldn't open audio device. Faking it.\n");
67 return 0;
68 #endif
69 }
70
71 /*
72 * Return the next available input event.
73 *
74 * We just pass this through to the real "write", since "fd" is real.
75 */
writeAudio(FakeDev * dev,int fd,const void * buf,size_t count)76 static ssize_t writeAudio(FakeDev* dev, int fd, const void* buf, size_t count)
77 {
78 #if BUILD_SIM_WITHOUT_AUDIO
79 return 0;
80 #else
81 AudioState *state = (AudioState*)dev->state;
82 if (state->fd >= 0)
83 return _ws_write(state->fd, buf, count);
84
85 // fake timing
86 usleep(count * 10000 / 441 * 4);
87 return count;
88 #endif
89 }
90
91 /*
92 * Handle event ioctls.
93 */
ioctlAudio(FakeDev * dev,int fd,int request,void * argp)94 static int ioctlAudio(FakeDev* dev, int fd, int request, void* argp)
95 {
96 return -1;
97 }
98
99 /*
100 * Free up our state before closing down the fake descriptor.
101 */
closeAudio(FakeDev * dev,int fd)102 static int closeAudio(FakeDev* dev, int fd)
103 {
104 #if BUILD_SIM_WITHOUT_AUDIO
105 return 0;
106 #else
107 AudioState *state = (AudioState*)dev->state;
108 close(state->fd);
109 free(state);
110 dev->state = NULL;
111 return 0;
112 #endif
113 }
114
115 /*
116 * Open an audio output device.
117 */
wsOpenDevAudio(const char * pathName,int flags)118 FakeDev* wsOpenDevAudio(const char* pathName, int flags)
119 {
120 FakeDev* newDev = wsCreateFakeDev(pathName);
121 if (newDev != NULL) {
122 newDev->write = writeAudio;
123 newDev->ioctl = ioctlAudio;
124 newDev->close = closeAudio;
125
126 AudioState* eventState = calloc(1, sizeof(AudioState));
127
128 if (configureInitialState(pathName, eventState) != 0) {
129 free(eventState);
130 return NULL;
131 }
132 newDev->state = eventState;
133 }
134
135 return newDev;
136 }
137