開關台自動刷新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;
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();
@ -167,13 +169,13 @@ namespace DualScreenDemo
{
// 建立結束播放用的 SongData 實例
SongData closeSong = new SongData(
"", "", "結束播放", 0, "", "", "", "",
DateTime.Now, closePath, "", "", "", "",
"", "", "結束播放", 0, "", "", "", "",
DateTime.Now, closePath, "", "", "", "",
"", "", "", "", "", "", "", 1
);
// 建立新的播放清單
VideoPlayerForm.publicPlaylist = new List<SongData>();
VideoPlayerForm.playingSongList = new List<SongData>();
PrimaryForm.playedSongsHistory = new List<SongData>();
@ -182,8 +184,8 @@ namespace DualScreenDemo
{
VideoPlayerForm.playingSongList.Add(VideoPlayerForm.Instance.currentPlayingSong);
}
VideoPlayerForm.publicPlaylist.Add(closeSong);
VideoPlayerForm.publicPlaylist.Add(closeSong);
// 將 CLOSE.MPG 加入播放清單
VideoPlayerForm.playingSongList.Add(closeSong);
@ -195,8 +197,16 @@ namespace DualScreenDemo
{
OverlayForm.MainForm.nextSongLabel.Visible = false;
}
VideoPlayerForm.Instance.PlayNextSong();
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