mirror of
https://github.com/ElvishArtisan/rivendell.git
synced 2025-04-07 01:13:50 +02:00
* Added the name of the Rivendell library component to 'Unknown Error' messages. Signed-off-by: Fred Gleason <fredg@paravelsystems.com>
748 lines
18 KiB
C++
748 lines
18 KiB
C++
// rdhpirecordstream.cpp
|
|
//
|
|
// A class for recording Microsoft WAV files.
|
|
//
|
|
// (C) Copyright 2002-2019 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
|
|
// published by the Free Software Foundation.
|
|
//
|
|
// This program 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 General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public
|
|
// License along with this program; if not, write to the Free Software
|
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
//
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <syslog.h>
|
|
#include <fcntl.h>
|
|
#include <qobject.h>
|
|
#include <qwidget.h>
|
|
#include <qstring.h>
|
|
#include <qdatetime.h>
|
|
|
|
#include <rdapplication.h>
|
|
|
|
#include "rdhpirecordstream.h"
|
|
|
|
RDHPIRecordStream::RDHPIRecordStream(RDHPISoundCard *card,QWidget *parent)
|
|
:QObject(parent),RDWaveFile()
|
|
{
|
|
int quan;
|
|
uint16_t type[HPI_MAX_ADAPTERS];
|
|
struct hpi_format fmt;
|
|
uint32_t dma_size=0;
|
|
|
|
if(getenv(DEBUG_VAR)==NULL) {
|
|
debug=false;
|
|
}
|
|
else {
|
|
debug=true;
|
|
printf("RDHPIRecordStream: debugging enabled\n");
|
|
}
|
|
if(getenv(XRUN_VAR)==NULL) {
|
|
xrun=false;
|
|
}
|
|
else {
|
|
xrun=true;
|
|
printf("RDHPIRecordStream: xrun notification enabled\n");
|
|
}
|
|
|
|
sound_card=card;
|
|
|
|
card_number=-1;
|
|
stream_number=-1;
|
|
is_ready=false;
|
|
is_recording=false;
|
|
is_paused=false;
|
|
stopping=false;
|
|
record_started=false;
|
|
record_length=0;
|
|
is_open=false;
|
|
pdata=NULL;
|
|
|
|
//
|
|
// Get Adapter Indices
|
|
//
|
|
#if HPI_VER < 0x00030600
|
|
for(unsigned i=0;i<HPI_MAX_ADAPTERS;i++) {
|
|
card_index[i]=i;
|
|
}
|
|
#else
|
|
LogHpi(HPI_SubSysGetNumAdapters(NULL,&quan),__LINE__);
|
|
for(int i=0;i<quan;i++) {
|
|
LogHpi(HPI_SubSysGetAdapter(NULL,i,card_index+i,type+i),__LINE__);
|
|
}
|
|
#endif // HPI_VER
|
|
|
|
//
|
|
// 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,RDHPIRECORDSTREAM_CLOCK_INTERVAL,
|
|
&dma_size),__LINE__)==0) {
|
|
dma_buffer_size=dma_size;
|
|
}
|
|
|
|
clock=new QTimer(this);
|
|
connect(clock,SIGNAL(timeout()),this,SLOT(tickClock()));
|
|
|
|
length_timer=new QTimer(this);
|
|
connect(length_timer,SIGNAL(timeout()),this,SLOT(pause()));
|
|
}
|
|
|
|
|
|
RDHPIRecordStream::~RDHPIRecordStream()
|
|
{
|
|
if(pdata!=NULL) {
|
|
delete pdata;
|
|
}
|
|
}
|
|
|
|
|
|
QString RDHPIRecordStream::errorString(RDHPIRecordStream::Error err)
|
|
{
|
|
QString str;
|
|
|
|
switch(err) {
|
|
case RDHPIRecordStream::Ok:
|
|
return QString(tr("Ok"));
|
|
break;
|
|
|
|
case RDHPIRecordStream::NoFile:
|
|
return QString(tr("Unable to create/open file"));
|
|
break;
|
|
|
|
case RDHPIRecordStream::NoStream:
|
|
return QString(tr("Input stream unavailable"));
|
|
break;
|
|
|
|
case RDHPIRecordStream::AlreadyOpen:
|
|
return QString(tr("Stream is already open"));
|
|
break;
|
|
|
|
default:
|
|
str=QString(tr("Unknown RDHpiRecordStream Error:"));
|
|
return QString().sprintf("%s %d\n",(const char *)str,err);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
RDHPIRecordStream::Error RDHPIRecordStream::createWave()
|
|
{
|
|
if(is_open) {
|
|
return RDHPIRecordStream::AlreadyOpen;
|
|
}
|
|
if(!RDWaveFile::createWave()) {
|
|
return RDHPIRecordStream::NoFile;
|
|
}
|
|
if(!GetStream()) {
|
|
closeWave();
|
|
return RDHPIRecordStream::NoStream;
|
|
}
|
|
is_open=true;
|
|
return RDHPIRecordStream::Ok;
|
|
}
|
|
|
|
|
|
RDHPIRecordStream::Error RDHPIRecordStream::createWave(QString filename)
|
|
{
|
|
if(is_open) {
|
|
return RDHPIRecordStream::AlreadyOpen;
|
|
}
|
|
setName(filename);
|
|
return createWave();
|
|
}
|
|
|
|
|
|
void RDHPIRecordStream::closeWave()
|
|
{
|
|
if(!is_open) {
|
|
return;
|
|
}
|
|
if(getState()!=RDHPIRecordStream::Stopped) {
|
|
stop();
|
|
}
|
|
RDWaveFile::closeWave(samples_recorded);
|
|
FreeStream();
|
|
is_open=false;
|
|
}
|
|
|
|
|
|
bool RDHPIRecordStream::formatSupported(RDWaveFile::Format format)
|
|
{
|
|
#if HPI_VER < HPI_VERSION_CONSTRUCTOR(3L,10,0)
|
|
HPI_FORMAT hformat;
|
|
#else
|
|
struct hpi_format hformat;
|
|
#endif
|
|
hpi_handle_t histream;
|
|
bool found=false;
|
|
|
|
if(card_number<0) {
|
|
return false;
|
|
}
|
|
if(format==RDWaveFile::Vorbis) {
|
|
#ifdef HAVE_VORBIS
|
|
return true;
|
|
#endif // HAVE_VORBIS
|
|
return false;
|
|
}
|
|
if(!is_open) {
|
|
for(int i=0;i<sound_card->getCardInputStreams(card_number);i++) {
|
|
if(LogHpi(HPI_InStreamOpen(NULL,card_index[card_number],i,&histream),
|
|
__LINE__)==0) {
|
|
found=true;
|
|
break;
|
|
}
|
|
}
|
|
if(!found) {
|
|
return false;
|
|
}
|
|
if(HPI_InStreamHostBufferAllocate(NULL,histream,dma_buffer_size));
|
|
}
|
|
else {
|
|
histream=hpi_stream;
|
|
}
|
|
switch(format) {
|
|
case RDWaveFile::Pcm8:
|
|
LogHpi(HPI_FormatCreate(&hformat,getChannels(),HPI_FORMAT_PCM8_UNSIGNED,
|
|
getSamplesPerSec(),getHeadBitRate(),0),__LINE__);
|
|
state=LogHpi(HPI_InStreamQueryFormat(NULL,histream,&hformat),__LINE__);
|
|
break;
|
|
|
|
case RDWaveFile::Pcm16:
|
|
LogHpi(HPI_FormatCreate(&hformat,getChannels(),HPI_FORMAT_PCM16_SIGNED,
|
|
getSamplesPerSec(),getHeadBitRate(),0),__LINE__);
|
|
state=LogHpi(HPI_InStreamQueryFormat(NULL,histream,&hformat),__LINE__);
|
|
break;
|
|
|
|
case RDWaveFile::Pcm24:
|
|
LogHpi(HPI_FormatCreate(&hformat,getChannels(),HPI_FORMAT_PCM24_SIGNED,
|
|
getSamplesPerSec(),getHeadBitRate(),0),__LINE__);
|
|
state=LogHpi(HPI_InStreamQueryFormat(NULL,histream,&hformat),__LINE__);
|
|
break;
|
|
|
|
case RDWaveFile::MpegL1:
|
|
LogHpi(HPI_FormatCreate(&hformat,getChannels(),HPI_FORMAT_MPEG_L1,
|
|
getSamplesPerSec(),getHeadBitRate(),0),__LINE__);
|
|
state=LogHpi(HPI_InStreamQueryFormat(NULL,histream,&hformat),__LINE__);
|
|
break;
|
|
|
|
case RDWaveFile::MpegL2:
|
|
LogHpi(HPI_FormatCreate(&hformat,getChannels(),HPI_FORMAT_MPEG_L2,
|
|
getSamplesPerSec(),getHeadBitRate(),0),__LINE__);
|
|
state=LogHpi(HPI_InStreamQueryFormat(NULL,histream,&hformat),__LINE__);
|
|
break;
|
|
|
|
case RDWaveFile::MpegL3:
|
|
LogHpi(HPI_FormatCreate(&hformat,getChannels(),HPI_FORMAT_MPEG_L3,
|
|
getSamplesPerSec(),getHeadBitRate(),0),__LINE__);
|
|
state=LogHpi(HPI_InStreamQueryFormat(NULL,histream,&hformat),__LINE__);
|
|
break;
|
|
|
|
default:
|
|
state=1;
|
|
break;
|
|
}
|
|
if(!is_open) {
|
|
if(HPI_InStreamHostBufferFree(NULL,histream));
|
|
LogHpi(HPI_InStreamClose(NULL,histream),__LINE__);
|
|
}
|
|
if(state!=0) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool RDHPIRecordStream::formatSupported()
|
|
{
|
|
switch(getFormatTag()) {
|
|
case WAVE_FORMAT_PCM:
|
|
switch(getBitsPerSample()) {
|
|
case 8:
|
|
return formatSupported(RDWaveFile::Pcm8);
|
|
break;
|
|
|
|
case 16:
|
|
return formatSupported(RDWaveFile::Pcm16);
|
|
break;
|
|
|
|
case 24:
|
|
return formatSupported(RDWaveFile::Pcm24);
|
|
break;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
break;
|
|
|
|
case WAVE_FORMAT_MPEG:
|
|
switch(getHeadLayer()) {
|
|
case 1:
|
|
return formatSupported(RDWaveFile::MpegL1);
|
|
break;
|
|
|
|
case 2:
|
|
return formatSupported(RDWaveFile::MpegL2);
|
|
break;
|
|
|
|
case 3:
|
|
return formatSupported(RDWaveFile::MpegL3);
|
|
break;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
int RDHPIRecordStream::getCard() const
|
|
{
|
|
return card_number;
|
|
}
|
|
|
|
|
|
void RDHPIRecordStream::setCard(int card)
|
|
{
|
|
if(!is_recording) {
|
|
card_number=card;
|
|
if(debug) {
|
|
printf("RDHPIRecordStream: using card %d\n",card_number);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
int RDHPIRecordStream::getStream() const
|
|
{
|
|
return stream_number;
|
|
}
|
|
|
|
|
|
void RDHPIRecordStream::setStream(int stream)
|
|
{
|
|
stream_number=stream;
|
|
}
|
|
|
|
|
|
bool RDHPIRecordStream::haveInputVOX() const
|
|
{
|
|
return sound_card->haveInputStreamVOX(card_number,stream_number);
|
|
}
|
|
|
|
|
|
RDHPIRecordStream::RecordState RDHPIRecordStream::getState()
|
|
{
|
|
if(is_recording) {
|
|
if(record_started) {
|
|
return RDHPIRecordStream::RecordStarted;
|
|
}
|
|
return RDHPIRecordStream::Recording;
|
|
}
|
|
if(is_paused) {
|
|
return RDHPIRecordStream::Paused;
|
|
}
|
|
if(is_ready) {
|
|
return RDHPIRecordStream::RecordReady;
|
|
}
|
|
return RDHPIRecordStream::Stopped;
|
|
}
|
|
|
|
|
|
int RDHPIRecordStream::getPosition() const
|
|
{
|
|
if((!is_recording)&&(!is_ready)&&(!is_paused)) {
|
|
return 0;
|
|
}
|
|
return samples_recorded;
|
|
}
|
|
|
|
|
|
unsigned RDHPIRecordStream::samplesRecorded() const
|
|
{
|
|
return samples_recorded;
|
|
}
|
|
|
|
|
|
bool RDHPIRecordStream::recordReady()
|
|
{
|
|
hpi_err_t hpi_error=0;
|
|
char hpi_text[200];
|
|
|
|
if(debug) {
|
|
printf("RDHPIRecordStream: received recordReady()\n");
|
|
}
|
|
if(!is_open) {
|
|
return false;
|
|
}
|
|
if((!is_recording)&&(!is_paused)) {
|
|
resetWave();
|
|
if(LogHpi(HPI_InStreamGetInfoEx(NULL,hpi_stream,
|
|
&state,&buffer_size,&data_recorded,
|
|
&samples_recorded,&reserved),__LINE__)!=0) {
|
|
if(debug) {
|
|
printf("RDHPIRecordStream: HPI_InStreamGetInfoEx() failed\n");
|
|
}
|
|
return false;
|
|
}
|
|
fragment_size=buffer_size/4;
|
|
if(fragment_size>192000) { // ALSA Compatibility Limitation
|
|
fragment_size=192000;
|
|
}
|
|
fragment_time=(1000*fragment_size)/(getAvgBytesPerSec());
|
|
if(pdata!=NULL) {
|
|
delete pdata;
|
|
}
|
|
pdata=(uint8_t *)malloc(fragment_size);
|
|
if(pdata==NULL) {
|
|
if(debug) {
|
|
printf("RDHPIRecordStream: couldn't allocate buffer\n");
|
|
}
|
|
return false;
|
|
}
|
|
switch(getFormatTag()) {
|
|
case WAVE_FORMAT_PCM:
|
|
if(debug) {
|
|
printf("RDHPIRecordStream: using PCM%d format\n",
|
|
getBitsPerSample());
|
|
}
|
|
switch(getBitsPerSample()) {
|
|
case 8:
|
|
hpi_error=LogHpi(HPI_FormatCreate(&format,getChannels(),
|
|
HPI_FORMAT_PCM8_UNSIGNED,
|
|
getSamplesPerSec(),0,0),__LINE__);
|
|
break;
|
|
|
|
case 16:
|
|
hpi_error=LogHpi(HPI_FormatCreate(&format,getChannels(),
|
|
HPI_FORMAT_PCM16_SIGNED,
|
|
getSamplesPerSec(),0,0),__LINE__);
|
|
break;
|
|
|
|
case 24:
|
|
hpi_error=LogHpi(HPI_FormatCreate(&format,getChannels(),
|
|
HPI_FORMAT_PCM24_SIGNED,
|
|
getSamplesPerSec(),0,0),__LINE__);
|
|
break;
|
|
|
|
case 32:
|
|
hpi_error=LogHpi(HPI_FormatCreate(&format,getChannels(),
|
|
HPI_FORMAT_PCM32_SIGNED,
|
|
getSamplesPerSec(),0,0),__LINE__);
|
|
break;
|
|
|
|
default:
|
|
if(debug) {
|
|
printf("RDHPIRecordStream: unsupported sample size\n");
|
|
}
|
|
return false;
|
|
}
|
|
break;
|
|
|
|
case WAVE_FORMAT_MPEG:
|
|
if(debug) {
|
|
printf("RDHPIRecordStream: using MPEG-1 Layer %d\n",getHeadLayer());
|
|
}
|
|
switch(getHeadLayer()) {
|
|
case 1:
|
|
hpi_error=LogHpi(HPI_FormatCreate(&format,getChannels(),
|
|
HPI_FORMAT_MPEG_L1,getSamplesPerSec(),
|
|
getHeadBitRate(),getHeadFlags()),
|
|
__LINE__);
|
|
break;
|
|
|
|
case 2:
|
|
hpi_error=LogHpi(HPI_FormatCreate(&format,getChannels(),
|
|
HPI_FORMAT_MPEG_L2,getSamplesPerSec(),
|
|
getHeadBitRate(),getHeadFlags()),
|
|
__LINE__);
|
|
break;
|
|
|
|
case 3:
|
|
hpi_error=LogHpi(HPI_FormatCreate(&format,getChannels(),
|
|
HPI_FORMAT_MPEG_L3,getSamplesPerSec(),
|
|
getHeadBitRate(),getHeadFlags()),
|
|
__LINE__);
|
|
break;
|
|
|
|
default:
|
|
hpi_error=LogHpi(HPI_AdapterClose(NULL,card_index[card_number]),
|
|
__LINE__);
|
|
if(debug) {
|
|
printf("RDHPIRecordStream: invalid MPEG-1 layer\n");
|
|
}
|
|
return false;
|
|
}
|
|
if(getMextChunk()) {
|
|
setMextHomogenous(true);
|
|
setMextPaddingUsed(false);
|
|
setMextHackedBitRate(true);
|
|
setMextFreeFormat(false);
|
|
setMextFrameSize(144*getHeadBitRate()/getSamplesPerSec());
|
|
setMextAncillaryLength(5);
|
|
setMextLeftEnergyPresent(true);
|
|
if(getChannels()>1) {
|
|
setMextRightEnergyPresent(true);
|
|
}
|
|
else {
|
|
setMextRightEnergyPresent(false);
|
|
}
|
|
setMextPrivateDataPresent(false);
|
|
}
|
|
break;
|
|
|
|
case WAVE_FORMAT_VORBIS:
|
|
if(debug) {
|
|
printf("RDHPIRecordStream: using OggVorbis\n");
|
|
}
|
|
hpi_error=LogHpi(HPI_FormatCreate(&format,getChannels(),
|
|
HPI_FORMAT_PCM16_SIGNED,
|
|
getSamplesPerSec(),0,0),__LINE__);
|
|
break;
|
|
|
|
default:
|
|
if(debug) {
|
|
printf("RDHPIRecordStream: invalid format tag\n");
|
|
}
|
|
return false;
|
|
break;
|
|
}
|
|
if((hpi_error=LogHpi(HPI_InStreamQueryFormat(NULL,hpi_stream,
|
|
&format),__LINE__))!=0) {
|
|
if(debug) {
|
|
HPI_GetErrorText(hpi_error,hpi_text);
|
|
printf("Num: %d\n",hpi_error);
|
|
printf("RDHPIRecordStream: %s\n",hpi_text);
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
#if HPI_VER < 0x00030500
|
|
LogHpi(HPI_DataCreate(&hpi_data,&format,pdata,fragment_size),__LINE__);
|
|
#endif
|
|
hpi_error=LogHpi(HPI_InStreamSetFormat(NULL,hpi_stream,&format),__LINE__);
|
|
hpi_error=LogHpi(HPI_InStreamStart(NULL,hpi_stream),__LINE__);
|
|
// clock->start(2*fragment_time/3);
|
|
clock->start(RDHPIRECORDSTREAM_CLOCK_INTERVAL);
|
|
is_ready=true;
|
|
is_recording=false;
|
|
is_paused=false;
|
|
stopping=false;
|
|
emit isStopped(false);
|
|
emit ready();
|
|
emit stateChanged(card_number,stream_number,1); // RecordReady
|
|
if(debug) {
|
|
printf("RDHPIRecordStream: emitted isStopped(false)\n");
|
|
printf("RDHPIRecordStream: emitted ready()\n");
|
|
printf("RDHPIRecordStream: emitted stateChanged(%d,%d,RDHPIRecordStream::RecordReady)\n",card_number,stream_number);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void RDHPIRecordStream::record()
|
|
{
|
|
if(debug) {
|
|
printf("RDHPIRecordStream: received record()\n");
|
|
}
|
|
if(!is_open) {
|
|
return;
|
|
}
|
|
if(!is_ready) {
|
|
recordReady();
|
|
}
|
|
record_started=false;
|
|
LogHpi(HPI_InStreamReset(NULL,hpi_stream),__LINE__);
|
|
LogHpi(HPI_InStreamStart(NULL,hpi_stream),__LINE__);
|
|
is_recording=true;
|
|
is_paused=false;
|
|
emit isStopped(false);
|
|
emit recording();
|
|
emit stateChanged(card_number,stream_number,0); // Recording
|
|
if(debug) {
|
|
printf("RDHPIRecordStream: emitted isStopped(false)\n");
|
|
printf("RDHPIRecordStream: emitted recording()\n");
|
|
printf("RDHPIRecordStream: emitted stateChanged(%d,%d,RDHPIRecordStream::Recording)\n",card_number,stream_number);
|
|
}
|
|
tickClock();
|
|
}
|
|
|
|
|
|
void RDHPIRecordStream::pause()
|
|
{
|
|
if(debug) {
|
|
printf("RDHPIRecordStream: received pause()\n");
|
|
}
|
|
if(!is_recording) {
|
|
return;
|
|
}
|
|
LogHpi(HPI_InStreamStop(NULL,hpi_stream),__LINE__);
|
|
tickClock();
|
|
LogHpi(HPI_InStreamGetInfoEx(NULL,hpi_stream,&state,&buffer_size,
|
|
&data_recorded,&samples_recorded,&reserved),
|
|
__LINE__);
|
|
is_recording=false;
|
|
is_paused=true;
|
|
LogHpi(HPI_InStreamStart(NULL,hpi_stream),__LINE__);
|
|
emit paused();
|
|
emit stateChanged(card_number,stream_number,2); // Paused
|
|
if(debug) {
|
|
printf("RDHPIRecordStream: emitted paused()\n");
|
|
printf("RDHPIRecordStream: emitted stateChanged(%d,%d,RDHPIRecordStream::Paused)\n",card_number,stream_number);
|
|
}
|
|
}
|
|
|
|
|
|
void RDHPIRecordStream::stop()
|
|
{
|
|
if(debug) {
|
|
printf("RDHPIRecordStream: received stop()\n");
|
|
}
|
|
if(is_ready|is_recording|is_paused) {
|
|
LogHpi(HPI_InStreamStop(NULL,hpi_stream),__LINE__);
|
|
tickClock();
|
|
clock->stop();
|
|
is_recording=false;
|
|
is_paused=false;
|
|
is_ready=false;
|
|
if(pdata!=NULL) {
|
|
delete pdata;
|
|
pdata=NULL;
|
|
}
|
|
emit isStopped(true);
|
|
emit stopped();
|
|
emit stateChanged(card_number,stream_number,RDHPIRecordStream::Stopped);
|
|
emit position(0);
|
|
if(debug) {
|
|
printf("RDHPIRecordStream: emitted isStopped(true)\n");
|
|
printf("RDHPIRecordStream: emitted stopped()\n");
|
|
printf("RDHPIRecordStream: emitted stateChanged(%d,%d,RDHPIRecordStream::Stopped)\n",card_number,stream_number);
|
|
printf("RDHPIRecordStream: emitted position(0)\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void RDHPIRecordStream::setInputVOX(int gain)
|
|
{
|
|
sound_card->setInputStreamVOX(card_number,stream_number,gain);
|
|
}
|
|
|
|
|
|
void RDHPIRecordStream::setRecordLength(int length)
|
|
{
|
|
record_length=length;
|
|
}
|
|
|
|
|
|
void RDHPIRecordStream::tickClock()
|
|
{
|
|
LogHpi(HPI_InStreamGetInfoEx(NULL,hpi_stream,
|
|
&state,&buffer_size,&data_recorded,
|
|
&samples_recorded,&reserved),__LINE__);
|
|
if((!record_started)&&(is_recording)) {
|
|
if(samples_recorded>0) {
|
|
if(record_length>0) {
|
|
length_timer->start(record_length,true);
|
|
}
|
|
emit recordStart();
|
|
emit stateChanged(card_number,stream_number,4); // RecordStarted
|
|
if(debug) {
|
|
printf("RDHPIRecordStream: emitted recordStart()\n");
|
|
printf("RDHPIRecordStream: emitted stateChanged(%d,%d,RDHPIRecordStream::RecordStarted)\n",card_number,stream_number);
|
|
}
|
|
record_started=true;
|
|
}
|
|
}
|
|
while(data_recorded>fragment_size) {
|
|
#if HPI_VER > 0x00030500
|
|
LogHpi(HPI_InStreamReadBuf(NULL,hpi_stream,pdata,fragment_size),__LINE__);
|
|
#else
|
|
LogHpi(HPI_InStreamRead(NULL,hpi_stream,&hpi_data),__LINE__);
|
|
#endif
|
|
if(is_recording) {
|
|
writeWave(pdata,fragment_size);
|
|
}
|
|
LogHpi(HPI_InStreamGetInfoEx(NULL,hpi_stream,&state,&buffer_size,
|
|
&data_recorded,&samples_recorded,&reserved),
|
|
__LINE__);
|
|
}
|
|
if(state==HPI_STATE_STOPPED) {
|
|
#if HPI_VER > 0x00030500
|
|
LogHpi(HPI_InStreamReadBuf(NULL,hpi_stream,pdata,data_recorded),__LINE__);
|
|
#else
|
|
LogHpi(HPI_DataCreate(&hpi_data,&format,pdata,data_recorded),__LINE__);
|
|
LogHpi(HPI_InStreamRead(NULL,hpi_stream,&hpi_data),__LINE__);
|
|
#endif
|
|
if(is_recording) {
|
|
writeWave(pdata,data_recorded);
|
|
}
|
|
}
|
|
emit position(samples_recorded);
|
|
if(debug) {
|
|
printf("RDHPIRecordStream: emitted position(%u)\n",
|
|
(unsigned)samples_recorded);
|
|
}
|
|
}
|
|
|
|
|
|
bool RDHPIRecordStream::GetStream()
|
|
{
|
|
hpi_err_t hpi_err;
|
|
char hpi_text[100];
|
|
|
|
if((hpi_err=
|
|
LogHpi(HPI_InStreamOpen(NULL,card_index[card_number],stream_number,
|
|
&hpi_stream),__LINE__))!=0) {
|
|
if(debug) {
|
|
HPI_GetErrorText(hpi_err,hpi_text);
|
|
fprintf(stderr,"*** HPI Error: %s ***\n",hpi_text);
|
|
}
|
|
return false;
|
|
}
|
|
if(HPI_InStreamHostBufferAllocate(NULL,hpi_stream,dma_buffer_size));
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void RDHPIRecordStream::FreeStream()
|
|
{
|
|
if(HPI_InStreamHostBufferFree(NULL,hpi_stream));
|
|
LogHpi(HPI_InStreamClose(NULL,hpi_stream),__LINE__);
|
|
}
|
|
|
|
|
|
hpi_err_t RDHPIRecordStream::LogHpi(hpi_err_t err,int lineno)
|
|
{
|
|
char err_txt[200];
|
|
|
|
if(err!=0) {
|
|
HPI_GetErrorText(err,err_txt);
|
|
RDApplication::syslog(sound_card->config(),LOG_WARNING,
|
|
"HPI Error: %s, %s line %d",err_txt,__FILE__,lineno);
|
|
}
|
|
return err;
|
|
}
|