Compare commits

...

47 Commits

Author SHA1 Message Date
Joshua M. Boniface
383d514353 Bump version to 10.8.8 2022-11-29 13:42:58 -05:00
Bond-009
6fc8237242 Merge pull request #8753 from thornbill/fix-items-access-backport 2022-11-22 21:52:53 +01:00
Bill Thornton
79d7a4d4df Remove unused using statement 2022-11-16 10:27:41 -05:00
Bill Thornton
e90031b4cc Use elevated access control for media folders endpoint 2022-11-15 16:52:49 -05:00
Bill Thornton
4f3d562d75 Fix media folders endpoint access control 2022-11-15 16:49:03 -05:00
Bill Thornton
6c8b40f413 Fix items endpoint not honoring library access control 2022-11-15 16:35:05 -05:00
Joshua M. Boniface
ec81dc9be2 Bump version to 10.8.7 2022-10-31 23:07:09 -04:00
Joshua M. Boniface
45f3fb1cfc Merge pull request #8662 from cvium/this_next_up_fix_wont_work_either 2022-10-31 17:05:38 -04:00
Cody Robibero
f83a24ec43 Merge pull request #8667 from daullmer/backport-omdb-fix 2022-10-31 14:33:33 -06:00
Joshua M. Boniface
84c03a2d93 Merge pull request #8649 from jellyfin/revert-8480-revert-data-streams 2022-10-31 12:55:56 -04:00
David Ullmer
bc8e249080 Enable OMDB plot for non-English languages as fallback 2022-10-31 13:10:00 +01:00
cvium
5ea9a74289 fix: use a combination of ParentIndexNumber and IndexNumber to determine next up episodes 2022-10-30 16:06:47 +01:00
Niels van Velzen
987d31ea16 Revert "Revert "Merge pull request #8298 from lomion0815/fix-data-stream"" 2022-10-29 11:38:14 +02:00
Joshua M. Boniface
f850779781 Bump version to 10.8.6 2022-10-28 22:41:11 -04:00
Claus Vium
3bdc2bff5f Merge pull request #8620 from nyanmisaka/fix-dg2-tonemap-tearing
Fix the DG2 HDR TM tearing issue on Windows
2022-10-25 12:43:47 +02:00
nyanmisaka
5c6a84549a Fix some encoding presets
Signed-off-by: nyanmisaka <nst799610810@gmail.com>
2022-10-25 16:26:55 +08:00
nyanmisaka
48da35f91f Fix the DG2 HDR TM tearing issue on Windows
Signed-off-by: nyanmisaka <nst799610810@gmail.com>
2022-10-25 16:26:55 +08:00
Claus Vium
39b29eb9f1 Merge pull request #8608 from cvium/activitylog_datecreated_index
Add index for DateCreated on ActivityLogs
2022-10-24 18:46:54 +02:00
Anthony Lavado
a6740bf51e Merge pull request #8609 from anthonylavado/sd-image-fix 2022-10-23 13:37:29 -04:00
cvium
c7797d3ead fix build 2022-10-23 18:54:43 +02:00
Claus Vium
c86d5838be Merge pull request #8611 from nielsvanvelzen/transcodereasons 2022-10-22 14:17:47 +02:00
Niels van Velzen
43223b9036 Fix TranscodeReasons type in OpenAPI output 2022-10-22 13:59:24 +02:00
Anthony Lavado
c71385d2db Add token for program metadata download 2022-10-22 04:30:45 -04:00
Anthony Lavado
ad5becc524 Use token when retrieving images 2022-10-22 04:10:20 -04:00
cvium
7c75dcfb9c use filescoped namespace 2022-10-22 10:04:50 +02:00
cvium
7937e31a9b add index for DateCreated on ActivityLog 2022-10-22 10:02:52 +02:00
Claus Vium
1f1f26306b Merge pull request #8600 from Shadowghost/10.8-slow-load 2022-10-21 17:44:38 +02:00
Shadowghost
577399ca05 Prevent host lookup on GetSmartUrl for HTTP requests 2022-10-21 10:09:45 +02:00
Bond-009
e7ea7c0383 Merge pull request #8523 from Gylesie/tweak-lastplayeddate 2022-10-10 19:29:03 +02:00
Gylesie
9fe7751d05 Fallback only to the current time when marking item as watched 2022-10-09 11:28:49 +02:00
Claus Vium
bf129ab9b8 Merge pull request #8411 from Maxr1998/audio-stream-fix
Allow direct play even if no audio stream is available
2022-10-09 09:08:01 +02:00
Claus Vium
6d23de64c0 Merge pull request #8516 from cvium/kill_ffprobe_when_extraction_crashes 2022-10-09 08:27:34 +02:00
Claus Vium
e4f48bb486 Merge pull request #8517 from cvium/backport_8335 2022-10-09 08:27:22 +02:00
Andreas Egli
866b4460b1 change variable to camelCase 2022-10-08 19:00:36 +02:00
Andreas Egli
9db0b275ff allow additional flags after K_ for ffprobe keyframe extraction 2022-10-08 19:00:23 +02:00
Andreas Egli
14008fd7d0 add gentps flag to ffprobe for keyframe extraction 2022-10-08 19:00:02 +02:00
Andreas Egli
8532d88a71 add TryParse to FFProbe Keyframe extraction 2022-10-08 18:59:43 +02:00
cvium
737c739d33 fix: kill ffprobe if keyframe parsing fails 2022-10-08 18:56:07 +02:00
Claus Vium
679e83082f Merge pull request #8501 from cvium/fix_nextup 2022-10-07 07:50:04 +02:00
Claus Vium
d8e53f35a5 Merge pull request #8499 from cvium/add_basque_language 2022-10-07 07:49:17 +02:00
cvium
7a0e7b3cf8 add MinParentIndexNumber 2022-10-06 14:21:21 +02:00
cvium
373c63bcc7 fix: set MinIndexNumber for the next up query 2022-10-06 14:06:24 +02:00
cvium
be5d343efb chore: add Basque to the list of localization options 2022-10-06 09:44:11 +02:00
Cody Robibero
c9c91cc34e Merge pull request #8480 from thornbill/revert-data-streams 2022-10-01 08:52:39 -06:00
Bill Thornton
774b4a0d3f Revert "Merge pull request #8298 from lomion0815/fix-data-stream"
This reverts commit 848ea703bc, reversing
changes made to af87706379.
2022-10-01 00:56:46 -04:00
Maxr1998
23100c9b86 Use ICollection for candidateAudioStreams 2022-09-18 22:56:38 +02:00
Maxr1998
8753b7200f Allow direct play even if no audio stream is available 2022-09-15 02:04:12 +02:00
31 changed files with 886 additions and 116 deletions

View File

@@ -36,6 +36,7 @@
- [dmitrylyzo](https://github.com/dmitrylyzo)
- [DMouse10462](https://github.com/DMouse10462)
- [DrPandemic](https://github.com/DrPandemic)
- [eglia](https://github.com/eglia)
- [EraYaN](https://github.com/EraYaN)
- [escabe](https://github.com/escabe)
- [excelite](https://github.com/excelite)

View File

@@ -36,7 +36,7 @@
<PropertyGroup>
<Authors>Jellyfin Contributors</Authors>
<PackageId>Jellyfin.Naming</PackageId>
<VersionPrefix>10.8.5</VersionPrefix>
<VersionPrefix>10.8.8</VersionPrefix>
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
</PropertyGroup>

View File

@@ -1088,15 +1088,7 @@ namespace Emby.Server.Implementations
return GetLocalApiUrl(request.Host.Host, request.Scheme, requestPort);
}
// Published server ends with a /
if (!string.IsNullOrEmpty(PublishedServerUrl))
{
// Published server ends with a '/', so we need to remove it.
return PublishedServerUrl.Trim('/');
}
string smart = NetManager.GetBindInterface(request, out var port);
return GetLocalApiUrl(smart.Trim('/'), request.Scheme, port);
return GetSmartApiUrl(request.HttpContext.Connection.RemoteIpAddress ?? IPAddress.Loopback);
}
/// <inheritdoc/>

View File

@@ -3541,6 +3541,13 @@ namespace Emby.Server.Implementations.Data
statement?.TryBind("@MinIndexNumber", query.MinIndexNumber.Value);
}
if (query.MinParentAndIndexNumber.HasValue)
{
whereClauses.Add("((ParentIndexNumber=@MinParentAndIndexNumberParent and IndexNumber>=@MinParentAndIndexNumberIndex) or ParentIndexNumber>@MinParentAndIndexNumberParent)");
statement?.TryBind("@MinParentAndIndexNumberParent", query.MinParentAndIndexNumber.Value.ParentIndexNumber);
statement?.TryBind("@MinParentAndIndexNumberIndex", query.MinParentAndIndexNumber.Value.IndexNumber);
}
if (query.MinDateCreated.HasValue)
{
whereClauses.Add("DateCreated>=@MinDateCreated");

View File

@@ -165,12 +165,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings
const double DesiredAspect = 2.0 / 3;
programEntry.PrimaryImage = GetProgramImage(ApiUrl, imagesWithText, DesiredAspect) ??
GetProgramImage(ApiUrl, allImages, DesiredAspect);
programEntry.PrimaryImage = GetProgramImage(ApiUrl, imagesWithText, DesiredAspect, token) ??
GetProgramImage(ApiUrl, allImages, DesiredAspect, token);
const double WideAspect = 16.0 / 9;
programEntry.ThumbImage = GetProgramImage(ApiUrl, imagesWithText, WideAspect);
programEntry.ThumbImage = GetProgramImage(ApiUrl, imagesWithText, WideAspect, token);
// Don't supply the same image twice
if (string.Equals(programEntry.PrimaryImage, programEntry.ThumbImage, StringComparison.Ordinal))
@@ -178,7 +178,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
programEntry.ThumbImage = null;
}
programEntry.BackdropImage = GetProgramImage(ApiUrl, imagesWithoutText, WideAspect);
programEntry.BackdropImage = GetProgramImage(ApiUrl, imagesWithoutText, WideAspect, token);
// programEntry.bannerImage = GetProgramImage(ApiUrl, data, "Banner", false) ??
// GetProgramImage(ApiUrl, data, "Banner-L1", false) ??
@@ -399,7 +399,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
return info;
}
private static string GetProgramImage(string apiUrl, IEnumerable<ImageDataDto> images, double desiredAspect)
private static string GetProgramImage(string apiUrl, IEnumerable<ImageDataDto> images, double desiredAspect, string token)
{
var match = images
.OrderBy(i => Math.Abs(desiredAspect - GetAspectRatio(i)))
@@ -423,7 +423,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
}
else
{
return apiUrl + "/image/" + uri;
return apiUrl + "/image/" + uri + "?token=" + token;
}
}
@@ -457,6 +457,8 @@ namespace Emby.Server.Implementations.LiveTv.Listings
IReadOnlyList<string> programIds,
CancellationToken cancellationToken)
{
var token = await GetToken(info, cancellationToken).ConfigureAwait(false);
if (programIds.Count == 0)
{
return Array.Empty<ShowImagesDto>();
@@ -478,6 +480,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
{
Content = new StringContent(str.ToString(), Encoding.UTF8, MediaTypeNames.Application.Json)
};
message.Headers.TryAddWithoutValidation("token", token);
try
{

View File

@@ -386,6 +386,7 @@ namespace Emby.Server.Implementations.Localization
yield return new LocalizationOption("Español (Dominicana)", "es_DO");
yield return new LocalizationOption("Español (México)", "es-MX");
yield return new LocalizationOption("Eesti", "et");
yield return new LocalizationOption("Basque", "eu");
yield return new LocalizationOption("فارسی", "fa");
yield return new LocalizationOption("Suomi", "fi");
yield return new LocalizationOption("Filipino", "fil");

View File

@@ -192,7 +192,6 @@ namespace Emby.Server.Implementations.TV
AncestorWithPresentationUniqueKey = null,
SeriesPresentationUniqueKey = seriesKey,
IncludeItemTypes = new[] { BaseItemKind.Episode },
OrderBy = new[] { (ItemSortBy.ParentIndexNumber, SortOrder.Descending), (ItemSortBy.IndexNumber, SortOrder.Descending) },
IsPlayed = true,
Limit = 1,
ParentIndexNumberNotEquals = 0,
@@ -203,11 +202,10 @@ namespace Emby.Server.Implementations.TV
}
};
if (rewatching)
{
// find last watched by date played, not by newest episode watched
lastQuery.OrderBy = new[] { (ItemSortBy.DatePlayed, SortOrder.Descending), (ItemSortBy.ParentIndexNumber, SortOrder.Descending), (ItemSortBy.IndexNumber, SortOrder.Descending) };
}
// If rewatching is enabled, sort first by date played and then by season and episode numbers
lastQuery.OrderBy = rewatching
? new[] { (ItemSortBy.DatePlayed, SortOrder.Descending), (ItemSortBy.ParentIndexNumber, SortOrder.Descending), (ItemSortBy.IndexNumber, SortOrder.Descending) }
: new[] { (ItemSortBy.ParentIndexNumber, SortOrder.Descending), (ItemSortBy.IndexNumber, SortOrder.Descending) };
var lastWatchedEpisode = _libraryManager.GetItemList(lastQuery).Cast<Episode>().FirstOrDefault();
@@ -226,18 +224,16 @@ namespace Emby.Server.Implementations.TV
DtoOptions = dtoOptions
};
Episode nextEpisode;
if (rewatching)
// Locate the next up episode based on the last watched episode's season and episode number
var lastWatchedParentIndexNumber = lastWatchedEpisode?.ParentIndexNumber;
var lastWatchedIndexNumber = lastWatchedEpisode?.IndexNumberEnd ?? lastWatchedEpisode?.IndexNumber;
if (lastWatchedParentIndexNumber.HasValue && lastWatchedIndexNumber.HasValue)
{
nextQuery.Limit = 2;
// get watched episode after most recently watched
nextEpisode = _libraryManager.GetItemList(nextQuery).Cast<Episode>().ElementAtOrDefault(1);
}
else
{
nextEpisode = _libraryManager.GetItemList(nextQuery).Cast<Episode>().FirstOrDefault();
nextQuery.MinParentAndIndexNumber = (lastWatchedParentIndexNumber.Value, lastWatchedIndexNumber.Value + 1);
}
var nextEpisode = _libraryManager.GetItemList(nextQuery).Cast<Episode>().FirstOrDefault();
if (_configurationManager.Configuration.DisplaySpecialsWithinSeasons)
{
var consideredEpisodes = _libraryManager.GetItemList(new InternalItemsQuery(user)

View File

@@ -270,30 +270,13 @@ namespace Jellyfin.Api.Controllers
includeItemTypes = new[] { BaseItemKind.Playlist };
}
var enabledChannels = user!.GetPreferenceValues<Guid>(PreferenceKind.EnabledChannels);
bool isInEnabledFolder = Array.IndexOf(user.GetPreferenceValues<Guid>(PreferenceKind.EnabledFolders), item.Id) != -1
// Assume all folders inside an EnabledChannel are enabled
|| Array.IndexOf(enabledChannels, item.Id) != -1
// Assume all items inside an EnabledChannel are enabled
|| Array.IndexOf(enabledChannels, item.ChannelId) != -1;
var collectionFolders = _libraryManager.GetCollectionFolders(item);
foreach (var collectionFolder in collectionFolders)
{
if (user.GetPreferenceValues<Guid>(PreferenceKind.EnabledFolders).Contains(collectionFolder.Id))
{
isInEnabledFolder = true;
}
}
if (item is not UserRootFolder
&& !isInEnabledFolder
&& !user.HasPermission(PermissionKind.EnableAllFolders)
&& !user.HasPermission(PermissionKind.EnableAllChannels)
&& !string.Equals(collectionType, CollectionType.Folders, StringComparison.OrdinalIgnoreCase))
// api keys can always access all folders
&& !ClaimHelpers.GetIsApiKey(User)
// check the item is visible for the user
&& !item.IsVisible(user))
{
_logger.LogWarning("{UserName} is not permitted to access Library {ItemName}.", user.Username, item.Name);
_logger.LogWarning("{UserName} is not permitted to access Library {ItemName}", user!.Username, item.Name);
return Unauthorized($"{user.Username} is not permitted to access Library {item.Name}.");
}

View File

@@ -492,7 +492,7 @@ namespace Jellyfin.Api.Controllers
/// <response code="200">Media folders returned.</response>
/// <returns>List of user media folders.</returns>
[HttpGet("Library/MediaFolders")]
[Authorize(Policy = Policies.DefaultAuthorization)]
[Authorize(Policy = Policies.RequiresElevation)]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<QueryResult<BaseItemDto>> GetMediaFolders([FromQuery] bool? isHidden)
{

View File

@@ -18,7 +18,7 @@
<PropertyGroup>
<Authors>Jellyfin Contributors</Authors>
<PackageId>Jellyfin.Data</PackageId>
<VersionPrefix>10.8.5</VersionPrefix>
<VersionPrefix>10.8.8</VersionPrefix>
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
</PropertyGroup>

View File

@@ -0,0 +1,657 @@
#pragma warning disable CS1591
// <auto-generated />
using System;
using Jellyfin.Server.Implementations;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Jellyfin.Server.Implementations.Migrations
{
[DbContext(typeof(JellyfinDb))]
[Migration("20221022080052_AddIndexActivityLogsDateCreated")]
partial class AddIndexActivityLogsDateCreated
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasDefaultSchema("jellyfin")
.HasAnnotation("ProductVersion", "6.0.9");
modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("DayOfWeek")
.HasColumnType("INTEGER");
b.Property<double>("EndHour")
.HasColumnType("REAL");
b.Property<double>("StartHour")
.HasColumnType("REAL");
b.Property<Guid>("UserId")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AccessSchedules", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<DateTime>("DateCreated")
.HasColumnType("TEXT");
b.Property<string>("ItemId")
.HasMaxLength(256)
.HasColumnType("TEXT");
b.Property<int>("LogSeverity")
.HasColumnType("INTEGER");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(512)
.HasColumnType("TEXT");
b.Property<string>("Overview")
.HasMaxLength(512)
.HasColumnType("TEXT");
b.Property<uint>("RowVersion")
.IsConcurrencyToken()
.HasColumnType("INTEGER");
b.Property<string>("ShortOverview")
.HasMaxLength(512)
.HasColumnType("TEXT");
b.Property<string>("Type")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("TEXT");
b.Property<Guid>("UserId")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("DateCreated");
b.ToTable("ActivityLogs", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Client")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("TEXT");
b.Property<Guid>("ItemId")
.HasColumnType("TEXT");
b.Property<string>("Key")
.IsRequired()
.HasColumnType("TEXT");
b.Property<Guid>("UserId")
.HasColumnType("TEXT");
b.Property<string>("Value")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("UserId", "ItemId", "Client", "Key")
.IsUnique();
b.ToTable("CustomItemDisplayPreferences", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("ChromecastVersion")
.HasColumnType("INTEGER");
b.Property<string>("Client")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("TEXT");
b.Property<string>("DashboardTheme")
.HasMaxLength(32)
.HasColumnType("TEXT");
b.Property<bool>("EnableNextVideoInfoOverlay")
.HasColumnType("INTEGER");
b.Property<int?>("IndexBy")
.HasColumnType("INTEGER");
b.Property<Guid>("ItemId")
.HasColumnType("TEXT");
b.Property<int>("ScrollDirection")
.HasColumnType("INTEGER");
b.Property<bool>("ShowBackdrop")
.HasColumnType("INTEGER");
b.Property<bool>("ShowSidebar")
.HasColumnType("INTEGER");
b.Property<int>("SkipBackwardLength")
.HasColumnType("INTEGER");
b.Property<int>("SkipForwardLength")
.HasColumnType("INTEGER");
b.Property<string>("TvHome")
.HasMaxLength(32)
.HasColumnType("TEXT");
b.Property<Guid>("UserId")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("UserId", "ItemId", "Client")
.IsUnique();
b.ToTable("DisplayPreferences", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("DisplayPreferencesId")
.HasColumnType("INTEGER");
b.Property<int>("Order")
.HasColumnType("INTEGER");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("DisplayPreferencesId");
b.ToTable("HomeSection", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<DateTime>("LastModified")
.HasColumnType("TEXT");
b.Property<string>("Path")
.IsRequired()
.HasMaxLength(512)
.HasColumnType("TEXT");
b.Property<Guid?>("UserId")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("UserId")
.IsUnique();
b.ToTable("ImageInfos", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Client")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("TEXT");
b.Property<int?>("IndexBy")
.HasColumnType("INTEGER");
b.Property<Guid>("ItemId")
.HasColumnType("TEXT");
b.Property<bool>("RememberIndexing")
.HasColumnType("INTEGER");
b.Property<bool>("RememberSorting")
.HasColumnType("INTEGER");
b.Property<string>("SortBy")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("TEXT");
b.Property<int>("SortOrder")
.HasColumnType("INTEGER");
b.Property<Guid>("UserId")
.HasColumnType("TEXT");
b.Property<int>("ViewType")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("ItemDisplayPreferences", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Kind")
.HasColumnType("INTEGER");
b.Property<Guid?>("Permission_Permissions_Guid")
.HasColumnType("TEXT");
b.Property<uint>("RowVersion")
.IsConcurrencyToken()
.HasColumnType("INTEGER");
b.Property<Guid?>("UserId")
.HasColumnType("TEXT");
b.Property<bool>("Value")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("UserId", "Kind")
.IsUnique()
.HasFilter("[UserId] IS NOT NULL");
b.ToTable("Permissions", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Kind")
.HasColumnType("INTEGER");
b.Property<Guid?>("Preference_Preferences_Guid")
.HasColumnType("TEXT");
b.Property<uint>("RowVersion")
.IsConcurrencyToken()
.HasColumnType("INTEGER");
b.Property<Guid?>("UserId")
.HasColumnType("TEXT");
b.Property<string>("Value")
.IsRequired()
.HasMaxLength(65535)
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("UserId", "Kind")
.IsUnique()
.HasFilter("[UserId] IS NOT NULL");
b.ToTable("Preferences", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.Security.ApiKey", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("AccessToken")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTime>("DateCreated")
.HasColumnType("TEXT");
b.Property<DateTime>("DateLastActivity")
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("AccessToken")
.IsUnique();
b.ToTable("ApiKeys", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("AccessToken")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("AppName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("TEXT");
b.Property<string>("AppVersion")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("TEXT");
b.Property<DateTime>("DateCreated")
.HasColumnType("TEXT");
b.Property<DateTime>("DateLastActivity")
.HasColumnType("TEXT");
b.Property<DateTime>("DateModified")
.HasColumnType("TEXT");
b.Property<string>("DeviceId")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("TEXT");
b.Property<string>("DeviceName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("TEXT");
b.Property<bool>("IsActive")
.HasColumnType("INTEGER");
b.Property<Guid>("UserId")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("DeviceId");
b.HasIndex("AccessToken", "DateLastActivity");
b.HasIndex("DeviceId", "DateLastActivity");
b.HasIndex("UserId", "DeviceId");
b.ToTable("Devices", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.Security.DeviceOptions", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("CustomName")
.HasColumnType("TEXT");
b.Property<string>("DeviceId")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("DeviceId")
.IsUnique();
b.ToTable("DeviceOptions", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.User", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("AudioLanguagePreference")
.HasMaxLength(255)
.HasColumnType("TEXT");
b.Property<string>("AuthenticationProviderId")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("TEXT");
b.Property<bool>("DisplayCollectionsView")
.HasColumnType("INTEGER");
b.Property<bool>("DisplayMissingEpisodes")
.HasColumnType("INTEGER");
b.Property<string>("EasyPassword")
.HasMaxLength(65535)
.HasColumnType("TEXT");
b.Property<bool>("EnableAutoLogin")
.HasColumnType("INTEGER");
b.Property<bool>("EnableLocalPassword")
.HasColumnType("INTEGER");
b.Property<bool>("EnableNextEpisodeAutoPlay")
.HasColumnType("INTEGER");
b.Property<bool>("EnableUserPreferenceAccess")
.HasColumnType("INTEGER");
b.Property<bool>("HidePlayedInLatest")
.HasColumnType("INTEGER");
b.Property<long>("InternalId")
.HasColumnType("INTEGER");
b.Property<int>("InvalidLoginAttemptCount")
.HasColumnType("INTEGER");
b.Property<DateTime?>("LastActivityDate")
.HasColumnType("TEXT");
b.Property<DateTime?>("LastLoginDate")
.HasColumnType("TEXT");
b.Property<int?>("LoginAttemptsBeforeLockout")
.HasColumnType("INTEGER");
b.Property<int>("MaxActiveSessions")
.HasColumnType("INTEGER");
b.Property<int?>("MaxParentalAgeRating")
.HasColumnType("INTEGER");
b.Property<bool>("MustUpdatePassword")
.HasColumnType("INTEGER");
b.Property<string>("Password")
.HasMaxLength(65535)
.HasColumnType("TEXT");
b.Property<string>("PasswordResetProviderId")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("TEXT");
b.Property<bool>("PlayDefaultAudioTrack")
.HasColumnType("INTEGER");
b.Property<bool>("RememberAudioSelections")
.HasColumnType("INTEGER");
b.Property<bool>("RememberSubtitleSelections")
.HasColumnType("INTEGER");
b.Property<int?>("RemoteClientBitrateLimit")
.HasColumnType("INTEGER");
b.Property<uint>("RowVersion")
.IsConcurrencyToken()
.HasColumnType("INTEGER");
b.Property<string>("SubtitleLanguagePreference")
.HasMaxLength(255)
.HasColumnType("TEXT");
b.Property<int>("SubtitleMode")
.HasColumnType("INTEGER");
b.Property<int>("SyncPlayAccess")
.HasColumnType("INTEGER");
b.Property<string>("Username")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("TEXT")
.UseCollation("NOCASE");
b.HasKey("Id");
b.HasIndex("Username")
.IsUnique();
b.ToTable("Users", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b =>
{
b.HasOne("Jellyfin.Data.Entities.User", null)
.WithMany("AccessSchedules")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b =>
{
b.HasOne("Jellyfin.Data.Entities.User", null)
.WithMany("DisplayPreferences")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b =>
{
b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null)
.WithMany("HomeSections")
.HasForeignKey("DisplayPreferencesId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b =>
{
b.HasOne("Jellyfin.Data.Entities.User", null)
.WithOne("ProfileImage")
.HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b =>
{
b.HasOne("Jellyfin.Data.Entities.User", null)
.WithMany("ItemDisplayPreferences")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b =>
{
b.HasOne("Jellyfin.Data.Entities.User", null)
.WithMany("Permissions")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b =>
{
b.HasOne("Jellyfin.Data.Entities.User", null)
.WithMany("Preferences")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b =>
{
b.HasOne("Jellyfin.Data.Entities.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b =>
{
b.Navigation("HomeSections");
});
modelBuilder.Entity("Jellyfin.Data.Entities.User", b =>
{
b.Navigation("AccessSchedules");
b.Navigation("DisplayPreferences");
b.Navigation("ItemDisplayPreferences");
b.Navigation("Permissions");
b.Navigation("Preferences");
b.Navigation("ProfileImage");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,28 @@
#pragma warning disable CS1591, SA1601
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Jellyfin.Server.Implementations.Migrations
{
public partial class AddIndexActivityLogsDateCreated : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateIndex(
name: "IX_ActivityLogs_DateCreated",
schema: "jellyfin",
table: "ActivityLogs",
column: "DateCreated");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_ActivityLogs_DateCreated",
schema: "jellyfin",
table: "ActivityLogs");
}
}
}

View File

@@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Jellyfin.Server.Implementations.Migrations
{
[DbContext(typeof(JellyfinDb))]
@@ -15,7 +17,7 @@ namespace Jellyfin.Server.Implementations.Migrations
#pragma warning disable 612, 618
modelBuilder
.HasDefaultSchema("jellyfin")
.HasAnnotation("ProductVersion", "5.0.7");
.HasAnnotation("ProductVersion", "6.0.9");
modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b =>
{
@@ -39,7 +41,7 @@ namespace Jellyfin.Server.Implementations.Migrations
b.HasIndex("UserId");
b.ToTable("AccessSchedules");
b.ToTable("AccessSchedules", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b =>
@@ -85,7 +87,9 @@ namespace Jellyfin.Server.Implementations.Migrations
b.HasKey("Id");
b.ToTable("ActivityLogs");
b.HasIndex("DateCreated");
b.ToTable("ActivityLogs", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b =>
@@ -117,7 +121,7 @@ namespace Jellyfin.Server.Implementations.Migrations
b.HasIndex("UserId", "ItemId", "Client", "Key")
.IsUnique();
b.ToTable("CustomItemDisplayPreferences");
b.ToTable("CustomItemDisplayPreferences", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b =>
@@ -174,7 +178,7 @@ namespace Jellyfin.Server.Implementations.Migrations
b.HasIndex("UserId", "ItemId", "Client")
.IsUnique();
b.ToTable("DisplayPreferences");
b.ToTable("DisplayPreferences", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b =>
@@ -196,7 +200,7 @@ namespace Jellyfin.Server.Implementations.Migrations
b.HasIndex("DisplayPreferencesId");
b.ToTable("HomeSection");
b.ToTable("HomeSection", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b =>
@@ -221,7 +225,7 @@ namespace Jellyfin.Server.Implementations.Migrations
b.HasIndex("UserId")
.IsUnique();
b.ToTable("ImageInfos");
b.ToTable("ImageInfos", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b =>
@@ -265,7 +269,7 @@ namespace Jellyfin.Server.Implementations.Migrations
b.HasIndex("UserId");
b.ToTable("ItemDisplayPreferences");
b.ToTable("ItemDisplayPreferences", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b =>
@@ -296,7 +300,7 @@ namespace Jellyfin.Server.Implementations.Migrations
.IsUnique()
.HasFilter("[UserId] IS NOT NULL");
b.ToTable("Permissions");
b.ToTable("Permissions", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b =>
@@ -329,7 +333,7 @@ namespace Jellyfin.Server.Implementations.Migrations
.IsUnique()
.HasFilter("[UserId] IS NOT NULL");
b.ToTable("Preferences");
b.ToTable("Preferences", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.Security.ApiKey", b =>
@@ -358,7 +362,7 @@ namespace Jellyfin.Server.Implementations.Migrations
b.HasIndex("AccessToken")
.IsUnique();
b.ToTable("ApiKeys");
b.ToTable("ApiKeys", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b =>
@@ -416,7 +420,7 @@ namespace Jellyfin.Server.Implementations.Migrations
b.HasIndex("UserId", "DeviceId");
b.ToTable("Devices");
b.ToTable("Devices", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.Security.DeviceOptions", b =>
@@ -437,7 +441,7 @@ namespace Jellyfin.Server.Implementations.Migrations
b.HasIndex("DeviceId")
.IsUnique();
b.ToTable("DeviceOptions");
b.ToTable("DeviceOptions", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.User", b =>
@@ -550,7 +554,7 @@ namespace Jellyfin.Server.Implementations.Migrations
b.HasIndex("Username")
.IsUnique();
b.ToTable("Users");
b.ToTable("Users", "jellyfin");
});
modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b =>

View File

@@ -0,0 +1,17 @@
using Jellyfin.Data.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Jellyfin.Server.Implementations.ModelConfiguration;
/// <summary>
/// FluentAPI configuration for the ActivityLog entity.
/// </summary>
public class ActivityLogConfiguration : IEntityTypeConfiguration<ActivityLog>
{
/// <inheritdoc/>
public void Configure(EntityTypeBuilder<ActivityLog> builder)
{
builder.HasIndex(entity => entity.DateCreated);
}
}

View File

@@ -434,11 +434,15 @@ namespace Jellyfin.Server.Extensions
options.MapType<TranscodeReason>(() =>
new OpenApiSchema
{
Type = "string",
Enum = Enum.GetNames<TranscodeReason>()
.Select(e => new OpenApiString(e))
.Cast<IOpenApiAny>()
.ToArray()
Type = "array",
Items = new OpenApiSchema
{
Reference = new OpenApiReference
{
Id = nameof(TranscodeReason),
Type = ReferenceType.Schema,
}
}
});
// Swashbuckle doesn't use JsonOptions to describe responses, so we need to manually describe it.

View File

@@ -1,4 +1,5 @@
using System;
using System.Linq;
using Jellyfin.Extensions;
using Jellyfin.Server.Migrations;
using MediaBrowser.Common.Plugins;
@@ -8,6 +9,7 @@ using MediaBrowser.Model.ApiClient;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Session;
using MediaBrowser.Model.SyncPlay;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
@@ -56,6 +58,15 @@ namespace Jellyfin.Server.Filters
context.SchemaGenerator.GenerateSchema(configuration.ConfigurationType, context.SchemaRepository);
}
context.SchemaRepository.AddDefinition(nameof(TranscodeReason), new OpenApiSchema
{
Type = "string",
Enum = Enum.GetNames<TranscodeReason>()
.Select(e => new OpenApiString(e))
.Cast<IOpenApiAny>()
.ToArray()
});
}
}
}

View File

@@ -8,7 +8,7 @@
<PropertyGroup>
<Authors>Jellyfin Contributors</Authors>
<PackageId>Jellyfin.Common</PackageId>
<VersionPrefix>10.8.5</VersionPrefix>
<VersionPrefix>10.8.8</VersionPrefix>
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
</PropertyGroup>

View File

@@ -1863,7 +1863,7 @@ namespace MediaBrowser.Controller.Entities
data.PlaybackPositionTicks = 0;
}
data.LastPlayedDate = datePlayed ?? data.LastPlayedDate ?? DateTime.UtcNow;
data.LastPlayedDate = datePlayed ?? DateTime.UtcNow;
data.Played = true;
UserDataManager.SaveUserData(user.Id, this, data, UserDataSaveReason.TogglePlayed, CancellationToken.None);

View File

@@ -205,6 +205,16 @@ namespace MediaBrowser.Controller.Entities
public int? MinIndexNumber { get; set; }
/// <summary>
/// Gets or sets the minimum ParentIndexNumber and IndexNumber.
/// </summary>
/// <remarks>
/// It produces this where clause:
/// <para>(ParentIndexNumber = X and IndexNumber >= Y) or ParentIndexNumber > X.
/// </para>
/// </remarks>
public (int ParentIndexNumber, int IndexNumber)? MinParentAndIndexNumber { get; set; }
public int? AiredDuringSeason { get; set; }
public double? MinCriticRating { get; set; }

View File

@@ -8,7 +8,7 @@
<PropertyGroup>
<Authors>Jellyfin Contributors</Authors>
<PackageId>Jellyfin.Controller</PackageId>
<VersionPrefix>10.8.5</VersionPrefix>
<VersionPrefix>10.8.8</VersionPrefix>
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
</PropertyGroup>

View File

@@ -1415,7 +1415,11 @@ namespace MediaBrowser.Controller.MediaEncoding
param += " -preset 7";
}
param += " -look_ahead 0";
// Only h264_qsv has look_ahead option
if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase))
{
param += " -look_ahead 0";
}
}
else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) // h264 (h264_nvenc)
|| string.Equals(videoEncoder, "hevc_nvenc", StringComparison.OrdinalIgnoreCase)) // hevc (hevc_nvenc)
@@ -1453,7 +1457,7 @@ namespace MediaBrowser.Controller.MediaEncoding
break;
default:
param += " -preset p4";
param += " -preset p1";
break;
}
}
@@ -3404,6 +3408,12 @@ namespace MediaBrowser.Controller.MediaEncoding
// map from d3d11va to qsv.
mainFilters.Add("hwmap=derive_device=qsv");
}
else
{
// Insert a qsv scaler to sync the decoder surface,
// msdk will passthrough this internally.
mainFilters.Add("hwmap=derive_device=qsv,scale_qsv");
}
}
// hw deint

View File

@@ -436,9 +436,9 @@ namespace MediaBrowser.Model.Dlna
{
containerSupported = true;
videoSupported = videoStream != null && profile.SupportsVideoCodec(videoStream.Codec);
videoSupported = videoStream == null || profile.SupportsVideoCodec(videoStream.Codec);
audioSupported = audioStream != null && profile.SupportsAudioCodec(audioStream.Codec);
audioSupported = audioStream == null || profile.SupportsAudioCodec(audioStream.Codec);
if (videoSupported && audioSupported)
{
@@ -447,18 +447,17 @@ namespace MediaBrowser.Model.Dlna
}
}
var list = new List<TranscodeReason>();
if (!containerSupported)
{
reasons |= TranscodeReason.ContainerNotSupported;
}
if (videoStream != null && !videoSupported)
if (!videoSupported)
{
reasons |= TranscodeReason.VideoCodecNotSupported;
}
if (audioStream != null && !audioSupported)
if (!audioSupported)
{
reasons |= TranscodeReason.AudioCodecNotSupported;
}
@@ -590,21 +589,19 @@ namespace MediaBrowser.Model.Dlna
}
// Collect candidate audio streams
IEnumerable<MediaStream> candidateAudioStreams = audioStream == null ? Array.Empty<MediaStream>() : new[] { audioStream };
ICollection<MediaStream> candidateAudioStreams = audioStream == null ? Array.Empty<MediaStream>() : new[] { audioStream };
if (!options.AudioStreamIndex.HasValue || options.AudioStreamIndex < 0)
{
if (audioStream?.IsDefault == true)
{
candidateAudioStreams = item.MediaStreams.Where(stream => stream.Type == MediaStreamType.Audio && stream.IsDefault);
candidateAudioStreams = item.MediaStreams.Where(stream => stream.Type == MediaStreamType.Audio && stream.IsDefault).ToArray();
}
else
{
candidateAudioStreams = item.MediaStreams.Where(stream => stream.Type == MediaStreamType.Audio && stream.Language == audioStream?.Language);
candidateAudioStreams = item.MediaStreams.Where(stream => stream.Type == MediaStreamType.Audio && stream.Language == audioStream?.Language).ToArray();
}
}
candidateAudioStreams = candidateAudioStreams.ToArray();
var videoStream = item.VideoStream;
var directPlayBitrateEligibility = IsBitrateEligibleForDirectPlayback(item, options.GetMaxBitrate(false) ?? 0, options, PlayMethod.DirectPlay);
@@ -1060,7 +1057,7 @@ namespace MediaBrowser.Model.Dlna
MediaSourceInfo mediaSource,
MediaStream videoStream,
MediaStream audioStream,
IEnumerable<MediaStream> candidateAudioStreams,
ICollection<MediaStream> candidateAudioStreams,
MediaStream subtitleStream,
bool isEligibleForDirectPlay,
bool isEligibleForDirectStream)
@@ -1182,14 +1179,18 @@ namespace MediaBrowser.Model.Dlna
}
// Check audio codec
var selectedAudioStream = candidateAudioStreams.FirstOrDefault(audioStream => directPlayProfile.SupportsAudioCodec(audioStream.Codec));
if (selectedAudioStream == null)
MediaStream selectedAudioStream = null;
if (candidateAudioStreams.Any())
{
directPlayProfileReasons |= TranscodeReason.AudioCodecNotSupported;
}
else
{
audioCodecProfileReasons = audioStreamMatches.GetValueOrDefault(selectedAudioStream);
selectedAudioStream = candidateAudioStreams.FirstOrDefault(audioStream => directPlayProfile.SupportsAudioCodec(audioStream.Codec));
if (selectedAudioStream == null)
{
directPlayProfileReasons |= TranscodeReason.AudioCodecNotSupported;
}
else
{
audioCodecProfileReasons = audioStreamMatches.GetValueOrDefault(selectedAudioStream);
}
}
var failureReasons = directPlayProfileReasons | containerProfileReasons | subtitleProfileReasons;

View File

@@ -8,7 +8,7 @@
<PropertyGroup>
<Authors>Jellyfin Contributors</Authors>
<PackageId>Jellyfin.Model</PackageId>
<VersionPrefix>10.8.5</VersionPrefix>
<VersionPrefix>10.8.8</VersionPrefix>
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
</PropertyGroup>

View File

@@ -408,10 +408,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
}
}
if (isEnglishRequested)
{
item.Overview = result.Plot;
}
item.Overview = result.Plot;
if (!Plugin.Instance.Configuration.CastAndCrew)
{

View File

@@ -1,4 +1,4 @@
using System.Reflection;
[assembly: AssemblyVersion("10.8.5")]
[assembly: AssemblyFileVersion("10.8.5")]
[assembly: AssemblyVersion("10.8.8")]
[assembly: AssemblyFileVersion("10.8.8")]

View File

@@ -1,7 +1,7 @@
---
# We just wrap `build` so this is really it
name: "jellyfin"
version: "10.8.5"
version: "10.8.8"
packages:
- debian.amd64
- debian.arm64

18
debian/changelog vendored
View File

@@ -1,3 +1,21 @@
jellyfin-server (10.8.8-1) unstable; urgency=medium
* New upstream version 10.8.8; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.8.8
-- Jellyfin Packaging Team <packaging@jellyfin.org> Tue, 29 Nov 2022 13:42:47 -0500
jellyfin-server (10.8.7-1) unstable; urgency=medium
* New upstream version 10.8.7; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.8.7
-- Jellyfin Packaging Team <packaging@jellyfin.org> Mon, 31 Oct 2022 23:07:06 -0400
jellyfin-server (10.8.6-1) unstable; urgency=medium
* New upstream version 10.8.6; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.8.6
-- Jellyfin Packaging Team <packaging@jellyfin.org> Fri, 28 Oct 2022 22:41:01 -0400
jellyfin-server (10.8.5-1) unstable; urgency=medium
* New upstream version 10.8.5; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.8.5

View File

@@ -5,7 +5,7 @@ Homepage: https://jellyfin.org
Standards-Version: 3.9.2
Package: jellyfin
Version: 10.8.5
Version: 10.8.8
Maintainer: Jellyfin Packaging Team <packaging@jellyfin.org>
Depends: jellyfin-server, jellyfin-web
Description: Provides the Jellyfin Free Software Media System

View File

@@ -7,7 +7,7 @@
%endif
Name: jellyfin
Version: 10.8.5
Version: 10.8.8
Release: 1%{?dist}
Summary: The Free Software Media System
License: GPLv2
@@ -176,6 +176,12 @@ fi
%systemd_postun_with_restart jellyfin.service
%changelog
* Tue Nov 29 2022 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.8.8; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.8.8
* Mon Oct 31 2022 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.8.7; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.8.7
* Fri Oct 28 2022 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.8.6; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.8.6
* Sat Sep 24 2022 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.8.5; release changelog at https://github.com/jellyfin/jellyfin/releases/tag/v10.8.5
* Sat Aug 13 2022 Jellyfin Packaging Team <packaging@jellyfin.org>

View File

@@ -13,7 +13,7 @@
<PropertyGroup>
<Authors>Jellyfin Contributors</Authors>
<PackageId>Jellyfin.Extensions</PackageId>
<VersionPrefix>10.8.5</VersionPrefix>
<VersionPrefix>10.8.8</VersionPrefix>
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
</PropertyGroup>

View File

@@ -11,7 +11,7 @@ namespace Jellyfin.MediaEncoding.Keyframes.FfProbe;
/// </summary>
public static class FfProbeKeyframeExtractor
{
private const string DefaultArguments = "-v error -skip_frame nokey -show_entries format=duration -show_entries stream=duration -show_entries packet=pts_time,flags -select_streams v -of csv \"{0}\"";
private const string DefaultArguments = "-fflags +genpts -v error -skip_frame nokey -show_entries format=duration -show_entries stream=duration -show_entries packet=pts_time,flags -select_streams v -of csv \"{0}\"";
/// <summary>
/// Extracts the keyframes using the ffprobe executable at the specified path.
@@ -38,9 +38,28 @@ public static class FfProbeKeyframeExtractor
EnableRaisingEvents = true
};
process.Start();
try
{
process.Start();
return ParseStream(process.StandardOutput);
return ParseStream(process.StandardOutput);
}
catch (Exception)
{
try
{
if (!process.HasExited)
{
process.Kill();
}
}
catch
{
// We do not care if this fails
}
throw;
}
}
internal static KeyframeData ParseStream(StreamReader reader)
@@ -62,12 +81,17 @@ public static class FfProbeKeyframeExtractor
var rest = line[(firstComma + 1)..];
if (lineType.Equals("packet", StringComparison.OrdinalIgnoreCase))
{
if (rest.EndsWith(",K_"))
// Split time and flags from the packet line. Example line: packet,7169.079000,K_
var secondComma = rest.IndexOf(',');
var ptsTime = rest[..secondComma];
var flags = rest[(secondComma + 1)..];
if (flags.StartsWith("K_"))
{
// Trim the flags from the packet line. Example line: packet,7169.079000,K_
var keyframe = double.Parse(rest[..^3], NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture);
// Have to manually convert to ticks to avoid rounding errors as TimeSpan is only precise down to 1 ms when converting double.
keyframes.Add(Convert.ToInt64(keyframe * TimeSpan.TicksPerSecond));
if (double.TryParse(ptsTime, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var keyframe))
{
// Have to manually convert to ticks to avoid rounding errors as TimeSpan is only precise down to 1 ms when converting double.
keyframes.Add(Convert.ToInt64(keyframe * TimeSpan.TicksPerSecond));
}
}
}
else if (lineType.Equals("stream", StringComparison.OrdinalIgnoreCase))