/// <summary> /// Create or remove DSFilterNodes and Noodles based on state of FilterGraph /// </summary> public List <DSFilterNode> SyncGraphs(IBaseFilter manuallyAddedFilter) { List <DSFilterNode> nodesAdded = new List <DSFilterNode>(); this.SuspendLayout(); this.BeginNoodleUpdate(); this.BeginCanvasUpdate(); List <IBaseFilter> filters = GetFilters(_Graph); List <IDaggerUINode> nodes = AllNodes; // remove any nodes that no longer have corresponding IBaseFilters in the filtergraph foreach (DSFilterNodeUI node in nodes) { if (!filters.Contains((node.Node as DSFilterNode)._filter)) { this.Graph.DeleteNode(node.Node); } } // sync the pins in the nodes of the graph foreach (DaggerUINode node in AllNodes) { (node.Node as DSFilterNode).SyncPins(); } // add nodes for any filters that aren't already in the graph for (int i = filters.Count - 1; i > -1; i--) { IBaseFilter filter = filters[i]; // see if we haven't made a DaggerNode for this filter yet if (FindFilter(filter) == null) { DSFilterNode node = new DSFilterNode(filter, manuallyAddedFilter == filter); nodesAdded.Add(node); // Setting _droppedNode to a value will make the node NOT visible when it's created. // This way, we can reposition and resize the UINode before we display it. _droppedNode = node; Graph.AddNode(node); _droppedNode = null; // set the node's position and increment the drop location to the left (node.UINode as DaggerUINode).Location = _dropLocation; _dropLocation = new Point((node.UINode as DaggerUINode).Right + 24, _dropLocation.Y); if (_dropLocation.X >= ActualCanvasSize.Width) { _dropLocation.X = 0; _dropLocation.Y = _dropLocation.Y + (node.UINode as DaggerUINode).Height; } // mark the node visible (node.UINode as DaggerUINode).Visible = true; } else { // we already have a node for this one, release the ref enum.next added if (filter.GetType().IsCOMObject) { int refc = Marshal.ReleaseComObject(filter); } } } // purge disconnected noodles PurgeNoodles(); // create new noodles BuildNoodles(); // redraw the Canvas Image ResumeLayout(); EndNoodleUpdate(); EndCanvasUpdate(); // route any dvd controls to thier video windows RouteDVDControl(); // return the list of DSFilterNode that were added to the graph return(nodesAdded); }
/// <summary> /// Event that is raised after a DaggerNode has been created and associated to the UI element /// </summary> /// <param name="node"></param> void DSFilterNodeUI_DaggerNodeAttached(DaggerLib.Core.DaggerNode node) { _dsfilternode = (DSFilterNode)node; CaptionText = node.ToString(); // hook the AfterNodeRemoved event to dispose of any directshow interfaces node.AfterNodeRemoved += new DaggerLib.Core.AfterNodeRemoveHandler(node_AfterNodeRemoved); // get the IBaseFilter from the DSFilterNode IBaseFilter filter = _dsfilternode._filter; // only grab the video window or EVR if it was manually added to the graph via the UI if (_dsfilternode._manualAdded || (_dsfilternode.ParentGraph.ParentUIGraph as DSDaggerUIGraph)._filterGraphCreated) { // if it supports IVideoWindow create a VideoInternalWindow for it IVideoWindow vw = filter as IVideoWindow; if (vw != null) { try { _videoWindow = new VideoInternalWindow(CaptionText, filter); _videoWindow.Dock = DockStyle.Fill; _videoWindow.Visible = true; InternalControl.Controls.Add(_videoWindow); // only nodes with video windows are resizeable Resizable = true; // hook the connection events to init/deinit the video window node.ParentGraph.AfterPinsConnected += new DaggerLib.Core.PinAfterConnectedHandler(ParentGraph_AfterPinsConnected); } catch (Exception ex) { #if DEBUG MessageBox.Show(ex.Message); #endif _videoWindow = null; } } // if it's an Enhaced Video Renderer create a VideoInternalWindow for it // (see docs for Windows Media Foundation) IMFGetService mfgs = filter as IMFGetService; if (mfgs != null) { // this is a video horse of a different color // create a video clipping window for the Media Foundation Enhanced Video Renderer try { // get the IMFVideoDisplayControl for the EVR filter object o = null; mfgs.GetService(MediaFoundation.MFServices.MR_VIDEO_RENDER_SERVICE, typeof(IMFVideoDisplayControl).GUID, out o ); m_pVideoDisplay = o as IMFVideoDisplayControl; // if the Video Size is 0,0 the EVR hasn't been initialized/connected yet MediaFoundation.Misc.SIZE videoSize = new MediaFoundation.Misc.SIZE(); MediaFoundation.Misc.SIZE ar = new MediaFoundation.Misc.SIZE(); m_pVideoDisplay.GetNativeVideoSize(videoSize, ar); if (videoSize.cx == 0 && videoSize.cy == 0) { // You only get one chance to set the number of pins in an EVR filter. PinsComboBoxForm pcf = new PinsComboBoxForm(); if (pcf.ShowDialog() == DialogResult.OK) { (filter as IEVRFilterConfig).SetNumberOfStreams(pcf.Value); } pcf.Dispose(); } _videoWindow = new VideoInternalWindow(CaptionText, m_pVideoDisplay); _videoWindow.Dock = DockStyle.Fill; _videoWindow.Visible = true; InternalControl.Controls.Add(_videoWindow); // only nodes with video windows are resizeable Resizable = true; // hook the connection events to init/deinit the video window node.ParentGraph.AfterPinsConnected += new DaggerLib.Core.PinAfterConnectedHandler(ParentGraph_AfterPinsConnected); } catch (InvalidCastException) { m_pVideoDisplay = null; } } } // if it's a DMO, create the DMO properties page for it if ((filter as IDMOWrapperFilter) != null) { // set the caption to show it's a DMO CaptionText = "DMO - " + CaptionText; CaptionColor = Color.Green; CaptionColorUnfocused = Color.LightGreen; } // remove clock button if it doesn't support IReferenceClock _referenceClock = filter as IReferenceClock; if (_referenceClock == null) { CaptionButtons.RemoveAt(CaptionButtons.AllButtons.IndexOf(_clockButton)); } else { // see if this filter is the reference clock for the graph IReferenceClock graphClock = null; filter.GetSyncSource(out graphClock); _clockButton.Tag = false; _clockButton.MouseOutsideTint = Color.DarkGray; if (graphClock != null) { if (graphClock == _referenceClock) { _clockButton.MouseOutsideTint = Color.Yellow; _clockButton.Tag = true; } Marshal.ReleaseComObject(graphClock); } } // remove video window button if it's not a video window if (_videoWindow == null) { CaptionButtons.RemoveAt(CaptionButtons.AllButtons.IndexOf(_detachVideoWindowButton)); } // Sync the pins to the Pin Property Pages SyncPinPropertyPages(null); // set it to the smallest possible size. DaggerLib uses InternalControlMinimumSize // to prevent the UI node from being smaller than designated this.Size = new Size(1, 1); }