mirror of
				https://github.com/jellyfin/jellyfin.git
				synced 2025-11-02 18:47:18 -05:00 
			
		
		
		
	Merge remote-tracking branch 'upstream/master' into query-fields
This commit is contained in:
		
						commit
						4f7c13ecf4
					
				@ -28,7 +28,13 @@ jobs:
 | 
				
			|||||||
      inputs:
 | 
					      inputs:
 | 
				
			||||||
        script: "wget https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/${{ parameters.GeneratorVersion }}/openapi-generator-cli-${{ parameters.GeneratorVersion }}.jar -O openapi-generator-cli.jar"
 | 
					        script: "wget https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/${{ parameters.GeneratorVersion }}/openapi-generator-cli-${{ parameters.GeneratorVersion }}.jar -O openapi-generator-cli.jar"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Generate npm api client
 | 
					## Authenticate with npm registry
 | 
				
			||||||
 | 
					    - task: npmAuthenticate@0
 | 
				
			||||||
 | 
					      inputs:
 | 
				
			||||||
 | 
					        workingFile: ./.npmrc
 | 
				
			||||||
 | 
					        customEndpoint: 'jellyfin-bot for NPM'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Generate npm api client
 | 
				
			||||||
# Unstable
 | 
					# Unstable
 | 
				
			||||||
    - task: CmdLine@2
 | 
					    - task: CmdLine@2
 | 
				
			||||||
      displayName: 'Build unstable typescript axios client'
 | 
					      displayName: 'Build unstable typescript axios client'
 | 
				
			||||||
@ -36,15 +42,6 @@ jobs:
 | 
				
			|||||||
      inputs:
 | 
					      inputs:
 | 
				
			||||||
        script: "bash ./apiclient/templates/typescript/axios/generate.sh $(System.ArtifactsDirectory) $(Build.BuildNumber)"
 | 
					        script: "bash ./apiclient/templates/typescript/axios/generate.sh $(System.ArtifactsDirectory) $(Build.BuildNumber)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - task: Npm@1
 | 
					 | 
				
			||||||
      displayName: 'Publish unstable typescript axios client'
 | 
					 | 
				
			||||||
      condition: startsWith(variables['Build.SourceBranch'], 'refs/heads/master')
 | 
					 | 
				
			||||||
      inputs:
 | 
					 | 
				
			||||||
        command: publish
 | 
					 | 
				
			||||||
        publishRegistry: useFeed
 | 
					 | 
				
			||||||
        publishFeed: 'unstable@Local'
 | 
					 | 
				
			||||||
        workingDir: ./apiclient/generated/typescript/axios
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Stable
 | 
					# Stable
 | 
				
			||||||
    - task: CmdLine@2
 | 
					    - task: CmdLine@2
 | 
				
			||||||
      displayName: 'Build stable typescript axios client'
 | 
					      displayName: 'Build stable typescript axios client'
 | 
				
			||||||
@ -52,6 +49,25 @@ jobs:
 | 
				
			|||||||
      inputs:
 | 
					      inputs:
 | 
				
			||||||
        script: "bash ./apiclient/templates/typescript/axios/generate.sh $(System.ArtifactsDirectory)"
 | 
					        script: "bash ./apiclient/templates/typescript/axios/generate.sh $(System.ArtifactsDirectory)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Run npm install
 | 
				
			||||||
 | 
					    - task: Npm@1
 | 
				
			||||||
 | 
					      displayName: 'Install npm dependencies'
 | 
				
			||||||
 | 
					      inputs:
 | 
				
			||||||
 | 
					        command: install
 | 
				
			||||||
 | 
					        workingDir: ./apiclient/generated/typescript/axios
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Publish npm packages
 | 
				
			||||||
 | 
					# Unstable
 | 
				
			||||||
 | 
					    - task: Npm@1
 | 
				
			||||||
 | 
					      displayName: 'Publish unstable typescript axios client'
 | 
				
			||||||
 | 
					      condition: startsWith(variables['Build.SourceBranch'], 'refs/heads/master')
 | 
				
			||||||
 | 
					      inputs:
 | 
				
			||||||
 | 
					        command: publish
 | 
				
			||||||
 | 
					        publishRegistry: useFeed
 | 
				
			||||||
 | 
					        publishFeed: 'jellyfin/unstable'
 | 
				
			||||||
 | 
					        workingDir: ./apiclient/generated/typescript/axios
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Stable
 | 
				
			||||||
    - task: Npm@1
 | 
					    - task: Npm@1
 | 
				
			||||||
      displayName: 'Publish stable typescript axios client'
 | 
					      displayName: 'Publish stable typescript axios client'
 | 
				
			||||||
      condition: startsWith(variables['Build.SourceBranch'], 'refs/tags/v')
 | 
					      condition: startsWith(variables['Build.SourceBranch'], 'refs/tags/v')
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										3
									
								
								.npmrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.npmrc
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					registry=https://registry.npmjs.org/
 | 
				
			||||||
 | 
					@jellyfin:registry=https://pkgs.dev.azure.com/jellyfin-project/jellyfin/_packaging/unstable/npm/registry/
 | 
				
			||||||
 | 
					always-auth=true
 | 
				
			||||||
@ -1,5 +1,3 @@
 | 
				
			|||||||
#pragma warning disable CS1591
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using System.Xml;
 | 
					using System.Xml;
 | 
				
			||||||
@ -10,8 +8,16 @@ using Microsoft.Extensions.Logging;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Emby.Dlna.MediaReceiverRegistrar
 | 
					namespace Emby.Dlna.MediaReceiverRegistrar
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Defines the <see cref="ControlHandler" />.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
    public class ControlHandler : BaseControlHandler
 | 
					    public class ControlHandler : BaseControlHandler
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Initializes a new instance of the <see cref="ControlHandler"/> class.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="config">The <see cref="IServerConfigurationManager"/> for use with the <see cref="ControlHandler"/> instance.</param>
 | 
				
			||||||
 | 
					        /// <param name="logger">The <see cref="ILogger"/> for use with the <see cref="ControlHandler"/> instance.</param>
 | 
				
			||||||
        public ControlHandler(IServerConfigurationManager config, ILogger logger)
 | 
					        public ControlHandler(IServerConfigurationManager config, ILogger logger)
 | 
				
			||||||
            : base(config, logger)
 | 
					            : base(config, logger)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@ -35,9 +41,17 @@ namespace Emby.Dlna.MediaReceiverRegistrar
 | 
				
			|||||||
            throw new ResourceNotFoundException("Unexpected control request name: " + methodName);
 | 
					            throw new ResourceNotFoundException("Unexpected control request name: " + methodName);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Records that the handle is authorized in the xml stream.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="xmlWriter">The <see cref="XmlWriter"/>.</param>
 | 
				
			||||||
        private static void HandleIsAuthorized(XmlWriter xmlWriter)
 | 
					        private static void HandleIsAuthorized(XmlWriter xmlWriter)
 | 
				
			||||||
            => xmlWriter.WriteElementString("Result", "1");
 | 
					            => xmlWriter.WriteElementString("Result", "1");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Records that the handle is validated in the xml stream.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="xmlWriter">The <see cref="XmlWriter"/>.</param>
 | 
				
			||||||
        private static void HandleIsValidated(XmlWriter xmlWriter)
 | 
					        private static void HandleIsValidated(XmlWriter xmlWriter)
 | 
				
			||||||
            => xmlWriter.WriteElementString("Result", "1");
 | 
					            => xmlWriter.WriteElementString("Result", "1");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,3 @@
 | 
				
			|||||||
#pragma warning disable CS1591
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using System.Net.Http;
 | 
					using System.Net.Http;
 | 
				
			||||||
using System.Threading.Tasks;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
using Emby.Dlna.Service;
 | 
					using Emby.Dlna.Service;
 | 
				
			||||||
@ -8,10 +6,19 @@ using Microsoft.Extensions.Logging;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Emby.Dlna.MediaReceiverRegistrar
 | 
					namespace Emby.Dlna.MediaReceiverRegistrar
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Defines the <see cref="MediaReceiverRegistrarService" />.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
    public class MediaReceiverRegistrarService : BaseService, IMediaReceiverRegistrar
 | 
					    public class MediaReceiverRegistrarService : BaseService, IMediaReceiverRegistrar
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly IServerConfigurationManager _config;
 | 
					        private readonly IServerConfigurationManager _config;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Initializes a new instance of the <see cref="MediaReceiverRegistrarService"/> class.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="logger">The <see cref="ILogger{MediaReceiverRegistrarService}"/> for use with the <see cref="MediaReceiverRegistrarService"/> instance.</param>
 | 
				
			||||||
 | 
					        /// <param name="httpClientFactory">The <see cref="IHttpClientFactory"/> for use with the <see cref="MediaReceiverRegistrarService"/> instance.</param>
 | 
				
			||||||
 | 
					        /// <param name="config">The <see cref="IServerConfigurationManager"/> for use with the <see cref="MediaReceiverRegistrarService"/> instance.</param>
 | 
				
			||||||
        public MediaReceiverRegistrarService(
 | 
					        public MediaReceiverRegistrarService(
 | 
				
			||||||
            ILogger<MediaReceiverRegistrarService> logger,
 | 
					            ILogger<MediaReceiverRegistrarService> logger,
 | 
				
			||||||
            IHttpClientFactory httpClientFactory,
 | 
					            IHttpClientFactory httpClientFactory,
 | 
				
			||||||
@ -24,7 +31,7 @@ namespace Emby.Dlna.MediaReceiverRegistrar
 | 
				
			|||||||
        /// <inheritdoc />
 | 
					        /// <inheritdoc />
 | 
				
			||||||
        public string GetServiceXml()
 | 
					        public string GetServiceXml()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return new MediaReceiverRegistrarXmlBuilder().GetXml();
 | 
					            return MediaReceiverRegistrarXmlBuilder.GetXml();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <inheritdoc />
 | 
					        /// <inheritdoc />
 | 
				
			||||||
 | 
				
			|||||||
@ -1,79 +1,89 @@
 | 
				
			|||||||
#pragma warning disable CS1591
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using Emby.Dlna.Common;
 | 
					using Emby.Dlna.Common;
 | 
				
			||||||
using Emby.Dlna.Service;
 | 
					using Emby.Dlna.Service;
 | 
				
			||||||
 | 
					using MediaBrowser.Model.Dlna;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Emby.Dlna.MediaReceiverRegistrar
 | 
					namespace Emby.Dlna.MediaReceiverRegistrar
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public class MediaReceiverRegistrarXmlBuilder
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Defines the <see cref="MediaReceiverRegistrarXmlBuilder" />.
 | 
				
			||||||
 | 
					    /// See https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-drmnd/5d37515e-7a63-4709-8258-8fd4e0ed4482.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public static class MediaReceiverRegistrarXmlBuilder
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public string GetXml()
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Retrieves an XML description of the X_MS_MediaReceiverRegistrar.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <returns>An XML representation of this service.</returns>
 | 
				
			||||||
 | 
					        public static string GetXml()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return new ServiceXmlBuilder().GetXml(
 | 
					            return new ServiceXmlBuilder().GetXml(ServiceActionListBuilder.GetActions(), GetStateVariables());
 | 
				
			||||||
                new ServiceActionListBuilder().GetActions(),
 | 
					 | 
				
			||||||
                GetStateVariables());
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// The a list of all the state variables for this invocation.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <returns>The <see cref="IEnumerable{StateVariable}"/>.</returns>
 | 
				
			||||||
        private static IEnumerable<StateVariable> GetStateVariables()
 | 
					        private static IEnumerable<StateVariable> GetStateVariables()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var list = new List<StateVariable>();
 | 
					            var list = new List<StateVariable>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
            list.Add(new StateVariable
 | 
					                new StateVariable
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    Name = "AuthorizationGrantedUpdateID",
 | 
					                    Name = "AuthorizationGrantedUpdateID",
 | 
				
			||||||
                    DataType = "ui4",
 | 
					                    DataType = "ui4",
 | 
				
			||||||
                    SendsEvents = true
 | 
					                    SendsEvents = true
 | 
				
			||||||
            });
 | 
					                },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            list.Add(new StateVariable
 | 
					                new StateVariable
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    Name = "A_ARG_TYPE_DeviceID",
 | 
					                    Name = "A_ARG_TYPE_DeviceID",
 | 
				
			||||||
                    DataType = "string",
 | 
					                    DataType = "string",
 | 
				
			||||||
                    SendsEvents = false
 | 
					                    SendsEvents = false
 | 
				
			||||||
            });
 | 
					                },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            list.Add(new StateVariable
 | 
					                new StateVariable
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    Name = "AuthorizationDeniedUpdateID",
 | 
					                    Name = "AuthorizationDeniedUpdateID",
 | 
				
			||||||
                    DataType = "ui4",
 | 
					                    DataType = "ui4",
 | 
				
			||||||
                    SendsEvents = true
 | 
					                    SendsEvents = true
 | 
				
			||||||
            });
 | 
					                },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            list.Add(new StateVariable
 | 
					                new StateVariable
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    Name = "ValidationSucceededUpdateID",
 | 
					                    Name = "ValidationSucceededUpdateID",
 | 
				
			||||||
                    DataType = "ui4",
 | 
					                    DataType = "ui4",
 | 
				
			||||||
                    SendsEvents = true
 | 
					                    SendsEvents = true
 | 
				
			||||||
            });
 | 
					                },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            list.Add(new StateVariable
 | 
					                new StateVariable
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    Name = "A_ARG_TYPE_RegistrationRespMsg",
 | 
					                    Name = "A_ARG_TYPE_RegistrationRespMsg",
 | 
				
			||||||
                    DataType = "bin.base64",
 | 
					                    DataType = "bin.base64",
 | 
				
			||||||
                    SendsEvents = false
 | 
					                    SendsEvents = false
 | 
				
			||||||
            });
 | 
					                },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            list.Add(new StateVariable
 | 
					                new StateVariable
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    Name = "A_ARG_TYPE_RegistrationReqMsg",
 | 
					                    Name = "A_ARG_TYPE_RegistrationReqMsg",
 | 
				
			||||||
                    DataType = "bin.base64",
 | 
					                    DataType = "bin.base64",
 | 
				
			||||||
                    SendsEvents = false
 | 
					                    SendsEvents = false
 | 
				
			||||||
            });
 | 
					                },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            list.Add(new StateVariable
 | 
					                new StateVariable
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    Name = "ValidationRevokedUpdateID",
 | 
					                    Name = "ValidationRevokedUpdateID",
 | 
				
			||||||
                    DataType = "ui4",
 | 
					                    DataType = "ui4",
 | 
				
			||||||
                    SendsEvents = true
 | 
					                    SendsEvents = true
 | 
				
			||||||
            });
 | 
					                },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            list.Add(new StateVariable
 | 
					                new StateVariable
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    Name = "A_ARG_TYPE_Result",
 | 
					                    Name = "A_ARG_TYPE_Result",
 | 
				
			||||||
                    DataType = "int",
 | 
					                    DataType = "int",
 | 
				
			||||||
                    SendsEvents = false
 | 
					                    SendsEvents = false
 | 
				
			||||||
            });
 | 
					                }
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return list;
 | 
					            return list;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,13 +1,19 @@
 | 
				
			|||||||
#pragma warning disable CS1591
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using Emby.Dlna.Common;
 | 
					using Emby.Dlna.Common;
 | 
				
			||||||
 | 
					using MediaBrowser.Model.Dlna;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Emby.Dlna.MediaReceiverRegistrar
 | 
					namespace Emby.Dlna.MediaReceiverRegistrar
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public class ServiceActionListBuilder
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Defines the <see cref="ServiceActionListBuilder" />.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public static class ServiceActionListBuilder
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public IEnumerable<ServiceAction> GetActions()
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Returns a list of services that this instance provides.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <returns>An <see cref="IEnumerable{ServiceAction}"/>.</returns>
 | 
				
			||||||
 | 
					        public static IEnumerable<ServiceAction> GetActions()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return new[]
 | 
					            return new[]
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -21,6 +27,10 @@ namespace Emby.Dlna.MediaReceiverRegistrar
 | 
				
			|||||||
            };
 | 
					            };
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Returns the action details for "IsValidated".
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <returns>The <see cref="ServiceAction"/>.</returns>
 | 
				
			||||||
        private static ServiceAction GetIsValidated()
 | 
					        private static ServiceAction GetIsValidated()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var action = new ServiceAction
 | 
					            var action = new ServiceAction
 | 
				
			||||||
@ -43,6 +53,10 @@ namespace Emby.Dlna.MediaReceiverRegistrar
 | 
				
			|||||||
            return action;
 | 
					            return action;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Returns the action details for "IsAuthorized".
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <returns>The <see cref="ServiceAction"/>.</returns>
 | 
				
			||||||
        private static ServiceAction GetIsAuthorized()
 | 
					        private static ServiceAction GetIsAuthorized()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var action = new ServiceAction
 | 
					            var action = new ServiceAction
 | 
				
			||||||
@ -65,6 +79,10 @@ namespace Emby.Dlna.MediaReceiverRegistrar
 | 
				
			|||||||
            return action;
 | 
					            return action;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Returns the action details for "RegisterDevice".
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <returns>The <see cref="ServiceAction"/>.</returns>
 | 
				
			||||||
        private static ServiceAction GetRegisterDevice()
 | 
					        private static ServiceAction GetRegisterDevice()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var action = new ServiceAction
 | 
					            var action = new ServiceAction
 | 
				
			||||||
@ -87,6 +105,10 @@ namespace Emby.Dlna.MediaReceiverRegistrar
 | 
				
			|||||||
            return action;
 | 
					            return action;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Returns the action details for "GetValidationSucceededUpdateID".
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <returns>The <see cref="ServiceAction"/>.</returns>
 | 
				
			||||||
        private static ServiceAction GetGetValidationSucceededUpdateID()
 | 
					        private static ServiceAction GetGetValidationSucceededUpdateID()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var action = new ServiceAction
 | 
					            var action = new ServiceAction
 | 
				
			||||||
@ -103,7 +125,11 @@ namespace Emby.Dlna.MediaReceiverRegistrar
 | 
				
			|||||||
            return action;
 | 
					            return action;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private ServiceAction GetGetAuthorizationDeniedUpdateID()
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Returns the action details for "GetGetAuthorizationDeniedUpdateID".
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <returns>The <see cref="ServiceAction"/>.</returns>
 | 
				
			||||||
 | 
					        private static ServiceAction GetGetAuthorizationDeniedUpdateID()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var action = new ServiceAction
 | 
					            var action = new ServiceAction
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -119,7 +145,11 @@ namespace Emby.Dlna.MediaReceiverRegistrar
 | 
				
			|||||||
            return action;
 | 
					            return action;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private ServiceAction GetGetValidationRevokedUpdateID()
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Returns the action details for "GetValidationRevokedUpdateID".
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <returns>The <see cref="ServiceAction"/>.</returns>
 | 
				
			||||||
 | 
					        private static ServiceAction GetGetValidationRevokedUpdateID()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var action = new ServiceAction
 | 
					            var action = new ServiceAction
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -135,7 +165,11 @@ namespace Emby.Dlna.MediaReceiverRegistrar
 | 
				
			|||||||
            return action;
 | 
					            return action;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private ServiceAction GetGetAuthorizationGrantedUpdateID()
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Returns the action details for "GetAuthorizationGrantedUpdateID".
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <returns>The <see cref="ServiceAction"/>.</returns>
 | 
				
			||||||
 | 
					        private static ServiceAction GetGetAuthorizationGrantedUpdateID()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var action = new ServiceAction
 | 
					            var action = new ServiceAction
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 | 
				
			|||||||
@ -235,13 +235,13 @@ namespace Emby.Dlna.Server
 | 
				
			|||||||
                    .Append(SecurityElement.Escape(service.ServiceId ?? string.Empty))
 | 
					                    .Append(SecurityElement.Escape(service.ServiceId ?? string.Empty))
 | 
				
			||||||
                    .Append("</serviceId>");
 | 
					                    .Append("</serviceId>");
 | 
				
			||||||
                builder.Append("<SCPDURL>")
 | 
					                builder.Append("<SCPDURL>")
 | 
				
			||||||
                    .Append(BuildUrl(service.ScpdUrl, true))
 | 
					                    .Append(BuildUrl(service.ScpdUrl))
 | 
				
			||||||
                    .Append("</SCPDURL>");
 | 
					                    .Append("</SCPDURL>");
 | 
				
			||||||
                builder.Append("<controlURL>")
 | 
					                builder.Append("<controlURL>")
 | 
				
			||||||
                    .Append(BuildUrl(service.ControlUrl, true))
 | 
					                    .Append(BuildUrl(service.ControlUrl))
 | 
				
			||||||
                    .Append("</controlURL>");
 | 
					                    .Append("</controlURL>");
 | 
				
			||||||
                builder.Append("<eventSubURL>")
 | 
					                builder.Append("<eventSubURL>")
 | 
				
			||||||
                    .Append(BuildUrl(service.EventSubUrl, true))
 | 
					                    .Append(BuildUrl(service.EventSubUrl))
 | 
				
			||||||
                    .Append("</eventSubURL>");
 | 
					                    .Append("</eventSubURL>");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                builder.Append("</service>");
 | 
					                builder.Append("</service>");
 | 
				
			||||||
@ -250,13 +250,7 @@ namespace Emby.Dlna.Server
 | 
				
			|||||||
            builder.Append("</serviceList>");
 | 
					            builder.Append("</serviceList>");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        private string BuildUrl(string url)
 | 
				
			||||||
        /// Builds a valid url for inclusion in the xml.
 | 
					 | 
				
			||||||
        /// </summary>
 | 
					 | 
				
			||||||
        /// <param name="url">Url to include.</param>
 | 
					 | 
				
			||||||
        /// <param name="absoluteUrl">Optional. When set to true, the absolute url is always used.</param>
 | 
					 | 
				
			||||||
        /// <returns>The url to use for the element.</returns>
 | 
					 | 
				
			||||||
        private string BuildUrl(string url, bool absoluteUrl = false)
 | 
					 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (string.IsNullOrEmpty(url))
 | 
					            if (string.IsNullOrEmpty(url))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -267,7 +261,7 @@ namespace Emby.Dlna.Server
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            url = "/dlna/" + _serverUdn + "/" + url;
 | 
					            url = "/dlna/" + _serverUdn + "/" + url;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (EnableAbsoluteUrls || absoluteUrl)
 | 
					            if (EnableAbsoluteUrls)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                url = _serverAddress.TrimEnd('/') + url;
 | 
					                url = _serverAddress.TrimEnd('/') + url;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -60,11 +60,9 @@ namespace Emby.Dlna.Service
 | 
				
			|||||||
                    Async = true
 | 
					                    Async = true
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                using (var reader = XmlReader.Create(streamReader, readerSettings))
 | 
					                using var reader = XmlReader.Create(streamReader, readerSettings);
 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                requestInfo = await ParseRequestAsync(reader).ConfigureAwait(false);
 | 
					                requestInfo = await ParseRequestAsync(reader).ConfigureAwait(false);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Logger.LogDebug("Received control request {0}", requestInfo.LocalName);
 | 
					            Logger.LogDebug("Received control request {0}", requestInfo.LocalName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -124,11 +122,9 @@ namespace Emby.Dlna.Service
 | 
				
			|||||||
                            {
 | 
					                            {
 | 
				
			||||||
                                if (!reader.IsEmptyElement)
 | 
					                                if (!reader.IsEmptyElement)
 | 
				
			||||||
                                {
 | 
					                                {
 | 
				
			||||||
                                    using (var subReader = reader.ReadSubtree())
 | 
					                                    using var subReader = reader.ReadSubtree();
 | 
				
			||||||
                                    {
 | 
					 | 
				
			||||||
                                    return await ParseBodyTagAsync(subReader).ConfigureAwait(false);
 | 
					                                    return await ParseBodyTagAsync(subReader).ConfigureAwait(false);
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                                }
 | 
					 | 
				
			||||||
                                else
 | 
					                                else
 | 
				
			||||||
                                {
 | 
					                                {
 | 
				
			||||||
                                    await reader.ReadAsync().ConfigureAwait(false);
 | 
					                                    await reader.ReadAsync().ConfigureAwait(false);
 | 
				
			||||||
@ -150,12 +146,12 @@ namespace Emby.Dlna.Service
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return new ControlRequestInfo();
 | 
					            throw new EndOfStreamException("Stream ended but no body tag found.");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private async Task<ControlRequestInfo> ParseBodyTagAsync(XmlReader reader)
 | 
					        private async Task<ControlRequestInfo> ParseBodyTagAsync(XmlReader reader)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var result = new ControlRequestInfo();
 | 
					            string namespaceURI = null, localName = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            await reader.MoveToContentAsync().ConfigureAwait(false);
 | 
					            await reader.MoveToContentAsync().ConfigureAwait(false);
 | 
				
			||||||
            await reader.ReadAsync().ConfigureAwait(false);
 | 
					            await reader.ReadAsync().ConfigureAwait(false);
 | 
				
			||||||
@ -165,16 +161,14 @@ namespace Emby.Dlna.Service
 | 
				
			|||||||
            {
 | 
					            {
 | 
				
			||||||
                if (reader.NodeType == XmlNodeType.Element)
 | 
					                if (reader.NodeType == XmlNodeType.Element)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    result.LocalName = reader.LocalName;
 | 
					                    localName = reader.LocalName;
 | 
				
			||||||
                    result.NamespaceURI = reader.NamespaceURI;
 | 
					                    namespaceURI = reader.NamespaceURI;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (!reader.IsEmptyElement)
 | 
					                    if (!reader.IsEmptyElement)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        using (var subReader = reader.ReadSubtree())
 | 
					                        var result = new ControlRequestInfo(localName, namespaceURI);
 | 
				
			||||||
                        {
 | 
					                        using var subReader = reader.ReadSubtree();
 | 
				
			||||||
                        await ParseFirstBodyChildAsync(subReader, result.Headers).ConfigureAwait(false);
 | 
					                        await ParseFirstBodyChildAsync(subReader, result.Headers).ConfigureAwait(false);
 | 
				
			||||||
                            return result;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    else
 | 
					                    else
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
@ -187,7 +181,12 @@ namespace Emby.Dlna.Service
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return result;
 | 
					            if (localName != null && namespaceURI != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return new ControlRequestInfo(localName, namespaceURI);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            throw new EndOfStreamException("Stream ended but no control found.");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private async Task ParseFirstBodyChildAsync(XmlReader reader, IDictionary<string, string> headers)
 | 
					        private async Task ParseFirstBodyChildAsync(XmlReader reader, IDictionary<string, string> headers)
 | 
				
			||||||
@ -234,11 +233,18 @@ namespace Emby.Dlna.Service
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        private class ControlRequestInfo
 | 
					        private class ControlRequestInfo
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            public ControlRequestInfo(string localName, string namespaceUri)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                LocalName = localName;
 | 
				
			||||||
 | 
					                NamespaceURI = namespaceUri;
 | 
				
			||||||
 | 
					                Headers = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            public string LocalName { get; set; }
 | 
					            public string LocalName { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            public string NamespaceURI { get; set; }
 | 
					            public string NamespaceURI { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            public Dictionary<string, string> Headers { get; } = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
 | 
					            public Dictionary<string, string> Headers { get; }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -36,7 +36,7 @@ namespace Emby.Drawing
 | 
				
			|||||||
        private readonly IImageEncoder _imageEncoder;
 | 
					        private readonly IImageEncoder _imageEncoder;
 | 
				
			||||||
        private readonly IMediaEncoder _mediaEncoder;
 | 
					        private readonly IMediaEncoder _mediaEncoder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private bool _disposed = false;
 | 
					        private bool _disposed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Initializes a new instance of the <see cref="ImageProcessor"/> class.
 | 
					        /// Initializes a new instance of the <see cref="ImageProcessor"/> class.
 | 
				
			||||||
@ -466,11 +466,11 @@ namespace Emby.Drawing
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <inheritdoc />
 | 
					        /// <inheritdoc />
 | 
				
			||||||
        public void CreateImageCollage(ImageCollageOptions options)
 | 
					        public void CreateImageCollage(ImageCollageOptions options, string? libraryName)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _logger.LogInformation("Creating image collage and saving to {Path}", options.OutputPath);
 | 
					            _logger.LogInformation("Creating image collage and saving to {Path}", options.OutputPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _imageEncoder.CreateImageCollage(options);
 | 
					            _imageEncoder.CreateImageCollage(options, libraryName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _logger.LogInformation("Completed creation of image collage and saved to {Path}", options.OutputPath);
 | 
					            _logger.LogInformation("Completed creation of image collage and saved to {Path}", options.OutputPath);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -38,7 +38,7 @@ namespace Emby.Drawing
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <inheritdoc />
 | 
					        /// <inheritdoc />
 | 
				
			||||||
        public void CreateImageCollage(ImageCollageOptions options)
 | 
					        public void CreateImageCollage(ImageCollageOptions options, string? libraryName)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            throw new NotImplementedException();
 | 
					            throw new NotImplementedException();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					#nullable enable
 | 
				
			||||||
#pragma warning disable CS1591
 | 
					#pragma warning disable CS1591
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
@ -16,21 +17,11 @@ namespace Emby.Naming.AudioBook
 | 
				
			|||||||
            _options = options;
 | 
					            _options = options;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public AudioBookFileInfo ParseFile(string path)
 | 
					        public AudioBookFileInfo? Resolve(string path, bool isDirectory = false)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return Resolve(path, false);
 | 
					            if (path.Length == 0)
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public AudioBookFileInfo ParseDirectory(string path)
 | 
					 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
            return Resolve(path, true);
 | 
					                throw new ArgumentException("String can't be empty.", nameof(path));
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public AudioBookFileInfo Resolve(string path, bool isDirectory = false)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (string.IsNullOrEmpty(path))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                throw new ArgumentNullException(nameof(path));
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // TODO
 | 
					            // TODO
 | 
				
			||||||
 | 
				
			|||||||
@ -128,7 +128,6 @@ namespace Emby.Server.Implementations
 | 
				
			|||||||
        private IMediaEncoder _mediaEncoder;
 | 
					        private IMediaEncoder _mediaEncoder;
 | 
				
			||||||
        private ISessionManager _sessionManager;
 | 
					        private ISessionManager _sessionManager;
 | 
				
			||||||
        private IHttpClientFactory _httpClientFactory;
 | 
					        private IHttpClientFactory _httpClientFactory;
 | 
				
			||||||
        private IWebSocketManager _webSocketManager;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private string[] _urlPrefixes;
 | 
					        private string[] _urlPrefixes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -667,7 +666,6 @@ namespace Emby.Server.Implementations
 | 
				
			|||||||
            _mediaEncoder = Resolve<IMediaEncoder>();
 | 
					            _mediaEncoder = Resolve<IMediaEncoder>();
 | 
				
			||||||
            _sessionManager = Resolve<ISessionManager>();
 | 
					            _sessionManager = Resolve<ISessionManager>();
 | 
				
			||||||
            _httpClientFactory = Resolve<IHttpClientFactory>();
 | 
					            _httpClientFactory = Resolve<IHttpClientFactory>();
 | 
				
			||||||
            _webSocketManager = Resolve<IWebSocketManager>();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ((AuthenticationRepository)Resolve<IAuthenticationRepository>()).Initialize();
 | 
					            ((AuthenticationRepository)Resolve<IAuthenticationRepository>()).Initialize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -788,7 +786,6 @@ namespace Emby.Server.Implementations
 | 
				
			|||||||
                        .ToArray();
 | 
					                        .ToArray();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _urlPrefixes = GetUrlPrefixes().ToArray();
 | 
					            _urlPrefixes = GetUrlPrefixes().ToArray();
 | 
				
			||||||
            _webSocketManager.Init(GetExports<IWebSocketListener>());
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Resolve<ILibraryManager>().AddParts(
 | 
					            Resolve<ILibraryManager>().AddParts(
 | 
				
			||||||
                GetExports<IResolverIgnoreRule>(),
 | 
					                GetExports<IResolverIgnoreRule>(),
 | 
				
			||||||
@ -821,38 +818,6 @@ namespace Emby.Server.Implementations
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            try
 | 
					            try
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                if (plugin is IPluginAssembly assemblyPlugin)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    var assembly = plugin.GetType().Assembly;
 | 
					 | 
				
			||||||
                    var assemblyName = assembly.GetName();
 | 
					 | 
				
			||||||
                    var assemblyFilePath = assembly.Location;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    var dataFolderPath = Path.Combine(ApplicationPaths.PluginsPath, Path.GetFileNameWithoutExtension(assemblyFilePath));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    assemblyPlugin.SetAttributes(assemblyFilePath, dataFolderPath, assemblyName.Version);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    try
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        var idAttributes = assembly.GetCustomAttributes(typeof(GuidAttribute), true);
 | 
					 | 
				
			||||||
                        if (idAttributes.Length > 0)
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            var attribute = (GuidAttribute)idAttributes[0];
 | 
					 | 
				
			||||||
                            var assemblyId = new Guid(attribute.Value);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            assemblyPlugin.SetId(assemblyId);
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    catch (Exception ex)
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        Logger.LogError(ex, "Error getting plugin Id from {PluginName}.", plugin.GetType().FullName);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if (plugin is IHasPluginConfiguration hasPluginConfiguration)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    hasPluginConfiguration.SetStartupInfo(s => Directory.CreateDirectory(s));
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                plugin.RegisterServices(ServiceCollection);
 | 
					                plugin.RegisterServices(ServiceCollection);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            catch (Exception ex)
 | 
					            catch (Exception ex)
 | 
				
			||||||
 | 
				
			|||||||
@ -157,7 +157,8 @@ namespace Emby.Server.Implementations.Data
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        protected bool TableExists(ManagedConnection connection, string name)
 | 
					        protected bool TableExists(ManagedConnection connection, string name)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return connection.RunInTransaction(db =>
 | 
					            return connection.RunInTransaction(
 | 
				
			||||||
 | 
					            db =>
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                using (var statement = PrepareStatement(db, "select DISTINCT tbl_name from sqlite_master"))
 | 
					                using (var statement = PrepareStatement(db, "select DISTINCT tbl_name from sqlite_master"))
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
 | 
				
			|||||||
@ -219,7 +219,8 @@ namespace Emby.Server.Implementations.Data
 | 
				
			|||||||
            {
 | 
					            {
 | 
				
			||||||
                connection.RunQueries(queries);
 | 
					                connection.RunQueries(queries);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                connection.RunInTransaction(db =>
 | 
					                connection.RunInTransaction(
 | 
				
			||||||
 | 
					                db =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    var existingColumnNames = GetColumnNames(db, "AncestorIds");
 | 
					                    var existingColumnNames = GetColumnNames(db, "AncestorIds");
 | 
				
			||||||
                    AddColumn(db, "AncestorIds", "AncestorIdText", "Text", existingColumnNames);
 | 
					                    AddColumn(db, "AncestorIds", "AncestorIdText", "Text", existingColumnNames);
 | 
				
			||||||
@ -495,7 +496,8 @@ namespace Emby.Server.Implementations.Data
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            using (var connection = GetConnection())
 | 
					            using (var connection = GetConnection())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                connection.RunInTransaction(db =>
 | 
					                connection.RunInTransaction(
 | 
				
			||||||
 | 
					                db =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    using (var saveImagesStatement = base.PrepareStatement(db, "Update TypedBaseItems set Images=@Images where guid=@Id"))
 | 
					                    using (var saveImagesStatement = base.PrepareStatement(db, "Update TypedBaseItems set Images=@Images where guid=@Id"))
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
@ -546,7 +548,8 @@ namespace Emby.Server.Implementations.Data
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            using (var connection = GetConnection())
 | 
					            using (var connection = GetConnection())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                connection.RunInTransaction(db =>
 | 
					                connection.RunInTransaction(
 | 
				
			||||||
 | 
					                db =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    SaveItemsInTranscation(db, tuples);
 | 
					                    SaveItemsInTranscation(db, tuples);
 | 
				
			||||||
                }, TransactionMode);
 | 
					                }, TransactionMode);
 | 
				
			||||||
@ -2032,7 +2035,8 @@ namespace Emby.Server.Implementations.Data
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            using (var connection = GetConnection())
 | 
					            using (var connection = GetConnection())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                connection.RunInTransaction(db =>
 | 
					                connection.RunInTransaction(
 | 
				
			||||||
 | 
					                db =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    // First delete chapters
 | 
					                    // First delete chapters
 | 
				
			||||||
                    db.Execute("delete from " + ChaptersTableName + " where ItemId=@ItemId", idBlob);
 | 
					                    db.Execute("delete from " + ChaptersTableName + " where ItemId=@ItemId", idBlob);
 | 
				
			||||||
@ -2921,7 +2925,8 @@ namespace Emby.Server.Implementations.Data
 | 
				
			|||||||
            var result = new QueryResult<BaseItem>();
 | 
					            var result = new QueryResult<BaseItem>();
 | 
				
			||||||
            using (var connection = GetConnection(true))
 | 
					            using (var connection = GetConnection(true))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                connection.RunInTransaction(db =>
 | 
					                connection.RunInTransaction(
 | 
				
			||||||
 | 
					                db =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    var statements = PrepareAll(db, statementTexts);
 | 
					                    var statements = PrepareAll(db, statementTexts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -3324,7 +3329,8 @@ namespace Emby.Server.Implementations.Data
 | 
				
			|||||||
            var result = new QueryResult<Guid>();
 | 
					            var result = new QueryResult<Guid>();
 | 
				
			||||||
            using (var connection = GetConnection(true))
 | 
					            using (var connection = GetConnection(true))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                connection.RunInTransaction(db =>
 | 
					                connection.RunInTransaction(
 | 
				
			||||||
 | 
					                db =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    var statements = PrepareAll(db, statementTexts);
 | 
					                    var statements = PrepareAll(db, statementTexts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -4899,7 +4905,8 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            using (var connection = GetConnection())
 | 
					            using (var connection = GetConnection())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                connection.RunInTransaction(db =>
 | 
					                connection.RunInTransaction(
 | 
				
			||||||
 | 
					                db =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    connection.ExecuteAll(sql);
 | 
					                    connection.ExecuteAll(sql);
 | 
				
			||||||
                }, TransactionMode);
 | 
					                }, TransactionMode);
 | 
				
			||||||
@ -4950,7 +4957,8 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            using (var connection = GetConnection())
 | 
					            using (var connection = GetConnection())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                connection.RunInTransaction(db =>
 | 
					                connection.RunInTransaction(
 | 
				
			||||||
 | 
					                db =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    var idBlob = id.ToByteArray();
 | 
					                    var idBlob = id.ToByteArray();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -5357,7 +5365,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                itemCountColumns = new Dictionary<string, string>()
 | 
					                itemCountColumns = new Dictionary<string, string>()
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    { "itemTypes", "(" + itemCountColumnQuery + ") as itemTypes"}
 | 
					                    { "itemTypes", "(" + itemCountColumnQuery + ") as itemTypes" }
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -5744,7 +5752,8 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            using (var connection = GetConnection())
 | 
					            using (var connection = GetConnection())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                connection.RunInTransaction(db =>
 | 
					                connection.RunInTransaction(
 | 
				
			||||||
 | 
					                db =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    var itemIdBlob = itemId.ToByteArray();
 | 
					                    var itemIdBlob = itemId.ToByteArray();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -5898,7 +5907,8 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            using (var connection = GetConnection())
 | 
					            using (var connection = GetConnection())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                connection.RunInTransaction(db =>
 | 
					                connection.RunInTransaction(
 | 
				
			||||||
 | 
					                db =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    var itemIdBlob = id.ToByteArray();
 | 
					                    var itemIdBlob = id.ToByteArray();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -6232,7 +6242,8 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            using (var connection = GetConnection())
 | 
					            using (var connection = GetConnection())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                connection.RunInTransaction(db =>
 | 
					                connection.RunInTransaction(
 | 
				
			||||||
 | 
					                db =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    var itemIdBlob = id.ToByteArray();
 | 
					                    var itemIdBlob = id.ToByteArray();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -44,7 +44,8 @@ namespace Emby.Server.Implementations.Data
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                var users = userDatasTableExists ? null : userManager.Users;
 | 
					                var users = userDatasTableExists ? null : userManager.Users;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                connection.RunInTransaction(db =>
 | 
					                connection.RunInTransaction(
 | 
				
			||||||
 | 
					                db =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    db.ExecuteAll(string.Join(";", new[] {
 | 
					                    db.ExecuteAll(string.Join(";", new[] {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -178,7 +179,8 @@ namespace Emby.Server.Implementations.Data
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            using (var connection = GetConnection())
 | 
					            using (var connection = GetConnection())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                connection.RunInTransaction(db =>
 | 
					                connection.RunInTransaction(
 | 
				
			||||||
 | 
					                db =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    SaveUserData(db, internalUserId, key, userData);
 | 
					                    SaveUserData(db, internalUserId, key, userData);
 | 
				
			||||||
                }, TransactionMode);
 | 
					                }, TransactionMode);
 | 
				
			||||||
@ -246,7 +248,8 @@ namespace Emby.Server.Implementations.Data
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            using (var connection = GetConnection())
 | 
					            using (var connection = GetConnection())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                connection.RunInTransaction(db =>
 | 
					                connection.RunInTransaction(
 | 
				
			||||||
 | 
					                db =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    foreach (var userItemData in userDataList)
 | 
					                    foreach (var userItemData in userDataList)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
 | 
				
			|||||||
@ -32,10 +32,10 @@
 | 
				
			|||||||
    <PackageReference Include="Microsoft.AspNetCore.ResponseCompression" Version="2.2.0" />
 | 
					    <PackageReference Include="Microsoft.AspNetCore.ResponseCompression" Version="2.2.0" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
 | 
					    <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.2.1" />
 | 
					    <PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.2.1" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.8" />
 | 
					    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.9" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="3.1.8" />
 | 
					    <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="3.1.9" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.8" />
 | 
					    <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.9" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.8" />
 | 
					    <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.9" />
 | 
				
			||||||
    <PackageReference Include="Mono.Nat" Version="3.0.0" />
 | 
					    <PackageReference Include="Mono.Nat" Version="3.0.0" />
 | 
				
			||||||
    <PackageReference Include="prometheus-net.DotNetRuntime" Version="3.4.0" />
 | 
					    <PackageReference Include="prometheus-net.DotNetRuntime" Version="3.4.0" />
 | 
				
			||||||
    <PackageReference Include="ServiceStack.Text.Core" Version="5.9.2" />
 | 
					    <PackageReference Include="ServiceStack.Text.Core" Version="5.9.2" />
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using System.Linq;
 | 
					 | 
				
			||||||
using System.Net.WebSockets;
 | 
					using System.Net.WebSockets;
 | 
				
			||||||
using System.Threading.Tasks;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
using Jellyfin.Data.Events;
 | 
					using Jellyfin.Data.Events;
 | 
				
			||||||
@ -14,16 +13,18 @@ namespace Emby.Server.Implementations.HttpServer
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public class WebSocketManager : IWebSocketManager
 | 
					    public class WebSocketManager : IWebSocketManager
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        private readonly Lazy<IEnumerable<IWebSocketListener>> _webSocketListeners;
 | 
				
			||||||
        private readonly ILogger<WebSocketManager> _logger;
 | 
					        private readonly ILogger<WebSocketManager> _logger;
 | 
				
			||||||
        private readonly ILoggerFactory _loggerFactory;
 | 
					        private readonly ILoggerFactory _loggerFactory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private IWebSocketListener[] _webSocketListeners = Array.Empty<IWebSocketListener>();
 | 
					 | 
				
			||||||
        private bool _disposed = false;
 | 
					        private bool _disposed = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public WebSocketManager(
 | 
					        public WebSocketManager(
 | 
				
			||||||
 | 
					            Lazy<IEnumerable<IWebSocketListener>> webSocketListeners,
 | 
				
			||||||
            ILogger<WebSocketManager> logger,
 | 
					            ILogger<WebSocketManager> logger,
 | 
				
			||||||
            ILoggerFactory loggerFactory)
 | 
					            ILoggerFactory loggerFactory)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            _webSocketListeners = webSocketListeners;
 | 
				
			||||||
            _logger = logger;
 | 
					            _logger = logger;
 | 
				
			||||||
            _loggerFactory = loggerFactory;
 | 
					            _loggerFactory = loggerFactory;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -68,15 +69,6 @@ namespace Emby.Server.Implementations.HttpServer
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					 | 
				
			||||||
        /// Adds the rest handlers.
 | 
					 | 
				
			||||||
        /// </summary>
 | 
					 | 
				
			||||||
        /// <param name="listeners">The web socket listeners.</param>
 | 
					 | 
				
			||||||
        public void Init(IEnumerable<IWebSocketListener> listeners)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            _webSocketListeners = listeners.ToArray();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Processes the web socket message received.
 | 
					        /// Processes the web socket message received.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
@ -90,7 +82,8 @@ namespace Emby.Server.Implementations.HttpServer
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            IEnumerable<Task> GetTasks()
 | 
					            IEnumerable<Task> GetTasks()
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                foreach (var x in _webSocketListeners)
 | 
					                var listeners = _webSocketListeners.Value;
 | 
				
			||||||
 | 
					                foreach (var x in listeners)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    yield return x.ProcessMessageAsync(result);
 | 
					                    yield return x.ProcessMessageAsync(result);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
				
			|||||||
@ -133,9 +133,20 @@ namespace Emby.Server.Implementations.Images
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        protected virtual IEnumerable<string> GetStripCollageImagePaths(BaseItem primaryItem, IEnumerable<BaseItem> items)
 | 
					        protected virtual IEnumerable<string> GetStripCollageImagePaths(BaseItem primaryItem, IEnumerable<BaseItem> items)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            var useBackdrop = primaryItem is CollectionFolder;
 | 
				
			||||||
            return items
 | 
					            return items
 | 
				
			||||||
                .Select(i =>
 | 
					                .Select(i =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
 | 
					                    // Use Backdrop instead of Primary image for Library images.
 | 
				
			||||||
 | 
					                    if (useBackdrop)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        var backdrop = i.GetImageInfo(ImageType.Backdrop, 0);
 | 
				
			||||||
 | 
					                        if (backdrop != null && backdrop.IsLocalFile)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            return backdrop.Path;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    var image = i.GetImageInfo(ImageType.Primary, 0);
 | 
					                    var image = i.GetImageInfo(ImageType.Primary, 0);
 | 
				
			||||||
                    if (image != null && image.IsLocalFile)
 | 
					                    if (image != null && image.IsLocalFile)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
@ -190,7 +201,7 @@ namespace Emby.Server.Implementations.Images
 | 
				
			|||||||
                return null;
 | 
					                return null;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ImageProcessor.CreateImageCollage(options);
 | 
					            ImageProcessor.CreateImageCollage(options, primaryItem.Name);
 | 
				
			||||||
            return outputPath;
 | 
					            return outputPath;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
#pragma warning disable CS1591
 | 
					#pragma warning disable CS1591
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Concurrent;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using System.Globalization;
 | 
					using System.Globalization;
 | 
				
			||||||
using System.IO;
 | 
					using System.IO;
 | 
				
			||||||
@ -43,7 +44,7 @@ namespace Emby.Server.Implementations.Library
 | 
				
			|||||||
        private readonly ILocalizationManager _localizationManager;
 | 
					        private readonly ILocalizationManager _localizationManager;
 | 
				
			||||||
        private readonly IApplicationPaths _appPaths;
 | 
					        private readonly IApplicationPaths _appPaths;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private readonly Dictionary<string, ILiveStream> _openStreams = new Dictionary<string, ILiveStream>(StringComparer.OrdinalIgnoreCase);
 | 
					        private readonly ConcurrentDictionary<string, ILiveStream> _openStreams = new ConcurrentDictionary<string, ILiveStream>(StringComparer.OrdinalIgnoreCase);
 | 
				
			||||||
        private readonly SemaphoreSlim _liveStreamSemaphore = new SemaphoreSlim(1, 1);
 | 
					        private readonly SemaphoreSlim _liveStreamSemaphore = new SemaphoreSlim(1, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private IMediaSourceProvider[] _providers;
 | 
					        private IMediaSourceProvider[] _providers;
 | 
				
			||||||
@ -582,11 +583,7 @@ namespace Emby.Server.Implementations.Library
 | 
				
			|||||||
            mediaSource.InferTotalBitrate();
 | 
					            mediaSource.InferTotalBitrate();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public async Task<IDirectStreamProvider> GetDirectStreamProviderByUniqueId(string uniqueId, CancellationToken cancellationToken)
 | 
					        public Task<IDirectStreamProvider> GetDirectStreamProviderByUniqueId(string uniqueId, CancellationToken cancellationToken)
 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            try
 | 
					 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var info = _openStreams.Values.FirstOrDefault(i =>
 | 
					            var info = _openStreams.Values.FirstOrDefault(i =>
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -599,12 +596,7 @@ namespace Emby.Server.Implementations.Library
 | 
				
			|||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return info as IDirectStreamProvider;
 | 
					            return Task.FromResult(info as IDirectStreamProvider);
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            finally
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                _liveStreamSemaphore.Release();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public async Task<LiveStreamResponse> OpenLiveStream(LiveStreamRequest request, CancellationToken cancellationToken)
 | 
					        public async Task<LiveStreamResponse> OpenLiveStream(LiveStreamRequest request, CancellationToken cancellationToken)
 | 
				
			||||||
@ -793,29 +785,20 @@ namespace Emby.Server.Implementations.Library
 | 
				
			|||||||
            return new Tuple<MediaSourceInfo, IDirectStreamProvider>(info.MediaSource, info as IDirectStreamProvider);
 | 
					            return new Tuple<MediaSourceInfo, IDirectStreamProvider>(info.MediaSource, info as IDirectStreamProvider);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private async Task<ILiveStream> GetLiveStreamInfo(string id, CancellationToken cancellationToken)
 | 
					        private Task<ILiveStream> GetLiveStreamInfo(string id, CancellationToken cancellationToken)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (string.IsNullOrEmpty(id))
 | 
					            if (string.IsNullOrEmpty(id))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                throw new ArgumentNullException(nameof(id));
 | 
					                throw new ArgumentNullException(nameof(id));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            try
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
            if (_openStreams.TryGetValue(id, out ILiveStream info))
 | 
					            if (_openStreams.TryGetValue(id, out ILiveStream info))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                    return info;
 | 
					                return Task.FromResult(info);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                    throw new ResourceNotFoundException();
 | 
					                return Task.FromException<ILiveStream>(new ResourceNotFoundException());
 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            finally
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                _liveStreamSemaphore.Release();
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -844,7 +827,7 @@ namespace Emby.Server.Implementations.Library
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                    if (liveStream.ConsumerCount <= 0)
 | 
					                    if (liveStream.ConsumerCount <= 0)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        _openStreams.Remove(id);
 | 
					                        _openStreams.TryRemove(id, out _);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        _logger.LogInformation("Closing live stream {0}", id);
 | 
					                        _logger.LogInformation("Closing live stream {0}", id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -32,7 +32,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
 | 
				
			|||||||
        /// <value>The priority.</value>
 | 
					        /// <value>The priority.</value>
 | 
				
			||||||
        public override ResolverPriority Priority => ResolverPriority.Fourth;
 | 
					        public override ResolverPriority Priority => ResolverPriority.Fourth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public MultiItemResolverResult ResolveMultiple(Folder parent,
 | 
					        public MultiItemResolverResult ResolveMultiple(
 | 
				
			||||||
 | 
					            Folder parent,
 | 
				
			||||||
            List<FileSystemMetadata> files,
 | 
					            List<FileSystemMetadata> files,
 | 
				
			||||||
            string collectionType,
 | 
					            string collectionType,
 | 
				
			||||||
            IDirectoryService directoryService)
 | 
					            IDirectoryService directoryService)
 | 
				
			||||||
@ -50,7 +51,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
 | 
				
			|||||||
            return result;
 | 
					            return result;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private MultiItemResolverResult ResolveMultipleInternal(Folder parent,
 | 
					        private MultiItemResolverResult ResolveMultipleInternal(
 | 
				
			||||||
 | 
					            Folder parent,
 | 
				
			||||||
            List<FileSystemMetadata> files,
 | 
					            List<FileSystemMetadata> files,
 | 
				
			||||||
            string collectionType,
 | 
					            string collectionType,
 | 
				
			||||||
            IDirectoryService directoryService)
 | 
					            IDirectoryService directoryService)
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,8 @@
 | 
				
			|||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
using Emby.Naming.Audio;
 | 
					using Emby.Naming.Audio;
 | 
				
			||||||
using MediaBrowser.Controller.Entities.Audio;
 | 
					using MediaBrowser.Controller.Entities.Audio;
 | 
				
			||||||
using MediaBrowser.Controller.Library;
 | 
					using MediaBrowser.Controller.Library;
 | 
				
			||||||
@ -113,22 +116,29 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
 | 
				
			|||||||
            IFileSystem fileSystem,
 | 
					            IFileSystem fileSystem,
 | 
				
			||||||
            ILibraryManager libraryManager)
 | 
					            ILibraryManager libraryManager)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            // check for audio files before digging down into directories
 | 
				
			||||||
 | 
					            var foundAudioFile = list.Any(fileSystemInfo => !fileSystemInfo.IsDirectory && libraryManager.IsAudioFile(fileSystemInfo.FullName));
 | 
				
			||||||
 | 
					            if (foundAudioFile)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // at least one audio file exists
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!allowSubfolders)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // not music since no audio file exists and we're not looking into subfolders
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var discSubfolderCount = 0;
 | 
					            var discSubfolderCount = 0;
 | 
				
			||||||
            var notMultiDisc = false;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions();
 | 
					            var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions();
 | 
				
			||||||
            var parser = new AlbumParser(namingOptions);
 | 
					            var parser = new AlbumParser(namingOptions);
 | 
				
			||||||
            foreach (var fileSystemInfo in list)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                if (fileSystemInfo.IsDirectory)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    if (allowSubfolders)
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        if (notMultiDisc)
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            continue;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var directories = list.Where(fileSystemInfo => fileSystemInfo.IsDirectory);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var result = Parallel.ForEach(directories, (fileSystemInfo, state) =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
                var path = fileSystemInfo.FullName;
 | 
					                var path = fileSystemInfo.FullName;
 | 
				
			||||||
                var hasMusic = ContainsMusic(directoryService.GetFileSystemEntries(path), false, directoryService, logger, fileSystem, libraryManager);
 | 
					                var hasMusic = ContainsMusic(directoryService.GetFileSystemEntries(path), false, directoryService, logger, fileSystem, libraryManager);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -137,28 +147,17 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
 | 
				
			|||||||
                    if (parser.IsMultiPart(path))
 | 
					                    if (parser.IsMultiPart(path))
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        logger.LogDebug("Found multi-disc folder: " + path);
 | 
					                        logger.LogDebug("Found multi-disc folder: " + path);
 | 
				
			||||||
                                discSubfolderCount++;
 | 
					                        Interlocked.Increment(ref discSubfolderCount);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    else
 | 
					                    else
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        // If there are folders underneath with music that are not multidisc, then this can't be a multi-disc album
 | 
					                        // If there are folders underneath with music that are not multidisc, then this can't be a multi-disc album
 | 
				
			||||||
                                notMultiDisc = true;
 | 
					                        state.Stop();
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                    }
 | 
					            });
 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                else
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    var fullName = fileSystemInfo.FullName;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (libraryManager.IsAudioFile(fullName))
 | 
					            if (!result.IsCompleted)
 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        return true;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (notMultiDisc)
 | 
					 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Linq;
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
using MediaBrowser.Controller.Configuration;
 | 
					using MediaBrowser.Controller.Configuration;
 | 
				
			||||||
using MediaBrowser.Controller.Entities.Audio;
 | 
					using MediaBrowser.Controller.Entities.Audio;
 | 
				
			||||||
using MediaBrowser.Controller.Library;
 | 
					using MediaBrowser.Controller.Library;
 | 
				
			||||||
@ -94,7 +95,18 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
 | 
				
			|||||||
            var albumResolver = new MusicAlbumResolver(_logger, _fileSystem, _libraryManager);
 | 
					            var albumResolver = new MusicAlbumResolver(_logger, _fileSystem, _libraryManager);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // If we contain an album assume we are an artist folder
 | 
					            // If we contain an album assume we are an artist folder
 | 
				
			||||||
            return args.FileSystemChildren.Where(i => i.IsDirectory).Any(i => albumResolver.IsMusicAlbum(i.FullName, directoryService)) ? new MusicArtist() : null;
 | 
					            var directories = args.FileSystemChildren.Where(i => i.IsDirectory);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var result = Parallel.ForEach(directories, (fileSystemInfo, state) =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (albumResolver.IsMusicAlbum(fileSystemInfo.FullName, directoryService))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    // stop once we see a music album
 | 
				
			||||||
 | 
					                    state.Stop();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return !result.IsCompleted ? new MusicArtist() : null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -50,7 +50,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Books
 | 
				
			|||||||
                var fileExtension = Path.GetExtension(f.FullName) ??
 | 
					                var fileExtension = Path.GetExtension(f.FullName) ??
 | 
				
			||||||
                                    string.Empty;
 | 
					                                    string.Empty;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return _validExtensions.Contains(fileExtension,
 | 
					                return _validExtensions.Contains(
 | 
				
			||||||
 | 
					                    fileExtension,
 | 
				
			||||||
                                                StringComparer
 | 
					                                                StringComparer
 | 
				
			||||||
                                                    .OrdinalIgnoreCase);
 | 
					                                                    .OrdinalIgnoreCase);
 | 
				
			||||||
            }).ToList();
 | 
					            }).ToList();
 | 
				
			||||||
 | 
				
			|||||||
@ -43,7 +43,7 @@ namespace Emby.Server.Implementations.LiveTv
 | 
				
			|||||||
            return new[]
 | 
					            return new[]
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // Every so often
 | 
					                // Every so often
 | 
				
			||||||
                new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks}
 | 
					                new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks }
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -85,7 +85,6 @@
 | 
				
			|||||||
    "ItemAddedWithName": "{0} is in die versameling",
 | 
					    "ItemAddedWithName": "{0} is in die versameling",
 | 
				
			||||||
    "HomeVideos": "Tuis opnames",
 | 
					    "HomeVideos": "Tuis opnames",
 | 
				
			||||||
    "HeaderRecordingGroups": "Groep Opnames",
 | 
					    "HeaderRecordingGroups": "Groep Opnames",
 | 
				
			||||||
    "HeaderCameraUploads": "Kamera Oplaai",
 | 
					 | 
				
			||||||
    "Genres": "Genres",
 | 
					    "Genres": "Genres",
 | 
				
			||||||
    "FailedLoginAttemptWithUserName": "Mislukte aansluiting van {0}",
 | 
					    "FailedLoginAttemptWithUserName": "Mislukte aansluiting van {0}",
 | 
				
			||||||
    "ChapterNameValue": "Hoofstuk",
 | 
					    "ChapterNameValue": "Hoofstuk",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "المجلدات",
 | 
					    "Folders": "المجلدات",
 | 
				
			||||||
    "Genres": "التضنيفات",
 | 
					    "Genres": "التضنيفات",
 | 
				
			||||||
    "HeaderAlbumArtists": "فناني الألبومات",
 | 
					    "HeaderAlbumArtists": "فناني الألبومات",
 | 
				
			||||||
    "HeaderCameraUploads": "تحميلات الكاميرا",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "استئناف",
 | 
					    "HeaderContinueWatching": "استئناف",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "الألبومات المفضلة",
 | 
					    "HeaderFavoriteAlbums": "الألبومات المفضلة",
 | 
				
			||||||
    "HeaderFavoriteArtists": "الفنانون المفضلون",
 | 
					    "HeaderFavoriteArtists": "الفنانون المفضلون",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Папки",
 | 
					    "Folders": "Папки",
 | 
				
			||||||
    "Genres": "Жанрове",
 | 
					    "Genres": "Жанрове",
 | 
				
			||||||
    "HeaderAlbumArtists": "Изпълнители на албуми",
 | 
					    "HeaderAlbumArtists": "Изпълнители на албуми",
 | 
				
			||||||
    "HeaderCameraUploads": "Качени от камера",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Продължаване на гледането",
 | 
					    "HeaderContinueWatching": "Продължаване на гледането",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Любими албуми",
 | 
					    "HeaderFavoriteAlbums": "Любими албуми",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Любими изпълнители",
 | 
					    "HeaderFavoriteArtists": "Любими изпълнители",
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,6 @@
 | 
				
			|||||||
    "HeaderFavoriteArtists": "প্রিয় শিল্পীরা",
 | 
					    "HeaderFavoriteArtists": "প্রিয় শিল্পীরা",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "প্রিয় এলবামগুলো",
 | 
					    "HeaderFavoriteAlbums": "প্রিয় এলবামগুলো",
 | 
				
			||||||
    "HeaderContinueWatching": "দেখতে থাকুন",
 | 
					    "HeaderContinueWatching": "দেখতে থাকুন",
 | 
				
			||||||
    "HeaderCameraUploads": "ক্যামেরার আপলোড সমূহ",
 | 
					 | 
				
			||||||
    "HeaderAlbumArtists": "এলবাম শিল্পী",
 | 
					    "HeaderAlbumArtists": "এলবাম শিল্পী",
 | 
				
			||||||
    "Genres": "জেনার",
 | 
					    "Genres": "জেনার",
 | 
				
			||||||
    "Folders": "ফোল্ডারগুলো",
 | 
					    "Folders": "ফোল্ডারগুলো",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Carpetes",
 | 
					    "Folders": "Carpetes",
 | 
				
			||||||
    "Genres": "Gèneres",
 | 
					    "Genres": "Gèneres",
 | 
				
			||||||
    "HeaderAlbumArtists": "Artistes del Àlbum",
 | 
					    "HeaderAlbumArtists": "Artistes del Àlbum",
 | 
				
			||||||
    "HeaderCameraUploads": "Pujades de Càmera",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Continua Veient",
 | 
					    "HeaderContinueWatching": "Continua Veient",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Àlbums Preferits",
 | 
					    "HeaderFavoriteAlbums": "Àlbums Preferits",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Artistes Preferits",
 | 
					    "HeaderFavoriteArtists": "Artistes Preferits",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Složky",
 | 
					    "Folders": "Složky",
 | 
				
			||||||
    "Genres": "Žánry",
 | 
					    "Genres": "Žánry",
 | 
				
			||||||
    "HeaderAlbumArtists": "Umělci alba",
 | 
					    "HeaderAlbumArtists": "Umělci alba",
 | 
				
			||||||
    "HeaderCameraUploads": "Nahrané fotografie",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Pokračovat ve sledování",
 | 
					    "HeaderContinueWatching": "Pokračovat ve sledování",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Oblíbená alba",
 | 
					    "HeaderFavoriteAlbums": "Oblíbená alba",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Oblíbení interpreti",
 | 
					    "HeaderFavoriteArtists": "Oblíbení interpreti",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Mapper",
 | 
					    "Folders": "Mapper",
 | 
				
			||||||
    "Genres": "Genrer",
 | 
					    "Genres": "Genrer",
 | 
				
			||||||
    "HeaderAlbumArtists": "Albumkunstnere",
 | 
					    "HeaderAlbumArtists": "Albumkunstnere",
 | 
				
			||||||
    "HeaderCameraUploads": "Kamera Uploads",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Fortsæt Afspilning",
 | 
					    "HeaderContinueWatching": "Fortsæt Afspilning",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Favoritalbummer",
 | 
					    "HeaderFavoriteAlbums": "Favoritalbummer",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Favoritkunstnere",
 | 
					    "HeaderFavoriteArtists": "Favoritkunstnere",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Verzeichnisse",
 | 
					    "Folders": "Verzeichnisse",
 | 
				
			||||||
    "Genres": "Genres",
 | 
					    "Genres": "Genres",
 | 
				
			||||||
    "HeaderAlbumArtists": "Album-Interpreten",
 | 
					    "HeaderAlbumArtists": "Album-Interpreten",
 | 
				
			||||||
    "HeaderCameraUploads": "Kamera-Uploads",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Fortsetzen",
 | 
					    "HeaderContinueWatching": "Fortsetzen",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Lieblingsalben",
 | 
					    "HeaderFavoriteAlbums": "Lieblingsalben",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Lieblings-Interpreten",
 | 
					    "HeaderFavoriteArtists": "Lieblings-Interpreten",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Φάκελοι",
 | 
					    "Folders": "Φάκελοι",
 | 
				
			||||||
    "Genres": "Είδη",
 | 
					    "Genres": "Είδη",
 | 
				
			||||||
    "HeaderAlbumArtists": "Καλλιτέχνες του Άλμπουμ",
 | 
					    "HeaderAlbumArtists": "Καλλιτέχνες του Άλμπουμ",
 | 
				
			||||||
    "HeaderCameraUploads": "Μεταφορτώσεις Κάμερας",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Συνεχίστε την παρακολούθηση",
 | 
					    "HeaderContinueWatching": "Συνεχίστε την παρακολούθηση",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Αγαπημένα Άλμπουμ",
 | 
					    "HeaderFavoriteAlbums": "Αγαπημένα Άλμπουμ",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Αγαπημένοι Καλλιτέχνες",
 | 
					    "HeaderFavoriteArtists": "Αγαπημένοι Καλλιτέχνες",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Folders",
 | 
					    "Folders": "Folders",
 | 
				
			||||||
    "Genres": "Genres",
 | 
					    "Genres": "Genres",
 | 
				
			||||||
    "HeaderAlbumArtists": "Album Artists",
 | 
					    "HeaderAlbumArtists": "Album Artists",
 | 
				
			||||||
    "HeaderCameraUploads": "Camera Uploads",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Continue Watching",
 | 
					    "HeaderContinueWatching": "Continue Watching",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Favourite Albums",
 | 
					    "HeaderFavoriteAlbums": "Favourite Albums",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Favourite Artists",
 | 
					    "HeaderFavoriteArtists": "Favourite Artists",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Folders",
 | 
					    "Folders": "Folders",
 | 
				
			||||||
    "Genres": "Genres",
 | 
					    "Genres": "Genres",
 | 
				
			||||||
    "HeaderAlbumArtists": "Album Artists",
 | 
					    "HeaderAlbumArtists": "Album Artists",
 | 
				
			||||||
    "HeaderCameraUploads": "Camera Uploads",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Continue Watching",
 | 
					    "HeaderContinueWatching": "Continue Watching",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Favorite Albums",
 | 
					    "HeaderFavoriteAlbums": "Favorite Albums",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Favorite Artists",
 | 
					    "HeaderFavoriteArtists": "Favorite Artists",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Carpetas",
 | 
					    "Folders": "Carpetas",
 | 
				
			||||||
    "Genres": "Géneros",
 | 
					    "Genres": "Géneros",
 | 
				
			||||||
    "HeaderAlbumArtists": "Artistas de álbum",
 | 
					    "HeaderAlbumArtists": "Artistas de álbum",
 | 
				
			||||||
    "HeaderCameraUploads": "Subidas de cámara",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Seguir viendo",
 | 
					    "HeaderContinueWatching": "Seguir viendo",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Álbumes favoritos",
 | 
					    "HeaderFavoriteAlbums": "Álbumes favoritos",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Artistas favoritos",
 | 
					    "HeaderFavoriteArtists": "Artistas favoritos",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Carpetas",
 | 
					    "Folders": "Carpetas",
 | 
				
			||||||
    "Genres": "Géneros",
 | 
					    "Genres": "Géneros",
 | 
				
			||||||
    "HeaderAlbumArtists": "Artistas del álbum",
 | 
					    "HeaderAlbumArtists": "Artistas del álbum",
 | 
				
			||||||
    "HeaderCameraUploads": "Subidas desde la cámara",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Continuar viendo",
 | 
					    "HeaderContinueWatching": "Continuar viendo",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Álbumes favoritos",
 | 
					    "HeaderFavoriteAlbums": "Álbumes favoritos",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Artistas favoritos",
 | 
					    "HeaderFavoriteArtists": "Artistas favoritos",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Carpetas",
 | 
					    "Folders": "Carpetas",
 | 
				
			||||||
    "Genres": "Géneros",
 | 
					    "Genres": "Géneros",
 | 
				
			||||||
    "HeaderAlbumArtists": "Artistas del álbum",
 | 
					    "HeaderAlbumArtists": "Artistas del álbum",
 | 
				
			||||||
    "HeaderCameraUploads": "Subidas desde la cámara",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Continuar viendo",
 | 
					    "HeaderContinueWatching": "Continuar viendo",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Álbumes favoritos",
 | 
					    "HeaderFavoriteAlbums": "Álbumes favoritos",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Artistas favoritos",
 | 
					    "HeaderFavoriteArtists": "Artistas favoritos",
 | 
				
			||||||
 | 
				
			|||||||
@ -105,7 +105,6 @@
 | 
				
			|||||||
    "Inherit": "Heredar",
 | 
					    "Inherit": "Heredar",
 | 
				
			||||||
    "HomeVideos": "Videos caseros",
 | 
					    "HomeVideos": "Videos caseros",
 | 
				
			||||||
    "HeaderRecordingGroups": "Grupos de grabación",
 | 
					    "HeaderRecordingGroups": "Grupos de grabación",
 | 
				
			||||||
    "HeaderCameraUploads": "Subidas desde la cámara",
 | 
					 | 
				
			||||||
    "FailedLoginAttemptWithUserName": "Intento fallido de inicio de sesión desde {0}",
 | 
					    "FailedLoginAttemptWithUserName": "Intento fallido de inicio de sesión desde {0}",
 | 
				
			||||||
    "DeviceOnlineWithName": "{0} está conectado",
 | 
					    "DeviceOnlineWithName": "{0} está conectado",
 | 
				
			||||||
    "DeviceOfflineWithName": "{0} se ha desconectado",
 | 
					    "DeviceOfflineWithName": "{0} se ha desconectado",
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,6 @@
 | 
				
			|||||||
    "Application": "Aplicación",
 | 
					    "Application": "Aplicación",
 | 
				
			||||||
    "AppDeviceValues": "App: {0}, Dispositivo: {1}",
 | 
					    "AppDeviceValues": "App: {0}, Dispositivo: {1}",
 | 
				
			||||||
    "HeaderContinueWatching": "Continuar Viendo",
 | 
					    "HeaderContinueWatching": "Continuar Viendo",
 | 
				
			||||||
    "HeaderCameraUploads": "Subidas de Cámara",
 | 
					 | 
				
			||||||
    "HeaderAlbumArtists": "Artistas del Álbum",
 | 
					    "HeaderAlbumArtists": "Artistas del Álbum",
 | 
				
			||||||
    "Genres": "Géneros",
 | 
					    "Genres": "Géneros",
 | 
				
			||||||
    "Folders": "Carpetas",
 | 
					    "Folders": "Carpetas",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "پوشهها",
 | 
					    "Folders": "پوشهها",
 | 
				
			||||||
    "Genres": "ژانرها",
 | 
					    "Genres": "ژانرها",
 | 
				
			||||||
    "HeaderAlbumArtists": "هنرمندان آلبوم",
 | 
					    "HeaderAlbumArtists": "هنرمندان آلبوم",
 | 
				
			||||||
    "HeaderCameraUploads": "آپلودهای دوربین",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "ادامه تماشا",
 | 
					    "HeaderContinueWatching": "ادامه تماشا",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "آلبومهای مورد علاقه",
 | 
					    "HeaderFavoriteAlbums": "آلبومهای مورد علاقه",
 | 
				
			||||||
    "HeaderFavoriteArtists": "هنرمندان مورد علاقه",
 | 
					    "HeaderFavoriteArtists": "هنرمندان مورد علاقه",
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    "HeaderLiveTV": "Live-TV",
 | 
					    "HeaderLiveTV": "Live-TV",
 | 
				
			||||||
    "NewVersionIsAvailable": "Uusi versio Jellyfin palvelimesta on ladattavissa.",
 | 
					    "NewVersionIsAvailable": "Uusi versio Jellyfin palvelimesta on ladattavissa.",
 | 
				
			||||||
    "NameSeasonUnknown": "Tuntematon Kausi",
 | 
					    "NameSeasonUnknown": "Tuntematon kausi",
 | 
				
			||||||
    "NameSeasonNumber": "Kausi {0}",
 | 
					    "NameSeasonNumber": "Kausi {0}",
 | 
				
			||||||
    "NameInstallFailed": "{0} asennus epäonnistui",
 | 
					    "NameInstallFailed": "{0} asennus epäonnistui",
 | 
				
			||||||
    "MusicVideos": "Musiikkivideot",
 | 
					    "MusicVideos": "Musiikkivideot",
 | 
				
			||||||
@ -19,24 +19,23 @@
 | 
				
			|||||||
    "ItemAddedWithName": "{0} lisättiin kirjastoon",
 | 
					    "ItemAddedWithName": "{0} lisättiin kirjastoon",
 | 
				
			||||||
    "Inherit": "Periytyä",
 | 
					    "Inherit": "Periytyä",
 | 
				
			||||||
    "HomeVideos": "Kotivideot",
 | 
					    "HomeVideos": "Kotivideot",
 | 
				
			||||||
    "HeaderRecordingGroups": "Nauhoiteryhmät",
 | 
					    "HeaderRecordingGroups": "Tallennusryhmät",
 | 
				
			||||||
    "HeaderNextUp": "Seuraavaksi",
 | 
					    "HeaderNextUp": "Seuraavaksi",
 | 
				
			||||||
    "HeaderFavoriteSongs": "Lempikappaleet",
 | 
					    "HeaderFavoriteSongs": "Suosikkikappaleet",
 | 
				
			||||||
    "HeaderFavoriteShows": "Lempisarjat",
 | 
					    "HeaderFavoriteShows": "Suosikkisarjat",
 | 
				
			||||||
    "HeaderFavoriteEpisodes": "Lempijaksot",
 | 
					    "HeaderFavoriteEpisodes": "Suosikkijaksot",
 | 
				
			||||||
    "HeaderCameraUploads": "Kamerasta Lähetetyt",
 | 
					    "HeaderFavoriteArtists": "Suosikkiartistit",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Lempiartistit",
 | 
					    "HeaderFavoriteAlbums": "Suosikkialbumit",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Lempialbumit",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Jatka katsomista",
 | 
					    "HeaderContinueWatching": "Jatka katsomista",
 | 
				
			||||||
    "HeaderAlbumArtists": "Albumin esittäjä",
 | 
					    "HeaderAlbumArtists": "Albumin artistit",
 | 
				
			||||||
    "Genres": "Tyylilajit",
 | 
					    "Genres": "Tyylilajit",
 | 
				
			||||||
    "Folders": "Kansiot",
 | 
					    "Folders": "Kansiot",
 | 
				
			||||||
    "Favorites": "Suosikit",
 | 
					    "Favorites": "Suosikit",
 | 
				
			||||||
    "FailedLoginAttemptWithUserName": "Kirjautuminen epäonnistui kohteesta {0}",
 | 
					    "FailedLoginAttemptWithUserName": "Kirjautuminen epäonnistui kohteesta {0}",
 | 
				
			||||||
    "DeviceOnlineWithName": "{0} on yhdistetty",
 | 
					    "DeviceOnlineWithName": "{0} on yhdistetty",
 | 
				
			||||||
    "DeviceOfflineWithName": "{0} on katkaissut yhteytensä",
 | 
					    "DeviceOfflineWithName": "{0} yhteys on katkaistu",
 | 
				
			||||||
    "Collections": "Kokoelmat",
 | 
					    "Collections": "Kokoelmat",
 | 
				
			||||||
    "ChapterNameValue": "Luku: {0}",
 | 
					    "ChapterNameValue": "Jakso: {0}",
 | 
				
			||||||
    "Channels": "Kanavat",
 | 
					    "Channels": "Kanavat",
 | 
				
			||||||
    "CameraImageUploadedFrom": "Uusi kamerakuva on ladattu {0}",
 | 
					    "CameraImageUploadedFrom": "Uusi kamerakuva on ladattu {0}",
 | 
				
			||||||
    "Books": "Kirjat",
 | 
					    "Books": "Kirjat",
 | 
				
			||||||
@ -62,25 +61,25 @@
 | 
				
			|||||||
    "UserPolicyUpdatedWithName": "Käyttöoikeudet päivitetty käyttäjälle {0}",
 | 
					    "UserPolicyUpdatedWithName": "Käyttöoikeudet päivitetty käyttäjälle {0}",
 | 
				
			||||||
    "UserPasswordChangedWithName": "Salasana vaihdettu käyttäjälle {0}",
 | 
					    "UserPasswordChangedWithName": "Salasana vaihdettu käyttäjälle {0}",
 | 
				
			||||||
    "UserOnlineFromDevice": "{0} on paikalla osoitteesta {1}",
 | 
					    "UserOnlineFromDevice": "{0} on paikalla osoitteesta {1}",
 | 
				
			||||||
    "UserOfflineFromDevice": "{0} yhteys katkaistu {1}",
 | 
					    "UserOfflineFromDevice": "{0} yhteys katkaistu kohteesta {1}",
 | 
				
			||||||
    "UserLockedOutWithName": "Käyttäjä {0} lukittu",
 | 
					    "UserLockedOutWithName": "Käyttäjä {0} lukittu",
 | 
				
			||||||
    "UserDownloadingItemWithValues": "{0} lataa {1}",
 | 
					    "UserDownloadingItemWithValues": "{0} lataa {1}",
 | 
				
			||||||
    "UserDeletedWithName": "Käyttäjä {0} poistettu",
 | 
					    "UserDeletedWithName": "Käyttäjä {0} poistettu",
 | 
				
			||||||
    "UserCreatedWithName": "Käyttäjä {0} luotu",
 | 
					    "UserCreatedWithName": "Käyttäjä {0} luotu",
 | 
				
			||||||
    "TvShows": "TV-sarjat",
 | 
					    "TvShows": "TV-ohjelmat",
 | 
				
			||||||
    "Sync": "Synkronoi",
 | 
					    "Sync": "Synkronoi",
 | 
				
			||||||
    "SubtitleDownloadFailureFromForItem": "Tekstitysten lataus ({0} -> {1}) epäonnistui //this string would have to be generated for each provider and movie because of finnish cases, sorry",
 | 
					    "SubtitleDownloadFailureFromForItem": "Tekstitystä ei voitu ladata osoitteesta {0} kohteelle {1}",
 | 
				
			||||||
    "StartupEmbyServerIsLoading": "Jellyfin palvelin latautuu. Kokeile hetken kuluttua uudelleen.",
 | 
					    "StartupEmbyServerIsLoading": "Jellyfin palvelin latautuu. Yritä hetken kuluttua uudelleen.",
 | 
				
			||||||
    "Songs": "Kappaleet",
 | 
					    "Songs": "Kappaleet",
 | 
				
			||||||
    "Shows": "Sarjat",
 | 
					    "Shows": "Ohjelmat",
 | 
				
			||||||
    "ServerNameNeedsToBeRestarted": "{0} täytyy käynnistää uudelleen",
 | 
					    "ServerNameNeedsToBeRestarted": "{0} on käynnistettävä uudelleen",
 | 
				
			||||||
    "ProviderValue": "Tarjoaja: {0}",
 | 
					    "ProviderValue": "Tarjoaja: {0}",
 | 
				
			||||||
    "Plugin": "Liitännäinen",
 | 
					    "Plugin": "Liitännäinen",
 | 
				
			||||||
    "NotificationOptionVideoPlaybackStopped": "Videon toisto pysäytetty",
 | 
					    "NotificationOptionVideoPlaybackStopped": "Videon toisto pysäytetty",
 | 
				
			||||||
    "NotificationOptionVideoPlayback": "Videota toistetaan",
 | 
					    "NotificationOptionVideoPlayback": "Videota toistetaan",
 | 
				
			||||||
    "NotificationOptionUserLockedOut": "Käyttäjä kirjautui ulos",
 | 
					    "NotificationOptionUserLockedOut": "Käyttäjä kirjautui ulos",
 | 
				
			||||||
    "NotificationOptionTaskFailed": "Ajastettu tehtävä epäonnistui",
 | 
					    "NotificationOptionTaskFailed": "Ajastettu tehtävä epäonnistui",
 | 
				
			||||||
    "NotificationOptionServerRestartRequired": "Palvelin pitää käynnistää uudelleen",
 | 
					    "NotificationOptionServerRestartRequired": "Palvelin on käynnistettävä uudelleen",
 | 
				
			||||||
    "NotificationOptionPluginUpdateInstalled": "Liitännäinen päivitetty",
 | 
					    "NotificationOptionPluginUpdateInstalled": "Liitännäinen päivitetty",
 | 
				
			||||||
    "NotificationOptionPluginUninstalled": "Liitännäinen poistettu",
 | 
					    "NotificationOptionPluginUninstalled": "Liitännäinen poistettu",
 | 
				
			||||||
    "NotificationOptionPluginInstalled": "Liitännäinen asennettu",
 | 
					    "NotificationOptionPluginInstalled": "Liitännäinen asennettu",
 | 
				
			||||||
@ -105,10 +104,10 @@
 | 
				
			|||||||
    "TaskRefreshPeople": "Päivitä henkilöt",
 | 
					    "TaskRefreshPeople": "Päivitä henkilöt",
 | 
				
			||||||
    "TaskCleanLogsDescription": "Poistaa lokitiedostot jotka ovat yli {0} päivää vanhoja.",
 | 
					    "TaskCleanLogsDescription": "Poistaa lokitiedostot jotka ovat yli {0} päivää vanhoja.",
 | 
				
			||||||
    "TaskCleanLogs": "Puhdista lokihakemisto",
 | 
					    "TaskCleanLogs": "Puhdista lokihakemisto",
 | 
				
			||||||
    "TaskRefreshLibraryDescription": "Skannaa mediakirjastosi uusien tiedostojen varalle, sekä virkistää metatiedot.",
 | 
					    "TaskRefreshLibraryDescription": "Skannaa mediakirjastosi uudet tiedostot ja päivittää metatiedot.",
 | 
				
			||||||
    "TaskRefreshLibrary": "Skannaa mediakirjasto",
 | 
					    "TaskRefreshLibrary": "Skannaa mediakirjasto",
 | 
				
			||||||
    "TaskRefreshChapterImagesDescription": "Luo pienoiskuvat videoille joissa on lukuja.",
 | 
					    "TaskRefreshChapterImagesDescription": "Luo pienoiskuvat videoille joissa on jaksoja.",
 | 
				
			||||||
    "TaskRefreshChapterImages": "Eristä lukujen kuvat",
 | 
					    "TaskRefreshChapterImages": "Pura jakson kuvat",
 | 
				
			||||||
    "TaskCleanCacheDescription": "Poistaa järjestelmälle tarpeettomat väliaikaistiedostot.",
 | 
					    "TaskCleanCacheDescription": "Poistaa järjestelmälle tarpeettomat väliaikaistiedostot.",
 | 
				
			||||||
    "TaskCleanCache": "Tyhjennä välimuisti-hakemisto",
 | 
					    "TaskCleanCache": "Tyhjennä välimuisti-hakemisto",
 | 
				
			||||||
    "TasksChannelsCategory": "Internet kanavat",
 | 
					    "TasksChannelsCategory": "Internet kanavat",
 | 
				
			||||||
 | 
				
			|||||||
@ -73,7 +73,6 @@
 | 
				
			|||||||
    "HeaderFavoriteArtists": "Paboritong Artista",
 | 
					    "HeaderFavoriteArtists": "Paboritong Artista",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Paboritong Albums",
 | 
					    "HeaderFavoriteAlbums": "Paboritong Albums",
 | 
				
			||||||
    "HeaderContinueWatching": "Ituloy Manood",
 | 
					    "HeaderContinueWatching": "Ituloy Manood",
 | 
				
			||||||
    "HeaderCameraUploads": "Camera Uploads",
 | 
					 | 
				
			||||||
    "HeaderAlbumArtists": "Artista ng Album",
 | 
					    "HeaderAlbumArtists": "Artista ng Album",
 | 
				
			||||||
    "Genres": "Kategorya",
 | 
					    "Genres": "Kategorya",
 | 
				
			||||||
    "Folders": "Folders",
 | 
					    "Folders": "Folders",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Dossiers",
 | 
					    "Folders": "Dossiers",
 | 
				
			||||||
    "Genres": "Genres",
 | 
					    "Genres": "Genres",
 | 
				
			||||||
    "HeaderAlbumArtists": "Artistes de l'album",
 | 
					    "HeaderAlbumArtists": "Artistes de l'album",
 | 
				
			||||||
    "HeaderCameraUploads": "Photos transférées",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Continuer à regarder",
 | 
					    "HeaderContinueWatching": "Continuer à regarder",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Albums favoris",
 | 
					    "HeaderFavoriteAlbums": "Albums favoris",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Artistes favoris",
 | 
					    "HeaderFavoriteArtists": "Artistes favoris",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Dossiers",
 | 
					    "Folders": "Dossiers",
 | 
				
			||||||
    "Genres": "Genres",
 | 
					    "Genres": "Genres",
 | 
				
			||||||
    "HeaderAlbumArtists": "Artistes",
 | 
					    "HeaderAlbumArtists": "Artistes",
 | 
				
			||||||
    "HeaderCameraUploads": "Photos transférées",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Continuer à regarder",
 | 
					    "HeaderContinueWatching": "Continuer à regarder",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Albums favoris",
 | 
					    "HeaderFavoriteAlbums": "Albums favoris",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Artistes préférés",
 | 
					    "HeaderFavoriteArtists": "Artistes préférés",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Ordner",
 | 
					    "Folders": "Ordner",
 | 
				
			||||||
    "Genres": "Genres",
 | 
					    "Genres": "Genres",
 | 
				
			||||||
    "HeaderAlbumArtists": "Album-Künstler",
 | 
					    "HeaderAlbumArtists": "Album-Künstler",
 | 
				
			||||||
    "HeaderCameraUploads": "Kamera-Uploads",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "weiter schauen",
 | 
					    "HeaderContinueWatching": "weiter schauen",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Lieblingsalben",
 | 
					    "HeaderFavoriteAlbums": "Lieblingsalben",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Lieblings-Künstler",
 | 
					    "HeaderFavoriteArtists": "Lieblings-Künstler",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "תיקיות",
 | 
					    "Folders": "תיקיות",
 | 
				
			||||||
    "Genres": "ז'אנרים",
 | 
					    "Genres": "ז'אנרים",
 | 
				
			||||||
    "HeaderAlbumArtists": "אמני האלבום",
 | 
					    "HeaderAlbumArtists": "אמני האלבום",
 | 
				
			||||||
    "HeaderCameraUploads": "העלאות ממצלמה",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "המשך לצפות",
 | 
					    "HeaderContinueWatching": "המשך לצפות",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "אלבומים מועדפים",
 | 
					    "HeaderFavoriteAlbums": "אלבומים מועדפים",
 | 
				
			||||||
    "HeaderFavoriteArtists": "אמנים מועדפים",
 | 
					    "HeaderFavoriteArtists": "אמנים מועדפים",
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										3
									
								
								Emby.Server.Implementations/Localization/Core/hi.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								Emby.Server.Implementations/Localization/Core/hi.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "Albums": "आल्बुम्"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Mape",
 | 
					    "Folders": "Mape",
 | 
				
			||||||
    "Genres": "Žanrovi",
 | 
					    "Genres": "Žanrovi",
 | 
				
			||||||
    "HeaderAlbumArtists": "Izvođači na albumu",
 | 
					    "HeaderAlbumArtists": "Izvođači na albumu",
 | 
				
			||||||
    "HeaderCameraUploads": "Uvoz sa kamere",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Nastavi gledati",
 | 
					    "HeaderContinueWatching": "Nastavi gledati",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Omiljeni albumi",
 | 
					    "HeaderFavoriteAlbums": "Omiljeni albumi",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Omiljeni izvođači",
 | 
					    "HeaderFavoriteArtists": "Omiljeni izvođači",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Könyvtárak",
 | 
					    "Folders": "Könyvtárak",
 | 
				
			||||||
    "Genres": "Műfajok",
 | 
					    "Genres": "Műfajok",
 | 
				
			||||||
    "HeaderAlbumArtists": "Album előadók",
 | 
					    "HeaderAlbumArtists": "Album előadók",
 | 
				
			||||||
    "HeaderCameraUploads": "Kamera feltöltések",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Megtekintés folytatása",
 | 
					    "HeaderContinueWatching": "Megtekintés folytatása",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Kedvenc albumok",
 | 
					    "HeaderFavoriteAlbums": "Kedvenc albumok",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Kedvenc előadók",
 | 
					    "HeaderFavoriteArtists": "Kedvenc előadók",
 | 
				
			||||||
 | 
				
			|||||||
@ -20,7 +20,6 @@
 | 
				
			|||||||
    "HeaderFavoriteArtists": "Artis Favorit",
 | 
					    "HeaderFavoriteArtists": "Artis Favorit",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Album Favorit",
 | 
					    "HeaderFavoriteAlbums": "Album Favorit",
 | 
				
			||||||
    "HeaderContinueWatching": "Lanjut Menonton",
 | 
					    "HeaderContinueWatching": "Lanjut Menonton",
 | 
				
			||||||
    "HeaderCameraUploads": "Unggahan Kamera",
 | 
					 | 
				
			||||||
    "HeaderAlbumArtists": "Album Artis",
 | 
					    "HeaderAlbumArtists": "Album Artis",
 | 
				
			||||||
    "Genres": "Aliran",
 | 
					    "Genres": "Aliran",
 | 
				
			||||||
    "Folders": "Folder",
 | 
					    "Folders": "Folder",
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,6 @@
 | 
				
			|||||||
    "HeaderFavoriteArtists": "Uppáhalds Listamenn",
 | 
					    "HeaderFavoriteArtists": "Uppáhalds Listamenn",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Uppáhalds Plötur",
 | 
					    "HeaderFavoriteAlbums": "Uppáhalds Plötur",
 | 
				
			||||||
    "HeaderContinueWatching": "Halda áfram að horfa",
 | 
					    "HeaderContinueWatching": "Halda áfram að horfa",
 | 
				
			||||||
    "HeaderCameraUploads": "Myndavéla upphal",
 | 
					 | 
				
			||||||
    "HeaderAlbumArtists": "Höfundur plötu",
 | 
					    "HeaderAlbumArtists": "Höfundur plötu",
 | 
				
			||||||
    "Genres": "Tegundir",
 | 
					    "Genres": "Tegundir",
 | 
				
			||||||
    "Folders": "Möppur",
 | 
					    "Folders": "Möppur",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Cartelle",
 | 
					    "Folders": "Cartelle",
 | 
				
			||||||
    "Genres": "Generi",
 | 
					    "Genres": "Generi",
 | 
				
			||||||
    "HeaderAlbumArtists": "Artisti degli Album",
 | 
					    "HeaderAlbumArtists": "Artisti degli Album",
 | 
				
			||||||
    "HeaderCameraUploads": "Caricamenti Fotocamera",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Continua a guardare",
 | 
					    "HeaderContinueWatching": "Continua a guardare",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Album Preferiti",
 | 
					    "HeaderFavoriteAlbums": "Album Preferiti",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Artisti Preferiti",
 | 
					    "HeaderFavoriteArtists": "Artisti Preferiti",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "フォルダー",
 | 
					    "Folders": "フォルダー",
 | 
				
			||||||
    "Genres": "ジャンル",
 | 
					    "Genres": "ジャンル",
 | 
				
			||||||
    "HeaderAlbumArtists": "アルバムアーティスト",
 | 
					    "HeaderAlbumArtists": "アルバムアーティスト",
 | 
				
			||||||
    "HeaderCameraUploads": "カメラアップロード",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "視聴を続ける",
 | 
					    "HeaderContinueWatching": "視聴を続ける",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "お気に入りのアルバム",
 | 
					    "HeaderFavoriteAlbums": "お気に入りのアルバム",
 | 
				
			||||||
    "HeaderFavoriteArtists": "お気に入りのアーティスト",
 | 
					    "HeaderFavoriteArtists": "お気に入りのアーティスト",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Qaltalar",
 | 
					    "Folders": "Qaltalar",
 | 
				
			||||||
    "Genres": "Janrlar",
 | 
					    "Genres": "Janrlar",
 | 
				
			||||||
    "HeaderAlbumArtists": "Álbom oryndaýshylary",
 | 
					    "HeaderAlbumArtists": "Álbom oryndaýshylary",
 | 
				
			||||||
    "HeaderCameraUploads": "Kameradan júktelgender",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Qaraýdy jalǵastyrý",
 | 
					    "HeaderContinueWatching": "Qaraýdy jalǵastyrý",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Tańdaýly álbomdar",
 | 
					    "HeaderFavoriteAlbums": "Tańdaýly álbomdar",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Tańdaýly oryndaýshylar",
 | 
					    "HeaderFavoriteArtists": "Tańdaýly oryndaýshylar",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "폴더",
 | 
					    "Folders": "폴더",
 | 
				
			||||||
    "Genres": "장르",
 | 
					    "Genres": "장르",
 | 
				
			||||||
    "HeaderAlbumArtists": "앨범 아티스트",
 | 
					    "HeaderAlbumArtists": "앨범 아티스트",
 | 
				
			||||||
    "HeaderCameraUploads": "카메라 업로드",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "계속 시청하기",
 | 
					    "HeaderContinueWatching": "계속 시청하기",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "즐겨찾는 앨범",
 | 
					    "HeaderFavoriteAlbums": "즐겨찾는 앨범",
 | 
				
			||||||
    "HeaderFavoriteArtists": "즐겨찾는 아티스트",
 | 
					    "HeaderFavoriteArtists": "즐겨찾는 아티스트",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Katalogai",
 | 
					    "Folders": "Katalogai",
 | 
				
			||||||
    "Genres": "Žanrai",
 | 
					    "Genres": "Žanrai",
 | 
				
			||||||
    "HeaderAlbumArtists": "Albumo atlikėjai",
 | 
					    "HeaderAlbumArtists": "Albumo atlikėjai",
 | 
				
			||||||
    "HeaderCameraUploads": "Kameros",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Žiūrėti toliau",
 | 
					    "HeaderContinueWatching": "Žiūrėti toliau",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Mėgstami Albumai",
 | 
					    "HeaderFavoriteAlbums": "Mėgstami Albumai",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Mėgstami Atlikėjai",
 | 
					    "HeaderFavoriteArtists": "Mėgstami Atlikėjai",
 | 
				
			||||||
 | 
				
			|||||||
@ -72,7 +72,6 @@
 | 
				
			|||||||
    "ItemAddedWithName": "{0} tika pievienots bibliotēkai",
 | 
					    "ItemAddedWithName": "{0} tika pievienots bibliotēkai",
 | 
				
			||||||
    "HeaderLiveTV": "Tiešraides TV",
 | 
					    "HeaderLiveTV": "Tiešraides TV",
 | 
				
			||||||
    "HeaderContinueWatching": "Turpināt Skatīšanos",
 | 
					    "HeaderContinueWatching": "Turpināt Skatīšanos",
 | 
				
			||||||
    "HeaderCameraUploads": "Kameras augšupielādes",
 | 
					 | 
				
			||||||
    "HeaderAlbumArtists": "Albumu Izpildītāji",
 | 
					    "HeaderAlbumArtists": "Albumu Izpildītāji",
 | 
				
			||||||
    "Genres": "Žanri",
 | 
					    "Genres": "Žanri",
 | 
				
			||||||
    "Folders": "Mapes",
 | 
					    "Folders": "Mapes",
 | 
				
			||||||
 | 
				
			|||||||
@ -51,7 +51,6 @@
 | 
				
			|||||||
    "HeaderFavoriteArtists": "Омилени Изведувачи",
 | 
					    "HeaderFavoriteArtists": "Омилени Изведувачи",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Омилени Албуми",
 | 
					    "HeaderFavoriteAlbums": "Омилени Албуми",
 | 
				
			||||||
    "HeaderContinueWatching": "Продолжи со гледање",
 | 
					    "HeaderContinueWatching": "Продолжи со гледање",
 | 
				
			||||||
    "HeaderCameraUploads": "Поставувања од камера",
 | 
					 | 
				
			||||||
    "HeaderAlbumArtists": "Изведувачи од Албуми",
 | 
					    "HeaderAlbumArtists": "Изведувачи од Албуми",
 | 
				
			||||||
    "Genres": "Жанрови",
 | 
					    "Genres": "Жанрови",
 | 
				
			||||||
    "Folders": "Папки",
 | 
					    "Folders": "Папки",
 | 
				
			||||||
 | 
				
			|||||||
@ -54,7 +54,6 @@
 | 
				
			|||||||
    "ItemAddedWithName": "{0} हे संग्रहालयात जोडले गेले",
 | 
					    "ItemAddedWithName": "{0} हे संग्रहालयात जोडले गेले",
 | 
				
			||||||
    "HomeVideos": "घरचे व्हिडीयो",
 | 
					    "HomeVideos": "घरचे व्हिडीयो",
 | 
				
			||||||
    "HeaderRecordingGroups": "रेकॉर्डिंग गट",
 | 
					    "HeaderRecordingGroups": "रेकॉर्डिंग गट",
 | 
				
			||||||
    "HeaderCameraUploads": "कॅमेरा अपलोड",
 | 
					 | 
				
			||||||
    "CameraImageUploadedFrom": "एक नवीन कॅमेरा चित्र {0} येथून अपलोड केले आहे",
 | 
					    "CameraImageUploadedFrom": "एक नवीन कॅमेरा चित्र {0} येथून अपलोड केले आहे",
 | 
				
			||||||
    "Application": "अॅप्लिकेशन",
 | 
					    "Application": "अॅप्लिकेशन",
 | 
				
			||||||
    "AppDeviceValues": "अॅप: {0}, यंत्र: {1}",
 | 
					    "AppDeviceValues": "अॅप: {0}, यंत्र: {1}",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Fail-fail",
 | 
					    "Folders": "Fail-fail",
 | 
				
			||||||
    "Genres": "Genre-genre",
 | 
					    "Genres": "Genre-genre",
 | 
				
			||||||
    "HeaderAlbumArtists": "Album Artis-artis",
 | 
					    "HeaderAlbumArtists": "Album Artis-artis",
 | 
				
			||||||
    "HeaderCameraUploads": "Muatnaik Kamera",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Terus Menonton",
 | 
					    "HeaderContinueWatching": "Terus Menonton",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Album-album Kegemaran",
 | 
					    "HeaderFavoriteAlbums": "Album-album Kegemaran",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Artis-artis Kegemaran",
 | 
					    "HeaderFavoriteArtists": "Artis-artis Kegemaran",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Mapper",
 | 
					    "Folders": "Mapper",
 | 
				
			||||||
    "Genres": "Sjangre",
 | 
					    "Genres": "Sjangre",
 | 
				
			||||||
    "HeaderAlbumArtists": "Albumartister",
 | 
					    "HeaderAlbumArtists": "Albumartister",
 | 
				
			||||||
    "HeaderCameraUploads": "Kameraopplastinger",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Fortsett å se",
 | 
					    "HeaderContinueWatching": "Fortsett å se",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Favorittalbum",
 | 
					    "HeaderFavoriteAlbums": "Favorittalbum",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Favorittartister",
 | 
					    "HeaderFavoriteArtists": "Favorittartister",
 | 
				
			||||||
 | 
				
			|||||||
@ -41,7 +41,6 @@
 | 
				
			|||||||
    "HeaderFavoriteArtists": "मनपर्ने कलाकारहरू",
 | 
					    "HeaderFavoriteArtists": "मनपर्ने कलाकारहरू",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "मनपर्ने एल्बमहरू",
 | 
					    "HeaderFavoriteAlbums": "मनपर्ने एल्बमहरू",
 | 
				
			||||||
    "HeaderContinueWatching": "हेर्न जारी राख्नुहोस्",
 | 
					    "HeaderContinueWatching": "हेर्न जारी राख्नुहोस्",
 | 
				
			||||||
    "HeaderCameraUploads": "क्यामेरा अपलोडहरू",
 | 
					 | 
				
			||||||
    "HeaderAlbumArtists": "एल्बमका कलाकारहरू",
 | 
					    "HeaderAlbumArtists": "एल्बमका कलाकारहरू",
 | 
				
			||||||
    "Genres": "विधाहरू",
 | 
					    "Genres": "विधाहरू",
 | 
				
			||||||
    "Folders": "फोल्डरहरू",
 | 
					    "Folders": "फोल्डरहरू",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Mappen",
 | 
					    "Folders": "Mappen",
 | 
				
			||||||
    "Genres": "Genres",
 | 
					    "Genres": "Genres",
 | 
				
			||||||
    "HeaderAlbumArtists": "Albumartiesten",
 | 
					    "HeaderAlbumArtists": "Albumartiesten",
 | 
				
			||||||
    "HeaderCameraUploads": "Camera-uploads",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Kijken hervatten",
 | 
					    "HeaderContinueWatching": "Kijken hervatten",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Favoriete albums",
 | 
					    "HeaderFavoriteAlbums": "Favoriete albums",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Favoriete artiesten",
 | 
					    "HeaderFavoriteArtists": "Favoriete artiesten",
 | 
				
			||||||
 | 
				
			|||||||
@ -19,7 +19,6 @@
 | 
				
			|||||||
    "HeaderFavoriteArtists": "Favoritt Artistar",
 | 
					    "HeaderFavoriteArtists": "Favoritt Artistar",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Favoritt Album",
 | 
					    "HeaderFavoriteAlbums": "Favoritt Album",
 | 
				
			||||||
    "HeaderContinueWatching": "Fortsett å sjå",
 | 
					    "HeaderContinueWatching": "Fortsett å sjå",
 | 
				
			||||||
    "HeaderCameraUploads": "Kamera Opplastingar",
 | 
					 | 
				
			||||||
    "HeaderAlbumArtists": "Album Artist",
 | 
					    "HeaderAlbumArtists": "Album Artist",
 | 
				
			||||||
    "Genres": "Sjangrar",
 | 
					    "Genres": "Sjangrar",
 | 
				
			||||||
    "Folders": "Mapper",
 | 
					    "Folders": "Mapper",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Foldery",
 | 
					    "Folders": "Foldery",
 | 
				
			||||||
    "Genres": "Gatunki",
 | 
					    "Genres": "Gatunki",
 | 
				
			||||||
    "HeaderAlbumArtists": "Wykonawcy albumów",
 | 
					    "HeaderAlbumArtists": "Wykonawcy albumów",
 | 
				
			||||||
    "HeaderCameraUploads": "Przekazane obrazy",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Kontynuuj odtwarzanie",
 | 
					    "HeaderContinueWatching": "Kontynuuj odtwarzanie",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Ulubione albumy",
 | 
					    "HeaderFavoriteAlbums": "Ulubione albumy",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Ulubieni wykonawcy",
 | 
					    "HeaderFavoriteArtists": "Ulubieni wykonawcy",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Pastas",
 | 
					    "Folders": "Pastas",
 | 
				
			||||||
    "Genres": "Gêneros",
 | 
					    "Genres": "Gêneros",
 | 
				
			||||||
    "HeaderAlbumArtists": "Artistas do Álbum",
 | 
					    "HeaderAlbumArtists": "Artistas do Álbum",
 | 
				
			||||||
    "HeaderCameraUploads": "Envios da Câmera",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Continuar Assistindo",
 | 
					    "HeaderContinueWatching": "Continuar Assistindo",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Álbuns Favoritos",
 | 
					    "HeaderFavoriteAlbums": "Álbuns Favoritos",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Artistas favoritos",
 | 
					    "HeaderFavoriteArtists": "Artistas favoritos",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Pastas",
 | 
					    "Folders": "Pastas",
 | 
				
			||||||
    "Genres": "Géneros",
 | 
					    "Genres": "Géneros",
 | 
				
			||||||
    "HeaderAlbumArtists": "Artistas do Álbum",
 | 
					    "HeaderAlbumArtists": "Artistas do Álbum",
 | 
				
			||||||
    "HeaderCameraUploads": "Envios a partir da câmara",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Continuar a Ver",
 | 
					    "HeaderContinueWatching": "Continuar a Ver",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Álbuns Favoritos",
 | 
					    "HeaderFavoriteAlbums": "Álbuns Favoritos",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Artistas Favoritos",
 | 
					    "HeaderFavoriteArtists": "Artistas Favoritos",
 | 
				
			||||||
@ -26,7 +25,7 @@
 | 
				
			|||||||
    "HeaderLiveTV": "TV em Direto",
 | 
					    "HeaderLiveTV": "TV em Direto",
 | 
				
			||||||
    "HeaderNextUp": "A Seguir",
 | 
					    "HeaderNextUp": "A Seguir",
 | 
				
			||||||
    "HeaderRecordingGroups": "Grupos de Gravação",
 | 
					    "HeaderRecordingGroups": "Grupos de Gravação",
 | 
				
			||||||
    "HomeVideos": "Videos caseiros",
 | 
					    "HomeVideos": "Vídeos Caseiros",
 | 
				
			||||||
    "Inherit": "Herdar",
 | 
					    "Inherit": "Herdar",
 | 
				
			||||||
    "ItemAddedWithName": "{0} foi adicionado à biblioteca",
 | 
					    "ItemAddedWithName": "{0} foi adicionado à biblioteca",
 | 
				
			||||||
    "ItemRemovedWithName": "{0} foi removido da biblioteca",
 | 
					    "ItemRemovedWithName": "{0} foi removido da biblioteca",
 | 
				
			||||||
 | 
				
			|||||||
@ -83,7 +83,6 @@
 | 
				
			|||||||
    "Playlists": "Listas de Reprodução",
 | 
					    "Playlists": "Listas de Reprodução",
 | 
				
			||||||
    "Photos": "Fotografias",
 | 
					    "Photos": "Fotografias",
 | 
				
			||||||
    "Movies": "Filmes",
 | 
					    "Movies": "Filmes",
 | 
				
			||||||
    "HeaderCameraUploads": "Carregamentos a partir da câmara",
 | 
					 | 
				
			||||||
    "FailedLoginAttemptWithUserName": "Tentativa de ligação falhada a partir de {0}",
 | 
					    "FailedLoginAttemptWithUserName": "Tentativa de ligação falhada a partir de {0}",
 | 
				
			||||||
    "DeviceOnlineWithName": "{0} está connectado",
 | 
					    "DeviceOnlineWithName": "{0} está connectado",
 | 
				
			||||||
    "DeviceOfflineWithName": "{0} desconectou-se",
 | 
					    "DeviceOfflineWithName": "{0} desconectou-se",
 | 
				
			||||||
 | 
				
			|||||||
@ -74,7 +74,6 @@
 | 
				
			|||||||
    "HeaderFavoriteArtists": "Artiști Favoriți",
 | 
					    "HeaderFavoriteArtists": "Artiști Favoriți",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Albume Favorite",
 | 
					    "HeaderFavoriteAlbums": "Albume Favorite",
 | 
				
			||||||
    "HeaderContinueWatching": "Vizionează în continuare",
 | 
					    "HeaderContinueWatching": "Vizionează în continuare",
 | 
				
			||||||
    "HeaderCameraUploads": "Incărcări Cameră Foto",
 | 
					 | 
				
			||||||
    "HeaderAlbumArtists": "Album Artiști",
 | 
					    "HeaderAlbumArtists": "Album Artiști",
 | 
				
			||||||
    "Genres": "Genuri",
 | 
					    "Genres": "Genuri",
 | 
				
			||||||
    "Folders": "Dosare",
 | 
					    "Folders": "Dosare",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Папки",
 | 
					    "Folders": "Папки",
 | 
				
			||||||
    "Genres": "Жанры",
 | 
					    "Genres": "Жанры",
 | 
				
			||||||
    "HeaderAlbumArtists": "Исполнители альбома",
 | 
					    "HeaderAlbumArtists": "Исполнители альбома",
 | 
				
			||||||
    "HeaderCameraUploads": "Камеры",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Продолжение просмотра",
 | 
					    "HeaderContinueWatching": "Продолжение просмотра",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Избранные альбомы",
 | 
					    "HeaderFavoriteAlbums": "Избранные альбомы",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Избранные исполнители",
 | 
					    "HeaderFavoriteArtists": "Избранные исполнители",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Priečinky",
 | 
					    "Folders": "Priečinky",
 | 
				
			||||||
    "Genres": "Žánre",
 | 
					    "Genres": "Žánre",
 | 
				
			||||||
    "HeaderAlbumArtists": "Umelci albumu",
 | 
					    "HeaderAlbumArtists": "Umelci albumu",
 | 
				
			||||||
    "HeaderCameraUploads": "Nahrané fotografie",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Pokračovať v pozeraní",
 | 
					    "HeaderContinueWatching": "Pokračovať v pozeraní",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Obľúbené albumy",
 | 
					    "HeaderFavoriteAlbums": "Obľúbené albumy",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Obľúbení umelci",
 | 
					    "HeaderFavoriteArtists": "Obľúbení umelci",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Mape",
 | 
					    "Folders": "Mape",
 | 
				
			||||||
    "Genres": "Zvrsti",
 | 
					    "Genres": "Zvrsti",
 | 
				
			||||||
    "HeaderAlbumArtists": "Izvajalci albuma",
 | 
					    "HeaderAlbumArtists": "Izvajalci albuma",
 | 
				
			||||||
    "HeaderCameraUploads": "Posnetki kamere",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Nadaljuj gledanje",
 | 
					    "HeaderContinueWatching": "Nadaljuj gledanje",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Priljubljeni albumi",
 | 
					    "HeaderFavoriteAlbums": "Priljubljeni albumi",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Priljubljeni izvajalci",
 | 
					    "HeaderFavoriteArtists": "Priljubljeni izvajalci",
 | 
				
			||||||
 | 
				
			|||||||
@ -96,7 +96,6 @@
 | 
				
			|||||||
    "HeaderFavoriteArtists": "Artistët e preferuar",
 | 
					    "HeaderFavoriteArtists": "Artistët e preferuar",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Albumet e preferuar",
 | 
					    "HeaderFavoriteAlbums": "Albumet e preferuar",
 | 
				
			||||||
    "HeaderContinueWatching": "Vazhdo të shikosh",
 | 
					    "HeaderContinueWatching": "Vazhdo të shikosh",
 | 
				
			||||||
    "HeaderCameraUploads": "Ngarkimet nga Kamera",
 | 
					 | 
				
			||||||
    "HeaderAlbumArtists": "Artistët e albumeve",
 | 
					    "HeaderAlbumArtists": "Artistët e albumeve",
 | 
				
			||||||
    "Genres": "Zhanre",
 | 
					    "Genres": "Zhanre",
 | 
				
			||||||
    "Folders": "Dosje",
 | 
					    "Folders": "Dosje",
 | 
				
			||||||
@ -113,5 +112,5 @@
 | 
				
			|||||||
    "Artists": "Artistë",
 | 
					    "Artists": "Artistë",
 | 
				
			||||||
    "Application": "Aplikacioni",
 | 
					    "Application": "Aplikacioni",
 | 
				
			||||||
    "AppDeviceValues": "Aplikacioni: {0}, Pajisja: {1}",
 | 
					    "AppDeviceValues": "Aplikacioni: {0}, Pajisja: {1}",
 | 
				
			||||||
    "Albums": "Albumet"
 | 
					    "Albums": "Albume"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -74,7 +74,6 @@
 | 
				
			|||||||
    "HeaderFavoriteArtists": "Омиљени извођачи",
 | 
					    "HeaderFavoriteArtists": "Омиљени извођачи",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Омиљени албуми",
 | 
					    "HeaderFavoriteAlbums": "Омиљени албуми",
 | 
				
			||||||
    "HeaderContinueWatching": "Настави гледање",
 | 
					    "HeaderContinueWatching": "Настави гледање",
 | 
				
			||||||
    "HeaderCameraUploads": "Слања са камере",
 | 
					 | 
				
			||||||
    "HeaderAlbumArtists": "Извођачи албума",
 | 
					    "HeaderAlbumArtists": "Извођачи албума",
 | 
				
			||||||
    "Genres": "Жанрови",
 | 
					    "Genres": "Жанрови",
 | 
				
			||||||
    "Folders": "Фасцикле",
 | 
					    "Folders": "Фасцикле",
 | 
				
			||||||
 | 
				
			|||||||
@ -9,14 +9,13 @@
 | 
				
			|||||||
    "Channels": "Kanaler",
 | 
					    "Channels": "Kanaler",
 | 
				
			||||||
    "ChapterNameValue": "Kapitel {0}",
 | 
					    "ChapterNameValue": "Kapitel {0}",
 | 
				
			||||||
    "Collections": "Samlingar",
 | 
					    "Collections": "Samlingar",
 | 
				
			||||||
    "DeviceOfflineWithName": "{0} har kopplat från",
 | 
					    "DeviceOfflineWithName": "{0} har kopplat ner",
 | 
				
			||||||
    "DeviceOnlineWithName": "{0} är ansluten",
 | 
					    "DeviceOnlineWithName": "{0} är ansluten",
 | 
				
			||||||
    "FailedLoginAttemptWithUserName": "Misslyckat inloggningsförsök från {0}",
 | 
					    "FailedLoginAttemptWithUserName": "Misslyckat inloggningsförsök från {0}",
 | 
				
			||||||
    "Favorites": "Favoriter",
 | 
					    "Favorites": "Favoriter",
 | 
				
			||||||
    "Folders": "Mappar",
 | 
					    "Folders": "Mappar",
 | 
				
			||||||
    "Genres": "Genrer",
 | 
					    "Genres": "Genrer",
 | 
				
			||||||
    "HeaderAlbumArtists": "Albumartister",
 | 
					    "HeaderAlbumArtists": "Albumartister",
 | 
				
			||||||
    "HeaderCameraUploads": "Kamerauppladdningar",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "Fortsätt kolla",
 | 
					    "HeaderContinueWatching": "Fortsätt kolla",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Favoritalbum",
 | 
					    "HeaderFavoriteAlbums": "Favoritalbum",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Favoritartister",
 | 
					    "HeaderFavoriteArtists": "Favoritartister",
 | 
				
			||||||
 | 
				
			|||||||
@ -20,7 +20,6 @@
 | 
				
			|||||||
    "MessageApplicationUpdated": "ஜெல்லிஃபின் சேவையகம் புதுப்பிக்கப்பட்டது",
 | 
					    "MessageApplicationUpdated": "ஜெல்லிஃபின் சேவையகம் புதுப்பிக்கப்பட்டது",
 | 
				
			||||||
    "Inherit": "மரபுரிமையாகப் பெறு",
 | 
					    "Inherit": "மரபுரிமையாகப் பெறு",
 | 
				
			||||||
    "HeaderRecordingGroups": "பதிவு குழுக்கள்",
 | 
					    "HeaderRecordingGroups": "பதிவு குழுக்கள்",
 | 
				
			||||||
    "HeaderCameraUploads": "புகைப்பட பதிவேற்றங்கள்",
 | 
					 | 
				
			||||||
    "Folders": "கோப்புறைகள்",
 | 
					    "Folders": "கோப்புறைகள்",
 | 
				
			||||||
    "FailedLoginAttemptWithUserName": "{0} இலிருந்து உள்நுழைவு முயற்சி தோல்வியடைந்தது",
 | 
					    "FailedLoginAttemptWithUserName": "{0} இலிருந்து உள்நுழைவு முயற்சி தோல்வியடைந்தது",
 | 
				
			||||||
    "DeviceOnlineWithName": "{0} இணைக்கப்பட்டது",
 | 
					    "DeviceOnlineWithName": "{0} இணைக்கப்பட்டது",
 | 
				
			||||||
 | 
				
			|||||||
@ -50,7 +50,6 @@
 | 
				
			|||||||
    "HeaderFavoriteArtists": "ศิลปินที่ชื่นชอบ",
 | 
					    "HeaderFavoriteArtists": "ศิลปินที่ชื่นชอบ",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "อัมบั้มที่ชื่นชอบ",
 | 
					    "HeaderFavoriteAlbums": "อัมบั้มที่ชื่นชอบ",
 | 
				
			||||||
    "HeaderContinueWatching": "ดูต่อ",
 | 
					    "HeaderContinueWatching": "ดูต่อ",
 | 
				
			||||||
    "HeaderCameraUploads": "อัปโหลดรูปถ่าย",
 | 
					 | 
				
			||||||
    "HeaderAlbumArtists": "อัลบั้มศิลปิน",
 | 
					    "HeaderAlbumArtists": "อัลบั้มศิลปิน",
 | 
				
			||||||
    "Genres": "ประเภท",
 | 
					    "Genres": "ประเภท",
 | 
				
			||||||
    "Folders": "โฟลเดอร์",
 | 
					    "Folders": "โฟลเดอร์",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "Klasörler",
 | 
					    "Folders": "Klasörler",
 | 
				
			||||||
    "Genres": "Türler",
 | 
					    "Genres": "Türler",
 | 
				
			||||||
    "HeaderAlbumArtists": "Albüm Sanatçıları",
 | 
					    "HeaderAlbumArtists": "Albüm Sanatçıları",
 | 
				
			||||||
    "HeaderCameraUploads": "Kamera Yüklemeleri",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "İzlemeye Devam Et",
 | 
					    "HeaderContinueWatching": "İzlemeye Devam Et",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Favori Albümler",
 | 
					    "HeaderFavoriteAlbums": "Favori Albümler",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Favori Sanatçılar",
 | 
					    "HeaderFavoriteArtists": "Favori Sanatçılar",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "HeaderFavoriteArtists": "Улюблені виконавці",
 | 
					    "HeaderFavoriteArtists": "Улюблені виконавці",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Улюблені альбоми",
 | 
					    "HeaderFavoriteAlbums": "Улюблені альбоми",
 | 
				
			||||||
    "HeaderContinueWatching": "Продовжити перегляд",
 | 
					    "HeaderContinueWatching": "Продовжити перегляд",
 | 
				
			||||||
    "HeaderCameraUploads": "Завантажено з камери",
 | 
					 | 
				
			||||||
    "HeaderAlbumArtists": "Виконавці альбому",
 | 
					    "HeaderAlbumArtists": "Виконавці альбому",
 | 
				
			||||||
    "Genres": "Жанри",
 | 
					    "Genres": "Жанри",
 | 
				
			||||||
    "Folders": "Каталоги",
 | 
					    "Folders": "Каталоги",
 | 
				
			||||||
 | 
				
			|||||||
@ -105,7 +105,6 @@
 | 
				
			|||||||
    "Inherit": "وراثت میں",
 | 
					    "Inherit": "وراثت میں",
 | 
				
			||||||
    "HomeVideos": "ہوم ویڈیو",
 | 
					    "HomeVideos": "ہوم ویڈیو",
 | 
				
			||||||
    "HeaderRecordingGroups": "ریکارڈنگ گروپس",
 | 
					    "HeaderRecordingGroups": "ریکارڈنگ گروپس",
 | 
				
			||||||
    "HeaderCameraUploads": "کیمرہ اپلوڈز",
 | 
					 | 
				
			||||||
    "FailedLoginAttemptWithUserName": "لاگن کئ کوشش ناکام {0}",
 | 
					    "FailedLoginAttemptWithUserName": "لاگن کئ کوشش ناکام {0}",
 | 
				
			||||||
    "DeviceOnlineWithName": "{0} متصل ھو چکا ھے",
 | 
					    "DeviceOnlineWithName": "{0} متصل ھو چکا ھے",
 | 
				
			||||||
    "DeviceOfflineWithName": "{0} منقطع ھو چکا ھے",
 | 
					    "DeviceOfflineWithName": "{0} منقطع ھو چکا ھے",
 | 
				
			||||||
 | 
				
			|||||||
@ -103,7 +103,6 @@
 | 
				
			|||||||
    "HeaderFavoriteEpisodes": "Tập Phim Yêu Thích",
 | 
					    "HeaderFavoriteEpisodes": "Tập Phim Yêu Thích",
 | 
				
			||||||
    "HeaderFavoriteArtists": "Nghệ Sĩ Yêu Thích",
 | 
					    "HeaderFavoriteArtists": "Nghệ Sĩ Yêu Thích",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "Album Ưa Thích",
 | 
					    "HeaderFavoriteAlbums": "Album Ưa Thích",
 | 
				
			||||||
    "HeaderCameraUploads": "Máy Ảnh Tải Lên",
 | 
					 | 
				
			||||||
    "FailedLoginAttemptWithUserName": "Nỗ lực đăng nhập thất bại từ {0}",
 | 
					    "FailedLoginAttemptWithUserName": "Nỗ lực đăng nhập thất bại từ {0}",
 | 
				
			||||||
    "DeviceOnlineWithName": "{0} đã kết nối",
 | 
					    "DeviceOnlineWithName": "{0} đã kết nối",
 | 
				
			||||||
    "DeviceOfflineWithName": "{0} đã ngắt kết nối",
 | 
					    "DeviceOfflineWithName": "{0} đã ngắt kết nối",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "文件夹",
 | 
					    "Folders": "文件夹",
 | 
				
			||||||
    "Genres": "风格",
 | 
					    "Genres": "风格",
 | 
				
			||||||
    "HeaderAlbumArtists": "专辑作家",
 | 
					    "HeaderAlbumArtists": "专辑作家",
 | 
				
			||||||
    "HeaderCameraUploads": "相机上传",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "继续观影",
 | 
					    "HeaderContinueWatching": "继续观影",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "收藏的专辑",
 | 
					    "HeaderFavoriteAlbums": "收藏的专辑",
 | 
				
			||||||
    "HeaderFavoriteArtists": "最爱的艺术家",
 | 
					    "HeaderFavoriteArtists": "最爱的艺术家",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "檔案夾",
 | 
					    "Folders": "檔案夾",
 | 
				
			||||||
    "Genres": "風格",
 | 
					    "Genres": "風格",
 | 
				
			||||||
    "HeaderAlbumArtists": "專輯藝人",
 | 
					    "HeaderAlbumArtists": "專輯藝人",
 | 
				
			||||||
    "HeaderCameraUploads": "相機上載",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "繼續觀看",
 | 
					    "HeaderContinueWatching": "繼續觀看",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "最愛專輯",
 | 
					    "HeaderFavoriteAlbums": "最愛專輯",
 | 
				
			||||||
    "HeaderFavoriteArtists": "最愛的藝人",
 | 
					    "HeaderFavoriteArtists": "最愛的藝人",
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
    "Folders": "資料夾",
 | 
					    "Folders": "資料夾",
 | 
				
			||||||
    "Genres": "風格",
 | 
					    "Genres": "風格",
 | 
				
			||||||
    "HeaderAlbumArtists": "專輯演出者",
 | 
					    "HeaderAlbumArtists": "專輯演出者",
 | 
				
			||||||
    "HeaderCameraUploads": "相機上傳",
 | 
					 | 
				
			||||||
    "HeaderContinueWatching": "繼續觀賞",
 | 
					    "HeaderContinueWatching": "繼續觀賞",
 | 
				
			||||||
    "HeaderFavoriteAlbums": "最愛專輯",
 | 
					    "HeaderFavoriteAlbums": "最愛專輯",
 | 
				
			||||||
    "HeaderFavoriteArtists": "最愛演出者",
 | 
					    "HeaderFavoriteArtists": "最愛演出者",
 | 
				
			||||||
 | 
				
			|||||||
@ -71,7 +71,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
 | 
				
			|||||||
            return new[]
 | 
					            return new[]
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // Every so often
 | 
					                // Every so often
 | 
				
			||||||
                new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks}
 | 
					                new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks }
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -65,7 +65,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            return new[]
 | 
					            return new[]
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks}
 | 
					                new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks }
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -54,7 +54,8 @@ namespace Emby.Server.Implementations.Security
 | 
				
			|||||||
            {
 | 
					            {
 | 
				
			||||||
                if (tableNewlyCreated && TableExists(connection, "AccessTokens"))
 | 
					                if (tableNewlyCreated && TableExists(connection, "AccessTokens"))
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    connection.RunInTransaction(db =>
 | 
					                    connection.RunInTransaction(
 | 
				
			||||||
 | 
					                    db =>
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        var existingColumnNames = GetColumnNames(db, "AccessTokens");
 | 
					                        var existingColumnNames = GetColumnNames(db, "AccessTokens");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -88,7 +89,8 @@ namespace Emby.Server.Implementations.Security
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            using (var connection = GetConnection())
 | 
					            using (var connection = GetConnection())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                connection.RunInTransaction(db =>
 | 
					                connection.RunInTransaction(
 | 
				
			||||||
 | 
					                db =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    using (var statement = db.PrepareStatement("insert into Tokens (AccessToken, DeviceId, AppName, AppVersion, DeviceName, UserId, UserName, IsActive, DateCreated, DateLastActivity) values (@AccessToken, @DeviceId, @AppName, @AppVersion, @DeviceName, @UserId, @UserName, @IsActive, @DateCreated, @DateLastActivity)"))
 | 
					                    using (var statement = db.PrepareStatement("insert into Tokens (AccessToken, DeviceId, AppName, AppVersion, DeviceName, UserId, UserName, IsActive, DateCreated, DateLastActivity) values (@AccessToken, @DeviceId, @AppName, @AppVersion, @DeviceName, @UserId, @UserName, @IsActive, @DateCreated, @DateLastActivity)"))
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
@ -119,7 +121,8 @@ namespace Emby.Server.Implementations.Security
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            using (var connection = GetConnection())
 | 
					            using (var connection = GetConnection())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                connection.RunInTransaction(db =>
 | 
					                connection.RunInTransaction(
 | 
				
			||||||
 | 
					                db =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    using (var statement = db.PrepareStatement("Update Tokens set AccessToken=@AccessToken, DeviceId=@DeviceId, AppName=@AppName, AppVersion=@AppVersion, DeviceName=@DeviceName, UserId=@UserId, UserName=@UserName, DateCreated=@DateCreated, DateLastActivity=@DateLastActivity where Id=@Id"))
 | 
					                    using (var statement = db.PrepareStatement("Update Tokens set AccessToken=@AccessToken, DeviceId=@DeviceId, AppName=@AppName, AppVersion=@AppVersion, DeviceName=@DeviceName, UserId=@UserId, UserName=@UserName, DateCreated=@DateCreated, DateLastActivity=@DateLastActivity where Id=@Id"))
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
@ -151,7 +154,8 @@ namespace Emby.Server.Implementations.Security
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            using (var connection = GetConnection())
 | 
					            using (var connection = GetConnection())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                connection.RunInTransaction(db =>
 | 
					                connection.RunInTransaction(
 | 
				
			||||||
 | 
					                db =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    using (var statement = db.PrepareStatement("Delete from Tokens where Id=@Id"))
 | 
					                    using (var statement = db.PrepareStatement("Delete from Tokens where Id=@Id"))
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
@ -346,7 +350,8 @@ namespace Emby.Server.Implementations.Security
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            using (var connection = GetConnection(true))
 | 
					            using (var connection = GetConnection(true))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return connection.RunInTransaction(db =>
 | 
					                return connection.RunInTransaction(
 | 
				
			||||||
 | 
					                db =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    using (var statement = base.PrepareStatement(db, "select CustomName from Devices where Id=@DeviceId"))
 | 
					                    using (var statement = base.PrepareStatement(db, "select CustomName from Devices where Id=@DeviceId"))
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
@ -377,7 +382,8 @@ namespace Emby.Server.Implementations.Security
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            using (var connection = GetConnection())
 | 
					            using (var connection = GetConnection())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                connection.RunInTransaction(db =>
 | 
					                connection.RunInTransaction(
 | 
				
			||||||
 | 
					                db =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    using (var statement = db.PrepareStatement("replace into devices (Id, CustomName, Capabilities) VALUES (@Id, @CustomName, (Select Capabilities from Devices where Id=@Id))"))
 | 
					                    using (var statement = db.PrepareStatement("replace into devices (Id, CustomName, Capabilities) VALUES (@Id, @CustomName, (Select Capabilities from Devices where Id=@Id))"))
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
 | 
				
			|||||||
@ -666,7 +666,7 @@ namespace Emby.Server.Implementations.Session
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var eventArgs = new PlaybackProgressEventArgs
 | 
					            var eventArgs = new PlaybackStartEventArgs
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                Item = libraryItem,
 | 
					                Item = libraryItem,
 | 
				
			||||||
                Users = users,
 | 
					                Users = users,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Linq;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
using Jellyfin.Api.Constants;
 | 
					using Jellyfin.Api.Constants;
 | 
				
			||||||
using Jellyfin.Data.Entities;
 | 
					using Jellyfin.Data.Queries;
 | 
				
			||||||
using MediaBrowser.Model.Activity;
 | 
					using MediaBrowser.Model.Activity;
 | 
				
			||||||
using MediaBrowser.Model.Querying;
 | 
					using MediaBrowser.Model.Querying;
 | 
				
			||||||
using Microsoft.AspNetCore.Authorization;
 | 
					using Microsoft.AspNetCore.Authorization;
 | 
				
			||||||
@ -39,19 +39,19 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
        /// <returns>A <see cref="QueryResult{ActivityLogEntry}"/> containing the log entries.</returns>
 | 
					        /// <returns>A <see cref="QueryResult{ActivityLogEntry}"/> containing the log entries.</returns>
 | 
				
			||||||
        [HttpGet("Entries")]
 | 
					        [HttpGet("Entries")]
 | 
				
			||||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
					        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
				
			||||||
        public ActionResult<QueryResult<ActivityLogEntry>> GetLogEntries(
 | 
					        public async Task<ActionResult<QueryResult<ActivityLogEntry>>> GetLogEntries(
 | 
				
			||||||
            [FromQuery] int? startIndex,
 | 
					            [FromQuery] int? startIndex,
 | 
				
			||||||
            [FromQuery] int? limit,
 | 
					            [FromQuery] int? limit,
 | 
				
			||||||
            [FromQuery] DateTime? minDate,
 | 
					            [FromQuery] DateTime? minDate,
 | 
				
			||||||
            [FromQuery] bool? hasUserId)
 | 
					            [FromQuery] bool? hasUserId)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var filterFunc = new Func<IQueryable<ActivityLog>, IQueryable<ActivityLog>>(
 | 
					            return await _activityManager.GetPagedResultAsync(new ActivityLogQuery
 | 
				
			||||||
                entries => entries.Where(entry => entry.DateCreated >= minDate
 | 
					            {
 | 
				
			||||||
                                                  && (!hasUserId.HasValue || (hasUserId.Value
 | 
					                StartIndex = startIndex,
 | 
				
			||||||
                                                      ? entry.UserId != Guid.Empty
 | 
					                Limit = limit,
 | 
				
			||||||
                                                      : entry.UserId == Guid.Empty))));
 | 
					                MinDate = minDate,
 | 
				
			||||||
 | 
					                HasUserId = hasUserId
 | 
				
			||||||
            return _activityManager.GetPagedResult(filterFunc, startIndex, limit);
 | 
					            }).ConfigureAwait(false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -54,7 +54,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
        /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
 | 
					        /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
 | 
				
			||||||
        /// <param name="excludeItemTypes">Optional. If specified, results will be filtered out based on item type. This allows multiple, comma delimited.</param>
 | 
					        /// <param name="excludeItemTypes">Optional. If specified, results will be filtered out based on item type. This allows multiple, comma delimited.</param>
 | 
				
			||||||
        /// <param name="includeItemTypes">Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited.</param>
 | 
					        /// <param name="includeItemTypes">Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited.</param>
 | 
				
			||||||
        /// <param name="filters">Optional. Specify additional filters to apply. This allows multiple, comma delimited. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes.</param>
 | 
					        /// <param name="filters">Optional. Specify additional filters to apply.</param>
 | 
				
			||||||
        /// <param name="isFavorite">Optional filter by items that are marked as favorite, or not.</param>
 | 
					        /// <param name="isFavorite">Optional filter by items that are marked as favorite, or not.</param>
 | 
				
			||||||
        /// <param name="mediaTypes">Optional filter by MediaType. Allows multiple, comma delimited.</param>
 | 
					        /// <param name="mediaTypes">Optional filter by MediaType. Allows multiple, comma delimited.</param>
 | 
				
			||||||
        /// <param name="genres">Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimited.</param>
 | 
					        /// <param name="genres">Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimited.</param>
 | 
				
			||||||
@ -89,7 +89,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] ItemFields[] fields,
 | 
					            [FromQuery] ItemFields[] fields,
 | 
				
			||||||
            [FromQuery] string? excludeItemTypes,
 | 
					            [FromQuery] string? excludeItemTypes,
 | 
				
			||||||
            [FromQuery] string? includeItemTypes,
 | 
					            [FromQuery] string? includeItemTypes,
 | 
				
			||||||
            [FromQuery] string? filters,
 | 
					            [FromQuery] ItemFilter[] filters,
 | 
				
			||||||
            [FromQuery] bool? isFavorite,
 | 
					            [FromQuery] bool? isFavorite,
 | 
				
			||||||
            [FromQuery] string? mediaTypes,
 | 
					            [FromQuery] string? mediaTypes,
 | 
				
			||||||
            [FromQuery] string? genres,
 | 
					            [FromQuery] string? genres,
 | 
				
			||||||
@ -188,7 +188,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
                }).Where(i => i != null).Select(i => i!.Id).ToArray();
 | 
					                }).Where(i => i != null).Select(i => i!.Id).ToArray();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            foreach (var filter in RequestHelpers.GetFilters(filters))
 | 
					            foreach (var filter in filters)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                switch (filter)
 | 
					                switch (filter)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
@ -263,7 +263,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
        /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
 | 
					        /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
 | 
				
			||||||
        /// <param name="excludeItemTypes">Optional. If specified, results will be filtered out based on item type. This allows multiple, comma delimited.</param>
 | 
					        /// <param name="excludeItemTypes">Optional. If specified, results will be filtered out based on item type. This allows multiple, comma delimited.</param>
 | 
				
			||||||
        /// <param name="includeItemTypes">Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited.</param>
 | 
					        /// <param name="includeItemTypes">Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited.</param>
 | 
				
			||||||
        /// <param name="filters">Optional. Specify additional filters to apply. This allows multiple, comma delimited. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes.</param>
 | 
					        /// <param name="filters">Optional. Specify additional filters to apply.</param>
 | 
				
			||||||
        /// <param name="isFavorite">Optional filter by items that are marked as favorite, or not.</param>
 | 
					        /// <param name="isFavorite">Optional filter by items that are marked as favorite, or not.</param>
 | 
				
			||||||
        /// <param name="mediaTypes">Optional filter by MediaType. Allows multiple, comma delimited.</param>
 | 
					        /// <param name="mediaTypes">Optional filter by MediaType. Allows multiple, comma delimited.</param>
 | 
				
			||||||
        /// <param name="genres">Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimited.</param>
 | 
					        /// <param name="genres">Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimited.</param>
 | 
				
			||||||
@ -298,7 +298,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] ItemFields[] fields,
 | 
					            [FromQuery] ItemFields[] fields,
 | 
				
			||||||
            [FromQuery] string? excludeItemTypes,
 | 
					            [FromQuery] string? excludeItemTypes,
 | 
				
			||||||
            [FromQuery] string? includeItemTypes,
 | 
					            [FromQuery] string? includeItemTypes,
 | 
				
			||||||
            [FromQuery] string? filters,
 | 
					            [FromQuery] ItemFilter[] filters,
 | 
				
			||||||
            [FromQuery] bool? isFavorite,
 | 
					            [FromQuery] bool? isFavorite,
 | 
				
			||||||
            [FromQuery] string? mediaTypes,
 | 
					            [FromQuery] string? mediaTypes,
 | 
				
			||||||
            [FromQuery] string? genres,
 | 
					            [FromQuery] string? genres,
 | 
				
			||||||
@ -397,7 +397,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
                }).Where(i => i != null).Select(i => i!.Id).ToArray();
 | 
					                }).Where(i => i != null).Select(i => i!.Id).ToArray();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            foreach (var filter in RequestHelpers.GetFilters(filters))
 | 
					            foreach (var filter in filters)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                switch (filter)
 | 
					                switch (filter)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
 | 
				
			|||||||
@ -105,7 +105,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
        /// <param name="startIndex">Optional. The record index to start at. All items with a lower index will be dropped from the results.</param>
 | 
					        /// <param name="startIndex">Optional. The record index to start at. All items with a lower index will be dropped from the results.</param>
 | 
				
			||||||
        /// <param name="limit">Optional. The maximum number of records to return.</param>
 | 
					        /// <param name="limit">Optional. The maximum number of records to return.</param>
 | 
				
			||||||
        /// <param name="sortOrder">Optional. Sort Order - Ascending,Descending.</param>
 | 
					        /// <param name="sortOrder">Optional. Sort Order - Ascending,Descending.</param>
 | 
				
			||||||
        /// <param name="filters">Optional. Specify additional filters to apply. This allows multiple, comma delimited. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes.</param>
 | 
					        /// <param name="filters">Optional. Specify additional filters to apply.</param>
 | 
				
			||||||
        /// <param name="sortBy">Optional. Specify one or more sort orders, comma delimited. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime.</param>
 | 
					        /// <param name="sortBy">Optional. Specify one or more sort orders, comma delimited. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime.</param>
 | 
				
			||||||
        /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
 | 
					        /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
 | 
				
			||||||
        /// <response code="200">Channel items returned.</response>
 | 
					        /// <response code="200">Channel items returned.</response>
 | 
				
			||||||
@ -121,7 +121,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] int? startIndex,
 | 
					            [FromQuery] int? startIndex,
 | 
				
			||||||
            [FromQuery] int? limit,
 | 
					            [FromQuery] int? limit,
 | 
				
			||||||
            [FromQuery] string? sortOrder,
 | 
					            [FromQuery] string? sortOrder,
 | 
				
			||||||
            [FromQuery] string? filters,
 | 
					            [FromQuery] ItemFilter[] filters,
 | 
				
			||||||
            [FromQuery] string? sortBy,
 | 
					            [FromQuery] string? sortBy,
 | 
				
			||||||
            [FromQuery] ItemFields[] fields)
 | 
					            [FromQuery] ItemFields[] fields)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@ -140,7 +140,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
                    .AddItemFields(fields)
 | 
					                    .AddItemFields(fields)
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            foreach (var filter in RequestHelpers.GetFilters(filters))
 | 
					            foreach (var filter in filters)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                switch (filter)
 | 
					                switch (filter)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
@ -196,7 +196,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] Guid? userId,
 | 
					            [FromQuery] Guid? userId,
 | 
				
			||||||
            [FromQuery] int? startIndex,
 | 
					            [FromQuery] int? startIndex,
 | 
				
			||||||
            [FromQuery] int? limit,
 | 
					            [FromQuery] int? limit,
 | 
				
			||||||
            [FromQuery] string? filters,
 | 
					            [FromQuery] ItemFilter[] filters,
 | 
				
			||||||
            [FromQuery] ItemFields[] fields,
 | 
					            [FromQuery] ItemFields[] fields,
 | 
				
			||||||
            [FromQuery] string? channelIds)
 | 
					            [FromQuery] string? channelIds)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@ -217,7 +217,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
                    .AddItemFields(fields)
 | 
					                    .AddItemFields(fields)
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            foreach (var filter in RequestHelpers.GetFilters(filters))
 | 
					            foreach (var filter in filters)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                switch (filter)
 | 
					                switch (filter)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
 | 
				
			|||||||
@ -55,7 +55,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
        /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
 | 
					        /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
 | 
				
			||||||
        /// <param name="excludeItemTypes">Optional. If specified, results will be filtered out based on item type. This allows multiple, comma delimited.</param>
 | 
					        /// <param name="excludeItemTypes">Optional. If specified, results will be filtered out based on item type. This allows multiple, comma delimited.</param>
 | 
				
			||||||
        /// <param name="includeItemTypes">Optional. If specified, results will be filtered in based on item type. This allows multiple, comma delimited.</param>
 | 
					        /// <param name="includeItemTypes">Optional. If specified, results will be filtered in based on item type. This allows multiple, comma delimited.</param>
 | 
				
			||||||
        /// <param name="filters">Optional. Specify additional filters to apply. This allows multiple, comma delimited. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes.</param>
 | 
					        /// <param name="filters">Optional. Specify additional filters to apply.</param>
 | 
				
			||||||
        /// <param name="isFavorite">Optional filter by items that are marked as favorite, or not.</param>
 | 
					        /// <param name="isFavorite">Optional filter by items that are marked as favorite, or not.</param>
 | 
				
			||||||
        /// <param name="mediaTypes">Optional filter by MediaType. Allows multiple, comma delimited.</param>
 | 
					        /// <param name="mediaTypes">Optional filter by MediaType. Allows multiple, comma delimited.</param>
 | 
				
			||||||
        /// <param name="genres">Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimited.</param>
 | 
					        /// <param name="genres">Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimited.</param>
 | 
				
			||||||
@ -90,7 +90,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] ItemFields[] fields,
 | 
					            [FromQuery] ItemFields[] fields,
 | 
				
			||||||
            [FromQuery] string? excludeItemTypes,
 | 
					            [FromQuery] string? excludeItemTypes,
 | 
				
			||||||
            [FromQuery] string? includeItemTypes,
 | 
					            [FromQuery] string? includeItemTypes,
 | 
				
			||||||
            [FromQuery] string? filters,
 | 
					            [FromQuery] ItemFilter[] filters,
 | 
				
			||||||
            [FromQuery] bool? isFavorite,
 | 
					            [FromQuery] bool? isFavorite,
 | 
				
			||||||
            [FromQuery] string? mediaTypes,
 | 
					            [FromQuery] string? mediaTypes,
 | 
				
			||||||
            [FromQuery] string? genres,
 | 
					            [FromQuery] string? genres,
 | 
				
			||||||
@ -188,7 +188,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
                    .ToArray();
 | 
					                    .ToArray();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            foreach (var filter in RequestHelpers.GetFilters(filters))
 | 
					            foreach (var filter in filters)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                switch (filter)
 | 
					                switch (filter)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
 | 
				
			|||||||
@ -333,7 +333,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
        /// <param name="quality">Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases.</param>
 | 
					        /// <param name="quality">Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases.</param>
 | 
				
			||||||
        /// <param name="tag">Optional. Supply the cache tag from the item object to receive strong caching headers.</param>
 | 
					        /// <param name="tag">Optional. Supply the cache tag from the item object to receive strong caching headers.</param>
 | 
				
			||||||
        /// <param name="cropWhitespace">Optional. Specify if whitespace should be cropped out of the image. True/False. If unspecified, whitespace will be cropped from logos and clear art.</param>
 | 
					        /// <param name="cropWhitespace">Optional. Specify if whitespace should be cropped out of the image. True/False. If unspecified, whitespace will be cropped from logos and clear art.</param>
 | 
				
			||||||
        /// <param name="format">Determines the output format of the image - original,gif,jpg,png.</param>
 | 
					        /// <param name="format">Optional. The <see cref="ImageFormat"/> of the returned image.</param>
 | 
				
			||||||
        /// <param name="addPlayedIndicator">Optional. Add a played indicator.</param>
 | 
					        /// <param name="addPlayedIndicator">Optional. Add a played indicator.</param>
 | 
				
			||||||
        /// <param name="percentPlayed">Optional. Percent to render for the percent played overlay.</param>
 | 
					        /// <param name="percentPlayed">Optional. Percent to render for the percent played overlay.</param>
 | 
				
			||||||
        /// <param name="unplayedCount">Optional. Unplayed count overlay to render.</param>
 | 
					        /// <param name="unplayedCount">Optional. Unplayed count overlay to render.</param>
 | 
				
			||||||
@ -364,7 +364,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] int? quality,
 | 
					            [FromQuery] int? quality,
 | 
				
			||||||
            [FromQuery] string? tag,
 | 
					            [FromQuery] string? tag,
 | 
				
			||||||
            [FromQuery] bool? cropWhitespace,
 | 
					            [FromQuery] bool? cropWhitespace,
 | 
				
			||||||
            [FromQuery] string? format,
 | 
					            [FromQuery] ImageFormat? format,
 | 
				
			||||||
            [FromQuery] bool? addPlayedIndicator,
 | 
					            [FromQuery] bool? addPlayedIndicator,
 | 
				
			||||||
            [FromQuery] double? percentPlayed,
 | 
					            [FromQuery] double? percentPlayed,
 | 
				
			||||||
            [FromQuery] int? unplayedCount,
 | 
					            [FromQuery] int? unplayedCount,
 | 
				
			||||||
@ -443,7 +443,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] int? quality,
 | 
					            [FromQuery] int? quality,
 | 
				
			||||||
            [FromRoute, Required] string tag,
 | 
					            [FromRoute, Required] string tag,
 | 
				
			||||||
            [FromQuery] bool? cropWhitespace,
 | 
					            [FromQuery] bool? cropWhitespace,
 | 
				
			||||||
            [FromRoute, Required] string format,
 | 
					            [FromRoute, Required] ImageFormat format,
 | 
				
			||||||
            [FromQuery] bool? addPlayedIndicator,
 | 
					            [FromQuery] bool? addPlayedIndicator,
 | 
				
			||||||
            [FromRoute, Required] double percentPlayed,
 | 
					            [FromRoute, Required] double percentPlayed,
 | 
				
			||||||
            [FromRoute, Required] int unplayedCount,
 | 
					            [FromRoute, Required] int unplayedCount,
 | 
				
			||||||
@ -516,7 +516,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromRoute, Required] string name,
 | 
					            [FromRoute, Required] string name,
 | 
				
			||||||
            [FromRoute, Required] ImageType imageType,
 | 
					            [FromRoute, Required] ImageType imageType,
 | 
				
			||||||
            [FromQuery] string tag,
 | 
					            [FromQuery] string tag,
 | 
				
			||||||
            [FromQuery] string format,
 | 
					            [FromQuery] ImageFormat? format,
 | 
				
			||||||
            [FromQuery] int? maxWidth,
 | 
					            [FromQuery] int? maxWidth,
 | 
				
			||||||
            [FromQuery] int? maxHeight,
 | 
					            [FromQuery] int? maxHeight,
 | 
				
			||||||
            [FromQuery] double? percentPlayed,
 | 
					            [FromQuery] double? percentPlayed,
 | 
				
			||||||
@ -595,7 +595,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromRoute, Required] string name,
 | 
					            [FromRoute, Required] string name,
 | 
				
			||||||
            [FromRoute, Required] ImageType imageType,
 | 
					            [FromRoute, Required] ImageType imageType,
 | 
				
			||||||
            [FromQuery] string tag,
 | 
					            [FromQuery] string tag,
 | 
				
			||||||
            [FromQuery] string format,
 | 
					            [FromQuery] ImageFormat? format,
 | 
				
			||||||
            [FromQuery] int? maxWidth,
 | 
					            [FromQuery] int? maxWidth,
 | 
				
			||||||
            [FromQuery] int? maxHeight,
 | 
					            [FromQuery] int? maxHeight,
 | 
				
			||||||
            [FromQuery] double? percentPlayed,
 | 
					            [FromQuery] double? percentPlayed,
 | 
				
			||||||
@ -674,7 +674,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromRoute, Required] string name,
 | 
					            [FromRoute, Required] string name,
 | 
				
			||||||
            [FromRoute, Required] ImageType imageType,
 | 
					            [FromRoute, Required] ImageType imageType,
 | 
				
			||||||
            [FromQuery] string tag,
 | 
					            [FromQuery] string tag,
 | 
				
			||||||
            [FromQuery] string format,
 | 
					            [FromQuery] ImageFormat? format,
 | 
				
			||||||
            [FromQuery] int? maxWidth,
 | 
					            [FromQuery] int? maxWidth,
 | 
				
			||||||
            [FromQuery] int? maxHeight,
 | 
					            [FromQuery] int? maxHeight,
 | 
				
			||||||
            [FromQuery] double? percentPlayed,
 | 
					            [FromQuery] double? percentPlayed,
 | 
				
			||||||
@ -753,7 +753,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromRoute, Required] string name,
 | 
					            [FromRoute, Required] string name,
 | 
				
			||||||
            [FromRoute, Required] ImageType imageType,
 | 
					            [FromRoute, Required] ImageType imageType,
 | 
				
			||||||
            [FromQuery] string tag,
 | 
					            [FromQuery] string tag,
 | 
				
			||||||
            [FromQuery] string format,
 | 
					            [FromQuery] ImageFormat? format,
 | 
				
			||||||
            [FromQuery] int? maxWidth,
 | 
					            [FromQuery] int? maxWidth,
 | 
				
			||||||
            [FromQuery] int? maxHeight,
 | 
					            [FromQuery] int? maxHeight,
 | 
				
			||||||
            [FromQuery] double? percentPlayed,
 | 
					            [FromQuery] double? percentPlayed,
 | 
				
			||||||
@ -832,7 +832,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromRoute, Required] string name,
 | 
					            [FromRoute, Required] string name,
 | 
				
			||||||
            [FromRoute, Required] ImageType imageType,
 | 
					            [FromRoute, Required] ImageType imageType,
 | 
				
			||||||
            [FromRoute, Required] string tag,
 | 
					            [FromRoute, Required] string tag,
 | 
				
			||||||
            [FromRoute, Required] string format,
 | 
					            [FromRoute, Required] ImageFormat format,
 | 
				
			||||||
            [FromQuery] int? maxWidth,
 | 
					            [FromQuery] int? maxWidth,
 | 
				
			||||||
            [FromQuery] int? maxHeight,
 | 
					            [FromQuery] int? maxHeight,
 | 
				
			||||||
            [FromQuery] double? percentPlayed,
 | 
					            [FromQuery] double? percentPlayed,
 | 
				
			||||||
@ -911,7 +911,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromRoute, Required] Guid userId,
 | 
					            [FromRoute, Required] Guid userId,
 | 
				
			||||||
            [FromRoute, Required] ImageType imageType,
 | 
					            [FromRoute, Required] ImageType imageType,
 | 
				
			||||||
            [FromQuery] string? tag,
 | 
					            [FromQuery] string? tag,
 | 
				
			||||||
            [FromQuery] string? format,
 | 
					            [FromQuery] ImageFormat? format,
 | 
				
			||||||
            [FromQuery] int? maxWidth,
 | 
					            [FromQuery] int? maxWidth,
 | 
				
			||||||
            [FromQuery] int? maxHeight,
 | 
					            [FromQuery] int? maxHeight,
 | 
				
			||||||
            [FromQuery] double? percentPlayed,
 | 
					            [FromQuery] double? percentPlayed,
 | 
				
			||||||
@ -1038,7 +1038,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            ImageType imageType,
 | 
					            ImageType imageType,
 | 
				
			||||||
            int? imageIndex,
 | 
					            int? imageIndex,
 | 
				
			||||||
            string? tag,
 | 
					            string? tag,
 | 
				
			||||||
            string? format,
 | 
					            ImageFormat? format,
 | 
				
			||||||
            int? maxWidth,
 | 
					            int? maxWidth,
 | 
				
			||||||
            int? maxHeight,
 | 
					            int? maxHeight,
 | 
				
			||||||
            double? percentPlayed,
 | 
					            double? percentPlayed,
 | 
				
			||||||
@ -1128,12 +1128,11 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
                isHeadRequest).ConfigureAwait(false);
 | 
					                isHeadRequest).ConfigureAwait(false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private ImageFormat[] GetOutputFormats(string? format)
 | 
					        private ImageFormat[] GetOutputFormats(ImageFormat? format)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (!string.IsNullOrWhiteSpace(format)
 | 
					            if (format.HasValue)
 | 
				
			||||||
                && Enum.TryParse(format, true, out ImageFormat parsedFormat))
 | 
					 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return new[] { parsedFormat };
 | 
					                return new[] { format.Value };
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return GetClientSupportedFormats();
 | 
					            return GetClientSupportedFormats();
 | 
				
			||||||
@ -1157,7 +1156,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            var acceptParam = Request.Query[HeaderNames.Accept];
 | 
					            var acceptParam = Request.Query[HeaderNames.Accept];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var supportsWebP = SupportsFormat(supportedFormats, acceptParam, "webp", false);
 | 
					            var supportsWebP = SupportsFormat(supportedFormats, acceptParam, ImageFormat.Webp, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!supportsWebP)
 | 
					            if (!supportsWebP)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -1179,7 +1178,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            formats.Add(ImageFormat.Jpg);
 | 
					            formats.Add(ImageFormat.Jpg);
 | 
				
			||||||
            formats.Add(ImageFormat.Png);
 | 
					            formats.Add(ImageFormat.Png);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (SupportsFormat(supportedFormats, acceptParam, "gif", true))
 | 
					            if (SupportsFormat(supportedFormats, acceptParam, ImageFormat.Gif, true))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                formats.Add(ImageFormat.Gif);
 | 
					                formats.Add(ImageFormat.Gif);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -1187,9 +1186,10 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            return formats.ToArray();
 | 
					            return formats.ToArray();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private bool SupportsFormat(IReadOnlyCollection<string> requestAcceptTypes, string acceptParam, string format, bool acceptAll)
 | 
					        private bool SupportsFormat(IReadOnlyCollection<string> requestAcceptTypes, string acceptParam, ImageFormat format, bool acceptAll)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var mimeType = "image/" + format;
 | 
					            var normalized = format.ToString().ToLowerInvariant();
 | 
				
			||||||
 | 
					            var mimeType = "image/" + normalized;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (requestAcceptTypes.Contains(mimeType))
 | 
					            if (requestAcceptTypes.Contains(mimeType))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -1201,7 +1201,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
                return true;
 | 
					                return true;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return string.Equals(acceptParam, format, StringComparison.OrdinalIgnoreCase);
 | 
					            return string.Equals(acceptParam, normalized, StringComparison.OrdinalIgnoreCase);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private async Task<ActionResult> GetImageResult(
 | 
					        private async Task<ActionResult> GetImageResult(
 | 
				
			||||||
 | 
				
			|||||||
@ -159,7 +159,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] bool? isHd,
 | 
					            [FromQuery] bool? isHd,
 | 
				
			||||||
            [FromQuery] bool? is4K,
 | 
					            [FromQuery] bool? is4K,
 | 
				
			||||||
            [FromQuery] string? locationTypes,
 | 
					            [FromQuery] string? locationTypes,
 | 
				
			||||||
            [FromQuery] string? excludeLocationTypes,
 | 
					            [FromQuery] LocationType[] excludeLocationTypes,
 | 
				
			||||||
            [FromQuery] bool? isMissing,
 | 
					            [FromQuery] bool? isMissing,
 | 
				
			||||||
            [FromQuery] bool? isUnaired,
 | 
					            [FromQuery] bool? isUnaired,
 | 
				
			||||||
            [FromQuery] double? minCommunityRating,
 | 
					            [FromQuery] double? minCommunityRating,
 | 
				
			||||||
@ -182,7 +182,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] ItemFields[] fields,
 | 
					            [FromQuery] ItemFields[] fields,
 | 
				
			||||||
            [FromQuery] string? excludeItemTypes,
 | 
					            [FromQuery] string? excludeItemTypes,
 | 
				
			||||||
            [FromQuery] string? includeItemTypes,
 | 
					            [FromQuery] string? includeItemTypes,
 | 
				
			||||||
            [FromQuery] string? filters,
 | 
					            [FromQuery] ItemFilter[] filters,
 | 
				
			||||||
            [FromQuery] bool? isFavorite,
 | 
					            [FromQuery] bool? isFavorite,
 | 
				
			||||||
            [FromQuery] string? mediaTypes,
 | 
					            [FromQuery] string? mediaTypes,
 | 
				
			||||||
            [FromQuery] string? imageTypes,
 | 
					            [FromQuery] string? imageTypes,
 | 
				
			||||||
@ -365,7 +365,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
                    query.CollapseBoxSetItems = false;
 | 
					                    query.CollapseBoxSetItems = false;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                foreach (var filter in RequestHelpers.GetFilters(filters!))
 | 
					                foreach (var filter in filters)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    switch (filter)
 | 
					                    switch (filter)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
@ -406,13 +406,10 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // ExcludeLocationTypes
 | 
					                // ExcludeLocationTypes
 | 
				
			||||||
                if (!string.IsNullOrEmpty(excludeLocationTypes))
 | 
					                if (excludeLocationTypes.Any(t => t == LocationType.Virtual))
 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    if (excludeLocationTypes.Split(',').Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true)).ToArray().Contains(LocationType.Virtual))
 | 
					 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    query.IsVirtualItem = false;
 | 
					                    query.IsVirtualItem = false;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (!string.IsNullOrEmpty(locationTypes))
 | 
					                if (!string.IsNullOrEmpty(locationTypes))
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
 | 
				
			|||||||
@ -55,7 +55,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
        /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
 | 
					        /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
 | 
				
			||||||
        /// <param name="excludeItemTypes">Optional. If specified, results will be filtered out based on item type. This allows multiple, comma delimited.</param>
 | 
					        /// <param name="excludeItemTypes">Optional. If specified, results will be filtered out based on item type. This allows multiple, comma delimited.</param>
 | 
				
			||||||
        /// <param name="includeItemTypes">Optional. If specified, results will be filtered in based on item type. This allows multiple, comma delimited.</param>
 | 
					        /// <param name="includeItemTypes">Optional. If specified, results will be filtered in based on item type. This allows multiple, comma delimited.</param>
 | 
				
			||||||
        /// <param name="filters">Optional. Specify additional filters to apply. This allows multiple, comma delimited. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes.</param>
 | 
					        /// <param name="filters">Optional. Specify additional filters to apply.</param>
 | 
				
			||||||
        /// <param name="isFavorite">Optional filter by items that are marked as favorite, or not.</param>
 | 
					        /// <param name="isFavorite">Optional filter by items that are marked as favorite, or not.</param>
 | 
				
			||||||
        /// <param name="mediaTypes">Optional filter by MediaType. Allows multiple, comma delimited.</param>
 | 
					        /// <param name="mediaTypes">Optional filter by MediaType. Allows multiple, comma delimited.</param>
 | 
				
			||||||
        /// <param name="genres">Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimited.</param>
 | 
					        /// <param name="genres">Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimited.</param>
 | 
				
			||||||
@ -89,7 +89,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] ItemFields[] fields,
 | 
					            [FromQuery] ItemFields[] fields,
 | 
				
			||||||
            [FromQuery] string? excludeItemTypes,
 | 
					            [FromQuery] string? excludeItemTypes,
 | 
				
			||||||
            [FromQuery] string? includeItemTypes,
 | 
					            [FromQuery] string? includeItemTypes,
 | 
				
			||||||
            [FromQuery] string? filters,
 | 
					            [FromQuery] ItemFilter[] filters,
 | 
				
			||||||
            [FromQuery] bool? isFavorite,
 | 
					            [FromQuery] bool? isFavorite,
 | 
				
			||||||
            [FromQuery] string? mediaTypes,
 | 
					            [FromQuery] string? mediaTypes,
 | 
				
			||||||
            [FromQuery] string? genres,
 | 
					            [FromQuery] string? genres,
 | 
				
			||||||
@ -187,7 +187,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
                    .ToArray();
 | 
					                    .ToArray();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            foreach (var filter in RequestHelpers.GetFilters(filters))
 | 
					            foreach (var filter in filters)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                switch (filter)
 | 
					                switch (filter)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
 | 
				
			|||||||
@ -89,7 +89,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] ItemFields[] fields,
 | 
					            [FromQuery] ItemFields[] fields,
 | 
				
			||||||
            [FromQuery] string? excludeItemTypes,
 | 
					            [FromQuery] string? excludeItemTypes,
 | 
				
			||||||
            [FromQuery] string? includeItemTypes,
 | 
					            [FromQuery] string? includeItemTypes,
 | 
				
			||||||
            [FromQuery] string? filters,
 | 
					            [FromQuery] ItemFilter[] filters,
 | 
				
			||||||
            [FromQuery] bool? isFavorite,
 | 
					            [FromQuery] bool? isFavorite,
 | 
				
			||||||
            [FromQuery] string? mediaTypes,
 | 
					            [FromQuery] string? mediaTypes,
 | 
				
			||||||
            [FromQuery] string? genres,
 | 
					            [FromQuery] string? genres,
 | 
				
			||||||
@ -187,7 +187,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
                    .ToArray();
 | 
					                    .ToArray();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            foreach (var filter in RequestHelpers.GetFilters(filters))
 | 
					            foreach (var filter in filters)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                switch (filter)
 | 
					                switch (filter)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
 | 
				
			|||||||
@ -36,7 +36,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
        /// <returns>The list of scheduled tasks.</returns>
 | 
					        /// <returns>The list of scheduled tasks.</returns>
 | 
				
			||||||
        [HttpGet]
 | 
					        [HttpGet]
 | 
				
			||||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
					        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
				
			||||||
        public IEnumerable<IScheduledTaskWorker> GetTasks(
 | 
					        public IEnumerable<TaskInfo> GetTasks(
 | 
				
			||||||
            [FromQuery] bool? isHidden,
 | 
					            [FromQuery] bool? isHidden,
 | 
				
			||||||
            [FromQuery] bool? isEnabled)
 | 
					            [FromQuery] bool? isEnabled)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@ -57,7 +57,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                yield return task;
 | 
					                yield return ScheduledTaskHelpers.GetTaskInfo(task);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -53,7 +53,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
        /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
 | 
					        /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
 | 
				
			||||||
        /// <param name="excludeItemTypes">Optional. If specified, results will be filtered out based on item type. This allows multiple, comma delimited.</param>
 | 
					        /// <param name="excludeItemTypes">Optional. If specified, results will be filtered out based on item type. This allows multiple, comma delimited.</param>
 | 
				
			||||||
        /// <param name="includeItemTypes">Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited.</param>
 | 
					        /// <param name="includeItemTypes">Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited.</param>
 | 
				
			||||||
        /// <param name="filters">Optional. Specify additional filters to apply. This allows multiple, comma delimited. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes.</param>
 | 
					        /// <param name="filters">Optional. Specify additional filters to apply.</param>
 | 
				
			||||||
        /// <param name="isFavorite">Optional filter by items that are marked as favorite, or not.</param>
 | 
					        /// <param name="isFavorite">Optional filter by items that are marked as favorite, or not.</param>
 | 
				
			||||||
        /// <param name="mediaTypes">Optional filter by MediaType. Allows multiple, comma delimited.</param>
 | 
					        /// <param name="mediaTypes">Optional filter by MediaType. Allows multiple, comma delimited.</param>
 | 
				
			||||||
        /// <param name="genres">Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimited.</param>
 | 
					        /// <param name="genres">Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimited.</param>
 | 
				
			||||||
@ -88,7 +88,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] ItemFields[] fields,
 | 
					            [FromQuery] ItemFields[] fields,
 | 
				
			||||||
            [FromQuery] string? excludeItemTypes,
 | 
					            [FromQuery] string? excludeItemTypes,
 | 
				
			||||||
            [FromQuery] string? includeItemTypes,
 | 
					            [FromQuery] string? includeItemTypes,
 | 
				
			||||||
            [FromQuery] string? filters,
 | 
					            [FromQuery] ItemFilter[] filters,
 | 
				
			||||||
            [FromQuery] bool? isFavorite,
 | 
					            [FromQuery] bool? isFavorite,
 | 
				
			||||||
            [FromQuery] string? mediaTypes,
 | 
					            [FromQuery] string? mediaTypes,
 | 
				
			||||||
            [FromQuery] string? genres,
 | 
					            [FromQuery] string? genres,
 | 
				
			||||||
@ -188,7 +188,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
                    .ToArray();
 | 
					                    .ToArray();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            foreach (var filter in RequestHelpers.GetFilters(filters))
 | 
					            foreach (var filter in filters)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                switch (filter)
 | 
					                switch (filter)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
using System;
 | 
					using System;
 | 
				
			||||||
using Jellyfin.Api.Constants;
 | 
					using Jellyfin.Api.Constants;
 | 
				
			||||||
using MediaBrowser.Model.Dto;
 | 
					using MediaBrowser.Model.Dto;
 | 
				
			||||||
 | 
					using MediaBrowser.Model.Entities;
 | 
				
			||||||
using MediaBrowser.Model.Querying;
 | 
					using MediaBrowser.Model.Querying;
 | 
				
			||||||
using Microsoft.AspNetCore.Authorization;
 | 
					using Microsoft.AspNetCore.Authorization;
 | 
				
			||||||
using Microsoft.AspNetCore.Http;
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
@ -124,7 +125,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] bool? isHd,
 | 
					            [FromQuery] bool? isHd,
 | 
				
			||||||
            [FromQuery] bool? is4K,
 | 
					            [FromQuery] bool? is4K,
 | 
				
			||||||
            [FromQuery] string? locationTypes,
 | 
					            [FromQuery] string? locationTypes,
 | 
				
			||||||
            [FromQuery] string? excludeLocationTypes,
 | 
					            [FromQuery] LocationType[] excludeLocationTypes,
 | 
				
			||||||
            [FromQuery] bool? isMissing,
 | 
					            [FromQuery] bool? isMissing,
 | 
				
			||||||
            [FromQuery] bool? isUnaired,
 | 
					            [FromQuery] bool? isUnaired,
 | 
				
			||||||
            [FromQuery] double? minCommunityRating,
 | 
					            [FromQuery] double? minCommunityRating,
 | 
				
			||||||
@ -146,7 +147,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] string? parentId,
 | 
					            [FromQuery] string? parentId,
 | 
				
			||||||
            [FromQuery] ItemFields[] fields,
 | 
					            [FromQuery] ItemFields[] fields,
 | 
				
			||||||
            [FromQuery] string? excludeItemTypes,
 | 
					            [FromQuery] string? excludeItemTypes,
 | 
				
			||||||
            [FromQuery] string? filters,
 | 
					            [FromQuery] ItemFilter[] filters,
 | 
				
			||||||
            [FromQuery] bool? isFavorite,
 | 
					            [FromQuery] bool? isFavorite,
 | 
				
			||||||
            [FromQuery] string? mediaTypes,
 | 
					            [FromQuery] string? mediaTypes,
 | 
				
			||||||
            [FromQuery] string? imageTypes,
 | 
					            [FromQuery] string? imageTypes,
 | 
				
			||||||
 | 
				
			|||||||
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