ソースを参照

Merge pull request #2436 from MediaBrowser/dev

Dev
Luke 8 年 前
コミット
7ab5db614f

+ 2 - 2
Emby.Server.Implementations/Emby.Server.Implementations.csproj

@@ -309,8 +309,8 @@
       <Project>{4f26d5d8-a7b0-42b3-ba42-7cb7d245934e}</Project>
       <Name>SocketHttpListener.Portable</Name>
     </ProjectReference>
-    <Reference Include="Emby.XmlTv, Version=1.0.6236.39295, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\Emby.XmlTv.1.0.4\lib\portable-net45+win8\Emby.XmlTv.dll</HintPath>
+    <Reference Include="Emby.XmlTv, Version=1.0.6241.4924, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\Emby.XmlTv.1.0.5\lib\portable-net45+win8\Emby.XmlTv.dll</HintPath>
       <Private>True</Private>
     </Reference>
     <Reference Include="MediaBrowser.Naming, Version=1.0.6201.24431, Culture=neutral, processorArchitecture=MSIL">

+ 6 - 0
Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs

@@ -64,6 +64,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
                         episode.SeasonId = season.Id;
                         episode.SeasonName = season.Name;
                     }
+
+                    // Assume season 1 if there's no season folder and a season number could not be determined
+                    if (season == null && !episode.ParentIndexNumber.HasValue && (episode.IndexNumber.HasValue || episode.PremiereDate.HasValue))
+                    {
+                        episode.ParentIndexNumber = 1;
+                    }
                 }
 
                 return episode;

+ 1 - 1
Emby.Server.Implementations/Library/SearchEngine.cs

@@ -176,7 +176,7 @@ namespace Emby.Server.Implementations.Library
                 return new Tuple<BaseItem, string, int>(item, index.Item1, index.Item2);
             }));
 
-            var returnValue = hints.Where(i => i.Item3 >= 0).OrderBy(i => i.Item3).Select(i => new SearchHintInfo
+            var returnValue = hints.Where(i => i.Item3 >= 0).OrderBy(i => i.Item3).ThenBy(i => i.Item1.SortName).Select(i => new SearchHintInfo
             {
                 Item = i.Item1,
                 MatchedTerm = i.Item2

+ 2 - 1
Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs

@@ -847,6 +847,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
 
                 var channelMappings = GetChannelMappings(provider.Item2);
                 var channelNumber = channel.Number;
+                var tunerChannelId = channel.TunerChannelId;
 
                 if (!string.IsNullOrWhiteSpace(channelNumber))
                 {
@@ -858,7 +859,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
                     }
                 }
 
-                var programs = await provider.Item1.GetProgramsAsync(provider.Item2, channelNumber, channel.Name, startDateUtc, endDateUtc, cancellationToken)
+                var programs = await provider.Item1.GetProgramsAsync(provider.Item2, tunerChannelId, channelNumber, channel.Name, startDateUtc, endDateUtc, cancellationToken)
                         .ConfigureAwait(false);
 
                 var list = programs.ToList();

+ 1 - 1
Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs

@@ -60,7 +60,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
             return dates;
         }
 
-        public async Task<IEnumerable<ProgramInfo>> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, string channelName, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
+        public async Task<IEnumerable<ProgramInfo>> GetProgramsAsync(ListingsProviderInfo info, string channelId, string channelNumber, string channelName, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
         {
             List<ProgramInfo> programsInfo = new List<ProgramInfo>();
 

+ 6 - 2
Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs

@@ -106,7 +106,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
             return cacheFile;
         }
 
-        public async Task<IEnumerable<ProgramInfo>> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, string channelName, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
+        public async Task<IEnumerable<ProgramInfo>> GetProgramsAsync(ListingsProviderInfo info, string channelId, string channelNumber, string channelName, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
         {
             if (!await EmbyTV.EmbyTVRegistration.Instance.EnableXmlTv().ConfigureAwait(false))
             {
@@ -161,8 +161,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings
             }
             else
             {
-                var uniqueString = (p.Title ?? string.Empty) + (episodeTitle ?? string.Empty);
+                var uniqueString = (p.Title ?? string.Empty) + (episodeTitle ?? string.Empty) + (p.IceTvEpisodeNumber ?? string.Empty);
 
+                if (programInfo.SeasonNumber.HasValue)
+                {
+                    uniqueString = "-" + programInfo.SeasonNumber.Value.ToString(CultureInfo.InvariantCulture);
+                }
                 if (programInfo.EpisodeNumber.HasValue)
                 {
                     uniqueString = "-" + programInfo.EpisodeNumber.Value.ToString(CultureInfo.InvariantCulture);

+ 14 - 0
Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs

@@ -76,6 +76,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
             var channels = new List<M3UChannel>();
             string line;
             string extInf = "";
+
             while ((line = reader.ReadLine()) != null)
             {
                 line = line.Trim();
@@ -111,6 +112,18 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
                     extInf = "";
                 }
             }
+
+            var startingNumber = 1;
+            foreach (var channel in channels)
+            {
+                if (!string.IsNullOrWhiteSpace(channel.Number))
+                {
+                    continue;
+                }
+
+                channel.Number = startingNumber.ToString(CultureInfo.InvariantCulture);
+                startingNumber++;
+            }
             return channels;
         }
 
@@ -137,6 +150,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
             if (attributes.TryGetValue("tvg-id", out value))
             {
                 channel.Id = value;
+                channel.TunerChannelId = value;
             }
 
             return channel;

+ 24 - 13
Emby.Server.Implementations/LiveTv/TunerHosts/MulticastStream.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
@@ -11,10 +12,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
 {
     public class MulticastStream
     {
-        private readonly List<QueueStream> _outputStreams = new List<QueueStream>();
+        private readonly ConcurrentDictionary<Guid,QueueStream> _outputStreams = new ConcurrentDictionary<Guid, QueueStream>();
         private const int BufferSize = 81920;
         private CancellationToken _cancellationToken;
         private readonly ILogger _logger;
+        private readonly ConcurrentQueue<byte[]> _sharedBuffer = new ConcurrentQueue<byte[]>();
 
         public MulticastStream(ILogger logger)
         {
@@ -35,17 +37,19 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
                 {
                     byte[] copy = new byte[bytesRead];
                     Buffer.BlockCopy(buffer, 0, copy, 0, bytesRead);
-                   
-                    List<QueueStream> streams = null;
 
-                    lock (_outputStreams)
+                    _sharedBuffer.Enqueue(copy);
+
+                    while (_sharedBuffer.Count > 3000)
                     {
-                        streams = _outputStreams.ToList();
+                        byte[] bytes;
+                        _sharedBuffer.TryDequeue(out bytes);
                     }
 
-                    foreach (var stream in streams)
+                    var allStreams = _outputStreams.ToList();
+                    foreach (var stream in allStreams)
                     {
-                        stream.Queue(copy);
+                        stream.Value.Queue(copy);
                     }
 
                     if (onStarted != null)
@@ -70,11 +74,20 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
                 OnFinished = OnFinished
             };
 
-            lock (_outputStreams)
+            var initial = _sharedBuffer.ToList();
+            var list = new List<byte>();
+
+            foreach (var bytes in initial)
             {
-                _outputStreams.Add(result);
+                list.AddRange(bytes);
             }
 
+            _logger.Info("QueueStream started with {0} initial bytes", list.Count);
+
+            result.Queue(list.ToArray());
+
+            _outputStreams.TryAdd(result.Id, result);
+
             result.Start(_cancellationToken);
 
             return result.TaskCompletion.Task;
@@ -82,10 +95,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
 
         public void RemoveOutputStream(QueueStream stream)
         {
-            lock (_outputStreams)
-            {
-                _outputStreams.Remove(stream);
-            }
+            QueueStream removed;
+            _outputStreams.TryRemove(stream.Id, out removed);
         }
 
         private void OnFinished(QueueStream queueStream)

+ 3 - 13
Emby.Server.Implementations/LiveTv/TunerHosts/QueueStream.cs

@@ -19,7 +19,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
 
         public Action<QueueStream> OnFinished { get; set; }
         private readonly ILogger _logger;
-        private bool _isActive;
+        public Guid Id = Guid.NewGuid();
 
         public QueueStream(Stream outputStream, ILogger logger)
         {
@@ -30,10 +30,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
 
         public void Queue(byte[] bytes)
         {
-            if (_isActive)
-            {
-                _queue.Enqueue(bytes);
-            }
+            _queue.Enqueue(bytes);
         }
 
         public void Start(CancellationToken cancellationToken)
@@ -59,10 +56,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
 
             try
             {
-                while (!cancellationToken.IsCancellationRequested)
+                while (true)
                 {
-                    _isActive = true;
-
                     var bytes = Dequeue();
                     if (bytes != null)
                     {
@@ -73,9 +68,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
                         await Task.Delay(50, cancellationToken).ConfigureAwait(false);
                     }
                 }
-
-                TaskCompletion.TrySetResult(true);
-                _logger.Debug("QueueStream complete");
             }
             catch (OperationCanceledException)
             {
@@ -89,8 +81,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
             }
             finally
             {
-                _isActive = false;
-
                 if (OnFinished != null)
                 {
                     OnFinished(this);

+ 1 - 1
Emby.Server.Implementations/packages.config

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="Emby.XmlTv" version="1.0.4" targetFramework="portable45-net45+win8" />
+  <package id="Emby.XmlTv" version="1.0.5" targetFramework="portable45-net45+win8" />
   <package id="MediaBrowser.Naming" version="1.0.4" targetFramework="portable45-net45+win8" />
   <package id="SQLitePCL.pretty" version="1.1.0" targetFramework="portable45-net45+win8" />
   <package id="SQLitePCLRaw.core" version="1.1.1" targetFramework="portable45-net45+win8" />

+ 7 - 22
MediaBrowser.Api/BasePeriodicWebSocketListener.cs

@@ -23,8 +23,8 @@ namespace MediaBrowser.Api
         /// <summary>
         /// The _active connections
         /// </summary>
-        protected readonly List<Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType, SemaphoreSlim>> ActiveConnections =
-            new List<Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType, SemaphoreSlim>>();
+        protected readonly List<Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType>> ActiveConnections =
+            new List<Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType>>();
 
         /// <summary>
         /// Gets the name.
@@ -132,11 +132,9 @@ namespace MediaBrowser.Api
                 InitialDelayMs = dueTimeMs
             };
 
-            var semaphore = new SemaphoreSlim(1, 1);
-
             lock (ActiveConnections)
             {
-                ActiveConnections.Add(new Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType, SemaphoreSlim>(message.Connection, cancellationTokenSource, timer, state, semaphore));
+                ActiveConnections.Add(new Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType>(message.Connection, cancellationTokenSource, timer, state));
             }
 
             if (timer != null)
@@ -153,7 +151,7 @@ namespace MediaBrowser.Api
         {
             var connection = (IWebSocketConnection)state;
 
-            Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType, SemaphoreSlim> tuple;
+            Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType> tuple;
 
             lock (ActiveConnections)
             {
@@ -176,7 +174,7 @@ namespace MediaBrowser.Api
 
         protected void SendData(bool force)
         {
-            List<Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType, SemaphoreSlim>> tuples;
+            List<Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType>> tuples;
 
             lock (ActiveConnections)
             {
@@ -204,14 +202,12 @@ namespace MediaBrowser.Api
             }
         }
 
-        private async void SendData(Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType, SemaphoreSlim> tuple)
+        private async void SendData(Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType> tuple)
         {
             var connection = tuple.Item1;
 
             try
             {
-                await tuple.Item5.WaitAsync(tuple.Item2.Token).ConfigureAwait(false);
-
                 var state = tuple.Item4;
 
                 var data = await GetDataToSend(state).ConfigureAwait(false);
@@ -227,8 +223,6 @@ namespace MediaBrowser.Api
 
                     state.DateLastSendUtc = DateTime.UtcNow;
                 }
-
-                tuple.Item5.Release();
             }
             catch (OperationCanceledException)
             {
@@ -265,7 +259,7 @@ namespace MediaBrowser.Api
         /// Disposes the connection.
         /// </summary>
         /// <param name="connection">The connection.</param>
-        private void DisposeConnection(Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType, SemaphoreSlim> connection)
+        private void DisposeConnection(Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType> connection)
         {
             Logger.Debug("{1} stop transmitting over websocket to {0}", connection.Item1.RemoteEndPoint, GetType().Name);
 
@@ -293,15 +287,6 @@ namespace MediaBrowser.Api
 
             }
 
-            try
-            {
-                connection.Item5.Dispose();
-            }
-            catch (ObjectDisposedException)
-            {
-
-            }
-
             ActiveConnections.Remove(connection);
         }
 

+ 18 - 11
MediaBrowser.Api/Playback/BaseStreamingService.cs

@@ -2720,6 +2720,15 @@ namespace MediaBrowser.Api.Playback
                     //inputModifier += " -noaccurate_seek";
                 }
 
+                if (!string.IsNullOrWhiteSpace(state.InputContainer))
+                {
+                    var inputFormat = GetInputFormat(state.InputContainer);
+                    if (!string.IsNullOrWhiteSpace(inputFormat))
+                    {
+                        inputModifier += " -f " + inputFormat;
+                    }
+                }
+
                 if (state.RunTimeTicks.HasValue)
                 {
                     foreach (var stream in state.MediaSource.MediaStreams)
@@ -2738,21 +2747,19 @@ namespace MediaBrowser.Api.Playback
                         }
                     }
                 }
+            }
 
-                //var videoStream = state.VideoStream;
-                //if (videoStream != null && !string.IsNullOrWhiteSpace(videoStream.Codec))
-                //{
-                //    inputModifier += "  -codec:0 " + videoStream.Codec;
+            return inputModifier;
+        }
 
-                //    var audioStream = state.AudioStream;
-                //    if (audioStream != null && !string.IsNullOrWhiteSpace(audioStream.Codec))
-                //    {
-                //        inputModifier += "  -codec:1 " + audioStream.Codec;
-                //    }
-                //}
+        private string GetInputFormat(string container)
+        {
+            if (string.Equals(container, "mkv", StringComparison.OrdinalIgnoreCase))
+            {
+                return "matroska";
             }
 
-            return inputModifier;
+            return container;
         }
 
         private string GetDecoderFromCodec(string codec)

+ 1 - 1
MediaBrowser.Api/Playback/Hls/BaseHlsService.cs

@@ -103,7 +103,7 @@ namespace MediaBrowser.Api.Playback.Hls
                             throw;
                         }
 
-                        var waitForSegments = state.SegmentLength >= 10 ? 2 : 3;
+                        var waitForSegments = state.SegmentLength >= 10 ? 2 : 2;
                         await WaitForMinimumSegmentCount(playlist, waitForSegments, cancellationTokenSource.Token).ConfigureAwait(false);
                     }
                 }

+ 2 - 0
MediaBrowser.Controller/LiveTv/ChannelInfo.cs

@@ -25,6 +25,8 @@ namespace MediaBrowser.Controller.LiveTv
         /// <value>The id of the channel.</value>
         public string Id { get; set; }
 
+        public string TunerChannelId { get; set; }
+
         /// <summary>
         /// Gets or sets the tuner host identifier.
         /// </summary>

+ 1 - 1
MediaBrowser.Controller/LiveTv/IListingsProvider.cs

@@ -11,7 +11,7 @@ namespace MediaBrowser.Controller.LiveTv
     {
         string Name { get; }
         string Type { get; }
-        Task<IEnumerable<ProgramInfo>> GetProgramsAsync(ListingsProviderInfo info, string channelNumber, string channelName, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken);
+        Task<IEnumerable<ProgramInfo>> GetProgramsAsync(ListingsProviderInfo info, string channelId, string channelNumber, string channelName, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken);
         Task AddMetadata(ListingsProviderInfo info, List<ChannelInfo> channels, CancellationToken cancellationToken);
         Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings);
         Task<List<NameIdPair>> GetLineups(ListingsProviderInfo info, string country, string location);