/* Copyright (C) 2015 J.F.Dockes
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "fiforeader.h"
#include <iostream>
#include <string>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include "log.h"
#include "audioutil.h"
using namespace std;
FifoReader::FifoReader(const string& fn, int sampleRate, int bitsPerSample,
int chans, bool needswap, bool blocking)
: m_fn(fn), m_needswap(needswap), m_blocking(blocking),
m_fd(-1), m_tmpbuf(0), m_tmpbufsize(0)
{
setAudioParams(sampleRate, bitsPerSample, chans);
}
FifoReader::~FifoReader()
{
if (m_fn.compare("stdin") && m_fd >= 0)
::close(m_fd);
if (m_tmpbuf)
free(m_tmpbuf);
}
bool FifoReader::open()
{
LOGDEB("FifoReader::open: blocking: " << m_blocking << endl);
if (m_fn.compare("stdin")) {
int flags = m_blocking ? O_RDONLY : O_RDONLY|O_NONBLOCK;
if ((m_fd = ::open(m_fn.c_str(), flags)) < 0) {
LOGERR("open() errno " << errno << " on " << m_fn << endl);
return false;
}
} else {
m_fd = 0;
if (!m_blocking) {
fcntl(m_fd, F_SETFL, O_NONBLOCK);
}
}
return true;
}
void FifoReader::close()
{
LOGDEB("FifoReader::close" << endl);
if (m_fd > 0) {
::close(m_fd);
m_fd = -1;
}
}
const unsigned char *FifoReader::data(size_t size, ssize_t &nread)
{
if (m_fd < 0) // nothing to read from
return 0;
nread = 0;
//LOGDEB("FifoReader: data " << size << " bytes. blocking " << m_blocking
// << endl);
if (m_tmpbufsize < size) {
m_tmpbuf = (unsigned char *)realloc(m_tmpbuf, size);
m_tmpbufsize = size;
}
if (m_blocking) {
size_t remaining = size;
while (remaining) {
ssize_t nread = read(m_fd, m_tmpbuf + size - remaining, remaining);
if (nread <= 0) {
LOGERR("FifoReader::read: ret " << nread << " errno " <<
errno << " : " << strerror(errno) << endl);
return 0;
} else {
remaining -= nread;
}
}
} else {
nread = read(m_fd, m_tmpbuf, size);
if (nread == -1) {
if (errno == EAGAIN)
return m_tmpbuf;
LOGERR("FifoReader::read: ret " << nread << " errno " <<
errno << " : " << strerror(errno) << endl);
return 0;
} else if (size - (size_t)nread > 0) {
LOGDEB("FifoReader::data: inserting " << size - nread <<
" bytes\n");
memset(m_tmpbuf + nread, 0, size - nread);
}
}
if (m_needswap)
swapSamples(m_tmpbuf, bytesPerSample(), m_tmpbufsize / bytesPerSample());
//LOGDEB("FifoReader: data done" << endl);
return m_tmpbuf;
}