using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.MediaSegments;
using Microsoft.EntityFrameworkCore;
namespace Jellyfin.Server.Implementations.MediaSegments;
///
/// Manages media segments retrival and storage.
///
public class MediaSegmentManager : IMediaSegmentManager
{
private readonly IDbContextFactory _dbProvider;
///
/// Initializes a new instance of the class.
///
/// EFCore Database factory.
public MediaSegmentManager(IDbContextFactory dbProvider)
{
_dbProvider = dbProvider;
}
///
public async Task CreateSegmentAsync(MediaSegmentDto mediaSegment, string segmentProviderId)
{
ArgumentOutOfRangeException.ThrowIfLessThan(mediaSegment.EndTicks, mediaSegment.StartTicks);
using var db = await _dbProvider.CreateDbContextAsync().ConfigureAwait(false);
db.MediaSegments.Add(Map(mediaSegment, segmentProviderId));
await db.SaveChangesAsync().ConfigureAwait(false);
return mediaSegment;
}
///
public async Task DeleteSegmentAsync(Guid segmentId)
{
using var db = await _dbProvider.CreateDbContextAsync().ConfigureAwait(false);
await db.MediaSegments.Where(e => e.Id.Equals(segmentId)).ExecuteDeleteAsync().ConfigureAwait(false);
}
///
public async Task> GetSegmentsAsync(Guid itemId, IEnumerable? typeFilter)
{
using var db = await _dbProvider.CreateDbContextAsync().ConfigureAwait(false);
var query = db.MediaSegments
.Where(e => e.ItemId.Equals(itemId));
if (typeFilter is not null)
{
query = query.Where(e => typeFilter.Contains(e.Type));
}
return query
.OrderBy(e => e.StartTicks)
.AsNoTracking()
.ToImmutableList()
.Select(Map);
}
private static MediaSegmentDto Map(MediaSegment segment)
{
return new MediaSegmentDto()
{
Id = segment.Id,
EndTicks = segment.EndTicks,
ItemId = segment.ItemId,
StartTicks = segment.StartTicks,
Type = segment.Type
};
}
private static MediaSegment Map(MediaSegmentDto segment, string segmentProviderId)
{
return new MediaSegment()
{
Id = segment.Id,
EndTicks = segment.EndTicks,
ItemId = segment.ItemId,
StartTicks = segment.StartTicks,
Type = segment.Type,
SegmentProviderId = segmentProviderId
};
}
///
public bool HasSegments(Guid itemId)
{
using var db = _dbProvider.CreateDbContext();
return db.MediaSegments.Any(e => e.ItemId.Equals(itemId));
}
///
public bool IsTypeSupported(BaseItem baseItem)
{
return baseItem.MediaType is Data.Enums.MediaType.Video or Data.Enums.MediaType.Audio;
}
}