Compare commits

...

1118 Commits

Author SHA1 Message Date
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
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
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
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
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
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
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
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
Joshua M. Boniface
761a4e8415 Merge pull request #6837 from crobibero/auth-exception 2021-11-13 15:31:14 -05:00
Joshua M. Boniface
f0028c728f Merge pull request #6841 from joshuaboniface/azure-pre 2021-11-13 15:28:10 -05:00
Joshua M. Boniface
fb0f3c3a76 Send SourceBranch to collect-server.azure.sh 2021-11-13 14:45:02 -05:00
Claus Vium
2f92ee374a Merge pull request #6838 from crobibero/openapi-nullable
Add nullable dictionary openapi mapping
2021-11-13 19:32:11 +01:00
Cody Robibero
bb377b1466 Add nullable dictionary openapi mapping 2021-11-13 07:29:58 -07:00
Cody Robibero
4a28f46cac Don't throw exception on unauthenticated requests 2021-11-13 07:27:28 -07:00
Cody Robibero
8868b34d78 Merge pull request #6822 from NickSica/master 2021-11-13 07:03:40 -07:00
Cody Robibero
01a1209f0e Merge pull request #6836 from cvium/apphost_light_cleanup 2021-11-13 07:02:39 -07:00
cvium
5a65bc1e69 Very light cleanup in applicationhost 2021-11-13 14:37:26 +01:00
Nicholas Sica
8ae5316198 Fix Ombi auth through Jellyfin 2021-11-12 16:23:58 -05:00
WWWesten
1fbe1266e2 Added translation using Weblate (Telugu) 2021-11-12 12:56:18 -05:00
WWWesten
412ae7f4d2 Added translation using Weblate (Zulu) 2021-11-12 12:55:27 -05:00
WWWesten
26001fca93 Added translation using Weblate (Belarusian) 2021-11-12 12:09:25 -05:00
Claus Vium
8579c8f9ce Merge pull request #6830 from crobibero/remote-image
Fix filtering images without dimensions
2021-11-12 16:32:53 +01: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
Claus Vium
fcfc774da1 Merge pull request #6829 from crobibero/obsolete-enum
Remove Obsolete attribute on enum
2021-11-12 15:46:17 +01:00
Cody Robibero
14c072dd32 Fix filtering images without dimensions 2021-11-12 07:21:46 -07:00
Cody Robibero
132440c683 Remove Obsolete attribute on enum 2021-11-12 06:58:18 -07:00
Joe Rogers
de9bf327c6 Merge similar tests with Theories 2021-11-12 13:44:48 +01:00
Claus Vium
7b1314aff5 Merge pull request #6823 from crobibero/displaypreferencesdto
Fix nullability on DisplayPreferencesDto
2021-11-11 19:29:49 +01:00
Nicholas Sica
c5e42ddcc6 Fix Ombi auth through Jellyfin
Co-authored-by: Cody Robibero <cody@robibe.ro>
2021-11-11 11:03:27 -05:00
Cody Robibero
3de86ffdb4 Fix nullability on DisplayPreferencesDto
Remove duplicate, fix namespace
2021-11-11 07:34:36 -07:00
NickSica
4b2c40f717 Fixes Ombi auth through Jellyfin 2021-11-11 00:43:43 -05: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
Cody Robibero
4c88bf3fe3 Merge pull request #6808 from cvium/dlnope_never_again 2021-11-09 20:34:09 -07:00
Cody Robibero
57d5423d64 Merge pull request #6816 from Bond-009/warn55
Fix some warnings
2021-11-09 18:36:00 -07:00
cvium
efa76c0b63 Remove unused field 2021-11-09 23:17:27 +01:00
cvium
3f09fb8d70 length 2021-11-09 22:45:34 +01:00
Bond_009
1d19a5be61 Fix some warnings
down to 580
2021-11-09 22:29:33 +01:00
Cody Robibero
a7a6a22109 Merge pull request #6814 from thornbill/fix-issue-template 2021-11-09 13:21:39 -07:00
Bill Thornton
97508c6f42 Fix yaml format issue in issue template 2021-11-09 15:17:10 -05:00
Bond-009
296ba26b19 Merge pull request #6507 from Artiume/patch-6 2021-11-09 19:56:35 +01:00
Claus Vium
c3523e7cf7 Merge pull request #5905 from BaronGreenback/TVFix
Fix for Livetv and DLNA when bind interfaces specified.
2021-11-09 19:53:21 +01:00
Claus Vium
c50c9c3dbf Merge pull request #6794 from Bond-009/dead
Remove some dead code
2021-11-09 19:47:34 +01:00
cvium
a90735bc5a Last small fixes 2021-11-09 19:44:21 +01:00
cvium
37a04d5dbf Reduce indentation 2021-11-09 19:40:36 +01:00
cvium
e1f7f1405e Use GetOrderBy in GetChildrenSorted 2021-11-09 19:33:15 +01:00
cvium
6985a4f255 Fix SortCriteria and refactor SetSorting 2021-11-09 19:31:54 +01:00
cvium
53c16c2342 Build an array instead of using LINQ 2021-11-09 19:22:16 +01:00
cvium
c1c77c8762 comments 2021-11-09 19:19:48 +01:00
WWWesten
6bd108877e Translated using Weblate (Russian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ru/
2021-11-09 12:45:38 -05:00
Bond_009
994101fcf4 Remove some dead code 2021-11-09 16:28:39 +01:00
Bond-009
1cfd11b98c Merge pull request #6811 from jellyfin/dependabot/nuget/Mono.Nat-3.0.2 2021-11-09 16:24:13 +01:00
cvium
2b02b53fc0 Merge branch 'master' into dlnope_never_again 2021-11-09 16:00:14 +01:00
cvium
996500b2f8 review stuff 2021-11-09 15:57:39 +01:00
dependabot[bot]
ce1c36dbf2 Bump Mono.Nat from 3.0.1 to 3.0.2
Bumps [Mono.Nat](https://github.com/mono/Mono.Nat) from 3.0.1 to 3.0.2.
- [Release notes](https://github.com/mono/Mono.Nat/releases)
- [Commits](https://github.com/mono/Mono.Nat/compare/release-v3.0.1...release-v3.0.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-09 14:26:19 +00:00
Claus Vium
04040b25e0 Merge pull request #6810 from jellyfin/dependabot/nuget/Microsoft.SourceLink.GitHub-1.1.0
Bump Microsoft.SourceLink.GitHub from 1.0.0 to 1.1.0
2021-11-09 15:25:30 +01:00
Claus Vium
66912deb84 Apply suggestions from code review 2021-11-09 14:47:42 +01:00
Claus Vium
ac06022e0f Update Emby.Dlna/ContentDirectory/ControlHandler.cs 2021-11-09 14:40:51 +01:00
dependabot[bot]
c2d99dc3f0 Bump Microsoft.SourceLink.GitHub from 1.0.0 to 1.1.0
Bumps [Microsoft.SourceLink.GitHub](https://github.com/dotnet/sourcelink) from 1.0.0 to 1.1.0.
- [Release notes](https://github.com/dotnet/sourcelink/releases)
- [Commits](https://github.com/dotnet/sourcelink/compare/1.0.0...1.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-09 13:11:42 +00:00
Claus Vium
ca6211ad61 Merge pull request #6813 from Bond-009/warn54
Fix some warnings
2021-11-09 14:02:38 +01:00
Bond_009
5726535a26 Fix some warnings
609 left
2021-11-09 13:14:31 +01:00
Claus Vium
6f85e30475 Merge pull request #6806 from crobibero/dotnet6
Update to full dotnet 6
2021-11-09 08:35:33 +01:00
cvium
a236f52c31 Simplify and reduce LOC in ControlHandler 2021-11-08 23:13:12 +01:00
Cody Robibero
64652b6392 Fix and disable new dotnet6 warnings 2021-11-08 12:40:52 -07:00
hoanghuy309
958a4f509c Translated using Weblate (Vietnamese)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/vi/
2021-11-08 13:30:56 -05:00
Cody Robibero
40045d2147 Update to full dotnet 6 2021-11-08 09:40:12 -07:00
Cody Robibero
65971eb27e Merge pull request #6795 from LinFor/pr-dlna
Fix DLNA on older Samsung TVs
2021-11-08 05:38:22 -07:00
rimasx
15dd23e4da Translated using Weblate (Estonian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/et/
2021-11-08 04:58:49 -05:00
cvium
1c47211a9e Merge remote-tracking branch 'BaronGreenback/TVFix' into TVFix 2021-11-08 10:58:28 +01:00
cvium
82e6a21f3b Use the new method in DLNA 2021-11-08 10:58:04 +01:00
cvium
f03e77a4d5 Merge branch 'master' into TVFix 2021-11-08 10:38:08 +01:00
LinFor
5c69d110cc Samsung DLNA fixes 2021-11-08 11:24:33 +03:00
Claus Vium
3906343c91 Merge pull request #6793 from Bond-009/rootedpath
Add some docs and tests
2021-11-08 07:49:36 +01:00
Claus Vium
0ee43f897b Merge pull request #5918 from crobibero/client-logger
Add endpoint to log client events
2021-11-08 07:46:51 +01:00
Bond_009
4dfb7b18ae Add some docs and tests 2021-11-07 22:32:08 +01:00
Cody Robibero
666e95e27f Add randomization to generated filename 2021-11-07 11:41:56 -07:00
Claus Vium
195831ad4a Merge pull request #6792 from Bond-009/authex
Fix UnauthorizedAccessException in GetDrives
2021-11-07 19:36:09 +01:00
Cody Robibero
892b05c5e6 Clean up redundant code 2021-11-07 08:20:11 -07:00
Bond_009
0f52896691 Fix UnauthorizedAccessException in GetDrives
```
[15:01:24] [ERR] [55] Jellyfin.Server.Middleware.ExceptionMiddleware: Error processing request. URL GET /Environment/Drives.
System.UnauthorizedAccessException: Access to the path is denied.
 ---> System.IO.IOException: Operation not permitted
   --- End of inner exception stack trace ---
   at System.IO.DriveInfo.CheckStatfsResultAndThrowIfNecessary(Int32 result)
   at System.IO.DriveInfo.get_TotalSize()
   at Emby.Server.Implementations.IO.ManagedFileSystem.<>c.<GetDrives>b__32_0(DriveInfo d) in /home/bond/dev/jellyfin/Emby.Server.Implementations/IO/ManagedFileSystem.cs:line 583
   at System.Linq.Enumerable.WhereSelectArrayIterator`2.ToList()
   at Emby.Server.Implementations.IO.ManagedFileSystem.GetDrives() in /home/bond/dev/jellyfin/Emby.Server.Implementations/IO/ManagedFileSystem.cs:line 583
   at Jellyfin.Api.Controllers.EnvironmentController.GetDrives() in /home/bond/dev/jellyfin/Jellyfin.Api/Controllers/EnvironmentController.cs:line 153
   at lambda_method559(Closure , Object , Object[] )
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
```
2021-11-07 15:33:39 +01:00
Bond-009
83859a1e6d Merge pull request #6783 from 1337joe/purge-screenshot 2021-11-06 23:07:11 +01:00
Bond-009
8d8e113771 Merge pull request #6791 from cvium/fix_plugin_loading 2021-11-06 23:06:08 +01:00
cvium
d95c281142 Load all types when checking plugin DLLs 2021-11-06 22:44:05 +01:00
Cody Robibero
b217f84d50 Merge pull request #6778 from jvoisin/patch-1
Add a bit of hardening to the systemd service
2021-11-06 15:21:52 -06:00
Joe Rogers
b4bf5af7c8 Remove ImageType.Screenshot and ItemFields.Screenshot 2021-11-06 20:43:20 +01:00
Cody Robibero
c8bd676b14 Merge remote-tracking branch 'upstream/master' into client-logger 2021-11-05 22:25:48 -06:00
Cody Robibero
3c69283e2c Merge pull request #6784 from nielsvanvelzen/openapi-head-checkout
Fix OpenAPI workflow fork cloning
2021-11-05 17:50:58 -06:00
Niels van Velzen
07b9ba2bb4 Set GITHUB_TOKEN permissions to read only in OpenAPI workflow 2021-11-05 22:43:09 +01:00
Niels van Velzen
2491dd513c Specify repository info in openapi head checkout 2021-11-05 22:12:43 +01:00
Cody Robibero
d3d9311f48 Merge remote-tracking branch 'upstream/master' into client-logger 2021-11-05 13:12:37 -06:00
Cody Robibero
17264a6020 Use client info from claims 2021-11-05 12:57:24 -06:00
Claus Vium
b64d9bcd40 Merge pull request #6782 from nielsvanvelzen/openapi-pr-target 2021-11-05 19:37:30 +01:00
Niels van Velzen
44dc647adb Fix OpenAPI workflow not working with pull requests from forks 2021-11-05 19:10:40 +01:00
Cody Robibero
0cd817bba3 Merge pull request #6781 from 1337joe/tmdb-settings
Add MaxCastMembers to TMDb Plugin Settings
2021-11-05 05:56:51 -06:00
WWWesten
1e93c6ae30 Translated using Weblate (Esperanto)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/eo/
2021-11-05 07:05:36 -04:00
WWWesten
13668a6ecb Translated using Weblate (Russian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ru/
2021-11-05 07:05:36 -04:00
Joe Rogers
c8eba90c17 Add cast limit to tmdb plugin settings 2021-11-05 00:38:50 +01:00
Joe Rogers
6c76d30538 Add missing checkboxes 2021-11-04 23:58:32 +01:00
Claus Vium
a870f4ce70 Merge pull request #6777 from ThibaultNocchi/fix/webvtt_region 2021-11-04 23:37:36 +01:00
Bond-009
e3e6953c6d Merge pull request #6774 from cvium/fix_no_thumb_in_fanart 2021-11-04 17:50:33 +01:00
Julien Voisin
564990964d Add a bit of hardening to the systemd service
Tested in an unprivileged lxc container, so it shouldn't™ break anything.
2021-11-04 16:15:42 +01:00
Thibault Nocchi
f91839dd8c Fix WebVTT region to spec 2021-11-04 15:44:15 +01:00
cvium
c0bab5c173 Make sure ReadToDescendant was successful, #6773 2021-11-04 11:50:46 +01:00
WWWesten
5aadf8c291 Translated using Weblate (Esperanto)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/eo/
2021-11-04 04:56:26 -04:00
WWWesten
654bd6fff1 Translated using Weblate (Turkish)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/tr/
2021-11-04 04:56:26 -04:00
nextlooper42
70b9f9bf56 Translated using Weblate (Slovak)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sk/
2021-11-04 04:56:26 -04:00
Claus Vium
ad7ed95b98 Merge pull request #6769 from Bond-009/hasscreenshots 2021-11-04 09:21:36 +01:00
Bond_009
924c6682b9 Remove unused IHasScreenshots interface 2021-11-04 01:06:21 +01:00
Claus Vium
5c5d49ee60 Merge pull request #6763 from 1337joe/tmdb-image-provider-dedup 2021-11-04 00:22:08 +01:00
Claus Vium
4279f13c67 Merge pull request #6766 from Bond-009/minor12 2021-11-04 00:18:34 +01:00
Joe Rogers
4fc0521d69 Move ConvertToRemoteImage to TmdbClientManager 2021-11-03 17:16:40 +01:00
Cody Robibero
3398f7f953 Merge branch 'master' into client-logger 2021-11-03 07:52:06 -06:00
Bond_009
416894008e Minor improvements
* Removed some allocations
* Removed some useless abstractions
2021-11-03 14:02:57 +01:00
Claus Vium
45ceba7ad1 Merge pull request #6764 from zehnerGIT/logspam 2021-11-03 13:02:15 +01:00
Claus Vium
6822693bd6 Merge pull request #6748 from ptalmeida/master 2021-11-03 13:01:53 +01:00
Claus Vium
0187500373 Merge pull request #6761 from Bond-009/startup2 2021-11-03 13:01:37 +01:00
Claus Vium
869d537aaa Merge pull request #6752 from 1337joe/fix-metadata-refresh-deletes-backgrounds 2021-11-03 13:01:23 +01:00
Cody Robibero
f444e93a56 Merge remote-tracking branch 'upstream/master' into client-logger 2021-11-02 17:56:12 -06:00
Joe Rogers
149c77d9b1 Remove commented theory data, merge tests 2021-11-02 22:46:53 +01:00
Joe Rogers
2b283d249f Switch to method per image conversion 2021-11-02 21:12:13 +01:00
Claus Vium
2c42d75288 Merge pull request #6027 from fredriklindberg/improve-series-matching 2021-11-02 20:17:49 +01:00
Claus Vium
a9c38870f9 Merge pull request #6379 from dearjoey/master 2021-11-02 20:12:42 +01:00
Claus Vium
77634d3b52 Merge pull request #6765 from zehnerGIT/tmdbtags 2021-11-02 20:04:58 +01:00
Claus Vium
eec4293e6f Merge pull request #6308 from nielsvanvelzen/openapi 2021-11-02 19:43:57 +01:00
Niels van Velzen
63eeb73608 Update openapi workflow to use .NET 6 2021-11-02 18:58:31 +01:00
Joe Rogers
7fcf01235c Change RemoveImages to array, improve download test 2021-11-02 16:16:06 +01:00
Bond_009
104e36f2f9 Streamline startup code 2021-11-02 16:02:52 +01:00
zehner
3d858955b6 Make tags import from TMDB configurable
new settings added
2021-11-02 15:11:01 +01:00
zehner
bbf40d6be2 Update StreamBuilder.cs
LogLevel INFO => DEBUG
2021-11-02 09:35:09 +01:00
Joe Rogers
7da6bd905a Fix edge case in multi-image replacing 2021-11-02 00:31:59 +01:00
Claus Vium
838225e962 Merge pull request #6762 from WWWesten/master
Add missing localization options
2021-11-02 00:06:27 +01:00
Joe Rogers
4a5e8b99a0 Extract duplicate code, add test 2021-11-01 23:17:00 +01:00
Pedro Almeida
5529625025 Translated using Weblate (Portuguese (Portugal))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/pt_PT/
2021-11-01 17:05:34 -04:00
WWWesten
967fd66ca9 Update LocalizationManager.cs 2021-11-02 00:22:16 +05:00
WWWesten
a229526454 Update LocalizationManager.cs 2021-11-01 23:47:31 +05:00
WWWesten
0a14279e2a Merge branch 'jellyfin:master' into master 2021-11-01 23:43:29 +05:00
Claus Vium
76eeb8f655 Merge pull request #6745 from crobibero/dlna-profile-save
Use correct id when finding existing dlna profile
2021-11-01 17:19:43 +01:00
Joe Rogers
6881cf6874 Merge remote-tracking branch 'origin/master' into fix-metadata-refresh-deletes-backgrounds 2021-11-01 16:41:05 +01:00
Bond-009
e8efc433fa Merge pull request #6757 from jellyfin/dependabot/nuget/Microsoft.NET.Test.Sdk-17.0.0 2021-11-01 16:19:36 +01:00
Bond-009
98587da53d Merge pull request #6759 from jellyfin/dependabot/nuget/UTF.Unknown-2.5.0 2021-11-01 16:19:01 +01:00
Bond-009
09909d4df2 Merge pull request #6758 from jellyfin/dependabot/nuget/SQLitePCLRaw.bundle_e_sqlite3-2.0.7 2021-11-01 16:17:54 +01:00
dependabot[bot]
2372931b13 Bump UTF.Unknown from 2.4.0 to 2.5.0
Bumps [UTF.Unknown](https://github.com/CharsetDetector/UTF-unknown) from 2.4.0 to 2.5.0.
- [Release notes](https://github.com/CharsetDetector/UTF-unknown/releases)
- [Commits](https://github.com/CharsetDetector/UTF-unknown/compare/v2.4...v2.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 12:01:04 +00:00
dependabot[bot]
8e046ce22b Bump SQLitePCLRaw.bundle_e_sqlite3 from 2.0.6 to 2.0.7
Bumps [SQLitePCLRaw.bundle_e_sqlite3](https://github.com/ericsink/SQLitePCL.raw) from 2.0.6 to 2.0.7.
- [Release notes](https://github.com/ericsink/SQLitePCL.raw/releases)
- [Commits](https://github.com/ericsink/SQLitePCL.raw/compare/v2.0.6...v2.0.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 12:00:57 +00:00
dependabot[bot]
baafa10e87 Bump Microsoft.NET.Test.Sdk from 16.11.0 to 17.0.0
Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 16.11.0 to 17.0.0.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Commits](https://github.com/microsoft/vstest/compare/v16.11.0...v17.0.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 12:00:53 +00:00
Joe Rogers
b478b115e3 Refactor to validate all images up front 2021-11-01 11:53:31 +01:00
Anthony Lavado
022e2d9f97 Merge pull request #6740 from zirdum/master 2021-10-31 21:36:07 -04:00
Joe Rogers
0fbd8d85c8 Validate multi-images, lazy-delete bg on refresh
Fix failing test: Invalid background images not purged by validate
Fixes #6310: Background images only delete when using "Replace existing images" when new image(s) is found to replace them
2021-11-01 00:16:11 +01:00
Joe Rogers
080b02cc4c Add comments, minor cleanup, add tests 2021-10-31 23:56:50 +01:00
Cody Robibero
7b89e0e3a5 Fix tests 2021-10-31 11:06:47 -06:00
Orry Verducci
9abe9e7e54 Add rounding to the time base check 2021-10-31 17:04:04 +00:00
Pedro Almeida
10a173c011 Add pt-pt as culture
Makes pt-pt selectable as metadata language
2021-10-31 15:28:51 +00:00
Pedro Almeida
a22c57ff33 Fix localization typo with Réunion 2021-10-31 15:13:23 +00:00
Cody Robibero
2f6437a987 Use correct id when finding existing dlna profile 2021-10-31 08:49:24 -06:00
Orry Verducci
3a89e88033 Merge remote-tracking branch 'upstream/master' into mbaff-interlace-detection 2021-10-31 10:04:14 +00:00
Cody Robibero
f4844c08a5 Update Jellyfin.Api/Models/ClientLogDtos/ClientLogDocumentResponseDto.cs
Co-authored-by: Niels van Velzen <nielsvanvelzen@users.noreply.github.com>
2021-10-30 11:29:22 -06:00
Alan Azar
5a7433472e Translated using Weblate (Arabic)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ar/
2021-10-30 01:05:32 -04:00
Cody Robibero
73201ed498 Default log upload to enabled 2021-10-29 06:33:46 -06:00
Cody Robibero
bcb1c9b652 Use response dto 2021-10-29 06:33:34 -06:00
Cody Robibero
0e584f6840 Update documentation; use information from authorization; return generated filename 2021-10-28 16:13:37 -06:00
Kenneth SB
17973964fa Translated using Weblate (Danish)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/da/
2021-10-28 13:05:32 -04:00
Alan Azar
fc2e826b4d Translated using Weblate (Arabic)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ar/
2021-10-28 13:05:32 -04:00
Cody Robibero
91204fc9f0 Fix logfile name if api key is used 2021-10-27 19:40:35 -06:00
Cody Robibero
c534c45033 Suggestions from review 2021-10-27 19:20:14 -06:00
zirdum
71ed47a5d3 Update README.md
The link with 'blob' specified in the URL doesn't work for the current version of unRaid. Switching it to 'tree' (which is where the 'blob' link resolves to) works fine.

Changes
Changed link referenced: https://github.com/jellyfin/jellyfin/blob/master/deployment/unraid/docker-templates

To this link: https://github.com/jellyfin/jellyfin/tree/master/deployment/unraid/docker-templates

Issues
Fixes template showing up in unRaid with the changes applied.
2021-10-27 10:54:54 -07:00
zirdum
4885f5e6c9 Update README.md
The link with 'blob' specified in the URL doesn't work for the current version of unRaid. Switching it to 'tree' (which is where the 'blob' link resolves to) works fine.

Changes
Changed link referenced: https://github.com/jellyfin/jellyfin/blob/master/deployment/unraid/docker-templates

To this link: https://github.com/jellyfin/jellyfin/tree/master/deployment/unraid/docker-templates

Issues
Fixes template showing up in unRaid with the changes applied.
2021-10-27 10:54:18 -07:00
De sousa John
4599ce659c Translated using Weblate (French)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fr/
2021-10-27 08:05:33 -04:00
WWWesten
91655bb5fe Translated using Weblate (Esperanto)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/eo/
2021-10-27 08:05:33 -04:00
Alan Azar
a1b63aaa08 Translated using Weblate (Arabic)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ar/
2021-10-27 08:05:33 -04:00
Claus Vium
b0e0eba667 Merge pull request #6737 from Bond-009/nullable9
Enable nullable for MediaBrowser.Providers
2021-10-27 09:04:18 +02:00
Bond-009
2d4066748d Merge pull request #6446 from Deathspike/master 2021-10-27 09:01:00 +02:00
Cody Robibero
a6357f89ab Add ability to upload entire file 2021-10-26 18:42:17 -06:00
Cody Robibero
f78f1e834c Merge remote-tracking branch 'upstream/master' into client-logger 2021-10-26 17:43:36 -06:00
Deathspike
2410b3a3cf Resolve subtitle selection feedback (#6446) 2021-10-26 20:51:35 +02:00
Bond_009
f5ca9cbc3b Enable nullable for MediaBrowser.Providers 2021-10-26 15:49:01 +02:00
Claus Vium
39d5bdac96 Change ReadOnlySpan to string following PR 6383 (#6734) 2021-10-26 14:47:34 +02:00
Claus Vium
1b478cfdec Merge pull request #6735 from Bond-009/nullable8
Enable nullable for more files
2021-10-26 14:35:32 +02:00
Bond_009
1b6eb2ff2d Enable nullable for more files 2021-10-26 13:56:30 +02:00
Roel van Uden
b830d38a34 Rework subtitle selection to reduce code clutter 2021-10-26 12:59:11 +02:00
Claus Vium
dc72d90703 Merge pull request #6383 from sushilicious/master
Made default parser a tiny bit mroe robust
2021-10-26 12:10:57 +02:00
Claus Vium
deb349f4c5 Merge pull request #5755 from BaronGreenback/NetworkAccessPolicy 2021-10-26 00:06:31 +02:00
Claus Vium
26cfde8765 Merge pull request #6551 from MrChip53/xmltv-improve 2021-10-26 00:03:37 +02:00
Claus Vium
8b2309df82 Merge pull request #6535 from Bond-009/dlnacontrollertests 2021-10-25 23:47:37 +02:00
Claus Vium
5eda5eb636 Merge pull request #6486 from fredriklindberg/support-forwarded-headers-for-api-url 2021-10-25 22:41:32 +02:00
Joshua M. Boniface
da6225fb73 Merge pull request #6680 from MarcelCoding/master
Add Docker Healthcheck
2021-10-24 12:03:53 -04:00
Bond-009
ca217270b7 Merge pull request #6544 from cvium/fix_ffmpeg_path_updating 2021-10-24 01:09:44 +02:00
ButterflyOfFire
f2656b7ee2 Translated using Weblate (Arabic)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ar/
2021-10-23 10:36:41 -04:00
WWWesten
d4c1912e64 Translated using Weblate (Esperanto)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/eo/
2021-10-23 06:39:31 -04:00
rimasx
1e69530752 Translated using Weblate (Estonian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/et/
2021-10-22 08:05:31 -04:00
WWWesten
b53dea7113 Translated using Weblate (Esperanto)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/eo/
2021-10-22 08:05:31 -04:00
Claus Vium
768ec60e11 Merge pull request #6689 from 1337joe/expand-image-extraction 2021-10-21 23:05:32 +02:00
Bond-009
197325020e Merge pull request #6716 from jellyfin/dependabot/nuget/Swashbuckle.AspNetCore.ReDoc-6.2.3 2021-10-20 14:43:15 +02:00
dependabot[bot]
1cf2ec26a3 Bump Swashbuckle.AspNetCore.ReDoc from 6.2.2 to 6.2.3
Bumps [Swashbuckle.AspNetCore.ReDoc](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) from 6.2.2 to 6.2.3.
- [Release notes](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/releases)
- [Commits](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/compare/v6.2.2...v6.2.3)

---
updated-dependencies:
- dependency-name: Swashbuckle.AspNetCore.ReDoc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-20 12:24:31 +00:00
Bond-009
4979a9597a Merge pull request #6714 from jellyfin/dependabot/nuget/Swashbuckle.AspNetCore-6.2.3 2021-10-20 14:23:54 +02:00
Bond-009
4cb0f6facf Merge pull request #6715 from jellyfin/dependabot/nuget/prometheus-net.DotNetRuntime-4.2.2 2021-10-20 14:23:35 +02:00
Bond-009
39bd559001 Merge pull request #6718 from MBR-0001/master 2021-10-20 14:22:59 +02:00
Joe Rogers
31baea072a Address review comments
Clean up style
Fix references in class summaries
Combine Where+FirstOrDefault queries
Break up large method, long lines
Add validation on file extension
Apply test naming conventions
Extract mock of Movie class, comment on why not mocking interface

Co-authored-by: Cody Robibero <cody@robibe.ro>
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-10-20 14:10:16 +02:00
Sindre S. Kjær
7d8fb947b6 Translated using Weblate (Norwegian Bokmål)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/nb_NO/
2021-10-19 15:25:05 -04:00
MBR-0001
ade3afad41 Add IsAutomated to SubtitleSearchRequest 2021-10-19 21:06:05 +02:00
Jessica
8388f7c462 Translated using Weblate (Welsh)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/cy/
2021-10-19 00:18:49 -04:00
WWWesten
4d32470715 Translated using Weblate (Esperanto)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/eo/
2021-10-18 14:01:35 -04:00
Jessica
dd0c1d3d27 Added translation using Weblate (Welsh) 2021-10-18 14:01:35 -04:00
dependabot[bot]
b084afa1a0 Bump prometheus-net.DotNetRuntime from 4.2.1 to 4.2.2
Bumps [prometheus-net.DotNetRuntime](https://github.com/djluck/prometheus-net.DotNetRuntime) from 4.2.1 to 4.2.2.
- [Release notes](https://github.com/djluck/prometheus-net.DotNetRuntime/releases)
- [Commits](https://github.com/djluck/prometheus-net.DotNetRuntime/compare/4.2.1...4.2.2)

---
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>
2021-10-18 12:01:09 +00:00
dependabot[bot]
0b937c32d5 Bump Swashbuckle.AspNetCore from 6.2.2 to 6.2.3
Bumps [Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) from 6.2.2 to 6.2.3.
- [Release notes](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/releases)
- [Commits](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/compare/v6.2.2...v6.2.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-18 12:00:59 +00:00
Joshua M. Boniface
5395892f66 Merge pull request #6695 from crobibero/dotnet6-rc2 2021-10-16 00:34:35 -04:00
rimasx
6cc4be85fc Translated using Weblate (Estonian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/et/
2021-10-14 16:05:30 -04:00
lyaschuchenko
a720b12ec3 Translated using Weblate (Ukrainian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/uk/
2021-10-14 16:05:30 -04:00
JULIAN AUGUSTO RUIZ MARTINEZ
e88e1fa8e9 Translated using Weblate (Pirate)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/pr/
2021-10-14 16:05:30 -04:00
Cody Robibero
2b10251b32 Update to dotnet6.rc2 2021-10-12 18:31:58 -06:00
Claus Vium
09f33d3b87 Merge pull request #6558 from dmitrylyzo/ffmpeg-exitcode 2021-10-13 00:04:09 +02:00
Claus Vium
6ab412ed00 Merge pull request #6681 from dmitrylyzo/fix-latest-sort-order 2021-10-13 00:02:03 +02:00
rimasx
e3edd7ae2c Added translation using Weblate (Estonian) 2021-10-11 15:39:58 -04:00
Bond-009
646733d298 Merge pull request #6687 from jellyfin/dependabot/nuget/Diacritics-3.3.4 2021-10-11 14:56:50 +02:00
Bond-009
12d9859113 Merge pull request #6688 from jellyfin/dependabot/nuget/Serilog.Settings.Configuration-3.3.0 2021-10-11 14:56:10 +02:00
Joe Rogers
e3eee10d05 Add image provider tests and clean up 2021-10-11 14:09:02 +02:00
Joe Rogers
8d70cc2dde Add support for non-jpg image extractions 2021-10-11 14:09:02 +02:00
Joe Rogers
6ce8cce12c Add handling for embedded background and logo 2021-10-11 14:09:01 +02:00
Joe Rogers
be9ed29f63 Split EmbeddedImage extracting to new provider 2021-10-11 14:09:01 +02:00
dependabot[bot]
37a87a41ba Bump Serilog.Settings.Configuration from 3.2.0 to 3.3.0
Bumps [Serilog.Settings.Configuration](https://github.com/serilog/serilog-settings-configuration) from 3.2.0 to 3.3.0.
- [Release notes](https://github.com/serilog/serilog-settings-configuration/releases)
- [Changelog](https://github.com/serilog/serilog-settings-configuration/blob/dev/CHANGES.md)
- [Commits](https://github.com/serilog/serilog-settings-configuration/commits)

---
updated-dependencies:
- dependency-name: Serilog.Settings.Configuration
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-11 12:00:53 +00:00
dependabot[bot]
59e3beb5fe Bump Diacritics from 2.1.20036.1 to 3.3.4
Bumps [Diacritics](https://github.com/thomasgalliker/Diacritics.NET) from 2.1.20036.1 to 3.3.4.
- [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-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-11 12:00:48 +00:00
Dmitry Lyzo
32f3d60a84 Throw on FFmpeg non-zero exit code 2021-10-10 19:53:32 +03:00
Dmitry Lyzo
c26e6d89b4 Move FfmpegException to MediaBrowser.Common 2021-10-10 19:48:11 +03:00
Marcel
b225c3fd3c Apply suggestions from code review
Co-authored-by: Cody Robibero <cody@robibe.ro>
2021-10-10 17:26:06 +02:00
Marcel
f750235933 Added healthcheck url environemnt variable 2021-10-10 15:15:43 +00:00
TheGoose
aa93774b29 Translated using Weblate (English (United Kingdom))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/en_GB/
2021-10-10 07:05:27 -04:00
Claus Vium
8fc4a48070 Merge pull request #6501 from crobibero/schedules-direct 2021-10-09 23:21:09 +02:00
Marcel
5d11fd68c6 Apply suggestions from code review
Co-authored-by: Cody Robibero <cody@robibe.ro>
2021-10-09 21:41:46 +02:00
Dmitry Lyzo
2b004e1f76 Add more sorting to Latest 2021-10-09 21:36:39 +03:00
Marcel
32d6e7db7c Apply suggestions from code review
Co-authored-by: Cody Robibero <cody@robibe.ro>
2021-10-09 17:00:20 +02:00
Cody Robibero
a81dfabdb6 Fix indentation and build errors 2021-10-09 07:16:50 -06:00
Claus Vium
e775286de5 Merge pull request #6646 from 1337joe/test-mp4-metadata 2021-10-09 12:48:30 +02:00
Claus Vium
1156699481 Merge pull request #6657 from Bond-009/dotnetbug 2021-10-09 12:19:44 +02:00
Marcel
fe461ff66b Added Docker Healthcheck 2021-10-09 08:25:22 +00:00
Claus Vium
1bfe6342df Merge pull request #6676 from Bond-009/rng
Use static crypto rng
2021-10-09 08:11:22 +02:00
Claus Vium
b16e6621b3 Merge pull request #6663 from crobibero/dotnet-6-rc1
Reference dotnet6-rc1 packages
2021-10-08 16:06:15 +02:00
Claus Vium
eea2ba9b68 Merge pull request #6678 from Bond-009/random
Use new Random.Shared instead of creating new instances
2021-10-08 16:04:23 +02:00
Claus Vium
851a5f3b55 Merge pull request #6665 from Bond-009/tests6
Improve test coverage for QuickConnectManager
2021-10-08 15:53:13 +02:00
Claus Vium
098b598293 Merge pull request #6677 from Bond-009/shuffle2
Remove duplicate Fisher–Yates shuffle impl
2021-10-08 15:51:51 +02:00
Cody Robibero
3bbd98cc3f Merge remote-tracking branch 'upstream/master' into schedules-direct 2021-10-08 07:49:40 -06:00
Bond-009
a01f9775ff Merge pull request #6667 from Bond-009/warn53 2021-10-08 15:43:38 +02:00
Bond_009
d05062fec0 Use new Random.Shared instead of creating new instances 2021-10-08 15:40:13 +02:00
Bond_009
dc8feca6bb Remove duplicate Fisher–Yates shuffle impl 2021-10-08 15:20:11 +02:00
Bond_009
3b492d4af8 Use static crypto rng 2021-10-08 15:02:58 +02:00
Bond-009
556ef5f157 Merge pull request #6673 from cvium/pinfile 2021-10-08 11:51:04 +02:00
cvium
3add805cbf Return the path to the pinfile in forgot password 2021-10-07 23:20:54 +02:00
Claus Vium
93198787d1 Merge pull request #6666 from Bond-009/issue6123 2021-10-07 21:56:37 +02:00
Bond-009
68aa5db2b5 Merge pull request #6670 from lyarenei/update-split-whitelist
Update artist split whitelist
2021-10-07 14:47:26 +02:00
Systerm
6297fa5bf7 Translated using Weblate (Portuguese)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/pt/
2021-10-06 17:39:23 -04:00
Bond_009
f7ae3c6a85 Set AnalysisMode to AllEnabledByDefault 2021-10-06 11:39:54 +02:00
Bond_009
03f933aaa0 Fix the last few warnings
Enables TreatWarningsAsErrors for all projects
2021-10-06 11:30:45 +02:00
Bond-009
c5285cee1c Merge pull request #6664 from cvium/subtitle_refresh 2021-10-06 10:48:32 +02:00
Bond-009
a1246ba3a0 Merge pull request #6649 from barronpm/implementations-warn2 2021-10-06 10:47:40 +02:00
Dominik Krivohlavek
ef99225c40 Add 22/7 to split whitelist 2021-10-06 10:32:28 +02:00
Patrick Barron
e0db541381 Update indentation 2021-10-05 22:07:16 -04:00
Bond_009
67147400bf Fix issue #6123 2021-10-05 21:47:59 +02:00
cvium
7abdf71c49 Revert to old line 2021-10-05 19:49:43 +02:00
Bond_009
74d75fad46 Improve test coverage for QuickConnectManager 2021-10-05 16:59:11 +02:00
cvium
229917a2f8 Queue refresh after subtitle upload + minor fixes 2021-10-04 21:12:09 +02:00
joanMelchor
d245e45254 Translated using Weblate (Catalan)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ca/
2021-10-04 14:05:26 -04:00
Cody Robibero
017380f1dd Reference dotnet6-rc1 packages 2021-10-04 07:43:40 -06:00
Bond-009
647c080ef7 Merge pull request #6662 from jellyfin/dependabot/nuget/DotNet.Glob-3.1.3 2021-10-04 15:07:37 +02:00
Bond-009
62d5315b0b Merge pull request #6661 from jellyfin/dependabot/nuget/sharpcompress-0.30.0 2021-10-04 15:07:11 +02:00
dependabot[bot]
fc96305e78 Bump DotNet.Glob from 3.1.2 to 3.1.3
Bumps [DotNet.Glob](https://github.com/dazinator/DotNet.Glob) from 3.1.2 to 3.1.3.
- [Release notes](https://github.com/dazinator/DotNet.Glob/releases)
- [Changelog](https://github.com/dazinator/DotNet.Glob/blob/develop/ReleaseNotes.md)
- [Commits](https://github.com/dazinator/DotNet.Glob/compare/3.1.2...3.1.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-04 12:01:09 +00:00
dependabot[bot]
2b61fad3a0 Bump sharpcompress from 0.29.0 to 0.30.0
Bumps [sharpcompress](https://github.com/adamhathcock/sharpcompress) from 0.29.0 to 0.30.0.
- [Release notes](https://github.com/adamhathcock/sharpcompress/releases)
- [Commits](https://github.com/adamhathcock/sharpcompress/compare/0.29...0.30)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-04 12:00:56 +00:00
Patrick Barron
232e48f5e8 Fix warnings in EmbyTV 2021-10-03 21:41:22 -04:00
Patrick Barron
25b68bc3b2 Fix warnings in ChannelManager 2021-10-03 21:41:22 -04:00
Patrick Barron
b7e405889d Fix warnings in LibraryChangedNotifier 2021-10-03 21:41:22 -04:00
Patrick Barron
6cc69b80b6 Fix warnings in DeviceId 2021-10-03 21:41:22 -04:00
Patrick Barron
80223c548c Fix warnings in WebSocketConnection 2021-10-03 21:41:22 -04:00
Patrick Barron
7180983654 Fix warnings in SessionManager 2021-10-03 21:41:22 -04:00
Patrick Barron
876a902356 Fix warnings in Library 2021-10-03 21:41:22 -04:00
Patrick Barron
aa3c33060d Fix warnings in Playlists 2021-10-03 21:41:22 -04:00
Patrick Barron
7ea4c844c8 Fix warnings in InstallationManager 2021-10-03 21:41:22 -04:00
Patrick Barron
b17a452d16 Fix warnings in ServerApplicationPaths 2021-10-03 21:41:22 -04:00
Patrick Barron
7ae055f740 Fix warnings in UdpServer 2021-10-03 21:41:22 -04:00
Patrick Barron
8c8ca9aded Fix warnings in UdpSocket 2021-10-03 21:41:22 -04:00
Patrick Barron
c09ef74b51 Fix warnings in IO 2021-10-03 21:41:22 -04:00
Patrick Barron
078200d8d4 Fix warnings in Sorting 2021-10-03 21:41:22 -04:00
Bond-009
1888e7ac21 Merge pull request #6656 from daullmer/vsc-net6 2021-10-03 20:28:10 +02:00
Bond_009
9af16fcb6c Remove workaround for dotnet/runtime#42790 2021-10-03 19:52:38 +02:00
David Ullmer
d284e09a8a Change .vscode/launch.json to use .NET 6 2021-10-03 18:38:21 +02:00
Bond-009
9718c0b2ee Merge pull request #6651 from KonH/fix_common_warnings 2021-10-03 17:17:56 +02:00
Bond-009
6a575b3f77 Merge pull request #6648 from barronpm/implementations-warn1 2021-10-03 17:13:39 +02:00
Claus Vium
c60428f869 Merge pull request #6580 from Artiume/patch-1 2021-10-03 14:04:45 +02:00
Claus Vium
4fb4ceab04 Merge pull request #6644 from Bond-009/nullable7 2021-10-03 14:03:56 +02:00
Claus Vium
1f779ce7cd Merge pull request #6641 from Bond-009/convertfrom 2021-10-03 14:03:46 +02:00
KonH
6cbfdea4c0 Fix warning: Type cast is redundant (#2149) 2021-10-03 11:05:18 +07:00
KonH
d45fcdd5af Fix warning: Redundant control flow jump statement (#2149) 2021-10-03 11:02:53 +07:00
KonH
e3fccd5ae6 Fix warning: Qualifier is redundant (#2149) 2021-10-03 11:01:40 +07:00
KonH
b6bf43af45 Fix warning: Using directive is not required by the code and can be safely removed (#2149) 2021-10-03 10:49:41 +07:00
KonH
7c282ec369 Fix warning: The nullable warning suppression expression is redundant (#2149) 2021-10-03 10:43:41 +07:00
Patrick Barron
21007aec20 Fix warnings in Data 2021-10-02 13:03:04 -04:00
Patrick Barron
4ba9b6c305 Fix warnings in ScheduledTasks 2021-10-02 12:53:51 -04:00
Patrick Barron
5043a887cc Document IStartupOptions 2021-10-02 11:54:31 -04:00
Joe Rogers
4c2adc39c7 Add test data and unit test for mp4 metadata probe 2021-10-01 22:03:12 +02:00
Bond_009
1ee58bf020 Enable nullable for ItemDataProvider 2021-10-01 11:21:22 +02:00
Bond_009
d4373a2ddb Use ConvertFrom with invariant culture instead of current culture 2021-10-01 10:54:06 +02:00
Claus Vium
531efc345a Merge pull request #6639 from 1337joe/mp4-track-title-fallback
Add mp4 track title fallback
2021-10-01 08:15:34 +02:00
Joe Rogers
ce0457faf5 Add mp4 track title fallback (#6638) 2021-09-30 23:53:33 +02:00
Tim040
7bf2ece20e Translated using Weblate (Dutch)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/nl/
2021-09-30 10:30:07 -04:00
Bond-009
dd5e9e3fc6 Merge pull request #6631 from GodTamIt/dotnet-version 2021-09-30 11:05:59 +02:00
Chris Tam
1a70ba6a48 Update README for .NET version 2021-09-29 16:31:17 -04:00
Bond-009
be6fe62d52 Merge pull request #6629 from crobibero/globalize 2021-09-29 09:42:47 +02:00
Cody Robibero
6fb3ec0319 Disable DOTNET_SYSTEM_GLOBALIZATION_INVARIANT in docker images 2021-09-28 19:09:37 -06:00
Claus Vium
fa506b1ff6 Merge pull request #6627 from Bond-009/empty
Add regression test for #6560
2021-09-28 13:17:06 +02:00
Bond_009
055e04338e Add regression test for #6560 2021-09-28 12:03:32 +02:00
Bond-009
94b1236459 Merge pull request #6623 from jellyfin/dependabot/nuget/Swashbuckle.AspNetCore.ReDoc-6.2.2 2021-09-28 11:15:35 +02:00
dependabot[bot]
3d098173ff Bump Swashbuckle.AspNetCore.ReDoc from 6.2.1 to 6.2.2
Bumps [Swashbuckle.AspNetCore.ReDoc](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) from 6.2.1 to 6.2.2.
- [Release notes](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/releases)
- [Commits](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/compare/v6.2.1...v6.2.2)

---
updated-dependencies:
- dependency-name: Swashbuckle.AspNetCore.ReDoc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-28 09:11:16 +00:00
Bond-009
a085e5a62c Merge pull request #6622 from jellyfin/dependabot/nuget/Swashbuckle.AspNetCore-6.2.2 2021-09-28 11:10:35 +02:00
Bond-009
2def7043ce Merge pull request #6546 from ianjazz246/theorydata 2021-09-28 10:59:25 +02:00
dependabot[bot]
5b1feb1cea Bump Swashbuckle.AspNetCore from 6.2.1 to 6.2.2
Bumps [Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) from 6.2.1 to 6.2.2.
- [Release notes](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/releases)
- [Commits](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/compare/v6.2.1...v6.2.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-27 12:00:58 +00:00
Claus Vium
60f3d7ca6c Merge pull request #6618 from crobibero/zip-dir 2021-09-27 09:21:48 +02:00
Cody Robibero
7668cd13f5 Create output directory when extracting archive files 2021-09-26 16:23:43 -06:00
Bond-009
837d8feddc Merge pull request #6616 from crobibero/culture-info 2021-09-26 17:52:34 +02:00
Cody Robibero
9234e5bf80 Remove all instances of en-US culture 2021-09-26 09:11:25 -06:00
Bond-009
8858d8e597 Merge branch 'master' into theorydata 2021-09-25 22:24:57 +02:00
Bond-009
82cb685178 Merge pull request #6596 from crobibero/jeff-ext
Add Jellyfin.Extensions to nuget package publish
2021-09-25 22:18:28 +02:00
Claus Vium
17273a6075 Merge pull request #6614 from Bond-009/warn36 2021-09-25 20:50:31 +02:00
Claus Vium
c5491dc46c Merge pull request #6613 from Bond-009/randomaccess 2021-09-25 20:34:21 +02:00
Bond_009
79642af3b8 Fix some warnings 2021-09-25 20:32:53 +02:00
Claus Vium
b37829dfbf Merge pull request #6611 from Bond-009/error 2021-09-25 20:25:42 +02:00
Claus Vium
e6f3531f40 Merge pull request #6612 from Bond-009/async3 2021-09-25 20:22:42 +02:00
Bond_009
a4eede29ab Use RandomAccess instead of a FileStream where it makes sense 2021-09-25 20:17:12 +02:00
Bond_009
f31224fa8f Remove sync FileStream hack 2021-09-25 19:44:40 +02:00
Bond_009
65665de660 Fix user DB migration 2021-09-25 19:39:24 +02:00
Bond-009
2ee3e9e00f Merge pull request #6590 from jellyfin/dotnet6 2021-09-25 19:21:37 +02:00
Bond_009
4643fd5dcb Address comments 2021-09-25 18:15:46 +02:00
Cody Robibero
5e8d58a6a6 Update path for openapi spec 2021-09-25 07:51:55 -06:00
Mislav Milinković
d81c9a7a8c Translated using Weblate (Croatian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/hr/
2021-09-25 09:30:05 -04:00
Ouail Ouazani
984f17c64f Translated using Weblate (Arabic)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ar/
2021-09-25 09:30:05 -04:00
Cody Robibero
d156d49113 Update codeql dotnet version 2021-09-25 06:40:19 -06:00
Cody Robibero
4fc3de9b75 Fix builds for dotnet6 (#6595)
* Target net6.0

* Use new Enum.TryParse(ReadOnlySpan<char>) overload

* Replace RNGCryptoServiceProvider with RandomNumberGenerator

* ci - target net6.0 (#6594)

* Update deployment for dotnet6

* Use generic 6.0.x preview for CI

* Update direct dotnet download links

Co-authored-by: Bond_009 <bond.009@outlook.com>
2021-09-25 06:21:48 -06:00
Bond_009
e627b1b154 Fix failing tests 2021-09-25 13:58:16 +02:00
Bond_009
5fd315b17c Address comments 2021-09-24 20:15:46 +02:00
Bond_009
086d5925c9 Update Jellyfin.Extensions to .Net6 2021-09-24 20:15:46 +02:00
Cody Robibero
be00480fe2 ci - target net6.0 (#6594) 2021-09-24 20:15:46 +02:00
Bond_009
fb2f07dc84 Replace RNGCryptoServiceProvider with RandomNumberGenerator 2021-09-24 20:15:46 +02:00
Bond_009
4d1d9f23d5 Use new Enum.TryParse(ReadOnlySpan<char>) overload 2021-09-24 20:15:46 +02:00
Bond_009
13fbfe6091 Target net6.0 2021-09-24 20:15:46 +02:00
Claus Vium
1ebd3c9ac3 Merge pull request #6593 from Bond-009/ex 2021-09-22 09:21:41 +02:00
Claus Vium
7c8a81f7bc Merge pull request #6592 from Bond-009/dlna3 2021-09-22 09:19:24 +02:00
Claus Vium
8d9114dea3 Merge pull request #6597 from Bond-009/subs 2021-09-22 08:20:57 +02:00
Bond_009
dc1b726ef8 Add regression test for #5323 2021-09-22 02:00:17 +02:00
Cody Robibero
a605a38499 Add Jellyfin.Extensions to nuget package publish 2021-09-21 17:05:34 -06:00
Bond-009
12a54c070e Apply suggestions from code review
Co-authored-by: Cody Robibero <cody@robibe.ro>
2021-09-21 23:12:38 +02:00
Claus Vium
a353081ea3 Update MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs 2021-09-21 22:54:11 +02:00
Bond_009
8fec510971 ItemImageProvider: improve HTTP error handling 2021-09-21 22:47:30 +02:00
Bond_009
ec45808275 SsdpHttpClient: Ensure successful status code before reading response 2021-09-21 22:32:14 +02:00
cvium
95f344722c Don't set ffmpeg path from null to its Display value + add 404 2021-09-21 18:51:15 +00:00
Claus Vium
b4c0518001 Merge pull request #6588 from Bond-009/escape
Fix issue #6587
2021-09-21 20:49:14 +02:00
Claus Vium
46701e16b5 Merge pull request #6589 from Bond-009/ffmpeg3 2021-09-21 20:49:02 +02:00
evlian
f1498d49ca Translated using Weblate (Albanian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sq/
2021-09-21 12:30:06 -04:00
artiume
5b1813b699 update armv8 2021-09-21 11:46:01 -04:00
artiume
9e54ee1829 update armv7 2021-09-21 11:44:20 -04:00
Bond_009
52585a865e Validate ffmpeg path 2021-09-21 13:28:34 +02:00
Bond_009
f6622bd810 Fix issue #6587 2021-09-21 13:22:40 +02:00
Claus Vium
b598f0e9fb Merge pull request #6584 from Bond-009/datetime
Specify DateTimeStyles when possible
2021-09-21 08:17:55 +02:00
Joshua M. Boniface
18506f7c21 Merge pull request #6569 from crobibero/dotnet-5.0.10
Update to dotnet 5.0.10
2021-09-21 02:11:27 -04:00
Claus Vium
c38d19682c Merge pull request #6553 from ankenyr/master 2021-09-21 08:09:41 +02:00
Bond_009
653df7d8e5 Specify DateTimeStyles when possible 2021-09-21 01:21:45 +02:00
Claus Vium
9bb222b408 Merge pull request #6582 from Bond-009/shutdown
Allow shutdown while starting WebHost
2021-09-20 23:40:58 +02:00
Bond-009
747d464be3 Merge pull request #6541 from cvium/symlink_workaround 2021-09-20 22:39:35 +02:00
Bond-009
32ea4806f8 Merge pull request #6538 from cvium/livetv_oh_no 2021-09-20 22:38:44 +02:00
Bond_009
520aeb9a8e Allow shutdown while starting WebHost 2021-09-20 22:27:20 +02:00
Claus Vium
1b0e6b871b Merge pull request #6571 from Dixin/master
Fix extra folder name and type mapping.
2021-09-20 21:25:12 +02:00
Bond-009
eb0f7e071b Merge pull request #6576 from jellyfin/dependabot/nuget/DiscUtils.Udf-0.16.13
Bump DiscUtils.Udf from 0.16.4 to 0.16.13
2021-09-20 14:41:30 +02:00
artiume
7e8557fec6 Update Docker Image 2021-09-20 08:30:47 -04:00
dependabot[bot]
a77c38a813 Bump DiscUtils.Udf from 0.16.4 to 0.16.13
Bumps [DiscUtils.Udf](https://github.com/DiscUtils/DiscUtils) from 0.16.4 to 0.16.13.
- [Release notes](https://github.com/DiscUtils/DiscUtils/releases)
- [Changelog](https://github.com/DiscUtils/DiscUtils/blob/develop/Changelog.txt)
- [Commits](https://github.com/DiscUtils/DiscUtils/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-20 12:01:05 +00:00
Claus Vium
b51a3cbf98 Merge pull request #6567 from Bond-009/alloc 2021-09-20 09:43:04 +02:00
Dixin
27e32083a1 Update LINQ query according to code review feedback.
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-09-20 00:27:51 -07:00
Dixin
dc8420c7a2 Fix extra folder type resolving. 2021-09-19 16:54:00 -07:00
Cody Robibero
e7d6c45509 Upgrade to dotnet 5.0.10 2021-09-19 15:06:27 -06:00
Bond_009
9148820d89 Add more tests 2021-09-19 21:26:00 +02:00
Bond_009
a6d1e542e6 Reduce allocations 2021-09-19 20:53:31 +02:00
Claus Vium
a3a8e058bc Merge pull request #6563 from Bond-009/subtitleencoder 2021-09-19 10:35:03 +02:00
Claus Vium
e2b746dfce Merge pull request #6564 from Bond-009/azure
Fix Azure CI
2021-09-18 16:57:38 +02:00
Bond_009
d283702cac Fix Azure CI 2021-09-18 16:21:54 +02:00
Bond_009
b0194bce6c Add regression test for issue #5168 2021-09-18 15:31:45 +02:00
Bond_009
34b38454e0 Fix SubtitleEncoder and add regression tests 2021-09-18 15:23:55 +02:00
Bond_009
69cf8c1947 Add tests for DlnaController 2021-09-17 20:53:52 +02:00
gbrea
8d57afb55f Translated using Weblate (Galician)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/gl/
2021-09-17 03:30:05 -04:00
Claus Vium
9d46b3695f Merge pull request #6556 from nielsvanvelzen/openapi-security-scheme
Use standard Authorization header in OpenAPI specification
2021-09-16 08:14:58 +02:00
Meem Khan
b9407779e4 Translated using Weblate (Urdu (Pakistan))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ur_PK/
2021-09-15 17:30:00 -04:00
Niels van Velzen
e6c9add45a Use more specific test command 2021-09-15 19:32:55 +02:00
Niels van Velzen
be946cef87 Use standard Authorization header in OpenAPI specification 2021-09-15 19:28:20 +02:00
Fredrik Lindberg
90174f68e2 Dynamically populate LocalAddress based on HTTP request
Support populating the LocalAddress field in the system info
endpoint based on the x-forwarded-host and x-forwarded-proto header.

The x-forwarded-host header must contain both the host and port for
the url to be properly constructed.

Behind network configuration option that is disabled by default.
2021-09-14 21:38:11 +02:00
emmanuel billeaud
fffdf9f7b6 Translated using Weblate (French)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fr/
2021-09-14 08:30:06 -04:00
Claus Vium
fffb57bb15 Merge pull request #6502 from crobibero/publish-jeff-extension
Add Jellyfin.Extensions to package publish
2021-09-14 13:44:46 +02:00
Claus Vium
97b8a672b5 Merge pull request #6555 from jellyfin/dependabot/nuget/libse-3.6.2 2021-09-13 18:39:30 +02:00
Claus Vium
da7a6e9fe4 Merge pull request #6554 from jellyfin/dependabot/nuget/sharpcompress-0.29.0 2021-09-13 18:39:09 +02:00
Fredrik Lindberg
ea439c5ccf Improve series name matching
Add a series path resolver that attempts to extract only the series
name from a path that contains more information that just the name.
2021-09-13 17:59:33 +02:00
Rob
d557a5371e Update Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-09-13 08:32:28 -07:00
Rob
8d45656c51 Update Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-09-13 08:32:18 -07:00
Rob
96bc24b1dc Update Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-09-13 08:32:12 -07:00
Cody Robibero
ea3e66e918 Fix namespace 2021-09-13 06:32:26 -06:00
dependabot[bot]
b53c36ee4a Bump libse from 3.6.0 to 3.6.2
Bumps [libse](https://github.com/SubtitleEdit/subtitleedit) from 3.6.0 to 3.6.2.
- [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.0...3.6.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-13 12:01:30 +00:00
dependabot[bot]
65e10946d8 Bump sharpcompress from 0.28.3 to 0.29.0
Bumps [sharpcompress](https://github.com/adamhathcock/sharpcompress) from 0.28.3 to 0.29.0.
- [Release notes](https://github.com/adamhathcock/sharpcompress/releases)
- [Commits](https://github.com/adamhathcock/sharpcompress/compare/0.28.3...0.29)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-13 12:01:22 +00:00
cocool97
83b4d4d25a Translated using Weblate (French (Canada))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fr_CA/
2021-09-13 04:30:03 -04:00
ankenyr
2b5f3f294e Fixing #6269 by comparing PremiereDate when episode comparison would otherwise be equal. 2021-09-12 15:05:37 -07:00
Cody Robibero
7a7fe3e681 Fix types and property names 2021-09-12 13:56:26 -06:00
Mr. Chip53
1a8dcae5e4 Fix #6171 2021-09-12 13:30:53 -05:00
Claus Vium
f11f572997 Merge pull request #6457 from Izumiko/adult 2021-09-11 23:00:11 +02:00
ianjazz246
19b8bcaec4 Use TheoryData instead of MemberData and ClassData 2021-09-11 13:31:24 -07:00
ianjazz246
3313efce19 Revert "Use TheoryData in UrlDecodeQueryFeatureTest"
This reverts commit c5393b2579.
2021-09-11 13:29:58 -07:00
Claus Vium
62113c4603 Update Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs 2021-09-11 15:07:09 +02:00
Claus Vium
cec0dd94ba Update Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs 2021-09-11 15:06:56 +02:00
Claus Vium
6b8b7f1426 Update Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs
Co-authored-by: Bond-009 <bond.009@outlook.com>
2021-09-11 14:19:50 +02:00
cvium
e34aa22dc1 Remove AsyncFile.OpenRead 2021-09-11 14:09:22 +02:00
cvium
794b73c62d Use File.GetAttributes instead of creating a new FileInfo 2021-09-11 13:32:59 +02:00
cvium
3bc9f38833 Fix SA1614 and SA1116 2021-09-11 12:47:01 +02:00
cvium
30152c8d96 Include the MIT license 2021-09-11 12:39:52 +02:00
cvium
6a2df35b37 Read file length for symlinks, supersedes #5775 and #5824 2021-09-11 12:31:29 +02:00
ianjazz246
c5393b2579 Use TheoryData in UrlDecodeQueryFeatureTest 2021-09-10 20:11:16 -07:00
Claus Vium
00f7f68e53 Merge pull request #5648 from OancaAndrei/syncplay-sessions-fix
Fix session references in SyncPlay
2021-09-10 17:44:44 +02:00
Bond-009
d7109d4d82 Merge pull request #6531 from GodTamIt/img-lang
Fix images "not loading" after manual identification
2021-09-10 13:35:03 +02:00
cvium
ae0055c494 Missing linebreaks that Rider apparently can't just do for me? 2021-09-10 13:09:24 +02:00
cvium
ff328fefc5 Replace GetDirectStreamProviderByUniqueId with GetLiveStreamInfoByUniqueId 2021-09-10 12:53:45 +02:00
cvium
026a7af0e8 Don't throw when livestream file isn't found 2021-09-10 11:54:26 +02:00
cvium
a60a1ab89b Fix xmldoc 2021-09-10 11:46:08 +02:00
cvium
6637a3096a Remove the dependency on BaseAuthorizationHandler 2021-09-10 11:44:50 +02:00
cvium
8496d7638a Merge branch 'master' into NetworkAccessPolicy 2021-09-10 11:40:28 +02:00
hoanghuy309
7ce62194d1 Translated using Weblate (Vietnamese)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/vi/
2021-09-10 04:30:00 -04:00
cvium
1a5a74d2a9 Remove more unused args 2021-09-10 10:03:42 +02:00
cvium
f3573b061c Remove the unused arg 2021-09-10 09:56:48 +02:00
cvium
1603d1928e Kill ProgressiveFileCopier and seek to end for ongoing livetv 2021-09-10 09:29:14 +02:00
Chris Tam
b0cd1f5e39 Fix images "not loading" after manual identification 2021-09-09 19:16:15 -04:00
Claus Vium
b96dbbf553 Merge pull request #6534 from Bond-009/warn35 2021-09-09 19:40:21 +02:00
Bond_009
0d16c48998 Fix some warnings 2021-09-09 15:59:13 +02:00
Bond-009
448125f2b4 Merge pull request #6523 from cvium/fix_livetv_cts_disposed 2021-09-09 13:46:26 +02:00
hoanghuy309
1a5d8e89da Translated using Weblate (Vietnamese)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/vi/
2021-09-08 13:30:00 -04:00
Lukáš Kucharczyk
95f287e819 Translated using Weblate (Czech)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/cs/
2021-09-08 13:30:00 -04:00
Claus Vium
4f51a22081 Update Jellyfin.Networking/Manager/NetworkManager.cs
Co-authored-by: Cody Robibero <cody@robibe.ro>
2021-09-07 19:52:17 +02:00
Claus Vium
c794e48562 Merge pull request #6522 from ferferga/efcore-improvements 2021-09-07 19:40:03 +02:00
Fernando Fernández
e5980f8686 Fix typo in comment and remove useless ones 2021-09-07 19:25:04 +02:00
Claus Vium
9c628cad22 Merge pull request #6526 from jellyfin/Bond-009-patch-2 2021-09-07 14:49:50 +02:00
Bond-009
71ab4a5754 Fix it for real(tm) this time 2021-09-07 14:18:04 +02:00
Bond-009
8dc0911374 Fix log message 2021-09-07 14:03:32 +02:00
cvium
153e920239 Ignore published server url for local access 2021-09-07 11:48:06 +02:00
cvium
be9663ae89 Use GetSmartApiUrl instead (hopefully it works) 2021-09-07 10:27:55 +02:00
cvium
fdab8eebc9 Fix disposed exception when ffmpeg exits early in GetLiveHlsStream 2021-09-07 08:54:58 +02:00
Fernando Fernández
154b7d8505 Fix identation 2021-09-06 21:35:54 +02:00
Fernando Fernández
f4af78817d Move model configuration to its own classes 2021-09-06 21:15:31 +02:00
Fernando Fernández
c2652d21e1 Log EFCore migrations 2021-09-06 21:15:31 +02:00
Fernando Fernández
3d0b1ccae6 Remove all unused usings 2021-09-06 21:15:30 +02:00
Fernando Fernández
59b67584fc Use appHost.Resolve for accessing the context in Program.cs 2021-09-06 20:35:02 +02:00
Cody Robibero
23e6c918a2 Remove Linq to index search 2021-09-06 11:08:40 -06:00
Claus Vium
ec35b8b425 Merge pull request #6521 from ferferga/fix-typos
Fix Dockerfile typos
2021-09-06 18:23:19 +02:00
Fernando Fernández
488e276f01 Fix Dockerfile typos 2021-09-06 17:51:08 +02:00
artiume
d7b2fa62a3 10.7.7 2021-09-06 09:41:29 -04:00
Bond-009
92aa820f37 Merge pull request #6520 from jellyfin/dependabot/nuget/Swashbuckle.AspNetCore.ReDoc-6.2.1
Bump Swashbuckle.AspNetCore.ReDoc from 6.1.5 to 6.2.1
2021-09-06 15:08:03 +02:00
Bond-009
18bac550de Merge pull request #6519 from jellyfin/dependabot/nuget/FsCheck.Xunit-2.16.3
Bump FsCheck.Xunit from 2.16.1 to 2.16.3
2021-09-06 14:28:19 +02:00
dependabot[bot]
5f1b5cd305 Bump Swashbuckle.AspNetCore.ReDoc from 6.1.5 to 6.2.1
Bumps [Swashbuckle.AspNetCore.ReDoc](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) from 6.1.5 to 6.2.1.
- [Release notes](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/releases)
- [Commits](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/compare/v6.1.5...v6.2.1)

---
updated-dependencies:
- dependency-name: Swashbuckle.AspNetCore.ReDoc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-06 12:17:43 +00:00
Bond-009
9ea42c8b6c Merge pull request #6517 from jellyfin/dependabot/nuget/prometheus-net.DotNetRuntime-4.2.1
Bump prometheus-net.DotNetRuntime from 4.2.0 to 4.2.1
2021-09-06 14:17:04 +02:00
Bond-009
dddfac9ac4 Merge pull request #6516 from jellyfin/dependabot/nuget/Swashbuckle.AspNetCore-6.2.1
Bump Swashbuckle.AspNetCore from 6.1.5 to 6.2.1
2021-09-06 14:16:58 +02:00
Bond-009
a26b03b9d7 Merge pull request #6518 from jellyfin/dependabot/nuget/SQLitePCLRaw.bundle_e_sqlite3-2.0.6
Bump SQLitePCLRaw.bundle_e_sqlite3 from 2.0.5 to 2.0.6
2021-09-06 14:16:46 +02:00
dependabot[bot]
c52fc714aa Bump FsCheck.Xunit from 2.16.1 to 2.16.3
Bumps [FsCheck.Xunit](https://github.com/fsharp/FsCheck) from 2.16.1 to 2.16.3.
- [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.1...2.16.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-06 12:01:04 +00:00
dependabot[bot]
fdec42bccc Bump SQLitePCLRaw.bundle_e_sqlite3 from 2.0.5 to 2.0.6
Bumps [SQLitePCLRaw.bundle_e_sqlite3](https://github.com/ericsink/SQLitePCL.raw) from 2.0.5 to 2.0.6.
- [Release notes](https://github.com/ericsink/SQLitePCL.raw/releases)
- [Commits](https://github.com/ericsink/SQLitePCL.raw/compare/v2.0.5...v2.0.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-06 12:00:58 +00:00
dependabot[bot]
9e96f36131 Bump prometheus-net.DotNetRuntime from 4.2.0 to 4.2.1
Bumps [prometheus-net.DotNetRuntime](https://github.com/djluck/prometheus-net.DotNetRuntime) from 4.2.0 to 4.2.1.
- [Release notes](https://github.com/djluck/prometheus-net.DotNetRuntime/releases)
- [Commits](https://github.com/djluck/prometheus-net.DotNetRuntime/compare/4.2.0...4.2.1)

---
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>
2021-09-06 12:00:55 +00:00
dependabot[bot]
4a4a291aa9 Bump Swashbuckle.AspNetCore from 6.1.5 to 6.2.1
Bumps [Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) from 6.1.5 to 6.2.1.
- [Release notes](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/releases)
- [Commits](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/compare/v6.1.5...v6.2.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-06 12:00:53 +00:00
Claus Vium
74fef6c05b Merge pull request #6177 from Bond-009/async
Use async FileStreams where it makes sense
2021-09-06 13:55:34 +02:00
Claus Vium
bf0a0c8b62 Merge pull request #6494 from Bond-009/cleanup 2021-09-06 13:55:16 +02:00
Claus Vium
06242121c5 Merge pull request #4615 from strugee/fix-restart.sh 2021-09-06 13:53:23 +02:00
Claus Vium
7d8efa35fa Merge pull request #5092 from OancaAndrei/syncplay-clear-queue 2021-09-06 13:51:07 +02:00
Claus Vium
ba90b1215b Merge pull request #6515 from Maeur1/master
Update Intel Compute Runtime Resources
2021-09-06 13:50:03 +02:00
Mayur Panchal
cee884613d Update Intel Compute Runtime Resources 2021-09-06 20:55:00 +10:00
dkanada
f6c0db4bb5 merge branch 'master' into syncplay-sessions-fix 2021-09-06 13:42:48 +09:00
dkanada
5e3905d41a merge branch 'master' into syncplay-clear-queue 2021-09-06 13:35:58 +09:00
dkanada
e9508616cc Merge pull request #4005 from cromefire/patch-2
Add additional opts for systemd / upstart
2021-09-06 13:31:44 +09:00
dkanada
1716137a89 Merge pull request #6066 from jellyfin/dependabot/github_actions/cirrus-actions/rebase-1.5
Bump cirrus-actions/rebase from 1.4 to 1.5
2021-09-06 02:31:59 +09:00
dkanada
b8eb8940c7 Merge pull request #6257 from MrTimscampi/music-library-backdrop
Use artist backdrop for generated library image
2021-09-06 02:30:49 +09:00
Claus Vium
66659b0842 Merge pull request #6089 from BaronGreenback/IsRoot_fix
Set UserRootFolder.IsRoot to true
2021-09-05 15:25:40 +02:00
cvium
ffe5ae8056 Merge branch 'master' into TVFix 2021-09-05 10:11:17 +02:00
artiume
711db363aa Update issue report.yml 2021-09-04 15:31:24 -04:00
artiume
957c5ee061 Delete bug_report.md 2021-09-04 14:46:49 -04:00
artiume
37e388dec1 Convert Issue Template to YAML 2021-09-04 14:46:22 -04:00
Bond-009
ff83fabac3 Merge pull request #6456 from GodTamIt/vp8-vp9
Disambiguate vpx to vp8 or vp9
2021-09-04 16:26:07 +02:00
Bond-009
a569e5860f Merge pull request #6506 from Artiume/patch-5 2021-09-04 16:17:55 +02:00
artiume
30bc5369ca Update bug_report.md 2021-09-04 09:43:39 -04:00
artiume
0c1f27d2db Request FFmpeg version 2021-09-04 09:33:02 -04:00
Chris Tam
b205d5a032 Disambiguate vpx to vp8 or vp9 2021-09-04 07:36:17 -04:00
Claus Vium
8c463b9b81 Merge pull request #4799 from tommasodotNET/bug/authorization-header-issue
Authorization header parsing
2021-09-04 00:31:13 +02:00
cvium
907d9fa195 remove some newlines 2021-09-03 23:58:07 +02:00
cvium
1172ece856 remove leading and trailing whitespace from the key 2021-09-03 23:56:19 +02:00
Cody Robibero
7a0a675bd5 Add Jellyfin.Extensions to package publish 2021-09-03 14:21:33 -06:00
Cody Robibero
04973a489f use JsonOptions 2021-09-03 13:56:51 -06:00
cvium
60185f99c4 fix the build 2021-09-03 21:43:06 +02:00
Cody Robibero
0587b539ec Suggestions from review 2021-09-03 13:36:07 -06:00
cvium
6b3ecf2533 Merge branch 'master' into bug/authorization-header-issue 2021-09-03 21:33:41 +02:00
cvium
048c478b0d Merge branch 'master' into bug/authorization-header-issue 2021-09-03 21:25:18 +02:00
Claus Vium
e229f6d9bb Merge pull request #6499 from Bond-009/warn34
Fix some warnings
2021-09-03 21:14:10 +02:00
Cody Robibero
47e24a2cf7 Add SchedulesDirect json tests 2021-09-03 12:35:52 -06:00
Cody Robibero
058baf5abd Add IReadOnlyList extensions 2021-09-03 12:35:32 -06:00
Bond_009
637e86478f Fix some warnings 2021-09-03 19:32:11 +02:00
Claus Vium
fb5385f1df Merge pull request #6201 from barronpm/authenticationdb-efcore
Migrate Authentication DB to EF Core
2021-09-03 19:17:13 +02:00
Cody Robibero
ff9d14c811 Merge remote-tracking branch 'upstream/master' into authenticationdb-efcore 2021-09-03 11:01:55 -06:00
Cody Robibero
47be1bf69f Enable nullable for SchedulesDirect 2021-09-03 10:59:40 -06:00
Claus Vium
95ca1d5487 Merge pull request #6498 from Bond-009/invalidop
Fix InvalidOperationException when serializing MediaPathInfo
2021-09-03 18:45:06 +02:00
Bond-009
3ec7ecf399 Merge pull request #6358 from MrTimscampi/audio-people 2021-09-03 17:15:58 +02:00
Bond_009
b458f85c47 Fix InvalidOperationException when serializing MediaPathInfo 2021-09-03 16:39:03 +02:00
Bond-009
79e51b7fa2 Merge pull request #6475 from crobibero/warn-259810
Remove more and more warnings
2021-09-03 16:17:02 +02:00
siankatabg
2f360151c2 Translated using Weblate (Bulgarian)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/bg/
2021-09-03 09:29:58 -04:00
Cody Robibero
bfb37a9ed9 Fix typos 2021-09-03 07:21:21 -06:00
Cody Robibero
3f2c706575 Apply suggestions from code review
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-09-03 07:19:50 -06:00
Cody Robibero
611c20dba8 Fix indentation 2021-09-03 06:57:33 -06:00
Cody Robibero
8e498b01e7 Fix issues from merge 2021-09-03 06:57:04 -06:00
Cody Robibero
ec13412155 Merge remote-tracking branch 'upstream/master' into warn-259810 2021-09-03 06:56:45 -06:00
Patrick Barron
88157fcc77 Re-add documentation 2021-09-02 20:22:08 -04:00
Patrick Barron
098bd5cfa9 Remove IAuditableEntity 2021-09-02 20:18:46 -04:00
Claus Vium
b1e7cfd84c Merge pull request #6497 from Bond-009/fuzz1
Add SqliteItemRepository.ItemImageInfoFromValueString as a fuzzing target
2021-09-02 21:48:46 +02:00
Bond_009
286dabdc4b Add SqliteItemRepository.ItemImageInfoFromValueString as a fuzzing
target

and add test cases
2021-09-02 21:28:00 +02:00
Bond_009
e3dac4fda2 Use async FileStreams where it makes sense 2021-09-02 14:02:04 +02:00
Bond-009
620dd94970 Merge pull request #6495 from qsniyg/zero-activity-days
Allow zero activity log retention days
2021-09-02 13:15:37 +02:00
Gokdag Goktepe
4bed19e22f Translated using Weblate (Turkish)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/tr/
2021-09-02 04:29:58 -04:00
Claus Vium
ffef1baa2f Merge pull request #6485 from markshark05/patch-1
Update M3U Channel Name Precedence
2021-09-02 08:39:18 +02:00
qsniyg
2cf08dcd34 Allow zero activity log retention days 2021-09-01 15:52:59 -07:00
Mike
cf9c678406 Add subtitle format(codec) to stream display title (#5853)
Co-authored-by: Michał Kurek <michal.kurek@mail.com>
2021-09-01 18:59:59 +02:00
Bond_009
6f405dc36d Clean up VideoImageProvider 2021-09-01 18:47:24 +02:00
Bond-009
855f9c4a8e Merge pull request #6425 from boolemancer/boolemancer/fix_image_extractor
Fix explicit stream selection in MediaEncoder.ExtractImageInternal
2021-09-01 18:24:29 +02:00
Claus Vium
5ca88a835e Merge pull request #6492 from Bond-009/gitignore
Ignore Omnisharp crash logs
2021-09-01 14:45:05 +02:00
Bond_009
55c8fb7814 Ignore Omnisharp crash logs 2021-09-01 12:28:52 +00:00
Claus Vium
8ae1eb6c50 Merge pull request #6491 from Bond-009/fixbuild
Fix build
2021-09-01 14:23:50 +02:00
Bond_009
07f64102dd Fix build 2021-09-01 14:06:09 +02:00
Claus Vium
4cd372109d Merge pull request #6473 from Bond-009/nullable7
Enable nullable for more files
2021-09-01 09:28:19 +02:00
Claus Vium
501c7a639f Merge pull request #6474 from Bond-009/tests11 2021-09-01 09:24:57 +02:00
Patrick Barron
cb52ccc699 Update Jellyfin.Server.Implementations/Devices/DeviceManager.cs
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-08-31 10:57:48 -04:00
Mark Titorenkov
a0ee16d38d Update M3U Channel Name Precedence
Sets the ExtInf display name to have a higher precedence than the `tvg-name` attribute for channel names.

Usually `namInExtInf` is a more descriptive and human readable name if both it and `tvg-name` are available. `tvg-name` is more likely to be an internal identifier such as just the channel number with a prefix in my provider's case.
2021-08-31 15:12:09 +03:00
Claus Vium
e83d7a8667 Merge pull request #6327 from nyanmisaka/tonemap-overlay 2021-08-30 20:41:12 +02:00
Claus Vium
ae031fdd28 Merge branch 'master' into tonemap-overlay 2021-08-30 20:02:31 +02:00
Claus Vium
442e756395 Merge pull request #6183 from stanionascu/bdiso-playback 2021-08-30 19:54:06 +02:00
Claus Vium
b7e13f3a03 Merge pull request #5697 from Bond-009/ffmpeg2
Simplify the way we choose our ffmpeg
2021-08-30 19:36:51 +02:00
Bond_009
963ab2dab6 Simplify the way we choose our ffmpeg
* no longer search $PATH
* no longer require a full path
* don't fall back
2021-08-30 15:40:52 +02:00
Cody Robibero
ecb4b8e0aa Apply suggestions from code review
Co-authored-by: Bond-009 <bond.009@outlook.com>
2021-08-30 07:11:34 -06:00
Bond-009
9bf2769cdb Merge pull request #6434 from crobibero/docker-bullseye 2021-08-30 15:09:47 +02:00
Bond-009
bb685e4920 Merge pull request #6422 from daullmer/nfo-fanart 2021-08-30 15:02:25 +02:00
Bond-009
32a11c006d Merge pull request #6480 from jellyfin/dependabot/nuget/prometheus-net.DotNetRuntime-4.2.0
Bump prometheus-net.DotNetRuntime from 4.1.0 to 4.2.0
2021-08-30 14:25:30 +02:00
Bond-009
d07a6eb7e0 Merge pull request #6481 from jellyfin/dependabot/nuget/SQLitePCLRaw.bundle_e_sqlite3-2.0.5
Bump SQLitePCLRaw.bundle_e_sqlite3 from 2.0.4 to 2.0.5
2021-08-30 14:25:12 +02:00
Bond-009
07c7ee8f9f Merge pull request #6479 from jellyfin/dependabot/nuget/FsCheck.Xunit-2.16.1
Bump FsCheck.Xunit from 2.16.0 to 2.16.1
2021-08-30 14:24:48 +02:00
dependabot[bot]
e2fdab4be4 Bump SQLitePCLRaw.bundle_e_sqlite3 from 2.0.4 to 2.0.5
Bumps [SQLitePCLRaw.bundle_e_sqlite3](https://github.com/ericsink/SQLitePCL.raw) from 2.0.4 to 2.0.5.
- [Release notes](https://github.com/ericsink/SQLitePCL.raw/releases)
- [Commits](https://github.com/ericsink/SQLitePCL.raw/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-30 12:01:04 +00:00
dependabot[bot]
4c5f7207e3 Bump prometheus-net.DotNetRuntime from 4.1.0 to 4.2.0
Bumps [prometheus-net.DotNetRuntime](https://github.com/djluck/prometheus-net.DotNetRuntime) from 4.1.0 to 4.2.0.
- [Release notes](https://github.com/djluck/prometheus-net.DotNetRuntime/releases)
- [Commits](https://github.com/djluck/prometheus-net.DotNetRuntime/compare/4.1.0...4.2.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-30 12:00:56 +00:00
dependabot[bot]
e40fde04d6 Bump FsCheck.Xunit from 2.16.0 to 2.16.1
Bumps [FsCheck.Xunit](https://github.com/fsharp/FsCheck) from 2.16.0 to 2.16.1.
- [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.0...2.16.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-30 12:00:52 +00:00
Cody Robibero
d7459fa2ec Add missing xmldoc 2021-08-28 23:02:13 -06:00
Cody Robibero
cba07b1ca6 Remove more and more warnings 2021-08-28 16:32:50 -06:00
Bond_009
0f7c875076 Fix test 2021-08-28 20:53:34 +02:00
Bond_009
69ba539c70 Add more tests for LibraryStructureController 2021-08-28 20:12:25 +02:00
Bond_009
909573f2f1 Add tests for LibraryStructureController 2021-08-28 19:30:57 +02:00
Bond_009
645825db36 Enable nullable for more files 2021-08-28 17:32:09 +02:00
TheFeelTrain
e88367fe70 Translated using Weblate (Japanese)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ja/
2021-08-28 07:29:55 -04:00
Bond-009
48fdc63367 Merge pull request #6461 from jellyfin/dependabot/nuget/prometheus-net.AspNetCore-5.0.1
Bump prometheus-net.AspNetCore from 4.2.0 to 5.0.1
2021-08-27 18:33:54 +02:00
dependabot[bot]
41712e16be Bump prometheus-net.AspNetCore from 4.2.0 to 5.0.1
Bumps [prometheus-net.AspNetCore](https://github.com/prometheus-net/prometheus-net) from 4.2.0 to 5.0.1.
- [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/v4.2.0...v5.0.1)

---
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>
2021-08-27 15:32:56 +00:00
Bond-009
72c6e4920d Merge pull request #6462 from jellyfin/dependabot/nuget/prometheus-net-5.0.1
Bump prometheus-net from 4.2.0 to 5.0.1
2021-08-27 17:32:24 +02:00
wolong gl
59b8056add Translated using Weblate (Chinese (Simplified))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/zh_Hans/
2021-08-26 21:29:56 -04:00
Vinícius Costa
5bcd1648cb Translated using Weblate (Portuguese (Brazil))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/pt_BR/
2021-08-26 21:29:56 -04:00
SeanPai
c2bcceaa21 Translated using Weblate (Chinese (Traditional))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/zh_Hant/
2021-08-26 21:29:56 -04:00
Changho Park
80dc92238a Translated using Weblate (Korean)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ko/
2021-08-26 21:29:56 -04:00
lsousa
3ebede56fe Translated using Weblate (Portuguese)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/pt/
2021-08-26 21:29:56 -04:00
Weevild
6c7b9d4044 Translated using Weblate (Swedish)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sv/
2021-08-26 21:29:56 -04:00
Lukáš Kucharczyk
d3527334bc Translated using Weblate (Czech)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/cs/
2021-08-26 21:29:56 -04:00
Kaiay
74d22d2f9a Translated using Weblate (Chinese (Hong Kong))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/zh_Hant_HK/
2021-08-26 21:29:56 -04:00
Izumiko
7027e2feb2 Add 'includeAdult' option for TheMovieDb 2021-08-25 20:46:51 +08:00
Claus Vium
e15fea5dad Merge pull request #5228 from lbenini/baseitemkind-fixes 2021-08-23 22:30:05 +02:00
dependabot[bot]
efed4728e6 Bump prometheus-net from 4.2.0 to 5.0.1
Bumps [prometheus-net](https://github.com/prometheus-net/prometheus-net) from 4.2.0 to 5.0.1.
- [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/v4.2.0...v5.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-23 12:00:54 +00:00
wolong gl
98b72019e6 Translated using Weblate (Chinese (Simplified))
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/zh_Hans/
2021-08-23 03:29:54 -04:00
Marcin Woliński
7c7ad820c2 Translated using Weblate (Polish)
Translation: Jellyfin/Jellyfin
Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/pl/
2021-08-23 03:29:54 -04:00
Cody Robibero
50b3d74c95 Switch to TheoryData and clean up tests 2021-08-21 17:31:06 -06:00
Bond-009
8a460fc6ba Merge pull request #6444 from cvium/fix_liverecordingsplayback
Use ProgressiveFileStream for LiveRecordings endpoint
2021-08-21 16:15:15 +02:00
Bond-009
ec649fcaf5 Merge pull request #6445 from cvium/progressivefilestream_timeout
Add timeout to ProgressiveFileStream
2021-08-21 16:14:34 +02:00
cvium
468283bfb2 Move test to TypedBaseItem folder to avoid conflicts 2021-08-18 20:11:28 +02:00
Claus Vium
663c79cba8 Merge branch 'master' into baseitemkind-fixes 2021-08-18 18:25:48 +02:00
Joshua M. Boniface
72d3f7020a Merge branch 'master' into patch-2 2021-08-18 02:46:59 -04:00
Deathspike
95988ce33d Fix embedded subtitles taking priority over external ones 2021-08-17 20:15:16 +02:00
cvium
12a7fda0a6 Add timeout to ProgressiveFileStream 2021-08-17 19:18:26 +02:00
cvium
f23ef1f1b9 Use ProgressiveFileStream for LiveRecordings endpoint 2021-08-17 13:38:28 +02:00
Cody Robibero
b504d1f724 Also update arm, arm64 Dockerfile 2021-08-15 19:32:45 -06:00
Cody Robibero
33bf8e34d1 Update Dockerfile to use debian:bullseye-slim 2021-08-15 18:57:14 -06:00
MrTimscampi
7f52cda03c Make performer regex static 2021-08-16 00:22:36 +02:00
MrTimscampi
d82c2e4237 Address comments 2021-08-16 00:22:36 +02:00
MrTimscampi
8594ee7a22 Fix documentation for lyricist and arranger 2021-08-16 00:22:36 +02:00
MrTimscampi
c9b1cd1d8c Add some new music-related person types and parse from ffprobe 2021-08-16 00:22:36 +02:00
MrTimscampi
f35a527608 Add performers to the ffprobe normalization for audio 2021-08-16 00:22:36 +02:00
MrTimscampi
24083d2e38 Address comments 2021-08-16 00:22:36 +02:00
MrTimscampi
7e71c25059 Add test for audio file ffprobe normalization 2021-08-16 00:22:34 +02:00
MrTimscampi
3300d2d7d3 Enable people for audio files 2021-08-16 00:20:48 +02:00
boolemancer
2345646ff1 Fix explicit stream selection in MediaEncoder.ExtractImageInternal 2021-08-14 02:55:51 -07:00
Patrick Barron
8a1e55251e Fix devices migration 2021-08-13 21:28:17 -04:00
Patrick Barron
1615663bd2 Remove old response code documentation 2021-08-13 21:08:49 -04:00
Patrick Barron
1b197a2c2a Fix QuickConnect tests, move class to proper namespace 2021-08-13 21:08:38 -04:00
Patrick Barron
45f478f63e Merge branch 'master' into authenticationdb-efcore
# Conflicts:
#	Jellyfin.Server.Implementations/Security/AuthorizationContext.cs
#	MediaBrowser.Controller/Library/IUserManager.cs
#	MediaBrowser.Controller/Security/IAuthenticationRepository.cs
#	MediaBrowser.Controller/Session/ISessionManager.cs
2021-08-13 21:08:24 -04:00
Patrick Barron
15baf04bd2 Add IAuditableEntity 2021-08-13 20:35:31 -04:00
David Ullmer
bf441e49b9 Add test for fanart tag 2021-08-13 20:36:14 +02:00
David Ullmer
12e58840eb Modify FetchThumbNode method to read children of fanart tag 2021-08-13 20:33:53 +02:00
David Ullmer
577d665192 Move thumb tag parsing to separate method 2021-08-13 20:16:05 +02:00
Nyanmisaka
a84dc794c6 Merge branch 'master' into tonemap-overlay 2021-08-13 15:01:06 +08:00
sushilicious
6bc7d78f6f Update Emby.Naming/Video/CleanStringParser.cs
Cleaned up code a bit

Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-08-05 13:09:42 -07:00
sushilicious
b2a10609af Made CleanStringParser go through regexps only once 2021-08-04 23:25:54 -07:00
sushilicious
7fdef4b82b Merge branch 'master' of https://github.com/jellyfin/jellyfin into HEAD 2021-08-04 23:15:48 -07:00
Cody Robibero
398ca85944 Merge remote-tracking branch 'upstream/master' into baseitemkind-fixes 2021-08-04 06:24:58 -06:00
Cody Robibero
d212b6fb08 Clean test 2021-08-04 06:24:25 -06:00
Nyanmisaka
d4f09c6c9b Apply suggestions from code review
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-08-04 16:25:17 +08:00
sushilicious
460fe76467 Merge branch 'master' of https://github.com/jellyfin/jellyfin 2021-08-03 14:30:20 -07:00
sushilicious
26f8b501e7 Made CleanStringParser more robust
Now it can handle [...] at beginning of string
2021-08-03 14:19:36 -07:00
joey
0c9b64de4b optimize episode parser 2021-08-03 13:25:23 +08:00
nyanmisaka
19e3c38fa8 Apply suggestions from code review
Co-authored-by: Claus Vium <cvium@users.noreply.github.com>
2021-07-26 03:09:44 +08:00
nyanmisaka
3beda02d92 add support for cuda tonemap and overlay 2021-07-25 00:52:16 +08:00
nyanmisaka
aaab6a3518 add tests for FFmpeg 4.4 and 4.3.2 2021-07-25 00:52:03 +08:00
Niels van Velzen
2cd1c70e55 Add OpenAPI workflow 2021-07-22 21:19:10 +02:00
Patrick Barron
60ce0c9fa9 Add dto for device options 2021-07-13 19:30:11 -04:00
MrTimscampi
3b8947aba6 Add using keywords to non-disposed objects in BuildThumbCollageBitmap 2021-07-05 19:41:10 +02:00
MrTimscampi
8a65a6dfc3 Use artist backdrop for generated library image 2021-07-03 02:50:28 +02:00
Patrick Barron
06d682c296 Merge remote-tracking branch 'origin/authenticationdb-efcore' into authenticationdb-efcore 2021-06-27 16:46:09 -04:00
Patrick Barron
af2e7aec2e Add missing service registration for IAuthenticationManager 2021-06-27 16:45:41 -04:00
Patrick Barron
fdba71e133 Fix Api Key authentication 2021-06-27 16:44:34 -04:00
Patrick Barron
bbac9ff67e GetDeviceOptions always returns an instance of DeviceOptions 2021-06-27 16:42:26 -04:00
Patrick Barron
5d1139ec62 Update Jellyfin.Server.Implementations/Devices/DeviceManager.cs
Co-authored-by: Cody Robibero <cody@robibe.ro>
2021-06-26 15:17:57 -04:00
Patrick Barron
befedaf6fc Update Emby.Server.Implementations/Session/SessionManager.cs
Co-authored-by: Cody Robibero <cody@robibe.ro>
2021-06-25 21:13:38 -04: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
Patrick Barron
dbfd30ec4c Migrate DeviceOptions 2021-06-24 09:38:37 -04:00
Patrick Barron
d3e02e918d Merge pull request #166 from crobibero/authdb-qc
Fix QuickConnect interation with AuthenticationDb
2021-06-24 06:21:41 -04:00
crobibero
397868be95 Fix issues with QuickConnect and AuthenticationDb 2021-06-23 21:07:08 -06:00
Patrick Barron
ae878fa051 Merge branch 'master' into authenticationdb-efcore
# Conflicts:
#	Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs
#	Emby.Server.Implementations/Session/SessionManager.cs
#	Jellyfin.Server.Implementations/Security/AuthorizationContext.cs
2021-06-23 20:22:12 -04:00
Patrick Barron
f96722fa74 Fix migration 2021-06-21 19:06:21 -04:00
Patrick Barron
3884837513 Convert method group to lambda in DeviceManager 2021-06-21 19:01:34 -04:00
Patrick Barron
784f29f753 Use named tuple for QuickConnect 2021-06-21 19:00:24 -04:00
Patrick Barron
544e059395 Revert unintended change in SchedulesDirect 2021-06-21 18:57:59 -04:00
crobibero
39e84ba4ab Suggestions from review 2021-06-21 16:06:54 -06:00
Cody Robibero
fa7b7b84e7 Update CONTRIBUTORS.md
Co-authored-by: Bond-009 <bond.009@outlook.com>
2021-06-21 16:06:25 -06:00
crobibero
ac76519081 Enhance BaseItemKindTests 2021-06-20 07:15:46 -06:00
crobibero
790b284184 Add missing BaseItemKind 2021-06-20 07:15:32 -06:00
crobibero
23dd6e2d9f Merge remote-tracking branch 'upstream/master' into baseitemkind-fixes 2021-06-20 07:09:24 -06:00
Patrick Barron
d64e14fcb8 Use ReadOnlySpan in GetImagesForPrograms 2021-06-19 15:26:24 -04:00
Patrick Barron
67308f489f Implement DeleteDevice 2021-06-19 15:24:53 -04:00
Patrick Barron
2a9474f6e7 Count records before skipping 2021-06-19 15:24:42 -04:00
Patrick Barron
6b24cc6d1f Fix UpdateDeviceOptions 2021-06-19 15:24:26 -04:00
Patrick Barron
3123ea2a94 Add missing ConfigureAwait call 2021-06-19 15:09:16 -04:00
BaronGreenback
6648b7d7da Merge branch 'master' into comparisons 2021-06-19 15:04:30 +01:00
Patrick Barron
54fdc2fd88 Use ExecuteSqlInterpolated instead of ExecuteSqlRaw
oop
2021-06-18 19:15:08 -04:00
Patrick Barron
be88efce3c Merge branch 'master' into authenticationdb-efcore
# Conflicts:
#	Emby.Server.Implementations/Devices/DeviceManager.cs
#	Emby.Server.Implementations/HttpServer/Security/SessionContext.cs
#	Emby.Server.Implementations/Security/AuthenticationRepository.cs
#	Emby.Server.Implementations/Session/SessionManager.cs
#	Jellyfin.Server.Implementations/Security/AuthorizationContext.cs
#	MediaBrowser.Controller/Library/IUserManager.cs
#	MediaBrowser.Controller/Net/ISessionContext.cs
2021-06-18 18:56:10 -04:00
Patrick Barron
336ba2879f Re-add support for API keys 2021-06-18 18:26:58 -04:00
Patrick Barron
0292936c65 Use consistent name for db context 2021-06-18 17:09:59 -04:00
Patrick Barron
4206c0e091 Combine if statements 2021-06-18 17:09:39 -04:00
Patrick Barron
3264575047 Add data migration 2021-06-18 17:07:30 -04:00
Patrick Barron
3fd0b1a359 Recreate devices migration with missing fields 2021-06-18 17:07:22 -04:00
Patrick Barron
3d9c16ba6b Fix concurrency issues 2021-06-18 17:06:38 -04:00
Patrick Barron
373155a063 Correctly handle devices without custom names 2021-06-18 16:57:46 -04:00
Stanislav Ionascu
351ae66509 Better detection of the ISO DVD/BD types
The ISO image will be opened and checked for disc-type specific
folders.
Can be overridden using NAME.dvd.iso / NAME.bluray.iso
2021-06-13 19:24:06 +02:00
dependabot[bot]
4e9570598b Bump cirrus-actions/rebase from 1.4 to 1.5
Bumps [cirrus-actions/rebase](https://github.com/cirrus-actions/rebase) from 1.4 to 1.5.
- [Release notes](https://github.com/cirrus-actions/rebase/releases)
- [Commits](https://github.com/cirrus-actions/rebase/compare/1.4...1.5)

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-07 14:17:50 +00:00
Tommaso Stocchi
02a56d8cf7 Changed return type desc in GetParts() summary 2021-06-03 17:45:22 +02:00
Tommaso Stocchi
2a72c33ba6 authorizationheader as readonlyspan<char> instead of string 2021-06-03 17:43:50 +02:00
Tommaso Stocchi
d1b34a1e97 -fix authorizationHeader is no longer a string 2021-06-03 17:37:42 +02:00
Tommaso Stocchi
2b232df07f Merge branch 'master' into bug/authorization-header-issue 2021-06-03 17:15:32 +02:00
Tommaso Stocchi
dc261b815f -fix AuthorizationHeader parameter name 2021-06-03 17:12:16 +02:00
Tommaso Stocchi
d86964eb6a Merge branch 'bug/authorization-header-issue' of https://github.com/tommasodotNET/jellyfin into bug/authorization-header-issue 2021-06-03 17:10:22 +02:00
Tommaso Stocchi
3c019d1324 Using for instead of while 2021-06-03 17:10:19 +02:00
Tommaso Stocchi
3951546b1f Update Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
Co-authored-by: artiume <siderite@gmail.com>
2021-06-03 17:07:25 +02:00
BaronGreenback
51fb6e1d2d Merge branch 'master' into IsRoot_fix 2021-05-22 22:01:03 +01:00
BaronGreenback
d0537a3271 Set isRoot to true 2021-05-21 15:07:35 +01:00
Patrick Barron
37a8a82ac5 Make methods static in AuthenticationContext 2021-05-21 00:19:54 -04:00
Patrick Barron
b6446c06ee Merge branch 'master' into authenticationdb-efcore
# Conflicts:
#	Emby.Server.Implementations/Security/AuthenticationRepository.cs
#	Jellyfin.Server.Implementations/Security/AuthorizationContext.cs
#	MediaBrowser.Controller/Devices/IDeviceManager.cs
2021-05-21 00:19:07 -04:00
Patrick Barron
a0c6f72762 Migrate authentication db to EF Core 2021-05-20 23:56:59 -04:00
Patrick Barron
b03f2353d8 Generate Access token in constructor 2021-05-20 20:57:10 -04:00
Patrick Barron
f4d1c3ef7a Add device query class 2021-05-20 20:48:53 -04:00
Patrick Barron
ab63a7745c Add PaginatedQuery abstract class, change startIndex to skip 2021-05-20 20:48:41 -04:00
Patrick Barron
e1f7086077 Remove unnecessary query class 2021-05-20 20:39:22 -04:00
Patrick Barron
a225f34796 Merge branch 'master' into authenticationdb-efcore
# Conflicts:
#	Jellyfin.Api/Helpers/RequestHelpers.cs
2021-05-18 18:09:46 -04:00
Cody Robibero
2888567ea5 Update Jellyfin.Api/Models/ClientLogDtos/ClientLogEventDto.cs
Co-authored-by: dkanada <dkanada@users.noreply.github.com>
2021-05-11 08:21:04 -06: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
BaronGreenback
417a7011c7 changed to first 2021-05-04 16:32:17 +01:00
crobibero
3c8abeda7d Require Authorization for the ClientLogController 2021-05-04 07:16:35 -06:00
BaronGreenback
7ff52bf755 Renamed 2021-05-03 19:30:56 +01:00
BaronGreenback
7936ea59eb Changed selection method 2021-05-03 17:27:23 +01:00
BaronGreenback
2e01fb3cda Update tests/Jellyfin.Networking.Tests/NetworkParseTests.cs
Co-authored-by: David Ullmer <davidullmer@outlook.de>
2021-05-01 17:16:25 +01:00
BaronGreenback
2fbc1190bc Update LiveTvMediaSourceProvider.cs 2021-05-01 17:15:45 +01:00
BaronGreenback
a5aabbb885 Update ApplicationHost.cs
Renamed method
2021-05-01 17:14:37 +01:00
BaronGreenback
975d1537d4 Update tests/Jellyfin.Networking.Tests/NetworkParseTests.cs
Co-authored-by: David Ullmer <davidullmer@outlook.de>
2021-05-01 16:29:28 +01:00
BaronGreenback
b4ab75cd69 Update tests/Jellyfin.Networking.Tests/NetworkParseTests.cs
Co-authored-by: David Ullmer <davidullmer@outlook.de>
2021-05-01 16:29:22 +01:00
BaronGreenback
a49ded84c6 Update tests/Jellyfin.Networking.Tests/NetworkParseTests.cs
Co-authored-by: David Ullmer <davidullmer@outlook.de>
2021-05-01 16:29:13 +01:00
BaronGreenback
2182640519 Update Emby.Server.Implementations/ApplicationHost.cs
Co-authored-by: Cody Robibero <cody@robibe.ro>
2021-04-30 09:08:56 +01:00
crobibero
f8cfc55a36 Clean client filename generation 2021-04-26 17:02:25 -06:00
BaronGreenback
851f610e11 Changed other method to match for consistency. 2021-04-26 19:59:35 +01:00
BaronGreenback
78e97dbaa9 updated comment 2021-04-26 19:56:15 +01:00
BaronGreenback
f30bbef781 Fixed test 2021-04-26 17:28:32 +01:00
BaronGreenback
2b85f43cab removed unused usings 2021-04-26 17:17:48 +01:00
BaronGreenback
5741fa7dfa Fix url for LiveTV 2021-04-26 17:13:45 +01:00
crobibero
1d6224c9c6 Add endpoint to log client events 2021-04-26 07:02:26 -06: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
Patrick Barron
12fa5c0c41 Add AccessToken to device 2021-04-13 20:01:31 -04:00
Patrick Barron
75df6965a0 Don't use database for QuickConnect 2021-04-13 20:01:21 -04:00
BaronGreenback
fb7587dd84 Renamed 2021-04-11 17:17:05 +01:00
Patrick Barron
ed0b5ff017 Fix builds 2021-04-10 17:11:59 -04:00
Patrick Barron
3ebc047434 Convert UpdateUser to solely async 2021-04-10 16:59:41 -04:00
Patrick Barron
8607b52541 Make device/session code async 2021-04-10 16:57:25 -04:00
Patrick Barron
44e71774b1 Rewrite device manager using EF Core 2021-04-10 16:17:36 -04:00
Patrick Barron
f47fe308b1 Add navigation property to device entity 2021-04-10 16:17:02 -04:00
Patrick Barron
98e19c9fd3 Add device indexes 2021-04-10 16:16:08 -04:00
Patrick Barron
e6f1ffdc8d Add device entities to schema. 2021-04-10 16:15:59 -04:00
Patrick Barron
9cd5352358 Add device options entity 2021-04-10 16:03:20 -04:00
BaronGreenback
af027b6283 Fixed after accepting suggestion. 2021-04-10 19:23:27 +01:00
BaronGreenback
0db5df86df Update Jellyfin.Api/Constants/Policies.cs
Co-authored-by: Cody Robibero <cody@robibe.ro>
2021-04-10 18:49:18 +01:00
BaronGreenback
cf3aff93f2 revert change error 2021-04-10 12:09:24 +01:00
BaronGreenback
5fb7557763 Network Access Policy 2021-04-10 12:03:52 +01:00
Patrick Barron
271b4cadb7 Add device entity. 2021-04-09 23:16:07 -04:00
Patrick Barron
499785bebb Use new entities for API key endpoints 2021-04-01 17:08:22 -04:00
Patrick Barron
1c501b17d7 Add ApiKey entity and associated relationships 2021-04-01 17:05:54 -04:00
Patrick Barron
16ca8c7536 Remove unused SessionManager methods 2021-04-01 10:49:09 -04:00
Ionut Andrei Oanca
776ce7c660 Send playing item status in SyncPlay group update 2021-03-29 11:29:48 +02:00
Ionut Andrei Oanca
9eb740ba57 Fix storing outdated sessions in SyncPlay 2021-03-28 13:25:40 +02:00
BaronGreenback
414e918c01 Optimized and added test 2021-02-26 14:30:00 +00:00
Luca Benini
078b6244ee Restored GUID in Jellyfin.XbmcMetadata.Tests
Restored the project type guid as by review
See https://github.com/dotnet/project-system/issues/1821
2021-02-14 12:46:28 +01:00
Luca Benini
1664109d14 Merge branch 'baseitemkind-fixes' of github.com:lbenini/jellyfin into baseitemkind-fixes 2021-02-14 12:40:33 +01:00
Luca Benini
2f8d15ed08 Moved test to Jellyfin.Server.Implementation.Tests as by review
Aligned code base to review comments:
	Jellyfin.Server.Implementation.Tests is the correct place
2021-02-14 12:40:08 +01:00
Luca Benini
c4d142eda1 Fix BaseItemKind conversion for PlaylistsFolder
Return the correct ClientTypeName to allow Enum Parse
Added dynamic unit tests to ensure all BaseItem concrete descend
2021-02-14 12:40:08 +01:00
Luca Benini
c8395899ba Moved test to Jellyfin.Server.Implementation.Tests as by review
Aligned code base to review comments:
	Jellyfin.Server.Implementation.Tests is the correct place
2021-02-13 19:40:15 +01:00
Luca Benini
991adc8efe Fix BaseItemKind conversion for PlaylistsFolder
Return the correct ClientTypeName to allow Enum Parse
Added dynamic unit tests to ensure all BaseItem concrete descend
2021-02-13 15:28:37 +01:00
Ionut Andrei Oanca
68969c9530 Clear playlist in SyncPlay group 2021-01-24 01:05:17 +01:00
MrTimscampi
c52a2f2f7b Move studios image providers to plugin 2021-01-12 22:45:28 +01:00
Tommaso Stocchi
452af30511 Added UrlDecode for authorization parts 2021-01-03 19:32:58 +01:00
Tommaso Stocchi
a03880b687 Improve get auth header parts using substring 2021-01-02 18:18:47 +01:00
Tommaso Stocchi
7c7f2316fa Added comments 2020-12-15 21:06:47 +01:00
Tommaso Stocchi
c6eefaac09 Added function to split the authorization header parts 2020-12-15 21:01:42 +01:00
Tommaso Stocchi
6e2cfc6569 Url decode for auth value 2020-12-14 14:05:53 +01:00
Tommaso Stocchi
b611a108f8 -fix split on comma and double quotes 2020-12-14 13:15:21 +01:00
Tommaso Stocchi
305e5ebaf4 Allow commas in auth values when wappred in a double quote 2020-12-14 13:14:18 +01:00
Tommaso Stocchi
13bc57ecc3 No need to double check param length 2020-12-14 13:08:07 +01:00
Tommaso Stocchi
064a9cedbd No htlml encoding on server side 2020-12-14 13:07:39 +01:00
AJ Jordan
bab389114b Use a service unit, not a scope unit, to restart
Reportedly `systemd-run --scope` still got killed by the service
manager; see #4615. The suspected cause is that `scope` units are run by
the `systemd-run` process itself and inherit the caller's execution
environment (see systemd-run(1)). To fix this, we use a systemd
`service` unit instead, which is run and managed by PID 1 - hopefully
this will isolate us sufficiently so that we don't get terminated along
with `jellyfin.service`.
2020-12-04 16:33:24 -08:00
AJ Jordan
d251c701b9 Use systemd-run(1) in restart.sh
systemd-run(1) runs `systemctl restart` in an isolated systemd unit
that is not subject to process termination as jellyfin.service is shut
down. We adjust the sudoers configuration for this new usage, removing
the old config, since restart.sh is the only user of the sudoers
policy.

Additionally we change `systemctl start` to `systemctl restart` since
there was a race condition where jellyfin.service was not fully
stopped by the time this ran, so `systemctl start` became a noop.
`systemctl restart` on the other hand works whether jellyfin.service is
stopped or not.

The at(1) hack (and the usage of `start` instead of `restart`) is left
in for other init systems since I cannot test on those systems, and
because I don't know of any systemd-run(1) equivalent (although it may
be a non-issue since alternate init systems do not keep track of daemon
children nearly as aggressively as systemd does).
2020-12-04 16:18:26 -08:00
AJ Jordan
b528816b2a Add sudo to package dependencies
It's used in the restart.sh script.

For Debian, this is a Recommends because virtually everyone will need
this (default APT policy is to install recommended packages so this
works ok), but technically you can configure the server to run as root
and then you wouldn't need it.

For Fedora... frankly I got confused by their Weak Dependencies etc. so
I just made it a hard dependency.
2020-11-29 04:15:11 -05:00
AJ Jordan
2911dfc37d Don't restart with sudo(8) if it's not available
Some environments, like system containers, have no reason to have
sudo(8) installed. In these environments restart.sh will silently fail
because /usr/bin/sudo does not exist to execute, so test that sudo
exists and don't try to use it otherwise.

Note also that hardcoding sudo's path is wrong: it can be installed in
other places. On FreeBSD, for example, it is /usr/local/bin/sudo when
installed from ports.
2020-11-29 04:04:38 -05:00
AJ Jordan
ce82932c9a Remove useless which(1) calls in restart.sh
at(1) runs commandlines with /bin/sh anyway, which resolves paths. No
need to do it ourselves.
2020-11-29 04:04:22 -05:00
AJ Jordan
a4e1732e35 Fix restart.sh to look at what's actually booted
The old code was wrong because e.g. systemd can be *installed* on the
system, but not actually used as PID1. In that case we would pick
`systemctl`, but it wouldn't actually work because PID1 was some other
init system.
2020-11-29 03:43:03 -05:00
Cromefire_
7aef0fce44 Use consistent style 2020-11-24 12:24:42 +01:00
Cromefire_
7396fcfb84 Removed bash style vars 2020-11-24 12:23:44 +01:00
Cromefire_
1897455004 Update debian/conf/jellyfin
Co-authored-by: Odd Stråbø <oddstr13@openshell.no>
2020-11-23 20:17:40 +01:00
Cromefire_
20b1f985f0 Added JELLYFIN_ADDITIONAL_OPTS to default file 2020-08-28 21:24:21 +02:00
Cromefire_
c0a8118c51 Added additional opts to service file 2020-08-28 21:19:42 +02:00
WWWesten
f2817fef74 Merge pull request #1 from jellyfin/master
Merge from upstream
2019-02-23 18:58:38 +05:00
908 changed files with 21689 additions and 14899 deletions

View File

@@ -7,7 +7,7 @@ parameters:
default: "ubuntu-latest"
- name: DotNetSdkVersion
type: string
default: 5.0.302
default: 6.0.x
jobs:
- job: CompatibilityCheck

View File

@@ -1,7 +1,7 @@
parameters:
LinuxImage: 'ubuntu-latest'
RestoreBuildProjects: 'Jellyfin.Server/Jellyfin.Server.csproj'
DotNetSdkVersion: 5.0.302
DotNetSdkVersion: 6.0.x
jobs:
- job: Build
@@ -91,3 +91,10 @@ jobs:
inputs:
targetPath: '$(build.ArtifactStagingDirectory)/Jellyfin.Server/MediaBrowser.Common.dll'
artifactName: 'Jellyfin.Common'
- task: PublishPipelineArtifact@1
displayName: 'Publish Artifact Extensions'
condition: and(succeeded(), eq(variables['BuildConfiguration'], 'Release'))
inputs:
targetPath: '$(build.ArtifactStagingDirectory)/Jellyfin.Server/Jellyfin.Extensions.dll'
artifactName: 'Jellyfin.Extensions'

View File

@@ -39,6 +39,14 @@ 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: './bump-version $(JellyfinVersion)'
displayName: Bump internal 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 +88,14 @@ 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: './bump-version $(JellyfinVersion)'
displayName: Bump internal version (stable)
condition: startsWith(variables['Build.SourceBranch'], 'refs/tags/v')
- task: DownloadPipelineArtifact@2
displayName: 'Download OpenAPI Spec'
inputs:
@@ -127,6 +143,10 @@ jobs:
displayName: Set release version (stable)
condition: startsWith(variables['Build.SourceBranch'], 'refs/tags/v')
- script: './bump-version $(JellyfinVersion)'
displayName: Bump internal version (stable)
condition: startsWith(variables['Build.SourceBranch'], 'refs/tags/v')
- task: Docker@2
displayName: 'Push Unstable Image'
condition: startsWith(variables['Build.SourceBranch'], 'refs/heads/master')
@@ -181,7 +201,7 @@ jobs:
inputs:
sshEndpoint: repository
runOptions: 'commands'
commands: nohup sudo /srv/repository/collect-server.azure.sh /srv/repository/incoming/azure $(Build.BuildNumber) &
commands: nohup sudo /srv/repository/collect-server.azure.sh /srv/repository/incoming/azure $(Build.BuildNumber) $(Build.SourceBranch) &
- job: PublishNuget
displayName: 'Publish NuGet packages'
@@ -195,10 +215,10 @@ jobs:
steps:
- task: UseDotNet@2
displayName: 'Use .NET 5.0 sdk'
displayName: 'Use .NET 6.0 sdk'
inputs:
packageType: 'sdk'
version: '5.0.x'
version: '6.0.x'
- task: DotNetCoreCLI@2
displayName: 'Build Stable Nuget packages'
@@ -211,6 +231,7 @@ jobs:
MediaBrowser.Controller/MediaBrowser.Controller.csproj
MediaBrowser.Model/MediaBrowser.Model.csproj
Emby.Naming/Emby.Naming.csproj
src/Jellyfin.Extensions/Jellyfin.Extensions.csproj
custom: 'pack'
arguments: -o $(Build.ArtifactStagingDirectory) -p:Version=$(JellyfinVersion)
@@ -225,6 +246,7 @@ jobs:
MediaBrowser.Controller/MediaBrowser.Controller.csproj
MediaBrowser.Model/MediaBrowser.Model.csproj
Emby.Naming/Emby.Naming.csproj
src/Jellyfin.Extensions/Jellyfin.Extensions.csproj
custom: 'pack'
arguments: '--version-suffix $(Build.BuildNumber) -o $(Build.ArtifactStagingDirectory) -p:Stability=Unstable'

View File

@@ -10,7 +10,7 @@ parameters:
default: "tests/**/*Tests.csproj"
- name: DotNetSdkVersion
type: string
default: 5.0.302
default: 6.0.x
jobs:
- job: Test
@@ -94,5 +94,5 @@ jobs:
displayName: 'Publish OpenAPI Artifact'
condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux'))
inputs:
targetPath: "tests/Jellyfin.Server.Integration.Tests/bin/Release/net5.0/openapi.json"
targetPath: "tests/Jellyfin.Server.Integration.Tests/bin/Release/net6.0/openapi.json"
artifactName: 'OpenAPI Spec'

View File

@@ -5,8 +5,6 @@ variables:
value: 'tests/**/*Tests.csproj'
- name: RestoreBuildProjects
value: 'Jellyfin.Server/Jellyfin.Server.csproj'
- name: DotNetSdkVersion
value: 5.0.302
pr:
autoCancel: true
@@ -57,6 +55,9 @@ jobs:
Common:
NugetPackageName: Jellyfin.Common
AssemblyFileName: MediaBrowser.Common.dll
Extensions:
NugetPackageName: Jellyfin.Extensions
AssemblyFileName: Jellyfin.Extensions.dll
LinuxImage: 'ubuntu-latest'
- ${{ if or(startsWith(variables['Build.SourceBranch'], 'refs/tags/v'), startsWith(variables['Build.SourceBranch'], 'refs/heads/master')) }}:

1
.copr Symbolic link
View File

@@ -0,0 +1 @@
fedora

View File

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

View File

@@ -1,50 +0,0 @@
---
name: Bug report
about: Create a bug report
title: ''
labels: bug
assignees: ''
---
**Describe the bug**
<!-- A clear and concise description of what the bug is. -->
**System (please complete the following information):**
- OS: [e.g. Debian, Windows]
- Virtualization: [e.g. Docker, KVM, LXC]
- Clients: [Browser, Android, Fire Stick, etc.]
- Browser: [e.g. Firefox 72, Chrome 80, Safari 13]
- Jellyfin Version: [e.g. 10.4.3, nightly 20191231]
- Playback: [Direct Play, Remux, Direct Stream, Transcode]
- Hardware Acceleration: [e.g. none, VAAPI, NVENC, etc.]
- Installed Plugins: [e.g. none, Fanart, Anime, etc.]
- Reverse Proxy: [e.g. none, nginx, apache, etc.]
- Base URL: [e.g. none, yes: /example]
- Networking: [e.g. Host, Bridge/NAT]
- Storage: [e.g. local, NFS, cloud]
**To Reproduce**
<!-- Steps to reproduce the behavior: -->
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
<!-- A clear and concise description of what you expected to happen. -->
**Server Logs**
<!-- Please paste any log errors. -->
**FFmpeg Logs**
<!-- Please paste any log errors. -->
**Browser Console Logs**
<!-- Please paste any log errors. -->
**Screenshots**
<!-- If applicable, add screenshots to help explain your problem. -->
**Additional context**
<!-- Add any other context about the problem here. -->

106
.github/ISSUE_TEMPLATE/issue report.yml vendored Normal file
View File

@@ -0,0 +1,106 @@
name: Issue Report
description: File an issue report
title: "[Issue]: "
labels: [bug, triage]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report! Please provide as much detail as necessary, most questions may not be applicable to you. If you need real-time help, join us on [Matrix](https://matrix.to/#/#jellyfin-troubleshooting:matrix.org) or [Discord](https://discord.gg/zHBxVSXdBV).
- type: textarea
id: what-happened
attributes:
label: Please describe your bug
description: Also tell us, what did you expect to happen?
placeholder: |
The more information that you are able to provide, the better. Did you do anything before this happened? Did you upgrade or change anything? Any screenshots or logs you can provide will be helpful.
This is my issue.
Steps to Reproduce
1. In this environment...
2. With this config...
3. Run '...'
4. See error...
validations:
required: true
- type: dropdown
id: version
attributes:
label: Jellyfin Version
description: What version of Jellyfin are you running?
options:
- 10.7.7
- 10.7.z
- 10.6.4
- Other
validations:
required: true
- type: input
id: version-other
attributes:
label: "if other:"
placeholder: Other
- type: textarea
attributes:
label: Environment
description: |
Examples:
- **OS**: [e.g. Debian, Windows]
- **Virtualization**: [e.g. Docker, KVM, LXC]
- **Clients**: [Browser, Android, Fire Stick, etc.]
- **Browser**: [e.g. Firefox 91, Chrome 93, Safari 13]
- **FFmpeg Version**: [e.g. 4.3.2-Jellyfin]
- **Playback**: [Direct Play, Remux, Direct Stream, Transcode]
- **Hardware Acceleration**: [e.g. none, VAAPI, NVENC, etc.]
- **Installed Plugins**: [e.g. none, Fanart, Anime, etc.]
- **Reverse Proxy**: [e.g. none, nginx, apache, etc.]
- **Base URL**: [e.g. none, yes: /example]
- **Networking**: [e.g. Host, Bridge/NAT]
- **Storage**: [e.g. local, NFS, cloud]
value: |
- OS:
- Virtualization:
- Clients:
- Browser:
- FFmpeg Version:
- Playback Method:
- Hardware Acceleration:
- Plugins:
- Reverse Proxy:
- Base URL:
- Networking:
- Storage:
render: markdown
- type: textarea
id: logs
attributes:
label: Jellyfin logs
description: Please copy and paste any relevant log output. This can be found in Dashboard > Logs.
placeholder: For playback issues, browser/client and FFmpeg logs may be more useful.
render: shell
- type: textarea
id: ffmpeg-logs
attributes:
label: FFmpeg logs
description: Please copy and paste any relevant log output. This can be found in Dashboard > Logs.
placeholder: It's important to include the specific codec details. If no FFmpeg logs appear, the file was Direct Played and did not use FFmpeg.
render: shell
- type: textarea
id: browserlogs
attributes:
label: Please attach any browser or client logs here
placeholder: Access browser logs by using the F12 to bring up the console. Screenshots are typically easier to read than raw logs. For clients such as Android or iOS, please see our documentation.
- type: textarea
id: screenshots
attributes:
label: Please attach any screenshots here
placeholder: Images can be pasted directly into the textbox and will be hosted by github.
- type: checkboxes
id: terms
attributes:
label: Code of Conduct
description: By submitting this issue, you agree to follow our [Code of Conduct](https://jellyfin.org/docs/general/community-standards.html#code-of-conduct)
options:
- label: I agree to follow this project's Code of Conduct
required: true

View File

@@ -24,7 +24,8 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: '5.0.x'
dotnet-version: '6.0.x'
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:

View File

@@ -29,7 +29,7 @@ jobs:
fetch-depth: 0
- name: Automatic Rebase
uses: cirrus-actions/rebase@1.4
uses: cirrus-actions/rebase@1.5
env:
GITHUB_TOKEN: ${{ secrets.JF_BOT_TOKEN }}

124
.github/workflows/openapi.yml vendored Normal file
View File

@@ -0,0 +1,124 @@
name: OpenAPI
on:
push:
branches:
- master
pull_request_target:
jobs:
openapi-head:
name: OpenAPI - HEAD
runs-on: ubuntu-latest
permissions: read-all
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: '6.0.x'
- name: Generate openapi.json
run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests"
- name: Upload openapi.json
uses: actions/upload-artifact@v2
with:
name: openapi-head
retention-days: 14
if-no-files-found: error
path: tests/Jellyfin.Server.Integration.Tests/bin/Release/net6.0/openapi.json
openapi-base:
name: OpenAPI - BASE
if: ${{ github.base_ref != '' }}
runs-on: ubuntu-latest
permissions: read-all
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
ref: ${{ github.base_ref }}
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: '6.0.x'
- name: Generate openapi.json
run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests"
- name: Upload openapi.json
uses: actions/upload-artifact@v2
with:
name: openapi-base
retention-days: 14
if-no-files-found: error
path: tests/Jellyfin.Server.Integration.Tests/bin/Release/net6.0/openapi.json
openapi-diff:
name: OpenAPI - Difference
if: ${{ github.event_name == 'pull_request_target' }}
runs-on: ubuntu-latest
needs:
- openapi-head
- openapi-base
steps:
- name: Download openapi-head
uses: actions/download-artifact@v2
with:
name: openapi-head
path: openapi-head
- name: Download openapi-base
uses: actions/download-artifact@v2
with:
name: openapi-base
path: openapi-base
- name: Workaround openapi-diff issue
run: |
sed -i 's/"allOf"/"oneOf"/g' openapi-head/openapi.json
sed -i 's/"allOf"/"oneOf"/g' openapi-base/openapi.json
- name: Calculate OpenAPI difference
uses: docker://openapitools/openapi-diff
continue-on-error: true
with:
args: --fail-on-changed --markdown openapi-changes.md openapi-base/openapi.json openapi-head/openapi.json
- id: read-diff
name: Read openapi-diff output
run: |
body=$(cat openapi-changes.md)
body="${body//'%'/'%25'}"
body="${body//$'\n'/'%0A'}"
body="${body//$'\r'/'%0D'}"
echo ::set-output name=body::$body
- name: Find difference comment
uses: peter-evans/find-comment@v1
id: find-comment
with:
issue-number: ${{ github.event.pull_request.number }}
direction: last
body-includes: openapi-diff-workflow-comment
- name: Reply or edit difference comment (changed)
uses: peter-evans/create-or-update-comment@v1.4.5
if: ${{ steps.read-diff.outputs.body != '' }}
with:
issue-number: ${{ github.event.pull_request.number }}
comment-id: ${{ steps.find-comment.outputs.comment-id }}
edit-mode: replace
body: |
<!--openapi-diff-workflow-comment-->
<details>
<summary>Changes in OpenAPI specification found. Expand to see details.</summary>
${{ steps.read-diff.outputs.body }}
</details>
- name: Edit difference comment (unchanged)
uses: peter-evans/create-or-update-comment@v1.4.5
if: ${{ steps.read-diff.outputs.body == '' && steps.find-comment.outputs.comment-id != '' }}
with:
issue-number: ${{ github.event.pull_request.number }}
comment-id: ${{ steps.find-comment.outputs.comment-id }}
edit-mode: replace
body: |
<!--openapi-diff-workflow-comment-->
No changes to OpenAPI specification found. See history of this comment for previous changes.

3
.gitignore vendored
View File

@@ -278,3 +278,6 @@ web/
web-src.*
MediaBrowser.WebDashboard/jellyfin-web
apiclient/generated
# Omnisharp crash logs
mono_crash.*.json

4
.vscode/launch.json vendored
View File

@@ -6,7 +6,7 @@
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/Jellyfin.Server/bin/Debug/net5.0/jellyfin.dll",
"program": "${workspaceFolder}/Jellyfin.Server/bin/Debug/net6.0/jellyfin.dll",
"args": [],
"cwd": "${workspaceFolder}/Jellyfin.Server",
"console": "internalConsole",
@@ -22,7 +22,7 @@
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/Jellyfin.Server/bin/Debug/net5.0/jellyfin.dll",
"program": "${workspaceFolder}/Jellyfin.Server/bin/Debug/net6.0/jellyfin.dll",
"args": ["--nowebclient"],
"cwd": "${workspaceFolder}/Jellyfin.Server",
"console": "internalConsole",

View File

@@ -46,6 +46,7 @@
- [fruhnow](https://github.com/fruhnow)
- [geilername](https://github.com/geilername)
- [gnattu](https://github.com/gnattu)
- [GodTamIt](https://github.com/GodTamIt)
- [grafixeyehero](https://github.com/grafixeyehero)
- [h1nk](https://github.com/h1nk)
- [hawken93](https://github.com/hawken93)
@@ -148,6 +149,8 @@
- [skyfrk](https://github.com/skyfrk)
- [ianjazz246](https://github.com/ianjazz246)
- [peterspenler](https://github.com/peterspenler)
- [MBR-0001](https://github.com/MBR-0001)
- [jonas-resch](https://github.com/jonas-resch)
# Emby Contributors
@@ -212,4 +215,5 @@
- [Tim Hobbs](https://github.com/timhobbs)
- [SvenVandenbrande](https://github.com/SvenVandenbrande)
- [olsh](https://github.com/olsh)
- [lbenini](https://github.com/lbenini)
- [gnuyent](https://github.com/gnuyent)

View File

@@ -3,10 +3,13 @@
<PropertyGroup>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)/jellyfin.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
</PropertyGroup>

View File

@@ -1,4 +1,8 @@
ARG DOTNET_VERSION=5.0
# DESIGNED FOR BUILDING ON AMD64 ONLY
#####################################
# Requires binfm_misc registration
# https://github.com/multiarch/qemu-user-static#binfmt_misc-register
ARG DOTNET_VERSION=6.0
FROM node:lts-alpine as web-builder
ARG JELLYFIN_WEB_VERSION=master
@@ -8,7 +12,7 @@ RUN apk add curl git zlib zlib-dev autoconf g++ make libpng-dev gifsicle alpine-
&& npm ci --no-audit --unsafe-perm \
&& mv dist /dist
FROM debian:buster-slim as app
FROM debian:stable-slim as app
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
ARG DEBIAN_FRONTEND="noninteractive"
@@ -18,15 +22,16 @@ 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=20.3.2
ARG IGC_VERSION=1.0.5435
ARG NEO_VERSION=20.46.18421
ARG LEVEL_ZERO_VERSION=1.0.18421
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
# Install dependencies:
# mesa-va-drivers: needed for AMD VAAPI. Mesa >= 20.1 is required for HEVC transcoding.
# curl: healthcheck
RUN apt-get update \
&& apt-get install --no-install-recommends --no-install-suggests -y ca-certificates gnupg wget apt-transport-https \
&& apt-get install --no-install-recommends --no-install-suggests -y ca-certificates gnupg wget apt-transport-https curl \
&& wget -O - https://repo.jellyfin.org/jellyfin_team.gpg.key | apt-key add - \
&& echo "deb [arch=$( dpkg --print-architecture )] https://repo.jellyfin.org/$( awk -F'=' '/^ID=/{ print $NF }' /etc/os-release ) $( awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release ) main" | tee /etc/apt/sources.list.d/jellyfin.list \
&& apt-get update \
@@ -57,7 +62,7 @@ RUN apt-get update \
&& chmod 777 /cache /config /media \
&& sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1
# ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1
ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
@@ -72,6 +77,8 @@ RUN dotnet publish Jellyfin.Server --disable-parallel --configuration Release --
FROM app
ENV HEALTHCHECK_URL=http://localhost:8096/health
COPY --from=builder /jellyfin /jellyfin
COPY --from=web-builder /dist /jellyfin/jellyfin-web
@@ -81,3 +88,6 @@ ENTRYPOINT ["./jellyfin/jellyfin", \
"--datadir", "/config", \
"--cachedir", "/cache", \
"--ffmpeg", "/usr/lib/jellyfin-ffmpeg/ffmpeg"]
HEALTHCHECK --interval=30s --timeout=30s --start-period=10s --retries=3 \
CMD curl -Lk "${HEALTHCHECK_URL}" || exit 1

View File

@@ -1,8 +1,8 @@
# DESIGNED FOR BUILDING ON AMD64 ONLY
# DESIGNED FOR BUILDING ON ARM ONLY
#####################################
# Requires binfm_misc registration
# https://github.com/multiarch/qemu-user-static#binfmt_misc-register
ARG DOTNET_VERSION=5.0
ARG DOTNET_VERSION=6.0
FROM node:lts-alpine as web-builder
@@ -14,7 +14,7 @@ RUN apk add curl git zlib zlib-dev autoconf g++ make libpng-dev gifsicle alpine-
&& mv dist /dist
FROM multiarch/qemu-user-static:x86_64-arm as qemu
FROM arm32v7/debian:buster-slim as app
FROM arm32v7/debian:stable-slim as app
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
ARG DEBIAN_FRONTEND="noninteractive"
@@ -24,6 +24,8 @@ ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn
ENV NVIDIA_DRIVER_CAPABILITIES="compute,video,utility"
COPY --from=qemu /usr/bin/qemu-arm-static /usr/bin
# curl: setup & healthcheck
RUN apt-get update \
&& apt-get install --no-install-recommends --no-install-suggests -y ca-certificates gnupg curl && \
curl -ks https://repo.jellyfin.org/debian/jellyfin_team.gpg.key | apt-key add - && \
@@ -42,7 +44,7 @@ RUN apt-get update \
vainfo \
libva2 \
locales \
&& apt-get remove curl gnupg -y \
&& apt-get remove gnupg -y \
&& apt-get clean autoclean -y \
&& apt-get autoremove -y \
&& rm -rf /var/lib/apt/lists/* \
@@ -50,7 +52,7 @@ RUN apt-get update \
&& chmod 777 /cache /config /media \
&& sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1
# ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1
ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
@@ -66,6 +68,8 @@ RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin"
FROM app
ENV HEALTHCHECK_URL=http://localhost:8096/health
COPY --from=builder /jellyfin /jellyfin
COPY --from=web-builder /dist /jellyfin/jellyfin-web
@@ -75,3 +79,6 @@ ENTRYPOINT ["./jellyfin/jellyfin", \
"--datadir", "/config", \
"--cachedir", "/cache", \
"--ffmpeg", "/usr/lib/jellyfin-ffmpeg/ffmpeg"]
HEALTHCHECK --interval=30s --timeout=30s --start-period=10s --retries=3 \
CMD curl -Lk "${HEALTHCHECK_URL}" || exit 1

View File

@@ -1,8 +1,8 @@
# DESIGNED FOR BUILDING ON AMD64 ONLY
# DESIGNED FOR BUILDING ON ARM64 ONLY
#####################################
# Requires binfm_misc registration
# https://github.com/multiarch/qemu-user-static#binfmt_misc-register
ARG DOTNET_VERSION=5.0
ARG DOTNET_VERSION=6.0
FROM node:lts-alpine as web-builder
@@ -14,7 +14,7 @@ RUN apk add curl git zlib zlib-dev autoconf g++ make libpng-dev gifsicle alpine-
&& mv dist /dist
FROM multiarch/qemu-user-static:x86_64-aarch64 as qemu
FROM arm64v8/debian:buster-slim as app
FROM arm64v8/debian:stable-slim as app
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
ARG DEBIAN_FRONTEND="noninteractive"
@@ -24,6 +24,8 @@ ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn
ENV NVIDIA_DRIVER_CAPABILITIES="compute,video,utility"
COPY --from=qemu /usr/bin/qemu-aarch64-static /usr/bin
# curl: healcheck
RUN apt-get update && apt-get install --no-install-recommends --no-install-suggests -y \
ffmpeg \
libssl-dev \
@@ -33,6 +35,7 @@ RUN apt-get update && apt-get install --no-install-recommends --no-install-sugge
libomxil-bellagio0 \
libomxil-bellagio-bin \
locales \
curl \
&& apt-get clean autoclean -y \
&& apt-get autoremove -y \
&& rm -rf /var/lib/apt/lists/* \
@@ -40,7 +43,7 @@ RUN apt-get update && apt-get install --no-install-recommends --no-install-sugge
&& chmod 777 /cache /config /media \
&& sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1
# ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1
ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
@@ -56,6 +59,8 @@ RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin"
FROM app
ENV HEALTHCHECK_URL=http://localhost:8096/health
COPY --from=builder /jellyfin /jellyfin
COPY --from=web-builder /dist /jellyfin/jellyfin-web
@@ -65,3 +70,6 @@ ENTRYPOINT ["./jellyfin/jellyfin", \
"--datadir", "/config", \
"--cachedir", "/cache", \
"--ffmpeg", "/usr/bin/ffmpeg"]
HEALTHCHECK --interval=30s --timeout=30s --start-period=10s --retries=3 \
CMD curl -Lk "${HEALTHCHECK_URL}" || exit 1

View File

@@ -10,7 +10,7 @@
</ItemGroup>
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AnalysisMode>AllDisabledByDefault</AnalysisMode>

View File

@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
@@ -76,7 +77,7 @@ namespace DvdLib.Ifo
private void ReadVTS(ushort vtsNum, IReadOnlyList<FileInfo> allFiles)
{
var filename = string.Format("VTS_{0:00}_0.IFO", vtsNum);
var filename = string.Format(CultureInfo.InvariantCulture, "VTS_{0:00}_0.IFO", vtsNum);
var vtsPath = allFiles.FirstOrDefault(i => string.Equals(i.Name, filename, StringComparison.OrdinalIgnoreCase)) ??
allFiles.FirstOrDefault(i => string.Equals(i.Name, Path.ChangeExtension(filename, ".bup"), StringComparison.OrdinalIgnoreCase));

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,3 @@
#pragma warning disable CS1591
using MediaBrowser.Controller.Entities;
namespace Emby.Dlna.ContentDirectory
@@ -13,24 +11,29 @@ namespace Emby.Dlna.ContentDirectory
/// Initializes a new instance of the <see cref="ServerItem"/> class.
/// </summary>
/// <param name="item">The <see cref="BaseItem"/>.</param>
public ServerItem(BaseItem item)
/// <param name="stubType">The stub type.</param>
public ServerItem(BaseItem item, StubType? stubType)
{
Item = item;
if (item is IItemByName && !(item is Folder))
if (stubType.HasValue)
{
StubType = stubType;
}
else if (item is IItemByName and not Folder)
{
StubType = Dlna.ContentDirectory.StubType.Folder;
}
}
/// <summary>
/// Gets or sets the underlying base item.
/// Gets the underlying base item.
/// </summary>
public BaseItem Item { get; set; }
public BaseItem Item { get; }
/// <summary>
/// Gets or sets the DLNA item type.
/// Gets the DLNA item type.
/// </summary>
public StubType? StubType { get; set; }
public StubType? StubType { get; }
}
}

View File

@@ -41,8 +41,6 @@ namespace Emby.Dlna.Didl
private const string NsUpnp = "urn:schemas-upnp-org:metadata-1-0/upnp/";
private const string NsDlna = "urn:schemas-dlna-org:metadata-1-0/";
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly DeviceProfile _profile;
private readonly IImageProcessor _imageProcessor;
private readonly string _serverAddress;
@@ -317,7 +315,7 @@ namespace Emby.Dlna.Didl
if (mediaSource.RunTimeTicks.HasValue)
{
writer.WriteAttributeString("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", _usCulture));
writer.WriteAttributeString("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", CultureInfo.InvariantCulture));
}
if (filter.Contains("res@size"))
@@ -328,7 +326,7 @@ namespace Emby.Dlna.Didl
if (size.HasValue)
{
writer.WriteAttributeString("size", size.Value.ToString(_usCulture));
writer.WriteAttributeString("size", size.Value.ToString(CultureInfo.InvariantCulture));
}
}
}
@@ -342,7 +340,7 @@ namespace Emby.Dlna.Didl
if (targetChannels.HasValue)
{
writer.WriteAttributeString("nrAudioChannels", targetChannels.Value.ToString(_usCulture));
writer.WriteAttributeString("nrAudioChannels", targetChannels.Value.ToString(CultureInfo.InvariantCulture));
}
if (filter.Contains("res@resolution"))
@@ -361,12 +359,12 @@ namespace Emby.Dlna.Didl
if (targetSampleRate.HasValue)
{
writer.WriteAttributeString("sampleFrequency", targetSampleRate.Value.ToString(_usCulture));
writer.WriteAttributeString("sampleFrequency", targetSampleRate.Value.ToString(CultureInfo.InvariantCulture));
}
if (totalBitrate.HasValue)
{
writer.WriteAttributeString("bitrate", totalBitrate.Value.ToString(_usCulture));
writer.WriteAttributeString("bitrate", totalBitrate.Value.ToString(CultureInfo.InvariantCulture));
}
var mediaProfile = _profile.GetVideoMediaProfile(
@@ -552,7 +550,7 @@ namespace Emby.Dlna.Didl
if (mediaSource.RunTimeTicks.HasValue)
{
writer.WriteAttributeString("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", _usCulture));
writer.WriteAttributeString("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", CultureInfo.InvariantCulture));
}
if (filter.Contains("res@size"))
@@ -563,7 +561,7 @@ namespace Emby.Dlna.Didl
if (size.HasValue)
{
writer.WriteAttributeString("size", size.Value.ToString(_usCulture));
writer.WriteAttributeString("size", size.Value.ToString(CultureInfo.InvariantCulture));
}
}
}
@@ -575,17 +573,17 @@ namespace Emby.Dlna.Didl
if (targetChannels.HasValue)
{
writer.WriteAttributeString("nrAudioChannels", targetChannels.Value.ToString(_usCulture));
writer.WriteAttributeString("nrAudioChannels", targetChannels.Value.ToString(CultureInfo.InvariantCulture));
}
if (targetSampleRate.HasValue)
{
writer.WriteAttributeString("sampleFrequency", targetSampleRate.Value.ToString(_usCulture));
writer.WriteAttributeString("sampleFrequency", targetSampleRate.Value.ToString(CultureInfo.InvariantCulture));
}
if (targetAudioBitrate.HasValue)
{
writer.WriteAttributeString("bitrate", targetAudioBitrate.Value.ToString(_usCulture));
writer.WriteAttributeString("bitrate", targetAudioBitrate.Value.ToString(CultureInfo.InvariantCulture));
}
var mediaProfile = _profile.GetAudioMediaProfile(
@@ -639,7 +637,7 @@ namespace Emby.Dlna.Didl
writer.WriteAttributeString("restricted", "1");
writer.WriteAttributeString("searchable", "1");
writer.WriteAttributeString("childCount", childCount.ToString(_usCulture));
writer.WriteAttributeString("childCount", childCount.ToString(CultureInfo.InvariantCulture));
var clientId = GetClientId(folder, stubType);
@@ -731,7 +729,7 @@ namespace Emby.Dlna.Didl
{
if (item.PremiereDate.HasValue)
{
AddValue(writer, "dc", "date", item.PremiereDate.Value.ToString("o", CultureInfo.InvariantCulture), NsDc);
AddValue(writer, "dc", "date", item.PremiereDate.Value.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture), NsDc);
}
}
@@ -748,7 +746,7 @@ namespace Emby.Dlna.Didl
AddValue(writer, "upnp", "publisher", studio, NsUpnp);
}
if (!(item is Folder))
if (item is not Folder)
{
if (filter.Contains("dc:description"))
{
@@ -931,11 +929,11 @@ namespace Emby.Dlna.Didl
if (item.IndexNumber.HasValue)
{
AddValue(writer, "upnp", "originalTrackNumber", item.IndexNumber.Value.ToString(_usCulture), NsUpnp);
AddValue(writer, "upnp", "originalTrackNumber", item.IndexNumber.Value.ToString(CultureInfo.InvariantCulture), NsUpnp);
if (item is Episode)
{
AddValue(writer, "upnp", "episodeNumber", item.IndexNumber.Value.ToString(_usCulture), NsUpnp);
AddValue(writer, "upnp", "episodeNumber", item.IndexNumber.Value.ToString(CultureInfo.InvariantCulture), NsUpnp);
}
}
}

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)
@@ -112,7 +110,7 @@ namespace Emby.Dlna
if (profile == null)
{
LogUnmatchedProfile(deviceInfo);
_logger.LogInformation("No matching device profile found. The default will need to be used. \n{@Profile}", deviceInfo);
}
else
{
@@ -122,23 +120,6 @@ namespace Emby.Dlna
return profile;
}
private void LogUnmatchedProfile(DeviceIdentification profile)
{
var builder = new StringBuilder();
builder.AppendLine("No matching device profile found. The default will need to be used.");
builder.Append("FriendlyName: ").AppendLine(profile.FriendlyName);
builder.Append("Manufacturer: ").AppendLine(profile.Manufacturer);
builder.Append("ManufacturerUrl: ").AppendLine(profile.ManufacturerUrl);
builder.Append("ModelDescription: ").AppendLine(profile.ModelDescription);
builder.Append("ModelName: ").AppendLine(profile.ModelName);
builder.Append("ModelNumber: ").AppendLine(profile.ModelNumber);
builder.Append("ModelUrl: ").AppendLine(profile.ModelUrl);
builder.Append("SerialNumber: ").AppendLine(profile.SerialNumber);
_logger.LogInformation(builder.ToString());
}
/// <summary>
/// Attempts to match a device with a profile.
/// Rules:
@@ -244,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
@@ -270,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);
@@ -313,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);
@@ -359,14 +333,17 @@ namespace Emby.Dlna
// The stream should exist as we just got its name from GetManifestResourceNames
using (var stream = _assembly.GetManifestResourceStream(name)!)
{
var length = stream.Length;
var fileInfo = _fileSystem.GetFileInfo(path);
if (!fileInfo.Exists || fileInfo.Length != stream.Length)
if (!fileInfo.Exists || fileInfo.Length != length)
{
Directory.CreateDirectory(systemProfilesPath);
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None))
var fileOptions = AsyncFile.WriteOptions;
fileOptions.Mode = FileMode.Create;
fileOptions.PreallocationSize = length;
using (var fileStream = new FileStream(path, fileOptions))
{
await stream.CopyToAsync(fileStream).ConfigureAwait(false);
}
@@ -413,7 +390,7 @@ namespace Emby.Dlna
}
/// <inheritdoc />
public void UpdateProfile(DeviceProfile profile)
public void UpdateProfile(string profileId, DeviceProfile profile)
{
profile = ReserializeProfile(profile);
@@ -427,7 +404,7 @@ namespace Emby.Dlna
throw new ArgumentException("Profile is missing Name");
}
var current = GetProfileInfosInternal().First(i => string.Equals(i.Info.Id, profile.Id, StringComparison.OrdinalIgnoreCase));
var current = GetProfileInfosInternal().First(i => string.Equals(i.Info.Id, profileId, StringComparison.OrdinalIgnoreCase));
var newFilename = _fileSystem.GetValidFilename(profile.Name) + ".xml";
var path = Path.Combine(UserProfilesPath, newFilename);
@@ -486,18 +463,22 @@ namespace Emby.Dlna
}
/// <inheritdoc />
public ImageStream GetIcon(string filename)
public ImageStream? GetIcon(string filename)
{
var format = filename.EndsWith(".png", StringComparison.OrdinalIgnoreCase)
? ImageFormat.Png
: ImageFormat.Jpg;
var resource = GetType().Namespace + ".Images." + filename.ToLowerInvariant();
return new ImageStream
var stream = _assembly.GetManifestResourceStream(resource);
if (stream == null)
{
Format = format,
Stream = _assembly.GetManifestResourceStream(resource)
return null;
}
return new ImageStream(stream)
{
Format = format
};
}

View File

@@ -17,16 +17,19 @@
</ItemGroup>
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AnalysisMode>AllDisabledByDefault</AnalysisMode>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<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.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>
@@ -73,7 +76,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
</ItemGroup>
</Project>

View File

@@ -11,6 +11,7 @@ using System.Net.Http;
using System.Net.Mime;
using System.Text;
using System.Threading.Tasks;
using Jellyfin.Extensions;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using Microsoft.Extensions.Logging;
@@ -25,8 +26,6 @@ namespace Emby.Dlna.Eventing
private readonly ILogger _logger;
private readonly IHttpClientFactory _httpClientFactory;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
public DlnaEventManager(ILogger logger, IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
@@ -82,9 +81,7 @@ namespace Emby.Dlna.Eventing
if (!string.IsNullOrEmpty(header))
{
// Starts with SECOND-
header = header.Split('-')[^1];
if (int.TryParse(header, NumberStyles.Integer, _usCulture, out var val))
if (int.TryParse(header.AsSpan().RightPart('-'), NumberStyles.Integer, CultureInfo.InvariantCulture, out var val))
{
return val;
}
@@ -107,7 +104,7 @@ namespace Emby.Dlna.Eventing
var response = new EventSubscriptionResponse(string.Empty, "text/plain");
response.Headers["SID"] = subscriptionId;
response.Headers["TIMEOUT"] = string.IsNullOrEmpty(requestedTimeoutString) ? ("SECOND-" + timeoutSeconds.ToString(_usCulture)) : requestedTimeoutString;
response.Headers["TIMEOUT"] = string.IsNullOrEmpty(requestedTimeoutString) ? ("SECOND-" + timeoutSeconds.ToString(CultureInfo.InvariantCulture)) : requestedTimeoutString;
return response;
}
@@ -164,7 +161,7 @@ namespace Emby.Dlna.Eventing
options.Headers.TryAddWithoutValidation("NT", subscription.NotificationType);
options.Headers.TryAddWithoutValidation("NTS", "upnp:propchange");
options.Headers.TryAddWithoutValidation("SID", subscription.Id);
options.Headers.TryAddWithoutValidation("SEQ", subscription.TriggerCount.ToString(_usCulture));
options.Headers.TryAddWithoutValidation("SEQ", subscription.TriggerCount.ToString(CultureInfo.InvariantCulture));
try
{

View File

@@ -52,7 +52,6 @@ namespace Emby.Dlna.Main
private readonly ISocketFactory _socketFactory;
private readonly INetworkManager _networkManager;
private readonly object _syncLock = new object();
private readonly NetworkConfiguration _netConfig;
private readonly bool _disabled;
private PlayToManager _manager;
@@ -125,8 +124,8 @@ namespace Emby.Dlna.Main
config);
Current = this;
_netConfig = config.GetConfiguration<NetworkConfiguration>("network");
_disabled = appHost.ListenWithHttps && _netConfig.RequireHttps;
var netConfig = config.GetConfiguration<NetworkConfiguration>(NetworkConfigurationStore.StoreKey);
_disabled = appHost.ListenWithHttps && netConfig.RequireHttps;
if (_disabled && _config.GetDlnaConfiguration().EnableServer)
{
@@ -219,11 +218,6 @@ namespace Emby.Dlna.Main
}
}
private void LogMessage(string msg)
{
_logger.LogDebug(msg);
}
private void StartDeviceDiscovery(ISsdpCommunicationsServer communicationsServer)
{
try
@@ -268,12 +262,11 @@ namespace Emby.Dlna.Main
{
_publisher = new SsdpDevicePublisher(
_communicationsServer,
_networkManager,
MediaBrowser.Common.System.OperatingSystem.Name,
Environment.OSVersion.VersionString,
_config.GetDlnaConfiguration().SendOnlyMatchedHost)
{
LogFunction = LogMessage,
LogFunction = (msg) => _logger.LogDebug("{Msg}", msg),
SupportPnpRootDevice = false
};
@@ -318,15 +311,9 @@ namespace Emby.Dlna.Main
var fullService = "urn:schemas-upnp-org:device:MediaServer:1";
_logger.LogInformation("Registering publisher for {0} on {1}", fullService, address);
_logger.LogInformation("Registering publisher for {ResourceName} on {DeviceAddress}", fullService, address);
var uri = new UriBuilder(_appHost.GetSmartApiUrl(address.Address) + descriptorUri);
if (!string.IsNullOrEmpty(_appHost.PublishedServerUrl))
{
// DLNA will only work over http, so we must reset to http:// : {port}.
uri.Scheme = "http";
uri.Port = _netConfig.HttpServerPortNumber;
}
var uri = new UriBuilder(_appHost.GetApiUrlForLocalAccess(false) + descriptorUri);
var device = new SsdpRootDevice
{
@@ -412,7 +399,6 @@ namespace Emby.Dlna.Main
_imageProcessor,
_deviceDiscovery,
_httpClientFactory,
_config,
_userDataManager,
_localization,
_mediaSourceManager,

View File

@@ -20,8 +20,6 @@ namespace Emby.Dlna.PlayTo
{
public class Device : IDisposable
{
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
private readonly IHttpClientFactory _httpClientFactory;
private readonly ILogger _logger;
@@ -640,7 +638,7 @@ namespace Emby.Dlna.PlayTo
return;
}
Volume = int.Parse(volumeValue, UsCulture);
Volume = int.Parse(volumeValue, CultureInfo.InvariantCulture);
if (Volume > 0)
{
@@ -842,7 +840,7 @@ namespace Emby.Dlna.PlayTo
if (!string.IsNullOrWhiteSpace(duration)
&& !string.Equals(duration, "NOT_IMPLEMENTED", StringComparison.OrdinalIgnoreCase))
{
Duration = TimeSpan.Parse(duration, UsCulture);
Duration = TimeSpan.Parse(duration, CultureInfo.InvariantCulture);
}
else
{
@@ -854,7 +852,7 @@ namespace Emby.Dlna.PlayTo
if (!string.IsNullOrWhiteSpace(position) && !string.Equals(position, "NOT_IMPLEMENTED", StringComparison.OrdinalIgnoreCase))
{
Position = TimeSpan.Parse(position, UsCulture);
Position = TimeSpan.Parse(position, CultureInfo.InvariantCulture);
}
var track = result.Document.Descendants("TrackMetaData").FirstOrDefault();
@@ -1181,6 +1179,7 @@ namespace Emby.Dlna.PlayTo
return new Device(deviceProperties, httpClientFactory, logger);
}
#nullable enable
private static DeviceIcon CreateIcon(XElement element)
{
if (element == null)
@@ -1188,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, UsCulture);
var heightValue = int.Parse(height, NumberStyles.Integer, UsCulture);
_ = 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 (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

@@ -30,8 +30,6 @@ namespace Emby.Dlna.PlayTo
{
public class PlayToController : ISessionController, IDisposable
{
private static readonly CultureInfo _usCulture = CultureInfo.ReadOnly(new CultureInfo("en-US"));
private readonly SessionInfo _session;
private readonly ISessionManager _sessionManager;
private readonly ILibraryManager _libraryManager;
@@ -212,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;
@@ -716,7 +714,7 @@ namespace Emby.Dlna.PlayTo
case GeneralCommandType.SetAudioStreamIndex:
if (command.Arguments.TryGetValue("Index", out string index))
{
if (int.TryParse(index, NumberStyles.Integer, _usCulture, out var val))
if (int.TryParse(index, NumberStyles.Integer, CultureInfo.InvariantCulture, out var val))
{
return SetAudioStreamIndex(val);
}
@@ -728,7 +726,7 @@ namespace Emby.Dlna.PlayTo
case GeneralCommandType.SetSubtitleStreamIndex:
if (command.Arguments.TryGetValue("Index", out index))
{
if (int.TryParse(index, NumberStyles.Integer, _usCulture, out var val))
if (int.TryParse(index, NumberStyles.Integer, CultureInfo.InvariantCulture, out var val))
{
return SetSubtitleStreamIndex(val);
}
@@ -740,7 +738,7 @@ namespace Emby.Dlna.PlayTo
case GeneralCommandType.SetVolume:
if (command.Arguments.TryGetValue("Volume", out string vol))
{
if (int.TryParse(vol, NumberStyles.Integer, _usCulture, out var volume))
if (int.TryParse(vol, NumberStyles.Integer, CultureInfo.InvariantCulture, out var volume))
{
return _device.SetVolume(volume, cancellationToken);
}

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;
@@ -173,7 +170,9 @@ namespace Emby.Dlna.PlayTo
uuid = uri.ToString().GetMD5().ToString("N", CultureInfo.InvariantCulture);
}
var sessionInfo = _sessionManager.LogSessionActivity("DLNA", _appHost.ApplicationVersionString, uuid, null, uri.OriginalString, null);
var sessionInfo = await _sessionManager
.LogSessionActivity("DLNA", _appHost.ApplicationVersionString, uuid, null, uri.OriginalString, null)
.ConfigureAwait(false);
var controller = sessionInfo.SessionControllers.OfType<PlayToController>().FirstOrDefault();

View File

@@ -20,8 +20,6 @@ namespace Emby.Dlna.PlayTo
private const string USERAGENT = "Microsoft-Windows/6.2 UPnP/1.0 Microsoft-DLNA DLNADOC/1.50";
private const string FriendlyName = "Jellyfin";
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly IHttpClientFactory _httpClientFactory;
public SsdpHttpClient(IHttpClientFactory httpClientFactory)
@@ -45,10 +43,12 @@ namespace Emby.Dlna.PlayTo
header,
cancellationToken)
.ConfigureAwait(false);
response.EnsureSuccessStatusCode();
await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
return await XDocument.LoadAsync(
stream,
LoadOptions.PreserveWhitespace,
LoadOptions.None,
cancellationToken).ConfigureAwait(false);
}
@@ -78,14 +78,15 @@ namespace Emby.Dlna.PlayTo
{
using var options = new HttpRequestMessage(new HttpMethod("SUBSCRIBE"), url);
options.Headers.UserAgent.ParseAdd(USERAGENT);
options.Headers.TryAddWithoutValidation("HOST", ip + ":" + port.ToString(_usCulture));
options.Headers.TryAddWithoutValidation("CALLBACK", "<" + localIp + ":" + eventport.ToString(_usCulture) + ">");
options.Headers.TryAddWithoutValidation("HOST", ip + ":" + port.ToString(CultureInfo.InvariantCulture));
options.Headers.TryAddWithoutValidation("CALLBACK", "<" + localIp + ":" + eventport.ToString(CultureInfo.InvariantCulture) + ">");
options.Headers.TryAddWithoutValidation("NT", "upnp:event");
options.Headers.TryAddWithoutValidation("TIMEOUT", "Second-" + timeOut.ToString(_usCulture));
options.Headers.TryAddWithoutValidation("TIMEOUT", "Second-" + timeOut.ToString(CultureInfo.InvariantCulture));
using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
.SendAsync(options, HttpCompletionOption.ResponseHeadersRead)
.ConfigureAwait(false);
response.EnsureSuccessStatusCode();
}
public async Task<XDocument> GetDataAsync(string url, CancellationToken cancellationToken)
@@ -94,12 +95,13 @@ namespace Emby.Dlna.PlayTo
options.Headers.UserAgent.ParseAdd(USERAGENT);
options.Headers.TryAddWithoutValidation("FriendlyName.DLNA.ORG", FriendlyName);
using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
try
{
return await XDocument.LoadAsync(
stream,
LoadOptions.PreserveWhitespace,
LoadOptions.None,
cancellationToken).ConfigureAwait(false);
}
catch

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

@@ -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

@@ -15,7 +15,6 @@ namespace Emby.Dlna.Server
{
private readonly DeviceProfile _profile;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly string _serverUdn;
private readonly string _serverAddress;
private readonly string _serverName;
@@ -190,16 +189,16 @@ 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(_usCulture)))
.Append(SecurityElement.Escape(icon.Width.ToString(CultureInfo.InvariantCulture)))
.Append("</width>");
builder.Append("<height>")
.Append(SecurityElement.Escape(icon.Height.ToString(_usCulture)))
.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))
@@ -220,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))
@@ -250,8 +249,7 @@ namespace Emby.Dlna.Server
url = _serverAddress.TrimEnd('/') + "/dlna/" + _serverUdn + "/" + url.TrimStart('/');
// TODO: @bond remove null-coalescing operator when https://github.com/dotnet/runtime/pull/52442 is merged/released
return SecurityElement.Escape(url) ?? string.Empty;
return SecurityElement.Escape(url);
}
private IEnumerable<DeviceIcon> GetIcons()

View File

@@ -64,7 +64,7 @@ namespace Emby.Dlna.Service
requestInfo = await ParseRequestAsync(reader).ConfigureAwait(false);
}
Logger.LogDebug("Received control request {0}", requestInfo.LocalName);
Logger.LogDebug("Received control request {LocalName}, params: {@Headers}", requestInfo.LocalName, requestInfo.Headers);
var settings = new XmlWriterSettings
{

View File

@@ -23,14 +23,14 @@ namespace Emby.Dlna.Service
return EventManager.CancelEventSubscription(subscriptionId);
}
public EventSubscriptionResponse RenewEventSubscription(string subscriptionId, string notificationType, string timeoutString, string callbackUrl)
public EventSubscriptionResponse RenewEventSubscription(string subscriptionId, string notificationType, string requestedTimeoutString, string callbackUrl)
{
return EventManager.RenewEventSubscription(subscriptionId, notificationType, timeoutString, callbackUrl);
return EventManager.RenewEventSubscription(subscriptionId, notificationType, requestedTimeoutString, callbackUrl);
}
public EventSubscriptionResponse CreateEventSubscription(string notificationType, string timeoutString, string callbackUrl)
public EventSubscriptionResponse CreateEventSubscription(string notificationType, string requestedTimeoutString, string callbackUrl)
{
return EventManager.CreateEventSubscription(notificationType, timeoutString, callbackUrl);
return EventManager.CreateEventSubscription(notificationType, requestedTimeoutString, callbackUrl);
}
}
}

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

@@ -6,10 +6,13 @@
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AnalysisMode>AllDisabledByDefault</AnalysisMode>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
@@ -25,7 +28,7 @@
<!-- Code analysers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<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.376" 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;
@@ -26,7 +27,7 @@ namespace Emby.Drawing
public sealed class ImageProcessor : IImageProcessor, IDisposable
{
// Increment this when there's a change requiring caches to be invalidated
private const string Version = "3";
private const char Version = '3';
private static readonly HashSet<string> _transparentImageTypes
= new HashSet<string>(StringComparer.OrdinalIgnoreCase) { ".png", ".webp", ".gif" };
@@ -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 = new FileStream(file.Item1, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, true))
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"),
@@ -437,7 +439,7 @@ namespace Emby.Drawing
.ToString("N", CultureInfo.InvariantCulture);
}
private async Task<(string path, DateTime dateModified)> GetSupportedImage(string originalImagePath, DateTime dateModified)
private async Task<(string Path, DateTime DateModified)> GetSupportedImage(string originalImagePath, DateTime dateModified)
{
var inputFormat = Path.GetExtension(originalImagePath)
.TrimStart('.')

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,4 +1,7 @@
#pragma warning disable CA1819
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Emby.Naming.Video;
@@ -122,11 +125,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[]
@@ -137,8 +140,11 @@ namespace Emby.Naming.Common
CleanStrings = new[]
{
@"[ _\,\.\(\)\[\]\-](3d|sbs|tab|hsbs|htab|mvc|HDR|HDC|UHD|UltraHD|4k|ac3|dts|custom|dc|divx|divx5|dsr|dsrip|dutch|dvd|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip|hdtvrip|internal|limited|multisubs|ntsc|ogg|ogm|pal|pdtv|proper|repack|rerip|retail|cd[1-9]|r3|r5|bd5|bd|se|svcd|swedish|german|read.nfo|nfofix|unrated|ws|telesync|ts|telecine|tc|brrip|bdrip|480p|480i|576p|576i|720p|720i|1080p|1080i|2160p|hrhd|hrhdtv|hddvd|bluray|blu-ray|x264|x265|h264|h265|xvid|xvidvd|xxx|www.www|AAC|DTS|\[.*\])([ _\,\.\(\)\[\]\-]|$)",
@"(\[.*\])"
@"^\s*(?<cleaned>.+?)[ _\,\.\(\)\[\]\-](3d|sbs|tab|hsbs|htab|mvc|HDR|HDC|UHD|UltraHD|4k|ac3|dts|custom|dc|divx|divx5|dsr|dsrip|dutch|dvd|dvdrip|dvdscr|dvdscreener|screener|dvdivx|cam|fragment|fs|hdtv|hdrip|hdtvrip|internal|limited|multisubs|ntsc|ogg|ogm|pal|pdtv|proper|repack|rerip|retail|cd[1-9]|r3|r5|bd5|bd|se|svcd|swedish|german|read.nfo|nfofix|unrated|ws|telesync|ts|telecine|tc|brrip|bdrip|480p|480i|576p|576i|720p|720i|1080p|1080i|2160p|hrhd|hrhdtv|hddvd|bluray|blu-ray|x264|x265|h264|h265|xvid|xvidvd|xxx|www.www|AAC|DTS|\[.*\])([ _\,\.\(\)\[\]\-]|$)",
@"^(?<cleaned>.+?)(\[.*\])",
@"^\s*(?<cleaned>.+?)\WE[0-9]+(-|~)E?[0-9]+(\W|$)",
@"^\s*\[[^\]]+\](?!\.\w+$)\s*(?<cleaned>.+)",
@"^\s*(?<cleaned>.+?)\s+-\s+[0-9]+\s*$"
};
SubtitleFileExtensions = new[]
@@ -250,6 +256,8 @@ namespace Emby.Naming.Common
},
// <!-- foo.ep01, foo.EP_01 -->
new EpisodeExpression(@"[\._ -]()[Ee][Pp]_?([0-9]+)([^\\/]*)$"),
// <!-- foo.E01., foo.e01. -->
new EpisodeExpression(@"[^\\/]*?()\.?[Ee]([0-9]+)\.([^\\/]*)$"),
new EpisodeExpression("(?<year>[0-9]{4})[\\.-](?<month>[0-9]{2})[\\.-](?<day>[0-9]{2})", true)
{
DateTimeFormats = new[]
@@ -368,6 +376,20 @@ namespace Emby.Naming.Common
IsOptimistic = true,
IsNamed = true
},
// Series and season only expression
// "the show/season 1", "the show/s01"
new EpisodeExpression(@"(.*(\\|\/))*(?<seriesname>.+)\/[Ss](eason)?[\. _\-]*(?<seasonnumber>[0-9]+)")
{
IsNamed = true
},
// Series and season only expression
// "the show S01", "the show season 1"
new EpisodeExpression(@"(.*(\\|\/))*(?<seriesname>.+)[\. _\-]+[sS](eason)?[\. _\-]*(?<seasonnumber>[0-9]+)")
{
IsNamed = true
},
};
EpisodeWithoutSeasonExpressions = new[]
@@ -382,6 +404,12 @@ namespace Emby.Naming.Common
VideoExtraRules = new[]
{
new ExtraRule(
ExtraType.Trailer,
ExtraRuleType.DirectoryName,
"trailers",
MediaType.Video),
new ExtraRule(
ExtraType.Trailer,
ExtraRuleType.Filename,
@@ -442,12 +470,24 @@ namespace Emby.Naming.Common
" sample",
MediaType.Video),
new ExtraRule(
ExtraType.ThemeVideo,
ExtraRuleType.DirectoryName,
"backdrops",
MediaType.Video),
new ExtraRule(
ExtraType.ThemeSong,
ExtraRuleType.Filename,
"theme",
MediaType.Audio),
new ExtraRule(
ExtraType.ThemeSong,
ExtraRuleType.DirectoryName,
"theme-music",
MediaType.Audio),
new ExtraRule(
ExtraType.Scene,
ExtraRuleType.Suffix,
@@ -478,6 +518,12 @@ namespace Emby.Naming.Common
"-deleted",
MediaType.Video),
new ExtraRule(
ExtraType.DeletedScene,
ExtraRuleType.Suffix,
"-deletedscene",
MediaType.Video),
new ExtraRule(
ExtraType.Clip,
ExtraRuleType.Suffix,
@@ -536,7 +582,7 @@ namespace Emby.Naming.Common
ExtraType.Unknown,
ExtraRuleType.DirectoryName,
"extras",
MediaType.Video),
MediaType.Video)
};
Format3DRules = new[]
@@ -648,9 +694,29 @@ namespace Emby.Naming.Common
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToArray();
AllExtrasTypesFolderNames = new Dictionary<string, ExtraType>(StringComparer.OrdinalIgnoreCase)
{
["trailers"] = ExtraType.Trailer,
["theme-music"] = ExtraType.ThemeSong,
["backdrops"] = ExtraType.ThemeVideo,
["extras"] = ExtraType.Unknown,
["behind the scenes"] = ExtraType.BehindTheScenes,
["deleted scenes"] = ExtraType.DeletedScene,
["interviews"] = ExtraType.Interview,
["scenes"] = ExtraType.Scene,
["samples"] = ExtraType.Sample,
["shorts"] = ExtraType.Clip,
["featurettes"] = ExtraType.Clip
};
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>
@@ -732,9 +798,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.
@@ -756,11 +822,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>
@@ -786,7 +847,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

@@ -6,14 +6,17 @@
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<AnalysisMode>AllDisabledByDefault</AnalysisMode>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Stability)'=='Unstable'">
@@ -39,13 +42,13 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
</ItemGroup>
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<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.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>

View File

@@ -2,6 +2,7 @@ using System;
using System.IO;
using System.Linq;
using Emby.Naming.Common;
using Jellyfin.Extensions;
namespace Emby.Naming.Subtitles
{
@@ -34,7 +35,7 @@ namespace Emby.Naming.Subtitles
}
var extension = Path.GetExtension(path);
if (!_options.SubtitleFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
if (!_options.SubtitleFileExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase))
{
return null;
}
@@ -42,11 +43,11 @@ namespace Emby.Naming.Subtitles
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)));
_options.SubtitleDefaultFlags.Any(i => flags.Contains(i, StringComparison.OrdinalIgnoreCase)),
_options.SubtitleForcedFlags.Any(i => flags.Contains(i, StringComparison.OrdinalIgnoreCase)));
var parts = flags.Where(i => !_options.SubtitleDefaultFlags.Contains(i, StringComparer.OrdinalIgnoreCase)
&& !_options.SubtitleForcedFlags.Contains(i, StringComparer.OrdinalIgnoreCase))
var parts = flags.Where(i => !_options.SubtitleDefaultFlags.Contains(i, StringComparison.OrdinalIgnoreCase)
&& !_options.SubtitleForcedFlags.Contains(i, StringComparison.OrdinalIgnoreCase))
.ToList();
// Should have a name, language and file extension

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

@@ -0,0 +1,29 @@
namespace Emby.Naming.TV
{
/// <summary>
/// Holder object for Series information.
/// </summary>
public class SeriesInfo
{
/// <summary>
/// Initializes a new instance of the <see cref="SeriesInfo"/> class.
/// </summary>
/// <param name="path">Path to the file.</param>
public SeriesInfo(string path)
{
Path = path;
}
/// <summary>
/// Gets or sets the path.
/// </summary>
/// <value>The path.</value>
public string Path { get; set; }
/// <summary>
/// Gets or sets the name of the series.
/// </summary>
/// <value>The name of the series.</value>
public string? Name { get; set; }
}
}

View File

@@ -0,0 +1,60 @@
using Emby.Naming.Common;
namespace Emby.Naming.TV
{
/// <summary>
/// Used to parse information about series from paths containing more information that only the series name.
/// Uses the same regular expressions as the EpisodePathParser but have different success criteria.
/// </summary>
public static class SeriesPathParser
{
/// <summary>
/// Parses information about series from path.
/// </summary>
/// <param name="options"><see cref="NamingOptions"/> object containing EpisodeExpressions and MultipleEpisodeExpressions.</param>
/// <param name="path">Path.</param>
/// <returns>Returns <see cref="SeriesPathParserResult"/> object.</returns>
public static SeriesPathParserResult Parse(NamingOptions options, string path)
{
SeriesPathParserResult? result = null;
foreach (var expression in options.EpisodeExpressions)
{
var currentResult = Parse(path, expression);
if (currentResult.Success)
{
result = currentResult;
break;
}
}
if (result != null)
{
if (!string.IsNullOrEmpty(result.SeriesName))
{
result.SeriesName = result.SeriesName.Trim(' ', '_', '.', '-');
}
}
return result ?? new SeriesPathParserResult();
}
private static SeriesPathParserResult Parse(string name, EpisodeExpression expression)
{
var result = new SeriesPathParserResult();
var match = expression.Regex.Match(name);
if (match.Success && match.Groups.Count >= 3)
{
if (expression.IsNamed)
{
result.SeriesName = match.Groups["seriesname"].Value;
result.Success = !string.IsNullOrEmpty(result.SeriesName) && !match.Groups["seasonnumber"].ValueSpan.IsEmpty;
}
}
return result;
}
}
}

View File

@@ -0,0 +1,19 @@
namespace Emby.Naming.TV
{
/// <summary>
/// Holder object for <see cref="SeriesPathParser"/> result.
/// </summary>
public class SeriesPathParserResult
{
/// <summary>
/// Gets or sets the name of the series.
/// </summary>
/// <value>The name of the series.</value>
public string? SeriesName { get; set; }
/// <summary>
/// Gets or sets a value indicating whether parsing was successful.
/// </summary>
public bool Success { get; set; }
}
}

View File

@@ -0,0 +1,49 @@
using System.IO;
using System.Text.RegularExpressions;
using Emby.Naming.Common;
namespace Emby.Naming.TV
{
/// <summary>
/// Used to resolve information about series from path.
/// </summary>
public static class SeriesResolver
{
/// <summary>
/// Regex that matches strings of at least 2 characters separated by a dot or underscore.
/// Used for removing separators between words, i.e turns "The_show" into "The show" while
/// preserving namings like "S.H.O.W".
/// </summary>
private static readonly Regex _seriesNameRegex = new Regex(@"((?<a>[^\._]{2,})[\._]*)|([\._](?<b>[^\._]{2,}))");
/// <summary>
/// Resolve information about series from path.
/// </summary>
/// <param name="options"><see cref="NamingOptions"/> object passed to <see cref="SeriesPathParser"/>.</param>
/// <param name="path">Path to series.</param>
/// <returns>SeriesInfo.</returns>
public static SeriesInfo Resolve(NamingOptions options, string path)
{
string seriesName = Path.GetFileName(path);
SeriesPathParserResult result = SeriesPathParser.Parse(options, path);
if (result.Success)
{
if (!string.IsNullOrEmpty(result.SeriesName))
{
seriesName = result.SeriesName;
}
}
if (!string.IsNullOrEmpty(seriesName))
{
seriesName = _seriesNameRegex.Replace(seriesName, "${a} ${b}").Trim();
}
return new SeriesInfo(path)
{
Name = seriesName
};
}
}
}

View File

@@ -1,4 +1,3 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text.RegularExpressions;
@@ -17,38 +16,39 @@ namespace Emby.Naming.Video
/// <param name="expressions">List of regex to parse name and year from.</param>
/// <param name="newName">Parsing result string.</param>
/// <returns>True if parsing was successful.</returns>
public static bool TryClean([NotNullWhen(true)] string? name, IReadOnlyList<Regex> expressions, out ReadOnlySpan<char> newName)
public static bool TryClean([NotNullWhen(true)] string? name, IReadOnlyList<Regex> expressions, out string newName)
{
if (string.IsNullOrEmpty(name))
{
newName = ReadOnlySpan<char>.Empty;
newName = string.Empty;
return false;
}
var len = expressions.Count;
for (int i = 0; i < len; i++)
// Iteratively apply the regexps to clean the string.
bool cleaned = false;
for (int i = 0; i < expressions.Count; i++)
{
if (TryClean(name, expressions[i], out newName))
{
return true;
cleaned = true;
name = newName;
}
}
newName = ReadOnlySpan<char>.Empty;
return false;
newName = cleaned ? name : string.Empty;
return cleaned;
}
private static bool TryClean(string name, Regex expression, out ReadOnlySpan<char> newName)
private static bool TryClean(string name, Regex expression, out string newName)
{
var match = expression.Match(name);
int index = match.Index;
if (match.Success && index != 0)
if (match.Success && match.Groups.TryGetValue("cleaned", out var cleaned))
{
newName = name.AsSpan().Slice(0, match.Index);
newName = cleaned.Value;
return true;
}
newName = ReadOnlySpan<char>.Empty;
newName = string.Empty;
return false;
}
}

View File

@@ -9,44 +9,27 @@ namespace Emby.Naming.Video
/// <summary>
/// Resolve if file is extra for video.
/// </summary>
public class ExtraResolver
public static class ExtraRuleResolver
{
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();
@@ -62,9 +45,10 @@ namespace Emby.Naming.Video
}
else if (rule.RuleType == ExtraRuleType.Suffix)
{
var filename = Path.GetFileNameWithoutExtension(pathSpan);
// Trim the digits from the end of the filename so we can recognize things like -trailer2
var filename = Path.GetFileNameWithoutExtension(pathSpan).TrimEnd(_digits);
if (filename.Contains(rule.Token, StringComparison.OrdinalIgnoreCase))
if (filename.EndsWith(rule.Token, StringComparison.OrdinalIgnoreCase))
{
result.ExtraType = rule.ExtraType;
result.Rule = rule;
@@ -74,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);
@@ -87,9 +88,9 @@ namespace Emby.Naming.Video
year = cleanDateTimeResult.Year;
if (extraResult.ExtraType == null
&& TryCleanString(name, namingOptions, out ReadOnlySpan<char> newName))
&& TryCleanString(name, namingOptions, out var newName))
{
name = newName.ToString();
name = newName;
}
}
@@ -138,7 +139,7 @@ namespace Emby.Naming.Video
/// <param name="namingOptions">The naming options.</param>
/// <param name="newName">Clean name.</param>
/// <returns>True if cleaning of name was successful.</returns>
public static bool TryCleanString([NotNullWhen(true)] string? name, NamingOptions namingOptions, out ReadOnlySpan<char> newName)
public static bool TryCleanString([NotNullWhen(true)] string? name, NamingOptions namingOptions, out string newName)
{
return CleanStringParser.TryClean(name, namingOptions.CleanStringRegexes, out newName);
}

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

@@ -6,7 +6,7 @@
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
@@ -24,7 +24,7 @@
<!-- Code analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<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.376" 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,7 +105,7 @@ 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;
}

View File

@@ -19,14 +19,14 @@
</ItemGroup>
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" 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));

View File

@@ -1,6 +1,5 @@
using System;
using System.IO;
using System.Linq;
using MediaBrowser.Model.Serialization;
namespace Emby.Server.Implementations.AppBase
@@ -41,20 +40,19 @@ namespace Emby.Server.Implementations.AppBase
xmlSerializer.SerializeToStream(configuration, stream);
// Take the object we just got and serialize it back to bytes
byte[] newBytes = stream.GetBuffer();
int newBytesLen = (int)stream.Length;
Span<byte> newBytes = stream.GetBuffer().AsSpan(0, (int)stream.Length);
// If the file didn't exist before, or if something has changed, re-save
if (buffer == null || !newBytes.AsSpan(0, newBytesLen).SequenceEqual(buffer))
if (buffer == null || !newBytes.SequenceEqual(buffer))
{
var directory = Path.GetDirectoryName(path) ?? throw new ArgumentException($"Provided path ({path}) is not valid.", nameof(path));
Directory.CreateDirectory(directory);
// Save it after load in case we got new items
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None))
{
fs.Write(newBytes, 0, newBytesLen);
fs.Write(newBytes);
}
}

View File

@@ -3,6 +3,7 @@
#pragma warning disable CS1591
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
@@ -18,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;
@@ -38,7 +40,6 @@ using Emby.Server.Implementations.Playlists;
using Emby.Server.Implementations.Plugins;
using Emby.Server.Implementations.QuickConnect;
using Emby.Server.Implementations.ScheduledTasks;
using Emby.Server.Implementations.Security;
using Emby.Server.Implementations.Serialization;
using Emby.Server.Implementations.Session;
using Emby.Server.Implementations.SyncPlay;
@@ -57,9 +58,9 @@ using MediaBrowser.Common.Updates;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Chapters;
using MediaBrowser.Controller.ClientEvent;
using MediaBrowser.Controller.Collections;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto;
@@ -75,7 +76,6 @@ using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.QuickConnect;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Controller.Security;
using MediaBrowser.Controller.Session;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Controller.Subtitles;
@@ -117,6 +117,11 @@ namespace Emby.Server.Implementations
/// </summary>
private static readonly string[] _relevantEnvVarPrefixes = { "JELLYFIN_", "DOTNET_", "ASPNETCORE_" };
/// <summary>
/// The disposable parts.
/// </summary>
private readonly ConcurrentDictionary<IDisposable, byte> _disposableParts = new();
private readonly IFileSystem _fileSystemManager;
private readonly IConfiguration _startupConfig;
private readonly IXmlSerializer _xmlSerializer;
@@ -126,7 +131,57 @@ namespace Emby.Server.Implementations
private List<Type> _creatingInstances;
private IMediaEncoder _mediaEncoder;
private ISessionManager _sessionManager;
private string[] _urlPrefixes;
/// <summary>
/// Gets or sets all concrete types.
/// </summary>
/// <value>All concrete types.</value>
private Type[] _allConcreteTypes;
private DeviceId _deviceId;
private bool _disposed = false;
/// <summary>
/// Initializes a new instance of the <see cref="ApplicationHost"/> class.
/// </summary>
/// <param name="applicationPaths">Instance of the <see cref="IServerApplicationPaths"/> interface.</param>
/// <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(
IServerApplicationPaths applicationPaths,
ILoggerFactory loggerFactory,
IStartupOptions options,
IConfiguration startupConfig)
{
ApplicationPaths = applicationPaths;
LoggerFactory = loggerFactory;
_startupOptions = options;
_startupConfig = startupConfig;
_fileSystemManager = new ManagedFileSystem(LoggerFactory.CreateLogger<ManagedFileSystem>(), applicationPaths);
Logger = LoggerFactory.CreateLogger<ApplicationHost>();
_fileSystemManager.AddShortcutHandler(new MbLinkShortcutHandler(_fileSystemManager));
ApplicationVersion = typeof(ApplicationHost).Assembly.GetName().Version;
ApplicationVersionString = ApplicationVersion.ToString(3);
ApplicationUserAgent = Name.Replace(' ', '-') + "/" + ApplicationVersionString;
_xmlSerializer = new MyXmlSerializer();
ConfigurationManager = new ServerConfigurationManager(ApplicationPaths, LoggerFactory, _xmlSerializer, _fileSystemManager);
_pluginManager = new PluginManager(
LoggerFactory.CreateLogger<PluginManager>(),
this,
ConfigurationManager.Configuration,
ApplicationPaths.PluginsPath,
ApplicationVersion);
}
/// <summary>
/// Occurs when [has pending restart changed].
/// </summary>
public event EventHandler HasPendingRestartChanged;
/// <summary>
/// Gets a value indicating whether this instance can self restart.
@@ -156,12 +211,7 @@ namespace Emby.Server.Implementations
/// <summary>
/// Gets the <see cref="INetworkManager"/> singleton instance.
/// </summary>
public INetworkManager NetManager { get; internal set; }
/// <summary>
/// Occurs when [has pending restart changed].
/// </summary>
public event EventHandler HasPendingRestartChanged;
public INetworkManager NetManager { get; private set; }
/// <summary>
/// Gets a value indicating whether this instance has changes that require the entire application to restart.
@@ -177,35 +227,22 @@ namespace Emby.Server.Implementations
/// </summary>
protected ILogger<ApplicationHost> Logger { get; }
protected IServiceCollection ServiceCollection { get; }
/// <summary>
/// Gets the logger factory.
/// </summary>
protected ILoggerFactory LoggerFactory { get; }
/// <summary>
/// Gets or sets the application paths.
/// Gets the application paths.
/// </summary>
/// <value>The application paths.</value>
protected IServerApplicationPaths ApplicationPaths { get; set; }
protected IServerApplicationPaths ApplicationPaths { get; }
/// <summary>
/// Gets or sets all concrete types.
/// </summary>
/// <value>All concrete types.</value>
private Type[] _allConcreteTypes;
/// <summary>
/// The disposable parts.
/// </summary>
private readonly List<IDisposable> _disposableParts = new List<IDisposable>();
/// <summary>
/// Gets or sets the configuration manager.
/// Gets the configuration manager.
/// </summary>
/// <value>The configuration manager.</value>
public ServerConfigurationManager ConfigurationManager { get; set; }
public ServerConfigurationManager ConfigurationManager { get; }
/// <summary>
/// Gets or sets the service provider.
@@ -227,79 +264,6 @@ namespace Emby.Server.Implementations
/// </summary>
public string PublishedServerUrl => _startupOptions.PublishedServerUrl ?? _startupConfig[UdpServer.AddressOverrideConfigKey];
/// <summary>
/// Initializes a new instance of the <see cref="ApplicationHost"/> class.
/// </summary>
/// <param name="applicationPaths">Instance of the <see cref="IServerApplicationPaths"/> interface.</param>
/// <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>
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
/// <param name="serviceCollection">Instance of the <see cref="IServiceCollection"/> interface.</param>
public ApplicationHost(
IServerApplicationPaths applicationPaths,
ILoggerFactory loggerFactory,
IStartupOptions options,
IConfiguration startupConfig,
IFileSystem fileSystem,
IServiceCollection serviceCollection)
{
ApplicationPaths = applicationPaths;
LoggerFactory = loggerFactory;
_startupOptions = options;
_startupConfig = startupConfig;
_fileSystemManager = fileSystem;
ServiceCollection = serviceCollection;
Logger = LoggerFactory.CreateLogger<ApplicationHost>();
fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem));
ApplicationVersion = typeof(ApplicationHost).Assembly.GetName().Version;
ApplicationVersionString = ApplicationVersion.ToString(3);
ApplicationUserAgent = Name.Replace(' ', '-') + "/" + ApplicationVersionString;
_xmlSerializer = new MyXmlSerializer();
ConfigurationManager = new ServerConfigurationManager(ApplicationPaths, LoggerFactory, _xmlSerializer, _fileSystemManager);
_pluginManager = new PluginManager(
LoggerFactory.CreateLogger<PluginManager>(),
this,
ConfigurationManager.Configuration,
ApplicationPaths.PluginsPath,
ApplicationVersion);
}
/// <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;
return path.Replace(appPaths.VirtualDataPath, appPaths.DataPath, StringComparison.OrdinalIgnoreCase)
.Replace(appPaths.VirtualInternalMetadataPath, appPaths.InternalMetadataPath, StringComparison.OrdinalIgnoreCase);
}
public string ReverseVirtualPath(string path)
{
var appPaths = ApplicationPaths;
return path.Replace(appPaths.DataPath, appPaths.VirtualDataPath, StringComparison.OrdinalIgnoreCase)
.Replace(appPaths.InternalMetadataPath, appPaths.VirtualInternalMetadataPath, StringComparison.OrdinalIgnoreCase);
}
/// <inheritdoc />
public Version ApplicationVersion { get; }
@@ -324,8 +288,6 @@ namespace Emby.Server.Implementations
/// <value>The application name.</value>
public string ApplicationProductName { get; } = FileVersionInfo.GetVersionInfo(Assembly.GetEntryAssembly().Location).ProductName;
private DeviceId _deviceId;
public string SystemId
{
get
@@ -339,21 +301,33 @@ namespace Emby.Server.Implementations
/// <inheritdoc/>
public string Name => ApplicationProductName;
/// <summary>
/// Creates an instance of type and resolves all constructor dependencies.
/// </summary>
/// <param name="type">The type.</param>
/// <returns>System.Object.</returns>
public object CreateInstance(Type type)
=> ActivatorUtilities.CreateInstance(ServiceProvider, type);
private string CertificatePath { get; set; }
/// <summary>
/// Creates an instance of type and resolves all constructor dependencies.
/// </summary>
/// <typeparam name="T">The type.</typeparam>
/// <returns>T.</returns>
public T CreateInstance<T>()
=> ActivatorUtilities.CreateInstance<T>(ServiceProvider);
public X509Certificate2 Certificate { get; private set; }
/// <inheritdoc/>
public bool ListenWithHttps => Certificate != null && ConfigurationManager.GetNetworkConfiguration().EnableHttps;
public string FriendlyName =>
string.IsNullOrEmpty(ConfigurationManager.Configuration.ServerName)
? Environment.MachineName
: ConfigurationManager.Configuration.ServerName;
public string ExpandVirtualPath(string path)
{
var appPaths = ApplicationPaths;
return path.Replace(appPaths.VirtualDataPath, appPaths.DataPath, StringComparison.OrdinalIgnoreCase)
.Replace(appPaths.VirtualInternalMetadataPath, appPaths.InternalMetadataPath, StringComparison.OrdinalIgnoreCase);
}
public string ReverseVirtualPath(string path)
{
var appPaths = ApplicationPaths;
return path.Replace(appPaths.DataPath, appPaths.VirtualDataPath, StringComparison.OrdinalIgnoreCase)
.Replace(appPaths.InternalMetadataPath, appPaths.VirtualInternalMetadataPath, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Creates the instance safe.
@@ -364,7 +338,7 @@ namespace Emby.Server.Implementations
{
_creatingInstances ??= new List<Type>();
if (_creatingInstances.IndexOf(type) != -1)
if (_creatingInstances.Contains(type))
{
Logger.LogError("DI Loop detected in the attempted creation of {Type}", type.FullName);
foreach (var entry in _creatingInstances)
@@ -374,7 +348,7 @@ namespace Emby.Server.Implementations
_pluginManager.FailPlugin(type.Assembly);
throw new ExternalException("DI Loop detected.");
throw new TypeLoadException("DI Loop detected");
}
try
@@ -407,8 +381,15 @@ namespace Emby.Server.Implementations
public IEnumerable<Type> GetExportTypes<T>()
{
var currentType = typeof(T);
return _allConcreteTypes.Where(i => currentType.IsAssignableFrom(i));
var numberOfConcreteTypes = _allConcreteTypes.Length;
for (var i = 0; i < numberOfConcreteTypes; i++)
{
var type = _allConcreteTypes[i];
if (currentType.IsAssignableFrom(type))
{
yield return type;
}
}
}
/// <inheritdoc />
@@ -423,9 +404,9 @@ namespace Emby.Server.Implementations
if (manageLifetime)
{
lock (_disposableParts)
foreach (var part in parts.OfType<IDisposable>())
{
_disposableParts.AddRange(parts.OfType<IDisposable>());
_disposableParts.TryAdd(part, byte.MinValue);
}
}
@@ -444,9 +425,9 @@ namespace Emby.Server.Implementations
if (manageLifetime)
{
lock (_disposableParts)
foreach (var part in parts.OfType<IDisposable>())
{
_disposableParts.AddRange(parts.OfType<IDisposable>());
_disposableParts.TryAdd(part, byte.MinValue);
}
}
@@ -456,6 +437,7 @@ namespace Emby.Server.Implementations
/// <summary>
/// Runs the startup tasks.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns><see cref="Task" />.</returns>
public async Task RunStartupTasksAsync(CancellationToken cancellationToken)
{
@@ -469,7 +451,7 @@ namespace Emby.Server.Implementations
_mediaEncoder.SetFFmpegPath();
Logger.LogInformation("ServerId: {0}", SystemId);
Logger.LogInformation("ServerId: {ServerId}", SystemId);
var entryPoints = GetExports<IServerEntryPoint>();
@@ -509,14 +491,12 @@ namespace Emby.Server.Implementations
}
/// <inheritdoc/>
public void Init()
public void Init(IServiceCollection serviceCollection)
{
DiscoverTypes();
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
@@ -536,140 +516,133 @@ namespace Emby.Server.Implementations
HttpsPort = NetworkConfiguration.DefaultHttpsPort;
}
CertificateInfo = new CertificateInfo
{
Path = networkConfiguration.CertificatePath,
Password = networkConfiguration.CertificatePassword
};
Certificate = GetCertificate(CertificateInfo);
CertificatePath = networkConfiguration.CertificatePath;
Certificate = GetCertificate(CertificatePath, networkConfiguration.CertificatePassword);
RegisterServices();
RegisterServices(serviceCollection);
_pluginManager.RegisterServices(ServiceCollection);
_pluginManager.RegisterServices(serviceCollection);
}
/// <summary>
/// Registers services/resources with the service collection that will be available via DI.
/// </summary>
protected virtual void RegisterServices()
/// <param name="serviceCollection">Instance of the <see cref="IServiceCollection"/> interface.</param>
protected virtual void RegisterServices(IServiceCollection serviceCollection)
{
ServiceCollection.AddSingleton(_startupOptions);
serviceCollection.AddSingleton(_startupOptions);
ServiceCollection.AddMemoryCache();
serviceCollection.AddMemoryCache();
ServiceCollection.AddSingleton<IServerConfigurationManager>(ConfigurationManager);
ServiceCollection.AddSingleton<IConfigurationManager>(ConfigurationManager);
ServiceCollection.AddSingleton<IApplicationHost>(this);
ServiceCollection.AddSingleton<IPluginManager>(_pluginManager);
ServiceCollection.AddSingleton<IApplicationPaths>(ApplicationPaths);
serviceCollection.AddSingleton<IServerConfigurationManager>(ConfigurationManager);
serviceCollection.AddSingleton<IConfigurationManager>(ConfigurationManager);
serviceCollection.AddSingleton<IApplicationHost>(this);
serviceCollection.AddSingleton(_pluginManager);
serviceCollection.AddSingleton<IApplicationPaths>(ApplicationPaths);
ServiceCollection.AddSingleton(_fileSystemManager);
ServiceCollection.AddSingleton<TmdbClientManager>();
serviceCollection.AddSingleton(_fileSystemManager);
serviceCollection.AddSingleton<TmdbClientManager>();
ServiceCollection.AddSingleton(NetManager);
serviceCollection.AddSingleton(NetManager);
ServiceCollection.AddSingleton<ITaskManager, TaskManager>();
serviceCollection.AddSingleton<ITaskManager, TaskManager>();
ServiceCollection.AddSingleton(_xmlSerializer);
serviceCollection.AddSingleton(_xmlSerializer);
ServiceCollection.AddSingleton<IStreamHelper, StreamHelper>();
serviceCollection.AddSingleton<IStreamHelper, StreamHelper>();
ServiceCollection.AddSingleton<ICryptoProvider, CryptographyProvider>();
serviceCollection.AddSingleton<ICryptoProvider, CryptographyProvider>();
ServiceCollection.AddSingleton<ISocketFactory, SocketFactory>();
serviceCollection.AddSingleton<ISocketFactory, SocketFactory>();
ServiceCollection.AddSingleton<IInstallationManager, InstallationManager>();
serviceCollection.AddSingleton<IInstallationManager, InstallationManager>();
ServiceCollection.AddSingleton<IZipClient, ZipClient>();
serviceCollection.AddSingleton<IZipClient, ZipClient>();
ServiceCollection.AddSingleton<IServerApplicationHost>(this);
ServiceCollection.AddSingleton<IServerApplicationPaths>(ApplicationPaths);
serviceCollection.AddSingleton<IServerApplicationHost>(this);
serviceCollection.AddSingleton(ApplicationPaths);
ServiceCollection.AddSingleton<ILocalizationManager, LocalizationManager>();
serviceCollection.AddSingleton<ILocalizationManager, LocalizationManager>();
ServiceCollection.AddSingleton<IBlurayExaminer, BdInfoExaminer>();
serviceCollection.AddSingleton<IBlurayExaminer, BdInfoExaminer>();
ServiceCollection.AddSingleton<IUserDataRepository, SqliteUserDataRepository>();
ServiceCollection.AddSingleton<IUserDataManager, UserDataManager>();
serviceCollection.AddSingleton<IUserDataRepository, SqliteUserDataRepository>();
serviceCollection.AddSingleton<IUserDataManager, UserDataManager>();
ServiceCollection.AddSingleton<IItemRepository, SqliteItemRepository>();
serviceCollection.AddSingleton<IItemRepository, SqliteItemRepository>();
ServiceCollection.AddSingleton<IAuthenticationRepository, AuthenticationRepository>();
ServiceCollection.AddSingleton<IMediaEncoder, MediaBrowser.MediaEncoding.Encoder.MediaEncoder>();
ServiceCollection.AddSingleton<EncodingHelper>();
serviceCollection.AddSingleton<IMediaEncoder, MediaBrowser.MediaEncoding.Encoder.MediaEncoder>();
serviceCollection.AddSingleton<EncodingHelper>();
// TODO: Refactor to eliminate the circular dependencies here so that Lazy<T> isn't required
ServiceCollection.AddTransient(provider => new Lazy<ILibraryMonitor>(provider.GetRequiredService<ILibraryMonitor>));
ServiceCollection.AddTransient(provider => new Lazy<IProviderManager>(provider.GetRequiredService<IProviderManager>));
ServiceCollection.AddTransient(provider => new Lazy<IUserViewManager>(provider.GetRequiredService<IUserViewManager>));
ServiceCollection.AddSingleton<ILibraryManager, LibraryManager>();
serviceCollection.AddTransient(provider => new Lazy<ILibraryMonitor>(provider.GetRequiredService<ILibraryMonitor>));
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>();
serviceCollection.AddSingleton<IMusicManager, MusicManager>();
ServiceCollection.AddSingleton<ILibraryMonitor, LibraryMonitor>();
serviceCollection.AddSingleton<ILibraryMonitor, LibraryMonitor>();
ServiceCollection.AddSingleton<ISearchEngine, SearchEngine>();
serviceCollection.AddSingleton<ISearchEngine, SearchEngine>();
ServiceCollection.AddSingleton<IWebSocketManager, WebSocketManager>();
serviceCollection.AddSingleton<IWebSocketManager, WebSocketManager>();
ServiceCollection.AddSingleton<IImageProcessor, ImageProcessor>();
serviceCollection.AddSingleton<IImageProcessor, ImageProcessor>();
ServiceCollection.AddSingleton<ITVSeriesManager, TVSeriesManager>();
serviceCollection.AddSingleton<ITVSeriesManager, TVSeriesManager>();
ServiceCollection.AddSingleton<IDeviceManager, DeviceManager>();
serviceCollection.AddSingleton<IMediaSourceManager, MediaSourceManager>();
ServiceCollection.AddSingleton<IMediaSourceManager, MediaSourceManager>();
serviceCollection.AddSingleton<ISubtitleManager, SubtitleManager>();
ServiceCollection.AddSingleton<ISubtitleManager, SubtitleManager>();
ServiceCollection.AddSingleton<IProviderManager, ProviderManager>();
serviceCollection.AddSingleton<IProviderManager, ProviderManager>();
// TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required
ServiceCollection.AddTransient(provider => new Lazy<ILiveTvManager>(provider.GetRequiredService<ILiveTvManager>));
ServiceCollection.AddSingleton<IDtoService, DtoService>();
serviceCollection.AddTransient(provider => new Lazy<ILiveTvManager>(provider.GetRequiredService<ILiveTvManager>));
serviceCollection.AddSingleton<IDtoService, DtoService>();
ServiceCollection.AddSingleton<IChannelManager, ChannelManager>();
serviceCollection.AddSingleton<IChannelManager, ChannelManager>();
ServiceCollection.AddSingleton<ISessionManager, SessionManager>();
serviceCollection.AddSingleton<ISessionManager, SessionManager>();
ServiceCollection.AddSingleton<IDlnaManager, DlnaManager>();
serviceCollection.AddSingleton<IDlnaManager, DlnaManager>();
ServiceCollection.AddSingleton<ICollectionManager, CollectionManager>();
serviceCollection.AddSingleton<ICollectionManager, CollectionManager>();
ServiceCollection.AddSingleton<IPlaylistManager, PlaylistManager>();
serviceCollection.AddSingleton<IPlaylistManager, PlaylistManager>();
ServiceCollection.AddSingleton<ISyncPlayManager, SyncPlayManager>();
serviceCollection.AddSingleton<ISyncPlayManager, SyncPlayManager>();
ServiceCollection.AddSingleton<LiveTvDtoService>();
ServiceCollection.AddSingleton<ILiveTvManager, LiveTvManager>();
serviceCollection.AddSingleton<LiveTvDtoService>();
serviceCollection.AddSingleton<ILiveTvManager, LiveTvManager>();
ServiceCollection.AddSingleton<IUserViewManager, UserViewManager>();
serviceCollection.AddSingleton<IUserViewManager, UserViewManager>();
ServiceCollection.AddSingleton<INotificationManager, NotificationManager>();
serviceCollection.AddSingleton<INotificationManager, NotificationManager>();
ServiceCollection.AddSingleton<IDeviceDiscovery, DeviceDiscovery>();
serviceCollection.AddSingleton<IDeviceDiscovery, DeviceDiscovery>();
ServiceCollection.AddSingleton<IChapterManager, ChapterManager>();
serviceCollection.AddSingleton<IChapterManager, ChapterManager>();
ServiceCollection.AddSingleton<IEncodingManager, MediaEncoder.EncodingManager>();
serviceCollection.AddSingleton<IEncodingManager, MediaEncoder.EncodingManager>();
ServiceCollection.AddSingleton<IAuthorizationContext, AuthorizationContext>();
ServiceCollection.AddSingleton<ISessionContext, SessionContext>();
serviceCollection.AddScoped<ISessionContext, SessionContext>();
ServiceCollection.AddSingleton<IAuthService, AuthService>();
ServiceCollection.AddSingleton<IQuickConnect, QuickConnectManager>();
serviceCollection.AddSingleton<IAuthService, AuthService>();
serviceCollection.AddSingleton<IQuickConnect, QuickConnectManager>();
ServiceCollection.AddSingleton<ISubtitleEncoder, MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder>();
serviceCollection.AddSingleton<ISubtitleEncoder, MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder>();
ServiceCollection.AddSingleton<IAttachmentExtractor, MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor>();
serviceCollection.AddSingleton<IAttachmentExtractor, MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor>();
ServiceCollection.AddSingleton<TranscodingJobHelper>();
ServiceCollection.AddScoped<MediaInfoHelper>();
ServiceCollection.AddScoped<AudioHelper>();
ServiceCollection.AddScoped<DynamicHlsHelper>();
ServiceCollection.AddSingleton<IDirectoryService, DirectoryService>();
serviceCollection.AddSingleton<TranscodingJobHelper>();
serviceCollection.AddScoped<MediaInfoHelper>();
serviceCollection.AddScoped<AudioHelper>();
serviceCollection.AddScoped<DynamicHlsHelper>();
serviceCollection.AddScoped<IClientEventLogger, ClientEventLogger>();
serviceCollection.AddSingleton<IDirectoryService, DirectoryService>();
}
/// <summary>
@@ -684,8 +657,6 @@ namespace Emby.Server.Implementations
_mediaEncoder = Resolve<IMediaEncoder>();
_sessionManager = Resolve<ISessionManager>();
((AuthenticationRepository)Resolve<IAuthenticationRepository>()).Initialize();
SetStaticProperties();
var userDataRepo = (SqliteUserDataRepository)Resolve<IUserDataRepository>();
@@ -724,30 +695,27 @@ namespace Emby.Server.Implementations
logger.LogInformation("Application directory: {ApplicationPath}", appPaths.ProgramSystemPath);
}
private X509Certificate2 GetCertificate(CertificateInfo info)
private X509Certificate2 GetCertificate(string path, string password)
{
var certificateLocation = info?.Path;
if (string.IsNullOrWhiteSpace(certificateLocation))
if (string.IsNullOrWhiteSpace(path))
{
return null;
}
try
{
if (!File.Exists(certificateLocation))
if (!File.Exists(path))
{
return null;
}
// Don't use an empty string password
var password = string.IsNullOrWhiteSpace(info.Password) ? null : info.Password;
password = string.IsNullOrWhiteSpace(password) ? null : password;
var localCert = new X509Certificate2(certificateLocation, password, X509KeyStorageFlags.UserKeySet);
// localCert.PrivateKey = PrivateKey.CreateFromFile(pvk_file).RSA;
var localCert = new X509Certificate2(path, password, X509KeyStorageFlags.UserKeySet);
if (!localCert.HasPrivateKey)
{
Logger.LogError("No private key included in SSL cert {CertificateLocation}.", certificateLocation);
Logger.LogError("No private key included in SSL cert {CertificateLocation}.", path);
return null;
}
@@ -755,7 +723,7 @@ namespace Emby.Server.Implementations
}
catch (Exception ex)
{
Logger.LogError(ex, "Error loading cert from {CertificateLocation}", certificateLocation);
Logger.LogError(ex, "Error loading cert from {CertificateLocation}", path);
return null;
}
}
@@ -797,8 +765,6 @@ namespace Emby.Server.Implementations
_pluginManager.CreatePlugins();
_urlPrefixes = GetUrlPrefixes().ToArray();
Resolve<ILibraryManager>().AddParts(
GetExports<IResolverIgnoreRule>(),
GetExports<IItemResolver>(),
@@ -866,36 +832,12 @@ namespace Emby.Server.Implementations
}
}
private CertificateInfo CertificateInfo { get; set; }
public X509Certificate2 Certificate { get; private set; }
private IEnumerable<string> GetUrlPrefixes()
{
var hosts = new[] { "+" };
return hosts.SelectMany(i =>
{
var prefixes = new List<string>
{
"http://" + i + ":" + HttpPort + "/"
};
if (CertificateInfo != null)
{
prefixes.Add("https://" + i + ":" + HttpsPort + "/");
}
return prefixes;
});
}
/// <summary>
/// Called when [configuration updated].
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
protected void OnConfigurationUpdated(object sender, EventArgs e)
private void OnConfigurationUpdated(object sender, EventArgs e)
{
var requiresRestart = false;
var networkConfiguration = ConfigurationManager.GetNetworkConfiguration();
@@ -904,8 +846,8 @@ namespace Emby.Server.Implementations
if (HttpPort != 0 && HttpsPort != 0)
{
// Need to restart if ports have changed
if (networkConfiguration.HttpServerPortNumber != HttpPort ||
networkConfiguration.HttpsPortNumber != HttpsPort)
if (networkConfiguration.HttpServerPortNumber != HttpPort
|| networkConfiguration.HttpsPortNumber != HttpsPort)
{
if (ConfigurationManager.Configuration.IsPortAuthorized)
{
@@ -917,11 +859,6 @@ namespace Emby.Server.Implementations
}
}
if (!_urlPrefixes.SequenceEqual(GetUrlPrefixes(), StringComparer.OrdinalIgnoreCase))
{
requiresRestart = true;
}
if (ValidateSslCertificate(networkConfiguration))
{
requiresRestart = true;
@@ -945,7 +882,7 @@ namespace Emby.Server.Implementations
var newPath = networkConfig.CertificatePath;
if (!string.IsNullOrWhiteSpace(newPath)
&& !string.Equals(CertificateInfo?.Path, newPath, StringComparison.Ordinal))
&& !string.Equals(CertificatePath, newPath, StringComparison.Ordinal))
{
if (File.Exists(newPath))
{
@@ -963,7 +900,7 @@ namespace Emby.Server.Implementations
}
/// <summary>
/// Notifies that the kernel that a change has been made that requires a restart.
/// Notifies the kernel that a change has been made that requires a restart.
/// </summary>
public void NotifyPendingRestart()
{
@@ -1073,9 +1010,9 @@ namespace Emby.Server.Implementations
/// <summary>
/// Gets the system status.
/// </summary>
/// <param name="source">Where this request originated.</param>
/// <param name="request">Where this request originated.</param>
/// <returns>SystemInfo.</returns>
public SystemInfo GetSystemInfo(IPAddress source)
public SystemInfo GetSystemInfo(HttpRequest request)
{
return new SystemInfo
{
@@ -1097,20 +1034,14 @@ namespace Emby.Server.Implementations
CanLaunchWebBrowser = CanLaunchWebBrowser,
TranscodingTempPath = ConfigurationManager.GetTranscodePath(),
ServerName = FriendlyName,
LocalAddress = GetSmartApiUrl(source),
LocalAddress = GetSmartApiUrl(request),
SupportsLibraryMonitor = true,
EncoderLocation = _mediaEncoder.EncoderLocation,
SystemArchitecture = RuntimeInformation.OSArchitecture,
PackageName = _startupOptions.PackageName
};
}
public IEnumerable<WakeOnLanInfo> GetWakeOnLanInfo()
=> NetManager.GetMacAddresses()
.Select(i => new WakeOnLanInfo(i))
.ToList();
public PublicSystemInfo GetPublicSystemInfo(IPAddress address)
public PublicSystemInfo GetPublicSystemInfo(HttpRequest request)
{
return new PublicSystemInfo
{
@@ -1119,16 +1050,13 @@ namespace Emby.Server.Implementations
Id = SystemId,
OperatingSystem = MediaBrowser.Common.System.OperatingSystem.Id.ToString(),
ServerName = FriendlyName,
LocalAddress = GetSmartApiUrl(address),
LocalAddress = GetSmartApiUrl(request),
StartupWizardCompleted = ConfigurationManager.CommonConfiguration.IsStartupWizardCompleted
};
}
/// <inheritdoc/>
public bool ListenWithHttps => Certificate != null && ConfigurationManager.GetNetworkConfiguration().EnableHttps;
/// <inheritdoc/>
public string GetSmartApiUrl(IPAddress remoteAddr, int? port = null)
public string GetSmartApiUrl(IPAddress remoteAddr)
{
// Published server ends with a /
if (!string.IsNullOrEmpty(PublishedServerUrl))
@@ -1137,19 +1065,25 @@ namespace Emby.Server.Implementations
return PublishedServerUrl.Trim('/');
}
string smart = NetManager.GetBindInterface(remoteAddr, out port);
// If the smartAPI doesn't start with http then treat it as a host or ip.
if (smart.StartsWith("http", StringComparison.OrdinalIgnoreCase))
{
return smart.Trim('/');
}
string smart = NetManager.GetBindInterface(remoteAddr, out var port);
return GetLocalApiUrl(smart.Trim('/'), null, port);
}
/// <inheritdoc/>
public string GetSmartApiUrl(HttpRequest request, int? port = null)
public string GetSmartApiUrl(HttpRequest request)
{
// Return the host in the HTTP request as the API url
if (ConfigurationManager.GetNetworkConfiguration().EnablePublishedServerUriByRequest)
{
int? requestPort = request.Host.Port;
if ((requestPort == 80 && string.Equals(request.Scheme, "http", StringComparison.OrdinalIgnoreCase)) || (requestPort == 443 && string.Equals(request.Scheme, "https", StringComparison.OrdinalIgnoreCase)))
{
requestPort = -1;
}
return GetLocalApiUrl(request.Host.Host, request.Scheme, requestPort);
}
// Published server ends with a /
if (!string.IsNullOrEmpty(PublishedServerUrl))
{
@@ -1157,18 +1091,12 @@ namespace Emby.Server.Implementations
return PublishedServerUrl.Trim('/');
}
string smart = NetManager.GetBindInterface(request, out port);
// If the smartAPI doesn't start with http then treat it as a host or ip.
if (smart.StartsWith("http", StringComparison.OrdinalIgnoreCase))
{
return smart.Trim('/');
}
string smart = NetManager.GetBindInterface(request, out var port);
return GetLocalApiUrl(smart.Trim('/'), request.Scheme, port);
}
/// <inheritdoc/>
public string GetSmartApiUrl(string hostname, int? port = null)
public string GetSmartApiUrl(string hostname)
{
// Published server ends with a /
if (!string.IsNullOrEmpty(PublishedServerUrl))
@@ -1177,31 +1105,29 @@ namespace Emby.Server.Implementations
return PublishedServerUrl.Trim('/');
}
string smart = NetManager.GetBindInterface(hostname, out port);
// If the smartAPI doesn't start with http then treat it as a host or ip.
if (smart.StartsWith("http", StringComparison.OrdinalIgnoreCase))
{
return smart.Trim('/');
}
string smart = NetManager.GetBindInterface(hostname, out var port);
return GetLocalApiUrl(smart.Trim('/'), null, port);
}
/// <inheritdoc/>
public string GetLoopbackHttpApiUrl()
public string GetApiUrlForLocalAccess(bool allowHttps = true)
{
if (NetManager.IsIP6Enabled)
{
return GetLocalApiUrl("::1", Uri.UriSchemeHttp, HttpPort);
}
return GetLocalApiUrl("127.0.0.1", Uri.UriSchemeHttp, HttpPort);
// With an empty source, the port will be null
string smart = NetManager.GetBindInterface(string.Empty, out _);
var scheme = !allowHttps ? Uri.UriSchemeHttp : null;
int? port = !allowHttps ? HttpPort : null;
return GetLocalApiUrl(smart.Trim('/'), scheme, port);
}
/// <inheritdoc/>
public string GetLocalApiUrl(string hostname, string scheme = null, int? port = null)
{
// If the smartAPI doesn't start with http then treat it as a host or ip.
if (hostname.StartsWith("http", StringComparison.OrdinalIgnoreCase))
{
return hostname.TrimEnd('/');
}
// 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.
return new UriBuilder
@@ -1213,14 +1139,7 @@ namespace Emby.Server.Implementations
}.ToString().TrimEnd('/');
}
public string FriendlyName =>
string.IsNullOrEmpty(ConfigurationManager.Configuration.ServerName)
? Environment.MachineName
: ConfigurationManager.Configuration.ServerName;
/// <summary>
/// Shuts down.
/// </summary>
/// <inheritdoc />
public async Task Shutdown()
{
if (IsShuttingDown)
@@ -1258,41 +1177,7 @@ namespace Emby.Server.Implementations
}
}
public virtual void LaunchUrl(string url)
{
if (!CanLaunchWebBrowser)
{
throw new NotSupportedException();
}
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = url,
UseShellExecute = true,
ErrorDialog = false
},
EnableRaisingEvents = true
};
process.Exited += (sender, args) => ((Process)sender).Dispose();
try
{
process.Start();
}
catch (Exception ex)
{
Logger.LogError(ex, "Error launching url: {url}", url);
throw;
}
}
private bool _disposed = false;
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
/// <inheritdoc />
public void Dispose()
{
Dispose(true);
@@ -1316,12 +1201,15 @@ namespace Emby.Server.Implementations
Logger.LogInformation("Disposing {Type}", type.Name);
var parts = _disposableParts.Distinct().Where(i => i.GetType() != type).ToList();
_disposableParts.Clear();
foreach (var part in parts)
foreach (var (part, _) in _disposableParts)
{
Logger.LogInformation("Disposing {Type}", part.GetType().Name);
var partType = part.GetType();
if (partType == type)
{
continue;
}
Logger.LogInformation("Disposing {Type}", partType.Name);
try
{
@@ -1329,19 +1217,14 @@ namespace Emby.Server.Implementations
}
catch (Exception ex)
{
Logger.LogError(ex, "Error disposing {Type}", part.GetType().Name);
Logger.LogError(ex, "Error disposing {Type}", partType.Name);
}
}
_disposableParts.Clear();
}
_disposed = true;
}
}
internal class CertificateInfo
{
public string Path { get; set; }
public string Password { get; set; }
}
}

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,53 +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;
}
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
};
reader.WriteAllToDirectory(targetPath, options);
}
/// <inheritdoc />
public void ExtractAllFromGz(Stream source, string targetPath, bool overwriteExistingFiles)
{
@@ -71,6 +21,7 @@ namespace Emby.Server.Implementations.Archiving
Overwrite = overwriteExistingFiles
};
Directory.CreateDirectory(targetPath);
reader.WriteAllToDirectory(targetPath, options);
}
@@ -91,67 +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
};
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
};
reader.WriteAllToDirectory(targetPath, options);
}
}
}

View File

@@ -10,8 +10,9 @@ using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common.Extensions;
using Jellyfin.Extensions;
using Jellyfin.Extensions.Json;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Progress;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
@@ -102,7 +103,7 @@ namespace Emby.Server.Implementations.Channels
var internalChannel = _libraryManager.GetItemById(item.ChannelId);
var channel = Channels.FirstOrDefault(i => GetInternalChannelId(i.Name).Equals(internalChannel.Id));
return !(channel is IDisableMediaSourceDisplay);
return channel is not IDisableMediaSourceDisplay;
}
/// <inheritdoc />
@@ -129,16 +130,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);
@@ -179,7 +178,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
{
@@ -541,7 +540,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();
}
@@ -586,7 +585,7 @@ namespace Emby.Server.Implementations.Channels
{
var supportsLatest = provider is ISupportsLatestMedia;
return new ChannelFeatures
return new ChannelFeatures(channel.Name, channel.Id)
{
CanFilter = !features.MaxPageSize.HasValue,
CanSearch = provider is ISearchableChannel,
@@ -596,8 +595,6 @@ namespace Emby.Server.Implementations.Channels
MediaTypes = features.MediaTypes.ToArray(),
SupportsSortOrderToggle = features.SupportsSortOrderToggle,
SupportsLatestMedia = supportsLatest,
Name = channel.Name,
Id = channel.Id.ToString("N", CultureInfo.InvariantCulture),
SupportsContentDownloading = features.SupportsContentDownloading,
AutoRefreshLevels = features.AutoRefreshLevels
};
@@ -815,7 +812,7 @@ namespace Emby.Server.Implementations.Channels
{
if (_fileSystem.GetLastWriteTimeUtc(cachePath).Add(cacheLength) > DateTime.UtcNow)
{
await using FileStream jsonStream = File.OpenRead(cachePath);
await using FileStream jsonStream = AsyncFile.OpenRead(cachePath);
var cachedResult = await JsonSerializer.DeserializeAsync<ChannelItemResult>(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false);
if (cachedResult != null)
{
@@ -838,7 +835,7 @@ namespace Emby.Server.Implementations.Channels
{
if (_fileSystem.GetLastWriteTimeUtc(cachePath).Add(cacheLength) > DateTime.UtcNow)
{
await using FileStream jsonStream = File.OpenRead(cachePath);
await using FileStream jsonStream = AsyncFile.OpenRead(cachePath);
var cachedResult = await JsonSerializer.DeserializeAsync<ChannelItemResult>(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false);
if (cachedResult != null)
{
@@ -1077,14 +1074,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;
@@ -1145,7 +1134,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);
@@ -1154,7 +1143,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);

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

@@ -95,7 +95,7 @@ namespace Emby.Server.Implementations.Collections
var libraryOptions = new LibraryOptions
{
PathInfos = new[] { new MediaPathInfo { Path = path } },
PathInfos = new[] { new MediaPathInfo(path) },
EnableRealtimeMonitor = false,
SaveLocalMetadata = true
};
@@ -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);
@@ -196,8 +196,8 @@ namespace Emby.Server.Implementations.Collections
}
/// <inheritdoc />
public Task AddToCollectionAsync(Guid collectionId, IEnumerable<Guid> ids)
=> AddToCollectionAsync(collectionId, ids, true, new MetadataRefreshOptions(new DirectoryService(_fileSystem)));
public Task AddToCollectionAsync(Guid collectionId, IEnumerable<Guid> itemIds)
=> AddToCollectionAsync(collectionId, itemIds, true, new MetadataRefreshOptions(new DirectoryService(_fileSystem)));
private async Task AddToCollectionAsync(Guid collectionId, IEnumerable<Guid> ids, bool fireEvent, MetadataRefreshOptions refreshOptions)
{

View File

@@ -1,17 +1,20 @@
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
{
/// <summary>
/// Class providing abstractions over cryptographic functions.
/// </summary>
public class CryptographyProvider : ICryptoProvider, IDisposable
public class CryptographyProvider : ICryptoProvider
{
// TODO: remove when not needed for backwards compat
private static readonly HashSet<string> _supportedHashMethods = new HashSet<string>()
{
"MD5",
@@ -30,71 +33,71 @@ namespace Emby.Server.Implementations.Cryptography
"System.Security.Cryptography.SHA512"
};
private RandomNumberGenerator _randomNumberGenerator;
/// <inheritdoc />
public string DefaultHashMethod => "PBKDF2-SHA512";
private bool _disposed;
/// <summary>
/// Initializes a new instance of the <see cref="CryptographyProvider"/> class.
/// </summary>
public CryptographyProvider()
/// <inheritdoc />
public PasswordHash CreatePasswordHash(ReadOnlySpan<char> password)
{
// 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
_randomNumberGenerator = RandomNumberGenerator.Create();
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 string DefaultHashMethod => "PBKDF2";
/// <inheritdoc />
public IEnumerable<string> GetSupportedHashMethods()
=> _supportedHashMethods;
private byte[] PBKDF2(string method, byte[] bytes, byte[] salt, int iterations)
public bool Verify(PasswordHash hash, 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)
if (string.Equals(hash.Id, "PBKDF2", StringComparison.Ordinal))
{
throw new CryptographicException($"Cannot currently use PBKDF2 with requested hash method: {method}");
return hash.Hash.SequenceEqual(
Rfc2898DeriveBytes.Pbkdf2(
password,
hash.Salt,
int.Parse(hash.Parameters["iterations"], CultureInfo.InvariantCulture),
HashAlgorithmName.SHA1,
32));
}
using var r = new Rfc2898DeriveBytes(bytes, salt, iterations);
return r.GetBytes(32);
}
/// <inheritdoc />
public byte[] ComputeHash(string hashMethod, byte[] bytes, byte[] salt)
{
if (hashMethod == DefaultHashMethod)
if (string.Equals(hash.Id, "PBKDF2-SHA512", 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.SHA512,
DefaultOutputLength));
}
if (!_supportedHashMethods.Contains(hashMethod))
if (!_supportedHashMethods.Contains(hash.Id))
{
throw new CryptographicException($"Requested hash method is not supported: {hashMethod}");
throw new CryptographicException($"Requested hash method is not supported: {hash.Id}");
}
using var h = HashAlgorithm.Create(hashMethod) ?? throw new ResourceNotFoundException($"Unknown hash method: {hashMethod}.");
if (salt.Length == 0)
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 h.ComputeHash(bytes);
return hash.Hash.SequenceEqual(h.ComputeHash(bytes));
}
byte[] salted = new byte[bytes.Length + salt.Length];
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);
@@ -102,35 +105,10 @@ namespace Emby.Server.Implementations.Cryptography
/// <inheritdoc />
public byte[] GenerateSalt(int length)
{
byte[] salt = new byte[length];
_randomNumberGenerator.GetBytes(salt);
var salt = new byte[length];
using var rng = RandomNumberGenerator.Create();
rng.GetNonZeroBytes(salt);
return salt;
}
/// <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)
{
_randomNumberGenerator.Dispose();
}
_disposed = true;
}
}
}

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;
@@ -61,7 +61,7 @@ namespace Emby.Server.Implementations.Data
protected virtual int? CacheSize => null;
/// <summary>
/// Gets the journal mode. <see href="https://www.sqlite.org/pragma.html#pragma_journal_mode" />
/// Gets the journal mode. <see href="https://www.sqlite.org/pragma.html#pragma_journal_mode" />.
/// </summary>
/// <value>The journal mode.</value>
protected virtual string JournalMode => "TRUNCATE";
@@ -98,7 +98,7 @@ namespace Emby.Server.Implementations.Data
/// <value>The write connection.</value>
protected SQLiteDatabaseConnection WriteConnection { get; set; }
protected ManagedConnection GetConnection(bool _ = false)
protected ManagedConnection GetConnection(bool readOnly = false)
{
WriteLock.Wait();
if (WriteConnection != null)
@@ -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;
}
@@ -249,55 +250,4 @@ namespace Emby.Server.Implementations.Data
_disposed = true;
}
}
/// <summary>
/// The disk synchronization mode, controls how aggressively SQLite will write data
/// all the way out to physical storage.
/// </summary>
public enum SynchronousMode
{
/// <summary>
/// SQLite continues without syncing as soon as it has handed data off to the operating system.
/// </summary>
Off = 0,
/// <summary>
/// SQLite database engine will still sync at the most critical moments.
/// </summary>
Normal = 1,
/// <summary>
/// SQLite database engine will use the xSync method of the VFS
/// to ensure that all content is safely written to the disk surface prior to continuing.
/// </summary>
Full = 2,
/// <summary>
/// EXTRA synchronous is like FULL with the addition that the directory containing a rollback journal
/// is synced after that journal is unlinked to commit a transaction in DELETE mode.
/// </summary>
Extra = 3
}
/// <summary>
/// Storage mode used by temporary database files.
/// </summary>
public enum TempStoreMode
{
/// <summary>
/// The compile-time C preprocessor macro SQLITE_TEMP_STORE
/// is used to determine where temporary tables and indices are stored.
/// </summary>
Default = 0,
/// <summary>
/// Temporary tables and indices are stored in a file.
/// </summary>
File = 1,
/// <summary>
/// Temporary tables and indices are kept in as if they were pure in-memory databases memory.
/// </summary>
Memory = 2
}
}

View File

@@ -7,10 +7,12 @@ using SQLitePCL.pretty;
namespace Emby.Server.Implementations.Data
{
public class ManagedConnection : IDisposable
public sealed class ManagedConnection : IDisposable
{
private SQLiteDatabaseConnection? _db;
private readonly SemaphoreSlim _writeLock;
private SQLiteDatabaseConnection? _db;
private bool _disposed = false;
public ManagedConnection(SQLiteDatabaseConnection db, SemaphoreSlim writeLock)

View File

@@ -94,7 +94,7 @@ namespace Emby.Server.Implementations.Data
dateText,
_datetimeFormats,
DateTimeFormatInfo.InvariantInfo,
DateTimeStyles.None).ToUniversalTime();
DateTimeStyles.AdjustToUniversal);
}
public static bool TryReadDateTime(this IReadOnlyList<ResultSetValue> reader, int index, out DateTime result)
@@ -108,9 +108,9 @@ namespace Emby.Server.Implementations.Data
var dateText = item.ToString();
if (DateTime.TryParseExact(dateText, _datetimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None, out var dateTimeResult))
if (DateTime.TryParseExact(dateText, _datetimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AdjustToUniversal, out var dateTimeResult))
{
result = dateTimeResult.ToUniversalTime();
result = dateTimeResult;
return true;
}

File diff suppressed because it is too large Load Diff

View File

@@ -32,6 +32,9 @@ namespace Emby.Server.Implementations.Data
/// <summary>
/// Opens the connection to the database.
/// </summary>
/// <param name="userManager">The user manager.</param>
/// <param name="dbLock">The lock to use for database IO.</param>
/// <param name="dbConnection">The connection to use for database IO.</param>
public void Initialize(IUserManager userManager, SemaphoreSlim dbLock, SQLiteDatabaseConnection dbConnection)
{
WriteLock.Dispose();
@@ -47,41 +50,42 @@ namespace Emby.Server.Implementations.Data
var users = userDatasTableExists ? null : userManager.Users;
connection.RunInTransaction(
db =>
{
db.ExecuteAll(string.Join(';', new[] {
"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)
db =>
{
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);
}
}
@@ -129,19 +133,17 @@ namespace Emby.Server.Implementations.Data
return list;
}
/// <summary>
/// Saves the user data.
/// </summary>
public void SaveUserData(long internalUserId, string key, UserItemData userData, CancellationToken cancellationToken)
/// <inheritdoc />
public void SaveUserData(long userId, string key, UserItemData userData, CancellationToken cancellationToken)
{
if (userData == null)
{
throw new ArgumentNullException(nameof(userData));
}
if (internalUserId <= 0)
if (userId <= 0)
{
throw new ArgumentNullException(nameof(internalUserId));
throw new ArgumentNullException(nameof(userId));
}
if (string.IsNullOrEmpty(key))
@@ -149,22 +151,23 @@ namespace Emby.Server.Implementations.Data
throw new ArgumentNullException(nameof(key));
}
PersistUserData(internalUserId, key, userData, cancellationToken);
PersistUserData(userId, key, userData, cancellationToken);
}
public void SaveAllUserData(long internalUserId, UserItemData[] userData, CancellationToken cancellationToken)
/// <inheritdoc />
public void SaveAllUserData(long userId, UserItemData[] userData, CancellationToken cancellationToken)
{
if (userData == null)
{
throw new ArgumentNullException(nameof(userData));
}
if (internalUserId <= 0)
if (userId <= 0)
{
throw new ArgumentNullException(nameof(internalUserId));
throw new ArgumentNullException(nameof(userId));
}
PersistAllUserData(internalUserId, userData, cancellationToken);
PersistAllUserData(userId, userData, cancellationToken);
}
/// <summary>
@@ -174,7 +177,6 @@ namespace Emby.Server.Implementations.Data
/// <param name="key">The key.</param>
/// <param name="userData">The user data.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public void PersistUserData(long internalUserId, string key, UserItemData userData, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -182,10 +184,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);
}
}
@@ -251,32 +254,33 @@ 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);
}
}
/// <summary>
/// Gets the user data.
/// </summary>
/// <param name="internalUserId">The user id.</param>
/// <param name="userId">The user id.</param>
/// <param name="key">The key.</param>
/// <returns>Task{UserItemData}.</returns>
/// <exception cref="ArgumentNullException">
/// userId
/// or
/// key
/// key.
/// </exception>
public UserItemData GetUserData(long internalUserId, string key)
public UserItemData GetUserData(long userId, string key)
{
if (internalUserId <= 0)
if (userId <= 0)
{
throw new ArgumentNullException(nameof(internalUserId));
throw new ArgumentNullException(nameof(userId));
}
if (string.IsNullOrEmpty(key))
@@ -288,7 +292,7 @@ namespace Emby.Server.Implementations.Data
{
using (var statement = connection.PrepareStatement("select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from UserDatas where key =@Key and userId=@UserId"))
{
statement.TryBind("@UserId", internalUserId);
statement.TryBind("@UserId", userId);
statement.TryBind("@Key", key);
foreach (var row in statement.ExecuteQuery())
@@ -301,7 +305,7 @@ namespace Emby.Server.Implementations.Data
}
}
public UserItemData GetUserData(long internalUserId, List<string> keys)
public UserItemData GetUserData(long userId, List<string> keys)
{
if (keys == null)
{
@@ -313,19 +317,19 @@ namespace Emby.Server.Implementations.Data
return null;
}
return GetUserData(internalUserId, keys[0]);
return GetUserData(userId, keys[0]);
}
/// <summary>
/// Return all user-data associated with the given user.
/// </summary>
/// <param name="internalUserId"></param>
/// <returns></returns>
public List<UserItemData> GetAllUserData(long internalUserId)
/// <param name="userId">The internal user id.</param>
/// <returns>The list of user item data.</returns>
public List<UserItemData> GetAllUserData(long userId)
{
if (internalUserId <= 0)
if (userId <= 0)
{
throw new ArgumentNullException(nameof(internalUserId));
throw new ArgumentNullException(nameof(userId));
}
var list = new List<UserItemData>();
@@ -334,7 +338,7 @@ namespace Emby.Server.Implementations.Data
{
using (var statement = connection.PrepareStatement("select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from UserDatas where userId=@UserId"))
{
statement.TryBind("@UserId", internalUserId);
statement.TryBind("@UserId", userId);
foreach (var row in statement.ExecuteQuery())
{
@@ -349,7 +353,8 @@ namespace Emby.Server.Implementations.Data
/// <summary>
/// Read a row from the specified reader into the provided userData object.
/// </summary>
/// <param name="reader"></param>
/// <param name="reader">The list of result set values.</param>
/// <returns>The user item data.</returns>
private UserItemData ReadRow(IReadOnlyList<ResultSetValue> reader)
{
var userData = new UserItemData();

View File

@@ -0,0 +1,30 @@
namespace Emby.Server.Implementations.Data;
/// <summary>
/// The disk synchronization mode, controls how aggressively SQLite will write data
/// all the way out to physical storage.
/// </summary>
public enum SynchronousMode
{
/// <summary>
/// SQLite continues without syncing as soon as it has handed data off to the operating system.
/// </summary>
Off = 0,
/// <summary>
/// SQLite database engine will still sync at the most critical moments.
/// </summary>
Normal = 1,
/// <summary>
/// SQLite database engine will use the xSync method of the VFS
/// to ensure that all content is safely written to the disk surface prior to continuing.
/// </summary>
Full = 2,
/// <summary>
/// EXTRA synchronous is like FULL with the addition that the directory containing a rollback journal
/// is synced after that journal is unlinked to commit a transaction in DELETE mode.
/// </summary>
Extra = 3
}

View File

@@ -0,0 +1,23 @@
namespace Emby.Server.Implementations.Data;
/// <summary>
/// Storage mode used by temporary database files.
/// </summary>
public enum TempStoreMode
{
/// <summary>
/// The compile-time C preprocessor macro SQLITE_TEMP_STORE
/// is used to determine where temporary tables and indices are stored.
/// </summary>
Default = 0,
/// <summary>
/// Temporary tables and indices are stored in a file.
/// </summary>
File = 1,
/// <summary>
/// Temporary tables and indices are kept in as if they were pure in-memory databases memory.
/// </summary>
Memory = 2
}

View File

@@ -15,9 +15,18 @@ namespace Emby.Server.Implementations.Devices
{
private readonly IApplicationPaths _appPaths;
private readonly ILogger<DeviceId> _logger;
private readonly object _syncLock = new object();
private string _id;
public DeviceId(IApplicationPaths appPaths, ILoggerFactory loggerFactory)
{
_appPaths = appPaths;
_logger = loggerFactory.CreateLogger<DeviceId>();
}
public string Value => _id ?? (_id = GetDeviceId());
private string CachePath => Path.Combine(_appPaths.DataPath, "device.txt");
private string GetCachedId()
@@ -28,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;
}
@@ -86,15 +95,5 @@ namespace Emby.Server.Implementations.Devices
return id;
}
private string _id;
public DeviceId(IApplicationPaths appPaths, ILoggerFactory loggerFactory)
{
_appPaths = appPaths;
_logger = loggerFactory.CreateLogger<DeviceId>();
}
public string Value => _id ?? (_id = GetDeviceId());
}
}

View File

@@ -1,146 +0,0 @@
#nullable disable
#pragma warning disable CS1591
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using Jellyfin.Data.Events;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Security;
using MediaBrowser.Model.Devices;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Session;
namespace Emby.Server.Implementations.Devices
{
public class DeviceManager : IDeviceManager
{
private readonly IUserManager _userManager;
private readonly IAuthenticationRepository _authRepo;
private readonly ConcurrentDictionary<string, ClientCapabilities> _capabilitiesMap = new ();
public DeviceManager(IAuthenticationRepository authRepo, IUserManager userManager)
{
_userManager = userManager;
_authRepo = authRepo;
}
public event EventHandler<GenericEventArgs<Tuple<string, DeviceOptions>>> DeviceOptionsUpdated;
public void SaveCapabilities(string deviceId, ClientCapabilities capabilities)
{
_capabilitiesMap[deviceId] = capabilities;
}
public void UpdateDeviceOptions(string deviceId, DeviceOptions options)
{
_authRepo.UpdateDeviceOptions(deviceId, options);
DeviceOptionsUpdated?.Invoke(this, new GenericEventArgs<Tuple<string, DeviceOptions>>(new Tuple<string, DeviceOptions>(deviceId, options)));
}
public DeviceOptions GetDeviceOptions(string deviceId)
{
return _authRepo.GetDeviceOptions(deviceId);
}
public ClientCapabilities GetCapabilities(string id)
{
return _capabilitiesMap.TryGetValue(id, out ClientCapabilities result)
? result
: new ClientCapabilities();
}
public DeviceInfo GetDevice(string id)
{
var session = _authRepo.Get(new AuthenticationInfoQuery
{
DeviceId = id
}).Items.FirstOrDefault();
var device = session == null ? null : ToDeviceInfo(session);
return device;
}
public QueryResult<DeviceInfo> GetDevices(DeviceQuery query)
{
IEnumerable<AuthenticationInfo> sessions = _authRepo.Get(new AuthenticationInfoQuery
{
// UserId = query.UserId
HasUser = true
}).Items;
// TODO: DeviceQuery doesn't seem to be used from client. Not even Swagger.
if (query.SupportsSync.HasValue)
{
var val = query.SupportsSync.Value;
sessions = sessions.Where(i => GetCapabilities(i.DeviceId).SupportsSync == val);
}
if (!query.UserId.Equals(Guid.Empty))
{
var user = _userManager.GetUserById(query.UserId);
sessions = sessions.Where(i => CanAccessDevice(user, i.DeviceId));
}
var array = sessions.Select(ToDeviceInfo).ToArray();
return new QueryResult<DeviceInfo>(array);
}
private DeviceInfo ToDeviceInfo(AuthenticationInfo authInfo)
{
var caps = GetCapabilities(authInfo.DeviceId);
return new DeviceInfo
{
AppName = authInfo.AppName,
AppVersion = authInfo.AppVersion,
Id = authInfo.DeviceId,
LastUserId = authInfo.UserId,
LastUserName = authInfo.UserName,
Name = authInfo.DeviceName,
DateLastActivity = authInfo.DateLastActivity,
IconUrl = caps?.IconUrl
};
}
public bool CanAccessDevice(User user, string deviceId)
{
if (user == null)
{
throw new ArgumentException("user not found");
}
if (string.IsNullOrEmpty(deviceId))
{
throw new ArgumentNullException(nameof(deviceId));
}
if (user.HasPermission(PermissionKind.EnableAllDevices) || user.HasPermission(PermissionKind.IsAdministrator))
{
return true;
}
if (!user.GetPreference(PreferenceKind.EnabledDevices).Contains(deviceId, StringComparer.OrdinalIgnoreCase))
{
var capabilities = GetCapabilities(deviceId);
if (capabilities != null && capabilities.SupportsPersistentIdentifier)
{
return false;
}
}
return true;
}
}
}

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;
@@ -51,8 +51,6 @@ namespace Emby.Server.Implementations.Dto
private readonly IMediaSourceManager _mediaSourceManager;
private readonly Lazy<ILiveTvManager> _livetvManagerFactory;
private ILiveTvManager LivetvManager => _livetvManagerFactory.Value;
public DtoService(
ILogger<DtoService> logger,
ILibraryManager libraryManager,
@@ -75,6 +73,8 @@ namespace Emby.Server.Implementations.Dto
_livetvManagerFactory = livetvManagerFactory;
}
private ILiveTvManager LivetvManager => _livetvManagerFactory.Value;
/// <inheritdoc />
public IReadOnlyList<BaseItemDto> GetBaseItemDtos(IReadOnlyList<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null)
{
@@ -109,7 +109,7 @@ namespace Emby.Server.Implementations.Dto
}
});
SetItemByNameInfo(item, dto, libraryItems, user);
SetItemByNameInfo(item, dto, libraryItems);
}
}
@@ -134,14 +134,11 @@ namespace Emby.Server.Implementations.Dto
var dto = GetBaseItemDtoInternal(item, options, user, owner);
if (item is LiveTvChannel tvChannel)
{
var list = new List<(BaseItemDto, LiveTvChannel)>(1) { (dto, tvChannel) };
LivetvManager.AddChannelInfo(list, options, user);
LivetvManager.AddChannelInfo(new[] { (dto, tvChannel) }, options, user);
}
else if (item is LiveTvProgram)
{
var list = new List<(BaseItem, BaseItemDto)>(1) { (item, dto) };
var task = LivetvManager.AddInfoToProgramDto(list, options.Fields, user);
Task.WaitAll(task);
LivetvManager.AddInfoToProgramDto(new[] { (item, dto) }, options.Fields, user).GetAwaiter().GetResult();
}
if (item is IItemByName itemByName
@@ -156,8 +153,7 @@ namespace Emby.Server.Implementations.Dto
new DtoOptions(false)
{
EnableImages = false
}),
user);
}));
}
return dto;
@@ -297,7 +293,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;
}
@@ -314,13 +310,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)
{
@@ -373,6 +369,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))
@@ -420,7 +422,7 @@ namespace Emby.Server.Implementations.Dto
// Just return something so that apps that are expecting a value won't think the folders are empty
if (folder is ICollectionFolder || folder is UserView)
{
return new Random().Next(1, 10);
return Random.Shared.Next(1, 10);
}
return folder.GetChildCount(user);
@@ -467,7 +469,7 @@ namespace Emby.Server.Implementations.Dto
{
var parentAlbumIds = _libraryManager.GetItemIds(new InternalItemsQuery
{
IncludeItemTypes = new[] { nameof(MusicAlbum) },
IncludeItemTypes = new[] { BaseItemKind.MusicAlbum },
Name = item.Album,
Limit = 1
});
@@ -497,7 +499,7 @@ namespace Emby.Server.Implementations.Dto
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting {imageType} image info for {path}", image.Type, image.Path);
_logger.LogError(ex, "Error getting {ImageType} image info for {Path}", image.Type, image.Path);
return null;
}
}
@@ -507,7 +509,6 @@ namespace Emby.Server.Implementations.Dto
/// </summary>
/// <param name="dto">The dto.</param>
/// <param name="item">The item.</param>
/// <returns>Task.</returns>
private void AttachPeople(BaseItemDto dto, BaseItem item)
{
// Ordering by person type to ensure actors and artists are at the front.
@@ -616,7 +617,6 @@ namespace Emby.Server.Implementations.Dto
/// </summary>
/// <param name="dto">The dto.</param>
/// <param name="item">The item.</param>
/// <returns>Task.</returns>
private void AttachStudios(BaseItemDto dto, BaseItem item)
{
dto.Studios = item.Studios
@@ -757,15 +757,6 @@ namespace Emby.Server.Implementations.Dto
dto.BackdropImageTags = GetTagsAndFillBlurhashes(dto, item, ImageType.Backdrop, backdropLimit);
}
if (options.ContainsField(ItemFields.ScreenshotImageTags))
{
var screenshotLimit = options.GetImageLimit(ImageType.Screenshot);
if (screenshotLimit > 0)
{
dto.ScreenshotImageTags = GetTagsAndFillBlurhashes(dto, item, ImageType.Screenshot, screenshotLimit);
}
}
if (options.ContainsField(ItemFields.Genres))
{
dto.Genres = item.Genres;
@@ -807,7 +798,7 @@ namespace Emby.Server.Implementations.Dto
dto.MediaType = item.MediaType;
if (!(item is LiveTvProgram))
if (item is not LiveTvProgram)
{
dto.LocationType = item.LocationType;
}
@@ -928,9 +919,9 @@ namespace Emby.Server.Implementations.Dto
}
// if (options.ContainsField(ItemFields.MediaSourceCount))
//{
// {
// Songs always have one
//}
// }
}
if (item is IHasArtist hasArtist)
@@ -938,10 +929,10 @@ namespace Emby.Server.Implementations.Dto
dto.Artists = hasArtist.Artists;
// var artistItems = _libraryManager.GetArtists(new InternalItemsQuery
//{
// {
// EnableTotalRecordCount = false,
// ItemIds = new[] { item.Id.ToString("N", CultureInfo.InvariantCulture) }
//});
// });
// dto.ArtistItems = artistItems.Items
// .Select(i =>
@@ -958,7 +949,7 @@ namespace Emby.Server.Implementations.Dto
// Include artists that are not in the database yet, e.g., just added via metadata editor
// var foundArtists = artistItems.Items.Select(i => i.Item1.Name).ToList();
dto.ArtistItems = hasArtist.Artists
//.Except(foundArtists, new DistinctNameComparer())
// .Except(foundArtists, new DistinctNameComparer())
.Select(i =>
{
// This should not be necessary but we're seeing some cases of it
@@ -990,10 +981,10 @@ namespace Emby.Server.Implementations.Dto
dto.AlbumArtist = hasAlbumArtist.AlbumArtists.FirstOrDefault();
// var artistItems = _libraryManager.GetAlbumArtists(new InternalItemsQuery
//{
// {
// EnableTotalRecordCount = false,
// ItemIds = new[] { item.Id.ToString("N", CultureInfo.InvariantCulture) }
//});
// });
// dto.AlbumArtists = artistItems.Items
// .Select(i =>
@@ -1008,7 +999,7 @@ namespace Emby.Server.Implementations.Dto
// .ToList();
dto.AlbumArtists = hasAlbumArtist.AlbumArtists
//.Except(foundArtists, new DistinctNameComparer())
// .Except(foundArtists, new DistinctNameComparer())
.Select(i =>
{
// This should not be necessary but we're seeing some cases of it
@@ -1035,8 +1026,7 @@ namespace Emby.Server.Implementations.Dto
}
// Add video info
var video = item as Video;
if (video != null)
if (item is Video video)
{
dto.VideoType = video.VideoType;
dto.Video3DFormat = video.Video3DFormat;
@@ -1075,9 +1065,7 @@ namespace Emby.Server.Implementations.Dto
if (options.ContainsField(ItemFields.MediaStreams))
{
// Add VideoInfo
var iHasMediaSources = item as IHasMediaSources;
if (iHasMediaSources != null)
if (item is IHasMediaSources)
{
MediaStream[] mediaStreams;
@@ -1146,7 +1134,7 @@ namespace Emby.Server.Implementations.Dto
// TODO maybe remove the if statement entirely
// if (options.ContainsField(ItemFields.SeriesPrimaryImage))
{
episodeSeries = episodeSeries ?? episode.Series;
episodeSeries ??= episode.Series;
if (episodeSeries != null)
{
dto.SeriesPrimaryImageTag = GetTagAndFillBlurhash(dto, episodeSeries, ImageType.Primary);
@@ -1159,7 +1147,7 @@ namespace Emby.Server.Implementations.Dto
if (options.ContainsField(ItemFields.SeriesStudio))
{
episodeSeries = episodeSeries ?? episode.Series;
episodeSeries ??= episode.Series;
if (episodeSeries != null)
{
dto.SeriesStudio = episodeSeries.Studios.FirstOrDefault();
@@ -1172,7 +1160,7 @@ namespace Emby.Server.Implementations.Dto
{
dto.AirDays = series.AirDays;
dto.AirTime = series.AirTime;
dto.Status = series.Status.HasValue ? series.Status.Value.ToString() : null;
dto.Status = series.Status?.ToString();
}
// Add SeasonInfo
@@ -1185,7 +1173,7 @@ namespace Emby.Server.Implementations.Dto
if (options.ContainsField(ItemFields.SeriesStudio))
{
series = series ?? season.Series;
series ??= season.Series;
if (series != null)
{
dto.SeriesStudio = series.Studios.FirstOrDefault();
@@ -1196,7 +1184,7 @@ namespace Emby.Server.Implementations.Dto
// TODO maybe remove the if statement entirely
// if (options.ContainsField(ItemFields.SeriesPrimaryImage))
{
series = series ?? season.Series;
series ??= season.Series;
if (series != null)
{
dto.SeriesPrimaryImageTag = GetTagAndFillBlurhash(dto, series, ImageType.Primary);
@@ -1283,7 +1271,7 @@ namespace Emby.Server.Implementations.Dto
var parent = currentItem.DisplayParent ?? currentItem.GetOwner() ?? currentItem.GetParent();
if (parent == null && !(originalItem is UserRootFolder) && !(originalItem is UserView) && !(originalItem is AggregateFolder) && !(originalItem is ICollectionFolder) && !(originalItem is Channel))
if (parent == null && originalItem is not UserRootFolder && originalItem is not UserView && originalItem is not AggregateFolder && originalItem is not ICollectionFolder && originalItem is not Channel)
{
parent = _libraryManager.GetCollectionFolders(originalItem).FirstOrDefault();
}
@@ -1316,9 +1304,12 @@ namespace Emby.Server.Implementations.Dto
var imageTags = dto.ImageTags;
while (((!(imageTags != null && imageTags.ContainsKey(ImageType.Logo)) && logoLimit > 0) || (!(imageTags != null && imageTags.ContainsKey(ImageType.Art)) && artLimit > 0) || (!(imageTags != null && imageTags.ContainsKey(ImageType.Thumb)) && thumbLimit > 0) || parent is Series) &&
(parent = parent ?? (isFirst ? GetImageDisplayParent(item, item) ?? owner : parent)) != null)
while ((!(imageTags != null && imageTags.ContainsKey(ImageType.Logo)) && logoLimit > 0)
|| (!(imageTags != null && imageTags.ContainsKey(ImageType.Art)) && artLimit > 0)
|| (!(imageTags != null && imageTags.ContainsKey(ImageType.Thumb)) && thumbLimit > 0)
|| parent is Series)
{
parent ??= isFirst ? GetImageDisplayParent(item, item) ?? owner : parent;
if (parent == null)
{
break;
@@ -1348,7 +1339,7 @@ namespace Emby.Server.Implementations.Dto
}
}
if (thumbLimit > 0 && !(imageTags != null && imageTags.ContainsKey(ImageType.Thumb)) && (dto.ParentThumbItemId == null || parent is Series) && !(parent is ICollectionFolder) && !(parent is UserView))
if (thumbLimit > 0 && !(imageTags != null && imageTags.ContainsKey(ImageType.Thumb)) && (dto.ParentThumbItemId == null || parent is Series) && parent is not ICollectionFolder && parent is not UserView)
{
var image = allImages.FirstOrDefault(i => i.Type == ImageType.Thumb);
@@ -1398,7 +1389,6 @@ namespace Emby.Server.Implementations.Dto
/// </summary>
/// <param name="dto">The dto.</param>
/// <param name="item">The item.</param>
/// <returns>Task.</returns>
public void AttachPrimaryImageAspectRatio(IItemDto dto, BaseItem item)
{
dto.PrimaryImageAspectRatio = GetPrimaryImageAspectRatio(item);
@@ -1413,44 +1403,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

@@ -23,17 +23,18 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="DiscUtils.Udf" Version="0.16.13" />
<PackageReference Include="Jellyfin.XmlTv" Version="10.6.2" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.2" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.9" />
<PackageReference Include="Mono.Nat" Version="3.0.1" />
<PackageReference Include="prometheus-net.DotNetRuntime" Version="4.1.0" />
<PackageReference Include="sharpcompress" Version="0.28.3" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.0" />
<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.1" />
<PackageReference Include="Mono.Nat" Version="3.0.2" />
<PackageReference Include="prometheus-net.DotNetRuntime" Version="4.2.2" />
<PackageReference Include="sharpcompress" Version="0.30.1" />
<PackageReference Include="SQLitePCL.pretty.netstandard" Version="3.1.0" />
<PackageReference Include="DotNet.Glob" Version="3.1.2" />
<PackageReference Include="DotNet.Glob" Version="3.1.3" />
</ItemGroup>
<ItemGroup>
@@ -41,22 +42,21 @@
</ItemGroup>
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<!-- https://github.com/microsoft/ApplicationInsights-dotnet/issues/2047 -->
<NoWarn>AD0001</NoWarn>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release'">
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<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.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>

View File

@@ -9,12 +9,10 @@ using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Events;
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;
@@ -28,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>();
@@ -43,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,12 +144,12 @@ 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)
{
if (!(item is Folder folder))
if (item is not Folder folder)
{
return false;
}
@@ -403,7 +403,7 @@ namespace Emby.Server.Implementations.EntryPoints
return false;
}
if (item is IItemByName && !(item is MusicArtist))
if (item is IItemByName && item is not MusicArtist)
{
return false;
}
@@ -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));
@@ -436,7 +435,7 @@ namespace Emby.Server.Implementations.EntryPoints
/// <summary>
/// Translates the physical item to user library.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="T">The type of item.</typeparam>
/// <param name="item">The item.</param>
/// <param name="user">The user.</param>
/// <param name="includeIfNotFound">if set to <c>true</c> [include if not found].</param>
@@ -465,6 +464,7 @@ namespace Emby.Server.Implementations.EntryPoints
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>

View File

@@ -37,6 +37,9 @@ namespace Emby.Server.Implementations.EntryPoints
/// <summary>
/// Initializes a new instance of the <see cref="UdpServerEntryPoint" /> class.
/// </summary>
/// <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>
public UdpServerEntryPoint(
ILogger<UdpServerEntryPoint> logger,
IServerApplicationHost appHost,

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

@@ -1,7 +1,7 @@
#pragma warning disable CS1591
using System.Threading.Tasks;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Authentication;
using MediaBrowser.Controller.Net;
using Microsoft.AspNetCore.Http;
@@ -17,13 +17,13 @@ namespace Emby.Server.Implementations.HttpServer.Security
_authorizationContext = authorizationContext;
}
public AuthorizationInfo Authenticate(HttpRequest request)
public async Task<AuthorizationInfo> Authenticate(HttpRequest request)
{
var auth = _authorizationContext.GetAuthorizationInfo(request);
var auth = await _authorizationContext.GetAuthorizationInfo(request).ConfigureAwait(false);
if (!auth.HasToken)
{
throw new AuthenticationException("Request does not contain a token.");
return auth;
}
if (!auth.IsAuthenticated)

View File

@@ -1,6 +1,7 @@
#pragma warning disable CS1591
using System;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Library;
@@ -23,27 +24,33 @@ namespace Emby.Server.Implementations.HttpServer.Security
_sessionManager = sessionManager;
}
public SessionInfo GetSession(HttpContext requestContext)
public async Task<SessionInfo> GetSession(HttpContext requestContext)
{
var authorization = _authContext.GetAuthorizationInfo(requestContext);
var authorization = await _authContext.GetAuthorizationInfo(requestContext).ConfigureAwait(false);
var user = authorization.User;
return _sessionManager.LogSessionActivity(authorization.Client, authorization.Version, authorization.DeviceId, authorization.Device, requestContext.GetNormalizedRemoteIp().ToString(), user);
return await _sessionManager.LogSessionActivity(
authorization.Client,
authorization.Version,
authorization.DeviceId,
authorization.Device,
requestContext.GetNormalizedRemoteIp().ToString(),
user).ConfigureAwait(false);
}
public SessionInfo GetSession(object requestContext)
public Task<SessionInfo> GetSession(object requestContext)
{
return GetSession((HttpContext)requestContext);
}
public User? GetUser(HttpContext requestContext)
public async Task<User?> GetUser(HttpContext requestContext)
{
var session = GetSession(requestContext);
var session = await GetSession(requestContext).ConfigureAwait(false);
return session == null || session.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(session.UserId);
return session.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(session.UserId);
}
public User? GetUser(object requestContext)
public Task<User?> GetUser(object requestContext)
{
return GetUser(((HttpRequest)requestContext).HttpContext);
}

View File

@@ -42,17 +42,14 @@ namespace Emby.Server.Implementations.HttpServer
/// <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;
@@ -62,7 +59,7 @@ namespace Emby.Server.Implementations.HttpServer
public event EventHandler<EventArgs>? Closed;
/// <summary>
/// Gets or sets the remote end point.
/// Gets the remote end point.
/// </summary>
public IPAddress? RemoteEndPoint { get; }
@@ -81,12 +78,6 @@ namespace Emby.Server.Implementations.HttpServer
/// <inheritdoc />
public DateTime LastKeepAliveDate { get; set; }
/// <summary>
/// Gets or sets the query string.
/// </summary>
/// <value>The query string.</value>
public IQueryCollection QueryString { get; }
/// <summary>
/// Gets the state.
/// </summary>
@@ -96,7 +87,7 @@ namespace Emby.Server.Implementations.HttpServer
/// <summary>
/// Sends a message asynchronously.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="T">The type of the message.</typeparam>
/// <param name="message">The message.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
@@ -150,8 +141,8 @@ namespace Emby.Server.Implementations.HttpServer
{
await ProcessInternal(pipe.Reader).ConfigureAwait(false);
}
} while (
(_socket.State == WebSocketState.Open || _socket.State == WebSocketState.Connecting)
}
while ((_socket.State == WebSocketState.Open || _socket.State == WebSocketState.Connecting)
&& receiveresult.MessageType != WebSocketMessageType.Close);
Closed?.Invoke(this, EventArgs.Empty);
@@ -180,7 +171,7 @@ namespace Emby.Server.Implementations.HttpServer
}
WebSocketMessage<object>? stub;
long bytesConsumed = 0;
long bytesConsumed;
try
{
stub = DeserializeWebSocketMessage(buffer, out bytesConsumed);
@@ -236,7 +227,8 @@ namespace Emby.Server.Implementations.HttpServer
{
MessageId = Guid.NewGuid(),
MessageType = SessionMessageType.KeepAlive
}, CancellationToken.None);
},
CancellationToken.None);
}
/// <inheritdoc />

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;
@@ -35,7 +36,12 @@ namespace Emby.Server.Implementations.HttpServer
/// <inheritdoc />
public async Task WebSocketRequestHandler(HttpContext context)
{
_ = _authService.Authenticate(context.Request);
var authorizationInfo = await _authService.Authenticate(context.Request).ConfigureAwait(false);
if (!authorizationInfo.IsAuthenticated)
{
throw new SecurityException("Token is required");
}
try
{
_logger.LogInformation("WS {IP} request", context.Connection.RemoteIpAddress);
@@ -45,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
};
@@ -54,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

@@ -41,6 +41,25 @@ namespace Emby.Server.Implementations.IO
private bool _disposed = false;
/// <summary>
/// Initializes a new instance of the <see cref="LibraryMonitor" /> class.
/// </summary>
/// <param name="logger">The logger.</param>
/// <param name="libraryManager">The library manager.</param>
/// <param name="configurationManager">The configuration manager.</param>
/// <param name="fileSystem">The filesystem.</param>
public LibraryMonitor(
ILogger<LibraryMonitor> logger,
ILibraryManager libraryManager,
IServerConfigurationManager configurationManager,
IFileSystem fileSystem)
{
_libraryManager = libraryManager;
_logger = logger;
_configurationManager = configurationManager;
_fileSystem = fileSystem;
}
/// <summary>
/// Add the path to our temporary ignore list. Use when writing to a path within our listening scope.
/// </summary>
@@ -80,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)
{
@@ -95,21 +114,6 @@ namespace Emby.Server.Implementations.IO
}
}
/// <summary>
/// Initializes a new instance of the <see cref="LibraryMonitor" /> class.
/// </summary>
public LibraryMonitor(
ILogger<LibraryMonitor> logger,
ILibraryManager libraryManager,
IServerConfigurationManager configurationManager,
IFileSystem fileSystem)
{
_libraryManager = libraryManager;
_logger = logger;
_configurationManager = configurationManager;
_fileSystem = fileSystem;
}
private bool IsLibraryMonitorEnabled(BaseItem item)
{
if (item is BasePluginFolder)
@@ -199,7 +203,7 @@ namespace Emby.Server.Implementations.IO
/// <param name="lst">The LST.</param>
/// <param name="path">The path.</param>
/// <returns><c>true</c> if [contains parent folder] [the specified LST]; otherwise, <c>false</c>.</returns>
/// <exception cref="ArgumentNullException">path</exception>
/// <exception cref="ArgumentNullException"><paramref name="path"/> is <c>null</c>.</exception>
private static bool ContainsParentFolder(IEnumerable<string> lst, string path)
{
if (string.IsNullOrEmpty(path))
@@ -263,7 +267,7 @@ namespace Emby.Server.Implementations.IO
if (_fileSystemWatchers.TryAdd(path, newWatcher))
{
newWatcher.EnableRaisingEvents = true;
_logger.LogInformation("Watching directory " + path);
_logger.LogInformation("Watching directory {Path}", path);
}
else
{
@@ -272,7 +276,7 @@ namespace Emby.Server.Implementations.IO
}
catch (Exception ex)
{
_logger.LogError(ex, "Error watching path: {path}", path);
_logger.LogError(ex, "Error watching path: {Path}", path);
}
});
}
@@ -445,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);
@@ -477,6 +481,7 @@ namespace Emby.Server.Implementations.IO
{
lock (_activeRefreshers)
{
refresher.Completed -= OnNewRefresherCompleted;
refresher.Dispose();
_activeRefreshers.Remove(refresher);
}
@@ -488,6 +493,7 @@ namespace Emby.Server.Implementations.IO
{
foreach (var refresher in _activeRefreshers.ToList())
{
refresher.Completed -= OnNewRefresherCompleted;
refresher.Dispose();
}

View File

@@ -1,15 +1,11 @@
#pragma warning disable CS1591
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using Jellyfin.Extensions;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.System;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.IO
@@ -19,20 +15,26 @@ namespace Emby.Server.Implementations.IO
/// </summary>
public class ManagedFileSystem : IFileSystem
{
protected ILogger<ManagedFileSystem> Logger;
private readonly ILogger<ManagedFileSystem> _logger;
private readonly List<IShortcutHandler> _shortcutHandlers = new List<IShortcutHandler>();
private readonly string _tempPath;
private static readonly bool _isEnvironmentCaseInsensitive = OperatingSystem.IsWindows();
/// <summary>
/// Initializes a new instance of the <see cref="ManagedFileSystem"/> class.
/// </summary>
/// <param name="logger">The <see cref="ILogger"/> instance to use.</param>
/// <param name="applicationPaths">The <see cref="IApplicationPaths"/> instance to use.</param>
public ManagedFileSystem(
ILogger<ManagedFileSystem> logger,
IApplicationPaths applicationPaths)
{
Logger = logger;
_logger = logger;
_tempPath = applicationPaths.TempDirectory;
}
/// <inheritdoc />
public virtual void AddShortcutHandler(IShortcutHandler handler)
{
_shortcutHandlers.Add(handler);
@@ -43,7 +45,7 @@ namespace Emby.Server.Implementations.IO
/// </summary>
/// <param name="filename">The filename.</param>
/// <returns><c>true</c> if the specified filename is shortcut; otherwise, <c>false</c>.</returns>
/// <exception cref="ArgumentNullException">filename</exception>
/// <exception cref="ArgumentNullException"><paramref name="filename"/> is <c>null</c>.</exception>
public virtual bool IsShortcut(string filename)
{
if (string.IsNullOrEmpty(filename))
@@ -60,7 +62,7 @@ namespace Emby.Server.Implementations.IO
/// </summary>
/// <param name="filename">The filename.</param>
/// <returns>System.String.</returns>
/// <exception cref="ArgumentNullException">filename</exception>
/// <exception cref="ArgumentNullException"><paramref name="filename"/> is <c>null</c>.</exception>
public virtual string? ResolveShortcut(string filename)
{
if (string.IsNullOrEmpty(filename))
@@ -74,6 +76,7 @@ namespace Emby.Server.Implementations.IO
return handler?.Resolve(filename);
}
/// <inheritdoc />
public virtual string MakeAbsolutePath(string folderPath, string filePath)
{
// path is actually a stream
@@ -235,9 +238,9 @@ namespace Emby.Server.Implementations.IO
result.IsDirectory = info is DirectoryInfo || (info.Attributes & FileAttributes.Directory) == FileAttributes.Directory;
// if (!result.IsDirectory)
//{
// {
// result.IsHidden = (info.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden;
//}
// }
if (info is FileInfo fileInfo)
{
@@ -248,15 +251,15 @@ namespace Emby.Server.Implementations.IO
{
try
{
using (Stream thisFileStream = File.OpenRead(fileInfo.FullName))
using (var fileHandle = File.OpenHandle(fileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
result.Length = thisFileStream.Length;
result.Length = RandomAccess.GetLength(fileHandle);
}
}
catch (FileNotFoundException ex)
{
// Dangling symlinks cannot be detected before opening the file unfortunately...
Logger.LogError(ex, "Reading the file size of the symlink at {Path} failed. Marking the file as not existing.", fileInfo.FullName);
_logger.LogError(ex, "Reading the file size of the symlink at {Path} failed. Marking the file as not existing.", fileInfo.FullName);
result.Exists = false;
}
}
@@ -345,7 +348,7 @@ namespace Emby.Server.Implementations.IO
}
catch (Exception ex)
{
Logger.LogError(ex, "Error determining CreationTimeUtc for {FullName}", info.FullName);
_logger.LogError(ex, "Error determining CreationTimeUtc for {FullName}", info.FullName);
return DateTime.MinValue;
}
}
@@ -360,11 +363,13 @@ namespace Emby.Server.Implementations.IO
return GetCreationTimeUtc(GetFileSystemInfo(path));
}
/// <inheritdoc />
public virtual DateTime GetCreationTimeUtc(FileSystemMetadata info)
{
return info.CreationTimeUtc;
}
/// <inheritdoc />
public virtual DateTime GetLastWriteTimeUtc(FileSystemMetadata info)
{
return info.LastWriteTimeUtc;
@@ -384,7 +389,7 @@ namespace Emby.Server.Implementations.IO
}
catch (Exception ex)
{
Logger.LogError(ex, "Error determining LastAccessTimeUtc for {FullName}", info.FullName);
_logger.LogError(ex, "Error determining LastAccessTimeUtc for {FullName}", info.FullName);
return DateTime.MinValue;
}
}
@@ -399,6 +404,7 @@ namespace Emby.Server.Implementations.IO
return GetLastWriteTimeUtc(GetFileSystemInfo(path));
}
/// <inheritdoc />
public virtual void SetHidden(string path, bool isHidden)
{
if (!OperatingSystem.IsWindows())
@@ -423,7 +429,8 @@ namespace Emby.Server.Implementations.IO
}
}
public virtual void SetAttributes(string path, bool isHidden, bool isReadOnly)
/// <inheritdoc />
public virtual void SetAttributes(string path, bool isHidden, bool readOnly)
{
if (!OperatingSystem.IsWindows())
{
@@ -437,16 +444,16 @@ namespace Emby.Server.Implementations.IO
return;
}
if (info.IsReadOnly == isReadOnly && info.IsHidden == isHidden)
if (info.IsReadOnly == readOnly && info.IsHidden == isHidden)
{
return;
}
var attributes = File.GetAttributes(path);
if (isReadOnly)
if (readOnly)
{
attributes = attributes | FileAttributes.ReadOnly;
attributes |= FileAttributes.ReadOnly;
}
else
{
@@ -455,7 +462,7 @@ namespace Emby.Server.Implementations.IO
if (isHidden)
{
attributes = attributes | FileAttributes.Hidden;
attributes |= FileAttributes.Hidden;
}
else
{
@@ -500,6 +507,7 @@ namespace Emby.Server.Implementations.IO
File.Copy(temp1, file2, true);
}
/// <inheritdoc />
public virtual bool ContainsSubPath(string parentPath, string path)
{
if (string.IsNullOrEmpty(parentPath))
@@ -517,6 +525,7 @@ namespace Emby.Server.Implementations.IO
_isEnvironmentCaseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
}
/// <inheritdoc />
public virtual string NormalizePath(string path)
{
if (string.IsNullOrEmpty(path))
@@ -532,24 +541,16 @@ namespace Emby.Server.Implementations.IO
return Path.TrimEndingDirectorySeparator(path);
}
/// <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),
_isEnvironmentCaseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
}
/// <inheritdoc />
public virtual string GetFileNameWithoutExtension(FileSystemMetadata info)
{
if (info.IsDirectory)
@@ -560,11 +561,11 @@ namespace Emby.Server.Implementations.IO
return Path.GetFileNameWithoutExtension(info.FullName);
}
/// <inheritdoc />
public virtual bool IsPathFile(string path)
{
// Cannot use Path.IsPathRooted because it returns false under mono when using windows-based paths, e.g. C:\\
if (path.IndexOf("://", StringComparison.OrdinalIgnoreCase) != -1 &&
!path.StartsWith("file://", StringComparison.OrdinalIgnoreCase))
if (path.Contains("://", StringComparison.OrdinalIgnoreCase)
&& !path.StartsWith("file://", StringComparison.OrdinalIgnoreCase))
{
return false;
}
@@ -572,17 +573,23 @@ namespace Emby.Server.Implementations.IO
return true;
}
/// <inheritdoc />
public virtual void DeleteFile(string path)
{
SetAttributes(path, false, false);
File.Delete(path);
}
/// <inheritdoc />
public virtual List<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
return DriveInfo.GetDrives().Where(d => d.IsReady && d.TotalSize != 0 && d.DriveType != DriveType.Ram)
return DriveInfo.GetDrives()
.Where(
d => (d.DriveType == DriveType.Fixed || d.DriveType == DriveType.Network || d.DriveType == DriveType.Removable)
&& d.IsReady
&& d.TotalSize != 0)
.Select(d => new FileSystemMetadata
{
Name = d.Name,
@@ -591,16 +598,19 @@ namespace Emby.Server.Implementations.IO
}).ToList();
}
/// <inheritdoc />
public virtual IEnumerable<FileSystemMetadata> GetDirectories(string path, bool recursive = false)
{
return ToMetadata(new DirectoryInfo(path).EnumerateDirectories("*", GetEnumerationOptions(recursive)));
}
/// <inheritdoc />
public virtual IEnumerable<FileSystemMetadata> GetFiles(string path, bool recursive = false)
{
return GetFiles(path, null, false, recursive);
}
/// <inheritdoc />
public virtual IEnumerable<FileSystemMetadata> GetFiles(string path, IReadOnlyList<string>? extensions, bool enableCaseSensitiveExtensions, bool recursive = false)
{
var enumerationOptions = GetEnumerationOptions(recursive);
@@ -631,6 +641,7 @@ namespace Emby.Server.Implementations.IO
return ToMetadata(files);
}
/// <inheritdoc />
public virtual IEnumerable<FileSystemMetadata> GetFileSystemEntries(string path, bool recursive = false)
{
var directoryInfo = new DirectoryInfo(path);
@@ -644,16 +655,19 @@ namespace Emby.Server.Implementations.IO
return infos.Select(GetFileSystemMetadata);
}
/// <inheritdoc />
public virtual IEnumerable<string> GetDirectoryPaths(string path, bool recursive = false)
{
return Directory.EnumerateDirectories(path, "*", GetEnumerationOptions(recursive));
}
/// <inheritdoc />
public virtual IEnumerable<string> GetFilePaths(string path, bool recursive = false)
{
return GetFilePaths(path, null, false, recursive);
}
/// <inheritdoc />
public virtual IEnumerable<string> GetFilePaths(string path, string[]? extensions, bool enableCaseSensitiveExtensions, bool recursive = false)
{
var enumerationOptions = GetEnumerationOptions(recursive);
@@ -684,6 +698,7 @@ namespace Emby.Server.Implementations.IO
return files;
}
/// <inheritdoc />
public virtual IEnumerable<string> GetFileSystemEntryPaths(string path, bool recursive = false)
{
return Directory.EnumerateFileSystemEntries(path, "*", GetEnumerationOptions(recursive));

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

@@ -1,7 +1,8 @@
#pragma warning disable CS1591
namespace Emby.Server.Implementations
{
/// <summary>
/// Specifies the contract for server startup options.
/// </summary>
public interface IStartupOptions
{
/// <summary>
@@ -10,7 +11,7 @@ namespace Emby.Server.Implementations
string? FFmpegPath { get; }
/// <summary>
/// Gets the value of the --service command line option.
/// Gets a value indicating whether to run as service by the --service command line option.
/// </summary>
bool IsService { get; }

View File

@@ -51,7 +51,7 @@ namespace Emby.Server.Implementations.Images
public int Order => 0;
protected virtual bool Supports(BaseItem _) => true;
protected virtual bool Supports(BaseItem item) => true;
public async Task<ItemUpdateType> FetchAsync(T item, MetadataRefreshOptions options, CancellationToken cancellationToken)
{
@@ -65,13 +65,13 @@ namespace Emby.Server.Implementations.Images
if (SupportedImages.Contains(ImageType.Primary))
{
var primaryResult = await FetchAsync(item, ImageType.Primary, options, cancellationToken).ConfigureAwait(false);
updateType = updateType | primaryResult;
updateType |= primaryResult;
}
if (SupportedImages.Contains(ImageType.Thumb))
{
var thumbResult = await FetchAsync(item, ImageType.Thumb, options, cancellationToken).ConfigureAwait(false);
updateType = updateType | thumbResult;
updateType |= thumbResult;
}
return updateType;

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