- Moved all settings to settings class. Singleton in settings class.

- New socketClosed function on OlaThread to handle olad closing
- Added some doc
This commit is contained in:
santi 2014-09-22 20:19:49 +02:00
parent fc1eda5ae9
commit 1b7664edaf
11 changed files with 278 additions and 152 deletions

View file

@ -4,7 +4,7 @@ AudioWidget::AudioWidget(QWidget *parent) :
QWidget(parent)
{
layout = new QHBoxLayout();
for (int i= 0; i < LAYERS_NUMBER; i++ ) {
for (int i= 0; i < Settings::getInstance()->getLayersNumber(); i++ ) {
// Conectar los slots
layout->insertWidget(i, new AudioLayerWidget(this, tr("Layer %1").arg(i)));
}

View file

@ -7,6 +7,7 @@
#include "audiomasterwidget.h"
#include "audiolayerwidget.h"
#include "defines.h"
#include "settings.h"
#include "SFML/Audio/SoundSource.hpp"

View file

@ -65,10 +65,6 @@ libreMediaServerAudio::libreMediaServerAudio(QStringList args, QWidget *parent)
aw = new AudioWidget(this);
setCentralWidget(aw);
// Inicia la lectur de datos DMX
ola->blockSignals(true);
ola->start(QThread::TimeCriticalPriority );
// Inicia el widget Master.
amw = new AudioMasterWidget(this);
QDockWidget *topWidget = new QDockWidget(tr("Master"), this);
@ -82,17 +78,17 @@ libreMediaServerAudio::libreMediaServerAudio(QStringList args, QWidget *parent)
connect(ui.actionChange_Media_Path, SIGNAL(triggered()), this, SLOT(ChangeMediaPath()));
connect(ui.actionLaunch_OLA_Setup, SIGNAL(triggered()), this, SLOT(olasetup()));
Settings *set = new Settings();
connect(set, SIGNAL( layersNumber(int)),
ola, SLOT( setLayersNumber(int)));
connect(set, SIGNAL( DMXConf(dmxSetting ) ),
ola, SLOT( setDMXConf(dmxSetting) ) );
connect(Settings::getInstance(), SIGNAL( registerUniverse(int) ),
ola, SLOT( registerUniverse(int) ) );
ola->registerUniverse(); // register now all the universes
ola->blockSignals(true);
connect(ola, SIGNAL (layerReceived()),
amw, SLOT(updateWatchDMX()));
// Lee la configuración por defecto
set->readDefaultFile();
// Inicia la mediaLibrary
MediaLibrary::getInstance()->initMediaLibrary();
// Inicia la lectura de datos DMX
ola->start(QThread::TimeCriticalPriority );
ola->blockSignals(false);
connect(ola, SIGNAL( dmxOutput(int, int, int) ),
this, SLOT( dmxInput(int, int, int) ) );
@ -151,7 +147,7 @@ void libreMediaServerAudio::ChangeMediaPath()
return;
fileNames = dialog.selectedFiles();
QString file = fileNames.at(0);
MediaLibrary::getInstance()->setPath(file);
Settings::getInstance()->setPathMedia(file);
QString desc = tr("Media Path Changed to: %1").arg(m_pathmedia);
qDebug(desc.toLatin1().constData());
}

View file

@ -3,8 +3,8 @@ TARGET = libremediaserver-audio
QT += webkitwidgets widgets
CONFIG += release
DESTDIR = ./release
CONFIG += debug
DESTDIR = ./debug
HEADERS += libremediaserver-audio.h \
medialibrary.h \

View file

@ -16,7 +16,7 @@ MediaLibrary *MediaLibrary::getInstance() {
MediaLibrary::MediaLibrary(QObject *parent) :
QObject(parent)
{
initMediaLibrary();
// initMediaLibrary();
// qDebug("Init MediaLibrary");
}
@ -26,8 +26,8 @@ MediaLibrary::MediaLibrary(QObject *parent) :
void MediaLibrary::initMediaLibrary() {
QDir dir;
if (!dir.cd(m_pathmedia)) {
qWarning("Can not cd to the path: %s", m_pathmedia.toLatin1().constData());
if (!dir.cd(Settings::getInstance()->getPathMedia())) {
qWarning("Can not cd to the path: %s", Settings::getInstance()->getPathMedia().toLatin1().constData());
return;
}
m_media = new QList<MediaFolder>;

View file

@ -5,38 +5,41 @@
#include <QDir>
#include "defines.h"
#include "settings.h"
class MediaLibrary : public QObject
{
Q_OBJECT
friend class Settings;
public:
static MediaLibrary *getInstance();
inline void setPath(QString path) { m_pathmedia = path; rescanMediaLibrary();}
QString requestNewFile(int folder, int layer);
void initMediaLibrary();
protected:
/**
* Change library/path
*/
inline void rescanMediaLibrary() {
if (m_media != NULL)
delete m_media;
initMediaLibrary();
}
private:
explicit MediaLibrary(QObject *parent = 0);
static MediaLibrary *_instance;
inline QString getPath () { return m_pathmedia; } // Get the path to the medias folder tree.
inline void deleteMediaLibrary() { delete m_media; m_media = NULL; }
/**
* Change library/path
*/
inline void rescanMediaLibrary() {
deleteMediaLibrary();
initMediaLibrary();
}
// Wich structure is more efficient for us?
// QList, QMap, QSet, QVector?
QList<MediaFolder> *m_media; // Library to save the folders/media libraries and index each media file inside
QString m_pathmedia; // Path to Medias
void initMediaLibrary();
/** Called when there is a change in the channels folder or file
* this is called. Creates a new source.
*/
QList<MediaFile> getMediaInformation(QDir dir); // Get all the information of each media file in a dir
signals:

View file

@ -5,23 +5,17 @@
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;
// Init the dmx buffer to 0
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;
}
}
init();
}
// --- DECONSTRUCTOR ---
@ -29,9 +23,6 @@ olaThread::~olaThread() {
stop();
}
/** Open the connection with olad and start processing data.
*/
// set up ola connection
void olaThread::init()
{
if (ola::InitLogging(ola::OLA_LOG_INFO , ola::OLA_LOG_STDERR)) {
@ -45,49 +36,30 @@ void olaThread::init()
m_client = m_clientWrapper->GetClient();
m_client->SetDMXCallback(ola::NewCallback(this, &olaThread::NewDmx));
m_clientWrapper->GetSelectServer()->RegisterRepeatingTimeout(4000, ola::NewCallback(this, &olaThread::CheckDataLoss));
// qDebug() << "Init olaThread";
m_client->SetCloseHandler(ola::NewSingleCallback(this, &olaThread::socketClosed));
}
void olaThread::run()
{
// qDebug() << tr("olaThread| Running");
emit toTerminal("Reading DMX");
emit toTerminal("Start 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));
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_client = NULL;
m_clientWrapper = NULL;
m_client = 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)
{
@ -95,19 +67,18 @@ void olaThread::NewDmx(const ola::client::DMXMetadata &data,
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;
}
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;
}
}
}
}
}
}
}
/**
@ -129,45 +100,36 @@ bool olaThread::CheckDataLoss() {
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 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::setDMXConf(dmxSetting set)
{
if (set.layer >= m_layersNumber) { return; }
m_settings.replace(set.layer, set);
// registro del nuevo universo si no está registrado ya
if (!m_universe->contains(set.universe)) {
registerUniverse(set.universe);
m_universe->append(set.universe);
}
}
void olaThread::socketClosed()
{
qDebug("ola close the connection. Trying reopening it... ");
// is needed some cleaning?
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 the universes
registerUniverse(1);
// register all universes
registerUniverse();
// start the thread????
run();

View file

@ -16,6 +16,7 @@
#include "defines.h"
#include "dmxPersonality.h"
#include "settings.h"
class olaThread : public QThread
{
@ -31,7 +32,6 @@ public:
*@param int channel the channel for the value wanted
*@return int the value
*/
inline int getValue(int layer, int channel) {
return m_dmx[layer][channel];
}
@ -39,16 +39,8 @@ public:
/**
* @brief resendDMX emite todo el buffer DMX
*/
void resendDmx();
QList<dmxSetting> settings() const;
void setSettings(const QList<dmxSetting> &settings);
private:
void run ();
@ -57,21 +49,16 @@ private:
unsigned int m_counter;
struct timeval m_last_data; // Last DMX frame received
// DMX Conf
QList<int> *m_universe; // Registered universes.
int m_layersNumber; // Number of layers in wich divide the dmx frame. Each layer, one source.
int m_dmx[LAYERS_NUMBER][LAYER_CHANNELS]; // DMX Buffer. Habría que cambiarlo si queremos hacer las capas dinámicas
QList<dmxSetting> m_settings;
inline void registerUniverse(int universe) {
// void ola::client::OlaClient::RegisterUniverse(unsigned int universe,RegisterAction register_action,SetCallback * callback
m_client->RegisterUniverse(universe, ola::client::REGISTER,ola::NewSingleCallback(this, &olaThread::RegisterComplete));
}
/**
* Control de errores en el registro de Universos en OLA
* @brief Callback from ola. Control de errores en el registro de Universos en OLA
* typedef SingleUseCallback1<void, const Result&> ola::client::SetCallback
* @param ola::client::Result &error
* @return void
*
*
*/
// typedef SingleUseCallback1<void, const Result&> ola::client::SetCallback
inline void RegisterComplete(const ola::client::Result &error) {
if (error.Success()) {
// qDebug("Register Universe success");
@ -82,18 +69,58 @@ private:
}
}
/**
* @brief Check if the dmx info is arriving each 4 seconds
* @return bool
*/
bool CheckDataLoss();
// typedef Callback2<void, const DMXMetadata&, const DmxBuffer&> ola::client::RepeatableDMXCallback
void NewDmx(const ola::client::DMXMetadata &dmx_meta, const ola::DmxBuffer &buffer); // Callback from OlaCLient when there is new dmx info
/**
* @brief RepeteableDMXCallBack from ola called when arrives a new dmx frame
* typedef Callback2<void, const DMXMetadata&, const DmxBuffer&> ola::client::RepeatableDMXCallback
* 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.
*
*
*/
void NewDmx(const ola::client::DMXMetadata &dmx_meta, const ola::DmxBuffer &buffer); //
/**
* @brief Sometimes the ola server closes the connection. This is a callback to handle this event an reconect to ola
*
*
*/
void socketClosed();
void init();
/**
* @brief Open the connection with olad and start processing data.
*
*
*/
void init();
public slots:
void stop(); // Close the connection with olad.
void setLayersNumber(int layersNumber);
void setDMXConf(dmxSetting set);
/**
* @brief register one Universe
* void ola::client::OlaClient::RegisterUniverse(unsigned int universe,RegisterAction register_action,SetCallback * callback
* @param universe
*/
inline void registerUniverse(int universe) {
m_client->RegisterUniverse(universe, ola::client::REGISTER,ola::NewSingleCallback(this, &olaThread::RegisterComplete));
}
/**
* @brief Register all the universes again
*
*/
inline void registerUniverse() {
for (int universe = 0; universe < Settings::getInstance()->getUniverseNumber(); universe++) {
registerUniverse(universe);
}
}
protected slots:

View file

@ -1,9 +1,29 @@
#include "settings.h"
Settings *Settings::_instance = 0;
Settings *Settings::getInstance() {
if (_instance == 0) {
_instance = new Settings();
Q_CHECK_PTR(_instance);
}
return _instance;
}
void Settings::setPathMedia(QString path)
{
m_pathmedia = path;
MediaLibrary::getInstance()->rescanMediaLibrary();
m_layersNumber = 0;
}
Settings::Settings(QObject *parent) :
QObject(parent)
{
readDefaultFile();
// m_universe = new QSet<int>();
// m_settings = new QList<dmxSetting>();
readFile();
}
// Read the dmx settings for dmx.xml At the moment we need:
@ -16,9 +36,11 @@ void Settings::readFromFile(QString file) {
QFile* xmlFile = new QFile(file);
if (!xmlFile->open(QIODevice::ReadOnly | QIODevice::Text)) {
QMessageBox::critical(NULL,"Load XML File Problem",
QString("Couldn't open %1 to load settings for olaInterface").arg(file),
QString("Couldn't open %1 to load settings").arg(file),
QMessageBox::Ok);
return;
// Instead exit give the oportunity to load another file or define the settings
qCritical("Load XML File Problem");
exit(1);
}
QXmlStreamReader* xmlReader = new QXmlStreamReader(xmlFile);
int counter = 0;
@ -35,9 +57,8 @@ void Settings::readFromFile(QString file) {
if(xmlReader->name() == "dmxSettings") {
int version = xmlReader->attributes().value("fileVersion").toLocal8Bit().toInt();
if(version == 1) {
int layers = xmlReader->attributes().value("layersNumber").toLocal8Bit().toInt();
emit layersNumber(layers);
MediaLibrary::getInstance()->setPath (xmlReader->attributes().value("path").toLocal8Bit());
m_layersNumber = xmlReader->attributes().value("layersNumber").toLocal8Bit().toInt();
m_pathmedia = xmlReader->attributes().value("path").toLocal8Bit();
continue;
}
}
@ -48,11 +69,16 @@ void Settings::readFromFile(QString file) {
temp.address = xmlReader->attributes().value("dmx").toLocal8Bit().toInt() - 1;
temp.universe = xmlReader->attributes().value("universe").toLocal8Bit().toInt();
temp.layer = counter;
emit DMXConf(temp);
m_settings.append(temp);
if (!m_universe.contains(temp.universe)) {
m_universe.insert(temp.universe);
// emit registerUniverse(temp.universe);
}
}
counter++;
}
}
if(xmlReader->hasError()) {
QMessageBox::critical(NULL,"File xml Parse Error ", xmlReader->errorString(), QMessageBox::Ok);
}
@ -64,16 +90,13 @@ void Settings::readFromFile(QString file) {
delete xmlFile;
}
/** Read the default file
*
*/
void Settings::readDefaultFile() {
void Settings::readFile() {
readFromFile(DEFAULT_FILE);
}
/*
void Settings::writeFile(QString filename)
{
/* QFile* xmlFile = new QFile(filename);
QFile* xmlFile = new QFile(filename);
if (!xmlFile->open(QIODevice::ReadOnly | QIODevice::Text)) {
QMessageBox::critical(NULL,"Load XML File Problem",
QString("Couldn't open %1 to load settings for olaInterface").arg(file),
@ -92,5 +115,11 @@ void Settings::writeFile(QString filename)
stream.writeEndElement();
stream.writeEndDocument();
*/
}
void Settings::writeFile()
{
writeFile(DEFAULT_FILE);
}
*/

View file

@ -5,24 +5,132 @@
#include <QXmlStreamReader>
#include <QFile>
#include <QMessageBox>
#include <QSet>
#include "olathread.h"
//#include "olathread.h"
#include "medialibrary.h"
#include "defines.h"
/**
* This class stores the settings on lms.
* Is a singleton with set and get methods to manage the settings
* Also writes and reads the settings files.
*/
class Settings : public QObject
{
Q_OBJECT
public:
explicit Settings(QObject *parent = 0);
static Settings *getInstance(); //Singleton
/**
* @brief getUniverses
* @return
*/
inline QSet<int> getUniverses() { return m_universe; }
/**
* @brief getPathMedia
* @return
*/
inline QString getPathMedia() { return m_pathmedia; }
/**
* @brief setPathMedia
* @param path
*/
void setPathMedia(QString path);
/**
* @brief getDmxSettings
* @return
*/
inline QList<dmxSetting> getDmxSettings() { return m_settings; }
/**
* @brief getlayersNumber
* @return
*/
inline int getLayersNumber() { return m_layersNumber; }
inline int getUniverseNumber() { return m_universe.size(); }
private:
static Settings *_instance;
/** Constructor
*
*/
explicit Settings(QObject *parent = 0);
QSet<int> m_universe; // Registered universes.
int m_layersNumber; // Number of layers in wich divide the dmx frame. Each layer, one source.
/**
* @brief olaThread::setLayersNumber
* @param layersNumber
*
*/
inline void setLayersNumber(int layersNumber)
{
if (layersNumber <= LAYERS_NUMBER)
m_layersNumber = layersNumber;
else
m_layersNumber = LAYERS_NUMBER;
}
// The list where we store the settings by layer
QList<dmxSetting> m_settings;
// The path to media library
QString m_pathmedia;
/**
* @brief readFromFile
* @param file
*/
void readFromFile(QString file);
void readDefaultFile();
void writeFile(QString filename);
/**
* @brief readDefaultFile
*/
void readFile();
/**
* @brief writeFile
* @param filename
*/
// void writeFile(QString filename); // Not implemented yet
/**
* @brief writeFile
* overload
*/
// void writeFile(); // Not implemented yet
signals:
/**
* @brief pathChanged
* @param path
*/
void pathChanged(QString path);
/**
* @brief layersNumber
* @param number
*/
void layersNumber(int number);
void DMXConf(dmxSetting universe);
/**
* @brief DMXConf
* @param universe
*/
void registerUniverse(int universe);
public slots:

View file

@ -20,7 +20,7 @@ void SettingsDialog::ChangeMediaPath()
return;
fileNames = dialog.selectedFiles();
QString file = fileNames.at(0);
MediaLibrary::getInstance()->setPath(file);
// MediaLibrary::getInstance()->setPath(file);
QString desc = tr("Media Path Changed to: %1").arg(file);
qDebug(desc.toLatin1().constData());
}