From 0e719d767b4b1dcda3b9347058ce379912379f83 Mon Sep 17 00:00:00 2001 From: carlou Date: Tue, 6 Sep 2016 08:43:48 +0200 Subject: [PATCH] Fixed server closing, added config file + doc --- MAKE-SERVER/be-server.pro | 9 +- doc/HOME.rst | 25 +++ doc/INTERACTION.rst | 100 ++++++++++++ doc/SETUP.rst | 65 ++++++++ src/PlayThread.cpp | 28 ++-- src/PlayThread.h | 10 +- src/SaveManager.cpp | 4 +- src/SerialManager.h | 3 +- src/Server.cpp | 331 ++++++++++++++++++++++++++------------ src/Server.h | 79 ++++++--- src/Track.cpp | 16 +- src/Track.h | 15 +- src/be-server.pro | 7 +- src/main.cpp | 20 ++- 14 files changed, 542 insertions(+), 170 deletions(-) create mode 100644 doc/HOME.rst create mode 100644 doc/INTERACTION.rst create mode 100644 doc/SETUP.rst diff --git a/MAKE-SERVER/be-server.pro b/MAKE-SERVER/be-server.pro index 8ada157..ed66b99 100644 --- a/MAKE-SERVER/be-server.pro +++ b/MAKE-SERVER/be-server.pro @@ -1,6 +1,7 @@ -QT += core gui serialport +QT += core serialport +QT -= gui -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets serialport +greaterThan(QT_MAJOR_VERSION, 4): QT += serialport TARGET = be-server TEMPLATE = app @@ -30,9 +31,7 @@ HEADERS += Server.h \ SaveManager.h \ SerialManager.h -FORMS += - -INCLUDEPATH += $$PWD/../deps/libwatermark +INCLUDEPATH += $$PWD/../deps/libwatermark DEPENDPATH += $$PWD/../deps/libwatermark INCLUDEPATH += /usr/include/oscpack/ /home/pi/boiteselec-interfaceqt/deps/rtaudio-4.1.2/ diff --git a/doc/HOME.rst b/doc/HOME.rst new file mode 100644 index 0000000..bcd73c3 --- /dev/null +++ b/doc/HOME.rst @@ -0,0 +1,25 @@ +=================== +Boîtes électriques +=================== + +Table of content +================ + +*HOME* + Presentation of the application + +*SETUP* + How to install and setup the server + +*INTERACTION* + How client and server interact with each other. + (Description of the protocol) + +General informations +==================== + +This documentation is formatted using the `reStructuredText `_ syntax, and is distributed under the Creative Commons BY-SA 4.0 license. + +The `RudeConfig™ Open Source C++ Config File Library `_ is written and distributed under the `GNU GPL v2 `_. + +The application itself is distributed under the `Zlib License `_. diff --git a/doc/INTERACTION.rst b/doc/INTERACTION.rst new file mode 100644 index 0000000..c60d926 --- /dev/null +++ b/doc/INTERACTION.rst @@ -0,0 +1,100 @@ +Interaction +=========== + +General informations +-------------------- + +To communicate, client and server use the OSC protocol. + +By default, the server uses the IP address ``192.170.0.1``, with the port ``9988`` to send messages and ``9989`` to receive them. + +Protocol +-------- + +**Note :** + ```` designate an integer value, ```` a string one, and ```` a boolean one. + +Server +~~~~~~ + +The server can receive the following messages from the client : + +``/box/update_threshold `` + Change the threshold value to ````. + +``/box/reset_threshold `` + Reset the threshold to its default value. + +``/box/enable `` + Switch the track number ````'s state (activate or deactivate it). + +``/box/volume `` + Change the track number ````'s volume value to ````. + +``/box/pan `` + Change the track number ````'s pan value to ````. + +``/box/mute `` + Mute (```` = ``true``) or unmute (``false``) the track number ````. + +``/box/solo `` + "Solo" (```` = ``true``) or "unsolo" (``false``) the track number ````. + +``/box/master `` + Change the master volume value to ````. + +``/box/play `` + Play the song + +``/box/stop `` + Stop the song + +``/box/reset `` + Stop the song and reset its options to their default values + +``/box/refresh_song `` + Refresh the song's informations + +``/box/select_song `` + Select another song + +``/box/sync `` + Send the informations of the actual song and the current state of the player to the client + +Client +~~~~~~ + +The client can receive the following messages from the server to access its informations : + +``/box/beat `` + The actual server's beat count value = ````. + +``/box/enable_out `` + The box number ```` has been activated. + +``/box/enable_sync `` + The numbers of the activated tracks, where ```` is a binary number indicating them. + For example, for an 8-tracks song with its 2nd, 4th, 5th and 8th tracks activated, ```` = 10011010. + +``/box/play `` + The selected song started playing (and that its tempo's value is ````). + +``/box/ready `` + The selected song is (```` = ``true``) or not (``false``) loaded and ready to be played. + +``/box/sensor `` + The actual server's threshold value = ````. + +``/box/songs_list `` + The available songs list = ````. + ```` is the concatenation of the songs' filenames, separated by the character ``|``. + +``/box/title `` + The actual server song's name is ````. + +``/box/tracks_count `` + The selected song's tracks count is ````. + +``/box/tracks_list `` + Send the informations of the selected song's tracks, as ````. + ``` is the concatenation of the songs' tracks' names, separated by the character ``|``. diff --git a/doc/SETUP.rst b/doc/SETUP.rst new file mode 100644 index 0000000..d6df819 --- /dev/null +++ b/doc/SETUP.rst @@ -0,0 +1,65 @@ +Setup +===== + +Installation +------------ + +Configuration +------------- + +General informations +~~~~~~~~~~~~~~~~~~~~ + +The server's configuration is saved in the ``config.txt`` file in the same folder as the executable. +This file is formatted with the (almost) standard `INI file format `_. + +The following options are available : + +``[default]`` section +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``threshold`` + Default threshold's value (integer) + Default : 200 + +``master`` + Default master volume's value (integer) + Default : 50 + +``volume`` + Default track's volume (integer) + Default : 50 + +``pan`` + Default track's pan (integer) + Default : 0 + +``activation`` + Default track's activation status (boolean : true or false) + Default : false + +``[files]`` section +~~~~~~~~~~~~~~~~~~~ + +``export_folder`` + Files save/load folder (string : path, ending with '/') + Default : /home/pi/songs/ + +``extension`` + Songs files' extension (string : '*.') + Default : *.song + +``[osc]`` section +~~~~~~~~~~~~~~~~~ + +``ip`` + Client's OSC IP address (integer) + Default : 192.170.0.17 + +``receiver`` + Server's OSC receiver port (integer) + Default : 9988 + +``sender`` + Server's OSC sender port (integer) + Default : 9989 diff --git a/src/PlayThread.cpp b/src/PlayThread.cpp index dc68c14..3f73e80 100644 --- a/src/PlayThread.cpp +++ b/src/PlayThread.cpp @@ -12,8 +12,12 @@ #include #include -PlayThread::PlayThread() : - QThread(0) { +PlayThread::PlayThread(QSettings* c) : + QThread(0), options(c) { + + options->beginGroup("default"); + setThreshold(options->value("threshold").toInt()); + options->endGroup(); } unsigned int PlayThread::getTracksCount() const { @@ -70,10 +74,12 @@ void PlayThread::timeHandle() { } void PlayThread::stop() { - manager->stop(); - manager->input()->reset(); - bufferCount = 0; - isPlaying = false; + if(this->isRunning()){ + manager->stop(); + manager->input()->reset(); + bufferCount = 0; + isPlaying = false; + } } bool PlayThread::isStopped() const { @@ -81,7 +87,9 @@ bool PlayThread::isStopped() const { } void PlayThread::reset() { - setMasterVolume(DEFAULT_MASTER_VOLUME); + options->beginGroup("default"); + setMasterVolume(options->value("master").toInt()); + options->endGroup(); for(int i=0; ireset(); @@ -122,7 +130,9 @@ void PlayThread::setThreshold(const unsigned int threshold){ } void PlayThread::resetThreshold() { - setThreshold(DEFAULT_THRESHOLD); + options->beginGroup("default"); + setThreshold(options->value("threshold").toInt()); + options->endGroup(); } void PlayThread::load(const SongData& s) { @@ -140,7 +150,7 @@ void PlayThread::load(const SongData& s) { #pragma omp parallel for for(int i = 0; i < track_count; i++) { - Track* t = new Track(s.tracks[i], conf, i); + Track* t = new Track(s.tracks[i], conf, options, i); connect(t, &Track::onActivationSwitch, this, &PlayThread::onEnablementChanged); tracks[i] = t; diff --git a/src/PlayThread.h b/src/PlayThread.h index b60280d..bd53080 100644 --- a/src/PlayThread.h +++ b/src/PlayThread.h @@ -10,6 +10,7 @@ #include "Track.h" #include +#include #include #include #include @@ -25,10 +26,6 @@ template class StreamingManager; - -#define DEFAULT_THRESHOLD 200 /*< Default raw threshold value */ -#define DEFAULT_MASTER_VOLUME 50 /*< Default master volume value */ - /** * @brief The PlayThread class * @@ -37,7 +34,7 @@ class StreamingManager; class PlayThread : public QThread { Q_OBJECT public: - explicit PlayThread(); + explicit PlayThread(QSettings*); /** * @brief Give the number of the song's tracks @@ -178,6 +175,7 @@ public slots: void load(const SongData& s); private: + QSettings* options; Parameters conf; /*< Configuration data */ std::shared_ptr> masterVolume {new Amplify(conf)}; std::shared_ptr> manager; @@ -188,7 +186,7 @@ public slots: int maxBufferCount {}; /*< Total buffer count in a loop */ bool isPlaying {false}; - int m_threshold {DEFAULT_THRESHOLD}; + int m_threshold; /** * @brief Check if a given track exists diff --git a/src/SaveManager.cpp b/src/SaveManager.cpp index 9e142e7..0d56127 100644 --- a/src/SaveManager.cpp +++ b/src/SaveManager.cpp @@ -85,8 +85,8 @@ void SaveManager::save(const QString savepath, Server* manager) { int count = settings.value("General/trackCount").toInt(); for(int i = 0; i < count; ++ i) { - settings.setValue(QString("Track%1/volume").arg(i), manager->player.getTrack(i)->getVolume()); - settings.setValue(QString("Track%1/pan").arg(i), manager->player.getTrack(i)->getPan()); + settings.setValue(QString("Track%1/volume").arg(i), manager->player->getTrack(i)->getVolume()); + settings.setValue(QString("Track%1/pan").arg(i), manager->player->getTrack(i)->getPan()); } settings.sync(); diff --git a/src/SerialManager.h b/src/SerialManager.h index 26e83b1..ff40575 100644 --- a/src/SerialManager.h +++ b/src/SerialManager.h @@ -10,7 +10,8 @@ #include #include #include -#include //#include +#include +#include #include #include diff --git a/src/Server.cpp b/src/Server.cpp index 5f3efc3..6b46bf2 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -8,22 +8,55 @@ #include #include -Server::Server() { +//#define CONFIG_FILE "~/.config/Boites Electriques/config.txt" +#define COMPANY_NAME "Rock & Chanson" +#define APP_NAME "Boites Electriques" - connect(&player, &PlayThread::muteChanged, - &player, &PlayThread::setMute); +#define DEFAULT_EXTENSION "*.song" /*< Song files extension */ +#define DEFAULT_FOLDER "/home/pi/songs/" /*< Files save/load folder*/ + +#define DEFAULT_IP "192.170.0.17" +#define DEFAULT_SENDER 9989 +#define DEFAULT_RECEIVER 9988 + +#define DEFAULT_THRESHOLD 50 /*< Default threshold value */ +#define DEFAULT_MASTER_VOLUME 50 /*< Default master volume value */ + +#define DEFAULT_VOLUME 50 +#define DEFAULT_PAN 0 +#define DEFAULT_ACTIVATION false + +Server::Server(int& argc, char *argv[]): + QCoreApplication(argc, argv){ + + options = new QSettings(QSettings::IniFormat, QSettings::UserScope, + COMPANY_NAME, APP_NAME); + initConf(options); + qDebug() << options->fileName(); + + player = new PlayThread(options); + + options->beginGroup("osc"); + receiver = new OscReceiver(options->value("receiver").toInt()); + sender = new OscSender(options->value("ip").toString().toStdString(), + options->value("sender").toInt()); + + options->endGroup(); + + connect(player, &PlayThread::muteChanged, + player, &PlayThread::setMute); connect(this, &Server::updateThreshold, - &player, &PlayThread::setThreshold); + player, &PlayThread::setThreshold); connect(this, &Server::resetThreshold, - &player, &PlayThread::resetThreshold); + player, &PlayThread::resetThreshold); - connect(&player, &PlayThread::actualBeatChanged, + connect(player, &PlayThread::actualBeatChanged, this, &Server::updateBeat); - connect(&player, &PlayThread::beatCountChanged, + connect(player, &PlayThread::beatCountChanged, this, &Server::updateBeatCount); - connect(&player, &PlayThread::songLoaded, + connect(player, &PlayThread::songLoaded, this, &Server::onSongLoaded); connect(&saveManager, &SaveManager::updatedTracksList, this, &Server::updateTrackList); @@ -36,55 +69,80 @@ Server::Server() { serialManager.start(); //Client events - receiver.addHandler("/box/update_threshold", - std::bind(&Server::handle__box_updateThreshold, - this, std::placeholders::_1)); - receiver.addHandler("/box/reset_threshold", - std::bind(&Server::handle__box_resetThreshold, - this, std::placeholders::_1)); - receiver.addHandler("/box/enable", - std::bind(&Server::handle__box_enable, - this, std::placeholders::_1)); - receiver.addHandler("/box/volume", - std::bind(&Server::handle__box_volume, - this, std::placeholders::_1)); - receiver.addHandler("/box/pan", - std::bind(&Server::handle__box_pan, - this, std::placeholders::_1)); - receiver.addHandler("/box/mute", - std::bind(&Server::handle__box_mute, - this, std::placeholders::_1)); - receiver.addHandler("/box/solo", - std::bind(&Server::handle__box_solo, - this, std::placeholders::_1)); - receiver.addHandler("/box/master", - std::bind(&Server::handle__box_master, - this, std::placeholders::_1)); - receiver.addHandler("/box/play", - std::bind(&Server::handle__box_play, - this, std::placeholders::_1)); - receiver.addHandler("/box/stop", - std::bind(&Server::handle__box_stop, - this, std::placeholders::_1)); - receiver.addHandler("/box/reset", - std::bind(&Server::handle__box_reset, - this, std::placeholders::_1)); - receiver.addHandler("/box/refresh_song", - std::bind(&Server::handle__box_refreshSong, - this, std::placeholders::_1)); - receiver.addHandler("/box/select_song", - std::bind(&Server::handle__box_selectSong, - this, std::placeholders::_1)); - - receiver.run(); + receiver->addHandler("/box/update_threshold", + std::bind(&Server::handle__box_updateThreshold, + this, std::placeholders::_1)); + receiver->addHandler("/box/reset_threshold", + std::bind(&Server::handle__box_resetThreshold, + this, std::placeholders::_1)); + receiver->addHandler("/box/enable", + std::bind(&Server::handle__box_enable, + this, std::placeholders::_1)); + receiver->addHandler("/box/volume", + std::bind(&Server::handle__box_volume, + this, std::placeholders::_1)); + receiver->addHandler("/box/pan", + std::bind(&Server::handle__box_pan, + this, std::placeholders::_1)); + receiver->addHandler("/box/mute", + std::bind(&Server::handle__box_mute, + this, std::placeholders::_1)); + receiver->addHandler("/box/solo", + std::bind(&Server::handle__box_solo, + this, std::placeholders::_1)); + receiver->addHandler("/box/master", + std::bind(&Server::handle__box_master, + this, std::placeholders::_1)); + receiver->addHandler("/box/play", + std::bind(&Server::handle__box_play, + this, std::placeholders::_1)); + receiver->addHandler("/box/stop", + std::bind(&Server::handle__box_stop, + this, std::placeholders::_1)); + receiver->addHandler("/box/reset", + std::bind(&Server::handle__box_reset, + this, std::placeholders::_1)); + receiver->addHandler("/box/refresh_song", + std::bind(&Server::handle__box_refreshSong, + this, std::placeholders::_1)); + receiver->addHandler("/box/select_song", + std::bind(&Server::handle__box_selectSong, + this, std::placeholders::_1)); + receiver->addHandler("/box/sync", + std::bind(&Server::handle__box_sync, + this, std::placeholders::_1)); + + receiver->run(); } Server::~Server() { + qDebug() << "Quitting server..."; stop(); - player.wait(); + player->stop(); + qDebug() << "PlayThread stopping..."; + if(!player->wait(5000)) { + qWarning("PlayThread : Potential deadlock detected !! Terminating..."); + player->terminate(); + player->wait(5000); + player->exit(1); + } + qDebug() << "SerialManager stopping..."; serialManager.stop(); - serialManager.wait(); + if(!serialManager.wait(5000)) { + qWarning("SerialManager : Potential deadlock detected !! Terminating..."); + serialManager.terminate(); + serialManager.wait(5000); + serialManager.exit(1); + } + + qDebug() << "Deleting pointers..."; + delete player; + delete options; + + qDebug() << "Proper quitting OK"; + + QCoreApplication::quit(); } int Server::getTempo() const { @@ -92,19 +150,61 @@ int Server::getTempo() const { } unsigned int Server::getThreshold() const { - return 99 - (player.getThreshold()-100)/4; + return 99 - (player->getThreshold()-100)/4; +} + +bool Server::initConf(QSettings *c) { + QFile f(c->fileName()); + + if(!f.exists()){ + c->beginGroup("default"); + c->setValue("threshold", DEFAULT_THRESHOLD); + c->setValue("master", DEFAULT_MASTER_VOLUME); + c->setValue("volume", DEFAULT_VOLUME); + c->setValue("pan", DEFAULT_PAN); + c->setValue("activation", DEFAULT_ACTIVATION); + c->endGroup(); + + c->beginGroup("files"); + c->setValue("folder", DEFAULT_FOLDER); + c->setValue("extension", DEFAULT_EXTENSION); + c->endGroup(); + + c->beginGroup("osc"); + c->setValue("ip", DEFAULT_IP); + c->setValue("sender", DEFAULT_SENDER); + c->setValue("receiver", DEFAULT_RECEIVER); + c->endGroup(); + + return false; + } else + return true; + } void Server::sendReady(bool isReady) { sendMsgReady(isReady); } -void Server::sendTracksCount(unsigned int i) { - sendMsgTracksCount(i); +void Server::sendThreshold() { + sendMsgThreshold(getThreshold()); +} + +void Server::sendActivatedTracks() { + sendMsgActivatedTracks(player->getActivatedTracks()); +} + +void Server::sendPlay() +{ + sendMsgPlay(getTempo()); +} + +void Server::sendTracksCount() { + sendMsgTracksCount(player->getTracksCount()); } void Server::sendBoxActivation(unsigned int i, int val) { - if(val >= player.getThreshold()){ + if(val >= player->getThreshold()){ sendMsgBoxActivation(i); } } @@ -113,12 +213,27 @@ void Server::sendBeatCount(unsigned int i) { sendMsgBeatCount(i); } -void Server::sendSongsList(const char *i) { - sendMsgSongsList(i); +void Server::sendSongsList() { + options->beginGroup("files"); + QDir exportFolder(options->value("folder").toString()); + + exportFolder.setNameFilters(QStringList()<value("extension").toString()); + QStringList fileList = exportFolder.entryList(); + QString str = fileList.join("|"); + QByteArray list = str.toLatin1(); + const char *c_list = list.data(); + + options->endGroup(); + + sendMsgSongsList(c_list); } -void Server::sendSongTitle(const char *i) { - sendMsgSongTitle(i); +void Server::sendSongTitle() { + QString raw_title = QString::fromStdString(song.name); + QByteArray title = raw_title.toLatin1(); + const char *c_title = title.data(); + + sendMsgSongTitle(c_title); } void Server::handle__box_updateThreshold(osc::ReceivedMessageArgumentStream args) { @@ -142,7 +257,7 @@ void Server::handle__box_enable(osc::ReceivedMessageArgumentStream args) { args >> box; qDebug() << "received /box/enable" << box; - switchBox(box, player.getThreshold()); + switchBox(box, player->getThreshold()); } void Server::handle__box_volume(osc::ReceivedMessageArgumentStream args) { @@ -151,7 +266,7 @@ void Server::handle__box_volume(osc::ReceivedMessageArgumentStream args) { args >> box >> vol; qDebug() << "received /box/volume" << vol; - player.setVolume(box, vol); + player->setVolume(box, vol); } void Server::handle__box_pan(osc::ReceivedMessageArgumentStream args) { @@ -160,7 +275,7 @@ void Server::handle__box_pan(osc::ReceivedMessageArgumentStream args) { args >> box >> vol; qDebug() << "received /box/pan" << box << vol; - player.setPan(box, vol); + player->setPan(box, vol); } void Server::handle__box_mute(osc::ReceivedMessageArgumentStream args) { @@ -169,7 +284,7 @@ void Server::handle__box_mute(osc::ReceivedMessageArgumentStream args) { args >> box >> state; qDebug() << "received /box/mute" << box << state; - player.setMute(box, state); + player->setMute(box, state); } void Server::handle__box_solo(osc::ReceivedMessageArgumentStream args) { @@ -178,7 +293,7 @@ void Server::handle__box_solo(osc::ReceivedMessageArgumentStream args) { args >> box >> state; qDebug() << "received /box/solo" << box << state; - player.solo(box, state); + player->solo(box, state); } void Server::handle__box_master(osc::ReceivedMessageArgumentStream args) { @@ -186,7 +301,7 @@ void Server::handle__box_master(osc::ReceivedMessageArgumentStream args) { args >> vol; qDebug() << "received /box/master" << vol; - player.setMasterVolume(vol); + player->setMasterVolume(vol); } void Server::handle__box_play(osc::ReceivedMessageArgumentStream args) { @@ -213,7 +328,7 @@ void Server::handle__box_reset(osc::ReceivedMessageArgumentStream args) { if(state) stop(); - player.reset(); + player->reset(); } void Server::handle__box_refreshSong(osc::ReceivedMessageArgumentStream args) { @@ -238,15 +353,29 @@ void Server::handle__box_selectSong(osc::ReceivedMessageArgumentStream args) { emit actionLoad(); } +void Server::handle__box_sync(osc::ReceivedMessageArgumentStream args) +{ + bool state; + args >> state; + qDebug() << "received /box/sync" << state; + + sendSongsList(); + sendThreshold(); + + sendSongTitle(); + sendTracksCount(); + sendActivatedTracks(); +} + void Server::reset() { stop(); - player.reset(); + player->reset(); } void Server::switchBox(unsigned int i, int val) { - if(val >= player.getThreshold()) { - player.switchBox(i); + if(val >= player->getThreshold()) { + player->switchBox(i); } } @@ -255,15 +384,15 @@ void Server::play() { if(load()) return; } - sendMsgPlay(getTempo()); - player.start(); + sendPlay(); + player->start(); m_playing = true; } void Server::stop() { if(!m_loaded || !m_playing) return; - player.stop(); + player->stop(); m_previousBeat = 0; m_playing = false; @@ -274,15 +403,15 @@ void Server::updateBeat(double t) { // in seconds int time = (int)(t * getTempo() / 60.0f) + 1; - if(time != m_previousBeat && time <= m_beatCount && !player.isStopped()) { + if(time != m_previousBeat && time <= m_beatCount && !player->isStopped()) { m_previousBeat = time; sendBeatCount(time); if(time == 8 || time == 16 || time == 24){ //sync - sendMsgActivatedTracks(player.getActivatedTracks()); + sendActivatedTracks(); sendBeatCount(time); } - } else if(player.isStopped()) { + } else if(player->isStopped()) { m_previousBeat = 0; sendBeatCount(0); } @@ -309,66 +438,59 @@ void Server::setTempo(unsigned int arg) { m_tempo = arg; } -void Server::sendMsgThreshold(int boxSensor) { - sender.send(osc::MessageGenerator()("/box/sensor", boxSensor)); - qDebug() << "sent /box/sensor" << boxSensor; +void Server::sendMsgThreshold(int t) { + sender->send(osc::MessageGenerator()("/box/sensor", t)); + qDebug() << "sent /box/sensor" << t; } void Server::sendMsgBoxActivation(int chan) { - sender.send(osc::MessageGenerator()("/box/enable_out", chan)); + sender->send(osc::MessageGenerator()("/box/enable_out", chan)); qDebug() << "sent /box/enable_out" << chan; } -void Server::sendMsgActivatedTracks(int val) { - sender.send(osc::MessageGenerator()("/box/enable_sync", val)); - qDebug() << "sent /box/enable_sync" << val; +void Server::sendMsgActivatedTracks(int tracks) { + sender->send(osc::MessageGenerator()("/box/enable_sync", tracks)); + qDebug() << "sent /box/enable_sync" << tracks; } void Server::sendMsgBeatCount(int beat) { - sender.send(osc::MessageGenerator()("/box/beat", beat)); + sender->send(osc::MessageGenerator()("/box/beat", beat)); qDebug() << "sent /box/beat" << beat; } void Server::sendMsgPlay(int tempo) { - sender.send(osc::MessageGenerator()("/box/play", tempo)); + sender->send(osc::MessageGenerator()("/box/play", tempo)); qDebug() << "sent /box/play" << tempo; } void Server::sendMsgSongTitle(const char *title) { - sender.send(osc::MessageGenerator()("/box/title", title)); + sender->send(osc::MessageGenerator()("/box/title", title)); qDebug() << "sent /box/title" << title; } void Server::sendMsgSongsList(const char *list) { - sender.send(osc::MessageGenerator()("/box/songs_list", list)); + sender->send(osc::MessageGenerator()("/box/songs_list", list)); qDebug() << "sent /box/songs_list" << list; } void Server::sendMsgTracksCount(int num) { - sender.send(osc::MessageGenerator()("/box/tracks_count", num)); + sender->send(osc::MessageGenerator()("/box/tracks_count", num)); qDebug() << "sent /box/tracks_count" << num; } void Server::sendMsgTracksList(const char *list) { - sender.send(osc::MessageGenerator()("/box/tracks_list", list)); + sender->send(osc::MessageGenerator()("/box/tracks_list", list)); qDebug() << "sent /box/tracks_list" << list; } -void Server::sendMsgReady(bool ready) { - sender.send(osc::MessageGenerator()("/box/ready", ready)); - qDebug() << "sent /box/ready" << ready; +void Server::sendMsgReady(bool isReady) { + sender->send(osc::MessageGenerator()("/box/ready", isReady)); + qDebug() << "sent /box/ready" << isReady; } int Server::load() { - QDir exportFolder(EXPORT_FOLDER); - - exportFolder.setNameFilters(QStringList()<load(song); m_loaded = true; - QString raw_title = QString::fromStdString(song.name); - QByteArray title = raw_title.toLatin1(); - const char *c_title = title.data(); - sendSongTitle(c_title); + sendSongTitle(); - sendTracksCount(player.getTracksCount()); + sendTracksCount(); return 0; } diff --git a/src/Server.h b/src/Server.h index fccb93b..510d699 100644 --- a/src/Server.h +++ b/src/Server.h @@ -24,34 +24,36 @@ class SaveManager; * * Handles the events and dispatch the corresponding actions */ -class Server : public QObject { +class Server : public QCoreApplication { Q_OBJECT Q_PROPERTY(int tempo READ getTempo WRITE setTempo) friend class SaveManager; private: - PlayThread player; /*< Audio play manager */ + PlayThread* player; /*< Audio play manager */ SaveManager saveManager; /*< File handling manager */ SerialManager serialManager {this}; /*< Interface with serial port */ + QSettings* options; /*< Config options */ + SongData song; /*< Actual song's data */ QString selSong; /*< Selected song's name */ int threshold; int nbChannels; - QString currentFile {}; + QString currentFile; bool m_loaded {false}; /*< Indicate if a song has been loaded */ bool m_playing {false}; /*< Indicate if a song is playing */ - int m_tempo {}; - double m_beatCount {}; + int m_tempo; + double m_beatCount; // Optimization : Comparison with the previous beat int m_previousBeat {-1}; - OscReceiver receiver {9988}; /*< Receiving interface with OSC protocol */ - OscSender sender {"192.170.0.17", 9989}; /*< Sending interface with OSC protocol */ + OscReceiver* receiver; /*< Receiving interface with OSC protocol */ + OscSender* sender; /*< Sending interface with OSC protocol */ /*************************** * TRANSMISSIONS TO CLIENT * @@ -61,21 +63,21 @@ class Server : public QObject { /** * @brief Send the actual threshold value to the client - * @param (Calculated) Threshold value (obtained with getThreshold() ) + * @param t Threshold value */ - void sendMsgThreshold(int boxSensor); + void sendMsgThreshold(int t); /** * @brief Notify the client of a box activation - * @param Track number + * @param chan Track number */ void sendMsgBoxActivation(int chan); /** * @brief Send the activated tracks' numbers to the client - * @param val Activated tracks + * @param tracks Tracks numbers * * Called each 8 beats, to keep the client synchronized */ - void sendMsgActivatedTracks(int val); + void sendMsgActivatedTracks(int tracks); /** * @brief Send the actual beat count * @param beat Beat count @@ -83,7 +85,7 @@ class Server : public QObject { void sendMsgBeatCount(int beat); /** * @brief Notify the client of the song's playing start - * @param tempo Song's tempo + * @param tempo Actual song's tempo */ void sendMsgPlay(int tempo); /** @@ -110,7 +112,7 @@ class Server : public QObject { * @brief Notify the client of the loading state * @param isReady Server's loading state */ - void sendMsgReady(bool sendMsgReady); + void sendMsgReady(bool isReady); /******************* @@ -208,9 +210,21 @@ class Server : public QObject { * Select a new song */ void handle__box_selectSong(osc::ReceivedMessageArgumentStream args); + /** + * @brief sync event handling + * @param args Nothing + * + * Send the informations of the actual song and the current state of the player + */ + void handle__box_sync(osc::ReceivedMessageArgumentStream args); public: - explicit Server(); + /** + * @brief Constructor of the Server class + * @param argc Number of arguments + * @param argv Arguments array + */ + explicit Server(int& argc, char* argv[]); ~Server(); /** @@ -225,6 +239,13 @@ class Server : public QObject { */ unsigned int getThreshold() const; + /** + * @brief Load or initialize the configuration options + * @param c Pointer to the options data + * @return If the config options have been loaded (true) or generated from the default values (false) + */ + bool initConf(QSettings *c); + signals: /** * @brief Notify the need to reload the actual song @@ -241,6 +262,13 @@ class Server : public QObject { void resetThreshold(); public slots: + + /** + * @brief Stop properly the application + * @param sig Exit signal + */ +// static void quit(int sig); + /** * @brief Reset the values to default */ @@ -325,19 +353,16 @@ public slots: void sendBeatCount(unsigned int beat); /** * @brief Send the actual song's title - * @param title Song's title */ - void sendSongTitle(const char* title); + void sendSongTitle(); /** * @brief Send the available songs' list - * @param list Songs' titles list */ - void sendSongsList(const char* list); + void sendSongsList(); /** * @brief Send the song's number of tracks - * @param num Count of tracks */ - void sendTracksCount(unsigned int num); + void sendTracksCount(); /** * @brief Notify the client of the loading state * @param isReady Server's loading state @@ -345,6 +370,18 @@ public slots: * Send true if all the songs are loaded, false else */ void sendReady(bool isReady); + /** + * @brief Send the server's threshold + */ + void sendThreshold(); + /** + * @brief Send the song's actual activated tracks + */ + void sendActivatedTracks(); + /** + * @brief Notify the client of the song's playing start + */ + void sendPlay(); }; #endif // SERVER_H diff --git a/src/Track.cpp b/src/Track.cpp index c68071b..888c997 100644 --- a/src/Track.cpp +++ b/src/Track.cpp @@ -7,11 +7,11 @@ Track::Track(): m_id(0), m_file(""), m_name(""), - m_soloState(false), m_activatedState(false) + m_soloState(false), m_activatedState(false), options(NULL) {} -Track::Track(const TrackData& data, Parameters conf, int id): - m_id(id), m_file(data.file), m_name(data.name), +Track::Track(const TrackData& data, Parameters conf, QSettings* opt, int id): + m_id(id), m_file(data.file), m_name(data.name), options(opt), m_soloState(false), m_activatedState(false) { m_volumePtr = std::make_shared>(conf); @@ -86,3 +86,13 @@ void Track::notifyEnabled(bool enabled) { if(!m_soloState) emit onActivationSwitch(enabled, m_id); } + +void Track::reset() { + options->beginGroup("default"); + + setVolume(options->value("volume").toInt()); + setPan(options->value("pan").toInt()); + setActivated(options->value("activation").toBool()); + + options->endGroup(); +} diff --git a/src/Track.h b/src/Track.h index e1e44af..7f65068 100644 --- a/src/Track.h +++ b/src/Track.h @@ -11,14 +11,11 @@ #include #include +#include #include #include #include -#define DEFAULT_VOLUME 50 -#define DEFAULT_PAN 0 -#define DEFAULT_ACTIVATION false - /** * @brief The Track class * @@ -36,6 +33,8 @@ class Track : public QObject bool m_soloState; bool m_activatedState; + QSettings* options; + std::shared_ptr> m_volumePtr; /*< Volume in the audio engine */ std::shared_ptr> m_panPtr; /*< Pan in the audio engine */ std::shared_ptr> m_muteState; /*< Mute state in the audio engine */ @@ -51,7 +50,7 @@ class Track : public QObject * @param conf Default configuration data (volume, pan, mute) * @param id Track number (should be its position in the PlayThread's tracks vector) */ - Track(const TrackData& data, Parameters conf, int id); + Track(const TrackData& data, Parameters conf, QSettings* opt, int id); std::string getName() const; std::string getFile() const; @@ -104,11 +103,7 @@ class Track : public QObject /** * @brief Reset the track's settings to their default values */ - void reset() { - setVolume(DEFAULT_VOLUME); - setPan(DEFAULT_PAN); - setActivated(DEFAULT_ACTIVATION); - } + void reset(); signals: /** diff --git a/src/be-server.pro b/src/be-server.pro index b24790e..2caa1c8 100644 --- a/src/be-server.pro +++ b/src/be-server.pro @@ -1,7 +1,8 @@ -QT += core gui serialport +QT += core serialport +QT -= gui CONFIG += console -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets serialport +greaterThan(QT_MAJOR_VERSION, 4): QT += serialport TARGET = be-server TEMPLATE = app @@ -32,7 +33,7 @@ HEADERS += \ SerialManager.h \ Server.h -INCLUDEPATH += $$PWD/../../libaudiotool/src/libwatermark +INCLUDEPATH += $$PWD/../../libaudiotool/src/libwatermark DEPENDPATH += $$PWD/../../libaudiotool/src/libwatermark LIBS+= -lgomp -lsndfile diff --git a/src/main.cpp b/src/main.cpp index cfeaa47..4a7d805 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,11 +4,23 @@ */ #include "Server.h" -#include +#include #include +#include + +struct QuitStruct{ + QuitStruct(){ + std::signal(SIGINT, &QuitStruct::exitApp ); + std::signal(SIGTERM, &QuitStruct::exitApp ); + } + + static void exitApp(int sig){ + QCoreApplication::exit(0); + } +}; int main(int argc, char *argv[]) { - QApplication a(argc, argv); - Server w; - return a.exec(); + QuitStruct qs; + Server s(argc, argv); + return s.exec(); }