diff options
22 files changed, 193 insertions, 101 deletions
diff --git a/MediaBrowser.Api/Sync/SyncService.cs b/MediaBrowser.Api/Sync/SyncService.cs index 57b5fa3f9..929d0a463 100644 --- a/MediaBrowser.Api/Sync/SyncService.cs +++ b/MediaBrowser.Api/Sync/SyncService.cs @@ -3,6 +3,7 @@ using MediaBrowser.Controller.Sync; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Sync; using ServiceStack; +using System.Collections.Generic; using System.Threading.Tasks; namespace MediaBrowser.Api.Sync @@ -50,9 +51,11 @@ namespace MediaBrowser.Api.Sync { } - [Route("/Sync/Schedules", "POST", Summary = "Gets sync schedules.")] - public class CreateSyncSchedule : SyncScheduleRequest + [Route("/Sync/Targets", "GET", Summary = "Gets a list of available sync targets.")] + public class GetSyncTarget : IReturn<List<SyncTarget>> { + [ApiMember(Name = "UserId", Description = "UserId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] + public string UserId { get; set; } } [Authenticated] @@ -65,6 +68,13 @@ namespace MediaBrowser.Api.Sync _syncManager = syncManager; } + public object Get(GetSyncTarget request) + { + var result = _syncManager.GetSyncTargets(request.UserId); + + return ToOptimizedResult(result); + } + public object Get(GetSyncJobs request) { var result = _syncManager.GetJobs(new SyncJobQuery @@ -119,12 +129,5 @@ namespace MediaBrowser.Api.Sync Task.WaitAll(task); } - - public void Post(CreateSyncSchedule request) - { - var task = _syncManager.CreateSchedule(request); - - Task.WaitAll(task); - } } } diff --git a/MediaBrowser.Controller/Sync/ISyncManager.cs b/MediaBrowser.Controller/Sync/ISyncManager.cs index ef4b84f27..714e71a1f 100644 --- a/MediaBrowser.Controller/Sync/ISyncManager.cs +++ b/MediaBrowser.Controller/Sync/ISyncManager.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Model.Querying; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Querying; using MediaBrowser.Model.Sync; using System.Collections.Generic; using System.Threading.Tasks; @@ -15,13 +16,6 @@ namespace MediaBrowser.Controller.Sync Task<List<SyncJob>> CreateJob(SyncJobRequest request); /// <summary> - /// Creates the schedule. - /// </summary> - /// <param name="request">The request.</param> - /// <returns>Task.</returns> - Task<SyncSchedule> CreateSchedule(SyncScheduleRequest request); - - /// <summary> /// Gets the jobs. /// </summary> /// <returns>QueryResult<SyncJob>.</returns> @@ -69,7 +63,13 @@ namespace MediaBrowser.Controller.Sync /// <summary> /// Gets the synchronize targets. /// </summary> - /// <returns>IEnumerable<SyncTarget>.</returns> - IEnumerable<SyncTarget> GetSyncTargets(); + IEnumerable<SyncTarget> GetSyncTargets(string userId); + + /// <summary> + /// Supportses the synchronize. + /// </summary> + /// <param name="item">The item.</param> + /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> + bool SupportsSync(BaseItem item); } } diff --git a/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs b/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs index 414bec715..230b5e145 100644 --- a/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs +++ b/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs @@ -86,9 +86,17 @@ namespace MediaBrowser.Dlna.Channels return; } - var device = await Device.CreateuPnpDeviceAsync(new Uri(location), _httpClient, _config, _logger).ConfigureAwait(false); + var device = await Device.CreateuPnpDeviceAsync(new Uri(location), _httpClient, _config, _logger) + .ConfigureAwait(false); - _servers.Add(device); + if (!_servers.Any(i => string.Equals(i.Properties.UUID, device.Properties.UUID, StringComparison.OrdinalIgnoreCase))) + { + _servers.Add(device); + } + } + catch (Exception ex) + { + } finally { diff --git a/MediaBrowser.Dlna/PlayTo/Device.cs b/MediaBrowser.Dlna/PlayTo/Device.cs index 272e34a78..0d7c450d6 100644 --- a/MediaBrowser.Dlna/PlayTo/Device.cs +++ b/MediaBrowser.Dlna/PlayTo/Device.cs @@ -757,13 +757,17 @@ namespace MediaBrowser.Dlna.PlayTo var deviceProperties = new DeviceInfo(); + var friendlyNames = new List<string>(); + var name = document.Descendants(uPnpNamespaces.ud.GetName("friendlyName")).FirstOrDefault(); - if (name != null) - deviceProperties.Name = name.Value; + if (name != null && !string.IsNullOrWhiteSpace(name.Value)) + friendlyNames.Add(name.Value); + + var room = document.Descendants(uPnpNamespaces.ud.GetName("roomName")).FirstOrDefault(); + if (room != null && !string.IsNullOrWhiteSpace(room.Value)) + friendlyNames.Add(room.Value); - var name2 = document.Descendants(uPnpNamespaces.ud.GetName("roomName")).FirstOrDefault(); - if (name2 != null) - deviceProperties.Name = name2.Value; + deviceProperties.Name = string.Join(" ", friendlyNames.ToArray()); var model = document.Descendants(uPnpNamespaces.ud.GetName("modelName")).FirstOrDefault(); if (model != null) diff --git a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs index cea397cae..a5b816919 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs @@ -7,7 +7,6 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Session; using MediaBrowser.Dlna.Ssdp; -using MediaBrowser.Model.Events; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Session; using System; diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index 17463941c..a892f8bf1 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -866,9 +866,6 @@ <Compile Include="..\MediaBrowser.Model\Sync\SyncScheduleQuery.cs"> <Link>Sync\SyncScheduleQuery.cs</Link> </Compile> - <Compile Include="..\MediaBrowser.Model\Sync\SyncScheduleRequest.cs"> - <Link>Sync\SyncScheduleRequest.cs</Link> - </Compile> <Compile Include="..\MediaBrowser.Model\Sync\SyncTarget.cs"> <Link>Sync\SyncTarget.cs</Link> </Compile> diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index 9dafe0cef..ab2a99109 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -823,9 +823,6 @@ <Compile Include="..\MediaBrowser.Model\Sync\SyncScheduleQuery.cs"> <Link>Sync\SyncScheduleQuery.cs</Link> </Compile> - <Compile Include="..\MediaBrowser.Model\Sync\SyncScheduleRequest.cs"> - <Link>Sync\SyncScheduleRequest.cs</Link> - </Compile> <Compile Include="..\MediaBrowser.Model\Sync\SyncTarget.cs"> <Link>Sync\SyncTarget.cs</Link> </Compile> diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index 7f7a4b8f0..d138ddf9b 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -53,6 +53,8 @@ namespace MediaBrowser.Model.Dto public bool IsUnidentified { get; set; } public int? AnimeSeriesIndex { get; set; } + + public bool? SupportsSync { get; set; } /// <summary> /// Gets or sets the DVD season number. diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 3c265ff91..6cdd2b8f5 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -303,7 +303,6 @@ <Compile Include="Sync\SyncQuality.cs" /> <Compile Include="Sync\SyncSchedule.cs" /> <Compile Include="Sync\SyncScheduleQuery.cs" /> - <Compile Include="Sync\SyncScheduleRequest.cs" /> <Compile Include="Sync\SyncTarget.cs" /> <Compile Include="System\LogFile.cs" /> <Compile Include="Themes\AppTheme.cs" /> diff --git a/MediaBrowser.Model/Querying/ItemFields.cs b/MediaBrowser.Model/Querying/ItemFields.cs index 790638446..9ceca311c 100644 --- a/MediaBrowser.Model/Querying/ItemFields.cs +++ b/MediaBrowser.Model/Querying/ItemFields.cs @@ -157,6 +157,11 @@ namespace MediaBrowser.Model.Querying Studios, /// <summary> + /// The synchronize information + /// </summary> + SyncInfo, + + /// <summary> /// The taglines of the item /// </summary> Taglines, diff --git a/MediaBrowser.Model/Sync/SyncJob.cs b/MediaBrowser.Model/Sync/SyncJob.cs index 34809834c..74dd79497 100644 --- a/MediaBrowser.Model/Sync/SyncJob.cs +++ b/MediaBrowser.Model/Sync/SyncJob.cs @@ -43,5 +43,10 @@ namespace MediaBrowser.Model.Sync /// </summary> /// <value>The transcoded path.</value> public string TranscodedPath { get; set; } + /// <summary> + /// Gets or sets the name. + /// </summary> + /// <value>The name.</value> + public string Name { get; set; } } } diff --git a/MediaBrowser.Model/Sync/SyncJobRequest.cs b/MediaBrowser.Model/Sync/SyncJobRequest.cs index 42b744db6..cd833068e 100644 --- a/MediaBrowser.Model/Sync/SyncJobRequest.cs +++ b/MediaBrowser.Model/Sync/SyncJobRequest.cs @@ -10,19 +10,25 @@ namespace MediaBrowser.Model.Sync /// <value>The device identifier.</value> public List<string> TargetIds { get; set; } /// <summary> - /// Gets or sets the item identifier. + /// Gets or sets the item ids. /// </summary> - /// <value>The item identifier.</value> - public string ItemId { get; set; } + /// <value>The item ids.</value> + public List<string> ItemIds { get; set; } /// <summary> /// Gets or sets the quality. /// </summary> /// <value>The quality.</value> public SyncQuality Quality { get; set; } + /// <summary> + /// Gets or sets the name. + /// </summary> + /// <value>The name.</value> + public string Name { get; set; } public SyncJobRequest() { TargetIds = new List<string>(); + ItemIds = new List<string>(); } } } diff --git a/MediaBrowser.Model/Sync/SyncScheduleRequest.cs b/MediaBrowser.Model/Sync/SyncScheduleRequest.cs deleted file mode 100644 index 076548f57..000000000 --- a/MediaBrowser.Model/Sync/SyncScheduleRequest.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Collections.Generic; - -namespace MediaBrowser.Model.Sync -{ - public class SyncScheduleRequest - { - /// <summary> - /// Gets or sets the device identifier. - /// </summary> - /// <value>The device identifier.</value> - public List<string> TargetIds { get; set; } - /// <summary> - /// Gets or sets the quality. - /// </summary> - /// <value>The quality.</value> - public SyncQuality Quality { get; set; } - - public SyncScheduleRequest() - { - TargetIds = new List<string>(); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index f01d973d6..c4499fac0 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -12,6 +12,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; +using MediaBrowser.Controller.Sync; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -38,8 +39,9 @@ namespace MediaBrowser.Server.Implementations.Dto private readonly IProviderManager _providerManager; private readonly Func<IChannelManager> _channelManagerFactory; + private readonly ISyncManager _syncManager; - public DtoService(ILogger logger, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IImageProcessor imageProcessor, IServerConfigurationManager config, IFileSystem fileSystem, IProviderManager providerManager, Func<IChannelManager> channelManagerFactory) + public DtoService(ILogger logger, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IImageProcessor imageProcessor, IServerConfigurationManager config, IFileSystem fileSystem, IProviderManager providerManager, Func<IChannelManager> channelManagerFactory, ISyncManager syncManager) { _logger = logger; _libraryManager = libraryManager; @@ -50,6 +52,7 @@ namespace MediaBrowser.Server.Implementations.Dto _fileSystem = fileSystem; _providerManager = providerManager; _channelManagerFactory = channelManagerFactory; + _syncManager = syncManager; } /// <summary> @@ -146,6 +149,11 @@ namespace MediaBrowser.Server.Implementations.Dto AttachBasicFields(dto, item, owner, fields); + if (fields.Contains(ItemFields.SyncInfo)) + { + dto.SupportsSync = _syncManager.SupportsSync(item); + } + if (fields.Contains(ItemFields.SoundtrackIds)) { var hasSoundtracks = item as IHasSoundtracks; diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 94715b490..d0ea07056 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -158,7 +158,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer HostContext.Config.HandlerFactoryPath = ListenerRequest.GetHandlerPathIfAny(UrlPrefixes.First()); _listener = NativeWebSocket.IsSupported - ? _listener = new WebSocketSharpListener(_logger, _threadPoolManager) + ? _listener = new HttpListenerServer(_logger, _threadPoolManager) : _listener = new WebSocketSharpListener(_logger, _threadPoolManager); _listener.WebSocketHandler = WebSocketHandler; diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 38e82db4f..9655771c6 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -272,6 +272,7 @@ <Compile Include="Sorting\VideoBitRateComparer.cs" /> <Compile Include="Sync\AppSyncProvider.cs" /> <Compile Include="Sync\CloudSyncProvider.cs" /> + <Compile Include="Sync\MockSyncProvider.cs" /> <Compile Include="Sync\SyncManager.cs" /> <Compile Include="Themes\AppThemeManager.cs" /> <Compile Include="Udp\UdpMessageReceivedEventArgs.cs" /> diff --git a/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs b/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs index 6dec2b717..c3cd047b6 100644 --- a/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs +++ b/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs @@ -10,12 +10,12 @@ namespace MediaBrowser.Server.Implementations.Sync { public IEnumerable<SyncTarget> GetSyncTargets() { - throw new NotImplementedException(); + return new List<SyncTarget>(); } public DeviceProfile GetDeviceProfile(SyncTarget target) { - throw new NotImplementedException(); + return new DeviceProfile(); } public string Name diff --git a/MediaBrowser.Server.Implementations/Sync/CloudSyncProvider.cs b/MediaBrowser.Server.Implementations/Sync/CloudSyncProvider.cs index ec3ac1239..fd12b1f8a 100644 --- a/MediaBrowser.Server.Implementations/Sync/CloudSyncProvider.cs +++ b/MediaBrowser.Server.Implementations/Sync/CloudSyncProvider.cs @@ -19,12 +19,12 @@ namespace MediaBrowser.Server.Implementations.Sync public IEnumerable<SyncTarget> GetSyncTargets() { - throw new NotImplementedException(); + return new List<SyncTarget>(); } public DeviceProfile GetDeviceProfile(SyncTarget target) { - throw new NotImplementedException(); + return new DeviceProfile(); } public string Name diff --git a/MediaBrowser.Server.Implementations/Sync/MockSyncProvider.cs b/MediaBrowser.Server.Implementations/Sync/MockSyncProvider.cs new file mode 100644 index 000000000..bc079ad80 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sync/MockSyncProvider.cs @@ -0,0 +1,33 @@ +using MediaBrowser.Common.Extensions; +using MediaBrowser.Controller.Sync; +using MediaBrowser.Model.Dlna; +using MediaBrowser.Model.Sync; +using System.Collections.Generic; + +namespace MediaBrowser.Server.Implementations.Sync +{ + public class MockSyncProvider : ISyncProvider + { + public string Name + { + get { return "Dummy Sync"; } + } + + public IEnumerable<SyncTarget> GetSyncTargets() + { + return new List<SyncTarget> + { + new SyncTarget + { + Id = "mock".GetMD5().ToString("N"), + Name = "Mock Sync" + } + }; + } + + public DeviceProfile GetDeviceProfile(SyncTarget target) + { + return new DeviceProfile(); + } + } +} diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs index 508fc188d..50f1030f3 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs @@ -1,4 +1,7 @@ -using MediaBrowser.Controller.Sync; +using MediaBrowser.Common.Extensions; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Sync; +using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Sync; using System; @@ -10,7 +13,7 @@ namespace MediaBrowser.Server.Implementations.Sync { public class SyncManager : ISyncManager { - private ISyncProvider[] _providers = new ISyncProvider[]{}; + private ISyncProvider[] _providers = new ISyncProvider[] { }; public void AddParts(IEnumerable<ISyncProvider> providers) { @@ -22,11 +25,6 @@ namespace MediaBrowser.Server.Implementations.Sync throw new NotImplementedException(); } - public Task<SyncSchedule> CreateSchedule(SyncScheduleRequest request) - { - throw new NotImplementedException(); - } - public QueryResult<SyncJob> GetJobs(SyncJobQuery query) { throw new NotImplementedException(); @@ -57,9 +55,70 @@ namespace MediaBrowser.Server.Implementations.Sync throw new NotImplementedException(); } - public IEnumerable<SyncTarget> GetSyncTargets() + public IEnumerable<SyncTarget> GetSyncTargets(string userId) + { + return _providers + .SelectMany(GetSyncTargets) + .OrderBy(i => i.Name); + } + + private IEnumerable<SyncTarget> GetSyncTargets(ISyncProvider provider) + { + var providerId = GetSyncProviderId(provider); + + return provider.GetSyncTargets().Select(i => new SyncTarget + { + Name = i.Name, + Id = providerId + "-" + i.Id + }); + } + + private ISyncProvider GetSyncProvider(SyncTarget target) + { + var providerId = target.Id.Split(new[] { '-' }, 2).First(); + + return _providers.First(i => string.Equals(providerId, GetSyncProviderId(i))); + } + + private string GetSyncProviderId(ISyncProvider provider) + { + return (provider.GetType().Name + provider.Name).GetMD5().ToString("N"); + } + + public bool SupportsSync(BaseItem item) { - return _providers.SelectMany(i => i.GetSyncTargets()); + if (item.LocationType == LocationType.Virtual) + { + return false; + } + + if (string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) || + string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase)) + { + if (item.RunTimeTicks.HasValue) + { + var video = item as Video; + + if (video != null) + { + if (video.VideoType != VideoType.VideoFile) + { + return false; + } + + if (video.IsMultiPart) + { + return false; + } + } + + return true; + } + + return false; + } + + return false; } } } diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index 2208bc217..55843bbdb 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -561,7 +561,10 @@ namespace MediaBrowser.ServerApplication ImageProcessor = new ImageProcessor(LogManager.GetLogger("ImageProcessor"), ServerConfigurationManager.ApplicationPaths, FileSystemManager, JsonSerializer, MediaEncoder); RegisterSingleInstance(ImageProcessor); - DtoService = new DtoService(Logger, LibraryManager, UserDataManager, ItemRepository, ImageProcessor, ServerConfigurationManager, FileSystemManager, ProviderManager, () => ChannelManager); + SyncManager = new SyncManager(); + RegisterSingleInstance(SyncManager); + + DtoService = new DtoService(Logger, LibraryManager, UserDataManager, ItemRepository, ImageProcessor, ServerConfigurationManager, FileSystemManager, ProviderManager, () => ChannelManager, SyncManager); RegisterSingleInstance(DtoService); SessionManager = new SessionManager(UserDataManager, ServerConfigurationManager, Logger, UserRepository, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, ItemRepository, JsonSerializer, this, HttpClient, AuthenticationRepository); @@ -614,9 +617,6 @@ namespace MediaBrowser.ServerApplication MediaEncoder, ChapterManager); RegisterSingleInstance(EncodingManager); - SyncManager = new SyncManager(); - RegisterSingleInstance(SyncManager); - var authContext = new AuthorizationContext(); RegisterSingleInstance<IAuthorizationContext>(authContext); RegisterSingleInstance<ISessionContext>(new SessionContext(UserManager, authContext, SessionManager)); diff --git a/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs index 79b262fc3..f9a6fc059 100644 --- a/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs @@ -43,37 +43,25 @@ namespace MediaBrowser.XbmcMetadata.Savers { var album = (MusicAlbum)item; - var tracks = album.Tracks - .ToList(); - - var artists = tracks - .SelectMany(i => - { - var list = new List<string>(); - - if (!string.IsNullOrEmpty(i.AlbumArtist)) - { - list.Add(i.AlbumArtist); - } - list.AddRange(i.Artists); - - return list; - }) - .Distinct(StringComparer.OrdinalIgnoreCase); - - foreach (var artist in artists) + foreach (var artist in album.Artists) { writer.WriteElementString("artist", artist); } - AddTracks(tracks, writer); + foreach (var artist in album.AlbumArtists) + { + writer.WriteElementString("albumartist", artist); + } + + AddTracks(album.Tracks, writer); } private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); private void AddTracks(IEnumerable<Audio> tracks, XmlWriter writer) { - foreach (var track in tracks.OrderBy(i => i.ParentIndexNumber ?? 0).ThenBy(i => i.IndexNumber ?? 0)) + foreach (var track in tracks.OrderBy(i => i.ParentIndexNumber ?? 0) + .ThenBy(i => i.IndexNumber ?? 0)) { writer.WriteStartElement("track"); @@ -103,7 +91,8 @@ namespace MediaBrowser.XbmcMetadata.Savers var list = new List<string> { "track", - "artist" + "artist", + "albumartist" }; return list; |
