feat: add safe Tornado K3D playout adapter
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using MBN_STOCK_WEBVIEW.Core.Playout;
|
||||
|
||||
namespace MBN_STOCK_WEBVIEW.Playout.Configuration;
|
||||
|
||||
public static class PlayoutOptionsLoader
|
||||
{
|
||||
public const string LiveAuthorizationEnvironmentVariable =
|
||||
"MBN_STOCK_PLAYOUT_AUTHORIZE_LIVE_OUTPUT";
|
||||
|
||||
public const string RequiredLiveAuthorizationValue =
|
||||
"I_AUTHORIZE_LIVE_PROGRAM_OUTPUT_FOR_THIS_LAUNCH";
|
||||
|
||||
public static string DefaultPath => Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
||||
"MBN_STOCK_WEBVIEW",
|
||||
"Config",
|
||||
"playout.local.json");
|
||||
|
||||
public static PlayoutOptions Load(string? path = null)
|
||||
{
|
||||
var options = LoadJson(path ?? DefaultPath);
|
||||
ApplyEnvironment(options);
|
||||
return options;
|
||||
}
|
||||
|
||||
internal static bool IsLiveAuthorizedForThisLaunch() =>
|
||||
string.Equals(
|
||||
Environment.GetEnvironmentVariable(LiveAuthorizationEnvironmentVariable),
|
||||
RequiredLiveAuthorizationValue,
|
||||
StringComparison.Ordinal);
|
||||
|
||||
private static PlayoutOptions LoadJson(string path)
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
return new PlayoutOptions();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var json = File.ReadAllText(path);
|
||||
return JsonSerializer.Deserialize<PlayoutOptions>(json, JsonOptions())
|
||||
?? new PlayoutOptions();
|
||||
}
|
||||
catch (JsonException exception)
|
||||
{
|
||||
throw new PlayoutConfigurationException(
|
||||
"송출 설정 파일 형식이 올바르지 않습니다.", exception);
|
||||
}
|
||||
catch (IOException exception)
|
||||
{
|
||||
throw new PlayoutConfigurationException(
|
||||
"송출 설정 파일을 읽을 수 없습니다.", exception);
|
||||
}
|
||||
catch (UnauthorizedAccessException exception)
|
||||
{
|
||||
throw new PlayoutConfigurationException(
|
||||
"송출 설정 파일에 접근할 수 없습니다.", exception);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ApplyEnvironment(PlayoutOptions options)
|
||||
{
|
||||
ApplyEnum("MBN_STOCK_PLAYOUT_MODE", value => options.Mode = value);
|
||||
ApplyString("MBN_STOCK_PLAYOUT_HOST", value => options.Host = value);
|
||||
ApplyInt("MBN_STOCK_PLAYOUT_PORT", value => options.Port = value);
|
||||
ApplyInt("MBN_STOCK_PLAYOUT_TCP_MODE", value => options.TcpMode = value);
|
||||
ApplyInt("MBN_STOCK_PLAYOUT_CLIENT_PORT", value => options.ClientPort = value);
|
||||
ApplyNullableInt("MBN_STOCK_PLAYOUT_OUTPUT_CHANNEL", value => options.OutputChannel = value);
|
||||
ApplyInt("MBN_STOCK_PLAYOUT_LAYOUT_INDEX", value => options.LayoutIndex = value);
|
||||
ApplyString("MBN_STOCK_PLAYOUT_SCENE_DIRECTORY", value => options.SceneDirectory = value);
|
||||
ApplyString(
|
||||
"MBN_STOCK_PLAYOUT_TEST_WINDOW_TITLE_PATTERN",
|
||||
value => options.TestProcessWindowTitlePattern = value);
|
||||
ApplyInt("MBN_STOCK_PLAYOUT_QUEUE_CAPACITY", value => options.QueueCapacity = value);
|
||||
ApplyInt(
|
||||
"MBN_STOCK_PLAYOUT_CONNECT_TIMEOUT_MS",
|
||||
value => options.ConnectTimeoutMilliseconds = value);
|
||||
ApplyInt(
|
||||
"MBN_STOCK_PLAYOUT_OPERATION_TIMEOUT_MS",
|
||||
value => options.OperationTimeoutMilliseconds = value);
|
||||
ApplyInt(
|
||||
"MBN_STOCK_PLAYOUT_DISCONNECT_TIMEOUT_MS",
|
||||
value => options.DisconnectTimeoutMilliseconds = value);
|
||||
ApplyInt(
|
||||
"MBN_STOCK_PLAYOUT_PROCESS_POLL_INTERVAL_MS",
|
||||
value => options.ProcessPollIntervalMilliseconds = value);
|
||||
ApplyInt(
|
||||
"MBN_STOCK_PLAYOUT_RECONNECT_DELAY_MS",
|
||||
value => options.ReconnectDelayMilliseconds = value);
|
||||
ApplyInt(
|
||||
"MBN_STOCK_PLAYOUT_MAXIMUM_RECONNECT_ATTEMPTS",
|
||||
value => options.MaximumReconnectAttempts = value);
|
||||
ApplyBool(
|
||||
"MBN_STOCK_PLAYOUT_RECONNECT_ENABLED",
|
||||
value => options.ReconnectEnabled = value);
|
||||
}
|
||||
|
||||
private static JsonSerializerOptions JsonOptions()
|
||||
{
|
||||
var result = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNameCaseInsensitive = true,
|
||||
ReadCommentHandling = JsonCommentHandling.Skip,
|
||||
AllowTrailingCommas = true
|
||||
};
|
||||
result.Converters.Add(new JsonStringEnumConverter());
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void ApplyString(string name, Action<string> apply)
|
||||
{
|
||||
var value = Environment.GetEnvironmentVariable(name);
|
||||
if (!string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
apply(value.Trim());
|
||||
}
|
||||
}
|
||||
|
||||
private static void ApplyInt(string name, Action<int> apply)
|
||||
{
|
||||
var text = Environment.GetEnvironmentVariable(name);
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!int.TryParse(text, out var value))
|
||||
{
|
||||
throw InvalidEnvironment(name);
|
||||
}
|
||||
|
||||
apply(value);
|
||||
}
|
||||
|
||||
private static void ApplyNullableInt(string name, Action<int?> apply)
|
||||
{
|
||||
var text = Environment.GetEnvironmentVariable(name);
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!int.TryParse(text, out var value))
|
||||
{
|
||||
throw InvalidEnvironment(name);
|
||||
}
|
||||
|
||||
apply(value);
|
||||
}
|
||||
|
||||
private static void ApplyBool(string name, Action<bool> apply)
|
||||
{
|
||||
var text = Environment.GetEnvironmentVariable(name);
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bool.TryParse(text, out var value))
|
||||
{
|
||||
throw InvalidEnvironment(name);
|
||||
}
|
||||
|
||||
apply(value);
|
||||
}
|
||||
|
||||
private static void ApplyEnum(string name, Action<PlayoutMode> apply)
|
||||
{
|
||||
var text = Environment.GetEnvironmentVariable(name);
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Enum.TryParse<PlayoutMode>(text, true, out var value))
|
||||
{
|
||||
throw InvalidEnvironment(name);
|
||||
}
|
||||
|
||||
apply(value);
|
||||
}
|
||||
|
||||
private static PlayoutConfigurationException InvalidEnvironment(string name) =>
|
||||
new($"환경 변수 {name} 값이 올바르지 않습니다.");
|
||||
}
|
||||
|
||||
public sealed class PlayoutConfigurationException : Exception
|
||||
{
|
||||
public PlayoutConfigurationException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public PlayoutConfigurationException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user