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 @@ + @@ -768,6 +769,11 @@ Ctrl+End + + + Basic.MainMenu.Help.CheckForUpdates + + 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();