diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index c3f767c0d2..c77758d251 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -314,7 +314,7 @@ namespace MediaBrowser.Controller.Entities [IgnoreDataMember] public IEnumerable Children { - get { return ActualChildren; } + get { return ActualChildren.ToList(); } } /// diff --git a/MediaBrowser.Controller/LiveTv/IListingsProvider.cs b/MediaBrowser.Controller/LiveTv/IListingsProvider.cs index e60183bd93..f5048bdda0 100644 --- a/MediaBrowser.Controller/LiveTv/IListingsProvider.cs +++ b/MediaBrowser.Controller/LiveTv/IListingsProvider.cs @@ -11,7 +11,7 @@ namespace MediaBrowser.Controller.LiveTv { string Name { get; } string Type { get; } - Task> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken); + Task> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, string channelName, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken); Task AddMetadata(ListingsProviderInfo info, List channels, CancellationToken cancellationToken); Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings); Task> GetLineups(ListingsProviderInfo info, string country, string location); diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 38fe0ecb72..4106d3dca7 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -145,8 +145,12 @@ namespace MediaBrowser.Providers.Manager foreach (var path in paths) { source.Position = 0; - - await SaveImageToLocation(source, path, retryPaths[currentPathIndex], cancellationToken).ConfigureAwait(false); + string retryPath = null; + if (paths.Length == retryPaths.Length) + { + retryPath = retryPaths[currentPathIndex]; + } + await SaveImageToLocation(source, path, retryPath, cancellationToken).ConfigureAwait(false); currentPathIndex++; } @@ -190,7 +194,8 @@ namespace MediaBrowser.Providers.Manager } catch (UnauthorizedAccessException) { - var retry = !string.Equals(path, retryPath, StringComparison.OrdinalIgnoreCase); + var retry = !string.IsNullOrWhiteSpace(retryPath) && + !string.Equals(path, retryPath, StringComparison.OrdinalIgnoreCase); if (retry) { diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index ca5cd5499d..31f9420168 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -280,6 +280,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV } _recordingProvider.Delete(remove); } + else + { + throw new ResourceNotFoundException("Recording not found: " + recordingId); + } } public Task CreateTimerAsync(TimerInfo info, CancellationToken cancellationToken) @@ -360,9 +364,31 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV throw new NotImplementedException(); } - public Task> GetRecordingsAsync(CancellationToken cancellationToken) + public async Task> GetRecordingsAsync(CancellationToken cancellationToken) { - return Task.FromResult((IEnumerable)_recordingProvider.GetAll()); + var recordings = _recordingProvider.GetAll().ToList(); + var updated = false; + + foreach (var recording in recordings) + { + if (recording.Status == RecordingStatus.InProgress) + { + if (string.IsNullOrWhiteSpace(recording.TimerId) || !_activeRecordings.ContainsKey(recording.TimerId)) + { + recording.Status = RecordingStatus.Cancelled; + recording.DateLastUpdated = DateTime.UtcNow; + _recordingProvider.Update(recording); + updated = true; + } + } + } + + if (updated) + { + recordings = _recordingProvider.GetAll().ToList(); + } + + return recordings; } public Task> GetTimersAsync(CancellationToken cancellationToken) @@ -417,7 +443,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV foreach (var provider in GetListingProviders()) { - var programs = await provider.Item1.GetProgramsAsync(provider.Item2, channel.Number, startDateUtc, endDateUtc, cancellationToken) + var programs = await provider.Item1.GetProgramsAsync(provider.Item2, channel.Number, channel.Name, startDateUtc, endDateUtc, cancellationToken) .ConfigureAwait(false); var list = programs.ToList(); diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/EmbyListings.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/EmbyListings.cs index e446ff469f..ae441b44e0 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/EmbyListings.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/EmbyListings.cs @@ -31,7 +31,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings.Emby get { return "emby"; } } - public Task> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken) + public Task> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, string channelName, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken) { return GetListingsProvider(info.Country).GetProgramsAsync(info, channelNumber, startDateUtc, endDateUtc, cancellationToken); } diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 227d4ca18c..083b6e48a2 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -60,7 +60,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings return dates; } - public async Task> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken) + public async Task> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, string channelName, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken) { List programsInfo = new List(); @@ -89,12 +89,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings var dates = GetScheduleRequestDates(startDateUtc, endDateUtc); - ScheduleDirect.Station station = null; + ScheduleDirect.Station station = GetStation(channelNumber, channelName); - if (!_channelPair.TryGetValue(channelNumber, out station)) + if (station == null) { return programsInfo; } + string stationID = station.stationID; _logger.Info("Channel Station ID is: " + stationID); @@ -167,6 +168,30 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings return programsInfo; } + private ScheduleDirect.Station GetStation(string channelNumber, string channelName) + { + ScheduleDirect.Station station; + + if (_channelPair.TryGetValue(channelNumber, out station)) + { + return station; + } + + if (string.IsNullOrWhiteSpace(channelName)) + { + return null; + } + + channelName = NormalizeName(channelName); + + return _channelPair.Values.FirstOrDefault(i => string.Equals(NormalizeName(i.callsign ?? string.Empty), channelName, StringComparison.OrdinalIgnoreCase)); + } + + private string NormalizeName(string value) + { + return value.Replace(" ", string.Empty).Replace("-", string.Empty); + } + public async Task AddMetadata(ListingsProviderInfo info, List channels, CancellationToken cancellationToken) { @@ -200,45 +225,42 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings _logger.Info("Mapping Stations to Channel"); foreach (ScheduleDirect.Map map in root.map) { - var channel = map.logicalChannelNumber; + var channelNumber = map.logicalChannelNumber; - if (string.IsNullOrWhiteSpace(channel)) + if (string.IsNullOrWhiteSpace(channelNumber)) { - channel = map.channel; + channelNumber = map.channel; } - if (string.IsNullOrWhiteSpace(channel)) + if (string.IsNullOrWhiteSpace(channelNumber)) { - channel = (map.atscMajor + "." + map.atscMinor); + channelNumber = (map.atscMajor + "." + map.atscMinor); } - channel = channel.TrimStart('0'); + channelNumber = channelNumber.TrimStart('0'); - _logger.Debug("Found channel: " + channel + " in Schedules Direct"); + _logger.Debug("Found channel: " + channelNumber + " in Schedules Direct"); var schChannel = root.stations.FirstOrDefault(item => item.stationID == map.stationID); - if (!_channelPair.ContainsKey(channel) && channel != "0.0" && schChannel != null) - { - _channelPair.TryAdd(channel, schChannel); - } + _channelPair.TryAdd(channelNumber, schChannel); } - _logger.Info("Added " + _channelPair.Count() + " channels to the dictionary"); + _logger.Info("Added " + _channelPair.Count + " channels to the dictionary"); foreach (ChannelInfo channel in channels) { - // Helper.logger.Info("Modifyin channel " + channel.Number); - if (_channelPair.ContainsKey(channel.Number)) + var station = GetStation(channel.Number, channel.Number); + + if (station != null) { - if (_channelPair[channel.Number].logo != null) + if (station.logo != null) { - channel.ImageUrl = _channelPair[channel.Number].logo.URL; + channel.ImageUrl = station.logo.URL; channel.HasImage = true; } - string channelName = _channelPair[channel.Number].name; + string channelName = station.name; channel.Name = channelName; } else { - _logger.Info("Schedules Direct doesnt have data for channel: " + channel.Number + " " + - channel.Name); + _logger.Info("Schedules Direct doesnt have data for channel: " + channel.Number + " " + channel.Name); } } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/XmlTv.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/XmlTv.cs index de107ced80..ac316f9a12 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/Listings/XmlTv.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/Listings/XmlTv.cs @@ -20,7 +20,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings get { return "xmltv"; } } - public Task> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken) + public Task> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, string channelName, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken) { throw new NotImplementedException(); } diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 875ea6d280..a11400a648 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -759,7 +759,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv { await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false); } - else if (pathChanged || info.DateLastUpdated > recording.DateLastSaved) + else if (pathChanged || info.DateLastUpdated > recording.DateLastSaved || info.Status != recording.Status) { await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false); } @@ -1292,7 +1292,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv var idList = await Task.WhenAll(recordingTasks).ConfigureAwait(false); - CleanDatabaseInternal(idList.ToList(), new[] { typeof(LiveTvVideoRecording).Name, typeof(LiveTvAudioRecording).Name }, new Progress(), cancellationToken).ConfigureAwait(false); + await CleanDatabaseInternal(idList.ToList(), new[] { typeof(LiveTvVideoRecording).Name, typeof(LiveTvAudioRecording).Name }, new Progress(), cancellationToken).ConfigureAwait(false); _lastRecordingRefreshTime = DateTime.UtcNow; } @@ -1601,7 +1601,17 @@ namespace MediaBrowser.Server.Implementations.LiveTv var service = GetService(recording.ServiceName); - await service.DeleteRecordingAsync(recording.ExternalId, CancellationToken.None).ConfigureAwait(false); + try + { + await service.DeleteRecordingAsync(recording.ExternalId, CancellationToken.None).ConfigureAwait(false); + } + catch (ResourceNotFoundException) + { + + } + + await _libraryManager.DeleteItem((BaseItem)recording).ConfigureAwait(false); + _lastRecordingRefreshTime = DateTime.MinValue; } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 00c10f0a12..36af719674 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -1396,8 +1396,6 @@ namespace MediaBrowser.Server.Implementations.Persistence typeof(LiveTvVideoRecording), typeof(LiveTvAudioRecording), typeof(Series), - typeof(LiveTvAudioRecording), - typeof(LiveTvVideoRecording), typeof(Audio), typeof(MusicAlbum), typeof(MusicArtist),