Feature #71 ยป muggle_alsa.patch
/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(¶ms);
|
||
/* 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 ();
|