mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-06-03 05:34:16 -04:00
Merge remote-tracking branch 'upstream/master' into support-running-without-web-content
This commit is contained in:
commit
99bf6edba2
149
CONTRIBUTORS.md
149
CONTRIBUTORS.md
@ -1,41 +1,132 @@
|
|||||||
# Jellyfin Contributors
|
# Jellyfin Contributors
|
||||||
|
|
||||||
- [JoshuaBoniface](https://github.com/joshuaboniface)
|
- [97carmine](https://github.com/97carmine)
|
||||||
- [nvllsvm](https://github.com/nvllsvm)
|
- [Abbe98](https://github.com/Abbe98)
|
||||||
- [JustAMan](https://github.com/JustAMan)
|
- [agrenott](https://github.com/agrenott)
|
||||||
- [dcrdev](https://github.com/dcrdev)
|
- [AndreCarvalho](https://github.com/AndreCarvalho)
|
||||||
- [EraYaN](https://github.com/EraYaN)
|
- [anthonylavado](https://github.com/anthonylavado)
|
||||||
- [flemse](https://github.com/flemse)
|
- [Artiume](https://github.com/Artiume)
|
||||||
|
- [AThomsen](https://github.com/AThomsen)
|
||||||
|
- [bilde2910](https://github.com/bilde2910)
|
||||||
- [bfayers](https://github.com/bfayers)
|
- [bfayers](https://github.com/bfayers)
|
||||||
- [Bond_009](https://github.com/Bond-009)
|
- [BnMcG](https://github.com/BnMcG)
|
||||||
- [AnthonyLavado](https://github.com/anthonylavado)
|
- [Bond-009](https://github.com/Bond-009)
|
||||||
- [sparky8251](https://github.com/sparky8251)
|
- [brianjmurrell](https://github.com/brianjmurrell)
|
||||||
- [LeoVerto](https://github.com/LeoVerto)
|
- [bugfixin](https://github.com/bugfixin)
|
||||||
- [grafixeyehero](https://github.com/grafixeyehero)
|
- [chaosinnovator](https://github.com/chaosinnovator)
|
||||||
|
- [ckcr4lyf](https://github.com/ckcr4lyf)
|
||||||
|
- [crankdoofus](https://github.com/crankdoofus)
|
||||||
|
- [crobibero](https://github.com/crobibero)
|
||||||
|
- [cromefire](https://github.com/cromefire)
|
||||||
|
- [cryptobank](https://github.com/cryptobank)
|
||||||
- [cvium](https://github.com/cvium)
|
- [cvium](https://github.com/cvium)
|
||||||
- [wtayl0r](https://github.com/wtayl0r)
|
- [dannymichel](https://github.com/dannymichel)
|
||||||
- [TtheCreator](https://github.com/Tthecreator)
|
- [DaveChild](https://github.com/DaveChild)
|
||||||
|
- [dcrdev](https://github.com/dcrdev)
|
||||||
|
- [dhartung](https://github.com/dhartung)
|
||||||
|
- [dinki](https://github.com/dinki)
|
||||||
- [dkanada](https://github.com/dkanada)
|
- [dkanada](https://github.com/dkanada)
|
||||||
- [LogicalPhallacy](https://github.com/LogicalPhallacy/)
|
- [dlahoti](https://github.com/dlahoti)
|
||||||
- [RazeLighter777](https://github.com/RazeLighter777)
|
- [dmitrylyzo](https://github.com/dmitrylyzo)
|
||||||
- [WillWill56](https://github.com/WillWill56)
|
- [DMouse10462](https://github.com/DMouse10462)
|
||||||
- [Liggy](https://github.com/Liggy)
|
- [DrPandemic](https://github.com/DrPandemic)
|
||||||
- [fruhnow](https://github.com/fruhnow)
|
- [EraYaN](https://github.com/EraYaN)
|
||||||
- [Lynxy](https://github.com/Lynxy)
|
- [escabe](https://github.com/escabe)
|
||||||
|
- [excelite](https://github.com/excelite)
|
||||||
- [fasheng](https://github.com/fasheng)
|
- [fasheng](https://github.com/fasheng)
|
||||||
- [ploughpuff](https://github.com/ploughpuff)
|
- [ferferga](https://github.com/ferferga)
|
||||||
- [pjeanjean](https://github.com/pjeanjean)
|
|
||||||
- [DrPandemic](https://github.com/drpandemic)
|
|
||||||
- [joern-h](https://github.com/joern-h)
|
|
||||||
- [Khinenw](https://github.com/HelloWorld017)
|
|
||||||
- [fhriley](https://github.com/fhriley)
|
- [fhriley](https://github.com/fhriley)
|
||||||
- [nevado](https://github.com/nevado)
|
- [flemse](https://github.com/flemse)
|
||||||
- [mark-monteiro](https://github.com/mark-monteiro)
|
- [Froghut](https://github.com/Froghut)
|
||||||
- [ullmie02](https://github.com/ullmie02)
|
- [fruhnow](https://github.com/fruhnow)
|
||||||
- [geilername](https://github.com/geilername)
|
- [geilername](https://github.com/geilername)
|
||||||
|
- [gnattu](https://github.com/gnattu)
|
||||||
|
- [grafixeyehero](https://github.com/grafixeyehero)
|
||||||
|
- [h1nk](https://github.com/h1nk)
|
||||||
|
- [hawken93](https://github.com/hawken93)
|
||||||
|
- [HelloWorld017](https://github.com/HelloWorld017)
|
||||||
|
- [jftuga](https://github.com/jftuga)
|
||||||
|
- [joern-h](https://github.com/joern-h)
|
||||||
|
- [joshuaboniface](https://github.com/joshuaboniface)
|
||||||
|
- [JustAMan](https://github.com/JustAMan)
|
||||||
|
- [justinfenn](https://github.com/justinfenn)
|
||||||
|
- [KerryRJ](https://github.com/KerryRJ)
|
||||||
|
- [Larvitar](https://github.com/Larvitar)
|
||||||
|
- [LeoVerto](https://github.com/LeoVerto)
|
||||||
|
- [Liggy](https://github.com/Liggy)
|
||||||
|
- [LogicalPhallacy](https://github.com/LogicalPhallacy)
|
||||||
|
- [loli10K](https://github.com/loli10K)
|
||||||
|
- [lostmypillow](https://github.com/lostmypillow)
|
||||||
|
- [Lynxy](https://github.com/Lynxy)
|
||||||
|
- [ManfredRichthofen](https://github.com/ManfredRichthofen)
|
||||||
|
- [Marenz](https://github.com/Marenz)
|
||||||
|
- [marius-luca-87](https://github.com/marius-luca-87)
|
||||||
|
- [mark-monteiro](https://github.com/mark-monteiro)
|
||||||
|
- [Matt07211](https://github.com/Matt07211)
|
||||||
|
- [mcarlton00](https://github.com/mcarlton00)
|
||||||
|
- [mitchfizz05](https://github.com/mitchfizz05)
|
||||||
|
- [MrTimscampi](https://github.com/MrTimscampi)
|
||||||
|
- [n8225](https://github.com/n8225)
|
||||||
|
- [Narfinger](https://github.com/Narfinger)
|
||||||
|
- [NathanPickard](https://github.com/NathanPickard)
|
||||||
|
- [neilsb](https://github.com/neilsb)
|
||||||
|
- [nevado](https://github.com/nevado)
|
||||||
|
- [Nickbert7](https://github.com/Nickbert7)
|
||||||
|
- [nvllsvm](https://github.com/nvllsvm)
|
||||||
|
- [nyanmisaka](https://github.com/nyanmisaka)
|
||||||
|
- [oddstr13](https://github.com/oddstr13)
|
||||||
|
- [petermcneil](https://github.com/petermcneil)
|
||||||
|
- [Phlogi](https://github.com/Phlogi)
|
||||||
|
- [pjeanjean](https://github.com/pjeanjean)
|
||||||
|
- [ploughpuff](https://github.com/ploughpuff)
|
||||||
- [pR0Ps](https://github.com/pR0Ps)
|
- [pR0Ps](https://github.com/pR0Ps)
|
||||||
- [artiume](https://github.com/Artiume)
|
- [PrplHaz4](https://github.com/PrplHaz4)
|
||||||
|
- [RazeLighter777](https://github.com/RazeLighter777)
|
||||||
|
- [redSpoutnik](https://github.com/redSpoutnik)
|
||||||
|
- [ringmatter](https://github.com/ringmatter)
|
||||||
|
- [ryan-hartzell](https://github.com/ryan-hartzell)
|
||||||
|
- [s0urcelab](https://github.com/s0urcelab)
|
||||||
|
- [sachk](https://github.com/sachk)
|
||||||
|
- [sammyrc34](https://github.com/sammyrc34)
|
||||||
|
- [samuel9554](https://github.com/samuel9554)
|
||||||
|
- [scheidleon](https://github.com/scheidleon)
|
||||||
|
- [sebPomme](https://github.com/sebPomme)
|
||||||
|
- [SenorSmartyPants](https://github.com/SenorSmartyPants)
|
||||||
|
- [shemanaev](https://github.com/shemanaev)
|
||||||
|
- [skaro13](https://github.com/skaro13)
|
||||||
|
- [sl1288](https://github.com/sl1288)
|
||||||
|
- [sorinyo2004](https://github.com/sorinyo2004)
|
||||||
|
- [sparky8251](https://github.com/sparky8251)
|
||||||
|
- [stanionascu](https://github.com/stanionascu)
|
||||||
|
- [stevehayles](https://github.com/stevehayles)
|
||||||
|
- [SuperSandro2000](https://github.com/SuperSandro2000)
|
||||||
|
- [tbraeutigam](https://github.com/tbraeutigam)
|
||||||
|
- [teacupx](https://github.com/teacupx)
|
||||||
|
- [Terror-Gene](https://github.com/Terror-Gene)
|
||||||
|
- [ThatNerdyPikachu](https://github.com/ThatNerdyPikachu)
|
||||||
|
- [ThibaultNocchi](https://github.com/ThibaultNocchi)
|
||||||
|
- [thornbill](https://github.com/thornbill)
|
||||||
|
- [ThreeFive-O](https://github.com/ThreeFive-O)
|
||||||
|
- [TrisMcC](https://github.com/TrisMcC)
|
||||||
|
- [trumblejoe](https://github.com/trumblejoe)
|
||||||
|
- [TtheCreator](https://github.com/TtheCreator)
|
||||||
|
- [twinkybot](https://github.com/twinkybot)
|
||||||
|
- [Ullmie02](https://github.com/Ullmie02)
|
||||||
|
- [Unhelpful](https://github.com/Unhelpful)
|
||||||
|
- [viaregio](https://github.com/viaregio)
|
||||||
|
- [vitorsemeano](https://github.com/vitorsemeano)
|
||||||
|
- [voodoos](https://github.com/voodoos)
|
||||||
|
- [whooo](https://github.com/whooo)
|
||||||
|
- [WiiPlayer2](https://github.com/WiiPlayer2)
|
||||||
|
- [WillWill56](https://github.com/WillWill56)
|
||||||
|
- [wtayl0r](https://github.com/wtayl0r)
|
||||||
|
- [Wuerfelbecher](https://github.com/Wuerfelbecher)
|
||||||
|
- [Wunax](https://github.com/Wunax)
|
||||||
|
- [WWWesten](https://github.com/WWWesten)
|
||||||
|
- [WX9yMOXWId](https://github.com/WX9yMOXWId)
|
||||||
|
- [xosdy](https://github.com/xosdy)
|
||||||
|
- [XVicarious](https://github.com/XVicarious)
|
||||||
|
- [YouKnowBlom](https://github.com/YouKnowBlom)
|
||||||
|
|
||||||
# Emby Contributors
|
# Emby Contributors
|
||||||
|
|
||||||
|
20
Dockerfile
20
Dockerfile
@ -21,6 +21,13 @@ RUN dotnet publish Jellyfin.Server --disable-parallel --configuration Release --
|
|||||||
FROM jellyfin/ffmpeg:${FFMPEG_VERSION} as ffmpeg
|
FROM jellyfin/ffmpeg:${FFMPEG_VERSION} as ffmpeg
|
||||||
FROM debian:buster-slim
|
FROM debian:buster-slim
|
||||||
|
|
||||||
|
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
|
||||||
|
ARG DEBIAN_FRONTEND="noninteractive"
|
||||||
|
# http://stackoverflow.com/questions/48162574/ddg#49462622
|
||||||
|
ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn
|
||||||
|
# https://github.com/NVIDIA/nvidia-docker/wiki/Installation-(Native-GPU-Support)
|
||||||
|
ENV NVIDIA_DRIVER_CAPABILITIES="compute,video,utility"
|
||||||
|
|
||||||
COPY --from=ffmpeg /opt/ffmpeg /opt/ffmpeg
|
COPY --from=ffmpeg /opt/ffmpeg /opt/ffmpeg
|
||||||
COPY --from=builder /jellyfin /jellyfin
|
COPY --from=builder /jellyfin /jellyfin
|
||||||
COPY --from=web-builder /dist /jellyfin/jellyfin-web
|
COPY --from=web-builder /dist /jellyfin/jellyfin-web
|
||||||
@ -31,9 +38,16 @@ COPY --from=web-builder /dist /jellyfin/jellyfin-web
|
|||||||
# mesa-va-drivers: needed for VAAPI
|
# mesa-va-drivers: needed for VAAPI
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install --no-install-recommends --no-install-suggests -y \
|
&& apt-get install --no-install-recommends --no-install-suggests -y \
|
||||||
libfontconfig1 libgomp1 libva-drm2 mesa-va-drivers openssl ca-certificates \
|
libfontconfig1 \
|
||||||
&& apt-get clean autoclean \
|
libgomp1 \
|
||||||
&& apt-get autoremove \
|
libva-drm2 \
|
||||||
|
mesa-va-drivers \
|
||||||
|
openssl \
|
||||||
|
ca-certificates \
|
||||||
|
vainfo \
|
||||||
|
i965-va-driver \
|
||||||
|
&& apt-get clean autoclean -y\
|
||||||
|
&& apt-get autoremove -y\
|
||||||
&& rm -rf /var/lib/apt/lists/* \
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
&& mkdir -p /cache /config /media \
|
&& mkdir -p /cache /config /media \
|
||||||
&& chmod 777 /cache /config /media \
|
&& chmod 777 /cache /config /media \
|
||||||
|
@ -27,10 +27,35 @@ RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin"
|
|||||||
|
|
||||||
FROM multiarch/qemu-user-static:x86_64-arm as qemu
|
FROM multiarch/qemu-user-static:x86_64-arm as qemu
|
||||||
FROM arm32v7/debian:buster-slim
|
FROM arm32v7/debian:buster-slim
|
||||||
|
|
||||||
|
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
|
||||||
|
ARG DEBIAN_FRONTEND="noninteractive"
|
||||||
|
# http://stackoverflow.com/questions/48162574/ddg#49462622
|
||||||
|
ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn
|
||||||
|
# https://github.com/NVIDIA/nvidia-docker/wiki/Installation-(Native-GPU-Support)
|
||||||
|
ENV NVIDIA_DRIVER_CAPABILITIES="compute,video,utility"
|
||||||
|
|
||||||
COPY --from=qemu /usr/bin/qemu-arm-static /usr/bin
|
COPY --from=qemu /usr/bin/qemu-arm-static /usr/bin
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install --no-install-recommends --no-install-suggests -y ffmpeg \
|
&& apt-get install --no-install-recommends --no-install-suggests -y ca-certificates gnupg curl && \
|
||||||
libssl-dev ca-certificates \
|
curl -ks https://repo.jellyfin.org/debian/jellyfin_team.gpg.key | apt-key add - && \
|
||||||
|
curl -s https://keyserver.ubuntu.com/pks/lookup?op=get\&search=0x6587ffd6536b8826e88a62547876ae518cbcf2f2 | apt-key add - && \
|
||||||
|
echo 'deb [arch=armhf] https://repo.jellyfin.org/debian buster main' > /etc/apt/sources.list.d/jellyfin.list && \
|
||||||
|
echo "deb http://ppa.launchpad.net/ubuntu-raspi2/ppa/ubuntu bionic main">> /etc/apt/sources.list.d/raspbins.list && \
|
||||||
|
apt-get update && \
|
||||||
|
apt-get install --no-install-recommends --no-install-suggests -y \
|
||||||
|
jellyfin-ffmpeg \
|
||||||
|
libssl-dev \
|
||||||
|
libfontconfig1 \
|
||||||
|
libfreetype6 \
|
||||||
|
libomxil-bellagio0 \
|
||||||
|
libomxil-bellagio-bin \
|
||||||
|
libraspberrypi0 \
|
||||||
|
vainfo \
|
||||||
|
libva2 \
|
||||||
|
&& apt-get remove curl gnupg -y \
|
||||||
|
&& apt-get clean autoclean -y \
|
||||||
|
&& apt-get autoremove -y \
|
||||||
&& rm -rf /var/lib/apt/lists/* \
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
&& mkdir -p /cache /config /media \
|
&& mkdir -p /cache /config /media \
|
||||||
&& chmod 777 /cache /config /media
|
&& chmod 777 /cache /config /media
|
||||||
@ -44,4 +69,4 @@ VOLUME /cache /config /media
|
|||||||
ENTRYPOINT ["./jellyfin/jellyfin", \
|
ENTRYPOINT ["./jellyfin/jellyfin", \
|
||||||
"--datadir", "/config", \
|
"--datadir", "/config", \
|
||||||
"--cachedir", "/cache", \
|
"--cachedir", "/cache", \
|
||||||
"--ffmpeg", "/usr/bin/ffmpeg"]
|
"--ffmpeg", "/usr/lib/jellyfin-ffmpeg"]
|
||||||
|
@ -26,10 +26,25 @@ RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin"
|
|||||||
|
|
||||||
FROM multiarch/qemu-user-static:x86_64-aarch64 as qemu
|
FROM multiarch/qemu-user-static:x86_64-aarch64 as qemu
|
||||||
FROM arm64v8/debian:buster-slim
|
FROM arm64v8/debian:buster-slim
|
||||||
|
|
||||||
|
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
|
||||||
|
ARG DEBIAN_FRONTEND="noninteractive"
|
||||||
|
# http://stackoverflow.com/questions/48162574/ddg#49462622
|
||||||
|
ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn
|
||||||
|
# https://github.com/NVIDIA/nvidia-docker/wiki/Installation-(Native-GPU-Support)
|
||||||
|
ENV NVIDIA_DRIVER_CAPABILITIES="compute,video,utility"
|
||||||
|
|
||||||
COPY --from=qemu /usr/bin/qemu-aarch64-static /usr/bin
|
COPY --from=qemu /usr/bin/qemu-aarch64-static /usr/bin
|
||||||
RUN apt-get update \
|
RUN apt-get update && apt-get install --no-install-recommends --no-install-suggests -y \
|
||||||
&& apt-get install --no-install-recommends --no-install-suggests -y ffmpeg \
|
ffmpeg \
|
||||||
libssl-dev ca-certificates \
|
libssl-dev \
|
||||||
|
ca-certificates \
|
||||||
|
libfontconfig1 \
|
||||||
|
libfreetype6 \
|
||||||
|
libomxil-bellagio0 \
|
||||||
|
libomxil-bellagio-bin \
|
||||||
|
&& apt-get clean autoclean -y \
|
||||||
|
&& apt-get autoremove -y \
|
||||||
&& rm -rf /var/lib/apt/lists/* \
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
&& mkdir -p /cache /config /media \
|
&& mkdir -p /cache /config /media \
|
||||||
&& chmod 777 /cache /config /media
|
&& chmod 777 /cache /config /media
|
||||||
|
@ -16,7 +16,11 @@ namespace Emby.Dlna.ConnectionManager
|
|||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
|
|
||||||
public ConnectionManager(IDlnaManager dlna, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient)
|
public ConnectionManager(
|
||||||
|
IDlnaManager dlna,
|
||||||
|
IServerConfigurationManager config,
|
||||||
|
ILogger<ConnectionManager> logger,
|
||||||
|
IHttpClient httpClient)
|
||||||
: base(logger, httpClient)
|
: base(logger, httpClient)
|
||||||
{
|
{
|
||||||
_dlna = dlna;
|
_dlna = dlna;
|
||||||
|
@ -38,7 +38,7 @@ namespace Emby.Dlna.ContentDirectory
|
|||||||
ILibraryManager libraryManager,
|
ILibraryManager libraryManager,
|
||||||
IServerConfigurationManager config,
|
IServerConfigurationManager config,
|
||||||
IUserManager userManager,
|
IUserManager userManager,
|
||||||
ILogger logger,
|
ILogger<ContentDirectory> logger,
|
||||||
IHttpClient httpClient,
|
IHttpClient httpClient,
|
||||||
ILocalizationManager localization,
|
ILocalizationManager localization,
|
||||||
IMediaSourceManager mediaSourceManager,
|
IMediaSourceManager mediaSourceManager,
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
#pragma warning disable SA1600
|
#pragma warning disable SA1600
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Net.Sockets;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Emby.Dlna.PlayTo;
|
using Emby.Dlna.PlayTo;
|
||||||
@ -27,7 +27,7 @@ using MediaBrowser.Model.System;
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Rssdp;
|
using Rssdp;
|
||||||
using Rssdp.Infrastructure;
|
using Rssdp.Infrastructure;
|
||||||
using OperatingSystem = MediaBrowser.Common.System.OperatingSystem;
|
using OperatingSystem = MediaBrowser.Common.System.OperatingSystem;
|
||||||
|
|
||||||
namespace Emby.Dlna.Main
|
namespace Emby.Dlna.Main
|
||||||
{
|
{
|
||||||
@ -59,7 +59,9 @@ namespace Emby.Dlna.Main
|
|||||||
private ISsdpCommunicationsServer _communicationsServer;
|
private ISsdpCommunicationsServer _communicationsServer;
|
||||||
|
|
||||||
internal IContentDirectory ContentDirectory { get; private set; }
|
internal IContentDirectory ContentDirectory { get; private set; }
|
||||||
|
|
||||||
internal IConnectionManager ConnectionManager { get; private set; }
|
internal IConnectionManager ConnectionManager { get; private set; }
|
||||||
|
|
||||||
internal IMediaReceiverRegistrar MediaReceiverRegistrar { get; private set; }
|
internal IMediaReceiverRegistrar MediaReceiverRegistrar { get; private set; }
|
||||||
|
|
||||||
public static DlnaEntryPoint Current;
|
public static DlnaEntryPoint Current;
|
||||||
@ -107,7 +109,7 @@ namespace Emby.Dlna.Main
|
|||||||
libraryManager,
|
libraryManager,
|
||||||
config,
|
config,
|
||||||
userManager,
|
userManager,
|
||||||
_logger,
|
loggerFactory.CreateLogger<ContentDirectory.ContentDirectory>(),
|
||||||
httpClient,
|
httpClient,
|
||||||
localizationManager,
|
localizationManager,
|
||||||
mediaSourceManager,
|
mediaSourceManager,
|
||||||
@ -115,9 +117,16 @@ namespace Emby.Dlna.Main
|
|||||||
mediaEncoder,
|
mediaEncoder,
|
||||||
tvSeriesManager);
|
tvSeriesManager);
|
||||||
|
|
||||||
ConnectionManager = new ConnectionManager.ConnectionManager(dlnaManager, config, _logger, httpClient);
|
ConnectionManager = new ConnectionManager.ConnectionManager(
|
||||||
|
dlnaManager,
|
||||||
|
config,
|
||||||
|
loggerFactory.CreateLogger<ConnectionManager.ConnectionManager>(),
|
||||||
|
httpClient);
|
||||||
|
|
||||||
MediaReceiverRegistrar = new MediaReceiverRegistrar.MediaReceiverRegistrar(_logger, httpClient, config);
|
MediaReceiverRegistrar = new MediaReceiverRegistrar.MediaReceiverRegistrar(
|
||||||
|
loggerFactory.CreateLogger<MediaReceiverRegistrar.MediaReceiverRegistrar>(),
|
||||||
|
httpClient,
|
||||||
|
config);
|
||||||
Current = this;
|
Current = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,10 @@ namespace Emby.Dlna.MediaReceiverRegistrar
|
|||||||
{
|
{
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
|
|
||||||
public MediaReceiverRegistrar(ILogger logger, IHttpClient httpClient, IServerConfigurationManager config)
|
public MediaReceiverRegistrar(
|
||||||
|
ILogger<MediaReceiverRegistrar> logger,
|
||||||
|
IHttpClient httpClient,
|
||||||
|
IServerConfigurationManager config)
|
||||||
: base(logger, httpClient)
|
: base(logger, httpClient)
|
||||||
{
|
{
|
||||||
_config = config;
|
_config = config;
|
||||||
|
@ -13,7 +13,7 @@ namespace Emby.Dlna.Service
|
|||||||
protected IHttpClient HttpClient;
|
protected IHttpClient HttpClient;
|
||||||
protected ILogger Logger;
|
protected ILogger Logger;
|
||||||
|
|
||||||
protected BaseService(ILogger logger, IHttpClient httpClient)
|
protected BaseService(ILogger<BaseService> logger, IHttpClient httpClient)
|
||||||
{
|
{
|
||||||
Logger = logger;
|
Logger = logger;
|
||||||
HttpClient = httpClient;
|
HttpClient = httpClient;
|
||||||
|
@ -119,7 +119,6 @@ namespace Emby.Server.Implementations
|
|||||||
public abstract class ApplicationHost : IServerApplicationHost, IDisposable
|
public abstract class ApplicationHost : IServerApplicationHost, IDisposable
|
||||||
{
|
{
|
||||||
private SqliteUserRepository _userRepository;
|
private SqliteUserRepository _userRepository;
|
||||||
|
|
||||||
private SqliteDisplayPreferencesRepository _displayPreferencesRepository;
|
private SqliteDisplayPreferencesRepository _displayPreferencesRepository;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -167,10 +166,9 @@ namespace Emby.Server.Implementations
|
|||||||
public bool IsShuttingDown { get; private set; }
|
public bool IsShuttingDown { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the logger.
|
/// Gets the logger.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The logger.</value>
|
protected ILogger Logger { get; }
|
||||||
protected ILogger Logger { get; set; }
|
|
||||||
|
|
||||||
private IPlugin[] _plugins;
|
private IPlugin[] _plugins;
|
||||||
|
|
||||||
@ -181,10 +179,9 @@ namespace Emby.Server.Implementations
|
|||||||
public IReadOnlyList<IPlugin> Plugins => _plugins;
|
public IReadOnlyList<IPlugin> Plugins => _plugins;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the logger factory.
|
/// Gets the logger factory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The logger factory.</value>
|
protected ILoggerFactory LoggerFactory { get; }
|
||||||
public ILoggerFactory LoggerFactory { get; protected set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the application paths.
|
/// Gets or sets the application paths.
|
||||||
@ -328,8 +325,6 @@ namespace Emby.Server.Implementations
|
|||||||
|
|
||||||
private IMediaSourceManager MediaSourceManager { get; set; }
|
private IMediaSourceManager MediaSourceManager { get; set; }
|
||||||
|
|
||||||
private readonly IConfiguration _configuration;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the installation manager.
|
/// Gets the installation manager.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -367,11 +362,8 @@ namespace Emby.Server.Implementations
|
|||||||
IStartupOptions options,
|
IStartupOptions options,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
IImageEncoder imageEncoder,
|
IImageEncoder imageEncoder,
|
||||||
INetworkManager networkManager,
|
INetworkManager networkManager)
|
||||||
IConfiguration configuration)
|
|
||||||
{
|
{
|
||||||
_configuration = configuration;
|
|
||||||
|
|
||||||
XmlSerializer = new MyXmlSerializer();
|
XmlSerializer = new MyXmlSerializer();
|
||||||
|
|
||||||
NetworkManager = networkManager;
|
NetworkManager = networkManager;
|
||||||
@ -587,7 +579,8 @@ namespace Emby.Server.Implementations
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task InitAsync(IServiceCollection serviceCollection)
|
/// <inheritdoc/>
|
||||||
|
public async Task InitAsync(IServiceCollection serviceCollection, IConfiguration startupConfig)
|
||||||
{
|
{
|
||||||
HttpPort = ServerConfigurationManager.Configuration.HttpServerPortNumber;
|
HttpPort = ServerConfigurationManager.Configuration.HttpServerPortNumber;
|
||||||
HttpsPort = ServerConfigurationManager.Configuration.HttpsPortNumber;
|
HttpsPort = ServerConfigurationManager.Configuration.HttpsPortNumber;
|
||||||
@ -620,7 +613,7 @@ namespace Emby.Server.Implementations
|
|||||||
|
|
||||||
DiscoverTypes();
|
DiscoverTypes();
|
||||||
|
|
||||||
await RegisterResources(serviceCollection).ConfigureAwait(false);
|
await RegisterResources(serviceCollection, startupConfig).ConfigureAwait(false);
|
||||||
|
|
||||||
ContentRoot = ServerConfigurationManager.Configuration.DashboardSourcePath;
|
ContentRoot = ServerConfigurationManager.Configuration.DashboardSourcePath;
|
||||||
if (string.IsNullOrEmpty(ContentRoot))
|
if (string.IsNullOrEmpty(ContentRoot))
|
||||||
@ -652,14 +645,14 @@ namespace Emby.Server.Implementations
|
|||||||
var response = context.Response;
|
var response = context.Response;
|
||||||
var localPath = context.Request.Path.ToString();
|
var localPath = context.Request.Path.ToString();
|
||||||
|
|
||||||
var req = new WebSocketSharpRequest(request, response, request.Path, Logger);
|
var req = new WebSocketSharpRequest(request, response, request.Path, LoggerFactory.CreateLogger<WebSocketSharpRequest>());
|
||||||
await HttpServer.RequestHandler(req, request.GetDisplayUrl(), request.Host.ToString(), localPath, context.RequestAborted).ConfigureAwait(false);
|
await HttpServer.RequestHandler(req, request.GetDisplayUrl(), request.Host.ToString(), localPath, context.RequestAborted).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Registers resources that classes will depend on
|
/// Registers resources that classes will depend on
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected async Task RegisterResources(IServiceCollection serviceCollection)
|
protected async Task RegisterResources(IServiceCollection serviceCollection, IConfiguration startupConfig)
|
||||||
{
|
{
|
||||||
serviceCollection.AddMemoryCache();
|
serviceCollection.AddMemoryCache();
|
||||||
|
|
||||||
@ -668,13 +661,10 @@ namespace Emby.Server.Implementations
|
|||||||
|
|
||||||
serviceCollection.AddSingleton<IApplicationPaths>(ApplicationPaths);
|
serviceCollection.AddSingleton<IApplicationPaths>(ApplicationPaths);
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IConfiguration>(_configuration);
|
|
||||||
|
|
||||||
serviceCollection.AddSingleton(JsonSerializer);
|
serviceCollection.AddSingleton(JsonSerializer);
|
||||||
|
|
||||||
serviceCollection.AddSingleton(LoggerFactory);
|
// TODO: Support for injecting ILogger should be deprecated in favour of ILogger<T> and this removed
|
||||||
serviceCollection.AddLogging();
|
serviceCollection.AddSingleton<ILogger>(Logger);
|
||||||
serviceCollection.AddSingleton(Logger);
|
|
||||||
|
|
||||||
serviceCollection.AddSingleton(FileSystemManager);
|
serviceCollection.AddSingleton(FileSystemManager);
|
||||||
serviceCollection.AddSingleton<TvDbClientManager>();
|
serviceCollection.AddSingleton<TvDbClientManager>();
|
||||||
@ -762,7 +752,7 @@ namespace Emby.Server.Implementations
|
|||||||
ProcessFactory,
|
ProcessFactory,
|
||||||
LocalizationManager,
|
LocalizationManager,
|
||||||
() => SubtitleEncoder,
|
() => SubtitleEncoder,
|
||||||
_configuration,
|
startupConfig,
|
||||||
StartupOptions.FFmpegPath);
|
StartupOptions.FFmpegPath);
|
||||||
serviceCollection.AddSingleton(MediaEncoder);
|
serviceCollection.AddSingleton(MediaEncoder);
|
||||||
|
|
||||||
@ -784,7 +774,7 @@ namespace Emby.Server.Implementations
|
|||||||
this,
|
this,
|
||||||
LoggerFactory.CreateLogger<HttpListenerHost>(),
|
LoggerFactory.CreateLogger<HttpListenerHost>(),
|
||||||
ServerConfigurationManager,
|
ServerConfigurationManager,
|
||||||
_configuration,
|
startupConfig,
|
||||||
NetworkManager,
|
NetworkManager,
|
||||||
JsonSerializer,
|
JsonSerializer,
|
||||||
XmlSerializer,
|
XmlSerializer,
|
||||||
@ -1206,7 +1196,7 @@ namespace Emby.Server.Implementations
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IHttpListener CreateHttpListener() => new WebSocketSharpListener(Logger);
|
protected IHttpListener CreateHttpListener() => new WebSocketSharpListener(LoggerFactory.CreateLogger<WebSocketSharpListener>());
|
||||||
|
|
||||||
private CertificateInfo GetCertificateInfo(bool generateCertificate)
|
private CertificateInfo GetCertificateInfo(bool generateCertificate)
|
||||||
{
|
{
|
||||||
|
@ -20,7 +20,11 @@ namespace Emby.Server.Implementations.Channels
|
|||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
|
||||||
public RefreshChannelsScheduledTask(IChannelManager channelManager, IUserManager userManager, ILogger logger, ILibraryManager libraryManager)
|
public RefreshChannelsScheduledTask(
|
||||||
|
IChannelManager channelManager,
|
||||||
|
IUserManager userManager,
|
||||||
|
ILogger<RefreshChannelsScheduledTask> logger,
|
||||||
|
ILibraryManager libraryManager)
|
||||||
{
|
{
|
||||||
_channelManager = channelManager;
|
_channelManager = channelManager;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
|
@ -348,7 +348,10 @@ namespace Emby.Server.Implementations.Collections
|
|||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
public CollectionManagerEntryPoint(ICollectionManager collectionManager, IServerConfigurationManager config, ILogger logger)
|
public CollectionManagerEntryPoint(
|
||||||
|
ICollectionManager collectionManager,
|
||||||
|
IServerConfigurationManager config,
|
||||||
|
ILogger<CollectionManagerEntryPoint> logger)
|
||||||
{
|
{
|
||||||
_collectionManager = (CollectionManager)collectionManager;
|
_collectionManager = (CollectionManager)collectionManager;
|
||||||
_config = config;
|
_config = config;
|
||||||
|
@ -17,7 +17,6 @@ namespace Emby.Server.Implementations
|
|||||||
{
|
{
|
||||||
{ NoWebContentKey, bool.FalseString },
|
{ NoWebContentKey, bool.FalseString },
|
||||||
{ HttpListenerHost.DefaultRedirectKey, "web/index.html" },
|
{ HttpListenerHost.DefaultRedirectKey, "web/index.html" },
|
||||||
{ MusicBrainzAlbumProvider.BaseUrlKey, "https://www.musicbrainz.org" },
|
|
||||||
{ FfmpegProbeSizeKey, "1G" },
|
{ FfmpegProbeSizeKey, "1G" },
|
||||||
{ FfmpegAnalyzeDurationKey, "200M" }
|
{ FfmpegAnalyzeDurationKey, "200M" }
|
||||||
};
|
};
|
||||||
|
@ -15,7 +15,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
public CleanDatabaseScheduledTask(ILibraryManager libraryManager, ILogger logger)
|
public CleanDatabaseScheduledTask(ILibraryManager libraryManager, ILogger<CleanDatabaseScheduledTask> logger)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
@ -407,7 +407,10 @@ namespace Emby.Server.Implementations.Devices
|
|||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private ILogger _logger;
|
private ILogger _logger;
|
||||||
|
|
||||||
public DeviceManagerEntryPoint(IDeviceManager deviceManager, IServerConfigurationManager config, ILogger logger)
|
public DeviceManagerEntryPoint(
|
||||||
|
IDeviceManager deviceManager,
|
||||||
|
IServerConfigurationManager config,
|
||||||
|
ILogger<DeviceManagerEntryPoint> logger)
|
||||||
{
|
{
|
||||||
_deviceManager = (DeviceManager)deviceManager;
|
_deviceManager = (DeviceManager)deviceManager;
|
||||||
_config = config;
|
_config = config;
|
||||||
|
@ -56,7 +56,12 @@ namespace Emby.Server.Implementations.EntryPoints
|
|||||||
|
|
||||||
private readonly IProviderManager _providerManager;
|
private readonly IProviderManager _providerManager;
|
||||||
|
|
||||||
public LibraryChangedNotifier(ILibraryManager libraryManager, ISessionManager sessionManager, IUserManager userManager, ILogger logger, IProviderManager providerManager)
|
public LibraryChangedNotifier(
|
||||||
|
ILibraryManager libraryManager,
|
||||||
|
ISessionManager sessionManager,
|
||||||
|
IUserManager userManager,
|
||||||
|
ILogger<LibraryChangedNotifier> logger,
|
||||||
|
IProviderManager providerManager)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_sessionManager = sessionManager;
|
_sessionManager = sessionManager;
|
||||||
|
@ -20,7 +20,11 @@ namespace Emby.Server.Implementations.EntryPoints
|
|||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
public RecordingNotifier(ISessionManager sessionManager, IUserManager userManager, ILogger logger, ILiveTvManager liveTvManager)
|
public RecordingNotifier(
|
||||||
|
ISessionManager sessionManager,
|
||||||
|
IUserManager userManager,
|
||||||
|
ILogger<RecordingNotifier> logger,
|
||||||
|
ILiveTvManager liveTvManager)
|
||||||
{
|
{
|
||||||
_sessionManager = sessionManager;
|
_sessionManager = sessionManager;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
|
@ -944,7 +944,6 @@ namespace Emby.Server.Implementations.Library
|
|||||||
IncludeItemTypes = new[] { typeof(T).Name },
|
IncludeItemTypes = new[] { typeof(T).Name },
|
||||||
Name = name,
|
Name = name,
|
||||||
DtoOptions = options
|
DtoOptions = options
|
||||||
|
|
||||||
}).Cast<MusicArtist>()
|
}).Cast<MusicArtist>()
|
||||||
.OrderBy(i => i.IsAccessedByName ? 1 : 0)
|
.OrderBy(i => i.IsAccessedByName ? 1 : 0)
|
||||||
.Cast<T>()
|
.Cast<T>()
|
||||||
@ -1080,7 +1079,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
|
|
||||||
var innerProgress = new ActionableProgress<double>();
|
var innerProgress = new ActionableProgress<double>();
|
||||||
|
|
||||||
innerProgress.RegisterAction(pct => progress.Report(pct * pct * 0.96));
|
innerProgress.RegisterAction(pct => progress.Report(pct * 0.96));
|
||||||
|
|
||||||
// Validate the entire media library
|
// Validate the entire media library
|
||||||
await RootFolder.ValidateChildren(innerProgress, cancellationToken, new MetadataRefreshOptions(new DirectoryService(_fileSystem)), recursive: true).ConfigureAwait(false);
|
await RootFolder.ValidateChildren(innerProgress, cancellationToken, new MetadataRefreshOptions(new DirectoryService(_fileSystem)), recursive: true).ConfigureAwait(false);
|
||||||
|
@ -27,7 +27,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
|
|||||||
/// <param name="fileSystem">The file system.</param>
|
/// <param name="fileSystem">The file system.</param>
|
||||||
/// <param name="libraryManager">The library manager.</param>
|
/// <param name="libraryManager">The library manager.</param>
|
||||||
/// <param name="config">The configuration manager.</param>
|
/// <param name="config">The configuration manager.</param>
|
||||||
public MusicArtistResolver(ILogger logger, IFileSystem fileSystem, ILibraryManager libraryManager, IServerConfigurationManager config)
|
public MusicArtistResolver(
|
||||||
|
ILogger<MusicArtistResolver> logger,
|
||||||
|
IFileSystem fileSystem,
|
||||||
|
ILibraryManager libraryManager,
|
||||||
|
IServerConfigurationManager config)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
|
@ -1,43 +1,35 @@
|
|||||||
#pragma warning disable CS1591
|
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Playlists;
|
using MediaBrowser.Controller.Playlists;
|
||||||
|
using MediaBrowser.Controller.Resolvers;
|
||||||
|
using MediaBrowser.LocalMetadata.Savers;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.Library.Resolvers
|
namespace Emby.Server.Implementations.Library.Resolvers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="IItemResolver"/> for <see cref="Playlist"/> library items.
|
||||||
|
/// </summary>
|
||||||
public class PlaylistResolver : FolderResolver<Playlist>
|
public class PlaylistResolver : FolderResolver<Playlist>
|
||||||
{
|
{
|
||||||
private string[] SupportedCollectionTypes = new string[] {
|
private string[] _musicPlaylistCollectionTypes = new string[] {
|
||||||
|
|
||||||
string.Empty,
|
string.Empty,
|
||||||
CollectionType.Music
|
CollectionType.Music
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc/>
|
||||||
/// Resolves the specified args.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="args">The args.</param>
|
|
||||||
/// <returns>BoxSet.</returns>
|
|
||||||
protected override Playlist Resolve(ItemResolveArgs args)
|
protected override Playlist Resolve(ItemResolveArgs args)
|
||||||
{
|
{
|
||||||
// It's a boxset if all of the following conditions are met:
|
|
||||||
// Is a Directory
|
|
||||||
// Contains [playlist] in the path
|
|
||||||
if (args.IsDirectory)
|
if (args.IsDirectory)
|
||||||
{
|
{
|
||||||
var filename = Path.GetFileName(args.Path);
|
// It's a boxset if the path is a directory with [playlist] in it's the name
|
||||||
|
// TODO: Should this use Path.GetDirectoryName() instead?
|
||||||
if (string.IsNullOrEmpty(filename))
|
bool isBoxSet = Path.GetFileName(args.Path)
|
||||||
{
|
?.Contains("[playlist]", StringComparison.OrdinalIgnoreCase)
|
||||||
return null;
|
?? false;
|
||||||
}
|
if (isBoxSet)
|
||||||
|
|
||||||
if (filename.IndexOf("[playlist]", StringComparison.OrdinalIgnoreCase) != -1)
|
|
||||||
{
|
{
|
||||||
return new Playlist
|
return new Playlist
|
||||||
{
|
{
|
||||||
@ -45,21 +37,32 @@ namespace Emby.Server.Implementations.Library.Resolvers
|
|||||||
Name = Path.GetFileName(args.Path).Replace("[playlist]", string.Empty, StringComparison.OrdinalIgnoreCase).Trim()
|
Name = Path.GetFileName(args.Path).Replace("[playlist]", string.Empty, StringComparison.OrdinalIgnoreCase).Trim()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
// It's a directory-based playlist if the directory contains a playlist file
|
||||||
{
|
var filePaths = Directory.EnumerateFiles(args.Path);
|
||||||
if (SupportedCollectionTypes.Contains(args.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase))
|
if (filePaths.Any(f => f.EndsWith(PlaylistXmlSaver.DefaultPlaylistFilename, StringComparison.OrdinalIgnoreCase)))
|
||||||
{
|
{
|
||||||
var extension = Path.GetExtension(args.Path);
|
return new Playlist
|
||||||
if (Playlist.SupportedExtensions.Contains(extension ?? string.Empty, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
{
|
||||||
return new Playlist
|
Path = args.Path,
|
||||||
{
|
Name = Path.GetFileName(args.Path)
|
||||||
Path = args.Path,
|
};
|
||||||
Name = Path.GetFileNameWithoutExtension(args.Path),
|
}
|
||||||
IsInMixedFolder = true
|
}
|
||||||
};
|
|
||||||
}
|
// Check if this is a music playlist file
|
||||||
|
// It should have the correct collection type and a supported file extension
|
||||||
|
else if (_musicPlaylistCollectionTypes.Contains(args.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
var extension = Path.GetExtension(args.Path);
|
||||||
|
if (Playlist.SupportedExtensions.Contains(extension ?? string.Empty, StringComparer.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return new Playlist
|
||||||
|
{
|
||||||
|
Path = args.Path,
|
||||||
|
Name = Path.GetFileNameWithoutExtension(args.Path),
|
||||||
|
IsInMixedFolder = true
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
|||||||
/// <param name="libraryManager">The library manager.</param>
|
/// <param name="libraryManager">The library manager.</param>
|
||||||
/// <param name="localization">The localization</param>
|
/// <param name="localization">The localization</param>
|
||||||
/// <param name="logger">The logger</param>
|
/// <param name="logger">The logger</param>
|
||||||
public SeasonResolver(IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization, ILogger logger)
|
public SeasonResolver(
|
||||||
|
IServerConfigurationManager config,
|
||||||
|
ILibraryManager libraryManager,
|
||||||
|
ILocalizationManager localization,
|
||||||
|
ILogger<SeasonResolver> logger)
|
||||||
{
|
{
|
||||||
_config = config;
|
_config = config;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
|
@ -31,7 +31,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
|
|||||||
/// <param name="fileSystem">The file system.</param>
|
/// <param name="fileSystem">The file system.</param>
|
||||||
/// <param name="logger">The logger.</param>
|
/// <param name="logger">The logger.</param>
|
||||||
/// <param name="libraryManager">The library manager.</param>
|
/// <param name="libraryManager">The library manager.</param>
|
||||||
public SeriesResolver(IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager)
|
public SeriesResolver(IFileSystem fileSystem, ILogger<SeriesResolver> logger, ILibraryManager libraryManager)
|
||||||
{
|
{
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
@ -25,7 +25,10 @@ namespace Emby.Server.Implementations.Library.Validators
|
|||||||
/// <param name="libraryManager">The library manager.</param>
|
/// <param name="libraryManager">The library manager.</param>
|
||||||
/// <param name="logger">The logger.</param>
|
/// <param name="logger">The logger.</param>
|
||||||
/// <param name="itemRepo">The item repository.</param>
|
/// <param name="itemRepo">The item repository.</param>
|
||||||
public ArtistsPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
|
public ArtistsPostScanTask(
|
||||||
|
ILibraryManager libraryManager,
|
||||||
|
ILogger<ArtistsPostScanTask> logger,
|
||||||
|
IItemRepository itemRepo)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
@ -25,7 +25,10 @@ namespace Emby.Server.Implementations.Library.Validators
|
|||||||
/// <param name="libraryManager">The library manager.</param>
|
/// <param name="libraryManager">The library manager.</param>
|
||||||
/// <param name="logger">The logger.</param>
|
/// <param name="logger">The logger.</param>
|
||||||
/// <param name="itemRepo">The item repository.</param>
|
/// <param name="itemRepo">The item repository.</param>
|
||||||
public GenresPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
|
public GenresPostScanTask(
|
||||||
|
ILibraryManager libraryManager,
|
||||||
|
ILogger<GenresPostScanTask> logger,
|
||||||
|
IItemRepository itemRepo)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
@ -25,7 +25,10 @@ namespace Emby.Server.Implementations.Library.Validators
|
|||||||
/// <param name="libraryManager">The library manager.</param>
|
/// <param name="libraryManager">The library manager.</param>
|
||||||
/// <param name="logger">The logger.</param>
|
/// <param name="logger">The logger.</param>
|
||||||
/// <param name="itemRepo">The item repository.</param>
|
/// <param name="itemRepo">The item repository.</param>
|
||||||
public MusicGenresPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
|
public MusicGenresPostScanTask(
|
||||||
|
ILibraryManager libraryManager,
|
||||||
|
ILogger<MusicGenresPostScanTask> logger,
|
||||||
|
IItemRepository itemRepo)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
@ -26,7 +26,10 @@ namespace Emby.Server.Implementations.Library.Validators
|
|||||||
/// <param name="libraryManager">The library manager.</param>
|
/// <param name="libraryManager">The library manager.</param>
|
||||||
/// <param name="logger">The logger.</param>
|
/// <param name="logger">The logger.</param>
|
||||||
/// <param name="itemRepo">The item repository.</param>
|
/// <param name="itemRepo">The item repository.</param>
|
||||||
public StudiosPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
|
public StudiosPostScanTask(
|
||||||
|
ILibraryManager libraryManager,
|
||||||
|
ILogger<StudiosPostScanTask> logger,
|
||||||
|
IItemRepository itemRepo)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
@ -80,7 +80,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||||||
IServerApplicationHost appHost,
|
IServerApplicationHost appHost,
|
||||||
IStreamHelper streamHelper,
|
IStreamHelper streamHelper,
|
||||||
IMediaSourceManager mediaSourceManager,
|
IMediaSourceManager mediaSourceManager,
|
||||||
ILogger logger,
|
ILogger<EmbyTV> logger,
|
||||||
IJsonSerializer jsonSerializer,
|
IJsonSerializer jsonSerializer,
|
||||||
IHttpClient httpClient,
|
IHttpClient httpClient,
|
||||||
IServerConfigurationManager config,
|
IServerConfigurationManager config,
|
||||||
|
@ -33,7 +33,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||||||
|
|
||||||
private const string ApiUrl = "https://json.schedulesdirect.org/20141201";
|
private const string ApiUrl = "https://json.schedulesdirect.org/20141201";
|
||||||
|
|
||||||
public SchedulesDirect(ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IApplicationHost appHost)
|
public SchedulesDirect(
|
||||||
|
ILogger<SchedulesDirect> logger,
|
||||||
|
IJsonSerializer jsonSerializer,
|
||||||
|
IHttpClient httpClient,
|
||||||
|
IApplicationHost appHost)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_jsonSerializer = jsonSerializer;
|
_jsonSerializer = jsonSerializer;
|
||||||
|
@ -34,7 +34,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||||||
public XmlTvListingsProvider(
|
public XmlTvListingsProvider(
|
||||||
IServerConfigurationManager config,
|
IServerConfigurationManager config,
|
||||||
IHttpClient httpClient,
|
IHttpClient httpClient,
|
||||||
ILogger logger,
|
ILogger<XmlTvListingsProvider> logger,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
IZipClient zipClient)
|
IZipClient zipClient)
|
||||||
{
|
{
|
||||||
|
@ -39,7 +39,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
|||||||
|
|
||||||
public HdHomerunHost(
|
public HdHomerunHost(
|
||||||
IServerConfigurationManager config,
|
IServerConfigurationManager config,
|
||||||
ILogger logger,
|
ILogger<HdHomerunHost> logger,
|
||||||
IJsonSerializer jsonSerializer,
|
IJsonSerializer jsonSerializer,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
IHttpClient httpClient,
|
IHttpClient httpClient,
|
||||||
|
@ -2,22 +2,22 @@
|
|||||||
"Albums": "ألبومات",
|
"Albums": "ألبومات",
|
||||||
"AppDeviceValues": "تطبيق: {0}, جهاز: {1}",
|
"AppDeviceValues": "تطبيق: {0}, جهاز: {1}",
|
||||||
"Application": "التطبيق",
|
"Application": "التطبيق",
|
||||||
"Artists": "الفنان",
|
"Artists": "الفنانين",
|
||||||
"AuthenticationSucceededWithUserName": "{0} سجل الدخول بنجاح",
|
"AuthenticationSucceededWithUserName": "{0} سجل الدخول بنجاح",
|
||||||
"Books": "كتب",
|
"Books": "كتب",
|
||||||
"CameraImageUploadedFrom": "صورة كاميرا جديدة تم رفعها من {0}",
|
"CameraImageUploadedFrom": "صورة كاميرا جديدة تم رفعها من {0}",
|
||||||
"Channels": "القنوات",
|
"Channels": "القنوات",
|
||||||
"ChapterNameValue": "الباب {0}",
|
"ChapterNameValue": "فصل {0}",
|
||||||
"Collections": "مجموعات",
|
"Collections": "مجموعات",
|
||||||
"DeviceOfflineWithName": "تم قطع اتصال {0}",
|
"DeviceOfflineWithName": "قُطِع الاتصال بـ{0}",
|
||||||
"DeviceOnlineWithName": "{0} متصل",
|
"DeviceOnlineWithName": "{0} متصل",
|
||||||
"FailedLoginAttemptWithUserName": "عملية تسجيل الدخول فشلت من {0}",
|
"FailedLoginAttemptWithUserName": "عملية تسجيل الدخول فشلت من {0}",
|
||||||
"Favorites": "التفضيلات",
|
"Favorites": "المفضلة",
|
||||||
"Folders": "المجلدات",
|
"Folders": "المجلدات",
|
||||||
"Genres": "أنواع الأفلام",
|
"Genres": "الأنواع",
|
||||||
"HeaderAlbumArtists": "فناني الألبومات",
|
"HeaderAlbumArtists": "فناني الألبومات",
|
||||||
"HeaderCameraUploads": "تحميلات الكاميرا",
|
"HeaderCameraUploads": "تحميلات الكاميرا",
|
||||||
"HeaderContinueWatching": "استئناف المشاهدة",
|
"HeaderContinueWatching": "استئناف",
|
||||||
"HeaderFavoriteAlbums": "الألبومات المفضلة",
|
"HeaderFavoriteAlbums": "الألبومات المفضلة",
|
||||||
"HeaderFavoriteArtists": "الفنانون المفضلون",
|
"HeaderFavoriteArtists": "الفنانون المفضلون",
|
||||||
"HeaderFavoriteEpisodes": "الحلقات المفضلة",
|
"HeaderFavoriteEpisodes": "الحلقات المفضلة",
|
||||||
@ -31,28 +31,28 @@
|
|||||||
"ItemAddedWithName": "تم إضافة {0} للمكتبة",
|
"ItemAddedWithName": "تم إضافة {0} للمكتبة",
|
||||||
"ItemRemovedWithName": "تم إزالة {0} من المكتبة",
|
"ItemRemovedWithName": "تم إزالة {0} من المكتبة",
|
||||||
"LabelIpAddressValue": "عنوان الآي بي: {0}",
|
"LabelIpAddressValue": "عنوان الآي بي: {0}",
|
||||||
"LabelRunningTimeValue": "وقت التشغيل: {0}",
|
"LabelRunningTimeValue": "المدة: {0}",
|
||||||
"Latest": "الأحدث",
|
"Latest": "الأحدث",
|
||||||
"MessageApplicationUpdated": "لقد تم تحديث خادم أمبي",
|
"MessageApplicationUpdated": "لقد تم تحديث خادم Jellyfin",
|
||||||
"MessageApplicationUpdatedTo": "تم تحديث سيرفر Jellyfin الى {0}",
|
"MessageApplicationUpdatedTo": "تم تحديث سيرفر Jellyfin الى {0}",
|
||||||
"MessageNamedServerConfigurationUpdatedWithValue": "تم تحديث إعدادات الخادم في قسم {0}",
|
"MessageNamedServerConfigurationUpdatedWithValue": "تم تحديث إعدادات الخادم في قسم {0}",
|
||||||
"MessageServerConfigurationUpdated": "تم تحديث إعدادات الخادم",
|
"MessageServerConfigurationUpdated": "تم تحديث إعدادات الخادم",
|
||||||
"MixedContent": "محتوى مخلوط",
|
"MixedContent": "محتوى مختلط",
|
||||||
"Movies": "الأفلام",
|
"Movies": "الأفلام",
|
||||||
"Music": "الموسيقى",
|
"Music": "الموسيقى",
|
||||||
"MusicVideos": "الفيديوهات الموسيقية",
|
"MusicVideos": "الفيديوهات الموسيقية",
|
||||||
"NameInstallFailed": "فشل التثبيت {0}",
|
"NameInstallFailed": "فشل التثبيت {0}",
|
||||||
"NameSeasonNumber": "الموسم {0}",
|
"NameSeasonNumber": "الموسم {0}",
|
||||||
"NameSeasonUnknown": "الموسم غير معروف",
|
"NameSeasonUnknown": "الموسم غير معروف",
|
||||||
"NewVersionIsAvailable": "نسخة حديثة من سيرفر Jellyfin متوفرة للتحميل .",
|
"NewVersionIsAvailable": "نسخة جديدة من سيرفر Jellyfin متوفرة للتحميل.",
|
||||||
"NotificationOptionApplicationUpdateAvailable": "يوجد تحديث للتطبيق",
|
"NotificationOptionApplicationUpdateAvailable": "يوجد تحديث للتطبيق",
|
||||||
"NotificationOptionApplicationUpdateInstalled": "تم تحديث التطبيق",
|
"NotificationOptionApplicationUpdateInstalled": "تم تحديث التطبيق",
|
||||||
"NotificationOptionAudioPlayback": "بدأ تشغيل المقطع الصوتي",
|
"NotificationOptionAudioPlayback": "بدأ تشغيل المقطع الصوتي",
|
||||||
"NotificationOptionAudioPlaybackStopped": "تم إيقاف تشغيل المقطع الصوتي",
|
"NotificationOptionAudioPlaybackStopped": "تم إيقاف تشغيل المقطع الصوتي",
|
||||||
"NotificationOptionCameraImageUploaded": "تم رقع صورة الكاميرا",
|
"NotificationOptionCameraImageUploaded": "تم رفع صورة الكاميرا",
|
||||||
"NotificationOptionInstallationFailed": "فشل في التثبيت",
|
"NotificationOptionInstallationFailed": "فشل في التثبيت",
|
||||||
"NotificationOptionNewLibraryContent": "تم إضافة محتوى جديد",
|
"NotificationOptionNewLibraryContent": "أُضِيفَ محتوى جديد",
|
||||||
"NotificationOptionPluginError": "فشل في الملحق",
|
"NotificationOptionPluginError": "فشل في الـPlugin",
|
||||||
"NotificationOptionPluginInstalled": "تم تثبيت الملحق",
|
"NotificationOptionPluginInstalled": "تم تثبيت الملحق",
|
||||||
"NotificationOptionPluginUninstalled": "تمت إزالة الملحق",
|
"NotificationOptionPluginUninstalled": "تمت إزالة الملحق",
|
||||||
"NotificationOptionPluginUpdateInstalled": "تم تثبيت تحديثات الملحق",
|
"NotificationOptionPluginUpdateInstalled": "تم تثبيت تحديثات الملحق",
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"AppDeviceValues": "App: {0}, Enhed: {1}",
|
"AppDeviceValues": "App: {0}, Enhed: {1}",
|
||||||
"Application": "Applikation",
|
"Application": "Applikation",
|
||||||
"Artists": "Kunstnere",
|
"Artists": "Kunstnere",
|
||||||
"AuthenticationSucceededWithUserName": "{0} bekræftet med succes",
|
"AuthenticationSucceededWithUserName": "{0} succesfuldt autentificeret",
|
||||||
"Books": "Bøger",
|
"Books": "Bøger",
|
||||||
"CameraImageUploadedFrom": "Et nyt kamerabillede er blevet uploadet fra {0}",
|
"CameraImageUploadedFrom": "Et nyt kamerabillede er blevet uploadet fra {0}",
|
||||||
"Channels": "Kanaler",
|
"Channels": "Kanaler",
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
{
|
{
|
||||||
"Albums": "Alben",
|
"Albums": "Alben",
|
||||||
"AppDeviceValues": "App: {0}, Gerät: {1}",
|
"AppDeviceValues": "Anw: {0}, Gerät: {1}",
|
||||||
"Application": "Anwendung",
|
"Application": "Programm",
|
||||||
"Artists": "Interpreten",
|
"Artists": "Interpreten",
|
||||||
"AuthenticationSucceededWithUserName": "{0} hat sich erfolgreich angemeldet",
|
"AuthenticationSucceededWithUserName": "{0} hat sich erfolgreich angemeldet",
|
||||||
"Books": "Bücher",
|
"Books": "Bücher",
|
||||||
"CameraImageUploadedFrom": "Ein neues Foto wurde hochgeladen von {0}",
|
"CameraImageUploadedFrom": "Ein neues Foto wurde von {0} hochgeladen",
|
||||||
"Channels": "Kanäle",
|
"Channels": "Kanäle",
|
||||||
"ChapterNameValue": "Kapitel {0}",
|
"ChapterNameValue": "Kapitel {0}",
|
||||||
"Collections": "Sammlungen",
|
"Collections": "Sammlungen",
|
||||||
"DeviceOfflineWithName": "{0} wurde getrennt",
|
"DeviceOfflineWithName": "{0} hat die Verbindung getrennt",
|
||||||
"DeviceOnlineWithName": "{0} ist verbunden",
|
"DeviceOnlineWithName": "{0} ist verbunden",
|
||||||
"FailedLoginAttemptWithUserName": "Fehlgeschlagener Anmeldeversuch von {0}",
|
"FailedLoginAttemptWithUserName": "Fehlgeschlagener Anmeldeversuch von {0}",
|
||||||
"Favorites": "Favoriten",
|
"Favorites": "Favoriten",
|
||||||
@ -17,7 +17,7 @@
|
|||||||
"Genres": "Genres",
|
"Genres": "Genres",
|
||||||
"HeaderAlbumArtists": "Album-Interpreten",
|
"HeaderAlbumArtists": "Album-Interpreten",
|
||||||
"HeaderCameraUploads": "Kamera-Uploads",
|
"HeaderCameraUploads": "Kamera-Uploads",
|
||||||
"HeaderContinueWatching": "Weiterschauen",
|
"HeaderContinueWatching": "Fortsetzen",
|
||||||
"HeaderFavoriteAlbums": "Lieblingsalben",
|
"HeaderFavoriteAlbums": "Lieblingsalben",
|
||||||
"HeaderFavoriteArtists": "Lieblings-Interpreten",
|
"HeaderFavoriteArtists": "Lieblings-Interpreten",
|
||||||
"HeaderFavoriteEpisodes": "Lieblingsepisoden",
|
"HeaderFavoriteEpisodes": "Lieblingsepisoden",
|
||||||
|
@ -17,31 +17,31 @@
|
|||||||
"LabelIpAddressValue": "IP-osoite: {0}",
|
"LabelIpAddressValue": "IP-osoite: {0}",
|
||||||
"ItemRemovedWithName": "{0} poistettiin kirjastosta",
|
"ItemRemovedWithName": "{0} poistettiin kirjastosta",
|
||||||
"ItemAddedWithName": "{0} lisättiin kirjastoon",
|
"ItemAddedWithName": "{0} lisättiin kirjastoon",
|
||||||
"Inherit": "Periä",
|
"Inherit": "Periytyä",
|
||||||
"HomeVideos": "Kotivideot",
|
"HomeVideos": "Kotivideot",
|
||||||
"HeaderRecordingGroups": "Äänitysryhmät",
|
"HeaderRecordingGroups": "Nauhoitusryhmät",
|
||||||
"HeaderNextUp": "Seuraavaksi",
|
"HeaderNextUp": "Seuraavaksi",
|
||||||
"HeaderFavoriteSongs": "Lempikappaleet",
|
"HeaderFavoriteSongs": "Lempikappaleet",
|
||||||
"HeaderFavoriteShows": "Lempisarjat",
|
"HeaderFavoriteShows": "Lempisarjat",
|
||||||
"HeaderFavoriteEpisodes": "Lempijaksot",
|
"HeaderFavoriteEpisodes": "Lempijaksot",
|
||||||
"HeaderCameraUploads": "Kamerasta lähetetyt",
|
"HeaderCameraUploads": "Kameralataukset",
|
||||||
"HeaderFavoriteArtists": "Lempiartistit",
|
"HeaderFavoriteArtists": "Lempiartistit",
|
||||||
"HeaderFavoriteAlbums": "Lempialbumit",
|
"HeaderFavoriteAlbums": "Lempialbumit",
|
||||||
"HeaderContinueWatching": "Jatka katsomista",
|
"HeaderContinueWatching": "Jatka katsomista",
|
||||||
"HeaderAlbumArtists": "Albumin artistit",
|
"HeaderAlbumArtists": "Albumin esittäjä",
|
||||||
"Genres": "Tyylilaji",
|
"Genres": "Tyylilajit",
|
||||||
"Folders": "Kansiot",
|
"Folders": "Kansiot",
|
||||||
"Favorites": "Suosikit",
|
"Favorites": "Suosikit",
|
||||||
"FailedLoginAttemptWithUserName": "Epäonnistunut kirjautumisyritys kohteesta {0}",
|
"FailedLoginAttemptWithUserName": "Kirjautuminen epäonnistui kohteesta {0}",
|
||||||
"DeviceOnlineWithName": "{0} on yhdistynyt",
|
"DeviceOnlineWithName": "{0} on yhdistetty",
|
||||||
"DeviceOfflineWithName": "{0} on katkaissut yhteytensä",
|
"DeviceOfflineWithName": "{0} on katkaissut yhteytensä",
|
||||||
"Collections": "Kokoelmat",
|
"Collections": "Kokoelmat",
|
||||||
"ChapterNameValue": "Luku: {0}",
|
"ChapterNameValue": "Luku: {0}",
|
||||||
"Channels": "Kanavat",
|
"Channels": "Kanavat",
|
||||||
"CameraImageUploadedFrom": "Uusi kamerakuva on lähetetty kohteesta {0}",
|
"CameraImageUploadedFrom": "Uusi kamerakuva on ladattu {0}",
|
||||||
"Books": "Kirjat",
|
"Books": "Kirjat",
|
||||||
"AuthenticationSucceededWithUserName": "{0} todennettu onnistuneesti",
|
"AuthenticationSucceededWithUserName": "{0} todennus onnistui",
|
||||||
"Artists": "Artistit",
|
"Artists": "Esiintyjät",
|
||||||
"Application": "Sovellus",
|
"Application": "Sovellus",
|
||||||
"AppDeviceValues": "Sovellus: {0}, Laite: {1}",
|
"AppDeviceValues": "Sovellus: {0}, Laite: {1}",
|
||||||
"Albums": "Albumit",
|
"Albums": "Albumit",
|
||||||
@ -76,21 +76,21 @@
|
|||||||
"Shows": "Ohjelmat",
|
"Shows": "Ohjelmat",
|
||||||
"ServerNameNeedsToBeRestarted": "{0} vaatii uudelleenkäynnistyksen",
|
"ServerNameNeedsToBeRestarted": "{0} vaatii uudelleenkäynnistyksen",
|
||||||
"ProviderValue": "Palveluntarjoaja: {0}",
|
"ProviderValue": "Palveluntarjoaja: {0}",
|
||||||
"Plugin": "Laajennus",
|
"Plugin": "Liitännäinen",
|
||||||
"NotificationOptionVideoPlaybackStopped": "Videon toistaminen pysäytetty",
|
"NotificationOptionVideoPlaybackStopped": "Videon toistaminen pysäytetty",
|
||||||
"NotificationOptionVideoPlayback": "Videon toistaminen aloitettu",
|
"NotificationOptionVideoPlayback": "Videon toistaminen aloitettu",
|
||||||
"NotificationOptionUserLockedOut": "Käyttäjä kirjautui ulos",
|
"NotificationOptionUserLockedOut": "Käyttäjä kirjautui ulos",
|
||||||
"NotificationOptionTaskFailed": "Ajastetun tehtävän ongelma",
|
"NotificationOptionTaskFailed": "Ajastetun tehtävän ongelma",
|
||||||
"NotificationOptionServerRestartRequired": "Palvelimen uudelleenkäynnistys vaaditaan",
|
"NotificationOptionServerRestartRequired": "Palvelimen uudelleenkäynnistys vaaditaan",
|
||||||
"NotificationOptionPluginUpdateInstalled": "Laajennuksen päivitys asennettu",
|
"NotificationOptionPluginUpdateInstalled": "Liitännäinen päivitetty",
|
||||||
"NotificationOptionPluginUninstalled": "Laajennus poistettu",
|
"NotificationOptionPluginUninstalled": "Liitännäinen poistettu",
|
||||||
"NotificationOptionPluginInstalled": "Laajennus asennettu",
|
"NotificationOptionPluginInstalled": "Liitännäinen asennettu",
|
||||||
"NotificationOptionPluginError": "Ongelma laajennuksessa",
|
"NotificationOptionPluginError": "Ongelma liitännäisessä",
|
||||||
"NotificationOptionNewLibraryContent": "Uusi sisältö lisätty",
|
"NotificationOptionNewLibraryContent": "Uutta sisältöä lisätty",
|
||||||
"NotificationOptionInstallationFailed": "Asennusvirhe",
|
"NotificationOptionInstallationFailed": "Asennus epäonnistui",
|
||||||
"NotificationOptionCameraImageUploaded": "Kameran kuva lisätty",
|
"NotificationOptionCameraImageUploaded": "Kuva ladattu kamerasta",
|
||||||
"NotificationOptionAudioPlaybackStopped": "Äänen toistaminen pysäytetty",
|
"NotificationOptionAudioPlaybackStopped": "Audion toisto pysäytetty",
|
||||||
"NotificationOptionAudioPlayback": "Äänen toistaminen aloitettu",
|
"NotificationOptionAudioPlayback": "Audion toisto aloitettu",
|
||||||
"NotificationOptionApplicationUpdateInstalled": "Ohjelmistopäivitys asennettu",
|
"NotificationOptionApplicationUpdateInstalled": "Ohjelmistopäivitys asennettu",
|
||||||
"NotificationOptionApplicationUpdateAvailable": "Ohjelmistopäivitys saatavilla"
|
"NotificationOptionApplicationUpdateAvailable": "Ohjelmistopäivitys saatavilla"
|
||||||
}
|
}
|
||||||
|
@ -2,33 +2,33 @@
|
|||||||
"Albums": "אלבומים",
|
"Albums": "אלבומים",
|
||||||
"AppDeviceValues": "יישום: {0}, מכשיר: {1}",
|
"AppDeviceValues": "יישום: {0}, מכשיר: {1}",
|
||||||
"Application": "אפליקציה",
|
"Application": "אפליקציה",
|
||||||
"Artists": "אמנים",
|
"Artists": "אומנים",
|
||||||
"AuthenticationSucceededWithUserName": "{0} זוהה בהצלחה",
|
"AuthenticationSucceededWithUserName": "{0} אומת בהצלחה",
|
||||||
"Books": "ספרים",
|
"Books": "ספרים",
|
||||||
"CameraImageUploadedFrom": "תמונה חדשה הועלתה מ{0}",
|
"CameraImageUploadedFrom": "תמונת מצלמה חדשה הועלתה מ {0}",
|
||||||
"Channels": "ערוצים",
|
"Channels": "ערוצים",
|
||||||
"ChapterNameValue": "פרק {0}",
|
"ChapterNameValue": "פרק {0}",
|
||||||
"Collections": "קולקציות",
|
"Collections": "אוספים",
|
||||||
"DeviceOfflineWithName": "{0} התנתק",
|
"DeviceOfflineWithName": "{0} התנתק",
|
||||||
"DeviceOnlineWithName": "{0} מחובר",
|
"DeviceOnlineWithName": "{0} מחובר",
|
||||||
"FailedLoginAttemptWithUserName": "ניסיון כניסה שגוי מ{0}",
|
"FailedLoginAttemptWithUserName": "ניסיון כניסה שגוי מ{0}",
|
||||||
"Favorites": "אהובים",
|
"Favorites": "מועדפים",
|
||||||
"Folders": "תיקיות",
|
"Folders": "תיקיות",
|
||||||
"Genres": "ז'אנרים",
|
"Genres": "ז'אנרים",
|
||||||
"HeaderAlbumArtists": "אמני האלבום",
|
"HeaderAlbumArtists": "אמני האלבום",
|
||||||
"HeaderCameraUploads": "העלאות ממצלמה",
|
"HeaderCameraUploads": "העלאות ממצלמה",
|
||||||
"HeaderContinueWatching": "המשך לצפות",
|
"HeaderContinueWatching": "המשך לצפות",
|
||||||
"HeaderFavoriteAlbums": "אלבומים שאהבתי",
|
"HeaderFavoriteAlbums": "אלבומים שאהבתי",
|
||||||
"HeaderFavoriteArtists": "אמנים שאהבתי",
|
"HeaderFavoriteArtists": "אמנים מועדפים",
|
||||||
"HeaderFavoriteEpisodes": "פרקים אהובים",
|
"HeaderFavoriteEpisodes": "פרקים מועדפים",
|
||||||
"HeaderFavoriteShows": "תוכניות אהובות",
|
"HeaderFavoriteShows": "סדרות מועדפות",
|
||||||
"HeaderFavoriteSongs": "שירים שאהבתי",
|
"HeaderFavoriteSongs": "שירים מועדפים",
|
||||||
"HeaderLiveTV": "טלוויזיה בשידור חי",
|
"HeaderLiveTV": "שידורים חיים",
|
||||||
"HeaderNextUp": "הבא",
|
"HeaderNextUp": "הבא",
|
||||||
"HeaderRecordingGroups": "קבוצות הקלטה",
|
"HeaderRecordingGroups": "קבוצות הקלטה",
|
||||||
"HomeVideos": "סרטונים בייתים",
|
"HomeVideos": "סרטונים בייתים",
|
||||||
"Inherit": "הורש",
|
"Inherit": "הורש",
|
||||||
"ItemAddedWithName": "{0} was added to the library",
|
"ItemAddedWithName": "{0} הוסף לספרייה",
|
||||||
"ItemRemovedWithName": "{0} נמחק מהספרייה",
|
"ItemRemovedWithName": "{0} נמחק מהספרייה",
|
||||||
"LabelIpAddressValue": "Ip כתובת: {0}",
|
"LabelIpAddressValue": "Ip כתובת: {0}",
|
||||||
"LabelRunningTimeValue": "משך צפייה: {0}",
|
"LabelRunningTimeValue": "משך צפייה: {0}",
|
||||||
@ -36,15 +36,15 @@
|
|||||||
"MessageApplicationUpdated": "שרת הJellyfin עודכן",
|
"MessageApplicationUpdated": "שרת הJellyfin עודכן",
|
||||||
"MessageApplicationUpdatedTo": "שרת הJellyfin עודכן לגרסא {0}",
|
"MessageApplicationUpdatedTo": "שרת הJellyfin עודכן לגרסא {0}",
|
||||||
"MessageNamedServerConfigurationUpdatedWithValue": "הגדרת השרת {0} שונתה",
|
"MessageNamedServerConfigurationUpdatedWithValue": "הגדרת השרת {0} שונתה",
|
||||||
"MessageServerConfigurationUpdated": "Server configuration has been updated",
|
"MessageServerConfigurationUpdated": "תצורת השרת עודכנה",
|
||||||
"MixedContent": "תוכן מעורב",
|
"MixedContent": "תוכן מעורב",
|
||||||
"Movies": "סרטים",
|
"Movies": "סרטים",
|
||||||
"Music": "מוזיקה",
|
"Music": "מוזיקה",
|
||||||
"MusicVideos": "Music videos",
|
"MusicVideos": "קליפים",
|
||||||
"NameInstallFailed": "{0} installation failed",
|
"NameInstallFailed": "התקנת {0} נכשלה",
|
||||||
"NameSeasonNumber": "Season {0}",
|
"NameSeasonNumber": "עונה {0}",
|
||||||
"NameSeasonUnknown": "Season Unknown",
|
"NameSeasonUnknown": "עונה לא ידועה",
|
||||||
"NewVersionIsAvailable": "A new version of Jellyfin Server is available for download.",
|
"NewVersionIsAvailable": "גרסה חדשה של שרת Jellyfin זמינה להורדה.",
|
||||||
"NotificationOptionApplicationUpdateAvailable": "Application update available",
|
"NotificationOptionApplicationUpdateAvailable": "Application update available",
|
||||||
"NotificationOptionApplicationUpdateInstalled": "Application update installed",
|
"NotificationOptionApplicationUpdateInstalled": "Application update installed",
|
||||||
"NotificationOptionAudioPlayback": "Audio playback started",
|
"NotificationOptionAudioPlayback": "Audio playback started",
|
||||||
@ -53,10 +53,10 @@
|
|||||||
"NotificationOptionInstallationFailed": "התקנה נכשלה",
|
"NotificationOptionInstallationFailed": "התקנה נכשלה",
|
||||||
"NotificationOptionNewLibraryContent": "New content added",
|
"NotificationOptionNewLibraryContent": "New content added",
|
||||||
"NotificationOptionPluginError": "Plugin failure",
|
"NotificationOptionPluginError": "Plugin failure",
|
||||||
"NotificationOptionPluginInstalled": "Plugin installed",
|
"NotificationOptionPluginInstalled": "התוסף הותקן",
|
||||||
"NotificationOptionPluginUninstalled": "Plugin uninstalled",
|
"NotificationOptionPluginUninstalled": "התוסף הוסר",
|
||||||
"NotificationOptionPluginUpdateInstalled": "Plugin update installed",
|
"NotificationOptionPluginUpdateInstalled": "העדכון לתוסף הותקן",
|
||||||
"NotificationOptionServerRestartRequired": "Server restart required",
|
"NotificationOptionServerRestartRequired": "יש לאתחל את השרת",
|
||||||
"NotificationOptionTaskFailed": "Scheduled task failure",
|
"NotificationOptionTaskFailed": "Scheduled task failure",
|
||||||
"NotificationOptionUserLockedOut": "User locked out",
|
"NotificationOptionUserLockedOut": "User locked out",
|
||||||
"NotificationOptionVideoPlayback": "Video playback started",
|
"NotificationOptionVideoPlayback": "Video playback started",
|
||||||
@ -71,26 +71,26 @@
|
|||||||
"ScheduledTaskFailedWithName": "{0} failed",
|
"ScheduledTaskFailedWithName": "{0} failed",
|
||||||
"ScheduledTaskStartedWithName": "{0} started",
|
"ScheduledTaskStartedWithName": "{0} started",
|
||||||
"ServerNameNeedsToBeRestarted": "{0} needs to be restarted",
|
"ServerNameNeedsToBeRestarted": "{0} needs to be restarted",
|
||||||
"Shows": "Shows",
|
"Shows": "סדרות",
|
||||||
"Songs": "Songs",
|
"Songs": "שירים",
|
||||||
"StartupEmbyServerIsLoading": "Jellyfin Server is loading. Please try again shortly.",
|
"StartupEmbyServerIsLoading": "שרת Jellyfin בהליכי טעינה. אנא נסה שנית בעוד זמן קצר.",
|
||||||
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
|
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
|
||||||
"SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}",
|
"SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}",
|
||||||
"SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
|
"SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
|
||||||
"Sync": "סנכרן",
|
"Sync": "סנכרן",
|
||||||
"System": "System",
|
"System": "System",
|
||||||
"TvShows": "TV Shows",
|
"TvShows": "סדרות טלוויזיה",
|
||||||
"User": "User",
|
"User": "User",
|
||||||
"UserCreatedWithName": "User {0} has been created",
|
"UserCreatedWithName": "המשתמש {0} נוצר",
|
||||||
"UserDeletedWithName": "User {0} has been deleted",
|
"UserDeletedWithName": "המשתמש {0} הוסר",
|
||||||
"UserDownloadingItemWithValues": "{0} is downloading {1}",
|
"UserDownloadingItemWithValues": "{0} מוריד את {1}",
|
||||||
"UserLockedOutWithName": "User {0} has been locked out",
|
"UserLockedOutWithName": "User {0} has been locked out",
|
||||||
"UserOfflineFromDevice": "{0} has disconnected from {1}",
|
"UserOfflineFromDevice": "{0} has disconnected from {1}",
|
||||||
"UserOnlineFromDevice": "{0} is online from {1}",
|
"UserOnlineFromDevice": "{0} is online from {1}",
|
||||||
"UserPasswordChangedWithName": "Password has been changed for user {0}",
|
"UserPasswordChangedWithName": "Password has been changed for user {0}",
|
||||||
"UserPolicyUpdatedWithName": "User policy has been updated for {0}",
|
"UserPolicyUpdatedWithName": "User policy has been updated for {0}",
|
||||||
"UserStartedPlayingItemWithValues": "{0} is playing {1} on {2}",
|
"UserStartedPlayingItemWithValues": "{0} מנגן את {1} על {2}",
|
||||||
"UserStoppedPlayingItemWithValues": "{0} has finished playing {1} on {2}",
|
"UserStoppedPlayingItemWithValues": "{0} סיים לנגן את {1} על {2}",
|
||||||
"ValueHasBeenAddedToLibrary": "{0} has been added to your media library",
|
"ValueHasBeenAddedToLibrary": "{0} has been added to your media library",
|
||||||
"ValueSpecialEpisodeName": "מיוחד- {0}",
|
"ValueSpecialEpisodeName": "מיוחד- {0}",
|
||||||
"VersionNumber": "Version {0}"
|
"VersionNumber": "Version {0}"
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
"Collections": "Gyűjtemények",
|
"Collections": "Gyűjtemények",
|
||||||
"DeviceOfflineWithName": "{0} kijelentkezett",
|
"DeviceOfflineWithName": "{0} kijelentkezett",
|
||||||
"DeviceOnlineWithName": "{0} belépett",
|
"DeviceOnlineWithName": "{0} belépett",
|
||||||
"FailedLoginAttemptWithUserName": "Sikertelen bejelentkezési kísérlet {0}",
|
"FailedLoginAttemptWithUserName": "Sikertelen bejelentkezési kísérlet tőle: {0}",
|
||||||
"Favorites": "Kedvencek",
|
"Favorites": "Kedvencek",
|
||||||
"Folders": "Könyvtárak",
|
"Folders": "Könyvtárak",
|
||||||
"Genres": "Műfajok",
|
"Genres": "Műfajok",
|
||||||
@ -27,7 +27,7 @@
|
|||||||
"HeaderNextUp": "Következik",
|
"HeaderNextUp": "Következik",
|
||||||
"HeaderRecordingGroups": "Felvételi csoportok",
|
"HeaderRecordingGroups": "Felvételi csoportok",
|
||||||
"HomeVideos": "Házi videók",
|
"HomeVideos": "Házi videók",
|
||||||
"Inherit": "Öröklés",
|
"Inherit": "Örökölt",
|
||||||
"ItemAddedWithName": "{0} hozzáadva a könyvtárhoz",
|
"ItemAddedWithName": "{0} hozzáadva a könyvtárhoz",
|
||||||
"ItemRemovedWithName": "{0} eltávolítva a könyvtárból",
|
"ItemRemovedWithName": "{0} eltávolítva a könyvtárból",
|
||||||
"LabelIpAddressValue": "IP cím: {0}",
|
"LabelIpAddressValue": "IP cím: {0}",
|
||||||
@ -73,7 +73,7 @@
|
|||||||
"ServerNameNeedsToBeRestarted": "{0}-t újra kell indítani",
|
"ServerNameNeedsToBeRestarted": "{0}-t újra kell indítani",
|
||||||
"Shows": "Műsorok",
|
"Shows": "Műsorok",
|
||||||
"Songs": "Dalok",
|
"Songs": "Dalok",
|
||||||
"StartupEmbyServerIsLoading": "A Jellyfin Szerver betöltődik. Kérlek próbáld újra később.",
|
"StartupEmbyServerIsLoading": "A Jellyfin Szerver betöltődik. Kérlek, próbáld újra hamarosan.",
|
||||||
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
|
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
|
||||||
"SubtitleDownloadFailureFromForItem": "Nem sikerült a felirat letöltése innen: {0} ehhez: {1}",
|
"SubtitleDownloadFailureFromForItem": "Nem sikerült a felirat letöltése innen: {0} ehhez: {1}",
|
||||||
"SubtitlesDownloadedForItem": "Letöltött feliratok a következőhöz: {0}",
|
"SubtitlesDownloadedForItem": "Letöltött feliratok a következőhöz: {0}",
|
||||||
@ -86,11 +86,11 @@
|
|||||||
"UserDownloadingItemWithValues": "{0} letölti {1}",
|
"UserDownloadingItemWithValues": "{0} letölti {1}",
|
||||||
"UserLockedOutWithName": "{0} felhasználó zárolva van",
|
"UserLockedOutWithName": "{0} felhasználó zárolva van",
|
||||||
"UserOfflineFromDevice": "{0} kijelentkezett innen: {1}",
|
"UserOfflineFromDevice": "{0} kijelentkezett innen: {1}",
|
||||||
"UserOnlineFromDevice": "{0} online itt: {1}",
|
"UserOnlineFromDevice": "{0} online innen: {1}",
|
||||||
"UserPasswordChangedWithName": "Jelszó megváltozott a következő felhasználó számára: {0}",
|
"UserPasswordChangedWithName": "Jelszó megváltozott a következő felhasználó számára: {0}",
|
||||||
"UserPolicyUpdatedWithName": "A felhasználói házirend frissítve lett neki: {0}",
|
"UserPolicyUpdatedWithName": "A felhasználói házirend frissítve lett neki: {0}",
|
||||||
"UserStartedPlayingItemWithValues": "{0} elkezdte játszani a következőt: {1} itt: {2}",
|
"UserStartedPlayingItemWithValues": "{0} elkezdte játszani a következőt: {1} itt: {2}",
|
||||||
"UserStoppedPlayingItemWithValues": "{0} befejezte a következőt: {1} itt: {2}",
|
"UserStoppedPlayingItemWithValues": "{0} befejezte {1} lejátászását itt: {2}",
|
||||||
"ValueHasBeenAddedToLibrary": "{0} hozzáadva a médiatárhoz",
|
"ValueHasBeenAddedToLibrary": "{0} hozzáadva a médiatárhoz",
|
||||||
"ValueSpecialEpisodeName": "Special - {0}",
|
"ValueSpecialEpisodeName": "Special - {0}",
|
||||||
"VersionNumber": "Verzió: {0}"
|
"VersionNumber": "Verzió: {0}"
|
||||||
|
@ -91,5 +91,6 @@
|
|||||||
"NotificationOptionVideoPlayback": "Pemutaran video dimulai",
|
"NotificationOptionVideoPlayback": "Pemutaran video dimulai",
|
||||||
"NotificationOptionAudioPlaybackStopped": "Pemutaran audio berhenti",
|
"NotificationOptionAudioPlaybackStopped": "Pemutaran audio berhenti",
|
||||||
"NotificationOptionAudioPlayback": "Pemutaran audio dimulai",
|
"NotificationOptionAudioPlayback": "Pemutaran audio dimulai",
|
||||||
"MixedContent": "Konten campur"
|
"MixedContent": "Konten campur",
|
||||||
|
"PluginUninstalledWithName": "{0} telah dihapus"
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
"Artists": "Artisti",
|
"Artists": "Artisti",
|
||||||
"AuthenticationSucceededWithUserName": "{0} autenticato con successo",
|
"AuthenticationSucceededWithUserName": "{0} autenticato con successo",
|
||||||
"Books": "Libri",
|
"Books": "Libri",
|
||||||
"CameraImageUploadedFrom": "È stata caricata una nuova immagine della fotocamera {0}",
|
"CameraImageUploadedFrom": "È stata caricata una nuova immagine della fotocamera da {0}",
|
||||||
"Channels": "Canali",
|
"Channels": "Canali",
|
||||||
"ChapterNameValue": "Capitolo {0}",
|
"ChapterNameValue": "Capitolo {0}",
|
||||||
"Collections": "Collezioni",
|
"Collections": "Collezioni",
|
||||||
@ -18,7 +18,7 @@
|
|||||||
"HeaderAlbumArtists": "Artisti dell' Album",
|
"HeaderAlbumArtists": "Artisti dell' Album",
|
||||||
"HeaderCameraUploads": "Caricamenti Fotocamera",
|
"HeaderCameraUploads": "Caricamenti Fotocamera",
|
||||||
"HeaderContinueWatching": "Continua a guardare",
|
"HeaderContinueWatching": "Continua a guardare",
|
||||||
"HeaderFavoriteAlbums": "Album preferiti",
|
"HeaderFavoriteAlbums": "Album Preferiti",
|
||||||
"HeaderFavoriteArtists": "Artisti Preferiti",
|
"HeaderFavoriteArtists": "Artisti Preferiti",
|
||||||
"HeaderFavoriteEpisodes": "Episodi Preferiti",
|
"HeaderFavoriteEpisodes": "Episodi Preferiti",
|
||||||
"HeaderFavoriteShows": "Serie TV Preferite",
|
"HeaderFavoriteShows": "Serie TV Preferite",
|
||||||
|
96
Emby.Server.Implementations/Localization/Core/lv.json
Normal file
96
Emby.Server.Implementations/Localization/Core/lv.json
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
{
|
||||||
|
"ServerNameNeedsToBeRestarted": "{0} ir vajadzīgs restarts",
|
||||||
|
"NotificationOptionTaskFailed": "Plānota uzdevuma kļūme",
|
||||||
|
"HeaderRecordingGroups": "Ierakstu Grupas",
|
||||||
|
"UserPolicyUpdatedWithName": "Lietotāju politika atjaunota priekš {0}",
|
||||||
|
"SubtitleDownloadFailureFromForItem": "Subtitru lejupielāde no {0} priekš {1} neizdevās",
|
||||||
|
"NotificationOptionVideoPlaybackStopped": "Video atskaņošana apturēta",
|
||||||
|
"NotificationOptionVideoPlayback": "Video atskaņošana sākta",
|
||||||
|
"NotificationOptionInstallationFailed": "Instalācija neizdevās",
|
||||||
|
"AuthenticationSucceededWithUserName": "{0} veiksmīgi autentificējies",
|
||||||
|
"ValueSpecialEpisodeName": "Speciālais - {0}",
|
||||||
|
"ScheduledTaskStartedWithName": "{0} iesākts",
|
||||||
|
"ScheduledTaskFailedWithName": "{0} neizdevās",
|
||||||
|
"Photos": "Attēli",
|
||||||
|
"NotificationOptionUserLockedOut": "Lietotājs bloķēts",
|
||||||
|
"LabelRunningTimeValue": "Garums: {0}",
|
||||||
|
"Inherit": "Mantot",
|
||||||
|
"AppDeviceValues": "Lietotne:{0}, Ierīce:{1}",
|
||||||
|
"VersionNumber": "Versija {0}",
|
||||||
|
"ValueHasBeenAddedToLibrary": "{0} ir ticis pievienots tavai multvides bibliotēkai",
|
||||||
|
"UserStoppedPlayingItemWithValues": "{0} ir beidzis atskaņot {1} uz {2}",
|
||||||
|
"UserStartedPlayingItemWithValues": "{0} atskaņo {1} uz {2}",
|
||||||
|
"UserPasswordChangedWithName": "Parole nomainīta lietotājam {0}",
|
||||||
|
"UserOnlineFromDevice": "{0} ir tiešsaistē no {1}",
|
||||||
|
"UserOfflineFromDevice": "{0} ir atvienojies no {1}",
|
||||||
|
"UserLockedOutWithName": "Lietotājs {0} ir ticis bloķēts",
|
||||||
|
"UserDownloadingItemWithValues": "{0} lejupielādē {1}",
|
||||||
|
"UserDeletedWithName": "Lietotājs {0} ir izdzēsts",
|
||||||
|
"UserCreatedWithName": "Lietotājs {0} ir ticis izveidots",
|
||||||
|
"User": "Lietotājs",
|
||||||
|
"TvShows": "TV Raidījumi",
|
||||||
|
"Sync": "Sinhronizācija",
|
||||||
|
"System": "Sistēma",
|
||||||
|
"SubtitlesDownloadedForItem": "Subtitri lejupielādēti priekš {0}",
|
||||||
|
"StartupEmbyServerIsLoading": "Jellyfin Serveris lādējas. Lūdzu mēģiniet vēlreiz pēc brīža.",
|
||||||
|
"Songs": "Dziesmas",
|
||||||
|
"Shows": "Raidījumi",
|
||||||
|
"PluginUpdatedWithName": "{0} tika atjaunots",
|
||||||
|
"PluginUninstalledWithName": "{0} tika noņemts",
|
||||||
|
"PluginInstalledWithName": "{0} tika uzstādīts",
|
||||||
|
"Plugin": "Paplašinājums",
|
||||||
|
"Playlists": "Atskaņošanas Saraksti",
|
||||||
|
"MixedContent": "Jaukts saturs",
|
||||||
|
"HomeVideos": "Mājas Video",
|
||||||
|
"HeaderNextUp": "Nākamais",
|
||||||
|
"ChapterNameValue": "Nodaļa {0}",
|
||||||
|
"Application": "Lietotne",
|
||||||
|
"NotificationOptionServerRestartRequired": "Vajadzīgs servera restarts",
|
||||||
|
"NotificationOptionPluginUpdateInstalled": "Paplašinājuma atjauninājums uzstādīts",
|
||||||
|
"NotificationOptionPluginUninstalled": "Paplašinājums noņemts",
|
||||||
|
"NotificationOptionPluginInstalled": "Paplašinājums uzstādīts",
|
||||||
|
"NotificationOptionPluginError": "Paplašinājuma kļūda",
|
||||||
|
"NotificationOptionNewLibraryContent": "Jauns saturs pievienots",
|
||||||
|
"NotificationOptionCameraImageUploaded": "Kameras attēls augšupielādēts",
|
||||||
|
"NotificationOptionAudioPlaybackStopped": "Audio atskaņošana apturēta",
|
||||||
|
"NotificationOptionAudioPlayback": "Audio atskaņošana sākta",
|
||||||
|
"NotificationOptionApplicationUpdateInstalled": "Lietotnes atjauninājums uzstādīts",
|
||||||
|
"NotificationOptionApplicationUpdateAvailable": "Lietotnes atjauninājums pieejams",
|
||||||
|
"NewVersionIsAvailable": "Lejupielādei ir pieejama jauna Jellyfin Server versija.",
|
||||||
|
"NameSeasonUnknown": "Nezināma Sezona",
|
||||||
|
"NameSeasonNumber": "Sezona {0}",
|
||||||
|
"NameInstallFailed": "{0} instalācija neizdevās",
|
||||||
|
"MusicVideos": "Mūzikas video",
|
||||||
|
"Music": "Mūzika",
|
||||||
|
"Movies": "Filmas",
|
||||||
|
"MessageServerConfigurationUpdated": "Servera konfigurācija ir tikusi atjaunota",
|
||||||
|
"MessageNamedServerConfigurationUpdatedWithValue": "Servera konfigurācijas sadaļa {0} ir tikusi atjaunota",
|
||||||
|
"MessageApplicationUpdatedTo": "Jellyfin Server ir ticis atjaunots uz {0}",
|
||||||
|
"MessageApplicationUpdated": "Jellyfin Server ir ticis atjaunots",
|
||||||
|
"Latest": "Jaunākais",
|
||||||
|
"LabelIpAddressValue": "IP adrese: {0}",
|
||||||
|
"ItemRemovedWithName": "{0} tika noņemts no bibliotēkas",
|
||||||
|
"ItemAddedWithName": "{0} tika pievienots bibliotēkai",
|
||||||
|
"HeaderLiveTV": "Tiešraides TV",
|
||||||
|
"HeaderContinueWatching": "Turpināt Skatīšanos",
|
||||||
|
"HeaderCameraUploads": "Kameras augšupielādes",
|
||||||
|
"HeaderAlbumArtists": "Albumu Izpildītāji",
|
||||||
|
"Genres": "Žanri",
|
||||||
|
"Folders": "Mapes",
|
||||||
|
"Favorites": "Favorīti",
|
||||||
|
"FailedLoginAttemptWithUserName": "Neizdevies pieslēgšanās mēģinājums no {0}",
|
||||||
|
"DeviceOnlineWithName": "{0} ir pievienojies",
|
||||||
|
"DeviceOfflineWithName": "{0} ir atvienojies",
|
||||||
|
"Collections": "Kolekcijas",
|
||||||
|
"Channels": "Kanāli",
|
||||||
|
"CameraImageUploadedFrom": "Jauns kameras attēls ir ticis augšupielādēts no {0}",
|
||||||
|
"Books": "Grāmatas",
|
||||||
|
"Artists": "Izpildītāji",
|
||||||
|
"Albums": "Albumi",
|
||||||
|
"ProviderValue": "Provider: {0}",
|
||||||
|
"HeaderFavoriteSongs": "Dziesmu Favorīti",
|
||||||
|
"HeaderFavoriteShows": "Raidījumu Favorīti",
|
||||||
|
"HeaderFavoriteEpisodes": "Episožu Favorīti",
|
||||||
|
"HeaderFavoriteArtists": "Izpildītāju Favorīti",
|
||||||
|
"HeaderFavoriteAlbums": "Albumu Favorīti"
|
||||||
|
}
|
96
Emby.Server.Implementations/Localization/Core/mk.json
Normal file
96
Emby.Server.Implementations/Localization/Core/mk.json
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
{
|
||||||
|
"ScheduledTaskFailedWithName": "{0} неуспешно",
|
||||||
|
"ProviderValue": "Провајдер: {0}",
|
||||||
|
"PluginUpdatedWithName": "{0} беше надоградено",
|
||||||
|
"PluginUninstalledWithName": "{0} беше успешно деинсталирано",
|
||||||
|
"PluginInstalledWithName": "{0} беше успешно инсталирано",
|
||||||
|
"Plugin": "Додатоци",
|
||||||
|
"Playlists": "Листи",
|
||||||
|
"Photos": "Слики",
|
||||||
|
"NotificationOptionVideoPlaybackStopped": "Видео стопирано",
|
||||||
|
"NotificationOptionVideoPlayback": "Видео пуштено",
|
||||||
|
"NotificationOptionUserLockedOut": "Корисникот е ослободен",
|
||||||
|
"NotificationOptionTaskFailed": "Закажани задачи неуспешно",
|
||||||
|
"NotificationOptionServerRestartRequired": "Задолжително рестартирање на серверот",
|
||||||
|
"NotificationOptionPluginUpdateInstalled": "Надоградба на Додаток успешна",
|
||||||
|
"NotificationOptionPluginUninstalled": "Додаток успешно деинсталиран",
|
||||||
|
"NotificationOptionPluginInstalled": "Додаток успешно инсталиран",
|
||||||
|
"NotificationOptionPluginError": "Грешка на додаток",
|
||||||
|
"NotificationOptionNewLibraryContent": "Додадена нова содржина",
|
||||||
|
"NotificationOptionInstallationFailed": "Неуспешна Инсталација",
|
||||||
|
"NotificationOptionCameraImageUploaded": "Слика од камера поставена",
|
||||||
|
"NotificationOptionAudioPlaybackStopped": "Аудио стопирано",
|
||||||
|
"NotificationOptionAudioPlayback": "Аудио стартувано",
|
||||||
|
"NotificationOptionApplicationUpdateInstalled": "Надоградбата на Апликацијата е иснталирана",
|
||||||
|
"NotificationOptionApplicationUpdateAvailable": "Возможна надоградба на Апликацијата",
|
||||||
|
"NewVersionIsAvailable": "Нова верзија од Jellyfin е возможна за спуштање.",
|
||||||
|
"NameSeasonUnknown": "Непозната Сезона",
|
||||||
|
"NameSeasonNumber": "Сезона {0}",
|
||||||
|
"NameInstallFailed": "{0} неуспешна инсталација",
|
||||||
|
"MusicVideos": "Музички видеа",
|
||||||
|
"Music": "Музика",
|
||||||
|
"Movies": "Филмови",
|
||||||
|
"MixedContent": "Мешана содржина",
|
||||||
|
"MessageServerConfigurationUpdated": "Серверската конфигурација беше надградена",
|
||||||
|
"MessageNamedServerConfigurationUpdatedWithValue": "Секцијата на конфигурација на сервер {0} беше надоградена",
|
||||||
|
"MessageApplicationUpdatedTo": "Jellyfin беше надограден до {0}",
|
||||||
|
"MessageApplicationUpdated": "Jellyfin Серверот беше надограден",
|
||||||
|
"Latest": "Последно",
|
||||||
|
"LabelRunningTimeValue": "Време на работа: {0}",
|
||||||
|
"LabelIpAddressValue": "ИП Адреса: {0}",
|
||||||
|
"ItemRemovedWithName": "{0} е избришано до Библиотеката",
|
||||||
|
"ItemAddedWithName": "{0} беше додадено во Библиотеката",
|
||||||
|
"Inherit": "Следно",
|
||||||
|
"HomeVideos": "Домашни Видеа",
|
||||||
|
"HeaderRecordingGroups": "Групи на снимање",
|
||||||
|
"HeaderNextUp": "Следно",
|
||||||
|
"HeaderLiveTV": "ТВ",
|
||||||
|
"HeaderFavoriteSongs": "Омилени Песни",
|
||||||
|
"HeaderFavoriteShows": "Омилени Серии",
|
||||||
|
"HeaderFavoriteEpisodes": "Омилени Епизоди",
|
||||||
|
"HeaderFavoriteArtists": "Омилени Изведувачи",
|
||||||
|
"HeaderFavoriteAlbums": "Омилени Албуми",
|
||||||
|
"HeaderContinueWatching": "Продолжи со гледање",
|
||||||
|
"HeaderCameraUploads": "Поставувања од камера",
|
||||||
|
"HeaderAlbumArtists": "Изведувачи од Албуми",
|
||||||
|
"Genres": "Жанрови",
|
||||||
|
"Folders": "Папки",
|
||||||
|
"Favorites": "Омилени",
|
||||||
|
"FailedLoginAttemptWithUserName": "Неуспешно поврзување од {0}",
|
||||||
|
"DeviceOnlineWithName": "{0} е приклучен",
|
||||||
|
"DeviceOfflineWithName": "{0} се исклучи",
|
||||||
|
"Collections": "Колекции",
|
||||||
|
"ChapterNameValue": "Дел {0}",
|
||||||
|
"Channels": "Канали",
|
||||||
|
"CameraImageUploadedFrom": "Нова слика од камера беше поставена од {0}",
|
||||||
|
"Books": "Книги",
|
||||||
|
"AuthenticationSucceededWithUserName": "{0} успешно поврзан",
|
||||||
|
"Artists": "Изведувач",
|
||||||
|
"Application": "Апликација",
|
||||||
|
"AppDeviceValues": "Аплиакција: {0}, Уред: {1}",
|
||||||
|
"Albums": "Албуми",
|
||||||
|
"VersionNumber": "Верзија {0}",
|
||||||
|
"ValueSpecialEpisodeName": "Специјално - {0}",
|
||||||
|
"ValueHasBeenAddedToLibrary": "{0} е додадено во твојата библиотека",
|
||||||
|
"UserStoppedPlayingItemWithValues": "{0} заврши со репродукција {1} во {2}",
|
||||||
|
"UserStartedPlayingItemWithValues": "{0} пушти {1} на {2}",
|
||||||
|
"UserPolicyUpdatedWithName": "Полисата на користење беше надоградена за {0}",
|
||||||
|
"UserPasswordChangedWithName": "Лозинката е сменета за корисникот {0}",
|
||||||
|
"UserOnlineFromDevice": "{0} е приклучен од {1}",
|
||||||
|
"UserOfflineFromDevice": "{0} е дисконектиран од {1}",
|
||||||
|
"UserLockedOutWithName": "Корисникот {0} е заклучен",
|
||||||
|
"UserDownloadingItemWithValues": "{0} се спушта {1}",
|
||||||
|
"UserDeletedWithName": "Корисникот {0} е избришан",
|
||||||
|
"UserCreatedWithName": "Корисникот {0} е креиран",
|
||||||
|
"User": "Корисник",
|
||||||
|
"TvShows": "ТВ Серии",
|
||||||
|
"System": "Систем",
|
||||||
|
"Sync": "Синхронизација",
|
||||||
|
"SubtitlesDownloadedForItem": "Спуштање превод за {0}",
|
||||||
|
"SubtitleDownloadFailureFromForItem": "Преводот неуспешно се спушти од {0} за {1}",
|
||||||
|
"StartupEmbyServerIsLoading": "Jellyfin Server се пушта. Ве молиме причекајте.",
|
||||||
|
"Songs": "Песни",
|
||||||
|
"Shows": "Серии",
|
||||||
|
"ServerNameNeedsToBeRestarted": "{0} треба да се рестартира",
|
||||||
|
"ScheduledTaskStartedWithName": "{0} започна"
|
||||||
|
}
|
@ -3,13 +3,13 @@
|
|||||||
"AppDeviceValues": "App: {0}, Apparaat: {1}",
|
"AppDeviceValues": "App: {0}, Apparaat: {1}",
|
||||||
"Application": "Applicatie",
|
"Application": "Applicatie",
|
||||||
"Artists": "Artiesten",
|
"Artists": "Artiesten",
|
||||||
"AuthenticationSucceededWithUserName": "{0} is succesvol geverifieerd",
|
"AuthenticationSucceededWithUserName": "{0} succesvol geauthenticeerd",
|
||||||
"Books": "Boeken",
|
"Books": "Boeken",
|
||||||
"CameraImageUploadedFrom": "Er is een nieuwe foto toegevoegd van {0}",
|
"CameraImageUploadedFrom": "Er is een nieuwe foto toegevoegd van {0}",
|
||||||
"Channels": "Kanalen",
|
"Channels": "Kanalen",
|
||||||
"ChapterNameValue": "Hoofdstuk {0}",
|
"ChapterNameValue": "Hoofdstuk {0}",
|
||||||
"Collections": "Verzamelingen",
|
"Collections": "Verzamelingen",
|
||||||
"DeviceOfflineWithName": "{0} heeft de verbinding verbroken",
|
"DeviceOfflineWithName": "Verbinding met {0} is verbroken",
|
||||||
"DeviceOnlineWithName": "{0} is verbonden",
|
"DeviceOnlineWithName": "{0} is verbonden",
|
||||||
"FailedLoginAttemptWithUserName": "Mislukte aanmeld poging van {0}",
|
"FailedLoginAttemptWithUserName": "Mislukte aanmeld poging van {0}",
|
||||||
"Favorites": "Favorieten",
|
"Favorites": "Favorieten",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"HeaderLiveTV": "TV ao Vivo",
|
"HeaderLiveTV": "TV em Directo",
|
||||||
"Collections": "Colecções",
|
"Collections": "Colecções",
|
||||||
"Books": "Livros",
|
"Books": "Livros",
|
||||||
"Artists": "Artistas",
|
"Artists": "Artistas",
|
||||||
@ -10,13 +10,13 @@
|
|||||||
"HeaderFavoriteAlbums": "Álbuns Favoritos",
|
"HeaderFavoriteAlbums": "Álbuns Favoritos",
|
||||||
"HeaderFavoriteEpisodes": "Episódios Favoritos",
|
"HeaderFavoriteEpisodes": "Episódios Favoritos",
|
||||||
"HeaderFavoriteShows": "Séries Favoritas",
|
"HeaderFavoriteShows": "Séries Favoritas",
|
||||||
"HeaderContinueWatching": "Continuar a Ver",
|
"HeaderContinueWatching": "Continuar a Assistir",
|
||||||
"HeaderAlbumArtists": "Artistas do Álbum",
|
"HeaderAlbumArtists": "Artistas do Álbum",
|
||||||
"Genres": "Géneros",
|
"Genres": "Géneros",
|
||||||
"Folders": "Pastas",
|
"Folders": "Directórios",
|
||||||
"Favorites": "Favoritos",
|
"Favorites": "Favoritos",
|
||||||
"Channels": "Canais",
|
"Channels": "Canais",
|
||||||
"UserDownloadingItemWithValues": "{0} está a transferir {1}",
|
"UserDownloadingItemWithValues": "{0} está a ser transferido {1}",
|
||||||
"VersionNumber": "Versão {0}",
|
"VersionNumber": "Versão {0}",
|
||||||
"ValueHasBeenAddedToLibrary": "{0} foi adicionado à sua biblioteca multimédia",
|
"ValueHasBeenAddedToLibrary": "{0} foi adicionado à sua biblioteca multimédia",
|
||||||
"UserStoppedPlayingItemWithValues": "{0} terminou a reprodução de {1} em {2}",
|
"UserStoppedPlayingItemWithValues": "{0} terminou a reprodução de {1} em {2}",
|
||||||
@ -24,12 +24,12 @@
|
|||||||
"UserPolicyUpdatedWithName": "A política do utilizador {0} foi alterada",
|
"UserPolicyUpdatedWithName": "A política do utilizador {0} foi alterada",
|
||||||
"UserPasswordChangedWithName": "A palavra-passe do utilizador {0} foi alterada",
|
"UserPasswordChangedWithName": "A palavra-passe do utilizador {0} foi alterada",
|
||||||
"UserOnlineFromDevice": "{0} ligou-se a partir de {1}",
|
"UserOnlineFromDevice": "{0} ligou-se a partir de {1}",
|
||||||
"UserOfflineFromDevice": "{0} desligou-se a partir de {1}",
|
"UserOfflineFromDevice": "{0} desconectou-se a partir de {1}",
|
||||||
"UserLockedOutWithName": "Utilizador {0} bloqueado",
|
"UserLockedOutWithName": "O utilizador {0} foi bloqueado",
|
||||||
"UserDeletedWithName": "Utilizador {0} removido",
|
"UserDeletedWithName": "O utilizador {0} foi removido",
|
||||||
"UserCreatedWithName": "Utilizador {0} criado",
|
"UserCreatedWithName": "O utilizador {0} foi criado",
|
||||||
"User": "Utilizador",
|
"User": "Utilizador",
|
||||||
"TvShows": "Programas",
|
"TvShows": "Séries",
|
||||||
"System": "Sistema",
|
"System": "Sistema",
|
||||||
"SubtitlesDownloadedForItem": "Legendas transferidas para {0}",
|
"SubtitlesDownloadedForItem": "Legendas transferidas para {0}",
|
||||||
"SubtitleDownloadFailureFromForItem": "Falha na transferência de legendas de {0} para {1}",
|
"SubtitleDownloadFailureFromForItem": "Falha na transferência de legendas de {0} para {1}",
|
||||||
@ -38,22 +38,22 @@
|
|||||||
"ScheduledTaskStartedWithName": "{0} iniciou",
|
"ScheduledTaskStartedWithName": "{0} iniciou",
|
||||||
"ScheduledTaskFailedWithName": "{0} falhou",
|
"ScheduledTaskFailedWithName": "{0} falhou",
|
||||||
"ProviderValue": "Fornecedor: {0}",
|
"ProviderValue": "Fornecedor: {0}",
|
||||||
"PluginUpdatedWithName": "{0} foi actualizado",
|
"PluginUpdatedWithName": "{0} foi atualizado",
|
||||||
"PluginUninstalledWithName": "{0} foi desinstalado",
|
"PluginUninstalledWithName": "{0} foi desinstalado",
|
||||||
"PluginInstalledWithName": "{0} foi instalado",
|
"PluginInstalledWithName": "{0} foi instalado",
|
||||||
"Plugin": "Extensão",
|
"Plugin": "Plugin",
|
||||||
"NotificationOptionVideoPlaybackStopped": "Reprodução de vídeo parada",
|
"NotificationOptionVideoPlaybackStopped": "Reprodução de vídeo parada",
|
||||||
"NotificationOptionVideoPlayback": "Reprodução de vídeo iniciada",
|
"NotificationOptionVideoPlayback": "Reprodução de vídeo iniciada",
|
||||||
"NotificationOptionUserLockedOut": "Utilizador bloqueado",
|
"NotificationOptionUserLockedOut": "Utilizador bloqueado",
|
||||||
"NotificationOptionTaskFailed": "Falha em tarefa agendada",
|
"NotificationOptionTaskFailed": "Falha em tarefa agendada",
|
||||||
"NotificationOptionServerRestartRequired": "É necessário reiniciar o servidor",
|
"NotificationOptionServerRestartRequired": "É necessário reiniciar o servidor",
|
||||||
"NotificationOptionPluginUpdateInstalled": "Extensão actualizada",
|
"NotificationOptionPluginUpdateInstalled": "Plugin actualizado",
|
||||||
"NotificationOptionPluginUninstalled": "Extensão desinstalada",
|
"NotificationOptionPluginUninstalled": "Plugin desinstalado",
|
||||||
"NotificationOptionPluginInstalled": "Extensão instalada",
|
"NotificationOptionPluginInstalled": "Plugin instalado",
|
||||||
"NotificationOptionPluginError": "Falha na extensão",
|
"NotificationOptionPluginError": "Falha no plugin",
|
||||||
"NotificationOptionNewLibraryContent": "Novo conteúdo adicionado",
|
"NotificationOptionNewLibraryContent": "Novo conteúdo adicionado",
|
||||||
"NotificationOptionInstallationFailed": "Falha de instalação",
|
"NotificationOptionInstallationFailed": "Falha de instalação",
|
||||||
"NotificationOptionCameraImageUploaded": "Imagem da câmara enviada",
|
"NotificationOptionCameraImageUploaded": "Imagem de câmara enviada",
|
||||||
"NotificationOptionAudioPlaybackStopped": "Reprodução Parada",
|
"NotificationOptionAudioPlaybackStopped": "Reprodução Parada",
|
||||||
"NotificationOptionAudioPlayback": "Reprodução Iniciada",
|
"NotificationOptionAudioPlayback": "Reprodução Iniciada",
|
||||||
"NotificationOptionApplicationUpdateInstalled": "A actualização da aplicação foi instalada",
|
"NotificationOptionApplicationUpdateInstalled": "A actualização da aplicação foi instalada",
|
||||||
@ -66,30 +66,30 @@
|
|||||||
"Music": "Música",
|
"Music": "Música",
|
||||||
"MixedContent": "Conteúdo Misto",
|
"MixedContent": "Conteúdo Misto",
|
||||||
"MessageServerConfigurationUpdated": "A configuração do servidor foi actualizada",
|
"MessageServerConfigurationUpdated": "A configuração do servidor foi actualizada",
|
||||||
"MessageNamedServerConfigurationUpdatedWithValue": "Configurações do servidor na secção {0} foram atualizadas",
|
"MessageNamedServerConfigurationUpdatedWithValue": "As configurações do servidor na secção {0} foram atualizadas",
|
||||||
"MessageApplicationUpdatedTo": "O servidor Jellyfin foi actualizado para a versão {0}",
|
"MessageApplicationUpdatedTo": "O servidor Jellyfin foi atualizado para a versão {0}",
|
||||||
"MessageApplicationUpdated": "O servidor Jellyfin foi actualizado",
|
"MessageApplicationUpdated": "O servidor Jellyfin foi actualizado",
|
||||||
"Latest": "Mais Recente",
|
"Latest": "Mais Recente",
|
||||||
"LabelRunningTimeValue": "Duração: {0}",
|
"LabelRunningTimeValue": "Duração: {0}",
|
||||||
"LabelIpAddressValue": "Endereço IP: {0}",
|
"LabelIpAddressValue": "Endereço de IP: {0}",
|
||||||
"ItemRemovedWithName": "{0} foi removido da biblioteca",
|
"ItemRemovedWithName": "{0} foi removido da biblioteca",
|
||||||
"ItemAddedWithName": "{0} foi adicionado à biblioteca",
|
"ItemAddedWithName": "{0} foi adicionado à biblioteca",
|
||||||
"Inherit": "Herdar",
|
"Inherit": "Herdar",
|
||||||
"HomeVideos": "Vídeos Caseiros",
|
"HomeVideos": "Vídeos Caseiros",
|
||||||
"HeaderRecordingGroups": "Grupos de Gravação",
|
"HeaderRecordingGroups": "Grupos de Gravação",
|
||||||
"ValueSpecialEpisodeName": "Especial - {0}",
|
"ValueSpecialEpisodeName": "Episódio Especial - {0}",
|
||||||
"Sync": "Sincronização",
|
"Sync": "Sincronização",
|
||||||
"Songs": "Músicas",
|
"Songs": "Músicas",
|
||||||
"Shows": "Séries",
|
"Shows": "Séries",
|
||||||
"Playlists": "Listas de Reprodução",
|
"Playlists": "Listas de Reprodução",
|
||||||
"Photos": "Fotografias",
|
"Photos": "Fotografias",
|
||||||
"Movies": "Filmes",
|
"Movies": "Filmes",
|
||||||
"HeaderCameraUploads": "Envios a partir da câmara",
|
"HeaderCameraUploads": "Carregamentos a partir da câmara",
|
||||||
"FailedLoginAttemptWithUserName": "Tentativa de ligação a partir de {0} falhou",
|
"FailedLoginAttemptWithUserName": "Tentativa de ligação falhada a partir de {0}",
|
||||||
"DeviceOnlineWithName": "{0} ligou-se",
|
"DeviceOnlineWithName": "{0} está connectado",
|
||||||
"DeviceOfflineWithName": "{0} desligou-se",
|
"DeviceOfflineWithName": "{0} desconectou-se",
|
||||||
"ChapterNameValue": "Capítulo {0}",
|
"ChapterNameValue": "Capítulo {0}",
|
||||||
"CameraImageUploadedFrom": "Uma nova imagem de câmara foi enviada a partir de {0}",
|
"CameraImageUploadedFrom": "Uma nova imagem da câmara foi enviada a partir de {0}",
|
||||||
"AuthenticationSucceededWithUserName": "{0} autenticado com sucesso",
|
"AuthenticationSucceededWithUserName": "{0} autenticado com sucesso",
|
||||||
"Application": "Aplicação",
|
"Application": "Aplicação",
|
||||||
"AppDeviceValues": "Aplicação {0}, Dispositivo: {1}"
|
"AppDeviceValues": "Aplicação {0}, Dispositivo: {1}"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"Albums": "Album",
|
"Albums": "Album",
|
||||||
"AppDeviceValues": "App: {0}, Enhet: {1}",
|
"AppDeviceValues": "Applikation: {0}, Enhet: {1}",
|
||||||
"Application": "App",
|
"Application": "Applikation",
|
||||||
"Artists": "Artister",
|
"Artists": "Artister",
|
||||||
"AuthenticationSucceededWithUserName": "{0} har autentiserats",
|
"AuthenticationSucceededWithUserName": "{0} har autentiserats",
|
||||||
"Books": "Böcker",
|
"Books": "Böcker",
|
||||||
@ -16,7 +16,7 @@
|
|||||||
"Folders": "Mappar",
|
"Folders": "Mappar",
|
||||||
"Genres": "Genrer",
|
"Genres": "Genrer",
|
||||||
"HeaderAlbumArtists": "Albumartister",
|
"HeaderAlbumArtists": "Albumartister",
|
||||||
"HeaderCameraUploads": "Kamera Uppladdningar",
|
"HeaderCameraUploads": "Kamerauppladdningar",
|
||||||
"HeaderContinueWatching": "Fortsätt kolla",
|
"HeaderContinueWatching": "Fortsätt kolla",
|
||||||
"HeaderFavoriteAlbums": "Favoritalbum",
|
"HeaderFavoriteAlbums": "Favoritalbum",
|
||||||
"HeaderFavoriteArtists": "Favoritartister",
|
"HeaderFavoriteArtists": "Favoritartister",
|
||||||
@ -34,9 +34,9 @@
|
|||||||
"LabelRunningTimeValue": "Speltid: {0}",
|
"LabelRunningTimeValue": "Speltid: {0}",
|
||||||
"Latest": "Senaste",
|
"Latest": "Senaste",
|
||||||
"MessageApplicationUpdated": "Jellyfin Server har uppdaterats",
|
"MessageApplicationUpdated": "Jellyfin Server har uppdaterats",
|
||||||
"MessageApplicationUpdatedTo": "Jellyfin Server har uppgraderats till {0}",
|
"MessageApplicationUpdatedTo": "Jellyfin Server har uppdaterats till {0}",
|
||||||
"MessageNamedServerConfigurationUpdatedWithValue": "Serverinställningarna {0} har uppdaterats",
|
"MessageNamedServerConfigurationUpdatedWithValue": "Serverinställningarna {0} har uppdaterats",
|
||||||
"MessageServerConfigurationUpdated": "Server konfigurationen har uppdaterats",
|
"MessageServerConfigurationUpdated": "Serverkonfigurationen har uppdaterats",
|
||||||
"MixedContent": "Blandat innehåll",
|
"MixedContent": "Blandat innehåll",
|
||||||
"Movies": "Filmer",
|
"Movies": "Filmer",
|
||||||
"Music": "Musik",
|
"Music": "Musik",
|
||||||
@ -44,11 +44,11 @@
|
|||||||
"NameInstallFailed": "{0} installationen misslyckades",
|
"NameInstallFailed": "{0} installationen misslyckades",
|
||||||
"NameSeasonNumber": "Säsong {0}",
|
"NameSeasonNumber": "Säsong {0}",
|
||||||
"NameSeasonUnknown": "Okänd säsong",
|
"NameSeasonUnknown": "Okänd säsong",
|
||||||
"NewVersionIsAvailable": "En ny version av Jellyfin Server är klar för nedladdning.",
|
"NewVersionIsAvailable": "En ny version av Jellyfin Server är tillgänglig att hämta.",
|
||||||
"NotificationOptionApplicationUpdateAvailable": "Ny programversion tillgänglig",
|
"NotificationOptionApplicationUpdateAvailable": "Ny programversion tillgänglig",
|
||||||
"NotificationOptionApplicationUpdateInstalled": "Programuppdatering installerad",
|
"NotificationOptionApplicationUpdateInstalled": "Programuppdatering installerad",
|
||||||
"NotificationOptionAudioPlayback": "Ljuduppspelning har påbörjats",
|
"NotificationOptionAudioPlayback": "Ljuduppspelning har påbörjats",
|
||||||
"NotificationOptionAudioPlaybackStopped": "Ljuduppspelning stoppad",
|
"NotificationOptionAudioPlaybackStopped": "Ljuduppspelning stoppades",
|
||||||
"NotificationOptionCameraImageUploaded": "Kamerabild har laddats upp",
|
"NotificationOptionCameraImageUploaded": "Kamerabild har laddats upp",
|
||||||
"NotificationOptionInstallationFailed": "Fel vid installation",
|
"NotificationOptionInstallationFailed": "Fel vid installation",
|
||||||
"NotificationOptionNewLibraryContent": "Nytt innehåll har lagts till",
|
"NotificationOptionNewLibraryContent": "Nytt innehåll har lagts till",
|
||||||
@ -60,7 +60,7 @@
|
|||||||
"NotificationOptionTaskFailed": "Schemalagd aktivitet har misslyckats",
|
"NotificationOptionTaskFailed": "Schemalagd aktivitet har misslyckats",
|
||||||
"NotificationOptionUserLockedOut": "Användare har låsts ut",
|
"NotificationOptionUserLockedOut": "Användare har låsts ut",
|
||||||
"NotificationOptionVideoPlayback": "Videouppspelning har påbörjats",
|
"NotificationOptionVideoPlayback": "Videouppspelning har påbörjats",
|
||||||
"NotificationOptionVideoPlaybackStopped": "Videouppspelning stoppad",
|
"NotificationOptionVideoPlaybackStopped": "Videouppspelning stoppades",
|
||||||
"Photos": "Bilder",
|
"Photos": "Bilder",
|
||||||
"Playlists": "Spellistor",
|
"Playlists": "Spellistor",
|
||||||
"Plugin": "Tillägg",
|
"Plugin": "Tillägg",
|
||||||
@ -69,13 +69,13 @@
|
|||||||
"PluginUpdatedWithName": "{0} uppdaterades",
|
"PluginUpdatedWithName": "{0} uppdaterades",
|
||||||
"ProviderValue": "Källa: {0}",
|
"ProviderValue": "Källa: {0}",
|
||||||
"ScheduledTaskFailedWithName": "{0} misslyckades",
|
"ScheduledTaskFailedWithName": "{0} misslyckades",
|
||||||
"ScheduledTaskStartedWithName": "{0} startad",
|
"ScheduledTaskStartedWithName": "{0} startades",
|
||||||
"ServerNameNeedsToBeRestarted": "{0} behöver startas om",
|
"ServerNameNeedsToBeRestarted": "{0} behöver startas om",
|
||||||
"Shows": "Serier",
|
"Shows": "Serier",
|
||||||
"Songs": "Låtar",
|
"Songs": "Låtar",
|
||||||
"StartupEmbyServerIsLoading": "Jellyfin server arbetar. Pröva igen inom kort.",
|
"StartupEmbyServerIsLoading": "Jellyfin Server arbetar. Pröva igen snart.",
|
||||||
"SubtitleDownloadFailureForItem": "Nerladdning av undertexter för {0} misslyckades",
|
"SubtitleDownloadFailureForItem": "Nerladdning av undertexter för {0} misslyckades",
|
||||||
"SubtitleDownloadFailureFromForItem": "Undertexter misslyckades att ladda ner {0} för {1}",
|
"SubtitleDownloadFailureFromForItem": "Undertexter kunde inte laddas ner från {0} för {1}",
|
||||||
"SubtitlesDownloadedForItem": "Undertexter har laddats ner till {0}",
|
"SubtitlesDownloadedForItem": "Undertexter har laddats ner till {0}",
|
||||||
"Sync": "Synk",
|
"Sync": "Synk",
|
||||||
"System": "System",
|
"System": "System",
|
||||||
@ -89,9 +89,9 @@
|
|||||||
"UserOnlineFromDevice": "{0} är uppkopplad från {1}",
|
"UserOnlineFromDevice": "{0} är uppkopplad från {1}",
|
||||||
"UserPasswordChangedWithName": "Lösenordet för {0} har ändrats",
|
"UserPasswordChangedWithName": "Lösenordet för {0} har ändrats",
|
||||||
"UserPolicyUpdatedWithName": "Användarpolicyn har uppdaterats för {0}",
|
"UserPolicyUpdatedWithName": "Användarpolicyn har uppdaterats för {0}",
|
||||||
"UserStartedPlayingItemWithValues": "{0} har börjat spela upp {1}",
|
"UserStartedPlayingItemWithValues": "{0} spelar upp {1} på {2}",
|
||||||
"UserStoppedPlayingItemWithValues": "{0} har avslutat uppspelningen av {1}",
|
"UserStoppedPlayingItemWithValues": "{0} har avslutat uppspelningen av {1} på {2}",
|
||||||
"ValueHasBeenAddedToLibrary": "{0} har blivit tillagd till ditt mediabibliotek",
|
"ValueHasBeenAddedToLibrary": "{0} har lagts till i ditt mediebibliotek",
|
||||||
"ValueSpecialEpisodeName": "Specialavsnitt - {0}",
|
"ValueSpecialEpisodeName": "Specialavsnitt - {0}",
|
||||||
"VersionNumber": "Version {0}"
|
"VersionNumber": "Version {0}"
|
||||||
}
|
}
|
||||||
|
@ -17,14 +17,14 @@
|
|||||||
"Genres": "风格",
|
"Genres": "风格",
|
||||||
"HeaderAlbumArtists": "专辑作家",
|
"HeaderAlbumArtists": "专辑作家",
|
||||||
"HeaderCameraUploads": "相机上传",
|
"HeaderCameraUploads": "相机上传",
|
||||||
"HeaderContinueWatching": "继续观看",
|
"HeaderContinueWatching": "继续观影",
|
||||||
"HeaderFavoriteAlbums": "收藏的专辑",
|
"HeaderFavoriteAlbums": "收藏的专辑",
|
||||||
"HeaderFavoriteArtists": "最爱的艺术家",
|
"HeaderFavoriteArtists": "最爱的艺术家",
|
||||||
"HeaderFavoriteEpisodes": "最爱的剧集",
|
"HeaderFavoriteEpisodes": "最爱的剧集",
|
||||||
"HeaderFavoriteShows": "最爱的节目",
|
"HeaderFavoriteShows": "最爱的节目",
|
||||||
"HeaderFavoriteSongs": "最爱的歌曲",
|
"HeaderFavoriteSongs": "最爱的歌曲",
|
||||||
"HeaderLiveTV": "电视直播",
|
"HeaderLiveTV": "电视直播",
|
||||||
"HeaderNextUp": "下一步",
|
"HeaderNextUp": "接下来",
|
||||||
"HeaderRecordingGroups": "录制组",
|
"HeaderRecordingGroups": "录制组",
|
||||||
"HomeVideos": "家庭视频",
|
"HomeVideos": "家庭视频",
|
||||||
"Inherit": "继承",
|
"Inherit": "继承",
|
||||||
|
@ -33,14 +33,14 @@ namespace Emby.Server.Implementations.Playlists
|
|||||||
ILibraryManager libraryManager,
|
ILibraryManager libraryManager,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
ILibraryMonitor iLibraryMonitor,
|
ILibraryMonitor iLibraryMonitor,
|
||||||
ILoggerFactory loggerFactory,
|
ILogger<PlaylistManager> logger,
|
||||||
IUserManager userManager,
|
IUserManager userManager,
|
||||||
IProviderManager providerManager)
|
IProviderManager providerManager)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
_iLibraryMonitor = iLibraryMonitor;
|
_iLibraryMonitor = iLibraryMonitor;
|
||||||
_logger = loggerFactory.CreateLogger(nameof(PlaylistManager));
|
_logger = logger;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_providerManager = providerManager;
|
_providerManager = providerManager;
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,10 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="DeleteCacheFileTask" /> class.
|
/// Initializes a new instance of the <see cref="DeleteCacheFileTask" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DeleteCacheFileTask(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem)
|
public DeleteCacheFileTask(
|
||||||
|
IApplicationPaths appPaths,
|
||||||
|
ILogger<DeleteCacheFileTask> logger,
|
||||||
|
IFileSystem fileSystem)
|
||||||
{
|
{
|
||||||
ApplicationPaths = appPaths;
|
ApplicationPaths = appPaths;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
@ -23,7 +23,10 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="DeleteTranscodeFileTask" /> class.
|
/// Initializes a new instance of the <see cref="DeleteTranscodeFileTask" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DeleteTranscodeFileTask(ILogger logger, IFileSystem fileSystem, IConfigurationManager configurationManager)
|
public DeleteTranscodeFileTask(
|
||||||
|
ILogger<DeleteTranscodeFileTask> logger,
|
||||||
|
IFileSystem fileSystem,
|
||||||
|
IConfigurationManager configurationManager)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
|
@ -23,7 +23,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
|
|||||||
|
|
||||||
private readonly IInstallationManager _installationManager;
|
private readonly IInstallationManager _installationManager;
|
||||||
|
|
||||||
public PluginUpdateTask(ILogger logger, IInstallationManager installationManager)
|
public PluginUpdateTask(ILogger<PluginUpdateTask> logger, IInstallationManager installationManager)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_installationManager = installationManager;
|
_installationManager = installationManager;
|
||||||
|
@ -21,15 +21,14 @@ namespace Emby.Server.Implementations.SocketSharp
|
|||||||
private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource();
|
private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource();
|
||||||
private CancellationToken _disposeCancellationToken;
|
private CancellationToken _disposeCancellationToken;
|
||||||
|
|
||||||
public WebSocketSharpListener(
|
public WebSocketSharpListener(ILogger<WebSocketSharpListener> logger)
|
||||||
ILogger logger)
|
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
||||||
_disposeCancellationToken = _disposeCancellationTokenSource.Token;
|
_disposeCancellationToken = _disposeCancellationTokenSource.Token;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Func<Exception, IRequest, bool, bool, Task> ErrorHandler { get; set; }
|
public Func<Exception, IRequest, bool, bool, Task> ErrorHandler { get; set; }
|
||||||
|
|
||||||
public Func<IHttpRequest, string, string, string, CancellationToken, Task> RequestHandler { get; set; }
|
public Func<IHttpRequest, string, string, string, CancellationToken, Task> RequestHandler { get; set; }
|
||||||
|
|
||||||
public Action<WebSocketConnectEventArgs> WebSocketConnected { get; set; }
|
public Action<WebSocketConnectEventArgs> WebSocketConnected { get; set; }
|
||||||
|
@ -1,99 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using MediaBrowser.Controller.Sorting;
|
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.Sorting
|
|
||||||
{
|
|
||||||
public class AlphanumComparator : IComparer<string>
|
|
||||||
{
|
|
||||||
public static int CompareValues(string s1, string s2)
|
|
||||||
{
|
|
||||||
if (s1 == null || s2 == null)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int thisMarker = 0, thisNumericChunk = 0;
|
|
||||||
int thatMarker = 0, thatNumericChunk = 0;
|
|
||||||
|
|
||||||
while ((thisMarker < s1.Length) || (thatMarker < s2.Length))
|
|
||||||
{
|
|
||||||
if (thisMarker >= s1.Length)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else if (thatMarker >= s2.Length)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
char thisCh = s1[thisMarker];
|
|
||||||
char thatCh = s2[thatMarker];
|
|
||||||
|
|
||||||
var thisChunk = new StringBuilder();
|
|
||||||
var thatChunk = new StringBuilder();
|
|
||||||
|
|
||||||
while ((thisMarker < s1.Length) && (thisChunk.Length == 0 || SortHelper.InChunk(thisCh, thisChunk[0])))
|
|
||||||
{
|
|
||||||
thisChunk.Append(thisCh);
|
|
||||||
thisMarker++;
|
|
||||||
|
|
||||||
if (thisMarker < s1.Length)
|
|
||||||
{
|
|
||||||
thisCh = s1[thisMarker];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((thatMarker < s2.Length) && (thatChunk.Length == 0 || SortHelper.InChunk(thatCh, thatChunk[0])))
|
|
||||||
{
|
|
||||||
thatChunk.Append(thatCh);
|
|
||||||
thatMarker++;
|
|
||||||
|
|
||||||
if (thatMarker < s2.Length)
|
|
||||||
{
|
|
||||||
thatCh = s2[thatMarker];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int result = 0;
|
|
||||||
// If both chunks contain numeric characters, sort them numerically
|
|
||||||
if (char.IsDigit(thisChunk[0]) && char.IsDigit(thatChunk[0]))
|
|
||||||
{
|
|
||||||
if (!int.TryParse(thisChunk.ToString(), out thisNumericChunk))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!int.TryParse(thatChunk.ToString(), out thatNumericChunk))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thisNumericChunk < thatNumericChunk)
|
|
||||||
{
|
|
||||||
result = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thisNumericChunk > thatNumericChunk)
|
|
||||||
{
|
|
||||||
result = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = thisChunk.ToString().CompareTo(thatChunk.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Compare(string x, string y)
|
|
||||||
{
|
|
||||||
return CompareValues(x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -23,23 +23,20 @@ namespace Jellyfin.Server
|
|||||||
/// <param name="fileSystem">The <see cref="IFileSystem" /> to be used by the <see cref="CoreAppHost" />.</param>
|
/// <param name="fileSystem">The <see cref="IFileSystem" /> to be used by the <see cref="CoreAppHost" />.</param>
|
||||||
/// <param name="imageEncoder">The <see cref="IImageEncoder" /> to be used by the <see cref="CoreAppHost" />.</param>
|
/// <param name="imageEncoder">The <see cref="IImageEncoder" /> to be used by the <see cref="CoreAppHost" />.</param>
|
||||||
/// <param name="networkManager">The <see cref="INetworkManager" /> to be used by the <see cref="CoreAppHost" />.</param>
|
/// <param name="networkManager">The <see cref="INetworkManager" /> to be used by the <see cref="CoreAppHost" />.</param>
|
||||||
/// <param name="configuration">The <see cref="IConfiguration" /> to be used by the <see cref="CoreAppHost" />.</param>
|
|
||||||
public CoreAppHost(
|
public CoreAppHost(
|
||||||
ServerApplicationPaths applicationPaths,
|
ServerApplicationPaths applicationPaths,
|
||||||
ILoggerFactory loggerFactory,
|
ILoggerFactory loggerFactory,
|
||||||
StartupOptions options,
|
StartupOptions options,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
IImageEncoder imageEncoder,
|
IImageEncoder imageEncoder,
|
||||||
INetworkManager networkManager,
|
INetworkManager networkManager)
|
||||||
IConfiguration configuration)
|
|
||||||
: base(
|
: base(
|
||||||
applicationPaths,
|
applicationPaths,
|
||||||
loggerFactory,
|
loggerFactory,
|
||||||
options,
|
options,
|
||||||
fileSystem,
|
fileSystem,
|
||||||
imageEncoder,
|
imageEncoder,
|
||||||
networkManager,
|
networkManager)
|
||||||
configuration)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
28
Jellyfin.Server/Migrations/IMigrationRoutine.cs
Normal file
28
Jellyfin.Server/Migrations/IMigrationRoutine.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Migrations
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interface that describes a migration routine.
|
||||||
|
/// </summary>
|
||||||
|
internal interface IMigrationRoutine
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the unique id for this migration. This should never be modified after the migration has been created.
|
||||||
|
/// </summary>
|
||||||
|
public Guid Id { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the display name of the migration.
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Execute the migration routine.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="host">Host that hosts current version.</param>
|
||||||
|
/// <param name="logger">Host logger.</param>
|
||||||
|
public void Perform(CoreAppHost host, ILogger logger);
|
||||||
|
}
|
||||||
|
}
|
24
Jellyfin.Server/Migrations/MigrationOptions.cs
Normal file
24
Jellyfin.Server/Migrations/MigrationOptions.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Migrations
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Configuration part that holds all migrations that were applied.
|
||||||
|
/// </summary>
|
||||||
|
public class MigrationOptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MigrationOptions"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public MigrationOptions()
|
||||||
|
{
|
||||||
|
Applied = new List<(Guid Id, string Name)>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the list of applied migration routine names.
|
||||||
|
/// </summary>
|
||||||
|
public List<(Guid Id, string Name)> Applied { get; }
|
||||||
|
}
|
||||||
|
}
|
73
Jellyfin.Server/Migrations/MigrationRunner.cs
Normal file
73
Jellyfin.Server/Migrations/MigrationRunner.cs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using MediaBrowser.Common.Configuration;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Migrations
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The class that knows which migrations to apply and how to apply them.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class MigrationRunner
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The list of known migrations, in order of applicability.
|
||||||
|
/// </summary>
|
||||||
|
internal static readonly IMigrationRoutine[] Migrations =
|
||||||
|
{
|
||||||
|
new Routines.DisableTranscodingThrottling(),
|
||||||
|
new Routines.CreateUserLoggingConfigFile()
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Run all needed migrations.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="host">CoreAppHost that hosts current version.</param>
|
||||||
|
/// <param name="loggerFactory">Factory for making the logger.</param>
|
||||||
|
public static void Run(CoreAppHost host, ILoggerFactory loggerFactory)
|
||||||
|
{
|
||||||
|
var logger = loggerFactory.CreateLogger<MigrationRunner>();
|
||||||
|
var migrationOptions = ((IConfigurationManager)host.ServerConfigurationManager).GetConfiguration<MigrationOptions>(MigrationsListStore.StoreKey);
|
||||||
|
|
||||||
|
if (!host.ServerConfigurationManager.Configuration.IsStartupWizardCompleted && migrationOptions.Applied.Count == 0)
|
||||||
|
{
|
||||||
|
// If startup wizard is not finished, this is a fresh install.
|
||||||
|
// Don't run any migrations, just mark all of them as applied.
|
||||||
|
logger.LogInformation("Marking all known migrations as applied because this is a fresh install");
|
||||||
|
migrationOptions.Applied.AddRange(Migrations.Select(m => (m.Id, m.Name)));
|
||||||
|
host.ServerConfigurationManager.SaveConfiguration(MigrationsListStore.StoreKey, migrationOptions);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var appliedMigrationIds = migrationOptions.Applied.Select(m => m.Id).ToHashSet();
|
||||||
|
|
||||||
|
for (var i = 0; i < Migrations.Length; i++)
|
||||||
|
{
|
||||||
|
var migrationRoutine = Migrations[i];
|
||||||
|
if (appliedMigrationIds.Contains(migrationRoutine.Id))
|
||||||
|
{
|
||||||
|
logger.LogDebug("Skipping migration '{Name}' since it is already applied", migrationRoutine.Name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.LogInformation("Applying migration '{Name}'", migrationRoutine.Name);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
migrationRoutine.Perform(host, logger);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.LogError(ex, "Could not apply migration '{Name}'", migrationRoutine.Name);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark the migration as completed
|
||||||
|
logger.LogInformation("Migration '{Name}' applied successfully", migrationRoutine.Name);
|
||||||
|
migrationOptions.Applied.Add((migrationRoutine.Id, migrationRoutine.Name));
|
||||||
|
host.ServerConfigurationManager.SaveConfiguration(MigrationsListStore.StoreKey, migrationOptions);
|
||||||
|
logger.LogDebug("Migration '{Name}' marked as applied in configuration.", migrationRoutine.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
Jellyfin.Server/Migrations/MigrationsFactory.cs
Normal file
20
Jellyfin.Server/Migrations/MigrationsFactory.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using MediaBrowser.Common.Configuration;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Migrations
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A factory that can find a persistent file of the migration configuration, which lists all applied migrations.
|
||||||
|
/// </summary>
|
||||||
|
public class MigrationsFactory : IConfigurationFactory
|
||||||
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IEnumerable<ConfigurationStore> GetConfigurations()
|
||||||
|
{
|
||||||
|
return new[]
|
||||||
|
{
|
||||||
|
new MigrationsListStore()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
Jellyfin.Server/Migrations/MigrationsListStore.cs
Normal file
24
Jellyfin.Server/Migrations/MigrationsListStore.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using MediaBrowser.Common.Configuration;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Migrations
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A configuration that lists all the migration routines that were applied.
|
||||||
|
/// </summary>
|
||||||
|
public class MigrationsListStore : ConfigurationStore
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the configuration in the storage.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly string StoreKey = "migrations";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MigrationsListStore"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public MigrationsListStore()
|
||||||
|
{
|
||||||
|
ConfigurationType = typeof(MigrationOptions);
|
||||||
|
Key = StoreKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using MediaBrowser.Common.Configuration;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Migrations.Routines
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Migration to initialize the user logging configuration file "logging.user.json".
|
||||||
|
/// If the deprecated logging.json file exists and has a custom config, it will be used as logging.user.json,
|
||||||
|
/// otherwise a blank file will be created.
|
||||||
|
/// </summary>
|
||||||
|
internal class CreateUserLoggingConfigFile : IMigrationRoutine
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// File history for logging.json as existed during this migration creation. The contents for each has been minified.
|
||||||
|
/// </summary>
|
||||||
|
private readonly List<string> _defaultConfigHistory = new List<string>
|
||||||
|
{
|
||||||
|
// 9a6c27947353585391e211aa88b925f81e8cd7b9
|
||||||
|
@"{""Serilog"":{""MinimumLevel"":{""Default"":""Information"",""Override"":{""Microsoft"":""Warning"",""System"":""Warning""}},""WriteTo"":[{""Name"":""Console"",""Args"":{""outputTemplate"":""[{Timestamp:HH:mm:ss}] [{Level:u3}] [{ThreadId}] {SourceContext}: {Message:lj}{NewLine}{Exception}""}},{""Name"":""Async"",""Args"":{""configure"":[{""Name"":""File"",""Args"":{""path"":""%JELLYFIN_LOG_DIR%//log_.log"",""rollingInterval"":""Day"",""retainedFileCountLimit"":3,""rollOnFileSizeLimit"":true,""fileSizeLimitBytes"":100000000,""outputTemplate"":""[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] [{ThreadId}] {SourceContext}: {Message}{NewLine}{Exception}""}}]}}],""Enrich"":[""FromLogContext"",""WithThreadId""]}}",
|
||||||
|
// 71bdcd730705a714ee208eaad7290b7c68df3885
|
||||||
|
@"{""Serilog"":{""MinimumLevel"":""Information"",""WriteTo"":[{""Name"":""Console"",""Args"":{""outputTemplate"":""[{Timestamp:HH:mm:ss}] [{Level:u3}] [{ThreadId}] {SourceContext}: {Message:lj}{NewLine}{Exception}""}},{""Name"":""Async"",""Args"":{""configure"":[{""Name"":""File"",""Args"":{""path"":""%JELLYFIN_LOG_DIR%//log_.log"",""rollingInterval"":""Day"",""retainedFileCountLimit"":3,""rollOnFileSizeLimit"":true,""fileSizeLimitBytes"":100000000,""outputTemplate"":""[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] [{ThreadId}] {SourceContext}: {Message}{NewLine}{Exception}""}}]}}],""Enrich"":[""FromLogContext"",""WithThreadId""]}}",
|
||||||
|
// a44936f97f8afc2817d3491615a7cfe1e31c251c
|
||||||
|
@"{""Serilog"":{""MinimumLevel"":""Information"",""WriteTo"":[{""Name"":""Console"",""Args"":{""outputTemplate"":""[{Timestamp:HH:mm:ss}] [{Level:u3}] {Message:lj}{NewLine}{Exception}""}},{""Name"":""File"",""Args"":{""path"":""%JELLYFIN_LOG_DIR%//log_.log"",""rollingInterval"":""Day"",""outputTemplate"":""[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message}{NewLine}{Exception}""}}]}}",
|
||||||
|
// 7af3754a11ad5a4284f107997fb5419a010ce6f3
|
||||||
|
@"{""Serilog"":{""MinimumLevel"":""Information"",""WriteTo"":[{""Name"":""Console"",""Args"":{""outputTemplate"":""[{Timestamp:HH:mm:ss}] [{Level:u3}] {Message:lj}{NewLine}{Exception}""}},{""Name"":""Async"",""Args"":{""configure"":[{""Name"":""File"",""Args"":{""path"":""%JELLYFIN_LOG_DIR%//log_.log"",""rollingInterval"":""Day"",""outputTemplate"":""[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message}{NewLine}{Exception}""}}]}}]}}",
|
||||||
|
// 60691349a11f541958e0b2247c9abc13cb40c9fb
|
||||||
|
@"{""Serilog"":{""MinimumLevel"":""Information"",""WriteTo"":[{""Name"":""Console"",""Args"":{""outputTemplate"":""[{Timestamp:HH:mm:ss}] [{Level:u3}] {Message:lj}{NewLine}{Exception}""}},{""Name"":""Async"",""Args"":{""configure"":[{""Name"":""File"",""Args"":{""path"":""%JELLYFIN_LOG_DIR%//log_.log"",""rollingInterval"":""Day"",""retainedFileCountLimit"":3,""rollOnFileSizeLimit"":true,""fileSizeLimitBytes"":100000000,""outputTemplate"":""[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message}{NewLine}{Exception}""}}]}}]}}",
|
||||||
|
// 65fe243afbcc4b596cf8726708c1965cd34b5f68
|
||||||
|
@"{""Serilog"":{""MinimumLevel"":""Information"",""WriteTo"":[{""Name"":""Console"",""Args"":{""outputTemplate"":""[{Timestamp:HH:mm:ss}] [{Level:u3}] {ThreadId} {SourceContext}: {Message:lj} {NewLine}{Exception}""}},{""Name"":""Async"",""Args"":{""configure"":[{""Name"":""File"",""Args"":{""path"":""%JELLYFIN_LOG_DIR%//log_.log"",""rollingInterval"":""Day"",""retainedFileCountLimit"":3,""rollOnFileSizeLimit"":true,""fileSizeLimitBytes"":100000000,""outputTemplate"":""[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {ThreadId} {SourceContext}:{Message} {NewLine}{Exception}""}}]}}],""Enrich"":[""FromLogContext"",""WithThreadId""]}}",
|
||||||
|
// 96c9af590494aa8137d5a061aaf1e68feee60b67
|
||||||
|
@"{""Serilog"":{""MinimumLevel"":""Information"",""WriteTo"":[{""Name"":""Console"",""Args"":{""outputTemplate"":""[{Timestamp:HH:mm:ss}] [{Level:u3}] [{ThreadId}] {SourceContext}: {Message:lj}{NewLine}{Exception}""}},{""Name"":""Async"",""Args"":{""configure"":[{""Name"":""File"",""Args"":{""path"":""%JELLYFIN_LOG_DIR%//log_.log"",""rollingInterval"":""Day"",""retainedFileCountLimit"":3,""rollOnFileSizeLimit"":true,""fileSizeLimitBytes"":100000000,""outputTemplate"":""[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] [{ThreadId}] {SourceContext}:{Message}{NewLine}{Exception}""}}]}}],""Enrich"":[""FromLogContext"",""WithThreadId""]}}",
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public Guid Id => Guid.Parse("{EF103419-8451-40D8-9F34-D1A8E93A1679}");
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string Name => "CreateLoggingConfigHeirarchy";
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Perform(CoreAppHost host, ILogger logger)
|
||||||
|
{
|
||||||
|
var logDirectory = host.Resolve<IApplicationPaths>().ConfigurationDirectoryPath;
|
||||||
|
var existingConfigPath = Path.Combine(logDirectory, "logging.json");
|
||||||
|
|
||||||
|
// If the existing logging.json config file is unmodified, then 'reset' it by moving it to 'logging.old.json'
|
||||||
|
// NOTE: This config file has 'reloadOnChange: true', so this change will take effect immediately even though it has already been loaded
|
||||||
|
if (File.Exists(existingConfigPath) && ExistingConfigUnmodified(existingConfigPath))
|
||||||
|
{
|
||||||
|
File.Move(existingConfigPath, Path.Combine(logDirectory, "logging.old.json"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if the existing logging.json file has not been modified by the user by comparing it to all the
|
||||||
|
/// versions in our git history. Until now, the file has never been migrated after first creation so users
|
||||||
|
/// could have any version from the git history.
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="IOException"><paramref name="oldConfigPath"/> does not exist or could not be read.</exception>
|
||||||
|
private bool ExistingConfigUnmodified(string oldConfigPath)
|
||||||
|
{
|
||||||
|
var existingConfigJson = JToken.Parse(File.ReadAllText(oldConfigPath));
|
||||||
|
return _defaultConfigHistory
|
||||||
|
.Select(historicalConfigText => JToken.Parse(historicalConfigText))
|
||||||
|
.Any(historicalConfigJson => JToken.DeepEquals(existingConfigJson, historicalConfigJson));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using MediaBrowser.Common.Configuration;
|
||||||
|
using MediaBrowser.Model.Configuration;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Migrations.Routines
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Disable transcode throttling for all installations since it is currently broken for certain video formats.
|
||||||
|
/// </summary>
|
||||||
|
internal class DisableTranscodingThrottling : IMigrationRoutine
|
||||||
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public Guid Id => Guid.Parse("{4124C2CD-E939-4FFB-9BE9-9B311C413638}");
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string Name => "DisableTranscodingThrottling";
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Perform(CoreAppHost host, ILogger logger)
|
||||||
|
{
|
||||||
|
// Set EnableThrottling to false since it wasn't used before and may introduce issues
|
||||||
|
var encoding = ((IConfigurationManager)host.ServerConfigurationManager).GetConfiguration<EncodingOptions>("encoding");
|
||||||
|
if (encoding.EnableThrottling)
|
||||||
|
{
|
||||||
|
logger.LogInformation("Disabling transcoding throttling during migration");
|
||||||
|
encoding.EnableThrottling = false;
|
||||||
|
|
||||||
|
host.ServerConfigurationManager.SaveConfiguration("encoding", encoding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -27,6 +27,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Logging.Abstractions;
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
using Serilog.Events;
|
||||||
using Serilog.Extensions.Logging;
|
using Serilog.Extensions.Logging;
|
||||||
using SQLitePCL;
|
using SQLitePCL;
|
||||||
using ILogger = Microsoft.Extensions.Logging.ILogger;
|
using ILogger = Microsoft.Extensions.Logging.ILogger;
|
||||||
@ -38,6 +39,16 @@ namespace Jellyfin.Server
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class Program
|
public static class Program
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The name of logging configuration file containing application defaults.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly string LoggingConfigFileDefault = "logging.default.json";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the logging configuration file containing the system-specific override settings.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly string LoggingConfigFileSystem = "logging.json";
|
||||||
|
|
||||||
private static readonly CancellationTokenSource _tokenSource = new CancellationTokenSource();
|
private static readonly CancellationTokenSource _tokenSource = new CancellationTokenSource();
|
||||||
private static readonly ILoggerFactory _loggerFactory = new SerilogLoggerFactory();
|
private static readonly ILoggerFactory _loggerFactory = new SerilogLoggerFactory();
|
||||||
private static ILogger _logger = NullLogger.Instance;
|
private static ILogger _logger = NullLogger.Instance;
|
||||||
@ -102,10 +113,12 @@ namespace Jellyfin.Server
|
|||||||
// $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager
|
// $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager
|
||||||
Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", appPaths.LogDirectoryPath);
|
Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", appPaths.LogDirectoryPath);
|
||||||
|
|
||||||
IConfiguration appConfig = await CreateConfiguration(appPaths).ConfigureAwait(false);
|
// Create an instance of the application configuration to use for application startup
|
||||||
|
await InitLoggingConfigFile(appPaths).ConfigureAwait(false);
|
||||||
CreateLogger(appConfig, appPaths);
|
IConfiguration startupConfig = CreateAppConfiguration(appPaths);
|
||||||
|
|
||||||
|
// Initialize logging framework
|
||||||
|
InitializeLoggingFramework(startupConfig, appPaths);
|
||||||
_logger = _loggerFactory.CreateLogger("Main");
|
_logger = _loggerFactory.CreateLogger("Main");
|
||||||
|
|
||||||
// Log uncaught exceptions to the logging instead of std error
|
// Log uncaught exceptions to the logging instead of std error
|
||||||
@ -170,22 +183,22 @@ namespace Jellyfin.Server
|
|||||||
options,
|
options,
|
||||||
new ManagedFileSystem(_loggerFactory.CreateLogger<ManagedFileSystem>(), appPaths),
|
new ManagedFileSystem(_loggerFactory.CreateLogger<ManagedFileSystem>(), appPaths),
|
||||||
GetImageEncoder(appPaths),
|
GetImageEncoder(appPaths),
|
||||||
new NetworkManager(_loggerFactory.CreateLogger<NetworkManager>()),
|
new NetworkManager(_loggerFactory.CreateLogger<NetworkManager>()));
|
||||||
appConfig);
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ServiceCollection serviceCollection = new ServiceCollection();
|
ServiceCollection serviceCollection = new ServiceCollection();
|
||||||
await appHost.InitAsync(serviceCollection).ConfigureAwait(false);
|
await appHost.InitAsync(serviceCollection, startupConfig).ConfigureAwait(false);
|
||||||
|
|
||||||
var host = CreateWebHostBuilder(appHost, serviceCollection, appConfig).Build();
|
var webHost = CreateWebHostBuilder(appHost, serviceCollection, startupConfig, appPaths).Build();
|
||||||
|
|
||||||
// A bit hacky to re-use service provider since ASP.NET doesn't allow a custom service collection.
|
// A bit hacky to re-use service provider since ASP.NET doesn't allow a custom service collection.
|
||||||
appHost.ServiceProvider = host.Services;
|
appHost.ServiceProvider = webHost.Services;
|
||||||
appHost.FindParts();
|
appHost.FindParts();
|
||||||
|
Migrations.MigrationRunner.Run(appHost, _loggerFactory);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await host.StartAsync().ConfigureAwait(false);
|
await webHost.StartAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@ -221,7 +234,11 @@ namespace Jellyfin.Server
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IWebHostBuilder CreateWebHostBuilder(ApplicationHost appHost, IServiceCollection serviceCollection, IConfiguration appConfig)
|
private static IWebHostBuilder CreateWebHostBuilder(
|
||||||
|
ApplicationHost appHost,
|
||||||
|
IServiceCollection serviceCollection,
|
||||||
|
IConfiguration startupConfig,
|
||||||
|
IApplicationPaths appPaths)
|
||||||
{
|
{
|
||||||
var webhostBuilder = new WebHostBuilder()
|
var webhostBuilder = new WebHostBuilder()
|
||||||
.UseKestrel(options =>
|
.UseKestrel(options =>
|
||||||
@ -261,6 +278,8 @@ namespace Jellyfin.Server
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.ConfigureAppConfiguration(config => config.ConfigureAppConfiguration(appPaths))
|
||||||
|
.UseSerilog()
|
||||||
.ConfigureServices(services =>
|
.ConfigureServices(services =>
|
||||||
{
|
{
|
||||||
// Merge the external ServiceCollection into ASP.NET DI
|
// Merge the external ServiceCollection into ASP.NET DI
|
||||||
@ -268,7 +287,7 @@ namespace Jellyfin.Server
|
|||||||
})
|
})
|
||||||
.UseStartup<Startup>();
|
.UseStartup<Startup>();
|
||||||
|
|
||||||
if (!appConfig.IsNoWebContent())
|
if (!startupConfig.IsNoWebContent())
|
||||||
{
|
{
|
||||||
// Fail startup if the web content does not exist
|
// Fail startup if the web content does not exist
|
||||||
if (!Directory.Exists(appHost.ContentRoot) || !Directory.GetFiles(appHost.ContentRoot).Any())
|
if (!Directory.Exists(appHost.ContentRoot) || !Directory.GetFiles(appHost.ContentRoot).Any())
|
||||||
@ -448,28 +467,39 @@ namespace Jellyfin.Server
|
|||||||
return new ServerApplicationPaths(dataDir, logDir, configDir, cacheDir, webDir);
|
return new ServerApplicationPaths(dataDir, logDir, configDir, cacheDir, webDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<IConfiguration> CreateConfiguration(IApplicationPaths appPaths)
|
/// <summary>
|
||||||
|
/// Initialize the logging configuration file using the bundled resource file as a default if it doesn't exist
|
||||||
|
/// already.
|
||||||
|
/// </summary>
|
||||||
|
private static async Task InitLoggingConfigFile(IApplicationPaths appPaths)
|
||||||
{
|
{
|
||||||
const string ResourcePath = "Jellyfin.Server.Resources.Configuration.logging.json";
|
// Do nothing if the config file already exists
|
||||||
string configPath = Path.Combine(appPaths.ConfigurationDirectoryPath, "logging.json");
|
string configPath = Path.Combine(appPaths.ConfigurationDirectoryPath, LoggingConfigFileDefault);
|
||||||
|
if (File.Exists(configPath))
|
||||||
if (!File.Exists(configPath))
|
|
||||||
{
|
{
|
||||||
// For some reason the csproj name is used instead of the assembly name
|
return;
|
||||||
await using Stream? resource = typeof(Program).Assembly.GetManifestResourceStream(ResourcePath);
|
|
||||||
if (resource == null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException(
|
|
||||||
string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
"Invalid resource path: '{0}'",
|
|
||||||
ResourcePath));
|
|
||||||
}
|
|
||||||
|
|
||||||
await using Stream dst = File.Open(configPath, FileMode.CreateNew);
|
|
||||||
await resource.CopyToAsync(dst).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get a stream of the resource contents
|
||||||
|
// NOTE: The .csproj name is used instead of the assembly name in the resource path
|
||||||
|
const string ResourcePath = "Jellyfin.Server.Resources.Configuration.logging.json";
|
||||||
|
await using Stream? resource = typeof(Program).Assembly.GetManifestResourceStream(ResourcePath)
|
||||||
|
?? throw new InvalidOperationException($"Invalid resource path: '{ResourcePath}'");
|
||||||
|
|
||||||
|
// Copy the resource contents to the expected file path for the config file
|
||||||
|
await using Stream dst = File.Open(configPath, FileMode.CreateNew);
|
||||||
|
await resource.CopyToAsync(dst).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IConfiguration CreateAppConfiguration(IApplicationPaths appPaths)
|
||||||
|
{
|
||||||
|
return new ConfigurationBuilder()
|
||||||
|
.ConfigureAppConfiguration(appPaths)
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IConfigurationBuilder ConfigureAppConfiguration(this IConfigurationBuilder config, IApplicationPaths appPaths)
|
||||||
|
{
|
||||||
// Use the swagger API page as the default redirect path if not hosting the jellyfin-web content
|
// Use the swagger API page as the default redirect path if not hosting the jellyfin-web content
|
||||||
var inMemoryDefaultConfig = ConfigurationOptions.DefaultConfiguration;
|
var inMemoryDefaultConfig = ConfigurationOptions.DefaultConfiguration;
|
||||||
if (string.IsNullOrEmpty(appPaths.WebPath))
|
if (string.IsNullOrEmpty(appPaths.WebPath))
|
||||||
@ -477,15 +507,18 @@ namespace Jellyfin.Server
|
|||||||
inMemoryDefaultConfig[HttpListenerHost.DefaultRedirectKey] = "swagger/index.html";
|
inMemoryDefaultConfig[HttpListenerHost.DefaultRedirectKey] = "swagger/index.html";
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ConfigurationBuilder()
|
return config
|
||||||
.SetBasePath(appPaths.ConfigurationDirectoryPath)
|
.SetBasePath(appPaths.ConfigurationDirectoryPath)
|
||||||
.AddInMemoryCollection(inMemoryDefaultConfig)
|
.AddInMemoryCollection(inMemoryDefaultConfig)
|
||||||
.AddJsonFile("logging.json", false, true)
|
.AddJsonFile(LoggingConfigFileDefault, optional: false, reloadOnChange: true)
|
||||||
.AddEnvironmentVariables("JELLYFIN_")
|
.AddJsonFile(LoggingConfigFileSystem, optional: true, reloadOnChange: true)
|
||||||
.Build();
|
.AddEnvironmentVariables("JELLYFIN_");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CreateLogger(IConfiguration configuration, IApplicationPaths appPaths)
|
/// <summary>
|
||||||
|
/// Initialize Serilog using configuration and fall back to defaults on failure.
|
||||||
|
/// </summary>
|
||||||
|
private static void InitializeLoggingFramework(IConfiguration configuration, IApplicationPaths appPaths)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
{
|
{
|
||||||
"Serilog": {
|
"Serilog": {
|
||||||
"MinimumLevel": "Information",
|
"MinimumLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Override": {
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"System": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
"WriteTo": [
|
"WriteTo": [
|
||||||
{
|
{
|
||||||
"Name": "Console",
|
"Name": "Console",
|
||||||
|
@ -61,7 +61,7 @@ namespace MediaBrowser.Api
|
|||||||
/// <param name="fileSystem">The file system.</param>
|
/// <param name="fileSystem">The file system.</param>
|
||||||
/// <param name="mediaSourceManager">The media source manager.</param>
|
/// <param name="mediaSourceManager">The media source manager.</param>
|
||||||
public ApiEntryPoint(
|
public ApiEntryPoint(
|
||||||
ILogger logger,
|
ILogger<ApiEntryPoint> logger,
|
||||||
ISessionManager sessionManager,
|
ISessionManager sessionManager,
|
||||||
IServerConfigurationManager config,
|
IServerConfigurationManager config,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
|
@ -815,7 +815,7 @@ namespace MediaBrowser.Api.Library
|
|||||||
if (!string.IsNullOrWhiteSpace(filename))
|
if (!string.IsNullOrWhiteSpace(filename))
|
||||||
{
|
{
|
||||||
// Kestrel doesn't support non-ASCII characters in headers
|
// Kestrel doesn't support non-ASCII characters in headers
|
||||||
if (Regex.IsMatch(filename, "[^[:ascii:]]"))
|
if (Regex.IsMatch(filename, @"[^\p{IsBasicLatin}]"))
|
||||||
{
|
{
|
||||||
// Manually encoding non-ASCII characters, following https://tools.ietf.org/html/rfc5987#section-3.2.2
|
// Manually encoding non-ASCII characters, following https://tools.ietf.org/html/rfc5987#section-3.2.2
|
||||||
headers[HeaderNames.ContentDisposition] = "attachment; filename*=UTF-8''" + WebUtility.UrlEncode(filename);
|
headers[HeaderNames.ContentDisposition] = "attachment; filename*=UTF-8''" + WebUtility.UrlEncode(filename);
|
||||||
|
@ -573,7 +573,8 @@ namespace MediaBrowser.Api.Playback
|
|||||||
{
|
{
|
||||||
attachment.DeliveryUrl = string.Format(
|
attachment.DeliveryUrl = string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
"/Videos/{0}/{1}/Attachments/{2}",
|
"{0}/Videos/{1}/{2}/Attachments/{3}",
|
||||||
|
ServerConfigurationManager.Configuration.BaseUrl,
|
||||||
item.Id,
|
item.Id,
|
||||||
mediaSource.Id,
|
mediaSource.Id,
|
||||||
attachment.Index);
|
attachment.Index);
|
||||||
|
@ -28,7 +28,7 @@ namespace MediaBrowser.Api.ScheduledTasks
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ScheduledTasksWebSocketListener" /> class.
|
/// Initializes a new instance of the <see cref="ScheduledTasksWebSocketListener" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ScheduledTasksWebSocketListener(ILogger logger, ITaskManager taskManager)
|
public ScheduledTasksWebSocketListener(ILogger<ScheduledTasksWebSocketListener> logger, ITaskManager taskManager)
|
||||||
: base(logger)
|
: base(logger)
|
||||||
{
|
{
|
||||||
TaskManager = taskManager;
|
TaskManager = taskManager;
|
||||||
|
@ -26,7 +26,7 @@ namespace MediaBrowser.Api.Sessions
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="SessionInfoWebSocketListener"/> class.
|
/// Initializes a new instance of the <see cref="SessionInfoWebSocketListener"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SessionInfoWebSocketListener(ILogger logger, ISessionManager sessionManager)
|
public SessionInfoWebSocketListener(ILogger<SessionInfoWebSocketListener> logger, ISessionManager sessionManager)
|
||||||
: base(logger)
|
: base(logger)
|
||||||
{
|
{
|
||||||
_sessionManager = sessionManager;
|
_sessionManager = sessionManager;
|
||||||
|
@ -23,7 +23,7 @@ namespace MediaBrowser.Api.System
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly IActivityManager _activityManager;
|
private readonly IActivityManager _activityManager;
|
||||||
|
|
||||||
public ActivityLogWebSocketListener(ILogger logger, IActivityManager activityManager) : base(logger)
|
public ActivityLogWebSocketListener(ILogger<ActivityLogWebSocketListener> logger, IActivityManager activityManager) : base(logger)
|
||||||
{
|
{
|
||||||
_activityManager = activityManager;
|
_activityManager = activityManager;
|
||||||
_activityManager.EntryCreated += _activityManager_EntryCreated;
|
_activityManager.EntryCreated += _activityManager_EntryCreated;
|
||||||
|
@ -16,12 +16,23 @@ namespace MediaBrowser.Common.Extensions
|
|||||||
/// <param name="list">The list that should get shuffled.</param>
|
/// <param name="list">The list that should get shuffled.</param>
|
||||||
/// <typeparam name="T">The type.</typeparam>
|
/// <typeparam name="T">The type.</typeparam>
|
||||||
public static void Shuffle<T>(this IList<T> list)
|
public static void Shuffle<T>(this IList<T> list)
|
||||||
|
{
|
||||||
|
list.Shuffle(_rng);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shuffles the items in a list.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="list">The list that should get shuffled.</param>
|
||||||
|
/// <param name="rng">The random number generator to use.</param>
|
||||||
|
/// <typeparam name="T">The type.</typeparam>
|
||||||
|
public static void Shuffle<T>(this IList<T> list, Random rng)
|
||||||
{
|
{
|
||||||
int n = list.Count;
|
int n = list.Count;
|
||||||
while (n > 1)
|
while (n > 1)
|
||||||
{
|
{
|
||||||
n--;
|
n--;
|
||||||
int k = _rng.Next(n + 1);
|
int k = rng.Next(n + 1);
|
||||||
T value = list[k];
|
T value = list[k];
|
||||||
list[k] = list[n];
|
list[k] = list[n];
|
||||||
list[n] = value;
|
list[n] = value;
|
||||||
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Plugins;
|
using MediaBrowser.Common.Plugins;
|
||||||
using MediaBrowser.Model.Updates;
|
using MediaBrowser.Model.Updates;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace MediaBrowser.Common
|
namespace MediaBrowser.Common
|
||||||
@ -121,11 +122,12 @@ namespace MediaBrowser.Common
|
|||||||
void RemovePlugin(IPlugin plugin);
|
void RemovePlugin(IPlugin plugin);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Inits this instance.
|
/// Initializes this instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="serviceCollection">The service collection.</param>
|
/// <param name="serviceCollection">The service collection.</param>
|
||||||
|
/// <param name="startupConfig">The configuration to use for initialization.</param>
|
||||||
/// <returns>A task.</returns>
|
/// <returns>A task.</returns>
|
||||||
Task InitAsync(IServiceCollection serviceCollection);
|
Task InitAsync(IServiceCollection serviceCollection, IConfiguration startupConfig);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates the instance.
|
/// Creates the instance.
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.1" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.1" />
|
||||||
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.2.8" />
|
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.2.8" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -198,6 +198,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.RequiresRefresh();
|
return base.RequiresRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class BaseItem
|
/// Class BaseItem
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class BaseItem : IHasProviderIds, IHasLookupInfo<ItemLookupInfo>
|
public abstract class BaseItem : IHasProviderIds, IHasLookupInfo<ItemLookupInfo>, IEquatable<BaseItem>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The supported image extensions
|
/// The supported image extensions
|
||||||
@ -387,15 +387,12 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
while (thisMarker < s1.Length)
|
while (thisMarker < s1.Length)
|
||||||
{
|
{
|
||||||
if (thisMarker >= s1.Length)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
char thisCh = s1[thisMarker];
|
char thisCh = s1[thisMarker];
|
||||||
|
|
||||||
var thisChunk = new StringBuilder();
|
var thisChunk = new StringBuilder();
|
||||||
|
bool isNumeric = char.IsDigit(thisCh);
|
||||||
|
|
||||||
while ((thisMarker < s1.Length) && (thisChunk.Length == 0 || SortHelper.InChunk(thisCh, thisChunk[0])))
|
while (thisMarker < s1.Length && char.IsDigit(thisCh) == isNumeric)
|
||||||
{
|
{
|
||||||
thisChunk.Append(thisCh);
|
thisChunk.Append(thisCh);
|
||||||
thisMarker++;
|
thisMarker++;
|
||||||
@ -406,7 +403,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var isNumeric = thisChunk.Length > 0 && char.IsDigit(thisChunk[0]);
|
|
||||||
list.Add(new Tuple<StringBuilder, bool>(thisChunk, isNumeric));
|
list.Add(new Tuple<StringBuilder, bool>(thisChunk, isNumeric));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2918,5 +2914,17 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
public static readonly IReadOnlyCollection<ExtraType> DisplayExtraTypes = new[] { Model.Entities.ExtraType.BehindTheScenes, Model.Entities.ExtraType.Clip, Model.Entities.ExtraType.DeletedScene, Model.Entities.ExtraType.Interview, Model.Entities.ExtraType.Sample, Model.Entities.ExtraType.Scene };
|
public static readonly IReadOnlyCollection<ExtraType> DisplayExtraTypes = new[] { Model.Entities.ExtraType.BehindTheScenes, Model.Entities.ExtraType.Clip, Model.Entities.ExtraType.DeletedScene, Model.Entities.ExtraType.Interview, Model.Entities.ExtraType.Sample, Model.Entities.ExtraType.Scene };
|
||||||
|
|
||||||
public virtual bool SupportsExternalTransfer => false;
|
public virtual bool SupportsExternalTransfer => false;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
return obj is BaseItem baseItem && this.Equals(baseItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public bool Equals(BaseItem item) => Object.Equals(Id, item?.Id);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override int GetHashCode() => HashCode.Combine(Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -322,10 +322,10 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
ProviderManager.OnRefreshProgress(this, 5);
|
ProviderManager.OnRefreshProgress(this, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
//build a dictionary of the current children we have now by Id so we can compare quickly and easily
|
// Build a dictionary of the current children we have now by Id so we can compare quickly and easily
|
||||||
var currentChildren = GetActualChildrenDictionary();
|
var currentChildren = GetActualChildrenDictionary();
|
||||||
|
|
||||||
//create a list for our validated children
|
// Create a list for our validated children
|
||||||
var newItems = new List<BaseItem>();
|
var newItems = new List<BaseItem>();
|
||||||
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
@ -391,7 +391,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
var folder = this;
|
var folder = this;
|
||||||
innerProgress.RegisterAction(p =>
|
innerProgress.RegisterAction(p =>
|
||||||
{
|
{
|
||||||
double newPct = .80 * p + 10;
|
double newPct = 0.80 * p + 10;
|
||||||
progress.Report(newPct);
|
progress.Report(newPct);
|
||||||
ProviderManager.OnRefreshProgress(folder, newPct);
|
ProviderManager.OnRefreshProgress(folder, newPct);
|
||||||
});
|
});
|
||||||
@ -421,7 +421,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
var folder = this;
|
var folder = this;
|
||||||
innerProgress.RegisterAction(p =>
|
innerProgress.RegisterAction(p =>
|
||||||
{
|
{
|
||||||
double newPct = .10 * p + 90;
|
double newPct = 0.10 * p + 90;
|
||||||
progress.Report(newPct);
|
progress.Report(newPct);
|
||||||
if (recursive)
|
if (recursive)
|
||||||
{
|
{
|
||||||
@ -807,11 +807,45 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static BaseItem[] SortItemsByRequest(InternalItemsQuery query, IReadOnlyList<BaseItem> items)
|
||||||
|
{
|
||||||
|
var ids = query.ItemIds;
|
||||||
|
int size = items.Count;
|
||||||
|
|
||||||
|
// ids can potentially contain non-unique guids, but query result cannot,
|
||||||
|
// so we include only first occurrence of each guid
|
||||||
|
var positions = new Dictionary<Guid, int>(size);
|
||||||
|
int index = 0;
|
||||||
|
for (int i = 0; i < ids.Length; i++)
|
||||||
|
{
|
||||||
|
if (positions.TryAdd(ids[i], index))
|
||||||
|
{
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var newItems = new BaseItem[size];
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
var item = items[i];
|
||||||
|
newItems[positions[item.Id]] = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newItems;
|
||||||
|
}
|
||||||
|
|
||||||
public QueryResult<BaseItem> GetItems(InternalItemsQuery query)
|
public QueryResult<BaseItem> GetItems(InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
if (query.ItemIds.Length > 0)
|
if (query.ItemIds.Length > 0)
|
||||||
{
|
{
|
||||||
return LibraryManager.GetItemsResult(query);
|
var result = LibraryManager.GetItemsResult(query);
|
||||||
|
|
||||||
|
if (query.OrderBy.Count == 0 && query.ItemIds.Length > 1)
|
||||||
|
{
|
||||||
|
result.Items = SortItemsByRequest(query, result.Items);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetItemsInternal(query);
|
return GetItemsInternal(query);
|
||||||
@ -823,7 +857,14 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
if (query.ItemIds.Length > 0)
|
if (query.ItemIds.Length > 0)
|
||||||
{
|
{
|
||||||
return LibraryManager.GetItemList(query);
|
var result = LibraryManager.GetItemList(query);
|
||||||
|
|
||||||
|
if (query.OrderBy.Count == 0 && query.ItemIds.Length > 1)
|
||||||
|
{
|
||||||
|
return SortItemsByRequest(query, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetItemsInternal(query).Items;
|
return GetItemsInternal(query).Items;
|
||||||
|
@ -28,7 +28,7 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="name">The name.</param>
|
/// <param name="name">The name.</param>
|
||||||
/// <param name="logger">The logger.</param>
|
/// <param name="logger">The logger.</param>
|
||||||
public Profiler(string name, ILogger logger)
|
public Profiler(string name, ILogger<Profiler> logger)
|
||||||
{
|
{
|
||||||
this._name = name;
|
this._name = name;
|
||||||
|
|
||||||
|
135
MediaBrowser.Controller/Sorting/AlphanumComparator.cs
Normal file
135
MediaBrowser.Controller/Sorting/AlphanumComparator.cs
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
#nullable enable
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.Sorting
|
||||||
|
{
|
||||||
|
public class AlphanumComparator : IComparer<string?>
|
||||||
|
{
|
||||||
|
public static int CompareValues(string? s1, string? s2)
|
||||||
|
{
|
||||||
|
if (s1 == null && s2 == null)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (s1 == null)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (s2 == null)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len1 = s1.Length;
|
||||||
|
int len2 = s2.Length;
|
||||||
|
|
||||||
|
// Early return for empty strings
|
||||||
|
if (len1 == 0 && len2 == 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (len1 == 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (len2 == 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pos1 = 0;
|
||||||
|
int pos2 = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int start1 = pos1;
|
||||||
|
int start2 = pos2;
|
||||||
|
|
||||||
|
bool isNum1 = char.IsDigit(s1[pos1++]);
|
||||||
|
bool isNum2 = char.IsDigit(s2[pos2++]);
|
||||||
|
|
||||||
|
while (pos1 < len1 && char.IsDigit(s1[pos1]) == isNum1)
|
||||||
|
{
|
||||||
|
pos1++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (pos2 < len2 && char.IsDigit(s2[pos2]) == isNum2)
|
||||||
|
{
|
||||||
|
pos2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
var span1 = s1.AsSpan(start1, pos1 - start1);
|
||||||
|
var span2 = s2.AsSpan(start2, pos2 - start2);
|
||||||
|
|
||||||
|
if (isNum1 && isNum2)
|
||||||
|
{
|
||||||
|
// Trim leading zeros so we can compare the length
|
||||||
|
// of the strings to find the largest number
|
||||||
|
span1 = span1.TrimStart('0');
|
||||||
|
span2 = span2.TrimStart('0');
|
||||||
|
var span1Len = span1.Length;
|
||||||
|
var span2Len = span2.Length;
|
||||||
|
if (span1Len < span2Len)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (span1Len > span2Len)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (span1Len >= 20) // Number is probably too big for a ulong
|
||||||
|
{
|
||||||
|
// Trim all the first digits that are the same
|
||||||
|
int i = 0;
|
||||||
|
while (i < span1Len && span1[i] == span2[i])
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are no more digits it's the same number
|
||||||
|
if (i == span1Len)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only need to compare the most significant digit
|
||||||
|
span1 = span1.Slice(i, 1);
|
||||||
|
span2 = span2.Slice(i, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ulong.TryParse(span1, out var num1)
|
||||||
|
|| !ulong.TryParse(span2, out var num2))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (num1 < num2)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (num1 > num2)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int result = span1.CompareTo(span2, StringComparison.InvariantCulture);
|
||||||
|
if (result != 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (pos1 < len1 && pos2 < len2);
|
||||||
|
|
||||||
|
return len1 - len2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public int Compare(string x, string y)
|
||||||
|
{
|
||||||
|
return CompareValues(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,137 +7,25 @@ namespace MediaBrowser.Controller.Sorting
|
|||||||
{
|
{
|
||||||
public static class SortExtensions
|
public static class SortExtensions
|
||||||
{
|
{
|
||||||
|
private static readonly AlphanumComparator _comparer = new AlphanumComparator();
|
||||||
public static IEnumerable<T> OrderByString<T>(this IEnumerable<T> list, Func<T, string> getName)
|
public static IEnumerable<T> OrderByString<T>(this IEnumerable<T> list, Func<T, string> getName)
|
||||||
{
|
{
|
||||||
return list.OrderBy(getName, new AlphanumComparator());
|
return list.OrderBy(getName, _comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<T> OrderByStringDescending<T>(this IEnumerable<T> list, Func<T, string> getName)
|
public static IEnumerable<T> OrderByStringDescending<T>(this IEnumerable<T> list, Func<T, string> getName)
|
||||||
{
|
{
|
||||||
return list.OrderByDescending(getName, new AlphanumComparator());
|
return list.OrderByDescending(getName, _comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IOrderedEnumerable<T> ThenByString<T>(this IOrderedEnumerable<T> list, Func<T, string> getName)
|
public static IOrderedEnumerable<T> ThenByString<T>(this IOrderedEnumerable<T> list, Func<T, string> getName)
|
||||||
{
|
{
|
||||||
return list.ThenBy(getName, new AlphanumComparator());
|
return list.ThenBy(getName, _comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IOrderedEnumerable<T> ThenByStringDescending<T>(this IOrderedEnumerable<T> list, Func<T, string> getName)
|
public static IOrderedEnumerable<T> ThenByStringDescending<T>(this IOrderedEnumerable<T> list, Func<T, string> getName)
|
||||||
{
|
{
|
||||||
return list.ThenByDescending(getName, new AlphanumComparator());
|
return list.ThenByDescending(getName, _comparer);
|
||||||
}
|
|
||||||
|
|
||||||
private class AlphanumComparator : IComparer<string>
|
|
||||||
{
|
|
||||||
private enum ChunkType { Alphanumeric, Numeric };
|
|
||||||
|
|
||||||
private static bool InChunk(char ch, char otherCh)
|
|
||||||
{
|
|
||||||
var type = ChunkType.Alphanumeric;
|
|
||||||
|
|
||||||
if (char.IsDigit(otherCh))
|
|
||||||
{
|
|
||||||
type = ChunkType.Numeric;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((type == ChunkType.Alphanumeric && char.IsDigit(ch))
|
|
||||||
|| (type == ChunkType.Numeric && !char.IsDigit(ch)))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int CompareValues(string s1, string s2)
|
|
||||||
{
|
|
||||||
if (s1 == null || s2 == null)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int thisMarker = 0, thisNumericChunk = 0;
|
|
||||||
int thatMarker = 0, thatNumericChunk = 0;
|
|
||||||
|
|
||||||
while ((thisMarker < s1.Length) || (thatMarker < s2.Length))
|
|
||||||
{
|
|
||||||
if (thisMarker >= s1.Length)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else if (thatMarker >= s2.Length)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
char thisCh = s1[thisMarker];
|
|
||||||
char thatCh = s2[thatMarker];
|
|
||||||
|
|
||||||
var thisChunk = new StringBuilder();
|
|
||||||
var thatChunk = new StringBuilder();
|
|
||||||
|
|
||||||
while ((thisMarker < s1.Length) && (thisChunk.Length == 0 || InChunk(thisCh, thisChunk[0])))
|
|
||||||
{
|
|
||||||
thisChunk.Append(thisCh);
|
|
||||||
thisMarker++;
|
|
||||||
|
|
||||||
if (thisMarker < s1.Length)
|
|
||||||
{
|
|
||||||
thisCh = s1[thisMarker];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((thatMarker < s2.Length) && (thatChunk.Length == 0 || InChunk(thatCh, thatChunk[0])))
|
|
||||||
{
|
|
||||||
thatChunk.Append(thatCh);
|
|
||||||
thatMarker++;
|
|
||||||
|
|
||||||
if (thatMarker < s2.Length)
|
|
||||||
{
|
|
||||||
thatCh = s2[thatMarker];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int result = 0;
|
|
||||||
// If both chunks contain numeric characters, sort them numerically
|
|
||||||
if (char.IsDigit(thisChunk[0]) && char.IsDigit(thatChunk[0]))
|
|
||||||
{
|
|
||||||
if (!int.TryParse(thisChunk.ToString(), out thisNumericChunk))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!int.TryParse(thatChunk.ToString(), out thatNumericChunk))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thisNumericChunk < thatNumericChunk)
|
|
||||||
{
|
|
||||||
result = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thisNumericChunk > thatNumericChunk)
|
|
||||||
{
|
|
||||||
result = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = thisChunk.ToString().CompareTo(thatChunk.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Compare(string x, string y)
|
|
||||||
{
|
|
||||||
return CompareValues(x, y);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
namespace MediaBrowser.Controller.Sorting
|
|
||||||
{
|
|
||||||
public static class SortHelper
|
|
||||||
{
|
|
||||||
private enum ChunkType { Alphanumeric, Numeric };
|
|
||||||
|
|
||||||
public static bool InChunk(char ch, char otherCh)
|
|
||||||
{
|
|
||||||
var type = ChunkType.Alphanumeric;
|
|
||||||
|
|
||||||
if (char.IsDigit(otherCh))
|
|
||||||
{
|
|
||||||
type = ChunkType.Numeric;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((type == ChunkType.Alphanumeric && char.IsDigit(ch))
|
|
||||||
|| (type == ChunkType.Numeric && !char.IsDigit(ch)))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,7 +16,7 @@ namespace MediaBrowser.LocalMetadata.Providers
|
|||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IProviderManager _providerManager;
|
private readonly IProviderManager _providerManager;
|
||||||
|
|
||||||
public BoxSetXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager)
|
public BoxSetXmlProvider(IFileSystem fileSystem, ILogger<BoxSetXmlProvider> logger, IProviderManager providerManager)
|
||||||
: base(fileSystem)
|
: base(fileSystem)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
@ -13,7 +13,10 @@ namespace MediaBrowser.LocalMetadata.Providers
|
|||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IProviderManager _providerManager;
|
private readonly IProviderManager _providerManager;
|
||||||
|
|
||||||
public PlaylistXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager)
|
public PlaylistXmlProvider(
|
||||||
|
IFileSystem fileSystem,
|
||||||
|
ILogger<PlaylistXmlProvider> logger,
|
||||||
|
IProviderManager providerManager)
|
||||||
: base(fileSystem)
|
: base(fileSystem)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
@ -30,7 +30,7 @@ namespace MediaBrowser.LocalMetadata.Savers
|
|||||||
return Path.Combine(item.Path, "collection.xml");
|
return Path.Combine(item.Path, "collection.xml");
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoxSetXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger)
|
public BoxSetXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger<BoxSetXmlSaver> logger)
|
||||||
: base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger)
|
: base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,11 @@ namespace MediaBrowser.LocalMetadata.Savers
|
|||||||
{
|
{
|
||||||
public class PlaylistXmlSaver : BaseXmlSaver
|
public class PlaylistXmlSaver : BaseXmlSaver
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The default file name to use when creating a new playlist.
|
||||||
|
/// </summary>
|
||||||
|
public const string DefaultPlaylistFilename = "playlist.xml";
|
||||||
|
|
||||||
public override bool IsEnabledFor(BaseItem item, ItemUpdateType updateType)
|
public override bool IsEnabledFor(BaseItem item, ItemUpdateType updateType)
|
||||||
{
|
{
|
||||||
if (!item.SupportsLocalMetadata)
|
if (!item.SupportsLocalMetadata)
|
||||||
@ -45,10 +50,10 @@ namespace MediaBrowser.LocalMetadata.Savers
|
|||||||
return Path.ChangeExtension(itemPath, ".xml");
|
return Path.ChangeExtension(itemPath, ".xml");
|
||||||
}
|
}
|
||||||
|
|
||||||
return Path.Combine(path, "playlist.xml");
|
return Path.Combine(path, DefaultPlaylistFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlaylistXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger)
|
public PlaylistXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger<PlaylistXmlSaver> logger)
|
||||||
: base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger)
|
: base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
using System;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Configuration
|
namespace MediaBrowser.Model.Configuration
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -25,6 +28,24 @@ namespace MediaBrowser.Model.Configuration
|
|||||||
/// <value>The cache path.</value>
|
/// <value>The cache path.</value>
|
||||||
public string CachePath { get; set; }
|
public string CachePath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Last known version that was ran using the configuration.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The version from previous run.</value>
|
||||||
|
[XmlIgnore]
|
||||||
|
public Version PreviousVersion { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stringified PreviousVersion to be stored/loaded,
|
||||||
|
/// because System.Version itself isn't xml-serializable
|
||||||
|
/// </summary>
|
||||||
|
/// <value>String value of PreviousVersion</value>
|
||||||
|
public string PreviousVersionStr
|
||||||
|
{
|
||||||
|
get => PreviousVersion?.ToString();
|
||||||
|
set => PreviousVersion = Version.Parse(value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="BaseApplicationConfiguration" /> class.
|
/// Initializes a new instance of the <see cref="BaseApplicationConfiguration" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -34,7 +34,7 @@ namespace MediaBrowser.Model.Configuration
|
|||||||
public EncodingOptions()
|
public EncodingOptions()
|
||||||
{
|
{
|
||||||
DownMixAudioBoost = 2;
|
DownMixAudioBoost = 2;
|
||||||
EnableThrottling = true;
|
EnableThrottling = false;
|
||||||
ThrottleDelaySeconds = 180;
|
ThrottleDelaySeconds = 180;
|
||||||
EncodingThreadCount = -1;
|
EncodingThreadCount = -1;
|
||||||
// This is a DRM device that is almost guaranteed to be there on every intel platform, plus it's the default one in ffmpeg if you don't specify anything
|
// This is a DRM device that is almost guaranteed to be there on every intel platform, plus it's the default one in ffmpeg if you don't specify anything
|
||||||
|
@ -238,7 +238,7 @@ namespace MediaBrowser.Model.Configuration
|
|||||||
CodecsUsed = Array.Empty<string>();
|
CodecsUsed = Array.Empty<string>();
|
||||||
PathSubstitutions = Array.Empty<PathSubstitution>();
|
PathSubstitutions = Array.Empty<PathSubstitution>();
|
||||||
IgnoreVirtualInterfaces = false;
|
IgnoreVirtualInterfaces = false;
|
||||||
EnableSimpleArtistDetection = true;
|
EnableSimpleArtistDetection = false;
|
||||||
|
|
||||||
DisplaySpecialsWithinSeasons = true;
|
DisplaySpecialsWithinSeasons = true;
|
||||||
EnableExternalContentInSuggestions = true;
|
EnableExternalContentInSuggestions = true;
|
||||||
@ -248,7 +248,7 @@ namespace MediaBrowser.Model.Configuration
|
|||||||
PublicHttpsPort = DefaultHttpsPort;
|
PublicHttpsPort = DefaultHttpsPort;
|
||||||
HttpServerPortNumber = DefaultHttpPort;
|
HttpServerPortNumber = DefaultHttpPort;
|
||||||
HttpsPortNumber = DefaultHttpsPort;
|
HttpsPortNumber = DefaultHttpsPort;
|
||||||
EnableHttps = true;
|
EnableHttps = false;
|
||||||
EnableDashboardResponseCaching = true;
|
EnableDashboardResponseCaching = true;
|
||||||
EnableCaseSensitiveItemIds = true;
|
EnableCaseSensitiveItemIds = true;
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StreamBuilder(ILogger logger)
|
public StreamBuilder(ILogger<StreamBuilder> logger)
|
||||||
: this(new FullTranscoderSupport(), logger)
|
: this(new FullTranscoderSupport(), logger)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ namespace MediaBrowser.Providers.Books
|
|||||||
{
|
{
|
||||||
public AudioBookMetadataService(
|
public AudioBookMetadataService(
|
||||||
IServerConfigurationManager serverConfigurationManager,
|
IServerConfigurationManager serverConfigurationManager,
|
||||||
ILogger logger,
|
ILogger<AudioBookMetadataService> logger,
|
||||||
IProviderManager providerManager,
|
IProviderManager providerManager,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
ILibraryManager libraryManager)
|
ILibraryManager libraryManager)
|
||||||
|
@ -13,7 +13,7 @@ namespace MediaBrowser.Providers.Books
|
|||||||
{
|
{
|
||||||
public BookMetadataService(
|
public BookMetadataService(
|
||||||
IServerConfigurationManager serverConfigurationManager,
|
IServerConfigurationManager serverConfigurationManager,
|
||||||
ILogger logger,
|
ILogger<BookMetadataService> logger,
|
||||||
IProviderManager providerManager,
|
IProviderManager providerManager,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
ILibraryManager libraryManager)
|
ILibraryManager libraryManager)
|
||||||
|
@ -16,7 +16,7 @@ namespace MediaBrowser.Providers.BoxSets
|
|||||||
{
|
{
|
||||||
public BoxSetMetadataService(
|
public BoxSetMetadataService(
|
||||||
IServerConfigurationManager serverConfigurationManager,
|
IServerConfigurationManager serverConfigurationManager,
|
||||||
ILogger logger,
|
ILogger<BoxSetMetadataService> logger,
|
||||||
IProviderManager providerManager,
|
IProviderManager providerManager,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
ILibraryManager libraryManager)
|
ILibraryManager libraryManager)
|
||||||
|
@ -13,7 +13,7 @@ namespace MediaBrowser.Providers.Channels
|
|||||||
{
|
{
|
||||||
public ChannelMetadataService(
|
public ChannelMetadataService(
|
||||||
IServerConfigurationManager serverConfigurationManager,
|
IServerConfigurationManager serverConfigurationManager,
|
||||||
ILogger logger,
|
ILogger<ChannelMetadataService> logger,
|
||||||
IProviderManager providerManager,
|
IProviderManager providerManager,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
ILibraryManager libraryManager)
|
ILibraryManager libraryManager)
|
||||||
|
@ -14,7 +14,7 @@ namespace MediaBrowser.Providers.Folders
|
|||||||
{
|
{
|
||||||
public CollectionFolderMetadataService(
|
public CollectionFolderMetadataService(
|
||||||
IServerConfigurationManager serverConfigurationManager,
|
IServerConfigurationManager serverConfigurationManager,
|
||||||
ILogger logger,
|
ILogger<CollectionFolderMetadataService> logger,
|
||||||
IProviderManager providerManager,
|
IProviderManager providerManager,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
ILibraryManager libraryManager)
|
ILibraryManager libraryManager)
|
||||||
|
@ -13,7 +13,7 @@ namespace MediaBrowser.Providers.Folders
|
|||||||
{
|
{
|
||||||
public FolderMetadataService(
|
public FolderMetadataService(
|
||||||
IServerConfigurationManager serverConfigurationManager,
|
IServerConfigurationManager serverConfigurationManager,
|
||||||
ILogger logger,
|
ILogger<FolderMetadataService> logger,
|
||||||
IProviderManager providerManager,
|
IProviderManager providerManager,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
ILibraryManager libraryManager)
|
ILibraryManager libraryManager)
|
||||||
|
@ -13,7 +13,7 @@ namespace MediaBrowser.Providers.Folders
|
|||||||
{
|
{
|
||||||
public UserViewMetadataService(
|
public UserViewMetadataService(
|
||||||
IServerConfigurationManager serverConfigurationManager,
|
IServerConfigurationManager serverConfigurationManager,
|
||||||
ILogger logger,
|
ILogger<UserViewMetadataService> logger,
|
||||||
IProviderManager providerManager,
|
IProviderManager providerManager,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
ILibraryManager libraryManager)
|
ILibraryManager libraryManager)
|
||||||
|
@ -13,7 +13,7 @@ namespace MediaBrowser.Providers.Genres
|
|||||||
{
|
{
|
||||||
public GenreMetadataService(
|
public GenreMetadataService(
|
||||||
IServerConfigurationManager serverConfigurationManager,
|
IServerConfigurationManager serverConfigurationManager,
|
||||||
ILogger logger,
|
ILogger<GenreMetadataService> logger,
|
||||||
IProviderManager providerManager,
|
IProviderManager providerManager,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
ILibraryManager libraryManager)
|
ILibraryManager libraryManager)
|
||||||
|
@ -13,7 +13,7 @@ namespace MediaBrowser.Providers.LiveTv
|
|||||||
{
|
{
|
||||||
public LiveTvMetadataService(
|
public LiveTvMetadataService(
|
||||||
IServerConfigurationManager serverConfigurationManager,
|
IServerConfigurationManager serverConfigurationManager,
|
||||||
ILogger logger,
|
ILogger<LiveTvMetadataService> logger,
|
||||||
IProviderManager providerManager,
|
IProviderManager providerManager,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
ILibraryManager libraryManager)
|
ILibraryManager libraryManager)
|
||||||
|
@ -24,4 +24,14 @@
|
|||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="Plugins\AudioDb\Configuration\config.html" />
|
||||||
|
<EmbeddedResource Include="Plugins\AudioDb\Configuration\config.html" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="Plugins\MusicBrainz\Configuration\config.html" />
|
||||||
|
<EmbeddedResource Include="Plugins\MusicBrainz\Configuration\config.html" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -121,7 +121,24 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||||||
}
|
}
|
||||||
|
|
||||||
private SubtitleResolver _subtitleResolver;
|
private SubtitleResolver _subtitleResolver;
|
||||||
public FFProbeProvider(ILogger logger, IMediaSourceManager mediaSourceManager, IChannelManager channelManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IItemRepository itemRepo, IBlurayExaminer blurayExaminer, ILocalizationManager localization, IApplicationPaths appPaths, IJsonSerializer json, IEncodingManager encodingManager, IFileSystem fileSystem, IServerConfigurationManager config, ISubtitleManager subtitleManager, IChapterManager chapterManager, ILibraryManager libraryManager)
|
|
||||||
|
public FFProbeProvider(
|
||||||
|
ILogger<FFProbeProvider> logger,
|
||||||
|
IMediaSourceManager mediaSourceManager,
|
||||||
|
IChannelManager channelManager,
|
||||||
|
IIsoManager isoManager,
|
||||||
|
IMediaEncoder mediaEncoder,
|
||||||
|
IItemRepository itemRepo,
|
||||||
|
IBlurayExaminer blurayExaminer,
|
||||||
|
ILocalizationManager localization,
|
||||||
|
IApplicationPaths appPaths,
|
||||||
|
IJsonSerializer json,
|
||||||
|
IEncodingManager encodingManager,
|
||||||
|
IFileSystem fileSystem,
|
||||||
|
IServerConfigurationManager config,
|
||||||
|
ISubtitleManager subtitleManager,
|
||||||
|
IChapterManager chapterManager,
|
||||||
|
ILibraryManager libraryManager)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_isoManager = isoManager;
|
_isoManager = isoManager;
|
||||||
|
@ -26,7 +26,13 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IJsonSerializer _json;
|
private readonly IJsonSerializer _json;
|
||||||
|
|
||||||
public SubtitleScheduledTask(ILibraryManager libraryManager, IJsonSerializer json, IServerConfigurationManager config, ISubtitleManager subtitleManager, ILogger logger, IMediaSourceManager mediaSourceManager)
|
public SubtitleScheduledTask(
|
||||||
|
ILibraryManager libraryManager,
|
||||||
|
IJsonSerializer json,
|
||||||
|
IServerConfigurationManager config,
|
||||||
|
ISubtitleManager subtitleManager,
|
||||||
|
ILogger<SubtitleScheduledTask> logger,
|
||||||
|
IMediaSourceManager mediaSourceManager)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_config = config;
|
_config = config;
|
||||||
|
@ -20,7 +20,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
|
|
||||||
public VideoImageProvider(IMediaEncoder mediaEncoder, ILogger logger, IFileSystem fileSystem)
|
public VideoImageProvider(IMediaEncoder mediaEncoder, ILogger<VideoImageProvider> logger, IFileSystem fileSystem)
|
||||||
{
|
{
|
||||||
_mediaEncoder = mediaEncoder;
|
_mediaEncoder = mediaEncoder;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
@ -13,7 +13,7 @@ namespace MediaBrowser.Providers.Movies
|
|||||||
{
|
{
|
||||||
public MovieMetadataService(
|
public MovieMetadataService(
|
||||||
IServerConfigurationManager serverConfigurationManager,
|
IServerConfigurationManager serverConfigurationManager,
|
||||||
ILogger logger,
|
ILogger<MovieMetadataService> logger,
|
||||||
IProviderManager providerManager,
|
IProviderManager providerManager,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
ILibraryManager libraryManager)
|
ILibraryManager libraryManager)
|
||||||
|
@ -13,7 +13,7 @@ namespace MediaBrowser.Providers.Movies
|
|||||||
{
|
{
|
||||||
public TrailerMetadataService(
|
public TrailerMetadataService(
|
||||||
IServerConfigurationManager serverConfigurationManager,
|
IServerConfigurationManager serverConfigurationManager,
|
||||||
ILogger logger,
|
ILogger<TrailerMetadataService> logger,
|
||||||
IProviderManager providerManager,
|
IProviderManager providerManager,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
ILibraryManager libraryManager)
|
ILibraryManager libraryManager)
|
||||||
|
@ -17,7 +17,7 @@ namespace MediaBrowser.Providers.Music
|
|||||||
{
|
{
|
||||||
public AlbumMetadataService(
|
public AlbumMetadataService(
|
||||||
IServerConfigurationManager serverConfigurationManager,
|
IServerConfigurationManager serverConfigurationManager,
|
||||||
ILogger logger,
|
ILogger<AlbumMetadataService> logger,
|
||||||
IProviderManager providerManager,
|
IProviderManager providerManager,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
ILibraryManager libraryManager)
|
ILibraryManager libraryManager)
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user