Merge pull request #1573 from MediaBrowser/dev

Dev
pull/702/head
Luke 8 years ago
commit 95f5859837

@ -63,6 +63,15 @@ namespace MediaBrowser.Api
_mediaSourceManager = mediaSourceManager;
Instance = this;
_sessionManager.PlaybackProgress += _sessionManager_PlaybackProgress;
}
void _sessionManager_PlaybackProgress(object sender, PlaybackProgressEventArgs e)
{
if (!string.IsNullOrWhiteSpace(e.PlaySessionId))
{
PingTranscodingJob(e.PlaySessionId, e.IsPaused);
}
}
/// <summary>
@ -300,26 +309,31 @@ namespace MediaBrowser.Api
PingTimer(job, false);
}
}
internal void PingTranscodingJob(string playSessionId)
internal void PingTranscodingJob(string playSessionId, bool? isUserPaused)
{
if (string.IsNullOrEmpty(playSessionId))
{
throw new ArgumentNullException("playSessionId");
}
//Logger.Debug("PingTranscodingJob PlaySessionId={0}", playSessionId);
//Logger.Debug("PingTranscodingJob PlaySessionId={0} isUsedPaused: {1}", playSessionId, isUserPaused);
var jobs = new List<TranscodingJob>();
List<TranscodingJob> jobs;
lock (_activeTranscodingJobs)
{
// This is really only needed for HLS.
// Progressive streams can stop on their own reliably
jobs = jobs.Where(j => string.Equals(playSessionId, j.PlaySessionId, StringComparison.OrdinalIgnoreCase)).ToList();
jobs = _activeTranscodingJobs.Where(j => string.Equals(playSessionId, j.PlaySessionId, StringComparison.OrdinalIgnoreCase)).ToList();
}
foreach (var job in jobs)
{
if (isUserPaused.HasValue)
{
//Logger.Debug("Setting job.IsUserPaused to {0}. jobId: {1}", isUserPaused, job.Id);
job.IsUserPaused = isUserPaused.Value;
}
PingTimer(job, true);
}
}
@ -655,6 +669,7 @@ namespace MediaBrowser.Api
public object ProcessLock = new object();
public bool HasExited { get; set; }
public bool IsUserPaused { get; set; }
public string Id { get; set; }

@ -61,8 +61,9 @@ namespace MediaBrowser.Api.Playback.Progressive
{
try
{
new ProgressiveFileCopier(_fileSystem, _job)
.StreamFile(Path, responseStream);
var task = new ProgressiveFileCopier(_fileSystem, _job, Logger).StreamFile(Path, responseStream);
Task.WaitAll(task);
}
catch (IOException)
{
@ -91,19 +92,21 @@ namespace MediaBrowser.Api.Playback.Progressive
{
private readonly IFileSystem _fileSystem;
private readonly TranscodingJob _job;
private readonly ILogger _logger;
// 256k
private const int BufferSize = 262144;
private long _bytesWritten = 0;
public ProgressiveFileCopier(IFileSystem fileSystem, TranscodingJob job)
public ProgressiveFileCopier(IFileSystem fileSystem, TranscodingJob job, ILogger logger)
{
_fileSystem = fileSystem;
_job = job;
_logger = logger;
}
public void StreamFile(string path, Stream outputStream)
public async Task StreamFile(string path, Stream outputStream)
{
var eofCount = 0;
long position = 0;
@ -126,8 +129,7 @@ namespace MediaBrowser.Api.Playback.Progressive
{
eofCount++;
}
var task = Task.Delay(100);
Task.WaitAll(task);
await Task.Delay(100).ConfigureAwait(false);
}
else
{
@ -145,6 +147,30 @@ namespace MediaBrowser.Api.Playback.Progressive
int count;
while ((count = source.Read(array, 0, array.Length)) != 0)
{
//if (_job != null)
//{
// var didPause = false;
// var totalPauseTime = 0;
// if (_job.IsUserPaused)
// {
// _logger.Debug("Pausing writing to network stream while user has paused playback.");
// while (_job.IsUserPaused && totalPauseTime < 30000)
// {
// didPause = true;
// var pauseTime = 500;
// totalPauseTime += pauseTime;
// await Task.Delay(pauseTime).ConfigureAwait(false);
// }
// }
// if (didPause)
// {
// _logger.Debug("Resuming writing to network stream due to user unpausing playback.");
// }
//}
destination.Write(array, 0, count);
_bytesWritten += count;

@ -213,8 +213,6 @@ namespace MediaBrowser.Api.Reports
SortBy = request.GetOrderBy(),
SortOrder = request.SortOrder ?? SortOrder.Ascending,
Filter = i => ApplyAdditionalFilters(request, i, user, _libraryManager),
IsFavorite = request.IsFavorite,
Limit = request.Limit,
StartIndex = request.StartIndex,
@ -350,6 +348,15 @@ namespace MediaBrowser.Api.Reports
query.MaxParentalRating = _localization.GetRatingLevel(request.MinOfficialRating);
}
// Artists
if (!string.IsNullOrEmpty(request.ArtistIds))
{
var artistIds = request.ArtistIds.Split(new[] { '|', ',' });
var artistItems = artistIds.Select(_libraryManager.GetItemById).Where(i => i != null).ToList();
query.ArtistNames = artistItems.Select(i => i.Name).ToArray();
}
// Artists
if (!string.IsNullOrEmpty(request.Artists))
{
@ -371,28 +378,6 @@ namespace MediaBrowser.Api.Reports
return query;
}
private bool ApplyAdditionalFilters(BaseReportRequest request, BaseItem i, User user, ILibraryManager libraryManager)
{
// Artists
if (!string.IsNullOrEmpty(request.ArtistIds))
{
var artistIds = request.ArtistIds.Split(new[] { '|', ',' });
var audio = i as IHasArtist;
if (!(audio != null && artistIds.Any(id =>
{
var artistItem = libraryManager.GetItemById(id);
return artistItem != null && audio.HasAnyArtist(artistItem.Name);
})))
{
return false;
}
}
return true;
}
/// <summary> Gets query result. </summary>
/// <param name="request"> The request. </param>
/// <returns> The query result. </returns>

@ -184,8 +184,6 @@ namespace MediaBrowser.Api.UserLibrary
SortBy = request.GetOrderBy(),
SortOrder = request.SortOrder ?? SortOrder.Ascending,
Filter = i => ApplyAdditionalFilters(request, i, user, _libraryManager),
IsFavorite = request.IsFavorite,
Limit = request.Limit,
StartIndex = request.StartIndex,
@ -323,6 +321,15 @@ namespace MediaBrowser.Api.UserLibrary
query.MaxParentalRating = _localization.GetRatingLevel(request.MinOfficialRating);
}
// Artists
if (!string.IsNullOrEmpty(request.ArtistIds))
{
var artistIds = request.ArtistIds.Split(new[] { '|', ',' });
var artistItems = artistIds.Select(_libraryManager.GetItemById).Where(i => i != null).ToList();
query.ArtistNames = artistItems.Select(i => i.Name).ToArray();
}
// Artists
if (!string.IsNullOrEmpty(request.Artists))
{
@ -337,28 +344,6 @@ namespace MediaBrowser.Api.UserLibrary
return query;
}
private bool ApplyAdditionalFilters(GetItems request, BaseItem i, User user, ILibraryManager libraryManager)
{
// Artists
if (!string.IsNullOrEmpty(request.ArtistIds))
{
var artistIds = request.ArtistIds.Split(new[] { '|', ',' });
var audio = i as IHasArtist;
if (!(audio != null && artistIds.Any(id =>
{
var artistItem = libraryManager.GetItemById(id);
return artistItem != null && audio.HasAnyArtist(artistItem.Name);
})))
{
return false;
}
}
return true;
}
}
/// <summary>

@ -335,11 +335,6 @@ namespace MediaBrowser.Api.UserLibrary
public void Post(ReportPlaybackProgress request)
{
if (!string.IsNullOrWhiteSpace(request.PlaySessionId))
{
ApiEntryPoint.Instance.PingTranscodingJob(request.PlaySessionId);
}
request.SessionId = GetSession().Result.Id;
var task = _sessionManager.OnPlaybackProgress(request);
@ -349,7 +344,7 @@ namespace MediaBrowser.Api.UserLibrary
public void Post(PingPlaybackSession request)
{
ApiEntryPoint.Instance.PingTranscodingJob(request.PlaySessionId);
ApiEntryPoint.Instance.PingTranscodingJob(request.PlaySessionId, null);
}
/// <summary>

@ -151,16 +151,6 @@ namespace MediaBrowser.Controller.Entities
AddChildInternal(item.Id);
await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
if (!EnableNewFolderQuerying())
{
await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
}
}
private static bool EnableNewFolderQuerying()
{
return ConfigurationManager.Configuration.MigrationVersion >= 1;
}
protected void AddChildrenInternal(List<Guid> children)
@ -197,21 +187,11 @@ namespace MediaBrowser.Controller.Entities
/// Removes the child.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
/// <exception cref="System.InvalidOperationException">Unable to remove + item.Name</exception>
public Task RemoveChild(BaseItem item, CancellationToken cancellationToken)
public void RemoveChild(BaseItem item)
{
RemoveChildrenInternal(new[] { item.Id }.ToList());
item.SetParent(null);
if (!EnableNewFolderQuerying())
{
return ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken);
}
return Task.FromResult(true);
}
#region Indexing
@ -500,11 +480,6 @@ namespace MediaBrowser.Controller.Entities
await LibraryManager.CreateItems(newItems, cancellationToken).ConfigureAwait(false);
AddChildrenInternal(newItems.Select(i => i.Id).ToList());
if (!EnableNewFolderQuerying())
{
await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
}
}
}
@ -734,45 +709,11 @@ namespace MediaBrowser.Controller.Entities
/// <returns>IEnumerable{BaseItem}.</returns>
protected IEnumerable<Guid> GetCachedChildren()
{
if (EnableNewFolderQuerying())
return ItemRepository.GetItemIdsList(new InternalItemsQuery
{
return ItemRepository.GetItemIdsList(new InternalItemsQuery
{
ParentId = Id
});
}
return ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null).Select(i => i.Id);
}
private BaseItem RetrieveChild(BaseItem child)
{
if (child == null || child.Id == Guid.Empty)
{
Logger.Error("Item found with empty Id: " + (child.Path ?? child.Name));
return null;
}
var item = LibraryManager.GetMemoryItemById(child.Id);
if (item != null)
{
if (item is IByReferenceItem)
{
return LibraryManager.GetOrAddByReferenceItem(item);
}
item.SetParent(this);
}
else
{
child.SetParent(this);
LibraryManager.RegisterItem(child);
item = child;
}
ParentId = Id
return item;
});
}
public QueryResult<BaseItem> QueryRecursive(InternalItemsQuery query)

@ -15,11 +15,14 @@ namespace MediaBrowser.Controller.Library
public BaseItem Item { get; set; }
public BaseItemInfo MediaInfo { get; set; }
public string MediaSourceId { get; set; }
public bool IsPaused { get; set; }
public string DeviceId { get; set; }
public string DeviceName { get; set; }
public string ClientName { get; set; }
public string PlaySessionId { get; set; }
public PlaybackProgressEventArgs()
{
Users = new List<User>();

@ -42,13 +42,6 @@ namespace MediaBrowser.Controller.Persistence
/// <returns>Task{IEnumerable{ItemReview}}.</returns>
IEnumerable<ItemReview> GetCriticReviews(Guid itemId);
/// <summary>
/// Gets the children items.
/// </summary>
/// <param name="parentId">The parent identifier.</param>
/// <returns>IEnumerable&lt;BaseItem&gt;.</returns>
IEnumerable<BaseItem> GetChildrenItems(Guid parentId);
/// <summary>
/// Saves the critic reviews.
/// </summary>
@ -96,22 +89,6 @@ namespace MediaBrowser.Controller.Persistence
/// <returns>Task.</returns>
Task SaveChapters(Guid id, IEnumerable<ChapterInfo> chapters, CancellationToken cancellationToken);
/// <summary>
/// Gets the children.
/// </summary>
/// <param name="parentId">The parent id.</param>
/// <returns>IEnumerable{ChildDefinition}.</returns>
IEnumerable<Guid> GetChildren(Guid parentId);
/// <summary>
/// Saves the children.
/// </summary>
/// <param name="parentId">The parent id.</param>
/// <param name="children">The children.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task SaveChildren(Guid parentId, IEnumerable<Guid> children, CancellationToken cancellationToken);
/// <summary>
/// Gets the media streams.
/// </summary>

@ -188,15 +188,15 @@ namespace MediaBrowser.Dlna.Didl
{
var subtitleAdded = AddSubtitleElement(container, subtitle);
if (subtitleAdded && _profile.EnableSingleSubtitleLimit)
{
break;
}
if (subtitleAdded && _profile.EnableSingleSubtitleLimit)
{
break;
}
}
}
}
private bool AddSubtitleElement(XmlElement container, SubtitleStreamInfo info)
private bool AddSubtitleElement(XmlElement container, SubtitleStreamInfo info)
{
var subtitleProfile = _profile.SubtitleProfiles
.FirstOrDefault(i => string.Equals(info.Format, i.Format, StringComparison.OrdinalIgnoreCase) && i.Method == SubtitleDeliveryMethod.External);
@ -213,13 +213,13 @@ namespace MediaBrowser.Dlna.Didl
// <sec:CaptionInfoEx sec:type="srt">http://192.168.1.3:9999/video.srt</sec:CaptionInfoEx>
// <sec:CaptionInfo sec:type="srt">http://192.168.1.3:9999/video.srt</sec:CaptionInfo>
//var res = container.OwnerDocument.CreateElement("SEC", "CaptionInfoEx");
var res = container.OwnerDocument.CreateElement("CaptionInfoEx", "sec");
//res.InnerText = info.Url;
res.InnerText = info.Url;
//// TODO: attribute needs SEC:
//res.SetAttribute("type", info.Format.ToLower());
//container.AppendChild(res);
res.SetAttribute("type", "sec", info.Format.ToLower());
container.AppendChild(res);
}
else if (string.Equals(subtitleMode, "smi", StringComparison.OrdinalIgnoreCase))
{
@ -243,7 +243,7 @@ namespace MediaBrowser.Dlna.Didl
container.AppendChild(res);
}
return true;
return true;
}
private void AddVideoResource(XmlElement container, IHasMediaSources video, string deviceId, Filter filter, string contentFeatures, StreamInfo streamInfo)

@ -604,7 +604,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
process.StandardError.BaseStream.CopyToAsync(logFileStream);
var ranToCompletion = process.WaitForExit(120000);
var ranToCompletion = process.WaitForExit(300000);
if (!ranToCompletion)
{

@ -421,7 +421,7 @@ namespace MediaBrowser.Providers.Manager
if (saveLocally)
{
if (item is Episode)
if (type == ImageType.Primary && item is Episode)
{
path = Path.Combine(Path.GetDirectoryName(item.Path), "metadata", filename + extension);
}

@ -430,7 +430,7 @@ namespace MediaBrowser.Server.Implementations.Library
}
else if (parent != null)
{
await parent.RemoveChild(item, CancellationToken.None).ConfigureAwait(false);
parent.RemoveChild(item);
}
await ItemRepository.DeleteItem(item.Id, CancellationToken.None).ConfigureAwait(false);

@ -63,8 +63,6 @@ namespace MediaBrowser.Server.Implementations.Persistence
private readonly string _criticReviewsPath;
private IDbCommand _deleteChildrenCommand;
private IDbCommand _saveChildrenCommand;
private IDbCommand _deleteItemCommand;
private IDbCommand _deletePeopleCommand;
@ -138,9 +136,6 @@ namespace MediaBrowser.Server.Implementations.Persistence
"create index if not exists idx_AncestorIds1 on AncestorIds(AncestorId)",
"create index if not exists idx_AncestorIds2 on AncestorIds(AncestorIdText)",
"create table if not exists ChildrenIds (ParentId GUID, ItemId GUID, PRIMARY KEY (ParentId, ItemId))",
"create index if not exists idx_ChildrenIds on ChildrenIds(ParentId,ItemId)",
"create table if not exists People (ItemId GUID, Name TEXT NOT NULL, Role TEXT, PersonType TEXT, SortOrder int, ListOrder int)",
"create index if not exists idxPeopleItemId on People(ItemId)",
"create index if not exists idxPeopleName on People(Name)",
@ -477,19 +472,10 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
_saveItemCommand.CommandText += ")";
_deleteChildrenCommand = _connection.CreateCommand();
_deleteChildrenCommand.CommandText = "delete from ChildrenIds where ParentId=@ParentId";
_deleteChildrenCommand.Parameters.Add(_deleteChildrenCommand, "@ParentId");
_deleteItemCommand = _connection.CreateCommand();
_deleteItemCommand.CommandText = "delete from TypedBaseItems where guid=@Id";
_deleteItemCommand.Parameters.Add(_deleteItemCommand, "@Id");
_saveChildrenCommand = _connection.CreateCommand();
_saveChildrenCommand.CommandText = "replace into ChildrenIds (ParentId, ItemId) values (@ParentId, @ItemId)";
_saveChildrenCommand.Parameters.Add(_saveChildrenCommand, "@ParentId");
_saveChildrenCommand.Parameters.Add(_saveChildrenCommand, "@ItemId");
// People
_deletePeopleCommand = _connection.CreateCommand();
_deletePeopleCommand.CommandText = "delete from People where ItemId=@Id";
@ -1375,63 +1361,6 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
}
public IEnumerable<Guid> GetChildren(Guid parentId)
{
if (parentId == Guid.Empty)
{
throw new ArgumentNullException("parentId");
}
CheckDisposed();
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = "select ItemId from ChildrenIds where ParentId = @ParentId";
cmd.Parameters.Add(cmd, "@ParentId", DbType.Guid).Value = parentId;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{
while (reader.Read())
{
yield return reader.GetGuid(0);
}
}
}
}
public IEnumerable<BaseItem> GetChildrenItems(Guid parentId)
{
if (parentId == Guid.Empty)
{
throw new ArgumentNullException("parentId");
}
CheckDisposed();
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = "select " + string.Join(",", _retriveItemColumns) + " from TypedBaseItems where guid in (select ItemId from ChildrenIds where ParentId = @ParentId)";
cmd.Parameters.Add(cmd, "@ParentId", DbType.Guid).Value = parentId;
//Logger.Debug(cmd.CommandText);
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{
while (reader.Read())
{
var item = GetItem(reader);
if (item != null)
{
yield return item;
}
}
}
}
}
public IEnumerable<BaseItem> GetItemsOfType(Type type)
{
if (type == null)
@ -2392,11 +2321,6 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
transaction = _connection.BeginTransaction();
// First delete children
_deleteChildrenCommand.GetParameter(0).Value = id;
_deleteChildrenCommand.Transaction = transaction;
_deleteChildrenCommand.ExecuteNonQuery();
// Delete people
_deletePeopleCommand.GetParameter(0).Value = id;
_deletePeopleCommand.Transaction = transaction;
@ -2455,79 +2379,6 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
}
public async Task SaveChildren(Guid parentId, IEnumerable<Guid> children, CancellationToken cancellationToken)
{
if (parentId == Guid.Empty)
{
throw new ArgumentNullException("parentId");
}
if (children == null)
{
throw new ArgumentNullException("children");
}
CheckDisposed();
await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false);
IDbTransaction transaction = null;
try
{
transaction = _connection.BeginTransaction();
// First delete
_deleteChildrenCommand.GetParameter(0).Value = parentId;
_deleteChildrenCommand.Transaction = transaction;
_deleteChildrenCommand.ExecuteNonQuery();
foreach (var id in children)
{
cancellationToken.ThrowIfCancellationRequested();
_saveChildrenCommand.GetParameter(0).Value = parentId;
_saveChildrenCommand.GetParameter(1).Value = id;
_saveChildrenCommand.Transaction = transaction;
_saveChildrenCommand.ExecuteNonQuery();
}
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save children:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
WriteLock.Release();
}
}
public List<string> GetPeopleNames(InternalPeopleQuery query)
{
if (query == null)

@ -705,7 +705,9 @@ namespace MediaBrowser.Server.Implementations.Session
MediaInfo = info.Item,
DeviceName = session.DeviceName,
ClientName = session.Client,
DeviceId = session.DeviceId
DeviceId = session.DeviceId,
IsPaused = info.IsPaused,
PlaySessionId = info.PlaySessionId
}, _logger);

@ -272,6 +272,9 @@
<Content Include="dashboard-ui\legacy\objectassign.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\legacy\selectmenu.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\livetvguideprovider.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

Loading…
Cancel
Save