/// <summary> /// Gets the user data. /// </summary> /// <param name="user">The user.</param> /// <param name="createIfNull">if set to <c>true</c> [create if null].</param> /// <returns>UserItemData.</returns> /// <exception cref="System.ArgumentNullException"></exception> public UserItemData GetUserData(User user, bool createIfNull) { if (user == null) { throw new ArgumentNullException(); } if (UserData == null) { if (!createIfNull) { return(null); } AddOrUpdateUserData(user, new UserItemData { UserId = user.Id }); } var data = UserData.FirstOrDefault(u => u.UserId == user.Id); if (data == null && createIfNull) { data = new UserItemData { UserId = user.Id }; AddOrUpdateUserData(user, data); } return(data); }
/// <summary> /// Adds the or update user data. /// </summary> /// <param name="user">The user.</param> /// <param name="data">The data.</param> /// <exception cref="System.ArgumentNullException"></exception> public void AddOrUpdateUserData(User user, UserItemData data) { if (user == null) { throw new ArgumentNullException(); } if (data == null) { throw new ArgumentNullException(); } data.UserId = user.Id; if (UserData == null) { UserData = new[] { data }; } else { var list = UserData.Where(u => u.UserId != user.Id).ToList(); list.Add(data); UserData = list; } }
private static bool Filter(BaseItem item, User user, UserItemsQuery query, IUserDataManager userDataManager) { if (query.MediaTypes.Length > 0 && !query.MediaTypes.Contains(item.MediaType ?? string.Empty, StringComparer.OrdinalIgnoreCase)) { return(false); } if (query.IsFolder.HasValue && query.IsFolder.Value != item.IsFolder) { return(false); } if (query.Filter != null && !query.Filter(item, user)) { return(false); } UserItemData userData = null; if (query.IsFavorite.HasValue) { userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey()); if (userData.IsFavorite != query.IsFavorite.Value) { return(false); } } if (query.IsResumable.HasValue) { userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey()); var isResumable = userData.PlaybackPositionTicks > 0; if (isResumable != query.IsResumable.Value) { return(false); } } if (query.IsPlayed.HasValue) { if (item.IsPlayed(user) != query.IsPlayed.Value) { return(false); } } return(true); }
public async Task SaveUserData(Guid userId, IHasUserData item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken) { if (userData == null) { throw new ArgumentNullException("userData"); } if (item == null) { throw new ArgumentNullException("item"); } if (userId == Guid.Empty) { throw new ArgumentNullException("userId"); } cancellationToken.ThrowIfCancellationRequested(); var keys = item.GetUserDataKeys(); foreach (var key in keys) { try { await Repository.SaveUserData(userId, key, userData, cancellationToken).ConfigureAwait(false); var newValue = userData; lock (_userData) { _userData[GetCacheKey(userId, key)] = newValue; } } catch (Exception ex) { _logger.ErrorException("Error saving user data", ex); throw; } } EventHelper.FireEventIfNotNull(UserDataSaved, this, new UserDataSaveEventArgs { Keys = keys, UserData = userData, SaveReason = reason, UserId = userId, Item = item }, _logger); }
public override async Task FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user) { if (!SupportsUserDataFromChildren) { return; } var unplayedQueryResult = await GetItems(new InternalItemsQuery(user) { Recursive = true, IsFolder = false, IsVirtualItem = false, EnableTotalRecordCount = true, Limit = 0, IsPlayed = false }).ConfigureAwait(false); var allItemsQueryResult = await GetItems(new InternalItemsQuery(user) { Recursive = true, IsFolder = false, IsVirtualItem = false, EnableTotalRecordCount = true, Limit = 0 }).ConfigureAwait(false); if (itemDto != null) { itemDto.RecursiveItemCount = allItemsQueryResult.TotalRecordCount; } var recursiveItemCount = allItemsQueryResult.TotalRecordCount; double unplayedCount = unplayedQueryResult.TotalRecordCount; if (recursiveItemCount > 0) { var unplayedPercentage = (unplayedCount / recursiveItemCount) * 100; dto.PlayedPercentage = 100 - unplayedPercentage; dto.Played = dto.PlayedPercentage.Value >= 100; dto.UnplayedItemCount = unplayedQueryResult.TotalRecordCount; } if (itemDto != null) { if (this is Season || this is MusicAlbum) { itemDto.ChildCount = recursiveItemCount; } } }
public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user, List <ItemFields> fields) { if (!SupportsUserDataFromChildren) { return; } if (itemDto != null) { if (fields.Contains(ItemFields.RecursiveItemCount)) { itemDto.RecursiveItemCount = GetRecursiveChildCount(user); } } if (SupportsPlayedStatus) { var unplayedQueryResult = GetItems(new InternalItemsQuery(user) { Recursive = true, IsFolder = false, IsVirtualItem = false, EnableTotalRecordCount = true, Limit = 0, IsPlayed = false, DtoOptions = new DtoOptions(false) { EnableImages = false } }); double unplayedCount = unplayedQueryResult.TotalRecordCount; dto.UnplayedItemCount = unplayedQueryResult.TotalRecordCount; if (itemDto != null && itemDto.RecursiveItemCount.HasValue) { if (itemDto.RecursiveItemCount.Value > 0) { var unplayedPercentage = (unplayedCount / itemDto.RecursiveItemCount.Value) * 100; dto.PlayedPercentage = 100 - unplayedPercentage; dto.Played = dto.PlayedPercentage.Value >= 100; } } else { dto.Played = (dto.UnplayedItemCount ?? 0) == 0; } } }
/// <summary> /// Saves the user data. /// </summary> /// <param name="userId">The user id.</param> /// <param name="key">The key.</param> /// <param name="userData">The user data.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> /// <exception cref="System.ArgumentNullException">userData /// or /// cancellationToken /// or /// userId /// or /// userDataId</exception> public Task SaveUserData(Guid userId, string key, UserItemData userData, CancellationToken cancellationToken) { if (userData == null) { throw new ArgumentNullException("userData"); } if (userId == Guid.Empty) { throw new ArgumentNullException("userId"); } if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException("key"); } return PersistUserData(userId, key, userData, cancellationToken); }
/// <summary> /// Saves the user data. /// </summary> /// <param name="userId">The user id.</param> /// <param name="item">The item.</param> /// <param name="userData">The user data.</param> /// <param name="reason">The reason.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> /// <exception cref="System.ArgumentNullException">userData /// or /// cancellationToken /// or /// userId /// or /// key</exception> public async Task SaveUserData(Guid userId, BaseItem item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken) { if (userData == null) { throw new ArgumentNullException("userData"); } if (item == null) { throw new ArgumentNullException("item"); } if (userId == Guid.Empty) { throw new ArgumentNullException("userId"); } cancellationToken.ThrowIfCancellationRequested(); var key = item.GetUserDataKey(); try { await Repository.SaveUserData(userId, key, userData, cancellationToken).ConfigureAwait(false); var newValue = userData; // Once it succeeds, put it into the dictionary to make it available to everyone else _userData.AddOrUpdate(GetCacheKey(userId, key), newValue, delegate { return newValue; }); } catch (Exception ex) { _logger.ErrorException("Error saving user data", ex); throw; } EventHelper.FireEventIfNotNull(UserDataSaved, this, new UserDataSaveEventArgs { Key = key, UserData = userData, SaveReason = reason, UserId = userId, Item = item }, _logger); }
public async Task SaveUserData(Guid userId, IHasUserData item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken) { if (userData == null) { throw new ArgumentNullException("userData"); } if (item == null) { throw new ArgumentNullException("item"); } if (userId == Guid.Empty) { throw new ArgumentNullException("userId"); } cancellationToken.ThrowIfCancellationRequested(); var keys = item.GetUserDataKeys(); foreach (var key in keys) { await Repository.SaveUserData(userId, key, userData, cancellationToken).ConfigureAwait(false); } var cacheKey = GetCacheKey(userId, item.Id); _userData.AddOrUpdate(cacheKey, userData, (k, v) => userData); EventHelper.FireEventIfNotNull(UserDataSaved, this, new UserDataSaveEventArgs { Keys = keys, UserData = userData, SaveReason = reason, UserId = userId, Item = item }, _logger); }
/// <summary> /// Persists the user data. /// </summary> /// <param name="userId">The user id.</param> /// <param name="key">The key.</param> /// <param name="userData">The user data.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> public async Task PersistUserData(Guid userId, string key, UserItemData userData, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); IDbTransaction transaction = null; try { transaction = _connection.BeginTransaction(); using (var cmd = _connection.CreateCommand()) { cmd.CommandText = "replace into userdata (key, userId, rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate) values (@key, @userId, @rating,@played,@playCount,@isFavorite,@playbackPositionTicks,@lastPlayedDate)"; cmd.Parameters.Add(cmd, "@key", DbType.String).Value = key; cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; cmd.Parameters.Add(cmd, "@rating", DbType.Double).Value = userData.Rating; cmd.Parameters.Add(cmd, "@played", DbType.Boolean).Value = userData.Played; cmd.Parameters.Add(cmd, "@playCount", DbType.Int32).Value = userData.PlayCount; cmd.Parameters.Add(cmd, "@isFavorite", DbType.Boolean).Value = userData.IsFavorite; cmd.Parameters.Add(cmd, "@playbackPositionTicks", DbType.Int64).Value = userData.PlaybackPositionTicks; cmd.Parameters.Add(cmd, "@lastPlayedDate", DbType.DateTime).Value = userData.LastPlayedDate; cmd.Transaction = transaction; cmd.ExecuteNonQuery(); } transaction.Commit(); } catch (OperationCanceledException) { if (transaction != null) { transaction.Rollback(); } throw; } catch (Exception e) { _logger.ErrorException("Failed to save user data:", e); if (transaction != null) { transaction.Rollback(); } throw; } finally { if (transaction != null) { transaction.Dispose(); } _writeLock.Release(); } }
/// <summary> /// Converts a UserItemData to a DTOUserItemData /// </summary> /// <param name="data">The data.</param> /// <returns>DtoUserItemData.</returns> /// <exception cref="System.ArgumentNullException"></exception> public static UserItemDataDto GetUserItemDataDto(UserItemData data) { if (data == null) { throw new ArgumentNullException("data"); } return new UserItemDataDto { IsFavorite = data.IsFavorite, Likes = data.Likes, PlaybackPositionTicks = data.PlaybackPositionTicks, PlayCount = data.PlayCount, Rating = data.Rating, Played = data.Played, LastPlayedDate = data.LastPlayedDate }; }
private void SetDefaultAudioStreamIndex(MediaSourceInfo source, UserItemData userData, User user, bool allowRememberingSelection) { if (userData.AudioStreamIndex.HasValue && user.Configuration.RememberAudioSelections && allowRememberingSelection) { var index = userData.AudioStreamIndex.Value; // Make sure the saved index is still valid if (source.MediaStreams.Any(i => i.Type == MediaStreamType.Audio && i.Index == index)) { source.DefaultAudioStreamIndex = index; return; } } var preferredAudio = string.IsNullOrEmpty(user.Configuration.AudioLanguagePreference) ? new string[] { } : new[] { user.Configuration.AudioLanguagePreference }; source.DefaultAudioStreamIndex = MediaStreamSelector.GetDefaultAudioStreamIndex(source.MediaStreams, preferredAudio, user.Configuration.PlayDefaultAudioTrack); }
private void SetDefaultSubtitleStreamIndex(MediaSourceInfo source, UserItemData userData, User user, bool allowRememberingSelection) { if (userData.SubtitleStreamIndex.HasValue && user.Configuration.RememberSubtitleSelections && user.Configuration.SubtitleMode != SubtitlePlaybackMode.None && allowRememberingSelection) { var index = userData.SubtitleStreamIndex.Value; // Make sure the saved index is still valid if (index == -1 || source.MediaStreams.Any(i => i.Type == MediaStreamType.Subtitle && i.Index == index)) { source.DefaultSubtitleStreamIndex = index; return; } } var preferredSubs = string.IsNullOrEmpty(user.Configuration.SubtitleLanguagePreference) ? new List<string>() : new List<string> { user.Configuration.SubtitleLanguagePreference }; var defaultAudioIndex = source.DefaultAudioStreamIndex; var audioLangage = defaultAudioIndex == null ? null : source.MediaStreams.Where(i => i.Type == MediaStreamType.Audio && i.Index == defaultAudioIndex).Select(i => i.Language).FirstOrDefault(); source.DefaultSubtitleStreamIndex = MediaStreamSelector.GetDefaultSubtitleStreamIndex(source.MediaStreams, preferredSubs, user.Configuration.SubtitleMode, audioLangage); MediaStreamSelector.SetSubtitleStreamScores(source.MediaStreams, preferredSubs, user.Configuration.SubtitleMode, audioLangage); }
public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user) { // Nothing meaninful here and will only waste resources }
/// <summary> /// Persists the user data. /// </summary> /// <param name="userId">The user id.</param> /// <param name="key">The key.</param> /// <param name="userData">The user data.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> public async Task PersistUserData(Guid userId, string key, UserItemData userData, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var serialized = _jsonSerializer.SerializeToBytes(userData); cancellationToken.ThrowIfCancellationRequested(); await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); SQLiteTransaction transaction = null; try { transaction = Connection.BeginTransaction(); using (var cmd = Connection.CreateCommand()) { cmd.CommandText = "replace into userdata (key, userId, data) values (@1, @2, @3)"; cmd.AddParam("@1", key); cmd.AddParam("@2", userId); cmd.AddParam("@3", serialized); cmd.Transaction = transaction; await cmd.ExecuteNonQueryAsync(cancellationToken); } transaction.Commit(); } catch (OperationCanceledException) { if (transaction != null) { transaction.Rollback(); } throw; } catch (Exception e) { Logger.ErrorException("Failed to save user data:", e); if (transaction != null) { transaction.Rollback(); } throw; } finally { if (transaction != null) { transaction.Dispose(); } _writeLock.Release(); } }
/// <summary> /// Saves the user data. /// </summary> /// <param name="userId">The user id.</param> /// <param name="key">The key.</param> /// <param name="userData">The user data.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> /// <exception cref="System.ArgumentNullException">userData /// or /// cancellationToken /// or /// userId /// or /// userDataId</exception> public async Task SaveUserData(Guid userId, string key, UserItemData userData, CancellationToken cancellationToken) { if (userData == null) { throw new ArgumentNullException("userData"); } if (cancellationToken == null) { throw new ArgumentNullException("cancellationToken"); } if (userId == Guid.Empty) { throw new ArgumentNullException("userId"); } if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException("key"); } cancellationToken.ThrowIfCancellationRequested(); try { await PersistUserData(userId, key, userData, cancellationToken).ConfigureAwait(false); var newValue = Task.FromResult(userData); // Once it succeeds, put it into the dictionary to make it available to everyone else _userData.AddOrUpdate(GetInternalKey(userId, key), newValue, delegate { return newValue; }); } catch (Exception ex) { Logger.ErrorException("Error saving user data", ex); throw; } }
/// <summary> /// Read a row from the specified reader into the provided userData object /// </summary> /// <param name="reader"></param> private UserItemData ReadRow(IDataReader reader) { var userData = new UserItemData(); userData.Key = reader.GetString(0); userData.UserId = reader.GetGuid(1); if (!reader.IsDBNull(2)) { userData.Rating = reader.GetDouble(2); } userData.Played = reader.GetBoolean(3); userData.PlayCount = reader.GetInt32(4); userData.IsFavorite = reader.GetBoolean(5); userData.PlaybackPositionTicks = reader.GetInt64(6); if (!reader.IsDBNull(7)) { userData.LastPlayedDate = reader.GetDateTime(7).ToUniversalTime(); } return userData; }
/// <summary> /// Gets the user data. /// </summary> /// <param name="userId">The user id.</param> /// <param name="key">The key.</param> /// <returns>Task{UserItemData}.</returns> /// <exception cref="System.ArgumentNullException"> /// userId /// or /// key /// </exception> public UserItemData GetUserData(Guid userId, string key) { if (userId == Guid.Empty) { throw new ArgumentNullException("userId"); } if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException("key"); } using (var cmd = _connection.CreateCommand()) { cmd.CommandText = "select rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate from userdata where key = @key and userId=@userId"; cmd.Parameters.Add(cmd, "@key", DbType.String).Value = key; cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; var userData = new UserItemData { UserId = userId, Key = key }; using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) { if (reader.Read()) { if (!reader.IsDBNull(0)) { userData.Rating = reader.GetDouble(0); } userData.Played = reader.GetBoolean(1); userData.PlayCount = reader.GetInt32(2); userData.IsFavorite = reader.GetBoolean(3); userData.PlaybackPositionTicks = reader.GetInt64(4); if (!reader.IsDBNull(5)) { userData.LastPlayedDate = reader.GetDateTime(5); } } } return userData; } }
public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user) { var recursiveItemCount = 0; var unplayed = 0; double totalPercentPlayed = 0; IEnumerable <BaseItem> children; var folder = this; var season = folder as Season; if (season != null) { children = season.GetEpisodes(user).Where(i => i.LocationType != LocationType.Virtual); } else { children = folder.GetRecursiveChildren(user, i => !i.IsFolder && i.LocationType != LocationType.Virtual); } // Loop through each recursive child foreach (var child in children) { recursiveItemCount++; var isUnplayed = true; var itemUserData = UserDataManager.GetUserData(user.Id, child.GetUserDataKey()); // Incrememt totalPercentPlayed if (itemUserData != null) { if (itemUserData.Played) { totalPercentPlayed += 100; isUnplayed = false; } else if (itemUserData.PlaybackPositionTicks > 0 && child.RunTimeTicks.HasValue && child.RunTimeTicks.Value > 0) { double itemPercent = itemUserData.PlaybackPositionTicks; itemPercent /= child.RunTimeTicks.Value; totalPercentPlayed += itemPercent; } } if (isUnplayed) { unplayed++; } } dto.UnplayedItemCount = unplayed; if (recursiveItemCount > 0) { dto.PlayedPercentage = totalPercentPlayed / recursiveItemCount; dto.Played = dto.PlayedPercentage.Value >= 100; } }
public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user) { if (!SupportsUserDataFromChildren) { return; } var recursiveItemCount = 0; var unplayed = 0; double totalPercentPlayed = 0; var itemsResult = GetItems(new InternalItemsQuery(user) { Recursive = true, IsFolder = false, ExcludeLocationTypes = new[] { LocationType.Virtual } }).Result; var children = itemsResult.Items; // Loop through each recursive child foreach (var child in children) { recursiveItemCount++; var isUnplayed = true; var itemUserData = UserDataManager.GetUserData(user, child); // Incrememt totalPercentPlayed if (itemUserData != null) { if (itemUserData.Played) { totalPercentPlayed += 100; isUnplayed = false; } else if (itemUserData.PlaybackPositionTicks > 0 && child.RunTimeTicks.HasValue && child.RunTimeTicks.Value > 0) { double itemPercent = itemUserData.PlaybackPositionTicks; itemPercent /= child.RunTimeTicks.Value; totalPercentPlayed += itemPercent; } } if (isUnplayed) { unplayed++; } } dto.UnplayedItemCount = unplayed; if (recursiveItemCount > 0) { dto.PlayedPercentage = totalPercentPlayed / recursiveItemCount; dto.Played = dto.PlayedPercentage.Value >= 100; } }
/// <summary> /// Persists the user data. /// </summary> /// <param name="userData">The user data.</param> /// <param name="database">The database.</param> /// <param name="transaction">The transaction.</param> private static void PersistUserData(UserItemData userData, IDbConnection database, IDbTransaction transaction) { using (var cmd = database.CreateCommand()) { cmd.CommandText = "replace into userdata (key, userId, rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate) values (@key, @userId, @rating,@played,@playCount,@isFavorite,@playbackPositionTicks,@lastPlayedDate)"; cmd.Parameters.Add(cmd, "@key", DbType.String).Value = userData.Key; cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userData.UserId; cmd.Parameters.Add(cmd, "@rating", DbType.Double).Value = userData.Rating; cmd.Parameters.Add(cmd, "@played", DbType.Boolean).Value = userData.Played; cmd.Parameters.Add(cmd, "@playCount", DbType.Int32).Value = userData.PlayCount; cmd.Parameters.Add(cmd, "@isFavorite", DbType.Boolean).Value = userData.IsFavorite; cmd.Parameters.Add(cmd, "@playbackPositionTicks", DbType.Int64).Value = userData.PlaybackPositionTicks; cmd.Parameters.Add(cmd, "@lastPlayedDate", DbType.DateTime).Value = userData.LastPlayedDate; cmd.Transaction = transaction; cmd.ExecuteNonQuery(); } }
public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user) { var recursiveItemCount = 0; var unplayed = 0; double totalPercentPlayed = 0; IEnumerable<BaseItem> children; var folder = this; var season = folder as Season; if (season != null) { children = season.GetEpisodes(user).Where(i => i.LocationType != LocationType.Virtual); } else { children = folder.GetRecursiveChildren(user) .Where(i => !i.IsFolder && i.LocationType != LocationType.Virtual); } // Loop through each recursive child foreach (var child in children) { recursiveItemCount++; var isUnplayed = true; var itemUserData = UserDataManager.GetUserData(user.Id, child.GetUserDataKey()); // Incrememt totalPercentPlayed if (itemUserData != null) { if (itemUserData.Played) { totalPercentPlayed += 100; isUnplayed = false; } else if (itemUserData.PlaybackPositionTicks > 0 && child.RunTimeTicks.HasValue && child.RunTimeTicks.Value > 0) { double itemPercent = itemUserData.PlaybackPositionTicks; itemPercent /= child.RunTimeTicks.Value; totalPercentPlayed += itemPercent; } } if (isUnplayed) { unplayed++; } } dto.UnplayedItemCount = unplayed; if (recursiveItemCount > 0) { dto.PlayedPercentage = totalPercentPlayed / recursiveItemCount; dto.Played = dto.PlayedPercentage.Value >= 100; } }
/// <summary> /// Updates playstate position for an item but does not save /// </summary> /// <param name="item">The item</param> /// <param name="data">User data for the item</param> /// <param name="positionTicks">The current playback position</param> private void UpdatePlayState(BaseItem item, UserItemData data, long positionTicks) { var hasRuntime = item.RunTimeTicks.HasValue && item.RunTimeTicks > 0; // If a position has been reported, and if we know the duration if (positionTicks > 0 && hasRuntime) { var pctIn = Decimal.Divide(positionTicks, item.RunTimeTicks.Value) * 100; // Don't track in very beginning if (pctIn < _configurationManager.Configuration.MinResumePct) { positionTicks = 0; } // If we're at the end, assume completed else if (pctIn > _configurationManager.Configuration.MaxResumePct || positionTicks >= item.RunTimeTicks.Value) { positionTicks = 0; data.Played = true; } else { // Enforce MinResumeDuration var durationSeconds = TimeSpan.FromTicks(item.RunTimeTicks.Value).TotalSeconds; if (durationSeconds < _configurationManager.Configuration.MinResumeDurationSeconds) { positionTicks = 0; data.Played = true; } } } else if (!hasRuntime) { // If we don't know the runtime we'll just have to assume it was fully played data.Played = true; positionTicks = 0; } if (item is Audio) { positionTicks = 0; } data.PlaybackPositionTicks = positionTicks; }
/// <summary> /// Gets the user data. /// </summary> /// <param name="userId">The user id.</param> /// <param name="key">The key.</param> /// <returns>Task{UserItemData}.</returns> public UserItemData GetUserData(Guid userId, string key) { if (userId == Guid.Empty) { throw new ArgumentNullException("userId"); } if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException("key"); } lock (_userData) { var cacheKey = GetCacheKey(userId, key); UserItemData value; if (_userData.TryGetValue(cacheKey, out value)) { return value; } value = Repository.GetUserData(userId, key); if (value == null) { value = new UserItemData { UserId = userId, Key = key }; } _userData[cacheKey] = value; return value; } }
public static bool Filter(BaseItem item, User user, InternalItemsQuery query, IUserDataManager userDataManager, ILibraryManager libraryManager) { if (query.MediaTypes.Length > 0 && !query.MediaTypes.Contains(item.MediaType ?? string.Empty, StringComparer.OrdinalIgnoreCase)) { return(false); } if (query.IncludeItemTypes.Length > 0 && !query.IncludeItemTypes.Contains(item.GetClientTypeName(), StringComparer.OrdinalIgnoreCase)) { return(false); } if (query.ExcludeItemTypes.Length > 0 && query.ExcludeItemTypes.Contains(item.GetClientTypeName(), StringComparer.OrdinalIgnoreCase)) { return(false); } if (query.IsVirtualItem.HasValue && item.IsVirtualItem != query.IsVirtualItem.Value) { return(false); } if (query.IsFolder.HasValue && query.IsFolder.Value != item.IsFolder) { return(false); } UserItemData userData = null; if (query.IsLiked.HasValue) { userData = userData ?? userDataManager.GetUserData(user, item); if (!userData.Likes.HasValue || userData.Likes != query.IsLiked.Value) { return(false); } } if (query.IsFavoriteOrLiked.HasValue) { userData = userData ?? userDataManager.GetUserData(user, item); var isFavoriteOrLiked = userData.IsFavorite || (userData.Likes ?? false); if (isFavoriteOrLiked != query.IsFavoriteOrLiked.Value) { return(false); } } if (query.IsFavorite.HasValue) { userData = userData ?? userDataManager.GetUserData(user, item); if (userData.IsFavorite != query.IsFavorite.Value) { return(false); } } if (query.IsResumable.HasValue) { userData = userData ?? userDataManager.GetUserData(user, item); var isResumable = userData.PlaybackPositionTicks > 0; if (isResumable != query.IsResumable.Value) { return(false); } } if (query.IsPlayed.HasValue) { if (item.IsPlayed(user) != query.IsPlayed.Value) { return(false); } } // Filter by Video3DFormat if (query.Is3D.HasValue) { var val = query.Is3D.Value; var video = item as Video; if (video == null || val != video.Video3DFormat.HasValue) { return(false); } } /* * f**k - fix this * if (query.IsHD.HasValue) * { * if (item.IsHD != query.IsHD.Value) * { * return false; * } * } */ if (query.IsLocked.HasValue) { var val = query.IsLocked.Value; if (item.IsLocked != val) { return(false); } } if (query.HasOverview.HasValue) { var filterValue = query.HasOverview.Value; var hasValue = !string.IsNullOrEmpty(item.Overview); if (hasValue != filterValue) { return(false); } } if (query.HasImdbId.HasValue) { var filterValue = query.HasImdbId.Value; var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.Imdb)); if (hasValue != filterValue) { return(false); } } if (query.HasTmdbId.HasValue) { var filterValue = query.HasTmdbId.Value; var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.Tmdb)); if (hasValue != filterValue) { return(false); } } if (query.HasTvdbId.HasValue) { var filterValue = query.HasTvdbId.Value; var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.Tvdb)); if (hasValue != filterValue) { return(false); } } if (query.HasOfficialRating.HasValue) { var filterValue = query.HasOfficialRating.Value; var hasValue = !string.IsNullOrEmpty(item.OfficialRating); if (hasValue != filterValue) { return(false); } } if (query.IsPlaceHolder.HasValue) { var filterValue = query.IsPlaceHolder.Value; var isPlaceHolder = false; var hasPlaceHolder = item as ISupportsPlaceHolders; if (hasPlaceHolder != null) { isPlaceHolder = hasPlaceHolder.IsPlaceHolder; } if (isPlaceHolder != filterValue) { return(false); } } if (query.HasSpecialFeature.HasValue) { var filterValue = query.HasSpecialFeature.Value; var movie = item as IHasSpecialFeatures; if (movie != null) { var ok = filterValue ? movie.SpecialFeatureIds.Length > 0 : movie.SpecialFeatureIds.Length == 0; if (!ok) { return(false); } } else { return(false); } } if (query.HasSubtitles.HasValue) { var val = query.HasSubtitles.Value; var video = item as Video; if (video == null || val != video.HasSubtitles) { return(false); } } if (query.HasParentalRating.HasValue) { var val = query.HasParentalRating.Value; var rating = item.CustomRating; if (string.IsNullOrEmpty(rating)) { rating = item.OfficialRating; } if (val) { if (string.IsNullOrEmpty(rating)) { return(false); } } else { if (!string.IsNullOrEmpty(rating)) { return(false); } } } if (query.HasTrailer.HasValue) { var val = query.HasTrailer.Value; var trailerCount = 0; var hasTrailers = item as IHasTrailers; if (hasTrailers != null) { trailerCount = hasTrailers.GetTrailerIds().Count; } var ok = val ? trailerCount > 0 : trailerCount == 0; if (!ok) { return(false); } } if (query.HasThemeSong.HasValue) { var filterValue = query.HasThemeSong.Value; var themeCount = item.ThemeSongIds.Length; var ok = filterValue ? themeCount > 0 : themeCount == 0; if (!ok) { return(false); } } if (query.HasThemeVideo.HasValue) { var filterValue = query.HasThemeVideo.Value; var themeCount = item.ThemeVideoIds.Length; var ok = filterValue ? themeCount > 0 : themeCount == 0; if (!ok) { return(false); } } // Apply genre filter if (query.Genres.Length > 0 && !query.Genres.Any(v => item.Genres.Contains(v, StringComparer.OrdinalIgnoreCase))) { return(false); } // Filter by VideoType if (query.VideoTypes.Length > 0) { var video = item as Video; if (video == null || !query.VideoTypes.Contains(video.VideoType)) { return(false); } } if (query.ImageTypes.Length > 0 && !query.ImageTypes.Any(item.HasImage)) { return(false); } // Apply studio filter if (query.StudioIds.Length > 0 && !query.StudioIds.Any(id => { var studioItem = libraryManager.GetItemById(id); return(studioItem != null && item.Studios.Contains(studioItem.Name, StringComparer.OrdinalIgnoreCase)); })) { return(false); } // Apply genre filter if (query.GenreIds.Length > 0 && !query.GenreIds.Any(id => { var genreItem = libraryManager.GetItemById(id); return(genreItem != null && item.Genres.Contains(genreItem.Name, StringComparer.OrdinalIgnoreCase)); })) { return(false); } // Apply year filter if (query.Years.Length > 0) { if (!(item.ProductionYear.HasValue && query.Years.Contains(item.ProductionYear.Value))) { return(false); } } // Apply official rating filter if (query.OfficialRatings.Length > 0 && !query.OfficialRatings.Contains(item.OfficialRating ?? string.Empty)) { return(false); } if (query.ItemIds.Length > 0) { if (!query.ItemIds.Contains(item.Id)) { return(false); } } // Apply tag filter var tags = query.Tags; if (tags.Length > 0) { if (!tags.Any(v => item.Tags.Contains(v, StringComparer.OrdinalIgnoreCase))) { return(false); } } if (query.MinPlayers.HasValue) { var filterValue = query.MinPlayers.Value; var game = item as Game; if (game != null) { var players = game.PlayersSupported ?? 1; var ok = players >= filterValue; if (!ok) { return(false); } } else { return(false); } } if (query.MaxPlayers.HasValue) { var filterValue = query.MaxPlayers.Value; var game = item as Game; if (game != null) { var players = game.PlayersSupported ?? 1; var ok = players <= filterValue; if (!ok) { return(false); } } else { return(false); } } if (query.MinCommunityRating.HasValue) { var val = query.MinCommunityRating.Value; if (!(item.CommunityRating.HasValue && item.CommunityRating >= val)) { return(false); } } if (query.MinCriticRating.HasValue) { var val = query.MinCriticRating.Value; if (!(item.CriticRating.HasValue && item.CriticRating >= val)) { return(false); } } if (query.MinIndexNumber.HasValue) { var val = query.MinIndexNumber.Value; if (!(item.IndexNumber.HasValue && item.IndexNumber.Value >= val)) { return(false); } } if (query.MinPremiereDate.HasValue) { var val = query.MinPremiereDate.Value; if (!(item.PremiereDate.HasValue && item.PremiereDate.Value >= val)) { return(false); } } if (query.MaxPremiereDate.HasValue) { var val = query.MaxPremiereDate.Value; if (!(item.PremiereDate.HasValue && item.PremiereDate.Value <= val)) { return(false); } } if (query.ParentIndexNumber.HasValue) { var filterValue = query.ParentIndexNumber.Value; if (item.ParentIndexNumber.HasValue && item.ParentIndexNumber.Value != filterValue) { return(false); } } if (query.SeriesStatuses.Length > 0) { var ok = new[] { item }.OfType <Series>().Any(p => p.Status.HasValue && query.SeriesStatuses.Contains(p.Status.Value)); if (!ok) { return(false); } } if (query.AiredDuringSeason.HasValue) { var episode = item as Episode; if (episode == null) { return(false); } if (!Series.FilterEpisodesBySeason(new[] { episode }, query.AiredDuringSeason.Value, true).Any()) { return(false); } } return(true); }
public UserItemData GetUserData(Guid userId, List<string> keys) { if (userId == Guid.Empty) { throw new ArgumentNullException("userId"); } if (keys == null) { throw new ArgumentNullException("keys"); } lock (_userData) { foreach (var key in keys) { var cacheKey = GetCacheKey(userId, key); UserItemData value; if (_userData.TryGetValue(cacheKey, out value)) { return value; } value = Repository.GetUserData(userId, key); if (value != null) { _userData[cacheKey] = value; return value; } } if (keys.Count > 0) { var key = keys[0]; var cacheKey = GetCacheKey(userId, key); var userdata = new UserItemData { UserId = userId, Key = key }; _userData[cacheKey] = userdata; return userdata; } return null; } }