diff --git a/build/data/obs-studio/locale/en-US.ini b/build/data/obs-studio/locale/en-US.ini
index c4a47d7d1600521d8a02042c41c7925510ad4eeb..b02b75e502b4d18de6051fe470929a6453429b96 100644
--- a/build/data/obs-studio/locale/en-US.ini
+++ b/build/data/obs-studio/locale/en-US.ini
@@ -56,6 +56,10 @@ LicenseAgreement.ClickIAgreeToContinue="If you accept the terms of the agreement
LicenseAgreement.IAgree="I Agree"
LicenseAgreement.Exit="Exit"
+# update dialog
+UpdateAvailable="New Update Available"
+UpdateAvailable.Text="Version %1.%2.%3 is now available. Click here to download"
+
# audio device names
Basic.DesktopDevice1="Desktop Audio"
Basic.DesktopDevice2="Desktop Audio 2"
@@ -164,6 +168,7 @@ Basic.MainMenu.Help="&Help"
Basic.MainMenu.Help.Logs="&Log Files"
Basic.MainMenu.Help.Logs.UploadCurrentLog="Upload &Current Log File"
Basic.MainMenu.Help.Logs.UploadLastLog="Upload &Last Log File"
+Basic.MainMenu.Help.CheckForUpdates="Check For Updates"
# basic mode settings dialog
Basic.Settings.ProgramRestart="The program must be restarted for these settings to take effect."
diff --git a/obs/forms/OBSBasic.ui b/obs/forms/OBSBasic.ui
index b46f2e3df3d25d3b76484a9450c6f49a49222dd3..f007fc2e7ad15352c0ed03d4883ec438b9601553 100644
--- a/obs/forms/OBSBasic.ui
+++ b/obs/forms/OBSBasic.ui
@@ -468,6 +468,7 @@
+
diff --git a/obs/window-basic-main.cpp b/obs/window-basic-main.cpp
index aa7154d54758f107915e5145b20e0eac2cd5fc2b..24fdb00772feeb1111aa5da519e8ac99c09942b0 100644
--- a/obs/window-basic-main.cpp
+++ b/obs/window-basic-main.cpp
@@ -16,6 +16,7 @@
along with this program. If not, see .
******************************************************************************/
+#include
#include
#include
#include
@@ -551,6 +552,7 @@ void OBSBasic::OBSInit()
Load(savePath);
ResetAudioDevices();
+ TimedCheckForUpdates();
loaded = true;
}
@@ -831,6 +833,101 @@ bool OBSBasic::QueryRemoveSource(obs_source_t source)
return button == QMessageBox::Yes;
}
+#define UPDATE_CHECK_INTERVAL (60*60*24*4) /* 4 days */
+
+void OBSBasic::TimedCheckForUpdates()
+{
+ long long lastUpdate = config_get_int(App()->GlobalConfig(), "General",
+ "LastUpdateCheck");
+ uint32_t lastVersion = config_get_int(App()->GlobalConfig(), "General",
+ "LastVersion");
+
+ if (lastVersion < LIBOBS_API_VER) {
+ lastUpdate = 0;
+ config_set_int(App()->GlobalConfig(), "General",
+ "LastUpdateCheck", 0);
+ }
+
+ long long t = (long long)time(nullptr);
+ long long secs = t - lastUpdate;
+
+ if (secs > UPDATE_CHECK_INTERVAL)
+ CheckForUpdates();
+}
+
+void OBSBasic::CheckForUpdates()
+{
+ ui->actionCheckForUpdates->setEnabled(false);
+
+ QUrl url("https://obsproject.com/obs2_update/mac_basic.json");
+ updateReply = networkManager.get(QNetworkRequest(url));
+ connect(updateReply, SIGNAL(finished()),
+ this, SLOT(updateFileFinished()));
+ connect(updateReply, SIGNAL(readyRead()),
+ this, SLOT(updateFileRead()));
+}
+
+void OBSBasic::updateFileRead()
+{
+ updateReturnData.push_back(updateReply->readAll());
+}
+
+void OBSBasic::updateFileFinished()
+{
+ ui->actionCheckForUpdates->setEnabled(true);
+
+ if (updateReply->error()) {
+ blog(LOG_WARNING, "Update check failed: %s",
+ QT_TO_UTF8(updateReply->errorString()));
+ return;
+ }
+
+ const char *jsonReply = updateReturnData.constData();
+ if (!jsonReply || !*jsonReply)
+ return;
+
+ obs_data_t returnData = obs_data_create_from_json(jsonReply);
+ obs_data_t versionData = obs_data_getobj(returnData, "version");
+ const char *description = obs_data_getstring(returnData, "description");
+ const char *download = obs_data_getstring(returnData, "download");
+
+ if (returnData && versionData && description && download) {
+ long major = obs_data_getint(versionData, "major");
+ long minor = obs_data_getint(versionData, "minor");
+ long patch = obs_data_getint(versionData, "patch");
+ long version = MAKE_SEMANTIC_VERSION(major, minor, patch);
+
+ blog(LOG_INFO, "Update check: latest version is: %ld.%ld.%ld",
+ major, minor, patch);
+
+ if (version > LIBOBS_API_VER) {
+ QString str = QTStr("UpdateAvailable.Text");
+ QMessageBox messageBox(this);
+
+ str = str.arg(QString::number(major),
+ QString::number(minor),
+ QString::number(patch),
+ download);
+
+ messageBox.setWindowTitle(QTStr("UpdateAvailable"));
+ messageBox.setTextFormat(Qt::RichText);
+ messageBox.setText(str);
+ messageBox.setInformativeText(QT_UTF8(description));
+ messageBox.exec();
+
+ long long t = (long long)time(nullptr);
+ config_set_int(App()->GlobalConfig(), "General",
+ "LastUpdateCheck", t);
+ config_save(App()->GlobalConfig());
+ }
+ } else {
+ blog(LOG_WARNING, "Bad JSON file received from server");
+ }
+
+ obs_data_release(versionData);
+ obs_data_release(returnData);
+}
+
void OBSBasic::RemoveSelectedScene()
{
OBSScene scene = GetCurrentScene();
@@ -1626,6 +1723,11 @@ void OBSBasic::on_actionUploadLastLog_triggered()
UploadLog(App()->GetLastLog());
}
+void OBSBasic::on_actionCheckForUpdates_triggered()
+{
+ CheckForUpdates();
+}
+
void OBSBasic::logUploadRead()
{
logUploadReturnData.push_back(logUploadReply->readAll());
diff --git a/obs/window-basic-main.hpp b/obs/window-basic-main.hpp
index 25620f506a7816a2fca44809c241f674ae50ea51..af90b2961ecd1a5774eed395b57b90d3fcc7bce4 100644
--- a/obs/window-basic-main.hpp
+++ b/obs/window-basic-main.hpp
@@ -69,6 +69,10 @@ private:
QNetworkReply *logUploadReply = nullptr;
QByteArray logUploadReturnData;
+ QBuffer updatePostData;
+ QNetworkReply *updateReply = nullptr;
+ QByteArray updateReturnData;
+
obs_output_t fileOutput = nullptr;
obs_output_t streamOutput = nullptr;
obs_service_t service = nullptr;
@@ -120,6 +124,9 @@ private:
bool QueryRemoveSource(obs_source_t source);
+ void TimedCheckForUpdates();
+ void CheckForUpdates();
+
void GetFPSCommon(uint32_t &num, uint32_t &den) const;
void GetFPSInteger(uint32_t &num, uint32_t &den) const;
void GetFPSFraction(uint32_t &num, uint32_t &den) const;
@@ -221,6 +228,7 @@ private slots:
void on_action_Settings_triggered();
void on_actionUploadCurrentLog_triggered();
void on_actionUploadLastLog_triggered();
+ void on_actionCheckForUpdates_triggered();
void on_actionEditTransform_triggered();
void on_actionResetTransform_triggered();
@@ -262,6 +270,9 @@ private slots:
void logUploadRead();
void logUploadFinished();
+ void updateFileRead();
+ void updateFileFinished();
+
void AddSourceFromAction();
void EditSceneName();