Compare commits

..

1177 Commits

Author SHA1 Message Date
Joshua Boniface
b344771f8a Bump version to 10.8.4 2022-08-13 21:51:50 -04:00
Joshua Boniface
3ff78b687d Revert "Restore "Merge pull request #8087 from cvium/generic_subtitleparser""
This reverts commit 5bcab0f0f8.
2022-08-13 21:51:23 -04:00
Joshua M. Boniface
d260f30810 Merge pull request #8257 from joshuaboniface/fix-dotnetargs 2022-08-13 21:45:57 -04:00
Cody Robibero
7ffdde9a0b Merge pull request #8212 from SenorSmartyPants/Add384ResolutionText
Add resolution text for 384 sized video
2022-08-13 18:34:17 -07:00
Joshua M. Boniface
e14194bfe2 Fix remaining instances in root package configs 2022-08-13 21:23:01 -04:00
Joshua M. Boniface
3bf1a7e445 Use separate args for dotnet publish commands
Fixes #8245
2022-08-13 21:18:28 -04:00
Bond-009
1faee43b11 Merge pull request #8182 from Shadowghost/fix-sub-characterset 2022-08-12 19:47:42 +02:00
Joshua M. Boniface
31f9938e3a Merge pull request #8234 from crobibero/dotnet-6.0.8 2022-08-11 22:46:31 -04:00
Cody Robibero
ae9fd4ab35 update remaining dependencies 2022-08-09 17:57:51 -06:00
Cody Robibero
71ed7f7676 update to dotnet 6.0.8 2022-08-09 17:57:21 -06:00
SenorSmartyPants
3b6e003029 Add 404p Resolution Text 2022-08-09 12:09:29 -05:00
Claus Vium
9357d610b1 Merge pull request #8209 from Shadowghost/fix-playback
Fix series query including missing episodes when it should not
2022-08-08 22:57:56 +02:00
Joshua M. Boniface
1d4755894e Merge pull request #8219 from nyanmisaka/fedora-hardening
Move Fedora service hardening options to override config
2022-08-07 21:10:03 -04:00
nyanmisaka
2320f06666 Move Fedora service hardening options to override config 2022-08-07 18:01:26 +08:00
SenorSmartyPants
30f6263806 Add resolution text for 384 sized video 2022-08-05 23:32:22 -05:00
Shadowghost
a9249393e1 Fix series query including missing episodes when it should not 2022-08-05 19:38:33 +02:00
Shadowghost
f49a051a5f Respect timestamps when extracting subtitles 2022-08-02 13:21:10 +02:00
Joshua Boniface
5bcab0f0f8 Restore "Merge pull request #8087 from cvium/generic_subtitleparser"
After tagging v10.8.3, this can be restored to how it was and corrected
as required in a separate PR.

This reverts commit 494ed7e4d2.
2022-08-01 20:40:54 -04:00
Joshua Boniface
c5a2ff8ac4 Bump version to 10.8.3 2022-08-01 20:20:00 -04:00
Joshua Boniface
494ed7e4d2 Revert "Merge pull request #8087 from cvium/generic_subtitleparser"
This PR was causing breakage in installs - ref #8198

This reverts commit 7323ccfc23, reversing
changes made to 77a007a24d.
2022-08-01 20:19:16 -04:00
Joshua M. Boniface
dd97e6bc45 Bump version to 10.8.2 2022-08-01 14:27:30 -04:00
Bond-009
7323ccfc23 Merge pull request #8087 from cvium/generic_subtitleparser 2022-08-01 19:24:45 +02:00
Claus Vium
d258a87fda Update MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs
Co-authored-by: Bond-009 <bond.009@outlook.com>
2022-08-01 18:30:32 +02:00
Bond-009
77a007a24d Merge pull request #8191 from cvium/remove_not_missing_episodes 2022-08-01 18:19:13 +02:00
cvium
a380153f92 remove redundant null check 2022-07-30 21:54:03 +02:00
cvium
56c81696d3 fix: remove Virtual episodes when their physical counterpart exists 2022-07-30 21:50:53 +02:00
Bond-009
7297431f23 Merge pull request #8174 from nyanmisaka/fixes
Disable auto inserted SW scaler for HW decoders
2022-07-30 15:00:41 +02:00
Claus Vium
f2c7bccb89 Update MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs
Co-authored-by: Bond-009 <bond.009@outlook.com>
2022-07-30 14:59:28 +02:00
Claus Vium
b0b4068ddf Update MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs
Co-authored-by: Bond-009 <bond.009@outlook.com>
2022-07-30 14:59:00 +02:00
Shadowghost
feb035b9e0 Extract external subs from container before determining character set 2022-07-27 10:08:53 +02:00
nyanmisaka
82f362abd9 Fix DV P5 MKV remuxing 2022-07-26 23:06:22 +08:00
nyanmisaka
04b73cace6 Disable auto inserted SW scaler for HW decoders in case of changed resolution 2022-07-26 23:06:11 +08:00
cvium
3b69f38a1f fix tests 2022-07-25 09:51:03 +02:00
cvium
126da94020 use reflection to get all subtitle formats without causing libse configuration loading 2022-07-25 09:47:21 +02:00
Bond-009
f9dffa767f Merge pull request #8167 from crobibero/plugin-library-scan 2022-07-24 22:59:21 +02:00
Claus Vium
444b0ea310 Merge pull request #8163 from daullmer/cover-m3u
Don't refresh playlists on album refresh
2022-07-24 19:38:54 +02:00
Claus Vium
484427b4aa Merge pull request #8127 from jellyfin/wa-i915-hang 2022-07-24 19:18:14 +02:00
David Ullmer
c3f0649fde Update MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2022-07-24 19:17:21 +02:00
Nyanmisaka
e877486056 Apply suggestions from code review
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2022-07-25 00:56:40 +08:00
Claus Vium
9854751137 Merge pull request #8061 from jellyfin/fix-long-time-interop
Fix intel dx11-ocl interop taking too long to initialize on windows
2022-07-24 18:54:04 +02:00
Claus Vium
057e8ef240 Merge pull request #8166 from joseph39/people-query-fix-10.8.z
Bind @userid only when it's in the statement
2022-07-24 18:27:59 +02:00
Cody Robibero
205783f46f re-add library scan from library manager 2022-07-23 18:59:30 -06:00
Cody Robibero
b2fb96ffed Merge pull request #8152 from thornbill/fix-rtsp-over-tcp
Fix support for rtsp streams over tcp
2022-07-23 18:24:35 -06:00
Cody Robibero
ee22feb89a Merge pull request #7732 from LewkyB/fix-websockets-close-gracefully-on-shutdown 2022-07-23 18:24:12 -06:00
Joseph
ca5979cd77 Bind @userid only when it's in the statement
This commit fixes a case where SqliteItemRepository attempts to bind @userid even when such parameter may not appear in the query; fixes https://github.com/jellyfin/jellyfin/issues/8141
2022-07-23 16:06:36 -07:00
David Ullmer
d36f49589a Don't refresh playlists on album refresh 2022-07-23 13:51:07 +02:00
luke brown
70f37f0527 Merge branch 'release-10.8.z' of github.com:jellyfin/jellyfin into fix-websockets-close-gracefully-on-shutdown 2022-07-22 18:16:55 -05:00
Bill Thornton
dfe0aef530 Fix support for rtsp streams over tcp 2022-07-20 15:13:11 -04:00
Luke Brown
9e31d5a73f relocated Dispose 2022-07-19 21:49:17 -05:00
Luke Brown
f088ca5555 add Dispose in DisposeAsyncCore 2022-07-19 17:31:00 -05:00
Bond-009
2b46917dcf Merge pull request #8104 from Shadowghost/resolution-fix 2022-07-17 23:52:49 +02:00
nyanmisaka
7bae6eff95 Fix intel dx11-ocl interop taking too long to initialize on windows 2022-07-17 11:47:17 +08:00
Joshua M. Boniface
d0fd23bb4b Merge pull request #8115 from crobibero/dotnet-6.0.7
Update to dotnet 6.0.7
2022-07-16 15:39:11 -04:00
Shadowghost
d694a6c09a Add more MediaStream resolution tests, sort them by width 2022-07-16 10:16:33 +02:00
nyanmisaka
58f61ed118 Workaround for linux 5.18+ i915 hang at cost of performance 2022-07-16 15:18:49 +08:00
Cody Robibero
b9da0e7f83 Update remaining dependencies 2022-07-12 17:41:32 -06:00
Cody Robibero
7eaa0600e0 Update to dotnet 6.0.7 2022-07-12 17:41:22 -06:00
Bond-009
47c2c536e4 Merge pull request #8078 from Andy2244/fix-stream_copy 2022-07-13 00:33:00 +02:00
Bond-009
7ef9e95d75 Merge pull request #8092 from Andy2244/fix-audio_codec_bitrate 2022-07-13 00:29:09 +02:00
Shadowghost
f8ea4577ab Add resolution text output for more resolutions 2022-07-11 15:45:11 +02:00
Andy Walsh
72da42cb0a allow higher opus, vorbis transcode bitrates 2022-07-10 02:14:49 +02:00
cvium
dbfa0f3027 fix unsupported 2022-07-08 20:12:00 +02:00
cvium
78f437401b loop over all compatible SubtitleFormats 2022-07-08 20:11:00 +02:00
cvium
1db748399c feat: make subtitleeditparser generic 2022-07-08 19:44:15 +02:00
Andy Walsh
a41c67d16b fix copy&paste error for requestedRangeTypes preventing stream copy
- add >=0 check to subtitle index check
- fixes #8070, #7880
2022-07-08 13:56:09 +02:00
Bond-009
84a1674f39 Merge pull request #8013 from daullmer/parental_password_fix 2022-07-07 12:42:20 +02:00
David Ullmer
81e535fc62 Rollback changes in IUserManager 2022-07-04 19:19:46 +02:00
David Ullmer
f9d26ea1bc Use IsInRole 2022-07-04 19:08:40 +02:00
David Ullmer
5f3dbd8294 Allow administrator to always change password 2022-07-04 18:16:36 +02:00
Claus Vium
9cebdfdec0 Merge pull request #8038 from Shadowghost/secure-sudoers 2022-06-30 16:40:59 +02:00
Shadowghost
891ccd7bb2 Remove mount and unmount permissions for jellyfin group from sudoers 2022-06-30 14:57:16 +02:00
Joshua M. Boniface
54778d875d Bump version to 10.8.1 2022-06-26 21:00:05 -04:00
Joshua M. Boniface
39d185c7b1 Merge pull request #7964 from jellyfin/dovi-side-data 2022-06-26 20:55:36 -04:00
Joshua M. Boniface
a7d45b5d3a Merge pull request #7994 from nyanmisaka/fix-throttler 2022-06-26 20:53:03 -04:00
David Ullmer
7efa4e38c1 Fix password change during parental schedule 2022-06-26 14:06:40 +02:00
nyanmisaka
506ed6940b Detach TranscodingJob from StreamState 2022-06-26 16:01:46 +08:00
nyanmisaka
5dbe16d3e6 Re-enable throttler for HWA and Copy 2022-06-26 16:01:46 +08:00
nyanmisaka
4c178e9188 Remove 'using' from HLS/Progressive StreamState 2022-06-26 16:01:46 +08:00
nyanmisaka
50bc41d84d Add VideoDoViTitle to display DV compatibility 2022-06-25 18:43:32 +08:00
nyanmisaka
e931f5a32b Add tests 2022-06-25 18:43:32 +08:00
nyanmisaka
d2caed25fb Register DOVI side_data in db 2022-06-25 18:43:32 +08:00
nyanmisaka
3f37ef70e1 Add json parser for DOVI side_data 2022-06-25 18:43:32 +08:00
Claus Vium
d342b79218 Merge pull request #8001 from jellyfin/fix-yuvj420p-hwdec
Fix yuvj420p pixel format hardware decoding
2022-06-24 14:49:27 +02:00
nyanmisaka
c35fc382d4 Fix yuvj420p pixel format hardware decoding 2022-06-24 19:33:53 +08:00
Cody Robibero
cb6e6879e2 Merge pull request #7614 from mihawk90/fedora-spec-rework 2022-06-23 08:04:54 -06:00
Bond-009
a71b190142 Merge pull request #7988 from jellyfin/external-streams-exceptions 2022-06-23 15:45:55 +02:00
Bond-009
910df89cce Merge pull request #7975 from jellyfin/libva-driver-env 2022-06-23 15:33:14 +02:00
Bond-009
5f15339919 Merge pull request #7968 from jellyfin/fix-hwa-bluray 2022-06-23 15:32:35 +02:00
Joshua M. Boniface
56e7b323de Merge pull request #7984 from crobibero/dotnet-6.0.6
Upgrade to dotnet 6.0.6, update remaining dependencies
2022-06-23 09:13:35 -04:00
Cody Robibero
a3a751a4f5 Merge pull request #7985 from jellyfin/revert-7961-next_up_idk
Revert "refactor: use season number and episode number for NextUp ordering instead of SortName"
2022-06-21 06:05:26 -06:00
nyanmisaka
c85255a615 Log external streams exceptions 2022-06-21 19:59:23 +08:00
nyanmisaka
8ea8dcf128 Catch external streams exceptions 2022-06-21 19:56:32 +08:00
Cody Robibero
7884e7e829 Revert "refactor: use season number and episode number for NextUp ordering instead of SortName" 2022-06-20 08:55:19 -06:00
Cody Robibero
3478554249 Fix build 2022-06-20 08:54:46 -06:00
Cody Robibero
9898c10880 Update remaining dependencies 2022-06-20 08:52:30 -06:00
Cody Robibero
ec2ad4ec8c Upgrade to dotnet 6.0.6 2022-06-20 08:48:40 -06:00
Joshua M. Boniface
1ffc77b43d Merge pull request #7961 from cvium/next_up_idk
refactor: use season number and episode number for NextUp ordering instead of SortName
2022-06-20 09:58:27 -04:00
Joshua M. Boniface
ae79bbc34c Merge pull request #7960 from Shadowghost/subrip-encoder-fix 2022-06-20 09:57:57 -04:00
Joshua M. Boniface
52704e8dd0 Merge pull request #7955 from nyanmisaka/fix-ext 2022-06-20 09:57:43 -04:00
Joshua M. Boniface
294ab0757e Merge pull request #7887 from joshuaboniface/fix-restart.sh 2022-06-20 09:57:18 -04:00
nyanmisaka
bdd52df230 Override the VAAPI driver env if i965 device is known 2022-06-20 18:59:54 +08:00
Nyanmisaka
73117b079c Fix HWA decoders are not applied to BluRay folders
fixes #6834
2022-06-19 19:14:55 +08:00
Shadowghost
b60905f991 Add barebone ASS/SSA writers to SubtitleEncoder 2022-06-19 08:59:48 +02:00
Tarulia
6d5c697183 Add make in Fedora Docker install
Fedora 36 doesn't seem to ship make, so add it manually.
2022-06-18 22:35:36 +02:00
Shadowghost
24c56328f2 Add subrip to SubtitleFormat 2022-06-18 01:20:05 +02:00
cvium
ef037ad371 refactor: use season number and episode number for NextUp ordering instead of SortName 2022-06-18 00:07:54 +02:00
Shadowghost
a64e21f57a Fix subtitle encoder if subrip is requested 2022-06-17 23:17:23 +02:00
nyanmisaka
56e135f5e6 Apply suggestions from code review
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2022-06-18 01:50:08 +08:00
nyanmisaka
ae22d0b7a5 Fix output extension if user has no transcoding permission 2022-06-18 00:25:55 +08:00
Cody Robibero
b36543275f Merge pull request #7950 from nyanmisaka/brighter-vpp-tonemap 2022-06-17 10:01:37 -06:00
Cody Robibero
2c0c3eb3ee Merge pull request #7954 from cvium/fix_7953_dlna_url 2022-06-17 10:01:20 -06:00
Cody Robibero
f1d56aa5ce Merge pull request #7947 from nyanmisaka/video-range-condition 2022-06-17 10:01:06 -06:00
Nyanmisaka
0b6fbebf72 Apply suggestions from code review
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2022-06-17 16:49:16 +08:00
Claus Vium
db714f967e Merge pull request #7939 from 1337joe/track-selector-fix
Track selector fix
2022-06-17 10:23:53 +02:00
cvium
f020bd6f3b use ignore case for scheme comparison 2022-06-17 09:00:59 +02:00
cvium
3275f83c3b fix: use proper bind address for DLNA location url (#7953) 2022-06-17 08:57:59 +02:00
nyanmisaka
f7813803c2 Brighter VPP tone-mapping on Intel 2022-06-16 23:29:36 +08:00
nyanmisaka
477b922e4a Apply suggestions from code review
Co-authored-by: Cody Robibero <cody@robibe.ro>
2022-06-16 22:11:06 +08:00
nyanmisaka
be72001ff9 Add VideoRangeType to video conditions
This is used to distinguish whether the client supports specific VideoRangeType,
such as SDR, HDR10, HLG and DOVI. Usage is similar to Video Profile condition.
2022-06-16 21:32:54 +08:00
Cody Robibero
6749313249 Merge pull request #7940 from Shadowghost/fix-recommendations 2022-06-16 07:15:39 -06:00
Cody Robibero
4ebe70cf6a Merge pull request #7946 from cvium/svg 2022-06-16 07:14:56 -06:00
cvium
c4051ac16d fix release build 2022-06-16 12:31:50 +02:00
cvium
3491f0968b feat: partially handle SVG files and remove exceptions from blurhash and dimensions 2022-06-16 12:22:46 +02:00
Cody Robibero
fd4ffc6ba3 Merge pull request #7941 from jellyfin/fix-overflow 2022-06-15 15:27:07 -06:00
Tarulia
5912a49d1d Further cleanup of Fedora spec-file
* Replaced shell script used to start JF with a symlink, since it didn't
  do anything else.
* Sorted installs by category/path to make it easier to maintain the
  spec.
* Defined `%defattr` in file section so we don't need to set it on a
  by-file level. This also helps with the messed up default file
  permissions `dotnet publish` produces.
* Removed some duplicate attribute definitions in `%install` and
  `%files` sections. They are now all in the `%install` section because
  of `%defattr` being specified and overriding them otherwise.
2022-06-15 23:12:12 +02:00
Tarulia
f336647d57 Remove env-var after moving web-files on Fedora
* when running Jellyfin as a user from a terminal without passing
  arguments, it would not find the web-files. They were moved in the
  JF-web build for Fedora, so this env-var would point to an invalid
  location. By removing it, JF now checks the default location.
* fixes jellyfin/jellyfin-web#2059
2022-06-15 23:12:12 +02:00
Tarulia
9b805c9e83 Use Fedora 36 image in Fedora Docker builds
* fixes #7504
2022-06-15 23:11:47 +02:00
Tarulia
19ccf414ac Fedora build: Filter dependency to fix F36 build
* fixes #7471
* Filter for F36+ since we don't know when (if ever) this issue will be
  fixed (it's up to .NET SDK). If it's ever fixed we can adjust or
  remove this condition.
2022-06-15 23:09:26 +02:00
Tarulia
0504ed9fe6 Standardise and cleanup Fedora build
* Remove additional dotnet-preview repo from Makefile
  * Repo doesn't seem maintained, and maintainers actively discourage
    the usage in production in its description
  * Considering this, we should build with stable .NET releases, which
    Fedora and RHEL 8+ repos already provide
* Use Fedora-version-specific runtime-identifier for `dotnet publish`
  * This has no actual effect right now judging by the [RID
    catalog](3efd59151a/docs/core/rid-catalog.md),
    so this is just future proofing.
* Remove AutoReqProv
  * There's rarely a reason to use this feature, this is not one of them
  * In the [proposal of this
    feature](https://fedoraproject.org/wiki/AutoReqProv_(draft)#Usage)
    it is stated that this is not to be used on packages with binaries
    in /usr/bin and others, which is the case in this package.
  * also didn't seem to work since we were still having dependency
    issues with implicit dependencies (see jellyfin/jellyfin#7471 )
* Removed DOTNET_SKIP_FIRST_TIME_EXPERIENCE as it is unused in .NET SDK
  * see dotnet/sdk#9945
  * it's already merged for removal in future versions
* Move building process `dotnet publish` to %build section
  * Also removed `--output` from this due to an outstanding bug on SDK's
    side. This also separates building and installing as intended
* define LICENSE as %license, which automatically puts it in a
  standardised directory
2022-06-15 23:09:26 +02:00
Tarulia
c243f588a0 Adjust license in Fedora Spec according to LICENSE 2022-06-15 23:09:26 +02:00
Tarulia
46491d0813 Rewrite Fedora build version detection
Rewrite so we don't need to constantly update with every new Fedora
release. This is especially useful when Fedora and Jellyfin release
cycles don't line up.

Version selection is as follows:
* TARGET environment variable, which is currently used already
* Currently running Fedora version
* Hardcoded Fallback version that can be updated occasionally
2022-06-15 23:09:26 +02:00
nyanmisaka
c7c0cdad95 Fix the map index of externel audio 2022-06-15 23:39:27 +08:00
nyanmisaka
255f5a6707 Fix the int overflow issue in encoder bufsize 2022-06-15 23:27:49 +08:00
Shadowghost
3f497459cb Fix recommendations 2022-06-15 12:34:04 +02:00
Joe Rogers
5d66c84f2d Fix default audio selection ignoring type 2022-06-15 11:58:12 +02:00
Joe Rogers
052a59ac3e Add tests for preferred audio language selection 2022-06-15 11:58:01 +02:00
Claus Vium
1b8a251991 Merge pull request #7934 from Bond-009/xmlasync2
Enable XmlReaderSettings.Async, fixes #7929
2022-06-14 21:24:19 +02:00
Bond-009
1a787e273a Merge pull request #7873 from cvium/fix_nfo_remoteimages 2022-06-14 19:11:37 +02:00
Bond_009
16fba6035c Enable XmlReaderSettings.Async, fixes #7929 2022-06-14 18:16:49 +02:00
Cody Robibero
d73e9f3af5 Fix splashscreen (#7895) 2022-06-14 08:18:35 -06:00
Cody Robibero
2888080098 Merge pull request #7924 from jellyfin/improve-swdec-amf-tonemap 2022-06-14 08:18:22 -06:00
Nyanmisaka
c8282e8441 Apply suggestions from code review
Co-authored-by: Bond-009 <bond.009@outlook.com>
2022-06-14 17:41:16 +08:00
Cody Robibero
b295b0478c Merge pull request #7925 from nyanmisaka/remove-mpeg4-amf 2022-06-13 16:27:45 -06:00
Cody Robibero
42aaea3556 Merge pull request #7913 from cvium/fix_response_logging 2022-06-13 16:27:38 -06:00
Cody Robibero
07b39655eb Merge pull request #7911 from cvium/fix_keyframe_transcode 2022-06-13 16:27:31 -06:00
Cody Robibero
0f75f17736 Merge pull request #7894 from crobibero/search-hints 2022-06-13 16:27:16 -06:00
nyanmisaka
83d8dbf93e Remove MPEG4 hwaccel from AMF 2022-06-14 02:21:00 +08:00
Nyanmisaka
e5aa708cb9 Improve AMF tonemap speed when using sw decoding
Reduce memory copy-back, also set the target device of hwupload explicitly.
2022-06-14 00:48:16 +08:00
cvium
ac760b9c86 fix: read configuration during Invoke instead of during construction 2022-06-13 11:53:19 +02:00
cvium
c07c7b753c fix: only use keyframes when remuxing video 2022-06-13 10:32:34 +02:00
Claus Vium
8b69b0f521 Merge pull request #7885 from iwalton3/fix-navigation-buttons
Prevent 400 error when using navigation buttons.
2022-06-13 09:47:25 +02:00
Cody Robibero
079fac4a54 Switch to FirstOrDefault extension 2022-06-12 09:17:18 -06:00
Cody Robibero
21afec3225 Merge pull request #7892 from cvium/fix_tv_multi 2022-06-12 07:54:32 -06:00
Ian Walton
11c5a0b182 Prevent 400 error when using navigation buttons.
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2022-06-12 09:00:35 -04:00
cvium
f318417c4f fix: tv shows do not support multi edition 2022-06-12 13:55:17 +02:00
Joshua M. Boniface
874fcaba69 Move service hardening options to override config
Some combination of these options were causing problems with the
functionality of restart.sh as described in the comment and in detail in
issue #7503.

While these seem OK on their face, the implications of this breaking
restart.sh means that they could potentially break other things too.

Thus, we should move these into the optional override file which is in
the administrator's full control, instead of in the default unit, and
leave them off unless a user or package maintainer (e.g. NixOS as
described in the original issue #6952) wants to enable them.

Fixes #7503
2022-06-12 01:05:29 -04:00
cvium
5204863705 fix: respect the image refresh options when parsing remote images from NFO 2022-06-11 15:08:07 +02:00
Joshua M. Boniface
93941f9728 Bump version to 10.8.0 2022-06-10 22:16:13 -04:00
Joshua M. Boniface
aa0f6cb5eb Merge pull request #7868 from cvium/disable_dlna 2022-06-10 21:59:21 -04:00
Cody Robibero
69cc1e0bd8 Merge pull request #7867 from crobibero/name-guid-pair 2022-06-10 10:39:51 -06:00
cvium
007856e61a actually disable DLNA... 2022-06-10 09:04:07 +02:00
cvium
b4954985be chore: disable DLNA by default 2022-06-10 08:56:58 +02:00
Cody Robibero
6b16d90b9b Don't add MigrationOptions to the api spec 2022-06-09 14:26:05 -06:00
Luke Brown
0f7ba42987 move the Dispose logic into DisposeAsyncCore 2022-06-06 23:59:09 -05:00
Cody Robibero
2a89683e80 Merge pull request #7854 from cvium/enable_mkv_keyframe_extraction 2022-06-06 09:40:38 -06:00
Bond-009
8595a979a8 Merge pull request #7828 from nyanmisaka/fix-dovi-tonemap
Fix Dolby Vision profile 5 and 8 to SDR HW tone-mapping
2022-06-06 17:29:39 +02:00
nyanmisaka
1900096012 Fix the too high default qmin option in amf encoders 2022-06-06 21:46:36 +08:00
nyanmisaka
0e8da3e805 Remove the redundant -sc_threshold from hw encoders 2022-06-06 21:46:36 +08:00
nyanmisaka
84c9e7a22b Fix thumbnail extraction in DoVi 2022-06-06 21:46:36 +08:00
nyanmisaka
be28f940b7 Fix the issue that analyzeduration env is not applied 2022-06-06 21:46:36 +08:00
nyanmisaka
fb95fb1a73 Update DoVi 10bit codec tags and remove extra -strict options 2022-06-06 21:46:36 +08:00
nyanmisaka
910995f922 Fix Dolby Vision profile 5 and 8 to SDR HW tone-mapping 2022-06-06 21:46:36 +08:00
cvium
4f0666ac5c chore: enable on demand keyframe extraction for mkv 2022-06-06 15:41:01 +02:00
Joshua M. Boniface
4bfadbc636 Merge pull request #7852 from nyanmisaka/fix-skia
Fix the PNG image decoding issue in Skia
2022-06-06 09:02:51 -04:00
nyanmisaka
2cc896251f Fix the PNG image decoding issue in Skia
Regression was introduced in 2.88.0: https://github.com/mono/SkiaSharp/issues/2095
2022-06-06 19:47:50 +08:00
Cody Robibero
5e343d30e1 Merge pull request #7810 from Bond-009/unaccpattern 2022-06-04 17:23:40 -06:00
Cody Robibero
df6c5b6d42 Merge pull request #7842 from crobibero/dependency-backport 2022-06-04 17:23:04 -06:00
Bond_009
754bda8f73 IAsyncDisposable is one big pitfall
https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-disposeasync#unacceptable-pattern

Regex used:
```
await using \(.+\)
\W+await using
```
2022-06-04 14:34:59 +02:00
Cody Robibero
3721b5e985 Backport all dependency updates 2022-06-03 18:53:05 -06:00
Luke Brown
3e8fe1ce11 change placeholder text in LogDebug message 2022-05-31 21:49:01 -05:00
Cody Robibero
77c73e241f Merge pull request #7781 from crobibero/live-tv-infinite 2022-05-29 08:49:50 -06:00
Cody Robibero
9954cbd550 Merge pull request #7802 from jellyfin/external 2022-05-29 08:49:36 -06:00
Cody Robibero
d8f1a87c85 Update Emby.Server.Implementations/Session/SessionManager.cs
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2022-05-27 16:25:31 -06:00
Cody Robibero
bf0a7c374c Close live stream on session end 2022-05-27 15:58:31 -06:00
Cody Robibero
8a6b26cd42 initial patch 2022-05-27 15:57:51 -06:00
Joe Rogers
b369194710 Fix tests 2022-05-27 06:12:16 +08:00
Nyanmisaka
293bcfb342 Exclude streams with mismatched types in external files 2022-05-27 06:12:10 +08:00
Cody Robibero
1c5571b24e Remove conditional skia inclusion (#7799) 2022-05-26 16:32:37 +02:00
Cody Robibero
b507d1a780 Merge pull request #7792 from crobibero/skia-native
Conditionally include platform specific Skia assets
2022-05-24 19:40:05 -06:00
Cody Robibero
d471be8d92 Merge pull request #7784 from crobibero/support-transcoding 2022-05-24 14:01:40 -06:00
Cody Robibero
3c5b4b9a27 Conditionally include platform specific Skia assets 2022-05-24 11:19:17 -06:00
Cody Robibero
c9491cf317 Merge pull request #7785 from dmitrylyzo/clear-transcodinginfo
Clear TranscodingInfo if play method changed
2022-05-24 07:59:13 -06:00
Dmitry Lyzo
c5dae18034 Apply suggestions from review 2022-05-23 07:49:54 -06:00
Dmitry Lyzo
ff4f624850 Clear TranscodingInfo if play method changed 2022-05-22 22:17:03 +03:00
Cody Robibero
d29a423475 Enable SupportsTranscoding if device has transcoding profiles 2022-05-22 11:06:38 -06:00
Cody Robibero
4c0510ee6d Merge pull request #7775 from crobibero/openapi-version 2022-05-21 08:59:24 -06:00
Cody Robibero
492c6bbd7e Merge pull request #7780 from 1337joe/fix-tv-guide-search-2 2022-05-21 08:59:13 -06:00
Joe Rogers
84878f537c Support searching with tv program filters 2022-05-21 13:11:26 +02:00
Cody Robibero
825e6460c9 Merge pull request #7774 from crobibero/api-authinfo 2022-05-20 20:49:25 -06:00
Cody Robibero
760b021032 Manually describe Version for openapi 2022-05-20 16:29:43 -06:00
Cody Robibero
a532a866e3 Populate authentication info with server details if using API key 2022-05-19 17:50:29 -06:00
Joshua M. Boniface
71bf567045 Merge pull request #7766 from crobibero/dotnet-6.0.5 2022-05-19 19:06:40 -04:00
Luke Brown
044ff0542b adding interface changes 2022-05-19 16:40:48 -05:00
Luke Brown
abfbd04782 Moved IAsyncDisposable and IDisposable from WebSocketConnection to it's interface. Added private variable and guard statement to avoid disposing of WebSocketConnection unnecessarily. 2022-05-18 21:04:22 -05:00
Luke Brown
8d0024ec49 change logging back to debug 2022-05-16 22:35:45 -05:00
Luke Brown
8f761a64f5 revert changes to SessionManager 2022-05-16 22:33:04 -05:00
Luke Brown
a64eebe79f changes to use dispose 2022-05-16 22:09:41 -05:00
Cody Robibero
a82e378da9 Update to dotnet 6.0.5 2022-05-16 14:14:26 -06:00
Joshua M. Boniface
884a59da07 Merge pull request #7724 from jtcasper/perms 2022-05-15 20:26:00 -04:00
Joshua M. Boniface
5a9e5e0d5d Merge pull request #7712 from jellyfin/fix-hevc-disable-option 2022-05-15 20:25:01 -04:00
Joshua M. Boniface
85cfea4c50 Merge branch 'release-10.8.z' into fix-hevc-disable-option 2022-05-15 20:24:52 -04:00
Joshua M. Boniface
3ea67374ae Merge pull request #7741 from LewkyB/fix-improperly-labeled-four-digit-episode-numbering
Fix to allow for episode numbering over 999 in certain scenarios
2022-05-15 20:23:59 -04:00
Joshua M. Boniface
5da4bcc782 Merge pull request #7736 from jellyfin/fix-swscale-pgs 2022-05-15 20:22:24 -04:00
Joshua M. Boniface
b46d61dfdf Merge pull request #7699 from Shadowghost/streambuilder-fix 2022-05-15 20:22:13 -04:00
Joshua M. Boniface
8119e4a573 Merge pull request #7749 from cvium/disable_auto_add_collection 2022-05-15 20:21:40 -04:00
Joshua M. Boniface
de3c68d474 Bump version to 10.8.0-beta3 2022-05-15 20:16:25 -04:00
cvium
7aa0db24d8 fix: disable "Automatically add to collection" by default 2022-05-15 14:53:40 +02:00
Luke Brown
be832e82cc change capture groups to take up to 4 digits and adding inline data to test 2022-05-11 22:22:52 -05:00
nyanmisaka
368d10d042 Fix the mismatched resolution in sw PGS burn-in 2022-05-11 19:18:31 +08:00
Nyanmisaka
9523a1682b Apply suggestions from code review
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2022-05-11 16:38:30 +08:00
Luke Brown
8bb4cd017c applied reviewer suggestions: removing unnecessary async and adding necessary async 2022-05-10 08:28:01 -05:00
Luke Brown
c5f09ab650 Fix broken CI by adding await 2022-05-09 23:59:31 -05:00
luke92brown
99df9c8fcd Replace redundant xml comments with inheritdoc. Make async changes to CloseSocket. 2022-05-09 23:44:37 -05:00
luke brown
4b563f4d7e Fix web sockets closing ungracefully 2022-05-09 23:44:24 -05:00
Jacob Casper
e67d8ce077 Don't let permission denied kill library scans
I have a single `./Movies` directory that contains symlinks to many
other directories, some of which are in shared paths. Other daemons
sometimes overwrite permissions on these paths and prevent Jellyfin from
being able to scan. Because this exception is unhandled within a LINQ
statement it can randomly kill the metadata refresh for my entire Movies
library.

Running with this patch has allowed me to at least add + scan for
movies in directories that Jellyfin can currently access and gives me
some notification of the symlinks failing due to permissions errors.

(cherry picked from commit 193cc8690a60bc2a432df14d256f00371e055c90)
2022-05-09 10:49:52 -05:00
Cody Robibero
39196bb5e2 Merge pull request #7723 from crobibero/tmdb-lib 2022-05-09 07:32:36 -06:00
Nyanmisaka
5386f06095 Apply suggestions from code review
Co-authored-by: Cody Robibero <cody@robibe.ro>
2022-05-09 17:09:03 +08:00
Cody Robibero
5a9afb0874 Merge pull request #7716 from Shadowghost/opus-fix
Respect limited opus sampling rates when building trancoding command
2022-05-08 15:23:58 -06:00
Shadowghost
029be321d1 Respect limited opus sampling rates when building trancoding command 2022-05-08 22:28:45 +02:00
Cody Robibero
96b7c46df4 Update TMDbLib to 1.9.2 2022-05-08 13:28:57 -06:00
Bond-009
f7ef7d9eda Merge pull request #7718 from jellyfin/dovi-hevc-remux 2022-05-08 21:06:03 +02:00
Nyanmisaka
c69e79f64d Fix the disordered color in Dolby Vision remuxing on Safari 2022-05-07 22:43:32 +08:00
nyanmisaka
4b1256e67b Fix the issue that HEVC transcoding can't be disabled 2022-05-06 02:27:16 +08:00
Bond-009
8d1d973438 Merge pull request #7604 from Jellifi007/fixes-diactritics
Co-authored-by: Cody Robibero <cody@robibe.ro>
2022-05-05 19:59:17 +02:00
Cody Robibero
60affd0965 Merge pull request #7529 from Shadowghost/strm-ffprobe-external-fix 2022-05-04 08:20:48 -06:00
Cody Robibero
8a1eca0913 Merge pull request #7544 from jaantaponen/long-filename-fix 2022-05-04 08:19:43 -06:00
Shadowghost
a4e4b761d5 Apply review suggestions 2022-05-04 16:13:06 +02:00
Shadowghost
2be9a34b26 Fix tests and profiles 2022-05-03 22:22:46 +02:00
Shadowghost
0c8b9091a5 Fix streambuilder reasons for direct playback checks 2022-05-03 15:48:46 +02:00
Shadowghost
128d54622a Fix stream index and subtitle container handling, preserve attachments and nonexternal streams between scans 2022-05-03 11:10:58 +02:00
Shadowghost
21ce0e58c6 Properly handle stream addition and removal for strm use cases 2022-05-03 11:10:58 +02:00
Cody Robibero
3229ba4918 Merge pull request #7693 from crobibero/auth-migrate 2022-05-02 07:41:13 -06:00
Cody Robibero
105f057512 Don't migrate auth token if user doesn't exist 2022-05-01 17:55:20 -06:00
Jaan Taponen
b6a2640f22 Update Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs
Co-authored-by: Joe Rogers <1337joe@users.noreply.github.com>
2022-04-30 22:24:11 +03:00
Cody Robibero
a2abae3014 Merge pull request #7654 from Shadowghost/nfo-provider-fix
Prefer MetadataProvider enum as provider id key over arbitrary strings
2022-04-27 18:16:31 -06:00
Shadowghost
7084541508 Prefer MetadataProvider enum as provider id key over arbitrary strings 2022-04-24 21:27:17 +02:00
Joshua M. Boniface
e87240b374 Merge pull request #7648 from jellyfin/libssl3-jammy
Add libssl3 as an alternative dependency for Ubuntu 22.04 LTS
2022-04-23 10:53:25 -04:00
Nyanmisaka
057d5dfc25 Add libssl3 as an alternative dependency for Ubuntu 22.04 LTS 2022-04-23 18:53:59 +08:00
Cody Robibero
12f9132975 Merge pull request #7643 from jellyfin/h264-level 2022-04-22 16:40:53 -06:00
Nyanmisaka
4a1aa619d2 Fix H264 level on safari fmp4 2022-04-22 17:36:36 +08:00
Jellifi007
1002d1d193 Update src/Jellyfin.Extensions/StringExtensions.cs
Co-authored-by: Cody Robibero <cody@robibe.ro>
2022-04-22 09:01:19 +02:00
Cody Robibero
7c91543694 Merge pull request #7638 from 1337joe/fix-quick-connect-tests 2022-04-21 17:48:29 -06:00
Joe Rogers
b04211a707 Fix quick connect tests 2022-04-21 23:24:45 +02:00
Cody Robibero
fcb65ac38d Merge pull request #7634 from neilsb/patch-1
Correct LocalTrailerCount in API
2022-04-21 14:26:17 -06:00
Jellifi007
727402f7f7 Adding Korean language tests Addresses #6393 2022-04-21 22:17:25 +02:00
Neil Burrows
2a1ca4badc Use already defined variable
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2022-04-21 11:11:25 +01:00
Neil Burrows
7f52f77ef5 Correct LocalTrailerCount in API
Revert a change which resulted in the `LocalTrailerCount` including the count of Local and Remote trailers which had been introduced in 10.8.
2022-04-21 11:03:33 +01:00
Cody Robibero
1d5961126e Merge pull request #7624 from nielsvanvelzen/quickconnect-enable-d 2022-04-20 17:37:53 -06:00
Cody Robibero
ec6f7bdcff Merge pull request #7625 from crobibero/xml-cache-delete 2022-04-20 17:37:44 -06:00
Cody Robibero
65c47c79da Only delete cache file if exist 2022-04-20 17:37:26 -06:00
Niels van Velzen
5d9df10e27 Enable Quick Connect by default 2022-04-19 21:48:11 +02:00
Joshua M. Boniface
d45d228b36 Bump version to 10.8.0-beta2 2022-04-17 15:52:43 -04:00
JaanTaponen
2b7d139b5b Fix XMLTV edge case where title & sub-title causes a too long filename error
Limit the series title to 241 bytes (so file extensions can be added).
If the end result is longer, the title will be dropped and only series name
with timestamp is used.
2022-04-17 16:46:01 +03:00
Cody Robibero
a280ff603f Merge pull request #7543 from daullmer/nfo-datefix 2022-04-17 06:40:28 -06:00
Cody Robibero
9beb3aff4e Merge pull request #7605 from crobibero/playback-start-stop
Add missing properties to PlaybackStart, PlaybackStop
2022-04-16 06:03:05 -06:00
Cody Robibero
066bdc1e72 Add missing properties to PlaybackStart, PlaybackStop 2022-04-15 17:44:30 -06:00
Cody Robibero
5833c70725 Merge pull request #7537 from dmitrylyzo/fix-streambuilder 2022-04-15 13:29:20 -06:00
Cody Robibero
cd93f49fa8 Merge pull request #7592 from 1337joe/live-tv-fixes 2022-04-15 13:29:10 -06:00
Cody Robibero
93009682b3 Merge pull request #7591 from 1337joe/update-xmltv 2022-04-15 13:29:00 -06:00
Jellifi007
56573f14b0 Fixes diactritics regressions 2022-04-15 20:14:13 +02:00
Joe Rogers
9001eaa67e Check cache file age directly and replace if old 2022-04-13 22:45:17 +02:00
Joe Rogers
76010e80dd Update Jellyfin.XmlTv to 10.8.0 2022-04-13 20:07:14 +02:00
Joshua M. Boniface
5778541d2f Merge pull request #7590 from crobibero/dotnet-6.0.4 2022-04-13 12:06:56 -04:00
Cody Robibero
cb0baddde3 Update to dotnet 6.0.4 2022-04-12 17:34:08 -06:00
Dmitry Lyzo
0ff37413b0 fix: Fix transcode reasons
Don't add codec failure reasons if the codec isn't supported.
2022-04-12 22:56:23 +03:00
Dmitry Lyzo
d5434988d7 test: Add tests for Tizen 3/4 2022-04-12 22:56:23 +03:00
Dmitry Lyzo
847518701d fix: Fix codec conditions
`ApplyConditions` is used to determine the applicability of
the current codec (`Conditions`).
`Conditions` is the actual conditions for the stream.

`CodecType.VideoAudio` (not `CodecType.Video`) must be used
for the audio tracks in the video.
2022-04-12 22:56:23 +03:00
Cody Robibero
c5212a20a3 Merge pull request #7580 from jellyfin/external-audio-map 2022-04-12 13:41:21 -06:00
Cody Robibero
385a0b9437 Merge pull request #7567 from cvium/fix_xmltv_caching 2022-04-12 13:40:05 -06:00
Nyanmisaka
884ba4f3ed Fix the wrong external audio map index if text subtitle exists 2022-04-10 22:49:40 +08:00
Cody Robibero
cba6a4e3f3 Merge pull request #7578 from Shadowghost/extension-parser-fix
Remove mp2 from video file extensions
2022-04-10 06:24:50 -06:00
Shadowghost
d5f44f7a5c Remove mp2 from video file extensions 2022-04-10 14:02:17 +02:00
Cody Robibero
bf1ccf7493 Merge pull request #7521 from 1337joe/image-mime-fallback
Add fallback for image downloads with bad reported MediaType
2022-04-09 08:46:06 -06:00
Cody Robibero
d7c548f3db Merge pull request #7561 from DMouse10462/named-config-api-fix
Fix NamedConfiguration API Generation
2022-04-09 08:45:13 -06:00
Joshua M. Boniface
a7abdca47a Merge pull request #7569 from crobibero/repo-auth 2022-04-08 11:23:30 -04:00
Cody Robibero
7a8eaa8811 Require elevation to save the list of plugin repositories 2022-04-08 08:46:55 -06:00
cvium
045dca49d0 fix: use the checksum as temp folder name when extracting xmltv listings 2022-04-07 22:12:12 +02:00
David Mouse
e9ce82445e Add ConfigurationType Types to generated OpenAPI
This allows clients to see and work with the associated types for each NamedConfiguration key, even if the UpdateNamedConfiguration endpoint doesn't properly advertise its types.
2022-04-05 23:19:27 -04:00
David Mouse
2133c6e348 Parameterize request body of UpdateNamedConfiguration
This gives OpenAPI clients the knowledge that they should provide a body of some kind.
2022-04-05 23:19:27 -04:00
Cody Robibero
5de2db9f52 Merge pull request #7507 from crobibero/studio-image-plugin
Fix StudioImageProvider
2022-04-05 05:52:48 -06:00
Cody Robibero
620625c4c1 Merge pull request #7557 from jellyfin/pgs-qsv-iris655 2022-04-04 16:05:50 -06:00
Nyanmisaka
e0b035e34e Apply suggestions from code review
Co-authored-by: Shadowghost <Shadowghost@users.noreply.github.com>
2022-04-05 00:02:13 +08:00
Nyanmisaka
1946414e14 Fix PGS burn-in on certain iGPU such as Iris Plus 655 2022-04-04 23:48:12 +08:00
Cody Robibero
132c85e554 Merge pull request #7542 from 1337joe/make-recording-stop
Make recording stop at scheduled stop time
2022-04-04 07:20:20 -06:00
Joe Rogers
9d1049e83f Make Record call block until finished as expected 2022-04-04 14:43:14 +02:00
Cody Robibero
72aca15191 Merge pull request #7548 from 1337joe/comparer-null-fix 2022-04-04 06:30:24 -06:00
Cody Robibero
577325b788 Merge pull request #7523 from crobibero/null-stream
Allow media without streams to playback
2022-04-04 05:45:45 -06:00
Cody Robibero
fec2cf5060 Merge pull request #7551 from cvium/fix_trailertype
fix: remove (incorrect) negation of bool expression
2022-04-04 05:02:58 -06:00
cvium
53b06ce4e3 fix: remove (incorrect) negation of bool expression 2022-04-04 08:35:41 +02:00
Cody Robibero
bdb85aeecf Merge pull request #7549 from cvium/fix_isinlocalnetwork 2022-04-03 16:38:04 -06:00
cvium
e299adc819 fix: use stdlib IPAddress.IsLoopback 2022-04-04 00:03:54 +02:00
Joe Rogers
0674f84e9e Add check so nulls will result in valid sort 2022-04-03 22:50:32 +02:00
David Ullmer
b6086398d3 Write Global Date to nfo files 2022-04-02 19:46:15 +02:00
Cody Robibero
1d585146d6 Merge pull request #7519 from nielsvanvelzen/resolverpriority-plugin2 2022-03-30 20:11:46 -06:00
Cody Robibero
aa1b1c6bbb Merge pull request #7527 from Shadowghost/mediaresolver-fix 2022-03-30 20:10:36 -06:00
Cody Robibero
bebe1808ce Merge pull request #7525 from 1337joe/fix-duplicate-library-media-paths 2022-03-30 20:10:12 -06:00
Shadowghost
fb2e4c2e1a Remove video file from file list before processing external files 2022-03-30 22:48:48 +02:00
Joe Rogers
784ed796ce Update name so media paths store to correct library 2022-03-30 15:20:57 +02:00
Cody Robibero
579155a571 Allow media without streams to playback 2022-03-29 20:17:12 -06:00
Joe Rogers
ca16a55a47 Add fallback for image downloads with bad MediaType 2022-03-29 21:42:54 +02:00
Niels van Velzen
e2ffd41141 Add new priority level to ResolverPriority for plugins 2022-03-29 20:00:50 +02:00
Cody Robibero
ca67a48140 Merge pull request #7512 from crobibero/update-plugin 2022-03-28 16:34:46 -06:00
Claus Vium
d2ce315c1d Merge pull request #7506 from crobibero/set-permissions
Safely get/set User permission/preference
2022-03-28 23:02:42 +02:00
Cody Robibero
6a6874aa16 Catch checksum mismatch when updating plugins 2022-03-28 06:48:21 -06:00
Cody Robibero
6f45848b51 Safely set/get user permission 2022-03-28 06:45:47 -06:00
Cody Robibero
23ba15ccfb Fix StudiosImageProvider 2022-03-27 21:42:35 -06:00
Joshua M. Boniface
5376c37d42 Bump packaging version to 10.8.0~beta1 2022-03-27 12:12:24 -04:00
Saiyd
a0eb1fd28b Translated using Weblate (Portuguese (Brazil))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/pt_BR/
2022-03-26 19:06:12 -04:00
Cody Robibero
130c935bc3 Merge pull request #7495 from crobibero/fix-entrypoint 2022-03-26 14:33:02 -06:00
Cody Robibero
003c48e351 Merge pull request #7496 from crobibero/transcode-reason 2022-03-26 14:32:54 -06:00
Cody Robibero
96a03776e1 Fix TranscodeReasons property name 2022-03-26 12:20:29 -06:00
Cody Robibero
ac33adf219 Learn how DllImport works before making changes 2022-03-26 12:14:09 -06:00
Cody Robibero
4fa7f49ffc Merge pull request #7202 from knackebrot/unix-perms 2022-03-26 07:24:06 -06:00
Cody Robibero
0a068b924f Fix casing of chmod 2022-03-26 07:12:35 -06:00
Cody Robibero
d80c4ee381 Merge pull request #7492 from crobibero/sort-by 2022-03-25 13:33:29 -06:00
Cody Robibero
e6014bb8d3 Merge pull request #7493 from Shadowghost/dlna-fix 2022-03-25 13:33:20 -06:00
Cody Robibero
8056b0e961 Merge pull request #7443 from whiteowl3/strm-probe 2022-03-25 13:33:10 -06:00
whiteowl3
6a7775de6e empty line required by linter 2022-03-25 19:08:03 +00:00
Shadowghost
4e91c3ebdc Fix DLNA DirectPlay 2022-03-25 18:02:31 +01:00
Cody Robibero
78a8c26690 Don't allow unknown sort-by 2022-03-25 09:18:18 -06:00
Joshua M. Boniface
c229f3ae0a Merge pull request #7333 from eyezak/hls/audio-bitstream-fmp4 2022-03-25 10:13:58 -04:00
Nyanmisaka
3cea6c61f3 Apply suggestions from code review 2022-03-25 22:12:56 +08:00
Joshua M. Boniface
8197e5921e Merge pull request #7198 from dmitrylyzo/transcode-conditions 2022-03-25 10:11:45 -04:00
Jason S
5f7ffd7863 Translated using Weblate (Kannada)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/kn/
2022-03-25 05:51:28 -04:00
Jason S
c28025ba5e Added translation using Weblate (Kannada) 2022-03-25 04:44:39 -04:00
Rhodri
af5200857e Translated using Weblate (Welsh)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/cy/
2022-03-23 20:24:28 -04:00
Joshua M. Boniface
97d3212410 Merge pull request #7437 from Nalsai/mks-attachments 2022-03-23 20:19:32 -04:00
Rhodri
8780fc0ea1 Translated using Weblate (Welsh)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/cy/
2022-03-23 17:28:09 -04:00
Joshua M. Boniface
570660099b Merge pull request #7483 from jellyfin/swdec-cu-tonemap 2022-03-23 15:25:39 -04:00
Joshua M. Boniface
945fb8b72e Merge pull request #7488 from crobibero/flag-enum-openapi 2022-03-23 15:24:31 -04:00
whiteowl3
16a449a023 Apply suggestions from code review
Co-authored-by: Cody Robibero <cody@robibe.ro>
2022-03-23 13:19:05 -04:00
whiteowl3
669029595b Update MediaBrowser.Providers/MediaInfo/MediaInfoResolver.cs
Co-authored-by: Cody Robibero <cody@robibe.ro>
2022-03-23 13:18:34 -04:00
Cody Robibero
72cfa6d7c9 Fix spec generation for TranscodeReason 2022-03-23 08:32:33 -06:00
Cody Robibero
7fb21132dd Merge pull request #7487 from InvoxiPlayGames/dlna-fix 2022-03-22 19:10:08 -06:00
Mocanu Marian
3bf5a7b801 Translated using Weblate (Romanian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ro/
2022-03-22 20:13:37 -04:00
tokiedokie
74bdad82c1 Translated using Weblate (Japanese)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ja/
2022-03-22 20:13:37 -04:00
nextlooper42
c59087606c Translated using Weblate (Slovak)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sk/
2022-03-22 20:13:37 -04:00
Nils Fürniß
d7d36a102a Fix releasing lock 2022-03-22 19:17:49 +01:00
Nils Fürniß
b4bb82b6d7 Improve code 2022-03-22 19:17:48 +01:00
Nils Fürniß
eb44f892b8 Only extract attachments from external .mks file 2022-03-22 19:17:48 +01:00
Nils Fürniß
90463d5e4f Pass CancellationToken to ExtractAllAttachments 2022-03-22 19:17:48 +01:00
Nils Fürniß
6904edf68c add extracting attachments from external subs 2022-03-22 19:17:48 +01:00
InvoxiPlayGames
dc8fdb154a get DLNA profile in XML request, correctly format UUID 2022-03-22 16:04:55 +00:00
Cody Robibero
c512e783b3 Merge pull request #7480 from jellyfin/dependabot/nuget/StyleCop.Analyzers-1.2.0-beta.406 2022-03-21 11:10:06 -06:00
Cody Robibero
4398475aac Merge pull request #7481 from jellyfin/dependabot/nuget/libse-3.6.5 2022-03-21 11:09:38 -06:00
Nyanmisaka
fb8ae0e9a1 Improve fps for cuda tonemap in sw decoding
avoid second copy if subtitle is not applied.
2022-03-22 00:45:07 +08:00
dependabot[bot]
5d44e45b90 Bump libse from 3.6.4 to 3.6.5
Bumps [libse](https://github.com/SubtitleEdit/subtitleedit) from 3.6.4 to 3.6.5.
- [Release notes](https://github.com/SubtitleEdit/subtitleedit/releases)
- [Changelog](https://github.com/SubtitleEdit/subtitleedit/blob/master/Changelog.txt)
- [Commits](https://github.com/SubtitleEdit/subtitleedit/compare/3.6.4...3.6.5)

---
updated-dependencies:
- dependency-name: libse
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-21 12:22:20 +00:00
dependabot[bot]
dde984bd0e Bump StyleCop.Analyzers from 1.2.0-beta.376 to 1.2.0-beta.406
Bumps [StyleCop.Analyzers](https://github.com/DotNetAnalyzers/StyleCopAnalyzers) from 1.2.0-beta.376 to 1.2.0-beta.406.
- [Release notes](https://github.com/DotNetAnalyzers/StyleCopAnalyzers/releases)
- [Commits](https://github.com/DotNetAnalyzers/StyleCopAnalyzers/compare/1.2.0-beta.376...1.2.0-beta.406)

---
updated-dependencies:
- dependency-name: StyleCop.Analyzers
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-21 12:22:11 +00:00
Cody Robibero
ba11add83b Merge pull request #7445 from Bond-009/baseitem 2022-03-20 08:01:31 -06:00
lyaschuchenko
e86e64807d Translated using Weblate (Ukrainian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/uk/
2022-03-20 04:13:37 -04:00
fatihbural
320ab8db6a Translated using Weblate (Turkish)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/tr/
2022-03-20 04:13:37 -04:00
Henrik Söderlund
60e0becc54 Translated using Weblate (Swedish)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sv/
2022-03-20 04:13:37 -04:00
millallo
acd4a97e65 Translated using Weblate (Italian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/it/
2022-03-20 04:13:37 -04:00
Joel Tony
009e3a6c72 Translated using Weblate (English (United Kingdom))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/en_GB/
2022-03-20 04:13:37 -04:00
xnick
f8b5631d62 Translated using Weblate (Greek)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/el/
2022-03-20 04:13:37 -04:00
3ole
8871e5af4b Translated using Weblate (German)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/de/
2022-03-20 04:13:36 -04:00
Xavier Rosell
4c117b0259 Translated using Weblate (Catalan)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ca/
2022-03-20 04:13:36 -04:00
Dmitry Lyzo
e4137a6279 Fix remuxing 2022-03-20 09:11:46 +03:00
Dmitry Lyzo
1fe82d0deb Add TranscodingProfile conditions 2022-03-20 09:11:46 +03:00
Cody Robibero
588c349eb4 Merge pull request #7477 from crobibero/requested-bitrate 2022-03-19 17:41:29 -06:00
Cody Robibero
b9c3a497d5 Use requested bitrate for calculations 2022-03-19 12:08:42 -06:00
Joshua M. Boniface
dd6845b8f3 Merge pull request #7476 from crobibero/tmdb-ended 2022-03-19 12:33:23 -04:00
Joshua M. Boniface
464ebf93dd Merge pull request #6985 from joshuaboniface/unharden-for-lxc 2022-03-19 12:31:33 -04:00
Joshua M. Boniface
93f569d286 Add comment about sysv options 2022-03-19 12:27:48 -04:00
Cody Robibero
0e2b20e6d6 tmdb - update available series end status 2022-03-18 18:49:12 -06:00
Cody Robibero
e1527857e9 Merge pull request #7468 from jakobkukla/master 2022-03-18 16:55:21 -06:00
Cody Robibero
6a567e8c76 Merge pull request #7474 from nielsvanvelzen/api-secure 2022-03-18 16:52:59 -06:00
dependabot[bot]
4b5148c69e Bump Swashbuckle.AspNetCore.ReDoc from 6.2.3 to 6.3.0 (#7457)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-18 22:38:55 +01:00
Niels van Velzen
8a827ba995 Update tests 2022-03-18 22:21:08 +01:00
Bond-009
bb7068cb63 Move StreamBuilderTests to correct project (#7461) 2022-03-18 22:19:02 +01:00
Niels van Velzen
46798cb918 Remove check for non-existent "emby rt" client in UserViewsController (#7470) 2022-03-18 22:16:08 +01:00
Niels van Velzen
5ece92d635 Add authorization attribute to UserViewsController 2022-03-18 21:56:42 +01:00
Niels van Velzen
9fbd675bed Add authorization attribute to GetConfigurationPages 2022-03-18 21:54:25 +01:00
Cody Robibero
5cf0c1b8f8 Merge pull request #7466 from jellyfin/prefer-cuvid
Prefer Cuvid to Nvdec by default for better performance
2022-03-18 05:45:41 -06:00
Josu Igoa
c8a8a85944 Translated using Weblate (Basque)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/eu/
2022-03-18 06:26:41 -04:00
Josu Igoa
9f147216be Translated using Weblate (Basque)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/eu/
2022-03-18 05:56:13 -04:00
Josu Igoa
db60c9da25 Added translation using Weblate (Basque) 2022-03-18 05:51:16 -04:00
jakobkukla
75475285da Fix supportsTranscoding not reflecting user permissions sometimes 2022-03-17 17:24:30 +01:00
Nyanmisaka
18c7dc210c Prefer Cuvid to Nvdec by default for better performance 2022-03-17 18:01:58 +08:00
Freethefire
ca517af0d9 Translated using Weblate (Swedish)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sv/
2022-03-17 03:14:57 -04:00
SeanPai
fccf3ac3eb Translated using Weblate (Chinese (Traditional))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/zh_Hant/
2022-03-17 01:13:34 -04:00
Joshua M. Boniface
1d7a524d82 Add SuccessExitStatus for exit 143
Fixes #3182
2022-03-15 20:27:38 -04:00
WWWesten
6a3da3a031 Translated using Weblate (Esperanto)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/eo/
2022-03-14 17:21:44 -04:00
hoanghuy309
456d95c878 Translated using Weblate (Vietnamese)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/vi/
2022-03-14 17:21:44 -04:00
Oatavandi
36040832cc Translated using Weblate (Tamil)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ta/
2022-03-14 17:21:44 -04:00
Oskari Lavinto
cb91ad184e Translated using Weblate (Finnish)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fi/
2022-03-14 17:21:44 -04:00
Magnetogenerator
122f6acb15 Translated using Weblate (Chinese (Simplified))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/zh_Hans/
2022-03-14 17:21:44 -04:00
WWWesten
b4913aad30 Translated using Weblate (Russian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ru/
2022-03-14 17:21:44 -04:00
WWWesten
6fa38e300a Translated using Weblate (Kazakh)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/kk/
2022-03-14 17:21:44 -04:00
Csaba
fbbb0368f7 Translated using Weblate (Hungarian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/hu/
2022-03-14 17:21:44 -04:00
Ali Dastpour
67a0a998cc Translated using Weblate (Persian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fa/
2022-03-14 17:21:44 -04:00
Lukáš Kucharczyk
95e97fea01 Translated using Weblate (Czech)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/cs/
2022-03-14 17:21:44 -04:00
Cody Robibero
cf47ee6261 Merge pull request #7449 from crobibero/revert-clamp 2022-03-13 12:46:30 -06:00
Cody Robibero
d29c7c1d9e Revert using Math.Clamp 2022-03-13 12:46:13 -06:00
Rasmus
72165ae96f Translated using Weblate (Pirate)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/pr/
2022-03-12 15:33:47 -05:00
WWWesten
34af6c48d7 Translated using Weblate (English (United Kingdom))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/en_GB/
2022-03-12 15:33:47 -05:00
Cody Robibero
e6df698df1 Merge pull request #7325 from eyezak/issue/6450 2022-03-12 09:08:25 -07:00
Cody Robibero
8ddcdc7430 Merge pull request #7448 from nielsvanvelzen/itemfreshcontroller 2022-03-12 08:56:45 -07:00
Niels van Velzen
d659b9b9ab Restrict item refreshing to administrators 2022-03-12 15:47:30 +01:00
Niels van Velzen
6bb50d5728 Change operation name in ItemRefreshController 2022-03-12 15:43:29 +01:00
Cody Robibero
3ea4174d12 Fix flipped Clamp args 2022-03-12 07:17:59 -07:00
Cody Robibero
5319f1571f Merge pull request #7444 from Bond-009/baseurl 2022-03-11 18:42:14 -07:00
Joshua M. Boniface
6e80c9b25f Merge pull request #6528 from oledfish/additional-episode-orders 2022-03-11 14:35:29 -05:00
Bond_009
7fdc0e3c3d BaseItem: remove unused function 2022-03-11 16:21:32 +01:00
Cody Robibero
28223704f3 Merge pull request #7441 from 1337joe/add-external-stream-indicator
Add label for external audio/sub tracks
2022-03-11 07:48:23 -07:00
Bond_009
edeb198313 Add tests for BaseUrl normalization 2022-03-11 15:44:16 +01:00
Joe Rogers
f671eeb6b2 Add self to CONTRIBUTORS.md 2022-03-11 15:23:17 +01:00
xnick
3342c29f4f Translated using Weblate (Greek)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/el/
2022-03-11 09:13:33 -05:00
Shadowghost
b2188c8676 Translated using Weblate (German)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/de/
2022-03-11 09:13:33 -05:00
Claus Vium
53209830e7 Merge pull request #7346 from Bond-009/guid
Optimize Guid comparisons
2022-03-11 08:15:12 +01:00
Claus Vium
21ef6661d6 Merge pull request #7440 from 1337joe/fix-add-external-audio
Match external sub/audio stream adding logic
2022-03-11 08:03:18 +01:00
whiteowl3
6f25291931 allow strm probe to succeed 2022-03-11 06:54:25 +00:00
Joe Rogers
1a307db7eb Add label for external audio/sub tracks 2022-03-10 22:20:35 +01:00
Cody Robibero
a5ffde0e9c Merge pull request #7432 from Bond-009/socketfactory 2022-03-10 14:19:08 -07:00
Joe Rogers
ac83effd44 Match external sub/audio stream adding logic 2022-03-10 22:02:46 +01:00
Mayur Panchal
96de01ce01 ProbeResultNormalizer: fix framerate compare + tests (#7167) 2022-03-10 20:55:30 +01:00
Bond_009
470d175f32 ExclusiveAddressUse: cheated by the docs 2022-03-10 20:51:22 +01:00
Joshua M. Boniface
388e0cba9f Merge pull request #7434 from crobibero/dotnet-6.0.3 2022-03-10 12:47:18 -05:00
Joshua M. Boniface
11fc84eebe Merge pull request #7435 from nyanmisaka/seek-fmp4 2022-03-10 12:44:28 -05:00
sabretou
1e80ba0462 Translated using Weblate (Marathi)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/mr/
2022-03-09 22:12:40 -05:00
Cody Robibero
a397cec981 Merge pull request #7410 from MinecraftPlaye/show-diff-dts-versions 2022-03-09 07:18:13 -07:00
nyanmisaka
b2c58338f2 Fix the fMP4 HLS audio sync issue on Safari 2022-03-09 21:28:58 +08:00
Cody Robibero
965bf7332f Update to dotnet 6.0.3 2022-03-08 17:16:33 -07:00
Cody Robibero
dacbfc83ff Merge pull request #7431 from Bond-009/autodiscovery 2022-03-08 14:37:01 -07:00
Bond_009
1d018c5575 SocketFactory: Remove redundant code
ExclusiveAddressUse should be false by default afaik
2022-03-08 22:20:43 +01:00
Bond_009
16e0d46771 UdpServerEntryPoint: Fix typo 2022-03-08 22:11:06 +01:00
Nyanmisaka
4f1efb3996 Re-enable the legacy NVIDIA CUVID decoder in full HWA pipeline (#7413) 2022-03-08 16:36:30 +01:00
Bill Thornton
c5ca29d2e2 Remove unused poster support from StudiosImageProvider (#7423) 2022-03-08 16:36:05 +01:00
Bond-009
03f1eff21a Implement TransportState according to spec (#7426) 2022-03-08 16:12:03 +01:00
Mattias
e3ea899bcc Translated using Weblate (Swedish)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sv/
2022-03-08 03:52:36 -05:00
Thomas Schwery
88c4e38ce2 Translated using Weblate (French)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fr/
2022-03-07 17:54:08 -05:00
Cody Robibero
ea7e6aeae0 Merge pull request #7425 from Bond-009/aurating 2022-03-07 13:45:30 -07:00
Bond_009
f48c8d4802 Remove none existing Australian rating
I'm not sure the numbers here are correct
2022-03-07 21:00:13 +01:00
Ali Dastpour
0ef35286c5 Translated using Weblate (Persian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fa/
2022-03-07 11:58:16 -05:00
dependabot[bot]
1ec3e899d6 Bump actions/checkout from 2 to 3 (#7420)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-07 16:44:10 +01:00
dependabot[bot]
023eddbef5 Bump actions/stale from 4.1.0 to 5 (#7421)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-07 16:43:59 +01:00
Cody Robibero
10d1c7b25d Merge pull request #7418 from jellyfin/dependabot/nuget/prometheus-net.AspNetCore-6.0.0
Bump prometheus-net.AspNetCore from 5.0.2 to 6.0.0
2022-03-07 07:47:15 -07:00
dependabot[bot]
de766e687d Bump prometheus-net.AspNetCore from 5.0.2 to 6.0.0
Bumps [prometheus-net.AspNetCore](https://github.com/prometheus-net/prometheus-net) from 5.0.2 to 6.0.0.
- [Release notes](https://github.com/prometheus-net/prometheus-net/releases)
- [Changelog](https://github.com/prometheus-net/prometheus-net/blob/master/History)
- [Commits](https://github.com/prometheus-net/prometheus-net/compare/v5.0.2...v6.0.0)

---
updated-dependencies:
- dependency-name: prometheus-net.AspNetCore
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-07 13:25:23 +00:00
dependabot[bot]
bb83e9f2d9 Bump prometheus-net from 5.0.2 to 6.0.0 (#7417)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-07 14:24:21 +01:00
dependabot[bot]
4c4f5dfe81 Bump Moq from 4.17.1 to 4.17.2 (#7416)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-07 14:23:43 +01:00
Cody Robibero
da41cd365c Suggestions from review 2022-03-06 18:17:49 -07:00
Cody Robibero
dbea7cac67 Use Enum.GetValues<T>() 2022-03-06 18:13:54 -07:00
Cody Robibero
bbd5d11d3b Remove TranscodeReason.None, Add JsonFlagEnum tests 2022-03-06 18:13:54 -07:00
Cody Robibero
c331e11c24 Clean up EnumFlags serialization 2022-03-06 18:13:54 -07:00
Isaac Gordezky
9ebd521754 Update MediaBrowser.Model/Dlna/StreamBuilder.cs
Co-authored-by: Cody Robibero <cody@robibe.ro>
2022-03-06 18:13:54 -07:00
Isaac Gordezky
84a3db6f84 Fix transcode video matching and add tests for Transcode and Safari 2022-03-06 18:13:54 -07:00
Isaac Gordezky
5e779f20ee Series: issue-6450
Issue: https://github.com/jellyfin/jellyfin/issues/6450

Enable DirectPlay responses
Rewrite DirectPlay and DirectStream resolution
Prefer copy transcode video codec options
Enhance condition processor
Support DirectStream and Transcode with parity
Rework audio stream selection and add tests for ExternalAudio
Update MediaInfoHelper to only call StreamBuilder once
2022-03-06 18:13:54 -07:00
Isaac Gordezky
d871dded9f Convert TranscodeReason to Flags 2022-03-06 18:13:54 -07:00
Isaac Gordezky
a3057afde8 StreamBuilder basic tests 2022-03-06 18:13:54 -07:00
Patrick Farwick
27b81a535c Let the UI show which DTS profile is in use
There are different profiles for DTS. For example, both DTS and DTS-HD
MA use the same codec, but provide a different profile.

Some files may provide both a DTS and DTS-HD MA audio track. With this
change, the UI shows which track is using which profile to allow the
user to choose between them.
2022-03-06 19:11:02 +00:00
Cody Robibero
1dcd537ea2 Merge pull request #7411 from jellyfin/revert-7240-add-readonly-connection 2022-03-06 11:04:36 -07:00
Cody Robibero
0a8bec1af4 Revert "chore: Add a read only connection for routes like Shows/NextUp" 2022-03-06 09:30:47 -07:00
Cody Robibero
973781c482 Merge pull request #7406 from crobibero/fix-build
Fix build
2022-03-06 06:47:32 -07:00
Cody Robibero
b37052a4a6 Fix build 2022-03-06 06:34:04 -07:00
Cody Robibero
15cae4ef00 Merge pull request #7405 from StollD/fix-strm-files 2022-03-05 15:03:45 -07:00
Dorian Stoll
7af1cae883 Add myself to CONTRIBUTORS.md 2022-03-05 22:15:43 +01:00
Dorian Stoll
178d00b14d Readd .strm as an allowed extension for videos 2022-03-05 22:05:26 +01:00
Cody Robibero
bc3cb04c0b Merge pull request #7240 from jaysonsantos/add-readonly-connection 2022-03-05 13:36:40 -07:00
Bond-009
2579b2db56 Merge pull request #7137 from SenorSmartyPants/master 2022-03-05 20:54:36 +01:00
Cody Robibero
3dc0cfc36e Merge pull request #7388 from GermanCoding/iso639-undefined 2022-03-05 12:43:51 -07:00
Cody Robibero
4791d56f6c Merge pull request #7403 from 1337joe/fix-external-file-prefix-check 2022-03-05 12:43:29 -07:00
Cody Robibero
b705ace262 Apply suggestions from code review 2022-03-05 12:37:23 -07:00
Joshua M. Boniface
947ff9defe Merge pull request #7404 from nyanmisaka/omx 2022-03-05 14:35:41 -05:00
Joshua M. Boniface
414004f83d Merge pull request #7397 from jellyfin/intel-vaapi 2022-03-05 14:30:30 -05:00
Joshua M. Boniface
e3d9c53baa Merge pull request #7396 from thornbill/update-artwork-repository 2022-03-05 14:30:21 -05:00
Joshua M. Boniface
a123391e7e Merge pull request #7383 from thornbill/next-up-rewatching 2022-03-05 14:29:49 -05:00
Rhodri
9f027bae41 Translated using Weblate (Welsh)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/cy/
2022-03-05 13:13:31 -05:00
Ray Cheung
5eda32980c Translated using Weblate (Chinese (Hong Kong))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/zh_Hant_HK/
2022-03-05 13:13:31 -05:00
Jorge IG
76019d3a34 Translated using Weblate (Spanish)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/es/
2022-03-05 13:13:31 -05:00
nyanmisaka
3bf83025f2 Fallback to no HWA when reporting transcoding info 2022-03-06 00:12:16 +08:00
nyanmisaka
bfc27e494b Remove the deprecated OMX and MMAL HWA 2022-03-05 21:47:59 +08:00
Joe Rogers
f7118bebfd Fix external file check for shorter names 2022-03-05 12:39:03 +01:00
Claus Vium
fab5f37e0e Merge pull request #7394 from 1337joe/remove-external-file-fuzzy-matching
Strip out external file fuzzy name matching
2022-03-05 09:26:55 +01:00
nyanmisaka
de4a084b03 Set the name of intel vaapi driver explicitly
Fix crashes on older intel gfx when both iHD and i965 driver are existed.
2022-03-05 01:32:06 +08:00
GermanCoding
3f6a14e1fd Use extension method for list search 2022-03-04 16:44:55 +01:00
Joe Rogers
dad7a6fdf6 Switch to using spans for string comparison 2022-03-04 15:58:01 +01:00
Joe Rogers
3205e97e1e Strip out external file fuzzy matching
Convert MediaFlagDelimiter back to char
2022-03-04 10:52:21 +01:00
Claus Vium
136eab9b1e Merge pull request #7370 from crobibero/internal-metadata-path
Only add internal files if the internal metadata path exists
2022-03-04 08:13:58 +01:00
Bill Thornton
46ef68d589 Update artwork repository urls 2022-03-04 01:39:21 -05:00
WWWesten
f712c554ab Translated using Weblate (Esperanto)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/eo/
2022-03-03 19:21:04 -05:00
hoanghuy309
e58f7ae5da Translated using Weblate (Vietnamese)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/vi/
2022-03-03 19:21:04 -05:00
Oatavandi
92fd6475fa Translated using Weblate (Tamil)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ta/
2022-03-03 19:21:04 -05:00
Oskari Lavinto
8121635d8c Translated using Weblate (Finnish)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fi/
2022-03-03 19:21:04 -05:00
小造xu_zh
9025cd13c5 Translated using Weblate (Chinese (Simplified))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/zh_Hans/
2022-03-03 19:21:04 -05:00
WWWesten
2ce0389d59 Translated using Weblate (Russian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ru/
2022-03-03 19:21:04 -05:00
WWWesten
957199dcba Translated using Weblate (Kazakh)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/kk/
2022-03-03 19:21:03 -05:00
Csaba
73805e0b4a Translated using Weblate (Hungarian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/hu/
2022-03-03 19:21:03 -05:00
Page Asgardius
f3de108617 Translated using Weblate (Spanish (Mexico))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/es_MX/
2022-03-03 19:21:03 -05:00
Lukáš Kucharczyk
94793e6c6b Translated using Weblate (Czech)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/cs/
2022-03-03 19:21:03 -05:00
GermanCoding
e09641b452 Hide ISO 639-2 special codes in display titles
They are still shown in associated metadata, just hidden from the more visible display titles.
2022-03-04 00:55:20 +01:00
Bond-009
b356c2b212 Merge pull request #7324 from Maxr1998/sort-by-index 2022-03-03 13:55:45 +01:00
Bond-009
2dbb32976c Merge pull request #7380 from crobibero/general-command 2022-03-03 13:55:33 +01:00
Bond-009
6e91657f01 Merge pull request #7381 from crobibero/migrate-datetime 2022-03-03 13:55:09 +01:00
Cody Robibero
1b3e56bae3 Split DirectoryExists and FileExists 2022-03-02 19:55:44 -07:00
Bill Thornton
df70d7bdf1 Use IReadOnlyList for seriesKeys 2022-03-02 10:17:24 -05:00
DetermineAbsurd
d16bdfbc05 Translated using Weblate (Pirate)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/pr/
2022-03-02 08:13:30 -05:00
Aman Setia
fe53243cfb Translated using Weblate (Hindi)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/hi/
2022-03-02 08:13:30 -05:00
Claus Vium
6498a5baca Merge pull request #7387 from jellyfin/nvdec-threads 2022-03-01 16:53:23 +01:00
Cody Robibero
71a9ae3150 Update MediaBrowser.Controller/Providers/DirectoryService.cs
Co-authored-by: Joe Rogers <1337joe@users.noreply.github.com>
2022-03-01 08:30:26 -07:00
Nyanmisaka
4239f80c81 Lowering the VRAM usage on NVDEC decoder 2022-03-01 23:14:35 +08:00
Cody Robibero
f0c28019dc Merge pull request #7386 from jellyfin/fonts 2022-03-01 08:13:53 -07:00
Nyanmisaka
ba8e478a2f Fix the path to the extracted fonts on Windows 2022-03-01 22:41:54 +08:00
Cody Robibero
0a953aca8a Merge pull request #7372 from jellyfin/dependabot/github_actions/actions/setup-dotnet-2 2022-03-01 06:45:00 -07:00
Bond-009
7d226e8eef Merge pull request #7376 from GermanCoding/fix_soundhandler 2022-03-01 11:24:20 +01:00
Bond-009
eff3d3e67e Merge pull request #7275 from Nalsai/burn-subtitle-attached-fonts 2022-03-01 11:21:19 +01:00
Bond-009
ef99a53abb Merge pull request #7366 from 1337joe/filter-theme-song-and-video 2022-03-01 11:12:32 +01:00
Bond-009
1e98f168c9 Merge pull request #7363 from 1337joe/ffmpeg-5-long-chapter-id 2022-03-01 11:11:23 +01:00
Bond-009
2bc8383968 Merge pull request #7382 from crobibero/keyframe-extractor 2022-03-01 10:55:02 +01:00
Bill Thornton
055c63bdee Include played and unplayed results in the same next up request 2022-03-01 00:50:16 -05:00
Joshua M. Boniface
7c9aa63382 Merge pull request #6058 from ferferga/deprecate-queueitem 2022-02-28 23:54:50 -05:00
Cody Robibero
5e1f956fe0 Allow KeyframeExtractor to be localized 2022-02-28 20:59:36 -07:00
Cody Robibero
89c29a7ed8 Fix migration of DateTime to EF 2022-02-28 20:44:17 -07:00
Cody Robibero
fe99800bde Merge pull request #7221 from SenorSmartyPants/UserViewThumb 2022-02-28 20:17:30 -07:00
Cody Robibero
3c0c7572ef Merge pull request #7338 from mueslimak3r/hls-remove-seek-param 2022-02-28 20:16:19 -07:00
Cody Robibero
3f441a44ba Merge pull request #7374 from jellyfin/intel-ocl 2022-02-28 20:15:32 -07:00
Cody Robibero
aec1ee5869 Merge pull request #7375 from jellyfin/presets-nvenc 2022-02-28 20:15:14 -07:00
Cody Robibero
c0b02ff0e5 Merge pull request #7378 from thornbill/fix-default-home-sections 2022-02-28 20:15:04 -07:00
Cody Robibero
dc1b224667 Add JsonConstructor 2022-02-28 17:30:17 -07:00
Cody Robibero
fc5c6c0404 Use IFileSystem 2022-02-28 17:14:33 -07:00
Bill Thornton
f32b2cb592 Add resume book as default home section 2022-02-28 16:33:17 -05:00
Joe Rogers
1d367712bb Improve tests 2022-02-28 10:00:23 -07:00
Cody Robibero
c9d5cfff1d Update MediaBrowser.Providers/MediaInfo/MediaInfoResolver.cs
Co-authored-by: Joe Rogers <1337joe@users.noreply.github.com>
2022-02-28 09:58:11 -07:00
GermanCoding
847d705969 Update CONTRIBUTORS.md (adding myself) 2022-02-28 17:47:57 +01:00
GermanCoding
11bb834957 Remove superfluous "SoundHandler" from audio stream names 2022-02-28 17:44:23 +01:00
Cody Robibero
40e413d575 Only add internal files if the internal metadata path exists
Signed-off-by: Cody Robibero <cody@robibe.ro>
2022-02-28 08:22:52 -07:00
Bond-009
cd4d51a515 Merge pull request #7371 from jellyfin/dependabot/nuget/Moq-4.17.1 2022-02-28 16:12:16 +01:00
Cody Robibero
f1808f6ae4 Merge pull request #7369 from Bond-009/jellyplus 2022-02-28 08:09:59 -07:00
Nyanmisaka
9251c875b1 Update presets for NVENC encoder 2022-02-28 23:05:08 +08:00
Nyanmisaka
10282dc444 Update intel compute runtime to 22.08.22549 2022-02-28 22:50:27 +08:00
Nyanmisaka
3fb3d7159c Update intel compute runtime to 22.05.22297 2022-02-28 21:13:06 +08:00
dependabot[bot]
11092a72a4 Bump actions/setup-dotnet from 1 to 2
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 1 to 2.
- [Release notes](https://github.com/actions/setup-dotnet/releases)
- [Commits](https://github.com/actions/setup-dotnet/compare/v1...v2)

---
updated-dependencies:
- dependency-name: actions/setup-dotnet
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-28 12:06:19 +00:00
dependabot[bot]
ee24b85f49 Bump Moq from 4.16.1 to 4.17.1
Bumps [Moq](https://github.com/moq/moq4) from 4.16.1 to 4.17.1.
- [Release notes](https://github.com/moq/moq4/releases)
- [Changelog](https://github.com/moq/moq4/blob/main/CHANGELOG.md)
- [Commits](https://github.com/moq/moq4/compare/v4.16.1...v4.17.1)

---
updated-dependencies:
- dependency-name: Moq
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-28 12:01:22 +00:00
Bond_009
acf30e00ce Remove obsolete code for premium plugins 2022-02-28 00:46:34 +01:00
Joe Rogers
354f22d065 Add post filtering for theme song and video 2022-02-27 23:38:00 +01:00
Joe Rogers
175ddff169 Switch chapter id to long to not break on ffmpeg 5.0 2022-02-27 21:04:11 +01:00
Joshua M. Boniface
e26446f9c0 Merge pull request #7112 from stanionascu/bdiso-playback 2022-02-26 12:53:34 -05:00
Cody Robibero
d7cbb25d0b Merge pull request #7291 from aolszowka/aolszowka-EncodingHelperChanges 2022-02-26 10:52:35 -07:00
Ali Dastpour
536ad62ea8 Translated using Weblate (Persian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fa/
2022-02-26 08:31:06 -05:00
Bond-009
ce62a4465a Merge pull request #7349 from 1337joe/MediaInfoResolver-tests 2022-02-22 19:44:36 +01:00
Joe Rogers
a9a3f6bf02 Split match/rejected tests, add wider sampling of extensions 2022-02-22 15:13:44 +01:00
Joe Rogers
cf033b25f8 Require delimiter immediately after filename match 2022-02-21 22:27:28 +01:00
Joe Rogers
15053516f8 Rewrite tests for coverage and less duplication
Address minor warnings
Revert making GetInternalMetadataPath mockable
2022-02-21 22:25:58 +01:00
Joshua M. Boniface
59040bfa7d Merge pull request #7255 from Shadowghost/external-sub-audio 2022-02-21 12:42:49 -05:00
Cody Robibero
d1f6a7f497 Merge pull request #7344 from jellyfin/dependabot/nuget/Microsoft.NET.Test.Sdk-17.1.0 2022-02-21 07:37:28 -07:00
Bond_009
f50a250cd9 Optimize Guid comparisons
* Use Guid.Equals(Guid) instead of the == override
* Ban the usage of Guid.Equals(Object) to prevent accidental boxing
* Compare to default(Guid) instead of Guid.Empty
2022-02-21 14:15:09 +01:00
Isaac Gordezky
def8500dd0 Update MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
Co-authored-by: Cody Robibero <cody@robibe.ro>
2022-02-21 07:54:13 -05:00
dependabot[bot]
06f259001c Bump Microsoft.NET.Test.Sdk from 17.0.0 to 17.1.0
Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.0.0 to 17.1.0.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Commits](https://github.com/microsoft/vstest/compare/v17.0.0...v17.1.0)

---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-21 12:01:10 +00:00
SenorSmartyPants
bbac59c6d6 Rewatching next up (#7253) 2022-02-20 18:05:57 +01:00
Cody Robibero
a61b42f7ef Merge pull request #7332 from eyezak/transcode-reporting 2022-02-20 09:32:09 -07:00
Stanislav Ionascu
554d1b2ca8 Fix #7100 by catching the exception on opening invalid UDF images
When an invalid UDF image is opened by the UdfReader, it may throw
and exception. This change is to catch and log the exception.
2022-02-20 13:30:55 +00:00
Shadowghost
bbb3117f83 Update MediaBrowser.Providers/MediaInfo/MediaInfoResolver.cs
Co-authored-by: Bond-009 <bond.009@outlook.com>
2022-02-19 23:47:11 +01:00
Niels van Velzen
6a8a6a1325 Use sha hash instead of branch name for OpenAPI workflow head reference (#7340) 2022-02-19 17:36:53 +01:00
cameron
36cdeaa53c dont use noaccurate_seek for hls 2022-02-18 23:18:28 -08:00
Shadowghost
a36e34fbd2 fix(external-media): implement review suggestions 2022-02-18 22:19:33 +01:00
Shadowghost
719b707281 feat(external-media): refactor to generic provider, extend tests and file recognition, consolidate and extend NamingOptions 2022-02-18 22:19:33 +01:00
Joe Rogers
f1878c43a4 feat(external-media): add tests for external audio and subtitle provider 2022-02-18 22:19:33 +01:00
Shadowghost
ca5112f45a feat(external-media): refactor external subtitle and audio provider 2022-02-18 22:19:24 +01:00
Isaac Gordezky
151ddd400d [Bugfix] Provile bitStreamArgs for HLS fMP4
Enable the audio bitstream arguments to ffmpeg for both ts and fMP4 HLS streaming
2022-02-18 13:18:08 +00:00
Isaac Gordezky
48a7d3f48f [Bugfix] Report transcoding complete
Currently, when transcoding finishes it is not reported - leaving the UI with an incomplete transcode %
This change reports transcoding progress as empty / complete when the transcoding job finishes
2022-02-18 13:01:19 +00:00
Cody Robibero
b92e1baa3c Merge pull request #7326 from Bond-009/deadcode2 2022-02-17 18:07:49 -07:00
Bond_009
adad13b865 Remove some dead code 2022-02-17 08:15:26 +01:00
Cody Robibero
7ccf7e6157 Merge pull request #7322 from Bond-009/db2 2022-02-16 20:47:33 -07:00
Cody Robibero
9930efec22 Merge pull request #7321 from Bond-009/warn61 2022-02-16 20:47:22 -07:00
Maxr1998
0aaf2f470a Implement Comparers for (Parent)IndexNumber
Can be used in item queries to sort by ParentIndexNumber and IndexNumber (used for disc and track numbers for example).
2022-02-17 01:35:59 +01:00
Bond_009
23ea14aa27 Clean up SqliteItemRepository
* remove dead code
* reduce allocations
2022-02-15 22:27:38 +01:00
Bond_009
5732e6188c Fix some warnings 2022-02-15 18:59:46 +01:00
Lukáš Kucharczyk
5825a0572b Translated using Weblate (Czech)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/cs/
2022-02-15 01:13:23 -05:00
Cody Robibero
4ef0099598 Merge pull request #7233 from Bond-009/warn60 2022-02-14 16:57:00 -07:00
Cody Robibero
4acab00963 Merge pull request #7038 from Bond-009/serverdiscovery 2022-02-14 16:56:29 -07:00
Joshua M. Boniface
94b5334da5 Merge pull request #7290 from crobibero/dotnet-6.0.2 2022-02-14 11:01:55 -05:00
Victor Gambier
dbf9e49258 Increase timeout for subtitle extraction to 30min (#7153) 2022-02-14 16:33:11 +01:00
Bond_009
5d28c5547e Fix indentation 2022-02-14 16:31:07 +01:00
Bond_009
dbd7be091d Fix MediaStreamSelector 2022-02-14 15:03:08 +01:00
Bond_009
8b2556adba Fix display preferences 2022-02-14 14:46:04 +01:00
Bond_009
1c14c86b20 Fix some warnings 2022-02-14 14:46:04 +01:00
Bond_009
3cb49d6df0 Fix option to disable server discovery 2022-02-14 14:39:33 +01:00
dependabot[bot]
68e7072698 Bump MimeTypes from 2.2.1 to 2.3.0 (#7309)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-14 14:14:04 +01:00
Bond-009
69e7deb07d Merge pull request #7300 from cvium/fix_keepreading 2022-02-12 20:24:02 +01:00
cvium
8ec71c094a Change KeepReading to StopReading and use bytes read as an indicator 2022-02-12 09:51:47 +01:00
dottokuya
8a2ebae74d Translated using Weblate (Vietnamese)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/vi/
2022-02-11 23:21:28 -05:00
Cody Robibero
603b6fe173 Merge pull request #7054 from matthew-jones-uk/disable-embedded-subs 2022-02-11 13:20:37 -07:00
knackebrot
52c61bd06f Add option to change unix socket permissions
There is probably no way to do it when creating the socket
2022-02-10 02:07:12 +01:00
Nils Fürniß
ab40554759 add extracting attachments for ffmpeg to burn subs 2022-02-10 01:01:08 +01:00
Matthew Jones
b7cab46b4a Added values to EmbeddedSubtitleOptions enum 2022-02-09 23:33:46 +00:00
Bond-009
bb7916767c Merge pull request #7286 from daullmer/sonarr-thumb 2022-02-09 19:09:53 +01:00
David Ullmer
a00e6ff426 Update tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2022-02-09 13:39:39 +01:00
Cody Robibero
b98cc71c3b Update to dotnet 6.0.2
Signed-off-by: Cody Robibero <cody@robibe.ro>
2022-02-08 17:36:20 -07:00
Cody Robibero
103a8e69a7 Merge pull request #7282 from jellyfin/dependabot/nuget/System.Linq.Async-6.0.1
Bump System.Linq.Async from 5.1.0 to 6.0.1
2022-02-08 05:43:53 -07:00
Cody Robibero
75cdfe4daf Merge pull request #7283 from jellyfin/dependabot/nuget/coverlet.collector-3.1.2
Bump coverlet.collector from 3.1.1 to 3.1.2
2022-02-08 05:43:08 -07:00
Cody Robibero
d855b6872a Merge pull request #7284 from jellyfin/dependabot/nuget/prometheus-net.DotNetRuntime-4.2.3
Bump prometheus-net.DotNetRuntime from 4.2.2 to 4.2.3
2022-02-08 05:42:46 -07:00
David Ullmer
fdfcb45c2a Add regression test for #7285 2022-02-08 09:09:33 +01:00
David Ullmer
7885167f54 Fix nfo thumb tags without aspect 2022-02-08 09:08:35 +01:00
Ace Olszowka
ea7e5e639d Fix h264_v4l2m2m acceleration in Raspberry Pi 4 2022-02-07 20:41:07 -07:00
dependabot[bot]
08e90039b1 Bump prometheus-net.DotNetRuntime from 4.2.2 to 4.2.3
Bumps [prometheus-net.DotNetRuntime](https://github.com/djluck/prometheus-net.DotNetRuntime) from 4.2.2 to 4.2.3.
- [Release notes](https://github.com/djluck/prometheus-net.DotNetRuntime/releases)
- [Commits](https://github.com/djluck/prometheus-net.DotNetRuntime/compare/4.2.2...4.2.3)

---
updated-dependencies:
- dependency-name: prometheus-net.DotNetRuntime
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-07 12:01:14 +00:00
dependabot[bot]
7649391b9d Bump coverlet.collector from 3.1.1 to 3.1.2
Bumps [coverlet.collector](https://github.com/coverlet-coverage/coverlet) from 3.1.1 to 3.1.2.
- [Release notes](https://github.com/coverlet-coverage/coverlet/releases)
- [Commits](https://github.com/coverlet-coverage/coverlet/commits)

---
updated-dependencies:
- dependency-name: coverlet.collector
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-07 12:01:11 +00:00
dependabot[bot]
0c89459d5b Bump System.Linq.Async from 5.1.0 to 6.0.1
Bumps [System.Linq.Async](https://github.com/dotnet/reactive) from 5.1.0 to 6.0.1.
- [Release notes](https://github.com/dotnet/reactive/releases)
- [Commits](https://github.com/dotnet/reactive/compare/ixnet-v5.1.0...ixnet-v6.0.1)

---
updated-dependencies:
- dependency-name: System.Linq.Async
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-07 12:01:03 +00:00
Cody Robibero
b6489e73ab Merge pull request #7241 from Bond-009/async5 2022-02-06 15:25:48 -07:00
Cody Robibero
10d52d16a8 Fix invalid cref (#7277) 2022-02-06 22:21:17 +01:00
Emil Manea
f3c3402984 Translated using Weblate (Romanian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ro/
2022-02-04 16:13:20 -05:00
SenorSmartyPants
2b769aae69 TV extras (#7178) 2022-02-04 20:44:38 +01:00
Cody Robibero
c16d71562e Prevent additional errors on startup/shutdown (#6788) 2022-02-04 20:36:17 +01:00
Cody Robibero
a2127a48ef Remove unused docker volumes (#7030) 2022-02-02 23:27:46 +01:00
SenorSmartyPants
509d66dcb5 Fix #7147: Don't return subtitles in mismatched format (#7149) 2022-02-02 23:24:10 +01:00
Nyanmisaka
6c53420fe3 Fix the broken fMP4 main playlist (#7263) 2022-02-01 22:30:19 +01:00
dependabot[bot]
6af7d5445f Bump coverlet.collector from 3.1.0 to 3.1.1 (#7266)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-01 22:29:41 +01:00
Cody Robibero
f863ca1f2d Merge pull request #7245 from h1dden-da3m0n/chore/stale-check-workflow 2022-01-28 08:12:44 -07:00
Cody Robibero
e5701c396a Merge pull request #6436 from daullmer/splashscreen 2022-01-28 08:12:21 -07:00
Claus Vium
488ce51032 Remove some allocations (#7246) 2022-01-28 12:21:40 +01:00
Bond-009
42724ef411 Merge pull request #7257 from Shadowghost/slash-artists 2022-01-28 12:17:08 +01:00
Shadowghost
4a3f1a51d2 chore(artist-split): add more artists to split whitelist 2022-01-27 22:01:40 +01:00
abdulla
83605affa0 Translated using Weblate (Uyghur)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ug/
2022-01-27 07:13:16 -05:00
Matthew Jones
91d143d6ee Changed boolean options to enums 2022-01-26 16:09:05 +00:00
abdulla
29f92724ef Added translation using Weblate (Uyghur) 2022-01-26 05:56:56 -05:00
K3rnelPan1c
614abddd64 remove obsolete permissions block
we use the JF_BOT_TOKEN PAT and not the default GITHUB_TOKEN
2022-01-25 22:53:09 +01:00
K3rnelPan1c
fabe7e1fb9 add org filter to stale workflow 2022-01-25 18:32:46 +01:00
Yohann Yo
887beee614 Translated using Weblate (French)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fr/
2022-01-25 11:29:36 -05:00
K3rnelPan1c
0c665af124 change PAT use for stale action 2022-01-23 18:19:39 +01:00
h1dden-da3m0n
28f4d574f7 add stale issue check workflow
this should replace the functionality of the discontinued stale-bot
2022-01-23 17:02:41 +01:00
Jayson Reis
09b8cde6aa fix: Avoid opening read connections without mutexes 2022-01-23 11:59:12 +01:00
Cody Robibero
ea3d79c0eb Merge pull request #7235 from Bond-009/async4 2022-01-22 15:52:12 -07:00
Cody Robibero
3c746f2743 Merge pull request #7236 from Bond-009/taskcompletionsource 2022-01-22 15:46:19 -07:00
Cody Robibero
da49437549 Merge pull request #7238 from 1337joe/ffprobe-metadata-merge 2022-01-22 15:46:04 -07:00
Cody Robibero
26ba99e420 Merge pull request #7239 from nielsvanvelzen/parent-guid 2022-01-22 15:44:55 -07:00
Bond_009
e7be01d7a5 Flush to disk async where possible 2022-01-22 23:36:42 +01:00
Jayson Reis
2e4dd02f76 chore: Add a read only connection for routes like Shows/NextUp 2022-01-22 21:52:30 +00:00
Niels van Velzen
2afcaa6ae1 Use Guid for BaseItemDto parent ids 2022-01-22 22:29:02 +01:00
Joe Rogers
fbd243e315 Make ffprobe consistent with MetadataService.MergeData 2022-01-22 21:59:17 +01:00
Bond-009
4f1eed862e Merge pull request #7234 from nielsvanvelzen/baseitemperson-guid 2022-01-22 17:08:02 +01:00
Bond_009
832da133d8 Always create TaskCompletionSource<T> with TaskCreationOptions.RunContinuationsAsynchronously 2022-01-22 17:06:57 +01:00
Bond_009
2dcb2f8a9f Ban the usage of Task.Result
If the calling function can't be made async easily you can still use
.GetAwaiter().GetResult(), which is way easier to find in the future
2022-01-22 16:48:31 +01:00
Niels van Velzen
e86f778c05 Use Guid for BaseItemPerson.Id 2022-01-22 15:46:12 +01:00
Bond-009
cd675475bc Merge pull request #7225 from crobibero/query-result 2022-01-21 19:50:08 +01:00
Cody Robibero
34ee6d82fb Merge pull request #6600 from cvium/keyframe_extraction_v1 2022-01-20 08:54:40 -07:00
Cody Robibero
a4246648f4 Merge pull request #7219 from 1337joe/tmdb-image-provider-logo 2022-01-20 08:54:07 -07:00
Cody Robibero
ee43b5117d Merge pull request #7217 from SenorSmartyPants/LibraryImages 2022-01-20 08:53:53 -07:00
Cody Robibero
a60cb280a3 Properly populate QueryResult 2022-01-20 08:53:06 -07:00
Joe Rogers
375903b215 Bump TMDbLib version 2022-01-20 11:43:26 +01:00
Lukáš Kucharczyk
cd4587b43f Translated using Weblate (Czech)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/cs/
2022-01-20 03:13:14 -05:00
SenorSmartyPants
5d9e1bfcea Shuffle items with images
They were always returning in the same order so thumb would never change.
2022-01-19 19:16:36 -06:00
SenorSmartyPants
b15ab397c7 User Backdrop for UserView, like CollectionFolder 2022-01-19 19:15:44 -06:00
Bond-009
3aeae150f8 Merge pull request #7176 from dmitrylyzo/fix-trailers-1 2022-01-19 22:47:08 +01:00
Claus Vium
8b36bc0ade Merge pull request #7203 from 1337joe/fix-resolving-local-alternates
Fix resolving local alternates
2022-01-19 14:36:50 +01:00
Joe Rogers
239b516659 Add TMDb logo handling 2022-01-19 09:54:52 +01:00
SenorSmartyPants
5c3119cf02 Generate cover image for music video type libraries. 2022-01-18 19:46:03 -06:00
Claus Vium
1a32153a31 Merge pull request #7197 from dmitrylyzo/fix-max-resolution
Fix maximum video resolution for dynamic HLS controller
2022-01-18 07:54:48 +01:00
oledfish
47269d5ec6 Add all TMDB episode orders 2022-01-18 01:02:45 -03:00
oledfish
3b075a5802 Merge branch 'jellyfin:master' into additional-episode-orders 2022-01-16 21:33:18 -03:00
Bond-009
ef0708d876 Merge pull request #7078 from 1337joe/metadata-merge-data 2022-01-16 23:17:40 +01:00
Joe Rogers
8b706cebef Add alternate resolver test, generate extra folder names 2022-01-16 23:00:30 +01:00
Joe Rogers
e762454787 Restore resolver that handles alternate videos
Co-authored-by: Cody Robibero <cody@robibe.ro>
2022-01-16 22:59:14 +01:00
cvium
90736ee346 Add pagination and fixes 2022-01-16 22:10:22 +01:00
Dmitry Lyzo
000b7ba62b Fix maximum video resolution for dynamic HLS controller 2022-01-16 21:42:04 +03:00
Joe Rogers
f87e780fb5 Address review comments
Co-authored-by: Bond-009 <bond.009@outlook.com>
2022-01-16 13:21:24 +01:00
Dmitry Lyzo
60fe77c089 Remove unnecessary array allocation
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2022-01-16 13:34:52 +03:00
Suphanath Kaewboonrung
7500c2b28b Translated using Weblate (Thai)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/th/
2022-01-16 03:13:12 -05:00
Claus Vium
1d7ec1071f Merge pull request #7186 from 1337joe/extra-rule-reorder
Order extra rules so directory takes precedence over naming
2022-01-15 20:24:14 +01:00
Joe Rogers
19b9646d72 Add -extra suffix for consistency 2022-01-15 15:43:06 +01:00
Joe Rogers
f11fa59b15 Order rules so directory takes precedence over naming 2022-01-15 15:16:11 +01:00
Cody Robibero
d88e39b71d Merge pull request #7185 from dmitrylyzo/warn-sa1642
Fix SA1642 warning
2022-01-15 06:32:07 -07:00
Dmitry Lyzo
54549cd5b5 Remove unnecessary array allocation
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2022-01-15 15:54:14 +03:00
Dmitry Lyzo
ea1f3fe6bd Fix SA1642 warning 2022-01-15 15:33:54 +03:00
Cody Robibero
ee32e46dde Merge pull request #7172 from SenorSmartyPants/SeasonName 2022-01-14 13:15:53 -07:00
Dmitry Lyzo
5aa748058e Fix duplication of local trailers 2022-01-14 23:06:45 +03:00
Dmitry Lyzo
112db30ff2 Fix duplication of remote trailers 2022-01-14 22:53:54 +03:00
Bond-009
3b486fc0ee Merge pull request #7175 from dmitrylyzo/fix-self-locking 2022-01-14 20:41:59 +01:00
Dmitry Lyzo
f28384ba30 Ignore JSON serialization for special features of movie.
When refreshing the metadata of the video with a local trailer, the server gets
stuck trying to read the database and save the item at the same time.
2022-01-14 22:15:14 +03:00
Cody Robibero
ee46754238 Fix build and clean up 2022-01-14 08:14:31 -07:00
Fernando Fernández
5df6058a8e Add FullNowPlayingQueue property 2022-01-14 14:40:27 +00:00
Matthew Jones
61d8d40a4a Added type options to disable embedded subs 2022-01-14 11:25:08 +00:00
Matt
126274c4ea Add video path to DisableEmbeddedSubtitles log
Co-authored-by: Cody Robibero <cody@robibe.ro>
2022-01-14 11:25:08 +00:00
Matthew Jones
3f7bd7b63e Changed DisableEmbeddedSubtitles logging to debug 2022-01-14 11:25:08 +00:00
Matthew Jones
aeed255bbf Update CONTRIBUTORS.md 2022-01-14 11:25:08 +00:00
Matthew Jones
4df7590e52 Add DisableEmbeddedSubtitles setting
Disables embedded subs being added to metadata
2022-01-14 11:25:08 +00:00
Claus Vium
70751722d2 Apply suggestions from code review
Co-authored-by: Cody Robibero <cody@robibe.ro>
2022-01-14 08:24:15 +01:00
SenorSmartyPants
c32db3ea26 Fix build error 2022-01-13 22:51:38 -06:00
SenorSmartyPants
a19b6a7f61 Config option to import season name from TMDB 2022-01-13 22:31:37 -06:00
Joe Rogers
62dc4a79ff Fix comment typo
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2022-01-13 23:21:02 +01:00
Dzonkins
07e9568de8 Translated using Weblate (Serbian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sr/
2022-01-12 16:13:11 -05:00
cvium
7ba9a24736 Fix bool 2022-01-12 20:10:35 +01:00
cvium
b9d4cbf3e8 Fix progress 2022-01-12 18:35:55 +01:00
Claus Vium
768b76b999 Apply suggestions from code review
Co-authored-by: Cody Robibero <cody@robibe.ro>
2022-01-12 17:27:02 +01:00
Cody Robibero
a0f248e200 Merge pull request #7134 from adavier/trakt-episode-links 2022-01-11 16:11:25 -07:00
cvium
f92806c246 Use local var for the length 2022-01-11 23:32:39 +01:00
cvium
9a5a079f42 Add progress report 2022-01-11 23:31:55 +01:00
cvium
6ffa9539bb Refactor and add scheduled task 2022-01-11 23:30:30 +01:00
Cody Robibero
307679afef Merge pull request #7131 from Bond-009/warn58 2022-01-10 17:05:20 -07:00
Cody Robibero
8a36fe7ed5 Use png for storage 2022-01-10 17:01:17 -07:00
Cody Robibero
0d335082c8 suggestions from review 2022-01-10 10:59:32 -07:00
Cody Robibero
6520ad03f0 Fix release build 2022-01-10 08:30:55 -07:00
Cody Robibero
ecb73168b3 Suggestions from review 2022-01-10 08:26:30 -07:00
Bond-009
4823e68a94 Merge pull request #7151 from jellyfin/dependabot/nuget/FsCheck.Xunit-2.16.4 2022-01-10 14:19:16 +01:00
dependabot[bot]
88e02c5290 Bump FsCheck.Xunit from 2.16.3 to 2.16.4
Bumps [FsCheck.Xunit](https://github.com/fsharp/FsCheck) from 2.16.3 to 2.16.4.
- [Release notes](https://github.com/fsharp/FsCheck/releases)
- [Changelog](https://github.com/fscheck/FsCheck/blob/master/FsCheck%20Release%20Notes.md)
- [Commits](https://github.com/fsharp/FsCheck/compare/2.16.3...2.16.4)

---
updated-dependencies:
- dependency-name: FsCheck.Xunit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-10 12:01:16 +00:00
Bond_009
05836c8cd3 Fix warning SA1414 and CA1849 2022-01-10 10:57:32 +01:00
Cody Robibero
d24683f0ab Merge pull request #7141 from nyanmisaka/seek-audio
Seek the external audio stream
2022-01-09 06:57:01 -07:00
nyanmisaka
8c3f98f41b Also seek the external audio stream 2022-01-09 13:49:40 +08:00
SenorSmartyPants
d5e7e75421 Remove unused httpContext parameter 2022-01-08 19:53:53 -06:00
Cody Robibero
54d24ddeaf Merge pull request #6866 from Bond-009/timeout 2022-01-08 10:53:58 -07:00
Cody Robibero
188f9632f8 Merge pull request #7138 from nyanmisaka/10bit-boxes 2022-01-08 08:55:52 -07:00
nyanmisaka
ddc2569258 Fix the wrong logic in HEVC VP9 10bit hwdec boxes 2022-01-08 22:31:45 +08:00
Joe Rogers
b43f46d5c9 Make identify flag describe purpose, not source 2022-01-08 14:03:59 +01:00
Cody Robibero
620a5d5e83 Merge pull request #7136 from 1337joe/fix-show-library-scan
Fix stuck show library scans
2022-01-08 04:46:19 -07:00
Cody Robibero
9b1965b48a Merge pull request #7101 from Bond-009/imagejpg
Remove incorrect mime type image/jpg
2022-01-08 04:45:58 -07:00
SenorSmartyPants
3ea54a8009 Remove isHeadRequest from GetStaticFile method signatures 2022-01-07 18:21:48 -06:00
SenorSmartyPants
bd2bec4d4a Remove special HTTP HEAD processing
removing this allows HTTP 206 Partial Content responses and lets some clients(popcorn hour namely) play videos from JF.
2022-01-07 16:29:22 -06:00
Joe Rogers
a26509a98a Keep from serializing trailers into database 2022-01-07 22:33:31 +01:00
Aragon
ce61dff4aa Translated using Weblate (Hebrew)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/he/
2022-01-07 15:13:09 -05:00
adavier
9574d13059 Implement trakt episode links using the implementation from Series.cs
The code is the same as `MediaBrowser.Controller/Entities/TV/Series.cs`, using the imdbID to generate Trakt links.
The trakt url for episodes is `https://trakt.tv/episodes/{0}`.
2022-01-07 19:47:36 +00:00
Anthony Lavado
565ebbb643 Merge pull request #7132 from Bond-009/readme
Update README.md
2022-01-07 09:11:15 -05:00
Bond_009
4234a657c8 Update README.md 2022-01-07 15:06:49 +01:00
Bond_009
3ab0afdc6b Remove task cancellation hacks 2022-01-07 11:24:36 +01:00
Bond-009
98962cc21f Merge pull request #7129 from crobibero/null-check 2022-01-07 10:31:19 +01:00
cvium
c658a883a2 Merge branch 'master' into keyframe_extraction_v1
# Conflicts:
#	Jellyfin.Api/Controllers/DynamicHlsController.cs
#	MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
#	MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
2022-01-07 10:23:22 +01:00
Cody Robibero
82260e22a2 ADd more null check 2022-01-06 21:49:13 -07:00
Cody Robibero
6b4f5a8663 Merge pull request #7118 from crobibero/audio-stream-null 2022-01-06 10:36:10 -07:00
Shin Khant Maung
f8a6b3b27b Translated using Weblate (Burmese)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/my/
2022-01-06 10:18:40 -05:00
Cody Robibero
904efeaddc Add null check for audio stream 2022-01-06 08:15:37 -07:00
Cody Robibero
b6b7a89bf2 Merge pull request #7121 from Bond-009/warn57 2022-01-05 16:18:08 -07:00
Bond_009
77c615ba42 Error on SA1316 2022-01-05 10:58:57 +01:00
Joshua M. Boniface
a2b51d551f Merge pull request #7115 from joshuaboniface/i-hate-ci-in-code 2022-01-04 20:02:17 -05:00
Joshua M. Boniface
e300b98573 Remove bump-version junk
This didn't work, and won't matter for beta1 so just scrap it.
2022-01-04 19:58:20 -05:00
WWWesten
75a46a1072 Translated using Weblate (Burmese)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/my/
2022-01-04 18:55:29 -05:00
hoanghuy309
6aa37ebb8f Translated using Weblate (Vietnamese)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/vi/
2022-01-04 18:55:29 -05:00
Joshua M. Boniface
072526d798 Merge pull request #7107 from Bond-009/namingtests 2022-01-04 18:17:16 -05:00
Joshua M. Boniface
4da240d731 Merge pull request #7105 from 1337joe/specials-folder-lock 2022-01-04 18:16:57 -05:00
Cody Robibero
b5b4e2ea89 Merge pull request #7109 from crobibero/yep
Use provided SortOrder
2022-01-04 15:53:33 -07:00
Cody Robibero
7d63377194 Use provided SortOrder 2022-01-04 13:07:51 -07:00
Bond_009
71ebe220f0 Speed up Jellyfin.Naming.Tests
In my limited testing this saves ~4 seconds, from 19 to 15 seconds (in
        Xunit itself)
2022-01-04 17:59:30 +01:00
Joe Rogers
3eb4bbbb86 Respect lock state when updating season 0 name 2022-01-04 16:58:14 +01:00
Cody Robibero
360fd70fc7 Clean up 2022-01-04 08:44:03 -07:00
Joe Rogers
b17fe35e2e Clean up list handling
Co-authored-by: Cody Robibero <cody@robibe.ro>
2022-01-04 16:25:36 +01:00
David Ullmer
9e0958d822 Apply suggestions from code review 2022-01-04 08:20:16 -07:00
David Ullmer
9e23af5636 Add missing xml doc 2022-01-04 08:20:16 -07:00
David Ullmer
6ad020acb2 Include Splashscreen url in the branding endpoint 2022-01-04 08:20:16 -07:00
David Ullmer
c70452b4a4 Add missing response code documentation 2022-01-04 08:20:16 -07:00
David Ullmer
045ef4b726 Generate Splashscreen during RefreshMediaLibrary scheduled task 2022-01-04 08:20:16 -07:00
David Ullmer
68db3be0e7 Remove darkening filter from Splashscreen
Using the foregroundLayer parameter has the same effect
2022-01-04 08:20:16 -07:00
David Ullmer
e026ba84c5 Add Splashscreen API endpoint to ImageController 2022-01-04 08:20:16 -07:00
David Ullmer
3fb3ee074a Remove splashscreen generation from IImageEncoder and add IImageGenerator 2022-01-04 08:20:16 -07:00
David Ullmer
0fd4ff4451 Always use 1080p, add max parental rating 2022-01-04 08:20:16 -07:00
David Ullmer
c934269a6e Add api controller for splashscreen 2022-01-04 08:20:16 -07:00
David Ullmer
4ba168c8a1 Add splashscreen builder 2022-01-04 08:20:16 -07:00
Bond_009
dc222b75c5 Remove incorrect mime type image/jpg 2022-01-04 10:40:16 +01:00
Cody Robibero
c6a1dcf420 Merge pull request #7080 from crobibero/ws-token 2022-01-03 17:48:21 -07:00
Cody Robibero
fddcaf17e1 Merge pull request #7092 from crobibero/orderby-flip 2022-01-03 17:48:11 -07:00
Cody Robibero
b9cd9487bd Merge pull request #7095 from crobibero/gif 2022-01-03 17:48:02 -07:00
Cody Robibero
fcb8ff7c0f Merge pull request #7052 from crobibero/image.jpeg 2022-01-03 17:47:52 -07:00
Cody Robibero
e51777fe4b Merge pull request #7093 from ilaborde/fix-5355 2022-01-03 17:16:04 -07:00
Joe Rogers
1dfbeae045 Embed ProviderUtils into MetadataService 2022-01-04 00:44:03 +01:00
Joe Rogers
19164378f2 Clean up warnings 2022-01-04 00:21:45 +01:00
Joe Rogers
c81d2e9dec Remove existing images when applying identify 2022-01-03 23:41:13 +01:00
Joe Rogers
ce66df2c92 Clean up warnings, simplify 2022-01-03 22:59:58 +01:00
Cody Robibero
6d299eed49 Don't transform gif 2022-01-03 12:23:55 -07:00
ignacio laborde
8952819494 remove unnecessary ToList in DlnaManager 2022-01-03 15:31:08 -03:00
Cody Robibero
f802763e8f Reverse all order-by 2022-01-03 07:59:50 -07:00
Cody Robibero
37061e5b6b Merge pull request #7091 from jellyfin/dependabot/nuget/Serilog.Sinks.Graylog-2.3.0
Bump Serilog.Sinks.Graylog from 2.2.2 to 2.3.0
2022-01-03 06:02:16 -07:00
dependabot[bot]
1c5c0ebb0f Bump Serilog.Sinks.Graylog from 2.2.2 to 2.3.0
Bumps [Serilog.Sinks.Graylog](https://github.com/whir1/serilog-sinks-graylog) from 2.2.2 to 2.3.0.
- [Release notes](https://github.com/whir1/serilog-sinks-graylog/releases)
- [Commits](https://github.com/whir1/serilog-sinks-graylog/commits)

---
updated-dependencies:
- dependency-name: Serilog.Sinks.Graylog
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-03 12:00:59 +00:00
Weevild
0c4b5a5ce8 Translated using Weblate (Swedish)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sv/
2022-01-02 17:05:58 -05:00
WWWesten
65bf393efb Translated using Weblate (Russian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ru/
2022-01-02 17:05:58 -05:00
Shadowghost
38d4300309 Translated using Weblate (German)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/de/
2022-01-02 17:05:58 -05:00
Joe Rogers
29755c9384 Merge a couple tests, extract duplicate code 2022-01-02 22:24:04 +01:00
Joe Rogers
608a91162a Add test for #6830 2022-01-02 22:23:47 +01:00
Joe Rogers
853ef727da Add refresh flag to remove existing data/images
Fixes #7040
2022-01-02 22:21:05 +01:00
Bond-009
11d0c6827f Merge pull request #7058 from cvium/the_most_important_feature 2022-01-02 12:31:20 +01:00
Cody Robibero
0765fd568f Use IAuthorizationContext for websocket 2022-01-01 12:34:22 -07:00
cvium
28c2ac9cc0 Remove file extension filter and fix build 2022-01-01 20:07:03 +01:00
Claus Vium
58b9e5af79 Update Emby.Server.Implementations/Library/Resolvers/GenericVideoResolver.cs
Co-authored-by: Joe Rogers <1337joe@users.noreply.github.com>
2022-01-01 14:52:54 +01:00
Claus Vium
1725b2ee69 Merge pull request #7076 from crobibero/providerid 2021-12-31 21:03:30 +01:00
Cody Robibero
25abe479eb Add ability to search by - 2021-12-31 08:51:50 -07:00
Claus Vium
1b9cb8cca6 Merge pull request #7075 from crobibero/sort 2021-12-31 16:32:26 +01:00
Cody Robibero
c3071f8996 Fix orderby query 2021-12-31 08:03:08 -07:00
Joshua M. Boniface
dc9e1ece29 Merge pull request #7070 from thornbill/fix-ci-builds 2021-12-31 03:47:06 -05:00
Joe Rogers
76e640b0b9 Add tests and documentation for ProviderUtils 2021-12-31 00:10:35 +01:00
Bill Thornton
226a43619f Fix fedora build version 2021-12-30 16:54:59 -05:00
WWWesten
53447976f0 Added translation using Weblate (Burmese) 2021-12-30 16:15:37 -05:00
Bond-009
b2a2bdb088 Merge pull request #7049 from crobibero/warn40219 2021-12-30 13:50:39 +01:00
WWWesten
bb713d1931 Translated using Weblate (Malayalam)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ml/
2021-12-28 10:05:57 -05:00
WWWesten
73a5fc6e26 Translated using Weblate (Thai)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/th/
2021-12-28 10:05:57 -05:00
WWWesten
019b631d7b Translated using Weblate (Urdu (Pakistan))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ur_PK/
2021-12-28 10:05:57 -05:00
WWWesten
6f4a0683ed Translated using Weblate (Lithuanian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/lt/
2021-12-28 10:05:57 -05:00
WWWesten
5a1b347b83 Translated using Weblate (Korean)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ko/
2021-12-28 10:05:57 -05:00
WWWesten
828bf1f0ac Translated using Weblate (Hebrew)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/he/
2021-12-28 10:05:57 -05:00
WWWesten
4ec7488bab Translated using Weblate (German (Swiss))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/gsw/
2021-12-28 10:05:57 -05:00
WWWesten
7ad1527fd0 Translated using Weblate (Greek)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/el/
2021-12-28 10:05:57 -05:00
WWWesten
80fce87f7a Translated using Weblate (Catalan)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ca/
2021-12-28 10:05:57 -05:00
Joe Rogers
e3a7c9238d Pull default MergeData implementation to parent 2021-12-28 15:12:09 +01:00
Bond-009
2ab3bf97ef Merge pull request #7059 from crobibero/device-order 2021-12-28 13:56:51 +01:00
Cody Robibero
57db188c2e Fix device ordering 2021-12-27 16:43:29 -07:00
cvium
2749509f00 Use dedicated resolvers for extras 2021-12-28 00:37:40 +01:00
Cody Robibero
7bfc6b5679 Remove more warnings 2021-12-27 07:38:06 -07:00
Cody Robibero
251b9a5235 Merge pull request #7004 from Bond-009/cleanup2 2021-12-27 07:33:11 -07:00
Bond_009
ea8f40e84a More cleanup 2021-12-27 14:20:05 +00:00
Bond-009
4441513ca4 Merge pull request #7055 from crobibero/fix-build-589710 2021-12-27 11:48:51 +00:00
Cody Robibero
ebbde383e8 Fix analysis issues 2021-12-26 11:08:43 -07:00
Cody Robibero
78bb581f0c Merge pull request #6934 from nyanmisaka/hwa
HWA pipeline refactor, AMD/Intel/Nvidia full hardware filtering support, AV1 hwdec
2021-12-26 17:32:06 +00:00
Cody Robibero
a615f87680 Merge pull request #7044 from 1337joe/fix-trailers-v2
Fix trailers v2
2021-12-25 23:31:46 +00:00
Cody Robibero
d594f81f65 Merge pull request #7048 from Bond-009/warn56 2021-12-25 18:46:08 +00:00
Cody Robibero
6804624c15 Add image/jpg to extension lookup 2021-12-25 11:41:39 -07:00
Joe Rogers
cf29aae690 Add rule to pick up theme videos 2021-12-24 21:21:19 +00:00
Joe Rogers
c0ab54f0bd Fix resolved type for Trailers 2021-12-24 21:21:19 +00:00
WWWesten
60e75f7b70 Translated using Weblate (Welsh)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/cy/
2021-12-24 13:05:54 -05:00
itsddpanda
17e6bd5f88 Translated using Weblate (Hindi)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/hi/
2021-12-24 13:05:54 -05:00
WWWesten
42c661e30f Translated using Weblate (Urdu (Pakistan))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ur_PK/
2021-12-24 13:05:54 -05:00
blob03
9f5873b8c4 Translated using Weblate (French)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fr/
2021-12-24 13:05:54 -05:00
Bond_009
cbfa355e31 Update StyleCop 2021-12-24 18:28:27 +01:00
nyanmisaka
728a5988b3 Merge remote-tracking branch 'origin/master' into hwa 2021-12-25 00:33:17 +08:00
Bond-009
2e7d173188 Merge pull request #7047 from Bond-009/fixbuild2 2021-12-24 15:42:19 +00:00
Bond_009
ec2645c0c0 Fix build 2021-12-24 16:35:57 +01:00
nyanmisaka
7db753d247 reduce tonemap cpu usage, add deint and AR support in thumbnails
Co-authored-by: Orry Verducci <orry@orryverducci.co.uk>
2021-12-24 17:03:57 +08:00
Claus Vium
d0832c60d4 Merge DynamicHlsController and VideoHlsController (#119)
* Merge DynamicHlsController and VideoHlsController

Co-authored-by: Nyanmisaka <nst799610810@gmail.com>
2021-12-24 17:03:57 +08:00
nyanmisaka
b2d85a02c2 Apply suggestions from code review
Co-authored-by: Cody Robibero <cody@robibe.ro>
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
Co-authored-by: Bond_009 <bond.009@outlook.com>
2021-12-24 17:03:57 +08:00
nyanmisaka
4b9c84c52e EncodingHelper hwaccel pipelines refactor
separate the HW pipeline according to HWA method for maintainability.
2021-12-24 17:03:57 +08:00
Claus Vium
daa76d3d34 Merge pull request #7042 from crobibero/fix-build 2021-12-24 10:00:43 +01:00
Cody Robibero
599fc9e671 Merge pull request #5836 from BaronGreenback/comparisons 2021-12-24 02:43:18 +00:00
Cody Robibero
17f43c8e01 Update Jellyfin.Api/Controllers/VideoHlsController.cs 2021-12-24 02:42:43 +00:00
Cody Robibero
634ce40c2f Merge branch 'master' into comparisons 2021-12-24 02:41:50 +00:00
Cody Robibero
b5459f49d3 Merge pull request #5009 from MrTimscampi/studios-images-plugin 2021-12-24 02:40:59 +00:00
Cody Robibero
932c2c6665 Fix config.html 2021-12-23 19:40:24 -07:00
Cody Robibero
a04ab6b876 Merge branch 'master' into studios-images-plugin
# Conflicts:
#	MediaBrowser.Providers/MediaBrowser.Providers.csproj
2021-12-23 19:38:10 -07:00
Cody Robibero
a8a8ce4e7b Fix build from PR merging 2021-12-23 19:27:51 -07:00
Cody Robibero
8c7dd0a691 Merge pull request #6819 from cvium/why_should_we_use_the_imageinfo_when_we_can_guess 2021-12-24 02:02:37 +00:00
Cody Robibero
55b429edb7 Merge pull request #6920 from marius-luca-87/subtitle_drop 2021-12-24 02:01:44 +00:00
Cody Robibero
cecfdeeec3 Merge branch 'master' into unharden-for-lxc 2021-12-24 02:01:06 +00:00
Cody Robibero
076a13abeb Merge pull request #7029 from cvium/allocations_maybe 2021-12-24 01:59:25 +00:00
Cody Robibero
259bc231d6 Merge pull request #6867 from yresquirol/related-media 2021-12-24 01:59:11 +00:00
Cody Robibero
7774cb2067 Update Jellyfin.Api/Controllers/LibraryController.cs 2021-12-23 20:46:27 +00:00
Cody Robibero
00211ca056 Merge pull request #7028 from cvium/everything_went_wrong 2021-12-22 17:57:00 +00:00
Cody Robibero
ca4769ab68 Merge pull request #7035 from cvium/force_remux_or_transcode 2021-12-21 11:23:02 -07:00
Bond-009
84ac692312 Merge pull request #7034 from cvium/dont_die 2021-12-21 14:57:04 +00:00
cvium
a7a7173cd5 Force a remux/transcode with external audio files 2021-12-21 14:35:58 +01:00
cvium
c86b064f80 Catch HttpRequestException when saving images from local provider 2021-12-21 12:29:09 +01:00
cvium
05c8834a3a Don't cache special feature ids 2021-12-21 00:10:58 +01:00
cvium
9158511017 Don't skip extras refresh when replacing metadata or doing a full refresh 2021-12-20 23:58:09 +01:00
Kichirou Hoshino
afaff1310f Translated using Weblate (Filipino)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fil/
2021-12-20 13:03:17 -05:00
cvium
b880dc8a4a Use our own Contains extension 2021-12-20 13:31:07 +01:00
cvium
91292b8ea5 Fix build 2021-12-20 12:34:16 +01:00
cvium
83a94aa612 Fix extras folders 2021-12-20 12:15:20 +01:00
Cody Robibero
cb41dda5b3 Merge pull request #7015 from Bond-009/zip 2021-12-19 11:32:12 -07:00
Cody Robibero
a633a3052f Merge pull request #7013 from 1337joe/increment-library-names 2021-12-19 11:32:06 -07:00
Cody Robibero
e8ae501430 Merge pull request #7018 from Bond-009/json2 2021-12-19 11:32:00 -07:00
Cody Robibero
db46eaa744 Merge pull request #7021 from cvium/baseitem_closure 2021-12-19 11:31:54 -07:00
Cody Robibero
71f6326e1a Merge pull request #7012 from nnnlog/remove-protect-clock 2021-12-19 11:13:47 -07:00
cvium
91f3ce3109 Use == instead of Object.Equals to avoid closure allocation 2021-12-19 18:24:05 +01:00
Bond-009
3f3295a5d6 Merge pull request #7020 from cvium/static_anon 2021-12-19 14:42:28 +00:00
cvium
76c2775d8c Use static lambdas 2021-12-19 10:27:57 +01:00
Claus Vium
cd760943a9 Merge pull request #7017 from crobibero/typo 2021-12-19 07:22:19 +01:00
Bond_009
ea9fc9f9cc Remove unreachable branches from JsonConverters
* If the type is a reference type we don't have to handle null ourselves
* reader.ValueSpan is only valid if reader.HasValueSequence is false
2021-12-19 02:20:46 +01:00
Cody Robibero
d9bc65469f Fix query param spelling 2021-12-18 17:17:03 -07:00
Joe Rogers
077f13ae4c Increment library number instead of appending 2021-12-18 20:50:36 +01:00
Bond_009
a4565da4a9 Use System.IO.Compression instead of SharpCompress for zips
Also removes unused methods from ZipClient
2021-12-18 17:52:38 +01:00
WWWesten
c35b704a83 Translated using Weblate (Welsh)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/cy/
2021-12-18 11:05:53 -05:00
Oatavandi
55146334e8 Translated using Weblate (Tamil)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ta/
2021-12-18 11:05:53 -05:00
Cody Robibero
232a148d3f Merge pull request #6978 from Bond-009/framerate
Add tests for ProbeResultNormalizer.GetFrameRate
2021-12-18 07:18:36 -07:00
Bond_009
968c534864 Return null on division by zero 2021-12-18 14:56:10 +01:00
Bond_009
f8fcbc88fc Add tests for ProbeResultNormalizer.GetFrameRate 2021-12-18 14:56:10 +01:00
nlog
92448ffabd Remove ProtectClock for hardware encoding 2021-12-18 13:00:51 +09:00
Cody Robibero
923720c988 Merge pull request #6956 from cvium/what_could_go_wrong 2021-12-17 07:51:32 -07:00
Bond-009
16bf4a013b Merge pull request #7005 from 1337joe/deprecate-enableinternetproviders 2021-12-16 22:49:19 +00:00
Bond-009
b3c48e8e78 Merge pull request #7006 from crobibero/base-item-kind-fixed 2021-12-16 22:43:22 +00:00
Joshua M. Boniface
42a7318fd0 Merge pull request #7000 from brianjmurrell/update-build-for-el7
Fix build on EL7
2021-12-16 17:01:15 -05:00
Cody Robibero
8ddba55214 Use string builder instead of string interpolation 2021-12-16 09:18:51 -07:00
Cody Robibero
0dd304f86c Log warning for unknown BaseItemKind to Type mapping 2021-12-16 07:54:22 -07:00
Cody Robibero
249a1ca955 Add mapping from BaseItemKind to Type.FullName for querying 2021-12-15 17:57:39 -07:00
Joe Rogers
dea5a3f3bc Deprecate LibraryOptions.EnableInternetProviders 2021-12-16 00:52:18 +01:00
WWWesten
b5d4fdb56e Translated using Weblate (Welsh)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/cy/
2021-12-15 13:05:52 -05:00
WWWesten
e34fd15196 Translated using Weblate (Malay)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ms/
2021-12-15 13:05:52 -05:00
Joshua M. Boniface
7405450da2 Merge pull request #7002 from crobibero/dotnet-6.0.1 2021-12-15 10:36:18 -05:00
Claus Vium
9a0618552b Merge branch 'master' into what_could_go_wrong 2021-12-15 08:38:39 +01:00
Claus Vium
4a58582ad5 Merge pull request #6912 from crobibero/filename-tvmaze
Add additional provider id parsing to file name
2021-12-15 08:37:34 +01:00
Claus Vium
4c9bd905c6 Merge pull request #6979 from crobibero/baseitemkind
Use BaseItemKind where possible
2021-12-15 08:28:44 +01:00
Cody Robibero
5e8aaa68cf Update to dotnet 6.0.1 2021-12-14 23:47:07 -07:00
Brian J. Murrell
543b0127b3 Fix build on EL7
Add /usr/local/bin to $PATH.

Update fedora/Makefile with enhancements from jellyfin-web.
2021-12-14 17:50:58 -05:00
Cody Robibero
87439665d7 Use array instead of HashSet 2021-12-14 15:10:40 -07:00
cvium
c3c4dc6839 Review 2021-12-14 23:05:45 +01:00
Claus Vium
e575d815cc Update MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs
Co-authored-by: Joe Rogers <1337joe@users.noreply.github.com>
2021-12-14 22:57:01 +01:00
Cody Robibero
ec9cff29df Merge pull request #6998 from 1337joe/dont-crash-on-missing-server-config
Fix crash on missing server config file
2021-12-14 11:56:44 -07:00
Joe Rogers
0f4da9f635 Fix crash on missing server config file 2021-12-14 19:29:31 +01:00
Cody Robibero
0edf77994a Cache BaseItemKind 2021-12-14 07:41:29 -07:00
Cody Robibero
38f0e611c8 Merge pull request #6994 from Tedyst/master
Fixed crash in MigrationRunner by checking migration for file existance
2021-12-14 05:02:31 -07:00
Stoica Tedy
4e03801931 Update Jellyfin.Server/Migrations/MigrationRunner.cs
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-12-14 09:57:20 +02:00
Stoica Tedy
250332104b Fixed crash in MigrationRunner
The crashed was caused by importing the migrationOptions even if the
migrations.xml file is non existant.
[Issue]: ~/.config/jellyfin/migrations.xml not found #6992
2021-12-14 09:31:35 +02:00
Bond-009
0872ede57b Merge pull request #6988 from jellyfin/dependabot/nuget/System.Linq.Async-5.1.0 2021-12-13 21:25:21 +00:00
dependabot[bot]
0120d80b78 Bump System.Linq.Async from 5.0.0 to 5.1.0
Bumps [System.Linq.Async](https://github.com/dotnet/reactive) from 5.0.0 to 5.1.0.
- [Release notes](https://github.com/dotnet/reactive/releases)
- [Commits](https://github.com/dotnet/reactive/compare/ixnet-v5.0.0...ixnet-v5.1.0)

---
updated-dependencies:
- dependency-name: System.Linq.Async
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-13 12:00:51 +00:00
cvium
9e665ff520 Fix usage of RegexOptions.Compiled 2021-12-13 08:27:20 +01:00
Claus Vium
5c3d0b5510 Update Emby.Naming/Video/ExtraResolver.cs
Co-authored-by: Bond-009 <bond.009@outlook.com>
2021-12-13 08:22:17 +01:00
cvium
3a4e7fb075 semi undo 2021-12-13 00:26:54 +01:00
Joshua M. Boniface
fcf5b9b46e Unify and standardize unit files between deb/rpm
Ensures that the RPM service unit has all the tweaks from the Deb
service unit, and some in the other direction too.
2021-12-12 17:01:35 -05:00
Joshua M. Boniface
9a2b88cb1f Revert some hardening that breaks LXC
For each of these, we should be OK since we run as an unprivileged user
anyways.
2021-12-12 16:57:35 -05:00
cvium
c5569c701c Folder can't have extras 2021-12-12 19:04:22 +01:00
Cody Robibero
32629cd7da Use BaseItemKind where possible 2021-12-12 06:11:27 -07:00
Claus Vium
2c6d6dbbf8 Merge pull request #6976 from Bond-009/float 2021-12-12 07:49:23 +01:00
Claus Vium
bdf9bdb9e6 Merge pull request #6977 from Bond-009/mime 2021-12-12 07:46:16 +01:00
Cody Robibero
0e8c97ed60 Merge pull request #5894 from brianjmurrell/bmurrell/setcap-low-port 2021-12-11 22:12:19 -07:00
Cody Robibero
843ba4506e Merge pull request #6980 from brianjmurrell/ci-autoversion-packages 2021-12-11 22:10:54 -07:00
Brian J. Murrell
3699fa43f0 Merge branch 'jellyfin:master' into ci-autoversion-packages 2021-12-11 23:09:43 -05:00
Brian J. Murrell
296a61cbc4 Run bump_version in make srpm
Also add an "rpms" target that builds the RPMs using mock in a target
environment.

Signed-off-by: Brian J. Murrell <brian@interlinx.bc.ca>
2021-12-11 22:49:19 -05:00
Cody Robibero
a04f8f5efb Fix new test 2021-12-11 20:35:43 -07:00
Cody Robibero
58f788e8ab Update tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs
Co-authored-by: Bond-009 <bond.009@outlook.com>
2021-12-11 19:43:01 -07:00
Bond_009
7ee96a59d3 Use correct jpeg MIME type
image/jpg isn't a valid MIME type
2021-12-12 02:07:35 +01:00
Bond_009
510f92f4c5 Don't check floats for equality 2021-12-12 01:26:47 +01:00
WWWesten
a90614d194 Translated using Weblate (Zulu)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/zu/
2021-12-11 16:05:50 -05:00
INOUE Daisuke
5e8f27d473 Translated using Weblate (Japanese)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ja/
2021-12-11 16:05:50 -05:00
WWWesten
1f02ab83cb Translated using Weblate (Persian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fa/
2021-12-11 16:05:50 -05:00
Cody Robibero
2a82f8dc40 Merge pull request #6222 from orryverducci/mbaff-interlace-detection 2021-12-11 13:54:52 -07:00
Joshua M. Boniface
584cf47ef5 Show detailed git status 2021-12-11 15:03:07 -05:00
Joshua M. Boniface
3223ef0e49 Properly handle the -1 tag
Avoids breaking Fedora/CentOS while preserving Debian.
2021-12-11 14:58:20 -05:00
Joshua M. Boniface
3797879d05 Automatically bump stable versions in build
Should prevent strangeness with building these for pre-releases or
actual release versions. Whatever the Git tag is, becomes the package
version.
2021-12-11 14:54:15 -05:00
Cody Robibero
8b4a36d6f7 Merge pull request #6898 from jonas-resch/support-external-audio-files
Add support for external audio files
2021-12-11 12:05:34 -07:00
Cody Robibero
4d1b824651 Merge pull request #6902 from cvium/migrate_networkconfig
Migrate network configuration safely
2021-12-11 12:04:58 -07:00
Cody Robibero
fbc79cb4ce Merge pull request #6965 from bendardenne/patch-1
Add artist to '/' split whitelist
2021-12-11 12:04:39 -07:00
cvium
6d6fb1bba3 Rename unknown parttype to "unknown" 2021-12-11 16:02:51 +01:00
cvium
681bfbd535 Remove duplication 2021-12-10 14:34:46 +01:00
cvium
220443eca1 Simplify StackResolver 2021-12-10 14:23:31 +01:00
WWWesten
4d446eb614 Translated using Weblate (Esperanto)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/eo/
2021-12-10 02:05:47 -05:00
Cody Robibero
d707a201c9 update tests 2021-12-09 12:31:32 -07:00
Marius Luca
7d86ef6f22 - add an option for dropping specific subtitle formats using the DLNA SubtitleProfile 2021-12-09 17:52:51 +02:00
Cody Robibero
eeb8192602 Add StringComparison 2021-12-09 08:38:00 -07:00
Benoît Dardenne
de2d292197 Added artist to '/' split whitelist 2021-12-09 16:07:57 +01:00
Cody Robibero
593b2fd359 Add more speed and more tests 2021-12-09 08:06:06 -07:00
WWWesten
13ac3e3665 Translated using Weblate (Macedonian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/mk/
2021-12-08 14:05:53 -05:00
WWWesten
5c407dbab6 Translated using Weblate (Romanian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ro/
2021-12-08 14:05:53 -05:00
Weevild
f50b2f7959 Translated using Weblate (Swedish)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sv/
2021-12-08 14:05:53 -05:00
archon eleven
1acb9e1d45 Translated using Weblate (Malay)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ms/
2021-12-08 14:05:53 -05:00
WWWesten
6640f3f782 Translated using Weblate (Malay)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ms/
2021-12-08 14:05:53 -05:00
WWWesten
8aef2cb282 Translated using Weblate (Lithuanian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/lt/
2021-12-08 14:05:53 -05:00
WWWesten
8bd331f5fa Translated using Weblate (Croatian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/hr/
2021-12-08 14:05:53 -05:00
Muhammed Aljailane
ee80602a0d Translated using Weblate (Arabic)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ar/
2021-12-08 14:05:53 -05:00
Jonas Resch
03b3f08354 Format code in MediaBrowser.Providers/MediaInfo/AudioResolver.cs
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-12-08 18:55:28 +01:00
Jonas Resch
65833076db Add "Async" suffix to AddExternalAudio method
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-12-08 16:49:27 +01:00
Jonas Resch
e18d966874 Add "Async" suffix to AddExternalAudio method
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-12-08 16:49:20 +01:00
Jonas Resch
4cdb590291 Exclude .strm files when searching for external audio files 2021-12-08 10:18:09 +01:00
Jonas Resch
d47811bdaf Fix wrong ffmpeg map argument due to wrong calculation 2021-12-08 10:17:25 +01:00
Jonas Resch
01a0a4a87c Add audioResolver argument to FFProbeVideoInfo initialization 2021-12-08 10:16:48 +01:00
Jonas Resch
87a6fdf847 Merge branch 'support-external-audio-files' of github.com:jonas-resch/jellyfin into support-external-audio-files 2021-12-08 09:55:16 +01:00
Cody Robibero
3513f5a84b Search for attribute text 2021-12-07 17:10:27 -07:00
Claus Vium
a327b43ab7 Update MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs 2021-12-07 20:28:51 +01:00
Claus Vium
3f69eeab27 Merge branch 'master' into support-external-audio-files 2021-12-07 20:16:32 +01:00
Claus Vium
dd8b9e9d23 Merge pull request #6953 from matthiasdv/mdv/harden-systemd-service
Add more hardening to systemd service
2021-12-07 19:46:45 +01:00
cvium
6030946d78 Fixes 2021-12-07 19:23:30 +01:00
cvium
fde84a1e00 Refactor extras parsing 2021-12-07 15:24:57 +01:00
matthiasdv
3176a4ddd9 add more hardening to systemd service 2021-12-06 22:40:00 +01:00
Bond-009
9cafa2cab4 Merge pull request #6946 from jellyfin/dependabot/nuget/libse-3.6.4 2021-12-06 14:46:10 +01:00
dependabot[bot]
c4c7d7431f Bump libse from 3.6.2 to 3.6.4
Bumps [libse](https://github.com/SubtitleEdit/subtitleedit) from 3.6.2 to 3.6.4.
- [Release notes](https://github.com/SubtitleEdit/subtitleedit/releases)
- [Changelog](https://github.com/SubtitleEdit/subtitleedit/blob/master/Changelog.txt)
- [Commits](https://github.com/SubtitleEdit/subtitleedit/compare/3.6.2...3.6.4)

---
updated-dependencies:
- dependency-name: libse
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-06 13:29:10 +00:00
Bond-009
f2648f3eee Merge pull request #6947 from jellyfin/dependabot/nuget/BDInfo-0.7.6.2 2021-12-06 14:28:17 +01:00
dependabot[bot]
29095ab390 Bump BDInfo from 0.7.6.1 to 0.7.6.2
Bumps [BDInfo](https://github.com/jellyfin/BDInfo) from 0.7.6.1 to 0.7.6.2.
- [Release notes](https://github.com/jellyfin/BDInfo/releases)
- [Commits](https://github.com/jellyfin/BDInfo/commits)

---
updated-dependencies:
- dependency-name: BDInfo
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-06 12:01:19 +00:00
WWWesten
b9b3959223 Translated using Weblate (Punjabi)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/pa/
2021-12-06 03:45:54 -05:00
WWWesten
9b71bf8cfe Translated using Weblate (Nepali)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ne/
2021-12-06 03:45:54 -05:00
WWWesten
5eff80fb8c Translated using Weblate (Macedonian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/mk/
2021-12-06 03:45:54 -05:00
mikixd586
2d77c729f2 Translated using Weblate (Serbian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sr/
2021-12-06 03:45:54 -05:00
mio2
9d387c542a Translated using Weblate (Japanese)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ja/
2021-12-06 03:45:54 -05:00
Bas Goos
60f4d70cc5 Translated using Weblate (Dutch)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/nl/
2021-12-06 03:45:54 -05:00
oxixes
bd48b74d5b Translated using Weblate (Spanish)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/es/
2021-12-06 03:45:54 -05:00
Mehyar
838adaea48 Translated using Weblate (Arabic)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ar/
2021-12-06 03:45:54 -05:00
archon eleven
46543ead27 Translated using Weblate (Malay)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ms/
2021-12-06 03:45:54 -05:00
Cody Robibero
707e5bab97 Merge pull request #6941 from holahmeds/mime-type
Use MimeTypes package to determine MIME type
2021-12-04 17:55:24 -07:00
Ahmed Rafiq
cf75f99f0e Update unit test name
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-12-04 21:14:52 +06:00
Ahmed Rafiq
fa6f6515a6 Update unit test name
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-12-04 21:14:16 +06:00
Ahmed Rafiq
0e491025ae Refactor MimeTypes.ToExtension()
Co-authored-by: Cody Robibero <cody@robibe.ro>
2021-12-04 21:13:18 +06:00
Ahmed Rafiq
40e05a7993 Update documentation 2021-12-04 21:06:51 +06:00
Ahmed Rafiq
6193fdea69 Use MimeTypes package to determine MIME type
This simplifies the code since we don't have to keep large mappings of extensions and MIME types.

We still keep the ability to override the mappings for:
- filling in entries not present in the package, for e.g. ".azw3"
- picking preferred extensions, for e.g. MimeTypes provides ".conf" as a possible extionsion for "text/plain", and while that is correct, ".txt" would be preferrable
- compatibility reasons
2021-12-04 20:08:16 +06:00
Jonas Resch
ca2d94ee97 Merge branch 'support-external-audio-files' of github.com:jonas-resch/jellyfin into support-external-audio-files 2021-12-03 19:19:53 +01:00
Jonas Resch
99a48554a6 Optimize calculation of external audio stream index in MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
Co-authored-by: Cody Robibero <cody@robibe.ro>
2021-12-03 19:19:22 +01:00
Jonas Resch
120828d8d0 Replace escaped quote string with quote character in MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
Co-authored-by: Cody Robibero <cody@robibe.ro>
2021-12-03 19:18:43 +01:00
Cody Robibero
9cea773d29 Merge pull request #6874 from 1337joe/tmdb-image-size-options 2021-12-03 07:03:02 -07:00
Cody Robibero
a474e4cf3b Merge pull request #6914 from marius-luca-87/dlna 2021-12-02 06:56:07 -07:00
Cody Robibero
b1025121b8 Merge pull request #6929 from Bond-009/jsoncontent 2021-12-02 06:55:28 -07:00
Bond-009
2029076ce8 Merge pull request #6936 from cvium/ffprobeprovider_tweak 2021-12-02 13:42:45 +01:00
cvium
5535b9c01f Reduce allocations 2021-12-02 11:21:59 +01:00
Orry Verducci
e446e9fde9 Merge branch 'master' into mbaff-interlace-detection 2021-12-01 22:13:52 +00:00
Jonas Resch
180e2dc329 Prevent crashes in specific scenarios 2021-12-01 21:05:43 +01:00
Bond_009
40be86eec0 Use PostAsJsonAsync where possible 2021-12-01 15:58:23 +01:00
Bond_009
beafd6eaab Use JsonContent where possible
Should reduce the # of allocated bytes
2021-12-01 15:40:06 +01:00
hoanghuy309
f6d8c19a7a Translated using Weblate (Vietnamese)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/vi/
2021-11-30 17:48:37 -05:00
snieguzary
2da7777e6d Translated using Weblate (Polish)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/pl/
2021-11-30 17:48:37 -05:00
WWWesten
a0df79d8a5 Translated using Weblate (Persian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fa/
2021-11-30 17:48:37 -05:00
Bond-009
01b95cf8e6 Merge pull request #6927 from 1337joe/use-ssl-for-tmdb-images 2021-11-30 23:43:26 +01:00
Jonas Resch
6bbfcf1906 Add documentation to AudioResolver class 2021-11-30 21:05:43 +01:00
Jonas Resch
7b50048020 Add ConfigureAwait true in MediaBrowser.Providers/MediaInfo/AudioResolver.cs
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-11-30 20:45:47 +01:00
Jonas Resch
a9a53dc657 Add ConfigureAwait true in MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-11-30 20:45:21 +01:00
Jonas Resch
0d8170cedb Move variable in MediaBrowser.Providers/MediaInfo/AudioResolver.cs
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-11-30 20:44:57 +01:00
Jonas Resch
1a35690834 Don't disable warnings in MediaBrowser.Providers/MediaInfo/AudioResolver.cs
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-11-30 20:44:16 +01:00
Jonas Resch
c61b9ef05a Fix warning due to new line after opening bracket 2021-11-30 19:52:44 +01:00
Jonas Resch
b5b994b22f Fix compiler warning due to missing EnumeratorCancellation attribute 2021-11-30 19:31:46 +01:00
Jonas Resch
0894a6193f Implement coding standards from 2nd code feedback 2021-11-30 19:31:46 +01:00
Jonas Resch
9d34d6339a Change return type from List<string> to IEnumerable<string> in MediaBrowser.Providers/MediaInfo/AudioResolver.cs
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-11-30 19:31:46 +01:00
Jonas Resch
bbf1399826 Check language for null or empty instead of only null in MediaBrowser.Providers/MediaInfo/AudioResolver.cs
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-11-30 19:31:46 +01:00
Jonas Resch
d016d483ae Change return type from Task<List<MediaStream>> to Task<IAsyncEnumerable<MediaStream>> in MediaBrowser.Providers/MediaInfo/AudioResolver.cs
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-11-30 19:31:46 +01:00
Jonas Resch
61b191d345 Fix indentation in MediaBrowser.Providers/MediaInfo/AudioResolver.cs
If statement which checks if filename of audio and video file match or if audio file starts with video filename

Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-11-30 19:31:46 +01:00
Jonas Resch
9433072f90 Only search in video folder for external audio files
Don't search in video metadata folder since audio files won't be stored there

Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-11-30 19:31:46 +01:00
Jonas Resch
a3c5afa443 Add ConfigureAwait false MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
Co-authored-by: Cody Robibero <cody@robibe.ro>
2021-11-30 19:31:46 +01:00
Jonas Resch
f1862f9b1a Add ConfigureAwait false to MediaBrowser.Providers/MediaInfo/AudioResolver.cs
Co-authored-by: Cody Robibero <cody@robibe.ro>
2021-11-30 19:31:46 +01:00
Jonas Resch
a68e58556c Implement code feedback
- Rewrite AudioResolver
- Use async & await instead of .Result
- Add support for audio containers with multiple audio streams (e.g.
  mka)
- Fix bug when using external subtitle and external audio streams at the
  same time
2021-11-30 19:31:46 +01:00
Jonas Resch
5e91f50c43 Update CONTRIBUTORS.md 2021-11-30 19:31:46 +01:00
Jonas Resch
c1a8385c9c Shorten calculation of audio startIndex in MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-11-30 19:31:46 +01:00
Jonas Resch
9978164438 Add support for external audio files 2021-11-30 19:31:46 +01:00
Marius Luca
eaa003775f - take into account the streams dlnaheaders query parameter set by the DidlBuilder NormalizeDlnaMediaUrl function 2021-11-30 16:09:02 +02:00
Joe Rogers
e778462955 Use SSL for tmdb images 2021-11-30 14:31:32 +01:00
Brian J. Murrell
148fcb1bb8 Put low port privilege into an optional subpackage
Move "AmbientCapabilities=CAP_NET_BIND_SERVICE" to the "[Service]"
section of the optional "lowport" unit drop-in file and package that
drop-in in a separate, optionally installable jellyfin-server-lowports
subpackage.

This isolates the CAP_NET_BIND_SERVICE capability to only installations
that desire it.

Signed-off-by: Brian J. Murrell <brian@interlinx.bc.ca>
2021-11-30 01:18:27 -05:00
Brian J. Murrell
757970bfc1 Merge remote-tracking branch 'origin/master' into HEAD 2021-11-29 17:53:26 -05:00
WWWesten
c677b4f6b7 Translated using Weblate (Mongolian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/mn/
2021-11-29 07:05:47 -05:00
WWWesten
20b0499b00 Translated using Weblate (Telugu)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/te/
2021-11-29 07:05:47 -05:00
rimasx
09f2456919 Translated using Weblate (Estonian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/et/
2021-11-29 07:05:47 -05:00
WWWesten
bcd84dedda Translated using Weblate (Pirate)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/pr/
2021-11-29 07:05:47 -05:00
WWWesten
2496c5d589 Translated using Weblate (Vietnamese)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/vi/
2021-11-29 07:05:47 -05:00
WWWesten
19c9319d2c Translated using Weblate (Albanian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sq/
2021-11-29 07:05:47 -05:00
WWWesten
6ef9ac6e53 Translated using Weblate (Tamil)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ta/
2021-11-29 07:05:47 -05:00
WontTell
502a5fc932 Translated using Weblate (Spanish (Latin America))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/es_419/
2021-11-29 07:05:47 -05:00
WWWesten
02ce95edaf Translated using Weblate (Serbian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sr/
2021-11-29 07:05:47 -05:00
WWWesten
5addb24e9b Translated using Weblate (Portuguese)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/pt/
2021-11-29 07:05:47 -05:00
wolong gl
dc27e7618f Translated using Weblate (Chinese (Simplified))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/zh_Hans/
2021-11-29 07:05:47 -05:00
Weevild
3e1bbdd3d4 Translated using Weblate (Swedish)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sv/
2021-11-29 07:05:47 -05:00
WWWesten
2ff786fd3d Translated using Weblate (Malay)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ms/
2021-11-29 07:05:47 -05:00
Bond-009
2a09d4244c Merge pull request #6923 from cvium/query_a_bit_less 2021-11-29 13:00:38 +01:00
cvium
beef6f0855 Don't query series twice 2021-11-28 19:56:31 +01:00
Cody Robibero
80c7119537 Merge pull request #6915 from 1337joe/subtitle-parsing-fix 2021-11-27 16:55:51 -07:00
Cody Robibero
1df56335ee Add more tests 2021-11-27 16:25:21 -07:00
Claus Vium
065d3fa837 performance++ 2021-11-27 16:10:43 -07:00
Joe Rogers
1df5b5034b Address suppressed warnings 2021-11-27 20:35:18 +01:00
Joe Rogers
4a20ae6cb4 Allow default/forced tag without setting language 2021-11-27 20:13:21 +01:00
Claus Vium
a87b87825d Update Jellyfin.Server/Migrations/MigrationRunner.cs
Co-authored-by: Cody Robibero <cody@robibe.ro>
2021-11-27 16:01:27 +01:00
Cody Robibero
976e3160b8 Merge pull request #6907 from marius-luca-87/dlna 2021-11-27 07:47:54 -07:00
Cody Robibero
4890454935 Add additional provider parsing to series file name 2021-11-27 07:44:12 -07:00
Claus Vium
ca887518dd Use the Memory overload for ReadAsync (#6865) 2021-11-27 03:23:46 +01:00
Marius Luca
5b5ae1ef52 - enable seek function when direct streaming over DLNA 2021-11-26 18:09:34 +02:00
WWWesten
3eec137100 Translated using Weblate (Spanish (Latin America))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/es_419/
2021-11-26 04:09:26 -05:00
WontTell
402a3797a4 Translated using Weblate (Spanish (Latin America))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/es_419/
2021-11-26 04:09:26 -05:00
cvium
0b871505a6 Remove stray datamember 2021-11-24 14:36:01 +01:00
cvium
0485ff1899 Create a store key constant for network 2021-11-24 13:42:14 +01:00
cvium
69df004b9f Migrate network configuration safely 2021-11-24 13:00:12 +01:00
N4v41
8b9ff893b3 Translated using Weblate (Portuguese)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/pt/
2021-11-24 06:28:00 -05:00
Pedro Almeida
b3d5383073 Translated using Weblate (Portuguese (Portugal))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/pt_PT/
2021-11-24 06:28:00 -05:00
Csaba
9d5f328a09 Translated using Weblate (Hungarian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/hu/
2021-11-24 06:27:59 -05:00
WWWesten
f469ee3010 Translated using Weblate (English)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/en/
2021-11-24 06:27:59 -05:00
Bond-009
e30ac91f16 Merge pull request #6900 from ianjazz246/local-time-test 2021-11-24 09:14:22 +01:00
ianjazz246
95183c365a Use local time for RecordingHelperTests 2021-11-23 12:57:05 -08:00
Joe Rogers
0af5e60094 Address review comments
Store null instead of calculating scaled image sizes.
Add endpoint to provide TMDb image size options.
2021-11-22 21:08:07 +01:00
Cody Robibero
3c030740ea Merge pull request #6895 from jellyfin/dependabot/nuget/prometheus-net.AspNetCore-5.0.2
Bump prometheus-net.AspNetCore from 5.0.1 to 5.0.2
2021-11-22 06:50:16 -07:00
dependabot[bot]
bb9ce98379 Bump prometheus-net.AspNetCore from 5.0.1 to 5.0.2
Bumps [prometheus-net.AspNetCore](https://github.com/prometheus-net/prometheus-net) from 5.0.1 to 5.0.2.
- [Release notes](https://github.com/prometheus-net/prometheus-net/releases)
- [Changelog](https://github.com/prometheus-net/prometheus-net/blob/master/History)
- [Commits](https://github.com/prometheus-net/prometheus-net/compare/v5.0.1...v5.0.2)

---
updated-dependencies:
- dependency-name: prometheus-net.AspNetCore
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-22 13:33:18 +00:00
Cody Robibero
02fda265b8 Merge pull request #6894 from jellyfin/dependabot/nuget/prometheus-net-5.0.2
Bump prometheus-net from 5.0.1 to 5.0.2
2021-11-22 06:32:48 -07:00
Cody Robibero
501919df35 Merge pull request #6893 from jellyfin/dependabot/nuget/sharpcompress-0.30.1
Bump sharpcompress from 0.30.0 to 0.30.1
2021-11-22 06:32:35 -07:00
Cody Robibero
107909de30 Merge pull request #6896 from jellyfin/dependabot/nuget/Serilog.Sinks.Console-4.0.1
Bump Serilog.Sinks.Console from 4.0.0 to 4.0.1
2021-11-22 06:32:19 -07:00
dependabot[bot]
052b667d6a Bump Serilog.Sinks.Console from 4.0.0 to 4.0.1
Bumps [Serilog.Sinks.Console](https://github.com/serilog/serilog-sinks-console) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/serilog/serilog-sinks-console/releases)
- [Commits](https://github.com/serilog/serilog-sinks-console/compare/v4.0.0...v4.0.1)

---
updated-dependencies:
- dependency-name: Serilog.Sinks.Console
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-22 12:01:30 +00:00
dependabot[bot]
e5ea607853 Bump prometheus-net from 5.0.1 to 5.0.2
Bumps [prometheus-net](https://github.com/prometheus-net/prometheus-net) from 5.0.1 to 5.0.2.
- [Release notes](https://github.com/prometheus-net/prometheus-net/releases)
- [Changelog](https://github.com/prometheus-net/prometheus-net/blob/master/History)
- [Commits](https://github.com/prometheus-net/prometheus-net/compare/v5.0.1...v5.0.2)

---
updated-dependencies:
- dependency-name: prometheus-net
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-22 12:01:20 +00:00
dependabot[bot]
223cc8314a Bump sharpcompress from 0.30.0 to 0.30.1
Bumps [sharpcompress](https://github.com/adamhathcock/sharpcompress) from 0.30.0 to 0.30.1.
- [Release notes](https://github.com/adamhathcock/sharpcompress/releases)
- [Commits](https://github.com/adamhathcock/sharpcompress/compare/0.30...0.30.1)

---
updated-dependencies:
- dependency-name: sharpcompress
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-22 12:01:01 +00:00
Claus Vium
39e6658d01 Merge pull request #6879 from crobibero/client-log-cleanup
Remove ClientLog endpoints
2021-11-21 23:57:13 +01:00
Claus Vium
8f051c86f7 Merge pull request #6873 from crobibero/resume-ignore-active
Add ability to exclude active sessions from resumable items
2021-11-21 23:54:17 +01:00
Claus Vium
11419cbbfd Merge pull request #6890 from crobibero/dlna-create
Fix creating DLNA profiles
2021-11-21 20:46:41 +01:00
Cody Robibero
5b7e8a27fb Fix creating DLNA profiles 2021-11-21 11:48:30 -07:00
WWWesten
718e4b8665 Translated using Weblate (Mongolian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/mn/
2021-11-20 14:05:43 -05:00
hoanghuy309
d387d4df92 Translated using Weblate (Vietnamese)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/vi/
2021-11-20 14:05:43 -05:00
WWWesten
1fa845de6e Translated using Weblate (Ukrainian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/uk/
2021-11-20 14:05:43 -05:00
WWWesten
7126f9dffc Translated using Weblate (English (United Kingdom))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/en_GB/
2021-11-20 14:05:43 -05:00
Cody Robibero
b2b4bd82d7 Merge pull request #6862 from 1337joe/query-instead-of-filtering 2021-11-20 08:50:39 -07:00
Cody Robibero
03c7bcf9c6 Merge pull request #6870 from cvium/fix_omdb_image_provider 2021-11-20 08:50:22 -07:00
Cody Robibero
ea355b4262 Remove ClientLog endpoints 2021-11-20 08:47:05 -07:00
cvium
71a0abe211 Remove unnecessary N/A checks (converter changes them to null) 2021-11-20 08:32:07 +01:00
cvium
d8c3b8e7f8 Don't use AppendFormat 2021-11-20 08:24:52 +01:00
Joe Rogers
88baff5693 Apply suggestions from code review
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-11-19 22:40:42 +01:00
Joe Rogers
6d3b129666 Add image scaling options for tmdb 2021-11-19 22:21:21 +01:00
Cody Robibero
8295a3be0d Add ability to exclude active sessions from resumable items 2021-11-19 14:07:50 -07:00
WWWesten
17a273d237 Update LocalizationManager.cs (#6839) 2021-11-19 18:00:20 +01:00
Cody Robibero
752bb88445 Merge pull request #6871 from cvium/fix_localapiurl 2021-11-19 09:18:25 -07:00
cvium
a263f3978b Only force scheme and port when HTTPS is disallowed 2021-11-19 16:57:48 +01:00
Cody Robibero
0009e5cc27 Merge pull request #6850 from PetrusZ/collection-validator 2021-11-19 07:54:41 -07:00
cvium
96ea865681 Refactor omdb providers 2021-11-19 15:32:07 +01:00
Cody Robibero
4a7498a0be Merge pull request #6869 from cvium/optimize_childcount
Small optimization to child count field
2021-11-19 05:07:54 -07:00
cvium
e3f0a53f59 Small optimization to child count field 2021-11-19 09:15:06 +01:00
Yordany Rodriguez Esquirol
3734c95fd4 Related media according to genre 2021-11-18 15:23:47 -05:00
Joe Rogers
9ba7bf96ef Query MediaSourceManager directly in image providers
Add doc comments/minor tweaks to AudioImageProvider
2021-11-18 15:11:50 +01:00
Joe Rogers
bff5ff0cb8 Merge similar tests with Theories 2021-11-18 14:29:22 +01:00
Petrus.Z
acb86066ff Replace library option to AutomaticallyAddToCollection
Signed-off-by: Petrus.Z <silencly07@gmail.com>
2021-11-18 16:00:14 +08:00
Petrus.Z
263bbf897a Reduce one query
Signed-off-by: Petrus.Z <silencly07@gmail.com>
2021-11-18 15:34:35 +08:00
Joe Rogers
97124f5fce Add missed override 2021-11-18 07:42:04 +01:00
Petrus.Z
6565b0cfbe Fix style issues
Signed-off-by: Petrus.Z <silencly07@gmail.com>
2021-11-18 13:33:44 +08:00
Petrus.Z
b635b5a7e3 Paginate movies query
Signed-off-by: Petrus.Z <silencly07@gmail.com>
2021-11-18 13:08:56 +08:00
Petrus.Z
6d74c83ddb Fix issues mentioned in review, except for option name
Signed-off-by: Petrus.Z <silencly07@gmail.com>
2021-11-18 12:07:27 +08:00
Joe Rogers
7cf5767949 Query media streams by type instead of filtering 2021-11-17 22:34:04 +01:00
Cody Robibero
fa366f0099 Merge pull request #6860 from cvium/fix_xml_endless_loops 2021-11-17 08:39:49 -07:00
Petrus.Z
989013c974 Add new line at end of file
Signed-off-by: Petrus.Z <silencly07@gmail.com>
2021-11-17 22:22:52 +08:00
Petrus.Z
c09e999916 Use List<Gid> instead of List<Movie>
Signed-off-by: Petrus.Z <silencly07@gmail.com>
2021-11-17 22:18:59 +08:00
cvium
61b75c82ce Read past empty elements 2021-11-17 14:49:30 +01:00
rimasx
773a4ae1f3 Translated using Weblate (Estonian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/et/
2021-11-17 08:48:37 -05:00
WWWesten
38ac84ad71 Translated using Weblate (Esperanto)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/eo/
2021-11-17 08:48:37 -05:00
WWWesten
054ca6a8fb Translated using Weblate (Kazakh)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/kk/
2021-11-17 08:48:37 -05:00
millallo
3d9f865247 Translated using Weblate (Italian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/it/
2021-11-17 08:48:37 -05:00
Csaba
5cd6fba11a Translated using Weblate (Hungarian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/hu/
2021-11-17 08:48:37 -05:00
blob03
f7b18d97a7 Translated using Weblate (French)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fr/
2021-11-17 08:48:37 -05:00
Lukáš Kucharczyk
45e6e2adee Translated using Weblate (Czech)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/cs/
2021-11-17 08:48:37 -05:00
blob03
704c1539a2 Translated using Weblate (English)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/en/
2021-11-17 08:48:37 -05:00
WWWesten
00b293d2e9 Added translation using Weblate (Mongolian) 2021-11-17 08:48:37 -05:00
Petrus.Z
52e9dc66f5 Remove extra blank line
Signed-off-by: Petrus.Z <silencly07@gmail.com>
2021-11-17 21:07:02 +08:00
Petrus.Z
3c8f7d380f Improve performance
Signed-off-by: Petrus.Z <silencly07@gmail.com>
2021-11-17 20:56:14 +08:00
Petrus.Z
0a0ddb0eaf Add AutoCollection option
it can determine whether auto create/add movies to collection

Signed-off-by: Petrus.Z <silencly07@gmail.com>
2021-11-17 14:02:07 +08:00
Cody Robibero
84b8c9c2bc Merge pull request #6857 from Bond-009/warn56 2021-11-16 12:25:54 -07:00
Bond_009
257e1be95f Fix some warnings 2021-11-16 16:31:57 +01:00
rimasx
6003289717 Translated using Weblate (Estonian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/et/
2021-11-16 09:50:35 -05:00
WWWesten
19d285149b Translated using Weblate (Macedonian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/mk/
2021-11-16 09:50:35 -05:00
blob03
33a2e1bd50 Translated using Weblate (French)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fr/
2021-11-16 09:50:35 -05:00
emmanuel billeaud
b8507371d5 Translated using Weblate (French)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fr/
2021-11-16 09:50:35 -05:00
Bond-009
bddded96ff Merge pull request #6856 from cvium/unused_deps 2021-11-16 15:42:32 +01:00
cvium
24024706bf Fix release build 2021-11-16 12:55:35 +01:00
cvium
93fd1c7075 Fix 2021-11-16 12:27:27 +01:00
cvium
5b1b2621ab Fix build 2021-11-16 12:25:46 +01:00
cvium
b50c3852ef Remove unused dependencies 2021-11-16 12:24:17 +01:00
Petrus.Z
1924d0740d Fix style and performance issues mentioned in review
Signed-off-by: Petrus.Z <silencly07@gmail.com>
2021-11-16 19:03:18 +08:00
Petrus.Z
74459ec403 Fix issues mentioned in review
Signed-off-by: Petrus.Z <silencly07@gmail.com>
2021-11-16 11:50:04 +08:00
Cody Robibero
c32a421ea7 Merge pull request #6851 from cvium/remove_references_to_ilibrarymanager 2021-11-15 15:45:49 -07:00
Cody Robibero
4cfe8fe588 Merge pull request #6831 from 1337joe/image-provider-cleanup 2021-11-15 15:45:33 -07:00
Cody Robibero
06c82973c6 Merge pull request #6854 from 1337joe/add-customprefs-set 2021-11-15 15:45:21 -07:00
Claus Vium
f638cd08ea Merge pull request #6852 from Bond-009/warn54
Fix some warnings
2021-11-15 23:35:53 +01:00
Claus Vium
31b87130a2 Merge pull request #6848 from marius-luca-87/dlna
Ensure the proper StartTimeTicks variable is forwarded to the AddDlnaHeaders function
2021-11-15 23:34:34 +01:00
Joe Rogers
ca99a27611 Add setter for CustomPrefs 2021-11-15 22:03:19 +01:00
Petrus.Z
5eb1fde88c Add Collection Validator, create collection based on nfo
Based on nfo's set element, automatically add movie to collection.

Signed-off-by: Petrus.Z <silencly07@gmail.com>
2021-11-16 00:17:14 +08:00
cvium
24679af2e8 Fix comment 2021-11-15 16:01:34 +01:00
Bond_009
474b035d99 Fix some warnings 2021-11-15 15:57:07 +01:00
cvium
4f45c52674 Remove ILibraryManager as a dependency in resolvers etc. 2021-11-15 15:56:02 +01:00
Joe Rogers
f059be8e4d Add logging and fast return 2021-11-15 15:30:43 +01:00
Cody Robibero
03435641c8 Merge pull request #6849 from 1337joe/server-disabled-metadata 2021-11-15 07:25:56 -07:00
Joe Rogers
58be1d7759 Actually check server disabled metadata providers 2021-11-15 14:47:06 +01:00
Marius Luca
4e0edaf544 - ensure the proper StartTimeTicks variable is forwarded to the AddDlnaHeaders function 2021-11-15 15:34:02 +02:00
rimasx
9c74103fbe Translated using Weblate (Estonian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/et/
2021-11-15 07:48:24 -05:00
WWWesten
551c6f02a2 Added translation using Weblate (Assamese) 2021-11-15 07:48:24 -05:00
Bond-009
358cf48506 Merge pull request #6847 from jellyfin/dependabot/nuget/Microsoft.SourceLink.GitHub-1.1.1 2021-11-15 13:31:56 +01:00
Bond-009
331d4ad849 Merge pull request #6846 from jellyfin/dependabot/nuget/Diacritics-3.3.10 2021-11-15 13:31:05 +01:00
dependabot[bot]
bd32cecf7a Bump Microsoft.SourceLink.GitHub from 1.1.0 to 1.1.1
Bumps [Microsoft.SourceLink.GitHub](https://github.com/dotnet/sourcelink) from 1.1.0 to 1.1.1.
- [Release notes](https://github.com/dotnet/sourcelink/releases)
- [Commits](https://github.com/dotnet/sourcelink/compare/1.1.0...1.1.1)

---
updated-dependencies:
- dependency-name: Microsoft.SourceLink.GitHub
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-15 12:01:08 +00:00
dependabot[bot]
c84f2e48b0 Bump Diacritics from 3.3.4 to 3.3.10
Bumps [Diacritics](https://github.com/thomasgalliker/Diacritics.NET) from 3.3.4 to 3.3.10.
- [Release notes](https://github.com/thomasgalliker/Diacritics.NET/releases)
- [Commits](https://github.com/thomasgalliker/Diacritics.NET/commits)

---
updated-dependencies:
- dependency-name: Diacritics
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-15 12:00:50 +00:00
Joe Rogers
370b7f8e12 Handle unexpected case more gracefully 2021-11-14 23:13:45 +01:00
Cody Robibero
4cb649853d Merge pull request #6845 from marius-luca-87/dlna
Flush the XmlWriter before calling the StringBuilder ToString() method
2021-11-14 13:02:46 -07:00
Marius Luca
a774d1fa10 - flush the XmlWriter before calling the StringBuilder ToString() method 2021-11-14 20:46:17 +02:00
Haadiy Rozzaq
5254e74719 Translated using Weblate (Indonesian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/id/
2021-11-14 01:36:37 -05:00
WWWesten
14b5e85461 Translated using Weblate (Belarusian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/be/
2021-11-14 01:36:37 -05:00
WWWesten
25f1cdbcb5 Translated using Weblate (Catalan)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ca/
2021-11-14 01:36:37 -05:00
Cody Robibero
34df1a030b Merge pull request #6818 from Bond-009/password 2021-11-13 16:56:25 -07:00
Joe Rogers
1d729b2b0f Use codec to determine image format 2021-11-12 16:30:30 +01:00
Joe Rogers
f73a7a6ed8 Use ImageFormat instead of string for extension 2021-11-12 16:22:11 +01:00
Joe Rogers
de9bf327c6 Merge similar tests with Theories 2021-11-12 13:44:48 +01:00
cvium
5d19c26d59 Simplify 2021-11-10 23:46:56 +01:00
cvium
0415d1ccef Reduce indentation 2021-11-10 23:29:41 +01:00
cvium
d10de5b7f9 Try to use Width and Height from ImageInfo to determine aspect ratio 2021-11-10 23:25:01 +01:00
Bond_009
5265b3eee7 Replace PBKDF2-SHA1 with PBKDF2-SHA512
This also migrates already created passwords on login

Source for the number of iterations:
https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pbkdf2
2021-11-10 22:34:54 +01:00
Orry Verducci
9abe9e7e54 Add rounding to the time base check 2021-10-31 17:04:04 +00:00
Orry Verducci
3a89e88033 Merge remote-tracking branch 'upstream/master' into mbaff-interlace-detection 2021-10-31 10:04:14 +00:00
cvium
2899b77cd5 Implement FfProbeKeyframeExtractor and add tests for it 2021-09-26 21:07:30 +02:00
cvium
41383e6fe4 Review comment 2021-09-25 23:37:41 +02:00
cvium
64a13a5d42 Add ComputeSegments test 2021-09-25 23:28:10 +02:00
cvium
43ea4af30f Update to .net 6 2021-09-25 20:55:48 +02:00
cvium
30f3be1da0 Merge branch 'master' into keyframe_extraction_v1 2021-09-25 20:52:09 +02:00
cvium
3e5cb8e04e Add tests for ComputeEqualLengthSegments and fix bug 2021-09-25 11:47:44 +02:00
cvium
c7b25a9fe4 Add first test 2021-09-25 11:17:16 +02:00
cvium
fa38b741ce Restructure the code to make it more testable 2021-09-25 10:54:54 +02:00
cvium
be233b49b6 Fixes 2021-09-25 10:41:36 +02:00
cvium
35c0801d6c More fixes 2021-09-23 18:59:34 +02:00
cvium
ee8bd9b3b5 Fix xmldoc issues 2021-09-23 18:49:48 +02:00
cvium
30230aff73 Fix build? 2021-09-23 17:00:39 +02:00
cvium
d995f0e092 Add dto changes 2021-09-23 15:51:46 +02:00
cvium
6e77d50563 Remove path hinting 2021-09-23 15:39:49 +02:00
cvium
3531dc85ae Fix build 2021-09-23 15:37:33 +02:00
cvium
9c15f96e12 Add first draft of keyframe extraction for Matroska 2021-09-23 15:29:12 +02:00
oledfish
86a5e72a65 Add "Production" and "TV" episode orders. 2021-09-07 16:38:18 -03:00
Orry Verducci
d5b63092ed Add H.264 MBAFF interlace check
Use the codec time base to determine if a MBAFF coded H.264 file is interlaced.
2021-06-24 17:51:35 +01:00
BaronGreenback
6648b7d7da Merge branch 'master' into comparisons 2021-06-19 15:04:30 +01:00
BaronGreenback
97c2c523a8 Merge branch 'master' into comparisons 2021-05-08 17:11:21 +01:00
BaronGreenback
e682c230bd Merge branch 'master' into comparisons 2021-05-05 23:22:54 +01:00
Brian J. Murrell
a3a4689af2 Allow to bind to priveleged ports (i.e. 80/443)
Add "AmbientCapabilities=CAP_NET_BIND_SERVICE" to the "[Service]"
section of the unit file to allow the server to bind to ports 80 and 443.

Signed-off-by: Brian J. Murrell <brian@interlinx.bc.ca>
2021-04-22 10:07:51 -04:00
BaronGreenback
107412f2f2 Update FFProbeVideoInfo.cs 2021-04-19 10:23:05 +01:00
BaronGreenback
6b2b484987 Update SubtitleScheduledTask.cs 2021-04-19 10:22:32 +01:00
BaronGreenback
80877aa945 Cleaned up "value assigned is not used in any execution path" 2021-04-17 09:27:58 +01:00
MrTimscampi
c52a2f2f7b Move studios image providers to plugin 2021-01-12 22:45:28 +01:00
785 changed files with 45513 additions and 13167 deletions

View File

@@ -39,6 +39,10 @@ jobs:
vmImage: 'ubuntu-latest'
steps:
- script: echo "##vso[task.setvariable variable=JellyfinVersion]$( awk -F '/' '{ print $NF }' <<<'$(Build.SourceBranch)' | sed 's/^v//' )"
displayName: Set release version (stable)
condition: startsWith(variables['Build.SourceBranch'], 'refs/tags/v')
- script: 'docker build -f deployment/Dockerfile.$(BuildConfiguration) -t jellyfin-server-$(BuildConfiguration) deployment'
displayName: 'Build Dockerfile'
@@ -80,6 +84,10 @@ jobs:
vmImage: 'ubuntu-latest'
steps:
- script: echo "##vso[task.setvariable variable=JellyfinVersion]$( awk -F '/' '{ print $NF }' <<<'$(Build.SourceBranch)' | sed 's/^v//' )"
displayName: Set release version (stable)
condition: startsWith(variables['Build.SourceBranch'], 'refs/tags/v')
- task: DownloadPipelineArtifact@2
displayName: 'Download OpenAPI Spec'
inputs:

1
.copr Symbolic link
View File

@@ -0,0 +1 @@
fedora

View File

@@ -1 +0,0 @@
../fedora/Makefile

29
.github/stale.yml vendored
View File

@@ -1,29 +0,0 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 120
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 21
# Issues with these labels will never be considered stale
exemptLabels:
- regression
- security
- dotnet-3.0-future
- roadmap
- future
- feature
- enhancement
- confirmed
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has gone 120 days without comment. To avoid abandoned issues, it will be closed in 21 days if there are no new comments.
If you're the original submitter of this issue, please comment confirming if this issue still affects you in the latest release or nightlies, or close the issue if it has been fixed. If you're another user also affected by this bug, please comment confirming so. Either action will remove the stale label.
This bot exists to prevent issues from becoming stale and forgotten. Jellyfin is always moving forward, and bugs are often fixed as side effects of other changes. We therefore ask that bug report authors remain vigilant about their issues to ensure they are closed if fixed, or re-confirmed - perhaps with fresh logs or reproduction examples - regularly. If you have any questions you can reach us on [Matrix or Social Media](https://docs.jellyfin.org/general/getting-help.html).
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false
# Disable automatic closing of pull requests
pulls:
daysUntilClose: false

View File

@@ -20,9 +20,9 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
uses: actions/setup-dotnet@v2
with:
dotnet-version: '6.0.x'

View File

@@ -23,7 +23,7 @@ jobs:
reactions: '+1'
- name: Checkout the latest code
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
token: ${{ secrets.JF_BOT_TOKEN }}
fetch-depth: 0
@@ -47,7 +47,7 @@ jobs:
reactions: eyes
- name: Checkout the latest code
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
token: ${{ secrets.JF_BOT_TOKEN }}
fetch-depth: 0

View File

@@ -12,12 +12,12 @@ jobs:
permissions: read-all
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.ref }}
ref: ${{ github.event.pull_request.head.sha }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
uses: actions/setup-dotnet@v2
with:
dotnet-version: '6.0.x'
- name: Generate openapi.json
@@ -37,11 +37,11 @@ jobs:
permissions: read-all
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
ref: ${{ github.base_ref }}
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
uses: actions/setup-dotnet@v2
with:
dotnet-version: '6.0.x'
- name: Generate openapi.json

27
.github/workflows/repo-stale.yaml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: Issue Stale Check
on:
schedule:
- cron: '30 1 * * *'
workflow_dispatch:
jobs:
stale:
runs-on: ubuntu-latest
if: ${{ contains(github.repository, 'jellyfin/') }}
steps:
- uses: actions/stale@v5
with:
repo-token: ${{ secrets.JF_BOT_TOKEN }}
days-before-stale: 120
days-before-pr-stale: -1
days-before-close: 21
days-before-pr-close: -1
exempt-issue-labels: regression,security,roadmap,future,feature,enhancement,confirmed
stale-issue-label: stale
stale-issue-message: |-
This issue has gone 120 days without comment. To avoid abandoned issues, it will be closed in 21 days if there are no new comments.
If you're the original submitter of this issue, please comment confirming if this issue still affects you in the latest release or master branch, or close the issue if it has been fixed. If you're another user also affected by this bug, please comment confirming so. Either action will remove the stale label.
This bot exists to prevent issues from becoming stale and forgotten. Jellyfin is always moving forward, and bugs are often fixed as side effects of other changes. We therefore ask that bug report authors remain vigilant about their issues to ensure they are closed if fixed, or re-confirmed - perhaps with fresh logs or reproduction examples - regularly. If you have any questions you can reach us on [Matrix or Social Media](https://docs.jellyfin.org/general/getting-help.html).

4
BannedSymbols.txt Normal file
View File

@@ -0,0 +1,4 @@
P:System.Threading.Tasks.Task`1.Result
M:System.Guid.op_Equality(System.Guid,System.Guid)
M:System.Guid.op_Inequality(System.Guid,System.Guid)
M:System.Guid.Equals(System.Object)

View File

@@ -1,5 +1,6 @@
# Jellyfin Contributors
- [1337joe](https://github.com/1337joe)
- [97carmine](https://github.com/97carmine)
- [Abbe98](https://github.com/Abbe98)
- [agrenott](https://github.com/agrenott)
@@ -45,6 +46,7 @@
- [Froghut](https://github.com/Froghut)
- [fruhnow](https://github.com/fruhnow)
- [geilername](https://github.com/geilername)
- [GermanCoding](https://github.com/GermanCoding)
- [gnattu](https://github.com/gnattu)
- [GodTamIt](https://github.com/GodTamIt)
- [grafixeyehero](https://github.com/grafixeyehero)
@@ -76,6 +78,7 @@
- [mitchfizz05](https://github.com/mitchfizz05)
- [MrTimscampi](https://github.com/MrTimscampi)
- [n8225](https://github.com/n8225)
- [Nalsai](https://github.com/Nalsai)
- [Narfinger](https://github.com/Narfinger)
- [NathanPickard](https://github.com/NathanPickard)
- [neilsb](https://github.com/neilsb)
@@ -115,6 +118,7 @@
- [ssenart](https://github.com/ssenart)
- [stanionascu](https://github.com/stanionascu)
- [stevehayles](https://github.com/stevehayles)
- [StollD](https://github.com/StollD)
- [SuperSandro2000](https://github.com/SuperSandro2000)
- [tbraeutigam](https://github.com/tbraeutigam)
- [teacupx](https://github.com/teacupx)
@@ -150,6 +154,9 @@
- [ianjazz246](https://github.com/ianjazz246)
- [peterspenler](https://github.com/peterspenler)
- [MBR-0001](https://github.com/MBR-0001)
- [jonas-resch](https://github.com/jonas-resch)
- [vgambier](https://github.com/vgambier)
- [MinecraftPlaye](https://github.com/MinecraftPlaye)
# Emby Contributors
@@ -216,3 +223,5 @@
- [olsh](https://github.com/olsh)
- [lbenini](https://github.com/lbenini)
- [gnuyent](https://github.com/gnuyent)
- [Matthew Jones](https://github.com/matthew-jones-uk)
- [Jakob Kukla](https://github.com/jakobkukla)

View File

@@ -6,7 +6,7 @@
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)/jellyfin.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<PropertyGroup>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
@@ -14,4 +14,8 @@
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
</PropertyGroup>
<ItemGroup>
<AdditionalFiles Include="$(SolutionDir)/BannedSymbols.txt" />
</ItemGroup>
</Project>

View File

@@ -22,10 +22,10 @@ ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn
ENV NVIDIA_DRIVER_CAPABILITIES="compute,video,utility"
# https://github.com/intel/compute-runtime/releases
ARG GMMLIB_VERSION=21.2.1
ARG IGC_VERSION=1.0.8517
ARG NEO_VERSION=21.35.20826
ARG LEVEL_ZERO_VERSION=1.2.20826
ARG GMMLIB_VERSION=22.0.2
ARG IGC_VERSION=1.0.10395
ARG NEO_VERSION=22.08.22549
ARG LEVEL_ZERO_VERSION=1.3.22549
# Install dependencies:
# mesa-va-drivers: needed for AMD VAAPI. Mesa >= 20.1 is required for HEVC transcoding.
@@ -48,8 +48,7 @@ RUN apt-get update \
&& wget https://github.com/intel/compute-runtime/releases/download/${NEO_VERSION}/intel-gmmlib_${GMMLIB_VERSION}_amd64.deb \
&& wget https://github.com/intel/intel-graphics-compiler/releases/download/igc-${IGC_VERSION}/intel-igc-core_${IGC_VERSION}_amd64.deb \
&& wget https://github.com/intel/intel-graphics-compiler/releases/download/igc-${IGC_VERSION}/intel-igc-opencl_${IGC_VERSION}_amd64.deb \
&& wget https://github.com/intel/compute-runtime/releases/download/${NEO_VERSION}/intel-opencl_${NEO_VERSION}_amd64.deb \
&& wget https://github.com/intel/compute-runtime/releases/download/${NEO_VERSION}/intel-ocloc_${NEO_VERSION}_amd64.deb \
&& wget https://github.com/intel/compute-runtime/releases/download/${NEO_VERSION}/intel-opencl-icd_${NEO_VERSION}_amd64.deb \
&& wget https://github.com/intel/compute-runtime/releases/download/${NEO_VERSION}/intel-level-zero-gpu_${LEVEL_ZERO_VERSION}_amd64.deb \
&& dpkg -i *.deb \
&& cd .. \
@@ -73,7 +72,7 @@ COPY . .
ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
# because of changes in docker and systemd we need to not build in parallel at the moment
# see https://success.docker.com/article/how-to-reserve-resource-temporarily-unavailable-errors-due-to-tasksmax-setting
RUN dotnet publish Jellyfin.Server --disable-parallel --configuration Release --output="/jellyfin" --self-contained --runtime linux-x64 "-p:DebugSymbols=false;DebugType=none"
RUN dotnet publish Jellyfin.Server --disable-parallel --configuration Release --output="/jellyfin" --self-contained --runtime linux-x64 -p:DebugSymbols=false -p:DebugType=none
FROM app
@@ -83,7 +82,7 @@ COPY --from=builder /jellyfin /jellyfin
COPY --from=web-builder /dist /jellyfin/jellyfin-web
EXPOSE 8096
VOLUME /cache /config /media
VOLUME /cache /config
ENTRYPOINT ["./jellyfin/jellyfin", \
"--datadir", "/config", \
"--cachedir", "/cache", \

View File

@@ -64,7 +64,7 @@ ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
# Discard objs - may cause failures if exists
RUN find . -type d -name obj | xargs -r rm -r
# Build
RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin" --self-contained --runtime linux-arm "-p:DebugSymbols=false;DebugType=none"
RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin" --self-contained --runtime linux-arm -p:DebugSymbols=false -p:DebugType=none
FROM app
@@ -74,7 +74,7 @@ COPY --from=builder /jellyfin /jellyfin
COPY --from=web-builder /dist /jellyfin/jellyfin-web
EXPOSE 8096
VOLUME /cache /config /media
VOLUME /cache /config
ENTRYPOINT ["./jellyfin/jellyfin", \
"--datadir", "/config", \
"--cachedir", "/cache", \

View File

@@ -55,7 +55,7 @@ ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
# Discard objs - may cause failures if exists
RUN find . -type d -name obj | xargs -r rm -r
# Build
RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin" --self-contained --runtime linux-arm64 "-p:DebugSymbols=false;DebugType=none"
RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin" --self-contained --runtime linux-arm64 -p:DebugSymbols=false -p:DebugType=none
FROM app
@@ -65,7 +65,7 @@ COPY --from=builder /jellyfin /jellyfin
COPY --from=web-builder /dist /jellyfin/jellyfin-web
EXPOSE 8096
VOLUME /cache /config /media
VOLUME /cache /config
ENTRYPOINT ["./jellyfin/jellyfin", \
"--datadir", "/config", \
"--cachedir", "/cache", \

View File

@@ -13,7 +13,7 @@ namespace Emby.Dlna.Configuration
public DlnaOptions()
{
EnablePlayTo = true;
EnableServer = true;
EnableServer = false;
BlastAliveMessages = true;
SendOnlyMatchedHost = true;
ClientDiscoveryIntervalSeconds = 60;

View File

@@ -18,11 +18,8 @@ using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Playlists;
using MediaBrowser.Controller.TV;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Dto;
@@ -30,12 +27,7 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Querying;
using Microsoft.Extensions.Logging;
using Book = MediaBrowser.Controller.Entities.Book;
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
using Genre = MediaBrowser.Controller.Entities.Genre;
using Movie = MediaBrowser.Controller.Entities.Movies.Movie;
using MusicAlbum = MediaBrowser.Controller.Entities.Audio.MusicAlbum;
using Series = MediaBrowser.Controller.Entities.TV.Series;
namespace Emby.Dlna.ContentDirectory
{
@@ -395,6 +387,7 @@ namespace Emby.Dlna.ContentDirectory
}
writer.WriteFullEndElement();
writer.Flush();
xmlWriter.WriteElementString("Result", builder.ToString());
}
@@ -484,6 +477,7 @@ namespace Emby.Dlna.ContentDirectory
}
writer.WriteFullEndElement();
writer.Flush();
xmlWriter.WriteElementString("Result", builder.ToString());
}
@@ -537,7 +531,7 @@ namespace Emby.Dlna.ContentDirectory
User = user,
Recursive = true,
IsMissing = false,
ExcludeItemTypes = new[] { nameof(Book) },
ExcludeItemTypes = new[] { BaseItemKind.Book },
IsFolder = isFolder,
MediaTypes = mediaTypes,
DtoOptions = GetDtoOptions()
@@ -617,7 +611,7 @@ namespace Emby.Dlna.ContentDirectory
Limit = limit,
StartIndex = startIndex,
IsVirtualItem = false,
ExcludeItemTypes = new[] { nameof(Book) },
ExcludeItemTypes = new[] { BaseItemKind.Book },
IsPlaceHolder = false,
DtoOptions = GetDtoOptions(),
OrderBy = GetOrderBy(sort, folder.IsPreSorted)
@@ -625,7 +619,7 @@ namespace Emby.Dlna.ContentDirectory
var queryResult = folder.GetItems(query);
return ToResult(queryResult);
return ToResult(startIndex, queryResult);
}
/// <summary>
@@ -642,13 +636,13 @@ namespace Emby.Dlna.ContentDirectory
{
StartIndex = startIndex,
Limit = limit,
IncludeItemTypes = new[] { nameof(LiveTvChannel) },
IncludeItemTypes = new[] { BaseItemKind.LiveTvChannel },
OrderBy = GetOrderBy(sort, false)
};
var result = _libraryManager.GetItemsResult(query);
return ToResult(result);
return ToResult(startIndex, result);
}
/// <summary>
@@ -673,39 +667,39 @@ namespace Emby.Dlna.ContentDirectory
switch (stubType)
{
case StubType.Latest:
return GetLatest(item, query, nameof(Audio));
return GetLatest(item, query, BaseItemKind.Audio);
case StubType.Playlists:
return GetMusicPlaylists(query);
case StubType.Albums:
return GetChildrenOfItem(item, query, nameof(MusicAlbum));
return GetChildrenOfItem(item, query, BaseItemKind.MusicAlbum);
case StubType.Artists:
return GetMusicArtists(item, query);
case StubType.AlbumArtists:
return GetMusicAlbumArtists(item, query);
case StubType.FavoriteAlbums:
return GetChildrenOfItem(item, query, nameof(MusicAlbum), true);
return GetChildrenOfItem(item, query, BaseItemKind.MusicAlbum, true);
case StubType.FavoriteArtists:
return GetFavoriteArtists(item, query);
case StubType.FavoriteSongs:
return GetChildrenOfItem(item, query, nameof(Audio), true);
return GetChildrenOfItem(item, query, BaseItemKind.Audio, true);
case StubType.Songs:
return GetChildrenOfItem(item, query, nameof(Audio));
return GetChildrenOfItem(item, query, BaseItemKind.Audio);
case StubType.Genres:
return GetMusicGenres(item, query);
}
var serverItems = new ServerItem[]
{
new (item, StubType.Latest),
new (item, StubType.Playlists),
new (item, StubType.Albums),
new (item, StubType.AlbumArtists),
new (item, StubType.Artists),
new (item, StubType.Songs),
new (item, StubType.Genres),
new (item, StubType.FavoriteArtists),
new (item, StubType.FavoriteAlbums),
new (item, StubType.FavoriteSongs)
new(item, StubType.Latest),
new(item, StubType.Playlists),
new(item, StubType.Albums),
new(item, StubType.AlbumArtists),
new(item, StubType.Artists),
new(item, StubType.Songs),
new(item, StubType.Genres),
new(item, StubType.FavoriteArtists),
new(item, StubType.FavoriteAlbums),
new(item, StubType.FavoriteSongs)
};
if (limit < serverItems.Length)
@@ -713,11 +707,10 @@ namespace Emby.Dlna.ContentDirectory
serverItems = serverItems[..limit.Value];
}
return new QueryResult<ServerItem>
{
Items = serverItems,
TotalRecordCount = serverItems.Length
};
return new QueryResult<ServerItem>(
startIndex,
serverItems.Length,
serverItems);
}
/// <summary>
@@ -744,25 +737,25 @@ namespace Emby.Dlna.ContentDirectory
case StubType.ContinueWatching:
return GetMovieContinueWatching(item, query);
case StubType.Latest:
return GetLatest(item, query, nameof(Movie));
return GetLatest(item, query, BaseItemKind.Movie);
case StubType.Movies:
return GetChildrenOfItem(item, query, nameof(Movie));
return GetChildrenOfItem(item, query, BaseItemKind.Movie);
case StubType.Collections:
return GetMovieCollections(query);
case StubType.Favorites:
return GetChildrenOfItem(item, query, nameof(Movie), true);
return GetChildrenOfItem(item, query, BaseItemKind.Movie, true);
case StubType.Genres:
return GetGenres(item, query);
}
var array = new ServerItem[]
{
new (item, StubType.ContinueWatching),
new (item, StubType.Latest),
new (item, StubType.Movies),
new (item, StubType.Collections),
new (item, StubType.Favorites),
new (item, StubType.Genres)
new(item, StubType.ContinueWatching),
new(item, StubType.Latest),
new(item, StubType.Movies),
new(item, StubType.Collections),
new(item, StubType.Favorites),
new(item, StubType.Genres)
};
if (limit < array.Length)
@@ -770,11 +763,10 @@ namespace Emby.Dlna.ContentDirectory
array = array[..limit.Value];
}
return new QueryResult<ServerItem>
{
Items = array,
TotalRecordCount = array.Length
};
return new QueryResult<ServerItem>(
startIndex,
array.Length,
array);
}
/// <summary>
@@ -796,11 +788,10 @@ namespace Emby.Dlna.ContentDirectory
.Select(i => new ServerItem(i, StubType.Folder))
.ToArray();
return new QueryResult<ServerItem>
{
Items = items,
TotalRecordCount = totalRecordCount
};
return new QueryResult<ServerItem>(
startIndex,
totalRecordCount,
items);
}
/// <summary>
@@ -829,26 +820,26 @@ namespace Emby.Dlna.ContentDirectory
case StubType.NextUp:
return GetNextUp(item, query);
case StubType.Latest:
return GetLatest(item, query, nameof(Episode));
return GetLatest(item, query, BaseItemKind.Episode);
case StubType.Series:
return GetChildrenOfItem(item, query, nameof(Series));
return GetChildrenOfItem(item, query, BaseItemKind.Series);
case StubType.FavoriteSeries:
return GetChildrenOfItem(item, query, nameof(Series), true);
return GetChildrenOfItem(item, query, BaseItemKind.Series, true);
case StubType.FavoriteEpisodes:
return GetChildrenOfItem(item, query, nameof(Episode), true);
return GetChildrenOfItem(item, query, BaseItemKind.Episode, true);
case StubType.Genres:
return GetGenres(item, query);
}
var serverItems = new ServerItem[]
{
new (item, StubType.ContinueWatching),
new (item, StubType.NextUp),
new (item, StubType.Latest),
new (item, StubType.Series),
new (item, StubType.FavoriteSeries),
new (item, StubType.FavoriteEpisodes),
new (item, StubType.Genres)
new(item, StubType.ContinueWatching),
new(item, StubType.NextUp),
new(item, StubType.Latest),
new(item, StubType.Series),
new(item, StubType.FavoriteSeries),
new(item, StubType.FavoriteEpisodes),
new(item, StubType.Genres)
};
if (limit < serverItems.Length)
@@ -856,11 +847,10 @@ namespace Emby.Dlna.ContentDirectory
serverItems = serverItems[..limit.Value];
}
return new QueryResult<ServerItem>
{
Items = serverItems,
TotalRecordCount = serverItems.Length
};
return new QueryResult<ServerItem>(
startIndex,
serverItems.Length,
serverItems);
}
/// <summary>
@@ -885,7 +875,7 @@ namespace Emby.Dlna.ContentDirectory
var result = _libraryManager.GetItemsResult(query);
return ToResult(result);
return ToResult(query.StartIndex, result);
}
/// <summary>
@@ -896,11 +886,11 @@ namespace Emby.Dlna.ContentDirectory
private QueryResult<ServerItem> GetMovieCollections(InternalItemsQuery query)
{
query.Recursive = true;
query.IncludeItemTypes = new[] { nameof(BoxSet) };
query.IncludeItemTypes = new[] { BaseItemKind.BoxSet };
var result = _libraryManager.GetItemsResult(query);
return ToResult(result);
return ToResult(query.StartIndex, result);
}
/// <summary>
@@ -911,7 +901,7 @@ namespace Emby.Dlna.ContentDirectory
/// <param name="itemType">The item type.</param>
/// <param name="isFavorite">A value indicating whether to only fetch favorite items.</param>
/// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns>
private QueryResult<ServerItem> GetChildrenOfItem(BaseItem parent, InternalItemsQuery query, string itemType, bool isFavorite = false)
private QueryResult<ServerItem> GetChildrenOfItem(BaseItem parent, InternalItemsQuery query, BaseItemKind itemType, bool isFavorite = false)
{
query.Recursive = true;
query.Parent = parent;
@@ -920,7 +910,7 @@ namespace Emby.Dlna.ContentDirectory
var result = _libraryManager.GetItemsResult(query);
return ToResult(result);
return ToResult(query.StartIndex, result);
}
/// <summary>
@@ -937,7 +927,7 @@ namespace Emby.Dlna.ContentDirectory
query.AncestorIds = new[] { parent.Id };
var genresResult = _libraryManager.GetGenres(query);
return ToResult(genresResult);
return ToResult(query.StartIndex, genresResult);
}
/// <summary>
@@ -953,7 +943,7 @@ namespace Emby.Dlna.ContentDirectory
query.AncestorIds = new[] { parent.Id };
var genresResult = _libraryManager.GetMusicGenres(query);
return ToResult(genresResult);
return ToResult(query.StartIndex, genresResult);
}
/// <summary>
@@ -969,7 +959,7 @@ namespace Emby.Dlna.ContentDirectory
query.AncestorIds = new[] { parent.Id };
var artists = _libraryManager.GetAlbumArtists(query);
return ToResult(artists);
return ToResult(query.StartIndex, artists);
}
/// <summary>
@@ -984,7 +974,7 @@ namespace Emby.Dlna.ContentDirectory
query.OrderBy = Array.Empty<(string, SortOrder)>();
query.AncestorIds = new[] { parent.Id };
var artists = _libraryManager.GetArtists(query);
return ToResult(artists);
return ToResult(query.StartIndex, artists);
}
/// <summary>
@@ -1000,7 +990,7 @@ namespace Emby.Dlna.ContentDirectory
query.AncestorIds = new[] { parent.Id };
query.IsFavorite = true;
var artists = _libraryManager.GetArtists(query);
return ToResult(artists);
return ToResult(query.StartIndex, artists);
}
/// <summary>
@@ -1011,12 +1001,12 @@ namespace Emby.Dlna.ContentDirectory
private QueryResult<ServerItem> GetMusicPlaylists(InternalItemsQuery query)
{
query.Parent = null;
query.IncludeItemTypes = new[] { nameof(Playlist) };
query.IncludeItemTypes = new[] { BaseItemKind.Playlist };
query.Recursive = true;
var result = _libraryManager.GetItemsResult(query);
return ToResult(result);
return ToResult(query.StartIndex, result);
}
/// <summary>
@@ -1040,7 +1030,7 @@ namespace Emby.Dlna.ContentDirectory
new[] { parent },
query.DtoOptions);
return ToResult(result);
return ToResult(query.StartIndex, result);
}
/// <summary>
@@ -1050,7 +1040,7 @@ namespace Emby.Dlna.ContentDirectory
/// <param name="query">The <see cref="InternalItemsQuery"/>.</param>
/// <param name="itemType">The item type.</param>
/// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns>
private QueryResult<ServerItem> GetLatest(BaseItem parent, InternalItemsQuery query, string itemType)
private QueryResult<ServerItem> GetLatest(BaseItem parent, InternalItemsQuery query, BaseItemKind itemType)
{
query.OrderBy = Array.Empty<(string, SortOrder)>();
@@ -1066,7 +1056,7 @@ namespace Emby.Dlna.ContentDirectory
},
query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray();
return ToResult(items);
return ToResult(query.StartIndex, items);
}
/// <summary>
@@ -1084,7 +1074,7 @@ namespace Emby.Dlna.ContentDirectory
{
Recursive = true,
ArtistIds = new[] { item.Id },
IncludeItemTypes = new[] { nameof(MusicAlbum) },
IncludeItemTypes = new[] { BaseItemKind.MusicAlbum },
Limit = limit,
StartIndex = startIndex,
DtoOptions = GetDtoOptions(),
@@ -1093,7 +1083,7 @@ namespace Emby.Dlna.ContentDirectory
var result = _libraryManager.GetItemsResult(query);
return ToResult(result);
return ToResult(startIndex, result);
}
/// <summary>
@@ -1113,8 +1103,8 @@ namespace Emby.Dlna.ContentDirectory
GenreIds = new[] { item.Id },
IncludeItemTypes = new[]
{
nameof(Movie),
nameof(Series)
BaseItemKind.Movie,
BaseItemKind.Series
},
Limit = limit,
StartIndex = startIndex,
@@ -1124,7 +1114,7 @@ namespace Emby.Dlna.ContentDirectory
var result = _libraryManager.GetItemsResult(query);
return ToResult(result);
return ToResult(startIndex, result);
}
/// <summary>
@@ -1142,7 +1132,7 @@ namespace Emby.Dlna.ContentDirectory
{
Recursive = true,
GenreIds = new[] { item.Id },
IncludeItemTypes = new[] { nameof(MusicAlbum) },
IncludeItemTypes = new[] { BaseItemKind.MusicAlbum },
Limit = limit,
StartIndex = startIndex,
DtoOptions = GetDtoOptions(),
@@ -1151,33 +1141,34 @@ namespace Emby.Dlna.ContentDirectory
var result = _libraryManager.GetItemsResult(query);
return ToResult(result);
return ToResult(startIndex, result);
}
/// <summary>
/// Converts <see cref="IReadOnlyCollection{BaseItem}"/> into a <see cref="QueryResult{ServerItem}"/>.
/// </summary>
/// <param name="startIndex">The start index.</param>
/// <param name="result">An array of <see cref="BaseItem"/>.</param>
/// <returns>A <see cref="QueryResult{ServerItem}"/>.</returns>
private static QueryResult<ServerItem> ToResult(IReadOnlyCollection<BaseItem> result)
private static QueryResult<ServerItem> ToResult(int? startIndex, IReadOnlyCollection<BaseItem> result)
{
var serverItems = result
.Select(i => new ServerItem(i, null))
.ToArray();
return new QueryResult<ServerItem>
{
TotalRecordCount = result.Count,
Items = serverItems
};
return new QueryResult<ServerItem>(
startIndex,
result.Count,
serverItems);
}
/// <summary>
/// Converts a <see cref="QueryResult{BaseItem}"/> to a <see cref="QueryResult{ServerItem}"/>.
/// </summary>
/// <param name="startIndex">The index the result started at.</param>
/// <param name="result">A <see cref="QueryResult{BaseItem}"/>.</param>
/// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns>
private static QueryResult<ServerItem> ToResult(QueryResult<BaseItem> result)
private static QueryResult<ServerItem> ToResult(int? startIndex, QueryResult<BaseItem> result)
{
var length = result.Items.Count;
var serverItems = new ServerItem[length];
@@ -1186,32 +1177,31 @@ namespace Emby.Dlna.ContentDirectory
serverItems[i] = new ServerItem(result.Items[i], null);
}
return new QueryResult<ServerItem>
{
TotalRecordCount = result.TotalRecordCount,
Items = serverItems
};
return new QueryResult<ServerItem>(
startIndex,
result.TotalRecordCount,
serverItems);
}
/// <summary>
/// Converts a query result to a <see cref="QueryResult{ServerItem}"/>.
/// </summary>
/// <param name="startIndex">The start index.</param>
/// <param name="result">A <see cref="QueryResult{BaseItem}"/>.</param>
/// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns>
private static QueryResult<ServerItem> ToResult(QueryResult<(BaseItem, ItemCounts)> result)
private static QueryResult<ServerItem> ToResult(int? startIndex, QueryResult<(BaseItem Item, ItemCounts ItemCounts)> result)
{
var length = result.Items.Count;
var serverItems = new ServerItem[length];
for (var i = 0; i < length; i++)
{
serverItems[i] = new ServerItem(result.Items[i].Item1, null);
serverItems[i] = new ServerItem(result.Items[i].Item, null);
}
return new QueryResult<ServerItem>
{
TotalRecordCount = result.TotalRecordCount,
Items = serverItems
};
return new QueryResult<ServerItem>(
startIndex,
result.TotalRecordCount,
serverItems);
}
/// <summary>
@@ -1219,7 +1209,7 @@ namespace Emby.Dlna.ContentDirectory
/// </summary>
/// <param name="sort">The <see cref="SortCriteria"/>.</param>
/// <param name="isPreSorted">True if pre-sorted.</param>
private static (string, SortOrder)[] GetOrderBy(SortCriteria sort, bool isPreSorted)
private static (string SortName, SortOrder SortOrder)[] GetOrderBy(SortCriteria sort, bool isPreSorted)
{
return isPreSorted ? Array.Empty<(string, SortOrder)>() : new[] { (ItemSortBy.SortName, sort.SortOrder) };
}

View File

@@ -160,7 +160,7 @@ namespace Emby.Dlna.Didl
else
{
var parent = item.DisplayParentId;
if (!parent.Equals(Guid.Empty))
if (!parent.Equals(default))
{
writer.WriteAttributeString("parentID", GetClientId(parent, null));
}
@@ -221,6 +221,7 @@ namespace Emby.Dlna.Didl
streamInfo.IsDirectStream,
streamInfo.RunTimeTicks ?? 0,
streamInfo.TargetVideoProfile,
streamInfo.TargetVideoRangeType,
streamInfo.TargetVideoLevel,
streamInfo.TargetFramerate ?? 0,
streamInfo.TargetPacketLength,
@@ -376,6 +377,7 @@ namespace Emby.Dlna.Didl
targetHeight,
streamInfo.TargetVideoBitDepth,
streamInfo.TargetVideoProfile,
streamInfo.TargetVideoRangeType,
streamInfo.TargetVideoLevel,
streamInfo.TargetFramerate ?? 0,
streamInfo.TargetPacketLength,
@@ -657,7 +659,7 @@ namespace Emby.Dlna.Didl
else
{
var parent = folder.DisplayParentId;
if (parent.Equals(Guid.Empty))
if (parent.Equals(default))
{
writer.WriteAttributeString("parentID", "0");
}
@@ -989,7 +991,7 @@ namespace Emby.Dlna.Didl
writer.WriteAttributeString("dlna", "profileID", NsDlna, _profile.AlbumArtPn);
}
writer.WriteString(albumArtUrlInfo.url);
writer.WriteString(albumArtUrlInfo.Url);
writer.WriteFullEndElement();
// TODO: Remove these default values
@@ -998,7 +1000,7 @@ namespace Emby.Dlna.Didl
_profile.MaxIconWidth ?? 48,
_profile.MaxIconHeight ?? 48,
"jpg");
writer.WriteElementString("upnp", "icon", NsUpnp, iconUrlInfo.url);
writer.WriteElementString("upnp", "icon", NsUpnp, iconUrlInfo.Url);
if (!_profile.EnableAlbumArtInDidl)
{
@@ -1045,8 +1047,8 @@ namespace Emby.Dlna.Didl
// Images must have a reported size or many clients (Bubble upnp), will only use the first thumbnail
// rather than using a larger one when available
var width = albumartUrlInfo.width ?? maxWidth;
var height = albumartUrlInfo.height ?? maxHeight;
var width = albumartUrlInfo.Width ?? maxWidth;
var height = albumartUrlInfo.Height ?? maxHeight;
var contentFeatures = ContentFeatureBuilder.BuildImageHeader(_profile, format, width, height, imageInfo.IsDirectStream, org_Pn);
@@ -1062,7 +1064,7 @@ namespace Emby.Dlna.Didl
"resolution",
string.Format(CultureInfo.InvariantCulture, "{0}x{1}", width, height));
writer.WriteString(albumartUrlInfo.url);
writer.WriteString(albumartUrlInfo.Url);
writer.WriteFullEndElement();
}
@@ -1200,7 +1202,7 @@ namespace Emby.Dlna.Didl
return id;
}
private (string url, int? width, int? height) GetImageUrl(ImageDownloadInfo info, int maxWidth, int maxHeight, string format)
private (string Url, int? Width, int? Height) GetImageUrl(ImageDownloadInfo info, int maxWidth, int maxHeight, string format)
{
var url = string.Format(
CultureInfo.InvariantCulture,

View File

@@ -17,8 +17,7 @@ namespace Emby.Dlna.Didl
public Filter(string filter)
{
_all = string.Equals(filter, "*", StringComparison.OrdinalIgnoreCase);
_fields = (filter ?? string.Empty).Split(',', StringSplitOptions.RemoveEmptyEntries);
_fields = filter.Split(',', StringSplitOptions.RemoveEmptyEntries);
}
public bool Contains(string field)

View File

@@ -5,7 +5,6 @@ using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
@@ -84,8 +83,7 @@ namespace Emby.Dlna
{
lock (_profiles)
{
var list = _profiles.Values.ToList();
return list
return _profiles.Values
.OrderBy(i => i.Item1.Info.Type == DeviceProfileType.User ? 0 : 1)
.ThenBy(i => i.Item1.Info.Name)
.Select(i => i.Item2)
@@ -227,11 +225,8 @@ namespace Emby.Dlna
{
try
{
var xmlFies = _fileSystem.GetFilePaths(path)
return _fileSystem.GetFilePaths(path)
.Where(i => string.Equals(Path.GetExtension(i), ".xml", StringComparison.OrdinalIgnoreCase))
.ToList();
return xmlFies
.Select(i => ParseProfileFile(i, type))
.Where(i => i != null)
.ToList()!; // We just filtered out all the nulls
@@ -253,11 +248,8 @@ namespace Emby.Dlna
try
{
DeviceProfile profile;
var tempProfile = (DeviceProfile)_xmlSerializer.DeserializeFromFile(typeof(DeviceProfile), path);
profile = ReserializeProfile(tempProfile);
var profile = ReserializeProfile(tempProfile);
profile.Id = path.ToLowerInvariant().GetMD5().ToString("N", CultureInfo.InvariantCulture);
@@ -296,8 +288,7 @@ namespace Emby.Dlna
{
lock (_profiles)
{
var list = _profiles.Values.ToList();
return list
return _profiles.Values
.Select(i => i.Item1)
.OrderBy(i => i.Info.Type == DeviceProfileType.User ? 0 : 1)
.ThenBy(i => i.Info.Name);
@@ -350,9 +341,10 @@ namespace Emby.Dlna
Directory.CreateDirectory(systemProfilesPath);
var fileOptions = AsyncFile.WriteOptions;
fileOptions.Mode = FileMode.CreateNew;
fileOptions.Mode = FileMode.Create;
fileOptions.PreallocationSize = length;
using (var fileStream = new FileStream(path, fileOptions))
var fileStream = new FileStream(path, fileOptions);
await using (fileStream.ConfigureAwait(false))
{
await stream.CopyToAsync(fileStream).ConfigureAwait(false);
}
@@ -464,7 +456,7 @@ namespace Emby.Dlna
/// <inheritdoc />
public string GetServerDescriptionXml(IHeaderDictionary headers, string serverUuId, string serverAddress)
{
var profile = GetDefaultProfile();
var profile = GetProfile(headers) ?? GetDefaultProfile();
var serverId = _appHost.SystemId;

View File

@@ -22,10 +22,18 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.406" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>

View File

@@ -124,7 +124,7 @@ namespace Emby.Dlna.Main
config);
Current = this;
var netConfig = config.GetConfiguration<NetworkConfiguration>("network");
var netConfig = config.GetConfiguration<NetworkConfiguration>(NetworkConfigurationStore.StoreKey);
_disabled = appHost.ListenWithHttps && netConfig.RequireHttps;
if (_disabled && _config.GetDlnaConfiguration().EnableServer)
@@ -262,7 +262,6 @@ namespace Emby.Dlna.Main
{
_publisher = new SsdpDevicePublisher(
_communicationsServer,
_networkManager,
MediaBrowser.Common.System.OperatingSystem.Name,
Environment.OSVersion.VersionString,
_config.GetDlnaConfiguration().SendOnlyMatchedHost)
@@ -314,7 +313,7 @@ namespace Emby.Dlna.Main
_logger.LogInformation("Registering publisher for {ResourceName} on {DeviceAddress}", fullService, address);
var uri = new UriBuilder(_appHost.GetApiUrlForLocalAccess(false) + descriptorUri);
var uri = new UriBuilder(_appHost.GetApiUrlForLocalAccess(address, false) + descriptorUri);
var device = new SsdpRootDevice
{
@@ -363,7 +362,7 @@ namespace Emby.Dlna.Main
guid = text.GetMD5();
}
return guid.ToString("N", CultureInfo.InvariantCulture);
return guid.ToString("D", CultureInfo.InvariantCulture);
}
private void SetProperies(SsdpDevice device, string fullDeviceType)
@@ -400,7 +399,6 @@ namespace Emby.Dlna.Main
_imageProcessor,
_deviceDiscovery,
_httpClientFactory,
_config,
_userDataManager,
_localization,
_mediaSourceManager,

View File

@@ -69,11 +69,11 @@ namespace Emby.Dlna.PlayTo
public TransportState TransportState { get; private set; }
public bool IsPlaying => TransportState == TransportState.Playing;
public bool IsPlaying => TransportState == TransportState.PLAYING;
public bool IsPaused => TransportState == TransportState.Paused || TransportState == TransportState.PausedPlayback;
public bool IsPaused => TransportState == TransportState.PAUSED_PLAYBACK;
public bool IsStopped => TransportState == TransportState.Stopped;
public bool IsStopped => TransportState == TransportState.STOPPED;
public Action OnDeviceUnavailable { get; set; }
@@ -494,7 +494,7 @@ namespace Emby.Dlna.PlayTo
cancellationToken: cancellationToken)
.ConfigureAwait(false);
TransportState = TransportState.Paused;
TransportState = TransportState.PAUSED_PLAYBACK;
RestartTimer(true);
}
@@ -527,7 +527,7 @@ namespace Emby.Dlna.PlayTo
if (transportState.HasValue)
{
// If we're not playing anything no need to get additional data
if (transportState.Value == TransportState.Stopped)
if (transportState.Value == TransportState.STOPPED)
{
UpdateMediaInfo(null, transportState.Value);
}
@@ -535,9 +535,9 @@ namespace Emby.Dlna.PlayTo
{
var tuple = await GetPositionInfo(avCommands, cancellationToken).ConfigureAwait(false);
var currentObject = tuple.Item2;
var currentObject = tuple.Track;
if (tuple.Item1 && currentObject == null)
if (tuple.Success && currentObject == null)
{
currentObject = await GetMediaInfo(avCommands, cancellationToken).ConfigureAwait(false);
}
@@ -556,7 +556,7 @@ namespace Emby.Dlna.PlayTo
}
// If we're not playing anything make sure we don't get data more often than necessary to keep the Session alive
if (transportState.Value == TransportState.Stopped)
if (transportState.Value == TransportState.STOPPED)
{
RestartTimerInactive();
}
@@ -797,7 +797,7 @@ namespace Emby.Dlna.PlayTo
return null;
}
private async Task<(bool, UBaseObject)> GetPositionInfo(TransportCommands avCommands, CancellationToken cancellationToken)
private async Task<(bool Success, UBaseObject Track)> GetPositionInfo(TransportCommands avCommands, CancellationToken cancellationToken)
{
var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetPositionInfo");
if (command == null)
@@ -1179,6 +1179,7 @@ namespace Emby.Dlna.PlayTo
return new Device(deviceProperties, httpClientFactory, logger);
}
#nullable enable
private static DeviceIcon CreateIcon(XElement element)
{
if (element == null)
@@ -1186,69 +1187,61 @@ namespace Emby.Dlna.PlayTo
throw new ArgumentNullException(nameof(element));
}
var mimeType = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("mimetype"));
var width = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("width"));
var height = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("height"));
var depth = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("depth"));
var url = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("url"));
var widthValue = int.Parse(width, NumberStyles.Integer, CultureInfo.InvariantCulture);
var heightValue = int.Parse(height, NumberStyles.Integer, CultureInfo.InvariantCulture);
_ = int.TryParse(width, NumberStyles.Integer, CultureInfo.InvariantCulture, out var widthValue);
_ = int.TryParse(height, NumberStyles.Integer, CultureInfo.InvariantCulture, out var heightValue);
return new DeviceIcon
{
Depth = depth,
Depth = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("depth")) ?? string.Empty,
Height = heightValue,
MimeType = mimeType,
Url = url,
MimeType = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("mimetype")) ?? string.Empty,
Url = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("url")) ?? string.Empty,
Width = widthValue
};
}
private static DeviceService Create(XElement element)
{
var type = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("serviceType"));
var id = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("serviceId"));
var scpdUrl = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("SCPDURL"));
var controlURL = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("controlURL"));
var eventSubURL = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("eventSubURL"));
return new DeviceService
=> new DeviceService()
{
ControlUrl = controlURL,
EventSubUrl = eventSubURL,
ScpdUrl = scpdUrl,
ServiceId = id,
ServiceType = type
ControlUrl = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("controlURL")) ?? string.Empty,
EventSubUrl = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("eventSubURL")) ?? string.Empty,
ScpdUrl = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("SCPDURL")) ?? string.Empty,
ServiceId = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("serviceId")) ?? string.Empty,
ServiceType = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("serviceType")) ?? string.Empty
};
}
private void UpdateMediaInfo(UBaseObject mediaInfo, TransportState state)
private void UpdateMediaInfo(UBaseObject? mediaInfo, TransportState state)
{
TransportState = state;
var previousMediaInfo = CurrentMediaInfo;
CurrentMediaInfo = mediaInfo;
if (previousMediaInfo == null && mediaInfo != null)
if (mediaInfo == null)
{
if (state != TransportState.Stopped)
if (previousMediaInfo != null)
{
OnPlaybackStop(previousMediaInfo);
}
}
else if (previousMediaInfo == null)
{
if (state != TransportState.STOPPED)
{
OnPlaybackStart(mediaInfo);
}
}
else if (mediaInfo != null && previousMediaInfo != null && !mediaInfo.Equals(previousMediaInfo))
{
OnMediaChanged(previousMediaInfo, mediaInfo);
}
else if (mediaInfo == null && previousMediaInfo != null)
{
OnPlaybackStop(previousMediaInfo);
}
else if (mediaInfo != null && mediaInfo.Equals(previousMediaInfo))
else if (mediaInfo.Equals(previousMediaInfo))
{
OnPlaybackProgress(mediaInfo);
}
else
{
OnMediaChanged(previousMediaInfo, mediaInfo);
}
}
private void OnPlaybackStart(UBaseObject mediaInfo)

View File

@@ -174,13 +174,13 @@ namespace Emby.Dlna.PlayTo
await _sessionManager.OnPlaybackStart(newItemProgress).ConfigureAwait(false);
// Send a message to the DLNA device to notify what is the next track in the playlist.
var currentItemIndex = _playlist.FindIndex(item => item.StreamInfo.ItemId == streamInfo.ItemId);
var currentItemIndex = _playlist.FindIndex(item => item.StreamInfo.ItemId.Equals(streamInfo.ItemId));
if (currentItemIndex >= 0)
{
_currentPlaylistIndex = currentItemIndex;
}
await SendNextTrackMessage(currentItemIndex, CancellationToken.None);
await SendNextTrackMessage(currentItemIndex, CancellationToken.None).ConfigureAwait(false);
}
catch (Exception ex)
{
@@ -210,9 +210,9 @@ namespace Emby.Dlna.PlayTo
var mediaSource = await streamInfo.GetMediaSource(CancellationToken.None).ConfigureAwait(false);
var duration = mediaSource == null ?
(_device.Duration == null ? (long?)null : _device.Duration.Value.Ticks) :
mediaSource.RunTimeTicks;
var duration = mediaSource == null
? _device.Duration?.Ticks
: mediaSource.RunTimeTicks;
var playedToCompletion = positionTicks.HasValue && positionTicks.Value == 0;
@@ -349,7 +349,9 @@ namespace Emby.Dlna.PlayTo
{
_logger.LogDebug("{0} - Received PlayRequest: {1}", _session.DeviceName, command.PlayCommand);
var user = command.ControllingUserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(command.ControllingUserId);
var user = command.ControllingUserId.Equals(default)
? null :
_userManager.GetUserById(command.ControllingUserId);
var items = new List<BaseItem>();
foreach (var id in command.ItemIds)
@@ -392,7 +394,7 @@ namespace Emby.Dlna.PlayTo
_playlist.AddRange(playlist);
}
if (!command.ControllingUserId.Equals(Guid.Empty))
if (!command.ControllingUserId.Equals(default))
{
_sessionManager.LogSessionActivity(
_session.Client,
@@ -446,14 +448,16 @@ namespace Emby.Dlna.PlayTo
if (info.Item != null && !EnableClientSideSeek(info))
{
var user = !_session.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(_session.UserId) : null;
var user = _session.UserId.Equals(default)
? null
: _userManager.GetUserById(_session.UserId);
var newItem = CreatePlaylistItem(info.Item, user, newPosition, info.MediaSourceId, info.AudioStreamIndex, info.SubtitleStreamIndex);
await _device.SetAvTransport(newItem.StreamUrl, GetDlnaHeaders(newItem), newItem.Didl, CancellationToken.None).ConfigureAwait(false);
// Send a message to the DLNA device to notify what is the next track in the play list.
var newItemIndex = _playlist.FindIndex(item => item.StreamUrl == newItem.StreamUrl);
await SendNextTrackMessage(newItemIndex, CancellationToken.None);
await SendNextTrackMessage(newItemIndex, CancellationToken.None).ConfigureAwait(false);
return;
}
@@ -557,6 +561,7 @@ namespace Emby.Dlna.PlayTo
streamInfo.IsDirectStream,
streamInfo.RunTimeTicks ?? 0,
streamInfo.TargetVideoProfile,
streamInfo.TargetVideoRangeType,
streamInfo.TargetVideoLevel,
streamInfo.TargetFramerate ?? 0,
streamInfo.TargetPacketLength,
@@ -569,7 +574,7 @@ namespace Emby.Dlna.PlayTo
streamInfo.TargetVideoCodecTag,
streamInfo.IsTargetAVC);
return list.Count == 0 ? null : list[0];
return list.FirstOrDefault();
}
return null;
@@ -654,7 +659,7 @@ namespace Emby.Dlna.PlayTo
await _device.SetAvTransport(currentitem.StreamUrl, GetDlnaHeaders(currentitem), currentitem.Didl, cancellationToken).ConfigureAwait(false);
// Send a message to the DLNA device to notify what is the next track in the play list.
await SendNextTrackMessage(index, cancellationToken);
await SendNextTrackMessage(index, cancellationToken).ConfigureAwait(false);
var streamInfo = currentitem.StreamInfo;
if (streamInfo.StartPositionTicks > 0 && EnableClientSideSeek(streamInfo))
@@ -764,14 +769,16 @@ namespace Emby.Dlna.PlayTo
{
var newPosition = GetProgressPositionTicks(info) ?? 0;
var user = !_session.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(_session.UserId) : null;
var user = _session.UserId.Equals(default)
? null
: _userManager.GetUserById(_session.UserId);
var newItem = CreatePlaylistItem(info.Item, user, newPosition, info.MediaSourceId, newIndex, info.SubtitleStreamIndex);
await _device.SetAvTransport(newItem.StreamUrl, GetDlnaHeaders(newItem), newItem.Didl, CancellationToken.None).ConfigureAwait(false);
// Send a message to the DLNA device to notify what is the next track in the play list.
var newItemIndex = _playlist.FindIndex(item => item.StreamUrl == newItem.StreamUrl);
await SendNextTrackMessage(newItemIndex, CancellationToken.None);
await SendNextTrackMessage(newItemIndex, CancellationToken.None).ConfigureAwait(false);
if (EnableClientSideSeek(newItem.StreamInfo))
{
@@ -793,14 +800,16 @@ namespace Emby.Dlna.PlayTo
{
var newPosition = GetProgressPositionTicks(info) ?? 0;
var user = !_session.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(_session.UserId) : null;
var user = _session.UserId.Equals(default)
? null
: _userManager.GetUserById(_session.UserId);
var newItem = CreatePlaylistItem(info.Item, user, newPosition, info.MediaSourceId, info.AudioStreamIndex, newIndex);
await _device.SetAvTransport(newItem.StreamUrl, GetDlnaHeaders(newItem), newItem.Didl, CancellationToken.None).ConfigureAwait(false);
// Send a message to the DLNA device to notify what is the next track in the play list.
var newItemIndex = _playlist.FindIndex(item => item.StreamUrl == newItem.StreamUrl);
await SendNextTrackMessage(newItemIndex, CancellationToken.None);
await SendNextTrackMessage(newItemIndex, CancellationToken.None).ConfigureAwait(false);
if (EnableClientSideSeek(newItem.StreamInfo) && newPosition > 0)
{
@@ -816,7 +825,7 @@ namespace Emby.Dlna.PlayTo
const int Interval = 500;
var currentWait = 0;
while (_device.TransportState != TransportState.Playing && currentWait < MaxWait)
while (_device.TransportState != TransportState.PLAYING && currentWait < MaxWait)
{
await Task.Delay(Interval, cancellationToken).ConfigureAwait(false);
currentWait += Interval;
@@ -883,7 +892,7 @@ namespace Emby.Dlna.PlayTo
private class StreamParams
{
private MediaSourceInfo mediaSource;
private MediaSourceInfo _mediaSource;
private IMediaSourceManager _mediaSourceManager;
public Guid ItemId { get; set; }
@@ -908,24 +917,22 @@ namespace Emby.Dlna.PlayTo
public async Task<MediaSourceInfo> GetMediaSource(CancellationToken cancellationToken)
{
if (mediaSource != null)
if (_mediaSource != null)
{
return mediaSource;
return _mediaSource;
}
var hasMediaSources = Item as IHasMediaSources;
if (hasMediaSources == null)
if (Item is not IHasMediaSources)
{
return null;
}
if (_mediaSourceManager != null)
{
mediaSource = await _mediaSourceManager.GetMediaSource(Item, MediaSourceId, LiveStreamId, false, cancellationToken).ConfigureAwait(false);
_mediaSource = await _mediaSourceManager.GetMediaSource(Item, MediaSourceId, LiveStreamId, false, cancellationToken).ConfigureAwait(false);
}
return mediaSource;
return _mediaSource;
}
private static Guid GetItemId(string url)
@@ -951,7 +958,7 @@ namespace Emby.Dlna.PlayTo
}
}
return Guid.Empty;
return default;
}
public static StreamParams ParseFromUrl(string url, ILibraryManager libraryManager, IMediaSourceManager mediaSourceManager)
@@ -966,7 +973,7 @@ namespace Emby.Dlna.PlayTo
ItemId = GetItemId(url)
};
if (request.ItemId.Equals(Guid.Empty))
if (request.ItemId.Equals(default))
{
return request;
}

View File

@@ -11,7 +11,6 @@ using System.Threading.Tasks;
using Jellyfin.Data.Events;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Library;
@@ -35,7 +34,6 @@ namespace Emby.Dlna.PlayTo
private readonly IServerApplicationHost _appHost;
private readonly IImageProcessor _imageProcessor;
private readonly IHttpClientFactory _httpClientFactory;
private readonly IServerConfigurationManager _config;
private readonly IUserDataManager _userDataManager;
private readonly ILocalizationManager _localization;
@@ -47,7 +45,7 @@ namespace Emby.Dlna.PlayTo
private SemaphoreSlim _sessionLock = new SemaphoreSlim(1, 1);
private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource();
public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClientFactory httpClientFactory, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder)
public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClientFactory httpClientFactory, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder)
{
_logger = logger;
_sessionManager = sessionManager;
@@ -58,7 +56,6 @@ namespace Emby.Dlna.PlayTo
_imageProcessor = imageProcessor;
_deviceDiscovery = deviceDiscovery;
_httpClientFactory = httpClientFactory;
_config = config;
_userDataManager = userDataManager;
_localization = localization;
_mediaSourceManager = mediaSourceManager;

View File

@@ -175,7 +175,7 @@ namespace Emby.Dlna.PlayTo
var sendValue = state.AllowedValues.FirstOrDefault(a => string.Equals(a, commandParameter, StringComparison.OrdinalIgnoreCase)) ??
(state.AllowedValues.Count > 0 ? state.AllowedValues[0] : value);
return string.Format(CultureInfo.InvariantCulture, "<{0} xmlns:dt=\"urn:schemas-microsoft-com:datatypes\" dt:dt=\"{1}\">{2}</{0}>", argument.Name, state.DataType ?? "string", sendValue);
return string.Format(CultureInfo.InvariantCulture, "<{0} xmlns:dt=\"urn:schemas-microsoft-com:datatypes\" dt:dt=\"{1}\">{2}</{0}>", argument.Name, state.DataType, sendValue);
}
return string.Format(CultureInfo.InvariantCulture, "<{0}>{1}</{0}>", argument.Name, value);

View File

@@ -2,12 +2,15 @@
namespace Emby.Dlna.PlayTo
{
/// <summary>
/// Core of the AVTransport service. It defines the conceptually top-
/// level state of the transport, for example, whether it is playing, recording, etc.
/// </summary>
public enum TransportState
{
Stopped,
Playing,
Transitioning,
PausedPlayback,
Paused
STOPPED,
PLAYING,
TRANSITIONING,
PAUSED_PLAYBACK
}
}

View File

@@ -167,8 +167,7 @@ namespace Emby.Dlna.Profiles
public void AddXmlRootAttribute(string name, string value)
{
var atts = XmlRootAttributes ?? System.Array.Empty<XmlAttribute>();
var list = atts.ToList();
var list = XmlRootAttributes.ToList();
list.Add(new XmlAttribute
{

View File

@@ -189,7 +189,7 @@ namespace Emby.Dlna.Server
builder.Append("<icon>");
builder.Append("<mimetype>")
.Append(SecurityElement.Escape(icon.MimeType ?? string.Empty))
.Append(SecurityElement.Escape(icon.MimeType))
.Append("</mimetype>");
builder.Append("<width>")
.Append(SecurityElement.Escape(icon.Width.ToString(CultureInfo.InvariantCulture)))
@@ -198,7 +198,7 @@ namespace Emby.Dlna.Server
.Append(SecurityElement.Escape(icon.Height.ToString(CultureInfo.InvariantCulture)))
.Append("</height>");
builder.Append("<depth>")
.Append(SecurityElement.Escape(icon.Depth ?? string.Empty))
.Append(SecurityElement.Escape(icon.Depth))
.Append("</depth>");
builder.Append("<url>")
.Append(BuildUrl(icon.Url))
@@ -219,10 +219,10 @@ namespace Emby.Dlna.Server
builder.Append("<service>");
builder.Append("<serviceType>")
.Append(SecurityElement.Escape(service.ServiceType ?? string.Empty))
.Append(SecurityElement.Escape(service.ServiceType))
.Append("</serviceType>");
builder.Append("<serviceId>")
.Append(SecurityElement.Escape(service.ServiceId ?? string.Empty))
.Append(SecurityElement.Escape(service.ServiceId))
.Append("</serviceId>");
builder.Append("<SCPDURL>")
.Append(BuildUrl(service.ScpdUrl))

View File

@@ -6,8 +6,8 @@ using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using Diacritics.Extensions;
using Emby.Dlna.Didl;
using Jellyfin.Extensions;
using MediaBrowser.Controller.Configuration;
using Microsoft.Extensions.Logging;
@@ -47,7 +47,7 @@ namespace Emby.Dlna.Service
private async Task<ControlResponse> ProcessControlRequestInternalAsync(ControlRequest request)
{
ControlRequestInfo? requestInfo = null;
ControlRequestInfo requestInfo;
using (var streamReader = new StreamReader(request.InputXml, Encoding.UTF8))
{
@@ -66,6 +66,11 @@ namespace Emby.Dlna.Service
Logger.LogDebug("Received control request {LocalName}, params: {@Headers}", requestInfo.LocalName, requestInfo.Headers);
return CreateControlResponse(requestInfo);
}
private ControlResponse CreateControlResponse(ControlRequestInfo requestInfo)
{
var settings = new XmlWriterSettings
{
Encoding = Encoding.UTF8,
@@ -112,29 +117,19 @@ namespace Emby.Dlna.Service
{
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.LocalName)
if (string.Equals(reader.LocalName, "Body", StringComparison.Ordinal))
{
case "Body":
{
if (!reader.IsEmptyElement)
{
using var subReader = reader.ReadSubtree();
return await ParseBodyTagAsync(subReader).ConfigureAwait(false);
}
else
{
await reader.ReadAsync().ConfigureAwait(false);
}
if (reader.IsEmptyElement)
{
await reader.ReadAsync().ConfigureAwait(false);
continue;
}
break;
}
default:
{
await reader.SkipAsync().ConfigureAwait(false);
break;
}
using var subReader = reader.ReadSubtree();
return await ParseBodyTagAsync(subReader).ConfigureAwait(false);
}
await reader.SkipAsync().ConfigureAwait(false);
}
else
{
@@ -160,17 +155,17 @@ namespace Emby.Dlna.Service
localName = reader.LocalName;
namespaceURI = reader.NamespaceURI;
if (!reader.IsEmptyElement)
if (reader.IsEmptyElement)
{
await reader.ReadAsync().ConfigureAwait(false);
}
else
{
var result = new ControlRequestInfo(localName, namespaceURI);
using var subReader = reader.ReadSubtree();
await ParseFirstBodyChildAsync(subReader, result.Headers).ConfigureAwait(false);
return result;
}
else
{
await reader.ReadAsync().ConfigureAwait(false);
}
}
else
{

View File

@@ -38,7 +38,7 @@ namespace Emby.Dlna.Service
builder.Append("<action>");
builder.Append("<name>")
.Append(SecurityElement.Escape(item.Name ?? string.Empty))
.Append(SecurityElement.Escape(item.Name))
.Append("</name>");
builder.Append("<argumentList>");
@@ -48,13 +48,13 @@ namespace Emby.Dlna.Service
builder.Append("<argument>");
builder.Append("<name>")
.Append(SecurityElement.Escape(argument.Name ?? string.Empty))
.Append(SecurityElement.Escape(argument.Name))
.Append("</name>");
builder.Append("<direction>")
.Append(SecurityElement.Escape(argument.Direction ?? string.Empty))
.Append(SecurityElement.Escape(argument.Direction))
.Append("</direction>");
builder.Append("<relatedStateVariable>")
.Append(SecurityElement.Escape(argument.RelatedStateVariable ?? string.Empty))
.Append(SecurityElement.Escape(argument.RelatedStateVariable))
.Append("</relatedStateVariable>");
builder.Append("</argument>");
@@ -81,10 +81,10 @@ namespace Emby.Dlna.Service
.Append("\">");
builder.Append("<name>")
.Append(SecurityElement.Escape(item.Name ?? string.Empty))
.Append(SecurityElement.Escape(item.Name))
.Append("</name>");
builder.Append("<dataType>")
.Append(SecurityElement.Escape(item.DataType ?? string.Empty))
.Append(SecurityElement.Escape(item.DataType))
.Append("</dataType>");
if (item.AllowedValues.Count > 0)

View File

@@ -11,6 +11,10 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
<ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />
@@ -23,8 +27,12 @@
<!-- Code analysers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.406" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Mime;
using System.Text;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
@@ -101,8 +102,7 @@ namespace Emby.Drawing
public async Task ProcessImage(ImageProcessingOptions options, Stream toStream)
{
var file = await ProcessImage(options).ConfigureAwait(false);
using (var fileStream = AsyncFile.OpenRead(file.Item1))
using (var fileStream = AsyncFile.OpenRead(file.Path))
{
await fileStream.CopyToAsync(toStream).ConfigureAwait(false);
}
@@ -117,7 +117,7 @@ namespace Emby.Drawing
=> _transparentImageTypes.Contains(Path.GetExtension(path));
/// <inheritdoc />
public async Task<(string path, string? mimeType, DateTime dateModified)> ProcessImage(ImageProcessingOptions options)
public async Task<(string Path, string? MimeType, DateTime DateModified)> ProcessImage(ImageProcessingOptions options)
{
ItemImageInfo originalImage = options.Image;
BaseItem item = options.Item;
@@ -130,20 +130,22 @@ namespace Emby.Drawing
originalImageSize = new ImageDimensions(originalImage.Width, originalImage.Height);
}
var mimeType = MimeTypes.GetMimeType(originalImagePath);
if (!_imageEncoder.SupportsImageEncoding)
{
return (originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
return (originalImagePath, mimeType, dateModified);
}
var supportedImageInfo = await GetSupportedImage(originalImagePath, dateModified).ConfigureAwait(false);
originalImagePath = supportedImageInfo.path;
originalImagePath = supportedImageInfo.Path;
if (!File.Exists(originalImagePath))
// Original file doesn't exist, or original file is gif.
if (!File.Exists(originalImagePath) || string.Equals(mimeType, MediaTypeNames.Image.Gif, StringComparison.OrdinalIgnoreCase))
{
return (originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
return (originalImagePath, mimeType, dateModified);
}
dateModified = supportedImageInfo.dateModified;
dateModified = supportedImageInfo.DateModified;
bool requiresTransparency = _transparentImageTypes.Contains(Path.GetExtension(originalImagePath));
bool autoOrient = false;
@@ -243,7 +245,7 @@ namespace Emby.Drawing
return ImageFormat.Jpg;
}
private string? GetMimeType(ImageFormat format, string path)
private string GetMimeType(ImageFormat format, string path)
=> format switch
{
ImageFormat.Bmp => MimeTypes.GetMimeType("i.bmp"),
@@ -393,7 +395,13 @@ namespace Emby.Drawing
public string GetImageBlurHash(string path)
{
var size = GetImageDimensions(path);
if (size.Width <= 0 || size.Height <= 0)
return GetImageBlurHash(path, size);
}
/// <inheritdoc />
public string GetImageBlurHash(string path, ImageDimensions imageDimensions)
{
if (imageDimensions.Width <= 0 || imageDimensions.Height <= 0)
{
return string.Empty;
}
@@ -401,8 +409,8 @@ namespace Emby.Drawing
// We want tiles to be as close to square as possible, and to *mostly* keep under 16 tiles for performance.
// One tile is (width / xComp) x (height / yComp) pixels, which means that ideally yComp = xComp * height / width.
// See more at https://github.com/woltapp/blurhash/#how-do-i-pick-the-number-of-x-and-y-components
float xCompF = MathF.Sqrt(16.0f * size.Width / size.Height);
float yCompF = xCompF * size.Height / size.Width;
float xCompF = MathF.Sqrt(16.0f * imageDimensions.Width / imageDimensions.Height);
float yCompF = xCompF * imageDimensions.Height / imageDimensions.Width;
int xComp = Math.Min((int)xCompF + 1, 9);
int yComp = Math.Min((int)yCompF + 1, 9);
@@ -437,47 +445,46 @@ namespace Emby.Drawing
.ToString("N", CultureInfo.InvariantCulture);
}
private async Task<(string path, DateTime dateModified)> GetSupportedImage(string originalImagePath, DateTime dateModified)
private Task<(string Path, DateTime DateModified)> GetSupportedImage(string originalImagePath, DateTime dateModified)
{
var inputFormat = Path.GetExtension(originalImagePath)
.TrimStart('.')
.Replace("jpeg", "jpg", StringComparison.OrdinalIgnoreCase);
var inputFormat = Path.GetExtension(originalImagePath.AsSpan()).TrimStart('.').ToString();
// These are just jpg files renamed as tbn
if (string.Equals(inputFormat, "tbn", StringComparison.OrdinalIgnoreCase))
{
return (originalImagePath, dateModified);
return Task.FromResult((originalImagePath, dateModified));
}
if (!_imageEncoder.SupportedInputFormats.Contains(inputFormat))
{
try
{
string filename = (originalImagePath + dateModified.Ticks.ToString(CultureInfo.InvariantCulture)).GetMD5().ToString("N", CultureInfo.InvariantCulture);
// TODO _mediaEncoder.ConvertImage is not implemented
// if (!_imageEncoder.SupportedInputFormats.Contains(inputFormat))
// {
// try
// {
// string filename = (originalImagePath + dateModified.Ticks.ToString(CultureInfo.InvariantCulture)).GetMD5().ToString("N", CultureInfo.InvariantCulture);
//
// string cacheExtension = _mediaEncoder.SupportsEncoder("libwebp") ? ".webp" : ".png";
// var outputPath = Path.Combine(_appPaths.ImageCachePath, "converted-images", filename + cacheExtension);
//
// var file = _fileSystem.GetFileInfo(outputPath);
// if (!file.Exists)
// {
// await _mediaEncoder.ConvertImage(originalImagePath, outputPath).ConfigureAwait(false);
// dateModified = _fileSystem.GetLastWriteTimeUtc(outputPath);
// }
// else
// {
// dateModified = file.LastWriteTimeUtc;
// }
//
// originalImagePath = outputPath;
// }
// catch (Exception ex)
// {
// _logger.LogError(ex, "Image conversion failed for {Path}", originalImagePath);
// }
// }
string cacheExtension = _mediaEncoder.SupportsEncoder("libwebp") ? ".webp" : ".png";
var outputPath = Path.Combine(_appPaths.ImageCachePath, "converted-images", filename + cacheExtension);
var file = _fileSystem.GetFileInfo(outputPath);
if (!file.Exists)
{
await _mediaEncoder.ConvertImage(originalImagePath, outputPath).ConfigureAwait(false);
dateModified = _fileSystem.GetLastWriteTimeUtc(outputPath);
}
else
{
dateModified = file.LastWriteTimeUtc;
}
originalImagePath = outputPath;
}
catch (Exception ex)
{
_logger.LogError(ex, "Image conversion failed for {Path}", originalImagePath);
}
}
return (originalImagePath, dateModified);
return Task.FromResult((originalImagePath, dateModified));
}
/// <summary>

View File

@@ -43,6 +43,12 @@ namespace Emby.Drawing
throw new NotImplementedException();
}
/// <inheritdoc />
public void CreateSplashscreen(IReadOnlyList<string> posters, IReadOnlyList<string> backdrops)
{
throw new NotImplementedException();
}
/// <inheritdoc />
public string GetImageBlurHash(int xComp, int yComp, string path)
{

View File

@@ -14,6 +14,7 @@ namespace Emby.Naming.AudioBook
public class AudioBookListResolver
{
private readonly NamingOptions _options;
private readonly AudioBookResolver _audioBookResolver;
/// <summary>
/// Initializes a new instance of the <see cref="AudioBookListResolver"/> class.
@@ -22,6 +23,7 @@ namespace Emby.Naming.AudioBook
public AudioBookListResolver(NamingOptions options)
{
_options = options;
_audioBookResolver = new AudioBookResolver(_options);
}
/// <summary>
@@ -31,21 +33,18 @@ namespace Emby.Naming.AudioBook
/// <returns>Returns IEnumerable of <see cref="AudioBookInfo"/>.</returns>
public IEnumerable<AudioBookInfo> Resolve(IEnumerable<FileSystemMetadata> files)
{
var audioBookResolver = new AudioBookResolver(_options);
// File with empty fullname will be sorted out here.
var audiobookFileInfos = files
.Select(i => audioBookResolver.Resolve(i.FullName))
.Select(i => _audioBookResolver.Resolve(i.FullName))
.OfType<AudioBookFileInfo>()
.ToList();
var stackResult = new StackResolver(_options)
.ResolveAudioBooks(audiobookFileInfos);
var stackResult = StackResolver.ResolveAudioBooks(audiobookFileInfos);
foreach (var stack in stackResult)
{
var stackFiles = stack.Files
.Select(i => audioBookResolver.Resolve(i))
.Select(i => _audioBookResolver.Resolve(i))
.OfType<AudioBookFileInfo>()
.ToList();

View File

@@ -1,7 +1,7 @@
using System;
using System.IO;
using System.Linq;
using Emby.Naming.Common;
using Jellyfin.Extensions;
namespace Emby.Naming.AudioBook
{
@@ -37,7 +37,7 @@ namespace Emby.Naming.AudioBook
var extension = Path.GetExtension(path);
// Check supported extensions
if (!_options.AudioFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
if (!_options.AudioFileExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase))
{
return null;
}

View File

@@ -1,6 +1,7 @@
#pragma warning disable CA1819
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Emby.Naming.Video;
@@ -22,47 +23,60 @@ namespace Emby.Naming.Common
{
VideoFileExtensions = new[]
{
".m4v",
".001",
".3g2",
".3gp",
".nsv",
".ts",
".ty",
".strm",
".rm",
".rmvb",
".ifo",
".mov",
".qt",
".divx",
".xvid",
".bivx",
".vob",
".nrg",
".img",
".iso",
".pva",
".wmv",
".amv",
".asf",
".asx",
".ogm",
".m2v",
".avi",
".bin",
".dvr-ms",
".mpg",
".mpeg",
".mp4",
".mkv",
".avc",
".vp3",
".svq3",
".nuv",
".viv",
".bivx",
".divx",
".dv",
".dvr-ms",
".f4v",
".fli",
".flv",
".001",
".tp"
".ifo",
".img",
".iso",
".m2t",
".m2ts",
".m2v",
".m4v",
".mkv",
".mk3d",
".mov",
".mp4",
".mpe",
".mpeg",
".mpg",
".mts",
".mxf",
".nrg",
".nsv",
".nuv",
".ogg",
".ogm",
".ogv",
".pva",
".qt",
".rec",
".rm",
".rmvb",
".strm",
".svq3",
".tp",
".ts",
".ty",
".viv",
".vob",
".vp3",
".webm",
".wmv",
".wtv",
".xvid"
};
VideoFlagDelimiters = new[]
@@ -124,11 +138,11 @@ namespace Emby.Naming.Common
token: "DSR")
};
VideoFileStackingExpressions = new[]
VideoFileStackingRules = new[]
{
"(?<title>.*?)(?<volume>[ _.-]*(?:cd|dvd|p(?:ar)?t|dis[ck])[ _.-]*[0-9]+)(?<ignore>.*?)(?<extension>\\.[^.]+)$",
"(?<title>.*?)(?<volume>[ _.-]*(?:cd|dvd|p(?:ar)?t|dis[ck])[ _.-]*[a-d])(?<ignore>.*?)(?<extension>\\.[^.]+)$",
"(?<title>.*?)(?<volume>[ ._-]*[a-d])(?<ignore>.*?)(?<extension>\\.[^.]+)$"
new FileStackRule(@"^(?<filename>.*?)(?:(?<=[\]\)\}])|[ _.-]+)[\(\[]?(?<parttype>cd|dvd|part|pt|dis[ck])[ _.-]*(?<number>[0-9]+)[\)\]]?(?:\.[^.]+)?$", true),
new FileStackRule(@"^(?<filename>.*?)(?:(?<=[\]\)\}])|[ _.-]+)[\(\[]?(?<parttype>cd|dvd|part|pt|dis[ck])[ _.-]*(?<number>[a-d])[\)\]]?(?:\.[^.]+)?$", false),
new FileStackRule(@"^(?<filename>.*?)(?:(?<=[\]\)\}])|[ _.-]?)(?<number>[a-d])(?:\.[^.]+)?$", false)
};
CleanDateTimes = new[]
@@ -148,32 +162,20 @@ namespace Emby.Naming.Common
SubtitleFileExtensions = new[]
{
".ass",
".mks",
".sami",
".smi",
".srt",
".ssa",
".ass",
".sub"
};
SubtitleFlagDelimiters = new[]
{
'.'
};
SubtitleForcedFlags = new[]
{
"foreign",
"forced"
};
SubtitleDefaultFlags = new[]
{
"default"
".sub",
".vtt",
};
AlbumStackingPrefixes = new[]
{
"disc",
"cd",
"disc",
"disk",
"vol",
"volume"
@@ -181,68 +183,101 @@ namespace Emby.Naming.Common
AudioFileExtensions = new[]
{
".nsv",
".m4a",
".flac",
".aac",
".strm",
".pls",
".rm",
".mpa",
".wav",
".wma",
".ogg",
".opus",
".mp3",
".mp2",
".mod",
".amf",
".669",
".3gp",
".aa",
".aac",
".aax",
".ac3",
".act",
".adp",
".adplug",
".adx",
".afc",
".amf",
".aif",
".aiff",
".alac",
".amr",
".ape",
".ast",
".au",
".awb",
".cda",
".cue",
".dmf",
".dsf",
".dsm",
".dsp",
".dts",
".dvf",
".far",
".flac",
".gdm",
".gsm",
".gym",
".hps",
".imf",
".it",
".m15",
".m4a",
".m4b",
".mac",
".med",
".mka",
".mmf",
".mod",
".mogg",
".mp2",
".mp3",
".mpa",
".mpc",
".mpp",
".mp+",
".msv",
".nmf",
".nsf",
".nsv",
".oga",
".ogg",
".okt",
".opus",
".pls",
".ra",
".rf64",
".rm",
".s3m",
".stm",
".sfx",
".shn",
".sid",
".spc",
".stm",
".strm",
".ult",
".uni",
".xm",
".sid",
".ac3",
".dts",
".cue",
".aif",
".aiff",
".ape",
".mac",
".mpc",
".mp+",
".mpp",
".shn",
".vox",
".wav",
".wma",
".wv",
".nsf",
".spc",
".gym",
".adplug",
".adx",
".dsp",
".adp",
".ymf",
".ast",
".afc",
".hps",
".xm",
".xsp",
".acc",
".m4b",
".oga",
".dsf",
".mka"
".ymf"
};
MediaFlagDelimiters = new[]
{
'.'
};
MediaForcedFlags = new[]
{
"foreign",
"forced"
};
MediaDefaultFlags = new[]
{
"default"
};
EpisodeExpressions = new[]
@@ -279,7 +314,7 @@ namespace Emby.Naming.Common
// This isn't a Kodi naming rule, but the expression below causes false positives,
// so we make sure this one gets tested first.
// "Foo Bar 889"
new EpisodeExpression(@".*[\\\/](?![Ee]pisode)(?<seriesname>[\w\s]+?)\s(?<epnumber>[0-9]{1,3})(-(?<endingepnumber>[0-9]{2,3}))*[^\\\/x]*$")
new EpisodeExpression(@".*[\\\/](?![Ee]pisode)(?<seriesname>[\w\s]+?)\s(?<epnumber>[0-9]{1,4})(-(?<endingepnumber>[0-9]{2,4}))*[^\\\/x]*$")
{
IsNamed = true
},
@@ -403,6 +438,72 @@ namespace Emby.Naming.Common
VideoExtraRules = new[]
{
new ExtraRule(
ExtraType.Trailer,
ExtraRuleType.DirectoryName,
"trailers",
MediaType.Video),
new ExtraRule(
ExtraType.ThemeVideo,
ExtraRuleType.DirectoryName,
"backdrops",
MediaType.Video),
new ExtraRule(
ExtraType.ThemeSong,
ExtraRuleType.DirectoryName,
"theme-music",
MediaType.Audio),
new ExtraRule(
ExtraType.BehindTheScenes,
ExtraRuleType.DirectoryName,
"behind the scenes",
MediaType.Video),
new ExtraRule(
ExtraType.DeletedScene,
ExtraRuleType.DirectoryName,
"deleted scenes",
MediaType.Video),
new ExtraRule(
ExtraType.Interview,
ExtraRuleType.DirectoryName,
"interviews",
MediaType.Video),
new ExtraRule(
ExtraType.Scene,
ExtraRuleType.DirectoryName,
"scenes",
MediaType.Video),
new ExtraRule(
ExtraType.Sample,
ExtraRuleType.DirectoryName,
"samples",
MediaType.Video),
new ExtraRule(
ExtraType.Clip,
ExtraRuleType.DirectoryName,
"shorts",
MediaType.Video),
new ExtraRule(
ExtraType.Clip,
ExtraRuleType.DirectoryName,
"featurettes",
MediaType.Video),
new ExtraRule(
ExtraType.Unknown,
ExtraRuleType.DirectoryName,
"extras",
MediaType.Video),
new ExtraRule(
ExtraType.Trailer,
ExtraRuleType.Filename,
@@ -517,55 +618,17 @@ namespace Emby.Naming.Common
"-short",
MediaType.Video),
new ExtraRule(
ExtraType.BehindTheScenes,
ExtraRuleType.DirectoryName,
"behind the scenes",
MediaType.Video),
new ExtraRule(
ExtraType.DeletedScene,
ExtraRuleType.DirectoryName,
"deleted scenes",
MediaType.Video),
new ExtraRule(
ExtraType.Interview,
ExtraRuleType.DirectoryName,
"interviews",
MediaType.Video),
new ExtraRule(
ExtraType.Scene,
ExtraRuleType.DirectoryName,
"scenes",
MediaType.Video),
new ExtraRule(
ExtraType.Sample,
ExtraRuleType.DirectoryName,
"samples",
MediaType.Video),
new ExtraRule(
ExtraType.Clip,
ExtraRuleType.DirectoryName,
"shorts",
MediaType.Video),
new ExtraRule(
ExtraType.Clip,
ExtraRuleType.DirectoryName,
"featurettes",
MediaType.Video),
new ExtraRule(
ExtraType.Unknown,
ExtraRuleType.DirectoryName,
"extras",
MediaType.Video),
ExtraRuleType.Suffix,
"-extra",
MediaType.Video)
};
AllExtrasTypesFolderNames = VideoExtraRules
.Where(i => i.RuleType == ExtraRuleType.DirectoryName)
.ToDictionary(i => i.Token, i => i.ExtraType, StringComparer.OrdinalIgnoreCase);
Format3DRules = new[]
{
// Kodi rules:
@@ -619,41 +682,6 @@ namespace Emby.Naming.Common
@"^\s*(?<name>[^ ].*?)\s*$"
};
var extensions = VideoFileExtensions.ToList();
extensions.AddRange(new[]
{
".mkv",
".m2t",
".m2ts",
".img",
".iso",
".mk3d",
".ts",
".rmvb",
".mov",
".avi",
".mpg",
".mpeg",
".wmv",
".mp4",
".divx",
".dvr-ms",
".wtv",
".ogm",
".ogv",
".asf",
".m4v",
".flv",
".f4v",
".3gp",
".webm",
".mts",
".m2v",
".rec",
".mxf"
});
MultipleEpisodeExpressions = new[]
{
@".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )[0-9]{1,4}[eExX](?<endingepnumber>[0-9]{1,3}))+[^\\\/]*$",
@@ -671,18 +699,34 @@ namespace Emby.Naming.Common
IsNamed = true
}).ToArray();
VideoFileExtensions = extensions
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToArray();
Compile();
}
/// <summary>
/// Gets or sets the folder name to extra types mapping.
/// </summary>
public Dictionary<string, ExtraType> AllExtrasTypesFolderNames { get; set; }
/// <summary>
/// Gets or sets list of audio file extensions.
/// </summary>
public string[] AudioFileExtensions { get; set; }
/// <summary>
/// Gets or sets list of external media flag delimiters.
/// </summary>
public char[] MediaFlagDelimiters { get; set; }
/// <summary>
/// Gets or sets list of external media forced flags.
/// </summary>
public string[] MediaForcedFlags { get; set; }
/// <summary>
/// Gets or sets list of external media default flags.
/// </summary>
public string[] MediaDefaultFlags { get; set; }
/// <summary>
/// Gets or sets list of album stacking prefixes.
/// </summary>
@@ -693,21 +737,6 @@ namespace Emby.Naming.Common
/// </summary>
public string[] SubtitleFileExtensions { get; set; }
/// <summary>
/// Gets or sets list of subtitles flag delimiters.
/// </summary>
public char[] SubtitleFlagDelimiters { get; set; }
/// <summary>
/// Gets or sets list of subtitle forced flags.
/// </summary>
public string[] SubtitleForcedFlags { get; set; }
/// <summary>
/// Gets or sets list of subtitle default flags.
/// </summary>
public string[] SubtitleDefaultFlags { get; set; }
/// <summary>
/// Gets or sets list of episode regular expressions.
/// </summary>
@@ -759,9 +788,9 @@ namespace Emby.Naming.Common
public Format3DRule[] Format3DRules { get; set; }
/// <summary>
/// Gets or sets list of raw video file-stacking expressions strings.
/// Gets the file stacking rules.
/// </summary>
public string[] VideoFileStackingExpressions { get; set; }
public FileStackRule[] VideoFileStackingRules { get; }
/// <summary>
/// Gets or sets list of raw clean DateTimes regular expressions strings.
@@ -783,11 +812,6 @@ namespace Emby.Naming.Common
/// </summary>
public ExtraRule[] VideoExtraRules { get; set; }
/// <summary>
/// Gets list of video file-stack regular expressions.
/// </summary>
public Regex[] VideoFileStackingRegexes { get; private set; } = Array.Empty<Regex>();
/// <summary>
/// Gets list of clean datetime regular expressions.
/// </summary>
@@ -813,7 +837,6 @@ namespace Emby.Naming.Common
/// </summary>
public void Compile()
{
VideoFileStackingRegexes = VideoFileStackingExpressions.Select(Compile).ToArray();
CleanDateTimeRegexes = CleanDateTimes.Select(Compile).ToArray();
CleanStringRegexes = CleanStrings.Select(Compile).ToArray();
EpisodeWithoutSeasonRegexes = EpisodeWithoutSeasonExpressions.Select(Compile).ToArray();

View File

@@ -15,6 +15,10 @@
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Stability)'=='Unstable'">
<!-- Include all symbols in the main nupkg until Azure Artifact Feed starts supporting ingesting NuGet symbol packages. -->
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
@@ -32,19 +36,23 @@
<PropertyGroup>
<Authors>Jellyfin Contributors</Authors>
<PackageId>Jellyfin.Naming</PackageId>
<VersionPrefix>10.8.0</VersionPrefix>
<VersionPrefix>10.8.4</VersionPrefix>
<RepositoryUrl>https://github.com/jellyfin/jellyfin</RepositoryUrl>
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
</ItemGroup>
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.406" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>

View File

@@ -0,0 +1,116 @@
using System;
using System.IO;
using System.Linq;
using Emby.Naming.Common;
using Jellyfin.Extensions;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Globalization;
namespace Emby.Naming.ExternalFiles
{
/// <summary>
/// External media file parser class.
/// </summary>
public class ExternalPathParser
{
private readonly NamingOptions _namingOptions;
private readonly DlnaProfileType _type;
private readonly ILocalizationManager _localizationManager;
/// <summary>
/// Initializes a new instance of the <see cref="ExternalPathParser"/> class.
/// </summary>
/// <param name="localizationManager">The localization manager.</param>
/// <param name="namingOptions">The <see cref="NamingOptions"/> object containing FileExtensions, MediaDefaultFlags, MediaForcedFlags and MediaFlagDelimiters.</param>
/// <param name="type">The <see cref="DlnaProfileType"/> of the parsed file.</param>
public ExternalPathParser(NamingOptions namingOptions, ILocalizationManager localizationManager, DlnaProfileType type)
{
_localizationManager = localizationManager;
_namingOptions = namingOptions;
_type = type;
}
/// <summary>
/// Parse filename and extract information.
/// </summary>
/// <param name="path">Path to file.</param>
/// <param name="extraString">Part of the filename only containing the extra information.</param>
/// <returns>Returns null or an <see cref="ExternalPathParserResult"/> object if parsing is successful.</returns>
public ExternalPathParserResult? ParseFile(string path, string? extraString)
{
if (path.Length == 0)
{
return null;
}
var extension = Path.GetExtension(path);
if (!(_type == DlnaProfileType.Subtitle && _namingOptions.SubtitleFileExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase))
&& !(_type == DlnaProfileType.Audio && _namingOptions.AudioFileExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase)))
{
return null;
}
var pathInfo = new ExternalPathParserResult(path);
if (string.IsNullOrEmpty(extraString))
{
return pathInfo;
}
foreach (var separator in _namingOptions.MediaFlagDelimiters)
{
var languageString = extraString;
var titleString = string.Empty;
const int SeparatorLength = 1;
while (languageString.Length > 0)
{
int lastSeparator = languageString.LastIndexOf(separator);
if (lastSeparator == -1)
{
break;
}
string currentSlice = languageString[lastSeparator..];
string currentSliceWithoutSeparator = currentSlice[SeparatorLength..];
if (_namingOptions.MediaDefaultFlags.Any(s => currentSliceWithoutSeparator.Contains(s, StringComparison.OrdinalIgnoreCase)))
{
pathInfo.IsDefault = true;
extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase);
languageString = languageString[..lastSeparator];
continue;
}
if (_namingOptions.MediaForcedFlags.Any(s => currentSliceWithoutSeparator.Contains(s, StringComparison.OrdinalIgnoreCase)))
{
pathInfo.IsForced = true;
extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase);
languageString = languageString[..lastSeparator];
continue;
}
// Try to translate to three character code
var culture = _localizationManager.FindLanguageInfo(currentSliceWithoutSeparator);
if (culture != null && pathInfo.Language == null)
{
pathInfo.Language = culture.ThreeLetterISOLanguageName;
extraString = extraString.Replace(currentSlice, string.Empty, StringComparison.OrdinalIgnoreCase);
}
else
{
titleString = currentSlice + titleString;
}
languageString = languageString[..lastSeparator];
}
pathInfo.Title = titleString.Length >= SeparatorLength ? titleString[SeparatorLength..] : null;
}
return pathInfo;
}
}
}

View File

@@ -1,17 +1,17 @@
namespace Emby.Naming.Subtitles
namespace Emby.Naming.ExternalFiles
{
/// <summary>
/// Class holding information about subtitle.
/// Class holding information about external files.
/// </summary>
public class SubtitleInfo
public class ExternalPathParserResult
{
/// <summary>
/// Initializes a new instance of the <see cref="SubtitleInfo"/> class.
/// Initializes a new instance of the <see cref="ExternalPathParserResult"/> class.
/// </summary>
/// <param name="path">Path to file.</param>
/// <param name="isDefault">Is subtitle default.</param>
/// <param name="isForced">Is subtitle forced.</param>
public SubtitleInfo(string path, bool isDefault, bool isForced)
/// <param name="isDefault">Is default.</param>
/// <param name="isForced">Is forced.</param>
public ExternalPathParserResult(string path, bool isDefault = false, bool isForced = false)
{
Path = path;
IsDefault = isDefault;
@@ -30,6 +30,12 @@ namespace Emby.Naming.Subtitles
/// <value>The language.</value>
public string? Language { get; set; }
/// <summary>
/// Gets or sets the title.
/// </summary>
/// <value>The title.</value>
public string? Title { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is default.
/// </summary>

View File

@@ -1,70 +0,0 @@
using System;
using System.IO;
using System.Linq;
using Emby.Naming.Common;
namespace Emby.Naming.Subtitles
{
/// <summary>
/// Subtitle Parser class.
/// </summary>
public class SubtitleParser
{
private readonly NamingOptions _options;
/// <summary>
/// Initializes a new instance of the <see cref="SubtitleParser"/> class.
/// </summary>
/// <param name="options"><see cref="NamingOptions"/> object containing SubtitleFileExtensions, SubtitleDefaultFlags, SubtitleForcedFlags and SubtitleFlagDelimiters.</param>
public SubtitleParser(NamingOptions options)
{
_options = options;
}
/// <summary>
/// Parse file to determine if is subtitle and <see cref="SubtitleInfo"/>.
/// </summary>
/// <param name="path">Path to file.</param>
/// <returns>Returns null or <see cref="SubtitleInfo"/> object if parsing is successful.</returns>
public SubtitleInfo? ParseFile(string path)
{
if (path.Length == 0)
{
return null;
}
var extension = Path.GetExtension(path);
if (!_options.SubtitleFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
{
return null;
}
var flags = GetFlags(path);
var info = new SubtitleInfo(
path,
_options.SubtitleDefaultFlags.Any(i => flags.Contains(i, StringComparer.OrdinalIgnoreCase)),
_options.SubtitleForcedFlags.Any(i => flags.Contains(i, StringComparer.OrdinalIgnoreCase)));
var parts = flags.Where(i => !_options.SubtitleDefaultFlags.Contains(i, StringComparer.OrdinalIgnoreCase)
&& !_options.SubtitleForcedFlags.Contains(i, StringComparer.OrdinalIgnoreCase))
.ToList();
// Should have a name, language and file extension
if (parts.Count >= 3)
{
info.Language = parts[^2];
}
return info;
}
private string[] GetFlags(string path)
{
// Note: the tags need be surrounded be either a space ( ), hyphen -, dot . or underscore _.
var file = Path.GetFileName(path);
return file.Split(_options.SubtitleFlagDelimiters, StringSplitOptions.RemoveEmptyEntries);
}
}
}

View File

@@ -1,8 +1,8 @@
using System;
using System.IO;
using System.Linq;
using Emby.Naming.Common;
using Emby.Naming.Video;
using Jellyfin.Extensions;
namespace Emby.Naming.TV
{
@@ -48,7 +48,7 @@ namespace Emby.Naming.TV
{
var extension = Path.GetExtension(path);
// Check supported extensions
if (!_options.VideoFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
if (!_options.VideoFileExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase))
{
// It's not supported. Check stub extensions
if (!StubResolver.TryResolveFile(path, _options, out stubType))

View File

@@ -55,7 +55,7 @@ namespace Emby.Naming.TV
/// <param name="supportSpecialAliases">if set to <c>true</c> [support special aliases].</param>
/// <param name="supportNumericSeasonFolders">if set to <c>true</c> [support numeric season folders].</param>
/// <returns>System.Nullable{System.Int32}.</returns>
private static (int? seasonNumber, bool isSeasonFolder) GetSeasonNumberFromPath(
private static (int? SeasonNumber, bool IsSeasonFolder) GetSeasonNumberFromPath(
string path,
bool supportSpecialAliases,
bool supportNumericSeasonFolders)
@@ -99,7 +99,7 @@ namespace Emby.Naming.TV
if (filename.Contains(name, StringComparison.OrdinalIgnoreCase))
{
var result = GetSeasonNumberFromPathSubstring(filename.Replace(name, " ", StringComparison.OrdinalIgnoreCase));
if (result.seasonNumber.HasValue)
if (result.SeasonNumber.HasValue)
{
return result;
}
@@ -142,7 +142,7 @@ namespace Emby.Naming.TV
/// </summary>
/// <param name="path">The path.</param>
/// <returns>System.Nullable{System.Int32}.</returns>
private static (int? seasonNumber, bool isSeasonFolder) GetSeasonNumberFromPathSubstring(ReadOnlySpan<char> path)
private static (int? SeasonNumber, bool IsSeasonFolder) GetSeasonNumberFromPathSubstring(ReadOnlySpan<char> path)
{
var numericStart = -1;
var length = 0;

View File

@@ -1,4 +1,3 @@
using System.Globalization;
using Emby.Naming.Common;
namespace Emby.Naming.TV
@@ -51,7 +50,7 @@ namespace Emby.Naming.TV
if (expression.IsNamed)
{
result.SeriesName = match.Groups["seriesname"].Value;
result.Success = !string.IsNullOrEmpty(result.SeriesName) && !string.IsNullOrEmpty(match.Groups["seasonnumber"]?.Value);
result.Success = !string.IsNullOrEmpty(result.SeriesName) && !match.Groups["seasonnumber"].ValueSpan.IsEmpty;
}
}

View File

@@ -1,4 +1,3 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text.RegularExpressions;

View File

@@ -9,45 +9,27 @@ namespace Emby.Naming.Video
/// <summary>
/// Resolve if file is extra for video.
/// </summary>
public class ExtraResolver
public static class ExtraRuleResolver
{
private static readonly char[] _digits = new[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
private readonly NamingOptions _options;
/// <summary>
/// Initializes a new instance of the <see cref="ExtraResolver"/> class.
/// </summary>
/// <param name="options"><see cref="NamingOptions"/> object containing VideoExtraRules and passed to <see cref="AudioFileParser"/> and <see cref="VideoResolver"/>.</param>
public ExtraResolver(NamingOptions options)
{
_options = options;
}
private static readonly char[] _digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
/// <summary>
/// Attempts to resolve if file is extra.
/// </summary>
/// <param name="path">Path to file.</param>
/// <param name="namingOptions">The naming options.</param>
/// <returns>Returns <see cref="ExtraResult"/> object.</returns>
public ExtraResult GetExtraInfo(string path)
public static ExtraResult GetExtraInfo(string path, NamingOptions namingOptions)
{
var result = new ExtraResult();
for (var i = 0; i < _options.VideoExtraRules.Length; i++)
for (var i = 0; i < namingOptions.VideoExtraRules.Length; i++)
{
var rule = _options.VideoExtraRules[i];
if (rule.MediaType == MediaType.Audio)
var rule = namingOptions.VideoExtraRules[i];
if ((rule.MediaType == MediaType.Audio && !AudioFileParser.IsAudioFile(path, namingOptions))
|| (rule.MediaType == MediaType.Video && !VideoResolver.IsVideoFile(path, namingOptions)))
{
if (!AudioFileParser.IsAudioFile(path, _options))
{
continue;
}
}
else if (rule.MediaType == MediaType.Video)
{
if (!VideoResolver.IsVideoFile(path, _options))
{
continue;
}
continue;
}
var pathSpan = path.AsSpan();
@@ -76,9 +58,9 @@ namespace Emby.Naming.Video
{
var filename = Path.GetFileName(path);
var regex = new Regex(rule.Token, RegexOptions.IgnoreCase);
var isMatch = Regex.IsMatch(filename, rule.Token, RegexOptions.IgnoreCase | RegexOptions.Compiled);
if (regex.IsMatch(filename))
if (isMatch)
{
result.ExtraType = rule.ExtraType;
result.Rule = rule;

View File

@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Jellyfin.Extensions;
namespace Emby.Naming.Video
{
@@ -12,25 +12,30 @@ namespace Emby.Naming.Video
/// <summary>
/// Initializes a new instance of the <see cref="FileStack"/> class.
/// </summary>
public FileStack()
/// <param name="name">The stack name.</param>
/// <param name="isDirectory">Whether the stack files are directories.</param>
/// <param name="files">The stack files.</param>
public FileStack(string name, bool isDirectory, IReadOnlyList<string> files)
{
Files = new List<string>();
Name = name;
IsDirectoryStack = isDirectory;
Files = files;
}
/// <summary>
/// Gets or sets name of file stack.
/// Gets the name of file stack.
/// </summary>
public string Name { get; set; } = string.Empty;
public string Name { get; }
/// <summary>
/// Gets or sets list of paths in stack.
/// Gets the list of paths in stack.
/// </summary>
public List<string> Files { get; set; }
public IReadOnlyList<string> Files { get; }
/// <summary>
/// Gets or sets a value indicating whether stack is directory stack.
/// Gets a value indicating whether stack is directory stack.
/// </summary>
public bool IsDirectoryStack { get; set; }
public bool IsDirectoryStack { get; }
/// <summary>
/// Helper function to determine if path is in the stack.
@@ -40,12 +45,12 @@ namespace Emby.Naming.Video
/// <returns>True if file is in the stack.</returns>
public bool ContainsFile(string file, bool isDirectory)
{
if (IsDirectoryStack == isDirectory)
if (string.IsNullOrEmpty(file))
{
return Files.Contains(file, StringComparer.OrdinalIgnoreCase);
return false;
}
return false;
return IsDirectoryStack == isDirectory && Files.Contains(file, StringComparison.OrdinalIgnoreCase);
}
}
}

View File

@@ -0,0 +1,48 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.RegularExpressions;
namespace Emby.Naming.Video;
/// <summary>
/// Regex based rule for file stacking (eg. disc1, disc2).
/// </summary>
public class FileStackRule
{
private readonly Regex _tokenRegex;
/// <summary>
/// Initializes a new instance of the <see cref="FileStackRule"/> class.
/// </summary>
/// <param name="token">Token.</param>
/// <param name="isNumerical">Whether the file stack rule uses numerical or alphabetical numbering.</param>
public FileStackRule(string token, bool isNumerical)
{
_tokenRegex = new Regex(token, RegexOptions.IgnoreCase);
IsNumerical = isNumerical;
}
/// <summary>
/// Gets a value indicating whether the rule uses numerical or alphabetical numbering.
/// </summary>
public bool IsNumerical { get; }
/// <summary>
/// Match the input against the rule regex.
/// </summary>
/// <param name="input">The input.</param>
/// <param name="result">The part type and number or <c>null</c>.</param>
/// <returns>A value indicating whether the input matched the rule.</returns>
public bool Match(string input, [NotNullWhen(true)] out (string StackName, string PartType, string PartNumber)? result)
{
result = null;
var match = _tokenRegex.Match(input);
if (!match.Success)
{
return false;
}
var partType = match.Groups["parttype"].Success ? match.Groups["parttype"].Value : "unknown";
result = (match.Groups["filename"].Value, partType, match.Groups["number"].Value);
return true;
}
}

View File

@@ -9,7 +9,7 @@ namespace Emby.Naming.Video
public static class Format3DParser
{
// Static default result to save on allocation costs.
private static readonly Format3DResult _defaultResult = new (false, null);
private static readonly Format3DResult _defaultResult = new(false, null);
/// <summary>
/// Parse 3D format related flags.

View File

@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Emby.Naming.AudioBook;
using Emby.Naming.Common;
using MediaBrowser.Model.IO;
@@ -12,37 +11,28 @@ namespace Emby.Naming.Video
/// <summary>
/// Resolve <see cref="FileStack"/> from list of paths.
/// </summary>
public class StackResolver
public static class StackResolver
{
private readonly NamingOptions _options;
/// <summary>
/// Initializes a new instance of the <see cref="StackResolver"/> class.
/// </summary>
/// <param name="options"><see cref="NamingOptions"/> object containing VideoFileStackingRegexes and passes options to <see cref="VideoResolver"/>.</param>
public StackResolver(NamingOptions options)
{
_options = options;
}
/// <summary>
/// Resolves only directories from paths.
/// </summary>
/// <param name="files">List of paths.</param>
/// <param name="namingOptions">The naming options.</param>
/// <returns>Enumerable <see cref="FileStack"/> of directories.</returns>
public IEnumerable<FileStack> ResolveDirectories(IEnumerable<string> files)
public static IEnumerable<FileStack> ResolveDirectories(IEnumerable<string> files, NamingOptions namingOptions)
{
return Resolve(files.Select(i => new FileSystemMetadata { FullName = i, IsDirectory = true }));
return Resolve(files.Select(i => new FileSystemMetadata { FullName = i, IsDirectory = true }), namingOptions);
}
/// <summary>
/// Resolves only files from paths.
/// </summary>
/// <param name="files">List of paths.</param>
/// <param name="namingOptions">The naming options.</param>
/// <returns>Enumerable <see cref="FileStack"/> of files.</returns>
public IEnumerable<FileStack> ResolveFiles(IEnumerable<string> files)
public static IEnumerable<FileStack> ResolveFiles(IEnumerable<string> files, NamingOptions namingOptions)
{
return Resolve(files.Select(i => new FileSystemMetadata { FullName = i, IsDirectory = false }));
return Resolve(files.Select(i => new FileSystemMetadata { FullName = i, IsDirectory = false }), namingOptions);
}
/// <summary>
@@ -50,7 +40,7 @@ namespace Emby.Naming.Video
/// </summary>
/// <param name="files">List of paths.</param>
/// <returns>Enumerable <see cref="FileStack"/> of directories.</returns>
public IEnumerable<FileStack> ResolveAudioBooks(IEnumerable<AudioBookFileInfo> files)
public static IEnumerable<FileStack> ResolveAudioBooks(IEnumerable<AudioBookFileInfo> files)
{
var groupedDirectoryFiles = files.GroupBy(file => Path.GetDirectoryName(file.Path));
@@ -60,19 +50,13 @@ namespace Emby.Naming.Video
{
foreach (var file in directory)
{
var stack = new FileStack { Name = Path.GetFileNameWithoutExtension(file.Path), IsDirectoryStack = false };
stack.Files.Add(file.Path);
var stack = new FileStack(Path.GetFileNameWithoutExtension(file.Path), false, new[] { file.Path });
yield return stack;
}
}
else
{
var stack = new FileStack { Name = Path.GetFileName(directory.Key), IsDirectoryStack = false };
foreach (var file in directory)
{
stack.Files.Add(file.Path);
}
var stack = new FileStack(Path.GetFileName(directory.Key), false, directory.Select(f => f.Path).ToArray());
yield return stack;
}
}
@@ -82,158 +66,91 @@ namespace Emby.Naming.Video
/// Resolves videos from paths.
/// </summary>
/// <param name="files">List of paths.</param>
/// <param name="namingOptions">The naming options.</param>
/// <returns>Enumerable <see cref="FileStack"/> of videos.</returns>
public IEnumerable<FileStack> Resolve(IEnumerable<FileSystemMetadata> files)
public static IEnumerable<FileStack> Resolve(IEnumerable<FileSystemMetadata> files, NamingOptions namingOptions)
{
var list = files
.Where(i => i.IsDirectory || VideoResolver.IsVideoFile(i.FullName, _options) || VideoResolver.IsStubFile(i.FullName, _options))
.OrderBy(i => i.FullName)
.ToList();
var potentialFiles = files
.Where(i => i.IsDirectory || VideoResolver.IsVideoFile(i.FullName, namingOptions) || VideoResolver.IsStubFile(i.FullName, namingOptions))
.OrderBy(i => i.FullName);
var expressions = _options.VideoFileStackingRegexes;
for (var i = 0; i < list.Count; i++)
var potentialStacks = new Dictionary<string, StackMetadata>();
foreach (var file in potentialFiles)
{
var offset = 0;
var file1 = list[i];
var expressionIndex = 0;
while (expressionIndex < expressions.Length)
var name = file.Name;
if (string.IsNullOrEmpty(name))
{
var exp = expressions[expressionIndex];
var stack = new FileStack();
name = Path.GetFileName(file.FullName);
}
// (Title)(Volume)(Ignore)(Extension)
var match1 = FindMatch(file1, exp, offset);
if (match1.Success)
for (var i = 0; i < namingOptions.VideoFileStackingRules.Length; i++)
{
var rule = namingOptions.VideoFileStackingRules[i];
if (!rule.Match(name, out var stackParsingResult))
{
var title1 = match1.Groups["title"].Value;
var volume1 = match1.Groups["volume"].Value;
var ignore1 = match1.Groups["ignore"].Value;
var extension1 = match1.Groups["extension"].Value;
continue;
}
var j = i + 1;
while (j < list.Count)
var stackName = stackParsingResult.Value.StackName;
var partNumber = stackParsingResult.Value.PartNumber;
var partType = stackParsingResult.Value.PartType;
if (!potentialStacks.TryGetValue(stackName, out var stackResult))
{
stackResult = new StackMetadata(file.IsDirectory, rule.IsNumerical, partType);
potentialStacks[stackName] = stackResult;
}
if (stackResult.Parts.Count > 0)
{
if (stackResult.IsDirectory != file.IsDirectory
|| !string.Equals(partType, stackResult.PartType, StringComparison.OrdinalIgnoreCase)
|| stackResult.ContainsPart(partNumber))
{
var file2 = list[j];
if (file1.IsDirectory != file2.IsDirectory)
{
j++;
continue;
}
// (Title)(Volume)(Ignore)(Extension)
var match2 = FindMatch(file2, exp, offset);
if (match2.Success)
{
var title2 = match2.Groups[1].Value;
var volume2 = match2.Groups[2].Value;
var ignore2 = match2.Groups[3].Value;
var extension2 = match2.Groups[4].Value;
if (string.Equals(title1, title2, StringComparison.OrdinalIgnoreCase))
{
if (!string.Equals(volume1, volume2, StringComparison.OrdinalIgnoreCase))
{
if (string.Equals(ignore1, ignore2, StringComparison.OrdinalIgnoreCase)
&& string.Equals(extension1, extension2, StringComparison.OrdinalIgnoreCase))
{
if (stack.Files.Count == 0)
{
stack.Name = title1 + ignore1;
stack.IsDirectoryStack = file1.IsDirectory;
stack.Files.Add(file1.FullName);
}
stack.Files.Add(file2.FullName);
}
else
{
// Sequel
offset = 0;
expressionIndex++;
break;
}
}
else if (!string.Equals(ignore1, ignore2, StringComparison.OrdinalIgnoreCase))
{
// False positive, try again with offset
offset = match1.Groups[3].Index;
break;
}
else
{
// Extension mismatch
offset = 0;
expressionIndex++;
break;
}
}
else
{
// Title mismatch
offset = 0;
expressionIndex++;
break;
}
}
else
{
// No match 2, next expression
offset = 0;
expressionIndex++;
break;
}
j++;
continue;
}
if (j == list.Count)
if (rule.IsNumerical != stackResult.IsNumerical)
{
expressionIndex = expressions.Length;
break;
}
}
else
{
// No match 1
offset = 0;
expressionIndex++;
}
if (stack.Files.Count > 1)
{
yield return stack;
i += stack.Files.Count - 1;
break;
}
stackResult.Parts.Add(partNumber, file);
break;
}
}
}
private static string GetRegexInput(FileSystemMetadata file)
{
// For directories, dummy up an extension otherwise the expressions will fail
var input = !file.IsDirectory
? file.FullName
: file.FullName + ".mkv";
return Path.GetFileName(input);
}
private static Match FindMatch(FileSystemMetadata input, Regex regex, int offset)
{
var regexInput = GetRegexInput(input);
if (offset < 0 || offset >= regexInput.Length)
foreach (var (fileName, stack) in potentialStacks)
{
return Match.Empty;
if (stack.Parts.Count < 2)
{
continue;
}
yield return new FileStack(fileName, stack.IsDirectory, stack.Parts.Select(kv => kv.Value.FullName).ToArray());
}
}
private class StackMetadata
{
public StackMetadata(bool isDirectory, bool isNumerical, string partType)
{
Parts = new Dictionary<string, FileSystemMetadata>(StringComparer.OrdinalIgnoreCase);
IsDirectory = isDirectory;
IsNumerical = isNumerical;
PartType = partType;
}
return regex.Match(regexInput, offset);
public Dictionary<string, FileSystemMetadata> Parts { get; }
public bool IsDirectory { get; }
public bool IsNumerical { get; }
public string PartType { get; }
public bool ContainsPart(string partNumber) => Parts.ContainsKey(partNumber);
}
}
}

View File

@@ -1,7 +1,7 @@
using System;
using System.IO;
using System.Linq;
using Emby.Naming.Common;
using Jellyfin.Extensions;
namespace Emby.Naming.Video
{
@@ -28,7 +28,7 @@ namespace Emby.Naming.Video
var extension = Path.GetExtension(path);
if (!options.StubFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
if (!options.StubFileExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase))
{
return false;
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using MediaBrowser.Model.Entities;
namespace Emby.Naming.Video
{
@@ -17,7 +18,6 @@ namespace Emby.Naming.Video
Name = name;
Files = Array.Empty<VideoFileInfo>();
Extras = Array.Empty<VideoFileInfo>();
AlternateVersions = Array.Empty<VideoFileInfo>();
}
@@ -39,16 +39,15 @@ namespace Emby.Naming.Video
/// <value>The files.</value>
public IReadOnlyList<VideoFileInfo> Files { get; set; }
/// <summary>
/// Gets or sets the extras.
/// </summary>
/// <value>The extras.</value>
public IReadOnlyList<VideoFileInfo> Extras { get; set; }
/// <summary>
/// Gets or sets the alternate versions.
/// </summary>
/// <value>The alternate versions.</value>
public IReadOnlyList<VideoFileInfo> AlternateVersions { get; set; }
/// <summary>
/// Gets or sets the extra type.
/// </summary>
public ExtraType? ExtraType { get; set; }
}
}

View File

@@ -4,7 +4,6 @@ using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Emby.Naming.Common;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
namespace Emby.Naming.Video
@@ -17,29 +16,41 @@ namespace Emby.Naming.Video
/// <summary>
/// Resolves alternative versions and extras from list of video files.
/// </summary>
/// <param name="files">List of related video files.</param>
/// <param name="videoInfos">List of related video files.</param>
/// <param name="namingOptions">The naming options.</param>
/// <param name="supportMultiVersion">Indication we should consider multi-versions of content.</param>
/// <param name="parseName">Whether to parse the name or use the filename.</param>
/// <returns>Returns enumerable of <see cref="VideoInfo"/> which groups files together when related.</returns>
public static IEnumerable<VideoInfo> Resolve(IEnumerable<FileSystemMetadata> files, NamingOptions namingOptions, bool supportMultiVersion = true)
public static IReadOnlyList<VideoInfo> Resolve(IReadOnlyList<VideoFileInfo> videoInfos, NamingOptions namingOptions, bool supportMultiVersion = true, bool parseName = true)
{
var videoInfos = files
.Select(i => VideoResolver.Resolve(i.FullName, i.IsDirectory, namingOptions))
.OfType<VideoFileInfo>()
.ToList();
// Filter out all extras, otherwise they could cause stacks to not be resolved
// See the unit test TestStackedWithTrailer
var nonExtras = videoInfos
.Where(i => i.ExtraType == null)
.Select(i => new FileSystemMetadata { FullName = i.Path, IsDirectory = i.IsDirectory });
var stackResult = new StackResolver(namingOptions)
.Resolve(nonExtras).ToList();
var stackResult = StackResolver.Resolve(nonExtras, namingOptions).ToList();
var remainingFiles = videoInfos
.Where(i => !stackResult.Any(s => i.Path != null && s.ContainsFile(i.Path, i.IsDirectory)))
.ToList();
var remainingFiles = new List<VideoFileInfo>();
var standaloneMedia = new List<VideoFileInfo>();
for (var i = 0; i < videoInfos.Count; i++)
{
var current = videoInfos[i];
if (stackResult.Any(s => s.ContainsFile(current.Path, current.IsDirectory)))
{
continue;
}
if (current.ExtraType == null)
{
standaloneMedia.Add(current);
}
else
{
remainingFiles.Add(current);
}
}
var list = new List<VideoInfo>();
@@ -47,38 +58,20 @@ namespace Emby.Naming.Video
{
var info = new VideoInfo(stack.Name)
{
Files = stack.Files.Select(i => VideoResolver.Resolve(i, stack.IsDirectoryStack, namingOptions))
Files = stack.Files.Select(i => VideoResolver.Resolve(i, stack.IsDirectoryStack, namingOptions, parseName))
.OfType<VideoFileInfo>()
.ToList()
};
info.Year = info.Files[0].Year;
var extras = ExtractExtras(remainingFiles, stack.Name, Path.GetFileNameWithoutExtension(stack.Files[0].AsSpan()), namingOptions.VideoFlagDelimiters);
if (extras.Count > 0)
{
info.Extras = extras;
}
list.Add(info);
}
var standaloneMedia = remainingFiles
.Where(i => i.ExtraType == null)
.ToList();
foreach (var media in standaloneMedia)
{
var info = new VideoInfo(media.Name) { Files = new[] { media } };
info.Year = info.Files[0].Year;
remainingFiles.Remove(media);
var extras = ExtractExtras(remainingFiles, media.FileNameWithoutExtension, namingOptions.VideoFlagDelimiters);
info.Extras = extras;
list.Add(info);
}
@@ -87,58 +80,12 @@ namespace Emby.Naming.Video
list = GetVideosGroupedByVersion(list, namingOptions);
}
// If there's only one resolved video, use the folder name as well to find extras
if (list.Count == 1)
{
var info = list[0];
var videoPath = list[0].Files[0].Path;
var parentPath = Path.GetDirectoryName(videoPath.AsSpan());
if (!parentPath.IsEmpty)
{
var folderName = Path.GetFileName(parentPath);
if (!folderName.IsEmpty)
{
var extras = ExtractExtras(remainingFiles, folderName, namingOptions.VideoFlagDelimiters);
extras.AddRange(info.Extras);
info.Extras = extras;
}
}
// Add the extras that are just based on file name as well
var extrasByFileName = remainingFiles
.Where(i => i.ExtraRule != null && i.ExtraRule.RuleType == ExtraRuleType.Filename)
.ToList();
remainingFiles = remainingFiles
.Except(extrasByFileName)
.ToList();
extrasByFileName.AddRange(info.Extras);
info.Extras = extrasByFileName;
}
// If there's only one video, accept all trailers
// Be lenient because people use all kinds of mishmash conventions with trailers.
if (list.Count == 1)
{
var trailers = remainingFiles
.Where(i => i.ExtraType == ExtraType.Trailer)
.ToList();
trailers.AddRange(list[0].Extras);
list[0].Extras = trailers;
remainingFiles = remainingFiles
.Except(trailers)
.ToList();
}
// Whatever files are left, just add them
list.AddRange(remainingFiles.Select(i => new VideoInfo(i.Name)
{
Files = new[] { i },
Year = i.Year
Year = i.Year,
ExtraType = i.ExtraType
}));
return list;
@@ -162,6 +109,11 @@ namespace Emby.Naming.Video
for (var i = 0; i < videos.Count; i++)
{
var video = videos[i];
if (video.ExtraType != null)
{
continue;
}
if (!IsEligibleForMultiVersion(folderName, video.Files[0].Path, namingOptions))
{
return videos;
@@ -178,17 +130,14 @@ namespace Emby.Naming.Video
var alternateVersionsLen = videos.Count - 1;
var alternateVersions = new VideoFileInfo[alternateVersionsLen];
var extras = new List<VideoFileInfo>(list[0].Extras);
for (int i = 0; i < alternateVersionsLen; i++)
{
var video = videos[i + 1];
alternateVersions[i] = video.Files[0];
extras.AddRange(video.Extras);
}
list[0].AlternateVersions = alternateVersions;
list[0].Name = folderName.ToString();
list[0].Extras = extras;
return list;
}
@@ -230,7 +179,7 @@ namespace Emby.Naming.Video
var tmpTestFilename = testFilename.ToString();
if (CleanStringParser.TryClean(tmpTestFilename, namingOptions.CleanStringRegexes, out var cleanName))
{
tmpTestFilename = cleanName.Trim().ToString();
tmpTestFilename = cleanName.Trim();
}
// The CleanStringParser should have removed common keywords etc.
@@ -238,67 +187,5 @@ namespace Emby.Naming.Video
|| testFilename[0] == '-'
|| Regex.IsMatch(tmpTestFilename, @"^\[([^]]*)\]", RegexOptions.Compiled);
}
private static ReadOnlySpan<char> TrimFilenameDelimiters(ReadOnlySpan<char> name, ReadOnlySpan<char> videoFlagDelimiters)
{
return name.IsEmpty ? name : name.TrimEnd().TrimEnd(videoFlagDelimiters).TrimEnd();
}
private static bool StartsWith(ReadOnlySpan<char> fileName, ReadOnlySpan<char> baseName, ReadOnlySpan<char> trimmedBaseName)
{
if (baseName.IsEmpty)
{
return false;
}
return fileName.StartsWith(baseName, StringComparison.OrdinalIgnoreCase)
|| (!trimmedBaseName.IsEmpty && fileName.StartsWith(trimmedBaseName, StringComparison.OrdinalIgnoreCase));
}
/// <summary>
/// Finds similar filenames to that of [baseName] and removes any matches from [remainingFiles].
/// </summary>
/// <param name="remainingFiles">The list of remaining filenames.</param>
/// <param name="baseName">The base name to use for the comparison.</param>
/// <param name="videoFlagDelimiters">The video flag delimiters.</param>
/// <returns>A list of video extras for [baseName].</returns>
private static List<VideoFileInfo> ExtractExtras(IList<VideoFileInfo> remainingFiles, ReadOnlySpan<char> baseName, ReadOnlySpan<char> videoFlagDelimiters)
{
return ExtractExtras(remainingFiles, baseName, ReadOnlySpan<char>.Empty, videoFlagDelimiters);
}
/// <summary>
/// Finds similar filenames to that of [firstBaseName] and [secondBaseName] and removes any matches from [remainingFiles].
/// </summary>
/// <param name="remainingFiles">The list of remaining filenames.</param>
/// <param name="firstBaseName">The first base name to use for the comparison.</param>
/// <param name="secondBaseName">The second base name to use for the comparison.</param>
/// <param name="videoFlagDelimiters">The video flag delimiters.</param>
/// <returns>A list of video extras for [firstBaseName] and [secondBaseName].</returns>
private static List<VideoFileInfo> ExtractExtras(IList<VideoFileInfo> remainingFiles, ReadOnlySpan<char> firstBaseName, ReadOnlySpan<char> secondBaseName, ReadOnlySpan<char> videoFlagDelimiters)
{
var trimmedFirstBaseName = TrimFilenameDelimiters(firstBaseName, videoFlagDelimiters);
var trimmedSecondBaseName = TrimFilenameDelimiters(secondBaseName, videoFlagDelimiters);
var result = new List<VideoFileInfo>();
for (var pos = remainingFiles.Count - 1; pos >= 0; pos--)
{
var file = remainingFiles[pos];
if (file.ExtraType == null)
{
continue;
}
var filename = file.FileNameWithoutExtension;
if (StartsWith(filename, firstBaseName, trimmedFirstBaseName)
|| StartsWith(filename, secondBaseName, trimmedSecondBaseName))
{
result.Add(file);
remainingFiles.RemoveAt(pos);
}
}
return result;
}
}
}

View File

@@ -16,10 +16,11 @@ namespace Emby.Naming.Video
/// </summary>
/// <param name="path">The path.</param>
/// <param name="namingOptions">The naming options.</param>
/// <param name="parseName">Whether to parse the name or use the filename.</param>
/// <returns>VideoFileInfo.</returns>
public static VideoFileInfo? ResolveDirectory(string? path, NamingOptions namingOptions)
public static VideoFileInfo? ResolveDirectory(string? path, NamingOptions namingOptions, bool parseName = true)
{
return Resolve(path, true, namingOptions);
return Resolve(path, true, namingOptions, parseName);
}
/// <summary>
@@ -74,7 +75,7 @@ namespace Emby.Naming.Video
var format3DResult = Format3DParser.Parse(path, namingOptions);
var extraResult = new ExtraResolver(namingOptions).GetExtraInfo(path);
var extraResult = ExtraRuleResolver.GetExtraInfo(path, namingOptions);
var name = Path.GetFileNameWithoutExtension(path);

View File

@@ -24,63 +24,63 @@ namespace Emby.Notifications
{
new NotificationTypeInfo
{
Type = NotificationType.ApplicationUpdateInstalled.ToString()
Type = nameof(NotificationType.ApplicationUpdateInstalled)
},
new NotificationTypeInfo
{
Type = NotificationType.InstallationFailed.ToString()
Type = nameof(NotificationType.InstallationFailed)
},
new NotificationTypeInfo
{
Type = NotificationType.PluginInstalled.ToString()
Type = nameof(NotificationType.PluginInstalled)
},
new NotificationTypeInfo
{
Type = NotificationType.PluginError.ToString()
Type = nameof(NotificationType.PluginError)
},
new NotificationTypeInfo
{
Type = NotificationType.PluginUninstalled.ToString()
Type = nameof(NotificationType.PluginUninstalled)
},
new NotificationTypeInfo
{
Type = NotificationType.PluginUpdateInstalled.ToString()
Type = nameof(NotificationType.PluginUpdateInstalled)
},
new NotificationTypeInfo
{
Type = NotificationType.ServerRestartRequired.ToString()
Type = nameof(NotificationType.ServerRestartRequired)
},
new NotificationTypeInfo
{
Type = NotificationType.TaskFailed.ToString()
Type = nameof(NotificationType.TaskFailed)
},
new NotificationTypeInfo
{
Type = NotificationType.NewLibraryContent.ToString()
Type = nameof(NotificationType.NewLibraryContent)
},
new NotificationTypeInfo
{
Type = NotificationType.AudioPlayback.ToString()
Type = nameof(NotificationType.AudioPlayback)
},
new NotificationTypeInfo
{
Type = NotificationType.VideoPlayback.ToString()
Type = nameof(NotificationType.VideoPlayback)
},
new NotificationTypeInfo
{
Type = NotificationType.AudioPlaybackStopped.ToString()
Type = nameof(NotificationType.AudioPlaybackStopped)
},
new NotificationTypeInfo
{
Type = NotificationType.VideoPlaybackStopped.ToString()
Type = nameof(NotificationType.VideoPlaybackStopped)
},
new NotificationTypeInfo
{
Type = NotificationType.UserLockedOut.ToString()
Type = nameof(NotificationType.UserLockedOut)
},
new NotificationTypeInfo
{
Type = NotificationType.ApplicationUpdateAvailable.ToString()
Type = nameof(NotificationType.ApplicationUpdateAvailable)
}
};
@@ -98,7 +98,7 @@ namespace Emby.Notifications
private void Update(NotificationTypeInfo note)
{
note.Name = _localization.GetLocalizedString("NotificationOption" + note.Type) ?? note.Type;
note.Name = _localization.GetLocalizedString("NotificationOption" + note.Type);
note.IsBasedOnUserEvent = note.Type.IndexOf("Playback", StringComparison.OrdinalIgnoreCase) != -1;

View File

@@ -23,8 +23,12 @@
<!-- Code analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.406" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>

View File

@@ -5,6 +5,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Events;
using Jellyfin.Extensions;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
@@ -104,14 +105,14 @@ namespace Emby.Notifications
var type = entry.Type;
if (string.IsNullOrEmpty(type) || !_coreNotificationTypes.Contains(type, StringComparer.OrdinalIgnoreCase))
if (string.IsNullOrEmpty(type) || !_coreNotificationTypes.Contains(type, StringComparison.OrdinalIgnoreCase))
{
return;
}
var userId = e.Argument.UserId;
if (!userId.Equals(Guid.Empty) && !GetOptions().IsEnabledToMonitorUser(type, userId))
if (!userId.Equals(default) && !GetOptions().IsEnabledToMonitorUser(type, userId))
{
return;
}

View File

@@ -15,7 +15,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="TagLibSharp" Version="2.2.0" />
<PackageReference Include="TagLibSharp" Version="2.3.0" />
</ItemGroup>
<PropertyGroup>
@@ -26,7 +26,11 @@
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.406" PrivateAssets="All" />
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>

View File

@@ -3,6 +3,7 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Extensions;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
@@ -60,7 +61,7 @@ namespace Emby.Photos
item.SetImagePath(ImageType.Primary, item.Path);
// Examples: https://github.com/mono/taglib-sharp/blob/a5f6949a53d09ce63ee7495580d6802921a21f14/tests/fixtures/TagLib.Tests.Images/NullOrientationTest.cs
if (_includeExtensions.Contains(Path.GetExtension(item.Path), StringComparer.OrdinalIgnoreCase))
if (_includeExtensions.Contains(Path.GetExtension(item.Path), StringComparison.OrdinalIgnoreCase))
{
try
{

View File

@@ -301,7 +301,7 @@ namespace Emby.Server.Implementations.AppBase
{
return _configurations.GetOrAdd(
key,
(k, configurationManager) =>
static (k, configurationManager) =>
{
var file = configurationManager.GetConfigurationFile(k);
@@ -371,7 +371,7 @@ namespace Emby.Server.Implementations.AppBase
NewConfiguration = configuration
});
_configurations.AddOrUpdate(key, configuration, (k, v) => configuration);
_configurations.AddOrUpdate(key, configuration, (_, _) => configuration);
var path = GetConfigurationFile(key);
Directory.CreateDirectory(Path.GetDirectoryName(path));
@@ -398,6 +398,12 @@ namespace Emby.Server.Implementations.AppBase
});
}
/// <inheritdoc />
public ConfigurationStore[] GetConfigurationStores()
{
return _configurationStores;
}
/// <inheritdoc />
public Type GetConfigurationType(string key)
{

View File

@@ -1,6 +1,5 @@
using System;
using System.IO;
using System.Linq;
using MediaBrowser.Model.Serialization;
namespace Emby.Server.Implementations.AppBase

View File

@@ -19,6 +19,7 @@ using Emby.Dlna;
using Emby.Dlna.Main;
using Emby.Dlna.Ssdp;
using Emby.Drawing;
using Emby.Naming.Common;
using Emby.Notifications;
using Emby.Photos;
using Emby.Server.Implementations.Archiving;
@@ -43,9 +44,9 @@ using Emby.Server.Implementations.Serialization;
using Emby.Server.Implementations.Session;
using Emby.Server.Implementations.SyncPlay;
using Emby.Server.Implementations.TV;
using Emby.Server.Implementations.Udp;
using Emby.Server.Implementations.Updates;
using Jellyfin.Api.Helpers;
using Jellyfin.MediaEncoding.Hls.Playlist;
using Jellyfin.Networking.Configuration;
using Jellyfin.Networking.Manager;
using MediaBrowser.Common;
@@ -102,6 +103,7 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Prometheus.DotNetRuntime;
using static MediaBrowser.Controller.Extensions.ConfigurationExtensions;
using WebSocketManager = Emby.Server.Implementations.HttpServer.WebSocketManager;
namespace Emby.Server.Implementations
@@ -109,7 +111,7 @@ namespace Emby.Server.Implementations
/// <summary>
/// Class CompositionRoot.
/// </summary>
public abstract class ApplicationHost : IServerApplicationHost, IDisposable
public abstract class ApplicationHost : IServerApplicationHost, IAsyncDisposable, IDisposable
{
/// <summary>
/// The environment variable prefixes to log at server startup.
@@ -119,7 +121,7 @@ namespace Emby.Server.Implementations
/// <summary>
/// The disposable parts.
/// </summary>
private readonly ConcurrentDictionary<IDisposable, byte> _disposableParts = new ();
private readonly ConcurrentDictionary<IDisposable, byte> _disposableParts = new();
private readonly IFileSystem _fileSystemManager;
private readonly IConfiguration _startupConfig;
@@ -148,7 +150,7 @@ namespace Emby.Server.Implementations
/// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param>
/// <param name="options">Instance of the <see cref="IStartupOptions"/> interface.</param>
/// <param name="startupConfig">The <see cref="IConfiguration" /> interface.</param>
public ApplicationHost(
protected ApplicationHost(
IServerApplicationPaths applicationPaths,
ILoggerFactory loggerFactory,
IStartupOptions options,
@@ -182,6 +184,11 @@ namespace Emby.Server.Implementations
/// </summary>
public event EventHandler HasPendingRestartChanged;
/// <summary>
/// Gets the value of the PublishedServerUrl setting.
/// </summary>
private string PublishedServerUrl => _startupConfig[AddressOverrideKey];
/// <summary>
/// Gets a value indicating whether this instance can self restart.
/// </summary>
@@ -258,11 +265,6 @@ namespace Emby.Server.Implementations
/// </summary>
public int HttpsPort { get; private set; }
/// <summary>
/// Gets the value of the PublishedServerUrl setting.
/// </summary>
public string PublishedServerUrl => _startupOptions.PublishedServerUrl ?? _startupConfig[UdpServer.AddressOverrideConfigKey];
/// <inheritdoc />
public Version ApplicationVersion { get; }
@@ -312,22 +314,6 @@ namespace Emby.Server.Implementations
? Environment.MachineName
: ConfigurationManager.Configuration.ServerName;
/// <summary>
/// Temporary function to migration network settings out of system.xml and into network.xml.
/// TODO: remove at the point when a fixed migration path has been decided upon.
/// </summary>
private void MigrateNetworkConfiguration()
{
string path = Path.Combine(ConfigurationManager.CommonApplicationPaths.ConfigurationDirectoryPath, "network.xml");
if (!File.Exists(path))
{
var networkSettings = new NetworkConfiguration();
ClassMigrationHelper.CopyProperties(ConfigurationManager.Configuration, networkSettings);
_xmlSerializer.SerializeToFile(networkSettings, path);
Logger.LogDebug("Successfully migrated network settings.");
}
}
public string ExpandVirtualPath(string path)
{
var appPaths = ApplicationPaths;
@@ -512,8 +498,6 @@ namespace Emby.Server.Implementations
ConfigurationManager.AddParts(GetExports<IConfigurationFactory>());
// Have to migrate settings here as migration subsystem not yet initialised.
MigrateNetworkConfiguration();
NetManager = new NetworkManager(ConfigurationManager, LoggerFactory.CreateLogger<NetworkManager>());
// Initialize runtime stat collection
@@ -596,6 +580,7 @@ namespace Emby.Server.Implementations
serviceCollection.AddTransient(provider => new Lazy<IProviderManager>(provider.GetRequiredService<IProviderManager>));
serviceCollection.AddTransient(provider => new Lazy<IUserViewManager>(provider.GetRequiredService<IUserViewManager>));
serviceCollection.AddSingleton<ILibraryManager, LibraryManager>();
serviceCollection.AddSingleton<NamingOptions>();
serviceCollection.AddSingleton<IMusicManager, MusicManager>();
@@ -989,7 +974,7 @@ namespace Emby.Server.Implementations
yield return typeof(IServerApplicationHost).Assembly;
// Include composable parts in the Providers assembly
yield return typeof(ProviderUtils).Assembly;
yield return typeof(ProviderManager).Assembly;
// Include composable parts in the Photos assembly
yield return typeof(PhotoProvider).Assembly;
@@ -1015,6 +1000,9 @@ namespace Emby.Server.Implementations
// Network
yield return typeof(NetworkManager).Assembly;
// Hls
yield return typeof(DynamicHlsPlaylistGenerator).Assembly;
foreach (var i in GetAssembliesWithPartsInternal())
{
yield return i;
@@ -1126,13 +1114,13 @@ namespace Emby.Server.Implementations
}
/// <inheritdoc/>
public string GetApiUrlForLocalAccess(bool allowHttps)
public string GetApiUrlForLocalAccess(IPObject hostname = null, bool allowHttps = true)
{
// With an empty source, the port will be null
string smart = NetManager.GetBindInterface(string.Empty, out _);
var scheme = allowHttps ? Uri.UriSchemeHttps : Uri.UriSchemeHttp;
var port = allowHttps ? HttpsPort : HttpPort;
return GetLocalApiUrl(smart.Trim('/'), scheme, port);
var smart = NetManager.GetBindInterface(hostname ?? IPHost.None, out _);
var scheme = !allowHttps ? Uri.UriSchemeHttp : null;
int? port = !allowHttps ? HttpPort : null;
return GetLocalApiUrl(smart, scheme, port);
}
/// <inheritdoc/>
@@ -1146,11 +1134,13 @@ namespace Emby.Server.Implementations
// NOTE: If no BaseUrl is set then UriBuilder appends a trailing slash, but if there is no BaseUrl it does
// not. For consistency, always trim the trailing slash.
scheme ??= ListenWithHttps ? Uri.UriSchemeHttps : Uri.UriSchemeHttp;
var isHttps = string.Equals(scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase);
return new UriBuilder
{
Scheme = scheme ?? (ListenWithHttps ? Uri.UriSchemeHttps : Uri.UriSchemeHttp),
Scheme = scheme,
Host = hostname,
Port = port ?? (ListenWithHttps ? HttpsPort : HttpPort),
Port = port ?? (isHttps ? HttpsPort : HttpPort),
Path = ConfigurationManager.GetNetworkConfiguration().BaseUrl
}.ToString().TrimEnd('/');
}
@@ -1242,5 +1232,49 @@ namespace Emby.Server.Implementations
_disposed = true;
}
public async ValueTask DisposeAsync()
{
await DisposeAsyncCore().ConfigureAwait(false);
Dispose(false);
GC.SuppressFinalize(this);
}
/// <summary>
/// Used to perform asynchronous cleanup of managed resources or for cascading calls to <see cref="DisposeAsync"/>.
/// </summary>
/// <returns>A ValueTask.</returns>
protected virtual async ValueTask DisposeAsyncCore()
{
var type = GetType();
Logger.LogInformation("Disposing {Type}", type.Name);
foreach (var (part, _) in _disposableParts)
{
var partType = part.GetType();
if (partType == type)
{
continue;
}
Logger.LogInformation("Disposing {Type}", partType.Name);
try
{
part.Dispose();
}
catch (Exception ex)
{
Logger.LogError(ex, "Error disposing {Type}", partType.Name);
}
}
// used for closing websockets
foreach (var session in _sessionManager.Sessions)
{
await session.DisposeAsync().ConfigureAwait(false);
}
}
}
}

View File

@@ -1,11 +1,8 @@
using System.IO;
using MediaBrowser.Model.IO;
using SharpCompress.Archives.SevenZip;
using SharpCompress.Archives.Tar;
using SharpCompress.Common;
using SharpCompress.Readers;
using SharpCompress.Readers.GZip;
using SharpCompress.Readers.Zip;
namespace Emby.Server.Implementations.Archiving
{
@@ -14,55 +11,6 @@ namespace Emby.Server.Implementations.Archiving
/// </summary>
public class ZipClient : IZipClient
{
/// <summary>
/// Extracts all.
/// </summary>
/// <param name="sourceFile">The source file.</param>
/// <param name="targetPath">The target path.</param>
/// <param name="overwriteExistingFiles">if set to <c>true</c> [overwrite existing files].</param>
public void ExtractAll(string sourceFile, string targetPath, bool overwriteExistingFiles)
{
using var fileStream = File.OpenRead(sourceFile);
ExtractAll(fileStream, targetPath, overwriteExistingFiles);
}
/// <summary>
/// Extracts all.
/// </summary>
/// <param name="source">The source.</param>
/// <param name="targetPath">The target path.</param>
/// <param name="overwriteExistingFiles">if set to <c>true</c> [overwrite existing files].</param>
public void ExtractAll(Stream source, string targetPath, bool overwriteExistingFiles)
{
using var reader = ReaderFactory.Open(source);
var options = new ExtractionOptions
{
ExtractFullPath = true
};
if (overwriteExistingFiles)
{
options.Overwrite = true;
}
Directory.CreateDirectory(targetPath);
reader.WriteAllToDirectory(targetPath, options);
}
/// <inheritdoc />
public void ExtractAllFromZip(Stream source, string targetPath, bool overwriteExistingFiles)
{
using var reader = ZipReader.Open(source);
var options = new ExtractionOptions
{
ExtractFullPath = true,
Overwrite = overwriteExistingFiles
};
Directory.CreateDirectory(targetPath);
reader.WriteAllToDirectory(targetPath, options);
}
/// <inheritdoc />
public void ExtractAllFromGz(Stream source, string targetPath, bool overwriteExistingFiles)
{
@@ -94,69 +42,5 @@ namespace Emby.Server.Implementations.Archiving
reader.WriteEntryToFile(Path.Combine(targetPath, filename));
}
}
/// <summary>
/// Extracts all from7z.
/// </summary>
/// <param name="sourceFile">The source file.</param>
/// <param name="targetPath">The target path.</param>
/// <param name="overwriteExistingFiles">if set to <c>true</c> [overwrite existing files].</param>
public void ExtractAllFrom7z(string sourceFile, string targetPath, bool overwriteExistingFiles)
{
using var fileStream = File.OpenRead(sourceFile);
ExtractAllFrom7z(fileStream, targetPath, overwriteExistingFiles);
}
/// <summary>
/// Extracts all from7z.
/// </summary>
/// <param name="source">The source.</param>
/// <param name="targetPath">The target path.</param>
/// <param name="overwriteExistingFiles">if set to <c>true</c> [overwrite existing files].</param>
public void ExtractAllFrom7z(Stream source, string targetPath, bool overwriteExistingFiles)
{
using var archive = SevenZipArchive.Open(source);
using var reader = archive.ExtractAllEntries();
var options = new ExtractionOptions
{
ExtractFullPath = true,
Overwrite = overwriteExistingFiles
};
Directory.CreateDirectory(targetPath);
reader.WriteAllToDirectory(targetPath, options);
}
/// <summary>
/// Extracts all from tar.
/// </summary>
/// <param name="sourceFile">The source file.</param>
/// <param name="targetPath">The target path.</param>
/// <param name="overwriteExistingFiles">if set to <c>true</c> [overwrite existing files].</param>
public void ExtractAllFromTar(string sourceFile, string targetPath, bool overwriteExistingFiles)
{
using var fileStream = File.OpenRead(sourceFile);
ExtractAllFromTar(fileStream, targetPath, overwriteExistingFiles);
}
/// <summary>
/// Extracts all from tar.
/// </summary>
/// <param name="source">The source.</param>
/// <param name="targetPath">The target path.</param>
/// <param name="overwriteExistingFiles">if set to <c>true</c> [overwrite existing files].</param>
public void ExtractAllFromTar(Stream source, string targetPath, bool overwriteExistingFiles)
{
using var archive = TarArchive.Open(source);
using var reader = archive.ExtractAllEntries();
var options = new ExtractionOptions
{
ExtractFullPath = true,
Overwrite = overwriteExistingFiles
};
Directory.CreateDirectory(targetPath);
reader.WriteAllToDirectory(targetPath, options);
}
}
}

View File

@@ -10,6 +10,7 @@ using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
using Jellyfin.Extensions.Json;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Progress;
@@ -38,7 +39,7 @@ namespace Emby.Server.Implementations.Channels
/// <summary>
/// The LiveTV channel manager.
/// </summary>
public class ChannelManager : IChannelManager
public class ChannelManager : IChannelManager, IDisposable
{
private readonly IUserManager _userManager;
private readonly IUserDataManager _userDataManager;
@@ -51,6 +52,7 @@ namespace Emby.Server.Implementations.Channels
private readonly IMemoryCache _memoryCache;
private readonly SemaphoreSlim _resourcePool = new SemaphoreSlim(1, 1);
private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
private bool _disposed = false;
/// <summary>
/// Initializes a new instance of the <see cref="ChannelManager"/> class.
@@ -129,16 +131,14 @@ namespace Emby.Server.Implementations.Channels
var internalChannel = _libraryManager.GetItemById(item.ChannelId);
if (internalChannel == null)
{
throw new ArgumentException();
throw new ArgumentException(nameof(item.ChannelId));
}
var channel = Channels.FirstOrDefault(i => GetInternalChannelId(i.Name).Equals(internalChannel.Id));
var supportsDelete = channel as ISupportsDelete;
if (supportsDelete == null)
if (channel is not ISupportsDelete supportsDelete)
{
throw new ArgumentException();
throw new ArgumentException(nameof(channel));
}
return supportsDelete.DeleteItem(item.ExternalId, CancellationToken.None);
@@ -162,7 +162,7 @@ namespace Emby.Server.Implementations.Channels
/// <inheritdoc />
public QueryResult<Channel> GetChannelsInternal(ChannelQuery query)
{
var user = query.UserId.Equals(Guid.Empty)
var user = query.UserId.Equals(default)
? null
: _userManager.GetUserById(query.UserId);
@@ -179,7 +179,7 @@ namespace Emby.Server.Implementations.Channels
try
{
return (GetChannelProvider(i) is IHasFolderAttributes hasAttributes
&& hasAttributes.Attributes.Contains("Recordings", StringComparer.OrdinalIgnoreCase)) == val;
&& hasAttributes.Attributes.Contains("Recordings", StringComparison.OrdinalIgnoreCase)) == val;
}
catch
{
@@ -265,17 +265,16 @@ namespace Emby.Server.Implementations.Channels
}
}
return new QueryResult<Channel>
{
Items = all,
TotalRecordCount = totalCount
};
return new QueryResult<Channel>(
query.StartIndex,
totalCount,
all);
}
/// <inheritdoc />
public QueryResult<BaseItemDto> GetChannels(ChannelQuery query)
{
var user = query.UserId.Equals(Guid.Empty)
var user = query.UserId.Equals(default)
? null
: _userManager.GetUserById(query.UserId);
@@ -286,11 +285,10 @@ namespace Emby.Server.Implementations.Channels
// TODO Fix The co-variant conversion (internalResult.Items) between Folder[] and BaseItem[], this can generate runtime issues.
var returnItems = _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user);
var result = new QueryResult<BaseItemDto>
{
Items = returnItems,
TotalRecordCount = internalResult.TotalRecordCount
};
var result = new QueryResult<BaseItemDto>(
query.StartIndex,
internalResult.TotalRecordCount,
returnItems);
return result;
}
@@ -334,7 +332,7 @@ namespace Emby.Server.Implementations.Channels
private Channel GetChannelEntity(IChannel channel)
{
return GetChannel(GetInternalChannelId(channel.Name)) ?? GetChannel(channel, CancellationToken.None).Result;
return GetChannel(GetInternalChannelId(channel.Name)) ?? GetChannel(channel, CancellationToken.None).GetAwaiter().GetResult();
}
private MediaSourceInfo[] GetSavedMediaSources(BaseItem item)
@@ -476,7 +474,7 @@ namespace Emby.Server.Implementations.Channels
item.ChannelId = id;
if (item.ParentId != parentFolderId)
if (!item.ParentId.Equals(parentFolderId))
{
forceUpdate = true;
}
@@ -541,7 +539,7 @@ namespace Emby.Server.Implementations.Channels
return _libraryManager.GetItemIds(
new InternalItemsQuery
{
IncludeItemTypes = new[] { nameof(Channel) },
IncludeItemTypes = new[] { BaseItemKind.Channel },
OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) }
}).Select(i => GetChannelFeatures(i)).ToArray();
}
@@ -621,11 +619,10 @@ namespace Emby.Server.Implementations.Channels
var returnItems = _dtoService.GetBaseItemDtos(items, query.DtoOptions, query.User);
var result = new QueryResult<BaseItemDto>
{
Items = returnItems,
TotalRecordCount = totalRecordCount
};
var result = new QueryResult<BaseItemDto>(
query.StartIndex,
totalRecordCount,
returnItems);
return result;
}
@@ -718,7 +715,9 @@ namespace Emby.Server.Implementations.Channels
// Find the corresponding channel provider plugin
var channelProvider = GetChannelProvider(channel);
var parentItem = query.ParentId == Guid.Empty ? channel : _libraryManager.GetItemById(query.ParentId);
var parentItem = query.ParentId.Equals(default)
? channel
: _libraryManager.GetItemById(query.ParentId);
var itemsResult = await GetChannelItems(
channelProvider,
@@ -729,7 +728,7 @@ namespace Emby.Server.Implementations.Channels
cancellationToken)
.ConfigureAwait(false);
if (query.ParentId == Guid.Empty)
if (query.ParentId.Equals(default))
{
query.Parent = channel;
}
@@ -787,11 +786,10 @@ namespace Emby.Server.Implementations.Channels
var returnItems = _dtoService.GetBaseItemDtos(internalResult.Items, query.DtoOptions, query.User);
var result = new QueryResult<BaseItemDto>
{
Items = returnItems,
TotalRecordCount = internalResult.TotalRecordCount
};
var result = new QueryResult<BaseItemDto>(
query.StartIndex,
internalResult.TotalRecordCount,
returnItems);
return result;
}
@@ -1075,14 +1073,6 @@ namespace Emby.Server.Implementations.Channels
forceUpdate = true;
}
// was used for status
// if (!string.Equals(item.ExternalEtag ?? string.Empty, info.Etag ?? string.Empty, StringComparison.Ordinal))
// {
// item.ExternalEtag = info.Etag;
// forceUpdate = true;
// _logger.LogDebug("Forcing update due to ExternalEtag {0}", item.Name);
// }
if (!internalChannelId.Equals(item.ChannelId))
{
forceUpdate = true;
@@ -1143,7 +1133,7 @@ namespace Emby.Server.Implementations.Channels
if (!info.IsLiveStream)
{
if (item.Tags.Contains("livestream", StringComparer.OrdinalIgnoreCase))
if (item.Tags.Contains("livestream", StringComparison.OrdinalIgnoreCase))
{
item.Tags = item.Tags.Except(new[] { "livestream" }, StringComparer.OrdinalIgnoreCase).ToArray();
_logger.LogDebug("Forcing update due to Tags {0}", item.Name);
@@ -1152,7 +1142,7 @@ namespace Emby.Server.Implementations.Channels
}
else
{
if (!item.Tags.Contains("livestream", StringComparer.OrdinalIgnoreCase))
if (!item.Tags.Contains("livestream", StringComparison.OrdinalIgnoreCase))
{
item.Tags = item.Tags.Concat(new[] { "livestream" }).ToArray();
_logger.LogDebug("Forcing update due to Tags {0}", item.Name);
@@ -1226,5 +1216,31 @@ namespace Emby.Server.Implementations.Channels
return result;
}
/// <inheritdoc />
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Releases unmanaged and optionally managed resources.
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
if (disposing)
{
_resourcePool?.Dispose();
}
_disposed = true;
}
}
}

View File

@@ -2,6 +2,7 @@ using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
@@ -51,7 +52,7 @@ namespace Emby.Server.Implementations.Channels
var uninstalledChannels = _libraryManager.GetItemList(new InternalItemsQuery
{
IncludeItemTypes = new[] { nameof(Channel) },
IncludeItemTypes = new[] { BaseItemKind.Channel },
ExcludeItemIds = installedChannelIds.ToArray()
});

View File

@@ -62,7 +62,7 @@ namespace Emby.Server.Implementations.Channels
public string Key => "RefreshInternetChannels";
/// <inheritdoc />
public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
public async Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
{
var manager = (ChannelManager)_channelManager;

View File

@@ -140,7 +140,7 @@ namespace Emby.Server.Implementations.Collections
if (parentFolder == null)
{
throw new ArgumentException();
throw new ArgumentException(nameof(parentFolder));
}
var path = Path.Combine(parentFolder.Path, folderName);
@@ -265,7 +265,7 @@ namespace Emby.Server.Implementations.Collections
{
var childItem = _libraryManager.GetItemById(guidId);
var child = collection.LinkedChildren.FirstOrDefault(i => (i.ItemId.HasValue && i.ItemId.Value == guidId) || (childItem != null && string.Equals(childItem.Path, i.Path, StringComparison.OrdinalIgnoreCase)));
var child = collection.LinkedChildren.FirstOrDefault(i => (i.ItemId.HasValue && i.ItemId.Value.Equals(guidId)) || (childItem != null && string.Equals(childItem.Path, i.Path, StringComparison.OrdinalIgnoreCase)));
if (child == null)
{

View File

@@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Security.Cryptography;
using System.Text;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Model.Cryptography;
using static MediaBrowser.Common.Cryptography.Constants;
using static MediaBrowser.Model.Cryptography.Constants;
namespace Emby.Server.Implementations.Cryptography
{
@@ -12,10 +14,7 @@ namespace Emby.Server.Implementations.Cryptography
/// </summary>
public class CryptographyProvider : ICryptoProvider
{
// FIXME: When we get DotNet Standard 2.1 we need to revisit how we do the crypto
// Currently supported hash methods from https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.cryptoconfig?view=netcore-2.1
// there might be a better way to autogenerate this list as dotnet updates, but I couldn't find one
// Please note the default method of PBKDF2 is not included, it cannot be used to generate hashes cleanly as it is actually a pbkdf with sha1
// TODO: remove when not needed for backwards compat
private static readonly HashSet<string> _supportedHashMethods = new HashSet<string>()
{
"MD5",
@@ -35,60 +34,81 @@ namespace Emby.Server.Implementations.Cryptography
};
/// <inheritdoc />
public string DefaultHashMethod => "PBKDF2";
public string DefaultHashMethod => "PBKDF2-SHA512";
/// <inheritdoc />
public IEnumerable<string> GetSupportedHashMethods()
=> _supportedHashMethods;
private byte[] PBKDF2(string method, byte[] bytes, byte[] salt, int iterations)
public PasswordHash CreatePasswordHash(ReadOnlySpan<char> password)
{
// downgrading for now as we need this library to be dotnetstandard compliant
// with this downgrade we'll add a check to make sure we're on the downgrade method at the moment
if (method != DefaultHashMethod)
{
throw new CryptographicException($"Cannot currently use PBKDF2 with requested hash method: {method}");
}
using var r = new Rfc2898DeriveBytes(bytes, salt, iterations);
return r.GetBytes(32);
byte[] salt = GenerateSalt();
return new PasswordHash(
DefaultHashMethod,
Rfc2898DeriveBytes.Pbkdf2(
password,
salt,
DefaultIterations,
HashAlgorithmName.SHA512,
DefaultOutputLength),
salt,
new Dictionary<string, string>
{
{ "iterations", DefaultIterations.ToString(CultureInfo.InvariantCulture) }
});
}
/// <inheritdoc />
public byte[] ComputeHash(string hashMethod, byte[] bytes, byte[] salt)
public bool Verify(PasswordHash hash, ReadOnlySpan<char> password)
{
if (hashMethod == DefaultHashMethod)
if (string.Equals(hash.Id, "PBKDF2", StringComparison.Ordinal))
{
return PBKDF2(hashMethod, bytes, salt, DefaultIterations);
return hash.Hash.SequenceEqual(
Rfc2898DeriveBytes.Pbkdf2(
password,
hash.Salt,
int.Parse(hash.Parameters["iterations"], CultureInfo.InvariantCulture),
HashAlgorithmName.SHA1,
32));
}
if (!_supportedHashMethods.Contains(hashMethod))
if (string.Equals(hash.Id, "PBKDF2-SHA512", StringComparison.Ordinal))
{
throw new CryptographicException($"Requested hash method is not supported: {hashMethod}");
return hash.Hash.SequenceEqual(
Rfc2898DeriveBytes.Pbkdf2(
password,
hash.Salt,
int.Parse(hash.Parameters["iterations"], CultureInfo.InvariantCulture),
HashAlgorithmName.SHA512,
DefaultOutputLength));
}
using var h = HashAlgorithm.Create(hashMethod) ?? throw new ResourceNotFoundException($"Unknown hash method: {hashMethod}.");
if (salt.Length == 0)
if (!_supportedHashMethods.Contains(hash.Id))
{
return h.ComputeHash(bytes);
throw new CryptographicException($"Requested hash method is not supported: {hash.Id}");
}
byte[] salted = new byte[bytes.Length + salt.Length];
using var h = HashAlgorithm.Create(hash.Id) ?? throw new ResourceNotFoundException($"Unknown hash method: {hash.Id}.");
var bytes = Encoding.UTF8.GetBytes(password.ToArray());
if (hash.Salt.Length == 0)
{
return hash.Hash.SequenceEqual(h.ComputeHash(bytes));
}
byte[] salted = new byte[bytes.Length + hash.Salt.Length];
Array.Copy(bytes, salted, bytes.Length);
Array.Copy(salt, 0, salted, bytes.Length, salt.Length);
return h.ComputeHash(salted);
hash.Salt.CopyTo(salted.AsSpan(bytes.Length));
return hash.Hash.SequenceEqual(h.ComputeHash(salted));
}
/// <inheritdoc />
public byte[] ComputeHashWithDefaultMethod(byte[] bytes, byte[] salt)
=> PBKDF2(DefaultHashMethod, bytes, salt, DefaultIterations);
/// <inheritdoc />
public byte[] GenerateSalt()
=> GenerateSalt(DefaultSaltLength);
/// <inheritdoc />
public byte[] GenerateSalt(int length)
=> RandomNumberGenerator.GetBytes(length);
{
var salt = new byte[length];
using var rng = RandomNumberGenerator.Create();
rng.GetNonZeroBytes(salt);
return salt;
}
}
}

View File

@@ -4,8 +4,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Jellyfin.Extensions;
using Microsoft.Extensions.Logging;
using SQLitePCL.pretty;
@@ -160,21 +160,22 @@ namespace Emby.Server.Implementations.Data
protected bool TableExists(ManagedConnection connection, string name)
{
return connection.RunInTransaction(
db =>
{
using (var statement = PrepareStatement(db, "select DISTINCT tbl_name from sqlite_master"))
db =>
{
foreach (var row in statement.ExecuteQuery())
using (var statement = PrepareStatement(db, "select DISTINCT tbl_name from sqlite_master"))
{
if (string.Equals(name, row.GetString(0), StringComparison.OrdinalIgnoreCase))
foreach (var row in statement.ExecuteQuery())
{
return true;
if (string.Equals(name, row.GetString(0), StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
}
}
return false;
}, ReadTransactionMode);
return false;
},
ReadTransactionMode);
}
protected List<string> GetColumnNames(IDatabaseConnection connection, string table)
@@ -194,7 +195,7 @@ namespace Emby.Server.Implementations.Data
protected void AddColumn(IDatabaseConnection connection, string table, string columnName, string type, List<string> existingColumnNames)
{
if (existingColumnNames.Contains(columnName, StringComparer.OrdinalIgnoreCase))
if (existingColumnNames.Contains(columnName, StringComparison.OrdinalIgnoreCase))
{
return;
}

View File

@@ -7,7 +7,7 @@ using SQLitePCL.pretty;
namespace Emby.Server.Implementations.Data
{
public class ManagedConnection : IDisposable
public sealed class ManagedConnection : IDisposable
{
private readonly SemaphoreSlim _writeLock;

File diff suppressed because it is too large Load Diff

View File

@@ -26,9 +26,6 @@ namespace Emby.Server.Implementations.Data
DbFilePath = Path.Combine(appPaths.DataPath, "library.db");
}
/// <inheritdoc />
public string Name => "SQLite";
/// <summary>
/// Opens the connection to the database.
/// </summary>
@@ -50,41 +47,42 @@ namespace Emby.Server.Implementations.Data
var users = userDatasTableExists ? null : userManager.Users;
connection.RunInTransaction(
db =>
{
db.ExecuteAll(string.Join(';', new[]
db =>
{
"create table if not exists UserDatas (key nvarchar not null, userId INT not null, rating float null, played bit not null, playCount int not null, isFavorite bit not null, playbackPositionTicks bigint not null, lastPlayedDate datetime null, AudioStreamIndex INT, SubtitleStreamIndex INT)",
"drop index if exists idx_userdata",
"drop index if exists idx_userdata1",
"drop index if exists idx_userdata2",
"drop index if exists userdataindex1",
"drop index if exists userdataindex",
"drop index if exists userdataindex3",
"drop index if exists userdataindex4",
"create unique index if not exists UserDatasIndex1 on UserDatas (key, userId)",
"create index if not exists UserDatasIndex2 on UserDatas (key, userId, played)",
"create index if not exists UserDatasIndex3 on UserDatas (key, userId, playbackPositionTicks)",
"create index if not exists UserDatasIndex4 on UserDatas (key, userId, isFavorite)"
}));
if (userDataTableExists)
{
var existingColumnNames = GetColumnNames(db, "userdata");
AddColumn(db, "userdata", "InternalUserId", "int", existingColumnNames);
AddColumn(db, "userdata", "AudioStreamIndex", "int", existingColumnNames);
AddColumn(db, "userdata", "SubtitleStreamIndex", "int", existingColumnNames);
if (!userDatasTableExists)
db.ExecuteAll(string.Join(';', new[]
{
ImportUserIds(db, users);
"create table if not exists UserDatas (key nvarchar not null, userId INT not null, rating float null, played bit not null, playCount int not null, isFavorite bit not null, playbackPositionTicks bigint not null, lastPlayedDate datetime null, AudioStreamIndex INT, SubtitleStreamIndex INT)",
db.ExecuteAll("INSERT INTO UserDatas (key, userId, rating, played, playCount, isFavorite, playbackPositionTicks, lastPlayedDate, AudioStreamIndex, SubtitleStreamIndex) SELECT key, InternalUserId, rating, played, playCount, isFavorite, playbackPositionTicks, lastPlayedDate, AudioStreamIndex, SubtitleStreamIndex from userdata where InternalUserId not null");
"drop index if exists idx_userdata",
"drop index if exists idx_userdata1",
"drop index if exists idx_userdata2",
"drop index if exists userdataindex1",
"drop index if exists userdataindex",
"drop index if exists userdataindex3",
"drop index if exists userdataindex4",
"create unique index if not exists UserDatasIndex1 on UserDatas (key, userId)",
"create index if not exists UserDatasIndex2 on UserDatas (key, userId, played)",
"create index if not exists UserDatasIndex3 on UserDatas (key, userId, playbackPositionTicks)",
"create index if not exists UserDatasIndex4 on UserDatas (key, userId, isFavorite)"
}));
if (userDataTableExists)
{
var existingColumnNames = GetColumnNames(db, "userdata");
AddColumn(db, "userdata", "InternalUserId", "int", existingColumnNames);
AddColumn(db, "userdata", "AudioStreamIndex", "int", existingColumnNames);
AddColumn(db, "userdata", "SubtitleStreamIndex", "int", existingColumnNames);
if (!userDatasTableExists)
{
ImportUserIds(db, users);
db.ExecuteAll("INSERT INTO UserDatas (key, userId, rating, played, playCount, isFavorite, playbackPositionTicks, lastPlayedDate, AudioStreamIndex, SubtitleStreamIndex) SELECT key, InternalUserId, rating, played, playCount, isFavorite, playbackPositionTicks, lastPlayedDate, AudioStreamIndex, SubtitleStreamIndex from userdata where InternalUserId not null");
}
}
}
}, TransactionMode);
},
TransactionMode);
}
}
@@ -101,7 +99,7 @@ namespace Emby.Server.Implementations.Data
continue;
}
statement.TryBind("@UserId", user.Id.ToByteArray());
statement.TryBind("@UserId", user.Id);
statement.TryBind("@InternalUserId", user.InternalId);
statement.MoveNext();
@@ -183,10 +181,11 @@ namespace Emby.Server.Implementations.Data
using (var connection = GetConnection())
{
connection.RunInTransaction(
db =>
{
SaveUserData(db, internalUserId, key, userData);
}, TransactionMode);
db =>
{
SaveUserData(db, internalUserId, key, userData);
},
TransactionMode);
}
}
@@ -252,13 +251,14 @@ namespace Emby.Server.Implementations.Data
using (var connection = GetConnection())
{
connection.RunInTransaction(
db =>
{
foreach (var userItemData in userDataList)
db =>
{
SaveUserData(db, internalUserId, userItemData.Key, userItemData);
}
}, TransactionMode);
foreach (var userItemData in userDataList)
{
SaveUserData(db, internalUserId, userItemData.Key, userItemData);
}
},
TransactionMode);
}
}
@@ -387,6 +387,7 @@ namespace Emby.Server.Implementations.Data
return userData;
}
#pragma warning disable CA2215
/// <inheritdoc/>
/// <remarks>
/// There is nothing to dispose here since <see cref="BaseSqliteRepository.WriteLock"/> and
@@ -395,6 +396,10 @@ namespace Emby.Server.Implementations.Data
/// </remarks>
protected override void Dispose(bool dispose)
{
// The write lock and connection for the item repository are shared with the user data repository
// since they point to the same database. The item repo has responsibility for disposing these two objects,
// so the user data repo should not attempt to dispose them as well
}
#pragma warning restore CA2215
}
}

View File

@@ -37,7 +37,7 @@ namespace Emby.Server.Implementations.Devices
{
var value = File.ReadAllText(CachePath, Encoding.UTF8);
if (Guid.TryParse(value, out var guid))
if (Guid.TryParse(value, out _))
{
return value;
}

View File

@@ -7,9 +7,9 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
using MediaBrowser.Common;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Drawing;
@@ -21,7 +21,6 @@ using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Playlists;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
@@ -109,7 +108,7 @@ namespace Emby.Server.Implementations.Dto
}
});
SetItemByNameInfo(item, dto, libraryItems, user);
SetItemByNameInfo(item, dto, libraryItems);
}
}
@@ -153,8 +152,7 @@ namespace Emby.Server.Implementations.Dto
new DtoOptions(false)
{
EnableImages = false
}),
user);
}));
}
return dto;
@@ -294,7 +292,7 @@ namespace Emby.Server.Implementations.Dto
path = path.TrimStart('.');
}
if (!string.IsNullOrEmpty(path) && containers.Contains(path, StringComparer.OrdinalIgnoreCase))
if (!string.IsNullOrEmpty(path) && containers.Contains(path, StringComparison.OrdinalIgnoreCase))
{
fileExtensionContainer = path;
}
@@ -311,13 +309,13 @@ namespace Emby.Server.Implementations.Dto
if (taggedItems != null && options.ContainsField(ItemFields.ItemCounts))
{
SetItemByNameInfo(item, dto, taggedItems, user);
SetItemByNameInfo(item, dto, taggedItems);
}
return dto;
}
private static void SetItemByNameInfo(BaseItem item, BaseItemDto dto, IList<BaseItem> taggedItems, User user = null)
private static void SetItemByNameInfo(BaseItem item, BaseItemDto dto, IList<BaseItem> taggedItems)
{
if (item is MusicArtist)
{
@@ -370,6 +368,12 @@ namespace Emby.Server.Implementations.Dto
if (item is MusicAlbum || item is Season || item is Playlist)
{
dto.ChildCount = dto.RecursiveItemCount;
var folderChildCount = folder.LinkedChildren.Length;
// The default is an empty array, so we can't reliably use the count when it's empty
if (folderChildCount > 0)
{
dto.ChildCount ??= folderChildCount;
}
}
if (options.ContainsField(ItemFields.ChildCount))
@@ -453,18 +457,13 @@ namespace Emby.Server.Implementations.Dto
}
}
private string GetDtoId(BaseItem item)
{
return item.Id.ToString("N", CultureInfo.InvariantCulture);
}
private void SetMusicVideoProperties(BaseItemDto dto, MusicVideo item)
{
if (!string.IsNullOrEmpty(item.Album))
{
var parentAlbumIds = _libraryManager.GetItemIds(new InternalItemsQuery
{
IncludeItemTypes = new[] { nameof(MusicAlbum) },
IncludeItemTypes = new[] { BaseItemKind.MusicAlbum },
Name = item.Album,
Limit = 1
});
@@ -579,7 +578,7 @@ namespace Emby.Server.Implementations.Dto
if (dictionary.TryGetValue(person.Name, out Person entity))
{
baseItemPerson.PrimaryImageTag = GetTagAndFillBlurhash(dto, entity, ImageType.Primary);
baseItemPerson.Id = entity.Id.ToString("N", CultureInfo.InvariantCulture);
baseItemPerson.Id = entity.Id;
if (dto.ImageBlurHashes != null)
{
// Only add BlurHash for the person's image.
@@ -738,8 +737,7 @@ namespace Emby.Server.Implementations.Dto
dto.Tags = item.Tags;
}
var hasAspectRatio = item as IHasAspectRatio;
if (hasAspectRatio != null)
if (item is IHasAspectRatio hasAspectRatio)
{
dto.AspectRatio = hasAspectRatio.AspectRatio;
}
@@ -889,15 +887,13 @@ namespace Emby.Server.Implementations.Dto
dto.CommunityRating = item.CommunityRating;
}
var supportsPlaceHolders = item as ISupportsPlaceHolders;
if (supportsPlaceHolders != null && supportsPlaceHolders.IsPlaceHolder)
if (item is ISupportsPlaceHolders supportsPlaceHolders && supportsPlaceHolders.IsPlaceHolder)
{
dto.IsPlaceHolder = supportsPlaceHolders.IsPlaceHolder;
}
// Add audio info
var audio = item as Audio;
if (audio != null)
if (item is Audio audio)
{
dto.Album = audio.Album;
if (audio.ExtraType.HasValue)
@@ -970,8 +966,7 @@ namespace Emby.Server.Implementations.Dto
}).Where(i => i != null).ToArray();
}
var hasAlbumArtist = item as IHasAlbumArtist;
if (hasAlbumArtist != null)
if (item is IHasAlbumArtist hasAlbumArtist)
{
dto.AlbumArtist = hasAlbumArtist.AlbumArtists.FirstOrDefault();
@@ -1097,12 +1092,13 @@ namespace Emby.Server.Implementations.Dto
if (options.ContainsField(ItemFields.LocalTrailerCount))
{
allExtras ??= item.GetExtras().ToArray();
dto.LocalTrailerCount = allExtras.Count(i => i.ExtraType == ExtraType.Trailer);
if (item is IHasTrailers hasTrailers)
{
dto.LocalTrailerCount += hasTrailers.GetTrailerCount();
dto.LocalTrailerCount = hasTrailers.LocalTrailers.Count;
}
else
{
dto.LocalTrailerCount = (allExtras ?? item.GetExtras()).Count(i => i.ExtraType == ExtraType.Trailer);
}
}
@@ -1312,35 +1308,35 @@ namespace Emby.Server.Implementations.Dto
var allImages = parent.ImageInfos;
if (logoLimit > 0 && !(imageTags != null && imageTags.ContainsKey(ImageType.Logo)) && dto.ParentLogoItemId == null)
if (logoLimit > 0 && !(imageTags != null && imageTags.ContainsKey(ImageType.Logo)) && dto.ParentLogoItemId is null)
{
var image = allImages.FirstOrDefault(i => i.Type == ImageType.Logo);
if (image != null)
{
dto.ParentLogoItemId = GetDtoId(parent);
dto.ParentLogoItemId = parent.Id;
dto.ParentLogoImageTag = GetTagAndFillBlurhash(dto, parent, image);
}
}
if (artLimit > 0 && !(imageTags != null && imageTags.ContainsKey(ImageType.Art)) && dto.ParentArtItemId == null)
if (artLimit > 0 && !(imageTags != null && imageTags.ContainsKey(ImageType.Art)) && dto.ParentArtItemId is null)
{
var image = allImages.FirstOrDefault(i => i.Type == ImageType.Art);
if (image != null)
{
dto.ParentArtItemId = GetDtoId(parent);
dto.ParentArtItemId = parent.Id;
dto.ParentArtImageTag = GetTagAndFillBlurhash(dto, parent, image);
}
}
if (thumbLimit > 0 && !(imageTags != null && imageTags.ContainsKey(ImageType.Thumb)) && (dto.ParentThumbItemId == null || parent is Series) && parent is not ICollectionFolder && parent is not UserView)
if (thumbLimit > 0 && !(imageTags != null && imageTags.ContainsKey(ImageType.Thumb)) && (dto.ParentThumbItemId is null || parent is Series) && parent is not ICollectionFolder && parent is not UserView)
{
var image = allImages.FirstOrDefault(i => i.Type == ImageType.Thumb);
if (image != null)
{
dto.ParentThumbItemId = GetDtoId(parent);
dto.ParentThumbItemId = parent.Id;
dto.ParentThumbImageTag = GetTagAndFillBlurhash(dto, parent, image);
}
}
@@ -1351,7 +1347,7 @@ namespace Emby.Server.Implementations.Dto
if (images.Count > 0)
{
dto.ParentBackdropItemId = GetDtoId(parent);
dto.ParentBackdropItemId = parent.Id;
dto.ParentBackdropImageTags = GetTagsAndFillBlurhashes(dto, parent, ImageType.Backdrop, images);
}
}
@@ -1398,44 +1394,27 @@ namespace Emby.Server.Implementations.Dto
return null;
}
ImageDimensions size;
var defaultAspectRatio = item.GetDefaultPrimaryImageAspectRatio();
if (defaultAspectRatio > 0)
{
return defaultAspectRatio;
}
if (!imageInfo.IsLocalFile)
{
return null;
return item.GetDefaultPrimaryImageAspectRatio();
}
try
{
size = _imageProcessor.GetImageDimensions(item, imageInfo);
if (size.Width <= 0 || size.Height <= 0)
var size = _imageProcessor.GetImageDimensions(item, imageInfo);
var width = size.Width;
var height = size.Height;
if (width > 0 && height > 0)
{
return null;
return (double)width / height;
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to determine primary image aspect ratio for {0}", imageInfo.Path);
return null;
_logger.LogError(ex, "Failed to determine primary image aspect ratio for {ImagePath}", imageInfo.Path);
}
var width = size.Width;
var height = size.Height;
if (width <= 0 || height <= 0)
{
return null;
}
return (double)width / height;
return item.GetDefaultPrimaryImageAspectRatio();
}
}
}

View File

@@ -24,15 +24,15 @@
<ItemGroup>
<PackageReference Include="DiscUtils.Udf" Version="0.16.13" />
<PackageReference Include="Jellyfin.XmlTv" Version="10.6.2" />
<PackageReference Include="Jellyfin.XmlTv" Version="10.8.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.0" />
<PackageReference Include="Mono.Nat" Version="3.0.2" />
<PackageReference Include="prometheus-net.DotNetRuntime" Version="4.2.2" />
<PackageReference Include="sharpcompress" Version="0.30.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.8" />
<PackageReference Include="Mono.Nat" Version="3.0.3" />
<PackageReference Include="prometheus-net.DotNetRuntime" Version="4.2.4" />
<PackageReference Include="sharpcompress" Version="0.32.2" />
<PackageReference Include="SQLitePCL.pretty.netstandard" Version="3.1.0" />
<PackageReference Include="DotNet.Glob" Version="3.1.3" />
</ItemGroup>
@@ -49,10 +49,18 @@
<NoWarn>AD0001</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.406" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>

View File

@@ -13,7 +13,6 @@ using Jellyfin.Networking.Configuration;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Model.Dlna;
using Microsoft.Extensions.Logging;
using Mono.Nat;
@@ -27,7 +26,6 @@ namespace Emby.Server.Implementations.EntryPoints
private readonly IServerApplicationHost _appHost;
private readonly ILogger<ExternalPortForwarding> _logger;
private readonly IServerConfigurationManager _config;
private readonly IDeviceDiscovery _deviceDiscovery;
private readonly ConcurrentDictionary<IPEndPoint, byte> _createdRules = new ConcurrentDictionary<IPEndPoint, byte>();
@@ -42,17 +40,14 @@ namespace Emby.Server.Implementations.EntryPoints
/// <param name="logger">The logger.</param>
/// <param name="appHost">The application host.</param>
/// <param name="config">The configuration manager.</param>
/// <param name="deviceDiscovery">The device discovery.</param>
public ExternalPortForwarding(
ILogger<ExternalPortForwarding> logger,
IServerApplicationHost appHost,
IServerConfigurationManager config,
IDeviceDiscovery deviceDiscovery)
IServerConfigurationManager config)
{
_logger = logger;
_appHost = appHost;
_config = config;
_deviceDiscovery = deviceDiscovery;
}
private string GetConfigIdentifier()

View File

@@ -101,7 +101,7 @@ namespace Emby.Server.Implementations.EntryPoints
}
}
_lastProgressMessageTimes.AddOrUpdate(item.Id, key => DateTime.UtcNow, (key, existing) => DateTime.UtcNow);
_lastProgressMessageTimes.AddOrUpdate(item.Id, _ => DateTime.UtcNow, (_, _) => DateTime.UtcNow);
var dict = new Dictionary<string, string>();
dict["ItemId"] = item.Id.ToString("N", CultureInfo.InvariantCulture);
@@ -144,7 +144,7 @@ namespace Emby.Server.Implementations.EntryPoints
{
OnProviderRefreshProgress(sender, new GenericEventArgs<Tuple<BaseItem, double>>(new Tuple<BaseItem, double>(e.Argument, 100)));
_lastProgressMessageTimes.TryRemove(e.Argument.Id, out DateTime removed);
_lastProgressMessageTimes.TryRemove(e.Argument.Id, out _);
}
private static bool EnableRefreshMessage(BaseItem item)
@@ -326,7 +326,7 @@ namespace Emby.Server.Implementations.EntryPoints
{
var userIds = _sessionManager.Sessions
.Select(i => i.UserId)
.Where(i => !i.Equals(Guid.Empty))
.Where(i => !i.Equals(default))
.Distinct()
.ToArray();
@@ -423,7 +423,6 @@ namespace Emby.Server.Implementations.EntryPoints
continue;
}
var collectionFolders = _libraryManager.GetCollectionFolders(item, allUserRootChildren);
foreach (var folder in allUserRootChildren)
{
list.Add(folder.Id.ToString("N", CultureInfo.InvariantCulture));
@@ -465,6 +464,7 @@ namespace Emby.Server.Implementations.EntryPoints
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>

View File

@@ -3,6 +3,8 @@ using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using Emby.Server.Implementations.Udp;
using Jellyfin.Networking.Configuration;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Plugins;
using Microsoft.Extensions.Configuration;
@@ -26,6 +28,7 @@ namespace Emby.Server.Implementations.EntryPoints
private readonly ILogger<UdpServerEntryPoint> _logger;
private readonly IServerApplicationHost _appHost;
private readonly IConfiguration _config;
private readonly IConfigurationManager _configurationManager;
/// <summary>
/// The UDP server.
@@ -40,14 +43,17 @@ namespace Emby.Server.Implementations.EntryPoints
/// <param name="logger">Instance of the <see cref="ILogger{UdpServerEntryPoint}"/> interface.</param>
/// <param name="appHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
/// <param name="configuration">Instance of the <see cref="IConfiguration"/> interface.</param>
/// <param name="configurationManager">Instance of the <see cref="IConfigurationManager"/> interface.</param>
public UdpServerEntryPoint(
ILogger<UdpServerEntryPoint> logger,
IServerApplicationHost appHost,
IConfiguration configuration)
IConfiguration configuration,
IConfigurationManager configurationManager)
{
_logger = logger;
_appHost = appHost;
_config = configuration;
_configurationManager = configurationManager;
}
/// <inheritdoc />
@@ -55,6 +61,11 @@ namespace Emby.Server.Implementations.EntryPoints
{
CheckDisposed();
if (!_configurationManager.GetNetworkConfiguration().AutoDiscovery)
{
return Task.CompletedTask;
}
try
{
_udpServer = new UdpServer(_logger, _appHost, _config, PortNumber);

View File

@@ -95,7 +95,7 @@ namespace Emby.Server.Implementations.EntryPoints
var changes = _changedItems.ToList();
_changedItems.Clear();
var task = SendNotifications(changes, CancellationToken.None);
SendNotifications(changes, CancellationToken.None).GetAwaiter().GetResult();
if (_updateTimer != null)
{

View File

@@ -2,7 +2,6 @@
using System.Threading.Tasks;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Authentication;
using MediaBrowser.Controller.Net;
using Microsoft.AspNetCore.Http;

View File

@@ -47,7 +47,9 @@ namespace Emby.Server.Implementations.HttpServer.Security
{
var session = await GetSession(requestContext).ConfigureAwait(false);
return session == null || session.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(session.UserId);
return session.UserId.Equals(default)
? null
: _userManager.GetUserById(session.UserId);
}
public Task<User?> GetUser(object requestContext)

View File

@@ -19,7 +19,7 @@ namespace Emby.Server.Implementations.HttpServer
/// <summary>
/// Class WebSocketConnection.
/// </summary>
public class WebSocketConnection : IWebSocketConnection, IDisposable
public class WebSocketConnection : IWebSocketConnection
{
/// <summary>
/// The logger.
@@ -36,23 +36,22 @@ namespace Emby.Server.Implementations.HttpServer
/// </summary>
private readonly WebSocket _socket;
private bool _disposed = false;
/// <summary>
/// Initializes a new instance of the <see cref="WebSocketConnection" /> class.
/// </summary>
/// <param name="logger">The logger.</param>
/// <param name="socket">The socket.</param>
/// <param name="remoteEndPoint">The remote end point.</param>
/// <param name="query">The query.</param>
public WebSocketConnection(
ILogger<WebSocketConnection> logger,
WebSocket socket,
IPAddress? remoteEndPoint,
IQueryCollection query)
IPAddress? remoteEndPoint)
{
_logger = logger;
_socket = socket;
RemoteEndPoint = remoteEndPoint;
QueryString = query;
_jsonOptions = JsonDefaults.Options;
LastActivityDate = DateTime.Now;
@@ -81,12 +80,6 @@ namespace Emby.Server.Implementations.HttpServer
/// <inheritdoc />
public DateTime LastKeepAliveDate { get; set; }
/// <summary>
/// Gets the query string.
/// </summary>
/// <value>The query string.</value>
public IQueryCollection QueryString { get; }
/// <summary>
/// Gets the state.
/// </summary>
@@ -180,7 +173,7 @@ namespace Emby.Server.Implementations.HttpServer
}
WebSocketMessage<object>? stub;
long bytesConsumed = 0;
long bytesConsumed;
try
{
stub = DeserializeWebSocketMessage(buffer, out bytesConsumed);
@@ -236,7 +229,8 @@ namespace Emby.Server.Implementations.HttpServer
{
MessageId = Guid.NewGuid(),
MessageType = SessionMessageType.KeepAlive
}, CancellationToken.None);
},
CancellationToken.None);
}
/// <inheritdoc />
@@ -252,10 +246,39 @@ namespace Emby.Server.Implementations.HttpServer
/// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose(bool dispose)
{
if (_disposed)
{
return;
}
if (dispose)
{
_socket.Dispose();
}
_disposed = true;
}
/// <inheritdoc />
public async ValueTask DisposeAsync()
{
await DisposeAsyncCore().ConfigureAwait(false);
Dispose(false);
GC.SuppressFinalize(this);
}
/// <summary>
/// Used to perform asynchronous cleanup of managed resources or for cascading calls to <see cref="DisposeAsync"/>.
/// </summary>
/// <returns>A ValueTask.</returns>
protected virtual async ValueTask DisposeAsyncCore()
{
if (_socket.State == WebSocketState.Open)
{
await _socket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "System Shutdown", CancellationToken.None).ConfigureAwait(false);
}
_socket.Dispose();
}
}
}

View File

@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Net.WebSockets;
using System.Threading.Tasks;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Net;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
@@ -50,8 +51,7 @@ namespace Emby.Server.Implementations.HttpServer
using var connection = new WebSocketConnection(
_loggerFactory.CreateLogger<WebSocketConnection>(),
webSocket,
context.Connection.RemoteIpAddress,
context.Request.Query)
context.GetNormalizedRemoteIp())
{
OnReceive = ProcessWebSocketMessageReceived
};
@@ -59,7 +59,7 @@ namespace Emby.Server.Implementations.HttpServer
var tasks = new Task[_webSocketListeners.Length];
for (var i = 0; i < _webSocketListeners.Length; ++i)
{
tasks[i] = _webSocketListeners[i].ProcessWebSocketConnectedAsync(connection);
tasks[i] = _webSocketListeners[i].ProcessWebSocketConnectedAsync(connection, context);
}
await Task.WhenAll(tasks).ConfigureAwait(false);

View File

@@ -1,5 +1,3 @@
#nullable disable
#pragma warning disable CS1591
using System;
@@ -14,7 +12,7 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.IO
{
public class FileRefresher : IDisposable
public sealed class FileRefresher : IDisposable
{
private readonly ILogger _logger;
private readonly ILibraryManager _libraryManager;
@@ -22,7 +20,7 @@ namespace Emby.Server.Implementations.IO
private readonly List<string> _affectedPaths = new List<string>();
private readonly object _timerLock = new object();
private Timer _timer;
private Timer? _timer;
private bool _disposed;
public FileRefresher(string path, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, ILogger logger)
@@ -36,7 +34,7 @@ namespace Emby.Server.Implementations.IO
AddPath(path);
}
public event EventHandler<EventArgs> Completed;
public event EventHandler<EventArgs>? Completed;
public string Path { get; private set; }
@@ -111,7 +109,7 @@ namespace Emby.Server.Implementations.IO
RestartTimer();
}
private void OnTimerCallback(object state)
private void OnTimerCallback(object? state)
{
List<string> paths;
@@ -127,7 +125,7 @@ namespace Emby.Server.Implementations.IO
try
{
ProcessPathChanges(paths.ToList());
ProcessPathChanges(paths);
}
catch (Exception ex)
{
@@ -137,12 +135,12 @@ namespace Emby.Server.Implementations.IO
private void ProcessPathChanges(List<string> paths)
{
var itemsToRefresh = paths
IEnumerable<BaseItem> itemsToRefresh = paths
.Distinct(StringComparer.OrdinalIgnoreCase)
.Select(GetAffectedBaseItem)
.Where(item => item != null)
.GroupBy(x => x.Id)
.Select(x => x.First());
.GroupBy(x => x!.Id) // Removed null values in the previous .Where()
.Select(x => x.First())!;
foreach (var item in itemsToRefresh)
{
@@ -176,15 +174,15 @@ namespace Emby.Server.Implementations.IO
/// </summary>
/// <param name="path">The path.</param>
/// <returns>BaseItem.</returns>
private BaseItem GetAffectedBaseItem(string path)
private BaseItem? GetAffectedBaseItem(string path)
{
BaseItem item = null;
BaseItem? item = null;
while (item == null && !string.IsNullOrEmpty(path))
{
item = _libraryManager.FindByPath(path, null);
path = System.IO.Path.GetDirectoryName(path);
path = System.IO.Path.GetDirectoryName(path) ?? string.Empty;
}
if (item != null)
@@ -219,8 +217,13 @@ namespace Emby.Server.Implementations.IO
/// <inheritdoc />
public void Dispose()
{
_disposed = true;
if (_disposed)
{
return;
}
DisposeTimer();
_disposed = true;
GC.SuppressFinalize(this);
}
}

View File

@@ -99,7 +99,7 @@ namespace Emby.Server.Implementations.IO
// But if we make this delay too high, we risk missing legitimate changes, such as user adding a new file, or hand-editing metadata
await Task.Delay(45000).ConfigureAwait(false);
_tempIgnoredPaths.TryRemove(path, out var val);
_tempIgnoredPaths.TryRemove(path, out _);
if (refreshPath)
{
@@ -449,12 +449,12 @@ namespace Emby.Server.Implementations.IO
}
var newRefresher = new FileRefresher(path, _configurationManager, _libraryManager, _logger);
newRefresher.Completed += NewRefresher_Completed;
newRefresher.Completed += OnNewRefresherCompleted;
_activeRefreshers.Add(newRefresher);
}
}
private void NewRefresher_Completed(object sender, EventArgs e)
private void OnNewRefresherCompleted(object sender, EventArgs e)
{
var refresher = (FileRefresher)sender;
DisposeRefresher(refresher);
@@ -481,6 +481,7 @@ namespace Emby.Server.Implementations.IO
{
lock (_activeRefreshers)
{
refresher.Completed -= OnNewRefresherCompleted;
refresher.Dispose();
_activeRefreshers.Remove(refresher);
}
@@ -492,6 +493,7 @@ namespace Emby.Server.Implementations.IO
{
foreach (var refresher in _activeRefreshers.ToList())
{
refresher.Completed -= OnNewRefresherCompleted;
refresher.Dispose();
}

View File

@@ -262,6 +262,10 @@ namespace Emby.Server.Implementations.IO
_logger.LogError(ex, "Reading the file size of the symlink at {Path} failed. Marking the file as not existing.", fileInfo.FullName);
result.Exists = false;
}
catch (UnauthorizedAccessException ex)
{
_logger.LogError(ex, "Reading the file at {Path} failed due to a permissions exception.", fileInfo.FullName);
}
}
}
@@ -544,16 +548,6 @@ namespace Emby.Server.Implementations.IO
/// <inheritdoc />
public virtual bool AreEqual(string path1, string path2)
{
if (path1 == null && path2 == null)
{
return true;
}
if (path1 == null || path2 == null)
{
return false;
}
return string.Equals(
NormalizePath(path1),
NormalizePath(path2),
@@ -591,7 +585,7 @@ namespace Emby.Server.Implementations.IO
}
/// <inheritdoc />
public virtual List<FileSystemMetadata> GetDrives()
public virtual IEnumerable<FileSystemMetadata> GetDrives()
{
// check for ready state to avoid waiting for drives to timeout
// some drives on linux have no actual size or are used for other purposes
@@ -605,7 +599,7 @@ namespace Emby.Server.Implementations.IO
Name = d.Name,
FullName = d.RootDirectory.FullName,
IsDirectory = true
}).ToList();
});
}
/// <inheritdoc />
@@ -714,6 +708,18 @@ namespace Emby.Server.Implementations.IO
return Directory.EnumerateFileSystemEntries(path, "*", GetEnumerationOptions(recursive));
}
/// <inheritdoc />
public virtual bool DirectoryExists(string path)
{
return Directory.Exists(path);
}
/// <inheritdoc />
public virtual bool FileExists(string path)
{
return File.Exists(path);
}
private EnumerationOptions GetEnumerationOptions(bool recursive)
{
return new EnumerationOptions

View File

@@ -17,11 +17,11 @@ namespace Emby.Server.Implementations.IO
try
{
int read;
while ((read = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0)
while ((read = await source.ReadAsync(buffer, cancellationToken).ConfigureAwait(false)) != 0)
{
cancellationToken.ThrowIfCancellationRequested();
await destination.WriteAsync(buffer, 0, read, cancellationToken).ConfigureAwait(false);
await destination.WriteAsync(buffer.AsMemory(0, read), cancellationToken).ConfigureAwait(false);
if (onStarted != null)
{
@@ -44,11 +44,11 @@ namespace Emby.Server.Implementations.IO
if (emptyReadLimit <= 0)
{
int read;
while ((read = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0)
while ((read = await source.ReadAsync(buffer, cancellationToken).ConfigureAwait(false)) != 0)
{
cancellationToken.ThrowIfCancellationRequested();
await destination.WriteAsync(buffer, 0, read, cancellationToken).ConfigureAwait(false);
await destination.WriteAsync(buffer.AsMemory(0, read), cancellationToken).ConfigureAwait(false);
}
return;
@@ -60,7 +60,7 @@ namespace Emby.Server.Implementations.IO
{
cancellationToken.ThrowIfCancellationRequested();
var bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false);
var bytesRead = await source.ReadAsync(buffer, cancellationToken).ConfigureAwait(false);
if (bytesRead == 0)
{
@@ -71,7 +71,7 @@ namespace Emby.Server.Implementations.IO
{
eofCount = 0;
await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
await destination.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken).ConfigureAwait(false);
}
}
}
@@ -88,13 +88,13 @@ namespace Emby.Server.Implementations.IO
{
int bytesRead;
while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0)
while ((bytesRead = await source.ReadAsync(buffer, cancellationToken).ConfigureAwait(false)) != 0)
{
var bytesToWrite = Math.Min(bytesRead, copyLength);
if (bytesToWrite > 0)
{
await destination.WriteAsync(buffer, 0, Convert.ToInt32(bytesToWrite), cancellationToken).ConfigureAwait(false);
await destination.WriteAsync(buffer.AsMemory(0, Convert.ToInt32(bytesToWrite)), cancellationToken).ConfigureAwait(false);
}
copyLength -= bytesToWrite;
@@ -137,9 +137,9 @@ namespace Emby.Server.Implementations.IO
int bytesRead;
int totalBytesRead = 0;
while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0)
while ((bytesRead = await source.ReadAsync(buffer, cancellationToken).ConfigureAwait(false)) != 0)
{
await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
await destination.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken).ConfigureAwait(false);
totalBytesRead += bytesRead;
}

View File

@@ -135,7 +135,7 @@ namespace Emby.Server.Implementations.Images
protected virtual IEnumerable<string> GetStripCollageImagePaths(BaseItem primaryItem, IEnumerable<BaseItem> items)
{
var useBackdrop = primaryItem is CollectionFolder;
var useBackdrop = primaryItem is CollectionFolder || primaryItem is UserView;
return items
.Select(i =>
{

View File

@@ -22,7 +22,7 @@ namespace Emby.Server.Implementations.Images
{
private readonly ILibraryManager _libraryManager;
public BaseFolderImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager)
protected BaseFolderImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager)
: base(fileSystem, providerManager, applicationPaths, imageProcessor)
{
_libraryManager = libraryManager;

View File

@@ -28,35 +28,39 @@ namespace Emby.Server.Implementations.Images
var view = (CollectionFolder)item;
var viewType = view.CollectionType;
string[] includeItemTypes;
BaseItemKind[] includeItemTypes;
if (string.Equals(viewType, CollectionType.Movies, StringComparison.Ordinal))
{
includeItemTypes = new string[] { "Movie" };
includeItemTypes = new[] { BaseItemKind.Movie };
}
else if (string.Equals(viewType, CollectionType.TvShows, StringComparison.Ordinal))
{
includeItemTypes = new string[] { "Series" };
includeItemTypes = new[] { BaseItemKind.Series };
}
else if (string.Equals(viewType, CollectionType.Music, StringComparison.Ordinal))
{
includeItemTypes = new string[] { "MusicAlbum" };
includeItemTypes = new[] { BaseItemKind.MusicAlbum };
}
else if (string.Equals(viewType, CollectionType.MusicVideos, StringComparison.Ordinal))
{
includeItemTypes = new[] { BaseItemKind.MusicVideo };
}
else if (string.Equals(viewType, CollectionType.Books, StringComparison.Ordinal))
{
includeItemTypes = new string[] { "Book", "AudioBook" };
includeItemTypes = new[] { BaseItemKind.Book, BaseItemKind.AudioBook };
}
else if (string.Equals(viewType, CollectionType.BoxSets, StringComparison.Ordinal))
{
includeItemTypes = new string[] { "BoxSet" };
includeItemTypes = new[] { BaseItemKind.BoxSet };
}
else if (string.Equals(viewType, CollectionType.HomeVideos, StringComparison.Ordinal) || string.Equals(viewType, CollectionType.Photos, StringComparison.Ordinal))
{
includeItemTypes = new string[] { "Video", "Photo" };
includeItemTypes = new[] { BaseItemKind.Video, BaseItemKind.Photo };
}
else
{
includeItemTypes = new string[] { "Video", "Audio", "Photo", "Movie", "Series" };
includeItemTypes = new[] { BaseItemKind.Video, BaseItemKind.Audio, BaseItemKind.Photo, BaseItemKind.Movie, BaseItemKind.Series };
}
var recursive = !string.Equals(CollectionType.Playlists, viewType, StringComparison.OrdinalIgnoreCase);
@@ -68,9 +72,9 @@ namespace Emby.Server.Implementations.Images
DtoOptions = new DtoOptions(false),
ImageTypes = new ImageType[] { ImageType.Primary },
Limit = 8,
OrderBy = new ValueTuple<string, SortOrder>[]
OrderBy = new[]
{
new ValueTuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending)
(ItemSortBy.Random, SortOrder.Ascending)
},
IncludeItemTypes = includeItemTypes
});

View File

@@ -6,6 +6,8 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto;
@@ -34,14 +36,14 @@ namespace Emby.Server.Implementations.Images
var view = (UserView)item;
var isUsingCollectionStrip = IsUsingCollectionStrip(view);
var recursive = isUsingCollectionStrip && !new[] { CollectionType.BoxSets, CollectionType.Playlists }.Contains(view.ViewType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
var recursive = isUsingCollectionStrip && !new[] { CollectionType.BoxSets, CollectionType.Playlists }.Contains(view.ViewType ?? string.Empty, StringComparison.OrdinalIgnoreCase);
var result = view.GetItemList(new InternalItemsQuery
{
User = view.UserId.HasValue ? _userManager.GetUserById(view.UserId.Value) : null,
CollapseBoxSetItems = false,
Recursive = recursive,
ExcludeItemTypes = new[] { "UserView", "CollectionFolder", "Person" },
ExcludeItemTypes = new[] { BaseItemKind.UserView, BaseItemKind.CollectionFolder, BaseItemKind.Person },
DtoOptions = new DtoOptions(false)
});
@@ -82,16 +84,20 @@ namespace Emby.Server.Implementations.Images
}).GroupBy(x => x.Id)
.Select(x => x.First());
List<BaseItem> returnItems;
if (isUsingCollectionStrip)
{
return items
returnItems = items
.Where(i => i.HasImage(ImageType.Primary) || i.HasImage(ImageType.Thumb))
.ToList();
returnItems.Shuffle();
return returnItems;
}
return items
returnItems = items
.Where(i => i.HasImage(ImageType.Primary))
.ToList();
returnItems.Shuffle();
return returnItems;
}
protected override bool Supports(BaseItem item)

View File

@@ -8,8 +8,6 @@ using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
@@ -43,7 +41,7 @@ namespace Emby.Server.Implementations.Images
return _libraryManager.GetItemList(new InternalItemsQuery
{
Genres = new[] { item.Name },
IncludeItemTypes = new[] { nameof(Series), nameof(Movie) },
IncludeItemTypes = new[] { BaseItemKind.Series, BaseItemKind.Movie },
OrderBy = new[] { (ItemSortBy.Random, SortOrder.Ascending) },
Limit = 4,
Recursive = true,

View File

@@ -44,9 +44,9 @@ namespace Emby.Server.Implementations.Images
Genres = new[] { item.Name },
IncludeItemTypes = new[]
{
nameof(MusicAlbum),
nameof(MusicVideo),
nameof(Audio)
BaseItemKind.MusicAlbum,
BaseItemKind.MusicVideo,
BaseItemKind.Audio
},
OrderBy = new[] { (ItemSortBy.Random, SortOrder.Ascending) },
Limit = 4,

View File

@@ -1,8 +1,9 @@
using System;
using System.IO;
using Emby.Naming.Audio;
using Emby.Naming.Common;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Model.IO;
@@ -13,17 +14,17 @@ namespace Emby.Server.Implementations.Library
/// </summary>
public class CoreResolutionIgnoreRule : IResolverIgnoreRule
{
private readonly ILibraryManager _libraryManager;
private readonly NamingOptions _namingOptions;
private readonly IServerApplicationPaths _serverApplicationPaths;
/// <summary>
/// Initializes a new instance of the <see cref="CoreResolutionIgnoreRule"/> class.
/// </summary>
/// <param name="libraryManager">The library manager.</param>
/// <param name="namingOptions">The naming options.</param>
/// <param name="serverApplicationPaths">The server application paths.</param>
public CoreResolutionIgnoreRule(ILibraryManager libraryManager, IServerApplicationPaths serverApplicationPaths)
public CoreResolutionIgnoreRule(NamingOptions namingOptions, IServerApplicationPaths serverApplicationPaths)
{
_libraryManager = libraryManager;
_namingOptions = namingOptions;
_serverApplicationPaths = serverApplicationPaths;
}
@@ -53,20 +54,10 @@ namespace Emby.Server.Implementations.Library
{
if (parent != null)
{
// Ignore trailer folders but allow it at the collection level
if (string.Equals(filename, BaseItem.TrailersFolderName, StringComparison.OrdinalIgnoreCase)
&& !(parent is AggregateFolder)
&& !(parent is UserRootFolder))
{
return true;
}
if (string.Equals(filename, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
{
return true;
}
if (string.Equals(filename, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
// Ignore extras folders but allow it at the collection level
if (_namingOptions.AllExtrasTypesFolderNames.ContainsKey(filename)
&& parent is not AggregateFolder
&& parent is not UserRootFolder)
{
return true;
}
@@ -78,7 +69,7 @@ namespace Emby.Server.Implementations.Library
{
// Don't resolve these into audio files
if (Path.GetFileNameWithoutExtension(filename.AsSpan()).Equals(BaseItem.ThemeSongFileName, StringComparison.Ordinal)
&& _libraryManager.IsAudioFile(filename))
&& AudioFileParser.IsAudioFile(filename, _namingOptions))
{
return true;
}

View File

@@ -11,14 +11,12 @@ using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Emby.Naming.Audio;
using Emby.Naming.Common;
using Emby.Naming.TV;
using Emby.Naming.Video;
using Emby.Server.Implementations.Library.Resolvers;
using Emby.Server.Implementations.Library.Validators;
using Emby.Server.Implementations.Playlists;
using Emby.Server.Implementations.ScheduledTasks;
using Emby.Server.Implementations.ScheduledTasks.Tasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
@@ -47,8 +45,8 @@ using MediaBrowser.Model.IO;
using MediaBrowser.Model.Library;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Tasks;
using MediaBrowser.Providers.MediaInfo;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
using EpisodeInfo = Emby.Naming.TV.EpisodeInfo;
@@ -79,6 +77,8 @@ namespace Emby.Server.Implementations.Library
private readonly IFileSystem _fileSystem;
private readonly IItemRepository _itemRepository;
private readonly IImageProcessor _imageProcessor;
private readonly NamingOptions _namingOptions;
private readonly ExtraResolver _extraResolver;
/// <summary>
/// The _root folder sync lock.
@@ -88,9 +88,6 @@ namespace Emby.Server.Implementations.Library
private readonly TimeSpan _viewRefreshInterval = TimeSpan.FromHours(24);
private NamingOptions _namingOptions;
private string[] _videoFileExtensions;
/// <summary>
/// The _root folder.
/// </summary>
@@ -103,7 +100,7 @@ namespace Emby.Server.Implementations.Library
/// Initializes a new instance of the <see cref="LibraryManager" /> class.
/// </summary>
/// <param name="appHost">The application host.</param>
/// <param name="logger">The logger.</param>
/// <param name="loggerFactory">The logger factory.</param>
/// <param name="taskManager">The task manager.</param>
/// <param name="userManager">The user manager.</param>
/// <param name="configurationManager">The configuration manager.</param>
@@ -116,9 +113,10 @@ namespace Emby.Server.Implementations.Library
/// <param name="itemRepository">The item repository.</param>
/// <param name="imageProcessor">The image processor.</param>
/// <param name="memoryCache">The memory cache.</param>
/// <param name="namingOptions">The naming options.</param>
public LibraryManager(
IServerApplicationHost appHost,
ILogger<LibraryManager> logger,
ILoggerFactory loggerFactory,
ITaskManager taskManager,
IUserManager userManager,
IServerConfigurationManager configurationManager,
@@ -130,10 +128,11 @@ namespace Emby.Server.Implementations.Library
IMediaEncoder mediaEncoder,
IItemRepository itemRepository,
IImageProcessor imageProcessor,
IMemoryCache memoryCache)
IMemoryCache memoryCache,
NamingOptions namingOptions)
{
_appHost = appHost;
_logger = logger;
_logger = loggerFactory.CreateLogger<LibraryManager>();
_taskManager = taskManager;
_userManager = userManager;
_configurationManager = configurationManager;
@@ -146,6 +145,9 @@ namespace Emby.Server.Implementations.Library
_itemRepository = itemRepository;
_imageProcessor = imageProcessor;
_memoryCache = memoryCache;
_namingOptions = namingOptions;
_extraResolver = new ExtraResolver(loggerFactory.CreateLogger<ExtraResolver>(), namingOptions);
_configurationManager.ConfigurationUpdated += ConfigurationUpdated;
@@ -532,8 +534,8 @@ namespace Emby.Server.Implementations.Library
return key.GetMD5();
}
public BaseItem ResolvePath(FileSystemMetadata fileInfo, Folder parent = null)
=> ResolvePath(fileInfo, new DirectoryService(_fileSystem), null, parent);
public BaseItem ResolvePath(FileSystemMetadata fileInfo, Folder parent = null, IDirectoryService directoryService = null)
=> ResolvePath(fileInfo, directoryService ?? new DirectoryService(_fileSystem), null, parent);
private BaseItem ResolvePath(
FileSystemMetadata fileInfo,
@@ -653,7 +655,7 @@ namespace Emby.Server.Implementations.Library
return !args.ContainsFileSystemEntryByName(".ignore");
}
public IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files, IDirectoryService directoryService, Folder parent, LibraryOptions libraryOptions, string collectionType)
public IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files, IDirectoryService directoryService, Folder parent, LibraryOptions libraryOptions, string collectionType = null)
{
return ResolvePaths(files, directoryService, parent, libraryOptions, collectionType, EntityResolvers);
}
@@ -676,11 +678,9 @@ namespace Emby.Server.Implementations.Library
{
var result = resolver.ResolveMultiple(parent, fileList, collectionType, directoryService);
if (result != null && result.Items.Count > 0)
if (result?.Items.Count > 0)
{
var items = new List<BaseItem>();
items.AddRange(result.Items);
var items = result.Items;
foreach (var item in items)
{
ResolverHelper.SetInitialItemValues(item, parent, this, directoryService);
@@ -756,7 +756,7 @@ namespace Emby.Server.Implementations.Library
Path = path
};
if (folder.Id.Equals(Guid.Empty))
if (folder.Id.Equals(default))
{
if (string.IsNullOrEmpty(folder.Path))
{
@@ -775,7 +775,7 @@ namespace Emby.Server.Implementations.Library
folder = dbItem;
}
if (folder.ParentId != rootFolder.Id)
if (!folder.ParentId.Equals(rootFolder.Id))
{
folder.ParentId = rootFolder.Id;
folder.UpdateToRepositoryAsync(ItemUpdateType.MetadataImport, CancellationToken.None).GetAwaiter().GetResult();
@@ -964,7 +964,7 @@ namespace Emby.Server.Implementations.Library
{
var existing = GetItemList(new InternalItemsQuery
{
IncludeItemTypes = new[] { nameof(MusicArtist) },
IncludeItemTypes = new[] { BaseItemKind.MusicArtist },
Name = name,
DtoOptions = options
}).Cast<MusicArtist>()
@@ -1005,14 +1005,8 @@ namespace Emby.Server.Implementations.Library
return GetNewItemIdInternal(path, typeof(T), forceCaseInsensitiveId);
}
/// <summary>
/// Validate and refresh the People sub-set of the IBN.
/// The items are stored in the db but not loaded into memory until actually requested by an operation.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="progress">The progress.</param>
/// <returns>Task.</returns>
public Task ValidatePeople(CancellationToken cancellationToken, IProgress<double> progress)
/// <inheritdoc />
public Task ValidatePeopleAsync(IProgress<double> progress, CancellationToken cancellationToken)
{
// Ensure the location is available.
Directory.CreateDirectory(_configurationManager.ApplicationPaths.PeoplePath);
@@ -1034,15 +1028,6 @@ namespace Emby.Server.Implementations.Library
return Task.CompletedTask;
}
/// <summary>
/// Queues the library scan.
/// </summary>
public void QueueLibraryScan()
{
// Just run the scheduled task so that the user can see it
_taskManager.QueueScheduledTask<RefreshMediaLibraryTask>();
}
/// <summary>
/// Validates the media library internal.
/// </summary>
@@ -1268,7 +1253,7 @@ namespace Emby.Server.Implementations.Library
/// <exception cref="ArgumentNullException"><paramref name="id"/> is <c>null</c>.</exception>
public BaseItem GetItemById(Guid id)
{
if (id == Guid.Empty)
if (id.Equals(default))
{
throw new ArgumentException("Guid can't be empty", nameof(id));
}
@@ -1290,7 +1275,7 @@ namespace Emby.Server.Implementations.Library
public List<BaseItem> GetItemList(InternalItemsQuery query, bool allowExternalContent)
{
if (query.Recursive && query.ParentId != Guid.Empty)
if (query.Recursive && !query.ParentId.Equals(default))
{
var parent = GetItemById(query.ParentId);
if (parent != null)
@@ -1314,7 +1299,7 @@ namespace Emby.Server.Implementations.Library
public int GetCount(InternalItemsQuery query)
{
if (query.Recursive && !query.ParentId.Equals(Guid.Empty))
if (query.Recursive && !query.ParentId.Equals(default))
{
var parent = GetItemById(query.ParentId);
if (parent != null)
@@ -1358,10 +1343,10 @@ namespace Emby.Server.Implementations.Library
return _itemRepository.GetItems(query);
}
return new QueryResult<BaseItem>
{
Items = _itemRepository.GetItemList(query)
};
return new QueryResult<BaseItem>(
query.StartIndex,
null,
_itemRepository.GetItemList(query));
}
public List<Guid> GetItemIds(InternalItemsQuery query)
@@ -1374,7 +1359,7 @@ namespace Emby.Server.Implementations.Library
return _itemRepository.GetItemIdsList(query);
}
public QueryResult<(BaseItem, ItemCounts)> GetStudios(InternalItemsQuery query)
public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetStudios(InternalItemsQuery query)
{
if (query.User != null)
{
@@ -1385,7 +1370,7 @@ namespace Emby.Server.Implementations.Library
return _itemRepository.GetStudios(query);
}
public QueryResult<(BaseItem, ItemCounts)> GetGenres(InternalItemsQuery query)
public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetGenres(InternalItemsQuery query)
{
if (query.User != null)
{
@@ -1396,7 +1381,7 @@ namespace Emby.Server.Implementations.Library
return _itemRepository.GetGenres(query);
}
public QueryResult<(BaseItem, ItemCounts)> GetMusicGenres(InternalItemsQuery query)
public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetMusicGenres(InternalItemsQuery query)
{
if (query.User != null)
{
@@ -1407,7 +1392,7 @@ namespace Emby.Server.Implementations.Library
return _itemRepository.GetMusicGenres(query);
}
public QueryResult<(BaseItem, ItemCounts)> GetAllArtists(InternalItemsQuery query)
public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetAllArtists(InternalItemsQuery query)
{
if (query.User != null)
{
@@ -1418,7 +1403,7 @@ namespace Emby.Server.Implementations.Library
return _itemRepository.GetAllArtists(query);
}
public QueryResult<(BaseItem, ItemCounts)> GetArtists(InternalItemsQuery query)
public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetArtists(InternalItemsQuery query)
{
if (query.User != null)
{
@@ -1442,7 +1427,7 @@ namespace Emby.Server.Implementations.Library
for (int i = 0; i < len; i++)
{
parents[i] = GetItemById(ancestorIds[i]);
if (!(parents[i] is ICollectionFolder || parents[i] is UserView))
if (parents[i] is not (ICollectionFolder or UserView))
{
return;
}
@@ -1459,7 +1444,7 @@ namespace Emby.Server.Implementations.Library
}
}
public QueryResult<(BaseItem, ItemCounts)> GetAlbumArtists(InternalItemsQuery query)
public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetAlbumArtists(InternalItemsQuery query)
{
if (query.User != null)
{
@@ -1472,7 +1457,7 @@ namespace Emby.Server.Implementations.Library
public QueryResult<BaseItem> GetItemsResult(InternalItemsQuery query)
{
if (query.Recursive && !query.ParentId.Equals(Guid.Empty))
if (query.Recursive && !query.ParentId.Equals(default))
{
var parent = GetItemById(query.ParentId);
if (parent != null)
@@ -1491,10 +1476,10 @@ namespace Emby.Server.Implementations.Library
return _itemRepository.GetItems(query);
}
return new QueryResult<BaseItem>
{
Items = _itemRepository.GetItemList(query)
};
return new QueryResult<BaseItem>(
query.StartIndex,
null,
_itemRepository.GetItemList(query));
}
private void SetTopParentIdsOrAncestors(InternalItemsQuery query, List<BaseItem> parents)
@@ -1528,7 +1513,7 @@ namespace Emby.Server.Implementations.Library
private void AddUserToQuery(InternalItemsQuery query, User user, bool allowExternalContent = true)
{
if (query.AncestorIds.Length == 0 &&
query.ParentId.Equals(Guid.Empty) &&
query.ParentId.Equals(default) &&
query.ChannelIds.Count == 0 &&
query.TopParentIds.Length == 0 &&
string.IsNullOrEmpty(query.AncestorWithPresentationUniqueKey) &&
@@ -1556,7 +1541,7 @@ namespace Emby.Server.Implementations.Library
}
// Translate view into folders
if (!view.DisplayParentId.Equals(Guid.Empty))
if (!view.DisplayParentId.Equals(default))
{
var displayParent = GetItemById(view.DisplayParentId);
if (displayParent != null)
@@ -1567,7 +1552,7 @@ namespace Emby.Server.Implementations.Library
return Array.Empty<Guid>();
}
if (!view.ParentId.Equals(Guid.Empty))
if (!view.ParentId.Equals(default))
{
var displayParent = GetItemById(view.ParentId);
if (displayParent != null)
@@ -1648,27 +1633,6 @@ namespace Emby.Server.Implementations.Library
}
}
/// <summary>
/// Gets all intro files.
/// </summary>
/// <returns>IEnumerable{System.String}.</returns>
public IEnumerable<string> GetAllIntroFiles()
{
return IntroProviders.SelectMany(i =>
{
try
{
return i.GetAllIntroFiles().ToList();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting intro files");
return new List<string>();
}
});
}
/// <summary>
/// Resolves the intro.
/// </summary>
@@ -1758,7 +1722,7 @@ namespace Emby.Server.Implementations.Library
return orderedItems ?? items;
}
public IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<ValueTuple<string, SortOrder>> orderBy)
public IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<(string OrderBy, SortOrder SortOrder)> orderBy)
{
var isFirst = true;
@@ -1896,7 +1860,9 @@ namespace Emby.Server.Implementations.Library
throw new ArgumentNullException(nameof(item));
}
var outdated = forceUpdate ? item.ImageInfos.Where(i => i.Path != null).ToArray() : item.ImageInfos.Where(ImageNeedsRefresh).ToArray();
var outdated = forceUpdate
? item.ImageInfos.Where(i => i.Path != null).ToArray()
: item.ImageInfos.Where(ImageNeedsRefresh).ToArray();
// Skip image processing if current or live tv source
if (outdated.Length == 0 || item.SourceType != SourceType.Library)
{
@@ -1919,7 +1885,7 @@ namespace Emby.Server.Implementations.Library
_logger.LogWarning("Cannot get image index for {ImagePath}", img.Path);
continue;
}
catch (Exception ex) when (ex is InvalidOperationException || ex is IOException)
catch (Exception ex) when (ex is InvalidOperationException or IOException)
{
_logger.LogWarning(ex, "Cannot fetch image from {ImagePath}", img.Path);
continue;
@@ -1931,23 +1897,24 @@ namespace Emby.Server.Implementations.Library
}
}
ImageDimensions size;
try
{
ImageDimensions size = _imageProcessor.GetImageDimensions(item, image);
size = _imageProcessor.GetImageDimensions(item, image);
image.Width = size.Width;
image.Height = size.Height;
}
catch (Exception ex)
{
_logger.LogError(ex, "Cannot get image dimensions for {ImagePath}", image.Path);
size = new ImageDimensions(0, 0);
image.Width = 0;
image.Height = 0;
continue;
}
try
{
image.BlurHash = _imageProcessor.GetImageBlurHash(image.Path);
image.BlurHash = _imageProcessor.GetImageBlurHash(image.Path, size);
}
catch (Exception ex)
{
@@ -2012,16 +1979,16 @@ namespace Emby.Server.Implementations.Library
public Task UpdateItemAsync(BaseItem item, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken)
=> UpdateItemsAsync(new[] { item }, parent, updateReason, cancellationToken);
public Task RunMetadataSavers(BaseItem item, ItemUpdateType updateReason)
public async Task RunMetadataSavers(BaseItem item, ItemUpdateType updateReason)
{
if (item.IsFileProtocol)
{
ProviderManager.SaveMetadata(item, updateReason);
await ProviderManager.SaveMetadataAsync(item, updateReason).ConfigureAwait(false);
}
item.DateLastSaved = DateTime.UtcNow;
return UpdateImagesAsync(item, updateReason >= ItemUpdateType.ImageUpdate);
await UpdateImagesAsync(item, updateReason >= ItemUpdateType.ImageUpdate).ConfigureAwait(false);
}
/// <summary>
@@ -2190,7 +2157,7 @@ namespace Emby.Server.Implementations.Library
return null;
}
while (!item.ParentId.Equals(Guid.Empty))
while (!item.ParentId.Equals(default))
{
var parent = item.GetParent();
if (parent == null || parent is AggregateFolder)
@@ -2268,7 +2235,9 @@ namespace Emby.Server.Implementations.Library
string viewType,
string sortName)
{
var parentIdString = parentId.Equals(Guid.Empty) ? null : parentId.ToString("N", CultureInfo.InvariantCulture);
var parentIdString = parentId.Equals(default)
? null
: parentId.ToString("N", CultureInfo.InvariantCulture);
var idValues = "38_namedview_" + name + user.Id.ToString("N", CultureInfo.InvariantCulture) + (parentIdString ?? string.Empty) + (viewType ?? string.Empty);
var id = GetNewItemId(idValues, typeof(UserView));
@@ -2302,7 +2271,7 @@ namespace Emby.Server.Implementations.Library
var refresh = isNew || DateTime.UtcNow - item.DateLastRefreshed >= _viewRefreshInterval;
if (!refresh && !item.DisplayParentId.Equals(Guid.Empty))
if (!refresh && !item.DisplayParentId.Equals(default))
{
var displayParent = GetItemById(item.DisplayParentId);
refresh = displayParent != null && displayParent.DateLastSaved > item.DateLastRefreshed;
@@ -2369,7 +2338,7 @@ namespace Emby.Server.Implementations.Library
var refresh = isNew || DateTime.UtcNow - item.DateLastRefreshed >= _viewRefreshInterval;
if (!refresh && !item.DisplayParentId.Equals(Guid.Empty))
if (!refresh && !item.DisplayParentId.Equals(default))
{
var displayParent = GetItemById(item.DisplayParentId);
refresh = displayParent != null && displayParent.DateLastSaved > item.DateLastRefreshed;
@@ -2402,7 +2371,9 @@ namespace Emby.Server.Implementations.Library
throw new ArgumentNullException(nameof(name));
}
var parentIdString = parentId.Equals(Guid.Empty) ? null : parentId.ToString("N", CultureInfo.InvariantCulture);
var parentIdString = parentId.Equals(default)
? null
: parentId.ToString("N", CultureInfo.InvariantCulture);
var idValues = "37_namedview_" + name + (parentIdString ?? string.Empty) + (viewType ?? string.Empty);
if (!string.IsNullOrEmpty(uniqueId))
{
@@ -2446,7 +2417,7 @@ namespace Emby.Server.Implementations.Library
var refresh = isNew || DateTime.UtcNow - item.DateLastRefreshed >= _viewRefreshInterval;
if (!refresh && !item.DisplayParentId.Equals(Guid.Empty))
if (!refresh && !item.DisplayParentId.Equals(default))
{
var displayParent = GetItemById(item.DisplayParentId);
refresh = displayParent != null && displayParent.DateLastSaved > item.DateLastRefreshed;
@@ -2467,24 +2438,6 @@ namespace Emby.Server.Implementations.Library
return item;
}
public void AddExternalSubtitleStreams(
List<MediaStream> streams,
string videoPath,
string[] files)
{
new SubtitleResolver(BaseItem.LocalizationManager).AddExternalSubtitleStreams(streams, videoPath, streams.Count, files);
}
public BaseItem GetParentItem(string parentId, Guid? userId)
{
if (string.IsNullOrEmpty(parentId))
{
return GetParentItem((Guid?)null, userId);
}
return GetParentItem(new Guid(parentId), userId);
}
public BaseItem GetParentItem(Guid? parentId, Guid? userId)
{
if (parentId.HasValue)
@@ -2492,7 +2445,7 @@ namespace Emby.Server.Implementations.Library
return GetItemById(parentId.Value);
}
if (userId.HasValue && userId != Guid.Empty)
if (userId.HasValue && !userId.Equals(default))
{
return GetUserRootFolder();
}
@@ -2501,15 +2454,11 @@ namespace Emby.Server.Implementations.Library
}
/// <inheritdoc />
public bool IsVideoFile(string path)
public void QueueLibraryScan()
{
return VideoResolver.IsVideoFile(path, GetNamingOptions());
_taskManager.QueueScheduledTask<RefreshMediaLibraryTask>();
}
/// <inheritdoc />
public bool IsAudioFile(string path)
=> AudioFileParser.IsAudioFile(path, GetNamingOptions());
/// <inheritdoc />
public int? GetSeasonNumberFromPath(string path)
=> SeasonPathParser.Parse(path, true, true).SeasonNumber;
@@ -2525,7 +2474,7 @@ namespace Emby.Server.Implementations.Library
isAbsoluteNaming = null;
}
var resolver = new EpisodeResolver(GetNamingOptions());
var resolver = new EpisodeResolver(_namingOptions);
var isFolder = episode.VideoType == VideoType.BluRay || episode.VideoType == VideoType.Dvd;
@@ -2682,113 +2631,77 @@ namespace Emby.Server.Implementations.Library
return changed;
}
/// <inheritdoc />
public NamingOptions GetNamingOptions()
{
if (_namingOptions == null)
{
_namingOptions = new NamingOptions();
_videoFileExtensions = _namingOptions.VideoFileExtensions;
}
return _namingOptions;
}
public ItemLookupInfo ParseName(string name)
{
var namingOptions = GetNamingOptions();
var namingOptions = _namingOptions;
var result = VideoResolver.CleanDateTime(name, namingOptions);
return new ItemLookupInfo
{
Name = VideoResolver.TryCleanString(result.Name, namingOptions, out var newName) ? newName.ToString() : result.Name,
Name = VideoResolver.TryCleanString(result.Name, namingOptions, out var newName) ? newName : result.Name,
Year = result.Year
};
}
public IEnumerable<Video> FindTrailers(BaseItem owner, List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService)
public IEnumerable<BaseItem> FindExtras(BaseItem owner, IReadOnlyList<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService)
{
var namingOptions = GetNamingOptions();
var files = owner.IsInMixedFolder ? new List<FileSystemMetadata>() : fileSystemChildren.Where(i => i.IsDirectory)
.Where(i => string.Equals(i.Name, BaseItem.TrailersFolderName, StringComparison.OrdinalIgnoreCase))
.SelectMany(i => _fileSystem.GetFiles(i.FullName, _videoFileExtensions, false, false))
.ToList();
var videos = VideoListResolver.Resolve(fileSystemChildren, namingOptions);
var currentVideo = videos.FirstOrDefault(i => string.Equals(owner.Path, i.Files[0].Path, StringComparison.OrdinalIgnoreCase));
if (currentVideo != null)
var ownerVideoInfo = VideoResolver.Resolve(owner.Path, owner.IsFolder, _namingOptions);
if (ownerVideoInfo == null)
{
files.AddRange(currentVideo.Extras.Where(i => i.ExtraType == ExtraType.Trailer).Select(i => _fileSystem.GetFileInfo(i.Path)));
yield break;
}
var resolvers = new IItemResolver[]
var count = fileSystemChildren.Count;
for (var i = 0; i < count; i++)
{
new GenericVideoResolver<Trailer>(this)
};
return ResolvePaths(files, directoryService, null, new LibraryOptions(), null, resolvers)
.OfType<Trailer>()
.Select(video =>
var current = fileSystemChildren[i];
if (current.IsDirectory && _namingOptions.AllExtrasTypesFolderNames.ContainsKey(current.Name))
{
// Try to retrieve it from the db. If we don't find it, use the resolved version
if (GetItemById(video.Id) is Trailer dbItem)
var filesInSubFolder = _fileSystem.GetFiles(current.FullName, null, false, false);
foreach (var file in filesInSubFolder)
{
video = dbItem;
if (!_extraResolver.TryGetExtraTypeForOwner(file.FullName, ownerVideoInfo, out var extraType))
{
continue;
}
var extra = GetExtra(file, extraType.Value);
if (extra != null)
{
yield return extra;
}
}
video.ParentId = Guid.Empty;
video.OwnerId = owner.Id;
video.ExtraType = ExtraType.Trailer;
video.TrailerTypes = new[] { TrailerType.LocalTrailer };
return video;
// Sort them so that the list can be easily compared for changes
}).OrderBy(i => i.Path);
}
public IEnumerable<Video> FindExtras(BaseItem owner, List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService)
{
var namingOptions = GetNamingOptions();
var files = owner.IsInMixedFolder ? new List<FileSystemMetadata>() : fileSystemChildren.Where(i => i.IsDirectory)
.Where(i => BaseItem.AllExtrasTypesFolderNames.ContainsKey(i.Name ?? string.Empty))
.SelectMany(i => _fileSystem.GetFiles(i.FullName, _videoFileExtensions, false, false))
.ToList();
var videos = VideoListResolver.Resolve(fileSystemChildren, namingOptions);
var currentVideo = videos.FirstOrDefault(i => string.Equals(owner.Path, i.Files[0].Path, StringComparison.OrdinalIgnoreCase));
if (currentVideo != null)
{
files.AddRange(currentVideo.Extras.Where(i => i.ExtraType != ExtraType.Trailer).Select(i => _fileSystem.GetFileInfo(i.Path)));
}
else if (!current.IsDirectory && _extraResolver.TryGetExtraTypeForOwner(current.FullName, ownerVideoInfo, out var extraType))
{
var extra = GetExtra(current, extraType.Value);
if (extra != null)
{
yield return extra;
}
}
}
return ResolvePaths(files, directoryService, null, new LibraryOptions(), null)
.OfType<Video>()
.Select(video =>
BaseItem GetExtra(FileSystemMetadata file, ExtraType extraType)
{
var extra = ResolvePath(_fileSystem.GetFileInfo(file.FullName), directoryService, _extraResolver.GetResolversForExtraType(extraType));
if (extra is not Video && extra is not Audio)
{
// Try to retrieve it from the db. If we don't find it, use the resolved version
var dbItem = GetItemById(video.Id) as Video;
return null;
}
if (dbItem != null)
{
video = dbItem;
}
// Try to retrieve it from the db. If we don't find it, use the resolved version
var itemById = GetItemById(extra.Id);
if (itemById != null)
{
extra = itemById;
}
video.ParentId = Guid.Empty;
video.OwnerId = owner.Id;
SetExtraTypeFromFilename(video);
return video;
// Sort them so that the list can be easily compared for changes
}).OrderBy(i => i.Path);
extra.ExtraType = extraType;
extra.ParentId = Guid.Empty;
extra.OwnerId = owner.Id;
return extra;
}
}
public string GetPathAfterNetworkSubstitution(string path, BaseItem ownerItem)
@@ -2828,25 +2741,6 @@ namespace Emby.Server.Implementations.Library
return path;
}
public string SubstitutePath(string path, string from, string to)
{
if (path.TryReplaceSubPath(from, to, out var newPath))
{
return newPath;
}
return path;
}
private void SetExtraTypeFromFilename(Video item)
{
var resolver = new ExtraResolver(GetNamingOptions());
var result = resolver.GetExtraInfo(item.Path);
item.ExtraType = result.ExtraType;
}
public List<PersonInfo> GetPeople(InternalPeopleQuery query)
{
return _itemRepository.GetPeople(query);
@@ -2953,10 +2847,13 @@ namespace Emby.Server.Implementations.Library
var rootFolderPath = _configurationManager.ApplicationPaths.DefaultUserViewsPath;
var existingNameCount = 1; // first numbered name will be 2
var virtualFolderPath = Path.Combine(rootFolderPath, name);
var originalName = name;
while (Directory.Exists(virtualFolderPath))
{
name += "1";
existingNameCount++;
name = originalName + existingNameCount;
virtualFolderPath = Path.Combine(rootFolderPath, name);
}
@@ -3059,7 +2956,10 @@ namespace Emby.Server.Implementations.Library
}
}
CreateItems(personsToSave, null, CancellationToken.None);
if (personsToSave.Count > 0)
{
CreateItems(personsToSave, null, CancellationToken.None);
}
}
private void StartScanInBackground()

View File

@@ -66,11 +66,8 @@ namespace Emby.Server.Implementations.Library
{
var delayMs = mediaSource.AnalyzeDurationMs ?? 0;
delayMs = Math.Max(3000, delayMs);
if (delayMs > 0)
{
_logger.LogInformation("Waiting {0}ms before probing the live stream", delayMs);
await Task.Delay(delayMs, cancellationToken).ConfigureAwait(false);
}
_logger.LogInformation("Waiting {0}ms before probing the live stream", delayMs);
await Task.Delay(delayMs, cancellationToken).ConfigureAwait(false);
}
mediaSource.AnalyzeDurationMs = 3000;

View File

@@ -151,7 +151,11 @@ namespace Emby.Server.Implementations.Library
{
var mediaSources = GetStaticMediaSources(item, enablePathSubstitution, user);
if (allowMediaProbe && mediaSources[0].Type != MediaSourceType.Placeholder && !mediaSources[0].MediaStreams.Any(i => i.Type == MediaStreamType.Audio || i.Type == MediaStreamType.Video))
// If file is strm or main media stream is missing, force a metadata refresh with remote probing
if (allowMediaProbe && mediaSources[0].Type != MediaSourceType.Placeholder
&& (item.Path.EndsWith(".strm", StringComparison.OrdinalIgnoreCase)
|| (item.MediaType == MediaType.Video && !mediaSources[0].MediaStreams.Any(i => i.Type == MediaStreamType.Video))
|| (item.MediaType == MediaType.Audio && !mediaSources[0].MediaStreams.Any(i => i.Type == MediaStreamType.Audio))))
{
await item.RefreshMetadata(
new MetadataRefreshOptions(_directoryService)
@@ -172,24 +176,16 @@ namespace Emby.Server.Implementations.Library
foreach (var source in dynamicMediaSources)
{
if (user != null)
{
SetDefaultAudioAndSubtitleStreamIndexes(item, source, user);
}
// Validate that this is actually possible
if (source.SupportsDirectStream)
{
source.SupportsDirectStream = SupportsDirectStream(source.Path, source.Protocol);
}
list.Add(source);
}
if (user != null)
{
foreach (var source in list)
if (user != null)
{
SetDefaultAudioAndSubtitleStreamIndexes(item, source, user);
if (string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase))
{
source.SupportsTranscoding = user.HasPermission(PermissionKind.EnableAudioPlaybackTranscoding);
@@ -200,6 +196,8 @@ namespace Emby.Server.Implementations.Library
source.SupportsDirectStream = user.HasPermission(PermissionKind.EnablePlaybackRemuxing);
}
}
list.Add(source);
}
return SortMediaSources(list);
@@ -338,13 +336,23 @@ namespace Emby.Server.Implementations.Library
foreach (var source in sources)
{
SetDefaultAudioAndSubtitleStreamIndexes(item, source, user);
if (string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase))
{
source.SupportsTranscoding = user.HasPermission(PermissionKind.EnableAudioPlaybackTranscoding);
}
else if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase))
{
source.SupportsTranscoding = user.HasPermission(PermissionKind.EnableVideoPlaybackTranscoding);
source.SupportsDirectStream = user.HasPermission(PermissionKind.EnablePlaybackRemuxing);
}
}
}
return sources;
}
private string[] NormalizeLanguage(string language)
private IReadOnlyList<string> NormalizeLanguage(string language)
{
if (string.IsNullOrEmpty(language))
{
@@ -464,12 +472,11 @@ namespace Emby.Server.Implementations.Library
try
{
var tuple = GetProvider(request.OpenToken);
var provider = tuple.Item1;
var (provider, keyId) = GetProvider(request.OpenToken);
var currentLiveStreams = _openStreams.Values.ToList();
liveStream = await provider.OpenMediaSource(tuple.Item2, currentLiveStreams, cancellationToken).ConfigureAwait(false);
liveStream = await provider.OpenMediaSource(keyId, currentLiveStreams, cancellationToken).ConfigureAwait(false);
mediaSource = liveStream.MediaSource;
@@ -515,10 +522,10 @@ namespace Emby.Server.Implementations.Library
_logger.LogInformation("Live stream opened: {@MediaSource}", mediaSource);
var clone = JsonSerializer.Deserialize<MediaSourceInfo>(json, _jsonOptions);
if (!request.UserId.Equals(Guid.Empty))
if (!request.UserId.Equals(default))
{
var user = _userManager.GetUserById(request.UserId);
var item = request.ItemId.Equals(Guid.Empty)
var item = request.ItemId.Equals(default)
? null
: _libraryManager.GetItemById(request.ItemId);
SetDefaultAudioAndSubtitleStreamIndexes(item, clone, user);
@@ -829,7 +836,7 @@ namespace Emby.Server.Implementations.Library
}
}
private (IMediaSourceProvider, string) GetProvider(string key)
private (IMediaSourceProvider MediaSourceProvider, string KeyId) GetProvider(string key)
{
if (string.IsNullOrEmpty(key))
{

View File

@@ -1,25 +1,23 @@
#nullable disable
#pragma warning disable CS1591
using System;
using System.Collections.Generic;
using System.Linq;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
using MediaBrowser.Model.Entities;
namespace Emby.Server.Implementations.Library
{
public static class MediaStreamSelector
{
public static int? GetDefaultAudioStreamIndex(List<MediaStream> streams, string[] preferredLanguages, bool preferDefaultTrack)
public static int? GetDefaultAudioStreamIndex(IReadOnlyList<MediaStream> streams, IReadOnlyList<string> preferredLanguages, bool preferDefaultTrack)
{
streams = GetSortedStreams(streams, MediaStreamType.Audio, preferredLanguages)
.ToList();
var sortedStreams = GetSortedStreams(streams, MediaStreamType.Audio, preferredLanguages).ToList();
if (preferDefaultTrack)
{
var defaultStream = streams.FirstOrDefault(i => i.IsDefault);
var defaultStream = sortedStreams.FirstOrDefault(i => i.IsDefault);
if (defaultStream != null)
{
@@ -27,24 +25,15 @@ namespace Emby.Server.Implementations.Library
}
}
var stream = streams.FirstOrDefault();
if (stream != null)
{
return stream.Index;
}
return null;
return sortedStreams.FirstOrDefault()?.Index;
}
public static int? GetDefaultSubtitleStreamIndex(
IEnumerable<MediaStream> streams,
string[] preferredLanguages,
IReadOnlyList<string> preferredLanguages,
SubtitlePlaybackMode mode,
string audioTrackLanguage)
{
MediaStream stream = null;
if (mode == SubtitlePlaybackMode.None)
{
return null;
@@ -58,24 +47,25 @@ namespace Emby.Server.Implementations.Library
.ThenByDescending(x => x.IsDefault)
.ToList();
MediaStream? stream = null;
if (mode == SubtitlePlaybackMode.Default)
{
// Prefer embedded metadata over smart logic
stream = sortedStreams.FirstOrDefault(s => s.IsExternal || s.IsForced || s.IsDefault);
// if the audio language is not understood by the user, load their preferred subs, if there are any
if (stream == null && !preferredLanguages.Contains(audioTrackLanguage, StringComparer.OrdinalIgnoreCase))
if (stream == null && !preferredLanguages.Contains(audioTrackLanguage, StringComparison.OrdinalIgnoreCase))
{
stream = sortedStreams.FirstOrDefault(s => !s.IsForced && preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase));
stream = sortedStreams.FirstOrDefault(s => !s.IsForced && preferredLanguages.Contains(s.Language, StringComparison.OrdinalIgnoreCase));
}
}
else if (mode == SubtitlePlaybackMode.Smart)
{
// if the audio language is not understood by the user, load their preferred subs, if there are any
if (!preferredLanguages.Contains(audioTrackLanguage, StringComparer.OrdinalIgnoreCase))
if (!preferredLanguages.Contains(audioTrackLanguage, StringComparison.OrdinalIgnoreCase))
{
stream = streams.FirstOrDefault(s => !s.IsForced && preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)) ??
streams.FirstOrDefault(s => preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase));
stream = streams.FirstOrDefault(s => !s.IsForced && preferredLanguages.Contains(s.Language, StringComparison.OrdinalIgnoreCase)) ??
streams.FirstOrDefault(s => preferredLanguages.Contains(s.Language, StringComparison.OrdinalIgnoreCase));
}
}
else if (mode == SubtitlePlaybackMode.Always)
@@ -94,26 +84,27 @@ namespace Emby.Server.Implementations.Library
return stream?.Index;
}
private static IEnumerable<MediaStream> GetSortedStreams(IEnumerable<MediaStream> streams, MediaStreamType type, string[] languagePreferences)
private static IEnumerable<MediaStream> GetSortedStreams(IEnumerable<MediaStream> streams, MediaStreamType type, IReadOnlyList<string> languagePreferences)
{
// Give some preference to external text subs for better performance
return streams.Where(i => i.Type == type)
return streams
.Where(i => i.Type == type)
.OrderBy(i =>
{
var index = FindIndex(languagePreferences, i.Language);
{
var index = languagePreferences.FindIndex(x => string.Equals(x, i.Language, StringComparison.OrdinalIgnoreCase));
return index == -1 ? 100 : index;
})
.ThenBy(i => GetBooleanOrderBy(i.IsDefault))
.ThenBy(i => GetBooleanOrderBy(i.SupportsExternalStream))
.ThenBy(i => GetBooleanOrderBy(i.IsTextSubtitleStream))
.ThenBy(i => GetBooleanOrderBy(i.IsExternal))
.ThenBy(i => i.Index);
return index == -1 ? 100 : index;
})
.ThenBy(i => GetBooleanOrderBy(i.IsDefault))
.ThenBy(i => GetBooleanOrderBy(i.SupportsExternalStream))
.ThenBy(i => GetBooleanOrderBy(i.IsTextSubtitleStream))
.ThenBy(i => GetBooleanOrderBy(i.IsExternal))
.ThenBy(i => i.Index);
}
public static void SetSubtitleStreamScores(
List<MediaStream> streams,
string[] preferredLanguages,
IReadOnlyList<MediaStream> streams,
IReadOnlyList<string> preferredLanguages,
SubtitlePlaybackMode mode,
string audioTrackLanguage)
{
@@ -122,70 +113,52 @@ namespace Emby.Server.Implementations.Library
return;
}
streams = GetSortedStreams(streams, MediaStreamType.Subtitle, preferredLanguages)
.ToList();
var sortedStreams = GetSortedStreams(streams, MediaStreamType.Subtitle, preferredLanguages);
var filteredStreams = new List<MediaStream>();
if (mode == SubtitlePlaybackMode.Default)
{
// Prefer embedded metadata over smart logic
filteredStreams = streams.Where(s => s.IsForced || s.IsDefault)
filteredStreams = sortedStreams.Where(s => s.IsForced || s.IsDefault)
.ToList();
}
else if (mode == SubtitlePlaybackMode.Smart)
{
// Prefer smart logic over embedded metadata
if (!preferredLanguages.Contains(audioTrackLanguage, StringComparer.OrdinalIgnoreCase))
if (!preferredLanguages.Contains(audioTrackLanguage, StringComparison.OrdinalIgnoreCase))
{
filteredStreams = streams.Where(s => !s.IsForced && preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase))
filteredStreams = sortedStreams.Where(s => !s.IsForced && preferredLanguages.Contains(s.Language, StringComparison.OrdinalIgnoreCase))
.ToList();
}
}
else if (mode == SubtitlePlaybackMode.Always)
{
// always load the most suitable full subtitles
filteredStreams = streams.Where(s => !s.IsForced)
.ToList();
filteredStreams = sortedStreams.Where(s => !s.IsForced).ToList();
}
else if (mode == SubtitlePlaybackMode.OnlyForced)
{
// always load the most suitable full subtitles
filteredStreams = streams.Where(s => s.IsForced).ToList();
filteredStreams = sortedStreams.Where(s => s.IsForced).ToList();
}
// load forced subs if we have found no suitable full subtitles
if (filteredStreams.Count == 0)
{
filteredStreams = streams
.Where(s => s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase))
.ToList();
}
var iterStreams = filteredStreams.Count == 0
? sortedStreams.Where(s => s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase))
: filteredStreams;
foreach (var stream in filteredStreams)
foreach (var stream in iterStreams)
{
stream.Score = GetSubtitleScore(stream, preferredLanguages);
}
}
private static int FindIndex(string[] list, string value)
{
for (var i = 0; i < list.Length; i++)
{
if (string.Equals(list[i], value, StringComparison.OrdinalIgnoreCase))
{
return i;
}
}
return -1;
}
private static int GetSubtitleScore(MediaStream stream, string[] languagePreferences)
private static int GetSubtitleScore(MediaStream stream, IReadOnlyList<string> languagePreferences)
{
var values = new List<int>();
var index = FindIndex(languagePreferences, stream.Language);
var index = languagePreferences.FindIndex(x => string.Equals(x, stream.Language, StringComparison.OrdinalIgnoreCase));
values.Add(index == -1 ? 0 : 100 - index);

View File

@@ -52,7 +52,7 @@ namespace Emby.Server.Implementations.Library
var genres = item
.GetRecursiveChildren(user, new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { nameof(Audio) },
IncludeItemTypes = new[] { BaseItemKind.Audio },
DtoOptions = dtoOptions
})
.Cast<Audio>()
@@ -80,7 +80,7 @@ namespace Emby.Server.Implementations.Library
{
return Guid.Empty;
}
}).Where(i => !i.Equals(Guid.Empty)).ToArray();
}).Where(i => !i.Equals(default)).ToArray();
return GetInstantMixFromGenreIds(genreIds, user, dtoOptions);
}
@@ -89,7 +89,7 @@ namespace Emby.Server.Implementations.Library
{
return _libraryManager.GetItemList(new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { nameof(Audio) },
IncludeItemTypes = new[] { BaseItemKind.Audio },
GenreIds = genreIds.ToArray(),
@@ -103,7 +103,7 @@ namespace Emby.Server.Implementations.Library
public List<BaseItem> GetInstantMixFromItem(BaseItem item, User user, DtoOptions dtoOptions)
{
if (item is MusicGenre genre)
if (item is MusicGenre)
{
return GetInstantMixFromGenreIds(new[] { item.Id }, user, dtoOptions);
}

View File

@@ -16,7 +16,7 @@ namespace Emby.Server.Implementations.Library
/// <param name="attribute">The attrib.</param>
/// <returns>System.String.</returns>
/// <exception cref="ArgumentException"><paramref name="str" /> or <paramref name="attribute" /> is empty.</exception>
public static string? GetAttributeValue(this string str, string attribute)
public static string? GetAttributeValue(this ReadOnlySpan<char> str, ReadOnlySpan<char> attribute)
{
if (str.Length == 0)
{
@@ -28,17 +28,31 @@ namespace Emby.Server.Implementations.Library
throw new ArgumentException("String can't be empty.", nameof(attribute));
}
string srch = "[" + attribute + "=";
int start = str.IndexOf(srch, StringComparison.OrdinalIgnoreCase);
if (start != -1)
var attributeIndex = str.IndexOf(attribute, StringComparison.OrdinalIgnoreCase);
// Must be at least 3 characters after the attribute =, ], any character.
var maxIndex = str.Length - attribute.Length - 3;
while (attributeIndex > -1 && attributeIndex < maxIndex)
{
start += srch.Length;
int end = str.IndexOf(']', start);
return str.Substring(start, end - start);
var attributeEnd = attributeIndex + attribute.Length;
if (attributeIndex > 0
&& str[attributeIndex - 1] == '['
&& (str[attributeEnd] == '=' || str[attributeEnd] == '-'))
{
var closingIndex = str[attributeEnd..].IndexOf(']');
// Must be at least 1 character before the closing bracket.
if (closingIndex > 1)
{
return str[(attributeEnd + 1)..(attributeEnd + closingIndex)].Trim().ToString();
}
}
str = str[attributeEnd..];
attributeIndex = str.IndexOf(attribute, StringComparison.OrdinalIgnoreCase);
}
// for imdbid we also accept pattern matching
if (string.Equals(attribute, "imdbid", StringComparison.OrdinalIgnoreCase))
if (attribute.Equals("imdbid", StringComparison.OrdinalIgnoreCase))
{
var match = ProviderIdParsers.TryFindImdbId(str, out var imdbId);
return match ? imdbId.ToString() : null;

View File

@@ -6,7 +6,10 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Emby.Naming.Audio;
using Emby.Naming.AudioBook;
using Emby.Naming.Common;
using Emby.Naming.Video;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
@@ -21,11 +24,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
/// </summary>
public class AudioResolver : ItemResolver<MediaBrowser.Controller.Entities.Audio.Audio>, IMultiItemResolver
{
private readonly ILibraryManager _libraryManager;
private readonly NamingOptions _namingOptions;
public AudioResolver(ILibraryManager libraryManager)
public AudioResolver(NamingOptions namingOptions)
{
_libraryManager = libraryManager;
_namingOptions = namingOptions;
}
/// <summary>
@@ -40,7 +43,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
string collectionType,
IDirectoryService directoryService)
{
var result = ResolveMultipleInternal(parent, files, collectionType, directoryService);
var result = ResolveMultipleInternal(parent, files, collectionType);
if (result != null)
{
@@ -56,12 +59,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
private MultiItemResolverResult ResolveMultipleInternal(
Folder parent,
List<FileSystemMetadata> files,
string collectionType,
IDirectoryService directoryService)
string collectionType)
{
if (string.Equals(collectionType, CollectionType.Books, StringComparison.OrdinalIgnoreCase))
{
return ResolveMultipleAudio<AudioBook>(parent, files, directoryService, false, collectionType, true);
return ResolveMultipleAudio(parent, files, true);
}
return null;
@@ -87,14 +89,10 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
return null;
}
var files = args.FileSystemChildren
.Where(i => !_libraryManager.IgnoreFile(i, args.Parent))
.ToList();
return FindAudio<AudioBook>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, false);
return FindAudioBook(args, false);
}
if (_libraryManager.IsAudioFile(args.Path))
if (AudioFileParser.IsAudioFile(args.Path, _namingOptions))
{
var extension = Path.GetExtension(args.Path);
@@ -107,7 +105,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
var isMixedCollectionType = string.IsNullOrEmpty(collectionType);
// For conflicting extensions, give priority to videos
if (isMixedCollectionType && _libraryManager.IsVideoFile(args.Path))
if (isMixedCollectionType && VideoResolver.IsVideoFile(args.Path, _namingOptions))
{
return null;
}
@@ -141,29 +139,23 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
return null;
}
private T FindAudio<T>(ItemResolveArgs args, string path, Folder parent, List<FileSystemMetadata> fileSystemEntries, IDirectoryService directoryService, string collectionType, bool parseName)
where T : MediaBrowser.Controller.Entities.Audio.Audio, new()
private AudioBook FindAudioBook(ItemResolveArgs args, bool parseName)
{
// TODO: Allow GetMultiDiscMovie in here
const bool supportsMultiVersion = false;
var result = ResolveMultipleAudio(args.Parent, args.GetActualFileSystemChildren(), parseName);
var result = ResolveMultipleAudio<T>(parent, fileSystemEntries, directoryService, supportsMultiVersion, collectionType, parseName) ??
new MultiItemResolverResult();
if (result.Items.Count == 1)
if (result == null || result.Items.Count != 1 || result.Items[0] is not AudioBook item)
{
// If we were supporting this we'd be checking filesFromOtherItems
var item = (T)result.Items[0];
item.IsInMixedFolder = false;
item.Name = Path.GetFileName(item.ContainingFolderPath);
return item;
return null;
}
return null;
// If we were supporting this we'd be checking filesFromOtherItems
item.IsInMixedFolder = false;
item.Name = Path.GetFileName(item.ContainingFolderPath);
return item;
}
private MultiItemResolverResult ResolveMultipleAudio<T>(Folder parent, IEnumerable<FileSystemMetadata> fileSystemEntries, IDirectoryService directoryService, bool suppportMultiEditions, string collectionType, bool parseName)
where T : MediaBrowser.Controller.Entities.Audio.Audio, new()
private MultiItemResolverResult ResolveMultipleAudio(Folder parent, IEnumerable<FileSystemMetadata> fileSystemEntries, bool parseName)
{
var files = new List<FileSystemMetadata>();
var items = new List<BaseItem>();
@@ -176,15 +168,13 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
{
leftOver.Add(child);
}
else if (!IsIgnored(child.Name))
else
{
files.Add(child);
}
}
var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions();
var resolver = new AudioBookListResolver(namingOptions);
var resolver = new AudioBookListResolver(_namingOptions);
var resolverResult = resolver.Resolve(files).ToList();
var result = new MultiItemResolverResult
@@ -210,7 +200,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
var firstMedia = resolvedItem.Files[0];
var libraryItem = new T
var libraryItem = new AudioBook
{
Path = firstMedia.Path,
IsInMixedFolder = isInMixedFolder,
@@ -230,12 +220,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
return result;
}
private bool ContainsFile(List<AudioBookInfo> result, FileSystemMetadata file)
private static bool ContainsFile(IEnumerable<AudioBookInfo> result, FileSystemMetadata file)
{
return result.Any(i => ContainsFile(i, file));
}
private bool ContainsFile(AudioBookInfo result, FileSystemMetadata file)
private static bool ContainsFile(AudioBookInfo result, FileSystemMetadata file)
{
return result.Files.Any(i => ContainsFile(i, file)) ||
result.AlternateVersions.Any(i => ContainsFile(i, file)) ||
@@ -246,10 +236,5 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
{
return string.Equals(result.Path, file.FullName, StringComparison.OrdinalIgnoreCase);
}
private static bool IsIgnored(string filename)
{
return false;
}
}
}

Some files were not shown because too many files have changed in this diff Show More