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 ();
|
||