/*
* 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;
}