mirror of
https://github.com/ElvishArtisan/rivendell.git
synced 2025-10-11 17:13:47 +02:00
2018-03-17 Fred Gleason <fredg@paravelsystems.com>
* Added support for DMA bus-mastering to the HPI driver.
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// A class for playing Microsoft WAV files.
|
||||
//
|
||||
// (C) Copyright 2002-2007,2016 Fred Gleason <fredg@paravelsystems.com>
|
||||
// (C) Copyright 2002-2007,2016-2018 Fred Gleason <fredg@paravelsystems.com>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
@@ -66,7 +66,10 @@ RDHPIPlayStream::RDHPIPlayStream(RDHPISoundCard *card,QWidget *parent)
|
||||
// hpi_err_t hpi_err;
|
||||
int quan;
|
||||
uint16_t type[HPI_MAX_ADAPTERS];
|
||||
struct hpi_format fmt;
|
||||
uint32_t dma_size=0;
|
||||
|
||||
dma_buffer_size=0;
|
||||
sound_card=card;
|
||||
card_number=-1;
|
||||
stream_number=-1;
|
||||
@@ -94,16 +97,28 @@ RDHPIPlayStream::RDHPIPlayStream(RDHPISoundCard *card,QWidget *parent)
|
||||
card_index[i]=i;
|
||||
}
|
||||
#else
|
||||
LogHpi(HPI_SubSysGetNumAdapters(NULL,&quan));
|
||||
LogHpi(HPI_SubSysGetNumAdapters(NULL,&quan),__LINE__);
|
||||
for(int i=0;i<quan;i++) {
|
||||
LogHpi(HPI_SubSysGetAdapter(NULL,i,card_index+i,type+i));
|
||||
LogHpi(HPI_SubSysGetAdapter(NULL,i,card_index+i,type+i),__LINE__);
|
||||
}
|
||||
#endif // HPI_VER
|
||||
|
||||
clock=new QTimer(this,"clock");
|
||||
//
|
||||
// Calculate DMA Buffer Size
|
||||
//
|
||||
memset(&fmt,0,sizeof(fmt)); // Worst case situation
|
||||
fmt.dwSampleRate=48000;
|
||||
fmt.wChannels=2;
|
||||
fmt.wFormat=HPI_FORMAT_PCM32_FLOAT;
|
||||
if(LogHpi(HPI_StreamEstimateBufferSize(&fmt,FRAGMENT_TIME,&dma_size),
|
||||
__LINE__)==0) {
|
||||
dma_buffer_size=dma_size;
|
||||
}
|
||||
|
||||
clock=new QTimer(this);
|
||||
connect(clock,SIGNAL(timeout()),this,SLOT(tickClock()));
|
||||
|
||||
play_timer=new QTimer(this,"play_timer");
|
||||
play_timer=new QTimer(this);
|
||||
connect(play_timer,SIGNAL(timeout()),this,SLOT(pause()));
|
||||
}
|
||||
|
||||
@@ -171,7 +186,9 @@ bool RDHPIPlayStream::formatSupported(RDWaveFile::Format format)
|
||||
}
|
||||
if(!is_open) {
|
||||
for(int i=0;i<sound_card->getCardOutputStreams(card_number);i++) {
|
||||
if(HPI_OutStreamOpen(NULL,card_index[card_number],i,&hostream)==0) {
|
||||
if(LogHpi(HPI_OutStreamOpen(NULL,card_index[card_number],i,&hostream),
|
||||
__LINE__)==0) {
|
||||
syslog(LOG_NOTICE,"buffer_size: %u\n",dma_buffer_size);
|
||||
found=true;
|
||||
break;
|
||||
}
|
||||
@@ -179,6 +196,11 @@ bool RDHPIPlayStream::formatSupported(RDWaveFile::Format format)
|
||||
if(!found) {
|
||||
return false;
|
||||
}
|
||||
if(LogHpi(HPI_OutStreamHostBufferAllocate(NULL,hostream,dma_buffer_size),
|
||||
__LINE__)!=0) {
|
||||
LogHpi(HPI_OutStreamClose(NULL,hostream),__LINE__);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
hostream=hpi_stream;
|
||||
@@ -187,36 +209,46 @@ bool RDHPIPlayStream::formatSupported(RDWaveFile::Format format)
|
||||
case RDWaveFile::Pcm16:
|
||||
LogHpi(HPI_FormatCreate(&hpi_format,getChannels(),
|
||||
HPI_FORMAT_PCM16_SIGNED,
|
||||
getSamplesPerSec(),getHeadBitRate(),0));
|
||||
state=HPI_OutStreamQueryFormat(NULL,hostream,&hpi_format);
|
||||
getSamplesPerSec(),getHeadBitRate(),0),
|
||||
__LINE__);
|
||||
state=LogHpi(HPI_OutStreamQueryFormat(NULL,hostream,&hpi_format),
|
||||
__LINE__);
|
||||
break;
|
||||
|
||||
case RDWaveFile::Pcm24:
|
||||
LogHpi(HPI_FormatCreate(&hpi_format,getChannels(),
|
||||
HPI_FORMAT_PCM24_SIGNED,
|
||||
getSamplesPerSec(),getHeadBitRate(),0));
|
||||
state=HPI_OutStreamQueryFormat(NULL,hostream,&hpi_format);
|
||||
getSamplesPerSec(),getHeadBitRate(),0),
|
||||
__LINE__);
|
||||
state=LogHpi(HPI_OutStreamQueryFormat(NULL,hostream,&hpi_format),
|
||||
__LINE__);
|
||||
break;
|
||||
|
||||
case RDWaveFile::MpegL1:
|
||||
LogHpi(HPI_FormatCreate(&hpi_format,getChannels(),
|
||||
HPI_FORMAT_MPEG_L1,
|
||||
getSamplesPerSec(),getHeadBitRate(),0));
|
||||
state=HPI_OutStreamQueryFormat(NULL,hostream,&hpi_format);
|
||||
getSamplesPerSec(),getHeadBitRate(),0),
|
||||
__LINE__);
|
||||
state=LogHpi(HPI_OutStreamQueryFormat(NULL,hostream,&hpi_format),
|
||||
__LINE__);
|
||||
break;
|
||||
|
||||
case RDWaveFile::MpegL2:
|
||||
LogHpi(HPI_FormatCreate(&hpi_format,getChannels(),
|
||||
HPI_FORMAT_MPEG_L2,
|
||||
getSamplesPerSec(),getHeadBitRate(),0));
|
||||
state=HPI_OutStreamQueryFormat(NULL,hostream,&hpi_format);
|
||||
getSamplesPerSec(),getHeadBitRate(),0),
|
||||
__LINE__);
|
||||
state=LogHpi(HPI_OutStreamQueryFormat(NULL,hostream,&hpi_format),
|
||||
__LINE__);
|
||||
break;;
|
||||
|
||||
case RDWaveFile::MpegL3:
|
||||
LogHpi(HPI_FormatCreate(&hpi_format,getChannels(),
|
||||
HPI_FORMAT_MPEG_L3,
|
||||
getSamplesPerSec(),getHeadBitRate(),0));
|
||||
state=HPI_OutStreamQueryFormat(NULL,hostream,&hpi_format);
|
||||
getSamplesPerSec(),getHeadBitRate(),0),
|
||||
__LINE__);
|
||||
state=LogHpi(HPI_OutStreamQueryFormat(NULL,hostream,&hpi_format),
|
||||
__LINE__);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -224,7 +256,8 @@ bool RDHPIPlayStream::formatSupported(RDWaveFile::Format format)
|
||||
break;
|
||||
}
|
||||
if(!is_open) {
|
||||
LogHpi(HPI_OutStreamClose(NULL,hostream));
|
||||
LogHpi(HPI_OutStreamHostBufferFree(NULL,hostream),__LINE__);
|
||||
LogHpi(HPI_OutStreamClose(NULL,hostream),__LINE__);
|
||||
}
|
||||
if(state!=0) {
|
||||
return false;
|
||||
@@ -396,10 +429,10 @@ bool RDHPIPlayStream::play()
|
||||
if((!playing)&&(!is_paused)) {
|
||||
LogHpi(HPI_OutStreamSetTimeScale(NULL,hpi_stream,
|
||||
(uint16_t)((RD_TIMESCALE_DIVISOR/(double)play_speed)*
|
||||
HPI_OSTREAM_TIMESCALE_UNITS)));
|
||||
if(HPI_OutStreamGetInfoEx(NULL,hpi_stream,
|
||||
&state,&buffer_size,&data_to_play,
|
||||
&samples_played,&reserved)!=0) {
|
||||
HPI_OSTREAM_TIMESCALE_UNITS)),__LINE__);
|
||||
if(LogHpi(HPI_OutStreamGetInfoEx(NULL,hpi_stream,
|
||||
&state,&buffer_size,&data_to_play,
|
||||
&samples_played,&reserved),__LINE__)!=0) {
|
||||
return false;
|
||||
}
|
||||
fragment_size=buffer_size/4;
|
||||
@@ -420,25 +453,25 @@ bool RDHPIPlayStream::play()
|
||||
case 8:
|
||||
LogHpi(HPI_FormatCreate(&format,getChannels(),
|
||||
HPI_FORMAT_PCM8_UNSIGNED,
|
||||
getSamplesPerSec(),0,0));
|
||||
getSamplesPerSec(),0,0),__LINE__);
|
||||
break;
|
||||
case 16:
|
||||
LogHpi(HPI_FormatCreate(&format,getChannels(),
|
||||
HPI_FORMAT_PCM16_SIGNED,
|
||||
getSamplesPerSec(),0,0));
|
||||
getSamplesPerSec(),0,0),__LINE__);
|
||||
break;
|
||||
case 24:
|
||||
LogHpi(HPI_FormatCreate(&format,getChannels(),
|
||||
HPI_FORMAT_PCM24_SIGNED,
|
||||
getSamplesPerSec(),0,0));
|
||||
getSamplesPerSec(),0,0),__LINE__);
|
||||
break;
|
||||
case 32:
|
||||
LogHpi(HPI_FormatCreate(&format,getChannels(),
|
||||
HPI_FORMAT_PCM32_SIGNED,
|
||||
getSamplesPerSec(),0,0));
|
||||
getSamplesPerSec(),0,0),__LINE__);
|
||||
break;
|
||||
default:
|
||||
LogHpi(HPI_AdapterClose(NULL,card_index[card_number]));
|
||||
LogHpi(HPI_AdapterClose(NULL,card_index[card_number]),__LINE__);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
@@ -448,20 +481,23 @@ bool RDHPIPlayStream::play()
|
||||
case 1:
|
||||
LogHpi(HPI_FormatCreate(&format,getChannels(),
|
||||
HPI_FORMAT_MPEG_L1,getSamplesPerSec(),
|
||||
getHeadBitRate(),getHeadFlags()));
|
||||
getHeadBitRate(),getHeadFlags()),
|
||||
__LINE__);
|
||||
break;
|
||||
case 2:
|
||||
LogHpi(HPI_FormatCreate(&format,getChannels(),
|
||||
HPI_FORMAT_MPEG_L2,getSamplesPerSec(),
|
||||
getHeadBitRate(),getHeadFlags()));
|
||||
getHeadBitRate(),getHeadFlags()),
|
||||
__LINE__);
|
||||
break;
|
||||
case 3:
|
||||
LogHpi(HPI_FormatCreate(&format,getChannels(),
|
||||
HPI_FORMAT_MPEG_L3,getSamplesPerSec(),
|
||||
getHeadBitRate(),getHeadFlags()));
|
||||
getHeadBitRate(),getHeadFlags()),
|
||||
__LINE__);
|
||||
break;
|
||||
default:
|
||||
LogHpi(HPI_AdapterClose(NULL,card_index[card_number]));
|
||||
LogHpi(HPI_AdapterClose(NULL,card_index[card_number]),__LINE__);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -469,7 +505,8 @@ bool RDHPIPlayStream::play()
|
||||
return false;
|
||||
}
|
||||
#if HPI_VER < 0x00030500
|
||||
if(HPI_DataCreate(&hpi_data,&format,pdata,fragment_size)!=0) {
|
||||
if(LogHpi(HPI_DataCreate(&hpi_data,&format,pdata,fragment_size),__LINE__)!=
|
||||
0) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@@ -488,15 +525,15 @@ bool RDHPIPlayStream::play()
|
||||
}
|
||||
readWave(pdata,read_bytes);
|
||||
#if HPI_VER > 0x00030500
|
||||
LogHpi(HPI_OutStreamWriteBuf(NULL,hpi_stream,pdata,read_bytes,&format));
|
||||
LogHpi(HPI_OutStreamWriteBuf(NULL,hpi_stream,pdata,read_bytes,&format),
|
||||
__LINE__);
|
||||
#else
|
||||
LogHpi(HPI_DataCreate(&hpi_data,&format,pdata,read_bytes));
|
||||
LogHpi(HPI_OutStreamWrite(NULL,hpi_stream,&hpi_data));
|
||||
LogHpi(HPI_DataCreate(&hpi_data,&format,pdata,read_bytes),__LINE__);
|
||||
LogHpi(HPI_OutStreamWrite(NULL,hpi_stream,&hpi_data),__LINE__);
|
||||
#endif
|
||||
if(HPI_OutStreamStart(NULL,hpi_stream)!=0) {
|
||||
if(LogHpi(HPI_OutStreamStart(NULL,hpi_stream),__LINE__)!=0) {
|
||||
return false;
|
||||
}
|
||||
clock->start(50);
|
||||
clock->start(FRAGMENT_TIME);
|
||||
playing=true;
|
||||
is_paused=false;
|
||||
@@ -513,7 +550,7 @@ bool RDHPIPlayStream::play()
|
||||
}
|
||||
}
|
||||
if((!playing)&(is_paused|repositioned)) {
|
||||
LogHpi(HPI_OutStreamStart(NULL,hpi_stream));
|
||||
LogHpi(HPI_OutStreamStart(NULL,hpi_stream),__LINE__);
|
||||
clock->start(FRAGMENT_TIME);
|
||||
playing=true;
|
||||
stopping=false;
|
||||
@@ -543,10 +580,11 @@ void RDHPIPlayStream::pause()
|
||||
return;
|
||||
}
|
||||
if(playing) {
|
||||
LogHpi(HPI_OutStreamStop(NULL,hpi_stream));
|
||||
LogHpi(HPI_OutStreamStop(NULL,hpi_stream),__LINE__);
|
||||
clock->stop();
|
||||
LogHpi(HPI_OutStreamGetInfoEx(NULL,hpi_stream,&state,&buffer_size,
|
||||
&data_to_play,&samples_played,&reserved));
|
||||
&data_to_play,&samples_played,&reserved),
|
||||
__LINE__);
|
||||
switch(getFormatTag()) {
|
||||
case WAVE_FORMAT_PCM:
|
||||
samples_pending=data_to_play/(getChannels()*getBitsPerSample()/8);
|
||||
@@ -580,12 +618,12 @@ void RDHPIPlayStream::stop()
|
||||
return;
|
||||
}
|
||||
if(playing|is_paused) {
|
||||
LogHpi(HPI_OutStreamStop(NULL,hpi_stream));
|
||||
LogHpi(HPI_OutStreamStop(NULL,hpi_stream),__LINE__);
|
||||
clock->stop();
|
||||
playing=false;
|
||||
is_paused=false;
|
||||
seekWave(0,SEEK_SET);
|
||||
LogHpi(HPI_OutStreamReset(NULL,hpi_stream));
|
||||
LogHpi(HPI_OutStreamReset(NULL,hpi_stream),__LINE__);
|
||||
samples_pending=0;
|
||||
samples_skipped=0;
|
||||
stream_state=RDHPIPlayStream::Stopped;
|
||||
@@ -632,7 +670,7 @@ bool RDHPIPlayStream::setPosition(unsigned samples)
|
||||
is_paused=false;
|
||||
repositioned=true;
|
||||
}
|
||||
LogHpi(HPI_OutStreamReset(NULL,hpi_stream));
|
||||
LogHpi(HPI_OutStreamReset(NULL,hpi_stream),__LINE__);
|
||||
samples_played=0;
|
||||
switch(getFormatTag()) {
|
||||
case WAVE_FORMAT_PCM:
|
||||
@@ -686,24 +724,25 @@ void RDHPIPlayStream::tickClock()
|
||||
char hpi_text[100];
|
||||
int n;
|
||||
|
||||
hpi_err=HPI_OutStreamGetInfoEx(NULL,hpi_stream,
|
||||
&state,&buffer_size,&data_to_play,
|
||||
&samples_played,&reserved);
|
||||
hpi_err=LogHpi(HPI_OutStreamGetInfoEx(NULL,hpi_stream,
|
||||
&state,&buffer_size,&data_to_play,
|
||||
&samples_played,&reserved),__LINE__);
|
||||
if(!stopping) {
|
||||
while((buffer_size-data_to_play)>=fragment_size) {
|
||||
n=readWave(pdata,fragment_size);
|
||||
if((n<=0)||(((uint32_t)n)<fragment_size)) {
|
||||
// End of file
|
||||
#if HPI_VER > 0x00030500
|
||||
if((hpi_err=HPI_OutStreamWriteBuf(NULL,hpi_stream,
|
||||
pdata,n,&format))!=0) {
|
||||
if((hpi_err=LogHpi(HPI_OutStreamWriteBuf(NULL,hpi_stream,
|
||||
pdata,n,&format),__LINE__))!=
|
||||
0) {
|
||||
HPI_GetErrorText(hpi_err,hpi_text);
|
||||
fprintf(stderr,"*** HPI Error: %s ***\n",hpi_text);
|
||||
}
|
||||
#else
|
||||
HPI_DataCreate(&hpi_data,&format,pdata,n);
|
||||
if((hpi_err=HPI_OutStreamWrite(NULL,hpi_stream,
|
||||
&hpi_data))!=0) {
|
||||
if((hpi_err=LogHpi(HPI_OutStreamWrite(NULL,hpi_stream,
|
||||
&hpi_data),__LINE__))!=0) {
|
||||
HPI_GetErrorText(hpi_err,hpi_text);
|
||||
fprintf(stderr,"*** HPI Error: %s ***\n",hpi_text);
|
||||
}
|
||||
@@ -714,26 +753,28 @@ void RDHPIPlayStream::tickClock()
|
||||
}
|
||||
left_to_write-=n;
|
||||
#if HPI_VER > 0x00030500
|
||||
hpi_err=HPI_OutStreamWriteBuf(NULL,hpi_stream,
|
||||
pdata,n,&format);
|
||||
hpi_err=LogHpi(HPI_OutStreamWriteBuf(NULL,hpi_stream,pdata,n,&format),
|
||||
__LINE__);
|
||||
#else
|
||||
hpi_err=HPI_DataCreate(&hpi_data,&format,pdata,n);
|
||||
hpi_err=HPI_OutStreamWrite(NULL,hpi_stream,&hpi_data);
|
||||
hpi_err=LogHpi(HPI_DataCreate(&hpi_data,&format,pdata,n),__LINE__);
|
||||
hpi_err=LogHpi(HPI_OutStreamWrite(NULL,hpi_stream,&hpi_data),__LINE__);
|
||||
#endif
|
||||
hpi_err=HPI_OutStreamGetInfoEx(NULL,hpi_stream,
|
||||
&state,&buffer_size,&data_to_play,
|
||||
&samples_played,&reserved);
|
||||
hpi_err=LogHpi(HPI_OutStreamGetInfoEx(NULL,hpi_stream,
|
||||
&state,&buffer_size,&data_to_play,
|
||||
&samples_played,&reserved),
|
||||
__LINE__);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(state==HPI_STATE_DRAINED) {
|
||||
hpi_err=HPI_OutStreamStop(NULL,hpi_stream);
|
||||
hpi_err=HPI_OutStreamClose(NULL,hpi_stream);
|
||||
hpi_err=HPI_AdapterClose(NULL,card_index[card_number]);
|
||||
LogHpi(HPI_OutStreamStop(NULL,hpi_stream),__LINE__);
|
||||
LogHpi(HPI_OutStreamHostBufferFree(NULL,hpi_stream),__LINE__);
|
||||
LogHpi(HPI_OutStreamClose(NULL,hpi_stream),__LINE__);
|
||||
hpi_err=LogHpi(HPI_AdapterClose(NULL,card_index[card_number]),__LINE__);
|
||||
clock->stop();
|
||||
playing=false;
|
||||
seekWave(0,SEEK_SET);
|
||||
hpi_err=HPI_OutStreamReset(NULL,hpi_stream);
|
||||
hpi_err=LogHpi(HPI_OutStreamReset(NULL,hpi_stream),__LINE__);
|
||||
samples_pending=0;
|
||||
samples_skipped=0;
|
||||
stream_state=RDHPIPlayStream::Stopped;
|
||||
@@ -761,7 +802,10 @@ int RDHPIPlayStream::GetStream()
|
||||
#ifdef RDHPIPLAYSTREAM_USE_LOCAL_MUTEX
|
||||
for(int i=0;i<sound_card->getCardOutputStreams(card_number);i++) {
|
||||
if(++stream_mutex[card_number][i]==1) {
|
||||
LogHpi(HPI_OutStreamOpen(NULL,card_index[card_number],i,&hpi_stream));
|
||||
LogHpi(HPI_OutStreamOpen(NULL,card_index[card_number],i,&hpi_stream),
|
||||
__LINE__);
|
||||
LogHpi(HPI_OutStreamHostBufferAllocate(NULL,hpi_stream,dma_buffer_size),
|
||||
__LINE__);
|
||||
stream_number=i;
|
||||
return stream_number;
|
||||
}
|
||||
@@ -772,7 +816,8 @@ int RDHPIPlayStream::GetStream()
|
||||
return -1;
|
||||
#else
|
||||
for(int i=0;i<sound_card->getCardOutputStreams(card_number);i++) {
|
||||
if(HPI_OutStreamOpen(NULL,card_index[card_number],i,&hpi_stream)==0) {
|
||||
if(LogHpi(HPI_OutStreamOpen(NULL,card_index[card_number],i,&hpi_stream),
|
||||
__LINE__)==0) {
|
||||
stream_number=i;
|
||||
// syslog(LOG_ERR,"HPI allocating ostream: %d",stream_number);
|
||||
return stream_number;
|
||||
@@ -787,23 +832,25 @@ void RDHPIPlayStream::FreeStream()
|
||||
{
|
||||
#ifdef RDHPIPLAYSTREAM_USE_LOCAL_MUTEX
|
||||
stream_mutex[card_number][stream_number]--;
|
||||
LogHpi(HPI_OutStreamClose(NULL,hpi_stream));
|
||||
LogHpi(HPI_OutStreamHostBufferFree(NULL,hpi_stream),__LINE__);
|
||||
LogHpi(HPI_OutStreamClose(NULL,hpi_stream),__LINE__);
|
||||
stream_number=-1;
|
||||
#else
|
||||
LogHpi(HPI_OutStreamClose(NULL,hpi_stream));
|
||||
LogHpi(HPI_OutStreamHostBufferFree(NULL,hpi_stream),__LINE__);
|
||||
LogHpi(HPI_OutStreamClose(NULL,hpi_stream),__LINE__);
|
||||
// syslog(LOG_ERR,"HPI closing ostream: %d",stream_number);
|
||||
stream_number=-1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
hpi_err_t RDHPIPlayStream::LogHpi(hpi_err_t err)
|
||||
hpi_err_t RDHPIPlayStream::LogHpi(hpi_err_t err,int lineno)
|
||||
{
|
||||
char err_txt[200];
|
||||
|
||||
if(err!=0) {
|
||||
HPI_GetErrorText(err,err_txt);
|
||||
syslog(LOG_NOTICE,"HPI Error: %s",err_txt);
|
||||
syslog(LOG_NOTICE,"HPI Error: %s, %s line %d",err_txt,__FILE__,lineno);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
Reference in New Issue
Block a user