202508081811
包帳 State 没變 不重復做 VideoPlayForm 大調整
This commit is contained in:
parent
5ff2e096fc
commit
f8a6e5c40d
@ -13,7 +13,7 @@ namespace DualScreenDemo
|
||||
private static PrimaryForm primaryForm; // 儲存實例的參考
|
||||
public static Room room = new Room();
|
||||
|
||||
public static string verSion = "Server V2.7 202508041725";
|
||||
public static string verSion = "Server V2.8 202508071811";
|
||||
|
||||
[STAThread]
|
||||
static void Main()
|
||||
@ -82,9 +82,6 @@ namespace DualScreenDemo
|
||||
|
||||
// 显示 videoPlayerForm 在第二显示器
|
||||
primaryForm.videoPlayerForm.Show();
|
||||
|
||||
// 初始化公共播放列表
|
||||
primaryForm.videoPlayerForm.PlayNextSong();
|
||||
}
|
||||
}
|
||||
primaryForm.Show();
|
||||
|
18
Room.cs
18
Room.cs
@ -65,22 +65,26 @@ namespace DualScreenDemo
|
||||
}
|
||||
public void set(string value)
|
||||
{
|
||||
State =getDB();
|
||||
Console.WriteLine($"hostname status: {hostName},{State},{startedAt},{endedAt}");
|
||||
string StateDB=getDB();
|
||||
|
||||
Console.WriteLine($"hostname status: {hostName},{StateDB},{startedAt},{endedAt} ,{State}");
|
||||
string marqueeMessage = "歡迎使用超級巨星歡唱,與你共度美好時光。";
|
||||
Color c = Color.White;
|
||||
if (State.Equals("fire"))
|
||||
if (StateDB.Equals("fire"))
|
||||
{
|
||||
PrimaryForm.Instance.ShowSendOffScreen();
|
||||
VideoPlayerForm.Instance.Pause();
|
||||
marqueeMessage = "發生火災,請跟隨引導至逃生出口!!!";
|
||||
c = Color.Red;
|
||||
}
|
||||
else if (State.Equals("active"))
|
||||
else if (StateDB.Equals("active"))
|
||||
{
|
||||
DBObj.SongList.clearSong();
|
||||
PrimaryForm.Instance.HotPlayButton_Click(null, EventArgs.Empty);
|
||||
PrimaryForm.Instance.HideSendOffScreen();
|
||||
if (!State.Equals(StateDB))
|
||||
{
|
||||
DBObj.SongList.clearSong();
|
||||
PrimaryForm.Instance.HotPlayButton_Click(null, EventArgs.Empty);
|
||||
PrimaryForm.Instance.HideSendOffScreen();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
370
Services/MediaService.cs
Normal file
370
Services/MediaService.cs
Normal file
@ -0,0 +1,370 @@
|
||||
using DirectShowLib;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace DualScreenDemo.Services
|
||||
{
|
||||
public class MediaService
|
||||
{
|
||||
public IGraphBuilder graphBuilder;
|
||||
private IMediaControl mediaControl;
|
||||
private IBaseFilter videoRenderer;
|
||||
private IBaseFilter lavSplitter;
|
||||
private IBaseFilter lavVideoDecoder;
|
||||
private IBaseFilter lavAudioDecoder;
|
||||
private IPin outputPin;
|
||||
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()
|
||||
{
|
||||
bool isAtEnd = false;
|
||||
if (mediaControl == null) { return false; }
|
||||
IMediaSeeking mediaSeeking = graphBuilder as IMediaSeeking;
|
||||
if (mediaSeeking != null)
|
||||
{
|
||||
long currentPosition;
|
||||
long duration;
|
||||
if (mediaSeeking.GetCurrentPosition(out currentPosition) >= 0 &&
|
||||
mediaSeeking.GetDuration(out duration) >= 0)
|
||||
{
|
||||
double currentSeconds = currentPosition / 10000000.0;
|
||||
double durationSeconds = duration / 10000000.0;
|
||||
|
||||
// 添加更严格的结束条件判断
|
||||
isAtEnd = durationSeconds > 0 && currentSeconds > 0 &&
|
||||
Math.Abs(currentSeconds - durationSeconds) < 0.1; // 确保真的到了结尾
|
||||
//Console.WriteLine($"檢測到歌曲 - 當前位置: {currentSeconds:F2}秒, 總時長: {durationSeconds:F2}秒");
|
||||
if (isAtEnd)
|
||||
{
|
||||
Console.WriteLine($"檢測到歌曲 -結束: {currentSeconds:F2}秒, 總時長: {durationSeconds:F2}秒");
|
||||
}
|
||||
}
|
||||
}
|
||||
return isAtEnd;
|
||||
}
|
||||
public void RenderMediaFile(string filePath, nint Handle, int Width, int Height)
|
||||
{
|
||||
StopAndReleaseResources();
|
||||
if (videoWindow != null) videoWindow.put_Visible(OABool.False);
|
||||
int hr = 0;
|
||||
graphBuilder = (IGraphBuilder)new FilterGraph();
|
||||
if (graphBuilder == null)
|
||||
{
|
||||
Console.WriteLine("Failed to create FilterGraph");
|
||||
throw new Exception("Failed to create FilterGraph");
|
||||
}
|
||||
try
|
||||
{
|
||||
lavSplitter = AddFilterByClsid(graphBuilder, "LAV Splitter", Clsid.LAVSplitter);
|
||||
lavVideoDecoder = AddFilterByClsid(graphBuilder, "LAV Video Decoder", Clsid.LAVVideoDecoder);
|
||||
lavAudioDecoder = AddFilterByClsid(graphBuilder, "LAV Audio Decoder", Clsid.LAVAudioDecoder);
|
||||
outputPin = FindPin(lavAudioDecoder, "Output");
|
||||
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;
|
||||
if (mediaControl == null)
|
||||
{
|
||||
Console.WriteLine("Failed to get Media Control");
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Error initializing graph builder with second monitor: " + ex.Message);
|
||||
}
|
||||
hr = graphBuilder.RenderFile(filePath, null);
|
||||
if (hr == 0)
|
||||
{
|
||||
Console.WriteLine("Secondary File rendered successfully.");
|
||||
SetAudioTrackTo(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
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); // 显示窗口
|
||||
}
|
||||
}
|
||||
|
||||
private static IBaseFilter AddFilterByClsid(IGraphBuilder graphBuilder, string name, Guid clsid)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 获取 CLSID 对应的类型
|
||||
Type filterType = Type.GetTypeFromCLSID(clsid);
|
||||
//Console.WriteLine($"Attempting to create filter of type: {filterType.FullName}");
|
||||
|
||||
// 创建实例
|
||||
object filterObject = Activator.CreateInstance(filterType);
|
||||
|
||||
// 尝试转换为 IBaseFilter
|
||||
IBaseFilter filter = filterObject as IBaseFilter;
|
||||
|
||||
if (filter == null)
|
||||
{
|
||||
// 如果转换失败,使用 IUnknown 获取并转换为 IBaseFilter
|
||||
IntPtr comObjectPointer = Marshal.GetIUnknownForObject(filterObject);
|
||||
filter = (IBaseFilter)Marshal.GetObjectForIUnknown(comObjectPointer);
|
||||
// Console.WriteLine($"Successfully converted COM object to IBaseFilter via IUnknown.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Console.WriteLine($"Successfully created IBaseFilter directly.");
|
||||
}
|
||||
|
||||
// 添加过滤器到图形构建器
|
||||
int hr = graphBuilder.AddFilter(filter, name);
|
||||
if (hr != 0)
|
||||
{
|
||||
// Console.WriteLine($"Failed to add filter {name} with CLSID {clsid}, HRESULT: {hr}");
|
||||
}
|
||||
|
||||
DsError.ThrowExceptionForHR(hr);
|
||||
// Console.WriteLine($"Successfully added filter {name} with CLSID {clsid}");
|
||||
return filter;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Exception in AddFilterByClsid: {ex.Message}");
|
||||
throw; // Rethrow the exception to handle it further up the call stack
|
||||
}
|
||||
}
|
||||
private IPin FindPin(IBaseFilter filter, string pinName)
|
||||
{
|
||||
IEnumPins enumPins;
|
||||
IPin[] pins = new IPin[1];
|
||||
|
||||
filter.EnumPins(out enumPins);
|
||||
enumPins.Reset();
|
||||
|
||||
while (enumPins.Next(1, pins, IntPtr.Zero) == 0)
|
||||
{
|
||||
PinInfo pinInfo;
|
||||
pins[0].QueryPinInfo(out pinInfo);
|
||||
Console.WriteLine(pinInfo);
|
||||
|
||||
if (pinInfo.name == pinName)
|
||||
{
|
||||
return pins[0];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public void SetVolume(int volume)
|
||||
{
|
||||
if (audioRenderer != null)
|
||||
{
|
||||
IBasicAudio basicAudio = audioRenderer as IBasicAudio;
|
||||
if (basicAudio != null)
|
||||
{
|
||||
basicAudio.put_Volume(volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
public int GetVolume()
|
||||
{
|
||||
if (audioRenderer != null)
|
||||
{
|
||||
IBasicAudio basicAudio = audioRenderer as IBasicAudio;
|
||||
if (basicAudio != null)
|
||||
{
|
||||
int volume;
|
||||
basicAudio.get_Volume(out volume);
|
||||
return volume;
|
||||
}
|
||||
}
|
||||
return -10000;
|
||||
}
|
||||
private bool isVocalRemoved = false;
|
||||
public bool ToggleVocalRemoval()
|
||||
{
|
||||
try
|
||||
{
|
||||
IAMStreamSelect streamSelect = lavSplitter as IAMStreamSelect;
|
||||
|
||||
if (streamSelect != null)
|
||||
{
|
||||
int trackCount;
|
||||
if (streamSelect.Count(out trackCount) == 0 && trackCount > 0)
|
||||
{
|
||||
int currentTrackIndex = -1;
|
||||
int audioTrack1 = -1;
|
||||
int audioTrack2 = -1;
|
||||
|
||||
for (int i = 0; i < trackCount; i++)
|
||||
{
|
||||
// 獲取音軌信息
|
||||
AMMediaType mediaType;
|
||||
AMStreamSelectInfoFlags flags;
|
||||
int lcid, dwGroup;
|
||||
string name;
|
||||
object pObject, pUnk;
|
||||
|
||||
streamSelect.Info(i, out mediaType, out flags, out lcid, out dwGroup, out name, out pObject, out pUnk);
|
||||
|
||||
if (mediaType.majorType == MediaType.Audio)
|
||||
{
|
||||
if (audioTrack1 == -1)
|
||||
{
|
||||
audioTrack1 = i;
|
||||
}
|
||||
else if (audioTrack2 == -1)
|
||||
{
|
||||
audioTrack2 = i;
|
||||
}
|
||||
|
||||
if ((flags & AMStreamSelectInfoFlags.Enabled) != 0)
|
||||
{
|
||||
currentTrackIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
DsUtils.FreeAMMediaType(mediaType);
|
||||
}
|
||||
|
||||
// 切換音軌
|
||||
if (currentTrackIndex == audioTrack1 && audioTrack2 != -1)
|
||||
{
|
||||
streamSelect.Enable(audioTrack2, AMStreamSelectEnableFlags.Enable);
|
||||
isVocalRemoved = true;
|
||||
}
|
||||
else if (currentTrackIndex == audioTrack2 && audioTrack1 != -1)
|
||||
{
|
||||
streamSelect.Enable(audioTrack1, AMStreamSelectEnableFlags.Enable);
|
||||
isVocalRemoved = false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
}
|
||||
return isVocalRemoved;
|
||||
}
|
||||
public void SetAudioTrackTo(int trackIndex)
|
||||
{
|
||||
try
|
||||
{
|
||||
IAMStreamSelect streamSelect = lavSplitter as IAMStreamSelect;
|
||||
|
||||
if (streamSelect != null)
|
||||
{
|
||||
int trackCount;
|
||||
if (streamSelect.Count(out trackCount) == 0 && trackCount > 0)
|
||||
{
|
||||
int audioTrackIndex = -1;
|
||||
|
||||
for (int i = 0; i < trackCount; i++)
|
||||
{
|
||||
AMMediaType mediaType;
|
||||
AMStreamSelectInfoFlags flags;
|
||||
int lcid, dwGroup;
|
||||
string name;
|
||||
object pObject, pUnk;
|
||||
|
||||
streamSelect.Info(i, out mediaType, out flags, out lcid, out dwGroup, out name, out pObject, out pUnk);
|
||||
|
||||
if (mediaType.majorType == MediaType.Audio)
|
||||
{
|
||||
audioTrackIndex++;
|
||||
if (audioTrackIndex == trackIndex)
|
||||
{
|
||||
streamSelect.Enable(i, AMStreamSelectEnableFlags.Enable);
|
||||
}
|
||||
else
|
||||
{
|
||||
streamSelect.Enable(i, AMStreamSelectEnableFlags.DisableAll);
|
||||
}
|
||||
}
|
||||
|
||||
DsUtils.FreeAMMediaType(mediaType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
}
|
||||
}
|
||||
private void SafeRelease<T>(ref T comObject) where T : class
|
||||
{
|
||||
if (comObject != null)
|
||||
{
|
||||
Marshal.ReleaseComObject(comObject);
|
||||
comObject = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
210
Services/MediaServicePrimary.cs
Normal file
210
Services/MediaServicePrimary.cs
Normal file
@ -0,0 +1,210 @@
|
||||
using DirectShowLib;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace DualScreenDemo.Services
|
||||
{
|
||||
public class MediaServicePrimary
|
||||
{
|
||||
IGraphBuilder graphBuilder;
|
||||
IBaseFilter sourceFilter;
|
||||
IBaseFilter lavSplitter;
|
||||
IBaseFilter lavVideoDecoder;
|
||||
IBaseFilter videoRenderer;
|
||||
IVideoWindow videoWindow;
|
||||
IMediaControl mediaControl;
|
||||
|
||||
|
||||
public MediaServicePrimary(){}
|
||||
|
||||
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 sourceFilter);
|
||||
SafeRelease(ref lavVideoDecoder);
|
||||
SafeRelease(ref lavSplitter);
|
||||
SafeRelease(ref graphBuilder);
|
||||
}
|
||||
|
||||
public void RenderMediaFile(string filePath, nint Handle, int Width, int Height)
|
||||
{
|
||||
StopAndReleaseResources();
|
||||
if (videoWindow != null) videoWindow.put_Visible(OABool.False);
|
||||
|
||||
int hr;
|
||||
graphBuilder = (IGraphBuilder)new FilterGraph();
|
||||
if (graphBuilder == null)
|
||||
throw new Exception("Failed to create FilterGraph for primary monitor.");
|
||||
|
||||
graphBuilder.AddSourceFilter(filePath, "Source", out sourceFilter);
|
||||
try
|
||||
{
|
||||
lavSplitter = AddFilterByClsid(graphBuilder, "LAV Splitter", Clsid.LAVSplitter);
|
||||
lavVideoDecoder = AddFilterByClsid(graphBuilder, "LAV Video Decoder", Clsid.LAVVideoDecoder);
|
||||
videoRenderer = AddFilterByClsid(graphBuilder, "Primary Video Renderer", Clsid.VideoRenderer);
|
||||
hr = graphBuilder.AddFilter(videoRenderer, "Primary Video Renderer");
|
||||
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");
|
||||
DsError.ThrowExceptionForHR(hr);
|
||||
hr = ConnectFilters(graphBuilder, lavSplitter, "Video", lavVideoDecoder, "Input");
|
||||
DsError.ThrowExceptionForHR(hr);
|
||||
hr = ConnectFilters(graphBuilder, lavVideoDecoder, "Output", videoRenderer, "VMR Input0");
|
||||
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)
|
||||
{
|
||||
Console.WriteLine("Error initializing graph builder for primary monitor: " + ex.Message);
|
||||
}
|
||||
}
|
||||
private static IBaseFilter AddFilterByClsid(IGraphBuilder graphBuilder, string name, Guid clsid)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 获取 CLSID 对应的类型
|
||||
Type filterType = Type.GetTypeFromCLSID(clsid);
|
||||
//Console.WriteLine($"Attempting to create filter of type: {filterType.FullName}");
|
||||
|
||||
// 创建实例
|
||||
object filterObject = Activator.CreateInstance(filterType);
|
||||
|
||||
// 尝试转换为 IBaseFilter
|
||||
IBaseFilter filter = filterObject as IBaseFilter;
|
||||
|
||||
if (filter == null)
|
||||
{
|
||||
// 如果转换失败,使用 IUnknown 获取并转换为 IBaseFilter
|
||||
IntPtr comObjectPointer = Marshal.GetIUnknownForObject(filterObject);
|
||||
filter = (IBaseFilter)Marshal.GetObjectForIUnknown(comObjectPointer);
|
||||
// Console.WriteLine($"Successfully converted COM object to IBaseFilter via IUnknown.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Console.WriteLine($"Successfully created IBaseFilter directly.");
|
||||
}
|
||||
|
||||
// 添加过滤器到图形构建器
|
||||
int hr = graphBuilder.AddFilter(filter, name);
|
||||
if (hr != 0)
|
||||
{
|
||||
// Console.WriteLine($"Failed to add filter {name} with CLSID {clsid}, HRESULT: {hr}");
|
||||
}
|
||||
|
||||
DsError.ThrowExceptionForHR(hr);
|
||||
// Console.WriteLine($"Successfully added filter {name} with CLSID {clsid}");
|
||||
return filter;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Exception in AddFilterByClsid: {ex.Message}");
|
||||
throw; // Rethrow the exception to handle it further up the call stack
|
||||
}
|
||||
}
|
||||
private int ConnectFilters(IGraphBuilder graphBuilder, IBaseFilter sourceFilter, string sourcePinName, IBaseFilter destFilter, string destPinName)
|
||||
{
|
||||
IPin outPin = FindPin(sourceFilter, sourcePinName);
|
||||
IPin inPin = FindPin(destFilter, destPinName);
|
||||
if (outPin == null || inPin == null)
|
||||
{
|
||||
Console.WriteLine(String.Format("Cannot find pins: {0} or {1}", sourcePinName, destPinName));
|
||||
return -1;
|
||||
}
|
||||
int hr = graphBuilder.Connect(outPin, inPin);
|
||||
return hr;
|
||||
}
|
||||
private IPin FindPin(IBaseFilter filter, string pinName)
|
||||
{
|
||||
IEnumPins enumPins;
|
||||
IPin[] pins = new IPin[1];
|
||||
|
||||
filter.EnumPins(out enumPins);
|
||||
enumPins.Reset();
|
||||
|
||||
while (enumPins.Next(1, pins, IntPtr.Zero) == 0)
|
||||
{
|
||||
PinInfo pinInfo;
|
||||
pins[0].QueryPinInfo(out pinInfo);
|
||||
Console.WriteLine(pinInfo);
|
||||
|
||||
if (pinInfo.name == pinName)
|
||||
{
|
||||
return pins[0];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private void SafeRelease<T>(ref T comObject) where T : class
|
||||
{
|
||||
if (comObject != null)
|
||||
{
|
||||
Marshal.ReleaseComObject(comObject);
|
||||
comObject = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user