/// <summary>
 /// Returns whether specified video matches specified conditions.
 /// </summary>
 /// <param name="video">The video to evaluate.</param>
 /// <param name="settings">An object containing various search settings.</param>
 /// <returns>True if video matches conditions, otherwise false.</returns>
 public static bool VideoMatchesConditions(Media video, SearchSettings settings) {
     return false;
     //using (Entities context = new Entities()) {
     //    Media Result = SelectVideo(context.Media.Where(v => v.MediaId == video.MediaId), settings);
     //    return (Result != null);
     //}
 }
        public Media ConvertToMedia(List<MediaCategory> mediaCategories, List<RatingCategory> ratingCategories) {
            Media Result = new Media();
            Result.MediaId = MediaId != Guid.Empty ? MediaId : Guid.NewGuid();
            Result.EditedOn = EditedOn ?? DateTime.Now;
            Result.MediaType = MediaType;
            Result.Artist = Artist ?? string.Empty;
            Result.Album = Album ?? string.Empty;
            Result.Title = Title;
            if (!string.IsNullOrEmpty(Category)) {
                MediaCategory ItemCategory = mediaCategories.FirstOrDefault(v => v.Name == Category && v.MediaTypeId == (int)MediaType);
                if (ItemCategory != null)
                    Result.MediaCategoryId = ItemCategory.MediaCategoryId;
            }
            Result.Preference = Preference;
            Result.Length = Length;
            Result.StartPos = StartPos;
            Result.EndPos = EndPos;
            Result.DownloadName = DownloadName ?? string.Empty;
            Result.DownloadUrl = DownloadUrl ?? string.Empty;
            Result.BuyUrl = BuyUrl ?? string.Empty;

            MediaRating NewRating;
            foreach (SyncRating item in Ratings) {
                NewRating = new MediaRating();
                NewRating.MediaId = Result.MediaId;
                NewRating.RatingId = ratingCategories.FirstOrDefault(r => r.Name == item.Name).RatingId;
                NewRating.Height = (item.Height != -1 ? (double?)item.Height : null);
                NewRating.Depth = (item.Depth != -1 ? (double?)item.Depth : null);
                Result.MediaRatings.Add(NewRating);
            }

            return Result;
        }
        private async void Window_Loaded(object sender, RoutedEventArgs e) {
            if (videoId != null) {
                video = business.GetVideoById(videoId.Value);
                if (video.MediaId == Guid.Empty)
                    throw new InvalidDataException("This Media information has an invalid empty GUID.");
            } else {
                video = business.GetVideoByFileName(fileName);
                if (video == null) {
                    video = business.NewVideo();
                    video.FileName = fileName;
                    video.MediaTypeId = (int)EditVideoBusiness.GetFileType(fileName);
                    video.DownloadName = System.IO.Path.GetFileNameWithoutExtension(fileName);
                    isNew = true;
                }
            }

            this.DataContext = video;
            CategoryCombo.ItemsSource = business.GetCategories(video.MediaTypeId);
            Custom1Combo.ItemsSource = business.GetCustomRatingCategories();
            Custom2Combo.ItemsSource = Custom1Combo.ItemsSource;
            ratingBusiness = business.GetRatings(video);
            RatingsGrid.DataContext = ratingBusiness;
            EditRating_LostFocus(null, null);
            if (player == null)
                PlayButton.Visibility = System.Windows.Visibility.Hidden;
            if (video.FileName != null && !File.Exists(Settings.NaturalGroundingFolder + video.FileName)) {
                fileNotFound = true;
                ErrorText.Text = "File not found.";
            }

            if (!isPopup && MediaInfoReader.HasMissingInfo(video))
                await LoadMediaInfoAsync();
        }
        /// <summary>
        /// Inserts specified media into the database, or updates an existing entry.
        /// </summary>
        /// <param name="item">The media item to merge into the database.</param>
        /// <param name="context">The database context.</param>
        public static void InsertOrMerge(Media item, Entities context) {
            // Try to find matching element already within the database.
            List<Media> DbMatch = (from m in context.Media
                                         where m.MediaId == item.MediaId || (m.Artist == item.Artist && m.Title == item.Title)
                                         select m).ToList();
            Media DbItem;
            if (DbMatch.Count > 1) // If both matches happen simultaneously, Artist/Title must take priority to avoid creating duplicate.
                DbItem = DbMatch.Single(m => m.Artist == item.Artist && m.Title == item.Title);
            else
                DbItem = DbMatch.FirstOrDefault();

            // If merging, delete existing entry and we'll create a new one and merge the fields.
            if (DbItem != null)
                context.Media.Remove(DbItem);

            // Insert new data.
            context.Media.Add(item);

            // Merge fields.
            if (DbItem != null) {
                item.FileName = DbItem.FileName;
                item.MediaId = DbItem.MediaId; // If matching by Artist/Title, we keep the same ID to avoid creating duplicate ID.
            }

            // Commit changes.
            context.SaveChanges();
        }
 /// <summary>
 /// Moves specified video to specified location.
 /// </summary>
 /// <param name="item">The video to move.</param>
 /// <param name="destination">The destination to move the file to.</param>
 /// <returns>True if the move was successful, otherwise False.</returns>
 public bool MoveFile(Media item, string destination) {
     MoveFileItem FileInfo = new MoveFileItem() {
         VideoId = item.MediaId,
         FileName = item.FileName,
         NewFileName = destination
     };
     return MoveFile(FileInfo, false);
 }
 public bool IsTitleDuplicate(Media video) {
     bool IsDuplicate = (from v in context.Media
                         where v.MediaId != video.MediaId &&
                             v.MediaTypeId == video.MediaTypeId &&
                             (video.Artist == null || v.Artist == video.Artist) &&
                             (video.Title == null || v.Title == video.Title)
                         select v.MediaId).Any();
     return IsDuplicate;
 }
 public async Task OpenMediaAsync(Media item) {
     this.Item = item;
     TitleText.Text = Item.Title;
     TitleText.ToolTip = Item.Title;
     PositionText.Text = "";
     playerBusiness = new WmpPlayerBusiness(Player);
     playerBusiness.PositionChanged += playerBusiness_PositionChanged;
     playerBusiness.Show();
     await playerBusiness.PlayVideoAsync(Item, false);
 }
 /// <summary>
 /// Applies 432hz auto-pitch if file PixelAspectRatio is 1 and FPS can be read.
 /// </summary>
 /// <param name="video">The video for which to create the auto-pitch script file.</param>
 /// <returns>Whether auto-pitch is enabled for this video.</returns>
 public static bool AppyAutoPitch(Media video) {
     using (MediaInfoReader InfoReader = new MediaInfoReader()) {
         InfoReader.LoadInfo(Settings.NaturalGroundingFolder + video.FileName);
         if (Settings.SavedFile.ChangeAudioPitch && InfoReader.PixelAspectRatio == 1 && !video.DisablePitch && (InfoReader.BitDepth ?? 8) == 8) {
             CreateScript(Settings.NaturalGroundingFolder + video.FileName, InfoReader);
             return true;
         } else
             return false;
     }
 }
 public DownloadItem(Media request, string destination, string title, int queuePos, bool upgradeAudio, EventHandler<DownloadCompletedEventArgs> callback) {
     this.Status = DownloadStatus.Waiting;
     this.Request = request;
     this.Destination = destination;
     this.Title = title;
     this.Status = DownloadStatus.Waiting;
     UpdateProgress();
     this.QueuePos = queuePos;
     this.UpgradeAudio = upgradeAudio;
     this.Callback = callback;
     this.Files = new List<FileProgress>();
 }
        public async Task OpenMediaAsync(Media item) {
            this.Item = item;

            TitleText.Text = Item.Title;
            TitleText.ToolTip = Item.Title;
            PositionText.Text = "";
            playerWindow = WmpPlayerWindow.Instance();
            playerBusiness = new WmpPlayerBusiness(playerWindow.Player);
            playerBusiness.AllowClose = true;
            playerBusiness.Closed += playerBusiness_Closed;
            playerBusiness.PositionChanged += playerBusiness_PositionChanged;
            playerBusiness.Show();
            await playerBusiness.PlayVideoAsync(Item);
        }
        public void OpenMedia(Media item) {
            this.Item = item;

            BitmapImage NewImage = new BitmapImage();
            NewImage.BeginInit();
            NewImage.UriSource = new Uri(Settings.NaturalGroundingFolder + item.FileName);
            NewImage.EndInit();
            Image NewImageControl = new Image();
            NewImageControl.Source = NewImage;

            TitleText.Text = Item.Title;
            TitleText.ToolTip = Item.Title;

            viewer = ImageViewerWindow.Instance(NewImageControl);
            viewer.Closed += viewer_Closed;
        }
        public SyncMedia(Media source) {
            MediaId = source.MediaId;
            EditedOn = source.EditedOn;
            MediaType = (MediaType)source.MediaTypeId;
            Artist = source.Artist;
            Album = source.Album;
            Title = source.Title;
            if (source.MediaCategoryId.HasValue)
                Category = source.MediaCategory.Name;
            Preference = source.Preference;
            Length = source.Length;
            StartPos = source.StartPos;
            EndPos = source.EndPos;
            DownloadName = source.DownloadName;
            DownloadUrl = source.DownloadUrl;
            BuyUrl = source.BuyUrl;

            Ratings = new List<SyncRating>();
            foreach (MediaRating item in source.MediaRatings) {
                Ratings.Add(new SyncRating(item.RatingCategory.Name, item.Height, item.Depth));
            }
        }
        /// <summary>
        /// Return a random video from the database matching specified conditions.
        /// </summary>
        /// <param name="data">The list of videos in which to search; generally Entities.Media.</param>
        /// <param name="settings">An object containing various search settings.</param>
        /// <param name="count">The quantity of results to return.</param>
        /// <param name="maintainCurrent">If specified, the currently selected video will be kept.</param>
        /// <returns>The randomly selected video, or null if no matches are found.</returns>
        public static List<Media> SelectVideo(IQueryable<Media> data, SearchSettings settings, int count, Media maintainCurrent) {
            if (settings == null)
                settings = new SearchSettings();
            if (settings.ExcludeVideos == null)
                settings.ExcludeVideos = new List<Guid>();

            // Exclude currently selected video so that it doesn't get randomly re-reselected.
            if (maintainCurrent != null) {
                settings.ExcludeVideos = new List<Guid>(settings.ExcludeVideos);
                settings.ExcludeVideos.Add(maintainCurrent.MediaId);
                count--;
            }

            var Query = (from v in data
                         where (settings.AllowDownloading || v.FileName != null) &&
                         (v.FileName != null || v.DownloadUrl != "") &&
                         (v.Length == null || ((v.EndPos != null ? v.EndPos.Value : v.Length.Value) - (v.StartPos != null ? v.StartPos.Value : 0)) <= 12 * 60) && // Don't get videos longer than 12 minutes
                         !settings.ExcludeVideos.Contains(v.MediaId) // Don't repeat same videos
                         select v);

            // Apply search filters.
            Query = SearchVideoAccess.ApplySearchFilters(Query, settings, null);

            // Return random result
            int TotalFound = 0;
            List<Guid> ResultId = SelectRandomId(Query, count, out TotalFound);
            List<Media> Result = new List<Media>();
            if (maintainCurrent != null)
                Result.Add(maintainCurrent);
            settings.TotalFound = TotalFound;
            if (TotalFound > 0 && ResultId.Count() > 0) {
                if (TotalFound <= count)
                    Result.AddRange(Query.Take(count).ToList());
                else
                    Result.AddRange(data.Where(v => ResultId.Contains(v.MediaId)).ToList());
            }
            return Result;
        }
        public void OpenMedia(Media item) {
            this.Item = item;

            TitleText.Text = Item.Title;
            TitleText.ToolTip = Item.Title;

            player = new MediaElement();
            player.LoadedBehavior = MediaState.Manual;
            player.UnloadedBehavior = MediaState.Manual;
            player.MediaEnded += player_MediaEnded;
            player.IsMuted = true;
            player.Source = new Uri(Settings.NaturalGroundingFolder + Item.FileName);
            player.Position = TimeSpan.FromSeconds(Item.StartPos.HasValue ? Item.StartPos.Value : 0);
            player.Play();

            viewer = ImageViewerWindow.Instance(player);
            viewer.Closed += viewer_Closed;

            positionTimer = new DispatcherTimer();
            positionTimer.Interval = TimeSpan.FromSeconds(1);
            positionTimer.Tick += positionTimer_Tick;
            positionTimer.Start();
        }
        /// <summary>
        /// Downloads specified video from YouTube.
        /// </summary>
        /// <param name="video">The video to download.</param>
        /// <param name="queuePos">The position in the queue to auto-play, or -1.</param>
        /// <param name="upgradeAudio">If true, only the audio will be downloaded and it will be merged with the local video file.</param>
        /// <param name="callback">The method to call once download is completed.</param>
        public async Task DownloadVideoAsync(Media video, int queuePos, bool upgradeAudio, EventHandler<DownloadCompletedEventArgs> callback) {
            if (video == null || string.IsNullOrEmpty(video.DownloadUrl))
                throw new ArgumentException("Video object is null or doesn't contain a valid YouTube URL.");

            if (IsDownloadDuplicate(video))
                return;

            // Store in the Temp folder.
            DefaultMediaPath PathCalc = new DefaultMediaPath(Settings.TempFilesPath.Substring(Settings.NaturalGroundingFolder.Length));
            string Destination = Settings.NaturalGroundingFolder + PathCalc.GetDefaultFileName(video.Artist, video.Title, null, (MediaType)video.MediaTypeId);
            string DownloadDesc = Path.GetFileName(Destination);
            Directory.CreateDirectory(Settings.TempFilesPath);

            // Add DownloadItem right away before doing any async work.
            DownloadItem DownloadInfo = new DownloadItem(video, Destination, DownloadDesc, queuePos, upgradeAudio, callback);
            Application.Current.Dispatcher.Invoke(() => downloadsList.Insert(0, DownloadInfo));

            // Notify UI of new download to show window.
            if (DownloadAdded != null)
                DownloadAdded(this, new EventArgs());

            if (downloadsList.Where(d => d.Status == DownloadStatus.Downloading || d.Status == DownloadStatus.Initializing).Count() < Settings.SimultaneousDownloads)
                await StartDownloadAsync(DownloadInfo).ConfigureAwait(false);
        }
 /// <summary>
 /// Saves updated preference field.
 /// </summary>
 /// <param name="video">The media object to update.</param>
 public void UpdatePreference(Media item) {
     if (item.MediaId != Guid.Empty) {
         using (var context = new Entities()) {
             Media Item = context.Media.Where(v => v.MediaId == item.MediaId).Single();
             Item.Preference = item.Preference;
             Item.IsCustomPreference = (item.Preference.HasValue);
             context.SaveChanges();
         }
     }
 }
 public void Delete(Media video) {
     context.Media.Remove(video);
     context.SaveChanges();
 }
 public Media NewVideo() {
     Media Result = new Media();
     Result.MediaId = Guid.NewGuid();
     context.Media.Add(Result);
     return Result;
 }
 public void AddVideo(Media video) {
     video.MediaId = Guid.NewGuid();
     context.Media.Add(video);
 }
 private async Task PlayVideo(Media video) {
     await Player.PlayVideoAsync(video);
     await Task.Delay(500);
     this.Activate();
 }
 public EditRatingsBusiness GetRatings(Media video) {
     return new EditRatingsBusiness(video, context);
 }
 /// <summary>
 /// Return a random video from the database matching specified conditions.
 /// </summary>
 /// <param name="playedVideos">The list of videos already played.</param>
 /// <param name="settings">An object containing various search settings.</param>
 /// <param name="count">The quantity of results to return.</param>
 /// <param name="maintainCurrent">If specified, the currently selected video will be kept.</param>
 /// <returns>The randomly selected video, or null if no matches are found.</returns>
 public static List<Media> SelectVideo(SearchSettings settings, int count, Media maintainCurrent) {
     using (Entities context = new Entities()) {
         // context.Database.Log = Console.Write;
         return SelectVideo(context.Media.Include("MediaRatings.RatingCategory"), settings, count, maintainCurrent);
     }
 }
        /// <summary>
        /// Plays the next video.
        /// </summary>
        private async Task PlayNextVideoAsync() {
            if (nextVideo == null)
                return;

            // Enable/Disable SVP if necessary.
            MpcConfigBusiness.AutoConfigure(nextVideo);

            // If next video is still downloading, advance QueuePos. If QueuePos = 0 when download finishes, it will auto-play.
            DownloadItem VideoDownload = GetNextVideoDownloading();
            if (VideoDownload != null) {
                if (VideoDownload.QueuePos > 0)
                    VideoDownload.QueuePos--;
                return;
            }

            await player.PlayVideoAsync(nextVideo);
            playedVideos.Add(nextVideo.MediaId);
            nextVideo = null;

            if (PlayMode == PlayerMode.SpecialRequest)
                PlayMode = PlayerMode.Normal;

            if (playMode != PlayerMode.Manual)
                await SelectNextVideoAsync(1);

            if (PlayMode == PlayerMode.Fire)
                PlayMode = PlayerMode.SpecialRequest;

            if (PlaylistChanged != null)
                PlaylistChanged(this, new EventArgs());
        }
 /// <summary>
 /// Occurs when download is completed.
 /// </summary>
 private async void Download_Complete(object sender, DownloadCompletedEventArgs args) {
     if (args.DownloadInfo.IsCompleted && (args.DownloadInfo.QueuePos == 0 || player.CurrentVideo == null) && !player.AllowClose) {
         nextVideo = args.DownloadInfo.Request;
         player_PlayNext(null, null);
     } else if (args.DownloadInfo.IsCanceled && args.DownloadInfo.QueuePos > -1 && playMode != PlayerMode.Manual) {
         nextVideo = null;
         await SelectNextVideoAsync(args.DownloadInfo.QueuePos);
     }
 }
        /// <summary>
        /// Selects which video will be played next.
        /// </summary>
        /// <param name="queuePos">The video position to select. 0 for current, 1 for next.</param>
        /// <param name="attempts">The number of attemps already made, to avoid infinite loop.</param>
        /// <returns>Whether the file is downloading.</returns>
        private async Task<bool> SelectNextVideoAsync(int queuePos, int attempts) {
            bool IsDownloading = false;
            if (attempts > 3) {
                nextVideo = null;
                return false;
            }

            timerChangeConditions.Stop();

            // Get video conditions
            GetConditionsEventArgs e = new GetConditionsEventArgs(FilterSettings);
            e.QueuePos = queuePos;
            if (GetConditions != null)
                GetConditions(this, e);

            // Select random video matching conditions.
            Media Result = PlayerAccess.SelectVideo(FilterSettings.Update(playedVideos, Settings.SavedFile.AutoDownload));
            lastSearchResultCount = FilterSettings.TotalFound;

            // If no video is found, try again while increasing tolerance
            if (Result == null) {
                e = new GetConditionsEventArgs(FilterSettings);
                e.IncreaseTolerance = true;
                if (GetConditions != null)
                    GetConditions(this, e);
                Result = PlayerAccess.SelectVideo(FilterSettings.Update(null, Settings.SavedFile.AutoDownload));
                FilterSettings.TotalFound = lastSearchResultCount;
            }

            if (Result != null) {
                if (nextVideo != null)
                    CancelNextDownload(nextVideo);
                nextVideo = Result;
                IsDownloading = await PrepareNextVideoAsync(queuePos, attempts);
            }

            timerChangeConditions.Stop();
            if (PlaylistChanged != null)
                PlaylistChanged(this, new EventArgs());

            return IsDownloading;
        }
        public async Task ReplayLastAsync() {
            if (!player.IsAvailable)
                return;

            if (playedVideos.Count > 1) {
                Media LastVideo = PlayerAccess.GetVideoById(playedVideos[playedVideos.Count - 2]);
                if (LastVideo.MediaId != player.CurrentVideo.MediaId) {
                    playedVideos.RemoveAt(playedVideos.Count - 1);
                    if (nextVideo != null)
                        CancelNextDownload(nextVideo);
                    nextVideo = player.CurrentVideo;

                    // Enable/Disable SVP if necessary.
                    MpcConfigBusiness.AutoConfigure(nextVideo);

                    await player.PlayVideoAsync(LastVideo);
                    if (PlaylistChanged != null)
                        PlaylistChanged(this, new EventArgs());
                }
            }
        }
 public EditRatingsBusiness(Media video, Entities context) {
     this.context = context;
     this.video = video;
     if (video.MediaId != null && video.MediaId != Guid.Empty)
         DisplayData();
 }
 public EditRatingsBusiness(Media video, double ratio) {
     this.video = video;
     this.Ratio = ratio;
     DisplayData();
 }
 public string GetVideoDisplayTitle(Media video) {
     if (video == null)
         return "None";
     else if (video.Artist.Length == 0)
         return video.Title;
     else
         return string.Format("{0} - {1}", video.Artist, video.Title);
 }
 private async void EditForm_Closed(Media result) {
     if (result != null) {
         VideoListItem OldItem = (VideoListItem)VideosView.SelectedItem;
         // business.RefreshPlaylist(result, OldItem != null ? OldItem.FileName : null);
         await LoadDataAsync();
     }
 }