lms-audio/src/olathread.cpp
2014-09-24 13:50:33 +02:00

141 lines
4.3 KiB
C++

#include "olathread.h"
#include <ola/Callback.h>
olaThread::olaThread(QObject *parent)
{
Q_UNUSED(parent);
m_counter = 0;
gettimeofday(&m_last_data, NULL);
// Init the dmx buffer to 0
for (int i=0; i < LAYERS_NUMBER; i++)
{
for (int j=0; j < LAYER_CHANNELS; j++)
{
m_dmx[i][j] = 0;
}
}
init(); // start the ola connection
}
// --- DECONSTRUCTOR ---
olaThread::~olaThread() {
stop();
}
void olaThread::init()
{
if (ola::InitLogging(ola::OLA_LOG_INFO , ola::OLA_LOG_STDERR)) {
qDebug() << "ola logging debug working";
} else {
qWarning() << "Can not init ola logging";
}
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();
m_client->SetDMXCallback(ola::NewCallback(this, &olaThread::NewDmx));
m_clientWrapper->GetSelectServer()->RegisterRepeatingTimeout(4000, ola::NewCallback(this, &olaThread::CheckDataLoss));
m_client->SetCloseHandler(ola::NewSingleCallback(this, &olaThread::socketClosed));
}
void olaThread::run()
{
emit toTerminal("Start reading DMX");
m_clientWrapper->GetSelectServer()->Run();
}
void olaThread::stop()
{
if (m_clientWrapper != NULL)
{
QSet<int> temp = Settings::getInstance()->getUniverses();
foreach (const int &i, temp) {
m_client->RegisterUniverse(i, ola::client::UNREGISTER, ola::NewSingleCallback(this, &olaThread::RegisterComplete));
}
m_clientWrapper->GetSelectServer()->Terminate();
m_clientWrapper = NULL;
m_client = NULL;
}
}
// 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
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();
foreach (const dmxSetting &i, Settings::getInstance()->getDmxSettings()) { // loop for reading the channels by layer.
if(i.universe == universe && i.address > -1) { // Compare if the layer is from this universe AND if the DMX address is 0 or greater, process this layer.
for (int j = 0; j < LAYER_CHANNELS; j++){
int value = buffer.Get((i.address) + j); // Get the value for this channel.
if (m_dmx[i.layer][j] != value) { // Compare the new value with the old value.
emit dmxOutput(i.layer,j,value);
m_dmx[i.layer][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::resendDmx()
{
// qDebug() << "Resending DMX info";
for (int i = 0; i < Settings::getInstance()->getLayersNumber(); 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::socketClosed()
{
qWarning("ola close the connection. Trying reopening it... ");
emit toTerminal("OLA closed the connection. Tryin reopening it... ");
// Qúe limpiamos? todo? el thread?
if (!m_client->Stop())
{
qWarning("Can not stop the ola client");
}
m_clientWrapper->GetSelectServer()->Terminate();
delete m_client;
m_client = NULL;
delete m_clientWrapper;
m_clientWrapper = NULL;
// set up ola connection
init();
// register all universes
registerUniverse();
// start the thread????
run();
}
////////////////////////////////////////////////////////////////////////////////////////////