From fe3b4a1230c26d6ace23e97b5f718d209a170302 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 17 Jul 2015 18:32:00 -0400 Subject: add more play buttons --- .../FFMpeg/FFMpegDownloadInfo.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'MediaBrowser.Server.Startup.Common') diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs index 8a7d10bd7..5c5bc10e7 100644 --- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs +++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs @@ -33,7 +33,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg case OperatingSystem.Linux: info.ArchiveType = "7z"; - info.Version = "20150331"; + info.Version = "20150717"; break; case OperatingSystem.Osx: @@ -54,7 +54,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg info.FFMpegFilename = "ffmpeg.exe"; info.FFProbeFilename = "ffprobe.exe"; - info.Version = "20150331"; + info.Version = "20150717"; info.ArchiveType = "7z"; switch (environment.SystemArchitecture) @@ -83,14 +83,14 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg case Architecture.X86_X64: return new[] { - "http://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-20150331-git-5cba529-win64-static.7z", - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20150331-git-5cba529-win64-static.7z" + "http://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-20150717-git-8250943-win64-static.7z", + "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20150717-git-8250943-win64-static.7z" }; case Architecture.X86: return new[] { - "http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20150331-git-5cba529-win32-static.7z", - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20150331-git-5cba529-win32-static.7z" + "http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20150717-git-8250943-win32-static.7z", + "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20150717-git-8250943-win32-static.7z" }; } break; @@ -119,12 +119,12 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg case Architecture.X86_X64: return new[] { - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-2.6.1-64bit-static.7z" + "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-2.7.1-64bit-static.7z" }; case Architecture.X86: return new[] { - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-2.6.1-32bit-static.7z" + "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-2.7.1-32bit-static.7z" }; } break; -- cgit v1.2.3 From 3fda8ec5c264f077b625247ab29ce504be25774c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 23 Jul 2015 09:23:22 -0400 Subject: update tuner setup --- MediaBrowser.Api/LiveTv/LiveTvService.cs | 56 +++++++++++-- .../LiveTv/IListingsProvider.cs | 6 +- MediaBrowser.Controller/LiveTv/ILiveTvManager.cs | 25 +++++- MediaBrowser.Controller/LiveTv/ITunerHost.cs | 6 ++ MediaBrowser.Model/LiveTv/LiveTvOptions.cs | 5 +- .../LiveTv/EmbyTV/EmbyTV.cs | 14 ++-- .../LiveTv/Listings/SchedulesDirect.cs | 73 +++++++++------- .../LiveTv/LiveTvManager.cs | 98 +++++++++++++++++++++- .../LiveTv/TunerHosts/HdHomerun.cs | 8 +- .../LiveTv/TunerHosts/M3UTunerHost.cs | 8 ++ .../Localization/JavaScript/javascript.json | 5 +- .../Localization/Server/server.json | 5 +- .../ApplicationHost.cs | 2 +- .../MediaBrowser.WebDashboard.csproj | 4 +- 14 files changed, 256 insertions(+), 59 deletions(-) (limited to 'MediaBrowser.Server.Startup.Common') diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index 49ba001ce..f40048ce4 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Configuration; +using System.Collections.Generic; +using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; @@ -345,6 +346,31 @@ namespace MediaBrowser.Api.LiveTv public string Id { get; set; } } + [Route("/LiveTv/ListingProviders", "POST", Summary = "Adds a listing provider")] + [Authenticated] + public class AddListingProvider : ListingsProviderInfo, IReturn + { + } + + [Route("/LiveTv/ListingProviders", "DELETE", Summary = "Deletes a listing provider")] + [Authenticated] + public class DeleteListingProvider : IReturnVoid + { + [ApiMember(Name = "Id", Description = "Provider id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "DELETE")] + public string Id { get; set; } + } + + [Route("/LiveTv/ListingProviders/Lineups", "GET", Summary = "Gets available lineups")] + [Authenticated] + public class GetLineups : IReturn> + { + [ApiMember(Name = "Id", Description = "Provider id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public string Id { get; set; } + + [ApiMember(Name = "Location", Description = "Location", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public string Location { get; set; } + } + public class LiveTvService : BaseApiService { private readonly ILiveTvManager _liveTvManager; @@ -373,20 +399,27 @@ namespace MediaBrowser.Api.LiveTv } } - public void Post(AddTunerHost request) + public object Post(AddListingProvider request) + { + var result = _liveTvManager.SaveListingProvider(request).Result; + return ToOptimizedResult(result); + } + + public void Delete(DeleteListingProvider request) { var config = GetConfiguration(); - config.TunerHosts.Add(new TunerHostInfo - { - Id = Guid.NewGuid().ToString("N"), - Url = request.Url, - Type = request.Type - }); + config.ListingProviders = config.ListingProviders.Where(i => !string.Equals(request.Id, i.Id, StringComparison.OrdinalIgnoreCase)).ToList(); _config.SaveConfiguration("livetv", config); } + public void Post(AddTunerHost request) + { + var task = _liveTvManager.SaveTunerHost(request); + Task.WaitAll(task); + } + public void Delete(DeleteTunerHost request) { var config = GetConfiguration(); @@ -401,6 +434,13 @@ namespace MediaBrowser.Api.LiveTv return _config.GetConfiguration("livetv"); } + public async Task Get(GetLineups request) + { + var info = await _liveTvManager.GetLineups(request.Id, request.Location).ConfigureAwait(false); + + return ToOptimizedSerializedResultUsingCache(info); + } + public async Task Get(GetLiveTvInfo request) { var info = await _liveTvManager.GetLiveTvInfo(CancellationToken.None).ConfigureAwait(false); diff --git a/MediaBrowser.Controller/LiveTv/IListingsProvider.cs b/MediaBrowser.Controller/LiveTv/IListingsProvider.cs index beaa4eeaf..e509728bf 100644 --- a/MediaBrowser.Controller/LiveTv/IListingsProvider.cs +++ b/MediaBrowser.Controller/LiveTv/IListingsProvider.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Model.LiveTv; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.LiveTv; using System; using System.Collections.Generic; using System.Threading; @@ -9,7 +10,10 @@ namespace MediaBrowser.Controller.LiveTv public interface IListingsProvider { string Name { get; } + string Type { get; } Task> GetProgramsAsync(ListingsProviderInfo info, ChannelInfo channel, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken); Task AddMetadata(ListingsProviderInfo info, List channels, CancellationToken cancellationToken); + Task Validate(ListingsProviderInfo info); + Task> GetLineups(ListingsProviderInfo info, string location); } } diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index 3aa1f66ef..3dbf9a9e9 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -56,12 +56,14 @@ namespace MediaBrowser.Controller.LiveTv /// The identifier. /// Task. Task CancelSeriesTimer(string id); - + /// /// Adds the parts. /// /// The services. - void AddParts(IEnumerable services); + /// The tuner hosts. + /// The listing providers. + void AddParts(IEnumerable services, IEnumerable tunerHosts, IEnumerable listingProviders); /// /// Gets the channels. @@ -337,5 +339,24 @@ namespace MediaBrowser.Controller.LiveTv /// The dto. /// The user. void AddInfoToProgramDto(BaseItem item, BaseItemDto dto, User user = null); + /// + /// Saves the tuner host. + /// + /// The information. + /// Task. + Task SaveTunerHost(TunerHostInfo info); + /// + /// Saves the listing provider. + /// + /// The information. + /// Task. + Task SaveListingProvider(ListingsProviderInfo info); + /// + /// Gets the lineups. + /// + /// The provider identifier. + /// The location. + /// Task<List<NameIdPair>>. + Task> GetLineups(string providerId, string location); } } diff --git a/MediaBrowser.Controller/LiveTv/ITunerHost.cs b/MediaBrowser.Controller/LiveTv/ITunerHost.cs index 2fa538c60..38ed43bd9 100644 --- a/MediaBrowser.Controller/LiveTv/ITunerHost.cs +++ b/MediaBrowser.Controller/LiveTv/ITunerHost.cs @@ -46,5 +46,11 @@ namespace MediaBrowser.Controller.LiveTv /// The cancellation token. /// Task<MediaSourceInfo>. Task GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken); + /// + /// Validates the specified information. + /// + /// The information. + /// Task. + Task Validate(TunerHostInfo info); } } diff --git a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs index c78fbe630..90cd8924d 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs @@ -28,10 +28,11 @@ namespace MediaBrowser.Model.LiveTv public class ListingsProviderInfo { - public string ProviderName { get; set; } + public string Id { get; set; } + public string Type { get; set; } public string Username { get; set; } public string Password { get; set; } - public string ZipCode { get; set; } public string ListingsId { get; set; } + public string ZipCode { get; set; } } } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 26e070921..6e8213ee0 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -30,18 +30,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private readonly ItemDataProvider _seriesTimerProvider; private readonly TimerManager _timerProvider; - private readonly List _tunerHosts = new List(); - private readonly List _listingProviders = new List(); + private readonly LiveTvManager _liveTvManager; - public EmbyTV(IApplicationHost appHost, ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IConfigurationManager config) + public EmbyTV(IApplicationHost appHost, ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IConfigurationManager config, ILiveTvManager liveTvManager) { _appHpst = appHost; _logger = logger; _httpClient = httpClient; _config = config; + _liveTvManager = (LiveTvManager)liveTvManager; _jsonSerializer = jsonSerializer; - _tunerHosts.AddRange(appHost.GetExports()); - _listingProviders.AddRange(appHost.GetExports()); _recordingProvider = new ItemDataProvider(jsonSerializer, _logger, Path.Combine(DataPath, "recordings"), (r1, r2) => string.Equals(r1.Id, r2.Id, StringComparison.OrdinalIgnoreCase)); _seriesTimerProvider = new SeriesTimerManager(jsonSerializer, _logger, Path.Combine(DataPath, "seriestimers")); @@ -76,7 +74,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV var status = new LiveTvServiceStatusInfo(); var list = new List(); - foreach (var host in _tunerHosts) + foreach (var host in _liveTvManager.TunerHosts) { foreach (var hostInstance in host.GetTunerHosts()) { @@ -104,7 +102,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { var list = new List(); - foreach (var host in _tunerHosts) + foreach (var host in _liveTvManager.TunerHosts) { foreach (var hostInstance in host.GetTunerHosts()) { @@ -288,7 +286,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV return GetConfiguration().ListingProviders .Select(i => { - var provider = _listingProviders.FirstOrDefault(l => string.Equals(l.Name, i.ProviderName, StringComparison.OrdinalIgnoreCase)); + var provider = _liveTvManager.ListingProviders.FirstOrDefault(l => string.Equals(l.Type, i.Type, StringComparison.OrdinalIgnoreCase)); return provider == null ? null : new Tuple(provider, i); }) diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 3b7564983..f5b41f3df 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -422,7 +422,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings return images; } - public async Task> GetHeadends(ListingsProviderInfo info, CancellationToken cancellationToken) + public async Task> GetHeadends(ListingsProviderInfo info, string location, CancellationToken cancellationToken) { var token = await GetToken(info, cancellationToken); @@ -437,7 +437,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings var options = new HttpRequestOptions() { - Url = ApiUrl + "/headends?country=USA&postalcode=" + info.ZipCode, + Url = ApiUrl + "/headends?country=USA&postalcode=" + location, UserAgent = UserAgent, CancellationToken = cancellationToken }; @@ -484,43 +484,43 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings private async Task GetToken(ListingsProviderInfo info, CancellationToken cancellationToken) { - await _tokenSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); - try - { - var username = info.Username; + var username = info.Username; - // Reset the token if there's no username - if (string.IsNullOrWhiteSpace(username)) - { - return null; - } + // Reset the token if there's no username + if (string.IsNullOrWhiteSpace(username)) + { + return null; + } - var password = info.Password; - if (string.IsNullOrWhiteSpace(password)) - { - return null; - } + var password = info.Password; + if (string.IsNullOrWhiteSpace(password)) + { + return null; + } - NameValuePair savedToken = null; - if (!_tokens.TryGetValue(username, out savedToken)) - { - savedToken = new NameValuePair(); - _tokens.TryAdd(username, savedToken); - } + NameValuePair savedToken = null; + if (!_tokens.TryGetValue(username, out savedToken)) + { + savedToken = new NameValuePair(); + _tokens.TryAdd(username, savedToken); + } - if (!string.IsNullOrWhiteSpace(savedToken.Name) && !string.IsNullOrWhiteSpace(savedToken.Value)) + if (!string.IsNullOrWhiteSpace(savedToken.Name) && !string.IsNullOrWhiteSpace(savedToken.Value)) + { + long ticks; + if (long.TryParse(savedToken.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out ticks)) { - long ticks; - if (long.TryParse(savedToken.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out ticks)) + // If it's under 24 hours old we can still use it + if ((DateTime.UtcNow.Ticks - ticks) < TimeSpan.FromHours(24).Ticks) { - // If it's under 24 hours old we can still use it - if ((DateTime.UtcNow.Ticks - ticks) < TimeSpan.FromHours(24).Ticks) - { - return savedToken.Name; - } + return savedToken.Name; } } + } + await _tokenSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); + try + { var result = await GetTokenInternal(username, password, cancellationToken).ConfigureAwait(false); savedToken.Name = result; savedToken.Value = DateTime.UtcNow.Ticks.ToString(CultureInfo.InvariantCulture); @@ -563,6 +563,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings get { return "Schedules Direct"; } } + public string Type + { + get { return "SchedulesDirect"; } + } + public class ScheduleDirect { public class Token @@ -842,5 +847,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings } + public async Task Validate(ListingsProviderInfo info) + { + } + + public Task> GetLineups(ListingsProviderInfo info, string location) + { + return GetHeadends(info, location, CancellationToken.None); + } } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 05bc276b8..a64ce31cf 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -57,6 +57,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv private readonly ConcurrentDictionary _refreshedPrograms = new ConcurrentDictionary(); + private readonly List _tunerHosts = new List(); + private readonly List _listingProviders = new List(); + public LiveTvManager(IApplicationHost appHost, IServerConfigurationManager config, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager, ILibraryManager libraryManager, ITaskManager taskManager, ILocalizationManager localization, IJsonSerializer jsonSerializer, IProviderManager providerManager) { _config = config; @@ -92,9 +95,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv /// Adds the parts. /// /// The services. - public void AddParts(IEnumerable services) + /// The tuner hosts. + /// The listing providers. + public void AddParts(IEnumerable services, IEnumerable tunerHosts, IEnumerable listingProviders) { _services.AddRange(services); + _tunerHosts.AddRange(tunerHosts); + _listingProviders.AddRange(listingProviders); foreach (var service in _services) { @@ -102,6 +109,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv } } + public List TunerHosts + { + get { return _tunerHosts; } + } + + public List ListingProviders + { + get { return _listingProviders; } + } + void service_DataSourceChanged(object sender, EventArgs e) { _taskManager.CancelIfRunningAndQueue(); @@ -2154,5 +2171,84 @@ namespace MediaBrowser.Server.Implementations.LiveTv var user = _userManager.GetUserById(userId); return await _libraryManager.GetNamedView(user, name, "livetv", "zz_" + name, cancellationToken).ConfigureAwait(false); } + + public async Task SaveTunerHost(TunerHostInfo info) + { + info = (TunerHostInfo)_jsonSerializer.DeserializeFromString(_jsonSerializer.SerializeToString(info), typeof(TunerHostInfo)); + + var provider = _tunerHosts.FirstOrDefault(i => string.Equals(info.Type, i.Type, StringComparison.OrdinalIgnoreCase)); + + if (provider == null) + { + throw new ResourceNotFoundException(); + } + + await provider.Validate(info).ConfigureAwait(false); + + var config = GetConfiguration(); + + var index = config.TunerHosts.FindIndex(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase)); + + if (index == -1 || string.IsNullOrWhiteSpace(info.Id)) + { + info.Id = Guid.NewGuid().ToString("N"); + config.TunerHosts.Add(info); + } + else + { + config.TunerHosts[index] = info; + } + + _config.SaveConfiguration("livetv", config); + } + + public async Task SaveListingProvider(ListingsProviderInfo info) + { + info = (ListingsProviderInfo)_jsonSerializer.DeserializeFromString(_jsonSerializer.SerializeToString(info), typeof(ListingsProviderInfo)); + + var provider = _listingProviders.FirstOrDefault(i => string.Equals(info.Type, i.Type, StringComparison.OrdinalIgnoreCase)); + + if (provider == null) + { + throw new ResourceNotFoundException(); + } + + await provider.Validate(info).ConfigureAwait(false); + + var config = GetConfiguration(); + + var index = config.ListingProviders.FindIndex(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase)); + + if (index == -1 || string.IsNullOrWhiteSpace(info.Id)) + { + info.Id = Guid.NewGuid().ToString("N"); + config.ListingProviders.Add(info); + } + else + { + config.ListingProviders[index] = info; + } + + _config.SaveConfiguration("livetv", config); + + return info; + } + + + public Task> GetLineups(string providerId, string location) + { + var config = GetConfiguration(); + + var info = config.ListingProviders.FirstOrDefault(i => string.Equals(i.Id, providerId, StringComparison.OrdinalIgnoreCase)); + + var provider = _listingProviders.FirstOrDefault(i => string.Equals(info.Type, i.Type, StringComparison.OrdinalIgnoreCase)); + + if (provider == null) + { + throw new ResourceNotFoundException(); + } + + return provider.GetLineups(info, location); + } } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun.cs index b5b588682..9aacd0c1e 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun.cs @@ -3,7 +3,6 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Logging; using MediaBrowser.Model.MediaInfo; @@ -15,7 +14,6 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Server.Implementations.LiveTv.EmbyTV; namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts { @@ -222,5 +220,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts } throw new ApplicationException("Channel not found."); } + + + public async Task Validate(TunerHostInfo info) + { + await GetChannels(info, CancellationToken.None).ConfigureAwait(false); + } } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs index 615e07a82..e91bd0f0b 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs @@ -185,5 +185,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts { } } + + public async Task Validate(TunerHostInfo info) + { + if (!File.Exists(info.Url)) + { + throw new FileNotFoundException(); + } + } } } diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json index d2b998ae8..cea0363f4 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json @@ -820,5 +820,8 @@ "MessageConfirmDeleteTunerDevice": "Are you sure you wish to delete this device?", "MessageConfirmDeleteGuideProvider": "Are you sure you wish to delete this guide provider?", "HeaderDeleteProvider": "Delete Provider", - "HeaderAddProvider": "Add Provider" + "HeaderAddProvider": "Add Provider", + "ErrorAddingTunerDevice": "There was an error adding the tuner device. Please ensure it is accessible and try again.", + "ErrorSavingTvProvider": "There was an error saving the TV provider. Please ensure it is accessible and try again.", + "ErrorGettingTvLineups": "There was an error downloading tv lineups. Please ensure your username and password are correct and try again." } diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index 83c2ccf5d..fe099dc67 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -1483,5 +1483,8 @@ "TabTuners": "Tuners", "HeaderGuideProviders": "Guide Providers", "AddGuideProviderHelp": "Add a source for TV Guide information", - "LabelZipCode": "Zip Code" + "LabelZipCode": "Zip Code:", + "GuideProviderListingsStep": "Step 2: Select Listings", + "GuideProviderLoginStep": "Step 1: Login", + "LabelLineup": "Lineup" } diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index fab6682d7..adef0a45f 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -784,7 +784,7 @@ namespace MediaBrowser.Server.Startup.Common ImageProcessor.AddParts(GetExports()); - LiveTvManager.AddParts(GetExports()); + LiveTvManager.AddParts(GetExports(), GetExports(), GetExports()); SubtitleManager.AddParts(GetExports()); ChapterManager.AddParts(GetExports()); diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 1920a9ed7..bc2b8eb7a 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -183,7 +183,7 @@ PreserveNewest - + PreserveNewest @@ -207,7 +207,7 @@ PreserveNewest - + PreserveNewest -- cgit v1.2.3 From ffd9460d51980a550ef5460e5df4e942b63077a7 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 23 Jul 2015 12:32:34 -0400 Subject: add hdhomerun auto-discovery --- MediaBrowser.Controller/Dlna/IDeviceDiscovery.cs | 10 + .../MediaBrowser.Controller.csproj | 1 + MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs | 10 +- MediaBrowser.Dlna/Main/DlnaEntryPoint.cs | 24 +-- MediaBrowser.Dlna/PlayTo/PlayToController.cs | 5 +- MediaBrowser.Dlna/PlayTo/PlayToManager.cs | 4 +- MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs | 19 +- .../Library/Resolvers/TV/SeriesResolver.cs | 9 +- .../LiveTv/Listings/SchedulesDirect.cs | 2 +- .../LiveTv/TunerHosts/HdHomerun.cs | 230 -------------------- .../TunerHosts/HdHomerun/HdHomerunDiscovery.cs | 114 ++++++++++ .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 235 +++++++++++++++++++++ .../MediaBrowser.Server.Implementations.csproj | 3 +- .../ApplicationHost.cs | 2 + 14 files changed, 396 insertions(+), 272 deletions(-) create mode 100644 MediaBrowser.Controller/Dlna/IDeviceDiscovery.cs delete mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunDiscovery.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs (limited to 'MediaBrowser.Server.Startup.Common') diff --git a/MediaBrowser.Controller/Dlna/IDeviceDiscovery.cs b/MediaBrowser.Controller/Dlna/IDeviceDiscovery.cs new file mode 100644 index 000000000..e8083b363 --- /dev/null +++ b/MediaBrowser.Controller/Dlna/IDeviceDiscovery.cs @@ -0,0 +1,10 @@ +using System; + +namespace MediaBrowser.Controller.Dlna +{ + public interface IDeviceDiscovery + { + event EventHandler DeviceDiscovered; + event EventHandler DeviceLeft; + } +} diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 603f756af..dd9383827 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -113,6 +113,7 @@ + diff --git a/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs b/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs index 7e896492d..f26ceff90 100644 --- a/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs +++ b/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs @@ -24,7 +24,7 @@ namespace MediaBrowser.Dlna.Channels private readonly ILogger _logger; private readonly IHttpClient _httpClient; - private DeviceDiscovery _deviceDiscovery; + private readonly IDeviceDiscovery _deviceDiscovery; private readonly SemaphoreSlim _syncLock = new SemaphoreSlim(1, 1); private List _servers = new List(); @@ -33,21 +33,21 @@ namespace MediaBrowser.Dlna.Channels private Func> _localServersLookup; - public DlnaChannelFactory(IServerConfigurationManager config, IHttpClient httpClient, ILogger logger) + public DlnaChannelFactory(IServerConfigurationManager config, IHttpClient httpClient, ILogger logger, IDeviceDiscovery deviceDiscovery) { _config = config; _httpClient = httpClient; _logger = logger; + _deviceDiscovery = deviceDiscovery; Instance = this; } - internal void Start(DeviceDiscovery deviceDiscovery, Func> localServersLookup) + internal void Start(Func> localServersLookup) { _localServersLookup = localServersLookup; - _deviceDiscovery = deviceDiscovery; //deviceDiscovery.DeviceDiscovered += deviceDiscovery_DeviceDiscovered; - deviceDiscovery.DeviceLeft += deviceDiscovery_DeviceLeft; + _deviceDiscovery.DeviceLeft += deviceDiscovery_DeviceLeft; } async void deviceDiscovery_DeviceDiscovered(object sender, SsdpMessageEventArgs e) diff --git a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs index f9f9c3f18..bdb778cab 100644 --- a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs +++ b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs @@ -38,7 +38,7 @@ namespace MediaBrowser.Dlna.Main private readonly IMediaSourceManager _mediaSourceManager; private readonly SsdpHandler _ssdpHandler; - private DeviceDiscovery _deviceDiscovery; + private readonly IDeviceDiscovery _deviceDiscovery; private readonly List _registeredServerIds = new List(); private bool _dlnaServerStarted; @@ -56,7 +56,7 @@ namespace MediaBrowser.Dlna.Main IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, - ISsdpHandler ssdpHandler) + ISsdpHandler ssdpHandler, IDeviceDiscovery deviceDiscovery) { _config = config; _appHost = appHost; @@ -70,6 +70,7 @@ namespace MediaBrowser.Dlna.Main _userDataManager = userDataManager; _localization = localization; _mediaSourceManager = mediaSourceManager; + _deviceDiscovery = deviceDiscovery; _ssdpHandler = (SsdpHandler)ssdpHandler; _logger = logManager.GetLogger("Dlna"); } @@ -81,7 +82,7 @@ namespace MediaBrowser.Dlna.Main _config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated; - DlnaChannelFactory.Instance.Start(_deviceDiscovery, () => _registeredServerIds); + DlnaChannelFactory.Instance.Start(() => _registeredServerIds); } void _config_NamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e) @@ -125,9 +126,7 @@ namespace MediaBrowser.Dlna.Main { _ssdpHandler.Start(); - _deviceDiscovery = new DeviceDiscovery(_logger, _config, _ssdpHandler, _appHost); - - _deviceDiscovery.Start(); + ((DeviceDiscovery)_deviceDiscovery).Start(_ssdpHandler); } catch (Exception ex) { @@ -135,18 +134,6 @@ namespace MediaBrowser.Dlna.Main } } - private void DisposeDeviceDiscovery() - { - try - { - _deviceDiscovery.Dispose(); - } - catch (Exception ex) - { - _logger.ErrorException("Error disposing device discovery", ex); - } - } - public void StartDlnaServer() { try @@ -240,7 +227,6 @@ namespace MediaBrowser.Dlna.Main { DisposeDlnaServer(); DisposePlayToManager(); - DisposeDeviceDiscovery(); } public void DisposeDlnaServer() diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs index f6cf2f02d..941b2aeca 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToController.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs @@ -5,7 +5,6 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Localization; using MediaBrowser.Controller.Session; using MediaBrowser.Dlna.Didl; -using MediaBrowser.Dlna.Ssdp; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -35,7 +34,7 @@ namespace MediaBrowser.Dlna.PlayTo private readonly ILocalizationManager _localization; private readonly IMediaSourceManager _mediaSourceManager; - private readonly DeviceDiscovery _deviceDiscovery; + private readonly IDeviceDiscovery _deviceDiscovery; private readonly string _serverAddress; private readonly string _accessToken; @@ -58,7 +57,7 @@ namespace MediaBrowser.Dlna.PlayTo private Timer _updateTimer; - public PlayToController(SessionInfo session, ISessionManager sessionManager, ILibraryManager libraryManager, ILogger logger, IDlnaManager dlnaManager, IUserManager userManager, IImageProcessor imageProcessor, string serverAddress, string accessToken, DeviceDiscovery deviceDiscovery, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager) + public PlayToController(SessionInfo session, ISessionManager sessionManager, ILibraryManager libraryManager, ILogger logger, IDlnaManager dlnaManager, IUserManager userManager, IImageProcessor imageProcessor, string serverAddress, string accessToken, IDeviceDiscovery deviceDiscovery, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager) { _session = session; _sessionManager = sessionManager; diff --git a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs index 5d37767a2..6c79007c4 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs @@ -32,13 +32,13 @@ namespace MediaBrowser.Dlna.PlayTo private readonly IUserDataManager _userDataManager; private readonly ILocalizationManager _localization; - private readonly DeviceDiscovery _deviceDiscovery; + private readonly IDeviceDiscovery _deviceDiscovery; private readonly IMediaSourceManager _mediaSourceManager; private readonly List _nonRendererUrls = new List(); private Timer _clearNonRenderersTimer; - public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, DeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager) + public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager) { _logger = logger; _sessionManager = sessionManager; diff --git a/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs b/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs index 3befa221b..c9b983bae 100644 --- a/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs +++ b/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs @@ -14,31 +14,31 @@ using System.Threading.Tasks; namespace MediaBrowser.Dlna.Ssdp { - public class DeviceDiscovery : IDisposable + public class DeviceDiscovery : IDeviceDiscovery, IDisposable { private bool _disposed; private readonly ILogger _logger; private readonly IServerConfigurationManager _config; - private readonly SsdpHandler _ssdpHandler; + private SsdpHandler _ssdpHandler; private readonly CancellationTokenSource _tokenSource; private readonly IServerApplicationHost _appHost; public event EventHandler DeviceDiscovered; public event EventHandler DeviceLeft; - public DeviceDiscovery(ILogger logger, IServerConfigurationManager config, SsdpHandler ssdpHandler, IServerApplicationHost appHost) + public DeviceDiscovery(ILogger logger, IServerConfigurationManager config, IServerApplicationHost appHost) { _tokenSource = new CancellationTokenSource(); _logger = logger; _config = config; - _ssdpHandler = ssdpHandler; _appHost = appHost; } - public void Start() + public void Start(SsdpHandler ssdpHandler) { + _ssdpHandler = ssdpHandler; _ssdpHandler.MessageReceived += _ssdpHandler_MessageReceived; foreach (var network in GetNetworkInterfaces()) @@ -71,7 +71,7 @@ namespace MediaBrowser.Dlna.Ssdp } } } - + void _ssdpHandler_MessageReceived(object sender, SsdpMessageEventArgs e) { string nts; @@ -199,7 +199,7 @@ namespace MediaBrowser.Dlna.Ssdp socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 4); socket.Bind(localEndpoint); - + return socket; } @@ -248,7 +248,10 @@ namespace MediaBrowser.Dlna.Ssdp public void Dispose() { - _ssdpHandler.MessageReceived -= _ssdpHandler_MessageReceived; + if (_ssdpHandler != null) + { + _ssdpHandler.MessageReceived -= _ssdpHandler_MessageReceived; + } if (!_disposed) { diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs index 70ab105b2..f12022dc7 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs @@ -125,7 +125,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV if ((attributes & FileAttributes.Directory) == FileAttributes.Directory) { - if (IsSeasonFolder(child.FullName, isTvContentType)) + if (IsSeasonFolder(child.FullName, isTvContentType, libraryManager)) { //logger.Debug("{0} is a series because of season folder {1}.", path, child.FullName); return true; @@ -188,10 +188,13 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV /// /// The path. /// if set to true [is tv content type]. + /// The library manager. /// true if [is season folder] [the specified path]; otherwise, false. - private static bool IsSeasonFolder(string path, bool isTvContentType) + private static bool IsSeasonFolder(string path, bool isTvContentType, ILibraryManager libraryManager) { - var seasonNumber = new SeasonPathParser(new ExtendedNamingOptions(), new RegexProvider()).Parse(path, isTvContentType, isTvContentType).SeasonNumber; + var namingOptions = ((LibraryManager)libraryManager).GetNamingOptions(); + + var seasonNumber = new SeasonPathParser(namingOptions, new RegexProvider()).Parse(path, isTvContentType, isTvContentType).SeasonNumber; return seasonNumber.HasValue; } diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 2656397bb..668f023d2 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -350,7 +350,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings { url = apiUrl + "/image/" + images.data[logoIndex].uri; } - _logger.Debug("URL for image is : " + url); + //_logger.Debug("URL for image is : " + url); } return url; } diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun.cs deleted file mode 100644 index 9aacd0c1e..000000000 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun.cs +++ /dev/null @@ -1,230 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.LiveTv; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.Serialization; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts -{ - public class HdHomerun : ITunerHost - { - private readonly IHttpClient _httpClient; - private readonly ILogger _logger; - private readonly IJsonSerializer _jsonSerializer; - private readonly IConfigurationManager _config; - - public HdHomerun(IHttpClient httpClient, ILogger logger, IJsonSerializer jsonSerializer, IConfigurationManager config) - { - _httpClient = httpClient; - _logger = logger; - _jsonSerializer = jsonSerializer; - _config = config; - } - - public string Name - { - get { return "HD Homerun"; } - } - - public string Type - { - get { return "hdhomerun"; } - } - - public async Task> GetChannels(TunerHostInfo info, CancellationToken cancellationToken) - { - var options = new HttpRequestOptions - { - Url = string.Format("{0}/lineup.json", GetApiUrl(info)), - CancellationToken = cancellationToken - }; - using (var stream = await _httpClient.Get(options)) - { - var root = _jsonSerializer.DeserializeFromStream>(stream); - - if (root != null) - { - return root.Select(i => new ChannelInfo - { - Name = i.GuideName, - Number = i.GuideNumber.ToString(CultureInfo.InvariantCulture), - Id = i.GuideNumber.ToString(CultureInfo.InvariantCulture), - IsFavorite = i.Favorite - - }); - } - return new List(); - } - } - - public async Task> GetTunerInfos(TunerHostInfo info, CancellationToken cancellationToken) - { - string model = null; - - using (var stream = await _httpClient.Get(new HttpRequestOptions() - { - Url = string.Format("{0}/", GetApiUrl(info)), - CancellationToken = cancellationToken - })) - { - using (var sr = new StreamReader(stream, System.Text.Encoding.UTF8)) - { - while (!sr.EndOfStream) - { - string line = StripXML(sr.ReadLine()); - if (line.StartsWith("Model:")) { model = line.Replace("Model: ", ""); } - //if (line.StartsWith("Device ID:")) { deviceID = line.Replace("Device ID: ", ""); } - //if (line.StartsWith("Firmware:")) { firmware = line.Replace("Firmware: ", ""); } - } - } - } - - using (var stream = await _httpClient.Get(new HttpRequestOptions() - { - Url = string.Format("{0}/tuners.html", GetApiUrl(info)), - CancellationToken = cancellationToken - })) - { - var tuners = new List(); - using (var sr = new StreamReader(stream, System.Text.Encoding.UTF8)) - { - while (!sr.EndOfStream) - { - string line = StripXML(sr.ReadLine()); - if (line.Contains("Channel")) - { - LiveTvTunerStatus status; - var index = line.IndexOf("Channel", StringComparison.OrdinalIgnoreCase); - var name = line.Substring(0, index - 1); - var currentChannel = line.Substring(index + 7); - if (currentChannel != "none") { status = LiveTvTunerStatus.LiveTv; } else { status = LiveTvTunerStatus.Available; } - tuners.Add(new LiveTvTunerInfo() - { - Name = name, - SourceType = string.IsNullOrWhiteSpace(model) ? Name : model, - ProgramName = currentChannel, - Status = status - }); - } - } - } - return tuners; - } - } - - public string GetApiUrl(TunerHostInfo info) - { - var url = info.Url; - - if (!url.StartsWith("http", StringComparison.OrdinalIgnoreCase)) - { - url = "http://" + url; - } - - return url.TrimEnd('/'); - } - - private static string StripXML(string source) - { - char[] buffer = new char[source.Length]; - int bufferIndex = 0; - bool inside = false; - - for (int i = 0; i < source.Length; i++) - { - char let = source[i]; - if (let == '<') - { - inside = true; - continue; - } - if (let == '>') - { - inside = false; - continue; - } - if (!inside) - { - buffer[bufferIndex] = let; - bufferIndex++; - } - } - return new string(buffer, 0, bufferIndex); - } - - private class Channels - { - public string GuideNumber { get; set; } - public string GuideName { get; set; } - public string URL { get; set; } - public bool Favorite { get; set; } - public bool DRM { get; set; } - } - - private LiveTvOptions GetConfiguration() - { - return _config.GetConfiguration("livetv"); - } - - public List GetTunerHosts() - { - return GetConfiguration().TunerHosts.Where(i => string.Equals(i.Type, Type, StringComparison.OrdinalIgnoreCase)).ToList(); - } - - public async Task GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken) - { - var channels = await GetChannels(info, cancellationToken).ConfigureAwait(false); - var tuners = await GetTunerInfos(info, cancellationToken).ConfigureAwait(false); - - var channel = channels.FirstOrDefault(c => string.Equals(c.Id, channelId, StringComparison.OrdinalIgnoreCase)); - if (channel != null) - { - if (tuners.FindIndex(t => t.Status == LiveTvTunerStatus.Available) >= 0) - { - return new MediaSourceInfo - { - Path = GetApiUrl(info) + "/auto/v" + channelId, - Protocol = MediaProtocol.Http, - MediaStreams = new List - { - new MediaStream - { - Type = MediaStreamType.Video, - // Set the index to -1 because we don't know the exact index of the video stream within the container - Index = -1, - IsInterlaced = true - }, - new MediaStream - { - Type = MediaStreamType.Audio, - // Set the index to -1 because we don't know the exact index of the audio stream within the container - Index = -1 - - } - } - }; - } - - throw new ApplicationException("No tuners avaliable."); - } - throw new ApplicationException("Channel not found."); - } - - - public async Task Validate(TunerHostInfo info) - { - await GetChannels(info, CancellationToken.None).ConfigureAwait(false); - } - } -} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunDiscovery.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunDiscovery.cs new file mode 100644 index 000000000..41652ae9f --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunDiscovery.cs @@ -0,0 +1,114 @@ +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Dlna; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Controller.Plugins; +using MediaBrowser.Model.Extensions; +using MediaBrowser.Model.LiveTv; +using MediaBrowser.Model.Logging; +using System; +using System.Linq; +using System.Threading; + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun +{ + public class HdHomerunDiscovery : IServerEntryPoint + { + private readonly IDeviceDiscovery _deviceDiscovery; + private readonly IServerConfigurationManager _config; + private readonly ILogger _logger; + private readonly ILiveTvManager _liveTvManager; + private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); + + public HdHomerunDiscovery(IDeviceDiscovery deviceDiscovery, IServerConfigurationManager config, ILogger logger, ILiveTvManager liveTvManager) + { + _deviceDiscovery = deviceDiscovery; + _config = config; + _logger = logger; + _liveTvManager = liveTvManager; + } + + public void Run() + { + _deviceDiscovery.DeviceDiscovered += _deviceDiscovery_DeviceDiscovered; + } + + void _deviceDiscovery_DeviceDiscovered(object sender, SsdpMessageEventArgs e) + { + string server = null; + if (e.Headers.TryGetValue("SERVER", out server) && server.IndexOf("HDHomeRun", StringComparison.OrdinalIgnoreCase) != -1) + { + string location; + if (e.Headers.TryGetValue("Location", out location)) + { + _logger.Debug("HdHomerun found at {0}", location); + + // Just get the beginning of the url + Uri uri; + if (Uri.TryCreate(location, UriKind.Absolute, out uri)) + { + var apiUrl = location.Replace(uri.LocalPath, String.Empty, StringComparison.OrdinalIgnoreCase) + .TrimEnd('/'); + + _logger.Debug("HdHomerun api url: {0}", apiUrl); + AddDevice(apiUrl); + } + } + } + } + + private async void AddDevice(string url) + { + await _semaphore.WaitAsync().ConfigureAwait(false); + + try + { + var options = GetConfiguration(); + + if (options.TunerHosts.Any(i => + string.Equals(i.Type, HdHomerunHost.DeviceType, StringComparison.OrdinalIgnoreCase) && + UriEquals(i.Url, url))) + { + return; + } + + await _liveTvManager.SaveTunerHost(new TunerHostInfo + { + Type = HdHomerunHost.DeviceType, + Url = url + + }).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error saving device", ex); + } + finally + { + _semaphore.Release(); + } + } + + private bool UriEquals(string savedUri, string location) + { + if (!savedUri.StartsWith("http", StringComparison.OrdinalIgnoreCase)) + { + savedUri = "http://" + savedUri; + } + + savedUri = savedUri.TrimEnd('/'); + location = location.TrimEnd('/'); + + return string.Equals(location, savedUri, StringComparison.OrdinalIgnoreCase); + } + + private LiveTvOptions GetConfiguration() + { + return _config.GetConfiguration("livetv"); + } + + public void Dispose() + { + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs new file mode 100644 index 000000000..187569ab4 --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -0,0 +1,235 @@ +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.LiveTv; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.MediaInfo; +using MediaBrowser.Model.Serialization; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun +{ + public class HdHomerunHost : ITunerHost + { + private readonly IHttpClient _httpClient; + private readonly ILogger _logger; + private readonly IJsonSerializer _jsonSerializer; + private readonly IConfigurationManager _config; + + public HdHomerunHost(IHttpClient httpClient, ILogger logger, IJsonSerializer jsonSerializer, IConfigurationManager config) + { + _httpClient = httpClient; + _logger = logger; + _jsonSerializer = jsonSerializer; + _config = config; + } + + public string Name + { + get { return "HD Homerun"; } + } + + public string Type + { + get { return DeviceType; } + } + + public static string DeviceType + { + get { return "hdhomerun"; } + } + + public async Task> GetChannels(TunerHostInfo info, CancellationToken cancellationToken) + { + var options = new HttpRequestOptions + { + Url = string.Format("{0}/lineup.json", GetApiUrl(info)), + CancellationToken = cancellationToken + }; + using (var stream = await _httpClient.Get(options)) + { + var root = _jsonSerializer.DeserializeFromStream>(stream); + + if (root != null) + { + return root.Select(i => new ChannelInfo + { + Name = i.GuideName, + Number = i.GuideNumber.ToString(CultureInfo.InvariantCulture), + Id = i.GuideNumber.ToString(CultureInfo.InvariantCulture), + IsFavorite = i.Favorite + + }); + } + return new List(); + } + } + + public async Task> GetTunerInfos(TunerHostInfo info, CancellationToken cancellationToken) + { + string model = null; + + using (var stream = await _httpClient.Get(new HttpRequestOptions() + { + Url = string.Format("{0}/", GetApiUrl(info)), + CancellationToken = cancellationToken + })) + { + using (var sr = new StreamReader(stream, System.Text.Encoding.UTF8)) + { + while (!sr.EndOfStream) + { + string line = StripXML(sr.ReadLine()); + if (line.StartsWith("Model:")) { model = line.Replace("Model: ", ""); } + //if (line.StartsWith("Device ID:")) { deviceID = line.Replace("Device ID: ", ""); } + //if (line.StartsWith("Firmware:")) { firmware = line.Replace("Firmware: ", ""); } + } + } + } + + using (var stream = await _httpClient.Get(new HttpRequestOptions() + { + Url = string.Format("{0}/tuners.html", GetApiUrl(info)), + CancellationToken = cancellationToken + })) + { + var tuners = new List(); + using (var sr = new StreamReader(stream, System.Text.Encoding.UTF8)) + { + while (!sr.EndOfStream) + { + string line = StripXML(sr.ReadLine()); + if (line.Contains("Channel")) + { + LiveTvTunerStatus status; + var index = line.IndexOf("Channel", StringComparison.OrdinalIgnoreCase); + var name = line.Substring(0, index - 1); + var currentChannel = line.Substring(index + 7); + if (currentChannel != "none") { status = LiveTvTunerStatus.LiveTv; } else { status = LiveTvTunerStatus.Available; } + tuners.Add(new LiveTvTunerInfo() + { + Name = name, + SourceType = string.IsNullOrWhiteSpace(model) ? Name : model, + ProgramName = currentChannel, + Status = status + }); + } + } + } + return tuners; + } + } + + public string GetApiUrl(TunerHostInfo info) + { + var url = info.Url; + + if (!url.StartsWith("http", StringComparison.OrdinalIgnoreCase)) + { + url = "http://" + url; + } + + return url.TrimEnd('/'); + } + + private static string StripXML(string source) + { + char[] buffer = new char[source.Length]; + int bufferIndex = 0; + bool inside = false; + + for (int i = 0; i < source.Length; i++) + { + char let = source[i]; + if (let == '<') + { + inside = true; + continue; + } + if (let == '>') + { + inside = false; + continue; + } + if (!inside) + { + buffer[bufferIndex] = let; + bufferIndex++; + } + } + return new string(buffer, 0, bufferIndex); + } + + private class Channels + { + public string GuideNumber { get; set; } + public string GuideName { get; set; } + public string URL { get; set; } + public bool Favorite { get; set; } + public bool DRM { get; set; } + } + + private LiveTvOptions GetConfiguration() + { + return _config.GetConfiguration("livetv"); + } + + public List GetTunerHosts() + { + return GetConfiguration().TunerHosts.Where(i => string.Equals(i.Type, Type, StringComparison.OrdinalIgnoreCase)).ToList(); + } + + public async Task GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken) + { + var channels = await GetChannels(info, cancellationToken).ConfigureAwait(false); + var tuners = await GetTunerInfos(info, cancellationToken).ConfigureAwait(false); + + var channel = channels.FirstOrDefault(c => string.Equals(c.Id, channelId, StringComparison.OrdinalIgnoreCase)); + if (channel != null) + { + if (tuners.FindIndex(t => t.Status == LiveTvTunerStatus.Available) >= 0) + { + return new MediaSourceInfo + { + Path = GetApiUrl(info) + "/auto/v" + channelId, + Protocol = MediaProtocol.Http, + MediaStreams = new List + { + new MediaStream + { + Type = MediaStreamType.Video, + // Set the index to -1 because we don't know the exact index of the video stream within the container + Index = -1, + IsInterlaced = true + }, + new MediaStream + { + Type = MediaStreamType.Audio, + // Set the index to -1 because we don't know the exact index of the audio stream within the container + Index = -1 + + } + } + }; + } + + throw new ApplicationException("No tuners avaliable."); + } + throw new ApplicationException("Channel not found."); + } + + + public async Task Validate(TunerHostInfo info) + { + await GetChannels(info, CancellationToken.None).ConfigureAwait(false); + } + } +} diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index dc149318b..c77c112a6 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -226,7 +226,8 @@ - + + diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index adef0a45f..5fd1dca43 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -514,6 +514,8 @@ namespace MediaBrowser.Server.Startup.Common SubtitleManager = new SubtitleManager(LogManager.GetLogger("SubtitleManager"), FileSystemManager, LibraryMonitor, LibraryManager, MediaSourceManager); RegisterSingleInstance(SubtitleManager); + RegisterSingleInstance(new DeviceDiscovery(LogManager.GetLogger("IDeviceDiscovery"), ServerConfigurationManager, this)); + ChapterManager = new ChapterManager(LibraryManager, LogManager.GetLogger("ChapterManager"), ServerConfigurationManager, ItemRepository); RegisterSingleInstance(ChapterManager); -- cgit v1.2.3 From 77afd4ba544abf2c92cd6d098e997dfc2d9b39c9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 24 Jul 2015 11:20:11 -0400 Subject: update live tv --- .../HttpClientManager/HttpClientManager.cs | 2 +- MediaBrowser.Model/Session/GeneralCommandType.cs | 4 +++- MediaBrowser.Model/Session/PlaybackProgressInfo.cs | 12 ++++++++++++ .../Library/UserViewManager.cs | 2 +- .../LiveTv/LiveTvManager.cs | 20 ++++++++++---------- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 3 ++- .../Playlists/PlaylistManager.cs | 15 +++++++++------ .../ApplicationHost.cs | 2 +- 8 files changed, 39 insertions(+), 21 deletions(-) (limited to 'MediaBrowser.Server.Startup.Common') diff --git a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs index 18441161f..89f405e8a 100644 --- a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs +++ b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs @@ -127,7 +127,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager private WebRequest GetRequest(HttpRequestOptions options, string method, bool enableHttpCompression) { - var request = WebRequest.Create(options.Url); + var request = CreateWebRequest(options.Url); var httpWebRequest = request as HttpWebRequest; if (httpWebRequest != null) diff --git a/MediaBrowser.Model/Session/GeneralCommandType.cs b/MediaBrowser.Model/Session/GeneralCommandType.cs index f8773a246..dcb3b20ca 100644 --- a/MediaBrowser.Model/Session/GeneralCommandType.cs +++ b/MediaBrowser.Model/Session/GeneralCommandType.cs @@ -33,6 +33,8 @@ ToggleFullscreen = 25, DisplayContent = 26, GoToSearch = 27, - DisplayMessage = 28 + DisplayMessage = 28, + SetRepeatAll = 29, + SetRepeatOne = 30 } } \ No newline at end of file diff --git a/MediaBrowser.Model/Session/PlaybackProgressInfo.cs b/MediaBrowser.Model/Session/PlaybackProgressInfo.cs index a7ca09c15..345931a62 100644 --- a/MediaBrowser.Model/Session/PlaybackProgressInfo.cs +++ b/MediaBrowser.Model/Session/PlaybackProgressInfo.cs @@ -88,5 +88,17 @@ namespace MediaBrowser.Model.Session /// /// The play session identifier. public string PlaySessionId { get; set; } + /// + /// Gets or sets the repeat mode. + /// + /// The repeat mode. + public RepeatMode RepeatMode { get; set; } + } + + public enum RepeatMode + { + RepeatNone = 0, + RepeatAll = 1, + RepeatOne = 2 } } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs index 69600f0fe..14c5c9a03 100644 --- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs @@ -99,7 +99,7 @@ namespace MediaBrowser.Server.Implementations.Library list.Add(await GetUserView(parents, list, CollectionType.TvShows, string.Empty, user, cancellationToken).ConfigureAwait(false)); } - parents = foldersWithViewTypes.Where(i => string.Equals(i.CollectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase) || string.Equals(i.CollectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase) || string.IsNullOrWhiteSpace(i.CollectionType)) + parents = foldersWithViewTypes.Where(i => string.Equals(i.CollectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase) || string.IsNullOrWhiteSpace(i.CollectionType)) .ToList(); if (parents.Count > 0) diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 6ef565129..3ca60ec51 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -544,16 +544,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv var replaceImages = new List(); - if (!string.Equals(item.ProviderImageUrl, channelInfo.ImageUrl, StringComparison.OrdinalIgnoreCase)) - { - isNew = true; - replaceImages.Add(ImageType.Primary); - } - if (!string.Equals(item.ProviderImagePath, channelInfo.ImagePath, StringComparison.OrdinalIgnoreCase)) - { - isNew = true; - replaceImages.Add(ImageType.Primary); - } + //if (!string.Equals(item.ProviderImageUrl, channelInfo.ImageUrl, StringComparison.OrdinalIgnoreCase)) + //{ + // isNew = true; + // replaceImages.Add(ImageType.Primary); + //} + //if (!string.Equals(item.ProviderImagePath, channelInfo.ImagePath, StringComparison.OrdinalIgnoreCase)) + //{ + // isNew = true; + // replaceImages.Add(ImageType.Primary); + //} item.ProviderImageUrl = channelInfo.ImageUrl; item.HasProviderImage = channelInfo.HasImage; diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 50303a89a..eb8f8f80e 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -325,7 +325,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun if (model.IndexOf("hdtc", StringComparison.OrdinalIgnoreCase) != -1) { - list.Add(GetMediaSource(info, channelId, "heavy")); + list.Insert(0, GetMediaSource(info, channelId, "heavy")); + list.Add(GetMediaSource(info, channelId, "internet480")); list.Add(GetMediaSource(info, channelId, "internet360")); list.Add(GetMediaSource(info, channelId, "internet240")); diff --git a/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs b/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs index 311cb9b51..857cf743f 100644 --- a/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs +++ b/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs @@ -23,14 +23,16 @@ namespace MediaBrowser.Server.Implementations.Playlists private readonly ILibraryMonitor _iLibraryMonitor; private readonly ILogger _logger; private readonly IUserManager _userManager; + private readonly IProviderManager _providerManager; - public PlaylistManager(ILibraryManager libraryManager, IFileSystem fileSystem, ILibraryMonitor iLibraryMonitor, ILogger logger, IUserManager userManager) + public PlaylistManager(ILibraryManager libraryManager, IFileSystem fileSystem, ILibraryMonitor iLibraryMonitor, ILogger logger, IUserManager userManager, IProviderManager providerManager) { _libraryManager = libraryManager; _fileSystem = fileSystem; _iLibraryMonitor = iLibraryMonitor; _logger = logger; _userManager = userManager; + _providerManager = providerManager; } public IEnumerable GetPlaylists(string userId) @@ -193,11 +195,11 @@ namespace MediaBrowser.Server.Implementations.Playlists playlist.LinkedChildren.AddRange(list); await playlist.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); - await playlist.RefreshMetadata(new MetadataRefreshOptions + + _providerManager.QueueRefresh(playlist.Id, new MetadataRefreshOptions { ForceSave = true - - }, CancellationToken.None).ConfigureAwait(false); + }); } public async Task RemoveFromPlaylist(string playlistId, IEnumerable entryIds) @@ -220,10 +222,11 @@ namespace MediaBrowser.Server.Implementations.Playlists .ToList(); await playlist.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); - await playlist.RefreshMetadata(new MetadataRefreshOptions + + _providerManager.QueueRefresh(playlist.Id, new MetadataRefreshOptions { ForceSave = true - }, CancellationToken.None).ConfigureAwait(false); + }); } public Folder GetPlaylistsFolder(string userId) diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 5fd1dca43..5e5babbb4 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -493,7 +493,7 @@ namespace MediaBrowser.Server.Startup.Common CollectionManager = new CollectionManager(LibraryManager, FileSystemManager, LibraryMonitor, LogManager.GetLogger("CollectionManager")); RegisterSingleInstance(CollectionManager); - PlaylistManager = new PlaylistManager(LibraryManager, FileSystemManager, LibraryMonitor, LogManager.GetLogger("PlaylistManager"), UserManager); + PlaylistManager = new PlaylistManager(LibraryManager, FileSystemManager, LibraryMonitor, LogManager.GetLogger("PlaylistManager"), UserManager, ProviderManager); RegisterSingleInstance(PlaylistManager); LiveTvManager = new LiveTvManager(this, ServerConfigurationManager, Logger, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager, LocalizationManager, JsonSerializer, ProviderManager); -- cgit v1.2.3 From 7f9a2f1af6c43ccf49b417884583c999e53298cd Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 27 Jul 2015 12:21:18 -0400 Subject: add path help messages --- MediaBrowser.Controller/LiveTv/ITunerHost.cs | 5 ----- MediaBrowser.Model/LiveTv/LiveTvOptions.cs | 6 ++++++ MediaBrowser.Model/System/SystemInfo.cs | 5 +++++ MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs | 1 + MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs | 6 +++--- .../LiveTv/RefreshChannelsScheduledTask.cs | 3 ++- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 5 ----- .../LiveTv/TunerHosts/M3UTunerHost.cs | 5 ----- .../Localization/JavaScript/javascript.json | 7 ++++--- MediaBrowser.Server.Startup.Common/ApplicationHost.cs | 3 ++- 10 files changed, 23 insertions(+), 23 deletions(-) (limited to 'MediaBrowser.Server.Startup.Common') diff --git a/MediaBrowser.Controller/LiveTv/ITunerHost.cs b/MediaBrowser.Controller/LiveTv/ITunerHost.cs index c9a96a9ca..a6c8021d9 100644 --- a/MediaBrowser.Controller/LiveTv/ITunerHost.cs +++ b/MediaBrowser.Controller/LiveTv/ITunerHost.cs @@ -19,11 +19,6 @@ namespace MediaBrowser.Controller.LiveTv /// The type. string Type { get; } /// - /// Gets the tuner hosts. - /// - /// List<TunerHostInfo>. - List GetTunerHosts(); - /// /// Gets the channels. /// /// The information. diff --git a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs index 004ee2ce6..c5e8f4636 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs @@ -25,6 +25,12 @@ namespace MediaBrowser.Model.LiveTv public string Url { get; set; } public string Type { get; set; } public bool ImportFavoritesOnly { get; set; } + public bool IsEnabled { get; set; } + + public TunerHostInfo() + { + IsEnabled = true; + } } public class ListingsProviderInfo diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index 8c1fc759f..094c4fda6 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -13,6 +13,11 @@ namespace MediaBrowser.Model.System /// /// The operating sytem. public string OperatingSystem { get; set; } + /// + /// Gets or sets the display name of the operating system. + /// + /// The display name of the operating system. + public string OperatingSystemDisplayName { get; set; } /// /// Gets or sets a value indicating whether this instance is running as service. diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index c32b8da10..d5bfc5449 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -134,6 +134,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private List> GetTunerHosts() { return GetConfiguration().TunerHosts + .Where(i => i.IsEnabled) .Select(i => { var provider = _liveTvManager.TunerHosts.FirstOrDefault(l => string.Equals(l.Type, i.Type, StringComparison.OrdinalIgnoreCase)); diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index b7091ee09..d8e60be5a 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -2127,7 +2127,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv private bool IsLiveTvEnabled(User user) { - return user.Policy.EnableLiveTvAccess && Services.Count > 0; + return user.Policy.EnableLiveTvAccess && (Services.Count > 1 || GetConfiguration().TunerHosts.Count(i => i.IsEnabled) > 0); } public IEnumerable GetEnabledUsers() @@ -2175,7 +2175,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv public async Task SaveTunerHost(TunerHostInfo info) { info = (TunerHostInfo)_jsonSerializer.DeserializeFromString(_jsonSerializer.SerializeToString(info), typeof(TunerHostInfo)); - + var provider = _tunerHosts.FirstOrDefault(i => string.Equals(info.Type, i.Type, StringComparison.OrdinalIgnoreCase)); if (provider == null) @@ -2236,7 +2236,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv _config.SaveConfiguration("livetv", config); _taskManager.CancelIfRunningAndQueue(); - + return info; } diff --git a/MediaBrowser.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs b/MediaBrowser.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs index 7cb616d3f..fa1a8b3e7 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs @@ -5,6 +5,7 @@ using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Tasks; using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.LiveTv @@ -61,7 +62,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv public bool IsHidden { - get { return _liveTvManager.Services.Count == 1 && GetConfiguration().TunerHosts.Count == 0; } + get { return _liveTvManager.Services.Count == 1 && GetConfiguration().TunerHosts.Count(i => i.IsEnabled) == 0; } } public bool IsEnabled diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 55d3e6a33..c01eb63ab 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -207,11 +207,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun return _config.GetConfiguration("livetv"); } - public List GetTunerHosts() - { - return GetConfiguration().TunerHosts.Where(i => string.Equals(i.Type, Type, StringComparison.OrdinalIgnoreCase)).ToList(); - } - private MediaSourceInfo GetMediaSource(TunerHostInfo info, string channelId, string profile) { int? width = null; diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs index 91f25bbee..bb31390f2 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs @@ -124,11 +124,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts return _config.GetConfiguration("livetv"); } - public List GetTunerHosts() - { - return GetConfiguration().TunerHosts.Where(i => string.Equals(i.Type, Type, StringComparison.OrdinalIgnoreCase)).ToList(); - } - public async Task GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken) { var channels = await GetChannels(info, cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json index acd54cb0f..2e61d181b 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json @@ -288,6 +288,7 @@ "HeaderSelectPath": "Select Path", "ButtonNetwork": "Network", "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.", + "MessageDirectoryPickerBSDInstruction": "For BSD, you may need to configure storage within your FreeNAS Jail in order to allow Emby to access it.", "HeaderMenu": "Menu", "ButtonOpen": "Open", "ButtonOpenInNewTab": "Open in new tab", @@ -828,7 +829,7 @@ "ErrorPleaseSelectLineup": "Please select a lineup and try again. If no lineups are available, then please check that your username, password, and postal code is correct.", "HeaderTryCinemaMode": "Try Cinema Mode", "ButtonBecomeSupporter": "Become an Emby Supporter", - "ButtonClosePlayVideo": "Close and play my video", - "MessageDidYouKnowCinemaMode": "Did you know that by becoming an Emby Supporter, you can enhance your experience with features like Cinema Mode?", - "MessageDidYouKnowCinemaMode2": "Cinema Mode gives you the true cinema experience with trailers and custom intros before the main feature." + "ButtonClosePlayVideo": "Close and play my media", + "MessageDidYouKnowCinemaMode": "Did you know that by becoming an Emby Supporter, you can enhance your experience with features like Cinema Mode?", + "MessageDidYouKnowCinemaMode2": "Cinema Mode gives you the true cinema experience with trailers and custom intros before the main feature." } diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 5e5babbb4..b554e0d1c 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -1055,7 +1055,8 @@ namespace MediaBrowser.Server.Startup.Common HttpServerPortNumber = HttpPort, SupportsHttps = SupportsHttps, HttpsPortNumber = HttpsPort, - OperatingSystem = OperatingSystemDisplayName, + OperatingSystem = NativeApp.Environment.OperatingSystem.ToString(), + OperatingSystemDisplayName = OperatingSystemDisplayName, CanSelfRestart = CanSelfRestart, CanSelfUpdate = CanSelfUpdate, WanAddress = ConnectManager.WanApiAddress, -- cgit v1.2.3 From 1936d6db43e10cc6f45fa72fde4b1628e06b8abd Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 10 Aug 2015 13:37:50 -0400 Subject: update search hints --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 5 + MediaBrowser.Api/SearchService.cs | 9 ++ .../Configuration/BaseApplicationConfiguration.cs | 2 - MediaBrowser.Model/Search/SearchHint.cs | 12 ++ .../Library/Resolvers/TV/SeriesResolver.cs | 10 +- .../LiveTv/Listings/Emby/EmbyListings.cs | 59 +++++++++ .../Listings/Emby/EmbyListingsNorthAmerica.cs | 144 +++++++++++++++++++++ .../LiveTv/Listings/Emby/IEmbyListingProvider.cs | 18 +++ .../MediaBrowser.Server.Implementations.csproj | 3 + .../ApplicationHost.cs | 21 ++- .../MediaBrowser.WebDashboard.csproj | 6 + 11 files changed, 276 insertions(+), 13 deletions(-) create mode 100644 MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/EmbyListings.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/EmbyListingsNorthAmerica.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/IEmbyListingProvider.cs (limited to 'MediaBrowser.Server.Startup.Common') diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index f108b344f..8f5301642 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1748,6 +1748,11 @@ namespace MediaBrowser.Api.Playback return false; } + if (videoStream.IsAnamorphic ?? false) + { + return false; + } + // Can't stream copy if we're burning in subtitles if (request.SubtitleStreamIndex.HasValue) { diff --git a/MediaBrowser.Api/SearchService.cs b/MediaBrowser.Api/SearchService.cs index 9d1aef300..302b8d834 100644 --- a/MediaBrowser.Api/SearchService.cs +++ b/MediaBrowser.Api/SearchService.cs @@ -4,6 +4,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Search; @@ -171,6 +172,8 @@ namespace MediaBrowser.Api ProductionYear = item.ProductionYear }; + result.ChannelId = item.ChannelId; + var primaryImageTag = _imageProcessor.GetImageCacheTag(item, ImageType.Primary); if (primaryImageTag != null) @@ -218,6 +221,12 @@ namespace MediaBrowser.Api result.Artists = song.Artists.ToArray(); } + if (!string.IsNullOrWhiteSpace(item.ChannelId)) + { + var channel = _libraryManager.GetItemById(item.ChannelId); + result.ChannelName = channel == null ? null : channel.Name; + } + return result; } diff --git a/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs b/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs index 1a05f38fa..2b53c6688 100644 --- a/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs +++ b/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs @@ -63,8 +63,6 @@ namespace MediaBrowser.Model.Configuration { EnableAutoUpdate = true; LogFileRetentionDays = 3; - - EnableDebugLevelLogging = true; } } } diff --git a/MediaBrowser.Model/Search/SearchHint.cs b/MediaBrowser.Model/Search/SearchHint.cs index 4eced7706..d51c0325d 100644 --- a/MediaBrowser.Model/Search/SearchHint.cs +++ b/MediaBrowser.Model/Search/SearchHint.cs @@ -132,5 +132,17 @@ namespace MediaBrowser.Model.Search /// /// The episode count. public int? EpisodeCount { get; set; } + + /// + /// Gets or sets the channel identifier. + /// + /// The channel identifier. + public string ChannelId { get; set; } + + /// + /// Gets or sets the name of the channel. + /// + /// The name of the channel. + public string ChannelName { get; set; } } } diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs index f12022dc7..c5565eb53 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs @@ -110,11 +110,11 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV { var attributes = child.Attributes; - if ((attributes & FileAttributes.Hidden) == FileAttributes.Hidden) - { - //logger.Debug("Igoring series file or folder marked hidden: {0}", child.FullName); - continue; - } + //if ((attributes & FileAttributes.Hidden) == FileAttributes.Hidden) + //{ + // //logger.Debug("Igoring series file or folder marked hidden: {0}", child.FullName); + // continue; + //} // Can't enforce this because files saved by Bitcasa are always marked System //if ((attributes & FileAttributes.System) == FileAttributes.System) diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/EmbyListings.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/EmbyListings.cs new file mode 100644 index 000000000..5edebb393 --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/EmbyListings.cs @@ -0,0 +1,59 @@ +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.LiveTv; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Model.Serialization; + +namespace MediaBrowser.Server.Implementations.LiveTv.Listings.Emby +{ + public class EmbyGuide : IListingsProvider + { + private readonly IHttpClient _httpClient; + private readonly IJsonSerializer _jsonSerializer; + + public EmbyGuide(IHttpClient httpClient, IJsonSerializer jsonSerializer) + { + _httpClient = httpClient; + _jsonSerializer = jsonSerializer; + } + + public string Name + { + get { return "Emby Guide"; } + } + + public string Type + { + get { return "emby"; } + } + + public Task> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken) + { + return GetListingsProvider(info.Country).GetProgramsAsync(info, channelNumber, startDateUtc, endDateUtc, cancellationToken); + } + + public Task AddMetadata(ListingsProviderInfo info, List channels, CancellationToken cancellationToken) + { + return GetListingsProvider(info.Country).AddMetadata(info, channels, cancellationToken); + } + + public Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings) + { + return GetListingsProvider(info.Country).Validate(info, validateLogin, validateListings); + } + + public Task> GetLineups(ListingsProviderInfo info, string country, string location) + { + return GetListingsProvider(country).GetLineups(info, country, location); + } + + private IEmbyListingProvider GetListingsProvider(string country) + { + return new EmbyListingsNorthAmerica(_httpClient, _jsonSerializer); + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/EmbyListingsNorthAmerica.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/EmbyListingsNorthAmerica.cs new file mode 100644 index 000000000..99bd5325e --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/EmbyListingsNorthAmerica.cs @@ -0,0 +1,144 @@ +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.LiveTv; +using MediaBrowser.Model.Serialization; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.LiveTv.Listings.Emby +{ + public class EmbyListingsNorthAmerica : IEmbyListingProvider + { + private readonly IHttpClient _httpClient; + private readonly IJsonSerializer _jsonSerializer; + + public EmbyListingsNorthAmerica(IHttpClient httpClient, IJsonSerializer jsonSerializer) + { + _httpClient = httpClient; + _jsonSerializer = jsonSerializer; + } + + public async Task> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken) + { + return new List(); + } + + public async Task AddMetadata(ListingsProviderInfo info, List channels, CancellationToken cancellationToken) + { + var response = await GetResponse("https://data.emby.media/service/lineups?id=" + info.ListingsId).ConfigureAwait(false); + + foreach (var channel in channels) + { + + } + } + + public Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings) + { + return Task.FromResult(true); + } + + public async Task> GetLineups(ListingsProviderInfo info, string country, string location) + { + var response = await GetResponse("https://data.emby.media/service/lineups?id=" + location).ConfigureAwait(false); + + return response.Select(i => new NameIdPair + { + + Name = GetName(i), + Id = i.lineupID + + }).ToList(); + } + + private string GetName(LineupInfo info) + { + var name = info.lineupName; + + if (string.Equals(info.lineupType, "cab", StringComparison.OrdinalIgnoreCase)) + { + name += " - Cable"; + } + else if (string.Equals(info.lineupType, "sat", StringComparison.OrdinalIgnoreCase)) + { + name += " - SAT"; + } + else if (string.Equals(info.lineupType, "ota", StringComparison.OrdinalIgnoreCase)) + { + name += " - OTA"; + } + + return name; + } + + private async Task GetResponse(string url) + where T : class + { + using (var stream = await _httpClient.Get(new HttpRequestOptions + { + Url = url + + }).ConfigureAwait(false)) + { + using (var reader = new StreamReader(stream)) + { + var path = await reader.ReadToEndAsync().ConfigureAwait(false); + + // location = zip code + using (var secondStream = await _httpClient.Get(new HttpRequestOptions + { + Url = "https://data.emby.media" + path + + }).ConfigureAwait(false)) + { + return _jsonSerializer.DeserializeFromStream(secondStream); + } + } + } + } + + private class LineupInfo + { + public string lineupID { get; set; } + public string lineupName { get; set; } + public string lineupType { get; set; } + public string providerID { get; set; } + public string providerName { get; set; } + public string serviceArea { get; set; } + public string country { get; set; } + } + + private class Station + { + public string number { get; set; } + public int channelNumber { get; set; } + public int subChannelNumber { get; set; } + public int stationID { get; set; } + public string name { get; set; } + public string callsign { get; set; } + public string network { get; set; } + public string stationType { get; set; } + public int NTSC_TSID { get; set; } + public int DTV_TSID { get; set; } + public string webLink { get; set; } + public string logoFilename { get; set; } + } + + private class LineupDetailResponse + { + public string lineupID { get; set; } + public string lineupName { get; set; } + public string lineupType { get; set; } + public string providerID { get; set; } + public string providerName { get; set; } + public string serviceArea { get; set; } + public string country { get; set; } + public List stations { get; set; } + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/IEmbyListingProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/IEmbyListingProvider.cs new file mode 100644 index 000000000..83477acfc --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/Listings/Emby/IEmbyListingProvider.cs @@ -0,0 +1,18 @@ +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.LiveTv; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.LiveTv.Listings.Emby +{ + public interface IEmbyListingProvider + { + Task> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, 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.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 7eddf5ed1..2571f9b2c 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -222,6 +222,9 @@ + + + diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index b554e0d1c..60ff36c6d 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -529,7 +529,7 @@ namespace MediaBrowser.Server.Startup.Common var sharingRepo = new SharingRepository(LogManager, ApplicationPaths); await sharingRepo.Initialize().ConfigureAwait(false); RegisterSingleInstance(new SharingManager(sharingRepo, ServerConfigurationManager, LibraryManager, this)); - + RegisterSingleInstance(new SsdpHandler(LogManager.GetLogger("SsdpHandler"), ServerConfigurationManager, this)); var activityLogRepo = await GetActivityLogRepository().ConfigureAwait(false); @@ -1088,15 +1088,24 @@ namespace MediaBrowser.Server.Startup.Common { get { - // Return the first matched address, if found, or the first known local address - var address = LocalIpAddress; + try + { + // Return the first matched address, if found, or the first known local address + var address = LocalIpAddress; - if (!string.IsNullOrWhiteSpace(address)) + if (!string.IsNullOrWhiteSpace(address)) + { + address = GetLocalApiUrl(address); + } + + return address; + } + catch (Exception ex) { - address = GetLocalApiUrl(address); + Logger.ErrorException("Error getting local Ip address information", ex); } - return address; + return null; } } diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index a1e232257..e8a2e8673 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -183,6 +183,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -213,6 +216,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest -- cgit v1.2.3 From 2f2ccfe8f3217c64a33c1e81c4516358f95c363a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 18 Aug 2015 11:25:57 -0400 Subject: update recordings --- MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs | 3 +++ MediaBrowser.Controller/LiveTv/RecordingInfo.cs | 6 ++++++ .../LiveTv/EmbyTV/EmbyTV.cs | 4 +++- .../LiveTv/LiveTvManager.cs | 14 +++++++++++--- MediaBrowser.Server.Startup.Common/ApplicationHost.cs | 2 +- 5 files changed, 24 insertions(+), 5 deletions(-) (limited to 'MediaBrowser.Server.Startup.Common') diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs b/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs index 1dd267c93..9fc60beb9 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs @@ -42,5 +42,8 @@ namespace MediaBrowser.Controller.LiveTv RecordingStatus Status { get; set; } DateTime? EndDate { get; set; } ChannelType ChannelType { get; set; } + DateTime DateLastSaved { get; set; } + DateTime DateCreated { get; set; } + DateTime DateModified { get; set; } } } diff --git a/MediaBrowser.Controller/LiveTv/RecordingInfo.cs b/MediaBrowser.Controller/LiveTv/RecordingInfo.cs index 42064cf50..3006b9bbe 100644 --- a/MediaBrowser.Controller/LiveTv/RecordingInfo.cs +++ b/MediaBrowser.Controller/LiveTv/RecordingInfo.cs @@ -191,6 +191,12 @@ namespace MediaBrowser.Controller.LiveTv /// The show identifier. public string ShowId { get; set; } + /// + /// Gets or sets the date last updated. + /// + /// The date last updated. + public DateTime DateLastUpdated { get; set; } + public RecordingInfo() { Genres = new List(); diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index a28e3faec..51476e296 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -576,6 +576,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV recording.Path = recordPath; recording.Status = RecordingStatus.InProgress; + recording.DateLastUpdated = DateTime.UtcNow; _recordingProvider.Update(recording); try @@ -598,7 +599,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV } catch (OperationCanceledException) { - _logger.Info("Recording cancelled"); + _logger.Info("Recording stopped"); recording.Status = RecordingStatus.Completed; } catch (Exception ex) @@ -607,6 +608,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV recording.Status = RecordingStatus.Error; } + recording.DateLastUpdated = DateTime.UtcNow; _recordingProvider.Update(recording); _timerProvider.Delete(timer); _logger.Info("Recording was a success"); diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 1280c52b1..4c44f5c3b 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1,6 +1,8 @@ -using MediaBrowser.Common; +using System.IO; +using MediaBrowser.Common; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.IO; using MediaBrowser.Common.Progress; using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Controller.Configuration; @@ -61,8 +63,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv private readonly List _tunerHosts = new List(); private readonly List _listingProviders = new List(); + private readonly IFileSystem _fileSystem; - public LiveTvManager(IApplicationHost appHost, IServerConfigurationManager config, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager, ILibraryManager libraryManager, ITaskManager taskManager, ILocalizationManager localization, IJsonSerializer jsonSerializer, IProviderManager providerManager) + public LiveTvManager(IApplicationHost appHost, IServerConfigurationManager config, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager, ILibraryManager libraryManager, ITaskManager taskManager, ILocalizationManager localization, IJsonSerializer jsonSerializer, IProviderManager providerManager, IFileSystem fileSystem) { _config = config; _logger = logger; @@ -73,6 +76,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv _localization = localization; _jsonSerializer = jsonSerializer; _providerManager = providerManager; + _fileSystem = fileSystem; _dtoService = dtoService; _userDataManager = userDataManager; @@ -729,6 +733,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv if (!string.IsNullOrEmpty(info.Path)) { item.Path = info.Path; + var fileInfo = new FileInfo(info.Path); + + recording.DateCreated = _fileSystem.GetCreationTimeUtc(fileInfo); + recording.DateModified = _fileSystem.GetLastWriteTimeUtc(fileInfo); } else if (!string.IsNullOrEmpty(info.Url)) { @@ -741,7 +749,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv { await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false); } - else if (pathChanged) + else if (pathChanged || info.DateLastUpdated > recording.DateLastSaved) { await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 60ff36c6d..9ecd0764a 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -496,7 +496,7 @@ namespace MediaBrowser.Server.Startup.Common PlaylistManager = new PlaylistManager(LibraryManager, FileSystemManager, LibraryMonitor, LogManager.GetLogger("PlaylistManager"), UserManager, ProviderManager); RegisterSingleInstance(PlaylistManager); - LiveTvManager = new LiveTvManager(this, ServerConfigurationManager, Logger, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager, LocalizationManager, JsonSerializer, ProviderManager); + LiveTvManager = new LiveTvManager(this, ServerConfigurationManager, Logger, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager, LocalizationManager, JsonSerializer, ProviderManager, FileSystemManager); RegisterSingleInstance(LiveTvManager); UserViewManager = new UserViewManager(LibraryManager, LocalizationManager, UserManager, ChannelManager, LiveTvManager, PlaylistManager, CollectionManager, ServerConfigurationManager); -- cgit v1.2.3 From dcd0feee6e63a956b595060df2c7337d4d841fe2 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 27 Aug 2015 12:37:30 -0400 Subject: update ffmpeg osx --- MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Server.Startup.Common') diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs index 5c5bc10e7..2d4ed94f7 100644 --- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs +++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs @@ -42,7 +42,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg switch (environment.SystemArchitecture) { case Architecture.X86_X64: - info.Version = "20150110"; + info.Version = "20150827"; break; case Architecture.X86: info.Version = "20150110"; @@ -102,7 +102,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg case Architecture.X86_X64: return new[] { - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/osx/ffmpeg-x64-2.5.3.7z" + "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/osx/ffmpeg-x64-2.7.2.7z" }; case Architecture.X86: return new[] -- cgit v1.2.3 From 067479f2d1dcf40127ada01fbd452040a14ae877 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 2 Sep 2015 11:33:20 -0400 Subject: update ffmpeg info --- MediaBrowser.Api/Library/LibraryService.cs | 45 ++++++++++++++++++++++ .../Session/SessionWebSocketListener.cs | 27 ++++++++----- .../FFMpeg/FFMpegDownloadInfo.cs | 4 +- 3 files changed, 64 insertions(+), 12 deletions(-) (limited to 'MediaBrowser.Server.Startup.Common') diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index ed3f2c633..96b307064 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -231,6 +231,17 @@ namespace MediaBrowser.Api.Library public string TvdbId { get; set; } } + [Route("/Library/Movies/Added", "POST", Summary = "Reports that new movies have been added by an external source")] + [Route("/Library/Movies/Updated", "POST", Summary = "Reports that new movies have been added by an external source")] + [Authenticated] + public class PostUpdatedMovies : IReturnVoid + { + [ApiMember(Name = "TmdbId", Description = "Tmdb Id", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")] + public string TmdbId { get; set; } + [ApiMember(Name = "ImdbId", Description = "Imdb Id", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")] + public string ImdbId { get; set; } + } + [Route("/Items/{Id}/Download", "GET", Summary = "Downloads item media")] [Authenticated(Roles = "download")] public class GetDownload @@ -444,6 +455,40 @@ namespace MediaBrowser.Api.Library } } + public void Post(PostUpdatedMovies request) + { + var movies = _libraryManager.GetItems(new InternalItemsQuery + { + IncludeItemTypes = new[] { typeof(Movie).Name } + + }).Items; + + if (!string.IsNullOrWhiteSpace(request.ImdbId)) + { + movies = movies.Where(i => string.Equals(request.ImdbId, i.GetProviderId(MetadataProviders.Imdb), StringComparison.OrdinalIgnoreCase)).ToArray(); + } + else if (!string.IsNullOrWhiteSpace(request.TmdbId)) + { + movies = movies.Where(i => string.Equals(request.TmdbId, i.GetProviderId(MetadataProviders.Tmdb), StringComparison.OrdinalIgnoreCase)).ToArray(); + } + else + { + movies = new BaseItem[] { }; + } + + if (movies.Length > 0) + { + foreach (var item in movies) + { + _libraryMonitor.ReportFileSystemChanged(item.Path); + } + } + else + { + Task.Run(() => _libraryManager.ValidateMediaLibrary(new Progress(), CancellationToken.None)); + } + } + public object Get(GetDownload request) { var item = _libraryManager.GetItemById(request.Id); diff --git a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs index b473444ac..602bc4876 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs @@ -85,16 +85,23 @@ namespace MediaBrowser.Server.Implementations.Session async void _httpServer_WebSocketConnecting(object sender, WebSocketConnectingEventArgs e) { - var token = e.QueryString["api_key"]; - if (!string.IsNullOrWhiteSpace(token)) - { - var session = await GetSession(e.QueryString, e.Endpoint).ConfigureAwait(false); - - if (session == null) - { - //e.AllowConnection = false; - } - } + //var token = e.QueryString["api_key"]; + //if (!string.IsNullOrWhiteSpace(token)) + //{ + // try + // { + // var session = await GetSession(e.QueryString, e.Endpoint).ConfigureAwait(false); + + // if (session == null) + // { + // e.AllowConnection = false; + // } + // } + // catch (Exception ex) + // { + // _logger.ErrorException("Error getting session info", ex); + // } + //} } private Task GetSession(NameValueCollection queryString, string remoteEndpoint) diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs index 2d4ed94f7..2910479ef 100644 --- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs +++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs @@ -84,13 +84,13 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg return new[] { "http://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-20150717-git-8250943-win64-static.7z", - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20150717-git-8250943-win64-static.7z" + "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20150901-git-b54e03c-win64-static.7z" }; case Architecture.X86: return new[] { "http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20150717-git-8250943-win32-static.7z", - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20150717-git-8250943-win32-static.7z" + "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20150901-git-b54e03c-win32-static.7z" }; } break; -- cgit v1.2.3