Merge branch 'dev' into beta

This commit is contained in:
Luke Pulverenti 2016-05-02 01:53:09 -04:00
commit ffff503e9b
81 changed files with 904 additions and 683 deletions

View File

@ -197,12 +197,7 @@ namespace MediaBrowser.Api.Movies
var parentIds = new string[] { };
var list = _libraryManager.GetItemList(query, parentIds)
.Where(i =>
{
// Strip out secondary versions
var v = i as Video;
return v != null && !v.PrimaryVersionId.HasValue;
})
.DistinctBy(i => i.PresentationUniqueKey, StringComparer.OrdinalIgnoreCase)
.DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N"))
.ToList();
@ -247,7 +242,7 @@ namespace MediaBrowser.Api.Movies
var recentlyPlayedMovies = allMoviesForCategories
.Select(i =>
{
var userdata = _userDataRepository.GetUserData(user.Id, i.GetUserDataKey());
var userdata = _userDataRepository.GetUserData(user, i);
return new Tuple<BaseItem, bool, DateTime>(i, userdata.Played, userdata.LastPlayedDate ?? DateTime.MinValue);
})
.Where(i => i.Item2)
@ -260,7 +255,7 @@ namespace MediaBrowser.Api.Movies
.Select(i =>
{
var score = 0;
var userData = _userDataRepository.GetUserData(user.Id, i.GetUserDataKey());
var userData = _userDataRepository.GetUserData(user, i);
if (userData.IsFavorite)
{

View File

@ -274,7 +274,7 @@ namespace MediaBrowser.Api.UserLibrary
{
items = items.Where(i =>
{
var userdata = UserDataRepository.GetUserData(user.Id, i.GetUserDataKey());
var userdata = UserDataRepository.GetUserData(user, i);
return userdata != null && userdata.Likes.HasValue && !userdata.Likes.Value;
});
@ -284,7 +284,7 @@ namespace MediaBrowser.Api.UserLibrary
{
items = items.Where(i =>
{
var userdata = UserDataRepository.GetUserData(user.Id, i.GetUserDataKey());
var userdata = UserDataRepository.GetUserData(user, i);
return userdata != null && userdata.Likes.HasValue && userdata.Likes.Value;
});
@ -294,7 +294,7 @@ namespace MediaBrowser.Api.UserLibrary
{
items = items.Where(i =>
{
var userdata = UserDataRepository.GetUserData(user.Id, i.GetUserDataKey());
var userdata = UserDataRepository.GetUserData(user, i);
var likes = userdata.Likes ?? false;
var favorite = userdata.IsFavorite;
@ -307,7 +307,7 @@ namespace MediaBrowser.Api.UserLibrary
{
items = items.Where(i =>
{
var userdata = UserDataRepository.GetUserData(user.Id, i.GetUserDataKey());
var userdata = UserDataRepository.GetUserData(user, i);
return userdata != null && userdata.IsFavorite;
});

View File

@ -519,10 +519,8 @@ namespace MediaBrowser.Api.UserLibrary
var item = string.IsNullOrEmpty(itemId) ? user.RootFolder : _libraryManager.GetItemById(itemId);
var key = item.GetUserDataKey();
// Get the user data for this item
var data = _userDataRepository.GetUserData(user.Id, key);
var data = _userDataRepository.GetUserData(user, item);
// Set favorite status
data.IsFavorite = isFavorite;
@ -567,10 +565,8 @@ namespace MediaBrowser.Api.UserLibrary
var item = string.IsNullOrEmpty(itemId) ? user.RootFolder : _libraryManager.GetItemById(itemId);
var key = item.GetUserDataKey();
// Get the user data for this item
var data = _userDataRepository.GetUserData(user.Id, key);
var data = _userDataRepository.GetUserData(user, item);
data.Likes = likes;

View File

@ -130,6 +130,7 @@ namespace MediaBrowser.Api
var items = request.Ids.Split(',')
.Select(i => new Guid(i))
.Select(i => _libraryManager.GetItemById(i))
.OfType<Video>()
.ToList();
if (items.Count < 2)
@ -137,14 +138,7 @@ namespace MediaBrowser.Api
throw new ArgumentException("Please supply at least two videos to merge.");
}
if (items.Any(i => !(i is Video)))
{
throw new ArgumentException("Only videos can be grouped together.");
}
var videos = items.Cast<Video>().ToList();
var videosWithVersions = videos.Where(i => i.MediaSourceCount > 1)
var videosWithVersions = items.Where(i => i.MediaSourceCount > 1)
.ToList();
if (videosWithVersions.Count > 1)
@ -156,7 +150,7 @@ namespace MediaBrowser.Api
if (primaryVersion == null)
{
primaryVersion = videos.OrderBy(i =>
primaryVersion = items.OrderBy(i =>
{
if (i.Video3DFormat.HasValue)
{
@ -179,7 +173,7 @@ namespace MediaBrowser.Api
}).First();
}
foreach (var item in videos.Where(i => i.Id != primaryVersion.Id))
foreach (var item in items.Where(i => i.Id != primaryVersion.Id))
{
item.PrimaryVersionId = primaryVersion.Id;

View File

@ -26,7 +26,7 @@ namespace MediaBrowser.Controller.Entities.Audio
IArchivable
{
public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
public long? Size { get; set; }
public string Container { get; set; }
public int? TotalBitrate { get; set; }
@ -150,12 +150,10 @@ namespace MediaBrowser.Controller.Entities.Audio
+ (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name;
}
/// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
protected override string CreateUserDataKey()
public override List<string> GetUserDataKeys()
{
var list = base.GetUserDataKeys();
if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys)
{
var songKey = IndexNumber.HasValue ? IndexNumber.Value.ToString("0000") : string.Empty;
@ -165,7 +163,7 @@ namespace MediaBrowser.Controller.Entities.Audio
{
songKey = ParentIndexNumber.Value.ToString("0000") + "-" + songKey;
}
songKey+= Name;
songKey += Name;
if (!string.IsNullOrWhiteSpace(Album))
{
@ -178,25 +176,25 @@ namespace MediaBrowser.Controller.Entities.Audio
songKey = albumArtist + "-" + songKey;
}
return songKey;
list.Insert(0, songKey);
}
var parent = AlbumEntity;
if (parent != null)
else
{
var parentKey = parent.GetUserDataKey();
var parent = AlbumEntity;
if (IndexNumber.HasValue)
if (parent != null && IndexNumber.HasValue)
{
var songKey = (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("0000 - ") : "")
+ IndexNumber.Value.ToString("0000 - ");
list.InsertRange(0, parent.GetUserDataKeys().Select(i =>
{
var songKey = (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("0000 - ") : "")
+ IndexNumber.Value.ToString("0000 - ");
return parentKey + songKey;
return i + songKey;
}));
}
}
return base.CreateUserDataKey();
return list;
}
public override UnratedItem GetBlockUnratedType()

View File

@ -96,36 +96,34 @@ namespace MediaBrowser.Controller.Entities.Audio
public List<string> Artists { get; set; }
/// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
protected override string CreateUserDataKey()
public override List<string> GetUserDataKeys()
{
var id = this.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
if (!string.IsNullOrWhiteSpace(id))
{
return "MusicAlbum-MusicBrainzReleaseGroup-" + id;
}
id = this.GetProviderId(MetadataProviders.MusicBrainzAlbum);
if (!string.IsNullOrWhiteSpace(id))
{
return "MusicAlbum-Musicbrainz-" + id;
}
var list = base.GetUserDataKeys();
if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys)
{
var albumArtist = AlbumArtist;
if (!string.IsNullOrWhiteSpace(albumArtist))
{
return albumArtist + "-" + Name;
list.Insert(0, albumArtist + "-" + Name);
}
}
return base.CreateUserDataKey();
var id = this.GetProviderId(MetadataProviders.MusicBrainzAlbum);
if (!string.IsNullOrWhiteSpace(id))
{
list.Insert(0, "MusicAlbum-Musicbrainz-" + id);
}
id = this.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
if (!string.IsNullOrWhiteSpace(id))
{
list.Insert(0, "MusicAlbum-MusicBrainzReleaseGroup-" + id);
}
return list;
}
protected override bool GetBlockUnratedValue(UserPolicy config)

View File

@ -80,13 +80,12 @@ namespace MediaBrowser.Controller.Entities.Audio
ProductionLocations = new List<string>();
}
/// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
protected override string CreateUserDataKey()
public override List<string> GetUserDataKeys()
{
return GetUserDataKey(this);
var list = base.GetUserDataKeys();
list.InsertRange(0, GetUserDataKeys(this));
return list;
}
/// <summary>
@ -121,16 +120,18 @@ namespace MediaBrowser.Controller.Entities.Audio
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
private static string GetUserDataKey(MusicArtist item)
private static List<string> GetUserDataKeys(MusicArtist item)
{
var list = new List<string>();
var id = item.GetProviderId(MetadataProviders.MusicBrainzArtist);
if (!string.IsNullOrEmpty(id))
{
return "Artist-Musicbrainz-" + id;
list.Add("Artist-Musicbrainz-" + id);
}
return "Artist-" + item.Name;
list.Add("Artist-" + item.Name);
return list;
}
protected override bool GetBlockUnratedValue(UserPolicy config)

View File

@ -10,13 +10,12 @@ namespace MediaBrowser.Controller.Entities.Audio
/// </summary>
public class MusicGenre : BaseItem, IItemByName
{
/// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
protected override string CreateUserDataKey()
public override List<string> GetUserDataKeys()
{
return "MusicGenre-" + Name;
var list = base.GetUserDataKeys();
list.Insert(0, "MusicGenre-" + Name);
return list;
}
[IgnoreDataMember]

View File

@ -1149,6 +1149,12 @@ namespace MediaBrowser.Controller.Entities
get { return null; }
}
[IgnoreDataMember]
public virtual string PresentationUniqueKey
{
get { return Id.ToString("N"); }
}
private string _userDataKey;
/// <summary>
/// Gets the user data key.
@ -1158,7 +1164,7 @@ namespace MediaBrowser.Controller.Entities
{
if (string.IsNullOrWhiteSpace(_userDataKey))
{
var key = CreateUserDataKey();
var key = GetUserDataKeys().First();
_userDataKey = key;
return key;
}
@ -1166,16 +1172,20 @@ namespace MediaBrowser.Controller.Entities
return _userDataKey;
}
protected virtual string CreateUserDataKey()
public virtual List<string> GetUserDataKeys()
{
var list = new List<string>();
if (SourceType == SourceType.Channel)
{
if (!string.IsNullOrWhiteSpace(ExternalId))
{
return ExternalId;
list.Add(ExternalId);
}
}
return Id.ToString();
list.Add(Id.ToString());
return list;
}
internal virtual bool IsValidFromResolver(BaseItem newItem)
@ -1617,9 +1627,7 @@ namespace MediaBrowser.Controller.Entities
throw new ArgumentNullException();
}
var key = GetUserDataKey();
var data = UserDataManager.GetUserData(user.Id, key);
var data = UserDataManager.GetUserData(user, this);
if (datePlayed.HasValue)
{
@ -1654,9 +1662,7 @@ namespace MediaBrowser.Controller.Entities
throw new ArgumentNullException();
}
var key = GetUserDataKey();
var data = UserDataManager.GetUserData(user.Id, key);
var data = UserDataManager.GetUserData(user, this);
//I think it is okay to do this here.
// if this is only called when a user is manually forcing something to un-played
@ -1987,14 +1993,14 @@ namespace MediaBrowser.Controller.Entities
public virtual bool IsPlayed(User user)
{
var userdata = UserDataManager.GetUserData(user.Id, GetUserDataKey());
var userdata = UserDataManager.GetUserData(user, this);
return userdata != null && userdata.Played;
}
public bool IsFavoriteOrLiked(User user)
{
var userdata = UserDataManager.GetUserData(user.Id, GetUserDataKey());
var userdata = UserDataManager.GetUserData(user, this);
return userdata != null && (userdata.IsFavorite || (userdata.Likes ?? false));
}
@ -2006,7 +2012,7 @@ namespace MediaBrowser.Controller.Entities
throw new ArgumentNullException("user");
}
var userdata = UserDataManager.GetUserData(user.Id, GetUserDataKey());
var userdata = UserDataManager.GetUserData(user, this);
return userdata == null || !userdata.Played;
}

View File

@ -839,11 +839,6 @@ namespace MediaBrowser.Controller.Entities
Logger.Debug("Query requires post-filtering due to ItemSortBy.SeriesSortName");
return true;
}
if (query.SortBy.Contains(ItemSortBy.StartDate, StringComparer.OrdinalIgnoreCase))
{
Logger.Debug("Query requires post-filtering due to ItemSortBy.StartDate");
return true;
}
if (query.SortBy.Contains(ItemSortBy.Studio, StringComparer.OrdinalIgnoreCase))
{
Logger.Debug("Query requires post-filtering due to ItemSortBy.Studio");
@ -1059,30 +1054,6 @@ namespace MediaBrowser.Controller.Entities
return true;
}
if (!string.IsNullOrWhiteSpace(query.NameContains))
{
Logger.Debug("Query requires post-filtering due to NameContains");
return true;
}
if (!string.IsNullOrWhiteSpace(query.NameLessThan))
{
Logger.Debug("Query requires post-filtering due to NameLessThan");
return true;
}
if (!string.IsNullOrWhiteSpace(query.NameStartsWith))
{
Logger.Debug("Query requires post-filtering due to NameStartsWith");
return true;
}
if (!string.IsNullOrWhiteSpace(query.NameStartsWithOrGreater))
{
Logger.Debug("Query requires post-filtering due to NameStartsWithOrGreater");
return true;
}
if (query.AirDays.Length > 0)
{
Logger.Debug("Query requires post-filtering due to AirDays");
@ -1635,7 +1606,7 @@ namespace MediaBrowser.Controller.Entities
var isUnplayed = true;
var itemUserData = UserDataManager.GetUserData(user.Id, child.GetUserDataKey());
var itemUserData = UserDataManager.GetUserData(user, child);
// Incrememt totalPercentPlayed
if (itemUserData != null)

View File

@ -76,15 +76,16 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public List<string> MultiPartGameFiles { get; set; }
protected override string CreateUserDataKey()
public override List<string> GetUserDataKeys()
{
var list = base.GetUserDataKeys();
var id = this.GetProviderId(MetadataProviders.Gamesdb);
if (!string.IsNullOrEmpty(id))
{
return "Game-Gamesdb-" + id;
list.Insert(0, "Game-Gamesdb-" + id);
}
return base.CreateUserDataKey();
return list;
}
public override IEnumerable<string> GetDeletePaths()

View File

@ -7,13 +7,12 @@ namespace MediaBrowser.Controller.Entities
{
public class GameGenre : BaseItem, IItemByName
{
/// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
protected override string CreateUserDataKey()
public override List<string> GetUserDataKeys()
{
return "GameGenre-" + Name;
var list = base.GetUserDataKeys();
list.Insert(0, "GameGenre-" + Name);
return list;
}
/// <summary>

View File

@ -2,6 +2,7 @@
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using System;
using System.Collections.Generic;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Entities
@ -31,17 +32,15 @@ namespace MediaBrowser.Controller.Entities
/// <value>The game system.</value>
public string GameSystemName { get; set; }
/// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
protected override string CreateUserDataKey()
public override List<string> GetUserDataKeys()
{
var list = base.GetUserDataKeys();
if (!string.IsNullOrEmpty(GameSystemName))
{
return "GameSystem-" + GameSystemName;
list.Insert(0, "GameSystem-" + GameSystemName);
}
return base.CreateUserDataKey();
return list;
}
protected override bool GetBlockUnratedValue(UserPolicy config)

View File

@ -11,13 +11,12 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public class Genre : BaseItem, IItemByName
{
/// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
protected override string CreateUserDataKey()
public override List<string> GetUserDataKeys()
{
return "Genre-" + Name;
var list = base.GetUserDataKeys();
list.Insert(0, "Genre-" + Name);
return list;
}
/// <summary>

View File

@ -1,4 +1,5 @@
using MediaBrowser.Model.Dto;
using System.Collections.Generic;
using MediaBrowser.Model.Dto;
namespace MediaBrowser.Controller.Entities
{
@ -13,6 +14,8 @@ namespace MediaBrowser.Controller.Entities
/// <returns>System.String.</returns>
string GetUserDataKey();
List<string> GetUserDataKeys();
/// <summary>
/// Fills the user data dto values.
/// </summary>

View File

@ -46,6 +46,7 @@ namespace MediaBrowser.Controller.Entities
public string NameLessThan { get; set; }
public string NameContains { get; set; }
public string PresentationUniqueKey { get; set; }
public string Path { get; set; }
public string Person { get; set; }

View File

@ -75,34 +75,6 @@ namespace MediaBrowser.Controller.Entities.Movies
get { return TmdbCollectionName; }
set { TmdbCollectionName = value; }
}
/// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
protected override string CreateUserDataKey()
{
var key = GetMovieUserDataKey(this);
if (string.IsNullOrWhiteSpace(key))
{
key = base.CreateUserDataKey();
}
return key;
}
public static string GetMovieUserDataKey(BaseItem movie)
{
var key = movie.GetProviderId(MetadataProviders.Tmdb);
if (string.IsNullOrWhiteSpace(key))
{
key = movie.GetProviderId(MetadataProviders.Imdb);
}
return key;
}
protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
{

View File

@ -44,15 +44,6 @@ namespace MediaBrowser.Controller.Entities
}
}
/// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
protected override string CreateUserDataKey()
{
return this.GetProviderId(MetadataProviders.Tmdb) ?? this.GetProviderId(MetadataProviders.Imdb) ?? base.CreateUserDataKey();
}
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.Music;

View File

@ -18,13 +18,12 @@ namespace MediaBrowser.Controller.Entities
/// <value>The place of birth.</value>
public string PlaceOfBirth { get; set; }
/// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
protected override string CreateUserDataKey()
public override List<string> GetUserDataKeys()
{
return "Person-" + Name;
var list = base.GetUserDataKeys();
list.Insert(0, "Person-" + Name);
return list;
}
public PersonLookupInfo GetLookupInfo()

View File

@ -10,13 +10,12 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public class Studio : BaseItem, IItemByName, IHasTags
{
/// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
protected override string CreateUserDataKey()
public override List<string> GetUserDataKeys()
{
return "Studio-" + Name;
var list = base.GetUserDataKeys();
list.Insert(0, "Studio-" + Name);
return list;
}
/// <summary>

View File

@ -58,25 +58,7 @@ namespace MediaBrowser.Controller.Entities.TV
{
get
{
return AirsAfterSeasonNumber ?? AirsBeforeSeasonNumber ?? PhysicalSeasonNumber;
}
}
[IgnoreDataMember]
public int? PhysicalSeasonNumber
{
get
{
var value = ParentIndexNumber;
if (value.HasValue)
{
return value;
}
var season = Season;
return season != null ? season.IndexNumber : null;
return AirsAfterSeasonNumber ?? AirsBeforeSeasonNumber ?? ParentIndexNumber;
}
}
@ -98,20 +80,26 @@ namespace MediaBrowser.Controller.Entities.TV
}
}
/// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
protected override string CreateUserDataKey()
[IgnoreDataMember]
protected override bool EnableDefaultVideoUserDataKeys
{
var series = Series;
get
{
return false;
}
}
public override List<string> GetUserDataKeys()
{
var list = base.GetUserDataKeys();
var series = Series;
if (series != null && ParentIndexNumber.HasValue && IndexNumber.HasValue)
{
return series.GetUserDataKey() + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000");
list.InsertRange(0, series.GetUserDataKeys().Select(i => i + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000")));
}
return base.CreateUserDataKey();
return list;
}
/// <summary>
@ -310,6 +298,19 @@ namespace MediaBrowser.Controller.Entities.TV
Logger.ErrorException("Error in FillMissingEpisodeNumbersFromPath. Episode: {0}", ex, Path ?? Name ?? Id.ToString());
}
if (!ParentIndexNumber.HasValue)
{
var season = Season;
if (season != null)
{
if (season.ParentIndexNumber.HasValue)
{
ParentIndexNumber = season.ParentIndexNumber;
hasChanges = true;
}
}
}
return hasChanges;
}
}

View File

@ -53,19 +53,17 @@ namespace MediaBrowser.Controller.Entities.TV
};
}
/// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
protected override string CreateUserDataKey()
public override List<string> GetUserDataKeys()
{
if (Series != null)
var list = base.GetUserDataKeys();
var series = Series;
if (series != null)
{
var seasonNo = IndexNumber ?? 0;
return Series.GetUserDataKey() + seasonNo.ToString("000");
list.InsertRange(0, series.GetUserDataKeys().Select(i => i + (IndexNumber ?? 0).ToString("000")));
}
return base.CreateUserDataKey();
return list;
}
/// <summary>
@ -94,6 +92,24 @@ namespace MediaBrowser.Controller.Entities.TV
}
}
[IgnoreDataMember]
public override string PresentationUniqueKey
{
get
{
if (IndexNumber.HasValue)
{
var series = Series;
if (series != null)
{
return series.PresentationUniqueKey + "-" + (IndexNumber ?? 0).ToString("000");
}
}
return base.PresentationUniqueKey;
}
}
/// <summary>
/// Creates the name of the sort.
/// </summary>
@ -171,16 +187,16 @@ namespace MediaBrowser.Controller.Entities.TV
public IEnumerable<Episode> GetEpisodes(User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
{
var episodes = GetRecursiveChildren(user)
.OfType<Episode>();
var series = Series;
if (IndexNumber.HasValue && series != null)
{
return series.GetEpisodes(user, IndexNumber.Value, includeMissingEpisodes, includeVirtualUnairedEpisodes, episodes);
return series.GetEpisodes(user, IndexNumber.Value, includeMissingEpisodes, includeVirtualUnairedEpisodes);
}
var episodes = GetRecursiveChildren(user)
.OfType<Episode>();
if (series != null && series.ContainsEpisodesWithoutSeasonFolders)
{
var seasonNumber = IndexNumber;

View File

@ -91,25 +91,33 @@ namespace MediaBrowser.Controller.Entities.TV
}
}
[IgnoreDataMember]
public override string PresentationUniqueKey
{
get { return GetUserDataKeys().First(); }
}
/// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
protected override string CreateUserDataKey()
public override List<string> GetUserDataKeys()
{
var key = this.GetProviderId(MetadataProviders.Tvdb);
var list = base.GetUserDataKeys();
if (string.IsNullOrWhiteSpace(key))
var key = this.GetProviderId(MetadataProviders.Imdb);
if (!string.IsNullOrWhiteSpace(key))
{
key = this.GetProviderId(MetadataProviders.Imdb);
list.Insert(0, key);
}
if (string.IsNullOrWhiteSpace(key))
key = this.GetProviderId(MetadataProviders.Tvdb);
if (!string.IsNullOrWhiteSpace(key))
{
key = base.CreateUserDataKey();
list.Insert(0, key);
}
return key;
return list;
}
/// <summary>
@ -126,8 +134,8 @@ namespace MediaBrowser.Controller.Entities.TV
// Studio, Genre and Rating will all be the same so makes no sense to index by these
protected override IEnumerable<string> GetIndexByOptions()
{
return new List<string> {
{"None"},
return new List<string> {
{"None"},
{"Performer"},
{"Director"},
{"Year"},
@ -183,8 +191,28 @@ namespace MediaBrowser.Controller.Entities.TV
public IEnumerable<Season> GetSeasons(User user, bool includeMissingSeasons, bool includeVirtualUnaired)
{
var seasons = base.GetChildren(user, true)
.OfType<Season>();
var seriesIds = LibraryManager.GetItemIds(new InternalItemsQuery(user)
{
PresentationUniqueKey = PresentationUniqueKey,
IncludeItemTypes = new[] { typeof(Series).Name }
});
IEnumerable<Season> seasons;
if (seriesIds.Count > 1)
{
seasons = LibraryManager.GetItemList(new InternalItemsQuery(user)
{
AncestorIds = seriesIds.Select(i => i.ToString("N")).ToArray(),
IncludeItemTypes = new[] { typeof(Season).Name },
SortBy = new[] { ItemSortBy.SortName }
}).OfType<Season>();
}
else
{
seasons = base.GetChildren(user, true).OfType<Season>();
}
if (!includeMissingSeasons && !includeVirtualUnaired)
{
@ -202,9 +230,7 @@ namespace MediaBrowser.Controller.Entities.TV
}
}
return LibraryManager
.Sort(seasons, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending)
.Cast<Season>();
return seasons;
}
public IEnumerable<Episode> GetEpisodes(User user)
@ -280,9 +306,9 @@ namespace MediaBrowser.Controller.Entities.TV
if (episode != null
&& refreshOptions.MetadataRefreshMode != MetadataRefreshMode.FullRefresh
&& !refreshOptions.ReplaceAllMetadata
&& episode.IsMissingEpisode
&& episode.LocationType == Model.Entities.LocationType.Virtual
&& episode.PremiereDate.HasValue
&& episode.IsMissingEpisode
&& episode.LocationType == Model.Entities.LocationType.Virtual
&& episode.PremiereDate.HasValue
&& (DateTime.UtcNow - episode.PremiereDate.Value).TotalDays > 30)
{
skipItem = true;
@ -313,19 +339,32 @@ namespace MediaBrowser.Controller.Entities.TV
public IEnumerable<Episode> GetEpisodes(User user, int seasonNumber, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
{
return GetEpisodes(user, seasonNumber, includeMissingEpisodes, includeVirtualUnairedEpisodes,
new List<Episode>());
}
var seriesIds = LibraryManager.GetItemIds(new InternalItemsQuery(user)
{
PresentationUniqueKey = PresentationUniqueKey,
IncludeItemTypes = new[] { typeof(Series).Name }
});
internal IEnumerable<Episode> GetEpisodes(User user, int seasonNumber, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable<Episode> additionalEpisodes)
{
var episodes = GetRecursiveChildren(user, i => i is Episode)
.Cast<Episode>();
IEnumerable<Episode> episodes;
if (seriesIds.Count > 1)
{
episodes = LibraryManager.GetItemList(new InternalItemsQuery(user)
{
AncestorIds = seriesIds.Select(i => i.ToString("N")).ToArray(),
IncludeItemTypes = new[] { typeof(Episode).Name },
SortBy = new[] { ItemSortBy.SortName }
}).OfType<Episode>();
}
else
{
episodes = GetRecursiveChildren(user, i => i is Episode)
.Cast<Episode>();
}
episodes = FilterEpisodesBySeason(episodes, seasonNumber, DisplaySpecialsWithSeasons);
episodes = episodes.Concat(additionalEpisodes).Distinct();
if (!includeMissingEpisodes)
{
episodes = episodes.Where(i => !i.IsMissingEpisode);
@ -352,7 +391,7 @@ namespace MediaBrowser.Controller.Entities.TV
{
if (!includeSpecials || seasonNumber < 1)
{
return episodes.Where(i => (i.PhysicalSeasonNumber ?? -1) == seasonNumber);
return episodes.Where(i => (i.ParentIndexNumber ?? -1) == seasonNumber);
}
return episodes.Where(i =>

View File

@ -56,26 +56,6 @@ namespace MediaBrowser.Controller.Entities
/// <value>The revenue.</value>
public double? Revenue { get; set; }
protected override string CreateUserDataKey()
{
var key = Movie.GetMovieUserDataKey(this);
if (!string.IsNullOrWhiteSpace(key))
{
key = key + "-trailer";
// Make sure different trailers have their own data.
if (RunTimeTicks.HasValue)
{
key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture);
}
return key;
}
return base.CreateUserDataKey();
}
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.Trailer;

View File

@ -348,7 +348,7 @@ namespace MediaBrowser.Controller.Entities
.Where(i => !i.IsFolder)
.OfType<IHasAlbumArtist>();
var artists = _libraryManager.GetAlbumArtists(items).Where(i => _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).IsFavorite);
var artists = _libraryManager.GetAlbumArtists(items).Where(i => _userDataManager.GetUserData(user, i).IsFavorite);
return GetResult(artists, parent, query);
}
@ -1218,7 +1218,7 @@ namespace MediaBrowser.Controller.Entities
if (query.IsLiked.HasValue)
{
userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey());
userData = userData ?? userDataManager.GetUserData(user, item);
if (!userData.Likes.HasValue || userData.Likes != query.IsLiked.Value)
{
@ -1228,7 +1228,7 @@ namespace MediaBrowser.Controller.Entities
if (query.IsFavoriteOrLiked.HasValue)
{
userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey());
userData = userData ?? userDataManager.GetUserData(user, item);
var isFavoriteOrLiked = userData.IsFavorite || (userData.Likes ?? false);
if (isFavoriteOrLiked != query.IsFavoriteOrLiked.Value)
@ -1239,7 +1239,7 @@ namespace MediaBrowser.Controller.Entities
if (query.IsFavorite.HasValue)
{
userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey());
userData = userData ?? userDataManager.GetUserData(user, item);
if (userData.IsFavorite != query.IsFavorite.Value)
{
@ -1249,7 +1249,7 @@ namespace MediaBrowser.Controller.Entities
if (query.IsResumable.HasValue)
{
userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey());
userData = userData ?? userDataManager.GetUserData(user, item);
var isResumable = userData.PlaybackPositionTicks > 0;
if (isResumable != query.IsResumable.Value)

View File

@ -44,6 +44,20 @@ namespace MediaBrowser.Controller.Entities
}
}
[IgnoreDataMember]
public override string PresentationUniqueKey
{
get
{
if (PrimaryVersionId.HasValue)
{
return PrimaryVersionId.Value.ToString("N");
}
return base.PresentationUniqueKey;
}
}
public long? Size { get; set; }
public string Container { get; set; }
public int? TotalBitrate { get; set; }
@ -90,6 +104,14 @@ namespace MediaBrowser.Controller.Entities
{
get
{
if (PrimaryVersionId.HasValue)
{
var item = LibraryManager.GetItemById(PrimaryVersionId.Value) as Video;
if (item != null)
{
return item.MediaSourceCount;
}
}
return LinkedAlternateVersions.Count + LocalAlternateVersions.Count + 1;
}
}
@ -131,42 +153,65 @@ namespace MediaBrowser.Controller.Entities
return LocalAlternateVersions.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
}
protected override string CreateUserDataKey()
[IgnoreDataMember]
protected virtual bool EnableDefaultVideoUserDataKeys
{
if (ExtraType.HasValue)
get
{
var key = this.GetProviderId(MetadataProviders.Imdb) ?? this.GetProviderId(MetadataProviders.Tmdb);
return true;
}
}
if (!string.IsNullOrWhiteSpace(key))
public override List<string> GetUserDataKeys()
{
var list = base.GetUserDataKeys();
if (EnableDefaultVideoUserDataKeys)
{
if (ExtraType.HasValue)
{
key = key + "-" + ExtraType.ToString().ToLower();
// Make sure different trailers have their own data.
if (RunTimeTicks.HasValue)
var key = this.GetProviderId(MetadataProviders.Tmdb);
if (!string.IsNullOrWhiteSpace(key))
{
key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture);
list.Insert(0, GetUserDataKey(key));
}
return key;
key = this.GetProviderId(MetadataProviders.Imdb);
if (!string.IsNullOrWhiteSpace(key))
{
list.Insert(0, GetUserDataKey(key));
}
}
else
{
var key = this.GetProviderId(MetadataProviders.Imdb);
if (!string.IsNullOrWhiteSpace(key))
{
list.Insert(0, key);
}
key = this.GetProviderId(MetadataProviders.Tmdb);
if (!string.IsNullOrWhiteSpace(key))
{
list.Insert(0, key);
}
}
}
return base.CreateUserDataKey();
return list;
}
/// <summary>
/// Gets the linked children.
/// </summary>
/// <returns>IEnumerable{BaseItem}.</returns>
public IEnumerable<Video> GetAlternateVersions()
private string GetUserDataKey(string providerId)
{
var filesWithinSameDirectory = GetLocalAlternateVersionIds()
.Select(i => LibraryManager.GetItemById(i))
.Where(i => i != null)
.OfType<Video>();
var key = providerId + "-" + ExtraType.ToString().ToLower();
return filesWithinSameDirectory.Concat(GetLinkedAlternateVersions())
.OrderBy(i => i.SortName);
// Make sure different trailers have their own data.
if (RunTimeTicks.HasValue)
{
key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture);
}
return key;
}
public IEnumerable<Video> GetLinkedAlternateVersions()
@ -468,6 +513,36 @@ namespace MediaBrowser.Controller.Entities
}).FirstOrDefault();
}
private List<Tuple<Video, MediaSourceType>> GetAllVideosForMediaSources()
{
var list = new List<Tuple<Video, MediaSourceType>>();
list.Add(new Tuple<Video, MediaSourceType>(this, MediaSourceType.Default));
list.AddRange(GetLinkedAlternateVersions().Select(i => new Tuple<Video, MediaSourceType>(i, MediaSourceType.Grouping)));
if (PrimaryVersionId.HasValue)
{
var primary = LibraryManager.GetItemById(PrimaryVersionId.Value) as Video;
if (primary != null)
{
var existingIds = list.Select(i => i.Item1.Id).ToList();
list.Add(new Tuple<Video, MediaSourceType>(primary, MediaSourceType.Grouping));
list.AddRange(primary.GetLinkedAlternateVersions().Where(i => !existingIds.Contains(i.Id)).Select(i => new Tuple<Video, MediaSourceType>(i, MediaSourceType.Grouping)));
}
}
var localAlternates = list
.SelectMany(i => i.Item1.GetLocalAlternateVersionIds())
.Select(LibraryManager.GetItemById)
.Where(i => i != null)
.OfType<Video>()
.ToList();
list.AddRange(localAlternates.Select(i => new Tuple<Video, MediaSourceType>(i, MediaSourceType.Default)));
return list;
}
public virtual IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
{
if (SourceType == SourceType.Channel)
@ -486,13 +561,8 @@ namespace MediaBrowser.Controller.Entities
};
}
var item = this;
var result = item.GetAlternateVersions()
.Select(i => GetVersionInfo(enablePathSubstitution, i, MediaSourceType.Grouping))
.ToList();
result.Add(GetVersionInfo(enablePathSubstitution, item, MediaSourceType.Default));
var list = GetAllVideosForMediaSources();
var result = list.Select(i => GetVersionInfo(enablePathSubstitution, i.Item1, i.Item2)).ToList();
return result.OrderBy(i =>
{

View File

@ -11,13 +11,12 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public class Year : BaseItem, IItemByName
{
/// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
protected override string CreateUserDataKey()
public override List<string> GetUserDataKeys()
{
return "Year-" + Name;
var list = base.GetUserDataKeys();
list.Insert(0, "Year-" + Name);
return list;
}
/// <summary>

View File

@ -45,6 +45,11 @@ namespace MediaBrowser.Controller.Library
/// <returns>Task{UserItemData}.</returns>
UserItemData GetUserData(Guid userId, string key);
UserItemData GetUserData(IHasUserData user, IHasUserData item);
UserItemData GetUserData(string userId, IHasUserData item);
UserItemData GetUserData(Guid userId, IHasUserData item);
/// <summary>
/// Gets the user data dto.
/// </summary>

View File

@ -1,6 +1,7 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
namespace MediaBrowser.Controller.Library
{
@ -15,11 +16,7 @@ namespace MediaBrowser.Controller.Library
/// <value>The user id.</value>
public Guid UserId { get; set; }
/// <summary>
/// Gets or sets the key.
/// </summary>
/// <value>The key.</value>
public string Key { get; set; }
public List<string> Keys { get; set; }
/// <summary>
/// Gets or sets the save reason.

View File

@ -45,17 +45,6 @@ namespace MediaBrowser.Controller.LiveTv
set { }
}
/// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
protected override string CreateUserDataKey()
{
var name = GetClientTypeName();
return name + "-" + Name + (EpisodeTitle ?? string.Empty);
}
/// <summary>
/// Gets a value indicating whether this instance is owned item.
/// </summary>

View File

@ -11,13 +11,12 @@ namespace MediaBrowser.Controller.LiveTv
{
public class LiveTvChannel : BaseItem, IHasMediaSources
{
/// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
protected override string CreateUserDataKey()
public override List<string> GetUserDataKeys()
{
return GetClientTypeName() + "-" + Name;
var list = base.GetUserDataKeys();
list.Insert(0, GetClientTypeName() + "-" + Name);
return list;
}
public override UnratedItem GetBlockUnratedType()

View File

@ -4,36 +4,40 @@ using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.LiveTv;
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.LiveTv
{
public class LiveTvProgram : BaseItem, IHasLookupInfo<LiveTvProgramLookupInfo>, IHasStartDate, IHasProgramAttributes
{
/// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
protected override string CreateUserDataKey()
public override List<string> GetUserDataKeys()
{
if (IsMovie)
{
var key = Movie.GetMovieUserDataKey(this);
var list = base.GetUserDataKeys();
if (!IsSeries)
{
var key = this.GetProviderId(MetadataProviders.Imdb);
if (!string.IsNullOrWhiteSpace(key))
{
return key;
list.Insert(0, key);
}
key = this.GetProviderId(MetadataProviders.Tmdb);
if (!string.IsNullOrWhiteSpace(key))
{
list.Insert(0, key);
}
}
if (IsSeries && !string.IsNullOrWhiteSpace(EpisodeTitle))
else if (!string.IsNullOrWhiteSpace(EpisodeTitle))
{
var name = GetClientTypeName();
return name + "-" + Name + (EpisodeTitle ?? string.Empty);
list.Insert(0, name + "-" + Name + (EpisodeTitle ?? string.Empty));
}
return base.CreateUserDataKey();
return list;
}
[IgnoreDataMember]

View File

@ -45,32 +45,6 @@ namespace MediaBrowser.Controller.LiveTv
set { }
}
/// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
protected override string CreateUserDataKey()
{
if (IsMovie)
{
var key = Movie.GetMovieUserDataKey(this);
if (!string.IsNullOrWhiteSpace(key))
{
return key;
}
}
if (IsSeries && !string.IsNullOrWhiteSpace(EpisodeTitle))
{
var name = GetClientTypeName();
return name + "-" + Name + (EpisodeTitle ?? string.Empty);
}
return base.CreateUserDataKey();
}
[IgnoreDataMember]
public override string MediaType
{

View File

@ -19,12 +19,6 @@ namespace MediaBrowser.Controller.Notifications
/// Occurs when [notifications marked read].
/// </summary>
event EventHandler<NotificationReadEventArgs> NotificationsMarkedRead;
/// <summary>
/// Opens the connection to the repository
/// </summary>
/// <returns>Task.</returns>
Task Initialize();
/// <summary>
/// Gets the notifications.

View File

@ -11,12 +11,6 @@ namespace MediaBrowser.Controller.Persistence
/// </summary>
public interface IDisplayPreferencesRepository : IRepository
{
/// <summary>
/// Opens the connection to the repository
/// </summary>
/// <returns>Task.</returns>
Task Initialize();
/// <summary>
/// Saves display preferences for an item
/// </summary>

View File

@ -13,12 +13,6 @@ namespace MediaBrowser.Controller.Persistence
/// </summary>
public interface IItemRepository : IRepository
{
/// <summary>
/// Opens the connection to the repository
/// </summary>
/// <returns>Task.</returns>
Task Initialize();
/// <summary>
/// Saves an item
/// </summary>

View File

@ -11,12 +11,6 @@ namespace MediaBrowser.Controller.Persistence
/// </summary>
public interface IUserDataRepository : IRepository
{
/// <summary>
/// Opens the connection to the repository
/// </summary>
/// <returns>Task.</returns>
Task Initialize();
/// <summary>
/// Saves the user data.
/// </summary>

View File

@ -21,11 +21,5 @@ namespace MediaBrowser.Controller.Providers
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task SaveMetadataStatus(MetadataStatus status, CancellationToken cancellationToken);
/// <summary>
/// Initializes this instance.
/// </summary>
/// <returns>Task.</returns>
Task Initialize();
}
}

View File

@ -111,7 +111,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
var newbookmark = int.Parse(sparams["PosSecond"], _usCulture);
var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey());
var userdata = _userDataManager.GetUserData(user, item);
userdata.PlaybackPositionTicks = TimeSpan.FromSeconds(newbookmark).Ticks;

View File

@ -201,6 +201,7 @@ namespace MediaBrowser.Model.Configuration
public string[] Migrations { get; set; }
public int MigrationVersion { get; set; }
public int SchemaVersion { get; set; }
public bool DownloadImagesInAdvance { get; set; }

View File

@ -444,7 +444,11 @@ namespace MediaBrowser.Providers.MediaInfo
{
if (string.IsNullOrWhiteSpace(video.Name) || string.Equals(video.Name, Path.GetFileNameWithoutExtension(video.Path), StringComparison.OrdinalIgnoreCase))
{
video.Name = data.Name;
// Don't use the embedded name for extras because it will often be the same name as the movie
if (!video.ExtraType.HasValue && !video.IsOwnedItem)
{
video.Name = data.Name;
}
}
}

View File

@ -27,11 +27,11 @@ namespace MediaBrowser.Server.Implementations.Activity
_appPaths = appPaths;
}
public async Task Initialize()
public async Task Initialize(IDbConnector dbConnector)
{
var dbFile = Path.Combine(_appPaths.DataPath, "activitylog.db");
_connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false);
_connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {

View File

@ -133,7 +133,7 @@ namespace MediaBrowser.Server.Implementations.Channels
if (query.IsFavorite.HasValue)
{
var val = query.IsFavorite.Value;
channels = channels.Where(i => _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).IsFavorite == val)
channels = channels.Where(i => _userDataManager.GetUserData(user, i).IsFavorite == val)
.ToList();
}
@ -1437,7 +1437,7 @@ namespace MediaBrowser.Server.Implementations.Channels
case ItemFilter.IsFavoriteOrLikes:
return items.Where(item =>
{
var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey());
var userdata = _userDataManager.GetUserData(user, item);
if (userdata == null)
{
@ -1453,7 +1453,7 @@ namespace MediaBrowser.Server.Implementations.Channels
case ItemFilter.Likes:
return items.Where(item =>
{
var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey());
var userdata = _userDataManager.GetUserData(user, item);
return userdata != null && userdata.Likes.HasValue && userdata.Likes.Value;
});
@ -1461,7 +1461,7 @@ namespace MediaBrowser.Server.Implementations.Channels
case ItemFilter.Dislikes:
return items.Where(item =>
{
var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey());
var userdata = _userDataManager.GetUserData(user, item);
return userdata != null && userdata.Likes.HasValue && !userdata.Likes.Value;
});
@ -1469,7 +1469,7 @@ namespace MediaBrowser.Server.Implementations.Channels
case ItemFilter.IsFavorite:
return items.Where(item =>
{
var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey());
var userdata = _userDataManager.GetUserData(user, item);
return userdata != null && userdata.IsFavorite;
});
@ -1477,7 +1477,7 @@ namespace MediaBrowser.Server.Implementations.Channels
case ItemFilter.IsResumable:
return items.Where(item =>
{
var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey());
var userdata = _userDataManager.GetUserData(user, item);
return userdata != null && userdata.PlaybackPositionTicks > 0;
});

View File

@ -487,7 +487,7 @@ namespace MediaBrowser.Server.Implementations.Dto
{
if (item.IsFolder)
{
var userData = _userDataRepository.GetUserData(user.Id, item.GetUserDataKey());
var userData = _userDataRepository.GetUserData(user, item);
// Skip the user data manager because we've already looped through the recursive tree and don't want to do it twice
// TODO: Improve in future
@ -1363,9 +1363,10 @@ namespace MediaBrowser.Server.Implementations.Dto
if (fields.Contains(ItemFields.MediaSourceCount))
{
if (video.MediaSourceCount != 1)
var mediaSourceCount = video.MediaSourceCount;
if (mediaSourceCount != 1)
{
dto.MediaSourceCount = video.MediaSourceCount;
dto.MediaSourceCount = mediaSourceCount;
}
}
@ -1686,7 +1687,7 @@ namespace MediaBrowser.Server.Implementations.Dto
dateLastMediaAdded = new[] { dateLastMediaAdded.Value, child.DateCreated }.Max();
}
var userdata = _userDataRepository.GetUserData(user.Id, child.GetUserDataKey());
var userdata = _userDataRepository.GetUserData(user, child);
recursiveItemCount++;

View File

@ -522,29 +522,7 @@ namespace MediaBrowser.Server.Implementations.Library
throw new ArgumentNullException("items");
}
var dict = new Dictionary<Guid, BaseItem>();
foreach (var item in items)
{
var video = item as Video;
if (video != null)
{
if (video.PrimaryVersionId.HasValue)
{
var primary = GetItemById(video.PrimaryVersionId.Value) as Video;
if (primary != null)
{
dict[primary.Id] = primary;
continue;
}
}
}
dict[item.Id] = item;
}
return dict.Values;
return items.DistinctBy(i => i.PresentationUniqueKey, StringComparer.OrdinalIgnoreCase);
}
/// <summary>

View File

@ -267,7 +267,7 @@ namespace MediaBrowser.Server.Implementations.Library
private void SetUserProperties(IHasUserData item, MediaSourceInfo source, User user)
{
var userData = item == null ? new UserItemData() : _userDataManager.GetUserData(user.Id, item.GetUserDataKey());
var userData = item == null ? new UserItemData() : _userDataManager.GetUserData(user, item);
var allowRememberingSelection = item == null || item.EnableRememberingTrackSelections;

View File

@ -56,27 +56,30 @@ namespace MediaBrowser.Server.Implementations.Library
cancellationToken.ThrowIfCancellationRequested();
var key = item.GetUserDataKey();
var keys = item.GetUserDataKeys();
try
foreach (var key in keys)
{
await Repository.SaveUserData(userId, key, userData, cancellationToken).ConfigureAwait(false);
try
{
await Repository.SaveUserData(userId, key, userData, cancellationToken).ConfigureAwait(false);
var newValue = userData;
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);
// 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;
throw;
}
}
EventHelper.FireEventIfNotNull(UserDataSaved, this, new UserDataSaveEventArgs
{
Key = key,
Keys = keys,
UserData = userData,
SaveReason = reason,
UserId = userId,
@ -172,6 +175,21 @@ namespace MediaBrowser.Server.Implementations.Library
return userId + key;
}
public UserItemData GetUserData(IHasUserData user, IHasUserData item)
{
return GetUserData(user.Id, item.GetUserDataKey());
}
public UserItemData GetUserData(string userId, IHasUserData item)
{
return GetUserData(userId, item.GetUserDataKey());
}
public UserItemData GetUserData(Guid userId, IHasUserData item)
{
return GetUserData(userId, item.GetUserDataKey());
}
public UserItemDataDto GetUserDataDto(IHasUserData item, User user)
{
var userData = GetUserData(user.Id, item.GetUserDataKey());

View File

@ -164,7 +164,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var val = query.IsFavorite.Value;
channels = channels
.Where(i => _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).IsFavorite == val);
.Where(i => _userDataManager.GetUserData(user, i).IsFavorite == val);
}
if (query.IsLiked.HasValue)
@ -174,7 +174,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
channels = channels
.Where(i =>
{
var likes = _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).Likes;
var likes = _userDataManager.GetUserData(user, i).Likes;
return likes.HasValue && likes.Value == val;
});
@ -187,7 +187,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
channels = channels
.Where(i =>
{
var likes = _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).Likes;
var likes = _userDataManager.GetUserData(user, i).Likes;
return likes.HasValue && likes.Value != val;
});
@ -200,7 +200,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
{
if (enableFavoriteSorting)
{
var userData = _userDataManager.GetUserData(user.Id, i.GetUserDataKey());
var userData = _userDataManager.GetUserData(user, i);
if (userData.IsFavorite)
{
@ -1005,7 +1005,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var channel = GetInternalChannel(program.ChannelId);
var channelUserdata = _userDataManager.GetUserData(userId, channel.GetUserDataKey());
var channelUserdata = _userDataManager.GetUserData(userId, channel);
if (channelUserdata.Likes ?? false)
{
@ -1036,7 +1036,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
if (genres.TryGetValue(i, out genre))
{
var genreUserdata = _userDataManager.GetUserData(userId, genre.GetUserDataKey());
var genreUserdata = _userDataManager.GetUserData(userId, genre);
if (genreUserdata.Likes ?? false)
{

View File

@ -78,9 +78,6 @@
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data.SQLite">
<HintPath>..\ThirdParty\System.Data.SQLite.ManagedOnly\1.0.94.0\System.Data.SQLite.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net" />
@ -261,6 +258,8 @@
<Compile Include="Notifications\IConfigurableNotificationService.cs" />
<Compile Include="Persistence\BaseSqliteRepository.cs" />
<Compile Include="Persistence\CleanDatabaseScheduledTask.cs" />
<Compile Include="Persistence\DataExtensions.cs" />
<Compile Include="Persistence\IDbConnector.cs" />
<Compile Include="Persistence\MediaStreamColumns.cs" />
<Compile Include="Social\SharingManager.cs" />
<Compile Include="Social\SharingRepository.cs" />
@ -275,7 +274,6 @@
<Compile Include="Notifications\InternalNotificationService.cs" />
<Compile Include="Notifications\NotificationConfigurationFactory.cs" />
<Compile Include="Notifications\NotificationManager.cs" />
<Compile Include="Persistence\SqliteExtensions.cs" />
<Compile Include="Persistence\SqliteFileOrganizationRepository.cs" />
<Compile Include="Notifications\SqliteNotificationsRepository.cs" />
<Compile Include="Persistence\SqliteProviderInfoRepository.cs" />

View File

@ -32,11 +32,11 @@ namespace MediaBrowser.Server.Implementations.Notifications
_appPaths = appPaths;
}
public async Task Initialize()
public async Task Initialize(IDbConnector dbConnector)
{
var dbFile = Path.Combine(_appPaths.DataPath, "notifications.db");
_connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false);
_connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {

View File

@ -110,6 +110,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
_config.SaveConfiguration();
}
if (_config.Configuration.SchemaVersion < SqliteItemRepository.LatestSchemaVersion)
{
_config.Configuration.SchemaVersion = SqliteItemRepository.LatestSchemaVersion;
_config.SaveConfiguration();
}
if (EnableUnavailableMessage)
{
EnableUnavailableMessage = false;

View File

@ -3,16 +3,12 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using System;
using System.Data;
using System.Data.SQLite;
using System.IO;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Persistence
{
/// <summary>
/// Class SQLiteExtensions
/// </summary>
static class SqliteExtensions
static class DataExtensions
{
/// <summary>
/// Determines whether the specified conn is open.
@ -28,11 +24,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
return (IDataParameter)cmd.Parameters[index];
}
public static IDataParameter Add(this IDataParameterCollection paramCollection, IDbCommand cmd, string name, DbType type)
{
var param = cmd.CreateParameter();
param.ParameterName = name;
param.DbType = type;
@ -48,11 +44,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
param.ParameterName = name;
paramCollection.Add(param);
return param;
}
/// <summary>
/// Gets a stream from a DataReader at a given ordinal
/// </summary>
@ -122,38 +118,6 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
}
/// <summary>
/// Connects to db.
/// </summary>
/// <param name="dbPath">The db path.</param>
/// <param name="logger">The logger.</param>
/// <returns>Task{IDbConnection}.</returns>
/// <exception cref="System.ArgumentNullException">dbPath</exception>
public static async Task<IDbConnection> ConnectToDb(string dbPath, ILogger logger)
{
if (string.IsNullOrEmpty(dbPath))
{
throw new ArgumentNullException("dbPath");
}
logger.Info("Sqlite {0} opening {1}", SQLiteConnection.SQLiteVersion, dbPath);
var connectionstr = new SQLiteConnectionStringBuilder
{
PageSize = 4096,
CacheSize = 2000,
SyncMode = SynchronizationModes.Full,
DataSource = dbPath,
JournalMode = SQLiteJournalModeEnum.Wal
};
var connection = new SQLiteConnection(connectionstr.ConnectionString);
await connection.OpenAsync().ConfigureAwait(false);
return connection;
}
public static void Attach(IDbConnection db, string path, string alias)
{
using (var cmd = db.CreateCommand())

View File

@ -0,0 +1,10 @@
using System.Data;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Persistence
{
public interface IDbConnector
{
Task<IDbConnection> Connect(string dbPath);
}
}

View File

@ -52,11 +52,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// Opens the connection to the database
/// </summary>
/// <returns>Task.</returns>
public async Task Initialize()
public async Task Initialize(IDbConnector dbConnector)
{
var dbFile = Path.Combine(_appPaths.DataPath, "displaypreferences.db");
_connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false);
_connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {

View File

@ -35,11 +35,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// Opens the connection to the database
/// </summary>
/// <returns>Task.</returns>
public async Task Initialize()
public async Task Initialize(IDbConnector dbConnector)
{
var dbFile = Path.Combine(_appPaths.DataPath, "fileorganization.db");
_connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false);
_connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {

View File

@ -20,6 +20,7 @@ using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Playlists;
using MediaBrowser.Model.LiveTv;
@ -55,7 +56,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// <summary>
/// The _app paths
/// </summary>
private readonly IApplicationPaths _appPaths;
private readonly IServerConfigurationManager _config;
/// <summary>
/// The _save item command
@ -81,35 +82,31 @@ namespace MediaBrowser.Server.Implementations.Persistence
private IDbCommand _updateInheritedRatingCommand;
private IDbCommand _updateInheritedTagsCommand;
private const int LatestSchemaVersion = 65;
public const int LatestSchemaVersion = 68;
/// <summary>
/// Initializes a new instance of the <see cref="SqliteItemRepository"/> class.
/// </summary>
/// <param name="appPaths">The app paths.</param>
/// <param name="jsonSerializer">The json serializer.</param>
/// <param name="logManager">The log manager.</param>
/// <exception cref="System.ArgumentNullException">
/// appPaths
/// or
/// jsonSerializer
/// </exception>
public SqliteItemRepository(IApplicationPaths appPaths, IJsonSerializer jsonSerializer, ILogManager logManager)
public SqliteItemRepository(IServerConfigurationManager config, IJsonSerializer jsonSerializer, ILogManager logManager)
: base(logManager)
{
if (appPaths == null)
if (config == null)
{
throw new ArgumentNullException("appPaths");
throw new ArgumentNullException("config");
}
if (jsonSerializer == null)
{
throw new ArgumentNullException("jsonSerializer");
}
_appPaths = appPaths;
_config = config;
_jsonSerializer = jsonSerializer;
_criticReviewsPath = Path.Combine(_appPaths.DataPath, "critic-reviews");
_criticReviewsPath = Path.Combine(_config.ApplicationPaths.DataPath, "critic-reviews");
}
private const string ChaptersTableName = "Chapters2";
@ -118,11 +115,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// Opens the connection to the database
/// </summary>
/// <returns>Task.</returns>
public async Task Initialize()
public async Task Initialize(IDbConnector dbConnector)
{
var dbFile = Path.Combine(_appPaths.DataPath, "library.db");
var dbFile = Path.Combine(_config.ApplicationPaths.DataPath, "library.db");
_connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false);
_connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
var createMediaStreamsTableCommand
= "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, IsAvc BIT NULL, PRIMARY KEY (ItemId, StreamIndex))";
@ -228,18 +225,27 @@ namespace MediaBrowser.Server.Implementations.Persistence
_connection.AddColumn(Logger, "TypedBaseItems", "DateModifiedDuringLastRefresh", "DATETIME");
_connection.AddColumn(Logger, "TypedBaseItems", "InheritedTags", "Text");
_connection.AddColumn(Logger, "TypedBaseItems", "CleanName", "Text");
_connection.AddColumn(Logger, "TypedBaseItems", "PresentationUniqueKey", "Text");
string[] postQueries =
{
"create index if not exists idx_PresentationUniqueKey on TypedBaseItems(PresentationUniqueKey)",
"create index if not exists idx_Type on TypedBaseItems(Type)"
};
_connection.RunQueries(postQueries, Logger);
PrepareStatements();
new MediaStreamColumns(_connection, Logger).AddColumns();
var chapterDbFile = Path.Combine(_appPaths.DataPath, "chapters.db");
var chapterDbFile = Path.Combine(_config.ApplicationPaths.DataPath, "chapters.db");
if (File.Exists(chapterDbFile))
{
MigrateChapters(chapterDbFile);
}
var mediaStreamsDbFile = Path.Combine(_appPaths.DataPath, "mediainfo.db");
var mediaStreamsDbFile = Path.Combine(_config.ApplicationPaths.DataPath, "mediainfo.db");
if (File.Exists(mediaStreamsDbFile))
{
MigrateMediaStreams(mediaStreamsDbFile);
@ -252,7 +258,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
var backupFile = file + ".bak";
File.Copy(file, backupFile, true);
SqliteExtensions.Attach(_connection, backupFile, "MediaInfoOld");
DataExtensions.Attach(_connection, backupFile, "MediaInfoOld");
var columns = string.Join(",", _mediaStreamSaveColumns);
@ -278,7 +284,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
var backupFile = file + ".bak";
File.Copy(file, backupFile, true);
SqliteExtensions.Attach(_connection, backupFile, "ChaptersOld");
DataExtensions.Attach(_connection, backupFile, "ChaptersOld");
string[] queries = {
"REPLACE INTO "+ChaptersTableName+"(ItemId, ChapterIndex, StartPositionTicks, Name, ImagePath) SELECT ItemId, ChapterIndex, StartPositionTicks, Name, ImagePath FROM ChaptersOld.Chapters;"
@ -469,7 +475,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
"CriticRatingSummary",
"DateModifiedDuringLastRefresh",
"InheritedTags",
"CleanName"
"CleanName",
"PresentationUniqueKey"
};
_saveItemCommand = _connection.CreateCommand();
_saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values (";
@ -803,6 +810,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
_saveItemCommand.GetParameter(index++).Value = item.Name.RemoveDiacritics();
}
_saveItemCommand.GetParameter(index++).Value = item.PresentationUniqueKey;
_saveItemCommand.Transaction = transaction;
@ -1463,6 +1471,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
CheckDisposed();
var now = DateTime.UtcNow;
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = "select " + string.Join(",", _retriveItemColumns) + " from TypedBaseItems";
@ -1475,6 +1485,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.CommandText += whereText;
if (EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66)
{
cmd.CommandText += " Group by PresentationUniqueKey";
}
cmd.CommandText += GetOrderByText(query);
if (query.Limit.HasValue)
@ -1482,10 +1497,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(CultureInfo.InvariantCulture);
}
//Logger.Debug(cmd.CommandText);
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{
Logger.Debug("GetItemList query time: {0}ms. Query: {1}",
Convert.ToInt32((DateTime.UtcNow - now).TotalMilliseconds),
cmd.CommandText);
while (reader.Read())
{
var item = GetItem(reader);
@ -1507,6 +1524,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
CheckDisposed();
var now = DateTime.UtcNow;
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = "select " + string.Join(",", _retriveItemColumns) + " from TypedBaseItems";
@ -1525,6 +1544,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.CommandText += whereText;
if (EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66)
{
cmd.CommandText += " Group by PresentationUniqueKey";
}
cmd.CommandText += GetOrderByText(query);
if (query.Limit.HasValue)
@ -1532,15 +1556,24 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(CultureInfo.InvariantCulture);
}
cmd.CommandText += "; select count (guid) from TypedBaseItems" + whereTextWithoutPaging;
//Logger.Debug(cmd.CommandText);
if (_config.Configuration.SchemaVersion >= 66)
{
cmd.CommandText += "; select count (distinct PresentationUniqueKey) from TypedBaseItems" + whereTextWithoutPaging;
}
else
{
cmd.CommandText += "; select count (guid) from TypedBaseItems" + whereTextWithoutPaging;
}
var list = new List<BaseItem>();
var count = 0;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
Logger.Debug("GetItems query time: {0}ms. Query: {1}",
Convert.ToInt32((DateTime.UtcNow - now).TotalMilliseconds),
cmd.CommandText);
while (reader.Read())
{
var item = GetItem(reader);
@ -1608,6 +1641,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
CheckDisposed();
var now = DateTime.UtcNow;
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = "select guid from TypedBaseItems";
@ -1620,6 +1655,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.CommandText += whereText;
if (EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66)
{
cmd.CommandText += " Group by PresentationUniqueKey";
}
cmd.CommandText += GetOrderByText(query);
if (query.Limit.HasValue)
@ -1629,10 +1669,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
var list = new List<Guid>();
//Logger.Debug(cmd.CommandText);
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{
Logger.Debug("GetItemIdsList query time: {0}ms. Query: {1}",
Convert.ToInt32((DateTime.UtcNow - now).TotalMilliseconds),
cmd.CommandText);
while (reader.Read())
{
list.Add(reader.GetGuid(0));
@ -1662,7 +1704,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
whereClauses = GetWhereClauses(query, cmd, true);
whereClauses = GetWhereClauses(query, cmd, true, false);
var whereText = whereClauses.Count == 0 ?
string.Empty :
@ -1670,6 +1712,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.CommandText += whereText;
if (EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66)
{
cmd.CommandText += " Group by PresentationUniqueKey";
}
cmd.CommandText += GetOrderByText(query);
if (query.Limit.HasValue)
@ -1721,6 +1768,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
CheckDisposed();
var now = DateTime.UtcNow;
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = "select guid from TypedBaseItems";
@ -1739,6 +1788,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.CommandText += whereText;
if (EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66)
{
cmd.CommandText += " Group by PresentationUniqueKey";
}
cmd.CommandText += GetOrderByText(query);
if (query.Limit.HasValue)
@ -1746,15 +1800,24 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(CultureInfo.InvariantCulture);
}
cmd.CommandText += "; select count (guid) from TypedBaseItems" + whereTextWithoutPaging;
if (EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66)
{
cmd.CommandText += "; select count (distinct PresentationUniqueKey) from TypedBaseItems" + whereTextWithoutPaging;
}
else
{
cmd.CommandText += "; select count (guid) from TypedBaseItems" + whereTextWithoutPaging;
}
var list = new List<Guid>();
var count = 0;
//Logger.Debug(cmd.CommandText);
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
Logger.Debug("GetItemIds query time: {0}ms. Query: {1}",
Convert.ToInt32((DateTime.UtcNow - now).TotalMilliseconds),
cmd.CommandText);
while (reader.Read())
{
list.Add(reader.GetGuid(0));
@ -1774,7 +1837,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
}
private List<string> GetWhereClauses(InternalItemsQuery query, IDbCommand cmd, bool addPaging)
private List<string> GetWhereClauses(InternalItemsQuery query, IDbCommand cmd, bool addPaging, bool enablePresentationUniqueKey = true)
{
var whereClauses = new List<string>();
@ -1873,6 +1936,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.Parameters.Add(cmd, "@Path", DbType.String).Value = query.Path;
}
if (!string.IsNullOrWhiteSpace(query.PresentationUniqueKey))
{
whereClauses.Add("PresentationUniqueKey=@PresentationUniqueKey");
cmd.Parameters.Add(cmd, "@PresentationUniqueKey", DbType.String).Value = query.PresentationUniqueKey;
}
if (query.MinCommunityRating.HasValue)
{
whereClauses.Add("CommunityRating>=@MinCommunityRating");
@ -1998,9 +2067,40 @@ namespace MediaBrowser.Server.Implementations.Persistence
if (!string.IsNullOrWhiteSpace(query.NameContains))
{
whereClauses.Add("CleanName like @NameContains");
if (_config.Configuration.SchemaVersion >= 66)
{
whereClauses.Add("CleanName like @NameContains");
}
else
{
whereClauses.Add("Name like @NameContains");
}
cmd.Parameters.Add(cmd, "@NameContains", DbType.String).Value = "%" + query.NameContains + "%";
}
if (!string.IsNullOrWhiteSpace(query.NameStartsWith))
{
if (_config.Configuration.SchemaVersion >= 66)
{
whereClauses.Add("CleanName like @NameStartsWith");
}
else
{
whereClauses.Add("Name like @NameStartsWith");
}
cmd.Parameters.Add(cmd, "@NameStartsWith", DbType.String).Value = query.NameStartsWith + "%";
}
if (!string.IsNullOrWhiteSpace(query.NameStartsWithOrGreater))
{
whereClauses.Add("SortName >= @NameStartsWithOrGreater");
// lowercase this because SortName is stored as lowercase
cmd.Parameters.Add(cmd, "@NameStartsWithOrGreater", DbType.String).Value = query.NameStartsWithOrGreater.ToLower();
}
if (!string.IsNullOrWhiteSpace(query.NameLessThan))
{
whereClauses.Add("SortName < @NameLessThan");
// lowercase this because SortName is stored as lowercase
cmd.Parameters.Add(cmd, "@NameLessThan", DbType.String).Value = query.NameLessThan.ToLower();
}
if (query.Genres.Length > 0)
{
@ -2134,7 +2234,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
whereClauses.Add("MediaType in (" + val + ")");
}
var enableItemsByName = query.IncludeItemsByName ?? query.IncludeItemTypes.Length > 0;
//var enableItemsByName = query.IncludeItemsByName ?? query.IncludeItemTypes.Length > 0;
var enableItemsByName = query.IncludeItemsByName ?? false;
if (query.TopParentIds.Length == 1)
{
@ -2197,7 +2298,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
excludeTagIndex = 0;
foreach (var excludeTag in query.ExcludeInheritedTags)
{
whereClauses.Add("(InheritedTags is null OR InheritedTags not like @excludeInheritedTag" + excludeTagIndex +")");
whereClauses.Add("(InheritedTags is null OR InheritedTags not like @excludeInheritedTag" + excludeTagIndex + ")");
cmd.Parameters.Add(cmd, "@excludeInheritedTag" + excludeTagIndex, DbType.String).Value = "%" + excludeTag + "%";
excludeTagIndex++;
}
@ -2210,6 +2311,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
if (enablePresentationUniqueKey && EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66)
{
pagingWhereText += " Group by PresentationUniqueKey";
}
var orderBy = GetOrderByText(query);
whereClauses.Add(string.Format("guid NOT IN (SELECT guid FROM TypedBaseItems {0}" + orderBy + " LIMIT {1})",
@ -2221,6 +2327,34 @@ namespace MediaBrowser.Server.Implementations.Persistence
return whereClauses;
}
private bool EnableGroupByPresentationUniqueKey(InternalItemsQuery query)
{
if (!string.IsNullOrWhiteSpace(query.PresentationUniqueKey))
{
return false;
}
if (query.IncludeItemTypes.Length == 0)
{
return true;
}
var types = new[] {
typeof(Episode).Name,
typeof(Video).Name ,
typeof(Movie).Name ,
typeof(MusicVideo).Name ,
typeof(Series).Name ,
typeof(Season).Name };
if (types.Any(i => query.IncludeItemTypes.Contains(i, StringComparer.OrdinalIgnoreCase)))
{
return true;
}
return false;
}
private static readonly Type[] KnownTypes =
{
typeof(LiveTvProgram),
@ -2299,7 +2433,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
try
{
transaction = _connection.BeginTransaction();
foreach (var item in newValues)
{
_updateInheritedTagsCommand.GetParameter(0).Value = item.Item1;

View File

@ -39,11 +39,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// Opens the connection to the database
/// </summary>
/// <returns>Task.</returns>
public async Task Initialize()
public async Task Initialize(IDbConnector dbConnector)
{
var dbFile = Path.Combine(_appPaths.DataPath, "refreshinfo.db");
_connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false);
_connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {

View File

@ -37,11 +37,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// Opens the connection to the database
/// </summary>
/// <returns>Task.</returns>
public async Task Initialize()
public async Task Initialize(IDbConnector dbConnector)
{
var dbFile = Path.Combine(_appPaths.DataPath, "userdata_v2.db");
_connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false);
_connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {

View File

@ -43,12 +43,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// Opens the connection to the database
/// </summary>
/// <returns>Task.</returns>
public async Task Initialize()
public async Task Initialize(IDbConnector dbConnector)
{
var dbFile = Path.Combine(_appPaths.DataPath, "users.db");
_connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false);
_connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {
"create table if not exists users (guid GUID primary key, data BLOB)",

View File

@ -27,11 +27,11 @@ namespace MediaBrowser.Server.Implementations.Security
_appPaths = appPaths;
}
public async Task Initialize()
public async Task Initialize(IDbConnector dbConnector)
{
var dbFile = Path.Combine(_appPaths.DataPath, "authentication.db");
_connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false);
_connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {

View File

@ -601,11 +601,9 @@ namespace MediaBrowser.Server.Implementations.Session
if (libraryItem != null)
{
var key = libraryItem.GetUserDataKey();
foreach (var user in users)
{
await OnPlaybackStart(user.Id, key, libraryItem).ConfigureAwait(false);
await OnPlaybackStart(user.Id, libraryItem).ConfigureAwait(false);
}
}
@ -632,12 +630,11 @@ namespace MediaBrowser.Server.Implementations.Session
/// Called when [playback start].
/// </summary>
/// <param name="userId">The user identifier.</param>
/// <param name="userDataKey">The user data key.</param>
/// <param name="item">The item.</param>
/// <returns>Task.</returns>
private async Task OnPlaybackStart(Guid userId, string userDataKey, IHasUserData item)
private async Task OnPlaybackStart(Guid userId, IHasUserData item)
{
var data = _userDataRepository.GetUserData(userId, userDataKey);
var data = _userDataRepository.GetUserData(userId, item);
data.PlayCount++;
data.LastPlayedDate = DateTime.UtcNow;
@ -676,11 +673,9 @@ namespace MediaBrowser.Server.Implementations.Session
if (libraryItem != null)
{
var key = libraryItem.GetUserDataKey();
foreach (var user in users)
{
await OnPlaybackProgress(user, key, libraryItem, info).ConfigureAwait(false);
await OnPlaybackProgress(user, libraryItem, info).ConfigureAwait(false);
}
}
@ -714,9 +709,9 @@ namespace MediaBrowser.Server.Implementations.Session
StartIdleCheckTimer();
}
private async Task OnPlaybackProgress(User user, string userDataKey, BaseItem item, PlaybackProgressInfo info)
private async Task OnPlaybackProgress(User user, BaseItem item, PlaybackProgressInfo info)
{
var data = _userDataRepository.GetUserData(user.Id, userDataKey);
var data = _userDataRepository.GetUserData(user.Id, item);
var positionTicks = info.PositionTicks;
@ -811,11 +806,9 @@ namespace MediaBrowser.Server.Implementations.Session
if (libraryItem != null)
{
var key = libraryItem.GetUserDataKey();
foreach (var user in users)
{
playedToCompletion = await OnPlaybackStopped(user.Id, key, libraryItem, info.PositionTicks, info.Failed).ConfigureAwait(false);
playedToCompletion = await OnPlaybackStopped(user.Id, libraryItem, info.PositionTicks, info.Failed).ConfigureAwait(false);
}
}
@ -848,13 +841,13 @@ namespace MediaBrowser.Server.Implementations.Session
await SendPlaybackStoppedNotification(session, CancellationToken.None).ConfigureAwait(false);
}
private async Task<bool> OnPlaybackStopped(Guid userId, string userDataKey, BaseItem item, long? positionTicks, bool playbackFailed)
private async Task<bool> OnPlaybackStopped(Guid userId, BaseItem item, long? positionTicks, bool playbackFailed)
{
bool playedToCompletion = false;
if (!playbackFailed)
{
var data = _userDataRepository.GetUserData(userId, userDataKey);
var data = _userDataRepository.GetUserData(userId, item);
if (positionTicks.HasValue)
{

View File

@ -26,11 +26,11 @@ namespace MediaBrowser.Server.Implementations.Social
/// Opens the connection to the database
/// </summary>
/// <returns>Task.</returns>
public async Task Initialize()
public async Task Initialize(IDbConnector dbConnector)
{
var dbFile = Path.Combine(_appPaths.DataPath, "shares.db");
_connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false);
_connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {

View File

@ -49,8 +49,8 @@ namespace MediaBrowser.Server.Implementations.Sorting
private int Compare(Episode x, Episode y)
{
var isXSpecial = (x.PhysicalSeasonNumber ?? -1) == 0;
var isYSpecial = (y.PhysicalSeasonNumber ?? -1) == 0;
var isXSpecial = (x.ParentIndexNumber ?? -1) == 0;
var isYSpecial = (y.ParentIndexNumber ?? -1) == 0;
if (isXSpecial && isYSpecial)
{
@ -74,7 +74,7 @@ namespace MediaBrowser.Server.Implementations.Sorting
{
// http://thetvdb.com/wiki/index.php?title=Special_Episodes
var xSeason = x.PhysicalSeasonNumber ?? -1;
var xSeason = x.ParentIndexNumber ?? -1;
var ySeason = y.AirsAfterSeasonNumber ?? y.AirsBeforeSeasonNumber ?? -1;
if (xSeason != ySeason)
@ -142,8 +142,8 @@ namespace MediaBrowser.Server.Implementations.Sorting
private int CompareEpisodes(Episode x, Episode y)
{
var xValue = (x.PhysicalSeasonNumber ?? -1) * 1000 + (x.IndexNumber ?? -1);
var yValue = (y.PhysicalSeasonNumber ?? -1) * 1000 + (y.IndexNumber ?? -1);
var xValue = (x.ParentIndexNumber ?? -1) * 1000 + (x.IndexNumber ?? -1);
var yValue = (y.ParentIndexNumber ?? -1) * 1000 + (y.IndexNumber ?? -1);
return xValue.CompareTo(yValue);
}

View File

@ -47,7 +47,7 @@ namespace MediaBrowser.Server.Implementations.Sorting
/// <returns>DateTime.</returns>
private DateTime GetDate(BaseItem x)
{
var userdata = UserDataRepository.GetUserData(User.Id, x.GetUserDataKey());
var userdata = UserDataRepository.GetUserData(User, x);
if (userdata != null && userdata.LastPlayedDate.HasValue)
{

View File

@ -34,7 +34,7 @@ namespace MediaBrowser.Server.Implementations.Sorting
/// <returns>DateTime.</returns>
private int GetValue(BaseItem x)
{
var userdata = UserDataRepository.GetUserData(User.Id, x.GetUserDataKey());
var userdata = UserDataRepository.GetUserData(User, x);
return userdata == null ? 0 : userdata.PlayCount;
}

View File

@ -687,7 +687,7 @@ namespace MediaBrowser.Server.Implementations.Sync
private Task ReportOfflinePlayedItem(UserAction action)
{
var item = _libraryManager.GetItemById(action.ItemId);
var userData = _userDataManager.GetUserData(new Guid(action.UserId), item.GetUserDataKey());
var userData = _userDataManager.GetUserData(action.UserId, item);
userData.LastPlayedDate = action.Date;
_userDataManager.UpdatePlayState(item, userData, action.PositionTicks);

View File

@ -39,11 +39,11 @@ namespace MediaBrowser.Server.Implementations.Sync
_appPaths = appPaths;
}
public async Task Initialize()
public async Task Initialize(IDbConnector dbConnector)
{
var dbFile = Path.Combine(_appPaths.DataPath, "sync14.db");
_connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false);
_connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {

View File

@ -36,10 +36,25 @@ namespace MediaBrowser.Server.Implementations.TV
? new string[] { }
: new[] { request.ParentId };
string presentationUniqueKey = null;
int? limit = null;
if (!string.IsNullOrWhiteSpace(request.SeriesId))
{
var series = _libraryManager.GetItemById(request.SeriesId);
if (series != null)
{
presentationUniqueKey = series.PresentationUniqueKey;
limit = 1;
}
}
var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(Series).Name },
SortOrder = SortOrder.Ascending
SortOrder = SortOrder.Ascending,
PresentationUniqueKey = presentationUniqueKey,
Limit = limit
}, parentIds).Cast<Series>();
@ -58,10 +73,25 @@ namespace MediaBrowser.Server.Implementations.TV
throw new ArgumentException("User not found");
}
string presentationUniqueKey = null;
int? limit = null;
if (!string.IsNullOrWhiteSpace(request.SeriesId))
{
var series = _libraryManager.GetItemById(request.SeriesId);
if (series != null)
{
presentationUniqueKey = series.PresentationUniqueKey;
limit = 1;
}
}
var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(Series).Name },
SortOrder = SortOrder.Ascending
SortOrder = SortOrder.Ascending,
PresentationUniqueKey = presentationUniqueKey,
Limit = limit
}, parentsFolders.Select(i => i.Id.ToString("N"))).Cast<Series>();
@ -76,30 +106,30 @@ namespace MediaBrowser.Server.Implementations.TV
// Avoid implicitly captured closure
var currentUser = user;
return FilterSeries(request, series)
return series
.AsParallel()
.Select(i => GetNextUp(i, currentUser))
// Include if an episode was found, and either the series is not unwatched or the specific series was requested
.Where(i => i.Item1 != null && (!i.Item3 || !string.IsNullOrWhiteSpace(request.SeriesId)))
.OrderByDescending(i =>
{
var episode = i.Item1;
//.OrderByDescending(i =>
//{
// var episode = i.Item1;
var seriesUserData = _userDataManager.GetUserData(user.Id, episode.Series.GetUserDataKey());
// var seriesUserData = _userDataManager.GetUserData(user, episode.Series);
if (seriesUserData.IsFavorite)
{
return 2;
}
// if (seriesUserData.IsFavorite)
// {
// return 2;
// }
if (seriesUserData.Likes.HasValue)
{
return seriesUserData.Likes.Value ? 1 : -1;
}
// if (seriesUserData.Likes.HasValue)
// {
// return seriesUserData.Likes.Value ? 1 : -1;
// }
return 0;
})
.ThenByDescending(i => i.Item2)
// return 0;
//})
.OrderByDescending(i => i.Item2)
.ThenByDescending(i => i.Item1.PremiereDate ?? DateTime.MinValue)
.Select(i => i.Item1);
}
@ -128,7 +158,7 @@ namespace MediaBrowser.Server.Implementations.TV
// Go back starting with the most recent episodes
foreach (var episode in allEpisodes)
{
var userData = _userDataManager.GetUserData(user.Id, episode.GetUserDataKey());
var userData = _userDataManager.GetUserData(user, episode);
if (userData.Played)
{
@ -142,7 +172,7 @@ namespace MediaBrowser.Server.Implementations.TV
}
else
{
if (!episode.IsVirtualUnaired && (!episode.IsMissingEpisode || includeMissing))
if (!episode.IsVirtualUnaired && (includeMissing || !episode.IsMissingEpisode))
{
nextUp = episode;
}
@ -154,24 +184,12 @@ namespace MediaBrowser.Server.Implementations.TV
return new Tuple<Episode, DateTime, bool>(nextUp, lastWatchedDate, false);
}
var firstEpisode = allEpisodes.LastOrDefault(i => !i.IsVirtualUnaired && (!i.IsMissingEpisode || includeMissing) && !i.IsPlayed(user));
var firstEpisode = allEpisodes.LastOrDefault(i => !i.IsVirtualUnaired && (includeMissing || !i.IsMissingEpisode) && !i.IsPlayed(user));
// Return the first episode
return new Tuple<Episode, DateTime, bool>(firstEpisode, DateTime.MinValue, true);
}
private IEnumerable<Series> FilterSeries(NextUpQuery request, IEnumerable<Series> items)
{
if (!string.IsNullOrWhiteSpace(request.SeriesId))
{
var id = new Guid(request.SeriesId);
items = items.Where(i => i.Id == id);
}
return items;
}
private QueryResult<BaseItem> GetResult(IEnumerable<BaseItem> items, int? totalRecordLimit, NextUpQuery query)
{
var itemsArray = totalRecordLimit.HasValue ? items.Take(totalRecordLimit.Value).ToArray() : items.ToArray();

View File

@ -76,12 +76,17 @@
<Reference Include="MediaBrowser.IsoMounting.Linux">
<HintPath>..\ThirdParty\MediaBrowser.IsoMounting.Linux\MediaBrowser.IsoMounting.Linux.dll</HintPath>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Data.SQLite">
<HintPath>..\ThirdParty\System.Data.SQLite.ManagedOnly\1.0.94.0\System.Data.SQLite.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\SharedVersion.cs">
<Link>Properties\SharedVersion.cs</Link>
</Compile>
<Compile Include="Native\BaseMonoApp.cs" />
<Compile Include="Native\SqliteExtensions.cs" />
<Compile Include="Networking\CertificateGenerator.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />

View File

@ -9,6 +9,7 @@ using System.Collections.Generic;
using System.Reflection;
using System.Text.RegularExpressions;
using MediaBrowser.Controller.Power;
using MediaBrowser.Server.Implementations.Persistence;
using MediaBrowser.Server.Startup.Common.FFMpeg;
using OperatingSystem = MediaBrowser.Server.Startup.Common.OperatingSystem;
@ -17,9 +18,12 @@ namespace MediaBrowser.Server.Mono.Native
public abstract class BaseMonoApp : INativeApp
{
protected StartupOptions StartupOptions { get; private set; }
protected BaseMonoApp(StartupOptions startupOptions)
protected ILogger Logger { get; private set; }
protected BaseMonoApp(StartupOptions startupOptions, ILogger logger)
{
StartupOptions = startupOptions;
Logger = logger;
}
/// <summary>
@ -227,6 +231,11 @@ namespace MediaBrowser.Server.Mono.Native
throw new NotImplementedException();
}
public IDbConnector GetDbConnector()
{
return new DbConnector(Logger);
}
public static FFMpegInstallInfo GetInfo(NativeEnvironment environment)
{
var info = new FFMpegInstallInfo();

View File

@ -1,4 +1,5 @@
using MediaBrowser.Server.Startup.Common;
using MediaBrowser.Model.Logging;
using MediaBrowser.Server.Startup.Common;
namespace MediaBrowser.Server.Mono.Native
{
@ -7,8 +8,8 @@ namespace MediaBrowser.Server.Mono.Native
/// </summary>
internal class NativeApp : BaseMonoApp
{
public NativeApp(StartupOptions startupOptions)
: base(startupOptions)
public NativeApp(StartupOptions startupOptions, ILogger logger)
: base(startupOptions, logger)
{
}

View File

@ -0,0 +1,62 @@
using System;
using System.Data;
using System.Data.SQLite;
using System.Threading.Tasks;
using MediaBrowser.Model.Logging;
using MediaBrowser.Server.Implementations.Persistence;
namespace MediaBrowser.Server.Mono.Native
{
/// <summary>
/// Class SQLiteExtensions
/// </summary>
static class SqliteExtensions
{
/// <summary>
/// Connects to db.
/// </summary>
/// <param name="dbPath">The db path.</param>
/// <param name="logger">The logger.</param>
/// <returns>Task{IDbConnection}.</returns>
/// <exception cref="System.ArgumentNullException">dbPath</exception>
public static async Task<IDbConnection> ConnectToDb(string dbPath, ILogger logger)
{
if (string.IsNullOrEmpty(dbPath))
{
throw new ArgumentNullException("dbPath");
}
logger.Info("Sqlite {0} opening {1}", SQLiteConnection.SQLiteVersion, dbPath);
var connectionstr = new SQLiteConnectionStringBuilder
{
PageSize = 4096,
CacheSize = 2000,
SyncMode = SynchronizationModes.Full,
DataSource = dbPath,
JournalMode = SQLiteJournalModeEnum.Wal
};
var connection = new SQLiteConnection(connectionstr.ConnectionString);
await connection.OpenAsync().ConfigureAwait(false);
return connection;
}
}
public class DbConnector : IDbConnector
{
private readonly ILogger _logger;
public DbConnector(ILogger logger)
{
_logger = logger;
}
public Task<IDbConnection> Connect(string dbPath)
{
return SqliteExtensions.ConnectToDb(dbPath, _logger);
}
}
}

View File

@ -79,7 +79,7 @@ namespace MediaBrowser.Server.Mono
var fileSystem = new ManagedFileSystem(new PatternsLogger(logManager.GetLogger("FileSystem")), false, false);
fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem));
var nativeApp = new NativeApp(options);
var nativeApp = new NativeApp(options, logManager.GetLogger("App"));
_appHost = new ApplicationHost(appPaths, logManager, options, fileSystem, "emby.mono.zip", nativeApp);

View File

@ -410,13 +410,16 @@ namespace MediaBrowser.Server.Startup.Common
UserRepository = await GetUserRepository().ConfigureAwait(false);
RegisterSingleInstance(UserRepository);
DisplayPreferencesRepository = new SqliteDisplayPreferencesRepository(LogManager, JsonSerializer, ApplicationPaths);
var displayPreferencesRepo = new SqliteDisplayPreferencesRepository(LogManager, JsonSerializer, ApplicationPaths);
DisplayPreferencesRepository = displayPreferencesRepo;
RegisterSingleInstance(DisplayPreferencesRepository);
ItemRepository = new SqliteItemRepository(ApplicationPaths, JsonSerializer, LogManager);
var itemRepo = new SqliteItemRepository(ServerConfigurationManager, JsonSerializer, LogManager);
ItemRepository = itemRepo;
RegisterSingleInstance(ItemRepository);
ProviderRepository = new SqliteProviderInfoRepository(LogManager, ApplicationPaths);
var providerRepo = new SqliteProviderInfoRepository(LogManager, ApplicationPaths);
ProviderRepository = providerRepo;
RegisterSingleInstance(ProviderRepository);
FileOrganizationRepository = await GetFileOrganizationRepository().ConfigureAwait(false);
@ -541,7 +544,7 @@ namespace MediaBrowser.Server.Startup.Common
RegisterSingleInstance(NativeApp.GetPowerManagement());
var sharingRepo = new SharingRepository(LogManager, ApplicationPaths);
await sharingRepo.Initialize().ConfigureAwait(false);
await sharingRepo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false);
RegisterSingleInstance<ISharingManager>(new SharingManager(sharingRepo, ServerConfigurationManager, LibraryManager, this));
RegisterSingleInstance<ISsdpHandler>(new SsdpHandler(LogManager.GetLogger("SsdpHandler"), ServerConfigurationManager, this));
@ -557,9 +560,11 @@ namespace MediaBrowser.Server.Startup.Common
SubtitleEncoder = new SubtitleEncoder(LibraryManager, LogManager.GetLogger("SubtitleEncoder"), ApplicationPaths, FileSystemManager, MediaEncoder, JsonSerializer, HttpClient, MediaSourceManager);
RegisterSingleInstance(SubtitleEncoder);
await ConfigureDisplayPreferencesRepositories().ConfigureAwait(false);
await ConfigureItemRepositories().ConfigureAwait(false);
await displayPreferencesRepo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false);
await itemRepo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false);
await providerRepo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false);
((LibraryManager)LibraryManager).ItemRepository = ItemRepository;
await ConfigureUserDataRepositories().ConfigureAwait(false);
await ConfigureNotificationsRepository().ConfigureAwait(false);
progress.Report(100);
@ -658,7 +663,7 @@ namespace MediaBrowser.Server.Startup.Common
{
var repo = new SqliteUserRepository(LogManager, ApplicationPaths, JsonSerializer);
await repo.Initialize().ConfigureAwait(false);
await repo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false);
return repo;
}
@ -677,7 +682,7 @@ namespace MediaBrowser.Server.Startup.Common
{
var repo = new SqliteFileOrganizationRepository(LogManager, ServerConfigurationManager.ApplicationPaths);
await repo.Initialize().ConfigureAwait(false);
await repo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false);
return repo;
}
@ -686,7 +691,7 @@ namespace MediaBrowser.Server.Startup.Common
{
var repo = new AuthenticationRepository(LogManager, ServerConfigurationManager.ApplicationPaths);
await repo.Initialize().ConfigureAwait(false);
await repo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false);
return repo;
}
@ -695,7 +700,7 @@ namespace MediaBrowser.Server.Startup.Common
{
var repo = new ActivityRepository(LogManager, ServerConfigurationManager.ApplicationPaths);
await repo.Initialize().ConfigureAwait(false);
await repo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false);
return repo;
}
@ -704,7 +709,7 @@ namespace MediaBrowser.Server.Startup.Common
{
var repo = new SyncRepository(LogManager, JsonSerializer, ServerConfigurationManager.ApplicationPaths);
await repo.Initialize().ConfigureAwait(false);
await repo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false);
return repo;
}
@ -717,35 +722,13 @@ namespace MediaBrowser.Server.Startup.Common
{
var repo = new SqliteNotificationsRepository(LogManager, ApplicationPaths);
await repo.Initialize().ConfigureAwait(false);
await repo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false);
NotificationsRepository = repo;
RegisterSingleInstance(NotificationsRepository);
}
/// <summary>
/// Configures the repositories.
/// </summary>
/// <returns>Task.</returns>
private async Task ConfigureDisplayPreferencesRepositories()
{
await DisplayPreferencesRepository.Initialize().ConfigureAwait(false);
}
/// <summary>
/// Configures the item repositories.
/// </summary>
/// <returns>Task.</returns>
private async Task ConfigureItemRepositories()
{
await ItemRepository.Initialize().ConfigureAwait(false);
await ProviderRepository.Initialize().ConfigureAwait(false);
((LibraryManager)LibraryManager).ItemRepository = ItemRepository;
}
/// <summary>
/// Configures the user data repositories.
/// </summary>
@ -754,7 +737,7 @@ namespace MediaBrowser.Server.Startup.Common
{
var repo = new SqliteUserDataRepository(LogManager, ApplicationPaths);
await repo.Initialize().ConfigureAwait(false);
await repo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false);
((UserDataManager)UserDataManager).Repository = repo;
}

View File

@ -3,6 +3,7 @@ using MediaBrowser.Model.Logging;
using System.Collections.Generic;
using System.Reflection;
using MediaBrowser.Controller.Power;
using MediaBrowser.Server.Implementations.Persistence;
using MediaBrowser.Server.Startup.Common.FFMpeg;
namespace MediaBrowser.Server.Startup.Common
@ -104,5 +105,7 @@ namespace MediaBrowser.Server.Startup.Common
FFMpegInstallInfo GetFfmpegInstallInfo();
void LaunchUrl(string url);
IDbConnector GetDbConnector();
}
}

View File

@ -13,6 +13,8 @@
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@ -81,9 +83,9 @@
<Reference Include="System.Configuration" />
<Reference Include="System.Configuration.Install" />
<Reference Include="System.Core" />
<Reference Include="System.Data.SQLite, Version=1.0.94.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\System.Data.SQLite.Core.1.0.94.0\lib\net45\System.Data.SQLite.dll</HintPath>
<Reference Include="System.Data.SQLite, Version=1.0.101.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL">
<HintPath>..\packages\System.Data.SQLite.Core.1.0.101.0\lib\net46\System.Data.SQLite.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.ServiceProcess" />
@ -112,6 +114,7 @@
</Compile>
<Compile Include="MainStartup.cs" />
<Compile Include="Native\LnkShortcutHandler.cs" />
<Compile Include="Native\SqliteExtensions.cs" />
<Compile Include="Native\Standby.cs" />
<Compile Include="Native\ServerAuthorization.cs" />
<Compile Include="Native\WindowsApp.cs" />
@ -156,14 +159,6 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Content Include="..\packages\System.Data.SQLite.Core.1.0.94.0\build\net45\x64\SQLite.Interop.dll">
<Link>x64\SQLite.Interop.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\packages\System.Data.SQLite.Core.1.0.94.0\build\net45\x86\SQLite.Interop.dll">
<Link>x86\SQLite.Interop.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\Tools\Installation\MediaBrowser.InstallUtil.dll">
<Link>MediaBrowser.InstallUtil.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
@ -1116,6 +1111,13 @@
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
<Import Project="..\packages\System.Data.SQLite.Core.1.0.101.0\build\net46\System.Data.SQLite.Core.targets" Condition="Exists('..\packages\System.Data.SQLite.Core.1.0.101.0\build\net46\System.Data.SQLite.Core.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\System.Data.SQLite.Core.1.0.101.0\build\net46\System.Data.SQLite.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\System.Data.SQLite.Core.1.0.101.0\build\net46\System.Data.SQLite.Core.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
@ -1123,5 +1125,4 @@
<Target Name="AfterBuild">
</Target>
-->
<Import Project="..\packages\System.Data.SQLite.Core.1.0.94.0\build\net45\System.Data.SQLite.Core.targets" Condition="Exists('..\packages\System.Data.SQLite.Core.1.0.94.0\build\net45\System.Data.SQLite.Core.targets')" />
</Project>

View File

@ -0,0 +1,62 @@
using System;
using System.Data;
using System.Data.SQLite;
using System.Threading.Tasks;
using MediaBrowser.Model.Logging;
using MediaBrowser.Server.Implementations.Persistence;
namespace MediaBrowser.ServerApplication.Native
{
/// <summary>
/// Class SQLiteExtensions
/// </summary>
static class SqliteExtensions
{
/// <summary>
/// Connects to db.
/// </summary>
/// <param name="dbPath">The db path.</param>
/// <param name="logger">The logger.</param>
/// <returns>Task{IDbConnection}.</returns>
/// <exception cref="System.ArgumentNullException">dbPath</exception>
public static async Task<IDbConnection> ConnectToDb(string dbPath, ILogger logger)
{
if (string.IsNullOrEmpty(dbPath))
{
throw new ArgumentNullException("dbPath");
}
logger.Info("Sqlite {0} opening {1}", SQLiteConnection.SQLiteVersion, dbPath);
var connectionstr = new SQLiteConnectionStringBuilder
{
PageSize = 4096,
CacheSize = 2000,
SyncMode = SynchronizationModes.Full,
DataSource = dbPath,
JournalMode = SQLiteJournalModeEnum.Wal
};
var connection = new SQLiteConnection(connectionstr.ConnectionString);
await connection.OpenAsync().ConfigureAwait(false);
return connection;
}
}
public class DbConnector : IDbConnector
{
private readonly ILogger _logger;
public DbConnector(ILogger logger)
{
_logger = logger;
}
public Task<IDbConnection> Connect(string dbPath)
{
return SqliteExtensions.ConnectToDb(dbPath, _logger);
}
}
}

View File

@ -10,6 +10,7 @@ using System.Reflection;
using System.Windows.Forms;
using CommonIO;
using MediaBrowser.Controller.Power;
using MediaBrowser.Server.Implementations.Persistence;
using MediaBrowser.Server.Startup.Common.FFMpeg;
using OperatingSystem = MediaBrowser.Server.Startup.Common.OperatingSystem;
@ -191,6 +192,11 @@ namespace MediaBrowser.ServerApplication.Native
}
}
public IDbConnector GetDbConnector()
{
return new DbConnector(_logger);
}
/// <summary>
/// Processes the exited.
/// </summary>

View File

@ -3,5 +3,5 @@
<package id="CommonIO" version="1.0.0.9" targetFramework="net45" />
<package id="ImageMagickSharp" version="1.0.0.18" targetFramework="net45" />
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
<package id="System.Data.SQLite.Core" version="1.0.94.0" targetFramework="net45" requireReinstallation="true" />
<package id="System.Data.SQLite.Core" version="1.0.101.0" targetFramework="net46" />
</packages>

View File

@ -936,7 +936,7 @@ namespace MediaBrowser.XbmcMetadata.Savers
return;
}
var userdata = userDataRepo.GetUserData(user.Id, item.GetUserDataKey());
var userdata = userDataRepo.GetUserData(user, item);
writer.WriteElementString("isuserfavorite", userdata.IsFavorite.ToString().ToLower());

View File

@ -1,4 +1,4 @@
using System.Reflection;
//[assembly: AssemblyVersion("3.0.*")]
[assembly: AssemblyVersion("3.0.5947")]
[assembly: AssemblyVersion("3.0.*")]
//[assembly: AssemblyVersion("3.0.5930")]