202508111732

調整開包廂計算關包廂時間
調整寫法
This commit is contained in:
jasonchenwork 2025-08-11 17:36:01 +08:00
parent be19d8bcf7
commit fdd8cf047d
13 changed files with 133 additions and 349 deletions

View File

@ -15,12 +15,9 @@ namespace DBObj
NameSimplified=nameSimplified; NameSimplified=nameSimplified;
} }
public string getName(bool IsSimplified=false) { return IsSimplified ? NameSimplified : Name; } public string getName(bool IsSimplified=false) { return IsSimplified ? NameSimplified : Name; }
public string getName() {return Name;} public string getName() => Name;
public override string ToString() => $"Name: {Name}";
public override string ToString()
{
//return $"Name: {Name}, Phonetic: {Phonetic}, Category: {Category}, Strokes: {Strokes}";
return $"Name: {Name}";
}
} }
} }

View File

@ -119,53 +119,22 @@ namespace DBObj
} }
return dict; return dict;
} }
public void moveNext() public void moveNext() => cursor++;
{ public void movePrevious() => cursor--;
cursor++; public void move(int index) => cursor = index;
} public void moveFirst() => cursor = 0;
public void movePrevious() public void moveEnd() => cursor = table.Rows.Count - 1;
{ public bool bof() => (cursor < 0) || (table.Rows.Count == 0);
cursor--; public bool eof() => cursor > table.Rows.Count - 1;
}
public void move(int index)
{
cursor = index;
}
public void moveFirst()
{
cursor = 0;
}
public void moveEnd()
{
cursor = table.Rows.Count - 1;
}
public bool bof()
{
return (cursor < 0) || (table.Rows.Count == 0);
}
public bool eof()
{
return cursor > table.Rows.Count - 1;
}
public bool Read() public bool Read()
{ {
if (eof()) return false; if (eof()) return false;
moveNext(); moveNext();
return !eof(); return !eof();
} }
public int recordCount() public int recordCount() => table.Rows.Count;
{ public bool found() => table.Rows.Count > 0;
return table.Rows.Count; public void clear() => table.Clear();
}
public bool found()
{
return table.Rows.Count > 0;
}
public void clear()
{
table.Clear();
}
// INSERT / UPDATE / DELETE 方法 // INSERT / UPDATE / DELETE 方法
public int ExecuteNonQuery(string query, MySqlParameter[] parameters) public int ExecuteNonQuery(string query, MySqlParameter[] parameters)

View File

@ -17,10 +17,10 @@ namespace DBObj
FileName=filename; FileName=filename;
HumanVoice =humanVoice; HumanVoice =humanVoice;
} }
public string getNumber() {return Number;} public string getNumber() => Number;
public string getName(bool IsSimplified) {return IsSimplified ? Name_Simplified : Name;} public string getName(bool IsSimplified) => IsSimplified ? Name_Simplified : Name;
public string getName() { return Name;} public string getName() =>Name;
public string getFileName() { return FileName;} public string getFileName() => FileName;
public int getHumanVoice() { return HumanVoice;} public int getHumanVoice() => HumanVoice;
} }
} }

View File

@ -21,12 +21,7 @@ namespace DBObj
{ {
basic=new(songNumber,song,songSimplified,filename,humanVoice); basic=new(songNumber,song,songSimplified,filename,humanVoice);
A = new Artist(artistA, artistASimplified); A = new Artist(artistA, artistASimplified);
if(!artistB.Equals("")){ B = !artistB.Equals("") ? new Artist(artistB, artistBSimplified) : null;
B = new Artist(artistB, artistBSimplified);
} else
{
B = null;
}
isPublicSong = false; isPublicSong = false;
} }
public SongData(SongData value,PlayState s){ public SongData(SongData value,PlayState s){
@ -39,15 +34,15 @@ namespace DBObj
public Artist getA() => A; public Artist getA() => A;
public Artist getB() => B; public Artist getB() => B;
public string getNumber() {return basic.getNumber();} public string getNumber() => basic.getNumber();
public string getName(bool IsSimplified=false) { return basic.getName(IsSimplified); } public string getName(bool IsSimplified=false) => basic.getName(IsSimplified);
public string getName() { return basic.getName();} public string getName() => basic.getName();
public string getArtist_A(bool IsSimplified) { return A.getName(IsSimplified); } public string getArtist_A(bool IsSimplified) => A.getName(IsSimplified);
public string getArtist_A() { return A.getName();} public string getArtist_A() => A.getName();
public string getArtist_B(bool IsSimplified) { return B.getName(IsSimplified); } public string getArtist_B(bool IsSimplified) => B.getName(IsSimplified);
public string getArtist_B() { return B.getName();} public string getArtist_B() => B.getName();
public int getNameLength() { return basic.getName().Length; } public int getNameLength() =>basic.getName().Length;
public string getFileName() {return basic.getFileName();} public string getFileName() => basic.getFileName();
public string next_song_text() public string next_song_text()
{ {
var str = (state == PlayState.InsertPlayback) ? GetStateTxt(false) : ""; var str = (state == PlayState.InsertPlayback) ? GetStateTxt(false) : "";
@ -101,26 +96,21 @@ namespace DBObj
} }
return null; // 找不到就回原本的 filename不加路徑 return null; // 找不到就回原本的 filename不加路徑
} }
public Color GetStateColor(){ public Color GetStateColor() => state switch
Color c = Color.White; {
if (state == PlayState.Played) c = Color.Gray;//Color.FromArgb(200, 75, 125); // 播畢顏色:紫紅色 PlayState.Played => Color.Gray,
else if (state == PlayState.Skipped)c = Color.Gray; PlayState.Skipped => Color.Gray,
else if (state == PlayState.NoFile)c = Color.Gray; PlayState.NoFile => Color.Gray,
else if (state == PlayState.Playing)c = Color.LimeGreen; PlayState.Playing => Color.LimeGreen,
else if (state == PlayState.InsertPlayback)c = Color.Gold; PlayState.InsertPlayback => Color.Gold,
return c; _ => Color.White
} };
public string GetStateTxt(bool IsSimplified){ public string GetStateTxt(bool IsSimplified) => (state==PlayState.NotPlayed)?"":$"({state.GetDescription(IsSimplified)})";
return (state==PlayState.NotPlayed)?"":$"({state.GetDescription(IsSimplified)})";
}
public void SetState(PlayState s) => state = s; public void SetState(PlayState s) => state = s;
public PlayState GetState() public PlayState GetState() => state;
{
return state;
}
public int getHumanVoice() { return basic.getHumanVoice(); } public int getHumanVoice() => basic.getHumanVoice();
public override string ToString() public override string ToString()
{ {
return String.Format("{0} {1}", basic.getName(),state.GetDescription() ); return String.Format("{0} {1}", basic.getName(),state.GetDescription() );

View File

@ -162,7 +162,6 @@ namespace DBObj
} }
public static void clearSong() public static void clearSong()
{ {
isWelcome = true; isWelcome = true;
not_played.Clear(); not_played.Clear();
played.Clear(); played.Clear();

View File

@ -38,7 +38,6 @@ namespace OverlayFormObj
private int topMargin; private int topMargin;
private int bottomMargin; private int bottomMargin;
public static System.Windows.Forms.Timer displayTimer = new System.Windows.Forms.Timer(); public static System.Windows.Forms.Timer displayTimer = new System.Windows.Forms.Timer();
public static System.Timers.Timer songDisplayTimer = new System.Timers.Timer();
public static System.Timers.Timer unifiedTimer; public static System.Timers.Timer unifiedTimer;
private System.Windows.Forms.Timer stickerTimer1 = new System.Windows.Forms.Timer(); private System.Windows.Forms.Timer stickerTimer1 = new System.Windows.Forms.Timer();
private System.Windows.Forms.Timer stickerTimer2 = new System.Windows.Forms.Timer(); private System.Windows.Forms.Timer stickerTimer2 = new System.Windows.Forms.Timer();
@ -360,12 +359,6 @@ namespace OverlayFormObj
displayTimer.Interval = 15000; displayTimer.Interval = 15000;
displayTimer.Tick += DisplayTimer_Tick; displayTimer.Tick += DisplayTimer_Tick;
songDisplayTimer = new System.Timers.Timer(30000);
songDisplayTimer.Elapsed += new ElapsedEventHandler(SongDisplayTimer_Elapsed);
songDisplayTimer.AutoReset = true;
songDisplayTimer.Enabled = true;
unifiedTimer = new System.Timers.Timer(15000); unifiedTimer = new System.Timers.Timer(15000);
unifiedTimer.Elapsed += new ElapsedEventHandler(UnifiedTimer_Elapsed); unifiedTimer.Elapsed += new ElapsedEventHandler(UnifiedTimer_Elapsed);
@ -416,35 +409,6 @@ namespace OverlayFormObj
displayTimer.Stop(); // 停止计时器 displayTimer.Stop(); // 停止计时器
} }
// 當 songDisplayTimer 計時完成時會呼叫此函式
private static void SongDisplayTimer_Elapsed(object sender, EventArgs e)
{
// 檢查是否需要跨執行緒操作 UI 控制項
if (MainForm.InvokeRequired)
{
// 如果目前不在 UI 執行緒上,必須透過 Invoke 安全執行 UI 更新邏輯
Console.WriteLine("SongDisplayTimer_Tick invoked on UI thread.");
MainForm.BeginInvoke(new Action(() =>
{
if (MainForm.topLeftLabel != null)
MainForm.topLeftLabel.Visible = true;
}));
}
else
{
// 如果已經在 UI 執行緒,就直接更新 UI 控制項
Console.WriteLine("SongDisplayTimer_Tick invoked on background thread.");
//MainForm.songDisplayLabel.Text = "";
MainForm.topLeftLabel.Visible = true;
}
// 停止計時器,避免重複觸發
songDisplayTimer.Stop();
}
private readonly object _lockObject = new object(); private readonly object _lockObject = new object();
private bool _handlingTimeout = false; private bool _handlingTimeout = false;
private async void UnifiedTimer_Elapsed(object sender, EventArgs e) private async void UnifiedTimer_Elapsed(object sender, EventArgs e)

View File

@ -175,7 +175,6 @@ namespace DualScreenDemo
private PictureBox serviceBellPictureBox; // 添加为类成员变量 private PictureBox serviceBellPictureBox; // 添加为类成员变量
private Timer autoRefreshTimer; private Timer autoRefreshTimer;
private TimeSpan remainingTime;
private Timer timerCountdown; private Timer timerCountdown;
string Rtime; string Rtime;
@ -232,7 +231,7 @@ namespace DualScreenDemo
timerCountdown = new Timer(); timerCountdown = new Timer();
timerCountdown.Interval = 1000; // 1 second timerCountdown.Interval = 1000; // 1 second
timerCountdown.Tick += TimerCountdown_Tick; timerCountdown.Tick += TimerCountdown_Tick;
timerCountdown.Start();
} }
// 添加 DPI 感知支持 // 添加 DPI 感知支持
@ -252,18 +251,10 @@ namespace DualScreenDemo
} }
} }
public void RoomTimeStart()
{
//DateTime now = DateTime.Now;
//DateTime tenMinutesLater = now.AddMinutes(120);
//remainingTime = tenMinutesLater - now;
remainingTime = Program.room.timePeriod;
timerCountdown.Start();
}
private async void TimerCountdown_Tick(object sender, EventArgs e) private async void TimerCountdown_Tick(object sender, EventArgs e)
{ {
TimeSpan remainingTime = Program.room.getTimeSpan();
if (remainingTime.TotalSeconds > 0) if (remainingTime.TotalSeconds > 0)
{ {
remainingTime = remainingTime.Subtract(TimeSpan.FromSeconds(1)); remainingTime = remainingTime.Subtract(TimeSpan.FromSeconds(1));

View File

@ -13,7 +13,7 @@ namespace DualScreenDemo
private static PrimaryForm primaryForm; // 儲存實例的參考 private static PrimaryForm primaryForm; // 儲存實例的參考
public static Room room = new Room(); public static Room room = new Room();
public static string verSion = "Server V2.8 202508081823"; public static string verSion = "Server V2.8 202508111732";
[STAThread] [STAThread]
static void Main() static void Main()

19
Room.cs
View File

@ -13,7 +13,6 @@ namespace DualScreenDemo
private string State = "error"; private string State = "error";
private DateTime? startedAt; private DateTime? startedAt;
private DateTime? endedAt; private DateTime? endedAt;
public TimeSpan timePeriod;
public Room() public Room()
{ {
@ -47,14 +46,13 @@ namespace DualScreenDemo
var Statedb = db.Field<string>("status"); var Statedb = db.Field<string>("status");
startedAt = ParseTime(db.Field<string>("started_at")); startedAt = ParseTime(db.Field<string>("started_at"));
endedAt = ParseTime(db.Field<string>("ended_at")); endedAt = ParseTime(db.Field<string>("ended_at"));
timePeriod = (TimeSpan)(endedAt - DateTime.Now);
PrimaryForm.Instance.RoomTimeStart();
if (Statedb.Equals("maintain")) { Statedb = "active"; } if (Statedb.Equals("maintain")) { Statedb = "active"; }
return Statedb; return Statedb;
} }
} }
return "error"; return "error";
} }
public TimeSpan getTimeSpan() => (endedAt!=null && endedAt.HasValue) ?(TimeSpan)(endedAt.Value - DateTime.Now):TimeSpan.Zero;
public void setDB(string value) public void setDB(string value)
{ {
using (var db = new MyDB()) using (var db = new MyDB())
@ -72,13 +70,9 @@ namespace DualScreenDemo
{ {
string StateDB=getDB(); string StateDB=getDB();
if (!StateDB.Equals(State)) if (!StateDB.Equals(State))
{
State = StateDB; State = StateDB;
}
else else
{
return; return;
}
string marqueeMessage = "歡迎使用超級巨星歡唱,與你共度美好時光。"; string marqueeMessage = "歡迎使用超級巨星歡唱,與你共度美好時光。";
Color c = Color.White; Color c = Color.White;
@ -119,14 +113,9 @@ namespace DualScreenDemo
return dt; return dt;
return null; return null;
} }
public bool IsClose() public bool IsClose() => State.Equals("closed");
{
return State.Equals("closed"); public bool IsOpen() => State.Equals("active");
}
public bool IsOpen()
{
return State.Equals("active");
}
} }

View File

@ -8,63 +8,12 @@ namespace DualScreenDemo.Services
{ {
public IGraphBuilder graphBuilder; public IGraphBuilder graphBuilder;
private IMediaControl mediaControl; private IMediaControl mediaControl;
private IBaseFilter videoRenderer; public IBaseFilter renderer;
//private IBaseFilter audioRenderer;
private IBaseFilter lavSplitter; private IBaseFilter lavSplitter;
private IBaseFilter lavVideoDecoder; public int Run() => (mediaControl != null) ? mediaControl.Run() : 0;
private IBaseFilter lavAudioDecoder; public int Stop() => (mediaControl != null) ? mediaControl.Stop() : 0;
private IPin outputPin; public int Pause() => (mediaControl != null) ? mediaControl.Pause() : 0;
private IBaseFilter audioRenderer;
private IVideoWindow videoWindow;
public int Run()
{
if (mediaControl != null)
return mediaControl.Run();
else
return 0;
}
public int Stop()
{
if (mediaControl != null)
return mediaControl.Stop();
else
return 0;
}
public int Pause()
{
if (mediaControl != null)
return mediaControl.Pause();
else
return 0;
}
public void VideoPlayerFormClosing()
{
if (videoWindow != null)
{
videoWindow.put_Visible(OABool.False);
videoWindow.put_Owner(IntPtr.Zero);
Marshal.ReleaseComObject(videoWindow);
videoWindow = null;
}
}
public void StopAndReleaseResources()
{
if (mediaControl != null)
{
mediaControl.Stop();
SafeRelease(ref mediaControl);
}
SafeRelease(ref videoWindow);
SafeRelease(ref videoRenderer);
SafeRelease(ref lavAudioDecoder);
SafeRelease(ref outputPin);
SafeRelease(ref lavVideoDecoder);
SafeRelease(ref lavSplitter);
SafeRelease(ref graphBuilder);
}
public bool isAtEnd() public bool isAtEnd()
{ {
bool isAtEnd = false; bool isAtEnd = false;
@ -92,42 +41,22 @@ namespace DualScreenDemo.Services
} }
return isAtEnd; return isAtEnd;
} }
public void RenderMediaFile(string filePath, nint Handle, int Width, int Height) public void RenderMediaFile(string filePath)
{ {
StopAndReleaseResources(); Stop();
if (videoWindow != null) videoWindow.put_Visible(OABool.False); SafeRelease(ref renderer);
SafeRelease(ref lavSplitter);
SafeRelease(ref graphBuilder);
int hr = 0; int hr = 0;
graphBuilder = (IGraphBuilder)new FilterGraph(); graphBuilder = (IGraphBuilder)new FilterGraph();
if (graphBuilder == null)
{
Console.WriteLine("Failed to create FilterGraph");
throw new Exception("Failed to create FilterGraph");
}
try try
{ {
lavSplitter = AddFilterByClsid(graphBuilder, "LAV Splitter", Clsid.LAVSplitter); lavSplitter = AddFilterByClsid(graphBuilder, "LAV Splitter", Clsid.LAVSplitter);
lavVideoDecoder = AddFilterByClsid(graphBuilder, "LAV Video Decoder", Clsid.LAVVideoDecoder); AddFilterByClsid(graphBuilder, "LAV Video Decoder", Clsid.LAVVideoDecoder);
lavAudioDecoder = AddFilterByClsid(graphBuilder, "LAV Audio Decoder", Clsid.LAVAudioDecoder); renderer = AddFilterByClsid(graphBuilder, "Secondary Video Renderer", Clsid.VideoRenderer);
outputPin = FindPin(lavAudioDecoder, "Output"); //audioRenderer = AddFilterByClsid(graphBuilder, "Default DirectSound Device", Clsid.AudioRenderer);
videoRenderer = AddFilterByClsid(graphBuilder, "Secondary Video Renderer", Clsid.VideoRenderer);
if (videoRenderer == null)
{
Console.WriteLine("Failed to initialize Secondary Video Renderer.");
return;
}
hr = graphBuilder.AddFilter(videoRenderer, "Secondary Video Renderer");
DsError.ThrowExceptionForHR(hr);
var clsidAudioRenderer = new Guid("79376820-07D0-11CF-A24D-0020AFD79767"); // CLSID for DirectSound Renderer
audioRenderer = (IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(clsidAudioRenderer));
hr = graphBuilder.AddFilter(audioRenderer, "Default DirectSound Device");
DsError.ThrowExceptionForHR(hr);
mediaControl = (IMediaControl)graphBuilder; mediaControl = (IMediaControl)graphBuilder;
if (mediaControl == null)
{
Console.WriteLine("Failed to get Media Control");
return;
}
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -135,40 +64,25 @@ namespace DualScreenDemo.Services
} }
hr = graphBuilder.RenderFile(filePath, null); hr = graphBuilder.RenderFile(filePath, null);
if (hr == 0) if (hr == 0)
{
Console.WriteLine("Secondary File rendered successfully.");
SetAudioTrackTo(1); SetAudioTrackTo(1);
}
else else
{
Console.WriteLine("Failed to render secondary file."); Console.WriteLine("Failed to render secondary file.");
}
// 绑定视频窗口到副屏幕
videoWindow = videoRenderer as IVideoWindow;
if (videoWindow != null)
{
videoWindow.put_Owner(Handle); // 副屏幕窗口句柄
videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren | WindowStyle.ClipSiblings);
videoWindow.SetWindowPosition(0, 0, Width, Height);
videoWindow.put_Visible(OABool.True); // 显示窗口
}
} }
public void SetVolume(int volume) public void SetVolume(int volume)
{ {
if (audioRenderer != null) if (graphBuilder != null)
{ {
IBasicAudio basicAudio = audioRenderer as IBasicAudio; IBasicAudio basicAudio = graphBuilder as IBasicAudio;
if (basicAudio != null) if (basicAudio != null)
{ basicAudio.put_Volume( Math.Max(-10000, Math.Min(0, volume)));
basicAudio.put_Volume(volume);
}
} }
} }
public int GetVolume() public int GetVolume()
{ {
if (audioRenderer != null) if (graphBuilder != null)
{ {
IBasicAudio basicAudio = audioRenderer as IBasicAudio; IBasicAudio basicAudio = graphBuilder as IBasicAudio;
if (basicAudio != null) if (basicAudio != null)
{ {
int volume; int volume;

View File

@ -9,46 +9,14 @@ namespace DualScreenDemo.Services
IGraphBuilder graphBuilder; IGraphBuilder graphBuilder;
IBaseFilter lavSplitter; IBaseFilter lavSplitter;
IBaseFilter lavVideoDecoder; IBaseFilter lavVideoDecoder;
IBaseFilter videoRenderer; public IBaseFilter videoRenderer;
IVideoWindow videoWindow;
IMediaControl mediaControl; IMediaControl mediaControl;
IBaseFilter sourceFilter; IBaseFilter sourceFilter;
public MediaServicePrimary() { } public MediaServicePrimary() { }
public int Run() public int Run() => (mediaControl != null) ? mediaControl.Run() : 0;
{ public int Stop() => (mediaControl != null)? mediaControl.Stop() : 0;
if (mediaControl != null) public int Pause() => (mediaControl != null) ? mediaControl.Pause() : 0;
return mediaControl.Run();
else
return 0;
}
public int Stop()
{
if (mediaControl != null)
return mediaControl.Stop();
else
return 0;
}
public int Pause()
{
if (mediaControl != null)
return mediaControl.Pause();
else
return 0;
}
public void VideoPlayerFormClosing()
{
if (videoWindow != null)
{
videoWindow.put_Visible(OABool.False);
videoWindow.put_Owner(IntPtr.Zero);
Marshal.ReleaseComObject(videoWindow);
videoWindow = null;
}
}
public void StopAndReleaseResources() public void StopAndReleaseResources()
{ {
@ -57,7 +25,6 @@ namespace DualScreenDemo.Services
mediaControl.Stop(); mediaControl.Stop();
SafeRelease(ref mediaControl); SafeRelease(ref mediaControl);
} }
SafeRelease(ref videoWindow);
SafeRelease(ref videoRenderer); SafeRelease(ref videoRenderer);
SafeRelease(ref sourceFilter); SafeRelease(ref sourceFilter);
SafeRelease(ref lavVideoDecoder); SafeRelease(ref lavVideoDecoder);
@ -65,10 +32,10 @@ namespace DualScreenDemo.Services
SafeRelease(ref graphBuilder); SafeRelease(ref graphBuilder);
} }
public void RenderMediaFile(string filePath, nint Handle, int Width, int Height) public void RenderMediaFile(string filePath)
{ {
StopAndReleaseResources(); StopAndReleaseResources();
if (videoWindow != null) videoWindow.put_Visible(OABool.False);
int hr; int hr;
graphBuilder = (IGraphBuilder)new FilterGraph(); graphBuilder = (IGraphBuilder)new FilterGraph();
@ -84,38 +51,12 @@ namespace DualScreenDemo.Services
hr = graphBuilder.AddFilter(videoRenderer, "Primary Video Renderer"); hr = graphBuilder.AddFilter(videoRenderer, "Primary Video Renderer");
DsError.ThrowExceptionForHR(hr); DsError.ThrowExceptionForHR(hr);
mediaControl = (IMediaControl)graphBuilder;
if (mediaControl == null)
{
Console.WriteLine("Failed to get Media Control for primary monitor.");
return;
}
hr = ConnectFilters(graphBuilder, sourceFilter, "Output", lavSplitter, "Input"); hr = ConnectFilters(graphBuilder, sourceFilter, "Output", lavSplitter, "Input");
DsError.ThrowExceptionForHR(hr); DsError.ThrowExceptionForHR(hr);
hr = ConnectFilters(graphBuilder, lavSplitter, "Video", lavVideoDecoder, "Input"); hr = ConnectFilters(graphBuilder, lavSplitter, "Video", lavVideoDecoder, "Input");
DsError.ThrowExceptionForHR(hr); DsError.ThrowExceptionForHR(hr);
hr = ConnectFilters(graphBuilder, lavVideoDecoder, "Output", videoRenderer, "VMR Input0"); hr = ConnectFilters(graphBuilder, lavVideoDecoder, "Output", videoRenderer, "VMR Input0");
DsError.ThrowExceptionForHR(hr); DsError.ThrowExceptionForHR(hr);
try
{
IVideoWindow videoWindow = (IVideoWindow)videoRenderer;
videoWindow.put_Owner(Handle);
videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren);
// ⬅ 左上角對齊(固定從 0,0 開始)
videoWindow.SetWindowPosition(0, 0, Width, Height);
videoWindow.put_Visible(OABool.True);
// Console.WriteLine("Video window configured successfully.");
}
catch (Exception ex)
{
Console.WriteLine(String.Format("Error syncing to primary monitor: {0}", ex.Message));
MessageBox.Show(String.Format("Error syncing to primary monitor: {0}", ex.Message));
}
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@ -54,7 +54,7 @@ namespace DualScreenDemo.Services
{ {
PinInfo pinInfo; PinInfo pinInfo;
pins[0].QueryPinInfo(out pinInfo); pins[0].QueryPinInfo(out pinInfo);
Console.WriteLine(pinInfo); //Console.WriteLine(pinInfo+":"+pinInfo.name);
if (pinInfo.name == pinName) if (pinInfo.name == pinName)
{ {

View File

@ -71,6 +71,8 @@ namespace DualScreenDemo
private const uint SWP_NOZORDER = 0x0004; private const uint SWP_NOZORDER = 0x0004;
private MediaServicePrimary primary = new MediaServicePrimary(); private MediaServicePrimary primary = new MediaServicePrimary();
private MediaService secondary = new MediaService(); private MediaService secondary = new MediaService();
private IVideoWindow videoWindowPrimary;
private IVideoWindow videoWindowSecondary;
public static OverlayForm overlayForm; public static OverlayForm overlayForm;
public bool isMuted = false; public bool isMuted = false;
@ -158,8 +160,20 @@ namespace DualScreenDemo
private void VideoPlayerForm_FormClosing(object sender, FormClosingEventArgs e) private void VideoPlayerForm_FormClosing(object sender, FormClosingEventArgs e)
{ {
primary.VideoPlayerFormClosing(); if (videoWindowPrimary != null)
secondary.VideoPlayerFormClosing(); {
videoWindowPrimary.put_Visible(OABool.False);
videoWindowPrimary.put_Owner(IntPtr.Zero);
Marshal.ReleaseComObject(videoWindowPrimary);
videoWindowPrimary = null;
}
if (videoWindowSecondary != null)
{
videoWindowSecondary.put_Visible(OABool.False);
videoWindowSecondary.put_Owner(IntPtr.Zero);
Marshal.ReleaseComObject(videoWindowSecondary);
videoWindowSecondary = null;
}
// 清理COM // 清理COM
CoUninitialize(); CoUninitialize();
} }
@ -273,10 +287,6 @@ namespace DualScreenDemo
SerialPortManager.mySerialPort.Write(commandBytesIncreasePitch1, 0, commandBytesIncreasePitch1.Length); SerialPortManager.mySerialPort.Write(commandBytesIncreasePitch1, 0, commandBytesIncreasePitch1.Length);
} }
} }
// pathToPlay 需要調整
var pathToPlay = songToPlay.getFile();
// 更新畫面上顯示的下一首歌資訊 // 更新畫面上顯示的下一首歌資訊
SongList.UpdateNextSongLabel(); SongList.UpdateNextSongLabel();
@ -286,45 +296,40 @@ namespace DualScreenDemo
// 隱藏「暫停中」標籤 // 隱藏「暫停中」標籤
overlayForm.HidePauseLabel(); overlayForm.HidePauseLabel();
await _InitializeAndPlayMedia(pathToPlay); await _InitializeAndPlayMedia(songToPlay);
} }
public async Task ReplayCurrentSong() public async Task ReplayCurrentSong() =>await _InitializeAndPlayMedia(SongList.Current());
{
var songToPlay = SongList.Current(); private async Task _InitializeAndPlayMedia(SongData song)
var pathToPlay = songToPlay.getFile();
// UpdateMarqueeTextForCurrentSong(songToPlay);
await _InitializeAndPlayMedia(pathToPlay);
}
private async Task _InitializeAndPlayMedia(string pathToPlay)
{ {
try try
{ {
if (InvokeRequired) if (InvokeRequired)
{ {
await InvokeAsync(() => InitializeAndPlayMedia(pathToPlay)); await InvokeAsync(() => InitializeAndPlayMedia(song));
} }
else else
{ {
await InitializeAndPlayMedia(pathToPlay); await InitializeAndPlayMedia(song);
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine($"播放時發生錯誤: {ex.Message}"); Console.WriteLine($"播放時發生錯誤: {ex.Message}");
await RetryInitializeAndPlayMedia(pathToPlay); await RetryInitializeAndPlayMedia(song);
} }
} }
private async Task RetryInitializeAndPlayMedia(string path) private async Task RetryInitializeAndPlayMedia(SongData song)
{ {
try try
{ {
int hr = CoInitializeEx(IntPtr.Zero, COINIT.APARTMENTTHREADED); int hr = CoInitializeEx(IntPtr.Zero, COINIT.APARTMENTTHREADED);
if (hr >= 0) if (hr >= 0)
{ {
await InitializeAndPlayMedia(path); await InitializeAndPlayMedia(song);
} }
else else
{ {
@ -356,11 +361,35 @@ namespace DualScreenDemo
return tcs.Task; return tcs.Task;
} }
private Task InitializeAndPlayMedia(string pathToPlay) private Task InitializeAndPlayMedia(SongData song)
{ {
string pathToPlay = song.getFile();
if (videoWindowPrimary != null) videoWindowPrimary.put_Visible(OABool.False);
if (videoWindowSecondary != null) videoWindowSecondary.put_Visible(OABool.False);
// 渲染媒體文件 // 渲染媒體文件
primary.RenderMediaFile(pathToPlay,PrimaryForm.Instance.primaryScreenPanel.Handle,newWidth,newHeight); primary.RenderMediaFile(pathToPlay);
secondary.RenderMediaFile(pathToPlay,this.Handle,secondMonitor.Bounds.Width,secondMonitor.Bounds.Height); secondary.RenderMediaFile(pathToPlay);
videoWindowPrimary = primary.videoRenderer as IVideoWindow;
if (videoWindowPrimary != null)
{
videoWindowPrimary.put_Owner(PrimaryForm.Instance.primaryScreenPanel.Handle);
videoWindowPrimary.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren);
videoWindowPrimary.SetWindowPosition(0, 0, newWidth, newHeight);
videoWindowPrimary.put_Visible(OABool.True);
}
// 绑定视频窗口到副屏幕
videoWindowSecondary = secondary.renderer as IVideoWindow;
if (videoWindowSecondary != null)
{
videoWindowSecondary.put_Owner(this.Handle);
videoWindowSecondary.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren | WindowStyle.ClipSiblings);
videoWindowSecondary.SetWindowPosition(0, 0, secondMonitor.Bounds.Width, secondMonitor.Bounds.Height);
videoWindowSecondary.put_Visible(OABool.True);
}
// 音量處理 // 音量處理
SetVolume(isMuted ? -10000 : previousVolume); SetVolume(isMuted ? -10000 : previousVolume);
@ -392,6 +421,7 @@ namespace DualScreenDemo
{ {
Task.Run(async () => Task.Run(async () =>
{ {
await Task.Delay(10000);
Console.WriteLine("開始監聽媒體事件..."); Console.WriteLine("開始監聽媒體事件...");
while (true) while (true)
{ {