Jelajahi Sumber

UI: Migrate WhatsNew to nlohmann JSON

derrod 2 tahun lalu
induk
melakukan
8955338624

+ 2 - 1
UI/cmake/feature-macos-update.cmake

@@ -14,7 +14,8 @@ target_sources(
           update/shared-update.hpp
           update/shared-update.hpp
           update/update-helpers.cpp
           update/update-helpers.cpp
           update/update-helpers.hpp
           update/update-helpers.hpp
-          update/models/branches.hpp)
+          update/models/branches.hpp
+          update/models/whatsnew.hpp)
 
 
 target_link_libraries(obs-studio PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Security.framework>" nlohmann_json::nlohmann_json
 target_link_libraries(obs-studio PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Security.framework>" nlohmann_json::nlohmann_json
                                          OBS::blake2)
                                          OBS::blake2)

+ 10 - 3
UI/cmake/feature-whatsnew.cmake

@@ -5,11 +5,18 @@ if(ENABLE_WHATSNEW AND TARGET OBS::browser-panels)
     include(cmake/feature-macos-update.cmake)
     include(cmake/feature-macos-update.cmake)
   elseif(OS_LINUX)
   elseif(OS_LINUX)
     find_package(MbedTLS REQUIRED)
     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(
     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()
   endif()
 
 
   target_enable_feature(obs-studio "What's New panel" WHATSNEW_ENABLED)
   target_enable_feature(obs-studio "What's New panel" WHATSNEW_ENABLED)

+ 5 - 2
UI/cmake/legacy.cmake

@@ -358,6 +358,7 @@ if(OS_WINDOWS)
             update/crypto-helpers-mbedtls.cpp
             update/crypto-helpers-mbedtls.cpp
             update/crypto-helpers.hpp
             update/crypto-helpers.hpp
             update/models/branches.hpp
             update/models/branches.hpp
+            update/models/whatsnew.hpp
             win-update/updater/manifest.hpp
             win-update/updater/manifest.hpp
             ${CMAKE_BINARY_DIR}/obs.rc)
             ${CMAKE_BINARY_DIR}/obs.rc)
 
 
@@ -438,7 +439,8 @@ elseif(OS_MACOS)
               update/shared-update.cpp
               update/shared-update.cpp
               update/shared-update.hpp
               update/shared-update.hpp
               update/update-helpers.cpp
               update/update-helpers.cpp
-              update/update-helpers.hpp)
+              update/update-helpers.hpp
+              update/models/whatsnew.hpp)
 
 
     if(SPARKLE_APPCAST_URL AND SPARKLE_PUBLIC_KEY)
     if(SPARKLE_APPCAST_URL AND SPARKLE_PUBLIC_KEY)
       find_library(SPARKLE Sparkle)
       find_library(SPARKLE Sparkle)
@@ -477,13 +479,14 @@ elseif(OS_POSIX)
 
 
   if(OS_LINUX AND ENABLE_WHATSNEW)
   if(OS_LINUX AND ENABLE_WHATSNEW)
     find_package(MbedTLS)
     find_package(MbedTLS)
+    find_package(nlohmann_json REQUIRED)
     if(NOT MBEDTLS_FOUND)
     if(NOT MBEDTLS_FOUND)
       obs_status(FATAL_ERROR "mbedTLS not found, but required for WhatsNew support on Linux")
       obs_status(FATAL_ERROR "mbedTLS not found, but required for WhatsNew support on Linux")
     endif()
     endif()
 
 
     target_sources(obs PRIVATE update/crypto-helpers.hpp update/crypto-helpers-mbedtls.cpp update/shared-update.cpp
     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)
                                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()
 endif()
 endif()
 
 

+ 1 - 0
UI/cmake/os-windows.cmake

@@ -29,6 +29,7 @@ target_sources(
           update/win-update.cpp
           update/win-update.cpp
           update/win-update.hpp
           update/win-update.hpp
           update/models/branches.hpp
           update/models/branches.hpp
+          update/models/whatsnew.hpp
           win-update/updater/manifest.hpp)
           win-update/updater/manifest.hpp)
 
 
 target_link_libraries(obs-studio PRIVATE crypt32 OBS::blake2 OBS::w32-pthreads MbedTLS::MbedTLS
 target_link_libraries(obs-studio PRIVATE crypt32 OBS::blake2 OBS::w32-pthreads MbedTLS::MbedTLS

+ 93 - 0
UI/update/models/whatsnew.hpp

@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2023 Dennis Sädtler <[email protected]>
+ *
+ * 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>;

+ 21 - 24
UI/window-basic-main.cpp

@@ -97,13 +97,12 @@
 
 
 #include <QWindow>
 #include <QWindow>
 
 
-#include <json11.hpp>
+#include "update/models/whatsnew.hpp"
 
 
 #ifdef ENABLE_WAYLAND
 #ifdef ENABLE_WAYLAND
 #include <obs-nix-platform.h>
 #include <obs-nix-platform.h>
 #endif
 #endif
 
 
-using namespace json11;
 using namespace std;
 using namespace std;
 
 
 #ifdef BROWSER_AVAILABLE
 #ifdef BROWSER_AVAILABLE
@@ -2397,54 +2396,52 @@ void OBSBasic::ReceivedIntroJson(const QString &text)
 	if (closing)
 	if (closing)
 		return;
 		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;
 		return;
+	}
 
 
 	std::string info_url;
 	std::string info_url;
 	int info_increment = -1;
 	int info_increment = -1;
 
 
 	/* check to see if there's an info page for this version */
 	/* 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
 #ifdef _WIN32
-			if (!platforms["windows"].bool_value())
+			if (!platforms.windows)
 				continue;
 				continue;
 #elif defined(__APPLE__)
 #elif defined(__APPLE__)
-			if (!platforms["macos"].bool_value())
+			if (!platforms.macos)
 				continue;
 				continue;
 #else
 #else
-			if (!platforms["linux"].bool_value())
+			if (!platforms.linux)
 				continue;
 				continue;
 #endif
 #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 major = 0;
 		int minor = 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 defined(OBS_RELEASE_CANDIDATE) && OBS_RELEASE_CANDIDATE > 0
 		if (major == OBS_RELEASE_CANDIDATE_MAJOR &&
 		if (major == OBS_RELEASE_CANDIDATE_MAJOR &&
 		    minor == OBS_RELEASE_CANDIDATE_MINOR &&
 		    minor == OBS_RELEASE_CANDIDATE_MINOR &&
-		    rc == OBS_RELEASE_CANDIDATE) {
+		    item.RC == OBS_RELEASE_CANDIDATE) {
 #elif OBS_BETA > 0
 #elif OBS_BETA > 0
 		if (major == OBS_BETA_MAJOR && minor == OBS_BETA_MINOR &&
 		if (major == OBS_BETA_MAJOR && minor == OBS_BETA_MINOR &&
-		    beta == OBS_BETA) {
+		    item.Beta == OBS_BETA) {
 #else
 #else
 		if (major == LIBOBS_API_MAJOR_VER &&
 		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
 #endif
-			info_url = url;
-			info_increment = increment;
+			info_url = item.url;
+			info_increment = item.increment;
 		}
 		}
 	}
 	}