mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-11-18 03:19:06 -07:00
commit
27fb398001
@ -491,7 +491,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
}
|
||||
}
|
||||
|
||||
//if (!(item is LiveTvProgram) || fields.Contains(ItemFields.PlayAccess))
|
||||
if (!(item is LiveTvProgram) || fields.Contains(ItemFields.PlayAccess))
|
||||
{
|
||||
dto.PlayAccess = item.GetPlayAccess(user);
|
||||
}
|
||||
@ -1639,7 +1639,7 @@ namespace Emby.Server.Implementations.Dto
|
||||
var width = size.Width;
|
||||
var height = size.Height;
|
||||
|
||||
if (width == 0 || height == 0)
|
||||
if (width.Equals(0) || height.Equals(0))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
@ -2543,6 +2543,22 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
public CancellationTokenSource CancellationTokenSource { get; set; }
|
||||
}
|
||||
|
||||
private const int TunerDiscoveryDurationMs = 3000;
|
||||
|
||||
public async Task<List<TunerHostInfo>> DiscoverTuners(CancellationToken cancellationToken)
|
||||
{
|
||||
var list = new List<TunerHostInfo>();
|
||||
|
||||
foreach (var host in _liveTvManager.TunerHosts)
|
||||
{
|
||||
var discoveredDevices = await DiscoverDevices(host, TunerDiscoveryDurationMs, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
list.AddRange(discoveredDevices);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public async Task ScanForTunerDeviceChanges(CancellationToken cancellationToken)
|
||||
{
|
||||
foreach (var host in _liveTvManager.TunerHosts)
|
||||
@ -2553,7 +2569,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||
|
||||
private async Task ScanForTunerDeviceChanges(ITunerHost host, CancellationToken cancellationToken)
|
||||
{
|
||||
var discoveredDevices = await DiscoverDevices(host, 3000, cancellationToken).ConfigureAwait(false);
|
||||
var discoveredDevices = await DiscoverDevices(host, TunerDiscoveryDurationMs, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var configuredDevices = GetConfiguration().TunerHosts
|
||||
.Where(i => string.Equals(i.Type, host.Type, StringComparison.OrdinalIgnoreCase))
|
||||
|
@ -205,6 +205,15 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
||||
}
|
||||
|
||||
programInfo.ShowId = uniqueString.GetMD5().ToString("N");
|
||||
|
||||
// If we don't have valid episode info, assume it's a unique program, otherwise recordings might be skipped
|
||||
if (programInfo.IsSeries && !programInfo.IsRepeat)
|
||||
{
|
||||
if ((programInfo.EpisodeNumber ?? 0) == 0)
|
||||
{
|
||||
programInfo.ShowId = programInfo.ShowId + programInfo.StartDate.Ticks.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Construct an id from the channel and start date
|
||||
|
@ -160,6 +160,11 @@ namespace Emby.Server.Implementations.LiveTv
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
public Task<List<TunerHostInfo>> DiscoverTuners(CancellationToken cancellationToken)
|
||||
{
|
||||
return EmbyTV.EmbyTV.Current.DiscoverTuners(cancellationToken);
|
||||
}
|
||||
|
||||
void service_DataSourceChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (!_isDisposed)
|
||||
|
@ -135,8 +135,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
{
|
||||
// Check to make sure the tuner is available
|
||||
// If there's only one tuner, don't bother with the check and just let the tuner be the one to throw an error
|
||||
if (hostsWithChannel.Count > 1 &&
|
||||
!await IsAvailable(host, channelId, cancellationToken).ConfigureAwait(false))
|
||||
if (hostsWithChannel.Count > 1 && !await IsAvailable(host, channelId, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
Logger.Error("Tuner is not currently available");
|
||||
continue;
|
||||
@ -208,6 +207,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
|
||||
foreach (var host in hostsWithChannel)
|
||||
{
|
||||
if (!channelId.StartsWith(ChannelIdPrefix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var liveStream = await GetChannelStream(host, channelId, streamId, cancellationToken).ConfigureAwait(false);
|
||||
@ -243,7 +247,22 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
|
||||
protected abstract Task<bool> IsAvailableInternal(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken);
|
||||
|
||||
protected abstract bool IsValidChannelId(string channelId);
|
||||
protected virtual string ChannelIdPrefix
|
||||
{
|
||||
get
|
||||
{
|
||||
return Type + "_";
|
||||
}
|
||||
}
|
||||
protected virtual bool IsValidChannelId(string channelId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(channelId))
|
||||
{
|
||||
throw new ArgumentNullException("channelId");
|
||||
}
|
||||
|
||||
return channelId.StartsWith(ChannelIdPrefix, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
protected LiveTvOptions GetConfiguration()
|
||||
{
|
||||
|
@ -56,7 +56,13 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||
get { return "hdhomerun"; }
|
||||
}
|
||||
|
||||
private const string ChannelIdPrefix = "hdhr_";
|
||||
protected override string ChannelIdPrefix
|
||||
{
|
||||
get
|
||||
{
|
||||
return "hdhr_";
|
||||
}
|
||||
}
|
||||
|
||||
private string GetChannelId(TunerHostInfo info, Channels i)
|
||||
{
|
||||
@ -559,26 +565,12 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||
return list;
|
||||
}
|
||||
|
||||
protected override bool IsValidChannelId(string channelId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(channelId))
|
||||
{
|
||||
throw new ArgumentNullException("channelId");
|
||||
}
|
||||
|
||||
return channelId.StartsWith(ChannelIdPrefix, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
protected override async Task<LiveStream> GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken)
|
||||
{
|
||||
var profile = streamId.Split('_')[0];
|
||||
|
||||
Logger.Info("GetChannelStream: channel id: {0}. stream id: {1} profile: {2}", channelId, streamId, profile);
|
||||
|
||||
if (!channelId.StartsWith(ChannelIdPrefix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new ArgumentException("Channel not found");
|
||||
}
|
||||
var hdhrId = GetHdHrIdFromChannelId(channelId);
|
||||
|
||||
var channels = await GetChannels(info, true, CancellationToken.None).ConfigureAwait(false);
|
||||
@ -706,6 +698,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||
var modelInfo = await GetModelInfo(hostInfo, false, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
hostInfo.DeviceId = modelInfo.DeviceID;
|
||||
hostInfo.FriendlyName = modelInfo.FriendlyName;
|
||||
|
||||
return hostInfo;
|
||||
}
|
||||
|
@ -46,8 +46,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
get { return "M3U Tuner"; }
|
||||
}
|
||||
|
||||
private const string ChannelIdPrefix = "m3u_";
|
||||
|
||||
protected override async Task<List<ChannelInfo>> GetChannelsInternal(TunerHostInfo info, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await new M3uParser(Logger, _fileSystem, _httpClient, _appHost).Parse(info.Url, ChannelIdPrefix, info.Id, !info.EnableTvgId, cancellationToken).ConfigureAwait(false);
|
||||
@ -87,16 +85,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool IsValidChannelId(string channelId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(channelId))
|
||||
{
|
||||
throw new ArgumentNullException("channelId");
|
||||
}
|
||||
|
||||
return channelId.StartsWith(ChannelIdPrefix, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
protected override async Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(TunerHostInfo info, string channelId, CancellationToken cancellationToken)
|
||||
{
|
||||
var urlHash = info.Url.GetMD5().ToString("N");
|
||||
|
@ -408,6 +408,7 @@ namespace Emby.Server.Implementations.Localization
|
||||
new LocalizatonOption{ Name="Italian", Value="it"},
|
||||
new LocalizatonOption{ Name="Kazakh", Value="kk"},
|
||||
new LocalizatonOption{ Name="Norwegian Bokmål", Value="nb"},
|
||||
new LocalizatonOption{ Name="Persian", Value="fa"},
|
||||
new LocalizatonOption{ Name="Polish", Value="pl"},
|
||||
new LocalizatonOption{ Name="Portuguese (Brazil)", Value="pt-BR"},
|
||||
new LocalizatonOption{ Name="Portuguese (Portugal)", Value="pt-PT"},
|
||||
|
@ -680,6 +680,13 @@ namespace MediaBrowser.Api.LiveTv
|
||||
|
||||
}
|
||||
|
||||
[Route("/LiveTv/Tuners/Discvover", "GET")]
|
||||
[Authenticated]
|
||||
public class DiscoverTuners : IReturn<List<TunerHostInfo>>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class LiveTvService : BaseApiService
|
||||
{
|
||||
private readonly ILiveTvManager _liveTvManager;
|
||||
@ -730,6 +737,12 @@ namespace MediaBrowser.Api.LiveTv
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<object> Get(DiscoverTuners request)
|
||||
{
|
||||
var result = await _liveTvManager.DiscoverTuners(CancellationToken.None).ConfigureAwait(false);
|
||||
return ToOptimizedResult(result);
|
||||
}
|
||||
|
||||
public async Task<object> Get(GetLiveStreamFile request)
|
||||
{
|
||||
var directStreamProvider = (await _liveTvManager.GetEmbyTvLiveStream(request.Id).ConfigureAwait(false)) as IDirectStreamProvider;
|
||||
|
@ -614,7 +614,8 @@ namespace MediaBrowser.Controller.Entities
|
||||
Timestamp = i.Timestamp,
|
||||
Type = type,
|
||||
PlayableStreamFileNames = i.PlayableStreamFileNames.ToList(),
|
||||
SupportsDirectStream = i.VideoType == VideoType.VideoFile
|
||||
SupportsDirectStream = i.VideoType == VideoType.VideoFile,
|
||||
IsRemote = i.IsShortcut
|
||||
};
|
||||
|
||||
if (info.Protocol == MediaProtocol.File)
|
||||
|
@ -382,6 +382,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||
List<IListingsProvider> ListingProviders { get; }
|
||||
|
||||
List<NameIdPair> GetTunerHostTypes();
|
||||
Task<List<TunerHostInfo>> DiscoverTuners(CancellationToken cancellationToken);
|
||||
|
||||
event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCancelled;
|
||||
event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCancelled;
|
||||
|
@ -185,6 +185,12 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||
return null;
|
||||
}
|
||||
|
||||
// obviously don't do this for strm files
|
||||
if (string.Equals(container, "strm", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,8 @@
|
||||
public bool EnableAutomaticSeriesGrouping { get; set; }
|
||||
public bool EnableEmbeddedTitles { get; set; }
|
||||
|
||||
public int AutomaticRefreshIntervalDays { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the preferred metadata language.
|
||||
/// </summary>
|
||||
|
@ -45,12 +45,21 @@ namespace MediaBrowser.Providers.Manager
|
||||
var updateType = ItemUpdateType.None;
|
||||
var requiresRefresh = false;
|
||||
|
||||
var libraryOptions = LibraryManager.GetLibraryOptions((BaseItem)item);
|
||||
|
||||
if (refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None)
|
||||
{
|
||||
// TODO: If this returns true, should we instead just change metadata refresh mode to Full?
|
||||
requiresRefresh = item.RequiresRefresh();
|
||||
}
|
||||
|
||||
if (!requiresRefresh &&
|
||||
libraryOptions.AutomaticRefreshIntervalDays > 0 &&
|
||||
(DateTime.UtcNow - item.DateLastRefreshed).TotalDays >= libraryOptions.AutomaticRefreshIntervalDays)
|
||||
{
|
||||
requiresRefresh = true;
|
||||
}
|
||||
|
||||
var itemImageProvider = new ItemImageProvider(Logger, ProviderManager, ServerConfigurationManager, FileSystem);
|
||||
var localImagesFailed = false;
|
||||
|
||||
@ -116,8 +125,6 @@ namespace MediaBrowser.Providers.Manager
|
||||
}
|
||||
}
|
||||
|
||||
LibraryOptions libraryOptions = null;
|
||||
|
||||
// Next run remote image providers, but only if local image providers didn't throw an exception
|
||||
if (!localImagesFailed && refreshOptions.ImageRefreshMode != ImageRefreshMode.ValidationOnly)
|
||||
{
|
||||
@ -125,11 +132,6 @@ namespace MediaBrowser.Providers.Manager
|
||||
|
||||
if (providers.Count > 0)
|
||||
{
|
||||
if (libraryOptions == null)
|
||||
{
|
||||
libraryOptions = LibraryManager.GetLibraryOptions((BaseItem)item);
|
||||
}
|
||||
|
||||
var result = await itemImageProvider.RefreshImages(itemOfType, libraryOptions, providers, refreshOptions, config, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
updateType = updateType | result.UpdateType;
|
||||
@ -177,11 +179,6 @@ namespace MediaBrowser.Providers.Manager
|
||||
item.DateLastRefreshed = default(DateTime);
|
||||
}
|
||||
|
||||
if (libraryOptions == null)
|
||||
{
|
||||
libraryOptions = LibraryManager.GetLibraryOptions((BaseItem)item);
|
||||
}
|
||||
|
||||
// Save to database
|
||||
await SaveItem(metadataResult, libraryOptions, updateType, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>MediaBrowser.Common</id>
|
||||
<version>3.0.696</version>
|
||||
<version>3.0.697</version>
|
||||
<title>Emby.Common</title>
|
||||
<authors>Emby Team</authors>
|
||||
<owners>ebr,Luke,scottisafool</owners>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>MediaBrowser.Server.Core</id>
|
||||
<version>3.0.696</version>
|
||||
<version>3.0.697</version>
|
||||
<title>Emby.Server.Core</title>
|
||||
<authors>Emby Team</authors>
|
||||
<owners>ebr,Luke,scottisafool</owners>
|
||||
|
@ -1,3 +1,3 @@
|
||||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyVersion("3.2.7.4")]
|
||||
[assembly: AssemblyVersion("3.2.7.5")]
|
||||
|
Loading…
Reference in New Issue
Block a user