public VideoViewModel(IEventAggregator eventAggregator)
        {
            EventAggregator = eventAggregator;
            VideoSettings = ServiceLocator.Current.GetInstance(typeof(VideoSettingsViewModel)) as VideoSettingsViewModel;
            VideoSettings.SettingsChanged += VideoSettings_SettingsChanged;

            IsInitialized = false;
            isInitializedSignal = new SemaphoreSlim(0, 1);

            CurrentItem = new VideoAudioPair(null, null);
                              
            OpenAndPlayCommand = new AsyncCommand<VideoAudioPair>(async item =>
            {
                await isInitializedSignal.WaitAsync();
                isInitializedSignal.Release();

                try
                {
                    CurrentItem = item;

                    String videoLocation = null;
                    String videoFormatName = null;

                    if (item.Video != null)
                    {
                        videoLocation = item.Video.Location;
                        if (item.Video is MediaStreamedItem)
                        {
                            if (item.Video.Metadata != null)
                            {
                                videoFormatName = MediaFormatConvert.mimeTypeToExtension(item.Video.Metadata.MimeType);
                            }
                        }

                    }

                    String audioLocation = null;
                    String audioFormatName = null;

                    if (item.Audio != null)
                    {
                        audioLocation = item.Audio.Location;

                        if (item.Audio is MediaStreamedItem && item.Audio.Metadata != null)
                        {                          
                            audioFormatName = MediaFormatConvert.mimeTypeToExtension(item.Audio.Metadata.MimeType);                                                       
                        }

                    }

                    CloseCommand.IsExecutable = true;
               
                    IsLoading = true;
                    
                    await VideoPlayer.openAndPlay(videoLocation, videoFormatName, audioLocation, audioFormatName);                   
                                        
                }
                catch (OperationCanceledException)
                {
                    CloseCommand.IsExecutable = false;
                    throw;
                }
                catch (Exception e)
                {
                    CloseCommand.IsExecutable = false;                   
                    MessageBox.Show("Error opening " + item.Video.Location + "\n\n" + e.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    throw;
                }
                finally
                {
                    IsLoading = false;
                  
                }
               
                EventAggregator.GetEvent<TitleChangedEvent>().Publish(CurrentItem.IsEmpty ? null : CurrentItem.Name);              
                
            });

            PlayCommand = new AsyncCommand(async () =>
            {                             
                if (VideoState == VideoPlayerControl.VideoState.CLOSED && !CurrentItem.IsEmpty)
                {
                    await openAndPlay(CurrentItem); 
                }
                else if (VideoState == VideoPlayerControl.VideoState.OPEN || VideoState == VideoPlayerControl.VideoState.PAUSED)
                {
                    VideoPlayer.play();
                }                

            }, false);

            PauseCommand = new Command(() => {
              
                VideoPlayer.pause(); 

            }, false);

            CloseCommand = new AsyncCommand(async () => {
                     
                await VideoPlayer.close(); 

            }, false);

            SeekCommand = new AsyncCommand<double>(async (pos) =>
            {              
                await VideoPlayer.seek(pos); 

            }, false);

            StepForwardCommand = new AsyncCommand(async () =>
                {
                    StepForwardCommand.IsExecutable = false;

                    double timeStamp = VideoPlayer.getFrameSeekTimeStamp() + Settings.Default.VideoStepDurationSeconds;                    
                    await VideoPlayer.seek(timeStamp, VideoLib.VideoPlayer.SeekKeyframeMode.SEEK_FORWARDS);

                    StepForwardCommand.IsExecutable = true;

                }, false);

            StepBackwardCommand = new AsyncCommand(async () =>
            {
                StepBackwardCommand.IsExecutable = false;

                double timeStamp = VideoPlayer.getFrameSeekTimeStamp() - Settings.Default.VideoStepDurationSeconds;                
                await VideoPlayer.seek(timeStamp, VideoLib.VideoPlayer.SeekKeyframeMode.SEEK_BACKWARDS);

                StepBackwardCommand.IsExecutable = true;

            }, false);

            FrameByFrameCommand = new Command(() => {
             
                VideoPlayer.displayNextFrame();
         
            }, false);

            CutVideoCommand = new Command(() =>
            {                
                String outputPath;

                if(FileUtils.isUrl(VideoPlayer.VideoLocation)) {

                    outputPath = MediaFileWatcher.Instance.Path;

                } else {

                    outputPath = FileUtils.getPathWithoutFileName(VideoPlayer.VideoLocation);
                }

                VideoTranscodeView videoTranscode = new VideoTranscodeView();
                videoTranscode.ViewModel.Items.Add(CurrentItem);
                videoTranscode.ViewModel.Title = "Cut Video";
                videoTranscode.ViewModel.IconUri = "/MediaViewer;component/Resources/Icons/videocut.ico";

                videoTranscode.ViewModel.OutputPath = outputPath;
                videoTranscode.ViewModel.IsTimeRangeEnabled = IsTimeRangeEnabled;
                videoTranscode.ViewModel.StartTimeRange = startTimeRangeTimeStamp;
                videoTranscode.ViewModel.EndTimeRange = endTimeRangeTimeStamp;

                String extension = Path.GetExtension(VideoPlayer.VideoLocation).ToLower().TrimStart('.');

                foreach(ContainerFormats format in Enum.GetValues(typeof(ContainerFormats))) {

                    if (format.ToString().ToLower().Equals(extension))
                    {
                        videoTranscode.ViewModel.ContainerFormat = format;
                    }
                }
                
                videoTranscode.ShowDialog();

            }, false);

            ScreenShotCommand = new Command(() =>
            {             
                try
                {
                    String screenShotName = FileUtils.removeIllegalCharsFromFileName(CurrentItem.Video.Name, " ");

                    screenShotName += "." + "jpg";

                    String path = null;

                    switch (Settings.Default.VideoScreenShotSaveMode)
                    {
                        case MediaViewer.Infrastructure.Constants.SaveLocation.Current:
                            {
                                path = MediaFileWatcher.Instance.Path;
                                break;
                            }
                        case MediaViewer.Infrastructure.Constants.SaveLocation.Ask:
                            {
                                DirectoryPickerView directoryPicker = new DirectoryPickerView();
                                DirectoryPickerViewModel vm = (DirectoryPickerViewModel)directoryPicker.DataContext;
                                directoryPicker.Title = "Screenshot Output Directory";
                                vm.SelectedPath = Settings.Default.VideoScreenShotLocation;
                                vm.PathHistory = Settings.Default.VideoScreenShotLocationHistory;

                                if (directoryPicker.ShowDialog() == true)
                                {
                                    path = vm.SelectedPath;
                                }
                                else
                                {
                                    return;
                                }
                                break;
                            }
                        case MediaViewer.Infrastructure.Constants.SaveLocation.Fixed:
                            {
                                path = Settings.Default.VideoScreenShotLocation;
                                break;
                            }
                        default:
                            break;
                    }
                                                                                                      
                    String fullPath = FileUtils.getUniqueFileName(path + "\\" + screenShotName);

                    VideoPlayer.createScreenShot(fullPath, VideoSettings.VideoScreenShotTimeOffset);
                }
                catch (Exception e)
                {
                    MessageBox.Show("Error creating screenshot.\n\n" + e.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                }

            }, false);
        
            SetLeftMarkerCommand = new Command(() =>
                {
                    if (IsTimeRangeEnabled == false)
                    {
                        IsTimeRangeEnabled = true;
                    }

                    // get the exact time of the current audio or video frame, positionseconds is potentially inaccurate
                    StartTimeRange = VideoPlayer.PositionSeconds;
                    startTimeRangeTimeStamp = VideoPlayer.getFrameSeekTimeStamp();

                }, false);

            SetRightMarkerCommand = new Command(() =>
            {
                if (IsTimeRangeEnabled == false)
                {
                    IsTimeRangeEnabled = true;
                    StartTimeRange = VideoPlayer.PositionSeconds;
                    startTimeRangeTimeStamp = VideoPlayer.getFrameSeekTimeStamp();
                }
                else
                {
                    EndTimeRange = VideoPlayer.PositionSeconds;
                    endTimeRangeTimeStamp = VideoPlayer.getFrameSeekTimeStamp();
                }

            }, false);

            OpenLocationCommand = new Command(async () =>
            {
                VideoOpenLocationView openLocation = new VideoOpenLocationView();
                                                
                bool? success = openLocation.ShowDialog();
                if (success == true) 
                {
                    MediaItem video = null;
                    MediaItem audio = null;
                    
                    if (!String.IsNullOrWhiteSpace(openLocation.ViewModel.VideoLocation))
                    {
                        video = MediaItemFactory.create(openLocation.ViewModel.VideoLocation);
                        MiscUtils.insertIntoHistoryCollection(Settings.Default.VideoLocationHistory, openLocation.ViewModel.VideoLocation);
                    }

                    if (!String.IsNullOrWhiteSpace(openLocation.ViewModel.AudioLocation))
                    {
                        audio = MediaItemFactory.create(openLocation.ViewModel.AudioLocation);
                        MiscUtils.insertIntoHistoryCollection(Settings.Default.AudioLocationHistory, openLocation.ViewModel.AudioLocation);
                    }

                    await openAndPlay(new VideoAudioPair(video, audio));
                }
              
            });
         
            HasAudio = true;
            VideoState = VideoPlayerControl.VideoState.CLOSED;
           
            IsTimeRangeEnabled = false;
            StartTimeRange = 0;
            EndTimeRange = 0;
            startTimeRangeTimeStamp = 0;
            endTimeRangeTimeStamp = 0;

        }
        public MediaFileBrowserViewModel(MediaFileWatcher mediaFileWatcher, IRegionManager regionManager, IEventAggregator eventAggregator)
        {
    
            MediaFileWatcher = mediaFileWatcher;
            RegionManager = regionManager;
            EventAggregator = eventAggregator;
          
            MediaFileGridViewModel = new MediaFileGridViewModel(mediaFileWatcher.MediaFileState, EventAggregator);
       
            ImageViewModel = new MediaFileBrowserImagePanelViewModel(eventAggregator);
            ImageViewModel.SelectedScaleMode = MediaViewer.UserControls.ImagePanel.ScaleMode.FIT_HEIGHT_AND_WIDTH;

            imageMediaStackPanelViewModel = new MediaFileStackPanelViewModel(MediaFileGridViewModel.MediaStateCollectionView, EventAggregator);            
            imageMediaStackPanelViewModel.IsVisible = true;

            VideoViewModel = new VideoPanel.VideoViewModel(EventAggregator);

            videoMediaStackPanelViewModel = new MediaFileStackPanelViewModel(MediaFileGridViewModel.MediaStateCollectionView, EventAggregator);            
            videoMediaStackPanelViewModel.IsVisible = true;

            GeotagFileBrowserViewModel = new GeotagFileBrowserViewModel(MediaFileGridViewModel.MediaStateCollectionView, EventAggregator);

            GeotagFileBrowserStackPanelViewModel = new MediaFileStackPanelViewModel(MediaFileGridViewModel.MediaStateCollectionView, EventAggregator);
            GeotagFileBrowserStackPanelViewModel.IsVisible = true;
                       
            DeleteSelectedItemsCommand = new Command(new Action(deleteSelectedItems));
      
            ImportSelectedItemsCommand = new Command(() =>
            {          
                ImportView import = new ImportView();
                import.DataContext = new ImportViewModel(MediaFileWatcher.Instance);
                import.ShowDialog();          
            });

            ExportSelectedItemsCommand = new Command(() =>
            {
                ImportView export = new ImportView();
                export.DataContext = new ExportViewModel(MediaFileWatcher.Instance);
                export.ShowDialog();
              
            });

            ExpandCommand = new Command<MediaFileItem>((item) =>
            {              
                if (item == null)
                {                   
                    if (SelectedItems.Count == 0) return;

                    item = SelectedItems.ElementAt(0) as MediaFileItem;
                }

                if (item.Metadata is ImageMetadata)
                {
                    navigateToImageView(item);
                }
                else if (item.Metadata is VideoMetadata ||
                    item.Metadata is AudioMetadata)
                {
                    navigateToVideoView(item);
                }
             
                
            });

            ContractCommand = new Command(() =>
                {
                    NavigateBackCommand.Execute(null);
                   
                });

            ContractCommand.IsExecutable = false;

            NavigateToGeotagFileBrowserCommand = new Command(() =>
                {
                    navigateToGeotagFileBrowser();
                   
                });

            CreateImageCollageCommand = new Command(() =>
            {
                if (SelectedItems.Count == 0) return;

                ImageCollageView collage = new ImageCollageView();

                collage.ViewModel.Media = SelectedItems;
                collage.ShowDialog();
            });

            TranscodeVideoCommand = new Command(() =>
            {
                if (SelectedItems.Count == 0) return;

                VideoTranscodeView transcode = new VideoTranscodeView();
                List<VideoAudioPair> items = new List<VideoAudioPair>();
                foreach (MediaItem item in SelectedItems)
                {
                    items.Add(new VideoAudioPair(item));
                }

                transcode.ViewModel.Items = items;
                transcode.ViewModel.OutputPath = MediaFileWatcher.Path;

                transcode.ShowDialog();
            });

            TranscodeImageCommand = new Command(() =>
            {
                if (SelectedItems.Count == 0) return;

                ImageTranscodeView transcode = new ImageTranscodeView();
                transcode.ViewModel.Items = SelectedItems;
                transcode.ViewModel.OutputPath = MediaFileWatcher.Path;

                transcode.ShowDialog();
            });

            CreateVideoPreviewImagesCommand = new Command(() =>
                {                 
                    if (SelectedItems.Count == 0) return;

                    VideoPreviewImageView preview = new VideoPreviewImageView();
                    
                    preview.ViewModel.Media = SelectedItems;
                    preview.ShowDialog();
                });
      
            CreateTorrentFileCommand = new Command(() =>
                {
               
                    //if (SelectedItems.Count == 0) return;

                    try
                    {
                        TorrentCreationView torrent = new TorrentCreationView();

                        torrent.ViewModel.PathRoot = mediaFileWatcher.Path;
                        torrent.ViewModel.Media = new ObservableCollection<MediaFileItem>(SelectedItems);
                        
                        torrent.ShowDialog();
                    }
                    catch (Exception e)
                    {
                        MessageBox.Show(e.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                });
  
            
           
            NavigateToMediaFileGridCommand = new Command(navigateToMediaFileGrid);
            NavigateToImageViewCommand = new Command<MediaFileItem>(navigateToImageView);
            NavigateToVideoViewCommand = new Command<MediaFileItem>(navigateToVideoView);

            NavigateBackCommand = NavigateToMediaFileGridCommand;

            SelectedItems = new List<MediaFileItem>();

            EventAggregator.GetEvent<MediaSelectionEvent>().Subscribe(mediaFileBrowser_MediaSelectionEvent);
            
        }