Project

General

Profile

Feature #71 ยป muggle_alsa.patch

Patch for ALSA output - oschwartz, 02/01/2009 11:11 AM

View differences:

/usr/src/myvdr/muggle-0.2.3_new/Makefile 2009-01-23 00:08:11.000000000 +0100
mg_skin.o quantize.o mg_playcommands.o pcmplayer.o \
lyrics.o bitmap.o imagecache.o
PLAYLIBS = -lmad $(shell taglib-config --libs) -lImlib2
PLAYLIBS = -lasound -lmad $(shell taglib-config --libs) -lImlib2
MILIBS = $(shell taglib-config --libs)
/usr/src/myvdr/muggle-0.2.3_new/pcmplayer.c 2009-01-22 21:00:49.000000000 +0100
#include "pcmplayer.h"
#include "vdr_sound.c"
#include <linux/types.h>
#include <alsa/asoundlib.h>
// --- cOutput -----------------------------------------------------------------
class mgPCMPlayer;
class cOutput {
protected:
mgPCMPlayer *player;
public:
cOutput(mgPCMPlayer *Player);
virtual ~cOutput() {}
virtual void Init(void);
virtual unsigned int SampleRate(unsigned int PcmSampleRate)=0;
virtual int Output(const unsigned char *Data, int Len, bool SOF, unsigned int SampleRate)=0;
virtual bool Poll(void)=0;
virtual void Play(void)=0;
virtual void Pause(void)=0;
};
cOutput::cOutput(mgPCMPlayer *Player)
{
player=Player;
}
void cOutput::Init(void)
{
}
// --- cOutputAlsa --------------------------------------------------------------
#if 1
const char *alsadevice="default";
class cOutputAlsa : public cOutput {
private:
snd_pcm_t* m_playback_handle;
cPoller poll;
unsigned int outSr;
unsigned char buff[8192];
//
bool Reset(unsigned int sr);
public:
cOutputAlsa(mgPCMPlayer *Player);
virtual ~cOutputAlsa();
virtual void Init(void);
virtual unsigned int SampleRate(unsigned int PcmSampleRate);
virtual int Output(const unsigned char *Data, int Len, bool SOF, unsigned int SampleRate);
virtual bool Poll(void);
virtual void Play(void);
virtual void Pause(void);
};
cOutputAlsa::cOutputAlsa(mgPCMPlayer *Player)
:cOutput(Player)
{
m_playback_handle=NULL; outSr=0;
mgDebug("muggle: using Alsa output\n");
}
cOutputAlsa::~cOutputAlsa()
{
snd_pcm_drain(m_playback_handle);
snd_pcm_close(m_playback_handle);
}
void cOutputAlsa::Init(void)
{
int err;
if (!m_playback_handle)
{
if ((err = snd_pcm_open (&m_playback_handle, alsadevice, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
esyslog ("ERROR: cannot open audio device %s (%s)\n",
alsadevice,
snd_strerror (err));
}
}
cOutput::Init();
}
bool cOutputAlsa::Reset(unsigned int sr)
{
snd_pcm_hw_params_t *params;
unsigned int val;
int dir;
if(m_playback_handle) {
/* Allocate a hardware parameters object. */
snd_pcm_hw_params_alloca(&params);
/* Fill it in with default values. */
snd_pcm_hw_params_any(m_playback_handle, params);
/* Set the desired hardware parameters. */
/* Interleaved mode */
snd_pcm_hw_params_set_access(m_playback_handle, params,
SND_PCM_ACCESS_RW_INTERLEAVED);
/* Signed 16-bit big-endian format */
snd_pcm_hw_params_set_format(m_playback_handle, params,
SND_PCM_FORMAT_S16_BE);
/* Two channels (stereo) */
snd_pcm_hw_params_set_channels(m_playback_handle, params, 2);
/* Sampling rate */
val = sr;
snd_pcm_hw_params_set_rate_near(m_playback_handle,
params, &val, &dir);
char msg[80];
snprintf(msg, 80, "alsa: DSP samplerate now %d\n",val);
mgDebug(msg);
/* Write the parameters to the driver */
int err = snd_pcm_hw_params(m_playback_handle, params);
if (err < 0) {
esyslog("ERROR: unable to set hw parameters: %s\n",
snd_strerror(err));
snd_pcm_hw_params_free (params);
snd_pcm_close(m_playback_handle);
m_playback_handle = NULL;
return false;
}
snd_pcm_hw_params_free (params);
outSr = sr;
mgDebug("muggle-alsa: DSP reset done\n");
return true;
}
return false;
}
unsigned int cOutputAlsa::SampleRate(unsigned int PcmSampleRate)
{
return PcmSampleRate;
}
int cOutputAlsa::Output(const unsigned char *Data, int Len, bool SOF, unsigned int SampleRate )
{
if(m_playback_handle) {
if(SOF) {
if(SampleRate!=outSr) Reset(SampleRate);
}
int r = snd_pcm_writei(m_playback_handle, Data, Len/4);
if (r == -EPIPE) {
/* EPIPE means underrun */
mgDebug("muggle-alsa: underrun occurred\n");
snd_pcm_prepare(m_playback_handle);
r = 0;
}
if (r<0) {
char msg[80];
snprintf(msg, 80, "alsa: Serious error: %s\n",snd_strerror(r));
mgDebug(msg);
//esyslog(msg);
snd_pcm_prepare(m_playback_handle);
}
if(r>=0) return r*4;
}
return -1;
}
bool cOutputAlsa::Poll(void)
{
return (m_playback_handle) ? poll.Poll(500) : false;
}
void cOutputAlsa::Play(void)
{
if(m_playback_handle) snd_pcm_prepare(m_playback_handle);
}
void cOutputAlsa::Pause(void)
{
if (m_playback_handle) snd_pcm_drain(m_playback_handle);
}
#endif
mgPCMPlayer::mgPCMPlayer (mgSelection * plist)
: cPlayer(the_setup.ImgMode==imgLive? pmAudioOnly:pmAudioOnlyBlack ) {
......
const unsigned char *p = 0;
int pc = 0, only48khz = the_setup.Only48kHz;
cPoller poll;
m_output = new cOutputAlsa(this);
#ifdef DEBUG
// int beat = 0;
#endif
......
m_state = msStop;
SetPlayMode (pmStopped);
#if 0
#if VDRVERSNUM >= 10318
cDevice::PrimaryDevice()->SetCurrentAudioTrack(ttAudio);
#endif
#endif
while (m_active) {
#ifdef DEBUG
/*
......
case msStart:
{
m_index = 0;
m_readindex = 0;
m_playing = true;
......
levelgood = true;
haslevel = false;
m_output->Init();
level.Init ();
m_state = msDecode;
......
case dsPlay:
{
pcm = ds->pcm;
m_index = ds->index / 1000;
m_state = msNormalize;
m_readindex = ds->index;
m_index = m_readindex / 1000;
m_state = msResample;
}
break;
case dsSkip:
......
data[1] = pcm->channels > 1 ? pcm->samples[1] : 0;
lpcmFrame.LPCM[5] &= 0xcf;
dvbSampleRate = pcm->samplerate;
#if 0
dvbSampleRate = 48000;
if (!only48khz) {
switch (pcm->samplerate) {
......
data[1] = resample[1].Resampled ();
}
}
#endif
m_state = msOutput;
}
break;
......
the_setup.AudioMode ?
amDither : amRound );
if (outlen) {
#if 0
outlen += sizeof (lpcmFrame.LPCM) + LEN_CORR;
lpcmFrame.PES[4] = outlen >> 8;
lpcmFrame.PES[5] = outlen;
......
outlen +
sizeof (lpcmFrame.PES) -
LEN_CORR);
#endif
m_rframe = new cFrame ((unsigned char *) lpcmFrame.Data,
outlen, ftUnknown, m_readindex);
}
}
else {
......
m_rframe = 0;
}
bool startOfFrame = false;
if (!m_pframe && m_playmode == pmPlay) {
m_pframe = m_ringbuffer->Get ();
if (m_pframe) {
p = m_pframe->Data ();
pc = m_pframe->Count ();
startOfFrame = true;
}
}
......
fwrite( (void *)p, pc, sizeof( char ), peslog );
#endif
#if 0
#if VDRVERSNUM >= 10318
int w = PlayPes (p, pc);
#else
int w = PlayVideo (p, pc);
#endif
#endif
int w = m_output->Output(p, pc, startOfFrame, pcm->samplerate);
if (w > 0) {
p += w;
pc -= w;
......
if ((m_rframe || curr_m_state == msWait) && m_pframe) {
// Wait for output to become ready
DevicePoll (poll, 500);
//DevicePoll (poll, 500);
m_output->Poll();
}
else {
if (m_playmode != pmPlay) {
......
delete m_decoder;
m_decoder = 0;
}
delete m_output;
m_output = 0;
m_playing = false;
SetPlayMode (pmStopped);
......
}
else {
if (m_playmode == pmPlay) {
// DeviceFreeze();
DeviceFreeze();
if(m_output) m_output->Pause();
SetPlayMode (pmPaused);
}
}
......
if (m_playmode == pmStopped) {
m_state = msStart;
}
// DevicePlay(); // TODO? Commented out in original code, too
DevicePlay(); // TODO? Commented out in original code, too
if(m_output) m_output->Play();
SetPlayMode (pmPlay);
Unlock ();
}
/usr/src/myvdr/muggle-0.2.3_new/pcmplayer.h 2009-01-22 21:00:49.000000000 +0100
unsigned char Data[MAX_FRAMESIZE - HDR_SIZE - LPCM_SIZE];
};
class cOutput;
/*!
* \brief a generic PCM player class
*
......
mgDecoder *m_decoder;
cFrame *m_rframe, *m_pframe;
cOutput* m_output;
emgPlayMode m_playmode;
enum eState
......
//
int m_index;
int m_readindex;
string imagefile;
void Empty ();
    (1-1/1)