0
0
mirror of https://github.com/obsproject/obs-studio.git synced 2024-09-20 04:42:18 +02:00

Merge pull request #9302 from derrod/ui-update-nlohmann

UI: Migrate WhatsNew, update branches, and Windows update check to nlohmann JSON
This commit is contained in:
Lain 2023-07-29 16:06:28 -07:00 committed by GitHub
commit 106e28d60f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 253 additions and 98 deletions

View File

@ -1,10 +1,21 @@
include_guard(DIRECTORY)
find_package(nlohmann_json REQUIRED)
if(NOT TARGET OBS::blake2)
add_subdirectory("${CMAKE_SOURCE_DIR}/deps/blake2" "${CMAKE_BINARY_DIR}/deps/blake2")
endif()
target_sources(obs-studio PRIVATE update/crypto-helpers.hpp update/crypto-helpers-mac.mm update/shared-update.cpp
update/shared-update.hpp update/update-helpers.cpp update/update-helpers.hpp)
target_sources(
obs-studio
PRIVATE update/crypto-helpers.hpp
update/crypto-helpers-mac.mm
update/shared-update.cpp
update/shared-update.hpp
update/update-helpers.cpp
update/update-helpers.hpp
update/models/branches.hpp
update/models/whatsnew.hpp)
target_link_libraries(obs-studio PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Security.framework>" OBS::blake2)
target_link_libraries(obs-studio PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Security.framework>" nlohmann_json::nlohmann_json
OBS::blake2)

View File

@ -5,11 +5,18 @@ if(ENABLE_WHATSNEW AND TARGET OBS::browser-panels)
include(cmake/feature-macos-update.cmake)
elseif(OS_LINUX)
find_package(MbedTLS REQUIRED)
target_link_libraries(obs-studio PRIVATE MbedTLS::MbedTLS OBS::blake2)
find_package(nlohmann_json REQUIRED)
target_link_libraries(obs-studio PRIVATE MbedTLS::MbedTLS nlohmann_json::nlohmann_json OBS::blake2)
target_sources(
obs-studio PRIVATE update/crypto-helpers-mbedtls.cpp update/crypto-helpers.hpp update/shared-update.cpp
update/shared-update.hpp update/update-helpers.cpp update/update-helpers.hpp)
obs-studio
PRIVATE update/crypto-helpers-mbedtls.cpp
update/crypto-helpers.hpp
update/shared-update.cpp
update/shared-update.hpp
update/update-helpers.cpp
update/update-helpers.hpp
update/models/whatsnew.hpp)
endif()
target_enable_feature(obs-studio "What's New panel" WHATSNEW_ENABLED)

View File

@ -340,6 +340,7 @@ if(OS_WINDOWS)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/obs.rc.in ${CMAKE_BINARY_DIR}/obs.rc)
find_package(Detours REQUIRED)
find_package(nlohmann_json REQUIRED)
target_sources(
obs
@ -356,10 +357,13 @@ if(OS_WINDOWS)
update/update-helpers.hpp
update/crypto-helpers-mbedtls.cpp
update/crypto-helpers.hpp
update/models/branches.hpp
update/models/whatsnew.hpp
win-update/updater/manifest.hpp
${CMAKE_BINARY_DIR}/obs.rc)
find_package(MbedTLS)
target_link_libraries(obs PRIVATE Mbedtls::Mbedtls OBS::blake2 Detours::Detours)
target_link_libraries(obs PRIVATE Mbedtls::Mbedtls nlohmann_json::nlohmann_json OBS::blake2 Detours::Detours)
target_compile_features(obs PRIVATE cxx_std_17)
@ -423,17 +427,27 @@ elseif(OS_MACOS)
if(ENABLE_WHATSNEW)
find_library(SECURITY Security)
find_package(nlohmann_json REQUIRED)
mark_as_advanced(SECURITY)
target_link_libraries(obs PRIVATE ${SECURITY} OBS::blake2)
target_sources(obs PRIVATE update/crypto-helpers.hpp update/crypto-helpers-mac.mm update/shared-update.cpp
update/shared-update.hpp update/update-helpers.cpp update/update-helpers.hpp)
target_link_libraries(obs PRIVATE ${SECURITY} OBS::blake2 nlohmann_json::nlohmann_json)
target_sources(
obs
PRIVATE update/crypto-helpers.hpp
update/crypto-helpers-mac.mm
update/shared-update.cpp
update/shared-update.hpp
update/update-helpers.cpp
update/update-helpers.hpp
update/models/whatsnew.hpp)
if(SPARKLE_APPCAST_URL AND SPARKLE_PUBLIC_KEY)
find_library(SPARKLE Sparkle)
mark_as_advanced(SPARKLE)
target_sources(obs PRIVATE update/mac-update.cpp update/mac-update.hpp update/sparkle-updater.mm)
target_sources(obs PRIVATE update/mac-update.cpp update/mac-update.hpp update/sparkle-updater.mm
update/models/branches.hpp)
target_compile_definitions(obs PRIVATE ENABLE_SPARKLE_UPDATER)
target_link_libraries(obs PRIVATE ${SPARKLE})
# Enable Automatic Reference Counting for Sparkle wrapper
@ -465,13 +479,14 @@ elseif(OS_POSIX)
if(OS_LINUX AND ENABLE_WHATSNEW)
find_package(MbedTLS)
find_package(nlohmann_json REQUIRED)
if(NOT MBEDTLS_FOUND)
obs_status(FATAL_ERROR "mbedTLS not found, but required for WhatsNew support on Linux")
endif()
target_sources(obs PRIVATE update/crypto-helpers.hpp update/crypto-helpers-mbedtls.cpp update/shared-update.cpp
update/shared-update.hpp update/update-helpers.cpp update/update-helpers.hpp)
target_link_libraries(obs PRIVATE Mbedtls::Mbedtls OBS::blake2)
target_link_libraries(obs PRIVATE Mbedtls::Mbedtls nlohmann_json::nlohmann_json OBS::blake2)
endif()
endif()

View File

@ -8,6 +8,7 @@ endif()
find_package(MbedTLS)
find_package(Detours REQUIRED)
find_package(nlohmann_json REQUIRED)
configure_file(cmake/windows/obs.rc.in obs.rc)
@ -26,9 +27,13 @@ target_sources(
update/update-window.cpp
update/update-window.hpp
update/win-update.cpp
update/win-update.hpp)
update/win-update.hpp
update/models/branches.hpp
update/models/whatsnew.hpp
win-update/updater/manifest.hpp)
target_link_libraries(obs-studio PRIVATE crypt32 OBS::blake2 OBS::w32-pthreads MbedTLS::MbedTLS Detours::Detours)
target_link_libraries(obs-studio PRIVATE crypt32 OBS::blake2 OBS::w32-pthreads MbedTLS::MbedTLS
nlohmann_json::nlohmann_json Detours::Detours)
target_compile_definitions(obs-studio PRIVATE PSAPI_VERSION=2)
target_link_options(obs-studio PRIVATE /IGNORE:4098 /IGNORE:4099)

View File

@ -65,7 +65,7 @@
#endif
#if defined(_WIN32) || defined(ENABLE_SPARKLE_UPDATER)
#include <json11.hpp>
#include "update/models/branches.hpp"
#endif
#if !defined(_WIN32) && !defined(__APPLE__)
@ -1289,28 +1289,31 @@ bool OBSApp::InitTheme()
void ParseBranchesJson(const std::string &jsonString, vector<UpdateBranch> &out,
std::string &error)
{
json11::Json root;
root = json11::Json::parse(jsonString, error);
if (!error.empty() || !root.is_array())
return;
JsonBranches branches;
for (const json11::Json &item : root.array_items()) {
try {
nlohmann::json json = nlohmann::json::parse(jsonString);
branches = json.get<JsonBranches>();
} catch (nlohmann::json::exception &e) {
error = e.what();
return;
}
for (const JsonBranch &json_branch : branches) {
#ifdef _WIN32
if (!item["windows"].bool_value())
if (!json_branch.windows)
continue;
#elif defined(__APPLE__)
if (!item["macos"].bool_value())
if (!json_branch.macos)
continue;
#endif
UpdateBranch branch = {
QString::fromStdString(item["name"].string_value()),
QString::fromStdString(
item["display_name"].string_value()),
QString::fromStdString(
item["description"].string_value()),
item["enabled"].bool_value(),
item["visible"].bool_value(),
QString::fromStdString(json_branch.name),
QString::fromStdString(json_branch.display_name),
QString::fromStdString(json_branch.description),
json_branch.enabled,
json_branch.visible,
};
out.push_back(branch);
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2023 Dennis Sädtler <dennis@obsproject.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#include <string>
#include <nlohmann/json.hpp>
struct JsonBranch {
/* Internal name / ID of the branch (used in updater) */
std::string name;
/* Human readable name */
std::string display_name;
/* Description */
std::string description;
/* Whether updating should use the branch if selected or fall back to stable */
bool enabled = false;
/* Whether the branch should be displayed in the UI */
bool visible = false;
/* OS compatibility */
bool windows = false;
bool macos = false;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(JsonBranch, name,
display_name, description,
enabled, visible, windows,
macos)
};
using JsonBranches = std::vector<JsonBranch>;

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 2023 Dennis Sädtler <dennis@obsproject.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#include <string>
#include <optional>
#include <nlohmann/json.hpp>
/* Ubuntu 22.04 be damned. */
#ifndef NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT
#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) \
nlohmann_json_t.v1 = \
nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
friend void to_json(nlohmann::json &nlohmann_json_j, \
const Type &nlohmann_json_t) \
{ \
NLOHMANN_JSON_EXPAND( \
NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) \
} \
friend void from_json(const nlohmann::json &nlohmann_json_j, \
Type &nlohmann_json_t) \
{ \
Type nlohmann_json_default_obj; \
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE( \
NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) \
}
#endif
/*
* Support for (de-)serialising std::optional
* Adapted from https://github.com/nlohmann/json/issues/1749#issuecomment-1555093802
*/
template<typename T> struct nlohmann::adl_serializer<std::optional<T>> {
static std::optional<T> from_json(const json &json)
{
return json.is_null() ? std::nullopt
: std::optional{json.get<T>()};
}
static void to_json(json &json, std::optional<T> t)
{
if (t)
json = *t;
else
json = nullptr;
}
};
struct WhatsNewPlatforms {
bool windows = false;
bool macos = false;
bool linux = false;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(WhatsNewPlatforms, windows,
macos, linux)
};
struct WhatsNewItem {
/* Target OBS version (patch is ignored) */
std::string version;
/* Beta/RC release to target */
int Beta = 0;
int RC = 0;
/* URL of webpage to be displayed */
std::string url;
/* Increment for this version's item */
int increment = 0;
/* Optional OS filter */
std::optional<WhatsNewPlatforms> os = std::nullopt;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(WhatsNewItem, version, Beta,
RC, url, increment, os)
};
using WhatsNewList = std::vector<WhatsNewItem>;

View File

@ -1,3 +1,4 @@
#include "../win-update/updater/manifest.hpp"
#include "update-helpers.hpp"
#include "shared-update.hpp"
#include "update-window.hpp"
@ -17,14 +18,13 @@
#include <util/windows/WinHandle.hpp>
#include <util/util.hpp>
#include <json11.hpp>
#ifdef BROWSER_AVAILABLE
#include <browser-panel.hpp>
#endif
using namespace std;
using namespace json11;
using namespace updater;
/* ------------------------------------------------------------------------ */
@ -71,60 +71,41 @@ using namespace json11;
#define CUR_COMMIT "00000000"
#endif
static bool ParseUpdateManifest(const char *manifest, bool *updatesAvailable,
string &notes_str, uint64_t &updateVer,
string &branch)
static bool ParseUpdateManifest(const char *manifest_data,
bool *updatesAvailable, string &notes,
uint64_t &updateVer, const string &branch)
try {
json manifestContents = json::parse(manifest_data);
Manifest manifest = manifestContents.get<Manifest>();
string error;
Json root = Json::parse(manifest, error);
if (!error.empty())
throw strprintf("Failed reading json string: %s",
error.c_str());
if (manifest.version_major == 0 && manifest.commit.empty())
throw strprintf("Invalid version number: %d.%d.%d",
manifest.version_major, manifest.version_minor,
manifest.version_patch);
if (!root.is_object())
throw string("Root of manifest is not an object");
int major = root["version_major"].int_value();
int minor = root["version_minor"].int_value();
int patch = root["version_patch"].int_value();
int rc = root["rc"].int_value();
int beta = root["beta"].int_value();
string commit_hash = root["commit"].string_value();
if (major == 0 && commit_hash.empty())
throw strprintf("Invalid version number: %d.%d.%d", major,
minor, patch);
const Json &notes = root["notes"];
if (!notes.is_string())
throw string("'notes' value invalid");
notes_str = notes.string_value();
const Json &packages = root["packages"];
if (!packages.is_array())
throw string("'packages' value invalid");
notes = manifest.notes;
uint64_t cur_ver;
uint64_t new_ver;
if (commit_hash.empty()) {
if (manifest.commit.empty()) {
cur_ver = CUR_VER;
new_ver = MAKE_SEMANTIC_VERSION(
(uint64_t)major, (uint64_t)minor, (uint64_t)patch);
new_ver =
MAKE_SEMANTIC_VERSION((uint64_t)manifest.version_major,
(uint64_t)manifest.version_minor,
(uint64_t)manifest.version_patch);
new_ver <<= 16;
/* RC builds are shifted so that rc1 and beta1 versions do not result
* in the same new_ver. */
if (rc > 0)
new_ver |= (uint64_t)rc << 8;
else if (beta > 0)
new_ver |= (uint64_t)beta;
if (manifest.rc > 0)
new_ver |= (uint64_t)manifest.rc << 8;
else if (manifest.beta > 0)
new_ver |= (uint64_t)manifest.beta;
} else {
/* Test or nightly builds may not have a (valid) version number,
* so compare commit hashes instead. */
cur_ver = stoul(CUR_COMMIT, nullptr, 16);
new_ver = stoul(commit_hash.substr(0, 8), nullptr, 16);
new_ver = stoul(manifest.commit.substr(0, 8), nullptr, 16);
}
updateVer = new_ver;

View File

@ -53,17 +53,17 @@ struct Manifest {
uint8_t version_patch = 0;
uint8_t beta = 0;
uint8_t rc = 0;
std::string commit;
/* Hash of VC redist file */
std::string vc2019_redist_x64;
/* Unused until UI is migrated to nlohmann_json */
// std::string commit;
// std::string notes;
/* Release notes in HTML format */
std::string notes;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(Manifest, packages, version_major,
version_minor, version_patch, beta, rc,
vc2019_redist_x64)
commit, vc2019_redist_x64, notes)
};
struct PatchRequest {

View File

@ -97,13 +97,12 @@
#include <QWindow>
#include <json11.hpp>
#include "update/models/whatsnew.hpp"
#ifdef ENABLE_WAYLAND
#include <obs-nix-platform.h>
#endif
using namespace json11;
using namespace std;
#ifdef BROWSER_AVAILABLE
@ -2399,54 +2398,52 @@ void OBSBasic::ReceivedIntroJson(const QString &text)
if (closing)
return;
std::string err;
Json json = Json::parse(QT_TO_UTF8(text), err);
if (!err.empty())
WhatsNewList items;
try {
nlohmann::json json = nlohmann::json::parse(text.toStdString());
items = json.get<WhatsNewList>();
} catch (nlohmann::json::exception &e) {
blog(LOG_WARNING, "Parsing whatsnew data failed: %s", e.what());
return;
}
std::string info_url;
int info_increment = -1;
/* check to see if there's an info page for this version */
const Json::array &items = json.array_items();
for (const Json &item : items) {
if (item["os"].is_object()) {
Json::object platforms = item["os"].object_items();
for (const WhatsNewItem &item : items) {
if (item.os) {
WhatsNewPlatforms platforms = *item.os;
#ifdef _WIN32
if (!platforms["windows"].bool_value())
if (!platforms.windows)
continue;
#elif defined(__APPLE__)
if (!platforms["macos"].bool_value())
if (!platforms.macos)
continue;
#else
if (!platforms["linux"].bool_value())
if (!platforms.linux)
continue;
#endif
}
const std::string &version = item["version"].string_value();
const std::string &url = item["url"].string_value();
int increment = item["increment"].int_value();
int beta = item["Beta"].int_value();
int rc = item["RC"].int_value();
int major = 0;
int minor = 0;
sscanf(version.c_str(), "%d.%d", &major, &minor);
sscanf(item.version.c_str(), "%d.%d", &major, &minor);
#if defined(OBS_RELEASE_CANDIDATE) && OBS_RELEASE_CANDIDATE > 0
if (major == OBS_RELEASE_CANDIDATE_MAJOR &&
minor == OBS_RELEASE_CANDIDATE_MINOR &&
rc == OBS_RELEASE_CANDIDATE) {
item.RC == OBS_RELEASE_CANDIDATE) {
#elif OBS_BETA > 0
if (major == OBS_BETA_MAJOR && minor == OBS_BETA_MINOR &&
beta == OBS_BETA) {
item.Beta == OBS_BETA) {
#else
if (major == LIBOBS_API_MAJOR_VER &&
minor == LIBOBS_API_MINOR_VER && rc == 0 && beta == 0) {
minor == LIBOBS_API_MINOR_VER && item.RC == 0 &&
item.Beta == 0) {
#endif
info_url = url;
info_increment = increment;
info_url = item.url;
info_increment = item.increment;
}
}