/* 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)
{
setAudioParams(sampleRate, bitsPerSample, chans);
}
FifoReader::~FifoReader()
{
LOGDEB1("FifoReader::~FifoReader\n");
if (m_fn.compare("stdin") && m_fd >= 0)
::close(m_fd);
if (m_tmpbuf)
free(m_tmpbuf);
}
bool FifoReader::open()
{
LOGDEB1("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()
{
LOGDEB1("FifoReader::close" << endl);
if (m_fd > 0) {
::close(m_fd);
m_fd = -1;
}
}
const unsigned char *FifoReader::data(size_t size, ssize_t &nread)
{
nread = 0;
if (m_fd < 0) {
LOGERR("FifoReader::data: not open\n");
return nullptr;
}
LOGDEB1("FifoReader::data: cnt "<<size<< " blocking " << m_blocking<<endl);
if (m_tmpbufsize < size) {
m_tmpbuf = (unsigned char *)realloc(m_tmpbuf, size);
if (nullptr == m_tmpbuf) {
LOGERR("FifoReader::data: could not alloc " << size << " bytes\n");
return nullptr;
}
m_tmpbufsize = size;
}
if (m_blocking) {
size_t remaining = size;
while (remaining) {
ssize_t cnt = read(m_fd, m_tmpbuf + size - remaining, remaining);
if (cnt <= 0) {
LOGERR("FifoReader::data: read ret " << nread << " errno " <<
errno << " : " << strerror(errno) << endl);
return nullptr;
} else {
remaining -= cnt;
nread += cnt;
}
}
} else {
nread = read(m_fd, m_tmpbuf, size);
if (nread == -1) {
if (errno == EAGAIN)
return m_tmpbuf;
LOGERR("FifoReader::data: read ret " << nread << " errno " <<
errno << " : " << strerror(errno) << endl);
return nullptr;
}
}
LOGDEB1("FifoReader: data() done. nread " << nread << endl);
return m_tmpbuf;
}