private string[] GetDevices()
        {
            int num_devices = DeckLinkPlugin.GetNumDevices();

            string[] devices = new string[num_devices];

            for (int i = 0; i < num_devices; ++i)
            {
                devices[i] = DeckLinkPlugin.GetDeviceDisplayName(i);
            }

            return(devices);
        }
Example #2
0
        private void ValidateKeyerMode()
        {
            bool internal_supported = DeckLinkPlugin.SupportsInternalKeying(_selectedDevice.intValue);
            bool external_supported = DeckLinkPlugin.SupportsExternalKeying(_selectedDevice.intValue);

            if ((DeckLinkOutput.KeyerMode)_keying_mode.intValue == DeckLinkOutput.KeyerMode.External)
            {
                if (!external_supported && validate)
                {
                    validate = false;
                    Debug.LogWarning("External keying mode for DeckLinkOutput component is not supported by the selected decklink device");
                }
            }
            else if ((DeckLinkOutput.KeyerMode)_keying_mode.intValue == DeckLinkOutput.KeyerMode.Internal)
            {
                if (!internal_supported && validate)
                {
                    validate = false;
                    Debug.LogWarning("Internal keying mode for DeckLinkOutput component is not supported by the selected card");
                }
            }
        }
        protected void DrawDeviceModes()
        {
            if (GUILayout.Button("Refresh devices"))
            {
                DeckLinkPlugin.Deinit();
                DeckLinkPlugin.Init();
            }

            var devices = GetDevices();

            _selectedDevice.intValue = Mathf.Min(_selectedDevice.intValue, devices.Length - 1);
            _selectedDevice.intValue = EditorGUILayout.Popup("Device", _selectedDevice.intValue < 0 ? 0 : _selectedDevice.intValue, devices);

            if (devices.Length == 0)
            {
                _selectedDevice.intValue = -1;
            }

            if (_displayModes)
            {
                GUILayout.Space(8f);

                if (GUILayout.Button("Modes", EditorStyles.toolbarButton))
                {
                    _expandModes = !_expandModes;
                }

                if (_expandModes)
                {
                    string[]          modes;
                    List <Resolution> resolutions;
                    Resolution[]      modeResolutions;
                    int[]             actual_positions;

                    if (_selectedDevice.intValue >= 0)
                    {
                        modes = GetDeviceModes(_selectedDevice.intValue, out resolutions, out modeResolutions, out actual_positions);
                    }
                    else
                    {
                        modes            = new string[0];
                        resolutions      = new List <Resolution>();
                        modeResolutions  = new Resolution[0];
                        actual_positions = new int[0];
                    }

                    int prev_pos = 0;

                    for (int i = 0; i < actual_positions.Length; ++i)
                    {
                        if (actual_positions[i] == _selectedMode.intValue)
                        {
                            prev_pos = i;
                            break;
                        }
                    }

                    EditorGUILayout.LabelField("Mode");

                    int rows = resolutions.Count % 4 == 0 ? resolutions.Count / 4 : resolutions.Count / 4 + 1;

                    for (int i = 0; i < rows; ++i)
                    {
                        EditorGUILayout.BeginHorizontal();
                        for (int j = 0; j < 4; ++j)
                        {
                            int pos = i * 4 + j;
                            if (pos >= resolutions.Count)
                            {
                                break;
                            }

                            if (_selectedResolution.intValue == pos)
                            {
                                GUI.color = Color.cyan;
                            }

                            if (GUILayout.Button(resolutions[pos].width + "x" + resolutions[pos].height))
                            {
                                _selectedResolution.intValue = pos;
                            }

                            GUI.color = Color.white;
                        }
                        EditorGUILayout.EndHorizontal();
                    }

                    if (_selectedResolution.intValue >= 0 && _selectedResolution.intValue < resolutions.Count)
                    {
                        _scrollPos = EditorGUILayout.BeginScrollView(_scrollPos, false, false, GUILayout.MaxHeight(200), GUILayout.MinHeight(200));

                        for (int i = 0; i < modes.Length; ++i)
                        {
                            if (modeResolutions[i].width != resolutions[_selectedResolution.intValue].width ||
                                modeResolutions[i].height != resolutions[_selectedResolution.intValue].height)
                            {
                                continue;
                            }

                            bool selected = false;

                            if (prev_pos == i)
                            {
                                GUI.color = Color.yellow;
                            }

                            selected = GUILayout.Button(modes[i]);

                            if (prev_pos == i)
                            {
                                GUI.color = Color.white;
                            }

                            if (selected)
                            {
                                _selectedMode.intValue = actual_positions[i];
                            }
                        }

                        EditorGUILayout.EndScrollView();
                    }

                    if (modes.Length == 0)
                    {
                        _selectedMode.intValue = -1;
                    }
                }
            }

            OnInspectorGUI_About();
        }
        protected void OnInspectorGUI_About()
        {
            GUILayout.Space(8f);

            if (GUILayout.Button("About", EditorStyles.toolbarButton))
            {
                _expandAbout.boolValue = !_expandAbout.boolValue;
            }

            if (_expandAbout.boolValue)
            {
                string version = DeckLinkPlugin.GetNativePluginVersion();

                EditorGUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                if (_icon == null)
                {
                    _icon = Resources.Load <Texture2D>("AVProDeckLinkIcon");
                }
                if (_icon != null)
                {
                    GUILayout.Label(new GUIContent(_icon));
                }
                GUILayout.FlexibleSpace();
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                GUI.color = Color.yellow;
                GUILayout.Label("AVPro DeckLink by RenderHeads Ltd", EditorStyles.boldLabel);
                GUI.color = Color.white;
                GUILayout.FlexibleSpace();
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                GUI.color = Color.yellow;
                GUILayout.Label("version " + version + " (scripts v" + Helper.Version + ")");
                GUI.color = Color.white;
                GUILayout.FlexibleSpace();
                EditorGUILayout.EndHorizontal();

                GUILayout.Space(32f);
                GUI.backgroundColor = Color.white;

                EditorGUILayout.LabelField("Links", EditorStyles.boldLabel);

                GUILayout.Space(8f);

                EditorGUILayout.LabelField("Documentation");
                if (GUILayout.Button("User Manual", GUILayout.ExpandWidth(false)))
                {
                    Application.OpenURL(LinkUserManual);
                }
                if (GUILayout.Button("Scripting Class Reference", GUILayout.ExpandWidth(false)))
                {
                    Application.OpenURL(LinkScriptingClassReference);
                }

                GUILayout.Space(16f);

                GUILayout.Label("Rate and Review (★★★★☆)", GUILayout.ExpandWidth(false));
                if (GUILayout.Button("Unity Asset Store Page", GUILayout.ExpandWidth(false)))
                {
                    Application.OpenURL(LinkAssetStorePage);
                }

                GUILayout.Space(16f);

                GUILayout.Label("Community");
                if (GUILayout.Button("Unity Forum Page", GUILayout.ExpandWidth(false)))
                {
                    Application.OpenURL(LinkForumPage);
                }

                GUILayout.Space(16f);

                GUILayout.Label("Homepage", GUILayout.ExpandWidth(false));
                if (GUILayout.Button("AVPro DeckLink Website", GUILayout.ExpandWidth(false)))
                {
                    Application.OpenURL(LinkPluginWebsite);
                }

                GUILayout.Space(16f);

                GUILayout.Label("Bugs and Support");
                EditorGUILayout.BeginHorizontal();
                if (GUILayout.Button("Email [email protected]", GUILayout.ExpandWidth(false)))
                {
                    Application.OpenURL(LinkEmailSupport);
                }
                EditorGUILayout.EndHorizontal();

                GUILayout.Space(32f);

                EditorGUILayout.LabelField("Credits", EditorStyles.boldLabel);
                GUILayout.Space(8f);

                GUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                GUILayout.Label("Programming", EditorStyles.boldLabel);
                GUILayout.FlexibleSpace();
                GUILayout.EndHorizontal();
                GUILayout.Space(8f);
                GUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                GUILayout.Label("Andrew Griffiths");
                GUILayout.FlexibleSpace();
                GUILayout.EndHorizontal();
                GUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                GUILayout.Label("Sunrise Wang");
                GUILayout.FlexibleSpace();
                GUILayout.EndHorizontal();

                GUILayout.Space(8f);
                GUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                GUILayout.Label("Graphics", EditorStyles.boldLabel);
                GUILayout.FlexibleSpace();
                GUILayout.EndHorizontal();
                GUILayout.Space(8f);

                GUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                GUILayout.Label("Jeff Rusch");
                GUILayout.FlexibleSpace();
                GUILayout.EndHorizontal();

                GUILayout.Space(32f);

                EditorGUILayout.LabelField("Bug Reporting Notes", EditorStyles.boldLabel);

                EditorGUILayout.SelectableLabel(SupportMessage, EditorStyles.wordWrappedLabel, GUILayout.Height(300f));
            }

            GUILayout.Space(8f);
        }
        private string[] GetDeviceModes(int device, out List <Resolution> resolutions, out Resolution[] modeResolutions, out int[] positions)
        {
            List <Resolution> outputRes = new List <Resolution>();
            int num_modes = DeckLinkPlugin.GetNumVideoInputModes(device);

            List <string>     modes            = new List <string>();
            List <Resolution> mrs              = new List <Resolution>();
            List <int>        actual_positions = new List <int>();

            for (int i = 0; i < num_modes; ++i)
            {
                int    width, height, fieldMode;
                float  frameRate;
                long   frameDuration;
                string modeDesc, pixelFormatDesc;

                if (_isInput)
                {
                    DeckLinkPlugin.GetVideoInputModeInfo(device, i, out width, out height, out frameRate, out frameDuration, out fieldMode, out modeDesc, out pixelFormatDesc);
                }
                else
                {
                    DeckLinkPlugin.GetVideoOutputModeInfo(device, i, out width, out height, out frameRate, out frameDuration, out fieldMode, out modeDesc, out pixelFormatDesc);
                }

                DeckLinkPlugin.PixelFormat format = DeckLinkPlugin.GetPixelFormat(pixelFormatDesc);

                if (FormatConverter.InputFormatSupported(format))
                {
                    modes.Add(modeDesc + " " + pixelFormatDesc);

                    Resolution r = new Resolution();
                    r.width  = width;
                    r.height = height;
                    mrs.Add(r);

                    actual_positions.Add(i);

                    bool resolutionFound = false;
                    for (int j = 0; j < outputRes.Count; ++j)
                    {
                        if (width == outputRes[j].width && height == outputRes[j].height)
                        {
                            resolutionFound = true;
                            break;
                        }
                    }

                    if (!resolutionFound)
                    {
                        Resolution res = new Resolution();
                        res.width  = width;
                        res.height = height;
                        outputRes.Add(res);
                    }
                }
            }

            resolutions     = outputRes;
            modeResolutions = mrs.ToArray();
            positions       = actual_positions.ToArray();

            return(modes.ToArray());
        }
Example #6
0
        public void OnGUI()
        {
            GUI.skin = _guiSkin;

            if (_modeListStyle == null)
            {
                _modeListStyle = GUI.skin.GetStyle("ModeList");
            }


            GUILayout.BeginHorizontal();
            // List the devices
            _deviceScrollPos = GUILayout.BeginScrollView(_deviceScrollPos, false, false);

            GUILayout.BeginVertical("box", GUILayout.MaxWidth(300));
            if (GUILayout.Button("Select Device:"))
            {
                _selectedDevice = null;
            }
            GUILayout.EndVertical();

            GUILayout.BeginVertical("box", GUILayout.MaxWidth(300));
            for (int i = 0; i < DeckLink.GetNumDevices(); i++)
            {
                Device device = DeckLink.GetDevice(i);

                if (device == _selectedDevice)
                {
                    GUI.color = Color.blue;
                }
                if (_activeMode != null && device == _selectedDevice && device.IsStreamingOutput)
                {
                    GUI.color = Color.green;
                }


                if (GUILayout.Button(device.Name + " " + device.ModelName, _modeListStyle))
                {
                    _selectedDevice = device;
                }
                GUI.color = Color.white;
            }
            GUILayout.EndVertical();
            GUILayout.EndScrollView();

            // For the selected device, list the modes available
            if (_selectedDevice != null)
            {
                GUILayout.BeginVertical();
                GUILayout.BeginVertical("box", GUILayout.MaxWidth(300));
                if (GUILayout.Button("Select Mode:"))
                {
                    _selectedDevice = null;
                }
                GUILayout.EndVertical();

                if (_selectedDevice != null)
                {
                    GUILayout.BeginVertical("box", GUILayout.MaxWidth(600));
                    _modeScrollPos = GUILayout.BeginScrollView(_modeScrollPos, false, false);
                    for (int j = 0; j < _selectedDevice.NumOutputModes; j++)
                    {
                        DeviceMode mode = _selectedDevice.GetOutputMode(j);

                        if (mode == _activeMode)
                        {
                            if (_selectedDevice.IsStreamingOutput)
                            {
                                GUI.color = Color.green;
                            }
                            else
                            {
                                GUI.color = Color.blue;
                            }
                        }
                        //GUILayout.BeginVertical("box", GUILayout.MaxWidth(300));
                        if (GUILayout.Button("" + j.ToString("D2") + ") " + mode.ModeDescription + " - " + mode.PixelFormatDescription + " - " + mode.Width + "x" + mode.Height, _modeListStyle))
                        {
                            _decklink.StopOutput();
                            _decklink.DeviceIndex = _selectedDevice.DeviceIndex;
                            _decklink.ModeIndex   = mode.Index;
                            _decklink.Begin();

                            _activeMode = mode;
                        }

                        GUI.color = Color.white;
                    }
                    GUILayout.EndScrollView();
                    GUILayout.EndVertical();
                }
                GUILayout.EndVertical();
            }

            if (_decklink.Device != null && _decklink.Device.IsStreamingOutput)
            {
                GUILayout.BeginVertical("box");
                int numDecklinkBufferedFrames = DeckLinkPlugin.GetOutputBufferedFramesCount(_decklink.Device.DeviceIndex);
                int numWaitingOutputFrames    = DeckLinkPlugin.GetWaitingOutputBufferCount(_decklink.Device.DeviceIndex);
                int numFreeOutputFrames       = DeckLinkPlugin.GetFreeOutputBufferCount(_decklink.Device.DeviceIndex);

                GUILayout.Space(20f);
                GUILayout.Label(string.Format("VSync {0}", QualitySettings.vSyncCount));
                GUILayout.Label(string.Format("{0:F3} {1}", _decklink.TargetFramerate, _decklink.OutputFramerate));
                GUILayout.Label(string.Format("Buffers: DeckLink {0:D2} << Full {1:D2} << Empty {2:D2}", numDecklinkBufferedFrames, numWaitingOutputFrames, numFreeOutputFrames));
                GUILayout.Label("Screen: " + Screen.currentResolution.width + "x" + Screen.currentResolution.height + " " + Screen.currentResolution.refreshRate);
                GUILayout.EndVertical();
            }

            GUILayout.EndHorizontal();
        }
Example #7
0
        public void OnGUI()
        {
            GUI.skin = _guiSkin;

            if (_modeListStyle == null)
            {
                _modeListStyle = GUI.skin.GetStyle("ModeList");
            }

            // List the devices
            GUILayout.BeginVertical("box", GUILayout.MaxWidth(400));
            if (GUILayout.Button("Select Input and Output Device:"))
            {
                _selectedInputDevice  = null;
                _selectedOutputDevice = null;
                _needsInputAutoScroll = _needsOutputAutoScroll = false;
            }
            GUILayout.EndVertical();

            GUILayout.BeginVertical("box", GUILayout.MaxWidth(400));
            for (int i = 0; i < DeckLink.GetNumDevices(); i++)
            {
                Device device = DeckLink.GetDevice(i);

                GUILayout.BeginHorizontal();
                GUILayout.Label(device.Name + " " + device.ModelName, _modeListStyle, GUILayout.Width(192f));

                GUI.color = Color.white;
                if (device == _selectedInputDevice)
                {
                    GUI.color = Color.blue;
                }
                if (device.IsStreamingInput)
                {
                    GUI.color = Color.green;
                }

                GUI.enabled = true;
                if (device.IsStreamingOutput && !device.FullDuplexSupported)
                {
                    GUI.enabled = false;
                }

                if (GUILayout.Button("Input", _modeListStyle))
                {
                    _selectedInputDevice  = device;
                    _needsInputAutoScroll = true;
                }

                GUI.color = Color.white;
                if (device == _selectedOutputDevice)
                {
                    GUI.color = Color.blue;
                }
                if (device.IsStreamingOutput)
                {
                    GUI.color = Color.green;
                }

                GUI.enabled = true;
                if (device.IsStreamingInput && !device.FullDuplexSupported)
                {
                    GUI.enabled = false;
                }

                if (GUILayout.Button("Output", _modeListStyle))
                {
                    _selectedOutputDevice  = device;
                    _needsOutputAutoScroll = true;
                }

                GUI.enabled = device.IsStreaming;
                GUI.color   = Color.white;
                if (GUILayout.Button("Stop", _modeListStyle))
                {
                    if (device.IsStreamingInput)
                    {
                        StopInput();
                    }
                    if (device.IsStreamingOutput)
                    {
                        StopOutput();
                    }
                }
                GUILayout.EndHorizontal();

                GUI.enabled = true;
                GUI.color   = Color.white;
            }
            GUILayout.EndVertical();

            _outputModeMatchInputMode = GUILayout.Toggle(_outputModeMatchInputMode, "Auto Match Output Mode To Input");

            GUILayout.BeginHorizontal();

            // For the selected device, list the INPUTmodes available
            if (_selectedInputDevice != null)
            {
                GUILayout.BeginVertical();
                GUILayout.BeginVertical("box", GUILayout.MaxWidth(500));
                if (GUILayout.Button("Select " + _selectedInputDevice.Name + " Input Mode:"))
                {
                    _selectedInputDevice = null;
                }
                GUILayout.EndVertical();

                if (_selectedInputDevice != null)
                {
                    GUILayout.BeginVertical("box", GUILayout.MaxWidth(500), GUILayout.MaxHeight(400));
                    _inputModeScrollPos = GUILayout.BeginScrollView(_inputModeScrollPos, false, false);

                    for (int j = 0; j < _selectedInputDevice.NumInputModes; j++)
                    {
                        DeviceMode mode = _selectedInputDevice.GetInputMode(j);

                        if (_inputDecklink.Device != null && _inputDecklink.Device.IsStreaming && _inputDecklink.Device.CurrentMode == mode)
                        {
                            GUI.color = Color.green;
                        }

                        if (GUILayout.Button("" + j.ToString("D2") + ") " + mode.ModeDescription + " - " + mode.PixelFormatDescription + " - " + mode.Width + "x" + mode.Height, _modeListStyle))
                        {
                            StartInput(mode);
                        }

                        GUI.color = Color.white;
                    }

                    if (Event.current.type == EventType.Repaint)
                    {
                        if (_needsInputAutoScroll)
                        {
                            if (_inputDecklink.Device != null && _inputDecklink.Device.IsStreaming && _inputDecklink.Device.CurrentMode != null)
                            {
                                float height = _modeListStyle.CalcHeight(new GUIContent("A"), 64);
                                float y      = _inputDecklink.Device.CurrentMode.Index * height;
                                GUI.ScrollTo(new Rect(0, y, 10, height * 8));
                            }
                            _needsInputAutoScroll = false;
                        }
                    }

                    GUILayout.EndScrollView();
                    GUILayout.EndVertical();
                }
                GUILayout.EndVertical();
            }

            // For the selected device, list the OUTPUT modes available
            if (_selectedOutputDevice != null)
            {
                GUILayout.BeginVertical();
                GUILayout.BeginVertical("box", GUILayout.MaxWidth(500));
                if (GUILayout.Button("Select " + _selectedOutputDevice.Name + " Output Mode:"))
                {
                    _selectedOutputDevice = null;
                }
                GUILayout.EndVertical();

                if (_selectedOutputDevice != null)
                {
                    GUILayout.BeginVertical("box", GUILayout.MaxWidth(500), GUILayout.MaxHeight(400));
                    _outputModeScrollPos = GUILayout.BeginScrollView(_outputModeScrollPos, false, false);

                    for (int j = 0; j < _selectedOutputDevice.NumOutputModes; j++)
                    {
                        DeviceMode mode = _selectedOutputDevice.GetOutputMode(j);

                        if (_outputDecklink.Device != null && _outputDecklink.Device.IsStreaming && _outputDecklink.Device.CurrentOutputMode == mode)
                        {
                            GUI.color = Color.green;
                        }

                        if (GUILayout.Button("" + j.ToString("D2") + ") " + mode.ModeDescription + " - " + mode.PixelFormatDescription + " - " + mode.Width + "x" + mode.Height, _modeListStyle))
                        {
                            StartOutput(mode);
                        }

                        GUI.color = Color.white;
                    }

                    if (Event.current.type == EventType.Repaint)
                    {
                        if (_needsOutputAutoScroll)
                        {
                            if (_outputDecklink.Device != null && _outputDecklink.Device.IsStreaming && _outputDecklink.Device.CurrentOutputMode != null)
                            {
                                float height = _modeListStyle.CalcHeight(new GUIContent("A"), 64);
                                float y      = _outputDecklink.Device.CurrentOutputMode.Index * height;
                                GUI.ScrollTo(new Rect(0, y, 10, height * 8));
                            }
                            _needsOutputAutoScroll = false;
                        }
                    }

                    GUILayout.EndScrollView();
                    GUILayout.EndVertical();
                }
                GUILayout.EndVertical();
            }

            GUILayout.EndHorizontal();


            // Active input output device summary
            GUILayout.BeginArea(new Rect(0, Screen.height - 64, Screen.width, 64));
            GUILayout.BeginVertical("box");
            string inputStr  = "None";
            string outputStr = "None";

            if (_inputDecklink.Device != null && _inputDecklink.Device.IsStreamingInput)
            {
                inputStr = "" + _inputDecklink.Device.Name + " - " + _inputDecklink.Device.CurrentMode.ModeDescription;
            }
            if (_outputDecklink.Device != null && _outputDecklink.Device.IsStreamingOutput)
            {
                outputStr = "" + _outputDecklink.Device.Name + " - " + _outputDecklink.Device.CurrentOutputMode.ModeDescription;
            }
            GUILayout.Label("Input: " + inputStr, _modeListStyle);
            GUILayout.Label("Output: " + outputStr, _modeListStyle);
            GUILayout.EndVertical();
            GUILayout.EndArea();

            // Output stats
            GUILayout.BeginArea(new Rect(Screen.width - 256, Screen.height - 192, 256, 192));
            GUILayout.BeginVertical("box", GUILayout.ExpandHeight(true));
            if (_outputDecklink.Device != null && _outputDecklink.Device.IsStreaming)
            {
                int numDecklinkBufferedFrames = DeckLinkPlugin.GetOutputBufferedFramesCount(_outputDecklink.Device.DeviceIndex);
                int numWaitingOutputFrames    = DeckLinkPlugin.GetWaitingOutputBufferCount(_outputDecklink.Device.DeviceIndex);
                int numFreeOutputFrames       = DeckLinkPlugin.GetFreeOutputBufferCount(_outputDecklink.Device.DeviceIndex);

                //GUILayout.Space(20f);
                GUILayout.Label(string.Format("VSync {0}", QualitySettings.vSyncCount));
                GUILayout.Label(string.Format("{0:F3} {1}", _outputDecklink.TargetFramerate, _outputDecklink.OutputFramerate));
                GUILayout.Label(string.Format("Buffers: DeckLink {0:D2} << Full {1:D2} << Empty {2:D2}", numDecklinkBufferedFrames, numWaitingOutputFrames, numFreeOutputFrames));

                //GUILayout.Label("Buffered Frames: " + AVProDeckLinkPlugin.GetOutputBufferedFramesCount(_outputDecklink.Device.DeviceIndex));
                //GUILayout.Label("Free Frames: " + AVProDeckLinkPlugin.GetFreeOutputBufferCount(_outputDecklink.Device.DeviceIndex));
                GUILayout.Label("Screen: " + Screen.currentResolution.width + "x" + Screen.currentResolution.height + " " + Screen.currentResolution.refreshRate);
            }
            else
            {
                GUILayout.Label("No Output Stats");
            }
            GUILayout.EndVertical();
            GUILayout.EndArea();
        }
        public void OnGUI()
        {
            GUI.skin = _guiSkin;

            _horizScrollPos = GUILayout.BeginScrollView(_horizScrollPos, false, false);
            GUILayout.BeginHorizontal();

            for (int i = 0; i < _instances.Count; i++)
            {
                DeckLinkInput decklink = _instances[i].decklink;

                GUILayout.BeginVertical("box", GUILayout.MaxWidth(375));

                // Image preview
                Rect cameraRect = GUILayoutUtility.GetRect(375, 200);
                if (GUI.Button(cameraRect, decklink.OutputTexture))
                {
                    if (_zoomed == null)
                    {
                        _zoomed      = decklink.OutputTexture;
                        _zoomSrcDest = cameraRect;
                        _zoomUp      = true;
                    }
                }

                // Controls
                GUILayout.Box("Device " + i + ": " + decklink.Device.Name);
                if (!decklink.Device.IsStreaming)
                {
                    GUILayout.Box("Stopped");
                }
                else
                {
                    GUILayout.Box(string.Format("{0} [{1}]", decklink.Device.CurrentMode.ModeDescription, decklink.Device.CurrentMode.PixelFormatDescription));
                    GUILayout.BeginHorizontal();
                    if (decklink.FlipX)
                    {
                        GUI.color = Color.green;
                    }

                    if (GUILayout.Button("Flip X"))
                    {
                        decklink.FlipX = !decklink.FlipX;
                    }

                    GUI.color = Color.white;

                    if (decklink.FlipY)
                    {
                        GUI.color = Color.green;
                    }

                    if (GUILayout.Button("Flip Y"))
                    {
                        decklink.FlipY = !decklink.FlipY;
                    }

                    GUI.color = Color.white;

                    GUILayout.EndHorizontal();
                    if (!DeckLinkPlugin.IsNoInputSignal(decklink.Device.DeviceIndex))
                    {
                        GUILayout.Box(string.Format("Capture {0}hz Display {1}hz", decklink.Device.CurrentMode.FrameRate.ToString("F2"), decklink.Device.FPS.ToString("F2")));
                    }
                    else
                    {
                        GUILayout.Box("No Signal");
                    }
                    if (GUILayout.Button("Stop"))
                    {
                        if (_zoomed == null)
                        {
                            decklink.Device.StopInput();
                        }
                        _instances[i].showModes = true;
                    }
                }


                if (decklink.Device.AutoDeinterlace != GUILayout.Toggle(decklink.Device.AutoDeinterlace, "Auto Deinterlace", GUILayout.ExpandWidth(true)))
                {
                    decklink.Device.AutoDeinterlace = !decklink.Device.AutoDeinterlace;
                }

                GUILayout.Space(16f);

                _instances[i].showModes = GUILayout.Toggle(_instances[i].showModes, "Show Modes:");

                if (_instances[i].showModes)
                {
                    _instances[i].scrollPos = GUILayout.BeginScrollView(_instances[i].scrollPos, false, false);
                    for (int j = 0; j < decklink.Device.NumInputModes; j++)
                    {
                        DeviceMode mode = decklink.Device.GetInputMode(j);

                        GUI.color = Color.white;
                        if (decklink.Device.IsStreaming && decklink.Device.CurrentMode == mode)
                        {
                            GUI.color = Color.green;
                        }

                        if (GUILayout.Button(j + "/ " + mode.ModeDescription + " [" + mode.PixelFormatDescription + "]"))
                        {
                            if (_zoomed == null)
                            {
                                // Start selected device
                                decklink._modeIndex = j;
                                decklink.Begin();
                                _instances[i].showModes = false;
                            }
                        }
                    }
                    GUILayout.EndScrollView();
                }


                GUILayout.EndVertical();
            }

            GUILayout.EndHorizontal();
            GUILayout.EndScrollView();

            // Show zoomed camera image
            if (_zoomed != null)
            {
                Rect fullScreenRect = new Rect(0, 0, Screen.width, Screen.height);

                float t = Mathf.Clamp01(_zoomTimer / ZoomTime);
                t = Mathf.SmoothStep(0, 1, t);
                Rect r = new Rect();
                r.x      = Mathf.Lerp(_zoomSrcDest.x, fullScreenRect.x, t);
                r.y      = Mathf.Lerp(_zoomSrcDest.y, fullScreenRect.y, t);
                r.width  = Mathf.Lerp(_zoomSrcDest.width, fullScreenRect.width, t);
                r.height = Mathf.Lerp(_zoomSrcDest.height, fullScreenRect.height, t);
                GUI.DrawTexture(r, _zoomed, ScaleMode.ScaleToFit, false);
            }
        }