File:
[DVB] /
libsoftmpeg /
src /
a_fusionsound.c
Revision
1.1:
download - view:
text,
annotated -
select for diffs
Wed Mar 17 14:23:06 2004 UTC (20 years, 2 months ago) by
hunold
Branches:
MAIN
CVS tags:
HEAD
- rip out all fusionsound stuff from main audio.c, put it to a_fusionsound.c, put a lean api around it
- check for availble audio ouput "devices" in audio.c, support fusionsound, follow changes in audio.c
- add copyright headers to all of the new files
- make all functions static in v_directfb.c
/*
(c) Copyright 2004 convergence GmbH
All rights reserved.
Written by Michael Hunold <hunold@convergence.de> and
Denis Oliver Kropp <dok@directfb.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include "audio.h"
static struct a_fusionsound_data
{
IDirectFB *DirectFB;
IFusionSound *sound;
IFusionSoundStream *stream;
IFusionSoundPlayback *playback;
int channels;
int initialized;
} priv;
static int init (struct audio_decoder *d, void *init_data)
{
struct a_fusionsound_data *data = &priv;
/* don't need any init data */
if (DFB_OK != DirectFBCreate(&data->DirectFB)) {
SOFTMPEG_ERROR("directfb master interface not available.\n");
return -1;
}
if (DFB_OK != data->DirectFB->GetInterface(data->DirectFB, "IFusionSound", NULL, NULL, (void **) &data->sound)) {
SOFTMPEG_ERROR("fusion sound interface not available.\n");
return -1;
}
/* we rely on the logic later on to initialize FusionSound properly */
data->initialized = 0;
return 0;
}
static int volume (struct audio_decoder *d, float volume)
{
struct a_fusionsound_data *data = &priv;
if (data->initialized == 0) {
AUDIO_OUTPUT("FusionSound playback not initialized (yet)\n");
return -1;
}
data->playback->SetVolume(data->playback, volume);
return 0;
}
static int apause (struct audio_decoder *d, int pause)
{
struct a_fusionsound_data *data = &priv;
int ret;
if (data->initialized == 0) {
AUDIO_OUTPUT("FusionSound playback not initialized (yet)\n");
return -1;
}
if (pause != 0) {
ret = data->playback->Stop(data->playback);
if (ret != 0) {
AUDIO_OUTPUT("warning: stopping audio playback failed.\n");
} else {
AUDIO_OUTPUT("stopped audio playback.\n");
}
return 1;
}
ret = data->playback->Continue(data->playback);
if (ret != 0) {
AUDIO_OUTPUT("warning: starting audio playback failed.\n");
} else {
AUDIO_OUTPUT("starting audio playback.\n");
}
return 0;
}
static int get_delay (struct audio_decoder *d, int *delay)
{
struct a_fusionsound_data *data = &priv;
DFBBoolean playing;
int filled;
int total;
if (data->initialized == 0) {
AUDIO_OUTPUT("FusionSound playback not initialized (yet)\n");
return -1;
}
*delay = 0;
data->stream->GetStatus(data->stream, &filled, &total, NULL, NULL, &playing);
if (!playing) {
AUDIO_OUTPUT("not playing / unexpected interrupt\n");
return -1;
}
data->stream->GetPresentationDelay(data->stream, delay);
return 0;
}
static int reconfigure (struct audio_decoder *d, unsigned int buffer_size, unsigned int sample_rate, unsigned int channels)
{
struct a_fusionsound_data *data = &priv;
FSStreamDescription sd;
data->initialized = 0;
if (NULL != data->stream) {
data->stream->Release(data->stream);
data->stream = NULL;
}
SOFTMPEG_DEBUG("changing audio configuration: buffer_size:%d, sample_rate:%d, channels:%d\n",buffer_size, sample_rate, channels);
if (sample_rate != 48000 && sample_rate != 44100 && sample_rate != 32000) {
AUDIO_OUTPUT("unsupported sample_rate %d\n",sample_rate);
return -1;
}
if (channels != 2 && channels != 1) {
AUDIO_OUTPUT("unsupported number of channels %d\n",channels);
return -1;
}
if (buffer_size < sample_rate) {
AUDIO_OUTPUT("buffer size smaller than sample rate.\n");
return -1;
}
sd.flags = (FSSDF_BUFFERSIZE | FSSDF_SAMPLEFORMAT | FSSDF_SAMPLERATE | FSSDF_CHANNELS | FSSDF_PREBUFFER);
sd.buffersize = buffer_size;
sd.sampleformat = FSSF_S16;
sd.samplerate = sample_rate;
sd.channels = channels;
sd.prebuffer = -1; /* Disables automatic playback. */
data->sound->CreateStream(data->sound, &sd, &data->stream);
if (NULL == data->stream) {
SOFTMPEG_ERROR("fusion sound stream init failed\n");
data->stream = NULL;
return -1;
}
data->stream->GetPlayback(data->stream, &data->playback);
if (NULL == data->playback) {
SOFTMPEG_ERROR("fusion sound get playback interface failed\n");
data->stream->Release(data->stream);
data->stream = NULL;
return -1;
}
data->channels = channels;
data->initialized = 1;
volume(d, 0.0);
return 0;
}
static int get_status (struct audio_decoder *d, int *filled, int *total, int *playing)
{
struct a_fusionsound_data *data = &priv;
DFBBoolean p;
int ret;
if (NULL == data->stream) {
AUDIO_OUTPUT("stream not available.\n");
return -1;
}
ret = data->stream->GetStatus(data->stream, filled, total, NULL, NULL, &p);
if (ret != 0) {
AUDIO_OUTPUT("status not available.\n");
return -1;
}
if (p == DFB_TRUE) {
*playing = 1;
} else {
*playing = 0;
}
return 0;
}
static int awrite (struct audio_decoder *d, struct audio_buffer *output, int *filled, int *total)
{
struct a_fusionsound_data *data = &priv;
DFBBoolean playing;
int ret;
if (data->initialized == 0) {
AUDIO_OUTPUT("FusionSound playback not initialized (yet)\n");
return -1;
}
ret = data->stream->Write(data->stream, (uint32_t *) output->buf, output->len / (data->channels*2));
if (ret) {
SOFTMPEG_DFB_ERROR( "IFusionSoundStream::Write()", ret );
return -1;
}
ret = data->stream->GetStatus(data->stream, filled, total, NULL, NULL, &playing);
if (ret) {
SOFTMPEG_DFB_ERROR( "IFusionSoundStream::GetStatus()", ret );
return -1;
}
if (playing == DFB_TRUE) {
return 1;
}
return 0;
}
static int flush (struct audio_decoder *d)
{
struct a_fusionsound_data *data = &priv;
if (data->initialized == 0) {
AUDIO_OUTPUT("FusionSound playback not initialized (yet)\n");
return -1;
}
data->stream->Flush(data->stream);
volume(d, 0.0);
return 0;
}
struct audio_operations a_fusionsound_ops =
{
.init = &init,
.pause = &apause,
.volume = &volume,
.get_delay = &get_delay,
.reconfigure = &reconfigure,
.get_status = &get_status,
.write = &awrite,
.flush = &flush,
.priv = &priv,
};
LinuxTV legacy CVS <linuxtv.org/cvs>