public List<Resolution> GetResolutions()
        {
            if (_modes == null)
            {
                _modes = new List<Resolution>();
                List<string> addedModes = new List<string>();
                int i = 0;

                DEVMODE dm = new DEVMODE();
                dm.dmDeviceName = new String(new char[32]);
                dm.dmFormName = new String(new char[32]);
                dm.dmSize = (short)Marshal.SizeOf(dm);

                while (0 != NativeMethods.EnumDisplaySettings(null, i, ref dm))
                {
                    if (dm.dmBitsPerPel == 32 || dm.dmBitsPerPel == 16)
                    {
                        Resolution r = new Resolution(dm.dmPelsWidth, dm.dmPelsHeight, dm.dmDisplayFrequency, (dm.dmDisplayFlags & NativeMethods.DM_INTERLACED) == NativeMethods.DM_INTERLACED, dm.dmDisplayFixedOutput, dm.dmBitsPerPel);
                        if (!addedModes.Contains(r.ToString()))
                        {
                            _modes.Add(r);
                            addedModes.Add(r.ToString());
                        }
                    }
                    i++;
                }
            }

            return _modes;
        }
        public void Play(PlayableItem item, bool enableMadvr, bool enableMadvrExclusiveMode)
        {
            try
            {
                _logger.Info("Playing {0}. Audio Renderer: {1}, Madvr: {2}, xySubFilter: {3}, ParentID: {4}", item.OriginalItem.Name,
                    _mbtConfig.Configuration.InternalPlayerConfiguration.AudioConfig.Renderer, enableMadvr,
                    _mbtConfig.Configuration.InternalPlayerConfiguration.SubtitleConfig.EnableXySubFilter,
                    item.OriginalItem.ParentId);
                _logger.Info("Playing Path {0}", item.PlayablePath);

                var mediaSource = item.MediaSource;

                _item = item;
                _isInExclusiveMode = false;
                TimeSpan itemDuration = TimeSpan.MaxValue;

                if (mediaSource.RunTimeTicks.HasValue && mediaSource.RunTimeTicks.Value > 0)
                    itemDuration = TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value);

                _iVideoScaling = (VideoScalingScheme)_mbtConfig.Configuration.InternalPlayerConfiguration.VideoConfig.ScalingMode;

                if (item.IsVideo
                    && IsFullScreen
                    && !string.IsNullOrWhiteSpace(item.OriginalItem.ParentId)
                    && _mbtConfig.Configuration.InternalPlayerConfiguration.VideoConfig.AutoChangeRefreshRate
                    && _mbtConfig.Configuration.InternalPlayerConfiguration.VideoConfig.MinRefreshRateMin < itemDuration.TotalMinutes
                    )
                {
                    if (item.MediaStreams == null)
                    {
                        _logger.Warn("item.MediaStreams is null, cannot detect framerate");
                    }
                    else
                    {
                        //find the video stream (assume that the first one is the main one)
                        foreach (var ms in item.MediaStreams)
                        {
                            if (ms.Type == MediaStreamType.Video)
                            {
                                _startResolution = Display.GetCurrentResolution();
                                if (ms.RealFrameRate.HasValue)
                                {
                                    int videoRate = (int)ms.RealFrameRate;

                                    if (videoRate == 25 || videoRate == 29 || videoRate == 30 || ms.IsInterlaced) // ms.IsInterlaced doesn't appear to be accurate
                                    {
                                        //Every display/GPU should be able to display @2x FPS and it's quite likely that 2x is the rendered FPS anyway
                                        videoRate = (int)(ms.RealFrameRate * 2);
                                    }

                                    _logger.Info("RealFrameRate: {0} videoRate: {1} startRate: {2}", ms.RealFrameRate, videoRate, _startResolution);

                                    if (videoRate != _startResolution.Rate)
                                    {
                                        Resolution desiredRes = new Resolution(_startResolution.ToString());
                                        desiredRes.Rate = videoRate;
                                        if (Display.ChangeResolution(desiredRes, false))
                                            _logger.Info("Changed resolution from {0} to {1}", _startResolution, desiredRes);
                                        else
                                        {
                                            _logger.Info("Couldn't change resolution from {0} to {1}", _startResolution, desiredRes);
                                            _startResolution = null;
                                        }
                                    }
                                    else
                                        _startResolution = null;

                                    break;
                                }
                            }
                            else
                                _startResolution = null;
                        }
                    }
                }

                var isDvd = ((item.MediaSource.VideoType ?? VideoType.VideoFile) == VideoType.Dvd ||
                             (item.MediaSource.IsoType ?? IsoType.BluRay) == IsoType.Dvd) &&
                            item.StreamInfo == null;

                Initialize(item.PlayablePath, enableMadvr, enableMadvrExclusiveMode,
                    _mbtConfig.Configuration.InternalPlayerConfiguration.SubtitleConfig.EnableXySubFilter, isDvd);

                _hiddenWindow.OnWMGRAPHNOTIFY = HandleGraphEvent;
                _hiddenWindow.OnDVDEVENT = HandleDvdEvent;

                //pre-roll the graph
                _logger.Debug("pre-roll the graph");
                var hr = _mediaControl.Pause();
                DsError.ThrowExceptionForHR(hr);

                _logger.Debug("run the graph");
                hr = _mediaControl.Run();
                DsError.ThrowExceptionForHR(hr);

                PlayState = PlayState.Playing;
                _currentPlaybackRate = 1.0;

                _streams = GetStreams();

                _logger.Debug("DSPlayer Done in play");
            }
            catch (Exception ex)
            {
                CloseInterfaces();
                throw ex;
            }
        }
        public static bool ChangeResolution(Resolution res, bool permanent)
        {
            int i = 0;

            DEVMODE cDm = new DEVMODE();
            //cDm.dmDeviceName = new String(new char[32]);
            //cDm.dmFormName = new String(new char[32]);
            cDm.dmSize = (short)Marshal.SizeOf(cDm);
            //FileLogger.Log("DEVMODE Size: {0}", Marshal.SizeOf(cDm));

            NativeMethods.EnumDisplaySettings(null, NativeMethods.ENUM_CURRENT_SETTINGS, ref cDm);

            if (cDm.dmBitsPerPel == res.PixelDepth
                    && cDm.dmPelsWidth == res.Width
                    && cDm.dmPelsHeight == res.Height
                    && cDm.dmDisplayFrequency == res.Rate
                    && ((cDm.dmDisplayFlags & NativeMethods.DM_INTERLACED) == NativeMethods.DM_INTERLACED) == res.Interlaced
                    && cDm.dmDisplayFixedOutput == res.FixedOutput)
            {
                return false;
            }

            DEVMODE dm = new DEVMODE();
            //dm.dmDeviceName = new String(new char[32]);
            //dm.dmFormName = new String(new char[32]);
            dm.dmSize = (short)Marshal.SizeOf(dm);

            while (0 != NativeMethods.EnumDisplaySettings(null, i, ref dm))
            {
                if (dm.dmBitsPerPel == res.PixelDepth
                    && dm.dmPelsWidth == res.Width
                    && dm.dmPelsHeight == res.Height
                    && dm.dmDisplayFrequency == res.Rate
                    && ((dm.dmDisplayFlags & NativeMethods.DM_INTERLACED) == NativeMethods.DM_INTERLACED) == res.Interlaced
                    && dm.dmDisplayFixedOutput == res.FixedOutput)
                {
                    int iRet = NativeMethods.ChangeDisplaySettings(ref dm, CDS.Test);

                    if (iRet == NativeMethods.DISP_CHANGE_SUCCESSFUL)
                    {
                        if (permanent)
                            iRet = NativeMethods.ChangeDisplaySettings(ref dm, CDS.UpdateRegistry);
                        else
                        {
                            iRet = NativeMethods.ChangeDisplaySettings(ref dm, CDS.Dynamic);
                            //IntPtr nRes = IntPtr.Zero;
                            //try
                            //{
                            //    nRes = Marshal.AllocHGlobal(Marshal.SizeOf(dm));
                            //    Marshal.StructureToPtr(dm, nRes, true);
                            //    iRet = NativeMethods.ChangeDisplaySettings(nRes, CDS.Dynamic);
                            //}
                            //finally
                            //{
                            //    if (nRes != IntPtr.Zero)
                            //        Marshal.FreeHGlobal(nRes);
                            //}
                        }
                    }

                    return iRet == NativeMethods.DISP_CHANGE_SUCCESSFUL;
                }

                i++;
            }
            return false;
        }
        public static Resolution GetCurrentResolution()
        {
            DEVMODE cDm = new DEVMODE();
            //cDm.dmDeviceName = new String(new char[32]);
            //cDm.dmFormName = new String(new char[32]);
            cDm.dmSize = (short)Marshal.SizeOf(cDm);

            NativeMethods.EnumDisplaySettings(null, NativeMethods.ENUM_CURRENT_SETTINGS, ref cDm);

            Resolution res = new Resolution(cDm.dmPelsWidth, cDm.dmPelsHeight, cDm.dmDisplayFrequency, ((cDm.dmDisplayFlags & NativeMethods.DM_INTERLACED) == NativeMethods.DM_INTERLACED), cDm.dmDisplayFixedOutput, cDm.dmBitsPerPel);

            return res;
        }