diff --git a/aboutdialog.ui b/aboutdialog.ui
index 2211abb..abd5cb9 100644
--- a/aboutdialog.ui
+++ b/aboutdialog.ui
@@ -264,7 +264,8 @@
Vladislav Kobzar
-------------------
Ilya Spivakov
-Matvey Adzhigirey
+Matvey Adzhigirey
+Stefan Slonevskiy
diff --git a/bible.cpp b/bible.cpp
index 1ed9890..1a8830e 100644
--- a/bible.cpp
+++ b/bible.cpp
@@ -178,20 +178,20 @@ Verse Bible::getCurrentVerseAndCaption(QList currentRows, BibleSettings& s
Verse v;
// get primary verse
- getVerseAndCaption(v.primary_text,v.primary_caption,verse_id,bv.primaryBible,sets.useAbbriviation);
+ getVerseAndCaption(v.primary_text,v.primary_caption,v.primary_abbr,verse_id,bv.primaryBible,sets.useAbbriviation);
// get secondary verse
if(bv.primaryBible!=bv.secondaryBible && bv.secondaryBible!="none")
- getVerseAndCaption(v.secondary_text,v.secondary_caption,verse_id,bv.secondaryBible,sets.useAbbriviation);
+ getVerseAndCaption(v.secondary_text,v.secondary_caption,v.secondary_abbr,verse_id,bv.secondaryBible,sets.useAbbriviation);
// get trinary versse
if(bv.trinaryBible!=bv.primaryBible && bv.trinaryBible!=bv.secondaryBible && bv.trinaryBible!="none")
- getVerseAndCaption(v.trinary_text,v.trinary_caption,verse_id,bv.trinaryBible,sets.useAbbriviation);
+ getVerseAndCaption(v.trinary_text,v.trinary_caption,v.trinary_abbr,verse_id,bv.trinaryBible,sets.useAbbriviation);
return v;
}
-void Bible::getVerseAndCaption(QString& verse, QString& caption, QString verId, QString& bibId, bool useAbbr)
+void Bible::getVerseAndCaption(QString& verse, QString& caption, QString& abbr, QString verId, QString& bibId, bool useAbbr)
{
QString verse_old, verse_show, verse_n, verse_nold, verse_nfirst, chapter;
QString book;
@@ -280,18 +280,19 @@ void Bible::getVerseAndCaption(QString& verse, QString& caption, QString verId,
caption = sq.value(0).toString() + caption;
sq.clear();
- // Add bible abbreveation if to to use it
- if(useAbbr)
- {
- sq.exec("SELECT abbreviation FROM BibleVersions WHERE id = " + bibId);
- sq.first();
- QString abr = sq.value(0).toString().trimmed();
- if (!abr.isEmpty())
+ // Add bible abbreviation if to to use it
+ sq.exec("SELECT abbreviation FROM BibleVersions WHERE id = " + bibId);
+ sq.first();
+ QString abr = sq.value(0).toString().trimmed();
+ if (!abr.isEmpty()) {
+ abbr = QString("%1").arg(abr);
+ if (useAbbr)
caption = QString("%1 (%2)").arg(caption).arg(abr);
}
verse = verse.simplified();
caption = caption.simplified();
+ abbr = abbr.simplified();
}
QList Bible::searchBible(bool allWords, QRegExp searchExp)
diff --git a/bible.hpp b/bible.hpp
index 134dc42..a2a76eb 100644
--- a/bible.hpp
+++ b/bible.hpp
@@ -41,11 +41,14 @@ class Verse
// For now both primary and secondary information is stored in
// primary_text and primary_caption
QString primary_text;
- QString secondary_text;
QString primary_caption;
+ QString primary_abbr;
+ QString secondary_text;
QString secondary_caption;
+ QString secondary_abbr;
QString trinary_text;
QString trinary_caption;
+ QString trinary_abbr;
};
class BibleSearch
@@ -96,7 +99,7 @@ public slots:
void getVerseRef(QString vId, QString &book, int &chapter, int &verse);
int getVerseNumberLast(QString vId);
QStringList getChapter(int book, int chapter);
- void getVerseAndCaption(QString &verse, QString &caption, QString verId, QString &bibId, bool useAbbr);
+ void getVerseAndCaption(QString& verse, QString& caption, QString& abbr, QString verId, QString& bibId, bool useAbbr);
int getCurrentBookRow(QString book);
Verse getCurrentVerseAndCaption(QList currentRows, BibleSettings& sets, BibleVersionSettings& bv);
void setBiblesId(QString& id);
diff --git a/biblewidget.cpp b/biblewidget.cpp
index 85e89e3..8619da4 100644
--- a/biblewidget.cpp
+++ b/biblewidget.cpp
@@ -376,7 +376,7 @@ void BibleWidget::on_search_button_clicked()
if (!search_results.isEmpty()) // If have results, then show them
{
- if( not ui->result_label->isVisible() )
+ if( !ui->result_label->isVisible() )
{
ui->lineEditBook->clear();
hidden_splitter_state = ui->results_splitter->saveState();
diff --git a/generalsettingwidget.cpp b/generalsettingwidget.cpp
index e582cb6..b8fb17b 100644
--- a/generalsettingwidget.cpp
+++ b/generalsettingwidget.cpp
@@ -59,7 +59,7 @@ void GeneralSettingWidget::loadSettings()
loadThemes();
ui->comboBoxTheme->setCurrentIndex(themeIdList.indexOf(mySettings.currentThemeId));
- // Get display screen infomration
+ // Get display screen information
monitors.clear();
QDesktopWidget d;
int screen_count = d.screenCount();
@@ -101,6 +101,10 @@ void GeneralSettingWidget::loadSettings()
ui->comboBoxControlsAlignV->setCurrentIndex(mySettings.displayControls.alignmentV);
ui->comboBoxControlsAlignH->setCurrentIndex(mySettings.displayControls.alignmentH);
ui->horizontalSliderOpacity->setValue(mySettings.displayControls.opacity*100);
+
+ // Set HTTP Controls
+ ui->checkBoxEnableHttpServer->setChecked(mySettings.httpServerEnabled);
+ ui->lineEditHttpPort->setText(QString::number(mySettings.httpServerPort));
}
void GeneralSettingWidget::loadThemes()
@@ -139,6 +143,9 @@ GeneralSettings GeneralSettingWidget::getSettings()
r = r/100;
mySettings.displayControls.opacity = r;
+ mySettings.httpServerEnabled = ui->checkBoxEnableHttpServer->isChecked();
+ mySettings.httpServerPort = ui->lineEditHttpPort->text().toInt();
+
return mySettings;
}
diff --git a/generalsettingwidget.ui b/generalsettingwidget.ui
index f2d843a..fa77a06 100644
--- a/generalsettingwidget.ui
+++ b/generalsettingwidget.ui
@@ -298,6 +298,58 @@
+ -
+
+
+ HTTP XML Feed Controls
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ 5
+
+
+
+ -
+
+
+ HTTP Server Port:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Enable HTTP XML feed
+
+
+
+
+
+
-
diff --git a/httpserver.cpp b/httpserver.cpp
new file mode 100644
index 0000000..2c642e1
--- /dev/null
+++ b/httpserver.cpp
@@ -0,0 +1,140 @@
+/***************************************************************************
+//
+// softProjector - an open source media projection software
+// Copyright (C) 2021 Vladislav Kobzar
+//
+// 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 version 3 of the License.
+//
+// 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, see .
+//
+***************************************************************************/
+
+#include "httpserver.hpp"
+
+HttpServer::HttpServer(QObject *parent) : QObject(parent)
+{
+ isRunning = false;
+}
+
+HttpServer::~HttpServer()
+{
+ stopServer();
+}
+
+void HttpServer::startServer(quint16 port)
+{
+ server = new QTcpServer(this);
+
+ // waiting for the web brower to make contact, this will emit signal
+ connect(server, SIGNAL(newConnection()), this, SLOT(startConnection()));
+
+ if(!server->listen(QHostAddress::Any, port))
+ isRunning = false;
+ else
+ isRunning = true;
+}
+
+void HttpServer::startConnection()
+{
+ QTcpSocket *socket = server->nextPendingConnection();
+ connect(socket, SIGNAL(readyRead()), this, SLOT(sendData()));
+ connect(socket, SIGNAL(disconnected()), this, SLOT(closingClient()));
+}
+
+void HttpServer::closingClient()
+{
+ QTcpSocket* socket = (QTcpSocket*)sender();
+ socket->deleteLater();
+}
+
+void HttpServer::sendData()
+{
+ QTcpSocket* socket = (QTcpSocket*)sender();
+
+ socket->write("HTTP/1.1 200 OK\r\n"); // \r needs to be before \n
+ socket->write("Content-Type: text/xml\r\n");
+ socket->write("Connection: close\r\n"); // Require two \r\n.
+ socket->write("\r\n");
+
+ socket->write("\r\n");
+ socket->write("\r\n");
+ socket->write(xmlData.toUtf8());
+ socket->write("\r\n");
+
+ socket->disconnectFromHost();
+}
+
+
+void HttpServer::stopServer()
+{
+ server->close();
+ delete server;
+ isRunning = false;
+}
+
+void HttpServer::setBibleText(Verse bVerse, BibleSettings &bSets)
+{
+ // Translation flags
+ bool havePrimary = ("none" != bSets.versions.primaryBible);
+ bool haveSecondary = ("none" != bSets.versions.secondaryBible);
+ bool haveTrinary = ("none" != bSets.versions.trinaryBible);
+
+ xmlData = "";
+
+ xmlData += "\r\n";
+ xmlData += "" + bVerse.primary_text + "\r\n";
+ xmlData += "" + bVerse.primary_caption + "\r\n";
+ xmlData += "" + bVerse.primary_abbr + "\r\n";
+ xmlData += "\r\n";
+
+ if (haveSecondary) {
+ xmlData += "\r\n";
+ xmlData += "" + bVerse.secondary_text + "\r\n";
+ xmlData += "" + bVerse.secondary_caption + "\r\n";
+ xmlData += "" + bVerse.secondary_abbr + "\r\n";
+ xmlData += "\r\n";
+ }
+
+ if (haveTrinary) {
+ xmlData += "\r\n";
+ xmlData += "" + bVerse.trinary_text + "\r\n";
+ xmlData += "" + bVerse.trinary_caption + "\r\n";
+ xmlData += "" + bVerse.trinary_abbr + "\r\n";
+ xmlData += "\r\n";
+ }
+}
+
+void HttpServer::setSongText(Stanza stanza, SongSettings &sSets)
+{
+ xmlData = "\r\n";
+
+ xmlData += "" + stanza.stanza + "\r\n";
+ xmlData += "" + stanza.stanzaTitle + "\r\n";
+ xmlData += "" + stanza.tune + "\r\n";
+ xmlData += "" + stanza.wordsBy + "\r\n";
+ xmlData += "" + stanza.musicBy + "\r\n";
+ xmlData += "" + QString::number(stanza.number) + "\r\n";
+ xmlData += "" + QString::number(stanza.isLast) + "\r\n";
+
+ xmlData += "\r\n";
+}
+
+void HttpServer::setAnnounceText(AnnounceSlide announce, TextSettings &aSets)
+{
+ xmlData = "\r\n";
+ xmlData += "" + announce.text + "\r\n";
+ xmlData += "\r\n";
+}
+
+void HttpServer::setBlank()
+{
+ xmlData = "";
+}
diff --git a/httpserver.hpp b/httpserver.hpp
new file mode 100644
index 0000000..d083895
--- /dev/null
+++ b/httpserver.hpp
@@ -0,0 +1,68 @@
+/***************************************************************************
+//
+// softProjector - an open source media projection software
+// Copyright (C) 2021 Vladislav Kobzar
+//
+// 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 version 3 of the License.
+//
+// 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, see .
+//
+***************************************************************************/
+
+// Simple HTTP server implementation in Qt taken from https://stackoverflow.com/a/32931195
+
+#ifndef HTTPSERVER_HPP
+#define HTTPSERVER_HPP
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "bible.hpp"
+#include "song.hpp"
+#include "announcement.hpp"
+
+class HttpServer : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit HttpServer(QObject *parent = 0);
+ ~HttpServer();
+ void startServer(quint16 port);
+ void stopServer();
+ void setBibleText(Verse bVerse, BibleSettings &bSets);
+ void setSongText(Stanza stanza, SongSettings &sSets);
+ void setAnnounceText(AnnounceSlide announce, TextSettings &aSets);
+ void setBlank();
+ bool isRunning;
+ //QTcpSocket *socket;
+
+public slots:
+ void startConnection();
+ void sendData();
+ void closingClient();
+
+private:
+ QTcpServer *server;
+ qint64 bytesAvailable() const;
+ QString xmlData;
+ void establishConnection();
+ bool servingConnection;
+
+signals:
+};
+
+#endif
diff --git a/mediawidget.cpp b/mediawidget.cpp
index a353faf..8505251 100644
--- a/mediawidget.cpp
+++ b/mediawidget.cpp
@@ -23,8 +23,17 @@
#include "ui_mediawidget.h"
#ifdef Q_OS_WIN
-#include // this need for Sleep function
+#include // for Sleep
#endif
+void qSleep(int ms)
+{
+#ifdef Q_OS_WIN
+ Sleep(uint(ms));
+#else
+ struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
+ nanosleep(&ts, NULL);
+#endif
+}
MediaWidget::MediaWidget(QWidget *parent) :
QWidget(parent),
@@ -407,13 +416,7 @@ void MediaWidget::goLiveFromSchedule()
{
while (!isReadyToPlay)
{
- int ms = 1000;
-#ifdef Q_OS_WIN
- Sleep(uint(ms));
-#else
- struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
- nanosleep(&ts, nullptr);
-#endif
+ qSleep(100);
}
qDebug()<isVisible()<pushButtonGoLive->isEnabled();
if(ui->pushButtonGoLive->isEnabled())
diff --git a/settings.cpp b/settings.cpp
index fe711a2..c329761 100644
--- a/settings.cpp
+++ b/settings.cpp
@@ -800,6 +800,10 @@ void Settings::loadSettings()
}
else if (n == "dcOpacity")
general.displayControls.opacity = v.toDouble();
+ else if (n == "httpEnabled")
+ general.httpServerEnabled = (v=="true");
+ else if (n == "httpPort")
+ general.httpServerPort = v.toInt();
}
}
else if(t == "spMain")
@@ -914,6 +918,11 @@ void Settings::saveSettings()
gset += "\ndcIconSize = " + QString::number(general.displayControls.buttonSize);
gset += QString("\ndcAlignment = %1,%2").arg(general.displayControls.alignmentV).arg(general.displayControls.alignmentH);
gset += "\ndcOpacity = " + QString::number(general.displayControls.opacity);
+ if(general.httpServerEnabled)
+ gset += "\nhttpEnabled = true";
+ else
+ gset += "\nhttpEnabled = false";
+ gset += "\nhttpPort = " + QString::number(general.httpServerPort);
// **** prepare softProjector main settings
spset += "spSplitter = " + spMain.spSplitter.toHex();
diff --git a/settings.hpp b/settings.hpp
index b3d2572..dc4e931 100644
--- a/settings.hpp
+++ b/settings.hpp
@@ -286,6 +286,8 @@ class GeneralSettings
bool settingsChangedAll;
bool settingsChangedMulti;
bool settingsChangedSingle;
+ bool httpServerEnabled;
+ int httpServerPort;
};
class DisplaySettings
diff --git a/settingsdialog.cpp b/settingsdialog.cpp
index e9cb1c0..c70d0d6 100644
--- a/settingsdialog.cpp
+++ b/settingsdialog.cpp
@@ -72,6 +72,8 @@ void SettingsDialog::loadSettings(GeneralSettings &sets, Theme &thm, SlideShowSe
is_always_on_top = gsettings.displayIsOnTop;
current_display_screen = gsettings.displayScreen;
currentDisplayScreen2 = gsettings.displayScreen2;
+ current_http_enabled = gsettings.httpServerEnabled;
+ current_http_port = gsettings.httpServerPort;
// Set individual items
generalSettingswidget->setSettings(gsettings);
@@ -154,6 +156,13 @@ void SettingsDialog::applySettings()
// Redraw the screen:
emit updateScreen();
+ // Update HTTP server state
+ if(current_http_port!=gsettings.httpServerPort
+ || current_http_enabled!=gsettings.httpServerEnabled)
+ {
+ emit httpServerState(gsettings.httpServerEnabled,gsettings.httpServerPort);
+ }
+
// Save Settings
theme.saveThemeUpdate();
@@ -161,6 +170,8 @@ void SettingsDialog::applySettings()
is_always_on_top = gsettings.displayIsOnTop;
current_display_screen = gsettings.displayScreen;
currentDisplayScreen2 = gsettings.displayScreen2;
+ current_http_enabled = gsettings.httpServerEnabled;
+ current_http_port = gsettings.httpServerPort;
}
void SettingsDialog::getThemes()
diff --git a/settingsdialog.hpp b/settingsdialog.hpp
index 82f58b0..be074e4 100644
--- a/settingsdialog.hpp
+++ b/settingsdialog.hpp
@@ -52,6 +52,7 @@ public slots:
BibleVersionSettings& bsets, BibleVersionSettings& bsets2);
void positionsDisplayWindow();
void updateScreen();
+ void httpServerState(bool& state, int& port);
private:
Ui::SettingsDialog *ui;
@@ -59,6 +60,8 @@ public slots:
int current_display_screen;
int currentDisplayScreen2;
bool is_always_on_top;
+ bool current_http_enabled;
+ int current_http_port;
GeneralSettings gsettings;
Theme theme;
diff --git a/softProjector.pro b/softProjector.pro
index 3d2129f..b105d27 100644
--- a/softProjector.pro
+++ b/softProjector.pro
@@ -88,7 +88,8 @@ SOURCES += main.cpp \
projectordisplayscreen.cpp \
imagegenerator.cpp \
spimageprovider.cpp \
- mediacontrol.cpp
+ mediacontrol.cpp \
+ httpserver.cpp
HEADERS += softprojector.hpp \
songwidget.hpp \
biblewidget.hpp \
@@ -131,7 +132,8 @@ HEADERS += softprojector.hpp \
projectordisplayscreen.hpp \
imagegenerator.hpp \
spimageprovider.hpp \
- mediacontrol.hpp
+ mediacontrol.hpp \
+ httpserver.hpp
FORMS += softprojector.ui \
songwidget.ui \
biblewidget.ui \
diff --git a/softprojector.cpp b/softprojector.cpp
index be4ef7b..6632169 100644
--- a/softprojector.cpp
+++ b/softprojector.cpp
@@ -55,6 +55,10 @@ SoftProjector::SoftProjector(QWidget *parent)
pictureWidget = new PictureWidget;
mediaPlayer = new MediaWidget;
mediaControls = new MediaControl(this);
+ httpServer = new HttpServer();
+
+ if (mySettings.general.httpServerEnabled)
+ httpServer->startServer(mySettings.general.httpServerPort);
ui->setupUi(this);
@@ -110,6 +114,7 @@ SoftProjector::SoftProjector(QWidget *parent)
BibleVersionSettings&,BibleVersionSettings&)));
connect(settingsDialog,SIGNAL(positionsDisplayWindow()),this,SLOT(positionDisplayWindow()));
connect(settingsDialog,SIGNAL(updateScreen()),this,SLOT(updateScreen()));
+ connect(settingsDialog,SIGNAL(httpServerState(bool&,int&)),this,SLOT(httpServerState(bool&,int&)));
connect(songWidget,SIGNAL(addToSchedule(Song&)),this,SLOT(addToShcedule(Song&)));
connect(announceWidget,SIGNAL(addToSchedule(Announcement&)),this,SLOT(addToShcedule(Announcement&)));
@@ -207,6 +212,7 @@ SoftProjector::~SoftProjector()
delete shSart2;
delete helpDialog;
delete ui;
+ delete httpServer;
}
void SoftProjector::positionDisplayWindow()
@@ -390,6 +396,15 @@ void SoftProjector::applySetting(GeneralSettings &g, Theme &t, SlideShowSettings
retranslateUis();
}
+void SoftProjector::httpServerState(bool &state, int &port)
+{
+ if (httpServer->isRunning)
+ httpServer->stopServer();
+
+ if (state)
+ httpServer->startServer(port);
+}
+
void SoftProjector::closeEvent(QCloseEvent *event)
{
if(is_schedule_saved || schedule_file_path.isEmpty())
@@ -695,6 +710,11 @@ void SoftProjector::updateScreen()
ui->actionShow->setEnabled(true);
ui->actionHide->setEnabled(false);
ui->actionClear->setEnabled(false);
+
+ if (mySettings.general.httpServerEnabled)
+ {
+ httpServer->setBlank();
+ }
}
else if ((currentRow >=0 || pType == VIDEO) && !new_list)
{
@@ -776,6 +796,13 @@ void SoftProjector::showBible()
mySettings.bibleSets),theme.bible);
}
}
+
+ if(mySettings.general.httpServerEnabled)
+ {
+ httpServer->setBibleText(bibleWidget->bible.
+ getCurrentVerseAndCaption(currentRows,theme.bible,
+ mySettings.bibleSets),theme.bible);
+ }
}
void SoftProjector::showSong(int currentRow)
@@ -803,6 +830,11 @@ void SoftProjector::showSong(int currentRow)
pds2->renderSongText(current_song.getStanza(currentRow),s1);
}
}
+
+ if(mySettings.general.httpServerEnabled)
+ {
+ httpServer->setSongText(current_song.getStanza(currentRow),s2);
+ }
}
void SoftProjector::showAnnounce(int currentRow)
@@ -819,6 +851,11 @@ void SoftProjector::showAnnounce(int currentRow)
pds2->renderAnnounceText(currentAnnounce.getAnnounceSlide(currentRow),theme.announce);
}
}
+
+ if(mySettings.general.httpServerEnabled)
+ {
+ httpServer->setAnnounceText(currentAnnounce.getAnnounceSlide(currentRow),theme.announce);
+ }
}
void SoftProjector::showPicture(int currentRow)
diff --git a/softprojector.hpp b/softprojector.hpp
index 3bcd1ee..7a04894 100644
--- a/softprojector.hpp
+++ b/softprojector.hpp
@@ -40,6 +40,7 @@
#include "videoinfo.hpp"
#include "slideshoweditor.hpp"
#include "schedule.hpp"
+#include "httpserver.hpp"
class QActionGroup;
@@ -76,6 +77,8 @@ class SoftProjector : public QMainWindow
MediaWidget *mediaPlayer;
MediaControl *mediaControls;
+ HttpServer *httpServer;
+
bool showing; // whether we are currently showing to the projector
Song current_song;
int current_song_verse;
@@ -93,6 +96,7 @@ public slots:
void saveSettings();
void positionDisplayWindow();
void updateScreen();
+ void httpServerState(bool &state, int &port);
void setWaitCursor();
void setArrowCursor();