From 20b990dc9a01f00e561181ad48ae73d62bcb2427 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 20 Jul 2015 14:32:55 -0400 Subject: start pulling in EmbyTV --- .../LiveTv/EmbyTV/RecordingHelper.cs | 119 +++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs (limited to 'MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs') diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs new file mode 100644 index 0000000000..0aa1cb2445 --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs @@ -0,0 +1,119 @@ +using System.Text; +using MediaBrowser.Common.Extensions; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Model.Extensions; +using MediaBrowser.Model.Logging; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV +{ + internal class RecordingHelper + { + public static List GetTimersForSeries(SeriesTimerInfo seriesTimer, IEnumerable epgData, IReadOnlyList currentRecordings, ILogger logger) + { + List timers = new List(); + + // Filtered Per Show + var filteredEpg = epgData.Where(epg => epg.Id.Substring(0, 10) == seriesTimer.Id); + + if (!seriesTimer.RecordAnyTime) + { + filteredEpg = filteredEpg.Where(epg => (seriesTimer.StartDate.TimeOfDay == epg.StartDate.TimeOfDay)); + } + + if (seriesTimer.RecordNewOnly) + { + filteredEpg = filteredEpg.Where(epg => !epg.IsRepeat); //Filtered by New only + } + + if (!seriesTimer.RecordAnyChannel) + { + filteredEpg = filteredEpg.Where(epg => string.Equals(epg.ChannelId, seriesTimer.ChannelId, StringComparison.OrdinalIgnoreCase)); + } + + filteredEpg = filteredEpg.Where(epg => seriesTimer.Days.Contains(epg.StartDate.DayOfWeek)); + + filteredEpg = filteredEpg.Where(epg => currentRecordings.All(r => r.Id.Substring(0, 14) != epg.Id.Substring(0, 14))); //filtered recordings already running + + filteredEpg = filteredEpg.GroupBy(epg => epg.Id.Substring(0, 14)).Select(g => g.First()).ToList(); + + foreach (var epg in filteredEpg) + { + timers.Add(CreateTimer(epg, seriesTimer)); + } + + return timers; + } + + public static DateTime GetStartTime(TimerInfo timer) + { + if (timer.StartDate.AddSeconds(-timer.PrePaddingSeconds + 1) < DateTime.UtcNow) + { + return DateTime.UtcNow.AddSeconds(1); + } + return timer.StartDate.AddSeconds(-timer.PrePaddingSeconds); + } + + public static TimerInfo CreateTimer(ProgramInfo parent, SeriesTimerInfo series) + { + var timer = new TimerInfo(); + + timer.ChannelId = parent.ChannelId; + timer.Id = (series.Id + parent.Id).GetMD5().ToString("N"); + timer.StartDate = parent.StartDate; + timer.EndDate = parent.EndDate; + timer.ProgramId = parent.Id; + timer.PrePaddingSeconds = series.PrePaddingSeconds; + timer.PostPaddingSeconds = series.PostPaddingSeconds; + timer.IsPostPaddingRequired = series.IsPostPaddingRequired; + timer.IsPrePaddingRequired = series.IsPrePaddingRequired; + timer.Priority = series.Priority; + timer.Name = parent.Name; + timer.Overview = parent.Overview; + timer.SeriesTimerId = series.Id; + + return timer; + } + + public static string GetRecordingName(TimerInfo timer, ProgramInfo info) + { + if (info == null) + { + return (timer.ProgramId + ".ts"); + } + var fancyName = info.Name; + if (info.ProductionYear != null) + { + fancyName += "_(" + info.ProductionYear + ")"; + } + if (info.IsSeries) + { + fancyName += "_" + info.EpisodeTitle.Replace("Season: ", "S").Replace(" Episode: ", "E"); + } + if (info.IsHD ?? false) + { + fancyName += "_HD"; + } + if (info.OriginalAirDate != null) + { + fancyName += "_" + info.OriginalAirDate.Value.ToString("yyyy-MM-dd"); + } + return RemoveSpecialCharacters(fancyName) + ".ts"; + } + + public static string RemoveSpecialCharacters(string str) + { + StringBuilder sb = new StringBuilder(); + foreach (char c in str) + { + if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '.' || c == '_' || c == '-' || c == ' ') + { + sb.Append(c); + } + } + return sb.ToString(); + } + } +} -- cgit v1.2.3 From 4d7f98361894e9de90ab964c3496fb7f613c28e2 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 28 Jul 2015 23:42:03 -0400 Subject: update recording scheduler --- MediaBrowser.Controller/LiveTv/RecordingInfo.cs | 6 ++++ .../Channels/ChannelPostScanTask.cs | 2 +- .../Channels/RefreshChannelsScheduledTask.cs | 24 ++++++++----- .../IO/LibraryMonitor.cs | 12 +++---- .../LiveTv/EmbyTV/EmbyTV.cs | 40 +++++++++++++++++----- .../LiveTv/EmbyTV/EntryPoint.cs | 16 +++++++++ .../LiveTv/EmbyTV/RecordingHelper.cs | 9 ++--- .../LiveTv/EmbyTV/TimerManager.cs | 16 ++++++++- .../MediaBrowser.Server.Implementations.csproj | 1 + .../ScheduledTasks/RefreshMediaLibraryTask.cs | 2 +- .../MediaBrowser.WebDashboard.csproj | 6 ---- 11 files changed, 94 insertions(+), 40 deletions(-) create mode 100644 MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs (limited to 'MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs') diff --git a/MediaBrowser.Controller/LiveTv/RecordingInfo.cs b/MediaBrowser.Controller/LiveTv/RecordingInfo.cs index bf453ccf4d..e5817d390d 100644 --- a/MediaBrowser.Controller/LiveTv/RecordingInfo.cs +++ b/MediaBrowser.Controller/LiveTv/RecordingInfo.cs @@ -16,6 +16,12 @@ namespace MediaBrowser.Controller.LiveTv /// /// The series timer identifier. public string SeriesTimerId { get; set; } + + /// + /// Gets or sets the timer identifier. + /// + /// The timer identifier. + public string TimerId { get; set; } /// /// ChannelId of the recording. diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs b/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs index d266cca6c0..baf446942b 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs @@ -12,7 +12,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.Channels { - public class ChannelPostScanTask : ILibraryPostScanTask + public class ChannelPostScanTask { private readonly IChannelManager _channelManager; private readonly IUserManager _userManager; diff --git a/MediaBrowser.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs b/MediaBrowser.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs index b1491d594e..df94580a57 100644 --- a/MediaBrowser.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs @@ -1,6 +1,7 @@ using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Controller.Channels; -using MediaBrowser.Model.Tasks; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Logging; using System; using System.Collections.Generic; using System.Threading.Tasks; @@ -9,11 +10,15 @@ namespace MediaBrowser.Server.Implementations.Channels { class RefreshChannelsScheduledTask : IScheduledTask, IConfigurableScheduledTask { - private readonly IChannelManager _manager; + private readonly IChannelManager _channelManager; + private readonly IUserManager _userManager; + private readonly ILogger _logger; - public RefreshChannelsScheduledTask(IChannelManager manager) + public RefreshChannelsScheduledTask(IChannelManager channelManager, IUserManager userManager, ILogger logger) { - _manager = manager; + _channelManager = channelManager; + _userManager = userManager; + _logger = logger; } public string Name @@ -31,11 +36,14 @@ namespace MediaBrowser.Server.Implementations.Channels get { return "Channels"; } } - public Task Execute(System.Threading.CancellationToken cancellationToken, IProgress progress) + public async Task Execute(System.Threading.CancellationToken cancellationToken, IProgress progress) { - var manager = (ChannelManager)_manager; + var manager = (ChannelManager)_channelManager; - return manager.RefreshChannels(progress, cancellationToken); + await manager.RefreshChannels(new Progress(), cancellationToken).ConfigureAwait(false); + + await new ChannelPostScanTask(_channelManager, _userManager, _logger).Run(progress, cancellationToken) + .ConfigureAwait(false); } public IEnumerable GetDefaultTriggers() @@ -48,7 +56,7 @@ namespace MediaBrowser.Server.Implementations.Channels public bool IsHidden { - get { return true; } + get { return false; } } public bool IsEnabled diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs index 26ccdfc9a4..e1c5291870 100644 --- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs +++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs @@ -1,5 +1,4 @@ -using System.ComponentModel; -using MediaBrowser.Common.IO; +using MediaBrowser.Common.IO; using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; @@ -372,15 +371,12 @@ namespace MediaBrowser.Server.Implementations.IO DisposeWatcher(dw); - if (ex is Win32Exception) + if (ConfigurationManager.Configuration.EnableLibraryMonitor == AutoOnOff.Auto) { Logger.Info("Disabling realtime monitor to prevent future instability"); - if (ConfigurationManager.Configuration.EnableLibraryMonitor == AutoOnOff.Auto) - { - ConfigurationManager.Configuration.EnableLibraryMonitor = AutoOnOff.Disabled; - Stop(); - } + ConfigurationManager.Configuration.EnableLibraryMonitor = AutoOnOff.Disabled; + Stop(); } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 0ed87bbff3..3374a3cc9c 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -33,8 +33,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private readonly LiveTvManager _liveTvManager; + public static EmbyTV Current; + public EmbyTV(IApplicationHost appHost, ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IConfigurationManager config, ILiveTvManager liveTvManager) { + Current = this; + _appHpst = appHost; _logger = logger; _httpClient = httpClient; @@ -48,6 +52,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV _timerProvider.TimerFired += _timerProvider_TimerFired; } + public void Start() + { + _timerProvider.RestartTimers(); + } + public event EventHandler DataSourceChanged; public event EventHandler RecordingStatusChanged; @@ -147,7 +156,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV public Task CancelSeriesTimerAsync(string timerId, CancellationToken cancellationToken) { - var remove = _seriesTimerProvider.GetAll().SingleOrDefault(r => r.Id == timerId); + var remove = _seriesTimerProvider.GetAll().FirstOrDefault(r => string.Equals(r.Id, timerId, StringComparison.OrdinalIgnoreCase)); if (remove != null) { _seriesTimerProvider.Delete(remove); @@ -157,7 +166,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private void CancelTimerInternal(string timerId) { - var remove = _timerProvider.GetAll().SingleOrDefault(r => r.Id == timerId); + var remove = _timerProvider.GetAll().FirstOrDefault(r => string.Equals(r.Id, timerId, StringComparison.OrdinalIgnoreCase)); if (remove != null) { _timerProvider.Delete(remove); @@ -176,11 +185,24 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV return Task.FromResult(true); } - public Task DeleteRecordingAsync(string recordingId, CancellationToken cancellationToken) + public async Task DeleteRecordingAsync(string recordingId, CancellationToken cancellationToken) { var remove = _recordingProvider.GetAll().FirstOrDefault(i => string.Equals(i.Id, recordingId, StringComparison.OrdinalIgnoreCase)); if (remove != null) { + if (!string.IsNullOrWhiteSpace(remove.TimerId)) + { + var enableDelay = _activeRecordings.ContainsKey(remove.TimerId); + + CancelTimerInternal(remove.TimerId); + + if (enableDelay) + { + // A hack yes, but need to make sure the file is closed before attempting to delete it + await Task.Delay(3000).ConfigureAwait(false); + } + } + try { File.Delete(remove.Path); @@ -195,7 +217,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV } _recordingProvider.Delete(remove); } - return Task.FromResult(true); } public Task CreateTimerAsync(TimerInfo info, CancellationToken cancellationToken) @@ -293,6 +314,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV if (list.Count > 0) { + SaveEpgDataForChannel(channelId, list); + return list; } } @@ -430,7 +453,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV } var mediaStreamInfo = await GetChannelStream(timer.ChannelId, null, CancellationToken.None); - var duration = (timer.EndDate - RecordingHelper.GetStartTime(timer)).TotalSeconds + timer.PrePaddingSeconds; + var duration = (timer.EndDate - DateTime.UtcNow).TotalSeconds + timer.PostPaddingSeconds; HttpRequestOptions httpRequestOptions = new HttpRequestOptions() { @@ -451,14 +474,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV recordPath = Path.Combine(recordPath, RecordingHelper.GetRecordingName(timer, info)); Directory.CreateDirectory(Path.GetDirectoryName(recordPath)); - var recording = _recordingProvider.GetAll().FirstOrDefault(x => string.Equals(x.Id, info.Id, StringComparison.OrdinalIgnoreCase)); + var recording = _recordingProvider.GetAll().FirstOrDefault(x => string.Equals(x.ProgramId, info.Id, StringComparison.OrdinalIgnoreCase)); if (recording == null) { recording = new RecordingInfo() { ChannelId = info.ChannelId, - Id = info.Id, + Id = Guid.NewGuid().ToString("N"), StartDate = info.StartDate, EndDate = info.EndDate, Genres = info.Genres ?? null, @@ -480,7 +503,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV OriginalAirDate = info.OriginalAirDate, Status = RecordingStatus.Scheduled, Overview = info.Overview, - SeriesTimerId = info.Id.Substring(0, 10) + SeriesTimerId = info.Id.Substring(0, 10), + TimerId = timer.Id }; _recordingProvider.Add(recording); } diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs new file mode 100644 index 0000000000..713cb9cd30 --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs @@ -0,0 +1,16 @@ +using MediaBrowser.Controller.Plugins; + +namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV +{ + public class EntryPoint : IServerEntryPoint + { + public void Run() + { + EmbyTV.Current.Start(); + } + + public void Dispose() + { + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs index 0aa1cb2445..db89680d2d 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs @@ -1,11 +1,10 @@ -using System.Text; -using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Logging; using System; using System.Collections.Generic; using System.Linq; +using System.Text; namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { @@ -49,10 +48,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV public static DateTime GetStartTime(TimerInfo timer) { - if (timer.StartDate.AddSeconds(-timer.PrePaddingSeconds + 1) < DateTime.UtcNow) - { - return DateTime.UtcNow.AddSeconds(1); - } return timer.StartDate.AddSeconds(-timer.PrePaddingSeconds); } diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs index 323197aa5c..0c8d2ca2ba 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs @@ -24,6 +24,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV public void RestartTimers() { StopTimers(); + + foreach (var item in GetAll().ToList()) + { + AddTimer(item); + } } public void StopTimers() @@ -90,7 +95,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private void AddTimer(TimerInfo item) { - var timespan = RecordingHelper.GetStartTime(item) - DateTime.UtcNow; + var startDate = RecordingHelper.GetStartTime(item); + var now = DateTime.UtcNow; + + if (startDate < now) + { + EventHelper.FireEventIfNotNull(TimerFired, this, new GenericEventArgs { Argument = item }, Logger); + return; + } + + var timespan = startDate - now; var timer = new Timer(TimerCallback, item.Id, timespan, TimeSpan.Zero); diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 5e0f374e0b..7eddf5ed15 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -217,6 +217,7 @@ + diff --git a/MediaBrowser.Server.Implementations/ScheduledTasks/RefreshMediaLibraryTask.cs b/MediaBrowser.Server.Implementations/ScheduledTasks/RefreshMediaLibraryTask.cs index 824d859f30..ed284a90d1 100644 --- a/MediaBrowser.Server.Implementations/ScheduledTasks/RefreshMediaLibraryTask.cs +++ b/MediaBrowser.Server.Implementations/ScheduledTasks/RefreshMediaLibraryTask.cs @@ -37,7 +37,7 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks new StartupTrigger(), - new IntervalTrigger{ Interval = TimeSpan.FromHours(6)} + new IntervalTrigger{ Interval = TimeSpan.FromHours(8)} }; } diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 16dd97387f..a4da8c2b77 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -742,9 +742,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest @@ -1006,9 +1003,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest -- cgit v1.2.3 From 1f6b5a8c7c049bea309351dd495d99ec21eb32cb Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 29 Jul 2015 13:16:00 -0400 Subject: update live tv recordings --- MediaBrowser.Api/LiveTv/LiveTvService.cs | 26 ++++++++++++- .../LiveTv/EmbyTV/EmbyTV.cs | 36 +++++++++++++++++- .../LiveTv/EmbyTV/RecordingHelper.cs | 39 ------------------- .../LiveTv/Listings/SchedulesDirect.cs | 44 ++++++++++++++-------- .../Sync/SyncHelper.cs | 4 +- .../MediaBrowser.WebDashboard.csproj | 6 --- 6 files changed, 89 insertions(+), 66 deletions(-) (limited to 'MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs') diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index b0359194c7..6814ad751b 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -1,4 +1,5 @@ using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; @@ -376,17 +377,40 @@ namespace MediaBrowser.Api.LiveTv public string Country { get; set; } } + [Route("/LiveTv/ListingProviders/SchedulesDirect/Countries", "GET", Summary = "Gets available lineups")] + [Authenticated] + public class GetSchedulesDirectCountries + { + } + public class LiveTvService : BaseApiService { private readonly ILiveTvManager _liveTvManager; private readonly IUserManager _userManager; private readonly IConfigurationManager _config; + private readonly IHttpClient _httpClient; - public LiveTvService(ILiveTvManager liveTvManager, IUserManager userManager, IConfigurationManager config) + public LiveTvService(ILiveTvManager liveTvManager, IUserManager userManager, IConfigurationManager config, IHttpClient httpClient) { _liveTvManager = liveTvManager; _userManager = userManager; _config = config; + _httpClient = httpClient; + } + + public async Task Get(GetSchedulesDirectCountries request) + { + // https://json.schedulesdirect.org/20141201/available/countries + + var response = await _httpClient.Get(new HttpRequestOptions + { + Url = "https://json.schedulesdirect.org/20141201/available/countries", + CacheLength = TimeSpan.FromDays(1), + CacheMode = CacheMode.Unconditional + + }).ConfigureAwait(false); + + return ResultFactory.GetResult(response, "application/json"); } private void AssertUserCanManageLiveTv() diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 3374a3cc9c..2319a6c2ca 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -228,7 +228,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV public Task CreateSeriesTimerAsync(SeriesTimerInfo info, CancellationToken cancellationToken) { - info.Id = info.ProgramId.Substring(0, 10); + info.Id = Guid.NewGuid().ToString("N"); UpdateTimersForSeriesTimer(info); _seriesTimerProvider.Add(info); @@ -581,7 +581,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV epgData = GetEpgDataForChannel(seriesTimer.ChannelId); } - var newTimers = RecordingHelper.GetTimersForSeries(seriesTimer, epgData, _recordingProvider.GetAll(), _logger); + var newTimers = GetTimersForSeries(seriesTimer, epgData, _recordingProvider.GetAll()).ToList(); var existingTimers = _timerProvider.GetAll() .Where(i => string.Equals(i.SeriesTimerId, seriesTimer.Id, StringComparison.OrdinalIgnoreCase)) @@ -603,6 +603,38 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV } } + private IEnumerable GetTimersForSeries(SeriesTimerInfo seriesTimer, IEnumerable allPrograms, IReadOnlyList currentRecordings) + { + allPrograms = GetProgramsForSeries(seriesTimer, allPrograms); + + allPrograms = allPrograms.Where(epg => currentRecordings.All(r => r.ProgramId.Substring(0, 14) != epg.Id.Substring(0, 14))); //filtered recordings already running + + return allPrograms.Select(i => RecordingHelper.CreateTimer(i, seriesTimer)); + } + + private IEnumerable GetProgramsForSeries(SeriesTimerInfo seriesTimer, IEnumerable allPrograms) + { + if (!seriesTimer.RecordAnyTime) + { + allPrograms = allPrograms.Where(epg => (seriesTimer.StartDate.TimeOfDay == epg.StartDate.TimeOfDay)); + } + + if (seriesTimer.RecordNewOnly) + { + allPrograms = allPrograms.Where(epg => !epg.IsRepeat); //Filtered by New only + } + + if (!seriesTimer.RecordAnyChannel) + { + allPrograms = allPrograms.Where(epg => string.Equals(epg.ChannelId, seriesTimer.ChannelId, StringComparison.OrdinalIgnoreCase)); + } + + allPrograms = allPrograms.Where(epg => seriesTimer.Days.Contains(epg.StartDate.DayOfWeek)); + + // TODO: This assumption will require review once additional listing providers are added + return allPrograms.Where(epg => epg.Id.StartsWith(seriesTimer.ProgramId, StringComparison.OrdinalIgnoreCase)); + } + private string GetChannelEpgCachePath(string channelId) { return Path.Combine(DataPath, "epg", channelId + ".json"); diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs index db89680d2d..31fb072cdf 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs @@ -1,51 +1,12 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.Logging; using System; -using System.Collections.Generic; -using System.Linq; using System.Text; namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { internal class RecordingHelper { - public static List GetTimersForSeries(SeriesTimerInfo seriesTimer, IEnumerable epgData, IReadOnlyList currentRecordings, ILogger logger) - { - List timers = new List(); - - // Filtered Per Show - var filteredEpg = epgData.Where(epg => epg.Id.Substring(0, 10) == seriesTimer.Id); - - if (!seriesTimer.RecordAnyTime) - { - filteredEpg = filteredEpg.Where(epg => (seriesTimer.StartDate.TimeOfDay == epg.StartDate.TimeOfDay)); - } - - if (seriesTimer.RecordNewOnly) - { - filteredEpg = filteredEpg.Where(epg => !epg.IsRepeat); //Filtered by New only - } - - if (!seriesTimer.RecordAnyChannel) - { - filteredEpg = filteredEpg.Where(epg => string.Equals(epg.ChannelId, seriesTimer.ChannelId, StringComparison.OrdinalIgnoreCase)); - } - - filteredEpg = filteredEpg.Where(epg => seriesTimer.Days.Contains(epg.StartDate.DayOfWeek)); - - filteredEpg = filteredEpg.Where(epg => currentRecordings.All(r => r.Id.Substring(0, 14) != epg.Id.Substring(0, 14))); //filtered recordings already running - - filteredEpg = filteredEpg.GroupBy(epg => epg.Id.Substring(0, 14)).Select(g => g.First()).ToList(); - - foreach (var epg in filteredEpg) - { - timers.Add(CreateTimer(epg, seriesTimer)); - } - - return timers; - } - public static DateTime GetStartTime(TimerInfo timer) { return timer.StartDate.AddSeconds(-timer.PrePaddingSeconds); diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 64599bc58c..ffafe59795 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -35,6 +35,22 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings _httpClient = httpClient; } + private List GetScheduleRequestDates(DateTime startDateUtc, DateTime endDateUtc) + { + List dates = new List(); + + var start = new List { startDateUtc, startDateUtc.ToLocalTime() }.Min(); + var end = new List { endDateUtc, endDateUtc.ToLocalTime() }.Max(); + + while (start.DayOfYear <= end.Day) + { + dates.Add(start.ToString("yyyy-MM-dd")); + start = start.AddDays(1); + } + + return dates; + } + public async Task> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken) { List programsInfo = new List(); @@ -60,15 +76,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings httpOptions.RequestHeaders["token"] = token; - List dates = new List(); - int numberOfDay = 0; - DateTime lastEntry = startDateUtc; - while (lastEntry != endDateUtc) - { - lastEntry = startDateUtc.AddDays(numberOfDay); - dates.Add(lastEntry.ToString("yyyy-MM-dd")); - numberOfDay++; - } + var dates = GetScheduleRequestDates(startDateUtc, endDateUtc); ScheduleDirect.Station station = null; @@ -97,8 +105,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings StreamReader reader = new StreamReader(response.Content); string responseString = reader.ReadToEnd(); var dailySchedules = _jsonSerializer.DeserializeFromString>(responseString); - _logger.Debug("Found " + dailySchedules.Count() + " programs on " + channelNumber + - " ScheduleDirect"); + _logger.Debug("Found " + dailySchedules.Count() + " programs on " + channelNumber + " ScheduleDirect"); httpOptions = new HttpRequestOptions() { @@ -234,10 +241,17 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings bool repeat = (programInfo.@new == null); string newID = programInfo.programID + "T" + startAt.Ticks + "C" + channel; - if (programInfo.audioProperties != null) { - if (programInfo.audioProperties.Exists(item => item == "stereo")) + if (programInfo.audioProperties.Exists(item => string.Equals(item, "dd 5.1", StringComparison.OrdinalIgnoreCase))) + { + audioType = ProgramAudio.DolbyDigital; + } + else if (programInfo.audioProperties.Exists(item => string.Equals(item, "dd", StringComparison.OrdinalIgnoreCase))) + { + audioType = ProgramAudio.DolbyDigital; + } + else if (programInfo.audioProperties.Exists(item => string.Equals(item, "stereo", StringComparison.OrdinalIgnoreCase))) { audioType = ProgramAudio.Stereo; } @@ -286,7 +300,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings imageLink = details.images; } - var info = new ProgramInfo { ChannelId = channel, @@ -554,7 +567,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings }; httpOptions.RequestHeaders["token"] = token; - + using (var response = await _httpClient.SendAsync(httpOptions, "PUT")) { } @@ -915,6 +928,5 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings } } - } } diff --git a/MediaBrowser.Server.Implementations/Sync/SyncHelper.cs b/MediaBrowser.Server.Implementations/Sync/SyncHelper.cs index 006284ee15..b6242950ff 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncHelper.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncHelper.cs @@ -10,11 +10,11 @@ namespace MediaBrowser.Server.Implementations.Sync { if (string.Equals(quality, "medium", StringComparison.OrdinalIgnoreCase)) { - profileBitrate = Convert.ToInt32(profileBitrate.Value * .75); + profileBitrate = Math.Min(Convert.ToInt32(profileBitrate.Value * .7), 4000000); } else if (string.Equals(quality, "low", StringComparison.OrdinalIgnoreCase)) { - profileBitrate = Convert.ToInt32(profileBitrate.Value*.5); + profileBitrate = Math.Min(Convert.ToInt32(profileBitrate.Value * .5), 1500000); } } diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index a4da8c2b77..f76651260c 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -742,9 +742,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest @@ -1003,9 +1000,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest -- cgit v1.2.3 From f6dcef0cfdb4364f11836e395ff8933974bcf627 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 15 Aug 2015 20:41:55 -0400 Subject: update recordings --- .../LiveTv/EmbyTV/EmbyTV.cs | 8 +++++--- .../LiveTv/EmbyTV/RecordingHelper.cs | 18 ++---------------- 2 files changed, 7 insertions(+), 19 deletions(-) (limited to 'MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs') diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 6e57492506..f4a6385a41 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1,6 +1,7 @@ using MediaBrowser.Common; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.IO; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.LiveTv; @@ -33,6 +34,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private readonly TimerManager _timerProvider; private readonly LiveTvManager _liveTvManager; + private IFileSystem _fileSystem; public static EmbyTV Current; @@ -481,14 +483,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV var recordPath = RecordingPath; if (info.IsMovie) { - recordPath = Path.Combine(recordPath, "Movies", RecordingHelper.RemoveSpecialCharacters(info.Name)); + recordPath = Path.Combine(recordPath, "Movies", _fileSystem.GetValidFilename(info.Name)); } else { - recordPath = Path.Combine(recordPath, "TV", RecordingHelper.RemoveSpecialCharacters(info.Name)); + recordPath = Path.Combine(recordPath, "TV", _fileSystem.GetValidFilename(info.Name)); } - recordPath = Path.Combine(recordPath, RecordingHelper.GetRecordingName(timer, info)); + recordPath = Path.Combine(recordPath, _fileSystem.GetValidFilename(RecordingHelper.GetRecordingName(timer, info))); Directory.CreateDirectory(Path.GetDirectoryName(recordPath)); var recording = _recordingProvider.GetAll().FirstOrDefault(x => string.Equals(x.ProgramId, info.Id, StringComparison.OrdinalIgnoreCase)); diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs index 31fb072cdf..09a5a3912b 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs @@ -1,7 +1,6 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.LiveTv; using System; -using System.Text; namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { @@ -44,7 +43,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { fancyName += "_(" + info.ProductionYear + ")"; } - if (info.IsSeries) + if (info.IsSeries && !string.IsNullOrWhiteSpace(info.EpisodeTitle)) { fancyName += "_" + info.EpisodeTitle.Replace("Season: ", "S").Replace(" Episode: ", "E"); } @@ -56,20 +55,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { fancyName += "_" + info.OriginalAirDate.Value.ToString("yyyy-MM-dd"); } - return RemoveSpecialCharacters(fancyName) + ".ts"; - } - - public static string RemoveSpecialCharacters(string str) - { - StringBuilder sb = new StringBuilder(); - foreach (char c in str) - { - if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '.' || c == '_' || c == '-' || c == ' ') - { - sb.Append(c); - } - } - return sb.ToString(); + return fancyName + ".ts"; } } } -- cgit v1.2.3 From 6d206bb9dcc457b573e5e5dc36651ff1246b52d9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 20 Aug 2015 19:55:23 -0400 Subject: update recording save path --- MediaBrowser.Controller/Entities/Movies/Movie.cs | 13 ++++++-- MediaBrowser.Controller/LiveTv/LiveTvProgram.cs | 10 ++++++ .../LiveTv/LiveTvVideoRecording.cs | 11 +++++++ .../LiveTv/EmbyTV/EmbyTV.cs | 13 ++++++++ .../LiveTv/EmbyTV/RecordingHelper.cs | 38 +++++++++++++--------- 5 files changed, 67 insertions(+), 18 deletions(-) (limited to 'MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs') diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index fc07f67788..083ec0cb4c 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -100,16 +100,23 @@ namespace MediaBrowser.Controller.Entities.Movies /// System.String. protected override string CreateUserDataKey() { - var key = this.GetProviderId(MetadataProviders.Tmdb); + var key = GetMovieUserDataKey(this); if (string.IsNullOrWhiteSpace(key)) { - key = this.GetProviderId(MetadataProviders.Imdb); + key = base.CreateUserDataKey(); } + return key; + } + + public static string GetMovieUserDataKey(BaseItem movie) + { + var key = movie.GetProviderId(MetadataProviders.Tmdb); + if (string.IsNullOrWhiteSpace(key)) { - key = base.CreateUserDataKey(); + key = movie.GetProviderId(MetadataProviders.Imdb); } return key; diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index b54a7aaeeb..14944d36fa 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -1,4 +1,5 @@ using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.LiveTv; @@ -17,6 +18,15 @@ namespace MediaBrowser.Controller.LiveTv /// System.String. protected override string CreateUserDataKey() { + if (IsMovie) + { + var key = Movie.GetMovieUserDataKey(this); + + if (!string.IsNullOrWhiteSpace(key)) + { + return key; + } + } return GetClientTypeName() + "-" + Name; } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs index aaaff6bdb9..960f8054a1 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs @@ -1,4 +1,5 @@ using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -40,6 +41,16 @@ namespace MediaBrowser.Controller.LiveTv /// System.String. protected override string CreateUserDataKey() { + if (IsMovie) + { + var key = Movie.GetMovieUserDataKey(this); + + if (!string.IsNullOrWhiteSpace(key)) + { + return key; + } + } + var name = GetClientTypeName(); if (!string.IsNullOrEmpty(ProgramId)) diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 355597fcf1..ebb5037d04 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -495,10 +495,23 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV var info = GetProgramInfoFromCache(timer.ChannelId, timer.ProgramId); var recordPath = RecordingPath; + if (info.IsMovie) { recordPath = Path.Combine(recordPath, "Movies", _fileSystem.GetValidFilename(info.Name)); } + else if (info.IsSeries) + { + recordPath = Path.Combine(recordPath, "Series", _fileSystem.GetValidFilename(info.Name)); + } + else if (info.IsKids) + { + recordPath = Path.Combine(recordPath, "Kids", _fileSystem.GetValidFilename(info.Name)); + } + else if (info.IsSports) + { + recordPath = Path.Combine(recordPath, "Sports", _fileSystem.GetValidFilename(info.Name)); + } else { recordPath = Path.Combine(recordPath, "TV", _fileSystem.GetValidFilename(info.Name)); diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs index 09a5a3912b..1b8cd2e618 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs @@ -1,6 +1,7 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.LiveTv; using System; +using System.Globalization; namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { @@ -36,26 +37,33 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { if (info == null) { - return (timer.ProgramId + ".ts"); + return timer.ProgramId + ".ts"; } - var fancyName = info.Name; - if (info.ProductionYear != null) - { - fancyName += "_(" + info.ProductionYear + ")"; - } - if (info.IsSeries && !string.IsNullOrWhiteSpace(info.EpisodeTitle)) - { - fancyName += "_" + info.EpisodeTitle.Replace("Season: ", "S").Replace(" Episode: ", "E"); - } - if (info.IsHD ?? false) + + var name = info.Name; + + if (info.IsSeries) { - fancyName += "_HD"; + if (info.SeasonNumber.HasValue && info.EpisodeNumber.HasValue) + { + name += string.Format(" S{0}E{1}", info.SeasonNumber.Value.ToString("00", CultureInfo.InvariantCulture), info.EpisodeNumber.Value.ToString("00", CultureInfo.InvariantCulture)); + } + else if (info.OriginalAirDate.HasValue) + { + name += " " + info.OriginalAirDate.Value.ToString("yyyy-MM-dd"); + } + else if (!string.IsNullOrWhiteSpace(info.EpisodeTitle)) + { + name += " " + info.EpisodeTitle; + } } - if (info.OriginalAirDate != null) + + else if (info.ProductionYear != null) { - fancyName += "_" + info.OriginalAirDate.Value.ToString("yyyy-MM-dd"); + name += " (" + info.ProductionYear + ")"; } - return fancyName + ".ts"; + + return name + ".ts"; } } } -- cgit v1.2.3 From ddcebc4ff704d08e5f0a4dab5d14fe40e244b6d1 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 20 Aug 2015 22:36:30 -0400 Subject: add tv suggestions --- MediaBrowser.Api/Library/LibraryService.cs | 126 ++++++++++++++++++++- MediaBrowser.Api/Movies/MoviesService.cs | 29 ++++- MediaBrowser.Api/Movies/TrailersService.cs | 39 +------ MediaBrowser.Api/Music/AlbumsService.cs | 50 ++++++++ MediaBrowser.Api/UserLibrary/GenresService.cs | 2 - .../Entities/IHasProgramAttributes.cs | 1 + MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs | 1 - MediaBrowser.Model/ApiClient/IApiClient.cs | 48 +------- MediaBrowser.Model/Dto/BaseItemDto.cs | 9 ++ .../LiveTv/EmbyTV/EmbyTV.cs | 4 +- .../LiveTv/EmbyTV/RecordingHelper.cs | 7 +- 11 files changed, 217 insertions(+), 99 deletions(-) (limited to 'MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs') diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index 50c4ad14fc..945e803b2a 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -1,4 +1,7 @@ -using MediaBrowser.Controller.Activity; +using MediaBrowser.Api.Movies; +using MediaBrowser.Api.Music; +using MediaBrowser.Controller.Activity; +using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; @@ -9,7 +12,9 @@ using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Localization; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Persistence; +using MediaBrowser.Controller.TV; using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Channels; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; @@ -238,6 +243,12 @@ namespace MediaBrowser.Api.Library public string Id { get; set; } } + [Route("/Items/{Id}/Similar", "GET", Summary = "Downloads item media")] + [Authenticated(Roles = "download")] + public class GetSimilarItems : BaseGetSimilarItemsFromItem + { + } + /// /// Class LibraryService /// @@ -257,12 +268,14 @@ namespace MediaBrowser.Api.Library private readonly IActivityManager _activityManager; private readonly ILocalizationManager _localization; private readonly ILiveTvManager _liveTv; + private readonly IChannelManager _channelManager; + private readonly ITVSeriesManager _tvManager; /// /// Initializes a new instance of the class. /// public LibraryService(IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager, - IDtoService dtoService, IUserDataManager userDataManager, IAuthorizationContext authContext, IActivityManager activityManager, ILocalizationManager localization, ILiveTvManager liveTv) + IDtoService dtoService, IUserDataManager userDataManager, IAuthorizationContext authContext, IActivityManager activityManager, ILocalizationManager localization, ILiveTvManager liveTv, IChannelManager channelManager, ITVSeriesManager tvManager) { _itemRepo = itemRepo; _libraryManager = libraryManager; @@ -273,6 +286,115 @@ namespace MediaBrowser.Api.Library _activityManager = activityManager; _localization = localization; _liveTv = liveTv; + _channelManager = channelManager; + _tvManager = tvManager; + } + + public object Get(GetSimilarItems request) + { + var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null; + + var item = string.IsNullOrEmpty(request.Id) ? + (!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder : + _libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id); + + if (item is Game) + { + return new GamesService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService) + { + AuthorizationContext = AuthorizationContext, + Logger = Logger, + Request = Request, + SessionContext = SessionContext, + ResultFactory = ResultFactory + + }.Get(new GetSimilarGames + { + Fields = request.Fields, + Id = request.Id, + Limit = request.Limit, + UserId = request.UserId + }); + } + if (item is MusicAlbum) + { + return new AlbumsService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService) + { + AuthorizationContext = AuthorizationContext, + Logger = Logger, + Request = Request, + SessionContext = SessionContext, + ResultFactory = ResultFactory + + }.Get(new GetSimilarAlbums + { + Fields = request.Fields, + Id = request.Id, + Limit = request.Limit, + UserId = request.UserId + }); + } + if (item is MusicArtist) + { + return new AlbumsService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService) + { + AuthorizationContext = AuthorizationContext, + Logger = Logger, + Request = Request, + SessionContext = SessionContext, + ResultFactory = ResultFactory + + }.Get(new GetSimilarArtists + { + Fields = request.Fields, + Id = request.Id, + Limit = request.Limit, + UserId = request.UserId + }); + } + + var program = item as IHasProgramAttributes; + var channelItem = item as ChannelVideoItem; + + if (item is Movie || (program != null && program.IsMovie) || (channelItem != null && channelItem.ContentType == ChannelMediaContentType.Movie && channelItem.ContentType == ChannelMediaContentType.MovieExtra)) + { + return new MoviesService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService, _channelManager) + { + AuthorizationContext = AuthorizationContext, + Logger = Logger, + Request = Request, + SessionContext = SessionContext, + ResultFactory = ResultFactory + + }.Get(new GetSimilarMovies + { + Fields = request.Fields, + Id = request.Id, + Limit = request.Limit, + UserId = request.UserId + }); + } + + if (item is Series || (program != null && program.IsSeries) || (channelItem != null && channelItem.ContentType == ChannelMediaContentType.Episode)) + { + return new TvShowsService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService, _tvManager) + { + AuthorizationContext = AuthorizationContext, + Logger = Logger, + Request = Request, + SessionContext = SessionContext, + ResultFactory = ResultFactory + + }.Get(new GetSimilarShows + { + Fields = request.Fields, + Id = request.Id, + Limit = request.Limit, + UserId = request.UserId + }); + } + + return new ItemsResult(); } public object Get(GetMediaFolders request) diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs index 97e9aa9c8f..fe8bae1a51 100644 --- a/MediaBrowser.Api/Movies/MoviesService.cs +++ b/MediaBrowser.Api/Movies/MoviesService.cs @@ -28,6 +28,14 @@ namespace MediaBrowser.Api.Movies { } + /// + /// Class GetSimilarTrailers + /// + [Route("/Trailers/{Id}/Similar", "GET", Summary = "Finds movies and trailers similar to a given trailer.")] + public class GetSimilarTrailers : BaseGetSimilarItemsFromItem + { + } + [Route("/Movies/Recommendations", "GET", Summary = "Gets movie recommendations")] public class GetMovieRecommendations : IReturn, IHasItemFields { @@ -117,6 +125,17 @@ namespace MediaBrowser.Api.Movies return ToOptimizedSerializedResultUsingCache(result); } + public async Task Get(GetSimilarTrailers request) + { + var result = await GetSimilarItemsResult( + // Strip out secondary versions + request, item => (item is Movie) && !((Video)item).PrimaryVersionId.HasValue, + + SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false); + + return ToOptimizedSerializedResultUsingCache(result); + } + public async Task Get(GetMovieRecommendations request) { var user = _userManager.GetUserById(request.UserId); @@ -126,7 +145,7 @@ namespace MediaBrowser.Api.Movies movies = _libraryManager.ReplaceVideosWithPrimaryVersions(movies); var listEligibleForCategories = new List(); - var listEligibleForSuggestion = new List (); + var listEligibleForSuggestion = new List(); var list = movies.ToList(); @@ -159,7 +178,7 @@ namespace MediaBrowser.Api.Movies var dtoOptions = GetDtoOptions(request); dtoOptions.Fields = request.GetItemFields().ToList(); - + var result = GetRecommendationCategories(user, listEligibleForCategories, listEligibleForSuggestion, request.CategoryLimit, request.ItemLimit, dtoOptions); return ToOptimizedResult(result); @@ -174,14 +193,14 @@ namespace MediaBrowser.Api.Movies _libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id); Func filter = i => i.Id != item.Id && includeInSearch(i); - + var inputItems = user == null ? _libraryManager.RootFolder.GetRecursiveChildren(filter) : user.RootFolder.GetRecursiveChildren(user, filter); var list = inputItems.ToList(); - if (item is Movie && user != null && user.Configuration.IncludeTrailersInSuggestions) + if (user != null && user.Configuration.IncludeTrailersInSuggestions) { var trailerResult = await _channelManager.GetAllMediaInternal(new AllChannelMediaQuery { @@ -224,7 +243,7 @@ namespace MediaBrowser.Api.Movies } var dtoOptions = GetDtoOptions(request); - + var result = new ItemsResult { Items = _dtoService.GetBaseItemDtos(returnItems, dtoOptions, user).ToArray(), diff --git a/MediaBrowser.Api/Movies/TrailersService.cs b/MediaBrowser.Api/Movies/TrailersService.cs index 0847fc7ed2..ed197911a0 100644 --- a/MediaBrowser.Api/Movies/TrailersService.cs +++ b/MediaBrowser.Api/Movies/TrailersService.cs @@ -2,15 +2,12 @@ using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Channels; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; using ServiceStack; -using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -18,14 +15,6 @@ using System.Threading.Tasks; namespace MediaBrowser.Api.Movies { - /// - /// Class GetSimilarTrailers - /// - [Route("/Trailers/{Id}/Similar", "GET", Summary = "Finds movies and trailers similar to a given trailer.")] - public class GetSimilarTrailers : BaseGetSimilarItemsFromItem - { - } - [Route("/Trailers", "GET", Summary = "Finds movies and trailers similar to a given trailer.")] public class Getrailers : BaseItemsRequest, IReturn { @@ -51,7 +40,6 @@ namespace MediaBrowser.Api.Movies /// private readonly ILibraryManager _libraryManager; - private readonly IItemRepository _itemRepo; private readonly IDtoService _dtoService; private readonly IChannelManager _channelManager; @@ -61,40 +49,15 @@ namespace MediaBrowser.Api.Movies /// The user manager. /// The user data repository. /// The library manager. - public TrailersService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IItemRepository itemRepo, IDtoService dtoService, IChannelManager channelManager) + public TrailersService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IDtoService dtoService, IChannelManager channelManager) { _userManager = userManager; _userDataRepository = userDataRepository; _libraryManager = libraryManager; - _itemRepo = itemRepo; _dtoService = dtoService; _channelManager = channelManager; } - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetSimilarTrailers request) - { - var dtoOptions = GetDtoOptions(request); - - var result = SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager, - _itemRepo, - _libraryManager, - _userDataRepository, - _dtoService, - Logger, - - // Strip out secondary versions - request, item => (item is Movie) && !((Video)item).PrimaryVersionId.HasValue, - - SimilarItemsHelper.GetSimiliarityScore); - - return ToOptimizedSerializedResultUsingCache(result); - } - public async Task Get(Getrailers request) { var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null; diff --git a/MediaBrowser.Api/Music/AlbumsService.cs b/MediaBrowser.Api/Music/AlbumsService.cs index ea87c3ad37..548598d429 100644 --- a/MediaBrowser.Api/Music/AlbumsService.cs +++ b/MediaBrowser.Api/Music/AlbumsService.cs @@ -4,6 +4,7 @@ using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Persistence; +using MediaBrowser.Model.Querying; using ServiceStack; using System; using System.Collections.Generic; @@ -16,6 +17,11 @@ namespace MediaBrowser.Api.Music { } + [Route("/Artists/{Id}/Similar", "GET", Summary = "Finds albums similar to a given album.")] + public class GetSimilarArtists : BaseGetSimilarItemsFromItem + { + } + [Authenticated] public class AlbumsService : BaseApiService { @@ -44,6 +50,17 @@ namespace MediaBrowser.Api.Music _dtoService = dtoService; } + public object Get(GetSimilarArtists request) + { + var result = GetSimilarItemsResult( + + request, + + SimilarItemsHelper.GetSimiliarityScore); + + return ToOptimizedSerializedResultUsingCache(result); + } + /// /// Gets the specified request. /// @@ -65,6 +82,39 @@ namespace MediaBrowser.Api.Music return ToOptimizedSerializedResultUsingCache(result); } + private ItemsResult GetSimilarItemsResult(BaseGetSimilarItemsFromItem request, Func, List, BaseItem, int> getSimilarityScore) + { + var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null; + + var item = string.IsNullOrEmpty(request.Id) ? + (!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder : + _libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id); + + var inputItems = _libraryManager.GetArtists(user.RootFolder.GetRecursiveChildren(user, i => i is IHasArtist).OfType()); + + var list = inputItems.ToList(); + + var items = SimilarItemsHelper.GetSimilaritems(item, _libraryManager, list, getSimilarityScore).ToList(); + + IEnumerable returnItems = items; + + if (request.Limit.HasValue) + { + returnItems = returnItems.Take(request.Limit.Value); + } + + var dtoOptions = GetDtoOptions(request); + + var result = new ItemsResult + { + Items = _dtoService.GetBaseItemDtos(returnItems, dtoOptions, user).ToArray(), + + TotalRecordCount = items.Count + }; + + return result; + } + /// /// Gets the album similarity score. /// diff --git a/MediaBrowser.Api/UserLibrary/GenresService.cs b/MediaBrowser.Api/UserLibrary/GenresService.cs index 9e56907dae..d383bd0adb 100644 --- a/MediaBrowser.Api/UserLibrary/GenresService.cs +++ b/MediaBrowser.Api/UserLibrary/GenresService.cs @@ -1,12 +1,10 @@ using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Querying; using ServiceStack; using System; using System.Collections.Generic; diff --git a/MediaBrowser.Controller/Entities/IHasProgramAttributes.cs b/MediaBrowser.Controller/Entities/IHasProgramAttributes.cs index 391c8f7a7e..9938a44894 100644 --- a/MediaBrowser.Controller/Entities/IHasProgramAttributes.cs +++ b/MediaBrowser.Controller/Entities/IHasProgramAttributes.cs @@ -11,6 +11,7 @@ namespace MediaBrowser.Controller.Entities bool IsKids { get; set; } bool IsRepeat { get; set; } bool? IsHD { get; set; } + bool IsSeries { get; set; } bool IsLive { get; set; } bool IsPremiere { get; set; } ProgramAudio? Audio { get; set; } diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs b/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs index 9fc60beb9b..ba0b82a0b6 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs @@ -37,7 +37,6 @@ namespace MediaBrowser.Controller.LiveTv string ExternalId { get; set; } string EpisodeTitle { get; set; } - bool IsSeries { get; set; } string SeriesTimerId { get; set; } RecordingStatus Status { get; set; } DateTime? EndDate { get; set; } diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs index e52e7535b6..6d441ccf89 100644 --- a/MediaBrowser.Model/ApiClient/IApiClient.cs +++ b/MediaBrowser.Model/ApiClient/IApiClient.cs @@ -353,39 +353,7 @@ namespace MediaBrowser.Model.ApiClient /// The query. /// The cancellation token. /// Task{ItemsResult}. - Task GetSimilarMoviesAsync(SimilarItemsQuery query, CancellationToken cancellationToken = default(CancellationToken)); - - /// - /// Gets the similar trailers async. - /// - /// The query. - /// The cancellation token. - /// Task{ItemsResult}. - Task GetSimilarTrailersAsync(SimilarItemsQuery query, CancellationToken cancellationToken = default(CancellationToken)); - - /// - /// Gets the similar series async. - /// - /// The query. - /// The cancellation token. - /// Task{ItemsResult}. - Task GetSimilarSeriesAsync(SimilarItemsQuery query, CancellationToken cancellationToken = default(CancellationToken)); - - /// - /// Gets the similar albums async. - /// - /// The query. - /// The cancellation token. - /// Task{ItemsResult}. - Task GetSimilarAlbumsAsync(SimilarItemsQuery query, CancellationToken cancellationToken = default(CancellationToken)); - - /// - /// Gets the similar games async. - /// - /// The query. - /// The cancellation token. - /// Task{ItemsResult}. - Task GetSimilarGamesAsync(SimilarItemsQuery query, CancellationToken cancellationToken = default(CancellationToken)); + Task GetSimilarItemsAsync(SimilarItemsQuery query, CancellationToken cancellationToken = default(CancellationToken)); /// /// Gets the people async. @@ -442,20 +410,6 @@ namespace MediaBrowser.Model.ApiClient /// Task{ItemsResult}. Task GetGenresAsync(ItemsByNameQuery query); - /// - /// Gets the music genres async. - /// - /// The query. - /// Task{ItemsResult}. - Task GetMusicGenresAsync(ItemsByNameQuery query); - - /// - /// Gets the game genres async. - /// - /// The query. - /// Task{ItemsResult}. - Task GetGameGenresAsync(ItemsByNameQuery query); - /// /// Gets the studios async. /// diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index aa68e09a0f..ac8fa3370b 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -1081,6 +1081,15 @@ namespace MediaBrowser.Model.Dto get { return StringHelper.EqualsIgnoreCase(Type, "Studio"); } } + [IgnoreDataMember] + public bool SupportsSimilarItems + { + get + { + return IsType("Movie") || IsType("Series") || IsType("MusicAlbum") || IsType("MusicArtist") || IsType("Program") || IsType("Recording") || IsType("ChannelVideoItem") || IsType("Game"); + } + } + /// /// Occurs when [property changed]. /// diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index ebb5037d04..200c6c9a6e 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -517,7 +517,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV recordPath = Path.Combine(recordPath, "TV", _fileSystem.GetValidFilename(info.Name)); } - recordPath = Path.Combine(recordPath, _fileSystem.GetValidFilename(RecordingHelper.GetRecordingName(timer, info))); + var recordingFileName = _fileSystem.GetValidFilename(RecordingHelper.GetRecordingName(timer, info)) + ".ts"; + + recordPath = Path.Combine(recordPath, recordingFileName); Directory.CreateDirectory(Path.GetDirectoryName(recordPath)); var recording = _recordingProvider.GetAll().FirstOrDefault(x => string.Equals(x.ProgramId, info.Id, StringComparison.OrdinalIgnoreCase)); diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs index 1b8cd2e618..f8f65c6d52 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs @@ -37,7 +37,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { if (info == null) { - return timer.ProgramId + ".ts"; + return timer.ProgramId; } var name = info.Name; @@ -52,7 +52,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { name += " " + info.OriginalAirDate.Value.ToString("yyyy-MM-dd"); } - else if (!string.IsNullOrWhiteSpace(info.EpisodeTitle)) + + if (!string.IsNullOrWhiteSpace(info.EpisodeTitle)) { name += " " + info.EpisodeTitle; } @@ -63,7 +64,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV name += " (" + info.ProductionYear + ")"; } - return name + ".ts"; + return name; } } } -- cgit v1.2.3 From 23519642132d3b4ed39e42336fd860c2e00dcd3b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 25 Aug 2015 22:13:28 -0400 Subject: update movie filters --- .../LiveTv/EmbyTV/RecordingHelper.cs | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs') diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs index f8f65c6d52..5b83d63b17 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs @@ -44,15 +44,23 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV if (info.IsSeries) { + var addHyphen = true; + if (info.SeasonNumber.HasValue && info.EpisodeNumber.HasValue) { name += string.Format(" S{0}E{1}", info.SeasonNumber.Value.ToString("00", CultureInfo.InvariantCulture), info.EpisodeNumber.Value.ToString("00", CultureInfo.InvariantCulture)); + addHyphen = false; } else if (info.OriginalAirDate.HasValue) { name += " " + info.OriginalAirDate.Value.ToString("yyyy-MM-dd"); } + if (addHyphen) + { + name += " -"; + } + if (!string.IsNullOrWhiteSpace(info.EpisodeTitle)) { name += " " + info.EpisodeTitle; -- cgit v1.2.3