開關台自動刷新QRCODE亂碼

This commit is contained in:
jasonchenwork 2025-05-19 13:02:09 +08:00
parent d5b7623dd8
commit 424ef89dbc
6 changed files with 136 additions and 19 deletions

View File

@ -35,8 +35,14 @@ namespace DualScreenDemo
private static readonly ConcurrentDictionary<string, byte[]> _fileCache = new ConcurrentDictionary<string, byte[]>();
private static readonly SemaphoreSlim _requestThrottle = new SemaphoreSlim(20); // 限制并发请求数
private static readonly CancellationTokenSource _serverCts = new CancellationTokenSource();
private static HttpListener _listener;
private static CancellationTokenSource _cts;
private static Task _serverTask;
private static string _baseDirectory = @"themes\superstar\_www"; // 根據實際情況設定
private static SongListManager _songListManager;
private static TaskCompletionSource<string> _qrReadyTcs;
/*
public static async Task StartServer(string baseDirectory, int port, SongListManager manager)
{
songListManager = manager; // 保存传递的SongListManager实例
@ -130,6 +136,101 @@ namespace DualScreenDemo
await ProcessRequestAsync(context, baseDirectory, randomFolderName);
}
}
*/
public static async Task StartServer(string baseDirectory, int port, SongListManager manager, CancellationToken token)
{
_songListManager = manager;
string randomFolderName = CreateRandomFolderAndRedirectHTML(baseDirectory);
randomFolderPath = randomFolderName;
Console.WriteLine("測試" + randomFolderPath);
string localAddress = GetLocalIPAddress();
string externalAddress = File.Exists(@"\\SVR01\superstarb\txt\ip.txt")
? File.ReadAllText(@"\\SVR01\superstarb\txt\ip.txt").Trim()
: "";
_listener = new HttpListener();
_listener.Prefixes.Add($"http://{localAddress}:{port}/");
string hostName = System.Net.Dns.GetHostName();
string externalPort = '1' + hostName.Substring(Math.Max(2, hostName.Length - 20));
if (!string.IsNullOrEmpty(externalAddress))
{
string host = externalAddress.Split(':')[0];
externalPort = '1' + System.Net.Dns.GetHostName().Substring(Math.Max(2, System.Net.Dns.GetHostName().Length - 20));
_listener.Prefixes.Add($"http://{host}:{externalPort}/");
}
string localQrContent = String.Format("http://{0}:{1}/{2}/windows.html", localAddress, port, randomFolderName);
// 修改外网二维码内容生成
string externalQrContent = !string.IsNullOrEmpty(externalAddress) ?
String.Format("http://{0}:{1}/{2}/windows.html", externalAddress, externalPort, randomFolderName) :
localQrContent;
/*string qrContent = !string.IsNullOrEmpty(externalAddress)
? $"http://{externalAddress}:{port}/{randomFolderName}/windows.html"
: $"http://{localAddress}:{port}/{randomFolderName}/windows.html";*/
Console.WriteLine("qrcode 測試內容 " + externalQrContent);
GenerateQRCode(externalQrContent, Path.Combine(baseDirectory, randomFolderName, "qrcode.png"));
_qrReadyTcs?.TrySetResult(randomFolderName); // safe callnull-safe
try
{
_listener.Start();
Console.WriteLine("Server started.");
}
catch (HttpListenerException ex)
{
Console.WriteLine("Error starting server: " + ex.Message);
return;
}
while (!token.IsCancellationRequested)
{
try
{
HttpListenerContext context = await _listener.GetContextAsync();
await ProcessRequestAsync(context, baseDirectory, randomFolderName);
}
catch (HttpListenerException)
{
// 可能是 Stop() 引起,不處理
break;
}
}
_listener.Close();
Console.WriteLine("Server stopped.");
}
public static async Task RestartServer()
{
Console.WriteLine("Restarting server...");
_cts?.Cancel();
_listener?.Stop();
if (_serverTask != null)
{
try { await _serverTask; }
catch (OperationCanceledException) { }
}
DeleteRandomFolder(_baseDirectory);
_cts = new CancellationTokenSource();
// ✅ 等 QR code 跑完
_qrReadyTcs = new TaskCompletionSource<string>();
_serverTask = StartServer(_baseDirectory, _port, _songListManager, _cts.Token);
string readyFolder = await _qrReadyTcs.Task;
// ✅ 等 QR Code 圖片準備好之後再處理 UI 更新
Console.WriteLine("restart : " + readyFolder);
PrimaryForm.Instance.OverlayQRCodeOnImage(readyFolder);
OverlayForm.Instance.DisplayQRCodeOnOverlay(readyFolder);
}
private static async Task ProcessRequestWithTimeout(HttpListenerContext context, string baseDirectory, string randomFolderName)
{

View File

@ -1,18 +1,21 @@
using System.IO;
using System.Linq;
using System.Windows.Forms;
using System.Threading;
namespace DualScreenDemo
{
public static class HttpServerManager
{
private static CancellationTokenSource _cts;
public static async void StartServer()
{
int httpPort = 9090; // 你可以修改此端口
string baseDirectory = Path.Combine(Application.StartupPath, @"themes\superstar\_www");
CleanUpDirectory(baseDirectory);
await HttpServer.StartServer(baseDirectory, httpPort, Program.songListManager);
// await HttpServer.StartServer(baseDirectory, httpPort, Program.songListManager);
_cts = new CancellationTokenSource();
await HttpServer.StartServer(baseDirectory, httpPort, Program.songListManager, _cts.Token);
}

View File

@ -74,11 +74,12 @@ namespace OverlayFormObj
get { return _mainForm; }
private set { _mainForm = value; }
}
public static OverlayForm Instance { get; private set; }
public OverlayForm()
{
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
MainForm = this;
Instance = this;
InitializeFormSettings();
ConfigureTimers();

View File

@ -7,10 +7,10 @@ namespace DualScreenDemo
{
public partial class PrimaryForm : Form
{
private PictureBox pictureBoxQRCode;
private Button closeQRCodeButton;
public PictureBox pictureBoxQRCode;
public Button closeQRCodeButton;
private void OverlayQRCodeOnImage(string randomFolderPath)
public void OverlayQRCodeOnImage(string randomFolderPath)
{
try
{
@ -48,13 +48,15 @@ namespace DualScreenDemo
return;
}
string tempPath = Path.GetTempFileName();
File.Copy(qrImagePath, tempPath, true); // 複製一份再讀,避開快取
Image qrCodeImage = null;
for (int i = 0; i < 3; i++)
{
try
{
using (var fs = new FileStream(qrImagePath, FileMode.Open, FileAccess.Read))
using (var fs = new FileStream(tempPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
qrCodeImage = Image.FromStream(fs);
}
@ -66,7 +68,7 @@ namespace DualScreenDemo
System.Threading.Thread.Sleep(100);
}
}
File.Delete(tempPath); // 用完記得刪除
if (qrCodeImage == null)
{
Console.WriteLine("Failed to load QR code image after multiple attempts.");

View File

@ -149,11 +149,13 @@ namespace DualScreenDemo
// 指令為 "X":播放 CLOSE.MPG並顯示送客畫面
if (command.Trim().Equals("X", StringComparison.OrdinalIgnoreCase))
{
PrimaryForm.Instance.pictureBoxQRCode.Visible = false;
PrimaryForm.Instance.closeQRCodeButton.Visible = false;
_ = SafeInvoke(VideoPlayerForm.Instance, async () =>
{
if (IsFormReady(PrimaryForm.Instance))
{
await SafeInvoke(PrimaryForm.Instance, () =>
await SafeInvoke(PrimaryForm.Instance, async () =>
{
PrimaryForm.Instance.ShowSendOffScreen();
PrimaryForm.Instance.HideFireScreen();
@ -197,6 +199,14 @@ namespace DualScreenDemo
}
VideoPlayerForm.Instance.PlayNextSong();
Console.WriteLine("已設置新的播放列表,包含當前歌曲和 CLOSE.MPG");
try
{
await HttpServer.RestartServer();
}
catch (Exception ex)
{
Console.WriteLine("RestartServer 發生錯誤: " + ex.Message);
}
}
else
{

View File

@ -14,5 +14,5 @@ Filter: LAV Splitter
Pin: Input
Pin: Video
Pin: Audio
Filter: C:\video\BGM01.mpg
Filter: C:\video\welcome.mpg
Pin: Output