lms-audio/src/olathread.cpp
2014-08-13 22:51:25 +02:00

158 lines
5 KiB
C++

#include "olathread.h"
olaThread::olaThread(QObject *parent)
{
Q_UNUSED(parent);
m_universe = new QList<int>();
m_counter = 0;
gettimeofday(&m_last_data, NULL);
dmxSetting newsetting;
newsetting.address = -1;
newsetting.universe = -1;
newsetting.updated = false;
m_layersNumber = LAYERS_NUMBER;
for (int i=0; i < LAYERS_NUMBER; i++)
{
newsetting.layer = i;
m_settings.append(newsetting);
for (int j=0; j < LAYER_CHANNELS; j++)
{
m_dmx[i][j] = 0;
}
}
// set up ola connection
m_clientWrapper = new ola::client::OlaClientWrapper;
Q_CHECK_PTR(m_clientWrapper);
if (!m_clientWrapper->Setup()) { qErrnoWarning("olaThread::olaStart| Failed Setup() in Client Wrapper"); }
m_client = m_clientWrapper->GetClient();
if (ola::InitLogging(ola::OLA_LOG_INFO , ola::OLA_LOG_STDERR)) {
qDebug() << "ola logging debug working";
} else {
qWarning() << "Can not init ola logging";
}
m_client->SetDMXCallback(ola::NewCallback(this, &olaThread::NewDmx));
m_clientWrapper->GetSelectServer()->RegisterRepeatingTimeout(4000, ola::NewCallback(this, &olaThread::CheckDataLoss));
// qDebug() << "Init olaThread";
}
// --- DECONSTRUCTOR ---
olaThread::~olaThread() {
stop();
}
/** Open the connection with olad and start processing data.
*/
void olaThread::run()
{
// qDebug() << tr("olaThread| Running");
emit toTerminal("Reading DMX");
m_clientWrapper->GetSelectServer()->Run();
}
QList<dmxSetting> olaThread::settings() const
{
return m_settings;
}
void olaThread::setSettings(const QList<dmxSetting> &settings)
{
m_settings = settings;
}
void olaThread::stop()
{
if (m_clientWrapper != NULL)
{
for (int i = 0; i < m_universe->size(); i++) {
m_client->RegisterUniverse(m_universe->at(i), ola::client::UNREGISTER, ola::NewSingleCallback(this, &olaThread::RegisterComplete));
}
m_clientWrapper->GetSelectServer()->Terminate();
m_client = NULL;
m_clientWrapper = NULL;
}
}
/**
* RepeteableDMXCallBack
* Callback2<void, const DMXMetada&, const DmxBuffer&>
* from OLA daemon when there is new DMX data. This is called one for second if there is not updated in the DMX frame. We need emit only the channels that
* has changed to save resources.
*/
// ToDo: It can be more efficient making the dmx buffer a DmxBuffer class instead a int array and compare with the new if there is changes at start. Also all access to the buffer it should be get/set. I should profile this
// typedef Callback2<void, const DMXMetadata&, const DmxBuffer&> ola::client::RepeatableDMXCallback
void olaThread::NewDmx(const ola::client::DMXMetadata &data,
const ola::DmxBuffer &buffer)
{
m_counter++;
gettimeofday(&m_last_data, NULL);
uint universe = data.universe;
emit layerReceived();
for (int i = 0; i < m_layersNumber; i++) { // loop for reading the channels by layer.
if(m_settings.at(i).universe == universe) { // Compare if the layer is from this universe
if ( m_settings.at(i).address > -1 ) { // AND if the DMX address is 0 or greater, process this layer.
for (int j = 0; j < LAYER_CHANNELS; j++){
int value = buffer.Get((m_settings.at(i).address) + j); // Get the value for this channel.
if (m_dmx[i][j] != value) { // Compare the new value with the old value.
emit dmxOutput(i,j,value);
m_dmx[i][j] = value;
}
}
}
}
}
}
/**
* Check for data loss each 4 seconds.
*/
bool olaThread::CheckDataLoss() {
struct timeval now, diff;
if (timerisset(&m_last_data)) {
gettimeofday(&now, NULL);
timersub(&now, &m_last_data, &diff);
if (diff.tv_sec > 4 || (diff.tv_sec == 4 && diff.tv_usec > 4000000)) {
// loss of data
qDebug()<< "olaThread| Can not read one or several universes";
emit toTerminal("olaThread: Can not read one universe");
// return false; // Retorna false para deshabilitar el callback
}
}
return true;
}
void olaThread::setLayersNumber(int layersNumber)
{
if (layersNumber <= LAYERS_NUMBER)
m_layersNumber = layersNumber;
else
m_layersNumber = LAYERS_NUMBER;
}
void olaThread::resendDmx()
{
// qDebug() << "Resending DMX info";
for (int i = 0; i < m_layersNumber; i++) { // loop for reading the channels by layer.
for (int j = 0; j < LAYER_CHANNELS; j++){
emit dmxOutput(i, j, m_dmx[i][j]); // Connected with dmx slot in olaInterface.
}
}
}
void olaThread::setDMXConf(dmxSetting set)
{
if (set.layer >= m_layersNumber) { return; }
m_settings.replace(set.layer, set);
// ToDo: registro del nuevo universo si no está registrado ya
if (!m_universe->contains(set.universe)) {
registerUniverse(set.universe);
m_universe->append(set.universe);
}
}
////////////////////////////////////////////////////////////////////////////////////////////