137 lines
3.0 KiB
C
137 lines
3.0 KiB
C
/*
|
|
* Copyright 2007 The Android Open Source Project
|
|
*
|
|
* Audio output device.
|
|
*/
|
|
#include "Common.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <esd.h>
|
|
|
|
#include <fcntl.h>
|
|
#include <sys/ioctl.h>
|
|
#include <linux/input.h>
|
|
|
|
|
|
/*
|
|
* Input event device state.
|
|
*/
|
|
typedef struct AudioState {
|
|
int fd;
|
|
int sourceId;
|
|
int esdVol;
|
|
int streamType;
|
|
} AudioState;
|
|
|
|
/*
|
|
* Set some stuff up.
|
|
*/
|
|
static int configureInitialState(const char* pathName, AudioState* audioState)
|
|
{
|
|
#if BUILD_SIM_WITHOUT_AUDIO
|
|
return 0;
|
|
#else
|
|
esd_player_info_t *pi;
|
|
audioState->fd = -1;
|
|
audioState->sourceId = -1;
|
|
audioState->esdVol = -1;
|
|
audioState->streamType = 0;
|
|
|
|
int format = ESD_BITS16 | ESD_STEREO | ESD_STREAM | ESD_PLAY;
|
|
char namestring[] = "Android Audio XXXXXXXX";
|
|
sprintf(namestring,"Android Audio %08x", (unsigned int)audioState);
|
|
int esd_fd = esd_play_stream_fallback(format, 44100, NULL, namestring);
|
|
if (esd_fd > 0) {
|
|
// find the source_id for this stream
|
|
int mix = esd_open_sound(NULL);
|
|
if (mix > 0) {
|
|
esd_info_t *info = esd_get_all_info(mix);
|
|
|
|
if (info) {
|
|
for(pi = info->player_list; pi; pi = pi->next) {
|
|
if(strcmp(pi->name, namestring) == 0) {
|
|
audioState->sourceId = pi->source_id;
|
|
break;
|
|
}
|
|
}
|
|
esd_free_all_info(info);
|
|
}
|
|
esd_close(mix);
|
|
}
|
|
audioState->fd = esd_fd;
|
|
return 0;
|
|
}
|
|
printf("Couldn't open audio device. Faking it.\n");
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Return the next available input event.
|
|
*
|
|
* We just pass this through to the real "write", since "fd" is real.
|
|
*/
|
|
static ssize_t writeAudio(FakeDev* dev, int fd, const void* buf, size_t count)
|
|
{
|
|
#if BUILD_SIM_WITHOUT_AUDIO
|
|
return 0;
|
|
#else
|
|
AudioState *state = (AudioState*)dev->state;
|
|
if (state->fd >= 0)
|
|
return _ws_write(state->fd, buf, count);
|
|
|
|
// fake timing
|
|
usleep(count * 10000 / 441 * 4);
|
|
return count;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Handle event ioctls.
|
|
*/
|
|
static int ioctlAudio(FakeDev* dev, int fd, int request, void* argp)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* Free up our state before closing down the fake descriptor.
|
|
*/
|
|
static int closeAudio(FakeDev* dev, int fd)
|
|
{
|
|
#if BUILD_SIM_WITHOUT_AUDIO
|
|
return 0;
|
|
#else
|
|
AudioState *state = (AudioState*)dev->state;
|
|
close(state->fd);
|
|
free(state);
|
|
dev->state = NULL;
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Open an audio output device.
|
|
*/
|
|
FakeDev* wsOpenDevAudio(const char* pathName, int flags)
|
|
{
|
|
FakeDev* newDev = wsCreateFakeDev(pathName);
|
|
if (newDev != NULL) {
|
|
newDev->write = writeAudio;
|
|
newDev->ioctl = ioctlAudio;
|
|
newDev->close = closeAudio;
|
|
|
|
AudioState* eventState = calloc(1, sizeof(AudioState));
|
|
|
|
if (configureInitialState(pathName, eventState) != 0) {
|
|
free(eventState);
|
|
return NULL;
|
|
}
|
|
newDev->state = eventState;
|
|
}
|
|
|
|
return newDev;
|
|
}
|