mirror of https://github.com/jellyfin/jellyfin.git
merge branch master into plugin
This commit is contained in:
commit
bd55bdb4e3
|
@ -23,7 +23,7 @@ jobs:
|
||||||
NugetPackageName: ${{ Package.value.NugetPackageName }}
|
NugetPackageName: ${{ Package.value.NugetPackageName }}
|
||||||
AssemblyFileName: ${{ Package.value.AssemblyFileName }}
|
AssemblyFileName: ${{ Package.value.AssemblyFileName }}
|
||||||
maxParallel: 2
|
maxParallel: 2
|
||||||
dependsOn: MainBuild
|
dependsOn: Build
|
||||||
steps:
|
steps:
|
||||||
- checkout: none
|
- checkout: none
|
||||||
|
|
||||||
|
|
|
@ -4,15 +4,14 @@ parameters:
|
||||||
DotNetSdkVersion: 3.1.100
|
DotNetSdkVersion: 3.1.100
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
- job: MainBuild
|
- job: Build
|
||||||
displayName: Main Build
|
displayName: Build
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
Release:
|
Release:
|
||||||
BuildConfiguration: Release
|
BuildConfiguration: Release
|
||||||
Debug:
|
Debug:
|
||||||
BuildConfiguration: Debug
|
BuildConfiguration: Debug
|
||||||
maxParallel: 2
|
|
||||||
pool:
|
pool:
|
||||||
vmImage: "${{ parameters.LinuxImage }}"
|
vmImage: "${{ parameters.LinuxImage }}"
|
||||||
steps:
|
steps:
|
||||||
|
@ -22,13 +21,13 @@ jobs:
|
||||||
persistCredentials: true
|
persistCredentials: true
|
||||||
|
|
||||||
- task: CmdLine@2
|
- task: CmdLine@2
|
||||||
displayName: "Clone Web Client (Master, Release, or Tag)"
|
displayName: "Clone Web Branch"
|
||||||
condition: and(succeeded(), or(contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')), eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
|
condition: and(succeeded(), or(contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')), eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
|
||||||
inputs:
|
inputs:
|
||||||
script: "git clone --single-branch --branch $(Build.SourceBranchName) --depth=1 https://github.com/jellyfin/jellyfin-web.git $(Agent.TempDirectory)/jellyfin-web"
|
script: "git clone --single-branch --branch $(Build.SourceBranchName) --depth=1 https://github.com/jellyfin/jellyfin-web.git $(Agent.TempDirectory)/jellyfin-web"
|
||||||
|
|
||||||
- task: CmdLine@2
|
- task: CmdLine@2
|
||||||
displayName: "Clone Web Client (PR)"
|
displayName: "Clone Web Target"
|
||||||
condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master')), eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest'))
|
condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master')), eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest'))
|
||||||
inputs:
|
inputs:
|
||||||
script: "git clone --single-branch --branch $(System.PullRequest.TargetBranch) --depth 1 https://github.com/jellyfin/jellyfin-web.git $(Agent.TempDirectory)/jellyfin-web"
|
script: "git clone --single-branch --branch $(System.PullRequest.TargetBranch) --depth 1 https://github.com/jellyfin/jellyfin-web.git $(Agent.TempDirectory)/jellyfin-web"
|
||||||
|
@ -37,7 +36,7 @@ jobs:
|
||||||
displayName: "Install Node"
|
displayName: "Install Node"
|
||||||
condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')), eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
|
condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')), eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
|
||||||
inputs:
|
inputs:
|
||||||
versionSpec: "10.x"
|
versionSpec: "12.x"
|
||||||
|
|
||||||
- task: CmdLine@2
|
- task: CmdLine@2
|
||||||
displayName: "Build Web Client"
|
displayName: "Build Web Client"
|
||||||
|
@ -69,33 +68,33 @@ jobs:
|
||||||
command: publish
|
command: publish
|
||||||
publishWebProjects: false
|
publishWebProjects: false
|
||||||
projects: "${{ parameters.RestoreBuildProjects }}"
|
projects: "${{ parameters.RestoreBuildProjects }}"
|
||||||
arguments: "--configuration $(BuildConfiguration) --output $(build.artifactstagingdirectory)"
|
arguments: "--configuration $(BuildConfiguration) --output $(Build.ArtifactStagingDirectory)"
|
||||||
zipAfterPublish: false
|
zipAfterPublish: false
|
||||||
|
|
||||||
- task: PublishPipelineArtifact@0
|
- task: PublishPipelineArtifact@0
|
||||||
displayName: "Publish Artifact Naming"
|
displayName: "Publish Artifact Naming"
|
||||||
condition: and(succeeded(), eq(variables['BuildConfiguration'], 'Release'))
|
condition: and(succeeded(), eq(variables['BuildConfiguration'], 'Release'))
|
||||||
inputs:
|
inputs:
|
||||||
targetPath: "$(build.artifactstagingdirectory)/Jellyfin.Server/Emby.Naming.dll"
|
targetPath: "$(build.ArtifactStagingDirectory)/Jellyfin.Server/Emby.Naming.dll"
|
||||||
artifactName: "Jellyfin.Naming"
|
artifactName: "Jellyfin.Naming"
|
||||||
|
|
||||||
- task: PublishPipelineArtifact@0
|
- task: PublishPipelineArtifact@0
|
||||||
displayName: "Publish Artifact Controller"
|
displayName: "Publish Artifact Controller"
|
||||||
condition: and(succeeded(), eq(variables['BuildConfiguration'], 'Release'))
|
condition: and(succeeded(), eq(variables['BuildConfiguration'], 'Release'))
|
||||||
inputs:
|
inputs:
|
||||||
targetPath: "$(build.artifactstagingdirectory)/Jellyfin.Server/MediaBrowser.Controller.dll"
|
targetPath: "$(build.ArtifactStagingDirectory)/Jellyfin.Server/MediaBrowser.Controller.dll"
|
||||||
artifactName: "Jellyfin.Controller"
|
artifactName: "Jellyfin.Controller"
|
||||||
|
|
||||||
- task: PublishPipelineArtifact@0
|
- task: PublishPipelineArtifact@0
|
||||||
displayName: "Publish Artifact Model"
|
displayName: "Publish Artifact Model"
|
||||||
condition: and(succeeded(), eq(variables['BuildConfiguration'], 'Release'))
|
condition: and(succeeded(), eq(variables['BuildConfiguration'], 'Release'))
|
||||||
inputs:
|
inputs:
|
||||||
targetPath: "$(build.artifactstagingdirectory)/Jellyfin.Server/MediaBrowser.Model.dll"
|
targetPath: "$(build.ArtifactStagingDirectory)/Jellyfin.Server/MediaBrowser.Model.dll"
|
||||||
artifactName: "Jellyfin.Model"
|
artifactName: "Jellyfin.Model"
|
||||||
|
|
||||||
- task: PublishPipelineArtifact@0
|
- task: PublishPipelineArtifact@0
|
||||||
displayName: "Publish Artifact Common"
|
displayName: "Publish Artifact Common"
|
||||||
condition: and(succeeded(), eq(variables['BuildConfiguration'], 'Release'))
|
condition: and(succeeded(), eq(variables['BuildConfiguration'], 'Release'))
|
||||||
inputs:
|
inputs:
|
||||||
targetPath: "$(build.artifactstagingdirectory)/Jellyfin.Server/MediaBrowser.Common.dll"
|
targetPath: "$(build.ArtifactStagingDirectory)/Jellyfin.Server/MediaBrowser.Common.dll"
|
||||||
artifactName: "Jellyfin.Common"
|
artifactName: "Jellyfin.Common"
|
||||||
|
|
|
@ -1,82 +0,0 @@
|
||||||
parameters:
|
|
||||||
WindowsImage: "windows-latest"
|
|
||||||
TestProjects: "tests/**/*Tests.csproj"
|
|
||||||
DotNetSdkVersion: 3.1.100
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
- job: PublishWindows
|
|
||||||
displayName: Publish Windows
|
|
||||||
pool:
|
|
||||||
vmImage: ${{ parameters.WindowsImage }}
|
|
||||||
steps:
|
|
||||||
- checkout: self
|
|
||||||
clean: true
|
|
||||||
submodules: true
|
|
||||||
persistCredentials: true
|
|
||||||
|
|
||||||
- task: CmdLine@2
|
|
||||||
displayName: "Clone Web Client (Master, Release, or Tag)"
|
|
||||||
condition: and(succeeded(), or(contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master'), contains(variables['Build.SourceBranch'], 'tag')), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
|
|
||||||
inputs:
|
|
||||||
script: "git clone --single-branch --branch $(Build.SourceBranchName) --depth=1 https://github.com/jellyfin/jellyfin-web.git $(Agent.TempDirectory)/jellyfin-web"
|
|
||||||
|
|
||||||
- task: CmdLine@2
|
|
||||||
displayName: "Clone Web Client (PR)"
|
|
||||||
condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master')), in(variables['Build.Reason'], 'PullRequest'))
|
|
||||||
inputs:
|
|
||||||
script: "git clone --single-branch --branch $(System.PullRequest.TargetBranch) --depth 1 https://github.com/jellyfin/jellyfin-web.git $(Agent.TempDirectory)/jellyfin-web"
|
|
||||||
|
|
||||||
- task: NodeTool@0
|
|
||||||
displayName: "Install Node"
|
|
||||||
condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
|
|
||||||
inputs:
|
|
||||||
versionSpec: "10.x"
|
|
||||||
|
|
||||||
- task: CmdLine@2
|
|
||||||
displayName: "Build Web Client"
|
|
||||||
condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
|
|
||||||
inputs:
|
|
||||||
script: yarn install
|
|
||||||
workingDirectory: $(Agent.TempDirectory)/jellyfin-web
|
|
||||||
|
|
||||||
- task: CopyFiles@2
|
|
||||||
displayName: "Copy Web Client"
|
|
||||||
condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion'))
|
|
||||||
inputs:
|
|
||||||
sourceFolder: $(Agent.TempDirectory)/jellyfin-web/dist
|
|
||||||
contents: "**"
|
|
||||||
targetFolder: $(Build.SourcesDirectory)/MediaBrowser.WebDashboard/jellyfin-web
|
|
||||||
cleanTargetFolder: true
|
|
||||||
overWrite: true
|
|
||||||
flattenFolders: false
|
|
||||||
|
|
||||||
- task: CmdLine@2
|
|
||||||
displayName: "Clone UX Repository"
|
|
||||||
inputs:
|
|
||||||
script: git clone --depth=1 https://github.com/jellyfin/jellyfin-ux $(Agent.TempDirectory)\jellyfin-ux
|
|
||||||
|
|
||||||
- task: PowerShell@2
|
|
||||||
displayName: "Build NSIS Installer"
|
|
||||||
inputs:
|
|
||||||
targetType: "filePath"
|
|
||||||
filePath: ./deployment/windows/build-jellyfin.ps1
|
|
||||||
arguments: -InstallFFMPEG -InstallNSSM -MakeNSIS -InstallTrayApp -UXLocation $(Agent.TempDirectory)\jellyfin-ux -InstallLocation $(build.artifactstagingdirectory)
|
|
||||||
errorActionPreference: "stop"
|
|
||||||
workingDirectory: $(Build.SourcesDirectory)
|
|
||||||
|
|
||||||
- task: CopyFiles@2
|
|
||||||
displayName: "Copy NSIS Installer"
|
|
||||||
inputs:
|
|
||||||
sourceFolder: $(Build.SourcesDirectory)/deployment/windows/
|
|
||||||
contents: "jellyfin*.exe"
|
|
||||||
targetFolder: $(System.ArtifactsDirectory)/setup
|
|
||||||
cleanTargetFolder: true
|
|
||||||
overWrite: true
|
|
||||||
flattenFolders: true
|
|
||||||
|
|
||||||
- task: PublishPipelineArtifact@0
|
|
||||||
displayName: "Publish Artifact Setup"
|
|
||||||
condition: succeeded()
|
|
||||||
inputs:
|
|
||||||
targetPath: "$(build.artifactstagingdirectory)/setup"
|
|
||||||
artifactName: "Jellyfin Server Setup"
|
|
|
@ -27,11 +27,6 @@ jobs:
|
||||||
Windows: "windows-latest"
|
Windows: "windows-latest"
|
||||||
macOS: "macos-latest"
|
macOS: "macos-latest"
|
||||||
|
|
||||||
- template: azure-pipelines-windows.yml
|
|
||||||
parameters:
|
|
||||||
WindowsImage: "windows-latest"
|
|
||||||
TestProjects: $(TestProjects)
|
|
||||||
|
|
||||||
- template: azure-pipelines-compat.yml
|
- template: azure-pipelines-compat.yml
|
||||||
parameters:
|
parameters:
|
||||||
Packages:
|
Packages:
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
---
|
||||||
|
name: Feature Request
|
||||||
|
about: Request a new feature
|
||||||
|
title: ''
|
||||||
|
labels: feature-request
|
||||||
|
assignees: ''
|
||||||
|
---
|
||||||
|
|
||||||
|
**PLEASE DO NOT OPEN FEATURE REQUEST ISSUES ON GITHUB**
|
||||||
|
|
||||||
|
**Feature requests should be opened on our dedicated [feature request](https://features.jellyfin.org/) hub so they can be appropriately discussed and prioritized.**
|
||||||
|
|
||||||
|
However, if you are willing to contribute to the project by adding a new feature yourself, then please ensure that you first review our [documentation](https://docs.jellyfin.org/general/contributing/development.html) on contributing code. Once you have reviewed the documentation, feel free to come back here and open an issue here outlining your proposed approach so that it can be documented, tracked, and discussed by other team members.
|
|
@ -39,6 +39,7 @@ ProgramData*/
|
||||||
CorePlugins*/
|
CorePlugins*/
|
||||||
ProgramData-Server*/
|
ProgramData-Server*/
|
||||||
ProgramData-UI*/
|
ProgramData-UI*/
|
||||||
|
MediaBrowser.WebDashboard/jellyfin-web/**
|
||||||
|
|
||||||
#################
|
#################
|
||||||
## Visual Studio
|
## Visual Studio
|
||||||
|
|
149
CONTRIBUTORS.md
149
CONTRIBUTORS.md
|
@ -1,40 +1,133 @@
|
||||||
# Jellyfin Contributors
|
# Jellyfin Contributors
|
||||||
|
|
||||||
- [JoshuaBoniface](https://github.com/joshuaboniface)
|
- [97carmine](https://github.com/97carmine)
|
||||||
- [nvllsvm](https://github.com/nvllsvm)
|
- [Abbe98](https://github.com/Abbe98)
|
||||||
- [JustAMan](https://github.com/JustAMan)
|
- [agrenott](https://github.com/agrenott)
|
||||||
- [dcrdev](https://github.com/dcrdev)
|
- [AndreCarvalho](https://github.com/AndreCarvalho)
|
||||||
- [EraYaN](https://github.com/EraYaN)
|
- [anthonylavado](https://github.com/anthonylavado)
|
||||||
- [flemse](https://github.com/flemse)
|
- [Artiume](https://github.com/Artiume)
|
||||||
|
- [AThomsen](https://github.com/AThomsen)
|
||||||
|
- [bilde2910](https://github.com/bilde2910)
|
||||||
- [bfayers](https://github.com/bfayers)
|
- [bfayers](https://github.com/bfayers)
|
||||||
- [Bond_009](https://github.com/Bond-009)
|
- [BnMcG](https://github.com/BnMcG)
|
||||||
- [AnthonyLavado](https://github.com/anthonylavado)
|
- [Bond-009](https://github.com/Bond-009)
|
||||||
- [sparky8251](https://github.com/sparky8251)
|
- [brianjmurrell](https://github.com/brianjmurrell)
|
||||||
- [LeoVerto](https://github.com/LeoVerto)
|
- [bugfixin](https://github.com/bugfixin)
|
||||||
- [grafixeyehero](https://github.com/grafixeyehero)
|
- [chaosinnovator](https://github.com/chaosinnovator)
|
||||||
|
- [ckcr4lyf](https://github.com/ckcr4lyf)
|
||||||
|
- [crankdoofus](https://github.com/crankdoofus)
|
||||||
|
- [crobibero](https://github.com/crobibero)
|
||||||
|
- [cromefire](https://github.com/cromefire)
|
||||||
|
- [cryptobank](https://github.com/cryptobank)
|
||||||
- [cvium](https://github.com/cvium)
|
- [cvium](https://github.com/cvium)
|
||||||
- [wtayl0r](https://github.com/wtayl0r)
|
- [dannymichel](https://github.com/dannymichel)
|
||||||
- [TtheCreator](https://github.com/Tthecreator)
|
- [DaveChild](https://github.com/DaveChild)
|
||||||
|
- [dcrdev](https://github.com/dcrdev)
|
||||||
|
- [dhartung](https://github.com/dhartung)
|
||||||
|
- [dinki](https://github.com/dinki)
|
||||||
- [dkanada](https://github.com/dkanada)
|
- [dkanada](https://github.com/dkanada)
|
||||||
- [LogicalPhallacy](https://github.com/LogicalPhallacy/)
|
- [dlahoti](https://github.com/dlahoti)
|
||||||
- [RazeLighter777](https://github.com/RazeLighter777)
|
- [dmitrylyzo](https://github.com/dmitrylyzo)
|
||||||
- [WillWill56](https://github.com/WillWill56)
|
- [DMouse10462](https://github.com/DMouse10462)
|
||||||
- [Liggy](https://github.com/Liggy)
|
- [DrPandemic](https://github.com/DrPandemic)
|
||||||
- [fruhnow](https://github.com/fruhnow)
|
- [EraYaN](https://github.com/EraYaN)
|
||||||
- [Lynxy](https://github.com/Lynxy)
|
- [escabe](https://github.com/escabe)
|
||||||
|
- [excelite](https://github.com/excelite)
|
||||||
- [fasheng](https://github.com/fasheng)
|
- [fasheng](https://github.com/fasheng)
|
||||||
- [ploughpuff](https://github.com/ploughpuff)
|
- [ferferga](https://github.com/ferferga)
|
||||||
- [pjeanjean](https://github.com/pjeanjean)
|
|
||||||
- [DrPandemic](https://github.com/drpandemic)
|
|
||||||
- [joern-h](https://github.com/joern-h)
|
|
||||||
- [Khinenw](https://github.com/HelloWorld017)
|
|
||||||
- [fhriley](https://github.com/fhriley)
|
- [fhriley](https://github.com/fhriley)
|
||||||
- [nevado](https://github.com/nevado)
|
- [flemse](https://github.com/flemse)
|
||||||
- [mark-monteiro](https://github.com/mark-monteiro)
|
- [Froghut](https://github.com/Froghut)
|
||||||
- [ullmie02](https://github.com/ullmie02)
|
- [fruhnow](https://github.com/fruhnow)
|
||||||
- [geilername](https://github.com/geilername)
|
- [geilername](https://github.com/geilername)
|
||||||
|
- [gnattu](https://github.com/gnattu)
|
||||||
|
- [grafixeyehero](https://github.com/grafixeyehero)
|
||||||
|
- [h1nk](https://github.com/h1nk)
|
||||||
|
- [hawken93](https://github.com/hawken93)
|
||||||
|
- [HelloWorld017](https://github.com/HelloWorld017)
|
||||||
|
- [jftuga](https://github.com/jftuga)
|
||||||
|
- [joern-h](https://github.com/joern-h)
|
||||||
|
- [joshuaboniface](https://github.com/joshuaboniface)
|
||||||
|
- [JustAMan](https://github.com/JustAMan)
|
||||||
|
- [justinfenn](https://github.com/justinfenn)
|
||||||
|
- [KerryRJ](https://github.com/KerryRJ)
|
||||||
|
- [Larvitar](https://github.com/Larvitar)
|
||||||
|
- [LeoVerto](https://github.com/LeoVerto)
|
||||||
|
- [Liggy](https://github.com/Liggy)
|
||||||
|
- [LogicalPhallacy](https://github.com/LogicalPhallacy)
|
||||||
|
- [loli10K](https://github.com/loli10K)
|
||||||
|
- [lostmypillow](https://github.com/lostmypillow)
|
||||||
|
- [Lynxy](https://github.com/Lynxy)
|
||||||
|
- [ManfredRichthofen](https://github.com/ManfredRichthofen)
|
||||||
|
- [Marenz](https://github.com/Marenz)
|
||||||
|
- [marius-luca-87](https://github.com/marius-luca-87)
|
||||||
|
- [mark-monteiro](https://github.com/mark-monteiro)
|
||||||
|
- [Matt07211](https://github.com/Matt07211)
|
||||||
|
- [mcarlton00](https://github.com/mcarlton00)
|
||||||
|
- [mitchfizz05](https://github.com/mitchfizz05)
|
||||||
|
- [MrTimscampi](https://github.com/MrTimscampi)
|
||||||
|
- [n8225](https://github.com/n8225)
|
||||||
|
- [Narfinger](https://github.com/Narfinger)
|
||||||
|
- [NathanPickard](https://github.com/NathanPickard)
|
||||||
|
- [neilsb](https://github.com/neilsb)
|
||||||
|
- [nevado](https://github.com/nevado)
|
||||||
|
- [Nickbert7](https://github.com/Nickbert7)
|
||||||
|
- [nvllsvm](https://github.com/nvllsvm)
|
||||||
|
- [nyanmisaka](https://github.com/nyanmisaka)
|
||||||
|
- [oddstr13](https://github.com/oddstr13)
|
||||||
|
- [petermcneil](https://github.com/petermcneil)
|
||||||
|
- [Phlogi](https://github.com/Phlogi)
|
||||||
|
- [pjeanjean](https://github.com/pjeanjean)
|
||||||
|
- [ploughpuff](https://github.com/ploughpuff)
|
||||||
- [pR0Ps](https://github.com/pR0Ps)
|
- [pR0Ps](https://github.com/pR0Ps)
|
||||||
|
- [PrplHaz4](https://github.com/PrplHaz4)
|
||||||
|
- [RazeLighter777](https://github.com/RazeLighter777)
|
||||||
|
- [redSpoutnik](https://github.com/redSpoutnik)
|
||||||
|
- [ringmatter](https://github.com/ringmatter)
|
||||||
|
- [ryan-hartzell](https://github.com/ryan-hartzell)
|
||||||
|
- [s0urcelab](https://github.com/s0urcelab)
|
||||||
|
- [sachk](https://github.com/sachk)
|
||||||
|
- [sammyrc34](https://github.com/sammyrc34)
|
||||||
|
- [samuel9554](https://github.com/samuel9554)
|
||||||
|
- [scheidleon](https://github.com/scheidleon)
|
||||||
|
- [sebPomme](https://github.com/sebPomme)
|
||||||
|
- [SegiH](https://github.com/SegiH)
|
||||||
|
- [SenorSmartyPants](https://github.com/SenorSmartyPants)
|
||||||
|
- [shemanaev](https://github.com/shemanaev)
|
||||||
|
- [skaro13](https://github.com/skaro13)
|
||||||
|
- [sl1288](https://github.com/sl1288)
|
||||||
|
- [sorinyo2004](https://github.com/sorinyo2004)
|
||||||
|
- [sparky8251](https://github.com/sparky8251)
|
||||||
|
- [stanionascu](https://github.com/stanionascu)
|
||||||
|
- [stevehayles](https://github.com/stevehayles)
|
||||||
|
- [SuperSandro2000](https://github.com/SuperSandro2000)
|
||||||
|
- [tbraeutigam](https://github.com/tbraeutigam)
|
||||||
|
- [teacupx](https://github.com/teacupx)
|
||||||
|
- [Terror-Gene](https://github.com/Terror-Gene)
|
||||||
|
- [ThatNerdyPikachu](https://github.com/ThatNerdyPikachu)
|
||||||
|
- [ThibaultNocchi](https://github.com/ThibaultNocchi)
|
||||||
|
- [thornbill](https://github.com/thornbill)
|
||||||
|
- [ThreeFive-O](https://github.com/ThreeFive-O)
|
||||||
|
- [TrisMcC](https://github.com/TrisMcC)
|
||||||
|
- [trumblejoe](https://github.com/trumblejoe)
|
||||||
|
- [TtheCreator](https://github.com/TtheCreator)
|
||||||
|
- [twinkybot](https://github.com/twinkybot)
|
||||||
|
- [Ullmie02](https://github.com/Ullmie02)
|
||||||
|
- [Unhelpful](https://github.com/Unhelpful)
|
||||||
|
- [viaregio](https://github.com/viaregio)
|
||||||
|
- [vitorsemeano](https://github.com/vitorsemeano)
|
||||||
|
- [voodoos](https://github.com/voodoos)
|
||||||
|
- [whooo](https://github.com/whooo)
|
||||||
|
- [WiiPlayer2](https://github.com/WiiPlayer2)
|
||||||
|
- [WillWill56](https://github.com/WillWill56)
|
||||||
|
- [wtayl0r](https://github.com/wtayl0r)
|
||||||
|
- [Wuerfelbecher](https://github.com/Wuerfelbecher)
|
||||||
|
- [Wunax](https://github.com/Wunax)
|
||||||
|
- [WWWesten](https://github.com/WWWesten)
|
||||||
|
- [WX9yMOXWId](https://github.com/WX9yMOXWId)
|
||||||
|
- [xosdy](https://github.com/xosdy)
|
||||||
|
- [XVicarious](https://github.com/XVicarious)
|
||||||
|
- [YouKnowBlom](https://github.com/YouKnowBlom)
|
||||||
|
|
||||||
# Emby Contributors
|
# Emby Contributors
|
||||||
|
|
||||||
|
|
30
Dockerfile
30
Dockerfile
|
@ -3,11 +3,10 @@ ARG FFMPEG_VERSION=latest
|
||||||
|
|
||||||
FROM node:alpine as web-builder
|
FROM node:alpine as web-builder
|
||||||
ARG JELLYFIN_WEB_VERSION=master
|
ARG JELLYFIN_WEB_VERSION=master
|
||||||
RUN apk add curl git \
|
RUN apk add curl git zlib zlib-dev autoconf g++ make libpng-dev gifsicle alpine-sdk automake libtool make gcc musl-dev nasm \
|
||||||
&& curl -L https://github.com/jellyfin/jellyfin-web/archive/${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \
|
&& curl -L https://github.com/jellyfin/jellyfin-web/archive/${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \
|
||||||
&& cd jellyfin-web-* \
|
&& cd jellyfin-web-* \
|
||||||
&& yarn install \
|
&& yarn install \
|
||||||
&& yarn build \
|
|
||||||
&& mv dist /dist
|
&& mv dist /dist
|
||||||
|
|
||||||
FROM mcr.microsoft.com/dotnet/core/sdk:${DOTNET_VERSION}-buster as builder
|
FROM mcr.microsoft.com/dotnet/core/sdk:${DOTNET_VERSION}-buster as builder
|
||||||
|
@ -21,6 +20,13 @@ RUN dotnet publish Jellyfin.Server --disable-parallel --configuration Release --
|
||||||
FROM jellyfin/ffmpeg:${FFMPEG_VERSION} as ffmpeg
|
FROM jellyfin/ffmpeg:${FFMPEG_VERSION} as ffmpeg
|
||||||
FROM debian:buster-slim
|
FROM debian:buster-slim
|
||||||
|
|
||||||
|
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
|
||||||
|
ARG DEBIAN_FRONTEND="noninteractive"
|
||||||
|
# http://stackoverflow.com/questions/48162574/ddg#49462622
|
||||||
|
ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn
|
||||||
|
# https://github.com/NVIDIA/nvidia-docker/wiki/Installation-(Native-GPU-Support)
|
||||||
|
ENV NVIDIA_DRIVER_CAPABILITIES="compute,video,utility"
|
||||||
|
|
||||||
COPY --from=ffmpeg /opt/ffmpeg /opt/ffmpeg
|
COPY --from=ffmpeg /opt/ffmpeg /opt/ffmpeg
|
||||||
COPY --from=builder /jellyfin /jellyfin
|
COPY --from=builder /jellyfin /jellyfin
|
||||||
COPY --from=web-builder /dist /jellyfin/jellyfin-web
|
COPY --from=web-builder /dist /jellyfin/jellyfin-web
|
||||||
|
@ -31,16 +37,28 @@ COPY --from=web-builder /dist /jellyfin/jellyfin-web
|
||||||
# mesa-va-drivers: needed for VAAPI
|
# mesa-va-drivers: needed for VAAPI
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install --no-install-recommends --no-install-suggests -y \
|
&& apt-get install --no-install-recommends --no-install-suggests -y \
|
||||||
libfontconfig1 libgomp1 libva-drm2 mesa-va-drivers openssl ca-certificates \
|
libfontconfig1 \
|
||||||
&& apt-get clean autoclean \
|
libgomp1 \
|
||||||
&& apt-get autoremove \
|
libva-drm2 \
|
||||||
|
mesa-va-drivers \
|
||||||
|
openssl \
|
||||||
|
ca-certificates \
|
||||||
|
vainfo \
|
||||||
|
i965-va-driver \
|
||||||
|
locales \
|
||||||
|
&& apt-get clean autoclean -y\
|
||||||
|
&& apt-get autoremove -y\
|
||||||
&& rm -rf /var/lib/apt/lists/* \
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
&& mkdir -p /cache /config /media \
|
&& mkdir -p /cache /config /media \
|
||||||
&& chmod 777 /cache /config /media \
|
&& chmod 777 /cache /config /media \
|
||||||
&& ln -s /opt/ffmpeg/bin/ffmpeg /usr/local/bin \
|
&& ln -s /opt/ffmpeg/bin/ffmpeg /usr/local/bin \
|
||||||
&& ln -s /opt/ffmpeg/bin/ffprobe /usr/local/bin
|
&& ln -s /opt/ffmpeg/bin/ffprobe /usr/local/bin \
|
||||||
|
&& sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen
|
||||||
|
|
||||||
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1
|
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1
|
||||||
|
ENV LC_ALL en_US.UTF-8
|
||||||
|
ENV LANG en_US.UTF-8
|
||||||
|
ENV LANGUAGE en_US:en
|
||||||
|
|
||||||
EXPOSE 8096
|
EXPOSE 8096
|
||||||
VOLUME /cache /config /media
|
VOLUME /cache /config /media
|
||||||
|
|
|
@ -7,11 +7,10 @@ ARG DOTNET_VERSION=3.1
|
||||||
|
|
||||||
FROM node:alpine as web-builder
|
FROM node:alpine as web-builder
|
||||||
ARG JELLYFIN_WEB_VERSION=master
|
ARG JELLYFIN_WEB_VERSION=master
|
||||||
RUN apk add curl git \
|
RUN apk add curl git zlib zlib-dev autoconf g++ make libpng-dev gifsicle alpine-sdk automake libtool make gcc musl-dev nasm python \
|
||||||
&& curl -L https://github.com/jellyfin/jellyfin-web/archive/${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \
|
&& curl -L https://github.com/jellyfin/jellyfin-web/archive/${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \
|
||||||
&& cd jellyfin-web-* \
|
&& cd jellyfin-web-* \
|
||||||
&& yarn install \
|
&& yarn install \
|
||||||
&& yarn build \
|
|
||||||
&& mv dist /dist
|
&& mv dist /dist
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,21 +26,52 @@ RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin"
|
||||||
|
|
||||||
FROM multiarch/qemu-user-static:x86_64-arm as qemu
|
FROM multiarch/qemu-user-static:x86_64-arm as qemu
|
||||||
FROM arm32v7/debian:buster-slim
|
FROM arm32v7/debian:buster-slim
|
||||||
|
|
||||||
|
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
|
||||||
|
ARG DEBIAN_FRONTEND="noninteractive"
|
||||||
|
# http://stackoverflow.com/questions/48162574/ddg#49462622
|
||||||
|
ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn
|
||||||
|
# https://github.com/NVIDIA/nvidia-docker/wiki/Installation-(Native-GPU-Support)
|
||||||
|
ENV NVIDIA_DRIVER_CAPABILITIES="compute,video,utility"
|
||||||
|
|
||||||
COPY --from=qemu /usr/bin/qemu-arm-static /usr/bin
|
COPY --from=qemu /usr/bin/qemu-arm-static /usr/bin
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install --no-install-recommends --no-install-suggests -y ffmpeg \
|
&& apt-get install --no-install-recommends --no-install-suggests -y ca-certificates gnupg curl && \
|
||||||
libssl-dev ca-certificates \
|
curl -ks https://repo.jellyfin.org/debian/jellyfin_team.gpg.key | apt-key add - && \
|
||||||
|
curl -s https://keyserver.ubuntu.com/pks/lookup?op=get\&search=0x6587ffd6536b8826e88a62547876ae518cbcf2f2 | apt-key add - && \
|
||||||
|
echo 'deb [arch=armhf] https://repo.jellyfin.org/debian buster main' > /etc/apt/sources.list.d/jellyfin.list && \
|
||||||
|
echo "deb http://ppa.launchpad.net/ubuntu-raspi2/ppa/ubuntu bionic main">> /etc/apt/sources.list.d/raspbins.list && \
|
||||||
|
apt-get update && \
|
||||||
|
apt-get install --no-install-recommends --no-install-suggests -y \
|
||||||
|
jellyfin-ffmpeg \
|
||||||
|
libssl-dev \
|
||||||
|
libfontconfig1 \
|
||||||
|
libfreetype6 \
|
||||||
|
libomxil-bellagio0 \
|
||||||
|
libomxil-bellagio-bin \
|
||||||
|
libraspberrypi0 \
|
||||||
|
vainfo \
|
||||||
|
libva2 \
|
||||||
|
locales \
|
||||||
|
&& apt-get remove curl gnupg -y \
|
||||||
|
&& apt-get clean autoclean -y \
|
||||||
|
&& apt-get autoremove -y \
|
||||||
&& rm -rf /var/lib/apt/lists/* \
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
&& mkdir -p /cache /config /media \
|
&& mkdir -p /cache /config /media \
|
||||||
&& chmod 777 /cache /config /media
|
&& chmod 777 /cache /config /media \
|
||||||
|
&& sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen
|
||||||
|
|
||||||
COPY --from=builder /jellyfin /jellyfin
|
COPY --from=builder /jellyfin /jellyfin
|
||||||
COPY --from=web-builder /dist /jellyfin/jellyfin-web
|
COPY --from=web-builder /dist /jellyfin/jellyfin-web
|
||||||
|
|
||||||
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1
|
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1
|
||||||
|
ENV LC_ALL en_US.UTF-8
|
||||||
|
ENV LANG en_US.UTF-8
|
||||||
|
ENV LANGUAGE en_US:en
|
||||||
|
|
||||||
EXPOSE 8096
|
EXPOSE 8096
|
||||||
VOLUME /cache /config /media
|
VOLUME /cache /config /media
|
||||||
ENTRYPOINT ["./jellyfin/jellyfin", \
|
ENTRYPOINT ["./jellyfin/jellyfin", \
|
||||||
"--datadir", "/config", \
|
"--datadir", "/config", \
|
||||||
"--cachedir", "/cache", \
|
"--cachedir", "/cache", \
|
||||||
"--ffmpeg", "/usr/bin/ffmpeg"]
|
"--ffmpeg", "/usr/lib/jellyfin-ffmpeg"]
|
||||||
|
|
|
@ -7,11 +7,10 @@ ARG DOTNET_VERSION=3.1
|
||||||
|
|
||||||
FROM node:alpine as web-builder
|
FROM node:alpine as web-builder
|
||||||
ARG JELLYFIN_WEB_VERSION=master
|
ARG JELLYFIN_WEB_VERSION=master
|
||||||
RUN apk add curl git \
|
RUN apk add curl git zlib zlib-dev autoconf g++ make libpng-dev gifsicle alpine-sdk automake libtool make gcc musl-dev nasm python \
|
||||||
&& curl -L https://github.com/jellyfin/jellyfin-web/archive/${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \
|
&& curl -L https://github.com/jellyfin/jellyfin-web/archive/${JELLYFIN_WEB_VERSION}.tar.gz | tar zxf - \
|
||||||
&& cd jellyfin-web-* \
|
&& cd jellyfin-web-* \
|
||||||
&& yarn install \
|
&& yarn install \
|
||||||
&& yarn build \
|
|
||||||
&& mv dist /dist
|
&& mv dist /dist
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,17 +25,38 @@ RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin"
|
||||||
|
|
||||||
FROM multiarch/qemu-user-static:x86_64-aarch64 as qemu
|
FROM multiarch/qemu-user-static:x86_64-aarch64 as qemu
|
||||||
FROM arm64v8/debian:buster-slim
|
FROM arm64v8/debian:buster-slim
|
||||||
|
|
||||||
|
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
|
||||||
|
ARG DEBIAN_FRONTEND="noninteractive"
|
||||||
|
# http://stackoverflow.com/questions/48162574/ddg#49462622
|
||||||
|
ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn
|
||||||
|
# https://github.com/NVIDIA/nvidia-docker/wiki/Installation-(Native-GPU-Support)
|
||||||
|
ENV NVIDIA_DRIVER_CAPABILITIES="compute,video,utility"
|
||||||
|
|
||||||
COPY --from=qemu /usr/bin/qemu-aarch64-static /usr/bin
|
COPY --from=qemu /usr/bin/qemu-aarch64-static /usr/bin
|
||||||
RUN apt-get update \
|
RUN apt-get update && apt-get install --no-install-recommends --no-install-suggests -y \
|
||||||
&& apt-get install --no-install-recommends --no-install-suggests -y ffmpeg \
|
ffmpeg \
|
||||||
libssl-dev ca-certificates \
|
libssl-dev \
|
||||||
|
ca-certificates \
|
||||||
|
libfontconfig1 \
|
||||||
|
libfreetype6 \
|
||||||
|
libomxil-bellagio0 \
|
||||||
|
libomxil-bellagio-bin \
|
||||||
|
locales \
|
||||||
|
&& apt-get clean autoclean -y \
|
||||||
|
&& apt-get autoremove -y \
|
||||||
&& rm -rf /var/lib/apt/lists/* \
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
&& mkdir -p /cache /config /media \
|
&& mkdir -p /cache /config /media \
|
||||||
&& chmod 777 /cache /config /media
|
&& chmod 777 /cache /config /media \
|
||||||
|
&& sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen
|
||||||
|
|
||||||
COPY --from=builder /jellyfin /jellyfin
|
COPY --from=builder /jellyfin /jellyfin
|
||||||
COPY --from=web-builder /dist /jellyfin/jellyfin-web
|
COPY --from=web-builder /dist /jellyfin/jellyfin-web
|
||||||
|
|
||||||
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1
|
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1
|
||||||
|
ENV LC_ALL en_US.UTF-8
|
||||||
|
ENV LANG en_US.UTF-8
|
||||||
|
ENV LANGUAGE en_US:en
|
||||||
|
|
||||||
EXPOSE 8096
|
EXPOSE 8096
|
||||||
VOLUME /cache /config /media
|
VOLUME /cache /config /media
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace DvdLib.Ifo
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var nums = ifo.Name.Split(new [] { '_' }, StringSplitOptions.RemoveEmptyEntries);
|
var nums = ifo.Name.Split(new[] { '_' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
if (nums.Length >= 2 && ushort.TryParse(nums[1], out var ifoNumber))
|
if (nums.Length >= 2 && ushort.TryParse(nums[1], out var ifoNumber))
|
||||||
{
|
{
|
||||||
ReadVTS(ifoNumber, ifo.FullName);
|
ReadVTS(ifoNumber, ifo.FullName);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -152,6 +152,7 @@ namespace Emby.Dlna.Api
|
||||||
return _resultFactory.GetStaticResult(Request, cacheKey, null, cacheLength, XMLContentType, () => Task.FromResult<Stream>(new MemoryStream(bytes)));
|
return _resultFactory.GetStaticResult(Request, cacheKey, null, cacheLength, XMLContentType, () => Task.FromResult<Stream>(new MemoryStream(bytes)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
|
||||||
public object Get(GetContentDirectory request)
|
public object Get(GetContentDirectory request)
|
||||||
{
|
{
|
||||||
var xml = ContentDirectory.GetServiceXml();
|
var xml = ContentDirectory.GetServiceXml();
|
||||||
|
@ -159,6 +160,7 @@ namespace Emby.Dlna.Api
|
||||||
return _resultFactory.GetResult(Request, xml, XMLContentType);
|
return _resultFactory.GetResult(Request, xml, XMLContentType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
|
||||||
public object Get(GetMediaReceiverRegistrar request)
|
public object Get(GetMediaReceiverRegistrar request)
|
||||||
{
|
{
|
||||||
var xml = MediaReceiverRegistrar.GetServiceXml();
|
var xml = MediaReceiverRegistrar.GetServiceXml();
|
||||||
|
@ -166,6 +168,7 @@ namespace Emby.Dlna.Api
|
||||||
return _resultFactory.GetResult(Request, xml, XMLContentType);
|
return _resultFactory.GetResult(Request, xml, XMLContentType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
|
||||||
public object Get(GetConnnectionManager request)
|
public object Get(GetConnnectionManager request)
|
||||||
{
|
{
|
||||||
var xml = ConnectionManager.GetServiceXml();
|
var xml = ConnectionManager.GetServiceXml();
|
||||||
|
@ -314,31 +317,37 @@ namespace Emby.Dlna.Api
|
||||||
return _resultFactory.GetStaticResult(Request, cacheKey, null, cacheLength, contentType, () => Task.FromResult(_dlnaManager.GetIcon(request.Filename).Stream));
|
return _resultFactory.GetStaticResult(Request, cacheKey, null, cacheLength, contentType, () => Task.FromResult(_dlnaManager.GetIcon(request.Filename).Stream));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
|
||||||
public object Subscribe(ProcessContentDirectoryEventRequest request)
|
public object Subscribe(ProcessContentDirectoryEventRequest request)
|
||||||
{
|
{
|
||||||
return ProcessEventRequest(ContentDirectory);
|
return ProcessEventRequest(ContentDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
|
||||||
public object Subscribe(ProcessConnectionManagerEventRequest request)
|
public object Subscribe(ProcessConnectionManagerEventRequest request)
|
||||||
{
|
{
|
||||||
return ProcessEventRequest(ConnectionManager);
|
return ProcessEventRequest(ConnectionManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
|
||||||
public object Subscribe(ProcessMediaReceiverRegistrarEventRequest request)
|
public object Subscribe(ProcessMediaReceiverRegistrarEventRequest request)
|
||||||
{
|
{
|
||||||
return ProcessEventRequest(MediaReceiverRegistrar);
|
return ProcessEventRequest(MediaReceiverRegistrar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
|
||||||
public object Unsubscribe(ProcessContentDirectoryEventRequest request)
|
public object Unsubscribe(ProcessContentDirectoryEventRequest request)
|
||||||
{
|
{
|
||||||
return ProcessEventRequest(ContentDirectory);
|
return ProcessEventRequest(ContentDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
|
||||||
public object Unsubscribe(ProcessConnectionManagerEventRequest request)
|
public object Unsubscribe(ProcessConnectionManagerEventRequest request)
|
||||||
{
|
{
|
||||||
return ProcessEventRequest(ConnectionManager);
|
return ProcessEventRequest(ConnectionManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
|
||||||
public object Unsubscribe(ProcessMediaReceiverRegistrarEventRequest request)
|
public object Unsubscribe(ProcessMediaReceiverRegistrarEventRequest request)
|
||||||
{
|
{
|
||||||
return ProcessEventRequest(MediaReceiverRegistrar);
|
return ProcessEventRequest(MediaReceiverRegistrar);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using MediaBrowser.Controller.Dlna;
|
using MediaBrowser.Controller.Dlna;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
|
@ -53,6 +53,7 @@ namespace Emby.Dlna.Api
|
||||||
_dlnaManager = dlnaManager;
|
_dlnaManager = dlnaManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
|
||||||
public object Get(GetProfileInfos request)
|
public object Get(GetProfileInfos request)
|
||||||
{
|
{
|
||||||
return _dlnaManager.GetProfileInfos().ToArray();
|
return _dlnaManager.GetProfileInfos().ToArray();
|
||||||
|
@ -63,6 +64,7 @@ namespace Emby.Dlna.Api
|
||||||
return _dlnaManager.GetProfile(request.Id);
|
return _dlnaManager.GetProfile(request.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
|
||||||
public object Get(GetDefaultProfile request)
|
public object Get(GetDefaultProfile request)
|
||||||
{
|
{
|
||||||
return _dlnaManager.GetDefaultProfile();
|
return _dlnaManager.GetDefaultProfile();
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
namespace Emby.Dlna.Common
|
namespace Emby.Dlna.Common
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
namespace Emby.Dlna.Common
|
namespace Emby.Dlna.Common
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
namespace Emby.Dlna.Configuration
|
namespace Emby.Dlna.Configuration
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Emby.Dlna.Configuration;
|
using Emby.Dlna.Configuration;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Emby.Dlna.Service;
|
using Emby.Dlna.Service;
|
||||||
|
@ -16,7 +15,11 @@ namespace Emby.Dlna.ConnectionManager
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
|
|
||||||
public ConnectionManager(IDlnaManager dlna, IServerConfigurationManager config, ILogger logger, IHttpClient httpClient)
|
public ConnectionManager(
|
||||||
|
IDlnaManager dlna,
|
||||||
|
IServerConfigurationManager config,
|
||||||
|
ILogger<ConnectionManager> logger,
|
||||||
|
IHttpClient httpClient)
|
||||||
: base(logger, httpClient)
|
: base(logger, httpClient)
|
||||||
{
|
{
|
||||||
_dlna = dlna;
|
_dlna = dlna;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Emby.Dlna.Common;
|
using Emby.Dlna.Common;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Emby.Dlna.Common;
|
using Emby.Dlna.Common;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -38,7 +37,7 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
ILibraryManager libraryManager,
|
ILibraryManager libraryManager,
|
||||||
IServerConfigurationManager config,
|
IServerConfigurationManager config,
|
||||||
IUserManager userManager,
|
IUserManager userManager,
|
||||||
ILogger logger,
|
ILogger<ContentDirectory> logger,
|
||||||
IHttpClient httpClient,
|
IHttpClient httpClient,
|
||||||
ILocalizationManager localization,
|
ILocalizationManager localization,
|
||||||
IMediaSourceManager mediaSourceManager,
|
IMediaSourceManager mediaSourceManager,
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Emby.Dlna.Common;
|
using Emby.Dlna.Common;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -79,7 +78,18 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
_profile = profile;
|
_profile = profile;
|
||||||
_config = config;
|
_config = config;
|
||||||
|
|
||||||
_didlBuilder = new DidlBuilder(profile, user, imageProcessor, serverAddress, accessToken, userDataManager, localization, mediaSourceManager, Logger, mediaEncoder);
|
_didlBuilder = new DidlBuilder(
|
||||||
|
profile,
|
||||||
|
user,
|
||||||
|
imageProcessor,
|
||||||
|
serverAddress,
|
||||||
|
accessToken,
|
||||||
|
userDataManager,
|
||||||
|
localization,
|
||||||
|
mediaSourceManager,
|
||||||
|
Logger,
|
||||||
|
mediaEncoder,
|
||||||
|
libraryManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
@ -154,7 +164,7 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
{
|
{
|
||||||
var id = sparams["ObjectID"];
|
var id = sparams["ObjectID"];
|
||||||
|
|
||||||
var serverItem = GetItemFromObjectId(id, _user);
|
var serverItem = GetItemFromObjectId(id);
|
||||||
|
|
||||||
var item = serverItem.Item;
|
var item = serverItem.Item;
|
||||||
|
|
||||||
|
@ -277,7 +287,7 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
|
|
||||||
DidlBuilder.WriteXmlRootAttributes(_profile, writer);
|
DidlBuilder.WriteXmlRootAttributes(_profile, writer);
|
||||||
|
|
||||||
var serverItem = GetItemFromObjectId(id, _user);
|
var serverItem = GetItemFromObjectId(id);
|
||||||
var item = serverItem.Item;
|
var item = serverItem.Item;
|
||||||
|
|
||||||
|
|
||||||
|
@ -294,7 +304,7 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var dlnaOptions = _config.GetDlnaConfiguration();
|
var dlnaOptions = _config.GetDlnaConfiguration();
|
||||||
_didlBuilder.WriteItemElement(dlnaOptions, writer, item, _user, null, null, deviceId, filter);
|
_didlBuilder.WriteItemElement(writer, item, _user, null, null, deviceId, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
provided++;
|
provided++;
|
||||||
|
@ -321,7 +331,7 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_didlBuilder.WriteItemElement(dlnaOptions, writer, childItem, _user, item, serverItem.StubType, deviceId, filter);
|
_didlBuilder.WriteItemElement(writer, childItem, _user, item, serverItem.StubType, deviceId, filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -388,7 +398,7 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
|
|
||||||
DidlBuilder.WriteXmlRootAttributes(_profile, writer);
|
DidlBuilder.WriteXmlRootAttributes(_profile, writer);
|
||||||
|
|
||||||
var serverItem = GetItemFromObjectId(sparams["ContainerID"], _user);
|
var serverItem = GetItemFromObjectId(sparams["ContainerID"]);
|
||||||
|
|
||||||
var item = serverItem.Item;
|
var item = serverItem.Item;
|
||||||
|
|
||||||
|
@ -407,7 +417,7 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_didlBuilder.WriteItemElement(dlnaOptions, writer, i, _user, item, serverItem.StubType, deviceId, filter);
|
_didlBuilder.WriteItemElement(writer, i, _user, item, serverItem.StubType, deviceId, filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,11 +523,11 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
}
|
}
|
||||||
else if (string.Equals(CollectionType.Folders, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase))
|
else if (string.Equals(CollectionType.Folders, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return GetFolders(item, user, stubType, sort, startIndex, limit);
|
return GetFolders(user, startIndex, limit);
|
||||||
}
|
}
|
||||||
else if (string.Equals(CollectionType.LiveTv, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase))
|
else if (string.Equals(CollectionType.LiveTv, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return GetLiveTvChannels(item, user, stubType, sort, startIndex, limit);
|
return GetLiveTvChannels(user, sort, startIndex, limit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -548,7 +558,7 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
return ToResult(queryResult);
|
return ToResult(queryResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
private QueryResult<ServerItem> GetLiveTvChannels(BaseItem item, User user, StubType? stubType, SortCriteria sort, int? startIndex, int? limit)
|
private QueryResult<ServerItem> GetLiveTvChannels(User user, SortCriteria sort, int? startIndex, int? limit)
|
||||||
{
|
{
|
||||||
var query = new InternalItemsQuery(user)
|
var query = new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
|
@ -580,7 +590,7 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
|
|
||||||
if (stubType.HasValue && stubType.Value == StubType.Playlists)
|
if (stubType.HasValue && stubType.Value == StubType.Playlists)
|
||||||
{
|
{
|
||||||
return GetMusicPlaylists(item, user, query);
|
return GetMusicPlaylists(user, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stubType.HasValue && stubType.Value == StubType.Albums)
|
if (stubType.HasValue && stubType.Value == StubType.Albums)
|
||||||
|
@ -708,7 +718,7 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
|
|
||||||
if (stubType.HasValue && stubType.Value == StubType.Collections)
|
if (stubType.HasValue && stubType.Value == StubType.Collections)
|
||||||
{
|
{
|
||||||
return GetMovieCollections(item, user, query);
|
return GetMovieCollections(user, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stubType.HasValue && stubType.Value == StubType.Favorites)
|
if (stubType.HasValue && stubType.Value == StubType.Favorites)
|
||||||
|
@ -721,46 +731,42 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
return GetGenres(item, user, query);
|
return GetGenres(item, user, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
var list = new List<ServerItem>();
|
var array = new ServerItem[]
|
||||||
|
|
||||||
list.Add(new ServerItem(item)
|
|
||||||
{
|
{
|
||||||
StubType = StubType.ContinueWatching
|
new ServerItem(item)
|
||||||
});
|
{
|
||||||
|
StubType = StubType.ContinueWatching
|
||||||
list.Add(new ServerItem(item)
|
},
|
||||||
{
|
new ServerItem(item)
|
||||||
StubType = StubType.Latest
|
{
|
||||||
});
|
StubType = StubType.Latest
|
||||||
|
},
|
||||||
list.Add(new ServerItem(item)
|
new ServerItem(item)
|
||||||
{
|
{
|
||||||
StubType = StubType.Movies
|
StubType = StubType.Movies
|
||||||
});
|
},
|
||||||
|
new ServerItem(item)
|
||||||
list.Add(new ServerItem(item)
|
{
|
||||||
{
|
StubType = StubType.Collections
|
||||||
StubType = StubType.Collections
|
},
|
||||||
});
|
new ServerItem(item)
|
||||||
|
{
|
||||||
list.Add(new ServerItem(item)
|
StubType = StubType.Favorites
|
||||||
{
|
},
|
||||||
StubType = StubType.Favorites
|
new ServerItem(item)
|
||||||
});
|
{
|
||||||
|
StubType = StubType.Genres
|
||||||
list.Add(new ServerItem(item)
|
}
|
||||||
{
|
};
|
||||||
StubType = StubType.Genres
|
|
||||||
});
|
|
||||||
|
|
||||||
return new QueryResult<ServerItem>
|
return new QueryResult<ServerItem>
|
||||||
{
|
{
|
||||||
Items = list,
|
Items = array,
|
||||||
TotalRecordCount = list.Count
|
TotalRecordCount = array.Length
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private QueryResult<ServerItem> GetFolders(BaseItem item, User user, StubType? stubType, SortCriteria sort, int? startIndex, int? limit)
|
private QueryResult<ServerItem> GetFolders(User user, int? startIndex, int? limit)
|
||||||
{
|
{
|
||||||
var folders = _libraryManager.GetUserRootFolder().GetChildren(user, true)
|
var folders = _libraryManager.GetUserRootFolder().GetChildren(user, true)
|
||||||
.OrderBy(i => i.SortName)
|
.OrderBy(i => i.SortName)
|
||||||
|
@ -793,7 +799,7 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
|
|
||||||
if (stubType.HasValue && stubType.Value == StubType.NextUp)
|
if (stubType.HasValue && stubType.Value == StubType.NextUp)
|
||||||
{
|
{
|
||||||
return GetNextUp(item, user, query);
|
return GetNextUp(item, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stubType.HasValue && stubType.Value == StubType.Latest)
|
if (stubType.HasValue && stubType.Value == StubType.Latest)
|
||||||
|
@ -911,7 +917,7 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
return ToResult(result);
|
return ToResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private QueryResult<ServerItem> GetMovieCollections(BaseItem parent, User user, InternalItemsQuery query)
|
private QueryResult<ServerItem> GetMovieCollections(User user, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
query.Recursive = true;
|
query.Recursive = true;
|
||||||
//query.Parent = parent;
|
//query.Parent = parent;
|
||||||
|
@ -1106,7 +1112,7 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
return ToResult(result);
|
return ToResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private QueryResult<ServerItem> GetMusicPlaylists(BaseItem parent, User user, InternalItemsQuery query)
|
private QueryResult<ServerItem> GetMusicPlaylists(User user, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
query.Parent = null;
|
query.Parent = null;
|
||||||
query.IncludeItemTypes = new[] { typeof(Playlist).Name };
|
query.IncludeItemTypes = new[] { typeof(Playlist).Name };
|
||||||
|
@ -1135,7 +1141,7 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
return ToResult(items);
|
return ToResult(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
private QueryResult<ServerItem> GetNextUp(BaseItem parent, User user, InternalItemsQuery query)
|
private QueryResult<ServerItem> GetNextUp(BaseItem parent, InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
query.OrderBy = Array.Empty<(string, SortOrder)>();
|
query.OrderBy = Array.Empty<(string, SortOrder)>();
|
||||||
|
|
||||||
|
@ -1290,15 +1296,15 @@ namespace Emby.Dlna.ContentDirectory
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ServerItem GetItemFromObjectId(string id, User user)
|
private ServerItem GetItemFromObjectId(string id)
|
||||||
{
|
{
|
||||||
return DidlBuilder.IsIdRoot(id)
|
return DidlBuilder.IsIdRoot(id)
|
||||||
|
|
||||||
? new ServerItem(_libraryManager.GetUserRootFolder())
|
? new ServerItem(_libraryManager.GetUserRootFolder())
|
||||||
: ParseItemId(id, user);
|
: ParseItemId(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ServerItem ParseItemId(string id, User user)
|
private ServerItem ParseItemId(string id)
|
||||||
{
|
{
|
||||||
StubType? stubType = null;
|
StubType? stubType = null;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Emby.Dlna.Common;
|
using Emby.Dlna.Common;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
@ -46,6 +45,7 @@ namespace Emby.Dlna.Didl
|
||||||
private readonly IMediaSourceManager _mediaSourceManager;
|
private readonly IMediaSourceManager _mediaSourceManager;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IMediaEncoder _mediaEncoder;
|
private readonly IMediaEncoder _mediaEncoder;
|
||||||
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
|
||||||
public DidlBuilder(
|
public DidlBuilder(
|
||||||
DeviceProfile profile,
|
DeviceProfile profile,
|
||||||
|
@ -57,7 +57,8 @@ namespace Emby.Dlna.Didl
|
||||||
ILocalizationManager localization,
|
ILocalizationManager localization,
|
||||||
IMediaSourceManager mediaSourceManager,
|
IMediaSourceManager mediaSourceManager,
|
||||||
ILogger logger,
|
ILogger logger,
|
||||||
IMediaEncoder mediaEncoder)
|
IMediaEncoder mediaEncoder,
|
||||||
|
ILibraryManager libraryManager)
|
||||||
{
|
{
|
||||||
_profile = profile;
|
_profile = profile;
|
||||||
_user = user;
|
_user = user;
|
||||||
|
@ -69,6 +70,7 @@ namespace Emby.Dlna.Didl
|
||||||
_mediaSourceManager = mediaSourceManager;
|
_mediaSourceManager = mediaSourceManager;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_mediaEncoder = mediaEncoder;
|
_mediaEncoder = mediaEncoder;
|
||||||
|
_libraryManager = libraryManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string NormalizeDlnaMediaUrl(string url)
|
public static string NormalizeDlnaMediaUrl(string url)
|
||||||
|
@ -76,7 +78,7 @@ namespace Emby.Dlna.Didl
|
||||||
return url + "&dlnaheaders=true";
|
return url + "&dlnaheaders=true";
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetItemDidl(DlnaOptions options, BaseItem item, User user, BaseItem context, string deviceId, Filter filter, StreamInfo streamInfo)
|
public string GetItemDidl(BaseItem item, User user, BaseItem context, string deviceId, Filter filter, StreamInfo streamInfo)
|
||||||
{
|
{
|
||||||
var settings = new XmlWriterSettings
|
var settings = new XmlWriterSettings
|
||||||
{
|
{
|
||||||
|
@ -101,7 +103,7 @@ namespace Emby.Dlna.Didl
|
||||||
|
|
||||||
WriteXmlRootAttributes(_profile, writer);
|
WriteXmlRootAttributes(_profile, writer);
|
||||||
|
|
||||||
WriteItemElement(options, writer, item, user, context, null, deviceId, filter, streamInfo);
|
WriteItemElement(writer, item, user, context, null, deviceId, filter, streamInfo);
|
||||||
|
|
||||||
writer.WriteFullEndElement();
|
writer.WriteFullEndElement();
|
||||||
//writer.WriteEndDocument();
|
//writer.WriteEndDocument();
|
||||||
|
@ -128,7 +130,6 @@ namespace Emby.Dlna.Didl
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteItemElement(
|
public void WriteItemElement(
|
||||||
DlnaOptions options,
|
|
||||||
XmlWriter writer,
|
XmlWriter writer,
|
||||||
BaseItem item,
|
BaseItem item,
|
||||||
User user,
|
User user,
|
||||||
|
@ -165,25 +166,23 @@ namespace Emby.Dlna.Didl
|
||||||
// refID?
|
// refID?
|
||||||
// storeAttribute(itemNode, object, ClassProperties.REF_ID, false);
|
// storeAttribute(itemNode, object, ClassProperties.REF_ID, false);
|
||||||
|
|
||||||
var hasMediaSources = item as IHasMediaSources;
|
if (item is IHasMediaSources)
|
||||||
|
|
||||||
if (hasMediaSources != null)
|
|
||||||
{
|
{
|
||||||
if (string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
AddAudioResource(options, writer, item, deviceId, filter, streamInfo);
|
AddAudioResource(writer, item, deviceId, filter, streamInfo);
|
||||||
}
|
}
|
||||||
else if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase))
|
else if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
AddVideoResource(options, writer, item, deviceId, filter, streamInfo);
|
AddVideoResource(writer, item, deviceId, filter, streamInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AddCover(item, context, null, writer);
|
AddCover(item, null, writer);
|
||||||
writer.WriteFullEndElement();
|
writer.WriteFullEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddVideoResource(DlnaOptions options, XmlWriter writer, BaseItem video, string deviceId, Filter filter, StreamInfo streamInfo = null)
|
private void AddVideoResource(XmlWriter writer, BaseItem video, string deviceId, Filter filter, StreamInfo streamInfo = null)
|
||||||
{
|
{
|
||||||
if (streamInfo == null)
|
if (streamInfo == null)
|
||||||
{
|
{
|
||||||
|
@ -227,7 +226,7 @@ namespace Emby.Dlna.Didl
|
||||||
|
|
||||||
foreach (var contentFeature in contentFeatureList)
|
foreach (var contentFeature in contentFeatureList)
|
||||||
{
|
{
|
||||||
AddVideoResource(writer, video, deviceId, filter, contentFeature, streamInfo);
|
AddVideoResource(writer, filter, contentFeature, streamInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
var subtitleProfiles = streamInfo.GetSubtitleProfiles(_mediaEncoder, false, _serverAddress, _accessToken);
|
var subtitleProfiles = streamInfo.GetSubtitleProfiles(_mediaEncoder, false, _serverAddress, _accessToken);
|
||||||
|
@ -284,7 +283,10 @@ namespace Emby.Dlna.Didl
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
writer.WriteStartElement(string.Empty, "res", NS_DIDL);
|
writer.WriteStartElement(string.Empty, "res", NS_DIDL);
|
||||||
var protocolInfo = string.Format("http-get:*:text/{0}:*", info.Format.ToLowerInvariant());
|
var protocolInfo = string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
"http-get:*:text/{0}:*",
|
||||||
|
info.Format.ToLowerInvariant());
|
||||||
writer.WriteAttributeString("protocolInfo", protocolInfo);
|
writer.WriteAttributeString("protocolInfo", protocolInfo);
|
||||||
|
|
||||||
writer.WriteString(info.Url);
|
writer.WriteString(info.Url);
|
||||||
|
@ -294,7 +296,7 @@ namespace Emby.Dlna.Didl
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddVideoResource(XmlWriter writer, BaseItem video, string deviceId, Filter filter, string contentFeatures, StreamInfo streamInfo)
|
private void AddVideoResource(XmlWriter writer, Filter filter, string contentFeatures, StreamInfo streamInfo)
|
||||||
{
|
{
|
||||||
writer.WriteStartElement(string.Empty, "res", NS_DIDL);
|
writer.WriteStartElement(string.Empty, "res", NS_DIDL);
|
||||||
|
|
||||||
|
@ -336,7 +338,13 @@ namespace Emby.Dlna.Didl
|
||||||
{
|
{
|
||||||
if (targetWidth.HasValue && targetHeight.HasValue)
|
if (targetWidth.HasValue && targetHeight.HasValue)
|
||||||
{
|
{
|
||||||
writer.WriteAttributeString("resolution", string.Format("{0}x{1}", targetWidth.Value, targetHeight.Value));
|
writer.WriteAttributeString(
|
||||||
|
"resolution",
|
||||||
|
string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
"{0}x{1}",
|
||||||
|
targetWidth.Value,
|
||||||
|
targetHeight.Value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,17 +378,19 @@ namespace Emby.Dlna.Didl
|
||||||
streamInfo.TargetVideoCodecTag,
|
streamInfo.TargetVideoCodecTag,
|
||||||
streamInfo.IsTargetAVC);
|
streamInfo.IsTargetAVC);
|
||||||
|
|
||||||
var filename = url.Substring(0, url.IndexOf('?'));
|
var filename = url.Substring(0, url.IndexOf('?', StringComparison.Ordinal));
|
||||||
|
|
||||||
var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType)
|
var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType)
|
||||||
? MimeTypes.GetMimeType(filename)
|
? MimeTypes.GetMimeType(filename)
|
||||||
: mediaProfile.MimeType;
|
: mediaProfile.MimeType;
|
||||||
|
|
||||||
writer.WriteAttributeString("protocolInfo", string.Format(
|
writer.WriteAttributeString(
|
||||||
"http-get:*:{0}:{1}",
|
"protocolInfo",
|
||||||
mimeType,
|
string.Format(
|
||||||
contentFeatures
|
CultureInfo.InvariantCulture,
|
||||||
));
|
"http-get:*:{0}:{1}",
|
||||||
|
mimeType,
|
||||||
|
contentFeatures));
|
||||||
|
|
||||||
writer.WriteString(url);
|
writer.WriteString(url);
|
||||||
|
|
||||||
|
@ -393,24 +403,24 @@ namespace Emby.Dlna.Didl
|
||||||
{
|
{
|
||||||
switch (itemStubType.Value)
|
switch (itemStubType.Value)
|
||||||
{
|
{
|
||||||
case StubType.Latest: return _localization.GetLocalizedString("Latest");
|
case StubType.Latest: return _localization.GetLocalizedString("Latest");
|
||||||
case StubType.Playlists: return _localization.GetLocalizedString("Playlists");
|
case StubType.Playlists: return _localization.GetLocalizedString("Playlists");
|
||||||
case StubType.AlbumArtists: return _localization.GetLocalizedString("HeaderAlbumArtists");
|
case StubType.AlbumArtists: return _localization.GetLocalizedString("HeaderAlbumArtists");
|
||||||
case StubType.Albums: return _localization.GetLocalizedString("Albums");
|
case StubType.Albums: return _localization.GetLocalizedString("Albums");
|
||||||
case StubType.Artists: return _localization.GetLocalizedString("Artists");
|
case StubType.Artists: return _localization.GetLocalizedString("Artists");
|
||||||
case StubType.Songs: return _localization.GetLocalizedString("Songs");
|
case StubType.Songs: return _localization.GetLocalizedString("Songs");
|
||||||
case StubType.Genres: return _localization.GetLocalizedString("Genres");
|
case StubType.Genres: return _localization.GetLocalizedString("Genres");
|
||||||
case StubType.FavoriteAlbums: return _localization.GetLocalizedString("HeaderFavoriteAlbums");
|
case StubType.FavoriteAlbums: return _localization.GetLocalizedString("HeaderFavoriteAlbums");
|
||||||
case StubType.FavoriteArtists: return _localization.GetLocalizedString("HeaderFavoriteArtists");
|
case StubType.FavoriteArtists: return _localization.GetLocalizedString("HeaderFavoriteArtists");
|
||||||
case StubType.FavoriteSongs: return _localization.GetLocalizedString("HeaderFavoriteSongs");
|
case StubType.FavoriteSongs: return _localization.GetLocalizedString("HeaderFavoriteSongs");
|
||||||
case StubType.ContinueWatching: return _localization.GetLocalizedString("HeaderContinueWatching");
|
case StubType.ContinueWatching: return _localization.GetLocalizedString("HeaderContinueWatching");
|
||||||
case StubType.Movies: return _localization.GetLocalizedString("Movies");
|
case StubType.Movies: return _localization.GetLocalizedString("Movies");
|
||||||
case StubType.Collections: return _localization.GetLocalizedString("Collections");
|
case StubType.Collections: return _localization.GetLocalizedString("Collections");
|
||||||
case StubType.Favorites: return _localization.GetLocalizedString("Favorites");
|
case StubType.Favorites: return _localization.GetLocalizedString("Favorites");
|
||||||
case StubType.NextUp: return _localization.GetLocalizedString("HeaderNextUp");
|
case StubType.NextUp: return _localization.GetLocalizedString("HeaderNextUp");
|
||||||
case StubType.FavoriteSeries: return _localization.GetLocalizedString("HeaderFavoriteShows");
|
case StubType.FavoriteSeries: return _localization.GetLocalizedString("HeaderFavoriteShows");
|
||||||
case StubType.FavoriteEpisodes: return _localization.GetLocalizedString("HeaderFavoriteEpisodes");
|
case StubType.FavoriteEpisodes: return _localization.GetLocalizedString("HeaderFavoriteEpisodes");
|
||||||
case StubType.Series: return _localization.GetLocalizedString("Shows");
|
case StubType.Series: return _localization.GetLocalizedString("Shows");
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -421,7 +431,10 @@ namespace Emby.Dlna.Didl
|
||||||
if (item.ParentIndexNumber.HasValue && item.ParentIndexNumber.Value == 0
|
if (item.ParentIndexNumber.HasValue && item.ParentIndexNumber.Value == 0
|
||||||
&& season.IndexNumber.HasValue && season.IndexNumber.Value != 0)
|
&& season.IndexNumber.HasValue && season.IndexNumber.Value != 0)
|
||||||
{
|
{
|
||||||
return string.Format(_localization.GetLocalizedString("ValueSpecialEpisodeName"), item.Name);
|
return string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
_localization.GetLocalizedString("ValueSpecialEpisodeName"),
|
||||||
|
item.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.IndexNumber.HasValue)
|
if (item.IndexNumber.HasValue)
|
||||||
|
@ -436,11 +449,34 @@ namespace Emby.Dlna.Didl
|
||||||
return number + " - " + item.Name;
|
return number + " - " + item.Name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (item is Episode ep)
|
||||||
|
{
|
||||||
|
var parent = ep.GetParent();
|
||||||
|
var name = parent.Name + " - ";
|
||||||
|
|
||||||
|
if (ep.ParentIndexNumber.HasValue)
|
||||||
|
{
|
||||||
|
name += "S" + ep.ParentIndexNumber.Value.ToString("00", CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
else if (!item.IndexNumber.HasValue)
|
||||||
|
{
|
||||||
|
return name + " - " + item.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
name += "E" + ep.IndexNumber.Value.ToString("00", CultureInfo.InvariantCulture);
|
||||||
|
if (ep.IndexNumberEnd.HasValue)
|
||||||
|
{
|
||||||
|
name += "-" + ep.IndexNumberEnd.Value.ToString("00", CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
name += " - " + item.Name;
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
return item.Name;
|
return item.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddAudioResource(DlnaOptions options, XmlWriter writer, BaseItem audio, string deviceId, Filter filter, StreamInfo streamInfo = null)
|
private void AddAudioResource(XmlWriter writer, BaseItem audio, string deviceId, Filter filter, StreamInfo streamInfo = null)
|
||||||
{
|
{
|
||||||
writer.WriteStartElement(string.Empty, "res", NS_DIDL);
|
writer.WriteStartElement(string.Empty, "res", NS_DIDL);
|
||||||
|
|
||||||
|
@ -506,7 +542,7 @@ namespace Emby.Dlna.Didl
|
||||||
targetSampleRate,
|
targetSampleRate,
|
||||||
targetAudioBitDepth);
|
targetAudioBitDepth);
|
||||||
|
|
||||||
var filename = url.Substring(0, url.IndexOf('?'));
|
var filename = url.Substring(0, url.IndexOf('?', StringComparison.Ordinal));
|
||||||
|
|
||||||
var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType)
|
var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType)
|
||||||
? MimeTypes.GetMimeType(filename)
|
? MimeTypes.GetMimeType(filename)
|
||||||
|
@ -522,11 +558,13 @@ namespace Emby.Dlna.Didl
|
||||||
streamInfo.RunTimeTicks ?? 0,
|
streamInfo.RunTimeTicks ?? 0,
|
||||||
streamInfo.TranscodeSeekInfo);
|
streamInfo.TranscodeSeekInfo);
|
||||||
|
|
||||||
writer.WriteAttributeString("protocolInfo", string.Format(
|
writer.WriteAttributeString(
|
||||||
"http-get:*:{0}:{1}",
|
"protocolInfo",
|
||||||
mimeType,
|
string.Format(
|
||||||
contentFeatures
|
CultureInfo.InvariantCulture,
|
||||||
));
|
"http-get:*:{0}:{1}",
|
||||||
|
mimeType,
|
||||||
|
contentFeatures));
|
||||||
|
|
||||||
writer.WriteString(url);
|
writer.WriteString(url);
|
||||||
|
|
||||||
|
@ -549,7 +587,7 @@ namespace Emby.Dlna.Didl
|
||||||
|
|
||||||
var clientId = GetClientId(folder, stubType);
|
var clientId = GetClientId(folder, stubType);
|
||||||
|
|
||||||
if (string.Equals(requestedId, "0"))
|
if (string.Equals(requestedId, "0", StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
writer.WriteAttributeString("id", "0");
|
writer.WriteAttributeString("id", "0");
|
||||||
writer.WriteAttributeString("parentID", "-1");
|
writer.WriteAttributeString("parentID", "-1");
|
||||||
|
@ -578,7 +616,7 @@ namespace Emby.Dlna.Didl
|
||||||
|
|
||||||
AddGeneralProperties(folder, stubType, context, writer, filter);
|
AddGeneralProperties(folder, stubType, context, writer, filter);
|
||||||
|
|
||||||
AddCover(folder, context, stubType, writer);
|
AddCover(folder, stubType, writer);
|
||||||
|
|
||||||
writer.WriteFullEndElement();
|
writer.WriteFullEndElement();
|
||||||
}
|
}
|
||||||
|
@ -611,7 +649,10 @@ namespace Emby.Dlna.Didl
|
||||||
|
|
||||||
if (playbackPositionTicks > 0)
|
if (playbackPositionTicks > 0)
|
||||||
{
|
{
|
||||||
var elementValue = string.Format("BM={0}", Convert.ToInt32(TimeSpan.FromTicks(playbackPositionTicks).TotalSeconds).ToString(_usCulture));
|
var elementValue = string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
"BM={0}",
|
||||||
|
Convert.ToInt32(TimeSpan.FromTicks(playbackPositionTicks).TotalSeconds));
|
||||||
AddValue(writer, "sec", "dcmInfo", elementValue, secAttribute.Value);
|
AddValue(writer, "sec", "dcmInfo", elementValue, secAttribute.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -764,37 +805,36 @@ namespace Emby.Dlna.Didl
|
||||||
|
|
||||||
private void AddPeople(BaseItem item, XmlWriter writer)
|
private void AddPeople(BaseItem item, XmlWriter writer)
|
||||||
{
|
{
|
||||||
//var types = new[]
|
if (!item.SupportsPeople)
|
||||||
//{
|
{
|
||||||
// PersonType.Director,
|
return;
|
||||||
// PersonType.Writer,
|
}
|
||||||
// PersonType.Producer,
|
|
||||||
// PersonType.Composer,
|
|
||||||
// "Creator"
|
|
||||||
//};
|
|
||||||
|
|
||||||
//var people = _libraryManager.GetPeople(item);
|
var types = new[]
|
||||||
|
{
|
||||||
|
PersonType.Director,
|
||||||
|
PersonType.Writer,
|
||||||
|
PersonType.Producer,
|
||||||
|
PersonType.Composer,
|
||||||
|
"creator"
|
||||||
|
};
|
||||||
|
|
||||||
//var index = 0;
|
// Seeing some LG models locking up due content with large lists of people
|
||||||
|
// The actual issue might just be due to processing a more metadata than it can handle
|
||||||
|
var people = _libraryManager.GetPeople(
|
||||||
|
new InternalPeopleQuery
|
||||||
|
{
|
||||||
|
ItemId = item.Id,
|
||||||
|
Limit = 6
|
||||||
|
});
|
||||||
|
|
||||||
//// Seeing some LG models locking up due content with large lists of people
|
foreach (var actor in people)
|
||||||
//// The actual issue might just be due to processing a more metadata than it can handle
|
{
|
||||||
//var limit = 6;
|
var type = types.FirstOrDefault(i => string.Equals(i, actor.Type, StringComparison.OrdinalIgnoreCase) || string.Equals(i, actor.Role, StringComparison.OrdinalIgnoreCase))
|
||||||
|
?? PersonType.Actor;
|
||||||
|
|
||||||
//foreach (var actor in people)
|
AddValue(writer, "upnp", type.ToLowerInvariant(), actor.Name, NS_UPNP);
|
||||||
//{
|
}
|
||||||
// var type = types.FirstOrDefault(i => string.Equals(i, actor.Type, StringComparison.OrdinalIgnoreCase) || string.Equals(i, actor.Role, StringComparison.OrdinalIgnoreCase))
|
|
||||||
// ?? PersonType.Actor;
|
|
||||||
|
|
||||||
// AddValue(writer, "upnp", type.ToLowerInvariant(), actor.Name, NS_UPNP);
|
|
||||||
|
|
||||||
// index++;
|
|
||||||
|
|
||||||
// if (index >= limit)
|
|
||||||
// {
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddGeneralProperties(BaseItem item, StubType? itemStubType, BaseItem context, XmlWriter writer, Filter filter)
|
private void AddGeneralProperties(BaseItem item, StubType? itemStubType, BaseItem context, XmlWriter writer, Filter filter)
|
||||||
|
@ -871,7 +911,7 @@ namespace Emby.Dlna.Didl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddCover(BaseItem item, BaseItem context, StubType? stubType, XmlWriter writer)
|
private void AddCover(BaseItem item, StubType? stubType, XmlWriter writer)
|
||||||
{
|
{
|
||||||
ImageDownloadInfo imageInfo = GetImageInfo(item);
|
ImageDownloadInfo imageInfo = GetImageInfo(item);
|
||||||
|
|
||||||
|
@ -916,17 +956,8 @@ namespace Emby.Dlna.Didl
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddEmbeddedImageAsCover(string name, XmlWriter writer)
|
private void AddImageResElement(
|
||||||
{
|
BaseItem item,
|
||||||
writer.WriteStartElement("upnp", "albumArtURI", NS_UPNP);
|
|
||||||
writer.WriteAttributeString("dlna", "profileID", NS_DLNA, _profile.AlbumArtPn);
|
|
||||||
writer.WriteString(_serverAddress + "/Dlna/icons/people480.jpg");
|
|
||||||
writer.WriteFullEndElement();
|
|
||||||
|
|
||||||
writer.WriteElementString("upnp", "icon", NS_UPNP, _serverAddress + "/Dlna/icons/people48.jpg");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddImageResElement(BaseItem item,
|
|
||||||
XmlWriter writer,
|
XmlWriter writer,
|
||||||
int maxWidth,
|
int maxWidth,
|
||||||
int maxHeight,
|
int maxHeight,
|
||||||
|
@ -952,13 +983,17 @@ namespace Emby.Dlna.Didl
|
||||||
var contentFeatures = new ContentFeatureBuilder(_profile)
|
var contentFeatures = new ContentFeatureBuilder(_profile)
|
||||||
.BuildImageHeader(format, width, height, imageInfo.IsDirectStream, org_Pn);
|
.BuildImageHeader(format, width, height, imageInfo.IsDirectStream, org_Pn);
|
||||||
|
|
||||||
writer.WriteAttributeString("protocolInfo", string.Format(
|
writer.WriteAttributeString(
|
||||||
"http-get:*:{0}:{1}",
|
"protocolInfo",
|
||||||
MimeTypes.GetMimeType("file." + format),
|
string.Format(
|
||||||
contentFeatures
|
CultureInfo.InvariantCulture,
|
||||||
));
|
"http-get:*:{0}:{1}",
|
||||||
|
MimeTypes.GetMimeType("file." + format),
|
||||||
|
contentFeatures));
|
||||||
|
|
||||||
writer.WriteAttributeString("resolution", string.Format("{0}x{1}", width, height));
|
writer.WriteAttributeString(
|
||||||
|
"resolution",
|
||||||
|
string.Format(CultureInfo.InvariantCulture, "{0}x{1}", width, height));
|
||||||
|
|
||||||
writer.WriteString(albumartUrlInfo.Url);
|
writer.WriteString(albumartUrlInfo.Url);
|
||||||
|
|
||||||
|
@ -1097,7 +1132,9 @@ namespace Emby.Dlna.Didl
|
||||||
|
|
||||||
private ImageUrlInfo GetImageUrl(ImageDownloadInfo info, int maxWidth, int maxHeight, string format)
|
private ImageUrlInfo GetImageUrl(ImageDownloadInfo info, int maxWidth, int maxHeight, string format)
|
||||||
{
|
{
|
||||||
var url = string.Format("{0}/Items/{1}/Images/{2}/0/{3}/{4}/{5}/{6}/0/0",
|
var url = string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
"{0}/Items/{1}/Images/{2}/0/{3}/{4}/{5}/{6}/0/0",
|
||||||
_serverAddress,
|
_serverAddress,
|
||||||
info.ItemId.ToString("N", CultureInfo.InvariantCulture),
|
info.ItemId.ToString("N", CultureInfo.InvariantCulture),
|
||||||
info.Type,
|
info.Type,
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using MediaBrowser.Model.Extensions;
|
|
||||||
|
|
||||||
namespace Emby.Dlna.Didl
|
namespace Emby.Dlna.Didl
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
@ -54,6 +53,6 @@ namespace Emby.Dlna.Didl
|
||||||
_encoding = encoding;
|
_encoding = encoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Encoding Encoding => (null == _encoding) ? base.Encoding : _encoding;
|
public override Encoding Encoding => _encoding ?? base.Encoding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
namespace Emby.Dlna
|
namespace Emby.Dlna
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
namespace Emby.Dlna
|
namespace Emby.Dlna
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
namespace Emby.Dlna
|
namespace Emby.Dlna
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
namespace Emby.Dlna
|
namespace Emby.Dlna
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Net.Sockets;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Emby.Dlna.PlayTo;
|
using Emby.Dlna.PlayTo;
|
||||||
|
@ -27,7 +26,7 @@ using MediaBrowser.Model.System;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Rssdp;
|
using Rssdp;
|
||||||
using Rssdp.Infrastructure;
|
using Rssdp.Infrastructure;
|
||||||
using OperatingSystem = MediaBrowser.Common.System.OperatingSystem;
|
using OperatingSystem = MediaBrowser.Common.System.OperatingSystem;
|
||||||
|
|
||||||
namespace Emby.Dlna.Main
|
namespace Emby.Dlna.Main
|
||||||
{
|
{
|
||||||
|
@ -59,7 +58,9 @@ namespace Emby.Dlna.Main
|
||||||
private ISsdpCommunicationsServer _communicationsServer;
|
private ISsdpCommunicationsServer _communicationsServer;
|
||||||
|
|
||||||
internal IContentDirectory ContentDirectory { get; private set; }
|
internal IContentDirectory ContentDirectory { get; private set; }
|
||||||
|
|
||||||
internal IConnectionManager ConnectionManager { get; private set; }
|
internal IConnectionManager ConnectionManager { get; private set; }
|
||||||
|
|
||||||
internal IMediaReceiverRegistrar MediaReceiverRegistrar { get; private set; }
|
internal IMediaReceiverRegistrar MediaReceiverRegistrar { get; private set; }
|
||||||
|
|
||||||
public static DlnaEntryPoint Current;
|
public static DlnaEntryPoint Current;
|
||||||
|
@ -107,7 +108,7 @@ namespace Emby.Dlna.Main
|
||||||
libraryManager,
|
libraryManager,
|
||||||
config,
|
config,
|
||||||
userManager,
|
userManager,
|
||||||
_logger,
|
loggerFactory.CreateLogger<ContentDirectory.ContentDirectory>(),
|
||||||
httpClient,
|
httpClient,
|
||||||
localizationManager,
|
localizationManager,
|
||||||
mediaSourceManager,
|
mediaSourceManager,
|
||||||
|
@ -115,9 +116,16 @@ namespace Emby.Dlna.Main
|
||||||
mediaEncoder,
|
mediaEncoder,
|
||||||
tvSeriesManager);
|
tvSeriesManager);
|
||||||
|
|
||||||
ConnectionManager = new ConnectionManager.ConnectionManager(dlnaManager, config, _logger, httpClient);
|
ConnectionManager = new ConnectionManager.ConnectionManager(
|
||||||
|
dlnaManager,
|
||||||
|
config,
|
||||||
|
loggerFactory.CreateLogger<ConnectionManager.ConnectionManager>(),
|
||||||
|
httpClient);
|
||||||
|
|
||||||
MediaReceiverRegistrar = new MediaReceiverRegistrar.MediaReceiverRegistrar(_logger, httpClient, config);
|
MediaReceiverRegistrar = new MediaReceiverRegistrar.MediaReceiverRegistrar(
|
||||||
|
loggerFactory.CreateLogger<MediaReceiverRegistrar.MediaReceiverRegistrar>(),
|
||||||
|
httpClient,
|
||||||
|
config);
|
||||||
Current = this;
|
Current = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,8 +262,8 @@ namespace Emby.Dlna.Main
|
||||||
{
|
{
|
||||||
if (address.AddressFamily == AddressFamily.InterNetworkV6)
|
if (address.AddressFamily == AddressFamily.InterNetworkV6)
|
||||||
{
|
{
|
||||||
// Not support IPv6 right now
|
// Not supporting IPv6 right now
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var fullService = "urn:schemas-upnp-org:device:MediaServer:1";
|
var fullService = "urn:schemas-upnp-org:device:MediaServer:1";
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Emby.Dlna.Service;
|
using Emby.Dlna.Service;
|
||||||
|
@ -13,7 +12,10 @@ namespace Emby.Dlna.MediaReceiverRegistrar
|
||||||
{
|
{
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
|
|
||||||
public MediaReceiverRegistrar(ILogger logger, IHttpClient httpClient, IServerConfigurationManager config)
|
public MediaReceiverRegistrar(
|
||||||
|
ILogger<MediaReceiverRegistrar> logger,
|
||||||
|
IHttpClient httpClient,
|
||||||
|
IServerConfigurationManager config)
|
||||||
: base(logger, httpClient)
|
: base(logger, httpClient)
|
||||||
{
|
{
|
||||||
_config = config;
|
_config = config;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Emby.Dlna.Common;
|
using Emby.Dlna.Common;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Emby.Dlna.Common;
|
using Emby.Dlna.Common;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -347,7 +346,12 @@ namespace Emby.Dlna.PlayTo
|
||||||
throw new InvalidOperationException("Unable to find service");
|
throw new InvalidOperationException("Unable to find service");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, 1));
|
return new SsdpHttpClient(_httpClient).SendCommandAsync(
|
||||||
|
Properties.BaseUrl,
|
||||||
|
service,
|
||||||
|
command.Name,
|
||||||
|
avCommands.BuildPost(command, service.ServiceType, 1),
|
||||||
|
cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SetPlay(CancellationToken cancellationToken)
|
public async Task SetPlay(CancellationToken cancellationToken)
|
||||||
|
@ -516,8 +520,12 @@ namespace Emby.Dlna.PlayTo
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType), true)
|
var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(
|
||||||
.ConfigureAwait(false);
|
Properties.BaseUrl,
|
||||||
|
service,
|
||||||
|
command.Name,
|
||||||
|
rendererCommands.BuildPost(command, service.ServiceType),
|
||||||
|
cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (result == null || result.Document == null)
|
if (result == null || result.Document == null)
|
||||||
{
|
{
|
||||||
|
@ -562,8 +570,12 @@ namespace Emby.Dlna.PlayTo
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType), true)
|
var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(
|
||||||
.ConfigureAwait(false);
|
Properties.BaseUrl,
|
||||||
|
service,
|
||||||
|
command.Name,
|
||||||
|
rendererCommands.BuildPost(command, service.ServiceType),
|
||||||
|
cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (result == null || result.Document == null)
|
if (result == null || result.Document == null)
|
||||||
return;
|
return;
|
||||||
|
@ -589,8 +601,12 @@ namespace Emby.Dlna.PlayTo
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType), false)
|
var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(
|
||||||
.ConfigureAwait(false);
|
Properties.BaseUrl,
|
||||||
|
service,
|
||||||
|
command.Name,
|
||||||
|
avCommands.BuildPost(command, service.ServiceType),
|
||||||
|
cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (result == null || result.Document == null)
|
if (result == null || result.Document == null)
|
||||||
{
|
{
|
||||||
|
@ -600,7 +616,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
var transportState =
|
var transportState =
|
||||||
result.Document.Descendants(uPnpNamespaces.AvTransport + "GetTransportInfoResponse").Select(i => i.Element("CurrentTransportState")).FirstOrDefault(i => i != null);
|
result.Document.Descendants(uPnpNamespaces.AvTransport + "GetTransportInfoResponse").Select(i => i.Element("CurrentTransportState")).FirstOrDefault(i => i != null);
|
||||||
|
|
||||||
var transportStateValue = transportState == null ? null : transportState.Value;
|
var transportStateValue = transportState?.Value;
|
||||||
|
|
||||||
if (transportStateValue != null
|
if (transportStateValue != null
|
||||||
&& Enum.TryParse(transportStateValue, true, out TRANSPORTSTATE state))
|
&& Enum.TryParse(transportStateValue, true, out TRANSPORTSTATE state))
|
||||||
|
@ -627,8 +643,12 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
|
var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType), false)
|
var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(
|
||||||
.ConfigureAwait(false);
|
Properties.BaseUrl,
|
||||||
|
service,
|
||||||
|
command.Name,
|
||||||
|
rendererCommands.BuildPost(command, service.ServiceType),
|
||||||
|
cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (result == null || result.Document == null)
|
if (result == null || result.Document == null)
|
||||||
{
|
{
|
||||||
|
@ -690,8 +710,12 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
|
var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType), false)
|
var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(
|
||||||
.ConfigureAwait(false);
|
Properties.BaseUrl,
|
||||||
|
service,
|
||||||
|
command.Name,
|
||||||
|
rendererCommands.BuildPost(command, service.ServiceType),
|
||||||
|
cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (result == null || result.Document == null)
|
if (result == null || result.Document == null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Emby.Dlna.Common;
|
using Emby.Dlna.Common;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -28,6 +27,8 @@ namespace Emby.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
public class PlayToController : ISessionController, IDisposable
|
public class PlayToController : ISessionController, IDisposable
|
||||||
{
|
{
|
||||||
|
private static readonly CultureInfo _usCulture = CultureInfo.ReadOnly(new CultureInfo("en-US"));
|
||||||
|
|
||||||
private Device _device;
|
private Device _device;
|
||||||
private readonly SessionInfo _session;
|
private readonly SessionInfo _session;
|
||||||
private readonly ISessionManager _sessionManager;
|
private readonly ISessionManager _sessionManager;
|
||||||
|
@ -46,9 +47,10 @@ namespace Emby.Dlna.PlayTo
|
||||||
private readonly string _serverAddress;
|
private readonly string _serverAddress;
|
||||||
private readonly string _accessToken;
|
private readonly string _accessToken;
|
||||||
|
|
||||||
public bool IsSessionActive => !_disposed && _device != null;
|
private readonly List<PlaylistItem> _playlist = new List<PlaylistItem>();
|
||||||
|
private int _currentPlaylistIndex;
|
||||||
|
|
||||||
public bool SupportsMediaControl => IsSessionActive;
|
private bool _disposed;
|
||||||
|
|
||||||
public PlayToController(
|
public PlayToController(
|
||||||
SessionInfo session,
|
SessionInfo session,
|
||||||
|
@ -84,18 +86,22 @@ namespace Emby.Dlna.PlayTo
|
||||||
_mediaEncoder = mediaEncoder;
|
_mediaEncoder = mediaEncoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsSessionActive => !_disposed && _device != null;
|
||||||
|
|
||||||
|
public bool SupportsMediaControl => IsSessionActive;
|
||||||
|
|
||||||
public void Init(Device device)
|
public void Init(Device device)
|
||||||
{
|
{
|
||||||
_device = device;
|
_device = device;
|
||||||
_device.OnDeviceUnavailable = OnDeviceUnavailable;
|
_device.OnDeviceUnavailable = OnDeviceUnavailable;
|
||||||
_device.PlaybackStart += _device_PlaybackStart;
|
_device.PlaybackStart += OnDevicePlaybackStart;
|
||||||
_device.PlaybackProgress += _device_PlaybackProgress;
|
_device.PlaybackProgress += OnDevicePlaybackProgress;
|
||||||
_device.PlaybackStopped += _device_PlaybackStopped;
|
_device.PlaybackStopped += OnDevicePlaybackStopped;
|
||||||
_device.MediaChanged += _device_MediaChanged;
|
_device.MediaChanged += OnDeviceMediaChanged;
|
||||||
|
|
||||||
_device.Start();
|
_device.Start();
|
||||||
|
|
||||||
_deviceDiscovery.DeviceLeft += _deviceDiscovery_DeviceLeft;
|
_deviceDiscovery.DeviceLeft += OnDeviceDiscoveryDeviceLeft;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDeviceUnavailable()
|
private void OnDeviceUnavailable()
|
||||||
|
@ -111,7 +117,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _deviceDiscovery_DeviceLeft(object sender, GenericEventArgs<UpnpDeviceInfo> e)
|
private void OnDeviceDiscoveryDeviceLeft(object sender, GenericEventArgs<UpnpDeviceInfo> e)
|
||||||
{
|
{
|
||||||
var info = e.Argument;
|
var info = e.Argument;
|
||||||
|
|
||||||
|
@ -126,7 +132,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async void _device_MediaChanged(object sender, MediaChangedEventArgs e)
|
private async void OnDeviceMediaChanged(object sender, MediaChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
{
|
{
|
||||||
|
@ -138,15 +144,15 @@ namespace Emby.Dlna.PlayTo
|
||||||
var streamInfo = StreamParams.ParseFromUrl(e.OldMediaInfo.Url, _libraryManager, _mediaSourceManager);
|
var streamInfo = StreamParams.ParseFromUrl(e.OldMediaInfo.Url, _libraryManager, _mediaSourceManager);
|
||||||
if (streamInfo.Item != null)
|
if (streamInfo.Item != null)
|
||||||
{
|
{
|
||||||
var positionTicks = GetProgressPositionTicks(e.OldMediaInfo, streamInfo);
|
var positionTicks = GetProgressPositionTicks(streamInfo);
|
||||||
|
|
||||||
ReportPlaybackStopped(e.OldMediaInfo, streamInfo, positionTicks);
|
ReportPlaybackStopped(streamInfo, positionTicks);
|
||||||
}
|
}
|
||||||
|
|
||||||
streamInfo = StreamParams.ParseFromUrl(e.NewMediaInfo.Url, _libraryManager, _mediaSourceManager);
|
streamInfo = StreamParams.ParseFromUrl(e.NewMediaInfo.Url, _libraryManager, _mediaSourceManager);
|
||||||
if (streamInfo.Item == null) return;
|
if (streamInfo.Item == null) return;
|
||||||
|
|
||||||
var newItemProgress = GetProgressInfo(e.NewMediaInfo, streamInfo);
|
var newItemProgress = GetProgressInfo(streamInfo);
|
||||||
|
|
||||||
await _sessionManager.OnPlaybackStart(newItemProgress).ConfigureAwait(false);
|
await _sessionManager.OnPlaybackStart(newItemProgress).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
@ -156,7 +162,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async void _device_PlaybackStopped(object sender, PlaybackStoppedEventArgs e)
|
private async void OnDevicePlaybackStopped(object sender, PlaybackStoppedEventArgs e)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
{
|
{
|
||||||
|
@ -169,9 +175,9 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
if (streamInfo.Item == null) return;
|
if (streamInfo.Item == null) return;
|
||||||
|
|
||||||
var positionTicks = GetProgressPositionTicks(e.MediaInfo, streamInfo);
|
var positionTicks = GetProgressPositionTicks(streamInfo);
|
||||||
|
|
||||||
ReportPlaybackStopped(e.MediaInfo, streamInfo, positionTicks);
|
ReportPlaybackStopped(streamInfo, positionTicks);
|
||||||
|
|
||||||
var mediaSource = await streamInfo.GetMediaSource(CancellationToken.None).ConfigureAwait(false);
|
var mediaSource = await streamInfo.GetMediaSource(CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
|
@ -195,7 +201,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Playlist.Clear();
|
_playlist.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -204,7 +210,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void ReportPlaybackStopped(uBaseObject mediaInfo, StreamParams streamInfo, long? positionTicks)
|
private async void ReportPlaybackStopped(StreamParams streamInfo, long? positionTicks)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -223,7 +229,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async void _device_PlaybackStart(object sender, PlaybackStartEventArgs e)
|
private async void OnDevicePlaybackStart(object sender, PlaybackStartEventArgs e)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
{
|
{
|
||||||
|
@ -236,7 +242,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
if (info.Item != null)
|
if (info.Item != null)
|
||||||
{
|
{
|
||||||
var progress = GetProgressInfo(e.MediaInfo, info);
|
var progress = GetProgressInfo(info);
|
||||||
|
|
||||||
await _sessionManager.OnPlaybackStart(progress).ConfigureAwait(false);
|
await _sessionManager.OnPlaybackStart(progress).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
@ -247,7 +253,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async void _device_PlaybackProgress(object sender, PlaybackProgressEventArgs e)
|
private async void OnDevicePlaybackProgress(object sender, PlaybackProgressEventArgs e)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
{
|
{
|
||||||
|
@ -267,7 +273,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
if (info.Item != null)
|
if (info.Item != null)
|
||||||
{
|
{
|
||||||
var progress = GetProgressInfo(e.MediaInfo, info);
|
var progress = GetProgressInfo(info);
|
||||||
|
|
||||||
await _sessionManager.OnPlaybackProgress(progress).ConfigureAwait(false);
|
await _sessionManager.OnPlaybackProgress(progress).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
@ -278,7 +284,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private long? GetProgressPositionTicks(uBaseObject mediaInfo, StreamParams info)
|
private long? GetProgressPositionTicks(StreamParams info)
|
||||||
{
|
{
|
||||||
var ticks = _device.Position.Ticks;
|
var ticks = _device.Position.Ticks;
|
||||||
|
|
||||||
|
@ -290,13 +296,13 @@ namespace Emby.Dlna.PlayTo
|
||||||
return ticks;
|
return ticks;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PlaybackStartInfo GetProgressInfo(uBaseObject mediaInfo, StreamParams info)
|
private PlaybackStartInfo GetProgressInfo(StreamParams info)
|
||||||
{
|
{
|
||||||
return new PlaybackStartInfo
|
return new PlaybackStartInfo
|
||||||
{
|
{
|
||||||
ItemId = info.ItemId,
|
ItemId = info.ItemId,
|
||||||
SessionId = _session.Id,
|
SessionId = _session.Id,
|
||||||
PositionTicks = GetProgressPositionTicks(mediaInfo, info),
|
PositionTicks = GetProgressPositionTicks(info),
|
||||||
IsMuted = _device.IsMuted,
|
IsMuted = _device.IsMuted,
|
||||||
IsPaused = _device.IsPaused,
|
IsPaused = _device.IsPaused,
|
||||||
MediaSourceId = info.MediaSourceId,
|
MediaSourceId = info.MediaSourceId,
|
||||||
|
@ -311,9 +317,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#region SendCommands
|
public Task SendPlayCommand(PlayRequest command, CancellationToken cancellationToken)
|
||||||
|
|
||||||
public async Task SendPlayCommand(PlayRequest command, CancellationToken cancellationToken)
|
|
||||||
{
|
{
|
||||||
_logger.LogDebug("{0} - Received PlayRequest: {1}", this._session.DeviceName, command.PlayCommand);
|
_logger.LogDebug("{0} - Received PlayRequest: {1}", this._session.DeviceName, command.PlayCommand);
|
||||||
|
|
||||||
|
@ -351,11 +355,12 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
if (command.PlayCommand == PlayCommand.PlayLast)
|
if (command.PlayCommand == PlayCommand.PlayLast)
|
||||||
{
|
{
|
||||||
Playlist.AddRange(playlist);
|
_playlist.AddRange(playlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command.PlayCommand == PlayCommand.PlayNext)
|
if (command.PlayCommand == PlayCommand.PlayNext)
|
||||||
{
|
{
|
||||||
Playlist.AddRange(playlist);
|
_playlist.AddRange(playlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!command.ControllingUserId.Equals(Guid.Empty))
|
if (!command.ControllingUserId.Equals(Guid.Empty))
|
||||||
|
@ -364,7 +369,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
_session.DeviceName, _session.RemoteEndPoint, user);
|
_session.DeviceName, _session.RemoteEndPoint, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
await PlayItems(playlist).ConfigureAwait(false);
|
return PlayItems(playlist, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task SendPlaystateCommand(PlaystateRequest command, CancellationToken cancellationToken)
|
private Task SendPlaystateCommand(PlaystateRequest command, CancellationToken cancellationToken)
|
||||||
|
@ -372,7 +377,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
switch (command.Command)
|
switch (command.Command)
|
||||||
{
|
{
|
||||||
case PlaystateCommand.Stop:
|
case PlaystateCommand.Stop:
|
||||||
Playlist.Clear();
|
_playlist.Clear();
|
||||||
return _device.SetStop(CancellationToken.None);
|
return _device.SetStop(CancellationToken.None);
|
||||||
|
|
||||||
case PlaystateCommand.Pause:
|
case PlaystateCommand.Pause:
|
||||||
|
@ -388,10 +393,10 @@ namespace Emby.Dlna.PlayTo
|
||||||
return Seek(command.SeekPositionTicks ?? 0);
|
return Seek(command.SeekPositionTicks ?? 0);
|
||||||
|
|
||||||
case PlaystateCommand.NextTrack:
|
case PlaystateCommand.NextTrack:
|
||||||
return SetPlaylistIndex(_currentPlaylistIndex + 1);
|
return SetPlaylistIndex(_currentPlaylistIndex + 1, cancellationToken);
|
||||||
|
|
||||||
case PlaystateCommand.PreviousTrack:
|
case PlaystateCommand.PreviousTrack:
|
||||||
return SetPlaylistIndex(_currentPlaylistIndex - 1);
|
return SetPlaylistIndex(_currentPlaylistIndex - 1, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
@ -427,14 +432,6 @@ namespace Emby.Dlna.PlayTo
|
||||||
return info.IsDirectStream;
|
return info.IsDirectStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Playlist
|
|
||||||
|
|
||||||
private int _currentPlaylistIndex;
|
|
||||||
private readonly List<PlaylistItem> _playlist = new List<PlaylistItem>();
|
|
||||||
private List<PlaylistItem> Playlist => _playlist;
|
|
||||||
|
|
||||||
private void AddItemFromId(Guid id, List<BaseItem> list)
|
private void AddItemFromId(Guid id, List<BaseItem> list)
|
||||||
{
|
{
|
||||||
var item = _libraryManager.GetItemById(id);
|
var item = _libraryManager.GetItemById(id);
|
||||||
|
@ -452,7 +449,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
_dlnaManager.GetDefaultProfile();
|
_dlnaManager.GetDefaultProfile();
|
||||||
|
|
||||||
var mediaSources = item is IHasMediaSources
|
var mediaSources = item is IHasMediaSources
|
||||||
? (_mediaSourceManager.GetStaticMediaSources(item, true, user))
|
? _mediaSourceManager.GetStaticMediaSources(item, true, user)
|
||||||
: new List<MediaSourceInfo>();
|
: new List<MediaSourceInfo>();
|
||||||
|
|
||||||
var playlistItem = GetPlaylistItem(item, mediaSources, profile, _session.DeviceId, mediaSourceId, audioStreamIndex, subtitleStreamIndex);
|
var playlistItem = GetPlaylistItem(item, mediaSources, profile, _session.DeviceId, mediaSourceId, audioStreamIndex, subtitleStreamIndex);
|
||||||
|
@ -460,8 +457,19 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
playlistItem.StreamUrl = DidlBuilder.NormalizeDlnaMediaUrl(playlistItem.StreamInfo.ToUrl(_serverAddress, _accessToken));
|
playlistItem.StreamUrl = DidlBuilder.NormalizeDlnaMediaUrl(playlistItem.StreamInfo.ToUrl(_serverAddress, _accessToken));
|
||||||
|
|
||||||
var itemXml = new DidlBuilder(profile, user, _imageProcessor, _serverAddress, _accessToken, _userDataManager, _localization, _mediaSourceManager, _logger, _mediaEncoder)
|
var itemXml = new DidlBuilder(
|
||||||
.GetItemDidl(_config.GetDlnaConfiguration(), item, user, null, _session.DeviceId, new Filter(), playlistItem.StreamInfo);
|
profile,
|
||||||
|
user,
|
||||||
|
_imageProcessor,
|
||||||
|
_serverAddress,
|
||||||
|
_accessToken,
|
||||||
|
_userDataManager,
|
||||||
|
_localization,
|
||||||
|
_mediaSourceManager,
|
||||||
|
_logger,
|
||||||
|
_mediaEncoder,
|
||||||
|
_libraryManager)
|
||||||
|
.GetItemDidl(item, user, null, _session.DeviceId, new Filter(), playlistItem.StreamInfo);
|
||||||
|
|
||||||
playlistItem.Didl = itemXml;
|
playlistItem.Didl = itemXml;
|
||||||
|
|
||||||
|
@ -571,30 +579,31 @@ namespace Emby.Dlna.PlayTo
|
||||||
/// Plays the items.
|
/// Plays the items.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="items">The items.</param>
|
/// <param name="items">The items.</param>
|
||||||
/// <returns></returns>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
private async Task<bool> PlayItems(IEnumerable<PlaylistItem> items)
|
/// <returns><c>true</c> on success.</returns>
|
||||||
|
private async Task<bool> PlayItems(IEnumerable<PlaylistItem> items, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
Playlist.Clear();
|
_playlist.Clear();
|
||||||
Playlist.AddRange(items);
|
_playlist.AddRange(items);
|
||||||
_logger.LogDebug("{0} - Playing {1} items", _session.DeviceName, Playlist.Count);
|
_logger.LogDebug("{0} - Playing {1} items", _session.DeviceName, _playlist.Count);
|
||||||
|
|
||||||
await SetPlaylistIndex(0).ConfigureAwait(false);
|
await SetPlaylistIndex(0, cancellationToken).ConfigureAwait(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SetPlaylistIndex(int index)
|
private async Task SetPlaylistIndex(int index, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= Playlist.Count)
|
if (index < 0 || index >= _playlist.Count)
|
||||||
{
|
{
|
||||||
Playlist.Clear();
|
_playlist.Clear();
|
||||||
await _device.SetStop(CancellationToken.None);
|
await _device.SetStop(cancellationToken).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentPlaylistIndex = index;
|
_currentPlaylistIndex = index;
|
||||||
var currentitem = Playlist[index];
|
var currentitem = _playlist[index];
|
||||||
|
|
||||||
await _device.SetAvTransport(currentitem.StreamUrl, GetDlnaHeaders(currentitem), currentitem.Didl, CancellationToken.None);
|
await _device.SetAvTransport(currentitem.StreamUrl, GetDlnaHeaders(currentitem), currentitem.Didl, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var streamInfo = currentitem.StreamInfo;
|
var streamInfo = currentitem.StreamInfo;
|
||||||
if (streamInfo.StartPositionTicks > 0 && EnableClientSideSeek(streamInfo))
|
if (streamInfo.StartPositionTicks > 0 && EnableClientSideSeek(streamInfo))
|
||||||
|
@ -603,10 +612,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
/// <inheritdoc />
|
||||||
|
|
||||||
private bool _disposed;
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
|
@ -625,19 +631,17 @@ namespace Emby.Dlna.PlayTo
|
||||||
_device.Dispose();
|
_device.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
_device.PlaybackStart -= _device_PlaybackStart;
|
_device.PlaybackStart -= OnDevicePlaybackStart;
|
||||||
_device.PlaybackProgress -= _device_PlaybackProgress;
|
_device.PlaybackProgress -= OnDevicePlaybackProgress;
|
||||||
_device.PlaybackStopped -= _device_PlaybackStopped;
|
_device.PlaybackStopped -= OnDevicePlaybackStopped;
|
||||||
_device.MediaChanged -= _device_MediaChanged;
|
_device.MediaChanged -= OnDeviceMediaChanged;
|
||||||
_deviceDiscovery.DeviceLeft -= _deviceDiscovery_DeviceLeft;
|
_deviceDiscovery.DeviceLeft -= OnDeviceDiscoveryDeviceLeft;
|
||||||
_device.OnDeviceUnavailable = null;
|
_device.OnDeviceUnavailable = null;
|
||||||
_device = null;
|
_device = null;
|
||||||
|
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly CultureInfo _usCulture = CultureInfo.ReadOnly(new CultureInfo("en-US"));
|
|
||||||
|
|
||||||
private Task SendGeneralCommand(GeneralCommand command, CancellationToken cancellationToken)
|
private Task SendGeneralCommand(GeneralCommand command, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (Enum.TryParse(command.Name, true, out GeneralCommandType commandType))
|
if (Enum.TryParse(command.Name, true, out GeneralCommandType commandType))
|
||||||
|
@ -714,7 +718,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
if (info.Item != null)
|
if (info.Item != null)
|
||||||
{
|
{
|
||||||
var newPosition = GetProgressPositionTicks(media, info) ?? 0;
|
var newPosition = GetProgressPositionTicks(info) ?? 0;
|
||||||
|
|
||||||
var user = !_session.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(_session.UserId) : null;
|
var user = !_session.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(_session.UserId) : null;
|
||||||
var newItem = CreatePlaylistItem(info.Item, user, newPosition, info.MediaSourceId, newIndex, info.SubtitleStreamIndex);
|
var newItem = CreatePlaylistItem(info.Item, user, newPosition, info.MediaSourceId, newIndex, info.SubtitleStreamIndex);
|
||||||
|
@ -739,7 +743,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
if (info.Item != null)
|
if (info.Item != null)
|
||||||
{
|
{
|
||||||
var newPosition = GetProgressPositionTicks(media, info) ?? 0;
|
var newPosition = GetProgressPositionTicks(info) ?? 0;
|
||||||
|
|
||||||
var user = !_session.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(_session.UserId) : null;
|
var user = !_session.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(_session.UserId) : null;
|
||||||
var newItem = CreatePlaylistItem(info.Item, user, newPosition, info.MediaSourceId, info.AudioStreamIndex, newIndex);
|
var newItem = CreatePlaylistItem(info.Item, user, newPosition, info.MediaSourceId, info.AudioStreamIndex, newIndex);
|
||||||
|
@ -853,8 +857,11 @@ namespace Emby.Dlna.PlayTo
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
var index = url.IndexOf('?');
|
var index = url.IndexOf('?', StringComparison.Ordinal);
|
||||||
if (index == -1) return request;
|
if (index == -1)
|
||||||
|
{
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
var query = url.Substring(index + 1);
|
var query = url.Substring(index + 1);
|
||||||
Dictionary<string, string> values = QueryHelpers.ParseQuery(query).ToDictionary(kv => kv.Key, kv => kv.Value.ToString());
|
Dictionary<string, string> values = QueryHelpers.ParseQuery(query).ToDictionary(kv => kv.Key, kv => kv.Value.ToString());
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
@ -24,7 +23,7 @@ using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Emby.Dlna.PlayTo
|
namespace Emby.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
public class PlayToManager : IDisposable
|
public sealed class PlayToManager : IDisposable
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly ISessionManager _sessionManager;
|
private readonly ISessionManager _sessionManager;
|
||||||
|
@ -232,6 +231,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_deviceDiscovery.DeviceDiscovered -= OnDeviceDiscoveryDeviceDiscovered;
|
_deviceDiscovery.DeviceDiscovered -= OnDeviceDiscoveryDeviceDiscovered;
|
||||||
|
@ -245,6 +245,9 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_sessionLock.Dispose();
|
||||||
|
_disposeCancellationTokenSource.Dispose();
|
||||||
|
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
@ -33,18 +32,15 @@ namespace Emby.Dlna.PlayTo
|
||||||
DeviceService service,
|
DeviceService service,
|
||||||
string command,
|
string command,
|
||||||
string postData,
|
string postData,
|
||||||
bool logRequest = true,
|
string header = null,
|
||||||
string header = null)
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var cancellationToken = CancellationToken.None;
|
|
||||||
|
|
||||||
var url = NormalizeServiceUrl(baseUrl, service.ControlUrl);
|
var url = NormalizeServiceUrl(baseUrl, service.ControlUrl);
|
||||||
using (var response = await PostSoapDataAsync(
|
using (var response = await PostSoapDataAsync(
|
||||||
url,
|
url,
|
||||||
$"\"{service.ServiceType}#{command}\"",
|
$"\"{service.ServiceType}#{command}\"",
|
||||||
postData,
|
postData,
|
||||||
header,
|
header,
|
||||||
logRequest,
|
|
||||||
cancellationToken)
|
cancellationToken)
|
||||||
.ConfigureAwait(false))
|
.ConfigureAwait(false))
|
||||||
using (var stream = response.Content)
|
using (var stream = response.Content)
|
||||||
|
@ -64,7 +60,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
return serviceUrl;
|
return serviceUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!serviceUrl.StartsWith("/"))
|
if (!serviceUrl.StartsWith("/", StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
serviceUrl = "/" + serviceUrl;
|
serviceUrl = "/" + serviceUrl;
|
||||||
}
|
}
|
||||||
|
@ -128,7 +124,6 @@ namespace Emby.Dlna.PlayTo
|
||||||
string soapAction,
|
string soapAction,
|
||||||
string postData,
|
string postData,
|
||||||
string header,
|
string header,
|
||||||
bool logRequest,
|
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (soapAction[0] != '\"')
|
if (soapAction[0] != '\"')
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
namespace Emby.Dlna.PlayTo
|
namespace Emby.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using Emby.Dlna.Eventing;
|
using Emby.Dlna.Eventing;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
|
@ -13,7 +12,7 @@ namespace Emby.Dlna.Service
|
||||||
protected IHttpClient HttpClient;
|
protected IHttpClient HttpClient;
|
||||||
protected ILogger Logger;
|
protected ILogger Logger;
|
||||||
|
|
||||||
protected BaseService(ILogger logger, IHttpClient httpClient)
|
protected BaseService(ILogger<BaseService> logger, IHttpClient httpClient)
|
||||||
{
|
{
|
||||||
Logger = logger;
|
Logger = logger;
|
||||||
HttpClient = httpClient;
|
HttpClient = httpClient;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
@ -8,19 +7,12 @@ using Emby.Naming.Common;
|
||||||
|
|
||||||
namespace Emby.Naming.Audio
|
namespace Emby.Naming.Audio
|
||||||
{
|
{
|
||||||
public class AudioFileParser
|
public static class AudioFileParser
|
||||||
{
|
{
|
||||||
private readonly NamingOptions _options;
|
public static bool IsAudioFile(string path, NamingOptions options)
|
||||||
|
|
||||||
public AudioFileParser(NamingOptions options)
|
|
||||||
{
|
|
||||||
_options = options;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsAudioFile(string path)
|
|
||||||
{
|
{
|
||||||
var extension = Path.GetExtension(path) ?? string.Empty;
|
var extension = Path.GetExtension(path) ?? string.Empty;
|
||||||
return _options.AudioFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase);
|
return options.AudioFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace Emby.Naming.AudioBook
|
||||||
/// <value>The type.</value>
|
/// <value>The type.</value>
|
||||||
public bool IsDirectory { get; set; }
|
public bool IsDirectory { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc />
|
||||||
public int CompareTo(AudioBookFileInfo other)
|
public int CompareTo(AudioBookFileInfo other)
|
||||||
{
|
{
|
||||||
if (ReferenceEquals(this, other))
|
if (ReferenceEquals(this, other))
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
#pragma warning disable SA1600
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue