aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2015-07-23 09:23:22 -0400
committerLuke Pulverenti <luke.pulverenti@gmail.com>2015-07-23 09:23:22 -0400
commit3fda8ec5c264f077b625247ab29ce504be25774c (patch)
tree41c6b3e14cf5161070edfebc50168f10128a3714
parentf9f29de05e318c2de4bee37eea6f19ce955a657c (diff)
update tuner setup
-rw-r--r--MediaBrowser.Api/LiveTv/LiveTvService.cs56
-rw-r--r--MediaBrowser.Controller/LiveTv/IListingsProvider.cs6
-rw-r--r--MediaBrowser.Controller/LiveTv/ILiveTvManager.cs25
-rw-r--r--MediaBrowser.Controller/LiveTv/ITunerHost.cs6
-rw-r--r--MediaBrowser.Model/LiveTv/LiveTvOptions.cs5
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs14
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs73
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs98
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun.cs8
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs8
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json5
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/server.json5
-rw-r--r--MediaBrowser.Server.Startup.Common/ApplicationHost.cs2
-rw-r--r--MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj4
14 files changed, 256 insertions, 59 deletions
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<ListingsProviderInfo>
+ {
+ }
+
+ [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<List<NameIdPair>>
+ {
+ [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<LiveTvOptions>("livetv");
}
+ public async Task<object> Get(GetLineups request)
+ {
+ var info = await _liveTvManager.GetLineups(request.Id, request.Location).ConfigureAwait(false);
+
+ return ToOptimizedSerializedResultUsingCache(info);
+ }
+
public async Task<object> 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<IEnumerable<ProgramInfo>> GetProgramsAsync(ListingsProviderInfo info, ChannelInfo channel, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken);
Task AddMetadata(ListingsProviderInfo info, List<ChannelInfo> channels, CancellationToken cancellationToken);
+ Task Validate(ListingsProviderInfo info);
+ Task<List<NameIdPair>> 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
/// <param name="id">The identifier.</param>
/// <returns>Task.</returns>
Task CancelSeriesTimer(string id);
-
+
/// <summary>
/// Adds the parts.
/// </summary>
/// <param name="services">The services.</param>
- void AddParts(IEnumerable<ILiveTvService> services);
+ /// <param name="tunerHosts">The tuner hosts.</param>
+ /// <param name="listingProviders">The listing providers.</param>
+ void AddParts(IEnumerable<ILiveTvService> services, IEnumerable<ITunerHost> tunerHosts, IEnumerable<IListingsProvider> listingProviders);
/// <summary>
/// Gets the channels.
@@ -337,5 +339,24 @@ namespace MediaBrowser.Controller.LiveTv
/// <param name="dto">The dto.</param>
/// <param name="user">The user.</param>
void AddInfoToProgramDto(BaseItem item, BaseItemDto dto, User user = null);
+ /// <summary>
+ /// Saves the tuner host.
+ /// </summary>
+ /// <param name="info">The information.</param>
+ /// <returns>Task.</returns>
+ Task SaveTunerHost(TunerHostInfo info);
+ /// <summary>
+ /// Saves the listing provider.
+ /// </summary>
+ /// <param name="info">The information.</param>
+ /// <returns>Task.</returns>
+ Task<ListingsProviderInfo> SaveListingProvider(ListingsProviderInfo info);
+ /// <summary>
+ /// Gets the lineups.
+ /// </summary>
+ /// <param name="providerId">The provider identifier.</param>
+ /// <param name="location">The location.</param>
+ /// <returns>Task&lt;List&lt;NameIdPair&gt;&gt;.</returns>
+ Task<List<NameIdPair>> 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
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task&lt;MediaSourceInfo&gt;.</returns>
Task<MediaSourceInfo> GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken);
+ /// <summary>
+ /// Validates the specified information.
+ /// </summary>
+ /// <param name="info">The information.</param>
+ /// <returns>Task.</returns>
+ 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<SeriesTimerInfo> _seriesTimerProvider;
private readonly TimerManager _timerProvider;
- private readonly List<ITunerHost> _tunerHosts = new List<ITunerHost>();
- private readonly List<IListingsProvider> _listingProviders = new List<IListingsProvider>();
+ 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<ITunerHost>());
- _listingProviders.AddRange(appHost.GetExports<IListingsProvider>());
_recordingProvider = new ItemDataProvider<RecordingInfo>(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<LiveTvTunerInfo>();
- 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<ChannelInfo>();
- 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<IListingsProvider, ListingsProviderInfo>(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<List<NameIdPair>> GetHeadends(ListingsProviderInfo info, CancellationToken cancellationToken)
+ public async Task<List<NameIdPair>> 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<string> 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<List<NameIdPair>> 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<Guid, Guid> _refreshedPrograms = new ConcurrentDictionary<Guid, Guid>();
+ private readonly List<ITunerHost> _tunerHosts = new List<ITunerHost>();
+ private readonly List<IListingsProvider> _listingProviders = new List<IListingsProvider>();
+
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.
/// </summary>
/// <param name="services">The services.</param>
- public void AddParts(IEnumerable<ILiveTvService> services)
+ /// <param name="tunerHosts">The tuner hosts.</param>
+ /// <param name="listingProviders">The listing providers.</param>
+ public void AddParts(IEnumerable<ILiveTvService> services, IEnumerable<ITunerHost> tunerHosts, IEnumerable<IListingsProvider> 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<ITunerHost> TunerHosts
+ {
+ get { return _tunerHosts; }
+ }
+
+ public List<IListingsProvider> ListingProviders
+ {
+ get { return _listingProviders; }
+ }
+
void service_DataSourceChanged(object sender, EventArgs e)
{
_taskManager.CancelIfRunningAndQueue<RefreshChannelsScheduledTask>();
@@ -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<ListingsProviderInfo> 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<List<NameIdPair>> 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<IImageEnhancer>());
- LiveTvManager.AddParts(GetExports<ILiveTvService>());
+ LiveTvManager.AddParts(GetExports<ILiveTvService>(), GetExports<ITunerHost>(), GetExports<IListingsProvider>());
SubtitleManager.AddParts(GetExports<ISubtitleProvider>());
ChapterManager.AddParts(GetExports<IChapterProvider>());
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 @@
<Content Include="dashboard-ui\livetvguide.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\livetvguidesettings.html">
+ <Content Include="dashboard-ui\livetvguideprovider-scd.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\livetvrecordings.html">
@@ -207,7 +207,7 @@
<Content Include="dashboard-ui\scripts\homeupcoming.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\scripts\livetvguidesettings.js">
+ <Content Include="dashboard-ui\scripts\livetvguideprovider-scd.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\mypreferenceshome.js">