• 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 <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