aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci-codeql-analysis.yml6
-rw-r--r--.github/workflows/ci-openapi.yml8
-rw-r--r--.github/workflows/ci-tests.yml12
-rw-r--r--.github/workflows/issue-stale.yml2
-rw-r--r--.github/workflows/pull-request-stale.yaml2
-rw-r--r--Emby.Server.Implementations/Library/UserDataManager.cs47
-rw-r--r--Emby.Server.Implementations/Localization/Core/ab.json1
-rw-r--r--Emby.Server.Implementations/Localization/Core/fil.json3
-rw-r--r--Emby.Server.Implementations/Localization/Core/nb.json4
-rw-r--r--Emby.Server.Implementations/Localization/Core/tr.json2
-rw-r--r--Jellyfin.Api/Controllers/ItemsController.cs66
-rw-r--r--MediaBrowser.Controller/Library/IUserDataManager.cs9
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs26
-rw-r--r--MediaBrowser.Model/Dto/UpdateUserItemDataDto.cs76
-rw-r--r--MediaBrowser.Model/Entities/UserDataSaveReason.cs7
15 files changed, 235 insertions, 36 deletions
diff --git a/.github/workflows/ci-codeql-analysis.yml b/.github/workflows/ci-codeql-analysis.yml
index b52596645..89f9c59d7 100644
--- a/.github/workflows/ci-codeql-analysis.yml
+++ b/.github/workflows/ci-codeql-analysis.yml
@@ -27,11 +27,11 @@ jobs:
dotnet-version: '8.0.x'
- name: Initialize CodeQL
- uses: github/codeql-action/init@407ffafae6a767df3e0230c3df91b6443ae8df75 # v2.22.8
+ uses: github/codeql-action/init@b374143c1149a9115d881581d29b8390bbcbb59c # v3.22.11
with:
languages: ${{ matrix.language }}
queries: +security-extended
- name: Autobuild
- uses: github/codeql-action/autobuild@407ffafae6a767df3e0230c3df91b6443ae8df75 # v2.22.8
+ uses: github/codeql-action/autobuild@b374143c1149a9115d881581d29b8390bbcbb59c # v3.22.11
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@407ffafae6a767df3e0230c3df91b6443ae8df75 # v2.22.8
+ uses: github/codeql-action/analyze@b374143c1149a9115d881581d29b8390bbcbb59c # v3.22.11
diff --git a/.github/workflows/ci-openapi.yml b/.github/workflows/ci-openapi.yml
index 7d6667794..5ff9820cb 100644
--- a/.github/workflows/ci-openapi.yml
+++ b/.github/workflows/ci-openapi.yml
@@ -25,7 +25,7 @@ jobs:
- name: Generate openapi.json
run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests"
- name: Upload openapi.json
- uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: openapi-head
retention-days: 14
@@ -59,7 +59,7 @@ jobs:
- name: Generate openapi.json
run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests"
- name: Upload openapi.json
- uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
with:
name: openapi-base
retention-days: 14
@@ -78,12 +78,12 @@ jobs:
- openapi-base
steps:
- name: Download openapi-head
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
+ uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0
with:
name: openapi-head
path: openapi-head
- name: Download openapi-base
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
+ uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0
with:
name: openapi-base
path: openapi-base
diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml
index 5a0125f5f..0dacbc5c6 100644
--- a/.github/workflows/ci-tests.yml
+++ b/.github/workflows/ci-tests.yml
@@ -19,9 +19,9 @@ jobs:
runs-on: "${{ matrix.os }}"
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- - uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4
+ - uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0
with:
dotnet-version: ${{ env.SDK_VERSION }}
@@ -34,7 +34,7 @@ jobs:
--verbosity minimal
- name: Merge code coverage results
- uses: danielpalme/ReportGenerator-GitHub-Action@4d510cbed8a05af5aefea46c7fd6e05b95844c89 # 5
+ uses: danielpalme/ReportGenerator-GitHub-Action@4d510cbed8a05af5aefea46c7fd6e05b95844c89 # 5.2.0
with:
reports: "**/coverage.cobertura.xml"
targetdir: "merged/"
@@ -42,9 +42,3 @@ jobs:
# TODO - which action / tool to use to publish code coverage results?
# - name: Publish code coverage results
-
- - name: Publish OpenAPI Artifact
- uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3
- with:
- name: "OpenAPI Spec"
- path: "tests/Jellyfin.Server.Integration.Tests/bin/Release/net*/openapi.json"
diff --git a/.github/workflows/issue-stale.yml b/.github/workflows/issue-stale.yml
index 926a7fbfb..5a1ca9f7a 100644
--- a/.github/workflows/issue-stale.yml
+++ b/.github/workflows/issue-stale.yml
@@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
if: ${{ contains(github.repository, 'jellyfin/') }}
steps:
- - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 # v8.0.0
+ - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0
with:
repo-token: ${{ secrets.JF_BOT_TOKEN }}
ascending: true
diff --git a/.github/workflows/pull-request-stale.yaml b/.github/workflows/pull-request-stale.yaml
index de093a988..d01b3f4a1 100644
--- a/.github/workflows/pull-request-stale.yaml
+++ b/.github/workflows/pull-request-stale.yaml
@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
if: ${{ contains(github.repository, 'jellyfin/') }}
steps:
- - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 # v8.0.0
+ - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0
with:
repo-token: ${{ secrets.JF_BOT_TOKEN }}
ascending: true
diff --git a/Emby.Server.Implementations/Library/UserDataManager.cs b/Emby.Server.Implementations/Library/UserDataManager.cs
index a0a90b129..8beeb8041 100644
--- a/Emby.Server.Implementations/Library/UserDataManager.cs
+++ b/Emby.Server.Implementations/Library/UserDataManager.cs
@@ -81,6 +81,53 @@ namespace Emby.Server.Implementations.Library
});
}
+ public void SaveUserData(User user, BaseItem item, UpdateUserItemDataDto userDataDto, UserDataSaveReason reason)
+ {
+ ArgumentNullException.ThrowIfNull(user);
+ ArgumentNullException.ThrowIfNull(item);
+ ArgumentNullException.ThrowIfNull(reason);
+ ArgumentNullException.ThrowIfNull(userDataDto);
+
+ var userData = GetUserData(user, item);
+
+ if (userDataDto.PlaybackPositionTicks.HasValue)
+ {
+ userData.PlaybackPositionTicks = userDataDto.PlaybackPositionTicks.Value;
+ }
+
+ if (userDataDto.PlayCount.HasValue)
+ {
+ userData.PlayCount = userDataDto.PlayCount.Value;
+ }
+
+ if (userDataDto.IsFavorite.HasValue)
+ {
+ userData.IsFavorite = userDataDto.IsFavorite.Value;
+ }
+
+ if (userDataDto.Likes.HasValue)
+ {
+ userData.Likes = userDataDto.Likes.Value;
+ }
+
+ if (userDataDto.Played.HasValue)
+ {
+ userData.Played = userDataDto.Played.Value;
+ }
+
+ if (userDataDto.LastPlayedDate.HasValue)
+ {
+ userData.LastPlayedDate = userDataDto.LastPlayedDate.Value;
+ }
+
+ if (userDataDto.Rating.HasValue)
+ {
+ userData.Rating = userDataDto.Rating.Value;
+ }
+
+ SaveUserData(user, item, userData, reason, CancellationToken.None);
+ }
+
/// <summary>
/// Save the provided user data for the given user. Batch operation. Does not fire any events or update the cache.
/// </summary>
diff --git a/Emby.Server.Implementations/Localization/Core/ab.json b/Emby.Server.Implementations/Localization/Core/ab.json
new file mode 100644
index 000000000..0967ef424
--- /dev/null
+++ b/Emby.Server.Implementations/Localization/Core/ab.json
@@ -0,0 +1 @@
+{}
diff --git a/Emby.Server.Implementations/Localization/Core/fil.json b/Emby.Server.Implementations/Localization/Core/fil.json
index 88a4a358e..55ee1abaa 100644
--- a/Emby.Server.Implementations/Localization/Core/fil.json
+++ b/Emby.Server.Implementations/Localization/Core/fil.json
@@ -124,5 +124,6 @@
"TaskKeyframeExtractor": "Tagabunot ng Keyframe",
"TaskKeyframeExtractorDescription": "Nagbubunot ng keyframe mula sa mga bidyo upang makabuo ng mas tumpak na HLS playlist. Maaaring matagal ito gawin.",
"External": "External",
- "TaskRefreshTrickplayImages": "Gumawa ng Trickplay na Imahe"
+ "TaskRefreshTrickplayImages": "Gumawa ng Trickplay na Imahe",
+ "TaskRefreshTrickplayImagesDescription": "Nanggagawa ng mga trickplay prebiyu para sa mga bidyo sa pinaganang mga aklatan."
}
diff --git a/Emby.Server.Implementations/Localization/Core/nb.json b/Emby.Server.Implementations/Localization/Core/nb.json
index 5c7dec7ef..0362c2417 100644
--- a/Emby.Server.Implementations/Localization/Core/nb.json
+++ b/Emby.Server.Implementations/Localization/Core/nb.json
@@ -124,5 +124,7 @@
"TaskKeyframeExtractorDescription": "Trekker ut nøkkelbilder fra videofiler for å skape mere nøyaktige HLS-spillelister. Denne oppgaven kan ta lang tid.",
"TaskKeyframeExtractor": "Nøkkelbilde-uttrekker",
"External": "Ekstern",
- "HearingImpaired": "Hørselshemmet"
+ "HearingImpaired": "Hørselshemmet",
+ "TaskRefreshTrickplayImages": "Generer Trickplay bilder",
+ "TaskRefreshTrickplayImagesDescription": "Oppretter trickplay-forhåndsvisninger for videoer i aktiverte biblioteker."
}
diff --git a/Emby.Server.Implementations/Localization/Core/tr.json b/Emby.Server.Implementations/Localization/Core/tr.json
index a4877f4b5..6a04115fa 100644
--- a/Emby.Server.Implementations/Localization/Core/tr.json
+++ b/Emby.Server.Implementations/Localization/Core/tr.json
@@ -89,7 +89,7 @@
"UserPolicyUpdatedWithName": "{0} için kullanıcı politikası güncellendi",
"UserStartedPlayingItemWithValues": "{0}, {2} cihazında {1} izliyor",
"UserStoppedPlayingItemWithValues": "{0}, {2} cihazında {1} izlemeyi bitirdi",
- "ValueHasBeenAddedToLibrary": "Medya kütüphanenize {0} eklendi",
+ "ValueHasBeenAddedToLibrary": "{0} medya kütüphanenize eklendi",
"ValueSpecialEpisodeName": "Özel - {0}",
"VersionNumber": "Sürüm {0}",
"TaskCleanCache": "Önbellek Dizinini Temizle",
diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs
index 5204d1822..a1fc8e11b 100644
--- a/Jellyfin.Api/Controllers/ItemsController.cs
+++ b/Jellyfin.Api/Controllers/ItemsController.cs
@@ -34,6 +34,7 @@ public class ItemsController : BaseJellyfinApiController
private readonly IDtoService _dtoService;
private readonly ILogger<ItemsController> _logger;
private readonly ISessionManager _sessionManager;
+ private readonly IUserDataManager _userDataRepository;
/// <summary>
/// Initializes a new instance of the <see cref="ItemsController"/> class.
@@ -44,13 +45,15 @@ public class ItemsController : BaseJellyfinApiController
/// <param name="dtoService">Instance of the <see cref="IDtoService"/> interface.</param>
/// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
/// <param name="sessionManager">Instance of the <see cref="ISessionManager"/> interface.</param>
+ /// <param name="userDataRepository">Instance of the <see cref="IUserDataManager"/> interface.</param>
public ItemsController(
IUserManager userManager,
ILibraryManager libraryManager,
ILocalizationManager localization,
IDtoService dtoService,
ILogger<ItemsController> logger,
- ISessionManager sessionManager)
+ ISessionManager sessionManager,
+ IUserDataManager userDataRepository)
{
_userManager = userManager;
_libraryManager = libraryManager;
@@ -58,6 +61,7 @@ public class ItemsController : BaseJellyfinApiController
_dtoService = dtoService;
_logger = logger;
_sessionManager = sessionManager;
+ _userDataRepository = userDataRepository;
}
/// <summary>
@@ -881,4 +885,64 @@ public class ItemsController : BaseJellyfinApiController
itemsResult.TotalRecordCount,
returnItems);
}
+
+ /// <summary>
+ /// Get Item User Data.
+ /// </summary>
+ /// <param name="userId">The user id.</param>
+ /// <param name="itemId">The item id.</param>
+ /// <response code="200">return item user data.</response>
+ /// <response code="404">Item is not found.</response>
+ /// <returns>Return <see cref="UserItemDataDto"/>.</returns>
+ [HttpGet("Users/{userId}/Items/{itemId}/UserData")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status404NotFound)]
+ public ActionResult<UserItemDataDto> GetItemUserData(
+ [FromRoute, Required] Guid userId,
+ [FromRoute, Required] Guid itemId)
+ {
+ if (!RequestHelpers.AssertCanUpdateUser(_userManager, User, userId, true))
+ {
+ return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to view this item user data.");
+ }
+
+ var user = _userManager.GetUserById(userId) ?? throw new ResourceNotFoundException();
+ var item = _libraryManager.GetItemById(itemId);
+
+ return (item == null) ? NotFound() : _userDataRepository.GetUserDataDto(item, user);
+ }
+
+ /// <summary>
+ /// Update Item User Data.
+ /// </summary>
+ /// <param name="userId">The user id.</param>
+ /// <param name="itemId">The item id.</param>
+ /// <param name="userDataDto">New user data object.</param>
+ /// <response code="200">return updated user item data.</response>
+ /// <response code="404">Item is not found.</response>
+ /// <returns>Return <see cref="UserItemDataDto"/>.</returns>
+ [HttpPost("Users/{userId}/Items/{itemId}/UserData")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status404NotFound)]
+ public ActionResult<UserItemDataDto> UpdateItemUserData(
+ [FromRoute, Required] Guid userId,
+ [FromRoute, Required] Guid itemId,
+ [FromBody, Required] UpdateUserItemDataDto userDataDto)
+ {
+ if (!RequestHelpers.AssertCanUpdateUser(_userManager, User, userId, true))
+ {
+ return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update this item user data.");
+ }
+
+ var user = _userManager.GetUserById(userId) ?? throw new ResourceNotFoundException();
+ var item = _libraryManager.GetItemById(itemId);
+ if (item == null)
+ {
+ return NotFound();
+ }
+
+ _userDataRepository.SaveUserData(user, item, userDataDto, UserDataSaveReason.UpdateUserData);
+
+ return _userDataRepository.GetUserDataDto(item, user);
+ }
}
diff --git a/MediaBrowser.Controller/Library/IUserDataManager.cs b/MediaBrowser.Controller/Library/IUserDataManager.cs
index 034c40591..43cccfc65 100644
--- a/MediaBrowser.Controller/Library/IUserDataManager.cs
+++ b/MediaBrowser.Controller/Library/IUserDataManager.cs
@@ -35,6 +35,15 @@ namespace MediaBrowser.Controller.Library
void SaveUserData(User user, BaseItem item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken);
+ /// <summary>
+ /// Save the provided user data for the given user.
+ /// </summary>
+ /// <param name="user">The user.</param>
+ /// <param name="item">The item.</param>
+ /// <param name="userDataDto">The reason for updating the user data.</param>
+ /// <param name="reason">The reason.</param>
+ void SaveUserData(User user, BaseItem item, UpdateUserItemDataDto userDataDto, UserDataSaveReason reason);
+
UserItemData GetUserData(User user, BaseItem item);
UserItemData GetUserData(Guid userId, BaseItem item);
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index 46fd1ae47..6a16d421c 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -3343,7 +3343,7 @@ namespace MediaBrowser.Controller.MediaEncoding
// [0:s]scale=s=1280x720
var subSwScaleFilter = GetCustomSwScaleFilter(inW, inH, reqW, reqH, reqMaxW, reqMaxH);
subFilters.Add(subSwScaleFilter);
- overlayFilters.Add("overlay=eof_action=endall:shortest=1:repeatlast=0");
+ overlayFilters.Add("overlay=eof_action=pass:repeatlast=0");
}
return (mainFilters, subFilters, overlayFilters);
@@ -3520,7 +3520,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
subFilters.Add("hwupload=derive_device=cuda");
- overlayFilters.Add("overlay_cuda=eof_action=endall:shortest=1:repeatlast=0");
+ overlayFilters.Add("overlay_cuda=eof_action=pass:repeatlast=0");
}
}
else
@@ -3529,7 +3529,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
var subSwScaleFilter = GetCustomSwScaleFilter(inW, inH, reqW, reqH, reqMaxW, reqMaxH);
subFilters.Add(subSwScaleFilter);
- overlayFilters.Add("overlay=eof_action=endall:shortest=1:repeatlast=0");
+ overlayFilters.Add("overlay=eof_action=pass:repeatlast=0");
}
}
@@ -3718,7 +3718,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
subFilters.Add("hwupload=derive_device=opencl");
- overlayFilters.Add("overlay_opencl=eof_action=endall:shortest=1:repeatlast=0");
+ overlayFilters.Add("overlay_opencl=eof_action=pass:repeatlast=0");
overlayFilters.Add("hwmap=derive_device=d3d11va:reverse=1");
overlayFilters.Add("format=d3d11");
}
@@ -3729,7 +3729,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
var subSwScaleFilter = GetCustomSwScaleFilter(inW, inH, reqW, reqH, reqMaxW, reqMaxH);
subFilters.Add(subSwScaleFilter);
- overlayFilters.Add("overlay=eof_action=endall:shortest=1:repeatlast=0");
+ overlayFilters.Add("overlay=eof_action=pass:repeatlast=0");
}
}
@@ -3964,7 +3964,7 @@ namespace MediaBrowser.Controller.MediaEncoding
: string.Empty;
var overlayQsvFilter = string.Format(
CultureInfo.InvariantCulture,
- "overlay_qsv=eof_action=endall:shortest=1:repeatlast=0{0}",
+ "overlay_qsv=eof_action=pass:repeatlast=0{0}",
overlaySize);
overlayFilters.Add(overlayQsvFilter);
}
@@ -3975,7 +3975,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
var subSwScaleFilter = GetCustomSwScaleFilter(inW, inH, reqW, reqH, reqMaxW, reqMaxH);
subFilters.Add(subSwScaleFilter);
- overlayFilters.Add("overlay=eof_action=endall:shortest=1:repeatlast=0");
+ overlayFilters.Add("overlay=eof_action=pass:repeatlast=0");
}
}
@@ -4180,7 +4180,7 @@ namespace MediaBrowser.Controller.MediaEncoding
: string.Empty;
var overlayQsvFilter = string.Format(
CultureInfo.InvariantCulture,
- "overlay_qsv=eof_action=endall:shortest=1:repeatlast=0{0}",
+ "overlay_qsv=eof_action=pass:repeatlast=0{0}",
overlaySize);
overlayFilters.Add(overlayQsvFilter);
}
@@ -4191,7 +4191,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
var subSwScaleFilter = GetCustomSwScaleFilter(inW, inH, reqW, reqH, reqMaxW, reqMaxH);
subFilters.Add(subSwScaleFilter);
- overlayFilters.Add("overlay=eof_action=pass:shortest=1:repeatlast=0");
+ overlayFilters.Add("overlay=eof_action=pass:repeatlast=0");
}
}
@@ -4445,7 +4445,7 @@ namespace MediaBrowser.Controller.MediaEncoding
: string.Empty;
var overlayVaapiFilter = string.Format(
CultureInfo.InvariantCulture,
- "overlay_vaapi=eof_action=endall:shortest=1:repeatlast=0{0}",
+ "overlay_vaapi=eof_action=pass:repeatlast=0{0}",
overlaySize);
overlayFilters.Add(overlayVaapiFilter);
}
@@ -4456,7 +4456,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
var subSwScaleFilter = GetCustomSwScaleFilter(inW, inH, reqW, reqH, reqMaxW, reqMaxH);
subFilters.Add(subSwScaleFilter);
- overlayFilters.Add("overlay=eof_action=pass:shortest=1:repeatlast=0");
+ overlayFilters.Add("overlay=eof_action=pass:repeatlast=0");
if (isVaapiEncoder)
{
@@ -4616,7 +4616,7 @@ namespace MediaBrowser.Controller.MediaEncoding
subFilters.Add("hwupload=derive_device=vulkan");
subFilters.Add("format=vulkan");
- overlayFilters.Add("overlay_vulkan=eof_action=endall:shortest=1:repeatlast=0");
+ overlayFilters.Add("overlay_vulkan=eof_action=pass:repeatlast=0");
if (isSwEncoder)
{
@@ -4817,7 +4817,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
var subSwScaleFilter = GetCustomSwScaleFilter(inW, inH, reqW, reqH, reqMaxW, reqMaxH);
subFilters.Add(subSwScaleFilter);
- overlayFilters.Add("overlay=eof_action=pass:shortest=1:repeatlast=0");
+ overlayFilters.Add("overlay=eof_action=pass:repeatlast=0");
if (isVaapiEncoder)
{
diff --git a/MediaBrowser.Model/Dto/UpdateUserItemDataDto.cs b/MediaBrowser.Model/Dto/UpdateUserItemDataDto.cs
new file mode 100644
index 000000000..7bfedf973
--- /dev/null
+++ b/MediaBrowser.Model/Dto/UpdateUserItemDataDto.cs
@@ -0,0 +1,76 @@
+using System;
+
+namespace MediaBrowser.Model.Dto
+{
+ /// <summary>
+ /// This is used by the api to get information about a item user data.
+ /// </summary>
+ public class UpdateUserItemDataDto
+ {
+ /// <summary>
+ /// Gets or sets the rating.
+ /// </summary>
+ /// <value>The rating.</value>
+ public double? Rating { get; set; }
+
+ /// <summary>
+ /// Gets or sets the played percentage.
+ /// </summary>
+ /// <value>The played percentage.</value>
+ public double? PlayedPercentage { get; set; }
+
+ /// <summary>
+ /// Gets or sets the unplayed item count.
+ /// </summary>
+ /// <value>The unplayed item count.</value>
+ public int? UnplayedItemCount { get; set; }
+
+ /// <summary>
+ /// Gets or sets the playback position ticks.
+ /// </summary>
+ /// <value>The playback position ticks.</value>
+ public long? PlaybackPositionTicks { get; set; }
+
+ /// <summary>
+ /// Gets or sets the play count.
+ /// </summary>
+ /// <value>The play count.</value>
+ public int? PlayCount { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance is favorite.
+ /// </summary>
+ /// <value><c>true</c> if this instance is favorite; otherwise, <c>false</c>.</value>
+ public bool? IsFavorite { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this <see cref="UpdateUserItemDataDto" /> is likes.
+ /// </summary>
+ /// <value><c>null</c> if [likes] contains no value, <c>true</c> if [likes]; otherwise, <c>false</c>.</value>
+ public bool? Likes { get; set; }
+
+ /// <summary>
+ /// Gets or sets the last played date.
+ /// </summary>
+ /// <value>The last played date.</value>
+ public DateTime? LastPlayedDate { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this <see cref="UserItemDataDto" /> is played.
+ /// </summary>
+ /// <value><c>true</c> if played; otherwise, <c>false</c>.</value>
+ public bool? Played { get; set; }
+
+ /// <summary>
+ /// Gets or sets the key.
+ /// </summary>
+ /// <value>The key.</value>
+ public string? Key { get; set; }
+
+ /// <summary>
+ /// Gets or sets the item identifier.
+ /// </summary>
+ /// <value>The item identifier.</value>
+ public string? ItemId { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Entities/UserDataSaveReason.cs b/MediaBrowser.Model/Entities/UserDataSaveReason.cs
index 20404e6f4..b8e73a98c 100644
--- a/MediaBrowser.Model/Entities/UserDataSaveReason.cs
+++ b/MediaBrowser.Model/Entities/UserDataSaveReason.cs
@@ -33,6 +33,11 @@ namespace MediaBrowser.Model.Entities
/// <summary>
/// The import.
/// </summary>
- Import = 6
+ Import = 6,
+
+ /// <summary>
+ /// API call updated item user data.
+ /// </summary>
+ UpdateUserData = 7,
}
}