diff options
45 files changed, 520 insertions, 162 deletions
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 224907a72..cf79148f6 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -912,32 +912,6 @@ namespace MediaBrowser.Controller.Entities } } - /// <summary> - /// Determine if we have changed vs the passed in copy - /// </summary> - /// <param name="copy">The copy.</param> - /// <returns><c>true</c> if the specified copy has changed; otherwise, <c>false</c>.</returns> - /// <exception cref="System.ArgumentNullException"></exception> - public virtual bool HasChanged(BaseItem copy) - { - if (copy == null) - { - throw new ArgumentNullException(); - } - if (IsInMixedFolder != copy.IsInMixedFolder) - { - Logger.Debug(Name + " changed due to different value for IsInMixedFolder."); - return true; - } - - var changed = copy.DateModified != DateModified; - if (changed) - { - Logger.Debug(Name + " changed - original creation: " + DateCreated + " new creation: " + copy.DateCreated + " original modified: " + DateModified + " new modified: " + copy.DateModified); - } - return changed; - } - public virtual string GetClientTypeName() { return GetType().Name; diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index c08a2ddf2..ead899873 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -181,8 +181,6 @@ namespace MediaBrowser.Controller.Entities item.Parent = null; - LibraryManager.ReportItemRemoved(item); - return ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken); } @@ -220,7 +218,6 @@ namespace MediaBrowser.Controller.Entities {LocalizedStrings.Instance.GetString("GenreDispPref")}, {LocalizedStrings.Instance.GetString("DirectorDispPref")}, {LocalizedStrings.Instance.GetString("YearDispPref")}, - //{LocalizedStrings.Instance.GetString("OfficialRatingDispPref"), null}, {LocalizedStrings.Instance.GetString("StudioDispPref")} }; diff --git a/MediaBrowser.Controller/Library/DeleteOptions.cs b/MediaBrowser.Controller/Library/DeleteOptions.cs new file mode 100644 index 000000000..81ed90899 --- /dev/null +++ b/MediaBrowser.Controller/Library/DeleteOptions.cs @@ -0,0 +1,8 @@ + +namespace MediaBrowser.Controller.Library +{ + public class DeleteOptions + { + public bool DeleteFileLocation { get; set; } + } +} diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index a34cfa78e..0b1ac9137 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -41,7 +41,7 @@ namespace MediaBrowser.Controller.Library /// <param name="parent">The parent.</param> /// <returns>BaseItem.</returns> BaseItem ResolvePath(FileSystemInfo fileInfo, Folder parent = null); - + /// <summary> /// Resolves a set of files into a list of BaseItem /// </summary> @@ -335,7 +335,19 @@ namespace MediaBrowser.Controller.Library /// Deletes the item. /// </summary> /// <param name="item">The item.</param> + /// <param name="options">The options.</param> /// <returns>Task.</returns> - Task DeleteItem(BaseItem item); + Task DeleteItem(BaseItem item, DeleteOptions options); + } + + public static class LibraryManagerExtensions + { + public static Task DeleteItem(this ILibraryManager manager, BaseItem item) + { + return manager.DeleteItem(item, new DeleteOptions + { + DeleteFileLocation = true + }); + } } }
\ No newline at end of file diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 32f2d151d..c88164897 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -111,6 +111,7 @@ <Compile Include="Entities\IHasAwards.cs" /> <Compile Include="Entities\Photo.cs" /> <Compile Include="FileOrganization\IFileOrganizationService.cs" /> + <Compile Include="Library\DeleteOptions.cs" /> <Compile Include="Library\ILibraryPostScanTask.cs" /> <Compile Include="Library\IMetadataSaver.cs" /> <Compile Include="Library\ItemUpdateType.cs" /> diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs index cc4314256..02bca739f 100644 --- a/MediaBrowser.Controller/Persistence/IItemRepository.cs +++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs @@ -96,6 +96,13 @@ namespace MediaBrowser.Controller.Persistence IEnumerable<Guid> GetChildren(Guid parentId); /// <summary> + /// Gets the type of the items of. + /// </summary> + /// <param name="type">The type.</param> + /// <returns>IEnumerable{Guid}.</returns> + IEnumerable<BaseItem> GetItemsOfType(Type type); + + /// <summary> /// Saves the children. /// </summary> /// <param name="parentId">The parent id.</param> diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs index eb4d3d9a6..ab3bf96cf 100644 --- a/MediaBrowser.Controller/Providers/IProviderManager.cs +++ b/MediaBrowser.Controller/Providers/IProviderManager.cs @@ -96,5 +96,19 @@ namespace MediaBrowser.Controller.Providers /// <param name="item">The item.</param> /// <returns>MetadataOptions.</returns> MetadataOptions GetMetadataOptions(IHasImages item); + + /// <summary> + /// Gets the remote search results. + /// </summary> + /// <typeparam name="TItemType">The type of the t item type.</typeparam> + /// <typeparam name="TLookupType">The type of the t lookup type.</typeparam> + /// <param name="searchInfo">The search information.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task{IEnumerable{SearchResult{``1}}}.</returns> + Task<IEnumerable<RemoteSearchResult>> GetRemoteSearchResults<TItemType, TLookupType>( + RemoteSearchQuery<TLookupType> searchInfo, + CancellationToken cancellationToken) + where TItemType : BaseItem, new() + where TLookupType : ItemLookupInfo; } }
\ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/IRemoteMetadataProvider.cs b/MediaBrowser.Controller/Providers/IRemoteMetadataProvider.cs index 268490079..f00a22a3a 100644 --- a/MediaBrowser.Controller/Providers/IRemoteMetadataProvider.cs +++ b/MediaBrowser.Controller/Providers/IRemoteMetadataProvider.cs @@ -1,4 +1,6 @@ -using MediaBrowser.Controller.Entities; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Providers; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -9,29 +11,27 @@ namespace MediaBrowser.Controller.Providers { } - public interface IRemoteMetadataProvider<TItemType, TLookupInfoType> : IMetadataProvider<TItemType>, IRemoteMetadataProvider + public interface IRemoteMetadataProvider<TItemType, in TLookupInfoType> : IMetadataProvider<TItemType>, IRemoteMetadataProvider, IRemoteSearchProvider<TLookupInfoType> where TItemType : IHasMetadata, IHasLookupInfo<TLookupInfoType> where TLookupInfoType : ItemLookupInfo, new() { Task<MetadataResult<TItemType>> GetMetadata(TLookupInfoType info, CancellationToken cancellationToken); } - public interface IRemoteSearchProvider<TLookupInfoType> + public interface IRemoteSearchProvider<in TLookupInfoType> : IMetadataProvider where TLookupInfoType : ItemLookupInfo { - string Name { get; } + Task<IEnumerable<RemoteSearchResult>> GetSearchResults(TLookupInfoType searchInfo, CancellationToken cancellationToken); - Task<IEnumerable<SearchResult<TLookupInfoType>>> GetSearchResults(TLookupInfoType searchInfo, CancellationToken cancellationToken); + /// <summary> + /// Gets the image response. + /// </summary> + /// <param name="url">The URL.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task{HttpResponseInfo}.</returns> + Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken); } - public class SearchResult<T> - where T : ItemLookupInfo - { - public T Item { get; set; } - - public string ImageUrl { get; set; } - } - public class RemoteSearchQuery<T> where T : ItemLookupInfo { diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index d95c27efd..8987cae5f 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -338,6 +338,9 @@ <Compile Include="..\MediaBrowser.Model\Providers\RemoteImageResult.cs"> <Link>Providers\RemoteImageResult.cs</Link> </Compile> + <Compile Include="..\MediaBrowser.Model\Providers\RemoteSearchResult.cs"> + <Link>Providers\RemoteSearchResult.cs</Link> + </Compile> <Compile Include="..\MediaBrowser.Model\Querying\ArtistsQuery.cs"> <Link>Querying\ArtistsQuery.cs</Link> </Compile> diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index 93d52e9c0..76fbe2000 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -325,6 +325,9 @@ <Compile Include="..\MediaBrowser.Model\Providers\RemoteImageResult.cs"> <Link>Providers\RemoteImageResult.cs</Link> </Compile> + <Compile Include="..\MediaBrowser.Model\Providers\RemoteSearchResult.cs"> + <Link>Providers\RemoteSearchResult.cs</Link> + </Compile> <Compile Include="..\MediaBrowser.Model\Querying\ArtistsQuery.cs"> <Link>Querying\ArtistsQuery.cs</Link> </Compile> diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 136a78381..efe450ac1 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -112,6 +112,7 @@ <Compile Include="Notifications\NotificationResult.cs" /> <Compile Include="Notifications\NotificationsSummary.cs" /> <Compile Include="Providers\RemoteImageResult.cs" /> + <Compile Include="Providers\RemoteSearchResult.cs" /> <Compile Include="Querying\ArtistsQuery.cs" /> <Compile Include="Querying\EpisodeQuery.cs" /> <Compile Include="Querying\ItemCountsQuery.cs" /> diff --git a/MediaBrowser.Model/Providers/RemoteSearchResult.cs b/MediaBrowser.Model/Providers/RemoteSearchResult.cs new file mode 100644 index 000000000..122266614 --- /dev/null +++ b/MediaBrowser.Model/Providers/RemoteSearchResult.cs @@ -0,0 +1,39 @@ +using MediaBrowser.Model.Entities; +using System; +using System.Collections.Generic; + +namespace MediaBrowser.Model.Providers +{ + public class RemoteSearchResult : IHasProviderIds + { + /// <summary> + /// Gets or sets the name. + /// </summary> + /// <value>The name.</value> + public string Name { get; set; } + /// <summary> + /// Gets or sets the provider ids. + /// </summary> + /// <value>The provider ids.</value> + public Dictionary<string, string> ProviderIds { get; set; } + /// <summary> + /// Gets or sets the year. + /// </summary> + /// <value>The year.</value> + public int? ProductionYear { get; set; } + public int? IndexNumber { get; set; } + public int? IndexNumberEnd { get; set; } + public int? ParentIndexNumber { get; set; } + + public DateTime? PremiereDate { get; set; } + + public string ImageUrl { get; set; } + + public string SearchProviderName { get; set; } + + public RemoteSearchResult() + { + ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); + } + } +} diff --git a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs index beb8fe887..bc29bad34 100644 --- a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs +++ b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs @@ -7,6 +7,7 @@ using MediaBrowser.Controller.Localization; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Providers; using MediaBrowser.Model.Serialization; using MediaBrowser.Providers.Movies; using System; @@ -42,6 +43,11 @@ namespace MediaBrowser.Providers.BoxSets Current = this; } + public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(BoxSetInfo searchInfo, CancellationToken cancellationToken) + { + return new List<RemoteSearchResult>(); + } + public async Task<MetadataResult<BoxSet>> GetMetadata(BoxSetInfo id, CancellationToken cancellationToken) { var tmdbId = id.GetProviderId(MetadataProviders.Tmdb); @@ -282,5 +288,10 @@ namespace MediaBrowser.Providers.BoxSets public List<Part> parts { get; set; } public Images images { get; set; } } + + public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } } } diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index a961be960..f584c40fa 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -586,7 +586,7 @@ namespace MediaBrowser.Providers.Manager } } - public async Task<IEnumerable<SearchResult<TLookupType>>> GetRemoteSearchResults<TItemType, TLookupType>(RemoteSearchQuery<TLookupType> searchInfo, + public async Task<IEnumerable<RemoteSearchResult>> GetRemoteSearchResults<TItemType, TLookupType>(RemoteSearchQuery<TLookupType> searchInfo, CancellationToken cancellationToken) where TItemType : BaseItem, new() where TLookupType : ItemLookupInfo @@ -623,7 +623,7 @@ namespace MediaBrowser.Providers.Manager } // Nothing found - return new List<SearchResult<TLookupType>>(); + return new List<RemoteSearchResult>(); } } }
\ No newline at end of file diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs index 2dc65e620..2f1c5cf18 100644 --- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs @@ -1,5 +1,4 @@ -using System.Linq; -using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Configuration; using MediaBrowser.Common.IO; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; @@ -9,10 +8,12 @@ using MediaBrowser.Controller.Localization; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Providers; using MediaBrowser.Model.Serialization; using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -45,6 +46,11 @@ namespace MediaBrowser.Providers.Movies Current = this; } + public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(MovieInfo searchInfo, CancellationToken cancellationToken) + { + return new List<RemoteSearchResult>(); + } + public Task<MetadataResult<Movie>> GetMetadata(MovieInfo info, CancellationToken cancellationToken) { return GetItemMetadata<Movie>(info, cancellationToken); @@ -549,5 +555,10 @@ namespace MediaBrowser.Providers.Movies return 1; } } + + public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } } } diff --git a/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs b/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs index 0ad19840e..8c981e2d8 100644 --- a/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs @@ -1,6 +1,9 @@ -using MediaBrowser.Controller.Entities; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Providers; using System; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -13,6 +16,11 @@ namespace MediaBrowser.Providers.Movies return MovieDbProvider.Current.GetItemMetadata<Trailer>(info, cancellationToken); } + public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(TrailerInfo searchInfo, CancellationToken cancellationToken) + { + return new List<RemoteSearchResult>(); + } + public string Name { get { return MovieDbProvider.Current.Name; } @@ -31,5 +39,10 @@ namespace MediaBrowser.Providers.Movies return 1; } } + + public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } } } diff --git a/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs b/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs index 20f4af52c..a9b3d8e11 100644 --- a/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs @@ -5,6 +5,7 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Providers; using MediaBrowser.Model.Serialization; using System; using System.Collections.Generic; @@ -15,7 +16,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.Music { - public class AudioDbAlbumProvider : IRemoteMetadataProvider<MusicAlbum,AlbumInfo>, IHasOrder + public class AudioDbAlbumProvider : IRemoteMetadataProvider<MusicAlbum, AlbumInfo>, IHasOrder { private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; @@ -36,6 +37,11 @@ namespace MediaBrowser.Providers.Music Current = this; } + public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(AlbumInfo searchInfo, CancellationToken cancellationToken) + { + return new List<RemoteSearchResult>(); + } + public async Task<MetadataResult<MusicAlbum>> GetMetadata(AlbumInfo info, CancellationToken cancellationToken) { var result = new MetadataResult<MusicAlbum>(); @@ -81,7 +87,7 @@ namespace MediaBrowser.Providers.Music item.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, result.strMusicBrainzArtistID); item.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, result.strMusicBrainzID); } - + public string Name { get { return "TheAudioDB"; } @@ -112,7 +118,7 @@ namespace MediaBrowser.Providers.Music var url = AudioDbArtistProvider.BaseUrl + "/album-mb.php?i=" + musicBrainzReleaseGroupId; var path = GetAlbumInfoPath(_config.ApplicationPaths, musicBrainzReleaseGroupId); - + Directory.CreateDirectory(Path.GetDirectoryName(path)); using (var response = await _httpClient.Get(new HttpRequestOptions @@ -206,5 +212,10 @@ namespace MediaBrowser.Providers.Music { public List<Album> album { get; set; } } + + public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } } } diff --git a/MediaBrowser.Providers/Music/AudioDbArtistProvider.cs b/MediaBrowser.Providers/Music/AudioDbArtistProvider.cs index 00c5b94e0..665911618 100644 --- a/MediaBrowser.Providers/Music/AudioDbArtistProvider.cs +++ b/MediaBrowser.Providers/Music/AudioDbArtistProvider.cs @@ -5,6 +5,7 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Providers; using MediaBrowser.Model.Serialization; using System; using System.Collections.Generic; @@ -36,6 +37,11 @@ namespace MediaBrowser.Providers.Music Current = this; } + public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ArtistInfo searchInfo, CancellationToken cancellationToken) + { + return new List<RemoteSearchResult>(); + } + public async Task<MetadataResult<MusicArtist>> GetMetadata(ArtistInfo info, CancellationToken cancellationToken) { var result = new MetadataResult<MusicArtist>(); @@ -213,5 +219,10 @@ namespace MediaBrowser.Providers.Music return 1; } } + + public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } } } diff --git a/MediaBrowser.Providers/Music/LastfmAlbumProvider.cs b/MediaBrowser.Providers/Music/LastfmAlbumProvider.cs index e1fd05a50..f7086d8e6 100644 --- a/MediaBrowser.Providers/Music/LastfmAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/LastfmAlbumProvider.cs @@ -4,6 +4,7 @@ using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Providers; using MediaBrowser.Model.Serialization; using MoreLinq; using System; @@ -32,6 +33,11 @@ namespace MediaBrowser.Providers.Music _logger = logger; } + public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(AlbumInfo searchInfo, CancellationToken cancellationToken) + { + return new List<RemoteSearchResult>(); + } + public async Task<MetadataResult<MusicAlbum>> GetMetadata(AlbumInfo id, CancellationToken cancellationToken) { var result = new MetadataResult<MusicAlbum>(); @@ -204,6 +210,11 @@ namespace MediaBrowser.Providers.Music return 2; } } + + public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } } #region Result Objects diff --git a/MediaBrowser.Providers/Music/LastfmArtistProvider.cs b/MediaBrowser.Providers/Music/LastfmArtistProvider.cs index b52185ccc..a50e5f9d5 100644 --- a/MediaBrowser.Providers/Music/LastfmArtistProvider.cs +++ b/MediaBrowser.Providers/Music/LastfmArtistProvider.cs @@ -5,8 +5,10 @@ using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Providers; using MediaBrowser.Model.Serialization; using System; +using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; @@ -38,6 +40,11 @@ namespace MediaBrowser.Providers.Music _logger = logger; } + public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ArtistInfo searchInfo, CancellationToken cancellationToken) + { + return new List<RemoteSearchResult>(); + } + public async Task<MetadataResult<MusicArtist>> GetMetadata(ArtistInfo id, CancellationToken cancellationToken) { var result = new MetadataResult<MusicArtist>(); @@ -170,5 +177,10 @@ namespace MediaBrowser.Providers.Music return 2; } } + + public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } } } diff --git a/MediaBrowser.Providers/Music/MovieDbMusicVideoProvider.cs b/MediaBrowser.Providers/Music/MovieDbMusicVideoProvider.cs index 99fe5c38d..55dcc99f5 100644 --- a/MediaBrowser.Providers/Music/MovieDbMusicVideoProvider.cs +++ b/MediaBrowser.Providers/Music/MovieDbMusicVideoProvider.cs @@ -1,8 +1,10 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Providers; using MediaBrowser.Providers.Movies; using System; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -15,6 +17,11 @@ namespace MediaBrowser.Providers.Music return MovieDbProvider.Current.GetItemMetadata<MusicVideo>(info, cancellationToken); } + public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(MusicVideoInfo searchInfo, CancellationToken cancellationToken) + { + return new List<RemoteSearchResult>(); + } + public string Name { get { return MovieDbProvider.Current.Name; } @@ -24,5 +31,10 @@ namespace MediaBrowser.Providers.Music { return MovieDbProvider.Current.HasChanged(item, date); } + + public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } } } diff --git a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs index 1a3860dab..43ee7bdbc 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs @@ -3,7 +3,9 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Providers; using System; +using System.Collections.Generic; using System.IO; using System.Net; using System.Text; @@ -27,6 +29,11 @@ namespace MediaBrowser.Providers.Music Current = this; } + public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(AlbumInfo searchInfo, CancellationToken cancellationToken) + { + return new List<RemoteSearchResult>(); + } + public async Task<MetadataResult<MusicAlbum>> GetMetadata(AlbumInfo id, CancellationToken cancellationToken) { var releaseId = id.GetReleaseId(); @@ -232,5 +239,10 @@ namespace MediaBrowser.Providers.Music { get { return 0; } } + + public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } } } diff --git a/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs index 3c45a7a48..7c0233d3e 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs @@ -1,7 +1,10 @@ -using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Providers; using System; +using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Net; @@ -14,6 +17,11 @@ namespace MediaBrowser.Providers.Music { public class MusicBrainzArtistProvider : IRemoteMetadataProvider<MusicArtist, ArtistInfo> { + public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ArtistInfo searchInfo, CancellationToken cancellationToken) + { + return new List<RemoteSearchResult>(); + } + public async Task<MetadataResult<MusicArtist>> GetMetadata(ArtistInfo id, CancellationToken cancellationToken) { var result = new MetadataResult<MusicArtist>(); @@ -115,5 +123,10 @@ namespace MediaBrowser.Providers.Music { get { return "MusicBrainz"; } } + + public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } } } diff --git a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs index 3f30626ff..f1cfebcea 100644 --- a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs +++ b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs @@ -5,11 +5,12 @@ using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Providers; using MediaBrowser.Model.Serialization; using MediaBrowser.Providers.Movies; using MediaBrowser.Providers.TV; using System; -using System.Globalization; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -29,6 +30,21 @@ namespace MediaBrowser.Providers.Omdb _logger = logger; } + public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken) + { + return new List<RemoteSearchResult>(); + } + + public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(TrailerInfo searchInfo, CancellationToken cancellationToken) + { + return new List<RemoteSearchResult>(); + } + + public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(MovieInfo searchInfo, CancellationToken cancellationToken) + { + return new List<RemoteSearchResult>(); + } + public string Name { get { return "IMDb via The Open Movie Database"; } @@ -139,5 +155,10 @@ namespace MediaBrowser.Providers.Omdb return new Tuple<string, string>(imdb, tvdb); } + + public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } } } diff --git a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs index 5691190dc..792c9e910 100644 --- a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs +++ b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs @@ -6,6 +6,7 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Providers; using MediaBrowser.Model.Serialization; using MediaBrowser.Providers.Movies; using System; @@ -42,7 +43,7 @@ namespace MediaBrowser.Providers.People get { return "TheMovieDb"; } } - public async Task<IEnumerable<SearchResult<PersonLookupInfo>>> GetSearchResults(PersonLookupInfo searchInfo, CancellationToken cancellationToken) + public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(PersonLookupInfo searchInfo, CancellationToken cancellationToken) { var tmdbId = searchInfo.GetProviderId(MetadataProviders.Tmdb); @@ -59,18 +60,15 @@ namespace MediaBrowser.Providers.People var images = (info.images ?? new Images()).profiles ?? new List<Profile>(); - var result = new SearchResult<PersonLookupInfo> + var result = new RemoteSearchResult { - Item = new PersonLookupInfo - { - Name = info.name - }, + Name = info.name, ImageUrl = images.Count == 0 ? null : (tmdbImageUrl + images[0].file_path) }; - result.Item.SetProviderId(MetadataProviders.Tmdb, info.id.ToString(_usCulture)); - result.Item.SetProviderId(MetadataProviders.Imdb, info.imdb_id.ToString(_usCulture)); + result.SetProviderId(MetadataProviders.Tmdb, info.id.ToString(_usCulture)); + result.SetProviderId(MetadataProviders.Imdb, info.imdb_id.ToString(_usCulture)); return new[] { result }; } @@ -92,19 +90,16 @@ namespace MediaBrowser.Providers.People } } - private SearchResult<PersonLookupInfo> GetSearchResult(PersonSearchResult i, string baseImageUrl) + private RemoteSearchResult GetSearchResult(PersonSearchResult i, string baseImageUrl) { - var result = new SearchResult<PersonLookupInfo> + var result = new RemoteSearchResult { - Item = new PersonLookupInfo - { - Name = i.Name - }, + Name = i.Name, ImageUrl = string.IsNullOrEmpty(i.Profile_Path) ? null : (baseImageUrl + i.Profile_Path) }; - result.Item.SetProviderId(MetadataProviders.Tmdb, i.Id.ToString(_usCulture)); + result.SetProviderId(MetadataProviders.Tmdb, i.Id.ToString(_usCulture)); return result; } @@ -175,7 +170,7 @@ namespace MediaBrowser.Providers.People { var results = await GetSearchResults(info, cancellationToken).ConfigureAwait(false); - return results.Select(i => i.Item.GetProviderId(MetadataProviders.Tmdb)).FirstOrDefault(); + return results.Select(i => i.GetProviderId(MetadataProviders.Tmdb)).FirstOrDefault(); } internal async Task EnsurePersonInfo(string id, CancellationToken cancellationToken) @@ -351,5 +346,10 @@ namespace MediaBrowser.Providers.People } #endregion + + public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } } } diff --git a/MediaBrowser.Providers/TV/FanartSeriesProvider.cs b/MediaBrowser.Providers/TV/FanartSeriesProvider.cs index 5f9754e4a..b640e373b 100644 --- a/MediaBrowser.Providers/TV/FanartSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/FanartSeriesProvider.cs @@ -367,22 +367,32 @@ namespace MediaBrowser.Providers.TV return Path.Combine(dataPath, "fanart.xml"); } - private readonly Task _cachedTask = Task.FromResult(true); - internal Task EnsureSeriesXml(string tvdbId, CancellationToken cancellationToken) + private readonly SemaphoreSlim _ensureSemaphore = new SemaphoreSlim(1, 1); + internal async Task EnsureSeriesXml(string tvdbId, CancellationToken cancellationToken) { - var xmlPath = GetSeriesDataPath(_config.ApplicationPaths, tvdbId); + var xmlPath = GetFanartXmlPath(tvdbId); - var fileInfo = _fileSystem.GetFileSystemInfo(xmlPath); + // Only allow one thread in here at a time since every season will be calling this method, possibly concurrently + await _ensureSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); - if (fileInfo.Exists) + try { - if ((DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 7) + var fileInfo = _fileSystem.GetFileSystemInfo(xmlPath); + + if (fileInfo.Exists) { - return _cachedTask; + if ((DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 7) + { + return; + } } - } - return DownloadSeriesXml(tvdbId, cancellationToken); + await DownloadSeriesXml(tvdbId, cancellationToken).ConfigureAwait(false); + } + finally + { + _ensureSemaphore.Release(); + } } /// <summary> diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs index fafd82948..f4191fe8f 100644 --- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs @@ -1,6 +1,7 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; @@ -20,13 +21,15 @@ namespace MediaBrowser.Providers.TV { private readonly IServerConfigurationManager _config; private readonly ILogger _logger; + private readonly ILibraryManager _libraryManager; private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - public MissingEpisodeProvider(ILogger logger, IServerConfigurationManager config) + public MissingEpisodeProvider(ILogger logger, IServerConfigurationManager config, ILibraryManager libraryManager) { _logger = logger; _config = config; + _libraryManager = libraryManager; } public async Task Run(IEnumerable<IGrouping<string, Series>> series, CancellationToken cancellationToken) @@ -268,7 +271,7 @@ namespace MediaBrowser.Providers.TV { _logger.Info("Removing missing/unaired episode {0} {1}x{2}", episodeToRemove.Series.Name, episodeToRemove.ParentIndexNumber, episodeToRemove.IndexNumber); - await episodeToRemove.Parent.RemoveChild(episodeToRemove, cancellationToken).ConfigureAwait(false); + await _libraryManager.DeleteItem(episodeToRemove).ConfigureAwait(false); hasChanges = true; } @@ -327,7 +330,7 @@ namespace MediaBrowser.Providers.TV { _logger.Info("Removing virtual season {0} {1}", seasonToRemove.Series.Name, seasonToRemove.IndexNumber); - await seasonToRemove.Parent.RemoveChild(seasonToRemove, cancellationToken).ConfigureAwait(false); + await _libraryManager.DeleteItem(seasonToRemove).ConfigureAwait(false); hasChanges = true; } diff --git a/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs b/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs index 5b7679e74..165f901ea 100644 --- a/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs @@ -8,15 +8,16 @@ using MediaBrowser.Controller.Localization; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Providers; using MediaBrowser.Model.Serialization; using MediaBrowser.Providers.Movies; using System; using System.Collections.Generic; using System.Globalization; using System.IO; +using System.Linq; using System.Threading; using System.Threading.Tasks; -using System.Linq; namespace MediaBrowser.Providers.TV { @@ -48,6 +49,11 @@ namespace MediaBrowser.Providers.TV get { return "TheMovieDb"; } } + public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken) + { + return new List<RemoteSearchResult>(); + } + public async Task<MetadataResult<Series>> GetMetadata(SeriesInfo info, CancellationToken cancellationToken) { var result = new MetadataResult<Series>(); @@ -453,5 +459,10 @@ namespace MediaBrowser.Providers.TV return 2; } } + + public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } } } diff --git a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs index 6ba9b4cdc..8c9b8672c 100644 --- a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs +++ b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs @@ -45,7 +45,7 @@ namespace MediaBrowser.Providers.TV group series by tvdbId into g select g; - await new MissingEpisodeProvider(_logger, _config).Run(seriesGroups, cancellationToken).ConfigureAwait(false); + await new MissingEpisodeProvider(_logger, _config, _libraryManager).Run(seriesGroups, cancellationToken).ConfigureAwait(false); var numComplete = 0; diff --git a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs index fd77b9b87..08d21ab39 100644 --- a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs @@ -1,9 +1,11 @@ using MediaBrowser.Common.IO; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Providers; using System; using System.Collections.Generic; using System.Globalization; @@ -34,17 +36,54 @@ namespace MediaBrowser.Providers.TV Current = this; } + public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(EpisodeInfo searchInfo, CancellationToken cancellationToken) + { + var list = new List<RemoteSearchResult>(); + + string seriesTvdbId; + searchInfo.SeriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesTvdbId); + + if (!string.IsNullOrEmpty(seriesTvdbId)) + { + var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesTvdbId); + + try + { + var item = FetchEpisodeData(searchInfo, seriesDataPath, cancellationToken); + + if (item != null) + { + list.Add(new RemoteSearchResult + { + IndexNumber = item.IndexNumber, + Name = item.Name, + ParentIndexNumber = item.ParentIndexNumber, + PremiereDate = item.PremiereDate, + ProductionYear = item.ProductionYear, + ProviderIds = item.ProviderIds, + SearchProviderName = Name, + IndexNumberEnd = item.IndexNumberEnd + }); + } + } + catch (FileNotFoundException) + { + // Don't fail the provider because this will just keep on going and going. + } + } + + return list; + } + public string Name { get { return "TheTVDB"; } } - public Task<MetadataResult<Episode>> GetMetadata(EpisodeInfo id, CancellationToken cancellationToken) + public Task<MetadataResult<Episode>> GetMetadata(EpisodeInfo searchInfo, CancellationToken cancellationToken) { - var episodeId = id; - string seriesTvdbId; - episodeId.SeriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesTvdbId); + searchInfo.SeriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesTvdbId); var result = new MetadataResult<Episode>(); @@ -54,7 +93,7 @@ namespace MediaBrowser.Providers.TV try { - result.Item = FetchEpisodeData(episodeId, seriesDataPath, cancellationToken); + result.Item = FetchEpisodeData(searchInfo, seriesDataPath, cancellationToken); result.HasMetadata = result.Item != null; } catch (FileNotFoundException) @@ -192,9 +231,9 @@ namespace MediaBrowser.Providers.TV var episode = new Episode { - IndexNumber = id.IndexNumber, - ParentIndexNumber = id.ParentIndexNumber, - IndexNumberEnd = id.IndexNumberEnd + IndexNumber = id.IndexNumber, + ParentIndexNumber = id.ParentIndexNumber, + IndexNumberEnd = id.IndexNumberEnd }; try @@ -674,5 +713,10 @@ namespace MediaBrowser.Providers.TV } } } + + public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } } } diff --git a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs index c0ebd4a65..920da9b10 100644 --- a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs @@ -9,6 +9,7 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Providers; using System; using System.Collections.Generic; using System.Globalization; @@ -47,6 +48,11 @@ namespace MediaBrowser.Providers.TV private const string SeriesQuery = "GetSeries.php?seriesname={0}"; private const string SeriesGetZip = "http://www.thetvdb.com/api/{0}/series/{1}/all/{2}.zip"; + public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken) + { + return new List<RemoteSearchResult>(); + } + public async Task<MetadataResult<Series>> GetMetadata(SeriesInfo itemId, CancellationToken cancellationToken) { var result = new MetadataResult<Series>(); @@ -1081,5 +1087,10 @@ namespace MediaBrowser.Providers.TV return 1; } } + + public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } } } diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs index d4d7f2f21..5bf6587a9 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs @@ -2,7 +2,6 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.FileOrganization; -using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; @@ -28,10 +27,11 @@ namespace MediaBrowser.Server.Implementations.FileOrganization private readonly IFileSystem _fileSystem; private readonly IFileOrganizationService _organizationService; private readonly IServerConfigurationManager _config; + private readonly IProviderManager _providerManager; private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - public EpisodeFileOrganizer(IFileOrganizationService organizationService, IServerConfigurationManager config, IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor) + public EpisodeFileOrganizer(IFileOrganizationService organizationService, IServerConfigurationManager config, IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IProviderManager providerManager) { _organizationService = organizationService; _config = config; @@ -39,9 +39,10 @@ namespace MediaBrowser.Server.Implementations.FileOrganization _logger = logger; _libraryManager = libraryManager; _libraryMonitor = libraryMonitor; + _providerManager = providerManager; } - public async Task<FileOrganizationResult> OrganizeEpisodeFile(string path, TvFileOrganizationOptions options, bool overwriteExisting) + public async Task<FileOrganizationResult> OrganizeEpisodeFile(string path, TvFileOrganizationOptions options, bool overwriteExisting, CancellationToken cancellationToken) { _logger.Info("Sorting file {0}", path); @@ -77,7 +78,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization result.ExtractedEndingEpisodeNumber = endingEpisodeNumber; - OrganizeEpisode(path, seriesName, season.Value, episode.Value, endingEpisodeNumber, options, overwriteExisting, result); + await OrganizeEpisode(path, seriesName, season.Value, episode.Value, endingEpisodeNumber, options, overwriteExisting, result, cancellationToken).ConfigureAwait(false); } else { @@ -119,20 +120,20 @@ namespace MediaBrowser.Server.Implementations.FileOrganization return result; } - public async Task<FileOrganizationResult> OrganizeWithCorrection(EpisodeFileOrganizationRequest request, TvFileOrganizationOptions options) + public async Task<FileOrganizationResult> OrganizeWithCorrection(EpisodeFileOrganizationRequest request, TvFileOrganizationOptions options, CancellationToken cancellationToken) { var result = _organizationService.GetResult(request.ResultId); var series = (Series)_libraryManager.GetItemById(new Guid(request.SeriesId)); - OrganizeEpisode(result.OriginalPath, series, request.SeasonNumber, request.EpisodeNumber, request.EndingEpisodeNumber, _config.Configuration.TvFileOrganizationOptions, true, result); + await OrganizeEpisode(result.OriginalPath, series, request.SeasonNumber, request.EpisodeNumber, request.EndingEpisodeNumber, _config.Configuration.TvFileOrganizationOptions, true, result, cancellationToken).ConfigureAwait(false); await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false); return result; } - private void OrganizeEpisode(string sourcePath, string seriesName, int seasonNumber, int episodeNumber, int? endingEpiosdeNumber, TvFileOrganizationOptions options, bool overwriteExisting, FileOrganizationResult result) + private Task OrganizeEpisode(string sourcePath, string seriesName, int seasonNumber, int episodeNumber, int? endingEpiosdeNumber, TvFileOrganizationOptions options, bool overwriteExisting, FileOrganizationResult result, CancellationToken cancellationToken) { var series = GetMatchingSeries(seriesName, result); @@ -142,18 +143,18 @@ namespace MediaBrowser.Server.Implementations.FileOrganization result.Status = FileSortingStatus.Failure; result.StatusMessage = msg; _logger.Warn(msg); - return; + return Task.FromResult(true); } - OrganizeEpisode(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, options, overwriteExisting, result); + return OrganizeEpisode(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, options, overwriteExisting, result, cancellationToken); } - private void OrganizeEpisode(string sourcePath, Series series, int seasonNumber, int episodeNumber, int? endingEpiosdeNumber, TvFileOrganizationOptions options, bool overwriteExisting, FileOrganizationResult result) + private async Task OrganizeEpisode(string sourcePath, Series series, int seasonNumber, int episodeNumber, int? endingEpiosdeNumber, TvFileOrganizationOptions options, bool overwriteExisting, FileOrganizationResult result, CancellationToken cancellationToken) { _logger.Info("Sorting file {0} into series {1}", sourcePath, series.Path); // Proceed to sort the file - var newPath = GetNewPath(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, options); + var newPath = await GetNewPath(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, options, cancellationToken).ConfigureAwait(false); if (string.IsNullOrEmpty(newPath)) { @@ -326,25 +327,33 @@ namespace MediaBrowser.Server.Implementations.FileOrganization /// <param name="endingEpisodeNumber">The ending episode number.</param> /// <param name="options">The options.</param> /// <returns>System.String.</returns> - private string GetNewPath(string sourcePath, Series series, int seasonNumber, int episodeNumber, int? endingEpisodeNumber, TvFileOrganizationOptions options) + private async Task<string> GetNewPath(string sourcePath, Series series, int seasonNumber, int episodeNumber, int? endingEpisodeNumber, TvFileOrganizationOptions options, CancellationToken cancellationToken) { - // If season and episode numbers match - var currentEpisodes = series.RecursiveChildren.OfType<Episode>() - .Where(i => i.IndexNumber.HasValue && - i.IndexNumber.Value == episodeNumber && - i.ParentIndexNumber.HasValue && - i.ParentIndexNumber.Value == seasonNumber) - .ToList(); + var episodeInfo = new EpisodeInfo + { + IndexNumber = episodeNumber, + IndexNumberEnd = endingEpisodeNumber, + MetadataCountryCode = series.GetPreferredMetadataCountryCode(), + MetadataLanguage = series.GetPreferredMetadataLanguage(), + ParentIndexNumber = seasonNumber, + SeriesProviderIds = series.ProviderIds + }; - if (currentEpisodes.Count == 0) + var searchResults = await _providerManager.GetRemoteSearchResults<Episode, EpisodeInfo>(new RemoteSearchQuery<EpisodeInfo> + { + SearchInfo = episodeInfo + + }, cancellationToken).ConfigureAwait(false); + + var episode = searchResults.FirstOrDefault(); + + if (episode == null) { return null; } var newPath = GetSeasonFolderPath(series, seasonNumber, options); - var episode = currentEpisodes.First(); - var episodeFileName = GetEpisodeFileName(sourcePath, series.Name, seasonNumber, episodeNumber, endingEpisodeNumber, episode.Name, options); newPath = Path.Combine(newPath, episodeFileName); diff --git a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs index c03ceb6e5..7cf38b0a0 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs @@ -3,9 +3,9 @@ using MediaBrowser.Common.IO; using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.FileOrganization; -using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; +using MediaBrowser.Controller.Providers; using MediaBrowser.Model.FileOrganization; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Querying; @@ -25,8 +25,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization private readonly ILibraryManager _libraryManager; private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; + private readonly IProviderManager _providerManager; - public FileOrganizationService(ITaskManager taskManager, IFileOrganizationRepository repo, ILogger logger, ILibraryMonitor libraryMonitor, ILibraryManager libraryManager, IServerConfigurationManager config, IFileSystem fileSystem) + public FileOrganizationService(ITaskManager taskManager, IFileOrganizationRepository repo, ILogger logger, ILibraryMonitor libraryMonitor, ILibraryManager libraryManager, IServerConfigurationManager config, IFileSystem fileSystem, IProviderManager providerManager) { _taskManager = taskManager; _repo = repo; @@ -35,6 +36,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization _libraryManager = libraryManager; _config = config; _fileSystem = fileSystem; + _providerManager = providerManager; } public void BeginProcessNewFiles() @@ -103,9 +105,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization } var organizer = new EpisodeFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager, - _libraryMonitor); + _libraryMonitor, _providerManager); - await organizer.OrganizeEpisodeFile(result.OriginalPath, _config.Configuration.TvFileOrganizationOptions, true) + await organizer.OrganizeEpisodeFile(result.OriginalPath, _config.Configuration.TvFileOrganizationOptions, true, CancellationToken.None) .ConfigureAwait(false); } @@ -117,9 +119,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization public async Task PerformEpisodeOrganization(EpisodeFileOrganizationRequest request) { var organizer = new EpisodeFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager, - _libraryMonitor); + _libraryMonitor, _providerManager); - await organizer.OrganizeWithCorrection(request, _config.Configuration.TvFileOrganizationOptions).ConfigureAwait(false); + await organizer.OrganizeWithCorrection(request, _config.Configuration.TvFileOrganizationOptions, CancellationToken.None).ConfigureAwait(false); } } } diff --git a/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs b/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs index 3c5e1ed0e..fbb743f94 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs @@ -2,8 +2,8 @@ using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.FileOrganization; -using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Logging; using System; using System.Collections.Generic; @@ -20,8 +20,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization private readonly IFileSystem _fileSystem; private readonly IServerConfigurationManager _config; private readonly IFileOrganizationService _organizationService; + private readonly IProviderManager _providerManager; - public OrganizerScheduledTask(ILibraryMonitor libraryMonitor, ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem, IServerConfigurationManager config, IFileOrganizationService organizationService) + public OrganizerScheduledTask(ILibraryMonitor libraryMonitor, ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem, IServerConfigurationManager config, IFileOrganizationService organizationService, IProviderManager providerManager) { _libraryMonitor = libraryMonitor; _libraryManager = libraryManager; @@ -29,6 +30,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization _fileSystem = fileSystem; _config = config; _organizationService = organizationService; + _providerManager = providerManager; } public string Name @@ -48,7 +50,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization public Task Execute(CancellationToken cancellationToken, IProgress<double> progress) { - return new TvFolderOrganizer(_libraryManager, _logger, _fileSystem, _libraryMonitor, _organizationService, _config) + return new TvFolderOrganizer(_libraryManager, _logger, _fileSystem, _libraryMonitor, _organizationService, _config, _providerManager) .Organize(_config.Configuration.TvFileOrganizationOptions, cancellationToken, progress); } diff --git a/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs index 85b45cf2c..9df6e7f1c 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs @@ -1,8 +1,8 @@ using MediaBrowser.Common.IO; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.FileOrganization; -using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.FileOrganization; @@ -24,8 +24,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization private readonly IFileSystem _fileSystem; private readonly IFileOrganizationService _organizationService; private readonly IServerConfigurationManager _config; + private readonly IProviderManager _providerManager; - public TvFolderOrganizer(ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, IFileOrganizationService organizationService, IServerConfigurationManager config) + public TvFolderOrganizer(ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, IFileOrganizationService organizationService, IServerConfigurationManager config, IProviderManager providerManager) { _libraryManager = libraryManager; _logger = logger; @@ -33,6 +34,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization _libraryMonitor = libraryMonitor; _organizationService = organizationService; _config = config; + _providerManager = providerManager; } public async Task Organize(TvFileOrganizationOptions options, CancellationToken cancellationToken, IProgress<double> progress) @@ -57,9 +59,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization foreach (var file in eligibleFiles) { var organizer = new EpisodeFileOrganizer(_organizationService, _config, _fileSystem, _logger, _libraryManager, - _libraryMonitor); + _libraryMonitor, _providerManager); - var result = await organizer.OrganizeEpisodeFile(file.FullName, options, false).ConfigureAwait(false); + var result = await organizer.OrganizeEpisodeFile(file.FullName, options, false, cancellationToken).ConfigureAwait(false); if (result.Status == FileSortingStatus.Success) { diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index b4c442ec8..009e4716d 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -1,4 +1,5 @@ -using Funq; +using System.Net.Sockets; +using Funq; using MediaBrowser.Common; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs index 8634919fc..fa1d4b0d5 100644 --- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs +++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs @@ -3,7 +3,6 @@ using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Server.Implementations.ScheduledTasks; using Microsoft.Win32; diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 656e0993f..c2044476a 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -408,8 +408,14 @@ namespace MediaBrowser.Server.Implementations.Library LibraryItemsCache.AddOrUpdate(item.Id, item, delegate { return item; }); } - public async Task DeleteItem(BaseItem item) + public async Task DeleteItem(BaseItem item, DeleteOptions options) { + _logger.Debug("Deleting item, Type: {0}, Name: {1}, Path: {2}, Id: {3}", + item.GetType().Name, + item.Name, + item.Path ?? string.Empty, + item.Id); + var parent = item.Parent; var locationType = item.LocationType; @@ -436,7 +442,7 @@ namespace MediaBrowser.Server.Implementations.Library } } - if (locationType == LocationType.FileSystem || locationType == LocationType.Offline) + if (options.DeleteFileLocation && (locationType == LocationType.FileSystem || locationType == LocationType.Offline)) { foreach (var path in item.GetDeletePaths().ToList()) { @@ -462,15 +468,14 @@ namespace MediaBrowser.Server.Implementations.Library { await parent.RemoveChild(item, CancellationToken.None).ConfigureAwait(false); } - else - { - throw new InvalidOperationException("Don't know how to delete " + item.Name); - } + await ItemRepository.DeleteItem(item.Id, CancellationToken.None).ConfigureAwait(false); foreach (var child in children) { await ItemRepository.DeleteItem(child.Id, CancellationToken.None).ConfigureAwait(false); } + + ReportItemRemoved(item); } private IEnumerable<string> GetMetadataPaths(BaseItem item, IEnumerable<BaseItem> children) diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index f25cf541b..989ed3c35 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -726,7 +726,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv foreach (var channelInfo in allChannelsList) { cancellationToken.ThrowIfCancellationRequested(); - + try { var item = await GetChannel(channelInfo.Item2, channelInfo.Item1, cancellationToken).ConfigureAwait(false); @@ -764,7 +764,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv foreach (var item in list) { cancellationToken.ThrowIfCancellationRequested(); - + // Avoid implicitly captured closure var currentChannel = item; @@ -793,17 +793,44 @@ namespace MediaBrowser.Server.Implementations.LiveTv double percent = numComplete; percent /= allChannelsList.Count; - progress.Report(80 * percent + 10); + progress.Report(70 * percent + 10); } _programs = programs.ToDictionary(i => i.Id); + progress.Report(80); // Load these now which will prefetch metadata await GetRecordings(new RecordingQuery(), cancellationToken).ConfigureAwait(false); - + progress.Report(85); + + await DeleteOldPrograms(_programs.Keys.ToList(), progress, cancellationToken).ConfigureAwait(false); + progress.Report(100); } + private async Task DeleteOldPrograms(List<Guid> currentIdList, IProgress<double> progress, CancellationToken cancellationToken) + { + var list = _itemRepo.GetItemsOfType(typeof(LiveTvProgram)).ToList(); + + var numComplete = 0; + + foreach (var program in list) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (!currentIdList.Contains(program.Id)) + { + await _libraryManager.DeleteItem(program).ConfigureAwait(false); + } + + numComplete++; + double percent = numComplete; + percent /= list.Count; + + progress.Report(15 * percent + 85); + } + } + private double GetGuideDays(int channelCount) { if (_config.Configuration.LiveTvOptions.GuideDays.HasValue) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 1098dbf6d..70362654e 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -281,25 +281,30 @@ namespace MediaBrowser.Server.Implementations.Persistence { if (reader.Read()) { - var typeString = reader.GetString(0); + return GetItem(reader); + } + } + return null; + } + } - var type = _typeMapper.GetType(typeString); + private BaseItem GetItem(IDataReader reader) + { + var typeString = reader.GetString(0); - if (type == null) - { - _logger.Debug("Unknown type {0}", typeString); + var type = _typeMapper.GetType(typeString); - return null; - } + if (type == null) + { + _logger.Debug("Unknown type {0}", typeString); - using (var stream = reader.GetMemoryStream(1)) - { - return _jsonSerializer.DeserializeFromStream(stream, type) as BaseItem; - } - } - } return null; } + + using (var stream = reader.GetMemoryStream(1)) + { + return _jsonSerializer.DeserializeFromStream(stream, type) as BaseItem; + } } /// <summary> @@ -468,6 +473,34 @@ namespace MediaBrowser.Server.Implementations.Persistence } } + public IEnumerable<BaseItem> GetItemsOfType(Type type) + { + if (type == null) + { + throw new ArgumentNullException("type"); + } + + using (var cmd = _connection.CreateCommand()) + { + cmd.CommandText = "select type,data from TypedBaseItems where type = @type"; + + cmd.Parameters.Add(cmd, "@type", DbType.String).Value = type.FullName; + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + while (reader.Read()) + { + var item = GetItem(reader); + + if (item != null) + { + yield return item; + } + } + } + } + } + public async Task DeleteItem(Guid id, CancellationToken cancellationToken) { if (id == Guid.Empty) diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index 10dec2da6..527e00f62 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -363,7 +363,7 @@ namespace MediaBrowser.ServerApplication var newsService = new Server.Implementations.News.NewsService(ApplicationPaths, JsonSerializer); RegisterSingleInstance<INewsService>(newsService); - var fileOrganizationService = new FileOrganizationService(TaskManager, FileOrganizationRepository, Logger, LibraryMonitor, LibraryManager, ServerConfigurationManager, FileSystemManager); + var fileOrganizationService = new FileOrganizationService(TaskManager, FileOrganizationRepository, Logger, LibraryMonitor, LibraryManager, ServerConfigurationManager, FileSystemManager, ProviderManager); RegisterSingleInstance<IFileOrganizationService>(fileOrganizationService); progress.Report(15); diff --git a/MediaBrowser.ServerApplication/Native/Autorun.cs b/MediaBrowser.ServerApplication/Native/Autorun.cs index d1c02db84..0262f711e 100644 --- a/MediaBrowser.ServerApplication/Native/Autorun.cs +++ b/MediaBrowser.ServerApplication/Native/Autorun.cs @@ -16,15 +16,17 @@ namespace MediaBrowser.ServerApplication.Native { var shortcutPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu), "Media Browser 3", "Media Browser Server.lnk"); + var startupPath = Environment.GetFolderPath(Environment.SpecialFolder.Startup); + if (autorun) { //Copy our shortut into the startup folder for this user - File.Copy(shortcutPath, Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Startup), Path.GetFileName(shortcutPath) ?? "MBstartup.lnk"), true); + File.Copy(shortcutPath, Path.Combine(startupPath, Path.GetFileName(shortcutPath) ?? "MBstartup.lnk"), true); } else { //Remove our shortcut from the startup folder for this user - File.Delete(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Startup), Path.GetFileName(shortcutPath) ?? "MBstartup.lnk")); + File.Delete(Path.Combine(startupPath, Path.GetFileName(shortcutPath) ?? "MBstartup.lnk")); } } } diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index a958415ff..b41293e3e 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <metadata> <id>MediaBrowser.Common.Internal</id> - <version>3.0.329</version> + <version>3.0.330</version> <title>MediaBrowser.Common.Internal</title> <authors>Luke</authors> <owners>ebr,Luke,scottisafool</owners> @@ -12,7 +12,7 @@ <description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description> <copyright>Copyright © Media Browser 2013</copyright> <dependencies> - <dependency id="MediaBrowser.Common" version="3.0.329" /> + <dependency id="MediaBrowser.Common" version="3.0.330" /> <dependency id="NLog" version="2.1.0" /> <dependency id="SimpleInjector" version="2.4.1" /> <dependency id="sharpcompress" version="0.10.2" /> diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index a552297d4..ef257122b 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <metadata> <id>MediaBrowser.Common</id> - <version>3.0.329</version> + <version>3.0.330</version> <title>MediaBrowser.Common</title> <authors>Media Browser Team</authors> <owners>ebr,Luke,scottisafool</owners> diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index 15da720c2..3bb5887c1 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <metadata> <id>MediaBrowser.Server.Core</id> - <version>3.0.329</version> + <version>3.0.330</version> <title>Media Browser.Server.Core</title> <authors>Media Browser Team</authors> <owners>ebr,Luke,scottisafool</owners> @@ -12,7 +12,7 @@ <description>Contains core components required to build plugins for Media Browser Server.</description> <copyright>Copyright © Media Browser 2013</copyright> <dependencies> - <dependency id="MediaBrowser.Common" version="3.0.329" /> + <dependency id="MediaBrowser.Common" version="3.0.330" /> </dependencies> </metadata> <files> |
