토네이도 연결 및 송출 확인
This commit is contained in:
@@ -1,13 +1,12 @@
|
|||||||
<Solution>
|
<Solution>
|
||||||
<Configurations>
|
<Configurations>
|
||||||
<Platform Name="ARM64" />
|
|
||||||
<Platform Name="x64" />
|
<Platform Name="x64" />
|
||||||
<Platform Name="x86" />
|
|
||||||
</Configurations>
|
</Configurations>
|
||||||
<Project Path="Tornado3_2026Election/Tornado3_2026Election.csproj">
|
<Project Path="Tornado3_2026Election/Tornado3_2026Election.csproj">
|
||||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
|
||||||
<Platform Solution="*|x64" Project="x64" />
|
<Platform Solution="*|x64" Project="x64" />
|
||||||
<Platform Solution="*|x86" Project="x86" />
|
|
||||||
<Deploy />
|
<Deploy />
|
||||||
</Project>
|
</Project>
|
||||||
|
<Project Path="tools/KarismaTcpProbe/KarismaTcpProbe.csproj">
|
||||||
|
<Platform Solution="*|x64" Project="x64" />
|
||||||
|
</Project>
|
||||||
</Solution>
|
</Solution>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Tornado3_2026Election.Services;
|
||||||
|
|
||||||
namespace Tornado3_2026Election.Persistence;
|
namespace Tornado3_2026Election.Persistence;
|
||||||
|
|
||||||
@@ -10,7 +11,7 @@ public sealed class AppState
|
|||||||
|
|
||||||
public string SelectedStationId { get; set; } = "KNN";
|
public string SelectedStationId { get; set; } = "KNN";
|
||||||
|
|
||||||
public string ImageRootPath { get; set; } = @"C:\Users\y2keu\Downloads\T3_Cut";
|
public string ImageRootPath { get; set; } = TornadoPathResolver.GetDefaultT3CutPath();
|
||||||
|
|
||||||
public bool AutoRestoreSchedules { get; set; } = true;
|
public bool AutoRestoreSchedules { get; set; } = true;
|
||||||
|
|
||||||
@@ -48,4 +49,3 @@ public sealed class AppState
|
|||||||
|
|
||||||
public Dictionary<string, string> StationRegionFilters { get; set; } = [];
|
public Dictionary<string, string> StationRegionFilters { get; set; } = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -86,10 +86,20 @@ public sealed class KarismaTornado3Adapter : ITornado3Adapter, IDisposable
|
|||||||
logService.Info($"Karisma adapter using default port {DefaultKarismaPort}.");
|
logService.Info($"Karisma adapter using default port {DefaultKarismaPort}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var t3CutPath = t3CutPathProvider();
|
var configuredT3CutPath = t3CutPathProvider();
|
||||||
|
var t3CutPath = string.IsNullOrWhiteSpace(configuredT3CutPath)
|
||||||
|
? TornadoPathResolver.GetDefaultT3CutPath()
|
||||||
|
: TornadoPathResolver.NormalizeConfiguredPath(configuredT3CutPath);
|
||||||
|
|
||||||
|
if (!string.Equals(configuredT3CutPath, t3CutPath, StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
!string.IsNullOrWhiteSpace(t3CutPath))
|
||||||
|
{
|
||||||
|
logService.Info($"Karisma adapter normalized T3_Cut path to '{t3CutPath}'.");
|
||||||
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(t3CutPath) || !Directory.Exists(t3CutPath))
|
if (string.IsNullOrWhiteSpace(t3CutPath) || !Directory.Exists(t3CutPath))
|
||||||
{
|
{
|
||||||
logService.Warning("Karisma adapter disabled: set a valid T3_Cut path in Settings.");
|
logService.Warning($"Karisma adapter disabled: set a valid T3_Cut path in Settings. current='{configuredT3CutPath}'");
|
||||||
adapter = new MockTornado3Adapter(logService);
|
adapter = new MockTornado3Adapter(logService);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -230,7 +240,11 @@ public sealed class KarismaTornado3Adapter : ITornado3Adapter, IDisposable
|
|||||||
|
|
||||||
private string ResolveT3CutPath()
|
private string ResolveT3CutPath()
|
||||||
{
|
{
|
||||||
var path = _t3CutPathProvider();
|
var configuredPath = _t3CutPathProvider();
|
||||||
|
var path = string.IsNullOrWhiteSpace(configuredPath)
|
||||||
|
? TornadoPathResolver.GetDefaultT3CutPath()
|
||||||
|
: TornadoPathResolver.NormalizeConfiguredPath(configuredPath);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(path) || !Directory.Exists(path))
|
if (string.IsNullOrWhiteSpace(path) || !Directory.Exists(path))
|
||||||
{
|
{
|
||||||
throw new DirectoryNotFoundException("T3_Cut path is not configured or does not exist.");
|
throw new DirectoryNotFoundException("T3_Cut path is not configured or does not exist.");
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using KAsyncEngineLib;
|
using KAsyncEngineLib;
|
||||||
@@ -372,9 +373,14 @@ public sealed class TornadoManager : IDisposable
|
|||||||
|
|
||||||
private sealed class StaDispatcher : IDisposable
|
private sealed class StaDispatcher : IDisposable
|
||||||
{
|
{
|
||||||
private readonly BlockingCollection<Action> _queue = new();
|
private const uint WmApp = 0x8000;
|
||||||
|
private const uint WmDispatch = WmApp + 1;
|
||||||
|
|
||||||
|
private readonly ConcurrentQueue<Action> _queue = new();
|
||||||
private readonly Thread _thread;
|
private readonly Thread _thread;
|
||||||
|
private readonly ManualResetEventSlim _threadReady = new();
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
private uint _threadId;
|
||||||
|
|
||||||
public StaDispatcher(string threadName)
|
public StaDispatcher(string threadName)
|
||||||
{
|
{
|
||||||
@@ -385,6 +391,7 @@ public sealed class TornadoManager : IDisposable
|
|||||||
};
|
};
|
||||||
_thread.SetApartmentState(ApartmentState.STA);
|
_thread.SetApartmentState(ApartmentState.STA);
|
||||||
_thread.Start();
|
_thread.Start();
|
||||||
|
_threadReady.Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task InvokeAsync(Action action, CancellationToken cancellationToken)
|
public Task InvokeAsync(Action action, CancellationToken cancellationToken)
|
||||||
@@ -402,18 +409,29 @@ public sealed class TornadoManager : IDisposable
|
|||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var completion = new TaskCompletionSource<T>(TaskCreationOptions.RunContinuationsAsynchronously);
|
var completion = new TaskCompletionSource<T>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||||
_queue.Add(() =>
|
_queue.Enqueue(() =>
|
||||||
{
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completion.TrySetCanceled(cancellationToken);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
completion.SetResult(action());
|
completion.TrySetResult(action());
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
completion.SetException(ex);
|
completion.TrySetException(ex);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!PostThreadMessage(_threadId, WmDispatch, UIntPtr.Zero, IntPtr.Zero))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Failed to signal Karisma STA dispatcher.");
|
||||||
|
}
|
||||||
|
|
||||||
return cancellationToken.CanBeCanceled
|
return cancellationToken.CanBeCanceled
|
||||||
? completion.Task.WaitAsync(cancellationToken)
|
? completion.Task.WaitAsync(cancellationToken)
|
||||||
: completion.Task;
|
: completion.Task;
|
||||||
@@ -427,17 +445,77 @@ public sealed class TornadoManager : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
_queue.CompleteAdding();
|
PostThreadMessage(_threadId, WmQuit, UIntPtr.Zero, IntPtr.Zero);
|
||||||
_thread.Join();
|
_thread.Join();
|
||||||
_queue.Dispose();
|
_threadReady.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Run()
|
private void Run()
|
||||||
{
|
{
|
||||||
foreach (var action in _queue.GetConsumingEnumerable())
|
PeekMessage(out _, IntPtr.Zero, 0, 0, 0);
|
||||||
|
_threadId = GetCurrentThreadId();
|
||||||
|
_threadReady.Set();
|
||||||
|
|
||||||
|
while (GetMessage(out var message, IntPtr.Zero, 0, 0) > 0)
|
||||||
|
{
|
||||||
|
if (message.message == WmDispatch)
|
||||||
|
{
|
||||||
|
DrainQueue();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
TranslateMessage(ref message);
|
||||||
|
DispatchMessage(ref message);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrainQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrainQueue()
|
||||||
|
{
|
||||||
|
while (_queue.TryDequeue(out var action))
|
||||||
{
|
{
|
||||||
action();
|
action();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private const uint WmQuit = 0x0012;
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll")]
|
||||||
|
private static extern uint GetCurrentThreadId();
|
||||||
|
|
||||||
|
[DllImport("user32.dll", SetLastError = true)]
|
||||||
|
private static extern bool PostThreadMessage(uint idThread, uint msg, UIntPtr wParam, IntPtr lParam);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
private static extern int GetMessage(out NativeMessage lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
private static extern bool TranslateMessage([In] ref NativeMessage lpMsg);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
private static extern IntPtr DispatchMessage([In] ref NativeMessage lpMsg);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
private static extern bool PeekMessage(out NativeMessage lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax, uint wRemoveMsg);
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
private struct NativeMessage
|
||||||
|
{
|
||||||
|
public IntPtr hwnd;
|
||||||
|
public uint message;
|
||||||
|
public UIntPtr wParam;
|
||||||
|
public IntPtr lParam;
|
||||||
|
public uint time;
|
||||||
|
public NativePoint pt;
|
||||||
|
public uint lPrivate;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
private struct NativePoint
|
||||||
|
{
|
||||||
|
public int x;
|
||||||
|
public int y;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
109
Tornado3_2026Election/Services/TornadoPathResolver.cs
Normal file
109
Tornado3_2026Election/Services/TornadoPathResolver.cs
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Tornado3_2026Election.Services;
|
||||||
|
|
||||||
|
public static class TornadoPathResolver
|
||||||
|
{
|
||||||
|
public static string GetDefaultT3CutPath()
|
||||||
|
{
|
||||||
|
foreach (var candidate in GetCandidatePaths())
|
||||||
|
{
|
||||||
|
var normalized = NormalizeConfiguredPath(candidate);
|
||||||
|
if (!string.IsNullOrWhiteSpace(normalized) && Directory.Exists(normalized))
|
||||||
|
{
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NormalizeConfiguredPath(Path.Combine(
|
||||||
|
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
|
||||||
|
"Tornado3 Data",
|
||||||
|
"T3_Cut",
|
||||||
|
"T3_Cut"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string NormalizeConfiguredPath(string? configuredPath)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(configuredPath))
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
var trimmedPath = configuredPath.Trim();
|
||||||
|
if (!Directory.Exists(trimmedPath))
|
||||||
|
{
|
||||||
|
return trimmedPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
var nestedDefault = Path.Combine(trimmedPath, "T3_Cut");
|
||||||
|
if (ContainsSceneFiles(nestedDefault))
|
||||||
|
{
|
||||||
|
return nestedDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ContainsSceneFiles(trimmedPath))
|
||||||
|
{
|
||||||
|
return trimmedPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
var nestedDirectory = TryFindNestedSceneDirectory(trimmedPath);
|
||||||
|
return nestedDirectory ?? trimmedPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<string> GetCandidatePaths()
|
||||||
|
{
|
||||||
|
var userProfile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||||
|
var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
|
||||||
|
var configured = Environment.GetEnvironmentVariable("TORNADO_T3CUT_PATH");
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(configured))
|
||||||
|
{
|
||||||
|
yield return configured;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(documents))
|
||||||
|
{
|
||||||
|
yield return Path.Combine(documents, "Tornado3 Data", "T3_Cut", "T3_Cut");
|
||||||
|
yield return Path.Combine(documents, "Tornado3 Data", "T3_Cut");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(userProfile))
|
||||||
|
{
|
||||||
|
yield return Path.Combine(userProfile, "Downloads", "T3_Cut");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string? TryFindNestedSceneDirectory(string rootPath)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Directory.EnumerateDirectories(rootPath, "*", SearchOption.TopDirectoryOnly)
|
||||||
|
.Select(NormalizeConfiguredPath)
|
||||||
|
.FirstOrDefault(path => !string.IsNullOrWhiteSpace(path) && ContainsSceneFiles(path));
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool ContainsSceneFiles(string? path)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(path) || !Directory.Exists(path))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Directory.EnumerateFiles(path, "*.tscn", SearchOption.AllDirectories).Any();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,24 +6,20 @@
|
|||||||
<RootNamespace>Tornado3_2026Election</RootNamespace>
|
<RootNamespace>Tornado3_2026Election</RootNamespace>
|
||||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
<ApplicationIcon>Assets\AppIcon.ico</ApplicationIcon>
|
<ApplicationIcon>Assets\AppIcon.ico</ApplicationIcon>
|
||||||
<Platforms>x86;x64;ARM64</Platforms>
|
<Platforms>x64</Platforms>
|
||||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64</RuntimeIdentifiers>
|
||||||
<UseWinUI>true</UseWinUI>
|
<UseWinUI>true</UseWinUI>
|
||||||
<WinUISDKReferences>false</WinUISDKReferences>
|
<WinUISDKReferences>false</WinUISDKReferences>
|
||||||
<EnableMsixTooling>true</EnableMsixTooling>
|
<EnableMsixTooling>true</EnableMsixTooling>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(RuntimeIdentifier)'=='' and ('$(Platform)'=='' or '$(Platform)'=='AnyCPU' or '$(Platform)'=='x64')">
|
<PropertyGroup Condition="'$(RuntimeIdentifier)'==''">
|
||||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(RuntimeIdentifier)'=='' and '$(Platform)'=='x86'">
|
<PropertyGroup>
|
||||||
<RuntimeIdentifier>win-x86</RuntimeIdentifier>
|
<KarismaSdkDir Condition="'$(KarismaSdkDir)'==''">C:\Karisma SDK</KarismaSdkDir>
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(RuntimeIdentifier)'=='' and '$(Platform)'=='ARM64'">
|
|
||||||
<RuntimeIdentifier>win-arm64</RuntimeIdentifier>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="Exists('Properties\PublishProfiles\win-$(Platform).pubxml')">
|
<PropertyGroup Condition="Exists('Properties\PublishProfiles\win-$(Platform).pubxml')">
|
||||||
@@ -89,7 +85,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Interop.KAsyncEngineLib">
|
<Reference Include="Interop.KAsyncEngineLib">
|
||||||
<HintPath>..\..\..\..\..\..\Karisma SDK\Bin\C#\Interop.KAsyncEngineLib.dll</HintPath>
|
<HintPath>$(KarismaSdkDir)\Bin\C#\Interop.KAsyncEngineLib.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ public sealed class MainViewModel : ObservableObject
|
|||||||
private readonly FormatCatalogService _formatCatalogService;
|
private readonly FormatCatalogService _formatCatalogService;
|
||||||
private readonly AppStateStore _stateStore;
|
private readonly AppStateStore _stateStore;
|
||||||
private readonly LogService _logService;
|
private readonly LogService _logService;
|
||||||
|
private readonly ITornado3Adapter _sharedTornadoAdapter;
|
||||||
private readonly SemaphoreSlim _stateSaveLock = new(1, 1);
|
private readonly SemaphoreSlim _stateSaveLock = new(1, 1);
|
||||||
private AppPage _currentPage = AppPage.IntegratedSchedule;
|
private AppPage _currentPage = AppPage.IntegratedSchedule;
|
||||||
private ChannelOperationMode _operationMode = ChannelOperationMode.General;
|
private ChannelOperationMode _operationMode = ChannelOperationMode.General;
|
||||||
@@ -56,11 +57,12 @@ public sealed class MainViewModel : ObservableObject
|
|||||||
|
|
||||||
Settings.PropertyChanged += Settings_PropertyChanged;
|
Settings.PropertyChanged += Settings_PropertyChanged;
|
||||||
Data.PropertyChanged += Data_PropertyChanged;
|
Data.PropertyChanged += Data_PropertyChanged;
|
||||||
|
_sharedTornadoAdapter = KarismaTornado3Adapter.CreateOrFallback(_logService, () => Settings.ImageRootPath);
|
||||||
|
|
||||||
NormalChannel = CreateChannelViewModel(BroadcastChannel.Normal, "노멀");
|
NormalChannel = CreateChannelViewModel(BroadcastChannel.Normal, "노멀", _sharedTornadoAdapter);
|
||||||
TopLeftChannel = CreateChannelViewModel(BroadcastChannel.TopLeft, "좌상단");
|
TopLeftChannel = CreateChannelViewModel(BroadcastChannel.TopLeft, "좌상단", _sharedTornadoAdapter);
|
||||||
BottomChannel = CreateChannelViewModel(BroadcastChannel.Bottom, "하단");
|
BottomChannel = CreateChannelViewModel(BroadcastChannel.Bottom, "하단", _sharedTornadoAdapter);
|
||||||
VideoWallChannel = CreateChannelViewModel(BroadcastChannel.VideoWall, "비디오월");
|
VideoWallChannel = CreateChannelViewModel(BroadcastChannel.VideoWall, "비디오월", _sharedTornadoAdapter);
|
||||||
|
|
||||||
Channels = [NormalChannel, TopLeftChannel, BottomChannel, VideoWallChannel];
|
Channels = [NormalChannel, TopLeftChannel, BottomChannel, VideoWallChannel];
|
||||||
foreach (var channel in Channels)
|
foreach (var channel in Channels)
|
||||||
@@ -82,6 +84,7 @@ public sealed class MainViewModel : ObservableObject
|
|||||||
_logService.Entries.CollectionChanged += (_, _) => RebuildFilteredLogs();
|
_logService.Entries.CollectionChanged += (_, _) => RebuildFilteredLogs();
|
||||||
SelectedLogFilterOption = LogFilterOptions[0];
|
SelectedLogFilterOption = LogFilterOptions[0];
|
||||||
_logService.Info("SYSTEM_SPEC 기반 MVVM 구조를 초기화했습니다.");
|
_logService.Info("SYSTEM_SPEC 기반 MVVM 구조를 초기화했습니다.");
|
||||||
|
_ = WarmupSharedCgConnectionAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataViewModel Data { get; }
|
public DataViewModel Data { get; }
|
||||||
@@ -439,6 +442,7 @@ public sealed class MainViewModel : ObservableObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
_logService.Info("저장한 시작 옵션에 따라 상태를 자동 복원했습니다.");
|
_logService.Info("저장한 시작 옵션에 따라 상태를 자동 복원했습니다.");
|
||||||
|
_ = WarmupSharedCgConnectionAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RestoreAsync()
|
public async Task RestoreAsync()
|
||||||
@@ -471,6 +475,11 @@ public sealed class MainViewModel : ObservableObject
|
|||||||
public async Task ShutdownAsync()
|
public async Task ShutdownAsync()
|
||||||
{
|
{
|
||||||
await SaveStateCoreAsync(writeLog: false);
|
await SaveStateCoreAsync(writeLog: false);
|
||||||
|
if (_sharedTornadoAdapter is IDisposable disposableAdapter)
|
||||||
|
{
|
||||||
|
disposableAdapter.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
Data.Dispose();
|
Data.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,6 +529,7 @@ public sealed class MainViewModel : ObservableObject
|
|||||||
if (args.PropertyName is nameof(SettingsViewModel.SelectedStationId) or nameof(SettingsViewModel.ImageRootPath))
|
if (args.PropertyName is nameof(SettingsViewModel.SelectedStationId) or nameof(SettingsViewModel.ImageRootPath))
|
||||||
{
|
{
|
||||||
QueueAutomaticSave();
|
QueueAutomaticSave();
|
||||||
|
_ = WarmupSharedCgConnectionAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -694,9 +704,25 @@ public sealed class MainViewModel : ObservableObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChannelScheduleViewModel CreateChannelViewModel(BroadcastChannel channel, string title)
|
private async Task WarmupSharedCgConnectionAsync()
|
||||||
|
{
|
||||||
|
if (!_sharedTornadoAdapter.IsLiveCg)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _sharedTornadoAdapter.EnsureConnectedAsync(CancellationToken.None).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logService.Warning($"CG startup connection attempt failed: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ChannelScheduleViewModel CreateChannelViewModel(BroadcastChannel channel, string title, ITornado3Adapter adapter)
|
||||||
{
|
{
|
||||||
var adapter = KarismaTornado3Adapter.CreateOrFallback(_logService, () => Settings.ImageRootPath);
|
|
||||||
var queue = new ObservableCollection<ChannelScheduleItem>();
|
var queue = new ObservableCollection<ChannelScheduleItem>();
|
||||||
var engine = new ChannelScheduleEngine(
|
var engine = new ChannelScheduleEngine(
|
||||||
channel,
|
channel,
|
||||||
|
|||||||
@@ -3,13 +3,14 @@ using System.Collections.ObjectModel;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Tornado3_2026Election.Common;
|
using Tornado3_2026Election.Common;
|
||||||
using Tornado3_2026Election.Domain;
|
using Tornado3_2026Election.Domain;
|
||||||
|
using Tornado3_2026Election.Services;
|
||||||
|
|
||||||
namespace Tornado3_2026Election.ViewModels;
|
namespace Tornado3_2026Election.ViewModels;
|
||||||
|
|
||||||
public sealed class SettingsViewModel : ObservableObject
|
public sealed class SettingsViewModel : ObservableObject
|
||||||
{
|
{
|
||||||
private string _selectedStationId = "KNN";
|
private string _selectedStationId = "KNN";
|
||||||
private string _imageRootPath = @"C:\Users\y2keu\Downloads\T3_Cut";
|
private string _imageRootPath = TornadoPathResolver.GetDefaultT3CutPath();
|
||||||
|
|
||||||
public SettingsViewModel(IEnumerable<BroadcastStationProfile> stations)
|
public SettingsViewModel(IEnumerable<BroadcastStationProfile> stations)
|
||||||
{
|
{
|
||||||
@@ -50,7 +51,7 @@ public sealed class SettingsViewModel : ObservableObject
|
|||||||
public string ImageRootPath
|
public string ImageRootPath
|
||||||
{
|
{
|
||||||
get => _imageRootPath;
|
get => _imageRootPath;
|
||||||
set => SetProperty(ref _imageRootPath, value);
|
set => SetProperty(ref _imageRootPath, TornadoPathResolver.NormalizeConfiguredPath(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public StationFilterItemViewModel SelectedStation
|
public StationFilterItemViewModel SelectedStation
|
||||||
|
|||||||
19
tools/KarismaTcpProbe/KarismaTcpProbe.csproj
Normal file
19
tools/KarismaTcpProbe/KarismaTcpProbe.csproj
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0-windows</TargetFramework>
|
||||||
|
<Platforms>x64</Platforms>
|
||||||
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<KarismaSdkDir Condition="'$(KarismaSdkDir)'==''">C:\Karisma SDK</KarismaSdkDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Interop.KAsyncEngineLib">
|
||||||
|
<HintPath>$(KarismaSdkDir)\Bin\C#\Interop.KAsyncEngineLib.dll</HintPath>
|
||||||
|
<Private>true</Private>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
426
tools/KarismaTcpProbe/Program.cs
Normal file
426
tools/KarismaTcpProbe/Program.cs
Normal file
@@ -0,0 +1,426 @@
|
|||||||
|
using System;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using KAsyncEngineLib;
|
||||||
|
|
||||||
|
var options = ProbeOptions.Parse(args);
|
||||||
|
|
||||||
|
Console.WriteLine($"Karisma TCP probe starting. target={options.Host}:{options.Port} timeout={options.Timeout.TotalSeconds:0}s");
|
||||||
|
|
||||||
|
var rawTcpOk = await ProbeRawTcpAsync(options).ConfigureAwait(false);
|
||||||
|
var sdkResult = await ProbeSdkAsync(options).ConfigureAwait(false);
|
||||||
|
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine("Summary");
|
||||||
|
Console.WriteLine($"- Raw TCP: {(rawTcpOk ? "OK" : "FAILED")}");
|
||||||
|
Console.WriteLine($"- SDK Connect(): {(sdkResult.ConnectRequestAccepted ? "ACCEPTED" : "REJECTED")}");
|
||||||
|
Console.WriteLine($"- SDK OnConnect: {sdkResult.ConnectOutcome}");
|
||||||
|
Console.WriteLine($"- SDK Detail: {sdkResult.Detail}");
|
||||||
|
|
||||||
|
Environment.ExitCode = rawTcpOk && sdkResult.ConnectRequestAccepted && sdkResult.ConnectOutcome == "SUCCESS"
|
||||||
|
? 0
|
||||||
|
: 1;
|
||||||
|
|
||||||
|
static async Task<bool> ProbeRawTcpAsync(ProbeOptions options)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var client = new TcpClient();
|
||||||
|
using var cts = new CancellationTokenSource(options.Timeout);
|
||||||
|
await client.ConnectAsync(options.Host, options.Port, cts.Token).ConfigureAwait(false);
|
||||||
|
Console.WriteLine($"[RAW] Connected local={client.Client.LocalEndPoint} remote={client.Client.RemoteEndPoint}");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[RAW] Failed: {ex.Message}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Task<SdkProbeResult> ProbeSdkAsync(ProbeOptions options)
|
||||||
|
{
|
||||||
|
var completion = new TaskCompletionSource<SdkProbeResult>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||||
|
|
||||||
|
var thread = new Thread(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var handler = new ProbeEventHandler();
|
||||||
|
var engine = (IKAEngine)new KAEngineClass();
|
||||||
|
|
||||||
|
Console.WriteLine("[SDK] Calling Connect()...");
|
||||||
|
var connectRequested = engine.Connect(options.Host, options.Port, handler);
|
||||||
|
Console.WriteLine($"[SDK] Connect() returned {(connectRequested != 0 ? "TRUE" : "FALSE")} raw={connectRequested}");
|
||||||
|
|
||||||
|
if (connectRequested == 0)
|
||||||
|
{
|
||||||
|
completion.TrySetResult(new SdkProbeResult(false, "FAILED", "Connect() returned 0."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!WaitForTaskWithMessagePump(handler.ConnectTask, options.Timeout))
|
||||||
|
{
|
||||||
|
completion.TrySetResult(new SdkProbeResult(true, "TIMEOUT", $"OnConnect was not received within {options.Timeout.TotalSeconds:0} seconds."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var errorCode = handler.ConnectTask.Result;
|
||||||
|
var outcome = errorCode == 0 ? "SUCCESS" : "FAILED";
|
||||||
|
completion.TrySetResult(new SdkProbeResult(true, outcome, $"OnConnect errorCode={errorCode}"));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
engine.Disconnect();
|
||||||
|
handler.CloseTask.Wait(TimeSpan.FromSeconds(2));
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
completion.TrySetResult(new SdkProbeResult(false, "EXCEPTION", ex.ToString()));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
{
|
||||||
|
IsBackground = true,
|
||||||
|
Name = "KarismaTcpProbe"
|
||||||
|
};
|
||||||
|
|
||||||
|
thread.SetApartmentState(ApartmentState.STA);
|
||||||
|
thread.Start();
|
||||||
|
return completion.Task;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool WaitForTaskWithMessagePump(Task task, TimeSpan timeout)
|
||||||
|
{
|
||||||
|
User32.PeekMessage(out _, IntPtr.Zero, 0, 0, 0);
|
||||||
|
|
||||||
|
var deadline = DateTime.UtcNow + timeout;
|
||||||
|
while (!task.IsCompleted)
|
||||||
|
{
|
||||||
|
while (User32.PeekMessage(out var message, IntPtr.Zero, 0, 0, 1))
|
||||||
|
{
|
||||||
|
User32.TranslateMessage(ref message);
|
||||||
|
User32.DispatchMessage(ref message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DateTime.UtcNow >= deadline)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.Sleep(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed record ProbeOptions(string Host, int Port, TimeSpan Timeout)
|
||||||
|
{
|
||||||
|
public static ProbeOptions Parse(string[] args)
|
||||||
|
{
|
||||||
|
var host = "127.0.0.1";
|
||||||
|
var port = 30001;
|
||||||
|
var timeout = TimeSpan.FromSeconds(5);
|
||||||
|
|
||||||
|
for (var index = 0; index < args.Length; index++)
|
||||||
|
{
|
||||||
|
switch (args[index])
|
||||||
|
{
|
||||||
|
case "--host" when index + 1 < args.Length:
|
||||||
|
host = args[++index];
|
||||||
|
break;
|
||||||
|
case "--port" when index + 1 < args.Length && int.TryParse(args[index + 1], out var parsedPort):
|
||||||
|
port = parsedPort;
|
||||||
|
index++;
|
||||||
|
break;
|
||||||
|
case "--timeout" when index + 1 < args.Length && double.TryParse(args[index + 1], out var parsedTimeoutSeconds):
|
||||||
|
timeout = TimeSpan.FromSeconds(parsedTimeoutSeconds);
|
||||||
|
index++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ProbeOptions(host, port, timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed record SdkProbeResult(bool ConnectRequestAccepted, string ConnectOutcome, string Detail);
|
||||||
|
|
||||||
|
internal sealed class ProbeEventHandler : KAEventHandler
|
||||||
|
{
|
||||||
|
private readonly TaskCompletionSource<int> _connectTask = new(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||||
|
private readonly TaskCompletionSource<int> _closeTask = new(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||||
|
|
||||||
|
public Task<int> ConnectTask => _connectTask.Task;
|
||||||
|
|
||||||
|
public Task<int> CloseTask => _closeTask.Task;
|
||||||
|
|
||||||
|
public void OnConnect(int ErrorCode)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[SDK] OnConnect errorCode={ErrorCode}");
|
||||||
|
_connectTask.TrySetResult(ErrorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnClose(int ErrorCode)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[SDK] OnClose errorCode={ErrorCode}");
|
||||||
|
_closeTask.TrySetResult(ErrorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnLoadScene(eKResult Result, string SceneName) { }
|
||||||
|
public void OnLoadSceneForce(eKResult Result, string SceneName) { }
|
||||||
|
public void OnLogMessage(string LogMessage) { }
|
||||||
|
public void OnMessageNo(uint MessageNo) { }
|
||||||
|
public void OnBeginTransaction(eKResult Result) { }
|
||||||
|
public void OnEndTransaction(eKResult Result) { }
|
||||||
|
public void OnHeartBeat(eKResult Result) { }
|
||||||
|
public void OnUnloadAll(eKResult Result) { }
|
||||||
|
public void OnSetTrialPlayoutMode(eKResult Result) { }
|
||||||
|
public void OnCheckVersion(eKResult Result, string ServerVersion, string SDKVersion) { }
|
||||||
|
public void OnSetAudioOutput(eKResult Result) { }
|
||||||
|
public void OnScenePrepare(eKResult Result, int OutputChannelIndex, int LayerNo) { }
|
||||||
|
public void OnScenePrepareEx(eKResult Result, int OutputChannelIndex, int LayerNo) { }
|
||||||
|
public void OnPlay(eKResult Result, int OutputChannelIndex, int LayerNo) { }
|
||||||
|
public void OnPlayOut(eKResult Result, int OutputChannelIndex, int LayerNo) { }
|
||||||
|
public void OnStop(eKResult Result, int OutputChannelIndex, int LayerNo) { }
|
||||||
|
public void OnStopAll(eKResult Result) { }
|
||||||
|
public void OnPause(eKResult Result, int OutputChannelIndex, int LayerNo) { }
|
||||||
|
public void OnResume(eKResult Result, int OutputChannelIndex, int LayerNo) { }
|
||||||
|
public void OnQueryIsOnAir(eKResult Result, int OutputChannelIndex, int LayerNo, int bOnAir) { }
|
||||||
|
public void OnTrigger(eKResult Result, int OutputChannelIndex, int LayerNo) { }
|
||||||
|
public void OnScenePlayingStarted(string SceneName, int OutputChannelIndex, int LayerNo) { }
|
||||||
|
public void OnScenePlayed(string SceneName, int OutputChannelIndex, int LayerNo) { }
|
||||||
|
public void OnSceneAnimationPlayed(string SceneName, int OutputChannelIndex, int LayerNo, string AnimationName) { }
|
||||||
|
public void OnScenePaused(string SceneName, int OutputChannelIndex, int LayerNo, int bLastPause) { }
|
||||||
|
public void OnSceneSaved(eKResult Result, string FileName) { }
|
||||||
|
public void OnTriggerObject(eKResult Result, int OutputChannelIndex, int LayerNo) { }
|
||||||
|
public void OnResumeBackground(eKResult Result, int OutputChannelIndex, int LayerNo) { }
|
||||||
|
public void OnSaveMixedPreviewImage(eKResult Result, int OutputChannelIndex, int LayerNo) { }
|
||||||
|
public void OnPlayDirect(eKResult Result, int OutputChannelIndex, int LayerNo) { }
|
||||||
|
public void OnCutIn(eKResult Result, int OutputChannelIndex, int LayerNo) { }
|
||||||
|
public void OnCutOut(eKResult Result, int OutputChannelIndex, int LayerNo) { }
|
||||||
|
public void OnClearNextPreview(eKResult Result, int OutputChannelIndex, int LayerNo) { }
|
||||||
|
public void OnPlayRange(eKResult Result, int OutputChannelIndex, int LayerNo) { }
|
||||||
|
public void OnQueryPlaybackRangeCount(eKResult Result, string SceneName, int PlaybackRangeCount) { }
|
||||||
|
public void OnQueryPlaybackRange(eKResult Result, string SceneName, int PlaybackRangeNo, int Start, int End) { }
|
||||||
|
public void OnQueryOutputChannelIndex(eKResult Result, string SceneName, int OutputChannelIndex) { }
|
||||||
|
public void OnPlayInNextPreview(eKResult Result, int OutputChannelIndex, int LayerNo) { }
|
||||||
|
public void OnPlayOutNextPreview(eKResult Result, int OutputChannelIndex, int LayerNo) { }
|
||||||
|
public void OnSetBackgroundFill(eKResult Result, string SceneName) { }
|
||||||
|
public void OnSetBackgroundTexture(eKResult Result, string SceneName) { }
|
||||||
|
public void OnSetBackgroundVideo(eKResult Result, string SceneName) { }
|
||||||
|
public void OnSetBackgroundLiveIn(eKResult Result, string SceneName) { }
|
||||||
|
public void OnUseBackground(eKResult Result, string SceneName) { }
|
||||||
|
public void OnSetBackgroundVideoPlayInfo(eKResult Result, string SceneName) { }
|
||||||
|
public void OnQueryBackgroundVideoPlayInfo(eKResult Result, string SceneName, ref sKVideoPlayInfo pVideoPlayInfo) { }
|
||||||
|
public void OnSetSceneEffectType(eKResult Result, string SceneName) { }
|
||||||
|
public void OnSaveSceneImage(eKResult Result, string SceneName) { }
|
||||||
|
public void OnSaveScene(eKResult Result, string SceneName) { }
|
||||||
|
public void OnUnloadScene(eKResult Result, string SceneName) { }
|
||||||
|
public void OnReloadScene(eKResult Result, string SceneName) { }
|
||||||
|
public void OnUpdateTextures(eKResult Result, string SceneName) { }
|
||||||
|
public void OnSetSceneAudioFile(eKResult Result, string SceneName) { }
|
||||||
|
public void OnEnableSceneAudio(eKResult Result, string SceneName) { }
|
||||||
|
public void OnSetSceneDuration(eKResult Result, string SceneName) { }
|
||||||
|
public void OnSetBackgroundPauseType(eKResult Result, string SceneName) { }
|
||||||
|
public void OnSetBackgroundChangeType(eKResult Result, string SceneName) { }
|
||||||
|
public void OnSetBackgroundPauseAtZeroFrameAsStandBy(eKResult Result, string SceneName) { }
|
||||||
|
public void OnResetDuration(eKResult Result, string SceneName) { }
|
||||||
|
public void OnSetDuration(eKResult Result, string SceneName) { }
|
||||||
|
public void OnAddObject(eKResult Result, string SceneName) { }
|
||||||
|
public void OnAddCloneObject(eKResult Result, string SceneName) { }
|
||||||
|
public void OnUpdateThumbnail(eKResult Result, string SceneName) { }
|
||||||
|
public void OnExportVideo(eKResult Result, string SceneName) { }
|
||||||
|
public void OnStopVideoExporting(eKResult Result) { }
|
||||||
|
public void OnQueryVideoExportingProgress(eKResult Result, string TargetName, int CurrentFrame, int TotalFrame) { }
|
||||||
|
public void OnFinishedVideoExporting(eKResult Result, string FileName) { }
|
||||||
|
public void OnAddPause(eKResult Result, string SceneName) { }
|
||||||
|
public void OnDeletePause(eKResult Result, string SceneName) { }
|
||||||
|
public void OnSetPause(eKResult Result, string SceneName) { }
|
||||||
|
public void OnSetPauseWithIndex(eKResult Result, string SceneName) { }
|
||||||
|
public void OnDeletePauseWithIndex(eKResult Result, string SceneName) { }
|
||||||
|
public void OnQueryPauseCount(eKResult Result, string SceneName, int PauseCount) { }
|
||||||
|
public void OnQueryObjectInfos(eKResult Result, string SceneName, KAObjectInfos pObjectInfos) { }
|
||||||
|
public void OnQueryAnimationNames(eKResult Result, string SceneName, KAStrings pAnimationNames) { }
|
||||||
|
public void OnQueryAnimationCount(eKResult Result, string SceneName, int AnimationCount) { }
|
||||||
|
public void OnQueryObjectInfosByScreenPoint(eKResult Result, KAObjectInfos pObjectInfos) { }
|
||||||
|
public void OnQuerySceneEffectType(eKResult Result, string SceneName, int bInEffect, eKEffectType EffectType, int Duration) { }
|
||||||
|
public void OnQueryDuration(eKResult Result, string SceneName, string AnimationName, int Duration) { }
|
||||||
|
public void OnQueryContentsOfTextObjects(eKResult Result, string SceneName, KAStrings pTexts) { }
|
||||||
|
public void OnSetStyleColor(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetStyleTexture(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetFaceTextColor(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetEdgeTextColor(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetShadowTextColor(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetVisible(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetValue(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnAddText(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnStoreTextStyle(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetTextStyle(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnEditText(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetFont(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetTextRange(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnResetTextRange(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnQueryObjectType(eKResult Result, string SceneName, string ObjectName, eKObjectType ObjectType) { }
|
||||||
|
public void OnSetChartCSVFile(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetChartCellData(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnQueryChartDataTable(eKResult Result, string SceneName, string ObjectName, KAChartDataTable Table) { }
|
||||||
|
public void OnQuerySize(eKResult Result, string SceneName, string ObjectName, float Width, float Height) { }
|
||||||
|
public void OnSetSize(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetCounterNumberKey(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetPositionKey(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetRotationKey(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetScaleKey(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetCylinderAngleKey(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetSphereAngleKey(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetCircleAngleKey(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetCropKey(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetCountDown(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetPosition(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetRotation(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetScale(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnAddPathPoint(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnClearPathPoints(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnAddPathShapePoint(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnClearPathShapePoints(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnQueryScrollRemainingDistance(eKResult Result, string SceneName, string ObjectName, int ScrollRemainingDistance) { }
|
||||||
|
public void OnQueryScrollChildRemainingDistance(eKResult Result, string SceneName, string ObjectName, string ChildName, int ScrollRemainingDistance) { }
|
||||||
|
public void OnAddScrollObject(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnAdjustScrollSpeed(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetScrollSpeed(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetVariableName(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetLoftPositionKey(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetChangeOut(eKResult Result, string SceneName) { }
|
||||||
|
public void OnModifyPathPoint(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnInitScrollObject(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetCounterInfo(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetCounterNumber(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetCounterRange(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetCounterRemainingTime(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetCounterElapsedTime(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSaveObjectImage(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetPositionOfPathAnimation(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetPositionKeyOfPathAnimation(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetStartFrame(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetObjectEffectType(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetObjectOutEffectDelay(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetColor(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetColorKey(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetEmissiveColor(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetEmissiveColorKey(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetTransparencyOpacity(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetTransparencyOpacityKey(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetExposure(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetExposureKey(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetMaterialTextureType(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetMaterialTextureFile(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetMaterialTextureOffset(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetMaterialTextureOffsetKey(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetMaterialTextureTiling(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetMaterialTextureTilingKey(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetMaterialTextureRotation(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetMaterialTextureRotationKey(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetMaterialTextureOpacity(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetMaterialTextureOpacityKey(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnQueryGroupType(eKResult Result, string SceneName, string ObjectName, eKGroupType GroupType) { }
|
||||||
|
public void OnQueryImageType(eKResult Result, string SceneName, string ObjectName, eKImageType ImageType) { }
|
||||||
|
public void OnSetVideoPlayInfo(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnQueryVideoPlayInfo(eKResult Result, string SceneName, string ObjectName, ref sKVideoPlayInfo pVideoPlayInfo) { }
|
||||||
|
public void OnQueryIs3D(eKResult Result, string SceneName, string ObjectName, int b3D) { }
|
||||||
|
public void OnQueryPosition(eKResult Result, string SceneName, string ObjectName, float X, float Y, float Z) { }
|
||||||
|
public void OnSetImageType(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetMemo(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnQueryMemo(eKResult Result, string SceneName, string ObjectName, string Memo) { }
|
||||||
|
public void OnQueryFont(eKResult Result, string SceneName, string ObjectName, ref sKFont Param) { }
|
||||||
|
public void OnSetImageOriginalSize(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnApplyChangeEffectLibrary(eKResult Result, string SceneName) { }
|
||||||
|
public void OnApplyObjectLibrary(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnApplyTextureEffectLibrary(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetTableValue(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetTableColor(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnQueryTableValue(eKResult Result, string SceneName, string ObjectName, int Row, int Column, string Value) { }
|
||||||
|
public void OnQueryTableValues(eKResult Result, string SceneName, string ObjectName, KATableValues pValues) { }
|
||||||
|
public void OnSetPathShapeOutlineThickness(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnEnablePathShapeOutline(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetPlaybackCamera(eKResult Result, string SceneName) { }
|
||||||
|
public void OnSetMaterialTextureVideoPlayInfo(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnQueryMaterialTextureVideoPlayInfo(eKResult Result, string SceneName, string ObjectName, ref sKVideoPlayInfo VideoPlayInfo) { }
|
||||||
|
public void OnQueryVideoFormat(eKResult Result, ref sKVideoFormat VideoFormat) { }
|
||||||
|
public void OnQueryLiveStreamingStatus(eKResult Result, string StreamingURI, eKLiveStreamingStatus Status) { }
|
||||||
|
public void OnPreloadLiveStreaming(eKResult Result, string StreamingURI) { }
|
||||||
|
public void OnReleaseLiveStreaming(eKResult Result, string StreamingURI) { }
|
||||||
|
public void OnUpdateImageResource(eKResult Result) { }
|
||||||
|
public void OnQueryLayerCount(eKResult Result, int LayerCount) { }
|
||||||
|
public void OnSetLayerViewportRate(eKResult Result, int OutputChannelIndex, int LayerNo) { }
|
||||||
|
public void OnSetLayerViewportRateEx(eKResult Result, int OutputChannelIndex, int LayerNo) { }
|
||||||
|
public void OnSetFitting(eKResult Result, string SceneName) { }
|
||||||
|
public void OnSetFittingOffset(eKResult Result, string SceneName) { }
|
||||||
|
public void OnSetFittingScale(eKResult Result, string SceneName) { }
|
||||||
|
public void OnSetLightColor(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnEnableLight(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetDirectionalLight(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetPointLight(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetSpotLight(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetInfinitePointLight(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetMaterialTextureLiveStreamingURI(eKResult Result, string SceneName, string ObjectName) { }
|
||||||
|
public void OnSetBackgroundLiveStreamingURI(eKResult Result, string SceneName) { }
|
||||||
|
public void OnLoadProject(eKResult Result, string FilePath, string AliasName) { }
|
||||||
|
public void OnNewProject(eKResult Result, string AliasName) { }
|
||||||
|
public void OnUnloadAllProject(eKResult Result) { }
|
||||||
|
public void OnSaveProject(eKResult Result, string AliasName) { }
|
||||||
|
public void OnQuerySceneItemCount(eKResult Result, string AliasName, int SceneItemCount) { }
|
||||||
|
public void OnQuerySceneItemInfos(eKResult Result, string AliasName, KASceneItemInfos SceneItemInfos) { }
|
||||||
|
public void OnAddSceneItem(eKResult Result, string AliasName, int Index) { }
|
||||||
|
public void OnInsertSceneItem(eKResult Result, string AliasName) { }
|
||||||
|
public void OnDeleteSceneItem(eKResult Result, string AliasNAme) { }
|
||||||
|
public void OnQueryProjectFormat(eKResult Result, ref sKVideoFormat ProjectFormat) { }
|
||||||
|
public void OnSetTimecode(eKResult Result, string AliasName) { }
|
||||||
|
public void OnSetTimecodeInOut(eKResult Result, string AliasName) { }
|
||||||
|
public void OnSetTimecodeTrack(eKResult Result, string AliasName) { }
|
||||||
|
public void OnSetTimecodeInOutType(eKResult Result, string AliasName) { }
|
||||||
|
public void OnDeleteTimecode(eKResult Result, string AliasName) { }
|
||||||
|
public void OnQueryTimecode(eKResult Result, int TrackNo, int In, int Out, int bOnTrack) { }
|
||||||
|
public void OnUnloadProject(eKResult Result, string AliasName) { }
|
||||||
|
public void OnEnableSyncWithSceneEffect(eKResult Result, string AliasName) { }
|
||||||
|
public void OnExportProjectVideo(eKResult Result, string AliasName) { }
|
||||||
|
public void OnExportSceneImage(eKResult Result, string SceneName) { }
|
||||||
|
public void OnStartVideoCapture(eKResult Result) { }
|
||||||
|
public void OnStopVideoCapture(eKResult Result) { }
|
||||||
|
public void OnCaptureImage(eKResult Result) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct NativeMessage
|
||||||
|
{
|
||||||
|
public IntPtr hwnd;
|
||||||
|
public uint message;
|
||||||
|
public UIntPtr wParam;
|
||||||
|
public IntPtr lParam;
|
||||||
|
public uint time;
|
||||||
|
public NativePoint pt;
|
||||||
|
public uint lPrivate;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct NativePoint
|
||||||
|
{
|
||||||
|
public int x;
|
||||||
|
public int y;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static class User32
|
||||||
|
{
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
internal static extern bool PeekMessage(out NativeMessage lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax, uint wRemoveMsg);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
internal static extern bool TranslateMessage([In] ref NativeMessage lpMsg);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
internal static extern IntPtr DispatchMessage([In] ref NativeMessage lpMsg);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user