private void PlayInternal(PlayOptions options)
        {
            EnsureMediaPlayerCreated();

            CurrentPlaylistIndex = 0;
            CurrentPlayOptions = options;

            _playlist = options.Items.ToList();
            _isPaused = false;

            var path = options.Items.First().Path;

            try
            {
                //var media = new PathMedia(@"D:\\Video\\TV\\30 Rock\\Season 1\\30 Rock - 1x02 - The Aftermath.mkv");
                var media = path.StartsWith("http", StringComparison.OrdinalIgnoreCase) ?
                    (MediaBase)new LocationMedia(path) :
                    (MediaBase)new PathMedia(path);

                //media.StateChanged +=
                //    delegate(MediaBase s, VlcEventArgs<States> args)
                //    {
                //        if (args.Data == States.Ended)
                //        {
                //            var subItems = media.SubItems;
                //            if (subItems.Count > 0)
                //            {
                //                _vlcControl.Play(subItems[0]);
                //            }
                //        }
                //    };
                //media.MediaSubItemAdded +=
                //    delegate(MediaBase s, VlcEventArgs<MediaBase> args)
                //    {
                //        _vlcControl.Media = args.Data;
                //        _vlcControl.Play();
                //    };

                _vlcControl = new VlcControl();

                _vlcControl.Media = media;
                _vlcControl.PlaybackMode = PlaybackModes.Loop;
                _vlcControl.Stopped += _vlcControl_Stopped;
                _vlcControl.Paused += _vlcControl_Paused;
                _vlcControl.Playing += _vlcControl_Playing;
                _vlcControl.Play();

                _vlcControl.SetHandle(_hiddenWindow.Form.Handle);

                _userInput.GlobalKeyDown += _userInput_KeyDown;
            }
            catch (Exception ex)
            {
                _logger.ErrorException("Error beginning playback", ex);

                DisposePlayer();
            }
        }
        /// <summary>
        /// Plays the specified options.
        /// </summary>
        /// <param name="options">The options.</param>
        /// <returns>Task.</returns>
        /// <exception cref="System.ArgumentNullException">
        /// options
        /// or
        /// options
        /// </exception>
        /// <exception cref="System.InvalidOperationException">There are no available players.</exception>
        public async Task Play(PlayOptions options)
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }

            if (options.Items == null || options.Items.Count(i => i.LocationType != LocationType.Offline) == 0)
            {
                throw new ArgumentException("At least one item must be supplied.");
            }

            PlayerConfiguration config;
            var player = GetPlayer(options.Items, out config);

            if (player == null)
            {
                throw new InvalidOperationException("There are no available players.");
            }

            StopAllPlayback();

            await Play(player, options, config);
        }
        /// <summary>
        /// Plays the specified player.
        /// </summary>
        /// <param name="player">The player.</param>
        /// <param name="options">The options.</param>
        /// <param name="configuration">The configuration.</param>
        /// <returns>Task.</returns>
        private async Task Play(IMediaPlayer player, PlayOptions options, PlayerConfiguration configuration)
        {
            if (options.Shuffle)
            {
                options.Items = options.Items.OrderBy(i => Guid.NewGuid()).ToList();
            }

            var firstItem = options.Items[0];

            if (options.StartPositionTicks == 0 && player.SupportsMultiFilePlayback && firstItem.IsVideo && firstItem.LocationType == LocationType.FileSystem && options.GoFullScreen)
            {
                try
                {
                    var intros = await _apiClient.GetIntrosAsync(firstItem.Id, _apiClient.CurrentUserId);

                    options.Items.InsertRange(0, intros.Items);
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Error retrieving intros", ex);
                }
            }

            options.Configuration = configuration;

            await player.Play(options);

            if (player is IInternalMediaPlayer && player is IVideoPlayer && firstItem.IsVideo)
            {
                await _presentationManager.Window.Dispatcher.InvokeAsync(() => _presentationManager.WindowOverlay.SetResourceReference(FrameworkElement.StyleProperty, "WindowBackgroundContentDuringPlayback"));

                if (options.GoFullScreen)
                {
                    await _nav.NavigateToInternalPlayerPage();
                }
            }

            OnPlaybackStarted(player, options);
        }
        /// <summary>
        /// Called when [playback started].
        /// </summary>
        /// <param name="player">The player.</param>
        /// <param name="options">The options.</param>
        private async void OnPlaybackStarted(IMediaPlayer player, PlayOptions options)
        {
            EventHelper.QueueEventIfNotNull(PlaybackStarted, this, new PlaybackStartEventArgs
            {
                Options = options,
                Player = player
            }, _logger);

            await new PlaybackProgressReporter(_apiClient, player, _logger, this).Start().ConfigureAwait(false);
        }
        public async Task Play(PlayOptions options)
        {
            CurrentPlaylistIndex = 0;
            CurrentPlayOptions = options;

            _playlist = options.Items.ToList();

            try
            {
                await PlayTrack(0, options.StartPositionTicks);
            }
            catch (Exception ex)
            {
                _logger.ErrorException("Error beginning playback", ex);

                DisposePlayer();

                throw;
            }
        }
 /// <summary>
 /// Gets the command arguments.
 /// </summary>
 /// <param name="items">The items.</param>
 /// <param name="options">The options.</param>
 /// <param name="isoMount">The iso mount.</param>
 /// <returns>System.String.</returns>
 protected virtual string GetCommandArguments(IEnumerable<BaseItemDto> items, PlayOptions options, IIsoMount isoMount)
 {
     return GetCommandArguments(items, options.Configuration.Args, isoMount);
 }
 /// <summary>
 /// Gets the process start info.
 /// </summary>
 /// <param name="items">The items.</param>
 /// <param name="options">The options.</param>
 /// <param name="isoMount">The iso mount.</param>
 /// <returns>ProcessStartInfo.</returns>
 protected virtual ProcessStartInfo GetProcessStartInfo(IEnumerable<BaseItemDto> items, PlayOptions options, IIsoMount isoMount)
 {
     return new ProcessStartInfo
     {
         FileName = options.Configuration.Command,
         Arguments = GetCommandArguments(items, options, isoMount)
     };
 }
        public async Task Play(PlayOptions options)
        {
            CurrentPlaylistIndex = 0;
            CurrentPlayOptions = options;

            _playlist = options.Items.ToList();

            _currentPlaybackDispatcher = _presentation.Window.Dispatcher;

            try
            {
                _currentPlaybackDispatcher.Invoke(() =>
                {
                    _hiddenWindow.WindowsFormsHost.Child = _mediaPlayer = new DirectShowPlayer(_logger, _hiddenWindow, this)
                    {
                        BackColor = Color.Black,
                        BorderStyle = BorderStyle.None
                    };

                    //HideCursor();
                });

                await PlayTrack(0, options.StartPositionTicks);
            }
            catch (Exception ex)
            {
                _logger.ErrorException("Error beginning playback", ex);

                DisposePlayer();

                throw;
            }
        }
        protected override string GetCommandArguments(IEnumerable<BaseItemDto> items, PlayOptions options)
        {
            var formatString = "{0} /play /fullscreen /close";

            var firstItem = items.First();

            var startTicks = Math.Max(options.StartPositionTicks, 0);

            if (startTicks > 0 && firstItem.IsVideo && firstItem.VideoType.HasValue && firstItem.VideoType.Value == VideoType.Dvd)
            {
                formatString += " /dvdpos 1#" + TimeSpan.FromTicks(startTicks).ToString("hh\\:mm\\:ss");
            }
            else
            {
                formatString += " /start " + TimeSpan.FromTicks(startTicks).TotalMilliseconds;
            }

            return GetCommandArguments(items, formatString);
        }
        /// <summary>
        /// Plays the specified player.
        /// </summary>
        /// <param name="player">The player.</param>
        /// <param name="options">The options.</param>
        /// <param name="configuration">The configuration.</param>
        /// <returns>Task.</returns>
        private async Task Play(IMediaPlayer player, PlayOptions options, PlayerConfiguration configuration)
        {
            if (options.Items[0].IsPlaceHolder??false)
            {
                // play a phyical disc in the cdrom drive
                // Will be re-entrant call, so has to be made befpre the interlocked.CompareExchange below
                await PlayExternalDisc(true);
                return;
            }

            if (Interlocked.CompareExchange(ref _isStarting, 1, 0) == 0) // prevent race conditions, thread safe check we are not already starting to play an item
            {
                try
                {
                    if (options.Shuffle)
                    {
                        options.Items = options.Items.OrderBy(i => Guid.NewGuid()).ToList();
                    }

                    var firstItem = options.Items[0];

                  
                    if (options.StartPositionTicks == 0 && player.SupportsMultiFilePlayback && firstItem.IsVideo && firstItem.LocationType == LocationType.FileSystem && options.GoFullScreen)
                    {
                        try
                        {
                            var intros = await _apiClient.GetIntrosAsync(firstItem.Id, _apiClient.CurrentUserId);

                            options.Items.InsertRange(0, intros.Items);
                        }
                        catch (Exception ex)
                        {
                            _logger.ErrorException("Error retrieving intros", ex);
                        }
                    }


                    options.Configuration = configuration;

                    await player.Play(options);

                    if (player is IInternalMediaPlayer && player is IVideoPlayer && firstItem.IsVideo)
                    {
                        await _presentationManager.Window.Dispatcher.InvokeAsync(() => _presentationManager.WindowOverlay.SetResourceReference(FrameworkElement.StyleProperty, "WindowBackgroundContentDuringPlayback"));

                        if (options.GoFullScreen)
                        {
                            await _nav.NavigateToInternalPlayerPage();
                        }
                    }
                    OnPlaybackStarted(player, options);
                    
                }
                finally
                {
                    Interlocked.Exchange(ref _isStarting, 0);
                }
            }
        }
        /// <summary>
        /// Plays the specified options.
        /// </summary>
        /// <param name="options">The options.</param>
        /// <returns>Task.</returns>
        /// <exception cref="ArgumentNullException">
        /// options
        /// or
        /// options
        /// </exception>
        /// <exception cref="System.InvalidOperationException">There are no available players.</exception>
        public async Task Play(PlayOptions options)
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }

            if (options.Items == null || options.Items.Count(i => i.LocationType != LocationType.Offline) == 0)
            {
                throw new ArgumentException("At least one item must be supplied.");
            }

            if (options.Items.Count == 1)
            {
                var item = options.Items[0];

                ItemQuery query = null;

                if (item.IsType("playlist"))
                {
                    query = new ItemQuery
                    {
                        ParentId = item.Id
                    };
                }
                else if (item.IsType("musicalbum"))
                {
                    query = new ItemQuery
                    {
                        ParentId = item.Id,
                        SortBy = new[] { ItemSortBy.SortName }
                    };
                }
                else if (item.IsType("musicartist"))
                {
                    query = new ItemQuery
                    {
                        SortBy = new[] { ItemSortBy.SortName },
                        IncludeItemTypes = new[] { "Audio" },
                        ArtistIds = new[] { item.Id }
                    };
                }
                else if (item.IsType("musicgenre"))
                {
                    query = new ItemQuery
                    {
                        SortBy = new[] { ItemSortBy.SortName },
                        IncludeItemTypes = new[] { "Audio" },
                        Genres = new[] { item.Name }
                    };
                }

                if (query != null)
                {
                    var apiClient = _connectionManager.GetApiClient(options.Items[0]);

                    query.UserId = apiClient.CurrentUserId;
                    query.Fields = new[] { ItemFields.Path, ItemFields.Chapters, ItemFields.MediaSources };

                    var result = await apiClient.GetItemsAsync(query);

                    options.Items = result.Items.ToList();
                }
            }

            PlayerConfiguration config;
            var player = GetPlayer(options.Items, options.EnableCustomPlayers, out config);

            if (player == null)
            {
                throw new InvalidOperationException("There are no available players.");
            }

            StopAllPlayback();

            await Task.Run(() => Play(player, options, config));
        }
        /// <summary>
        /// Called when [playback started].
        /// </summary>
        /// <param name="player">The player.</param>
        /// <param name="options">The options.</param>
        private async void OnPlaybackStarted(IMediaPlayer player, PlayOptions options)
        {
            EventHelper.QueueEventIfNotNull(PlaybackStarted, this, new PlaybackStartEventArgs
            {
                Options = options,
                Player = player
            }, _logger);

            lock (_reporterLock)
            {
                if (_reporter != null)
                {
                    _reporter.Dispose();
                    _reporter = null;
                }
            }

            _reporter = new PlaybackProgressReporter(_connectionManager, player, _logger, this, _apiPlaybackManager);
            await _reporter.Start().ConfigureAwait(false);
        }
 /// <summary>
 /// Plays the specified options.
 /// </summary>
 /// <param name="options">The options.</param>
 /// <returns>Task.</returns>
 public async Task Play(PlayOptions options)
 {
     InvokeOnPlayerThread(() => PlayInternal(options));
 }
        /// <summary>
        /// Enables the madvr.
        /// </summary>
        /// <param name="options">The options.</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
        private bool EnableReclock(PlayOptions options)
        {
            var video = options.Items.First();

            if (!video.IsVideo)
            {
                return false;
            }

            if (!_config.Configuration.InternalPlayerConfiguration.EnableReclock)
            {
                return false;
            }

            return true;
        }
        public async Task Play(PlayOptions options)
        {
            CurrentPlaylistIndex = 0;
            CurrentPlayOptions = options;

            _playlist = options.Items.ToList();

            try
            {
                //InvokeOnPlayerThread(() =>
                //{
                //    _mediaPlayer = new DirectShowPlayer(_logger, _hiddenWindow, this, _presentation.WindowHandle, _sessionManager, _config, _inputManager, _apiClient, _zipClient, _httpClient);

                //    //HideCursor();
                //});

                await PlayTrack(0, options.StartPositionTicks);
            }
            catch (Exception ex)
            {
                _logger.ErrorException("Error beginning playback", ex);

                DisposePlayer();

                throw;
            }
        }
        /// <summary>
        /// Plays the specified options.
        /// </summary>
        /// <param name="options">The options.</param>
        /// <returns>Task.</returns>
        public async Task Play(PlayOptions options)
        {
            _currentIsoMount = options.Items.Count == 1 && options.Configuration.IsoMethod == IsoConfiguration.Mount ?
                await GetIsoMount(options.Items[0], CancellationToken.None) :
                null;

            CurrentPlaylistIndex = 0;
            CurrentPlayOptions = options;

            _playlist = options.Items.ToList();

            var process = new Process
            {
                EnableRaisingEvents = true,
                StartInfo = GetProcessStartInfo(options.Items, options, _currentIsoMount)
            };

            Logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);

            try
            {
                process.Start();
            }
            catch (Exception ex)
            {
                Logger.ErrorException("Error starting player", ex);

                _playlist.Clear();

                throw;
            }

            if (options.Configuration.CloseOnStopButton && !CanCloseAutomaticallyOnStopButton)
            {
                _userInput.GlobalKeyDown += KeyboardListener_KeyDown;
            }

            process.Exited += CurrentProcess_Exited;

            _currentProcess = process;

            OnPlayerLaunched();
        }
        /// <summary>
        /// Enables the madvr.
        /// </summary>
        /// <param name="options">The options.</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
        private bool EnableMadvr(PlayOptions options)
        {
            var video = options.Items.First();

            if (!video.IsVideo)
            {
                return false;
            }

            if (!_config.Configuration.InternalPlayerConfiguration.VideoConfig.EnableMadvr)
            {
                return false;
            }

            if (!options.GoFullScreen)
            {
                return false;
            }

            return true;
        }
        /// <summary>
        /// Plays the specified options.
        /// </summary>
        /// <param name="options">The options.</param>
        /// <returns>Task.</returns>
        public Task Play(PlayOptions options)
        {
            return Task.Run(() =>
            {
                CurrentPlaylistIndex = 0;
                CurrentPlayOptions = options;

                _playlist = options.Items.ToList();

                var process = new Process
                {
                    EnableRaisingEvents = true,
                    StartInfo = GetProcessStartInfo(options.Items, options)
                };

                Logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);

                try
                {
                    process.Start();
                }
                catch (Exception ex)
                {
                    Logger.ErrorException("Error starting player", ex);

                    _playlist.Clear();

                    throw;
                }

                if (options.Configuration.CloseOnStopButton && !CanCloseAutomaticallyOnStopButton)
                {
                    _userInput.KeyDown += KeyboardListener_KeyDown;
                }

                process.Exited += CurrentProcess_Exited;

                _currentProcess = process;

                OnPlayerLaunched();
            });
        }