Enhance debugging capabilities and update build configuration
- Introduced a new debug logging mechanism by defining `dbg_log` for conditional logging based on the `DEBUG_BUILD` option. - Updated `build.ps1` to include a debug flag for CMake configuration. - Refactored logging calls across multiple source files to utilize the new `dbg_log` function, improving consistency and clarity in debug output. - Added a new header file `debug-log.h` to centralize debug logging definitions.
This commit is contained in:
@@ -160,8 +160,11 @@ else()
|
|||||||
set(_PLUGIN_VER "${PROJECT_VERSION}")
|
set(_PLUGIN_VER "${PROJECT_VERSION}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
option(DEBUG_BUILD "Debug build: show update dialog but don't stop server" OFF)
|
||||||
|
|
||||||
target_compile_definitions(easy-irl-stream PRIVATE
|
target_compile_definitions(easy-irl-stream PRIVATE
|
||||||
PLUGIN_VERSION="${_PLUGIN_VER}"
|
PLUGIN_VERSION="${_PLUGIN_VER}"
|
||||||
|
$<$<BOOL:${DEBUG_BUILD}>:DEBUG_BUILD>
|
||||||
)
|
)
|
||||||
|
|
||||||
set_target_properties(easy-irl-stream PROPERTIES PREFIX "")
|
set_target_properties(easy-irl-stream PROPERTIES PREFIX "")
|
||||||
|
|||||||
@@ -90,6 +90,8 @@ if (-not (Test-Path "$OBS_LIBS\obs.lib") -or (Get-Item "$OBS_LIBS\obs.lib").Leng
|
|||||||
|
|
||||||
# --- 5. Build ---
|
# --- 5. Build ---
|
||||||
Write-Host "[5/5] Building..."
|
Write-Host "[5/5] Building..."
|
||||||
|
$debugFlag = if ($env:DEBUG_BUILD -eq "1") { "-DDEBUG_BUILD=ON" } else { "-DDEBUG_BUILD=OFF" }
|
||||||
|
|
||||||
cmake -S $ROOT -B $BUILD_DIR -G "Ninja" `
|
cmake -S $ROOT -B $BUILD_DIR -G "Ninja" `
|
||||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo `
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo `
|
||||||
-DCMAKE_C_COMPILER=cl `
|
-DCMAKE_C_COMPILER=cl `
|
||||||
@@ -97,7 +99,8 @@ cmake -S $ROOT -B $BUILD_DIR -G "Ninja" `
|
|||||||
-DOBS_SOURCE_DIR="$OBS_SRC" `
|
-DOBS_SOURCE_DIR="$OBS_SRC" `
|
||||||
-DOBS_LIB_DIR="$OBS_LIBS" `
|
-DOBS_LIB_DIR="$OBS_LIBS" `
|
||||||
-DFFMPEG_DIR="$OBS_DEPS" `
|
-DFFMPEG_DIR="$OBS_DEPS" `
|
||||||
-DQT6_DIR="$QT6_DIR"
|
-DQT6_DIR="$QT6_DIR" `
|
||||||
|
$debugFlag
|
||||||
|
|
||||||
cmake --build $BUILD_DIR --config RelWithDebInfo
|
cmake --build $BUILD_DIR --config RelWithDebInfo
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <obs-module.h>
|
||||||
|
|
||||||
|
#ifndef PLUGIN_NAME
|
||||||
|
#define PLUGIN_NAME "Easy IRL Stream"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG_BUILD
|
||||||
|
#define dbg_log(...) blog(__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define dbg_log(...) ((void)0)
|
||||||
|
#endif
|
||||||
+6
-6
@@ -131,7 +131,7 @@ static void fire_low_quality_actions(struct irl_source_data *data)
|
|||||||
char *src_copy = bstrdup(src_name ? src_name : "Easy IRL Stream");
|
char *src_copy = bstrdup(src_name ? src_name : "Easy IRL Stream");
|
||||||
pthread_mutex_unlock(&data->mutex);
|
pthread_mutex_unlock(&data->mutex);
|
||||||
|
|
||||||
blog(LOG_DEBUG, "[%s] Low quality detected (%lld kbps)", PLUGIN_NAME,
|
dbg_log(LOG_DEBUG, "[%s] Low quality detected (%lld kbps)", PLUGIN_NAME,
|
||||||
(long long)data->current_bitrate_kbps);
|
(long long)data->current_bitrate_kbps);
|
||||||
|
|
||||||
queue_scene_switch(scene);
|
queue_scene_switch(scene);
|
||||||
@@ -168,7 +168,7 @@ static void fire_quality_recovered_actions(struct irl_source_data *data)
|
|||||||
char *src_copy = bstrdup(src_name ? src_name : "Easy IRL Stream");
|
char *src_copy = bstrdup(src_name ? src_name : "Easy IRL Stream");
|
||||||
pthread_mutex_unlock(&data->mutex);
|
pthread_mutex_unlock(&data->mutex);
|
||||||
|
|
||||||
blog(LOG_DEBUG, "[%s] Quality recovered (%lld kbps)", PLUGIN_NAME,
|
dbg_log(LOG_DEBUG, "[%s] Quality recovered (%lld kbps)", PLUGIN_NAME,
|
||||||
(long long)data->current_bitrate_kbps);
|
(long long)data->current_bitrate_kbps);
|
||||||
|
|
||||||
queue_scene_switch(scene);
|
queue_scene_switch(scene);
|
||||||
@@ -210,7 +210,7 @@ static void fire_disconnect_actions(struct irl_source_data *data)
|
|||||||
char *src_copy = bstrdup(src_name ? src_name : "Easy IRL Stream");
|
char *src_copy = bstrdup(src_name ? src_name : "Easy IRL Stream");
|
||||||
pthread_mutex_unlock(&data->mutex);
|
pthread_mutex_unlock(&data->mutex);
|
||||||
|
|
||||||
blog(LOG_DEBUG, "[%s] Firing disconnect actions", PLUGIN_NAME);
|
dbg_log(LOG_DEBUG, "[%s] Firing disconnect actions", PLUGIN_NAME);
|
||||||
|
|
||||||
queue_scene_switch(scene);
|
queue_scene_switch(scene);
|
||||||
queue_overlay(overlay, true);
|
queue_overlay(overlay, true);
|
||||||
@@ -249,7 +249,7 @@ static void fire_reconnect_actions(struct irl_source_data *data)
|
|||||||
char *src_copy = bstrdup(src_name ? src_name : "Easy IRL Stream");
|
char *src_copy = bstrdup(src_name ? src_name : "Easy IRL Stream");
|
||||||
pthread_mutex_unlock(&data->mutex);
|
pthread_mutex_unlock(&data->mutex);
|
||||||
|
|
||||||
blog(LOG_DEBUG, "[%s] Firing reconnect actions", PLUGIN_NAME);
|
dbg_log(LOG_DEBUG, "[%s] Firing reconnect actions", PLUGIN_NAME);
|
||||||
|
|
||||||
queue_scene_switch(scene);
|
queue_scene_switch(scene);
|
||||||
queue_overlay(overlay, false);
|
queue_overlay(overlay, false);
|
||||||
@@ -272,7 +272,7 @@ static void fire_reconnect_actions(struct irl_source_data *data)
|
|||||||
|
|
||||||
void event_handler_on_connect(struct irl_source_data *data)
|
void event_handler_on_connect(struct irl_source_data *data)
|
||||||
{
|
{
|
||||||
blog(LOG_DEBUG, "[%s] Client connected", PLUGIN_NAME);
|
dbg_log(LOG_DEBUG, "[%s] Client connected", PLUGIN_NAME);
|
||||||
|
|
||||||
bool was_disconnected;
|
bool was_disconnected;
|
||||||
pthread_mutex_lock(&data->mutex);
|
pthread_mutex_lock(&data->mutex);
|
||||||
@@ -295,7 +295,7 @@ void event_handler_on_connect(struct irl_source_data *data)
|
|||||||
|
|
||||||
void event_handler_on_disconnect(struct irl_source_data *data)
|
void event_handler_on_disconnect(struct irl_source_data *data)
|
||||||
{
|
{
|
||||||
blog(LOG_DEBUG, "[%s] Client disconnected", PLUGIN_NAME);
|
dbg_log(LOG_DEBUG, "[%s] Client disconnected", PLUGIN_NAME);
|
||||||
|
|
||||||
pthread_mutex_lock(&data->mutex);
|
pthread_mutex_lock(&data->mutex);
|
||||||
data->disconnect_time_ns = os_gettime_ns();
|
data->disconnect_time_ns = os_gettime_ns();
|
||||||
|
|||||||
+7
-7
@@ -40,7 +40,7 @@ static void build_url(struct irl_source_data *data, char *buf, size_t sz)
|
|||||||
dstr_catf(&url, "&passphrase=%s",
|
dstr_catf(&url, "&passphrase=%s",
|
||||||
data->srt_passphrase);
|
data->srt_passphrase);
|
||||||
} else {
|
} else {
|
||||||
blog(LOG_WARNING,
|
dbg_log(LOG_WARNING,
|
||||||
"[%s] SRT passphrase ignored: "
|
"[%s] SRT passphrase ignored: "
|
||||||
"must be 10-79 characters (got %zu)",
|
"must be 10-79 characters (got %zu)",
|
||||||
PLUGIN_NAME, plen);
|
PLUGIN_NAME, plen);
|
||||||
@@ -94,7 +94,7 @@ static void *ingest_thread_func(void *arg)
|
|||||||
|
|
||||||
os_atomic_set_long(&data->connection_state,
|
os_atomic_set_long(&data->connection_state,
|
||||||
CONN_STATE_LISTENING);
|
CONN_STATE_LISTENING);
|
||||||
blog(LOG_DEBUG, "[%s] Listening: %s", PLUGIN_NAME, url);
|
dbg_log(LOG_DEBUG, "[%s] Listening: %s", PLUGIN_NAME, url);
|
||||||
|
|
||||||
AVFormatContext *fmt_ctx = avformat_alloc_context();
|
AVFormatContext *fmt_ctx = avformat_alloc_context();
|
||||||
if (!fmt_ctx) {
|
if (!fmt_ctx) {
|
||||||
@@ -119,7 +119,7 @@ static void *ingest_thread_func(void *arg)
|
|||||||
break;
|
break;
|
||||||
char errbuf[256];
|
char errbuf[256];
|
||||||
av_strerror(ret, errbuf, sizeof(errbuf));
|
av_strerror(ret, errbuf, sizeof(errbuf));
|
||||||
blog(LOG_WARNING,
|
dbg_log(LOG_WARNING,
|
||||||
"[%s] avformat_open_input failed: %s",
|
"[%s] avformat_open_input failed: %s",
|
||||||
PLUGIN_NAME, errbuf);
|
PLUGIN_NAME, errbuf);
|
||||||
os_sleep_ms(2000);
|
os_sleep_ms(2000);
|
||||||
@@ -130,7 +130,7 @@ static void *ingest_thread_func(void *arg)
|
|||||||
|
|
||||||
ret = avformat_find_stream_info(fmt_ctx, NULL);
|
ret = avformat_find_stream_info(fmt_ctx, NULL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
blog(LOG_WARNING, "[%s] Could not find stream info",
|
dbg_log(LOG_WARNING, "[%s] Could not find stream info",
|
||||||
PLUGIN_NAME);
|
PLUGIN_NAME);
|
||||||
avformat_close_input(&data->fmt_ctx);
|
avformat_close_input(&data->fmt_ctx);
|
||||||
data->fmt_ctx = NULL;
|
data->fmt_ctx = NULL;
|
||||||
@@ -191,7 +191,7 @@ static void *ingest_thread_func(void *arg)
|
|||||||
srtla_server_stop(&data->srtla);
|
srtla_server_stop(&data->srtla);
|
||||||
|
|
||||||
os_atomic_set_long(&data->connection_state, CONN_STATE_IDLE);
|
os_atomic_set_long(&data->connection_state, CONN_STATE_IDLE);
|
||||||
blog(LOG_DEBUG, "[%s] Ingest thread exited", PLUGIN_NAME);
|
dbg_log(LOG_DEBUG, "[%s] Ingest thread exited", PLUGIN_NAME);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,7 +207,7 @@ void ingest_thread_start(struct irl_source_data *data)
|
|||||||
data) == 0) {
|
data) == 0) {
|
||||||
data->thread_created = true;
|
data->thread_created = true;
|
||||||
} else {
|
} else {
|
||||||
blog(LOG_ERROR, "[%s] Failed to create ingest thread",
|
dbg_log(LOG_ERROR, "[%s] Failed to create ingest thread",
|
||||||
PLUGIN_NAME);
|
PLUGIN_NAME);
|
||||||
data->active = false;
|
data->active = false;
|
||||||
}
|
}
|
||||||
@@ -224,5 +224,5 @@ void ingest_thread_stop(struct irl_source_data *data)
|
|||||||
data->thread_created = false;
|
data->thread_created = false;
|
||||||
|
|
||||||
os_atomic_set_long(&data->connection_state, CONN_STATE_IDLE);
|
os_atomic_set_long(&data->connection_state, CONN_STATE_IDLE);
|
||||||
blog(LOG_DEBUG, "[%s] Ingest thread stopped", PLUGIN_NAME);
|
dbg_log(LOG_DEBUG, "[%s] Ingest thread stopped", PLUGIN_NAME);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
#define PLUGIN_NAME "Easy IRL Stream"
|
#define PLUGIN_NAME "Easy IRL Stream"
|
||||||
#define SOURCE_ID "easy_irl_stream_source"
|
#define SOURCE_ID "easy_irl_stream_source"
|
||||||
|
|
||||||
|
#include "debug-log.h"
|
||||||
|
|
||||||
/* IP detection globals (filled by plugin-main.c on startup) */
|
/* IP detection globals (filled by plugin-main.c on startup) */
|
||||||
extern char g_local_ip[64];
|
extern char g_local_ip[64];
|
||||||
extern char g_external_ip[64];
|
extern char g_external_ip[64];
|
||||||
|
|||||||
+8
-8
@@ -36,7 +36,7 @@ bool decoder_open(struct irl_source_data *data)
|
|||||||
data->stats_video_width = par->width;
|
data->stats_video_width = par->width;
|
||||||
data->stats_video_height = par->height;
|
data->stats_video_height = par->height;
|
||||||
data->stats_video_pixfmt[0] = '\0';
|
data->stats_video_pixfmt[0] = '\0';
|
||||||
blog(LOG_DEBUG,
|
dbg_log(LOG_DEBUG,
|
||||||
"[%s] Video stream #%u: %s %dx%d",
|
"[%s] Video stream #%u: %s %dx%d",
|
||||||
PLUGIN_NAME, i, codec->name, par->width,
|
PLUGIN_NAME, i, codec->name, par->width,
|
||||||
par->height);
|
par->height);
|
||||||
@@ -64,7 +64,7 @@ bool decoder_open(struct irl_source_data *data)
|
|||||||
sizeof(data->stats_audio_codec), "%s",
|
sizeof(data->stats_audio_codec), "%s",
|
||||||
codec->name);
|
codec->name);
|
||||||
data->stats_audio_sample_rate = par->sample_rate;
|
data->stats_audio_sample_rate = par->sample_rate;
|
||||||
blog(LOG_DEBUG,
|
dbg_log(LOG_DEBUG,
|
||||||
"[%s] Audio stream #%u: %s %dHz",
|
"[%s] Audio stream #%u: %s %dHz",
|
||||||
PLUGIN_NAME, i, codec->name,
|
PLUGIN_NAME, i, codec->name,
|
||||||
par->sample_rate);
|
par->sample_rate);
|
||||||
@@ -72,7 +72,7 @@ bool decoder_open(struct irl_source_data *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (data->video_stream_idx < 0) {
|
if (data->video_stream_idx < 0) {
|
||||||
blog(LOG_WARNING, "[%s] No video stream found", PLUGIN_NAME);
|
dbg_log(LOG_WARNING, "[%s] No video stream found", PLUGIN_NAME);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ static void output_video_frame(struct irl_source_data *data, AVFrame *frame)
|
|||||||
data->sws_width = w;
|
data->sws_width = w;
|
||||||
data->sws_height = h;
|
data->sws_height = h;
|
||||||
data->sws_src_fmt = src_fmt;
|
data->sws_src_fmt = src_fmt;
|
||||||
blog(LOG_DEBUG,
|
dbg_log(LOG_DEBUG,
|
||||||
"[%s] Video: %s %dx%d -> direct output (fmt=%d, full_range=%d)",
|
"[%s] Video: %s %dx%d -> direct output (fmt=%d, full_range=%d)",
|
||||||
PLUGIN_NAME,
|
PLUGIN_NAME,
|
||||||
av_get_pix_fmt_name(src_fmt), w, h,
|
av_get_pix_fmt_name(src_fmt), w, h,
|
||||||
@@ -220,7 +220,7 @@ static void output_video_frame(struct irl_source_data *data, AVFrame *frame)
|
|||||||
data->sws_height = h;
|
data->sws_height = h;
|
||||||
data->sws_src_fmt = src_fmt;
|
data->sws_src_fmt = src_fmt;
|
||||||
|
|
||||||
blog(LOG_DEBUG,
|
dbg_log(LOG_DEBUG,
|
||||||
"[%s] Video: %s %dx%d -> NV12 sws conversion",
|
"[%s] Video: %s %dx%d -> NV12 sws conversion",
|
||||||
PLUGIN_NAME,
|
PLUGIN_NAME,
|
||||||
av_get_pix_fmt_name(src_fmt), w, h);
|
av_get_pix_fmt_name(src_fmt), w, h);
|
||||||
@@ -329,7 +329,7 @@ bool decoder_decode_packet(struct irl_source_data *data, AVPacket *pkt)
|
|||||||
|
|
||||||
if (send_ret < 0) {
|
if (send_ret < 0) {
|
||||||
if (data->dec_vid_pkt_count <= 5)
|
if (data->dec_vid_pkt_count <= 5)
|
||||||
blog(LOG_WARNING,
|
dbg_log(LOG_WARNING,
|
||||||
"[%s] avcodec_send_packet failed: %d (pkt #%d, size=%d)",
|
"[%s] avcodec_send_packet failed: %d (pkt #%d, size=%d)",
|
||||||
PLUGIN_NAME, send_ret,
|
PLUGIN_NAME, send_ret,
|
||||||
data->dec_vid_pkt_count, pkt->size);
|
data->dec_vid_pkt_count, pkt->size);
|
||||||
@@ -341,7 +341,7 @@ bool decoder_decode_packet(struct irl_source_data *data, AVPacket *pkt)
|
|||||||
data->dec_vid_frame_count++;
|
data->dec_vid_frame_count++;
|
||||||
if (data->dec_vid_frame_count <= 3 ||
|
if (data->dec_vid_frame_count <= 3 ||
|
||||||
(data->dec_vid_frame_count % 300 == 0))
|
(data->dec_vid_frame_count % 300 == 0))
|
||||||
blog(LOG_DEBUG,
|
dbg_log(LOG_DEBUG,
|
||||||
"[%s] Video frame #%d decoded (fmt=%d %dx%d)",
|
"[%s] Video frame #%d decoded (fmt=%d %dx%d)",
|
||||||
PLUGIN_NAME,
|
PLUGIN_NAME,
|
||||||
data->dec_vid_frame_count,
|
data->dec_vid_frame_count,
|
||||||
@@ -355,7 +355,7 @@ bool decoder_decode_packet(struct irl_source_data *data, AVPacket *pkt)
|
|||||||
|
|
||||||
if (data->dec_vid_pkt_count == 30 &&
|
if (data->dec_vid_pkt_count == 30 &&
|
||||||
data->dec_vid_frame_count == 0)
|
data->dec_vid_frame_count == 0)
|
||||||
blog(LOG_WARNING,
|
dbg_log(LOG_WARNING,
|
||||||
"[%s] 30 video packets sent but 0 frames decoded",
|
"[%s] 30 video packets sent but 0 frames decoded",
|
||||||
PLUGIN_NAME);
|
PLUGIN_NAME);
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -35,7 +35,8 @@ static void xor_dec(char *out, const XorStr<N> &x)
|
|||||||
OBF_FUNC(obf_stools_host, "stools.cc")
|
OBF_FUNC(obf_stools_host, "stools.cc")
|
||||||
OBF_FUNC(obf_api_settings_path, "/api/plugin/settings")
|
OBF_FUNC(obf_api_settings_path, "/api/plugin/settings")
|
||||||
OBF_FUNC(obf_api_obs_info_path, "/api/plugin/obs-info")
|
OBF_FUNC(obf_api_obs_info_path, "/api/plugin/obs-info")
|
||||||
OBF_FUNC(obf_api_version_path, "/api/plugin/version")
|
OBF_FUNC(obf_api_me_path, "/api/me")
|
||||||
|
OBF_FUNC(obf_api_releases_path, "/api/releases/easy-irl-stream")
|
||||||
OBF_FUNC(obf_dash_tools_path, "/dashboard/tools")
|
OBF_FUNC(obf_dash_tools_path, "/dashboard/tools")
|
||||||
OBF_FUNC(obf_dash_downloads_path, "/dashboard/downloads")
|
OBF_FUNC(obf_dash_downloads_path, "/dashboard/downloads")
|
||||||
OBF_FUNC(obf_ipify_host, "api.ipify.org")
|
OBF_FUNC(obf_ipify_host, "api.ipify.org")
|
||||||
|
|||||||
+2
-11
@@ -1,15 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
/* Simple XOR encode/decode — symmetric operation */
|
|
||||||
static inline void xor_crypt(char *buf, const char *src, size_t len)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < len; i++)
|
|
||||||
buf[i] = src[i] ^ 0x5A;
|
|
||||||
buf[len] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Obfuscated string accessors (implemented in obfuscation.cpp) */
|
/* Obfuscated string accessors (implemented in obfuscation.cpp) */
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -18,7 +8,8 @@ extern "C" {
|
|||||||
const char *obf_stools_host(void);
|
const char *obf_stools_host(void);
|
||||||
const char *obf_api_settings_path(void);
|
const char *obf_api_settings_path(void);
|
||||||
const char *obf_api_obs_info_path(void);
|
const char *obf_api_obs_info_path(void);
|
||||||
const char *obf_api_version_path(void);
|
const char *obf_api_me_path(void);
|
||||||
|
const char *obf_api_releases_path(void);
|
||||||
const char *obf_dash_tools_path(void);
|
const char *obf_dash_tools_path(void);
|
||||||
const char *obf_dash_downloads_path(void);
|
const char *obf_dash_downloads_path(void);
|
||||||
const char *obf_ipify_host(void);
|
const char *obf_ipify_host(void);
|
||||||
|
|||||||
+11
-183
@@ -1,4 +1,4 @@
|
|||||||
#include <obs-module.h>
|
#include <obs-module.h>
|
||||||
#include <obs-frontend-api.h>
|
#include <obs-frontend-api.h>
|
||||||
#include <util/threading.h>
|
#include <util/threading.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -25,6 +25,8 @@
|
|||||||
#include "irl-source.h"
|
#include "irl-source.h"
|
||||||
#include "obfuscation.h"
|
#include "obfuscation.h"
|
||||||
#include "translations.h"
|
#include "translations.h"
|
||||||
|
#include "help-dialog.hpp"
|
||||||
|
#include "stats-dialog.hpp"
|
||||||
|
|
||||||
OBS_DECLARE_MODULE()
|
OBS_DECLARE_MODULE()
|
||||||
|
|
||||||
@@ -184,10 +186,10 @@ void duckdns_update(const char *domain, const char *token)
|
|||||||
http_get_body(obf_duckdns_host(), path, result, sizeof(result));
|
http_get_body(obf_duckdns_host(), path, result, sizeof(result));
|
||||||
|
|
||||||
if (strncmp(result, "OK", 2) == 0 || strncmp(result, "KO", 2) == 0) {
|
if (strncmp(result, "OK", 2) == 0 || strncmp(result, "KO", 2) == 0) {
|
||||||
blog(LOG_DEBUG, "[%s] DuckDNS update for %s.duckdns.org: %s",
|
dbg_log(LOG_DEBUG, "[%s] DuckDNS update for %s.duckdns.org: %s",
|
||||||
PLUGIN_NAME, domain, result);
|
PLUGIN_NAME, domain, result);
|
||||||
} else {
|
} else {
|
||||||
blog(LOG_WARNING, "[%s] DuckDNS update failed: %s",
|
dbg_log(LOG_WARNING, "[%s] DuckDNS update failed: %s",
|
||||||
PLUGIN_NAME, result);
|
PLUGIN_NAME, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -230,7 +232,7 @@ static void *ip_detect_thread(void *arg)
|
|||||||
detect_local_ip();
|
detect_local_ip();
|
||||||
http_get_body(obf_ipify_host(), "/", g_external_ip,
|
http_get_body(obf_ipify_host(), "/", g_external_ip,
|
||||||
sizeof(g_external_ip));
|
sizeof(g_external_ip));
|
||||||
blog(LOG_DEBUG, "[%s] Local IP: %s, External IP: %s", PLUGIN_NAME,
|
dbg_log(LOG_DEBUG, "[%s] Local IP: %s, External IP: %s", PLUGIN_NAME,
|
||||||
g_local_ip, g_external_ip);
|
g_local_ip, g_external_ip);
|
||||||
|
|
||||||
while (g_ip_thread_active) {
|
while (g_ip_thread_active) {
|
||||||
@@ -246,7 +248,7 @@ static void *ip_detect_thread(void *arg)
|
|||||||
|
|
||||||
if (new_ip[0] && strcmp(new_ip, "?") != 0 &&
|
if (new_ip[0] && strcmp(new_ip, "?") != 0 &&
|
||||||
strcmp(new_ip, g_external_ip) != 0) {
|
strcmp(new_ip, g_external_ip) != 0) {
|
||||||
blog(LOG_DEBUG,
|
dbg_log(LOG_DEBUG,
|
||||||
"[%s] External IP changed: %s -> %s",
|
"[%s] External IP changed: %s -> %s",
|
||||||
PLUGIN_NAME, g_external_ip, new_ip);
|
PLUGIN_NAME, g_external_ip, new_ip);
|
||||||
snprintf(g_external_ip, sizeof(g_external_ip),
|
snprintf(g_external_ip, sizeof(g_external_ip),
|
||||||
@@ -258,161 +260,6 @@ static void *ip_detect_thread(void *arg)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---- Update check ---- */
|
|
||||||
|
|
||||||
static volatile bool g_update_required = false;
|
|
||||||
static char g_remote_version[64] = "";
|
|
||||||
|
|
||||||
struct update_mem_buf {
|
|
||||||
char *data;
|
|
||||||
size_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
static size_t update_write_cb(void *contents, size_t size, size_t nmemb,
|
|
||||||
void *userp)
|
|
||||||
{
|
|
||||||
size_t total = size * nmemb;
|
|
||||||
struct update_mem_buf *buf = (struct update_mem_buf *)userp;
|
|
||||||
char *tmp = realloc(buf->data, buf->size + total + 1);
|
|
||||||
if (!tmp) return 0;
|
|
||||||
buf->data = tmp;
|
|
||||||
memcpy(buf->data + buf->size, contents, total);
|
|
||||||
buf->size += total;
|
|
||||||
buf->data[buf->size] = '\0';
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int compare_versions(const char *a, const char *b)
|
|
||||||
{
|
|
||||||
int a1 = 0, a2 = 0, a3 = 0, b1 = 0, b2 = 0, b3 = 0;
|
|
||||||
sscanf(a, "%d.%d.%d", &a1, &a2, &a3);
|
|
||||||
sscanf(b, "%d.%d.%d", &b1, &b2, &b3);
|
|
||||||
if (a1 != b1) return a1 - b1;
|
|
||||||
if (a2 != b2) return a2 - b2;
|
|
||||||
return a3 - b3;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct update_ctx {
|
|
||||||
char version[64];
|
|
||||||
};
|
|
||||||
|
|
||||||
#include "help-dialog.hpp"
|
|
||||||
#include "stats-dialog.hpp"
|
|
||||||
|
|
||||||
static int curl_debug_cb(CURL *handle, curl_infotype type, char *data,
|
|
||||||
size_t size, void *userptr)
|
|
||||||
{
|
|
||||||
(void)handle;
|
|
||||||
(void)userptr;
|
|
||||||
|
|
||||||
const char *prefix;
|
|
||||||
switch (type) {
|
|
||||||
case CURLINFO_TEXT:
|
|
||||||
prefix = "* ";
|
|
||||||
break;
|
|
||||||
case CURLINFO_SSL_DATA_IN:
|
|
||||||
case CURLINFO_SSL_DATA_OUT:
|
|
||||||
return 0;
|
|
||||||
case CURLINFO_HEADER_IN:
|
|
||||||
prefix = "< ";
|
|
||||||
break;
|
|
||||||
case CURLINFO_HEADER_OUT:
|
|
||||||
prefix = "> ";
|
|
||||||
break;
|
|
||||||
case CURLINFO_DATA_IN:
|
|
||||||
case CURLINFO_DATA_OUT:
|
|
||||||
return 0;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char buf[1024];
|
|
||||||
size_t len = size < sizeof(buf) - 1 ? size : sizeof(buf) - 1;
|
|
||||||
memcpy(buf, data, len);
|
|
||||||
while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r'))
|
|
||||||
len--;
|
|
||||||
buf[len] = '\0';
|
|
||||||
|
|
||||||
blog(LOG_INFO, "[%s] curl: %s%s", PLUGIN_NAME, prefix, buf);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool check_update_blocking(void)
|
|
||||||
{
|
|
||||||
char url[256];
|
|
||||||
snprintf(url, sizeof(url), "%s%s%s",
|
|
||||||
obf_https_prefix(), obf_stools_host(),
|
|
||||||
obf_api_version_path());
|
|
||||||
|
|
||||||
char ua[128];
|
|
||||||
snprintf(ua, sizeof(ua), "%s%s", obf_ua_prefix(), PLUGIN_VERSION);
|
|
||||||
|
|
||||||
CURL *curl = curl_easy_init();
|
|
||||||
if (!curl) return false;
|
|
||||||
|
|
||||||
struct update_mem_buf buf = {NULL, 0};
|
|
||||||
char errbuf[CURL_ERROR_SIZE] = "";
|
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, update_write_cb);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buf);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3L);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, ua);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
|
||||||
#ifdef _WIN32
|
|
||||||
curl_easy_setopt(curl, CURLOPT_SSLVERSION,
|
|
||||||
CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, (long)CURLSSLOPT_NO_REVOKE);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION,
|
|
||||||
(long)CURL_HTTP_VERSION_1_1);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_ENABLE_ALPN, 0L);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, (long)CURL_IPRESOLVE_V4);
|
|
||||||
#endif
|
|
||||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, curl_debug_cb);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
|
|
||||||
|
|
||||||
CURLcode res = curl_easy_perform(curl);
|
|
||||||
long http_code = 0;
|
|
||||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
|
|
||||||
curl_easy_cleanup(curl);
|
|
||||||
|
|
||||||
if (res != CURLE_OK) {
|
|
||||||
blog(LOG_WARNING, "[%s] Update check failed: %s (%s)",
|
|
||||||
PLUGIN_NAME, curl_easy_strerror(res),
|
|
||||||
errbuf[0] ? errbuf : "no details");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res != CURLE_OK || http_code != 200 || !buf.data) {
|
|
||||||
free(buf.data);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *vkey = strstr(buf.data, "\"version\"");
|
|
||||||
if (!vkey) { free(buf.data); return false; }
|
|
||||||
const char *vstart = strchr(vkey + 9, '"');
|
|
||||||
if (!vstart) { free(buf.data); return false; }
|
|
||||||
vstart++;
|
|
||||||
const char *vend = strchr(vstart, '"');
|
|
||||||
if (!vend || vend - vstart > 60) { free(buf.data); return false; }
|
|
||||||
|
|
||||||
size_t vlen = (size_t)(vend - vstart);
|
|
||||||
memcpy(g_remote_version, vstart, vlen);
|
|
||||||
g_remote_version[vlen] = '\0';
|
|
||||||
free(buf.data);
|
|
||||||
|
|
||||||
return compare_versions(g_remote_version, PLUGIN_VERSION) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void task_show_forced_update(void *param)
|
|
||||||
{
|
|
||||||
struct update_ctx *ctx = param;
|
|
||||||
forced_update_show(ctx->version, obs_get_locale());
|
|
||||||
free(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---- Tools menu ---- */
|
/* ---- Tools menu ---- */
|
||||||
|
|
||||||
static void tools_menu_cb(void *private_data)
|
static void tools_menu_cb(void *private_data)
|
||||||
@@ -436,49 +283,30 @@ bool obs_module_load(void)
|
|||||||
|
|
||||||
curl_version_info_data *vi = curl_version_info(CURLVERSION_NOW);
|
curl_version_info_data *vi = curl_version_info(CURLVERSION_NOW);
|
||||||
if (vi) {
|
if (vi) {
|
||||||
blog(LOG_INFO,
|
dbg_log(LOG_INFO,
|
||||||
"[%s] curl %s, SSL: %s, features: 0x%x",
|
"[%s] curl %s, SSL: %s, features: 0x%x",
|
||||||
PLUGIN_NAME, vi->version,
|
PLUGIN_NAME, vi->version,
|
||||||
vi->ssl_version ? vi->ssl_version : "none",
|
vi->ssl_version ? vi->ssl_version : "none",
|
||||||
(unsigned)vi->features);
|
(unsigned)vi->features);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_update_blocking()) {
|
|
||||||
g_update_required = true;
|
|
||||||
blog(LOG_WARNING,
|
|
||||||
"[%s] Update required (v%s available), plugin disabled",
|
|
||||||
PLUGIN_NAME, g_remote_version);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
obs_register_source(&irl_source_info);
|
obs_register_source(&irl_source_info);
|
||||||
|
|
||||||
g_ip_thread_active = true;
|
g_ip_thread_active = true;
|
||||||
if (pthread_create(&g_ip_thread, NULL, ip_detect_thread, NULL) != 0)
|
if (pthread_create(&g_ip_thread, NULL, ip_detect_thread, NULL) != 0)
|
||||||
g_ip_thread_active = false;
|
g_ip_thread_active = false;
|
||||||
|
|
||||||
blog(LOG_INFO, "[%s] Plugin loaded (v%s)", PLUGIN_NAME, PLUGIN_VERSION);
|
dbg_log(LOG_INFO, "[%s] Plugin loaded (v%s)", PLUGIN_NAME, PLUGIN_VERSION);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs_module_post_load(void)
|
void obs_module_post_load(void)
|
||||||
{
|
{
|
||||||
if (g_update_required) {
|
|
||||||
struct update_ctx *ctx = malloc(sizeof(*ctx));
|
|
||||||
if (ctx) {
|
|
||||||
snprintf(ctx->version, sizeof(ctx->version), "%s",
|
|
||||||
g_remote_version);
|
|
||||||
obs_queue_task(OBS_TASK_UI, task_show_forced_update,
|
|
||||||
ctx, false);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
obs_frontend_add_tools_menu_item(tr_tools_menu_help(),
|
obs_frontend_add_tools_menu_item(tr_tools_menu_help(),
|
||||||
tools_menu_cb, NULL);
|
tools_menu_cb, NULL);
|
||||||
obs_frontend_add_tools_menu_item(tr_tools_menu_stats(),
|
obs_frontend_add_tools_menu_item(tr_tools_menu_stats(),
|
||||||
tools_stats_cb, NULL);
|
tools_stats_cb, NULL);
|
||||||
blog(LOG_DEBUG, "[%s] Tools menu registered", PLUGIN_NAME);
|
dbg_log(LOG_DEBUG, "[%s] Tools menu registered", PLUGIN_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
void obs_module_unload(void)
|
void obs_module_unload(void)
|
||||||
@@ -489,5 +317,5 @@ void obs_module_unload(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
curl_global_cleanup();
|
curl_global_cleanup();
|
||||||
blog(LOG_INFO, "[%s] Plugin unloaded", PLUGIN_NAME);
|
dbg_log(LOG_INFO, "[%s] Plugin unloaded", PLUGIN_NAME);
|
||||||
}
|
}
|
||||||
|
|||||||
+116
-7
@@ -81,7 +81,7 @@ static int curl_debug_cb(CURL *handle, curl_infotype type, char *data,
|
|||||||
len--;
|
len--;
|
||||||
buf[len] = '\0';
|
buf[len] = '\0';
|
||||||
|
|
||||||
blog(LOG_INFO, "[%s] curl: %s%s", PLUGIN_NAME, prefix, buf);
|
dbg_log(LOG_INFO, "[%s] curl: %s%s", PLUGIN_NAME, prefix, buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +159,7 @@ static char *api_get(const char *path, const char *token)
|
|||||||
curl_easy_cleanup(curl);
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
if (res != CURLE_OK) {
|
if (res != CURLE_OK) {
|
||||||
blog(LOG_WARNING, "[%s] API GET %s failed: %s (%s)",
|
dbg_log(LOG_WARNING, "[%s] API GET %s failed: %s (%s)",
|
||||||
PLUGIN_NAME, path, curl_easy_strerror(res),
|
PLUGIN_NAME, path, curl_easy_strerror(res),
|
||||||
errbuf[0] ? errbuf : "no details");
|
errbuf[0] ? errbuf : "no details");
|
||||||
maybe_show_ssl_error(res, errbuf);
|
maybe_show_ssl_error(res, errbuf);
|
||||||
@@ -167,7 +167,7 @@ static char *api_get(const char *path, const char *token)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (http_code != 200) {
|
if (http_code != 200) {
|
||||||
blog(LOG_WARNING, "[%s] API GET %s returned HTTP %ld",
|
dbg_log(LOG_WARNING, "[%s] API GET %s returned HTTP %ld",
|
||||||
PLUGIN_NAME, path, http_code);
|
PLUGIN_NAME, path, http_code);
|
||||||
free(buf.data);
|
free(buf.data);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -212,14 +212,14 @@ static bool api_post(const char *path, const char *token, const char *json_body)
|
|||||||
curl_easy_cleanup(curl);
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
if (res != CURLE_OK) {
|
if (res != CURLE_OK) {
|
||||||
blog(LOG_WARNING, "[%s] API POST %s failed: %s (%s)",
|
dbg_log(LOG_WARNING, "[%s] API POST %s failed: %s (%s)",
|
||||||
PLUGIN_NAME, path, curl_easy_strerror(res),
|
PLUGIN_NAME, path, curl_easy_strerror(res),
|
||||||
errbuf[0] ? errbuf : "no details");
|
errbuf[0] ? errbuf : "no details");
|
||||||
maybe_show_ssl_error(res, errbuf);
|
maybe_show_ssl_error(res, errbuf);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (http_code != 200) {
|
if (http_code != 200) {
|
||||||
blog(LOG_WARNING, "[%s] API POST %s returned HTTP %ld",
|
dbg_log(LOG_WARNING, "[%s] API POST %s returned HTTP %ld",
|
||||||
PLUGIN_NAME, path, http_code);
|
PLUGIN_NAME, path, http_code);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -320,8 +320,6 @@ static void apply_remote_settings(struct irl_source_data *data, const char *json
|
|||||||
data->srtla_enabled = json_get_bool(json, "srtlaEnabled", data->srtla_enabled);
|
data->srtla_enabled = json_get_bool(json, "srtlaEnabled", data->srtla_enabled);
|
||||||
data->srtla_port = json_get_int(json, "srtlaPort", data->srtla_port);
|
data->srtla_port = json_get_int(json, "srtlaPort", data->srtla_port);
|
||||||
|
|
||||||
data->show_watermark = !json_get_bool(json, "patreon", false);
|
|
||||||
|
|
||||||
bfree(data->duckdns_domain);
|
bfree(data->duckdns_domain);
|
||||||
data->duckdns_domain = json_get_string(json, "duckdnsDomain");
|
data->duckdns_domain = json_get_string(json, "duckdnsDomain");
|
||||||
|
|
||||||
@@ -352,6 +350,89 @@ static void apply_remote_settings(struct irl_source_data *data, const char *json
|
|||||||
ingest_thread_start(data);
|
ingest_thread_start(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---- Update check via /api/releases ---- */
|
||||||
|
|
||||||
|
static int compare_versions(const char *a, const char *b)
|
||||||
|
{
|
||||||
|
int a1 = 0, a2 = 0, a3 = 0, b1 = 0, b2 = 0, b3 = 0;
|
||||||
|
sscanf(a, "%d.%d.%d", &a1, &a2, &a3);
|
||||||
|
sscanf(b, "%d.%d.%d", &b1, &b2, &b3);
|
||||||
|
if (a1 != b1) return a1 - b1;
|
||||||
|
if (a2 != b2) return a2 - b2;
|
||||||
|
return a3 - b3;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct update_show_ctx {
|
||||||
|
char version[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
static void task_show_forced_update(void *param)
|
||||||
|
{
|
||||||
|
struct update_show_ctx *ctx = param;
|
||||||
|
forced_update_show(ctx->version, obs_get_locale());
|
||||||
|
free(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool check_update_with_token(const char *token)
|
||||||
|
{
|
||||||
|
char *json = api_get(obf_api_releases_path(), token);
|
||||||
|
if (!json)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Find first stable release: scan for "prerelease":false */
|
||||||
|
const char *pos = json;
|
||||||
|
char remote_ver[64] = "";
|
||||||
|
|
||||||
|
while ((pos = strstr(pos, "\"version\"")) != NULL) {
|
||||||
|
/* Extract version value */
|
||||||
|
const char *vstart = strchr(pos + 9, '"');
|
||||||
|
if (!vstart) break;
|
||||||
|
vstart++;
|
||||||
|
const char *vend = strchr(vstart, '"');
|
||||||
|
if (!vend || (vend - vstart) > 60) break;
|
||||||
|
|
||||||
|
/* Check if this release has "prerelease":false nearby */
|
||||||
|
const char *next_version = strstr(vend, "\"version\"");
|
||||||
|
const char *pre = strstr(vend, "\"prerelease\"");
|
||||||
|
if (pre && (!next_version || pre < next_version)) {
|
||||||
|
const char *pval = pre + 12;
|
||||||
|
while (*pval == ' ' || *pval == ':') pval++;
|
||||||
|
if (strncmp(pval, "false", 5) == 0) {
|
||||||
|
const char *v = vstart;
|
||||||
|
if (*v == 'v') v++;
|
||||||
|
size_t len = (size_t)(vend - v);
|
||||||
|
memcpy(remote_ver, v, len);
|
||||||
|
remote_ver[len] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = vend;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(json);
|
||||||
|
|
||||||
|
if (!remote_ver[0])
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (compare_versions(remote_ver, PLUGIN_VERSION) > 0) {
|
||||||
|
dbg_log(LOG_WARNING,
|
||||||
|
"[%s] Update required: v%s available (current: %s)",
|
||||||
|
PLUGIN_NAME, remote_ver, PLUGIN_VERSION);
|
||||||
|
|
||||||
|
struct update_show_ctx *ctx = malloc(sizeof(*ctx));
|
||||||
|
if (ctx) {
|
||||||
|
snprintf(ctx->version, sizeof(ctx->version), "%s",
|
||||||
|
remote_ver);
|
||||||
|
obs_queue_task(OBS_TASK_UI, task_show_forced_update,
|
||||||
|
ctx, false);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* ---- Background poll thread ---- */
|
/* ---- Background poll thread ---- */
|
||||||
|
|
||||||
static pthread_t g_settings_thread;
|
static pthread_t g_settings_thread;
|
||||||
@@ -365,6 +446,8 @@ static void *settings_poll_thread(void *arg)
|
|||||||
|
|
||||||
os_sleep_ms(3000);
|
os_sleep_ms(3000);
|
||||||
|
|
||||||
|
bool update_checked = false;
|
||||||
|
|
||||||
while (g_settings_thread_active) {
|
while (g_settings_thread_active) {
|
||||||
obs_data_t *settings = obs_source_get_settings(data->source);
|
obs_data_t *settings = obs_source_get_settings(data->source);
|
||||||
const char *api_token = obs_data_get_string(settings, "api_token");
|
const char *api_token = obs_data_get_string(settings, "api_token");
|
||||||
@@ -372,6 +455,18 @@ static void *settings_poll_thread(void *arg)
|
|||||||
obs_data_release(settings);
|
obs_data_release(settings);
|
||||||
|
|
||||||
if (token_copy) {
|
if (token_copy) {
|
||||||
|
if (!update_checked) {
|
||||||
|
update_checked = true;
|
||||||
|
if (check_update_with_token(token_copy)) {
|
||||||
|
#ifndef DEBUG_BUILD
|
||||||
|
ingest_thread_stop(data);
|
||||||
|
bfree(token_copy);
|
||||||
|
g_settings_thread_active = false;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char *json = api_get(obf_api_settings_path(), token_copy);
|
char *json = api_get(obf_api_settings_path(), token_copy);
|
||||||
bool force_sync = false;
|
bool force_sync = false;
|
||||||
if (json) {
|
if (json) {
|
||||||
@@ -380,6 +475,20 @@ static void *settings_poll_thread(void *arg)
|
|||||||
free(json);
|
free(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *me_json = api_get(obf_api_me_path(), token_copy);
|
||||||
|
if (me_json) {
|
||||||
|
bool is_patreon = json_get_bool(me_json, "patreonSub", false);
|
||||||
|
data->show_watermark = !is_patreon;
|
||||||
|
dbg_log(LOG_INFO, "[%s] Patreon check: patreonSub=%s, watermark=%s",
|
||||||
|
PLUGIN_NAME,
|
||||||
|
is_patreon ? "true" : "false",
|
||||||
|
data->show_watermark ? "on" : "off");
|
||||||
|
free(me_json);
|
||||||
|
} else {
|
||||||
|
dbg_log(LOG_WARNING, "[%s] /api/me request failed, watermark stays on",
|
||||||
|
PLUGIN_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
remote_report_obs_info(token_copy);
|
remote_report_obs_info(token_copy);
|
||||||
|
|
||||||
if (force_sync) {
|
if (force_sync) {
|
||||||
|
|||||||
+24
-24
@@ -1,4 +1,5 @@
|
|||||||
#include "srtla-server.h"
|
#include "srtla-server.h"
|
||||||
|
#include "debug-log.h"
|
||||||
#include <util/platform.h>
|
#include <util/platform.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -143,7 +144,7 @@ static void add_connection_to_group(struct srtla_group *g,
|
|||||||
c->addr_len = from_len;
|
c->addr_len = from_len;
|
||||||
c->last_activity_ns = os_gettime_ns();
|
c->last_activity_ns = os_gettime_ns();
|
||||||
c->active = true;
|
c->active = true;
|
||||||
blog(LOG_DEBUG,
|
dbg_log(LOG_DEBUG,
|
||||||
"[%s] SRTLA: connection %d added to group",
|
"[%s] SRTLA: connection %d added to group",
|
||||||
PLUGIN_NAME, g->num_conns);
|
PLUGIN_NAME, g->num_conns);
|
||||||
}
|
}
|
||||||
@@ -187,13 +188,13 @@ static void handle_reg1(struct srtla_state *state, const uint8_t *buf, int len,
|
|||||||
const struct sockaddr_storage *from, socklen_t from_len)
|
const struct sockaddr_storage *from, socklen_t from_len)
|
||||||
{
|
{
|
||||||
if (len < SRTLA_REG_PKT_SIZE) {
|
if (len < SRTLA_REG_PKT_SIZE) {
|
||||||
blog(LOG_WARNING,
|
dbg_log(LOG_WARNING,
|
||||||
"[%s] SRTLA: REG1 too short (%d, need %d)",
|
"[%s] SRTLA: REG1 too short (%d, need %d)",
|
||||||
PLUGIN_NAME, len, SRTLA_REG_PKT_SIZE);
|
PLUGIN_NAME, len, SRTLA_REG_PKT_SIZE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
blog(LOG_DEBUG, "[%s] SRTLA: Got REG1 (create group)", PLUGIN_NAME);
|
dbg_log(LOG_DEBUG, "[%s] SRTLA: Got REG1 (create group)", PLUGIN_NAME);
|
||||||
|
|
||||||
uint8_t group_id[SRTLA_GROUP_ID_LEN];
|
uint8_t group_id[SRTLA_GROUP_ID_LEN];
|
||||||
memcpy(group_id, buf + 2, 128);
|
memcpy(group_id, buf + 2, 128);
|
||||||
@@ -202,7 +203,7 @@ static void handle_reg1(struct srtla_state *state, const uint8_t *buf, int len,
|
|||||||
group_id[128 + i] = (uint8_t)(rand() & 0xFF);
|
group_id[128 + i] = (uint8_t)(rand() & 0xFF);
|
||||||
|
|
||||||
if (find_group(state, group_id)) {
|
if (find_group(state, group_id)) {
|
||||||
blog(LOG_WARNING,
|
dbg_log(LOG_WARNING,
|
||||||
"[%s] SRTLA: group ID collision, ignoring",
|
"[%s] SRTLA: group ID collision, ignoring",
|
||||||
PLUGIN_NAME);
|
PLUGIN_NAME);
|
||||||
return;
|
return;
|
||||||
@@ -210,7 +211,7 @@ static void handle_reg1(struct srtla_state *state, const uint8_t *buf, int len,
|
|||||||
|
|
||||||
struct srtla_group *g = alloc_group(state);
|
struct srtla_group *g = alloc_group(state);
|
||||||
if (!g) {
|
if (!g) {
|
||||||
blog(LOG_WARNING,
|
dbg_log(LOG_WARNING,
|
||||||
"[%s] SRTLA: max groups reached",
|
"[%s] SRTLA: max groups reached",
|
||||||
PLUGIN_NAME);
|
PLUGIN_NAME);
|
||||||
return;
|
return;
|
||||||
@@ -221,7 +222,7 @@ static void handle_reg1(struct srtla_state *state, const uint8_t *buf, int len,
|
|||||||
memcpy(g->group_id, group_id, SRTLA_GROUP_ID_LEN);
|
memcpy(g->group_id, group_id, SRTLA_GROUP_ID_LEN);
|
||||||
g->srt_sock = create_srt_forward_sock(state->srt_port);
|
g->srt_sock = create_srt_forward_sock(state->srt_port);
|
||||||
if (g->srt_sock == SRTLA_INVALID_SOCKET) {
|
if (g->srt_sock == SRTLA_INVALID_SOCKET) {
|
||||||
blog(LOG_WARNING,
|
dbg_log(LOG_WARNING,
|
||||||
"[%s] SRTLA: failed to create SRT forward socket",
|
"[%s] SRTLA: failed to create SRT forward socket",
|
||||||
PLUGIN_NAME);
|
PLUGIN_NAME);
|
||||||
return;
|
return;
|
||||||
@@ -229,7 +230,7 @@ static void handle_reg1(struct srtla_state *state, const uint8_t *buf, int len,
|
|||||||
g->active = true;
|
g->active = true;
|
||||||
g->last_activity_ns = os_gettime_ns();
|
g->last_activity_ns = os_gettime_ns();
|
||||||
|
|
||||||
blog(LOG_DEBUG,
|
dbg_log(LOG_DEBUG,
|
||||||
"[%s] SRTLA: group created, sending REG2 response",
|
"[%s] SRTLA: group created, sending REG2 response",
|
||||||
PLUGIN_NAME);
|
PLUGIN_NAME);
|
||||||
|
|
||||||
@@ -249,13 +250,13 @@ static void handle_reg2(struct srtla_state *state, const uint8_t *buf, int len,
|
|||||||
const struct sockaddr_storage *from, socklen_t from_len)
|
const struct sockaddr_storage *from, socklen_t from_len)
|
||||||
{
|
{
|
||||||
if (len < SRTLA_REG_PKT_SIZE) {
|
if (len < SRTLA_REG_PKT_SIZE) {
|
||||||
blog(LOG_WARNING,
|
dbg_log(LOG_WARNING,
|
||||||
"[%s] SRTLA: REG2 too short (%d, need %d)",
|
"[%s] SRTLA: REG2 too short (%d, need %d)",
|
||||||
PLUGIN_NAME, len, SRTLA_REG_PKT_SIZE);
|
PLUGIN_NAME, len, SRTLA_REG_PKT_SIZE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
blog(LOG_DEBUG,
|
dbg_log(LOG_DEBUG,
|
||||||
"[%s] SRTLA: Got REG2 (register connection)",
|
"[%s] SRTLA: Got REG2 (register connection)",
|
||||||
PLUGIN_NAME);
|
PLUGIN_NAME);
|
||||||
|
|
||||||
@@ -263,7 +264,7 @@ static void handle_reg2(struct srtla_state *state, const uint8_t *buf, int len,
|
|||||||
struct srtla_group *g = find_group(state, gid);
|
struct srtla_group *g = find_group(state, gid);
|
||||||
|
|
||||||
if (!g) {
|
if (!g) {
|
||||||
blog(LOG_DEBUG,
|
dbg_log(LOG_DEBUG,
|
||||||
"[%s] SRTLA: unknown group, sending REG_NGP",
|
"[%s] SRTLA: unknown group, sending REG_NGP",
|
||||||
PLUGIN_NAME);
|
PLUGIN_NAME);
|
||||||
uint8_t ngp[2];
|
uint8_t ngp[2];
|
||||||
@@ -276,7 +277,7 @@ static void handle_reg2(struct srtla_state *state, const uint8_t *buf, int len,
|
|||||||
add_connection_to_group(g, from, from_len);
|
add_connection_to_group(g, from, from_len);
|
||||||
g->last_activity_ns = os_gettime_ns();
|
g->last_activity_ns = os_gettime_ns();
|
||||||
|
|
||||||
blog(LOG_DEBUG,
|
dbg_log(LOG_DEBUG,
|
||||||
"[%s] SRTLA: connection registered, sending REG3 (%d conns)",
|
"[%s] SRTLA: connection registered, sending REG3 (%d conns)",
|
||||||
PLUGIN_NAME, g->num_conns);
|
PLUGIN_NAME, g->num_conns);
|
||||||
|
|
||||||
@@ -352,7 +353,7 @@ static void cleanup_stale_groups(struct srtla_state *state)
|
|||||||
uint64_t age_ms =
|
uint64_t age_ms =
|
||||||
(now - state->groups[i].last_activity_ns) / 1000000;
|
(now - state->groups[i].last_activity_ns) / 1000000;
|
||||||
if (age_ms > 30000) {
|
if (age_ms > 30000) {
|
||||||
blog(LOG_DEBUG,
|
dbg_log(LOG_DEBUG,
|
||||||
"[%s] SRTLA: group %d timed out (age=%llu ms, last_ns=%llu, now_ns=%llu)",
|
"[%s] SRTLA: group %d timed out (age=%llu ms, last_ns=%llu, now_ns=%llu)",
|
||||||
PLUGIN_NAME, i,
|
PLUGIN_NAME, i,
|
||||||
(unsigned long long)age_ms,
|
(unsigned long long)age_ms,
|
||||||
@@ -371,7 +372,7 @@ static void *srtla_thread_func(void *arg)
|
|||||||
|
|
||||||
state->listen_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
state->listen_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
if (state->listen_sock == SRTLA_INVALID_SOCKET) {
|
if (state->listen_sock == SRTLA_INVALID_SOCKET) {
|
||||||
blog(LOG_ERROR, "[%s] SRTLA: failed to create socket",
|
dbg_log(LOG_ERROR, "[%s] SRTLA: failed to create socket",
|
||||||
PLUGIN_NAME);
|
PLUGIN_NAME);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -387,7 +388,7 @@ static void *srtla_thread_func(void *arg)
|
|||||||
|
|
||||||
if (bind(state->listen_sock, (struct sockaddr *)&bind_addr,
|
if (bind(state->listen_sock, (struct sockaddr *)&bind_addr,
|
||||||
sizeof(bind_addr)) != 0) {
|
sizeof(bind_addr)) != 0) {
|
||||||
blog(LOG_ERROR,
|
dbg_log(LOG_ERROR,
|
||||||
"[%s] SRTLA: failed to bind port %d",
|
"[%s] SRTLA: failed to bind port %d",
|
||||||
PLUGIN_NAME, state->listen_port);
|
PLUGIN_NAME, state->listen_port);
|
||||||
closesocket(state->listen_sock);
|
closesocket(state->listen_sock);
|
||||||
@@ -406,7 +407,7 @@ static void *srtla_thread_func(void *arg)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
blog(LOG_DEBUG,
|
dbg_log(LOG_DEBUG,
|
||||||
"[%s] SRTLA: listening on UDP port %d, forwarding to SRT port %d",
|
"[%s] SRTLA: listening on UDP port %d, forwarding to SRT port %d",
|
||||||
PLUGIN_NAME, state->listen_port, state->srt_port);
|
PLUGIN_NAME, state->listen_port, state->srt_port);
|
||||||
|
|
||||||
@@ -484,7 +485,7 @@ static void *srtla_thread_func(void *arg)
|
|||||||
from_len);
|
from_len);
|
||||||
g->last_activity_ns =
|
g->last_activity_ns =
|
||||||
os_gettime_ns();
|
os_gettime_ns();
|
||||||
blog(LOG_DEBUG,
|
dbg_log(LOG_DEBUG,
|
||||||
"[%s] SRTLA: auto-registered client (%d bytes)",
|
"[%s] SRTLA: auto-registered client (%d bytes)",
|
||||||
PLUGIN_NAME, n);
|
PLUGIN_NAME, n);
|
||||||
} else {
|
} else {
|
||||||
@@ -504,15 +505,14 @@ static void *srtla_thread_func(void *arg)
|
|||||||
n, 0);
|
n, 0);
|
||||||
g->last_activity_ns = os_gettime_ns();
|
g->last_activity_ns = os_gettime_ns();
|
||||||
if (sent < 0) {
|
if (sent < 0) {
|
||||||
blog(LOG_WARNING,
|
|
||||||
"[%s] SRTLA: forward failed (err=%d)",
|
|
||||||
PLUGIN_NAME,
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
WSAGetLastError()
|
int fwd_err = WSAGetLastError();
|
||||||
#else
|
#else
|
||||||
errno
|
int fwd_err = errno;
|
||||||
#endif
|
#endif
|
||||||
);
|
dbg_log(LOG_WARNING,
|
||||||
|
"[%s] SRTLA: forward failed (err=%d)",
|
||||||
|
PLUGIN_NAME, fwd_err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_srt_data_packet(buf, n) &&
|
if (is_srt_data_packet(buf, n) &&
|
||||||
@@ -608,7 +608,7 @@ static void *srtla_thread_func(void *arg)
|
|||||||
closesocket(state->listen_sock);
|
closesocket(state->listen_sock);
|
||||||
state->listen_sock = SRTLA_INVALID_SOCKET;
|
state->listen_sock = SRTLA_INVALID_SOCKET;
|
||||||
|
|
||||||
blog(LOG_DEBUG, "[%s] SRTLA: server stopped", PLUGIN_NAME);
|
dbg_log(LOG_DEBUG, "[%s] SRTLA: server stopped", PLUGIN_NAME);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -631,7 +631,7 @@ void srtla_server_start(struct srtla_state *state, int listen_port,
|
|||||||
0) {
|
0) {
|
||||||
state->thread_created = true;
|
state->thread_created = true;
|
||||||
} else {
|
} else {
|
||||||
blog(LOG_ERROR, "[%s] SRTLA: failed to create thread",
|
dbg_log(LOG_ERROR, "[%s] SRTLA: failed to create thread",
|
||||||
PLUGIN_NAME);
|
PLUGIN_NAME);
|
||||||
state->running = false;
|
state->running = false;
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-5
@@ -1,5 +1,6 @@
|
|||||||
#include "webhook.h"
|
#include "webhook.h"
|
||||||
#include <obs-module.h>
|
#include <obs-module.h>
|
||||||
|
#include "debug-log.h"
|
||||||
#include <util/threading.h>
|
#include <util/threading.h>
|
||||||
#include <util/platform.h>
|
#include <util/platform.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -58,7 +59,7 @@ static int webhook_curl_debug_cb(CURL *handle, curl_infotype type, char *data,
|
|||||||
len--;
|
len--;
|
||||||
buf[len] = '\0';
|
buf[len] = '\0';
|
||||||
|
|
||||||
blog(LOG_INFO, "[Easy IRL Stream] curl: %s%s", prefix, buf);
|
dbg_log(LOG_INFO, "[Easy IRL Stream] curl: %s%s", prefix, buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +67,7 @@ static void webhook_do_send(const char *url, const char *json_body)
|
|||||||
{
|
{
|
||||||
CURL *curl = curl_easy_init();
|
CURL *curl = curl_easy_init();
|
||||||
if (!curl) {
|
if (!curl) {
|
||||||
blog(LOG_WARNING, "[%s] Webhook: curl_easy_init failed",
|
dbg_log(LOG_WARNING, "[%s] Webhook: curl_easy_init failed",
|
||||||
"Easy IRL Stream");
|
"Easy IRL Stream");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -100,13 +101,13 @@ static void webhook_do_send(const char *url, const char *json_body)
|
|||||||
|
|
||||||
CURLcode res = curl_easy_perform(curl);
|
CURLcode res = curl_easy_perform(curl);
|
||||||
if (res != CURLE_OK) {
|
if (res != CURLE_OK) {
|
||||||
blog(LOG_WARNING, "[%s] Webhook failed (%s): %s (%s)",
|
dbg_log(LOG_WARNING, "[%s] Webhook failed (%s): %s (%s)",
|
||||||
"Easy IRL Stream", url, curl_easy_strerror(res),
|
"Easy IRL Stream", url, curl_easy_strerror(res),
|
||||||
errbuf[0] ? errbuf : "no details");
|
errbuf[0] ? errbuf : "no details");
|
||||||
} else {
|
} else {
|
||||||
long http_code = 0;
|
long http_code = 0;
|
||||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
|
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
|
||||||
blog(LOG_DEBUG, "[%s] Webhook sent: %s (HTTP %ld)",
|
dbg_log(LOG_DEBUG, "[%s] Webhook sent: %s (HTTP %ld)",
|
||||||
"Easy IRL Stream", url, http_code);
|
"Easy IRL Stream", url, http_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,7 +178,7 @@ void webhook_send_async(const char *url, const char *event_name,
|
|||||||
static void *cmd_thread_func(void *arg)
|
static void *cmd_thread_func(void *arg)
|
||||||
{
|
{
|
||||||
struct cmd_args *ca = arg;
|
struct cmd_args *ca = arg;
|
||||||
blog(LOG_DEBUG, "[%s] Executing command: %s", "Easy IRL Stream",
|
dbg_log(LOG_DEBUG, "[%s] Executing command: %s", "Easy IRL Stream",
|
||||||
ca->command);
|
ca->command);
|
||||||
(void)system(ca->command);
|
(void)system(ca->command);
|
||||||
bfree(ca->command);
|
bfree(ca->command);
|
||||||
|
|||||||
Reference in New Issue
Block a user